diff --git a/.claude/skills/challenge/SKILL.md b/.claude/skills/challenge/SKILL.md new file mode 100644 index 0000000..fd738a2 --- /dev/null +++ b/.claude/skills/challenge/SKILL.md @@ -0,0 +1,290 @@ +--- +name: challenge +description: > + Run a risk-scaled blind-spot discovery pass over a converged, exported + frame BETWEEN /think and /spec-to-plan (the seventh origin skill, third + leg in flow order): pressure-test the spec through structured lenses, + route every finding back through the existing deterministic moves as + proposed-only content the human adjudicates, and on a clean pass record + the examined lenses/surfaces and residual uncertainty — never a claim + that there are no unknown unknowns. Use when the user says "challenge + this spec", "blind-spot pass", "pressure-test the frame", "what are we + missing", "unknown unknowns", or after /think exports and before + `devague plan new`. Authored and maintained in agentculture/devague + (origin = devague); guildmaster pulls this skill from here and broadcasts + it to the AgentCulture mesh — it is NOT vendored from guildmaster like + the inbound skills here. +type: command +--- + +# challenge — hunt the blind spots before the plan inherits them + +The skill is named **`challenge`**; it is the **blind-spot discovery leg** of +the devague method — the *seventh* origin skill, sitting *third* in flow +order, between the spec leg and the plan leg: + +```text +scope -> think -> challenge -> spec-to-plan -> assign-to-workforce -> deviate -> summarize-delivery +``` + +Before this leg existed, a frame could converge on precisely stated claims +while the original framing was still incomplete: open questions only captured +uncertainty someone had already noticed — **nothing actively hunted omitted +dimensions, hidden dependencies, or assumptions shared by everyone in the +frame, and no record existed of which surfaces were ever examined** +(issue 73's problem statement). Strictly speaking, an unknown unknown cannot +be listed directly — once articulated, it becomes a known unknown. The useful +capability is therefore to **raise the odds of discovering blind spots and +lower the cost of the surprises that remain**, not to promise their +elimination. + +That is the surprise-cost rationale: an articulated blind spot becomes a +known unknown the method can manage; an unexamined one surfaces later as a +mid-run `/deviate` or a production surprise. Discovery *before* planning is +cheaper than either — a proposed claim the human rejects costs minutes; the +same gap found mid-fan-out stops a wave, and found in production it costs +whatever the blast radius costs. + +This doc is written for two readers. The **operator** — the main agent — runs +the pass: sweeps the lenses, drives the deterministic CLI move by move, and +proposes findings. The **gate-owning human** adjudicates: every finding lands +`proposed`, and confirming, rejecting, or resolving it is the human exercising +the existing **spec gate** (gate 1) — challenge adds no fourth gate, mirroring +how `/deviate` amends gate 2 rather than adding one. + +## When it runs + +The timing is a recorded decision — quote it, don't re-derive it: + +> the challenge pass runs after /think exports: challenge the converged, +> exported frame before `devague plan new`; findings reopen the frame, +> reconverge, and re-export the same dated spec file — /think stays +> self-contained (resolves q1) + +— decision c17 in `docs/specs/2026-07-15-challenge-skill.md`. + +Concretely: `/think` finishes its own arc (converge, export) untouched. Then +`/challenge` pressure-tests the exported spec **before** `devague plan new` +seeds a plan from it. Findings land as proposed claims, honesty conditions, +questions, or parks — which reopens the frame — the human adjudicates, the +frame **reconverges**, and `devague export` **re-exports the same dated +file** (`docs/specs/-.md`; exports are prefixed with the +frame's creation date, so a re-export overwrites in place rather than +spawning a duplicate). That reconverge-and-re-export loop repeats until the +pass's findings are all adjudicated and the spec artifact carries them. + +## Proportionality — scale the pass to the risk + +The pass is **mandatory but proportional**: lightweight for ordinary work, +rigorous for high-risk work (integration option 1 from issue 73, per the +issue author — a distinct operator skill, no new CLI engine until the +workflow proves it needs one). Which work is high-risk is likewise a recorded +decision: + +> the named escalation signals that deepen the pass from lightweight to +> rigorous: migrations, security-sensitive work, distributed state, hardware, +> destructive operations, other hard-to-reverse changes, concurrency hazards, +> and any surface that can lose user data (resolves q3) + +— decision c19 in `docs/specs/2026-07-15-challenge-skill.md`. + +If **any** escalation signal applies, run the rigorous form: every lens, +deliberate counter-evidence hunting, and cheap probes where they would settle +a real question. If none applies, a lightweight sweep — one pass over the +lenses against the exported spec, minutes not hours — satisfies the method. +Lightweight never means skipped: even the lightest pass leaves durable +records (see the hard rules). + +## The lenses + +Sweep the exported spec, the live frame, and the surfaces the idea touches +through these structured lenses (from issue 73): + +- **adjacent systems and hidden dependencies** — what else reads, writes, or + assumes the thing being changed; +- **unstated assumptions and missing counter-evidence** — what everyone in + the frame believes without a claim saying so, and what was never checked + because nobody argued the other side; +- **overlooked actors, lifecycle stages, data flows, and failure modes** — + who and what the frame forgot: other users, upgrade/downgrade paths, + half-completed operations; +- **security, migration, concurrency, operations, and reversibility** — the + classic hard surfaces, each also an escalation signal when present; +- **missing observability, containment, rollback, and recovery paths** — + when the surprise happens anyway, how it is seen, bounded, and undone; +- **cheap probes or experiments** — small, scratch-space checks that could + expose a surprise now instead of mid-run (probes never mutate the repo or + `.devague/` state). + +## The method + +1. **Confirm the entry condition.** A converged frame that `/think` has + already exported, and no plan seeded from it yet (`devague status` shows + where the frame stands; the exported spec-md is the artifact under + challenge). +2. **Set the depth.** Check the idea against the c19 escalation signals + above. Any hit → rigorous; none → lightweight. Say which you chose and + why — the depth decision is part of the pass's record. +3. **Sweep the lenses read-only.** Read the exported spec claim by claim, + the frame's parked vagueness and resolved questions, and the actual + surfaces the idea touches. Nothing mutates during the sweep; the only + mutations are the deterministic moves that record findings. +4. **Route every finding through an existing move.** Use the routing table + below. Everything the agent proposes carries `--origin llm` and lands + `proposed` — the pass cannot silently convert speculation into confirmed + requirements. +5. **Let the human adjudicate.** `devague review` lists every proposal with + ids; `devague confirm` / `devague reject` / `devague question --resolve` + are user-only decisions. This is the existing spec gate doing its job. +6. **Reconverge and re-export.** `devague converge`, then `devague export` — + the same dated spec file now carries the adjudicated findings and the + pass's provenance (the exported spec renders scope entries in its + Scope exploration section). +7. **On a clean pass, record the pass itself.** A sweep that finds nothing + still records which lenses and surfaces were examined (`devague scope` + entries, one per lens/surface, e.g. `challenge pass / concurrency lens: + devague/store.py`) and what residual uncertainty remains (`park`). A bare + "no issues found" is not an outcome this skill produces. + +## Where findings land + +Challenge keeps **no parallel prose-only artifact** — the frame is the +record, and every output category from issue 73 has an existing deterministic +move to land in: + +| Output category (issue 73) | What it is | Landing move | +|----------------------------|------------|--------------| +| known facts | something the pass established, with provenance | `capture --kind requirement` / `--kind decision` / `--kind boundary` (`--origin llm` → lands `proposed`) | +| assumptions | beliefs the frame leaned on unstated | `capture --kind assumption --origin llm`, then pressure-test with `interrogate --honesty` / `--hard-question` / `--contradicts` | +| known unknowns / open questions | articulated uncertainty | `question ""` when it needs a user decision; `park --kind unknown_nonblocking\|unknown_blocking` when not decidable now | +| unexamined surfaces | what this pass did not (or could not) look at | `devague scope "" --finding ""` | +| residual surprise risk | uncertainty that survives the pass | `park` on the frame while speccing; `devague plan risk --kind ` once the plan exists | +| resilience measures | containment, rollback, recovery the surprise cost demands | spec-side `capture --kind requirement` / `--kind boundary`; plan-side `devague plan risk` (see below) | + +Every finding names the **lens and surface** it came from (the +`challenge pass / : ` convention in scope entries; provenance +citations inside claim text). That provenance bar is how the method hunts +blind spots **without encouraging speculative issue generation** — a finding +you cannot trace to something you actually read is speculation, not a +finding. + +## Resilience placement — spec-side or plan-side + +Where a resilience measure lands is a recorded decision: + +> resilience measures land in both spec and plan by nature: spec-side as +> requirement/boundary claims when they change what to build, plan-side as +> plan risks or tasks when they change how to build it — the skill coaches +> which is which (resolves q2) + +— decision c18 in `docs/specs/2026-07-15-challenge-skill.md`. + +The coaching: ask *"does this change **what** ships, or **how** it gets +built?"* A rollback path the user needs, a fail-closed version check, a +containment boundary — those change the product: `capture` them spec-side as +`requirement` / `boundary` claims so the re-exported spec carries them. +A staging sequence, a merge-order constraint, an uncertainty the workforce +must build around — those change the build: land them plan-side via +`devague plan risk --kind ` (blocking or nonblocking, honestly chosen) +once `/spec-to-plan` seeds the plan, where the plan's convergence gate keeps +blocking risks visible until resolved. + +## Hard rules (do not violate) + +- **Never conclude there are no unknown unknowns.** Not after a rigorous + pass, not after a clean one. The only honest clean-pass output is a record + of which lenses and surfaces were examined — `devague scope` entries — plus + the residual uncertainty that remains — `park` — so the pass leaves durable + provenance instead of a comforting absolute (issue 73 success criteria; + the anti-fabrication contract in `docs/llm-guidance.md`). +- **LLM-origin findings stay proposed until the user confirms.** Every + finding the agent proposes carries `--origin llm` and lands `proposed`; + only the user's `confirm` makes it real. The pass must not be able to + silently convert speculation into confirmed requirements. +- **Findings route through existing deterministic moves only.** `capture`, + `interrogate`, `question`, `park`, `devague scope`, `devague plan risk` — + nothing else. No parallel prose artifact, no new CLI verb, engine, or + state model (issue 20; issue 73's stated preference). If it didn't land in + a move, it didn't land. +- **Provenance on every finding.** Name the lens and the surface it came + from. If you didn't read it, don't claim it — same bar as `/scope`. +- **Proportional, never skipped.** Lightweight is the floor, not an + exemption; any c19 escalation signal makes the rigorous form mandatory. + Skipping the pass entirely is not a depth setting. +- **Not a fourth standing gate.** The three human gates stay: exported spec, + implementation split plan, final PR. Challenge output is adjudicated + inside the existing spec gate — mirroring how `/deviate` amends gate 2 + rather than adding one. +- **The sweep is read-only until it routes.** Reading spec, frame, and + surfaces never edits files or state; probes run in scratch space. The only + mutations are the recording moves themselves. + +## Worked example + +Challenging the exported spec for a store-schema migration (illustrative +slug `store-schema-v3`) — "migrations" and "any surface that can lose user +data" are both c19 escalation signals, so the pass runs rigorous: + +```bash +# Entry condition: /think exported docs/specs/2026-07-15-store-schema-v3.md +# and no plan exists yet. Depth: rigorous (migration + data-loss signals). + +# adjacent-systems lens: an older installed devague reads the same store +devague capture --origin llm --kind assumption "older installed devague binaries refuse a v3 store via the fail-closed schema_version check in devague/store.py" +devague interrogate c9 --origin llm --honesty "a v2-reading binary pointed at a v3 store exits with the version hint, not a traceback" +devague scope "challenge pass / adjacent-systems lens: devague/store.py schema_version gate" --finding "older binaries fail closed on v3; seeded the compat assumption" --seeds c9 + +# failure-mode lens: the migration can die halfway +devague capture --origin llm --kind requirement "migration writes to a temp file and renames — a killed run never leaves a half-written store" + +# overlooked-actors lens: needs a user decision, not a guess +devague question "do mesh agents share one store, or does each checkout own its own?" + +# reversibility lens: genuinely unknown, not decidable now +devague park "whether a v3->v2 downgrade path is ever needed" --kind unknown_nonblocking + +# concurrency lens found nothing — record the clean pass, not a conclusion +devague scope "challenge pass / concurrency lens: devague/store.py + delivery_store.py" --finding "single-writer CLI, no locking today; clean pass — residual risk only if two agents ever share a checkout" + +# --- HUMAN adjudicates: the existing spec gate at work --- +devague review +devague confirm c9 h4 c10 +devague question --resolve q1 --decision "each checkout owns its own store" + +# Reconverge and re-export — the SAME dated file, now carrying the pass +devague converge +devague export + +# Residual risk that changes HOW to build lands plan-side once +# /spec-to-plan seeds the plan: +devague plan new --frame store-schema-v3 +devague plan risk "two agents sharing a checkout could interleave store writes mid-migration" --kind unknown_nonblocking +``` + +Every finding above is traceable to a lens and a surface; the clean lens is +recorded as examined rather than silently dropped; and nothing the agent +proposed became confirmed without the human's `confirm`. + +## After the pass — hand off to /spec-to-plan + +Once the frame reconverges and the same dated spec file is re-exported, the +pass is done — the examined surfaces, residual uncertainty, and adjudicated +findings all live in frame state and render into the spec artifact. Continue +with `/spec-to-plan` as usual: the plan seeds from the challenged frame, and +any residual surprise risk you routed plan-side lands via +`devague plan risk` as first-class plan state. If a surprise still gets +through mid-fan-out, that is `/deviate`'s job — and every approved `dN` +deviation record is evidence for what the *next* challenge pass's lenses +should look harder at. + +## Provenance + +This is a **first-party** skill — its origin is `agentculture/devague`, the +*seventh* in the outbound family after `/scope`, `/think`, `/spec-to-plan`, +`/assign-to-workforce`, `/deviate`, and `/summarize-delivery`, sitting third +in flow order as the blind-spot discovery leg between `/think` and +`/spec-to-plan`. guildmaster pulls it from here and broadcasts it to the +AgentCulture mesh; because devague is upstream, it is **never re-vendored +back** from guildmaster's re-broadcast copy. The `cite, don't import` policy +still holds: downstream repos copy it, they don't symlink or depend on it. +See `docs/skill-sources.md`. diff --git a/.devague/current_plan b/.devague/current_plan index 0d836e1..c948eff 100644 --- a/.devague/current_plan +++ b/.devague/current_plan @@ -1 +1 @@ -execution-seam-and-deviate +challenge-skill diff --git a/.devague/deliveries/challenge-skill.json b/.devague/deliveries/challenge-skill.json new file mode 100644 index 0000000..420d4a2 --- /dev/null +++ b/.devague/deliveries/challenge-skill.json @@ -0,0 +1,20 @@ +{ + "plan_slug": "challenge-skill", + "schema_version": 1, + "created": "2026-07-15T06:52:02Z", + "updated": "2026-07-15T06:53:35Z", + "deviations": [ + { + "id": "d1", + "what": "t4 additionally prepends a 0.19.0 release paragraph to CLAUDE.md's Status section (newest-first, repo convention)", + "task_ref": "t4", + "reason": "the confirmed t4 acceptance criteria name only pyproject.toml and CHANGELOG.md; every prior release (0.15.0, 0.17.0, 0.18.0) also added a CLAUDE.md Status paragraph \u2014 omitting it would leave the Status section stale at 0.18.0 after this ships", + "affects": [ + "c4" + ], + "origin": "llm", + "status": "approved", + "classification": "acceptable" + } + ] +} diff --git a/.devague/frames/challenge-skill.json b/.devague/frames/challenge-skill.json new file mode 100644 index 0000000..415bd58 --- /dev/null +++ b/.devague/frames/challenge-skill.json @@ -0,0 +1,377 @@ +{ + "slug": "challenge-skill", + "title": "challenge skill", + "schema_version": 2, + "status": "exported", + "created": "2026-07-15T06:10:22Z", + "updated": "2026-07-15T06:29:41Z", + "claims": [ + { + "id": "c1", + "kind": "announcement", + "text": "devague gains a seventh origin skill, /challenge \u2014 a risk-scaled blind-spot discovery pass that pressure-tests the converged frame between /think and /spec-to-plan through structured lenses, routes every finding back through the existing deterministic moves, and records examined surfaces plus residual uncertainty instead of ever claiming there are no unknown unknowns", + "origin": "user", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h1", + "text": "the shipped SKILL.md actually is what the announcement claims: risk-scaled (an explicit proportionality rule), positioned between /think and /spec-to-plan in every flow doc, findings routed only through existing deterministic moves, and a no-unknown-unknowns-claim rule", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "diff the shipped SKILL.md against this announcement claim by claim: risk-scaling rule present, position between /think and /spec-to-plan, findings routed through existing moves only, examined-surfaces record on a clean pass" + }, + { + "id": "c2", + "kind": "requirement", + "text": "the new skill ships as .claude/skills/challenge/SKILL.md in the method-only shape \u2014 SKILL.md only, no scripts/ resolver, `type: command` frontmatter, a Provenance section naming devague as origin \u2014 matching the shipped deviate and summarize-delivery skills and the two-shape rule in docs/skills.md", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h2", + "text": "listing .claude/skills/challenge/ shows exactly one file, SKILL.md, whose frontmatter carries `type: command` and whose Provenance section names devague as origin \u2014 no scripts/ directory", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c3", + "kind": "requirement", + "text": "devague/cli/_commands/learn.py OPERATOR_SKILLS gains a seventh entry for challenge and its six-skill / six-leg wording updates, so `devague learn skills` and `skills:challenge` teach the new skill; this is teaching-content in the existing learn verb, not a new engine", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h3", + "text": "`devague learn skills:challenge` exits 0 and emits the challenge authoring recipe; `devague learn skills` output says seven operator skills in seven-leg order", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c4", + "kind": "requirement", + "text": "every surface naming the six-leg flow is updated to seven legs with challenge third: README.md (lines 82-94), CLAUDE.md (Status + Project intent), docs/skills.md (flow table + per-skill section), docs/skill-sources.md (origin-skills table + dont-re-vendor list)", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h4", + "text": "grepping README.md, CLAUDE.md, docs/skills.md, and docs/skill-sources.md for six-leg wording returns no hits, and all four surfaces name challenge as the third leg", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c5", + "kind": "boundary", + "text": "no new CLI engine, verb, or state model \u2014 challenge findings route through the existing deterministic moves only: capture / interrogate / question / park on the frame, `devague scope` for examined surfaces, `devague plan risk` for residual risk; the CLI stays deterministic and non-orchestrating per issue 20 and the issue 73 stated preference", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h5", + "text": "the PR diff registers no new argparse subparser, adds no new devague/ module or store, and the only devague/ code change is teaching content in cli/_commands/learn.py", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c6", + "kind": "non_goal", + "text": "challenge is not a fourth standing human gate \u2014 the three gates (exported spec, implementation split plan, final PR) stay; challenge output lands as proposed claims and questions the user confirms inside the existing spec gate, mirroring how /deviate amends gate 2 rather than adding one", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c7", + "kind": "requirement", + "text": "when the pass finds nothing, it records which lenses and surfaces were examined and what residual uncertainty remains \u2014 it never claims there are no unknown unknowns (issue 73 success criteria; anti-fabrication contract in docs/llm-guidance.md)", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h6", + "text": "the SKILL.md hard-rules section contains an explicit rule forbidding a no-unknown-unknowns conclusion, with the required fallback of recording examined lenses/surfaces plus residual uncertainty", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c8", + "kind": "assumption", + "text": "examined-surfaces records reuse the existing `devague scope` move (surface + finding + optional seeds) \u2014 Frame.scope_entries already persists them and the exported spec-md already renders a Scope exploration section (issue 53 t3/t6), so residual-uncertainty provenance survives into the buildable spec with no new state", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c9", + "kind": "assumption", + "text": "residual risk that survives into planning lands via `devague plan risk --kind` \u2014 RISK_KINDS equals the vagueness kinds (unknown_nonblocking / unknown_blocking / out_of_scope / follow_up) in devague/plan.py, which already distinguishes blocking from nonblocking residual uncertainty", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c10", + "kind": "decision", + "text": "integration option 1 from issue 73, per the issue author: a distinct operator skill /challenge, run as a mandatory but proportional pass \u2014 lightweight for ordinary work, rigorous for high-risk work \u2014 with no new CLI engine until the workflow proves it needs one", + "origin": "user", + "status": "confirmed", + "honesty_conditions": [], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c11", + "kind": "decision", + "text": "challenge is the seventh documented leg, positioned third: scope, think, challenge, spec-to-plan, assign-to-workforce, deviate, summarize-delivery \u2014 per the issue 73 proposal flow and the user's request driving this frame", + "origin": "user", + "status": "confirmed", + "honesty_conditions": [], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c12", + "kind": "audience", + "text": "operators \u2014 the main agent driving the deterministic CLI move by move \u2014 and the humans who own the spec and implementation-split-plan gates; downstream, the AgentCulture mesh once guildmaster re-broadcasts the skill", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h7", + "text": "the SKILL.md description and body address the operator (move-by-move CLI driving) and the gate-owning human (confirmation of findings) as distinct readers, matching the other six origin skills", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "check the SKILL.md description names both audiences and docs/skill-sources.md routes challenge to guildmaster like the other six origin skills" + }, + { + "id": "c13", + "kind": "before_state", + "text": "a frame can converge on precisely stated claims while the original framing is still incomplete: open questions only capture uncertainty someone already noticed \u2014 nothing actively hunts omitted dimensions, hidden dependencies, or shared assumptions, and no record exists of which surfaces were ever examined (issue 73 problem statement)", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h8", + "text": "issue 73's problem statement is accurately reflected: before this change no devague surface actively searched for omitted dimensions or recorded examined surfaces at spec time", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c14", + "kind": "why_it_matters", + "text": "an articulated blind spot becomes a known unknown the method can manage; an unexamined one surfaces later as a mid-run /deviate or a production surprise \u2014 the pass raises the odds of discovery before planning and lowers the cost of the surprises that remain (issue 73)", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h9", + "text": "the skill's intro states the surprise-cost rationale \u2014 discovery before planning is cheaper than /deviate mid-run or a production surprise \u2014 rather than promising to eliminate unknown unknowns", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c15", + "kind": "after_state", + "text": "a converged frame no longer slides straight into planning untested: the operator runs a proportional challenge pass over structured lenses, every finding lands as a proposed claim, question, or park that the user adjudicates, the frame reconverges, and the exported spec carries examined-surfaces provenance and residual uncertainty", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h10", + "text": "a dogfooded /challenge run on a real converged frame produces only proposed findings, triggers reconvergence, and the re-exported spec renders the examined surfaces \u2014 verified before the skill is called done", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "dogfood /challenge on a real frame and verify findings landed proposed-only, the frame reconverged, and the re-exported spec shows the examined surfaces" + }, + { + "id": "c16", + "kind": "success_signal", + "text": "every challenge pass leaves at least 1 durable record \u2014 proposed findings routed through existing moves, or examined-surfaces entries with residual uncertainty on a clean pass; 0 passes conclude with a bare no-issues-found, and 0 LLM-origin findings reach confirmed status without an explicit user confirm", + "origin": "llm", + "status": "confirmed", + "honesty_conditions": [ + { + "id": "h11", + "text": "the success-signal counts are checkable from state alone: frame JSON plus session transcript show every finding's lens/surface trace and zero llm-origin items confirmed without a user confirm move", + "status": "confirmed", + "instruction": "" + } + ], + "hard_questions": [], + "links": [], + "instruction": "review a dogfooded pass: each finding traceable to a lens and surface; grep the frame JSON for llm-origin claims that are confirmed without a user confirm in the session log" + }, + { + "id": "c17", + "kind": "decision", + "text": "the challenge pass runs after /think exports: challenge the converged, exported frame before `devague plan new`; findings reopen the frame, reconverge, and re-export the same dated spec file \u2014 /think stays self-contained (resolves q1)", + "origin": "user", + "status": "confirmed", + "honesty_conditions": [], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c18", + "kind": "decision", + "text": "resilience measures land in both spec and plan by nature: spec-side as requirement/boundary claims when they change what to build, plan-side as plan risks or tasks when they change how to build it \u2014 the skill coaches which is which (resolves q2)", + "origin": "user", + "status": "confirmed", + "honesty_conditions": [], + "hard_questions": [], + "links": [], + "instruction": "" + }, + { + "id": "c19", + "kind": "decision", + "text": "the named escalation signals that deepen the pass from lightweight to rigorous: migrations, security-sensitive work, distributed state, hardware, destructive operations, other hard-to-reverse changes, concurrency hazards, and any surface that can lose user data (resolves q3)", + "origin": "user", + "status": "confirmed", + "honesty_conditions": [], + "hard_questions": [], + "links": [], + "instruction": "" + } + ], + "open_vagueness": [ + { + "id": "v1", + "text": "guildmaster re-vendors /challenge and re-broadcasts it to the mesh on its own schedule \u2014 outside this repo's control; the skill-sources row documents the re-vendor path so downstream picks it up on the next sync", + "kind": "follow_up", + "claim_id": null + }, + { + "id": "v2", + "text": "whether the proportionality rule (lightweight vs rigorous) is calibrated right is only observable across future dogfooded runs \u2014 the first few /challenge passes should be watched for over- or under-escalation", + "kind": "unknown_nonblocking", + "claim_id": null + } + ], + "scope_entries": [ + { + "id": "s1", + "surface": ".claude/skills/deviate/SKILL.md + .claude/skills/summarize-delivery/ + docs/skills.md file-structure rules", + "finding": "the method-only origin-skill shape is established: SKILL.md only, type: command frontmatter required for culture/agex backends, Provenance section naming devague as origin; deviate (0.18.0) and summarize-delivery (0.17.0) both shipped this way", + "seeds": [ + "c2" + ] + }, + { + "id": "s2", + "surface": "devague/cli/_commands/learn.py (OPERATOR_SKILLS at line 280, six-skill wording at lines 393/412/435)", + "finding": "learn skills now teaches all six operator skills from a data tuple; adding challenge is one tuple entry plus wording \u2014 teaching content, not a new engine", + "seeds": [ + "c3" + ] + }, + { + "id": "s3", + "surface": "README.md:82-94, CLAUDE.md Status/Project-intent, docs/skills.md flow table, docs/skill-sources.md origin table", + "finding": "four doc surfaces name the six-leg flow and the origin-skill family explicitly; all four must move to seven legs together or the docs drift", + "seeds": [ + "c4" + ] + }, + { + "id": "s4", + "surface": "docs/spec-contract.md vocabulary + devague/plan.py RISK_KINDS + .claude/skills/scope/SKILL.md findings table", + "finding": "the existing move vocabulary already covers every challenge output: findings as capture kinds (requirement/assumption/boundary/non_goal/decision), pressure-tests as interrogate, pending decisions as question, open vagueness as park, examined surfaces as devague scope entries, residual plan risk as plan risk with the four vagueness kinds \u2014 no gap forcing a new CLI verb", + "seeds": [ + "c5", + "c8", + "c9" + ] + }, + { + "id": "s5", + "surface": "issue 73 (integration options, success criteria) + CLAUDE.md three-human-gates section", + "finding": "issue author prefers a distinct mandatory-but-proportional operator pass with no new CLI engine; success criteria require findings to reconverge the authoritative frame and forbid claiming zero unknown unknowns \u2014 and the three-gate structure stays untouched", + "seeds": [ + "c6", + "c7", + "c10", + "c11" + ] + }, + { + "id": "s6", + "surface": "challenge pass / hidden-dependency lens: tests/test_cli_learn.py lines 43-56", + "finding": "the learn tests hardcode the origin-skill tuple, METHOD_ONLY_NAMES, and parametrized skills:name cases \u2014 they must move to seven skills in lockstep with learn.py or CI fails; lands as acceptance criteria on the learn-content plan task under c3", + "seeds": [ + "c3" + ] + }, + { + "id": "s7", + "surface": "challenge pass / adjacent-systems lens: .claude/skills.local.yaml.example, culture.yaml, .github/workflows", + "finding": "clean pass \u2014 none of these carry a skill-count dependency; no change needed", + "seeds": [] + }, + { + "id": "s8", + "surface": "challenge pass / failure-mode + reversibility lenses over the spec itself", + "finding": "no CLI behavior change means no version-skew failure mode for installed devague binaries (learn.py text is the only code delta); change is docs+skill additive, fully reversible by revert; concurrency and data-loss lenses not applicable to a docs-only delivery", + "seeds": [] + } + ] +} diff --git a/.devague/plans/challenge-skill.json b/.devague/plans/challenge-skill.json new file mode 100644 index 0000000..ec6f101 --- /dev/null +++ b/.devague/plans/challenge-skill.json @@ -0,0 +1,226 @@ +{ + "slug": "challenge-skill", + "title": "challenge skill", + "frame_slug": "challenge-skill", + "schema_version": 2, + "status": "exported", + "created": "2026-07-15T06:30:49Z", + "updated": "2026-07-15T06:32:56Z", + "targets": [ + { + "id": "c1", + "kind": "announcement", + "text": "devague gains a seventh origin skill, /challenge \u2014 a risk-scaled blind-spot discovery pass that pressure-tests the converged frame between /think and /spec-to-plan through structured lenses, routes every finding back through the existing deterministic moves, and records examined surfaces plus residual uncertainty instead of ever claiming there are no unknown unknowns" + }, + { + "id": "h1", + "kind": "honesty", + "text": "the shipped SKILL.md actually is what the announcement claims: risk-scaled (an explicit proportionality rule), positioned between /think and /spec-to-plan in every flow doc, findings routed only through existing deterministic moves, and a no-unknown-unknowns-claim rule" + }, + { + "id": "c2", + "kind": "requirement", + "text": "the new skill ships as .claude/skills/challenge/SKILL.md in the method-only shape \u2014 SKILL.md only, no scripts/ resolver, `type: command` frontmatter, a Provenance section naming devague as origin \u2014 matching the shipped deviate and summarize-delivery skills and the two-shape rule in docs/skills.md" + }, + { + "id": "h2", + "kind": "honesty", + "text": "listing .claude/skills/challenge/ shows exactly one file, SKILL.md, whose frontmatter carries `type: command` and whose Provenance section names devague as origin \u2014 no scripts/ directory" + }, + { + "id": "c3", + "kind": "requirement", + "text": "devague/cli/_commands/learn.py OPERATOR_SKILLS gains a seventh entry for challenge and its six-skill / six-leg wording updates, so `devague learn skills` and `skills:challenge` teach the new skill; this is teaching-content in the existing learn verb, not a new engine" + }, + { + "id": "h3", + "kind": "honesty", + "text": "`devague learn skills:challenge` exits 0 and emits the challenge authoring recipe; `devague learn skills` output says seven operator skills in seven-leg order" + }, + { + "id": "c4", + "kind": "requirement", + "text": "every surface naming the six-leg flow is updated to seven legs with challenge third: README.md (lines 82-94), CLAUDE.md (Status + Project intent), docs/skills.md (flow table + per-skill section), docs/skill-sources.md (origin-skills table + dont-re-vendor list)" + }, + { + "id": "h4", + "kind": "honesty", + "text": "grepping README.md, CLAUDE.md, docs/skills.md, and docs/skill-sources.md for six-leg wording returns no hits, and all four surfaces name challenge as the third leg" + }, + { + "id": "c5", + "kind": "boundary", + "text": "no new CLI engine, verb, or state model \u2014 challenge findings route through the existing deterministic moves only: capture / interrogate / question / park on the frame, `devague scope` for examined surfaces, `devague plan risk` for residual risk; the CLI stays deterministic and non-orchestrating per issue 20 and the issue 73 stated preference" + }, + { + "id": "h5", + "kind": "honesty", + "text": "the PR diff registers no new argparse subparser, adds no new devague/ module or store, and the only devague/ code change is teaching content in cli/_commands/learn.py" + }, + { + "id": "c7", + "kind": "requirement", + "text": "when the pass finds nothing, it records which lenses and surfaces were examined and what residual uncertainty remains \u2014 it never claims there are no unknown unknowns (issue 73 success criteria; anti-fabrication contract in docs/llm-guidance.md)" + }, + { + "id": "h6", + "kind": "honesty", + "text": "the SKILL.md hard-rules section contains an explicit rule forbidding a no-unknown-unknowns conclusion, with the required fallback of recording examined lenses/surfaces plus residual uncertainty" + }, + { + "id": "c12", + "kind": "audience", + "text": "operators \u2014 the main agent driving the deterministic CLI move by move \u2014 and the humans who own the spec and implementation-split-plan gates; downstream, the AgentCulture mesh once guildmaster re-broadcasts the skill" + }, + { + "id": "h7", + "kind": "honesty", + "text": "the SKILL.md description and body address the operator (move-by-move CLI driving) and the gate-owning human (confirmation of findings) as distinct readers, matching the other six origin skills" + }, + { + "id": "c13", + "kind": "before_state", + "text": "a frame can converge on precisely stated claims while the original framing is still incomplete: open questions only capture uncertainty someone already noticed \u2014 nothing actively hunts omitted dimensions, hidden dependencies, or shared assumptions, and no record exists of which surfaces were ever examined (issue 73 problem statement)" + }, + { + "id": "h8", + "kind": "honesty", + "text": "issue 73's problem statement is accurately reflected: before this change no devague surface actively searched for omitted dimensions or recorded examined surfaces at spec time" + }, + { + "id": "c14", + "kind": "why_it_matters", + "text": "an articulated blind spot becomes a known unknown the method can manage; an unexamined one surfaces later as a mid-run /deviate or a production surprise \u2014 the pass raises the odds of discovery before planning and lowers the cost of the surprises that remain (issue 73)" + }, + { + "id": "h9", + "kind": "honesty", + "text": "the skill's intro states the surprise-cost rationale \u2014 discovery before planning is cheaper than /deviate mid-run or a production surprise \u2014 rather than promising to eliminate unknown unknowns" + }, + { + "id": "c15", + "kind": "after_state", + "text": "a converged frame no longer slides straight into planning untested: the operator runs a proportional challenge pass over structured lenses, every finding lands as a proposed claim, question, or park that the user adjudicates, the frame reconverges, and the exported spec carries examined-surfaces provenance and residual uncertainty" + }, + { + "id": "h10", + "kind": "honesty", + "text": "a dogfooded /challenge run on a real converged frame produces only proposed findings, triggers reconvergence, and the re-exported spec renders the examined surfaces \u2014 verified before the skill is called done" + }, + { + "id": "c16", + "kind": "success_signal", + "text": "every challenge pass leaves at least 1 durable record \u2014 proposed findings routed through existing moves, or examined-surfaces entries with residual uncertainty on a clean pass; 0 passes conclude with a bare no-issues-found, and 0 LLM-origin findings reach confirmed status without an explicit user confirm" + }, + { + "id": "h11", + "kind": "honesty", + "text": "the success-signal counts are checkable from state alone: frame JSON plus session transcript show every finding's lens/surface trace and zero llm-origin items confirmed without a user confirm move" + } + ], + "tasks": [ + { + "id": "t1", + "summary": "Author .claude/skills/challenge/SKILL.md \u2014 the seventh origin skill, method-only shape", + "origin": "llm", + "status": "confirmed", + "acceptance_criteria": [ + ".claude/skills/challenge/ contains exactly one file, SKILL.md; frontmatter carries name: challenge, type: command, and a description with trigger phrases naming devague as origin", + "the hard-rules section explicitly forbids concluding there are no unknown unknowns and requires recording examined lenses/surfaces plus residual uncertainty on a clean pass via `devague scope` entries and `park`", + "the body carries the proportionality rule with the named escalation signals (migrations, security-sensitive work, distributed state, hardware, destructive operations, hard-to-reverse changes, concurrency hazards, data-loss surfaces), the structured lenses, a findings-routing table using only existing moves (capture / interrogate / question / park / `devague scope` / `devague plan risk`), the after-/think-export timing with the reconverge-and-re-export loop, and resilience-placement coaching (spec-side when it changes what, plan-side when it changes how)", + "the intro states the before-state and surprise-cost rationale from issue 73 (nothing previously hunted omitted dimensions; discovery before planning is cheaper than a mid-run /deviate) and addresses both audiences \u2014 the operator and the gate-owning human", + "a worked example uses only real devague verbs (each appears in devague --help or devague plan --help); a Provenance section names devague as origin, seventh in the outbound family, guildmaster as re-broadcaster; markdownlint-cli2 on the file passes" + ], + "deps": [], + "covers": [ + "c1", + "h1", + "c2", + "h2", + "c7", + "h6", + "c12", + "h7", + "c13", + "h8", + "c14", + "h9", + "c15", + "h10", + "c16", + "h11" + ], + "instruction": "Model the shape on .claude/skills/deviate/SKILL.md and .claude/skills/scope/SKILL.md (the method-only shape: SKILL.md only, no scripts/). Source of truth: docs/specs/2026-07-15-challenge-skill.md \u2014 quote decisions c17 (run after /think export, before plan new; findings reopen, reconverge, re-export the same dated file), c18 (resilience both-by-nature), c19 (escalation signal list) rather than re-deriving them. Flow position: seventh leg, third in order \u2014 scope, think, challenge, spec-to-plan, assign-to-workforce, deviate, summarize-delivery. Include the six output categories from issue 73 (known facts / assumptions / known unknowns / unexamined surfaces / residual surprise risk / resilience measures) mapped to their landing moves." + }, + { + "id": "t2", + "summary": "learn teaches challenge: devague/cli/_commands/learn.py + tests/test_cli_learn.py in lockstep", + "origin": "llm", + "status": "confirmed", + "acceptance_criteria": [ + "`uv run devague learn skills:challenge` exits 0 and emits the challenge authoring recipe; `learn skills` and `learn skills:all` name seven operator skills in seven-leg order with challenge third, method-only (no script URL)", + "tests/test_cli_learn.py's origin-skill tuple, METHOD_ONLY_NAMES, and every parametrized skills:name case include challenge; `uv run pytest -n auto` passes", + "no stale six-skill or six-leg wording remains anywhere in devague/cli/_commands/learn.py", + "the diff adds no new argparse subparser, no new devague/ module, and no new store \u2014 the only devague/ code change is teaching content in learn.py" + ], + "deps": [], + "covers": [ + "c3", + "h3", + "c5", + "h5" + ], + "instruction": "Insert one OPERATOR_SKILLS entry for challenge in flow order (third, after think) with method_only semantics matching scope/deviate/summarize-delivery entries; update the six-to-seven wording at learn.py lines 212, 252, 280, 393, 412, 435. Mirror in tests/test_cli_learn.py lines 43-56 (tuple + METHOD_ONLY_NAMES) and the parametrized lists around lines 128-175. Write the failing tests first." + }, + { + "id": "t3", + "summary": "Seven-leg docs sweep: README.md, CLAUDE.md, docs/skills.md, docs/skill-sources.md", + "origin": "llm", + "status": "confirmed", + "acceptance_criteria": [ + "grepping the four files for six-leg / six leg / six operator wording returns no hits; all four name the seven-leg order with challenge third", + "docs/skills.md gains a challenge per-skill section and flow-table row whose description matches the shipped SKILL.md; docs/skill-sources.md gains the challenge outbound origin row and adds challenge to the do-not-re-vendor list", + "markdownlint-cli2 on the four files passes" + ], + "deps": [ + "t1" + ], + "covers": [ + "c4", + "h4" + ], + "instruction": "Depends on t1: quote the shipped .claude/skills/challenge/SKILL.md description into docs/skills.md and the skill-sources row instead of paraphrasing. README.md lines 82-94 and CLAUDE.md (Status paragraph + Project intent + ecosystem origin-skill list) move to seven legs. Keep CLAUDE.md's Status section style: newest release paragraph first." + }, + { + "id": "t4", + "summary": "Version bump to 0.19.0 + CHANGELOG entry; full gate green", + "origin": "llm", + "status": "confirmed", + "acceptance_criteria": [ + "pyproject.toml version is 0.19.0 and a Keep-a-Changelog 0.19.0 entry names the challenge skill, the learn/tests update, and the docs sweep, citing issue 73", + "on the final tree: uv run pytest -n auto, flake8, black --check, isort --check --profile black, and markdownlint-cli2 on changed markdown all pass" + ], + "deps": [ + "t1", + "t2", + "t3" + ], + "covers": [], + "instruction": "Use the vendored version-bump skill (scripts/bump.py, minor). The package version single-sources from pyproject via importlib.metadata \u2014 no __init__.py edit needed. Changelog entry lists: Added (challenge skill, seventh leg), Changed (learn teaches seven skills; docs to seven-leg flow)." + } + ], + "risks": [ + { + "id": "r1", + "text": "guildmaster re-vendors /challenge and re-broadcasts to the mesh on its own schedule \u2014 outside this repo's control; the skill-sources row documents the re-vendor path", + "kind": "follow_up", + "task_id": null + }, + { + "id": "r2", + "text": "proportionality calibration (lightweight vs rigorous) is only observable across future dogfooded runs; watch the first passes for over- or under-escalation", + "kind": "unknown_nonblocking", + "task_id": null + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6822362..05c3913 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file. Format follows [Keep a Changelog](https://keepachangelog.com/). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.19.0] - 2026-07-15 + +### Added + +- **New seventh origin skill `/challenge`** (`.claude/skills/challenge/SKILL.md`) — + method-only: no script, no new CLI verb. A risk-scaled blind-spot discovery + pass between `/think` and `/spec-to-plan` that pressure-tests a converged, + exported frame; findings route back through existing deterministic moves as + proposed-only content for the human to adjudicate, and a clean pass records + the examined surfaces plus residual uncertainty instead of claiming there + are no unknown unknowns (#73). + +### Changed + +- **`devague learn skills` now teaches seven operator skills** in seven-leg + flow order (`learn.py` and its tests updated in lockstep); README.md, + CLAUDE.md, `docs/skills.md`, and `docs/skill-sources.md` moved from the + six-leg to the seven-leg flow (#73). + ## [0.18.1] - 2026-07-15 ### Fixed diff --git a/CLAUDE.md b/CLAUDE.md index f6a9da0..05ab3ea 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,6 +4,22 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Status +**The challenge skill lands — the seventh leg (0.19.0, #73).** New seventh +origin skill **`/challenge`** (`.claude/skills/challenge/SKILL.md`) — a +risk-scaled blind-spot discovery pass that runs after `/think` exports and +before `devague plan new`, pressure-testing the converged, exported frame +through structured lenses. Method-only: no script, no new CLI verb, no new +engine (#20) — every finding routes back through the existing deterministic +moves (`capture`, `interrogate`, `park`, …) as proposed-only content for the +human to adjudicate, and a reopened frame reconverges and re-exports before +the plan leg proceeds. A clean pass records the examined surfaces and +residual uncertainty via existing moves (`devague scope` entries, `park`, +`plan risk`) — never a claim that there are no unknown unknowns. +`devague learn skills` now teaches all **seven** operator skills in seven-leg +order; `README.md`, this file, `docs/skills.md`, and `docs/skill-sources.md` +are swept to the seven-leg flow — `scope` → `think` → `challenge` → +`spec-to-plan` → `assign-to-workforce` → `deviate` → `summarize-delivery`. + **The execution seam and deviate (0.18.0, #53 esd t1–t11).** The flow gains a **sixth leg** — **`deviate`** — plus the read-only "end state" that closes the loop between a confirmed plan and what the workforce actually produces mid-run. @@ -29,10 +45,11 @@ verbatim (#69, #70); `summarize-delivery` now starts from the `devague summary` skeleton and quotes approved deviations by `dN` id instead of reconstructing drift from memory. `culture.yaml` reverts `backend` to `claude`, the mesh standard, now that `agex-cli#46` is closed (#66). Docs (this file, `README.md`, -`docs/skills.md`) now name the **six-leg flow** — `scope` → `think` → -`spec-to-plan` → `assign-to-workforce` → `deviate` → `summarize-delivery` — and -the two audiences it serves: operators (the main agent driving the CLI) and -the humans who own the go/no-go and final-PR gates. +`docs/skills.md`) now name the **seven-leg flow** — `scope` → `think` → +`challenge` → `spec-to-plan` → `assign-to-workforce` → `deviate` → +`summarize-delivery` — and the two audiences it serves: operators (the main +agent driving the CLI) and the humans who own the go/no-go and final-PR +gates. **Operator kit carries the sharper method + new `/scope` skill (0.15.0).** The sharper end-to-end method spec+plan merged in #53 (0.14.1: docs + state only); @@ -257,18 +274,20 @@ and hard questions, parking unresolved uncertainty as first-class "open vagueness," and only exporting a buildable spec once the frame *converges*. The plan method: seed a plan from that converged frame and converge it on coverage, acceptance criteria, and an acyclic dependency order before exporting a plan. -The operator skills cover the **six legs** in flow order: **`/scope`** +The operator skills cover the **seven legs** in flow order: **`/scope`** (idea→explored scope, the optional opening leg), **`/think`** (idea→spec), -**`/spec-to-plan`** (spec→plan), **`/assign-to-workforce`** -(plan→parallel implementation), **`/deviate`** (the execution-time leg — stop -an in-flight fan-out the moment it must diverge from the confirmed plan, get -explicit human approval, and record the divergence before resuming), and -**`/summarize-delivery`** (execution→a committed accountability artifact, the -delivery-side closure leg); the product/CLI they drive is **`devague`**. The -skills are written for two audiences: **operators** — the main agent driving -the deterministic CLI move by move — and the **humans** who own the go/no-go -decision on the implementation split plan (gate 2, including any deviation -against it) and the final PR review (gate 3). +**`/challenge`** (a risk-scaled blind-spot discovery pass between /think and +/spec-to-plan, adjudicated inside the existing spec gate), **`/spec-to-plan`** +(spec→plan), **`/assign-to-workforce`** (plan→parallel implementation), +**`/deviate`** (the execution-time leg — stop an in-flight fan-out the moment +it must diverge from the confirmed plan, get explicit human approval, and +record the divergence before resuming), and **`/summarize-delivery`** +(execution→a committed accountability artifact, the delivery-side closure +leg); the product/CLI they drive is **`devague`**. The skills are written for +two audiences: **operators** — the main agent driving the deterministic CLI +move by move — and the **humans** who own the go/no-go decision on the +implementation split plan (gate 2, including any deviation against it) and +the final PR review (gate 3). This is a **state machine over claims, honesty conditions, open vagueness, and convergence** driven by LLM-chosen moves — not a linear wizard. The CLI is @@ -294,9 +313,9 @@ steward→guildmaster cutover; `steward` is still a sibling but no longer broadcasts). Vendored skills are cited, not imported (cite-don't-import): copy from `../guildmaster/.claude/skills//` and track provenance in `docs/skill-sources.md`. The exception is devague's own `scope` / `think` / -`spec-to-plan` / `assign-to-workforce` / `deviate` / `summarize-delivery` — -devague is their origin, so guildmaster re-broadcasts them *from* here; never -re-vendor them back. +`challenge` / `spec-to-plan` / `assign-to-workforce` / `deviate` / +`summarize-delivery` — devague is their origin, so guildmaster re-broadcasts +them *from* here; never re-vendor them back. ## Stack expectations (when code lands) diff --git a/README.md b/README.md index b304d10..9f4a1eb 100644 --- a/README.md +++ b/README.md @@ -79,19 +79,22 @@ committed. ## Driving it from an agent Inside AgentCulture, an assistant drives this CLI through a family of operator -skills that cover the **six-leg flow** end to end, in order: **`/scope`** +skills that cover the **seven-leg flow** end to end, in order: **`/scope`** (idea→explored scope, the optional opening leg), **`/think`** (idea→spec), -**`/spec-to-plan`** (spec→plan), **`/assign-to-workforce`** +**`/challenge`** (a risk-scaled blind-spot discovery pass between /think and +/spec-to-plan), **`/spec-to-plan`** (spec→plan), **`/assign-to-workforce`** (plan→parallel implementation), **`/deviate`** (the execution-time leg — stop an in-flight fan-out the moment it must diverge from the confirmed plan, get explicit human approval via `devague deviate`, and resume), and -**`/summarize-delivery`** (execution→a committed accountability artifact). The -CLI-driving pair — `/think` and `/spec-to-plan` — add a portable wrapper and a -`status` next-move helper over the convergence gate; the CLI is the -deterministic affordance and the agent decides the next move. +**`/summarize-delivery`** (execution→a committed accountability artifact). +`/challenge` is method-only — no wrapper script, no new CLI verb; findings +route through the same moves `/think` already uses. The CLI-driving pair — +`/think` and `/spec-to-plan` — add a portable wrapper and a `status` +next-move helper over the convergence gate; the CLI is the deterministic +affordance and the agent decides the next move. These skills serve two audiences: **operators** — the main agent that drives -the deterministic CLI move by move across all six legs — and the **humans** +the deterministic CLI move by move across all seven legs — and the **humans** who own the three standing gates: the exported spec, the go/no-go on the implementation split plan (including any mid-run deviation approved against it via `/deviate`), and the final PR review. See `CLAUDE.md` for that workflow diff --git a/devague/cli/_commands/learn.py b/devague/cli/_commands/learn.py index 3e5c7af..f2ca901 100644 --- a/devague/cli/_commands/learn.py +++ b/devague/cli/_commands/learn.py @@ -209,7 +209,7 @@ ) -# --- Authoring the six operator skills (devague#34, extended #53 esd) ------- +# --- Authoring the seven operator skills (devague#34, extended #53 esd, #73) - # # `devague learn` knows the operator skills exist but never taught an agent how # to *author* them. This section closes that gap: it is written as instructions @@ -244,12 +244,12 @@ " CLI-driving (think, spec-to-plan, assign-to-workforce):\n" " //SKILL.md frontmatter + the operating doc\n" " //scripts/.sh portable CLI resolver (executable)\n" - " Method-only (scope, deviate, summarize-delivery):\n" + " Method-only (scope, challenge, deviate, summarize-delivery):\n" " //SKILL.md frontmatter + the operating doc — " "no scripts/ directory; the skill invokes the devague CLI directly." ), "frontmatter": ( - "SKILL.md opens with YAML frontmatter (all six skills):\n" + "SKILL.md opens with YAML frontmatter (all seven skills):\n" " name: \n" " description: >\n" " one paragraph — what it does, when to use it, and that it is\n" @@ -265,8 +265,8 @@ " 2. else 'uv run devague' when inside a devague checkout;\n" " 3. else print the hint 'uv tool install devague' and exit non-zero.\n" "Copy the exact script from the per-skill source below — don't hand-write it.\n" - "The method-only skills (scope, deviate, summarize-delivery) have no " - "scripts/ resolver at all — SKILL.md invokes the devague CLI directly." + "The method-only skills (scope, challenge, deviate, summarize-delivery) have " + "no scripts/ resolver at all — SKILL.md invokes the devague CLI directly." ), "contract": ( "The skill drives the deterministic CLI and adds no logic of its own:\n" @@ -277,11 +277,12 @@ ), } -# The six operator skills, in six-leg workflow order (devague#53 esd): -# scope -> think -> spec-to-plan -> assign-to-workforce -> deviate -> summarize-delivery -# `method_only` marks the three that ship a SKILL.md and NO scripts/.sh -# resolver (scope, deviate, summarize-delivery) — they invoke the devague CLI -# directly rather than going through the portable resolver script. +# The seven operator skills, in seven-leg workflow order (devague#73): +# scope -> think -> challenge -> spec-to-plan -> assign-to-workforce -> deviate +# -> summarize-delivery +# `method_only` marks the four that ship a SKILL.md and NO scripts/.sh +# resolver (scope, challenge, deviate, summarize-delivery) — they invoke the +# devague CLI directly rather than going through the portable resolver script. OPERATOR_SKILLS = ( { "name": "scope", @@ -304,6 +305,19 @@ ), "method_only": False, }, + { + "name": "challenge", + "leg": "spec (third leg): a risk-scaled blind-spot discovery pass", + "role": ( + "Pressure-tests the converged, exported frame before 'devague plan new' " + "for blind spots a risk-scaled pass would catch. Findings route back " + "through existing deterministic moves (capture / interrogate / question / " + "park / scope entries / plan risk) and reopen-reconverge-re-export the " + "frame. On a clean pass it records examined surfaces plus residual " + "uncertainty — never claiming there are no unknown unknowns." + ), + "method_only": True, + }, { "name": "spec-to-plan", "leg": "spec -> plan (working forwards)", @@ -390,8 +404,8 @@ def _skills_text(names: tuple[str, ...], *, full: bool) -> str: "Authoring your operator skills (create them with user consent)", "=============================================================", "", - "devague is driven by six operator skills — three CLI-driving (a " - "scripts/.sh resolver) and three method-only (SKILL.md only, no " + "devague is driven by seven operator skills — three CLI-driving (a " + "scripts/.sh resolver) and four method-only (SKILL.md only, no " "resolver script). Recreate them in your own runtime so you can drive " "devague the same way everywhere.", "", @@ -409,7 +423,7 @@ def _skills_text(names: tuple[str, ...], *, full: bool) -> str: "", SKILL_AUTHORING["contract"], "", - "The six skills (six-leg workflow order):", + "The seven skills (seven-leg workflow order):", ] for s in OPERATOR_SKILLS: if s["name"] not in names: @@ -432,7 +446,7 @@ def _skills_text(names: tuple[str, ...], *, full: bool) -> str: parts.append("") if not full: parts.append( - "Run 'devague learn skills:all' for the source URLs of all six, or " + "Run 'devague learn skills:all' for the source URLs of all seven, or " "'devague learn skills:' for one." ) parts.append("") diff --git a/docs/deliveries/2026-07-15-challenge-skill.md b/docs/deliveries/2026-07-15-challenge-skill.md new file mode 100644 index 0000000..49d1ed9 --- /dev/null +++ b/docs/deliveries/2026-07-15-challenge-skill.md @@ -0,0 +1,115 @@ +# Delivery Summary — challenge skill + +plan: `challenge-skill` · run: `complete` · date: `2026-07-15` +baseline: `devague summary skeleton` + +## Intent + +Ship devague's seventh origin skill, `/challenge` — a risk-scaled blind-spot +discovery pass between `/think` and `/spec-to-plan` (issue #73) — by executing +the converged `challenge-skill` plan through `/assign-to-workforce`: four +tasks over three waves, one agent per task in an isolated git worktree, +TDD-gated merges, no new CLI engine (#20). + +> devague gains a seventh origin skill, /challenge — a risk-scaled blind-spot +> discovery pass that pressure-tests the converged frame between /think and +> /spec-to-plan through structured lenses, routes every finding back through +> the existing deterministic moves, and records examined surfaces plus +> residual uncertainty instead of ever claiming there are no unknown unknowns + +## Planned Work + +Quoted verbatim from the `devague summary` skeleton: + +- `t1` — Author .claude/skills/challenge/SKILL.md — the seventh origin skill, + method-only shape +- `t2` — learn teaches challenge: devague/cli/_commands/learn.py + + tests/test_cli_learn.py in lockstep +- `t3` — Seven-leg docs sweep: README.md, CLAUDE.md, docs/skills.md, + docs/skill-sources.md +- `t4` — Version bump to 0.19.0 + CHANGELOG entry; full gate green + +## Actual Delivery + +| Plan task | Status | What actually landed | +|-----------|--------|----------------------| +| `t1` | delivered | `.claude/skills/challenge/SKILL.md` (290 lines, sole file — method-only shape, `type: command`), all 5 acceptance criteria check-verified; commit `8ddd6b3`, merged `cca3d1b` | +| `t2` | delivered | one new `OPERATOR_SKILLS` entry + six→seven wording in `devague/cli/_commands/learn.py`, mirrored in `tests/test_cli_learn.py` (failing-first TDD: 8 failed → 616 passed); no new subparser/module/store; commit `a46bb33`, merged `b420372` | +| `t3` | delivered | seven-leg sweep of README.md, CLAUDE.md, docs/skills.md, docs/skill-sources.md — six-leg grep returns no hits, challenge third everywhere, shipped description quoted verbatim; commit `170dee2`, merged `735697d` | +| `t4` | delivered | `pyproject.toml` → 0.19.0 (+ `uv.lock`), Keep-a-Changelog 0.19.0 entry citing #73, and (per `d1`) the 0.19.0 CLAUDE.md Status paragraph; commit `d8758e0`, merged `fa49c23` | + +## Mid-work Decisions + +- `d1` — t4 additionally prepends a 0.19.0 release paragraph to CLAUDE.md's + Status section (newest-first, repo convention) — the confirmed t4 acceptance + criteria name only pyproject.toml and CHANGELOG.md; every prior release + (0.15.0, 0.17.0, 0.18.0) also added a CLAUDE.md Status paragraph — omitting + it would leave the Status section stale at 0.18.0 after this ships + (recorded via `/deviate`, human-approved before t4 was spawned). +- t3 updated the standing "six-leg flow" sentence *inside* the historical + 0.18.0 Status paragraph to "seven-leg" — no deviation record covers this; + t3's confirmed acceptance criterion 1 ("grepping the four files for six-leg + wording returns no hits") required it, and the two purely historical + "sixth" mentions in the same paragraph were left untouched. +- t3 kept README's "CLI-driving pair" framing (think / spec-to-plan) instead + of grouping `/challenge` with the scripted skills, since challenge ships + method-only with no wrapper script — a fidelity choice, captured here + directly. +- The final PR was opened with `gh pr create` directly instead of the `cicd` + skill's `agex pr open` wrapper, which failed transiently and treated + pre-existing untracked working files as fatal; the `- devague (Claude)` + signature was appended manually per convention. +- t1 attributes the spec's decision quotes as c17/c18/c19 (ids from the plan + brief's mapping) even though the exported spec lists decisions unlabeled — + flagged by the task agent, accepted as-is. + +## Drift From Plan + +| Plan item | Reason for divergence | Classification | +|-----------|-----------------------|----------------| +| `t4` (`d1`) | the confirmed t4 acceptance criteria name only pyproject.toml and CHANGELOG.md; every prior release (0.15.0, 0.17.0, 0.18.0) also added a CLAUDE.md Status paragraph — omitting it would leave the Status section stale at 0.18.0 after this ships | acceptable | + +No other task drifted: t1, t2, and t3 delivered exactly against their +confirmed acceptance criteria (task-by-task accounting above). + +## Evidence + +- tests: `uv run pytest -n auto` — pass, **616 passed** (run after every wave + merge: post-t2, post-t1, post-t3, post-t4) +- tests (TDD proof, t2): `tests/test_cli_learn.py` — 8 failed on + tests-first run, green after implementation +- lint: `uv run flake8 --config=.flake8 devague/ tests/` — exit 0; + `uv run black --check devague/ tests/` — clean; + `uv run isort --check --profile black devague/ tests/` — exit 0; + `markdownlint-cli2` on every changed markdown file — 0 errors +- version: `uv run devague --version` — `devague 0.19.0` +- commits: `a19819f..fa49c23` on `feat/challenge-skill` (spec `51f8490`, + plan `2baa17c`, tasks `8ddd6b3` / `a46bb33` / `170dee2` / `d8758e0`, + deviation ledger `f114634`) +- PRs / issues: PR #76 · issue #73 +- deviation ledger: `.devague/deliveries/challenge-skill.json` (`d1`, + approved, acceptable) + +## Delivery Claims + +| Claim | Confidence | Evidence | +|-------|------------|----------| +| `/challenge` ships as the seventh origin skill in the method-only shape (SKILL.md only, `type: command`, no new CLI verb) | high | file `.claude/skills/challenge/SKILL.md` · commit `8ddd6b3` · PR #76 | +| the skill's hard rules forbid a "no unknown unknowns" conclusion and require examined-surfaces + residual-uncertainty records on a clean pass | high | commit `8ddd6b3` (grep-verified against acceptance criteria 2/3) | +| `devague learn skills` teaches seven operator skills in seven-leg order, challenge third, method-only | high | commit `a46bb33` · `tests/test_cli_learn.py` in the 616-green suite | +| the CLI gained no new engine, verb, or store — the boundary (#20) held | high | t2 diff scope check (only `learn.py` + its tests under `devague/`) · commit `a46bb33` | +| all four doc surfaces name the seven-leg flow with challenge third | high | commit `170dee2` (six-leg grep: no hits) | +| 0.19.0 release prep is complete (version, changelog, Status paragraph) | high | commit `d8758e0` · `devague 0.19.0` | +| a `/challenge` pass following the shipped SKILL.md text end-to-end works on a real frame | unverified | the pass this run performed (scope entries s6–s8, parks v1–v2 on the `challenge-skill` frame) executed the specced method *before* the SKILL.md text existed; the first post-merge run per the shipped doc is follow-up evidence — not claimed done | + +## Remaining Work / Follow-up + +- Gate 3 — human review and merge of PR #76 (the final human gate; this + artifact is its review map). +- Dogfood the shipped `/challenge` on the next real frame and watch the + proportionality rule for over-/under-escalation (frame park `v2`, + plan risk `r2`, and the `unverified` claim above — same follow-up). +- guildmaster re-vendors `/challenge` from + `../devague/.claude/skills/challenge/` and re-broadcasts to the mesh on its + own schedule (frame park `v1`, plan risk `r1`; the docs/skill-sources.md row + documents the path). diff --git a/docs/plans/2026-07-15-challenge-skill.md b/docs/plans/2026-07-15-challenge-skill.md new file mode 100644 index 0000000..a08022a --- /dev/null +++ b/docs/plans/2026-07-15-challenge-skill.md @@ -0,0 +1,51 @@ +# Build Plan — challenge skill + +slug: `challenge-skill` · status: `exported` · from frame: `challenge-skill` + +> devague gains a seventh origin skill, /challenge — a risk-scaled blind-spot discovery pass that pressure-tests the converged frame between /think and /spec-to-plan through structured lenses, routes every finding back through the existing deterministic moves, and records examined surfaces plus residual uncertainty instead of ever claiming there are no unknown unknowns + +## Tasks + +### t1 — Author .claude/skills/challenge/SKILL.md — the seventh origin skill, method-only shape + +- instruction: Model the shape on .claude/skills/deviate/SKILL.md and .claude/skills/scope/SKILL.md (the method-only shape: SKILL.md only, no scripts/). Source of truth: docs/specs/2026-07-15-challenge-skill.md — quote decisions c17 (run after /think export, before plan new; findings reopen, reconverge, re-export the same dated file), c18 (resilience both-by-nature), c19 (escalation signal list) rather than re-deriving them. Flow position: seventh leg, third in order — scope, think, challenge, spec-to-plan, assign-to-workforce, deviate, summarize-delivery. Include the six output categories from issue 73 (known facts / assumptions / known unknowns / unexamined surfaces / residual surprise risk / resilience measures) mapped to their landing moves. +- covers: c1, h1, c2, h2, c7, h6, c12, h7, c13, h8, c14, h9, c15, h10, c16, h11 +- acceptance: + - .claude/skills/challenge/ contains exactly one file, SKILL.md; frontmatter carries name: challenge, type: command, and a description with trigger phrases naming devague as origin + - the hard-rules section explicitly forbids concluding there are no unknown unknowns and requires recording examined lenses/surfaces plus residual uncertainty on a clean pass via `devague scope` entries and `park` + - the body carries the proportionality rule with the named escalation signals (migrations, security-sensitive work, distributed state, hardware, destructive operations, hard-to-reverse changes, concurrency hazards, data-loss surfaces), the structured lenses, a findings-routing table using only existing moves (capture / interrogate / question / park / `devague scope` / `devague plan risk`), the after-/think-export timing with the reconverge-and-re-export loop, and resilience-placement coaching (spec-side when it changes what, plan-side when it changes how) + - the intro states the before-state and surprise-cost rationale from issue 73 (nothing previously hunted omitted dimensions; discovery before planning is cheaper than a mid-run /deviate) and addresses both audiences — the operator and the gate-owning human + - a worked example uses only real devague verbs (each appears in devague --help or devague plan --help); a Provenance section names devague as origin, seventh in the outbound family, guildmaster as re-broadcaster; markdownlint-cli2 on the file passes + +### t2 — learn teaches challenge: devague/cli/_commands/learn.py + tests/test_cli_learn.py in lockstep + +- instruction: Insert one OPERATOR_SKILLS entry for challenge in flow order (third, after think) with method_only semantics matching scope/deviate/summarize-delivery entries; update the six-to-seven wording at learn.py lines 212, 252, 280, 393, 412, 435. Mirror in tests/test_cli_learn.py lines 43-56 (tuple + METHOD_ONLY_NAMES) and the parametrized lists around lines 128-175. Write the failing tests first. +- covers: c3, h3, c5, h5 +- acceptance: + - `uv run devague learn skills:challenge` exits 0 and emits the challenge authoring recipe; `learn skills` and `learn skills:all` name seven operator skills in seven-leg order with challenge third, method-only (no script URL) + - tests/test_cli_learn.py's origin-skill tuple, METHOD_ONLY_NAMES, and every parametrized skills:name case include challenge; `uv run pytest -n auto` passes + - no stale six-skill or six-leg wording remains anywhere in devague/cli/_commands/learn.py + - the diff adds no new argparse subparser, no new devague/ module, and no new store — the only devague/ code change is teaching content in learn.py + +### t3 — Seven-leg docs sweep: README.md, CLAUDE.md, docs/skills.md, docs/skill-sources.md + +- instruction: Depends on t1: quote the shipped .claude/skills/challenge/SKILL.md description into docs/skills.md and the skill-sources row instead of paraphrasing. README.md lines 82-94 and CLAUDE.md (Status paragraph + Project intent + ecosystem origin-skill list) move to seven legs. Keep CLAUDE.md's Status section style: newest release paragraph first. +- depends on: t1 +- covers: c4, h4 +- acceptance: + - grepping the four files for six-leg / six leg / six operator wording returns no hits; all four name the seven-leg order with challenge third + - docs/skills.md gains a challenge per-skill section and flow-table row whose description matches the shipped SKILL.md; docs/skill-sources.md gains the challenge outbound origin row and adds challenge to the do-not-re-vendor list + - markdownlint-cli2 on the four files passes + +### t4 — Version bump to 0.19.0 + CHANGELOG entry; full gate green + +- instruction: Use the vendored version-bump skill (scripts/bump.py, minor). The package version single-sources from pyproject via importlib.metadata — no __init__.py edit needed. Changelog entry lists: Added (challenge skill, seventh leg), Changed (learn teaches seven skills; docs to seven-leg flow). +- depends on: t1, t2, t3 +- acceptance: + - pyproject.toml version is 0.19.0 and a Keep-a-Changelog 0.19.0 entry names the challenge skill, the learn/tests update, and the docs sweep, citing issue 73 + - on the final tree: uv run pytest -n auto, flake8, black --check, isort --check --profile black, and markdownlint-cli2 on changed markdown all pass + +## Risks + +- [follow_up] guildmaster re-vendors /challenge and re-broadcasts to the mesh on its own schedule — outside this repo's control; the skill-sources row documents the re-vendor path +- [unknown_nonblocking] proportionality calibration (lightweight vs rigorous) is only observable across future dogfooded runs; watch the first passes for over- or under-escalation diff --git a/docs/skill-sources.md b/docs/skill-sources.md index 13889d9..031e342 100644 --- a/docs/skill-sources.md +++ b/docs/skill-sources.md @@ -35,13 +35,14 @@ upstream repo are shared across all inbound rows. ## Origin skills (outbound) -Not every skill here is inbound. The `scope`, `think`, `spec-to-plan`, `assign-to-workforce`, -`deviate`, and `summarize-delivery` skills are **authored and maintained in -this repo** — devague is their origin/upstream, not a downstream consumer. The -devague agent dogfoods them to operate the devague CLI while improving the -tool. The flow runs the *opposite* direction of the table above: `guildmaster` -re-vendors them from here and re-broadcasts them to the mesh. (The skill names -are `scope` / `think` / `spec-to-plan` / `assign-to-workforce` / `deviate` / +Not every skill here is inbound. The `scope`, `think`, `challenge`, +`spec-to-plan`, `assign-to-workforce`, `deviate`, and `summarize-delivery` +skills are **authored and maintained in this repo** — devague is their +origin/upstream, not a downstream consumer. The devague agent dogfoods them +to operate the devague CLI while improving the tool. The flow runs the +*opposite* direction of the table above: `guildmaster` re-vendors them from +here and re-broadcasts them to the mesh. (The skill names are `scope` / +`think` / `challenge` / `spec-to-plan` / `assign-to-workforce` / `deviate` / `summarize-delivery`; the product/CLI they drive is `devague`. `think` was renamed from `devague` in 0.4.0 — when guildmaster re-vendors, it must relearn the new name.) Because devague is upstream, these are **not** re-vendored @@ -51,12 +52,14 @@ issue #38 reply). As of 0.13.0 (#38) all origin skills carry `type: command` at the source, so guildmaster's re-broadcast copies (which had to add it on vendor for the culture/agex backend) match the source and need no patch. `scope` (new in -0.15.0) and `deviate` (new in 0.18.0) both shipped with it from day one. +0.15.0), `deviate` (new in 0.18.0), and `challenge` (new in 0.19.0) all +shipped with it from day one. | Skill | Origin | Downstream | Notes | |-------|--------|------------|-------| | `scope` | **devague** (here: `.claude/skills/scope/`) | `guildmaster`, then the AgentCulture mesh | Operator for the **idea→scope** leg: the optional pre-frame exploration stage from the sharper end-to-end method spec (devague#53). Method-only today — no entry-point script; findings land through existing `devague` moves via the `/think` wrapper. The deterministic `devague scope` CLI move (first-class findings with provenance) is planned in the #53 build plan (task t3); its `devague learn skills` authoring recipe lands with that move (tasks t10/t11). New in 0.15.0. Re-vendor from `../devague/.claude/skills/scope/`. | | `think` | **devague** (here: `.claude/skills/think/`) | `guildmaster`, then the AgentCulture mesh | Operator for the **idea→spec** leg of the deterministic devague CLI: portable resolution, driving the flat `devague ` verbs (`status` is now a first-class CLI verb, not embedded Python). Renamed from `devague` in 0.4.0. `guildmaster` re-vendors it from `../devague/.claude/skills/think/` and broadcasts it to the mesh. | +| `challenge` | **devague** (here: `.claude/skills/challenge/`) | `guildmaster`, then the AgentCulture mesh | Operator for the **spec** leg, third in flow order — quoted verbatim from the shipped `SKILL.md` frontmatter `description`: "a risk-scaled blind-spot discovery pass over a converged, exported frame BETWEEN /think and /spec-to-plan (the seventh origin skill, third leg in flow order): pressure-test the spec through structured lenses, route every finding back through the existing deterministic moves as proposed-only content the human adjudicates, and on a clean pass record the examined lenses/surfaces and residual uncertainty — never a claim that there are no unknown unknowns." Method-only — no entry-point script; findings route through existing deterministic moves only (`capture` / `interrogate` / `question` / `park` / `devague scope` / `devague plan risk`), never a new CLI verb, engine, or state model (#20, devague#73). Not a fourth standing gate — findings are adjudicated inside the existing spec gate. New in 0.19.0. Re-vendor from `../devague/.claude/skills/challenge/`. | | `spec-to-plan` | **devague** (here: `.claude/skills/spec-to-plan/`) | `guildmaster`, then the AgentCulture mesh | Operator for the **spec→plan** leg (`devague plan ...`): portable resolution over the plan convergence gate. New in 0.4.0. Re-vendor from `../devague/.claude/skills/spec-to-plan/`. | | `assign-to-workforce` | **devague** (here: `.claude/skills/assign-to-workforce/`) | `guildmaster`, then the AgentCulture mesh | Operator for the **implementation** leg (fan out `devague plan waves` to parallel agents in isolated git worktrees, with TDD-gated merges by the main agent). Three human gates only: spec / implementation split plan / final PR. The devague CLI remains non-orchestrating (#20) — this skill is the convention + helper, not new CLI behavior. New in 0.7.0. Re-vendor from `../devague/.claude/skills/assign-to-workforce/`. | | `deviate` | **devague** (here: `.claude/skills/deviate/`) | `guildmaster`, then the AgentCulture mesh | Operator for the **execution-time** leg: runs *during* an `/assign-to-workforce` fan-out, at the moment execution must diverge from the confirmed plan — stop the run, present what/why/what-it-affects, get explicit human approval, record via the deterministic `devague deviate` move (`--origin llm` lands proposed; only the user `--confirm`s), adjust the affected task briefs, resume. Not a fourth standing gate — the human owner of gate 2 (the implementation split plan) amending it mid-flight. Deviation records persist under `.devague/deliveries/.json` (devague#53 esd t3) and are the connective tissue `/summarize-delivery` quotes by `dN` id instead of reconstructing drift from memory. New in 0.18.0 (devague#53 esd t7). Re-vendor from `../devague/.claude/skills/deviate/`. | @@ -74,6 +77,7 @@ symlink/dependency. Written portable-first so they pass guildmaster's `../guildmaster/.claude/skills//`. - **Diverge intentionally.** Record any divergence in the table above and in the downstream `SKILL.md` frontmatter `description`. -- **Don't re-vendor devague-origin skills.** `scope` / `think` / `spec-to-plan` / - `assign-to-workforce` / `deviate` / `summarize-delivery` are authored here; pull - fixes forward into this repo, not back from guildmaster's re-broadcast copies. +- **Don't re-vendor devague-origin skills.** `scope` / `think` / `challenge` / + `spec-to-plan` / `assign-to-workforce` / `deviate` / `summarize-delivery` are + authored here; pull fixes forward into this repo, not back from + guildmaster's re-broadcast copies. diff --git a/docs/skills.md b/docs/skills.md index cf851ba..20c918c 100644 --- a/docs/skills.md +++ b/docs/skills.md @@ -137,7 +137,7 @@ A skill drives the deterministic CLI and adds no business logic of its own: ## The operator skills -The **six-leg flow**, with the two audiences each leg serves — **operators** +The **seven-leg flow**, with the two audiences each leg serves — **operators** (the main agent driving the CLI move by move) and the **humans** who own the three standing gates (the exported spec, the go/no-go on the implementation split plan — including any mid-run deviation approved against it — and the @@ -147,6 +147,7 @@ final PR review): |-------|-----|----------------| | `scope` | idea → explored scope (the optional opening leg) | read-only exploration; findings land via existing `devague` moves | | `think` | idea → spec (working backwards) | the flat `devague ` verbs | +| `challenge` | "a risk-scaled blind-spot discovery pass over a converged, exported frame BETWEEN /think and /spec-to-plan" | "pressure-test the spec through structured lenses, route every finding back through the existing deterministic moves as proposed-only content the human adjudicates" | | `spec-to-plan` | spec → plan (working forwards) | the `devague plan ` group | | `assign-to-workforce` | plan → parallel implementation | reads `devague plan waves` and `devague plan deliverables` (read-only) | | `deviate` | execution-time — an in-flight fan-out diverges from the confirmed plan | the `devague deviate` move (`--list [--json]`, `--confirm`/`--reject`), backed by the delivery store | @@ -184,6 +185,47 @@ first-class open vagueness, and `export` a spec only once the frame **converges* [`.claude/skills/think/`](https://github.com/agentculture/devague/blob/main/.claude/skills/think/SKILL.md) (`SKILL.md` + `scripts/think.sh`). +### `challenge` — risk-scaled blind-spot discovery pass (method-only) + +Quoted verbatim from the shipped `SKILL.md` frontmatter `description` (not +paraphrased, per the doc-sweep instruction that shipped it): + +> Run a risk-scaled blind-spot discovery pass over a converged, exported +> frame BETWEEN /think and /spec-to-plan (the seventh origin skill, third +> leg in flow order): pressure-test the spec through structured lenses, +> route every finding back through the existing deterministic moves as +> proposed-only content the human adjudicates, and on a clean pass record +> the examined lenses/surfaces and residual uncertainty — never a claim +> that there are no unknown unknowns. Use when the user says "challenge +> this spec", "blind-spot pass", "pressure-test the frame", "what are we +> missing", "unknown unknowns", or after /think exports and before +> `devague plan new`. Authored and maintained in agentculture/devague +> (origin = devague); guildmaster pulls this skill from here and broadcasts +> it to the AgentCulture mesh — it is NOT vendored from guildmaster like +> the inbound skills here. + +Concretely: it sweeps structured lenses (adjacent systems, unstated +assumptions, overlooked actors/lifecycle stages/failure modes, security/ +migration/concurrency/reversibility, missing observability/rollback, cheap +probes) against the exported spec, routes findings through the existing +deterministic moves (`capture` / `interrogate` / `question` / `park` / +`devague scope` / `devague plan risk`) as `--origin llm`-proposed content the +human adjudicates, then reconverges and re-exports the same dated spec file. +Mandatory but proportional — lightweight for ordinary work, rigorous when an +escalation signal (migrations, security-sensitive work, distributed state, +hardware, destructive or hard-to-reverse changes, concurrency hazards, any +data-loss surface) applies. Not a fourth standing gate: findings are +adjudicated inside the existing spec gate, mirroring how `/deviate` amends +gate 2 rather than adding one. + +The skill ships no entry-point script of its own — it drives the same flat +`devague ` verbs `/think` already uses, so no new CLI surface, +subparser, or state model exists to resolve (#20). New in 0.19.0. + +- Source: + [`.claude/skills/challenge/`](https://github.com/agentculture/devague/blob/main/.claude/skills/challenge/SKILL.md) + (`SKILL.md` only). + ### `spec-to-plan` — converged spec → buildable plan Seed a plan from a **converged** frame (`devague plan new --frame `), add diff --git a/docs/specs/2026-07-15-challenge-skill.md b/docs/specs/2026-07-15-challenge-skill.md new file mode 100644 index 0000000..2c59db6 --- /dev/null +++ b/docs/specs/2026-07-15-challenge-skill.md @@ -0,0 +1,87 @@ +# challenge skill + +> devague gains a seventh origin skill, /challenge — a risk-scaled blind-spot discovery pass that pressure-tests the converged frame between /think and /spec-to-plan through structured lenses, routes every finding back through the existing deterministic moves, and records examined surfaces plus residual uncertainty instead of ever claiming there are no unknown unknowns +> instruction: diff the shipped SKILL.md against this announcement claim by claim: risk-scaling rule present, position between /think and /spec-to-plan, findings routed through existing moves only, examined-surfaces record on a clean pass + +## Audience + +- operators — the main agent driving the deterministic CLI move by move — and the humans who own the spec and implementation-split-plan gates; downstream, the AgentCulture mesh once guildmaster re-broadcasts the skill + - instruction: check the SKILL.md description names both audiences and docs/skill-sources.md routes challenge to guildmaster like the other six origin skills + +## Before → After + +- Before: a frame can converge on precisely stated claims while the original framing is still incomplete: open questions only capture uncertainty someone already noticed — nothing actively hunts omitted dimensions, hidden dependencies, or shared assumptions, and no record exists of which surfaces were ever examined (issue 73 problem statement) +- After: a converged frame no longer slides straight into planning untested: the operator runs a proportional challenge pass over structured lenses, every finding lands as a proposed claim, question, or park that the user adjudicates, the frame reconverges, and the exported spec carries examined-surfaces provenance and residual uncertainty + - instruction: dogfood /challenge on a real frame and verify findings landed proposed-only, the frame reconverged, and the re-exported spec shows the examined surfaces + +## Why it matters + +- an articulated blind spot becomes a known unknown the method can manage; an unexamined one surfaces later as a mid-run /deviate or a production surprise — the pass raises the odds of discovery before planning and lowers the cost of the surprises that remain (issue 73) + +## Requirements + +- the new skill ships as .claude/skills/challenge/SKILL.md in the method-only shape — SKILL.md only, no scripts/ resolver, `type: command` frontmatter, a Provenance section naming devague as origin — matching the shipped deviate and summarize-delivery skills and the two-shape rule in docs/skills.md + - honesty: listing .claude/skills/challenge/ shows exactly one file, SKILL.md, whose frontmatter carries `type: command` and whose Provenance section names devague as origin — no scripts/ directory +- devague/cli/_commands/learn.py OPERATOR_SKILLS gains a seventh entry for challenge and its six-skill / six-leg wording updates, so `devague learn skills` and `skills:challenge` teach the new skill; this is teaching-content in the existing learn verb, not a new engine + - honesty: `devague learn skills:challenge` exits 0 and emits the challenge authoring recipe; `devague learn skills` output says seven operator skills in seven-leg order +- every surface naming the six-leg flow is updated to seven legs with challenge third: README.md (lines 82-94), CLAUDE.md (Status + Project intent), docs/skills.md (flow table + per-skill section), docs/skill-sources.md (origin-skills table + dont-re-vendor list) + - honesty: grepping README.md, CLAUDE.md, docs/skills.md, and docs/skill-sources.md for six-leg wording returns no hits, and all four surfaces name challenge as the third leg +- when the pass finds nothing, it records which lenses and surfaces were examined and what residual uncertainty remains — it never claims there are no unknown unknowns (issue 73 success criteria; anti-fabrication contract in docs/llm-guidance.md) + - honesty: the SKILL.md hard-rules section contains an explicit rule forbidding a no-unknown-unknowns conclusion, with the required fallback of recording examined lenses/surfaces plus residual uncertainty + +## Honesty conditions + +- the shipped SKILL.md actually is what the announcement claims: risk-scaled (an explicit proportionality rule), positioned between /think and /spec-to-plan in every flow doc, findings routed only through existing deterministic moves, and a no-unknown-unknowns-claim rule +- the PR diff registers no new argparse subparser, adds no new devague/ module or store, and the only devague/ code change is teaching content in cli/_commands/learn.py +- the SKILL.md description and body address the operator (move-by-move CLI driving) and the gate-owning human (confirmation of findings) as distinct readers, matching the other six origin skills +- issue 73's problem statement is accurately reflected: before this change no devague surface actively searched for omitted dimensions or recorded examined surfaces at spec time +- the skill's intro states the surprise-cost rationale — discovery before planning is cheaper than /deviate mid-run or a production surprise — rather than promising to eliminate unknown unknowns +- a dogfooded /challenge run on a real converged frame produces only proposed findings, triggers reconvergence, and the re-exported spec renders the examined surfaces — verified before the skill is called done +- the success-signal counts are checkable from state alone: frame JSON plus session transcript show every finding's lens/surface trace and zero llm-origin items confirmed without a user confirm move + +## Success signals + +- every challenge pass leaves at least 1 durable record — proposed findings routed through existing moves, or examined-surfaces entries with residual uncertainty on a clean pass; 0 passes conclude with a bare no-issues-found, and 0 LLM-origin findings reach confirmed status without an explicit user confirm + - instruction: review a dogfooded pass: each finding traceable to a lens and surface; grep the frame JSON for llm-origin claims that are confirmed without a user confirm in the session log + +## Scope / boundaries + +- no new CLI engine, verb, or state model — challenge findings route through the existing deterministic moves only: capture / interrogate / question / park on the frame, `devague scope` for examined surfaces, `devague plan risk` for residual risk; the CLI stays deterministic and non-orchestrating per issue 20 and the issue 73 stated preference + +## Non-goals + +- challenge is not a fourth standing human gate — the three gates (exported spec, implementation split plan, final PR) stay; challenge output lands as proposed claims and questions the user confirms inside the existing spec gate, mirroring how /deviate amends gate 2 rather than adding one + +## Assumptions + +- examined-surfaces records reuse the existing `devague scope` move (surface + finding + optional seeds) — Frame.scope_entries already persists them and the exported spec-md already renders a Scope exploration section (issue 53 t3/t6), so residual-uncertainty provenance survives into the buildable spec with no new state +- residual risk that survives into planning lands via `devague plan risk --kind` — RISK_KINDS equals the vagueness kinds (unknown_nonblocking / unknown_blocking / out_of_scope / follow_up) in devague/plan.py, which already distinguishes blocking from nonblocking residual uncertainty + +## Scope exploration + +- `s1` — `.claude/skills/deviate/SKILL.md + .claude/skills/summarize-delivery/ + docs/skills.md file-structure rules`: the method-only origin-skill shape is established: SKILL.md only, type: command frontmatter required for culture/agex backends, Provenance section naming devague as origin; deviate (0.18.0) and summarize-delivery (0.17.0) both shipped this way + - seeds: `c2` +- `s2` — `devague/cli/_commands/learn.py (OPERATOR_SKILLS at line 280, six-skill wording at lines 393/412/435)`: learn skills now teaches all six operator skills from a data tuple; adding challenge is one tuple entry plus wording — teaching content, not a new engine + - seeds: `c3` +- `s3` — `README.md:82-94, CLAUDE.md Status/Project-intent, docs/skills.md flow table, docs/skill-sources.md origin table`: four doc surfaces name the six-leg flow and the origin-skill family explicitly; all four must move to seven legs together or the docs drift + - seeds: `c4` +- `s4` — `docs/spec-contract.md vocabulary + devague/plan.py RISK_KINDS + .claude/skills/scope/SKILL.md findings table`: the existing move vocabulary already covers every challenge output: findings as capture kinds (requirement/assumption/boundary/non_goal/decision), pressure-tests as interrogate, pending decisions as question, open vagueness as park, examined surfaces as devague scope entries, residual plan risk as plan risk with the four vagueness kinds — no gap forcing a new CLI verb + - seeds: `c5`, `c8`, `c9` +- `s5` — `issue 73 (integration options, success criteria) + CLAUDE.md three-human-gates section`: issue author prefers a distinct mandatory-but-proportional operator pass with no new CLI engine; success criteria require findings to reconverge the authoritative frame and forbid claiming zero unknown unknowns — and the three-gate structure stays untouched + - seeds: `c6`, `c7`, `c10`, `c11` +- `s6` — `challenge pass / hidden-dependency lens: tests/test_cli_learn.py lines 43-56`: the learn tests hardcode the origin-skill tuple, METHOD_ONLY_NAMES, and parametrized skills:name cases — they must move to seven skills in lockstep with learn.py or CI fails; lands as acceptance criteria on the learn-content plan task under c3 + - seeds: `c3` +- `s7` — `challenge pass / adjacent-systems lens: .claude/skills.local.yaml.example, culture.yaml, .github/workflows`: clean pass — none of these carry a skill-count dependency; no change needed +- `s8` — `challenge pass / failure-mode + reversibility lenses over the spec itself`: no CLI behavior change means no version-skew failure mode for installed devague binaries (learn.py text is the only code delta); change is docs+skill additive, fully reversible by revert; concurrency and data-loss lenses not applicable to a docs-only delivery + +## Decisions + +- integration option 1 from issue 73, per the issue author: a distinct operator skill /challenge, run as a mandatory but proportional pass — lightweight for ordinary work, rigorous for high-risk work — with no new CLI engine until the workflow proves it needs one +- challenge is the seventh documented leg, positioned third: scope, think, challenge, spec-to-plan, assign-to-workforce, deviate, summarize-delivery — per the issue 73 proposal flow and the user's request driving this frame +- the challenge pass runs after /think exports: challenge the converged, exported frame before `devague plan new`; findings reopen the frame, reconverge, and re-export the same dated spec file — /think stays self-contained (resolves q1) +- resilience measures land in both spec and plan by nature: spec-side as requirement/boundary claims when they change what to build, plan-side as plan risks or tasks when they change how to build it — the skill coaches which is which (resolves q2) +- the named escalation signals that deepen the pass from lightweight to rigorous: migrations, security-sensitive work, distributed state, hardware, destructive operations, other hard-to-reverse changes, concurrency hazards, and any surface that can lose user data (resolves q3) + +## Open / follow-up + +- guildmaster re-vendors /challenge and re-broadcasts it to the mesh on its own schedule — outside this repo's control; the skill-sources row documents the re-vendor path so downstream picks it up on the next sync diff --git a/pyproject.toml b/pyproject.toml index a551d7f..bd6848c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "devague" -version = "0.18.1" +version = "0.19.0" description = "devague — turns a vague feature idea into a buildable spec, then a buildable plan." readme = "README.md" diff --git a/tests/test_cli_learn.py b/tests/test_cli_learn.py index 1f795da..9dbea69 100644 --- a/tests/test_cli_learn.py +++ b/tests/test_cli_learn.py @@ -40,10 +40,11 @@ def test_learn_json_includes_assign_to_workforce_section( assert "assign_to_workforce" in payload or "assign-to-workforce" in str(payload).lower() -# The six origin skills, in six-leg workflow order (devague#53 esd). +# The seven origin skills, in seven-leg workflow order (devague#73). SKILL_NAMES = ( "scope", "think", + "challenge", "spec-to-plan", "assign-to-workforce", "deviate", @@ -53,7 +54,7 @@ def test_learn_json_includes_assign_to_workforce_section( # Method-only skills ship a SKILL.md and NO scripts/.sh resolver — they # invoke the devague CLI directly. The other three are CLI-driving and DO ship # a scripts/.sh resolver. -METHOD_ONLY_NAMES = ("scope", "deviate", "summarize-delivery") +METHOD_ONLY_NAMES = ("scope", "challenge", "deviate", "summarize-delivery") CLI_DRIVING_NAMES = ("think", "spec-to-plan", "assign-to-workforce") @@ -171,6 +172,7 @@ def test_learn_unknown_skill_errors(capsys: pytest.CaptureFixture[str]) -> None: "skills:all", "skills:think", "skills:scope", + "skills:challenge", "skills:deviate", "skills:summarize-delivery", ], diff --git a/uv.lock b/uv.lock index ed1c773..6d1a392 100644 --- a/uv.lock +++ b/uv.lock @@ -183,7 +183,7 @@ wheels = [ [[package]] name = "devague" -version = "0.18.1" +version = "0.19.0" source = { editable = "." } [package.dev-dependencies]