dotCMS / dotCMS/core

Adopt /speckit-converge as the mandatory closing step of the dotCMS Spec-Kit flow, covering documentation drift

Open
#37,267 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Team : Falcon Type : Task
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.implement and 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:95Flow 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.yaml is auto-generated at compile and CI fails if the committed file doesn't match the build (see CLAUDE.md → OpenAPI / Swagger).
  • docs/ is the single source of truth for backend and frontend standards; CLAUDE.md is 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 (implementconverge) 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-converge after /speckit-implement, with the implement → converge loop and the exit to PR 2.
  • §2 tier table lists /speckit-converge as 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-converge as 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:95 Flow 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.yml declares an after_implement hook pointing at speckit.converge with optional: false, following the same schema and comment style as the existing before_planspeckit.adr-context hook.
  • /speckit-implement fires that hook on completion of the task list, and converge runs without the developer typing the command.
  • Re-running /speckit-implement on the appended Convergence tasks fires converge again, so the loop is self-sustaining until it reports converged.
  • The hook is documented in .specify/CUSTOMIZATIONS.md as 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/ and CLAUDE.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.yaml and REST contracts — when the feature touched a JAX-RS resource, converge checks that @Operation / @Parameter / @Schema annotations describe what was actually built and that the committed openapi.yaml matches the current build output (the CI check in CLAUDE.md → OpenAPI / Swagger).
  • spec.md / plan.md back-annotation — where the final implementation diverged from the approved spec, the divergence is reported so it can be reconciled. Converge itself must not edit spec.md or plan.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: Convergence section to tasks.md. It does not edit docs/, 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.md is left byte-for-byte unchanged and converge reports converged.
  • 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.md is regenerated (just skills-catalog) if the skill's description or status changes.
  • If .claude/skills/speckit-converge/SKILL.md is edited, its sha256 in .specify/integrations/claude.manifest.json is 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_planadr-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 (upstream templates/commands/converge.md)
  • Hook precedent: .specify/extensions.ymlbefore_plan / speckit.adr-context
  • Commit policy: tasks.md is 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-analyze does (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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.