* 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:
5
.changeset/1190-progress-converge-surface.md
Normal file
5
.changeset/1190-progress-converge-surface.md
Normal 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)
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
179
tests/adr-15-progress-converge.test.cjs
Normal file
179
tests/adr-15-progress-converge.test.cjs
Normal 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',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user