feat(#1190): wire --converge primary surface into /gsd:progress --next (ADR-15) (#1237)

* feat(#1190): wire --converge primary surface into /gsd:progress --next (ADR-15)

ADR-15 designates /gsd-progress --next --auto --converge as the PRIMARY plan-convergence surface, but only the secondary surface (autonomous.md) was wired. next.md now parses --converge/--cross-ai into a plan strategy, gates on workflow.plan_review_convergence, forwards reviewer flags + --max-cycles, and routes Route-3 planning through /gsd:plan-review-convergence (mirroring autonomous.md); --auto chaining preserves converge mode. Adds argument-hint + help/full.md + COMMANDS.md + how-to parity and a structural regression test.

Closes #1190

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(#1190): add changeset for progress --converge surface (#1237)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(#1190): keep progress --converge docs skill-dep-clean + regen workflow size baseline

CI surfaced two ripples from the ADR-15 workflow edits: (1) lint-skill-deps + profile-closure flagged /gsd:plan-phase and /gsd:plan-review-convergence SlashCommand tokens in progress.md's flag docs as undeclared deps — reworded to plain prose since progress.md only advertises the flag (the real invocation lives in next.md); (2) the per-file workflow size baseline needed regenerating after the next.md/help edits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-14 15:52:22 -04:00
committed by GitHub
parent e97b5d6b7b
commit 0b3a2e5f9c
8 changed files with 256 additions and 7 deletions

View File

@@ -0,0 +1,5 @@
---
type: Added
pr: 1237
---
**`/gsd-progress --next --auto --converge` now routes planning through plan-review convergence.** ADR-15's designated *primary* convergence surface is wired into the progress/next workflow (previously only `/gsd-autonomous --converge` honored it; on `/gsd-progress` the flag was silently dropped). Accepts `--cross-ai` as an alias plus reviewer flags and `--max-cycles N`, and is gated on `workflow.plan_review_convergence`. (#1190)

View File

@@ -1,7 +1,7 @@
---
name: gsd:progress
description: Check progress, advance workflow, or dispatch freeform intent — the unified GSD situational command
argument-hint: "[--forensic | --next | --do \"task description\"]"
argument-hint: "[--forensic | --next [--auto] [--converge] | --do \"task description\"]"
effort: low
allowed-tools:
- Read
@@ -25,6 +25,7 @@ Three modes:
<flags>
- **--next**: Detect current project state and automatically invoke the next logical GSD workflow step. Scans all prior phases for incomplete work before routing. `--next --force` bypasses safety gates.
- **--next --auto**: Like `--next`, but after the determined step completes, automatically re-invokes `/gsd:progress --next --auto` to continue chaining steps until completion or a blocking decision. Enables hands-free plan→execute→verify→complete progression.
- **--next --converge**: When the next action is planning (Route 3), route it through the plan-review **convergence** loop instead of the standard planner. Requires `workflow.plan_review_convergence=true` (enable with `gsd config-set workflow.plan_review_convergence true`). `--cross-ai` is an alias. Reviewer flags (`--codex`, `--gemini`, `--claude`, `--opencode`, `--ollama`, `--lm-studio`, `--llama-cpp`, `--all`) and `--max-cycles N` are forwarded to the convergence loop.
- **--do "..."**: Smart dispatcher — match freeform intent to the best GSD command using routing rules, confirm the match, then hand off.
- **--forensic**: Run 6-check integrity audit after the standard progress report.
- **(no flag)**: Standard progress check + intelligent routing (Routes A through F).

View File

@@ -558,13 +558,17 @@ Show status, next steps, and automatically advance to the next logical workflow
| Flag | Description |
|------|-------------|
| `--next` | Automatically advance to the next logical workflow step without manual route selection |
| `--next --auto` | Like `--next`, but chains steps automatically until milestone completion or a blocking decision |
| `--next --converge` | When the next action is planning, route it through `/gsd-plan-review-convergence`; requires `workflow.plan_review_convergence=true` |
| `--cross-ai` | Alias for `--converge` |
| Reviewer flags | With `--converge`, pass through `--codex`, `--gemini`, `--claude`, `--opencode`, `--ollama`, `--lm-studio`, `--llama-cpp`, `--all`, and `--max-cycles N` |
| `--do "task description"` | Analyze freeform intent and dispatch to the most appropriate GSD command |
| `--forensic` | Append a 6-check integrity audit after the standard report (STATE consistency, orphaned handoffs, deferred scope drift, memory-flagged pending work, blocking todos, uncommitted code) |
**Auto-routing behavior (`--next`):**
- No project → suggests `/gsd-new-project`
- Phase needs discussion → runs `/gsd-discuss-phase`
- Phase needs planning → runs `/gsd-plan-phase`
- Phase needs planning → runs `/gsd-plan-phase` (or `/gsd-plan-review-convergence` when `--converge` is set)
- Phase needs execution → runs `/gsd-execute-phase`
- Phase needs verification → runs `/gsd-verify-work`
- All phases complete → suggests `/gsd-complete-milestone`
@@ -572,6 +576,8 @@ Show status, next steps, and automatically advance to the next logical workflow
```bash
/gsd-progress # "Where am I? What's next?" with auto-routing
/gsd-progress --next # Advance to next step automatically
/gsd-progress --next --auto # Chain steps automatically until completion
/gsd-progress --next --auto --converge # Hands-free run with plan-review convergence
/gsd-progress --do "fix the auth bug" # Dispatch freeform intent to best GSD command
/gsd-progress --forensic # Standard report + integrity audit
```

View File

@@ -56,17 +56,23 @@ If the phase is already complete, autonomous mode exits immediately with a messa
## Run with plan convergence
Use `--converge` when you want each phase to run the plan-review convergence loop before execution:
Use `--converge` when you want each phase to run the plan-review convergence loop before execution. Both `/gsd-autonomous` and `/gsd-progress --next --auto` support this flag.
```bash
gsd config-set workflow.plan_review_convergence true
# Via autonomous (multi-phase or single-phase):
/gsd-autonomous --only 4 --converge
/gsd-autonomous --from 3 --to 5 --converge --all --max-cycles 5
# Via progress --next --auto (step-chaining with convergence):
/gsd-progress --next --auto --converge
/gsd-progress --next --auto --converge --codex --max-cycles 4
```
`--cross-ai` is accepted as an alias for `--converge`. Reviewer flags supported by `/gsd-plan-review-convergence` pass through unchanged, including `--codex`, `--gemini`, `--claude`, `--opencode`, `--ollama`, `--lm-studio`, `--llama-cpp`, `--all`, and `--max-cycles N`.
If `workflow.plan_review_convergence` is not enabled, autonomous mode stops before planning and prints the enable command instead of silently falling back to regular planning.
If `workflow.plan_review_convergence` is not enabled, the command stops before planning and prints the enable command instead of silently falling back to regular planning.
---

View File

@@ -256,11 +256,15 @@ Check project status and intelligently route to next action.
Modes:
- **default** — progress report + intelligent routing
- **`--next`** — auto-advance to the next logical step (use `--next --force` to bypass safety gates)
- **`--next --auto`** — like `--next`, but chains steps automatically until milestone completion or a blocking decision
- **`--next --converge`** — when the next action is planning, route it through `/gsd:plan-review-convergence` instead of `/gsd:plan-phase`; requires `workflow.plan_review_convergence=true`. `--cross-ai` is an alias. Reviewer flags (`--codex`, `--gemini`, `--claude`, `--opencode`, `--ollama`, `--lm-studio`, `--llama-cpp`, `--all`) and `--max-cycles N` forward to the convergence loop.
- **`--forensic`** — append a 6-check integrity audit after the progress report
- **`--do "<text>"`** — smart router: dispatch freeform intent to the matching `/gsd-*` command (see *Smart Router* above)
Usage: `/gsd:progress`
Usage: `/gsd:progress --next`
Usage: `/gsd:progress --next --auto`
Usage: `/gsd:progress --next --auto --converge`
Usage: `/gsd:progress --forensic`
### Session Management

View File

@@ -230,7 +230,7 @@ If the current phase directory exists but has neither CONTEXT.md nor RESEARCH.md
**Route 3: Phase has context but no plans → plan**
If the current phase has CONTEXT.md (or RESEARCH.md) but no PLAN.md files:
→ Next action: `/gsd:plan-phase <current-phase>`
→ Next action: `/gsd:plan-phase <current-phase>` (or `/gsd:plan-review-convergence <current-phase>` when `PLAN_STRATEGY=converge`)
**Route 4: Phase has plans but incomplete summaries → execute**
If plans exist but not all have matching summaries:
@@ -254,6 +254,47 @@ If STATE.md shows paused_at:
</step>
<step name="show_and_execute">
Parse the arguments passed to this workflow to detect the plan strategy and build convergence pass-through args:
```bash
PLAN_STRATEGY="local"
if echo "$ARGUMENTS" | grep -qE '(^|[[:space:]])\-\-(converge|cross-ai)([[:space:]]|$)'; then
PLAN_STRATEGY="converge"
fi
CONVERGENCE_ARGS=""
for REVIEW_FLAG in --codex --gemini --claude --opencode --ollama --lm-studio --llama-cpp --all --text; do
if echo "$ARGUMENTS" | grep -qE "(^|[[:space:]])${REVIEW_FLAG}([[:space:]]|$)"; then
CONVERGENCE_ARGS="${CONVERGENCE_ARGS} ${REVIEW_FLAG}"
fi
done
MAX_CYCLES_ARG=""
if echo "$ARGUMENTS" | grep -qE '\-\-max-cycles\s+[0-9]+'; then
MAX_CYCLES_ARG=$(echo "$ARGUMENTS" | grep -oE '\-\-max-cycles\s+[0-9]+' | awk '{print $2}')
CONVERGENCE_ARGS="${CONVERGENCE_ARGS} --max-cycles ${MAX_CYCLES_ARG}"
fi
```
If `PLAN_STRATEGY` is `converge`, fail fast unless the convergence feature gate is enabled:
```bash
if [ "$PLAN_STRATEGY" = "converge" ]; then
CONVERGENCE_ENABLED=$(gsd_run query config-get workflow.plan_review_convergence 2>/dev/null || echo "false")
if [ "$CONVERGENCE_ENABLED" != "true" ]; then
printf '%s\n' \
'/gsd:progress --next --converge is disabled (workflow.plan_review_convergence=false).' \
'' \
'Enable plan convergence with:' \
'' \
' gsd config-set workflow.plan_review_convergence true' \
'' \
'Then re-run with --converge.'
exit 1
fi
fi
```
Display the determination:
```
@@ -269,7 +310,9 @@ Display the determination:
Then immediately invoke the determined command via SlashCommand.
Do not ask for confirmation — the whole point of `/gsd:progress --next` is zero-friction advancement.
**If `--auto` was passed:** after the determined command completes, automatically re-invoke `/gsd:progress --next --auto` to continue chaining to the next step. Repeat until one of:
**Route 3 convergence override:** When the routing decision is Route 3 (plan) and `PLAN_STRATEGY=converge`, invoke `/gsd:plan-review-convergence <current-phase> ${CONVERGENCE_ARGS}` instead of `/gsd:plan-phase <current-phase>`.
**If `--auto` was passed:** after the determined command completes, automatically re-invoke `/gsd:progress --next --auto` (forwarding `--converge`/`--cross-ai` and any reviewer flags if they were originally passed) to continue chaining to the next step. Repeat until one of:
- A milestone completes (`/gsd:complete-milestone` is reached)
- A blocking decision is required (safety gate triggers, prior-phase completeness prompt, user input needed)
- An error or paused state is detected
@@ -296,4 +339,9 @@ Resume with: `/gsd:progress --next --auto` once resolved.
- [ ] Next action correctly determined from routing rules
- [ ] Command invoked immediately without user confirmation
- [ ] Clear status shown before invoking
- [ ] `--converge` routes Route 3 planning through `gsd-plan-review-convergence`
- [ ] `--cross-ai` is accepted as an alias for `--converge`
- [ ] `--converge` fails fast with enable instructions when `workflow.plan_review_convergence=false`
- [ ] `--converge` forwards reviewer selector flags and `--max-cycles N`
- [ ] Default planning remains `gsd-plan-phase` when convergence is not requested
</success_criteria>

View File

@@ -0,0 +1,179 @@
// allow-test-rule: source-text-is-the-product #1190
// The progress command and next workflow markdown are runtime-loaded contracts.
// Checking their text verifies the shipped slash-command behavior.
'use strict';
const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const REPO_ROOT = path.join(__dirname, '..');
const COMMAND_PATH = path.join(REPO_ROOT, 'commands', 'gsd', 'progress.md');
const WORKFLOW_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'next.md');
const FULL_MD_PATH = path.join(REPO_ROOT, 'gsd-core', 'workflows', 'help', 'modes', 'full.md');
const COMMANDS_DOC_PATH = path.join(REPO_ROOT, 'docs', 'COMMANDS.md');
const HOW_TO_PATH = path.join(REPO_ROOT, 'docs', 'how-to', 'run-phases-autonomously.md');
function read(filePath) {
return fs.readFileSync(filePath, 'utf8');
}
describe('ADR-15: /gsd:progress --next --auto --converge (#1190)', () => {
test('progress command advertises --converge, --auto, and notes --cross-ai alias', () => {
const command = read(COMMAND_PATH);
assert.match(
command,
/^argument-hint:.*--converge/m,
'progress command should advertise --converge in argument-hint',
);
assert.match(
command,
/^argument-hint:.*--auto/m,
'progress command should advertise --auto in argument-hint',
);
assert.match(command, /--cross-ai/, 'progress command should document --cross-ai alias');
assert.match(
command,
/workflow\.plan_review_convergence=true/,
'progress command should mention the convergence feature gate',
);
});
test('next workflow parses converge aliases into a plan strategy', () => {
const workflow = read(WORKFLOW_PATH);
assert.match(workflow, /PLAN_STRATEGY="local"/, 'workflow should default to local planning');
assert.match(workflow, /PLAN_STRATEGY="converge"/, 'workflow should opt into converge planning');
assert.match(workflow, /converge\|cross-ai/, 'workflow should accept --converge and --cross-ai');
});
test('next workflow fails fast when convergence is requested but disabled', () => {
const workflow = read(WORKFLOW_PATH);
assert.match(
workflow,
/config-get workflow\.plan_review_convergence/,
'workflow should check workflow.plan_review_convergence before planning',
);
assert.match(
workflow,
/gsd config-set workflow\.plan_review_convergence true/,
'workflow should print the enable command instead of silently downgrading',
);
});
test('next workflow routes Route 3 through plan-review-convergence when PLAN_STRATEGY=converge', () => {
const workflow = read(WORKFLOW_PATH);
assert.match(
workflow,
/\/gsd:plan-review-convergence/,
'next workflow should reference /gsd:plan-review-convergence for the converge route',
);
assert.match(
workflow,
/PLAN_STRATEGY=converge/,
'next workflow should check PLAN_STRATEGY for the converge override',
);
assert.match(
workflow,
/gsd:plan-phase/,
'local planning path should remain available for default next runs',
);
// Args-forwarding contract: Route 3 invocation must pass ${CONVERGENCE_ARGS} to the convergence
// command — not just route to the command name but actually forward the built args variable.
assert.match(
workflow,
/\/gsd:plan-review-convergence[^\n]*\$\{CONVERGENCE_ARGS\}/,
'Route 3 convergence invocation must include ${CONVERGENCE_ARGS} on the same line as the command',
);
});
test('next workflow forwards reviewer flags and max cycles to convergence', () => {
const workflow = read(WORKFLOW_PATH);
const reviewerFlags = [
'--codex',
'--gemini',
'--claude',
'--opencode',
'--ollama',
'--lm-studio',
'--llama-cpp',
'--all',
'--text',
];
assert.match(workflow, /CONVERGENCE_ARGS/, 'workflow should build convergence pass-through args');
for (const flag of reviewerFlags) {
assert.ok(workflow.includes(flag), `workflow should pass through ${flag}`);
}
assert.match(workflow, /--max-cycles/, 'workflow should pass through --max-cycles N');
});
test('next workflow preserves --auto re-invocation chaining', () => {
const workflow = read(WORKFLOW_PATH);
assert.match(
workflow,
/--auto/,
'workflow should document the --auto chaining behavior',
);
assert.match(
workflow,
/\/gsd:progress --next --auto/,
'workflow should re-invoke /gsd:progress --next --auto for chaining',
);
// Forwarding contract: the --auto re-invocation must explicitly state that --converge/--cross-ai
// and reviewer flags are forwarded — not just re-invoke --auto alone.
assert.match(
workflow,
/\/gsd:progress --next --auto[^\n]*(forwarding|--converge)/,
'workflow --auto re-invocation should document forwarding --converge/--cross-ai and reviewer flags',
);
});
test('full.md documents --converge, --auto, and --cross-ai for /gsd:progress', () => {
const fullMd = read(FULL_MD_PATH);
assert.match(
fullMd,
/\/gsd:progress --next --auto --converge/,
'full.md should show /gsd:progress --next --auto --converge usage',
);
assert.match(
fullMd,
/--auto/,
'full.md should document --auto for progress',
);
assert.match(
fullMd,
/--cross-ai/,
'full.md should mention --cross-ai alias for convergence',
);
});
test('COMMANDS.md documents progress convergence flags and usage', () => {
const commandsDoc = read(COMMANDS_DOC_PATH);
assert.match(
commandsDoc,
/\/gsd-progress --next --auto --converge/,
'COMMANDS.md should show /gsd-progress --next --auto --converge usage example',
);
assert.match(commandsDoc, /--converge/, 'COMMANDS.md should document --converge for progress');
assert.match(commandsDoc, /--cross-ai/, 'COMMANDS.md should document --cross-ai alias for progress');
});
test('how-to shows /gsd-progress --next --auto --converge usage', () => {
const howTo = read(HOW_TO_PATH);
assert.match(
howTo,
/\/gsd-progress --next --auto --converge/,
'how-to should show /gsd-progress --next --auto --converge usage',
);
});
});

View File

@@ -46,7 +46,7 @@
"new-milestone.md": 32422,
"new-project.md": 61802,
"new-workspace.md": 11254,
"next.md": 17868,
"next.md": 20094,
"node-repair.md": 4173,
"note.md": 6563,
"pause-work.md": 14397,