Skip to content

Commit 092d8a3

Browse files
committed
mass-update: deterministic update
1 parent f2bc406 commit 092d8a3

3 files changed

Lines changed: 781 additions & 0 deletions

File tree

.claude/skills/deviate/SKILL.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
---
2+
name: deviate
3+
description: >
4+
Stop an in-flight assign-to-workforce run the moment execution must diverge
5+
from the confirmed plan, get explicit human approval for the divergence, and
6+
record it as a first-class, append-only deviation record via `devague
7+
deviate` before resuming — never fold a deviation silently into drift after
8+
the fact. Use when the user says "deviate from the plan", "we need to change
9+
the plan mid-run", "record a deviation", "this isn't matching the plan
10+
anymore", or when a task agent discovers the confirmed plan no longer
11+
matches reality partway through a workforce run. Authored and maintained in
12+
agentculture/devague (origin = devague); guildmaster pulls this skill from
13+
here and broadcasts it to the AgentCulture mesh — it is NOT vendored from
14+
guildmaster like the other skills here.
15+
type: command
16+
---
17+
18+
# deviate — record an approved mid-run departure from the confirmed plan
19+
20+
The skill is named **`deviate`**; it is the **execution-time leg** of the
21+
devague method — the *sixth* leg, sitting between the two execution skills:
22+
23+
```text
24+
scope -> think -> spec-to-plan -> assign-to-workforce -> deviate -> summarize-delivery
25+
```
26+
27+
Where `/assign-to-workforce` fans out a converged plan's waves and
28+
`/summarize-delivery` closes the loop afterward, `/deviate` runs **during**
29+
the fan-out, at the exact moment reality stops matching the plan the human
30+
approved at gate 2 (the implementation split plan). It is not a new standing
31+
gate — it is the human owner of gate 2 **amending** the approved split
32+
mid-flight, scoped to the one deviation in front of them.
33+
34+
The plan the user confirmed is a contract. Task agents hit constraints,
35+
discover a dependency was wrong, or find the acceptance criteria no longer
36+
make sense once code is in front of them. Until this skill existed, that
37+
reality either silently reshaped what got built (undocumented drift) or the
38+
run stalled with no recorded path forward. `/deviate` is that path: the
39+
departure is named, approved, and recorded **before** anyone keeps building
40+
against it.
41+
42+
## The method
43+
44+
1. **STOP the run.** The moment a task agent (or the main agent) discovers
45+
the confirmed plan no longer matches what needs to happen, halt — do not
46+
keep implementing against the stale contract and do not let the fan-out
47+
continue past this task.
48+
2. **Present what, why, and what it affects.** Lay out, for the human:
49+
- **what** is diverging — the specific change from the confirmed task(s);
50+
- **why** — the constraint or discovery that forced it;
51+
- **what it affects** — the plan item ref(s) involved (`--task`), any
52+
other task ids or coverage targets it touches (`--affects`), and which
53+
acceptance criteria are no longer accurate.
54+
3. **Get explicit human approval.** This is the one non-negotiable step. A
55+
deviation is not real until a human says yes to *this specific* departure
56+
— not a standing blanket permission, not an inference from silence.
57+
4. **Record it via `devague deviate`.** Once approved, record the deviation
58+
as a first-class ledger entry (never edit the plan itself — the plan
59+
stays the untouched historical contract; see `devague/delivery.py`). An
60+
`--origin llm` record lands `proposed` and still needs the user's
61+
`--confirm` — recording is not the same as approval landing as final.
62+
5. **Adjust the affected task briefs.** Update the working instructions the
63+
task agent(s) are building against so they reflect the approved
64+
departure, not the stale plan text.
65+
6. **Resume.** Only after the record exists (and, for an `llm`-origin record,
66+
only after it is confirmed) does the fan-out continue.
67+
68+
Deviations are never silently folded into drift after the fact — by the time
69+
`/summarize-delivery` runs, every departure from the plan already has a
70+
`dN` record with a reason, an approval, and an optional classification. The
71+
delivery summary quotes these records; it does not reconstruct drift from
72+
memory.
73+
74+
## The shipped CLI surface
75+
76+
This skill invokes the CLI directly and stays self-contained (if `devague`
77+
isn't on your PATH: `uv tool install devague`). Deviation state persists
78+
under `.devague/deliveries/<plan-slug>.json` — a peer of the plan store, keyed
79+
by the plan slug, and never touches the plan JSON itself.
80+
81+
| Move | What it does |
82+
|------|---------------|
83+
| `devague deviate "<what>" --task <tN> --reason "<text>"` | Record a deviation against plan item `<tN>`. User-origin (the default) auto-approves. |
84+
| `devague deviate "<what>" --task <tN> --reason "<text>" --affects <ref> [<ref> ...]` | Same, also naming every other plan item ref or coverage target the deviation touches (repeatable). |
85+
| `devague deviate "<what>" --task <tN> --reason "<text>" --classification acceptable\|risky\|needs-follow-up` | Same, tagging the deviation with the classification the drift-entry contract consumes downstream. |
86+
| `devague deviate "<what>" --task <tN> --reason "<text>" --origin llm` | An LLM-proposed record; lands `proposed`, not `approved`. |
87+
| `devague deviate --confirm <dN>` | User-only: approve a `proposed` deviation. |
88+
| `devague deviate --reject <dN>` | User-only: reject a `proposed` (or any) deviation. |
89+
| `devague deviate --list [--json]` | Read every recorded deviation back (also the default action with no positional/flag). |
90+
| `devague deviate ... --plan <slug>` | Target a plan other than the current one. |
91+
92+
`--reason` is required on every record — omitting it is refused with a hint.
93+
`--task` naming the plan item ref is likewise required.
94+
95+
## Hard rules (do not violate)
96+
97+
- **Never record a deviation the human did not approve.** `devague deviate`
98+
without `--origin llm` auto-approves the instant it is run — so a
99+
user-origin record IS the approval. Only run it after the human has said
100+
yes to this specific departure, never preemptively "to be safe."
101+
- **Never continue past a refused approval.** If the human does not approve,
102+
the run stays stopped on that task. Do not record the deviation anyway, do
103+
not quietly implement the diverging approach, and do not advance the wave.
104+
- **LLM-origin records stay proposed until the user confirms.** `--origin
105+
llm` lands `proposed`; only `devague deviate --confirm <dN>` (user-only)
106+
makes it `approved`. Same anti-fabrication contract as every other origin
107+
in the method — an agent's own proposal never self-confirms.
108+
- **Deviations are never silently folded into drift after the fact.** Every
109+
departure from the confirmed plan gets a `dN` record at the moment it
110+
happens — not reconstructed from memory when `/summarize-delivery` runs
111+
later.
112+
- **The CLI stays non-orchestrating (issue #20).** `devague deviate` records
113+
a decision the human already made; it does not spawn agents, gate merges,
114+
mark tasks done, or make the approval decision itself. Recording is
115+
deterministic — no LLM calls inside the CLI.
116+
- **This is not a fourth standing gate.** `/assign-to-workforce`'s three
117+
human gates are the exported spec, the implementation split plan, and the
118+
final PR. `/deviate` does not add a fourth — it is the human owner of gate
119+
2 amending the approved split for one scoped, in-flight decision.
120+
121+
## Worked example
122+
123+
Mid-fan-out on task `t4`, the task agent discovers the acceptance criteria
124+
assumed a helper that task `t2` never actually shipped:
125+
126+
```bash
127+
# 1. STOP — the main agent halts t4's worktree before more code lands
128+
# against a criterion that can't be met as written.
129+
130+
# 2. Present what/why/what-it-affects to the human:
131+
# what: t4's acceptance criterion 2 assumes a `--json` flag on a
132+
# helper that t2 shipped without one
133+
# why: t2's scope was cut to land its wave on time
134+
# affects: t4 (this task), and coverage target c9 (the criterion in
135+
# question)
136+
137+
# --- HUMAN: approves dropping the --json assumption from t4's criterion ---
138+
139+
# 3. Record the approved deviation
140+
devague deviate "drop the --json assumption from t4's acceptance criterion" \
141+
--task t4 --reason "t2 shipped its helper without --json to land its wave on time" \
142+
--affects t2 --affects c9 --classification acceptable
143+
144+
# 4. Adjust t4's working brief to match what was approved, then resume the
145+
# task agent against the corrected instruction.
146+
147+
# Read the ledger back at any point:
148+
devague deviate --list
149+
devague deviate --list --json
150+
```
151+
152+
If the agent had proposed the record itself (`--origin llm`), the same
153+
record would land `proposed` and need an explicit
154+
`devague deviate --confirm d1` from the user before `/summarize-delivery`
155+
could cite it as approved.
156+
157+
## After recording — resume, then hand off to /summarize-delivery
158+
159+
Once the affected task briefs are adjusted and the fan-out resumes, nothing
160+
further is needed from this skill — the record already lives in the delivery
161+
store. When the run reaches `/summarize-delivery`, that skill's Drift From
162+
Plan and Mid-work Decisions sections quote these records by their `dN` id
163+
instead of reconstructing drift from memory, so the connective tissue between
164+
the confirmed plan and the delivery summary is the ledger this skill wrote,
165+
not anyone's recollection of the run.
166+
167+
## Provenance
168+
169+
This is a **first-party** skill — its origin is `agentculture/devague`, the
170+
*sixth* in the outbound family after `/scope`, `/think`, `/spec-to-plan`,
171+
`/assign-to-workforce`, and `/summarize-delivery`, covering the execution-time
172+
leg that runs inside an `/assign-to-workforce` fan-out. guildmaster pulls it
173+
from here and broadcasts it to the AgentCulture mesh; because devague is
174+
upstream, it is **never re-vendored back** from guildmaster's re-broadcast
175+
copy. The `cite, don't import` policy still holds: downstream repos copy it,
176+
they don't symlink or depend on it. See `docs/skill-sources.md`.

.claude/skills/scope/SKILL.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
---
2+
name: scope
3+
description: >
4+
Explore the scope of a vague idea BEFORE framing it into a spec (the
5+
idea→scope leg; the optional opening move ahead of /think). Survey the
6+
surfaces the idea touches — code, docs, skills, CI, sibling repos — and seed
7+
the coming Announcement Frame with boundary, non-goal, and assumption claims
8+
that cite what was actually explored (provenance, not generic disclaimers).
9+
Use when the user says "explore scope", "scope this idea", "what does this
10+
touch", "map the scope", "scope exploration", or when an idea touches an
11+
existing codebase and speccing it cold would mean guessing its boundaries.
12+
Hand off to the sibling /think skill to build the frame. Authored and
13+
maintained in agentculture/devague (origin = devague); guildmaster pulls this
14+
skill from here and broadcasts it to the AgentCulture mesh — it is NOT
15+
vendored from guildmaster like the inbound skills here.
16+
type: command
17+
---
18+
19+
# scope — explore what an idea touches before you frame it
20+
21+
The skill is named **`scope`**; it is the **opening leg** of the devague method
22+
— run it *before* the sibling **`/think`** skill frames an idea into a spec.
23+
Where `/think` converges on *what* to build, `/scope` grounds *where the idea
24+
lives*: which surfaces it touches, which it must not, and what is genuinely
25+
unknown — so the frame starts from explored territory instead of guesses.
26+
27+
This comes from the sharper end-to-end method spec (devague#53): scope grounded
28+
up front means convergence measures real coverage instead of vibes. The
29+
exploration itself is **agent-side work** — the devague CLI stays deterministic
30+
and never explores anything (#20).
31+
32+
## When to use — and when to skip
33+
34+
Use `/scope` when the idea touches an existing codebase or ecosystem: a feature
35+
in a real repo, a process change across skills, anything where boundaries are
36+
discoverable rather than invented.
37+
38+
**Skip it freely for small ideas.** Scope exploration is *not* a mandatory
39+
first stage — the move-driven adaptive arc stays intact, and an idea that fits
40+
in one announcement can go straight to `/think`. (This is a recorded non-goal
41+
of the method: no wizard.)
42+
43+
## The method
44+
45+
1. **Enumerate candidate surfaces.** List what the idea *might* touch: source
46+
packages, CLI verbs, renderers, schemas, tests, docs, skills, CI workflows,
47+
sibling repos. `git ls-files` and the repo's `CLAUDE.md` are the usual map.
48+
2. **Explore each surface read-only.** Read enough of each candidate to decide:
49+
touched, not touched, or unknown. Exploration never mutates anything —
50+
no edits, no state changes, no CLI moves yet.
51+
3. **Classify every finding.** Each explored surface yields one of:
52+
- **in scope** — the idea changes it → becomes a `requirement` or
53+
`assumption` claim in the frame;
54+
- **out of scope** — the idea must not change it → becomes a `boundary` or
55+
`non_goal` claim;
56+
- **genuinely unknown** — can't tell without a decision → becomes a `park`
57+
(open vagueness) or a `question` (pending user decision).
58+
4. **Record findings on the frame, with provenance.** Start the frame with
59+
`devague new "<announcement>" --title "<short>"` (this is also `/think`'s
60+
first move) — scope entries live on the frame, so it must exist first.
61+
Record each explored surface as a first-class finding:
62+
`` `devague scope "<surface>" --finding "<text>" [--seeds <claim-id> ...]` ``
63+
— text that **cites the surface explored** ("the CLI stays deterministic
64+
per issue 20; scope exploration is agent-side" beats "we won't overreach").
65+
Capture the claim it seeded first (`capture --kind ...`), then pass its id
66+
to `--seeds` — an unknown seed id is refused with a hint. Provenance, not
67+
generic disclaimers: a reviewer should be able to trace every boundary claim
68+
back to something you read.
69+
70+
## How findings land (the shipped surface)
71+
72+
This skill invokes the CLI directly and stays self-contained (if `devague`
73+
isn't on your PATH: `uv tool install devague`).
74+
75+
The **primary** landing surface is the deterministic `devague scope` move,
76+
shipped in task t3 of the committed sharper-end-to-end-method plan
77+
(`docs/plans/2026-07-01-devague-ships-a-sharper-end-to-end-method-a-guided.md`,
78+
devague#53). It records an explored surface + finding as first-class frame
79+
state (`Frame.scope_entries` / `ScopeEntry`: `id` (`sN`), `surface`, `finding`,
80+
`seeds`) — deterministic recording only, no LLM calls, no subprocess, no
81+
filesystem exploration inside the CLI. Like `capture`, it needs a frame to
82+
already exist, so run `devague new` first:
83+
84+
| Move | What it does |
85+
|------|--------------|
86+
| `devague scope "<surface>" --finding "<text>"` | Record a finding on the current frame. |
87+
| `devague scope "<surface>" --finding "<text>" --seeds <claim-id> [<claim-id> ...]` | Record a finding, linking it to the claim id(s) it went on to seed. An unknown seed id is refused with a hint (`run 'devague show' to see valid claim ids`). |
88+
| `devague scope --list [--json]` | Read every recorded entry back. |
89+
90+
Boundary / non-goal / in-scope claims still land the same way they always
91+
did, through the normal frame moves — `devague scope` documents *what surface
92+
you explored and what you learned*, `capture` records *the claim that
93+
followed*:
94+
95+
| Finding | Move |
96+
|---------|------|
97+
| in scope (the idea changes this) | `capture --kind requirement` / `--kind assumption` (with `--origin llm` if you proposed it) |
98+
| out of scope (must not change) | `capture --kind boundary` / `--kind non_goal` |
99+
| genuinely unknown, needs a user decision | `question "<text>"` (later `question --resolve <qid> --decision "<text>"`) |
100+
| genuinely unknown, not decidable now | `park "<text>" --kind unknown_blocking\|unknown_nonblocking` |
101+
102+
## Hard rules (do not violate)
103+
104+
- **Exploration is read-only.** Surveying scope never edits files, never
105+
mutates frame state, never runs a mutating CLI move.
106+
- **Provenance in every seeded claim.** A scope-derived claim cites what was
107+
explored. If you didn't read it, don't claim it.
108+
- **LLM proposals stay proposed.** Findings you capture with `--origin llm`
109+
land `proposed`; the user confirms. Same anti-fabrication contract as
110+
`/think`.
111+
- **Don't become a wizard.** Scope exploration is optional-by-size and
112+
adaptive. Never block a small idea on a survey it doesn't need.
113+
114+
## Worked example
115+
116+
Scoping "devague exports should carry per-item instructions" against the
117+
devague repo itself:
118+
119+
```bash
120+
# 1–2. enumerate + explore (read-only)
121+
git ls-files devague/ | head -30 # the CLI package map
122+
# read: devague/frame.py (claim model), devague/render/spec_md.py (renderer),
123+
# docs/spec-contract.md (schema contract), .claude/skills/think/SKILL.md
124+
125+
# 3. start the frame (also /think's first move — scope entries live on it)
126+
devague new "devague exports carry per-item instructions" --title "per-item instructions"
127+
128+
# 4. capture each finding as a claim, then record the scope entry that seeded it
129+
devague capture --origin llm --kind requirement "claims gain an optional instruction field — devague/frame.py claim model + docs/spec-contract.md schema both need a bump"
130+
devague scope "devague/frame.py" --finding "claim model needs an optional instruction field per docs/spec-contract.md's schema contract" --seeds c2
131+
132+
devague capture --origin llm --kind boundary "render/spec_md.py renders instructions verbatim; absent instructions render nothing — the renderer never fabricates filler"
133+
devague scope "render/spec_md.py" --finding "renderer must render instructions verbatim; absent instructions render nothing — never fabricate filler" --seeds c3
134+
135+
devague capture --origin llm --kind non_goal "no LLM calls land inside the CLI (issue 20) — instruction text is authored by the operator/user, never generated in-CLI"
136+
devague scope "issue 20 (no LLM calls in-CLI)" --finding "instruction text is authored by the operator/user, never generated in-CLI" --seeds c4
137+
138+
devague question "do instructions attach to frame claims, plan tasks, or both?"
139+
devague scope --list # read every recorded finding back, with its seeded claim ids
140+
```
141+
142+
Every claim above names the file or issue that was actually read — that is the
143+
provenance bar. Note the order: `--seeds` needs the claim id to already exist,
144+
so `capture` runs first and the matching `scope` call cites it back.
145+
146+
## After scoping — hand off to /think
147+
148+
The recorded scope entries and the claims captured alongside them both live on
149+
the same frame — there is nothing separate to export. `devague scope --list`
150+
is the durable, citable record of what was explored; a converged frame's
151+
exported spec-md also renders a `## Scope exploration` section from the same
152+
entries (surface, finding, and seeded claim ids), so the provenance survives
153+
into the buildable artifact (#53 t6). When the survey is done, continue with
154+
`/think`'s remaining moves (`interrogate`, `confirm`/`reject`, `converge`,
155+
`export`) to take the frame the rest of the way. The user confirms
156+
LLM-proposed claims there, as always.
157+
158+
## Provenance
159+
160+
This is a **first-party** skill — its origin is `agentculture/devague`, the
161+
*fourth* in the outbound family after `/think`, `/spec-to-plan`, and
162+
`/assign-to-workforce`, covering the pre-frame exploration leg. guildmaster
163+
pulls it from here and broadcasts it to the AgentCulture mesh. The
164+
`cite, don't import` policy still holds: downstream repos copy it, they don't
165+
symlink or depend on it. See `docs/skill-sources.md`.

0 commit comments

Comments
 (0)