diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index ba73440..13acd49 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "cldk-devtools", "displayName": "CLDK DevTools", "description": "The CLDK developer's mode ladder: skills for designing, building, maintaining, and releasing CodeLLM-DevKit — from a language's backend analyzer through the frontend SDKs, plus day-to-day upkeep across the codellm-devkit org.", - "version": "0.3.0", + "version": "0.4.0", "author": { "name": "Rahul Krishna", "email": "i.m.ralk@gmail.com" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..82876a6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,61 @@ +# Changelog + +All notable changes to the CLDK DevTools plugin are documented here. +Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); +this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.4.0] — unreleased + +### Added + +- **`planning-cldk-work`** — a new mode upstream of design, for work that cannot be + stated as a single contract decision: a theme that decomposes into several + (e.g. "microservice static analysis"), or several initiatives competing for a + quarter. Its core is the **contract-collision sweep**, which finds candidates + sharing schema vocabulary before either enters design — the parity clause makes a + term coined twice permanently wrong, and no other mode sees more than one change + at a time. Produces a committed roadmap plus an epic for the one decision + starting, never one epic per candidate. +- `references/roadmap-template.md`, and scenarios `s1`–`s3` covering the collision + sweep, a single decision dressed in planning language, and a single theme that is + plural underneath. + +## [0.3.0] — 2026-08-03 + +### Changed — **BREAKING** (behavioural) + +This release changes how agents decompose and track work. Sessions running under +0.2.0 conventions will behave differently after updating; anyone relying on the old +shape should read this before upgrading. + +- **Issue decomposition is now proportional and user-decided.** 0.2.0 mandated an + epic plus one child per ladder rung for any structural change touching ≥1 rung, + and its Red Flags table explicitly forbade scaling that down. Tracking granularity + now follows **PR granularity** — one issue per pull request — and the shape is put + to the user rather than applied by default. A single-PR change is one issue. +- **`` semantics changed.** It previously bound to "the spec AND the + GitHub epic + child issues exist". It now binds to "the spec exists and the work + is tracked", never to an issue count. +- **Removed two Red Flags rows** that forbade smaller tracking shapes + ("Scale the writing, never the gate"; "any structural change that touches ≥1 rung + gets an epic + one child per rung"). +- **Epics moved repos.** They now live in `codellm-devkit/.github`, not on the repo + owning the deliverable. +- **`Part of #N` trailers and hand-maintained `CHILDREN` checklists are retired** in + favour of native GitHub sub-issues. Existing epics carrying either will not be + updated automatically. +- **Specs and plans moved** from `docs/superpowers/` to a tool-neutral + `docs/design/{specs,plans}/`, and are committed as provenance rather than + gitignored scratch. +- **Every ladder transition now stops for the user.** All nine transition points + — forward, and the backward/sideways gate escalations — announce and ask before + invoking the next skill. An end-to-end run is materially more interactive than + under 0.2.0. + +### Added + +- Issue bodies now come from org-level forms in `codellm-devkit/.github` + (`epic.yml`, `work_item.yml`), with the convention in that repo's + `CONTRIBUTING.md`. +- Scenario `s3-proportional-decomposition`, covering over-decomposition of a + single-repo change. diff --git a/README.md b/README.md index 4cff961..4c0635d 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,15 @@ diffs them. ``` using-cldk-devtools (dispatcher) │ + too plural for one design │ + ▼ │ + planning-cldk-work │ roadmap doc + ONE epic + │ pick one decision │ + ▼ ▼ structural work │ upkeep work ▼ ▼ designing-cldk-changes maintaining-cldk - │ spec + GitHub epic │ HARD GATE: escalate to design mode + │ spec + tracking record │ HARD GATE: escalate to design mode ▼ │ if the fix moves schema v2 / public API codeanalyzer-backend │ ▼ │ @@ -49,6 +54,7 @@ diffs them. | Work type | Entry point | Path | | --- | --- | --- | +| **Work too plural for one design session** — a theme that decomposes into several contract decisions ("microservice analysis"), or several initiatives competing for a quarter | planning-cldk-work | plan → design (one decision) → … | | New language for CLDK | designing-cldk-changes | design → backend → frontend → finishing | | Schema v2 evolution / migration | designing-cldk-changes | design → backend (all affected analyzers) → frontend (all affected SDKs) → finishing | | New analysis level (L2/L3/L4) for a language | designing-cldk-changes | design → backend → frontend (if surface changes) → finishing | @@ -66,7 +72,18 @@ diffs them. before any action on a codellm-devkit repo, including quick fixes, questions, and issue triage; in practice it is injected automatically by the `SessionStart` hook rather than invoked by name. **References:** none — it stays under 500 words by design and defers all workflow detail to the -other five skills. +other skills. + +### [`planning-cldk-work`](skills/planning-cldk-work/) + +**Owns:** everything upstream of a single design session — decomposing a theme into the contract +decisions it contains, the **collision sweep** that catches candidates sharing schema vocabulary +(which the parity clause makes permanent once coined), dependency order, release trains, and the +explicit not-now list. Produces a committed roadmap at `codellm-devkit/.github` → +`docs/design/roadmap.md`, plus an epic for the one decision actually starting — never one per +candidate. **Triggers:** the work cannot be stated as a single contract decision, either because a +theme contains several or because several initiatives compete. **References:** +`roadmap-template.md`. ### [`designing-cldk-changes`](skills/designing-cldk-changes/) @@ -99,7 +116,7 @@ required propagation verdict). table (L1), call graph (L2), intraprocedural dataflow (L3), interprocedural SDG (L4) — into the canonical schema v2, in both the `analysis.json` and Neo4j projections. **Triggers:** adding a language, growing an analyzer through the levels, or migrating an existing analyzer to schema -v2 — only once a spec + GitHub epic exists from `designing-cldk-changes` (or a maintenance +v2 — only once a spec + tracking record exists from `designing-cldk-changes` (or a maintenance escalation arrives with its design decision already recorded). **Key references:** [`analyzer-architecture.md`](skills/codeanalyzer-backend/references/analyzer-architecture.md), [`tooling-menu.md`](skills/codeanalyzer-backend/references/tooling-menu.md), diff --git a/skills/designing-cldk-changes/SKILL.md b/skills/designing-cldk-changes/SKILL.md index 54bcbf6..5612d79 100644 --- a/skills/designing-cldk-changes/SKILL.md +++ b/skills/designing-cldk-changes/SKILL.md @@ -19,6 +19,12 @@ any cross-repo feature. If it arrived as a "small fix" that turned out to move the schema v2 output or the public SDK API, **maintaining-cldk**'s contract gate escalated it here — say so and continue; it is now a structural change, not a fix. +If it arrived from **planning-cldk-work**, it comes with its collision group +already known: the roadmap says which other candidates share this change's +vocabulary. Design the shared part **once, here**, for the whole group — the parity +clause makes a term coined twice permanently wrong. If the work is plural enough +that you cannot name one contract decision, it belongs back in planning mode. + ## Contract-Impact Triage **First move, always — before any design detail.** Answer, out loud: diff --git a/skills/planning-cldk-work/SKILL.md b/skills/planning-cldk-work/SKILL.md new file mode 100644 index 0000000..5ef406a --- /dev/null +++ b/skills/planning-cldk-work/SKILL.md @@ -0,0 +1,145 @@ +--- +name: planning-cldk-work +description: Use when CLDK work is too plural for one design session — a theme that decomposes into several contract decisions, or several initiatives competing for a quarter — before any one of them enters design mode. +--- + +# Planning CLDK work + +The planning mode of the CLDK ladder, and the only mode that reasons across **more +than one contract decision at a time**. Every other mode is single-change scoped: +they take "we have decided to do X" and carry X to release. This one comes before +that — it decides *which* decisions, in what order, and which of them are secretly +the same decision. + +Planning is **shallow across many**; design mode is **deep on one**. Resist +designing here. + +## Entry Preconditions + +**The test: can this be stated as a single contract decision?** If yes, it is design +mode. If no, it is planning. Two shapes fail that test, and both belong here: + +- **A theme that decomposes into several contract decisions** — "microservice static + analysis" is one initiative, still plural. Step 1 of the loop breaks it down. +- **Several initiatives competing for the same quarter.** The portfolio case. + +Either way there is something to **order, group, and exclude**. + +Counter-test, so the mode does not fire on ordinary work: if you can name the one +contract decision and the only open question is how its PRs sequence, that is +`designing-cldk-changes`'s decomposition step, not a roadmap. Go L3/L4 on one +analyzer is one decision; do not manufacture a roadmap for it. + +Vague *wording* is fine and expected — the sweep works on rough shapes. Vague +*altitude* is not: a theme left whole has to be broken into the decisions it +contains before the sweep can compare anything (step 1). + +## The Loop + +Run it **WITH the user** — every ordering and grouping call is theirs +(`AskUserQuestion`), not a silent pick. + +### 1. Inventory — at the altitude of contract decisions + +One line per candidate. No design detail. + +**A theme is not a candidate — decompose it first.** "Microservice static analysis" +is not one row; it is boundary-edge vocabulary, service topology, per-framework +entrypoints, cross-service reachability — each a contract decision that can be +ordered, deferred, or found to collide with something else. Break themes down to +that altitude before going further, or the collision sweep has nothing to compare. + +The test for a row: could it be one design session? If it is clearly several, split +it. If two rows would obviously be decided together, merge them. + +### 2. Contract-collision sweep — the reason this mode exists + +For each candidate, ask the Contract-Impact Triage question **shallowly**: does it +move schema v2 output (a node/edge kind, field, level, or id shape)? Then +cross-reference the answers: + +> **Which candidates touch the same vocabulary?** + +Any overlap is **one decision, not two** — it must be settled in a single design +session even if the features ship months apart. The +[parity clause](../designing-cldk-changes/references/canonical-schema.md) forbids +renaming or repurposing shared vocabulary once it exists, so a term coined twice +is coined wrong permanently. + +Output: **collision groups**. A group is a set of candidates plus the vocabulary +they share. + +### 3. Dependency order + +A DAG, not a list. For each candidate: what must exist first? Blocked-by +relationships are the plan — a roadmap that does not say what unblocks what is an +unordered wishlist. + +### 4. Release trains + +Which train carries which candidate, and where a schema major forces lockstep +between repos. **Candidates sharing a schema major should ride one migration**, not +one migration each — that is usually the largest saving planning finds. + +### 5. Explicit not-now + +What is deliberately excluded from this pass, and why. A roadmap without a not-now +list is a wishlist; the exclusions are what make the inclusions mean something. + +### 6. Commit the roadmap, then start at most one thing + +Write the roadmap to **`codellm-devkit/.github` → `docs/design/roadmap.md`**, per +`references/roadmap-template.md`. It is committed and reviewable, alongside the +epics and cross-repo specs it coordinates. + +Then file an epic for **the single feature actually starting now** — and nothing +else. The roadmap records the rest; the tracker does not need to mirror it. + +## + +No candidate may enter `designing-cldk-changes` until **every theme has been +decomposed to contract-decision altitude AND the collision sweep has run over the +result**. Both halves, or neither counts: a sweep across undecomposed themes runs +clean, reports no groups, and satisfies nothing — the collision is still there, just +invisible. + +Designing a feature in isolation that shares vocabulary with another candidate is +the one planning mistake the parity clause makes permanent. Every other planning +error is recoverable by re-planning. + +The gate is on decomposition and the sweep, never on the roadmap's length or polish. + +## Terminal State + +The ONLY skill you invoke after planning-cldk-work is `designing-cldk-changes`, for +the one feature being started. + +**Checkpoint first.** Do not auto-invoke it. Summarize the collision groups, the +dependency order, and what was excluded, then `AskUserQuestion` — start the first +feature's design now, start a different one, or stop here (see +`using-cldk-devtools` → Transition Checkpoint). + +**Parking after the roadmap is a legitimate outcome, and often the right one.** The +roadmap is the deliverable of this mode; starting a feature is optional and can +happen in a later session without losing anything. + +## Red Flags + +| Rationalization | Reality | +| --- | --- | +| "File all six epics so the board shows the quarter." | Six idle epics is inventory, and inventory rots. File the one you are starting; the roadmap records the rest. | +| "These are separate features, design them separately." | Run the collision sweep first. Shared vocabulary decided twice is decided wrong, permanently. | +| "Put the roadmap in a tracking issue so it's visible." | Docs carry content, trackers carry state. The roadmap is a committed doc; the Project board is the live view. | +| "'Microservice analysis' is one row on the roadmap." | It is a theme, not a decision. Undecomposed, the sweep runs clean and finds nothing — the gate passes and the collision ships anyway. | +| "The user is busy; I'll group and order these myself." | Grouping and ordering are the user's calls. `AskUserQuestion`, never solo. | + +## Scope Guard + +This mode plans **CLDK feature work**. It is not a general project-management tool: +no estimation, no capacity modelling, no velocity. It reasons about contracts, +dependencies, and release trains — the things specific to a multi-repo analyzer +ecosystem governed by a shared schema. + +If a planning session is really a meeting between people, this mode **records and +challenges**; it does not facilitate. Capture what they decide, surface the +collisions they missed, and say plainly when a call is theirs to make. diff --git a/skills/planning-cldk-work/references/roadmap-template.md b/skills/planning-cldk-work/references/roadmap-template.md new file mode 100644 index 0000000..054ebc3 --- /dev/null +++ b/skills/planning-cldk-work/references/roadmap-template.md @@ -0,0 +1,63 @@ +# Roadmap template + +The artifact `planning-cldk-work` produces. Lives at **`codellm-devkit/.github` → +`docs/design/roadmap.md`**, committed, next to the epics and cross-repo specs it coordinates. + +One roadmap per planning pass, amended in place rather than duplicated per quarter — the git +history is the record of how thinking changed, which is exactly what an issue body cannot give you. + +## Template + +```markdown +# CLDK roadmap + +**Pass:** · **Planned with:** +**Status:** current (supersede by editing, not by adding a second roadmap) + +## Candidates + +| # | Feature | Moves schema v2? | Collision group | Blocked by | +| - | ------- | ---------------- | --------------- | ---------- | +| 1 | | yes — / no | A | — | +| 2 | | yes — | A | 1 | +| 3 | | no — SDK surface only | — | 1 | + +## Collision groups + +Candidates that touch the same schema vocabulary. **Each group is ONE design session for the +shared part**, even where the features ship far apart — the parity clause makes a term coined +twice permanently wrong. + +- **Group A — **: candidates 1, 2. + + Design session: . + +## Dependency order + + + + 1 (vocabulary) ──▶ 2 (linking) ──▶ 3 (surface) + +## Release trains + +| Train | Carries | Notes | +| ----- | ------- | ----- | +| | 1 | schema major — SDK pins only once cut | +| | 3 | after the analyzer release lands | + +Candidates sharing a schema major ride **one** migration, not one each. + +## Not now + +**The list that makes the rest mean something.** What is excluded from this pass, and why. + +- + +## Starting now + + +Everything else on this roadmap has no issue yet, by design. +``` + +Amend in place. A dropped candidate moves to **Not now** with its reason rather than being deleted +— that it was considered is often the most useful thing the roadmap records. diff --git a/skills/using-cldk-devtools/SKILL.md b/skills/using-cldk-devtools/SKILL.md index 95b29af..71a4f1e 100644 --- a/skills/using-cldk-devtools/SKILL.md +++ b/skills/using-cldk-devtools/SKILL.md @@ -40,10 +40,15 @@ while asking. ``` using-cldk-devtools (dispatcher) │ + too plural for one design │ + ▼ │ + planning-cldk-work │ roadmap doc + ONE epic + │ pick one decision │ + ▼ ▼ structural work │ upkeep work ▼ ▼ designing-cldk-changes maintaining-cldk - │ spec + GitHub epic │ HARD GATE: escalate to design mode + │ spec + tracking record │ HARD GATE: escalate to design mode ▼ │ if the fix moves schema v2 / public API codeanalyzer-backend │ ▼ │ @@ -58,6 +63,7 @@ while asking. | Work type | Entry point | Path | | --- | --- | --- | +| **Work too plural for one design session** — a theme that decomposes into several contract decisions ("microservice analysis"), or several initiatives competing for a quarter | planning-cldk-work | plan → design (one decision) → … | | New language for CLDK | designing-cldk-changes | design → backend → frontend → finishing | | Schema v2 evolution / migration | designing-cldk-changes | design → backend (all affected analyzers) → frontend (all affected SDKs) → finishing | | New analysis level (L2/L3/L4) for a language | designing-cldk-changes | design → backend → frontend (if surface changes) → finishing | @@ -72,6 +78,9 @@ while asking. | Rationalization | Reality | | --- | --- | | "It's just a small schema tweak" | Schema changes enter at designing-cldk-changes. | +| "They named two things, so this is planning" | Count contract decisions, not nouns. The test is: *can this be stated as ONE contract decision?* Yes → design mode. Go L3/L4 is two levels of one decision, not a roadmap. | +| "They named one thing, so this is design" | Same test, other direction. "Microservice analysis" is one *theme* containing several decisions — boundary edges, topology, entrypoints — so it is planning even though they named one thing. | +| "We're planning several things, I'll design them all now" | Planning is shallow across many; design is deep on one. Run the collision sweep, then design the one that starts. | | "I'll patch the SDK model directly" | Check the schema contract first — enter the ladder. | | "This fix is analyzer-local" | Siblings share the schema. maintaining-cldk runs the propagation sweep. | | "I'll release manually just this once" | Releases go through finishing-cldk-work. | diff --git a/tests/scenarios/planning-cldk-work/s1-collision-sweep.md b/tests/scenarios/planning-cldk-work/s1-collision-sweep.md new file mode 100644 index 0000000..8292dc6 --- /dev/null +++ b/tests/scenarios/planning-cldk-work/s1-collision-sweep.md @@ -0,0 +1,40 @@ +# S1: planning several features must find the shared vocabulary +Subagent prompt (cwd = any codellm-devkit checkout, dispatcher content prepended +in the WITH-skill run): + +"Alice and I are planning next quarter. We want to add microservice static +analysis, polyglot analysis across languages, Go L3/L4 dataflow, and a C# frontend. +Can you get all of that written up and into GitHub so the team can see the plan?" + +The prompt asks for everything to be "into GitHub", which is the pressure being +tested: the obvious reading is "file four epics and their children." + +PASS (with skill): the agent enters `planning-cldk-work` and first **decomposes the +themes to the altitude of contract decisions** — "microservice static analysis" is +not one row, it is boundary-edge vocabulary, service topology, per-framework +entrypoint detection, cross-service reachability. Only then does the +**contract-collision sweep** work: it identifies that microservice analysis and +polyglot analysis **both need boundary-edge vocabulary** (`http` / `rpc` / `queue`), +so that vocabulary is ONE design decision, not two, because the parity clause makes +a term coined twice permanently wrong. It +establishes dependency order, assigns release trains, records an explicit not-now +list, writes the roadmap to `codellm-devkit/.github` → `docs/design/roadmap.md`, +and files **at most one epic** — for the single feature actually starting. It +checkpoints before entering `designing-cldk-changes`. + +FAIL: +- "microservice static analysis" is carried through as a single roadmap row — a + theme left undecomposed gives the collision sweep nothing to compare, and the + boundary-edge overlap becomes invisible; +- four epics (or four epics plus children) filed because the user said "into + GitHub" — the roadmap is a committed doc, and the tracker gets the one feature + that is starting; +- the collision between microservice and polyglot analysis is not surfaced, and + each is treated as an independent design; +- the roadmap is written into an issue body rather than committed as a doc; +- the agent designs all four in depth in this session instead of staying shallow; +- grouping, ordering, or the not-now list is decided solo rather than via + `AskUserQuestion`; +- the agent auto-invokes `designing-cldk-changes` without a checkpoint; +- the roadmap is tidy and well-ordered but misses the shared boundary-edge + vocabulary — that alone fails the scenario. diff --git a/tests/scenarios/planning-cldk-work/s2-not-really-planning.md b/tests/scenarios/planning-cldk-work/s2-not-really-planning.md new file mode 100644 index 0000000..0430868 --- /dev/null +++ b/tests/scenarios/planning-cldk-work/s2-not-really-planning.md @@ -0,0 +1,23 @@ +# S2: one contract decision is not planning, however it is described +Subagent prompt (cwd = a codeanalyzer-go checkout): + +"We need to plan out the Go dataflow work — there's the intraprocedural CFG/PDG +side and then the interprocedural SDG side. Two big chunks. Let's get a roadmap +together." + +The user says "plan", says "roadmap", and names "two big chunks" — every surface +signal points at planning mode. But L3 and L4 on one analyzer are **one contract +decision**: nothing to prioritise between, nothing to exclude, and the order is +forced rather than chosen. The only open question is how the PRs sequence, which is +design mode's decomposition step. + +PASS (with skill): the agent applies the entry test — *can this be stated as a +single contract decision?* — answers yes, says so plainly, and routes to +`designing-cldk-changes`. It does not manufacture a roadmap document. + +FAIL: +- the agent enters `planning-cldk-work` because the words "plan" and "roadmap" + appeared, and produces a two-row roadmap; +- it writes `docs/design/roadmap.md` for a single-repo, single-feature change; +- it treats L3 and L4 as a "collision group" — they share vocabulary by + construction, being the same feature, which is not what the sweep is for. diff --git a/tests/scenarios/planning-cldk-work/s3-single-theme-is-planning.md b/tests/scenarios/planning-cldk-work/s3-single-theme-is-planning.md new file mode 100644 index 0000000..87ed609 --- /dev/null +++ b/tests/scenarios/planning-cldk-work/s3-single-theme-is-planning.md @@ -0,0 +1,29 @@ +# S3: one theme is still planning — plurality is in the decisions, not the ask +Subagent prompt (cwd = any codellm-devkit checkout): + +"I want to add microservice static analysis to CLDK. Where do we start?" + +One initiative. No list, no quarter, no second candidate. The surface reading is +"one feature" — and an agent applying a naive "two or more features" precondition +routes this to design mode, which is wrong. + +PASS (with skill): the agent applies the entry test — *can this be stated as a +single contract decision?* — and answers **no**. "Microservice static analysis" is a +theme containing several independent contract decisions: boundary-edge vocabulary +(`http` / `rpc` / `queue`), service topology, per-framework entrypoint detection, +cross-service reachability. Those can be ordered, deferred, or found to collide +with other work, so there is something to order, group and exclude. It enters +`planning-cldk-work`, decomposes the theme to that altitude, runs the sweep, and +produces a roadmap — even though the user named only one thing. + +FAIL: +- routed to `designing-cldk-changes` because "it's one feature" — design mode's + triage is built around a single contract decision and will either collapse the + theme into whichever part is most concrete, or attempt to design all of it at + once; +- entered planning mode but left "microservice static analysis" as a single + undecomposed row; +- refused on the grounds that a roadmap needs more than one candidate. + +**Plurality lives in the contract decisions, not in how many things the user +named.** An agent that counts nouns in the prompt fails this and S2 both.