Adopt /speckit-converge as the mandatory closing step of the dotCMS Spec-Kit flow, covering documentation drift
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Description
The upstream Spec-Kit quickstart (github.github.com/spec-kit/quickstart.html) defines /speckit.converge as step 9 — the final step of the flow:
Checks the codebase against the spec, plan, and tasks. If it finds gaps, it appends new tasks to
tasks.md; run/speckit.implementand converge again until it reports converged. Otherwise you're done — proceed to review or open a PR.
The command is already installed in this repo (.claude/skills/speckit-converge/SKILL.md, registered in .claude/skills/skills.config.json) and already documented in docs/core/SPEC_KIT_QUICK_START.md §8 and §9. This issue is not about adding the command — it is about closing two gaps between how we ship it today and what we actually need from it.
Gap 1 — it is not positioned as the closing step of our flow
Today /speckit-converge lives in §9 "The other commands", framed as an optional escape hatch ("Code has run ahead of tasks.md and you want to know what's left"). It is absent everywhere the canonical flow is written down:
| Location | Current state |
|---|---|
SPEC_KIT_QUICK_START.md §1 — flow diagram |
✗ ends at /speckit-implement |
SPEC_KIT_QUICK_START.md §2 — tier table (Lean / Full) |
✗ not listed in either flow |
SPEC_KIT_QUICK_START.md §3 — two-PR sequence (steps 1–5) |
✗ not mentioned before PR 2 |
SPEC_KIT_QUICK_START.md §9 |
✓ documented, but as an optional tool |
CLAUDE.md:95 — Flow line |
✗ ends at /speckit-implement → PR 2 |
.specify/CUSTOMIZATIONS.md — "The standard flow" |
✗ ends at /speckit-implement |
.specify/extensions.yml |
✗ only before_plan exists; no post-implement hook |
The practical consequence: nothing in our process asks "does the code actually match the spec that was approved in PR 1?" before PR 2 is opened. That question is the whole point of gating on an approved spec (§3), and right now it is left to the reviewer to reconstruct from the diff — exactly the failure mode the two-PR flow was designed to avoid.
Gap 2 — it converges code, but never documentation
The shipped skill reads spec.md, plan.md, tasks.md and the codebase. It has no notion of documentation drift — no reference to docs/, CLAUDE.md, openapi.yaml, or Javadoc anywhere in SKILL.md. So a feature can converge "clean" while docs/ still describes the old behavior and openapi.yaml still advertises the old contract.
This matters more here than in a vanilla Spec-Kit repo, because dotCMS already treats several docs as build-verified or normative:
openapi.yamlis auto-generated at compile and CI fails if the committed file doesn't match the build (seeCLAUDE.md→ OpenAPI / Swagger).docs/is the single source of truth for backend and frontend standards;CLAUDE.mdis the always-loaded navigation hub.- The
@Schema/ return-type correspondence is a Critical Rule.
What we want
/speckit-converge becomes the mandatory closing step of the dotCMS Spec-Kit flow, running automatically after /speckit-implement, and its gap analysis covers documentation alongside code. It stays append-only — doc drift becomes new tasks in the ## Phase N: Convergence section for /speckit-implement to execute, never a direct edit by converge itself. The loop repeats (implement → converge) until it reports converged; only then do you open PR 2.
/speckit-specify | /speckit-specify-fix
│
▼ PR 1 (spec) approved
/speckit-plan → /speckit-tasks → /speckit-implement
│
▼
/speckit-converge ← auto (after_implement)
│
gaps found ───────────┴──────── converged
│ │
└──► back to implement ▼
PR 2
Acceptance Criteria
A. /speckit-converge is documented as the final step of the flow
-
docs/core/SPEC_KIT_QUICK_START.md§1 flow diagram shows/speckit-convergeafter/speckit-implement, with theimplement → convergeloop and the exit to PR 2. - §2 tier table lists
/speckit-convergeas part of both the Lean (Tier 1) and Full (Tier 2) flows, unparenthesized (i.e. not an optional step). - §3 ("Two PRs") step list includes converging to a clean result as the precondition for opening PR 2.
- §9 no longer frames
/speckit-convergeas an optional "other command"; its subsection is retained (or relocated) and rewritten to describe the mandatory closing step, including the loop-until-converged semantics. -
CLAUDE.md:95Flow line reads… → /speckit-tasks → /speckit-implement → /speckit-converge → PR 2 (implementation). -
.specify/CUSTOMIZATIONS.md"The standard flow" section is updated to the same four-plus-converge sequence. - §10 Troubleshooting gains a row for the most likely new confusion: converge keeps appending tasks / never reports converged.
B. Converge runs automatically after implement
-
.specify/extensions.ymldeclares anafter_implementhook pointing atspeckit.convergewithoptional: false, following the same schema and comment style as the existingbefore_plan→speckit.adr-contexthook. -
/speckit-implementfires that hook on completion of the task list, and converge runs without the developer typing the command. - Re-running
/speckit-implementon the appended Convergence tasks fires converge again, so the loop is self-sustaining until it reports converged. - The hook is documented in
.specify/CUSTOMIZATIONS.mdas a numbered customization, stating whether it is upgrade-safe, consistent with how customization #2 (before_plan) is recorded.
C. Documentation drift is part of the gap analysis
Converge's assessment covers, in addition to the code:
-
docs/andCLAUDE.md— a doc that describes behavior, a command, or a pattern the implementation changed, and no longer matches it, is reported as a finding. -
openapi.yamland REST contracts — when the feature touched a JAX-RS resource, converge checks that@Operation/@Parameter/@Schemaannotations describe what was actually built and that the committedopenapi.yamlmatches the current build output (the CI check inCLAUDE.md→ OpenAPI / Swagger). -
spec.md/plan.mdback-annotation — where the final implementation diverged from the approved spec, the divergence is reported so it can be reconciled. Converge itself must not editspec.mdorplan.md(the existing operating constraint holds); the reconciliation is surfaced as a task, and a divergence from an approved spec is flagged as needing re-approval per §3. - Javadoc and code comments — comments left describing the previous behavior of code the feature changed are reported.
- Each documentation finding is classified with the same existing vocabulary (
missing/partial/contradicts/unrequested) and carries the file path it refers to. - Documentation findings are ordered after constitution violations, consistent with the current severity ordering.
D. Append-only invariant is preserved
- Converge's only write remains appending a
## Phase N: Convergencesection totasks.md. It does not editdocs/,CLAUDE.md,openapi.yaml, Javadoc,spec.md,plan.md, or any application code. - Documentation gaps are emitted as ordinary tasks in that section, actionable by
/speckit-implement, each naming the file to update. - When code and docs both already satisfy the artifacts,
tasks.mdis left byte-for-byte unchanged and converge reportsconverged. - Existing task IDs are never renumbered, reordered, or deleted; a second Convergence phase is appended as a new phase.
E. Verification
- A dry run on a real feature directory (a recent Tier 2 spec under
specs/) produces at least one documentation finding that is genuinely actionable, and produces zero findings on a feature known to be complete. -
.claude/skills/CATALOG.mdis regenerated (just skills-catalog) if the skill's description or status changes. - If
.claude/skills/speckit-converge/SKILL.mdis edited, its sha256 in.specify/integrations/claude.manifest.jsonis updated so the integration manifest stays valid.
Priority
Medium
Additional Context
Implementation route — decide in /speckit-plan. There are two ways to add the documentation dimension, and they trade off differently against Spec-Kit upgrades:
| Route | How | Trade-off |
|---|---|---|
| Edit the shipped skill | Extend .claude/skills/speckit-converge/SKILL.md directly |
Simplest, single command. But it edits a shipped file — same category as customizations #5 and #6 in CUSTOMIZATIONS.md, must be re-applied on every Spec-Kit upgrade, and invalidates the manifest hash (AC E). |
| Additive companion skill | New dotCMS skill (e.g. speckit.docs-converge) wired as an after_converge hook in extensions.yml |
Upgrade-safe, same pattern as customization #2 (before_plan → adr-context). Costs a second command and a second hook in the chain. |
The AC above describe the behavior the developer should see, not the route — either satisfies them.
Related existing pieces:
- Shipped skill:
.claude/skills/speckit-converge/SKILL.md(upstreamtemplates/commands/converge.md) - Hook precedent:
.specify/extensions.yml→before_plan/speckit.adr-context - Commit policy:
tasks.mdis gitignored by design (§8) — converge's output stays local and is never part of PR 2 - Upstream reference: https://github.github.com/spec-kit/quickstart.html (step 9)
Out of scope:
- Changing what
/speckit-analyzedoes (it stays the pre-implement, read-only artifact audit) - Letting converge create or edit ADRs — Spec-Kit never authors ADRs (§7)
- Any CI enforcement of convergence; the gate is in the dev loop, not in the pipeline
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with .claude/skills/speckit-converge/SKILL.md, .specify/extensions.yml, docs/core/SPEC_KIT_QUICK_START.md, CLAUDE.md, and .specify/CUSTOMIZATIONS.md. Run the requested dry run against a real specs/ feature and verify that implement→converge repeats, documentation findings become append-only tasks, and a complete feature remains byte-for-byte unchanged in tasks.md.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, openapi
- Domain
- backend-api-design, documentation, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100