* chore(#604): rename get-shit-done/ runtime directory to gsd-core/ Renames the installed runtime directory `get-shit-done/` to `gsd-core/` so the on-disk name matches the package (`@opengsd/gsd-core`), repo, and binary (`gsd-tools`). The npm package name and binary are unchanged; npx/npm consumers are unaffected. Mechanical (bulk, ~90% of the diff): - `git mv get-shit-done gsd-core` - Swept path/identifier references across the repo via `perl -pe 's/get-shit-done(?!-\w)/gsd-core/g'`. The negative lookahead preserves the five legitimate slug variants that are NOT the directory: get-shit-done-{OLD,cc,classic,cli,redux} (old package/repo names). - Build/manifest wiring: package.json (bin, files, coverage globs), tsconfig.build.json (outDir), ~86 .gitignore build-output entries, stryker.config.mjs, scan-ignore files, install.js path strings. - Frozen (not rewritten): CHANGELOG.md history; translated docs (README.<locale>.md and docs/{ja-JP,ko-KR,pt-BR,zh-CN}/). New logic (review here): - src/installer-migrations/003-rename-get-shit-done-to-gsd-core.cts: a proper ADR-0008 installer migration. On upgrade it walks the legacy `~/.claude/get-shit-done/` tree, classifies each file via the prior install manifest, and emits remove-managed / backup-and-remove for managed files while PRESERVING unknown user-added files. Symlink-safe (skips a symlinked root and symlinked entries; bounds-checks every path under configDir). The framework rolls back on install failure. Emptied dirs may remain (framework has no recursive dir-removal primitive) — documented. - scripts/lint-legacy-dir-name.cjs: CI regression guard forbidding the bare `get-shit-done` directory token (split token to avoid self-match; case- insensitive; `(?!-\w)` lookahead allows the slug variants; allowlists CHANGELOG, translated docs, and `gsd-allow-legacy-name` marker lines). Wired into the lint-tests CI job. - Restored scripts/lint-package-identity-drift.cjs detection regexes (the mechanical sweep had wrongly rewritten the old-name patterns it exists to detect) and marked them as intentional legacy references. - TDD tests for the migration and the guard; do.md slash-command guard regex tightened so a `/gsd-core/bin` path segment is not mistaken for a command; changeset + docs/installer-migrations.md row added. Breaking: the installed runtime path moves `~/.claude/get-shit-done/` -> `~/.claude/gsd-core/`. Migration 003 removes the stale legacy dir's managed files (preserving user files) on upgrade. Users with custom hooks/configs hardcoding the old path must update them. Closes #604 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unsweep pending changesets + allowlist injection-example docs CI fixes for the rename PR: - Do not sweep pending .changeset/*.md (ephemeral release-note fragments, like CHANGELOG); reverted those body edits so 5 pre-existing malformed fragments (missing type/pr) no longer enter the PR diff and trip docs-lint. Allowlisted .changeset/ in the legacy-name guard accordingly. - Allowlisted TEST-EXAMPLES.md and docs/explanation/security-model.md in prompt-injection-scan.sh: they contain intentional injection examples / security-model prose; the path-reference rewrites are kept. CodeQL alerts on this PR are pre-existing (alert lines unchanged by this PR; none in the new migration/guard) and are out of scope for the rename. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): resolve CodeQL alerts surfaced on this PR The rename diff touched files carrying pre-existing CodeQL findings; per the no-pre-existing-dismissal rule, fixing every surfaced alert rather than waving them off. All behavior-preserving: - scripts/ci-test-scope.cjs: build the config-path match from string .includes() instead of a RegExp over an arg-derived value (js/regex-injection). - src/profile-output.cts: escape backslashes before pipe-escaping desc/safeName so the table-cell escape is complete (js/incomplete-sanitization). - tests/{bug-2643,bug-2808,docs-parity-live-registry}: two-pass HTML-comment strip so a bare/unclosed `<!--` cannot survive (js/incomplete-multi-character-sanitization). - tests/inline-plan-threshold: drop the no-op `\s`->`\s` identity replace, keep the meaningful POSIX-class conversion (js/identity-replacement). Verified: build:lib green; the touched test files + ci-test-scope + profile-output suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): correctly resolve remaining CodeQL alerts (regex-injection + sanitization) The prior commit's fixes for two alerts were ineffective: - ci-test-scope.cjs js/regex-injection: the alert is the CLI-arg-derived `file` reaching static regex `.test(file)` calls (not the config rule). Removed ALL regex over file/t — startsWith/includes/=== string checks + an isWindowsHint helper — so there is no regex sink for the tainted value. - js/incomplete-multi-character-sanitization (3 test files): a single `.replace(/<!--...-->/g,'')` can let `<!--` re-form. Replaced with a fixpoint loop (replace until stable) plus a final bare-opener strip. Verified: no regex over file/t remains; ci-test-scope + the 3 test suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): make ci-test-scope + comment-strippers regex-free to clear CodeQL CodeQL flags the regex PATTERNS syntactically (regex-injection on the --files arg split; incomplete-multi-character-sanitization on the <!--...--> replace), so loop fixes do not satisfy it. Made these paths regex-free: - ci-test-scope.cjs splitFiles: char-by-char separator tokenizer (no /[,\\s]+/). - 3 test files: indexOf/slice HTML-comment stripper (no .replace(/<!--/)). Behavior preserved; ci-test-scope + the 3 suites pass; guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unblock security base64 scan on the large rename diff The security job hit its 10m timeout: base64-scan.sh choked on the binary test fixture tests/feat-3594-parser-property-style.test.cjs (embedded NUL/ non-UTF8 bytes -> thousands of bogus blobs + "ignored null byte" warnings), and the ~800-file rename diff is slow to scan regardless. - scripts/base64-scan.sh: skip binary-by-content files (grep -Iq .) — they can't carry base64-obfuscated *text* and feeding NUL bytes through the per-line scanner is pathologically slow. collect_files already filtered binary *extensions*; this catches binary *content* in text extensions. - .github/workflows/security-scan.yml: raise the security job timeout 10m->30m to accommodate very large diffs (the scan itself is unchanged). Verified locally: scan skips the fixture, 0 "ignored null byte" warnings, 0 findings, exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): sweep get-shit-done refs introduced by merging next The branch was updated with next (#614/#384/#618 etc.), which reference the get-shit-done/ dir (still named that on next). Swept the stale references in the merged files to gsd-core so the rename stays consistent and lint:legacy-name passes: - commands/gsd/discuss-phase.md (runtime-launcher shim paths) - src/core.cts (getAgentsDir layout comments) - tests/bug-384-agents-runtime-aware.test.cjs (require path to runtime lib) Verified: guard 0 violations; build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): exclude gsd-core/ path segments from bug-3683 command cross-ref invariant The #614 runtime-launcher shim added to discuss-phase.md references `${_GSD_RUNTIME_ROOT}/gsd-core/bin/...`. bug-3683's REF_PATTERN excluded path-y refs only via lookbehind, but `}` precedes `/gsd-core/` in the shim, so it mis-read the directory path as a dangling `/gsd-core` command ref (same class as the #604 bug-2954 fix). Added a trailing `(?![\w-]*\/)` so `/gsd-<x>/...` path segments are not treated as slash-command references. Verified locally on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22 image) full suite: 0 failures - bug-3683 + bug-2954 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): lazily resolve findProjectRoot in gsd-tools (harden flaky CI) CI intermittently failed state.test's gsd-tools subprocess with "findProjectRoot is not a function" (flip-flopping across legs; not reproducible on mac full suite, gsd-test linux full suite, test:unit, or state.test x8). findProjectRoot is a re-export from core.cjs (sourced from project-root.cjs); binding it via destructure at module-load can be undefined under a load-ordering edge. Resolve it lazily at call time via a small wrapper so the lookup happens after core.cjs is fully initialized. Verified green on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22) full suite: 0 failures - state.test.cjs: 106/106; gsd-tools loads cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): allowlist verification-patterns.md placeholder examples in secret scan The rename git-mv'd references/verification-patterns.md into gsd-core/, pulling it into the secret-scan diff. It documents stub/placeholder RED-FLAG env-var examples (illustrative Stripe test-key / database-URL / API-key placeholders) — not real credentials. Added it to .secretscanignore with the strict annotation, mirroring the existing gsd-core/workflows/plan-phase.md exception. Verified locally: secret-scan-lint --strict OK; secret-scan --diff origin/next exits 0 with 0 findings. 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:
694
gsd-core/workflows/transition.md
Normal file
694
gsd-core/workflows/transition.md
Normal file
@@ -0,0 +1,694 @@
|
||||
<internal_workflow>
|
||||
|
||||
**This is an INTERNAL workflow — NOT a user-facing command.**
|
||||
|
||||
There is no `/gsd-transition` command. This workflow is invoked automatically by
|
||||
`execute-phase` during auto-advance, or inline by the orchestrator after phase
|
||||
verification. Users should never be told to run `/gsd-transition`.
|
||||
|
||||
**Valid user commands for phase progression:**
|
||||
- `/gsd:discuss-phase {N}` — discuss a phase before planning
|
||||
- `/gsd:plan-phase {N}` — plan a phase
|
||||
- `/gsd:execute-phase {N}` — execute a phase
|
||||
- `/gsd:progress` — see roadmap progress
|
||||
|
||||
</internal_workflow>
|
||||
|
||||
<required_reading>
|
||||
|
||||
**Read these files NOW:**
|
||||
|
||||
1. `.planning/STATE.md`
|
||||
2. `.planning/PROJECT.md`
|
||||
3. `.planning/ROADMAP.md`
|
||||
4. Current phase's plan files (`*-PLAN.md`)
|
||||
5. Current phase's summary files (`*-SUMMARY.md`)
|
||||
|
||||
</required_reading>
|
||||
|
||||
<purpose>
|
||||
|
||||
Mark current phase complete and advance to next. This is the natural point where progress tracking and PROJECT.md evolution happen.
|
||||
|
||||
"Planning next phase" = "current phase is done"
|
||||
|
||||
</purpose>
|
||||
|
||||
<process>
|
||||
|
||||
<step name="load_project_state" priority="first">
|
||||
|
||||
Before transition, read project state:
|
||||
|
||||
```bash
|
||||
cat .planning/STATE.md 2>/dev/null || true
|
||||
cat .planning/PROJECT.md 2>/dev/null || true
|
||||
```
|
||||
|
||||
Parse current position to verify we're transitioning the right phase.
|
||||
Note accumulated context that may need updating after transition.
|
||||
|
||||
</step>
|
||||
|
||||
<step name="verify_completion">
|
||||
|
||||
Check current phase has all plan summaries:
|
||||
|
||||
```bash
|
||||
(ls .planning/phases/XX-current/*-PLAN.md 2>/dev/null || true) | sort
|
||||
(ls .planning/phases/XX-current/*-SUMMARY.md 2>/dev/null || true) | sort
|
||||
```
|
||||
|
||||
**Verification logic:**
|
||||
|
||||
- Count PLAN files
|
||||
- Count SUMMARY files
|
||||
- If counts match: all plans complete
|
||||
- If counts don't match: incomplete
|
||||
|
||||
<config-check>
|
||||
|
||||
```bash
|
||||
cat .planning/config.json 2>/dev/null || true
|
||||
```
|
||||
|
||||
</config-check>
|
||||
|
||||
**Check for verification debt in this phase:**
|
||||
|
||||
```bash
|
||||
# Count outstanding items in current phase
|
||||
OUTSTANDING=""
|
||||
for f in .planning/phases/XX-current/*-UAT.md .planning/phases/XX-current/*-VERIFICATION.md; do
|
||||
[ -f "$f" ] || continue
|
||||
grep -q "result: pending\|result: blocked\|status: partial\|status: human_needed\|status: diagnosed" "$f" && OUTSTANDING="$OUTSTANDING\n$(basename $f)"
|
||||
done
|
||||
```
|
||||
|
||||
**If OUTSTANDING is not empty:**
|
||||
|
||||
Append to the completion confirmation message (regardless of mode):
|
||||
|
||||
```
|
||||
Outstanding verification items in this phase:
|
||||
{list filenames}
|
||||
|
||||
These will carry forward as debt. Review: `/gsd:audit-uat`
|
||||
```
|
||||
|
||||
This does NOT block transition — it ensures the user sees the debt before confirming.
|
||||
|
||||
**If all plans complete:**
|
||||
|
||||
<if mode="yolo">
|
||||
|
||||
```
|
||||
⚡ Auto-approved: Transition Phase [X] → Phase [X+1]
|
||||
Phase [X] complete — all [Y] plans finished.
|
||||
|
||||
Proceeding to mark done and advance...
|
||||
```
|
||||
|
||||
Proceed directly to cleanup_handoff step.
|
||||
|
||||
</if>
|
||||
|
||||
<if mode="interactive" OR="custom with gates.confirm_transition true">
|
||||
|
||||
Ask: "Phase [X] complete — all [Y] plans finished. Ready to mark done and move to Phase [X+1]?"
|
||||
|
||||
Wait for confirmation before proceeding.
|
||||
|
||||
</if>
|
||||
|
||||
**If plans incomplete:**
|
||||
|
||||
**SAFETY RAIL: always_confirm_destructive applies here.**
|
||||
Skipping incomplete plans is destructive — ALWAYS prompt regardless of mode.
|
||||
|
||||
Present:
|
||||
|
||||
```
|
||||
Phase [X] has incomplete plans:
|
||||
- {phase}-01-SUMMARY.md ✓ Complete
|
||||
- {phase}-02-SUMMARY.md ✗ Missing
|
||||
- {phase}-03-SUMMARY.md ✗ Missing
|
||||
|
||||
⚠️ Safety rail: Skipping plans requires confirmation (destructive action)
|
||||
|
||||
Options:
|
||||
1. Continue current phase (execute remaining plans)
|
||||
2. Mark complete anyway (skip remaining plans)
|
||||
3. Review what's left
|
||||
```
|
||||
|
||||
Wait for user decision.
|
||||
|
||||
</step>
|
||||
|
||||
<step name="cleanup_handoff">
|
||||
|
||||
Check for lingering handoffs:
|
||||
|
||||
```bash
|
||||
ls .planning/phases/XX-current/.continue-here*.md 2>/dev/null || true
|
||||
```
|
||||
|
||||
If found, delete them — phase is complete, handoffs are stale.
|
||||
|
||||
</step>
|
||||
|
||||
<step name="update_roadmap_and_state">
|
||||
|
||||
**Delegate ROADMAP.md and STATE.md updates to `gsd-tools.cjs query phase.complete`:**
|
||||
|
||||
```bash
|
||||
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="$HOME/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi
|
||||
TRANSITION=$(gsd_run query phase.complete "${current_phase}")
|
||||
```
|
||||
|
||||
The CLI handles:
|
||||
- Marking the phase checkbox as `[x]` complete with today's date
|
||||
- Updating plan count to final (e.g., "3/3 plans complete")
|
||||
- Updating the Progress table (Status → Complete, adding date)
|
||||
- Advancing STATE.md to next phase (Current Phase, Status → Ready to plan, Current Plan → Not started)
|
||||
- Detecting if this is the last phase in the milestone
|
||||
|
||||
Extract from result: `completed_phase`, `plans_executed`, `next_phase`, `next_phase_name`, `is_last_phase`.
|
||||
|
||||
</step>
|
||||
|
||||
<step name="archive_prompts">
|
||||
|
||||
If prompts were generated for the phase, they stay in place.
|
||||
The `completed/` subfolder pattern from create-meta-prompts handles archival.
|
||||
|
||||
</step>
|
||||
|
||||
<step name="evolve_project">
|
||||
|
||||
Evolve PROJECT.md to reflect learnings from completed phase.
|
||||
|
||||
**Read phase summaries:**
|
||||
|
||||
```bash
|
||||
cat .planning/phases/XX-current/*-SUMMARY.md
|
||||
```
|
||||
|
||||
**Assess requirement changes:**
|
||||
|
||||
1. **Requirements validated?**
|
||||
- Any Active requirements shipped in this phase?
|
||||
- Move to Validated with phase reference: `- ✓ [Requirement] — Phase X`
|
||||
|
||||
2. **Requirements invalidated?**
|
||||
- Any Active requirements discovered to be unnecessary or wrong?
|
||||
- Move to Out of Scope with reason: `- [Requirement] — [why invalidated]`
|
||||
|
||||
3. **Requirements emerged?**
|
||||
- Any new requirements discovered during building?
|
||||
- Add to Active: `- [ ] [New requirement]`
|
||||
|
||||
4. **Decisions to log?**
|
||||
- Extract decisions from SUMMARY.md files
|
||||
- Add to Key Decisions table with outcome if known
|
||||
|
||||
5. **"What This Is" still accurate?**
|
||||
- If the product has meaningfully changed, update the description
|
||||
- Keep it current and accurate
|
||||
|
||||
**Update PROJECT.md:**
|
||||
|
||||
Make the edits inline. Update "Last updated" footer:
|
||||
|
||||
```markdown
|
||||
---
|
||||
*Last updated: [date] after Phase [X]*
|
||||
```
|
||||
|
||||
**Example evolution:**
|
||||
|
||||
Before:
|
||||
|
||||
```markdown
|
||||
### Active
|
||||
|
||||
- [ ] JWT authentication
|
||||
- [ ] Real-time sync < 500ms
|
||||
- [ ] Offline mode
|
||||
|
||||
### Out of Scope
|
||||
|
||||
- OAuth2 — complexity not needed for v1
|
||||
```
|
||||
|
||||
After (Phase 2 shipped JWT auth, discovered rate limiting needed):
|
||||
|
||||
```markdown
|
||||
### Validated
|
||||
|
||||
- ✓ JWT authentication — Phase 2
|
||||
|
||||
### Active
|
||||
|
||||
- [ ] Real-time sync < 500ms
|
||||
- [ ] Offline mode
|
||||
- [ ] Rate limiting on sync endpoint
|
||||
|
||||
### Out of Scope
|
||||
|
||||
- OAuth2 — complexity not needed for v1
|
||||
```
|
||||
|
||||
**Step complete when:**
|
||||
|
||||
- [ ] Phase summaries reviewed for learnings
|
||||
- [ ] Validated requirements moved from Active
|
||||
- [ ] Invalidated requirements moved to Out of Scope with reason
|
||||
- [ ] Emerged requirements added to Active
|
||||
- [ ] New decisions logged with rationale
|
||||
- [ ] "What This Is" updated if product changed
|
||||
- [ ] "Last updated" footer reflects this transition
|
||||
|
||||
</step>
|
||||
|
||||
<step name="graduation_scan">
|
||||
|
||||
Scan LEARNINGS.md files from recent phases for recurring patterns and surface promotion candidates to the developer.
|
||||
|
||||
**Invoke the graduation helper:**
|
||||
|
||||
```text
|
||||
@~/.claude/gsd-core/workflows/graduation.md
|
||||
```
|
||||
|
||||
This step is fully delegated to `graduation.md`. It handles guard checks (feature flag, window size, threshold), clustering, backlog filtering, HITL prompting, promotion writes, and STATE.md updates.
|
||||
|
||||
**This step is always non-blocking:** graduation candidates are surfaced for the developer's decision; no action is required to continue the transition. If the graduation scan produces no qualifying clusters, it prints a single `[graduation: no qualifying clusters]` line and returns.
|
||||
|
||||
**Step complete when:**
|
||||
|
||||
- [ ] graduation.md guard checks passed (or skipped with silent no-op)
|
||||
- [ ] Recurring clusters surfaced (or `[graduation: no qualifying clusters]` printed)
|
||||
- [ ] Each cluster resolved as Promote / Defer / Dismiss (or all skipped)
|
||||
|
||||
</step>
|
||||
|
||||
<step name="update_current_position_after_transition">
|
||||
|
||||
**Note:** Basic position updates (Current Phase, Status, Current Plan, Last Activity) were already handled by `gsd-tools.cjs query phase.complete` in the update_roadmap_and_state step.
|
||||
|
||||
Verify the updates are correct by reading STATE.md. If the progress bar needs updating, use:
|
||||
|
||||
```bash
|
||||
PROGRESS=$(gsd_run query progress.bar --raw)
|
||||
```
|
||||
|
||||
Update the progress bar line in STATE.md with the result.
|
||||
|
||||
**Step complete when:**
|
||||
|
||||
- [ ] Phase number incremented to next phase (done by phase complete)
|
||||
- [ ] Plan status reset to "Not started" (done by phase complete)
|
||||
- [ ] Status shows "Ready to plan" (done by phase complete)
|
||||
- [ ] Progress bar reflects total completed plans
|
||||
|
||||
</step>
|
||||
|
||||
<step name="update_project_reference">
|
||||
|
||||
Update Project Reference section in STATE.md.
|
||||
|
||||
```markdown
|
||||
## Project Reference
|
||||
|
||||
See: .planning/PROJECT.md (updated [today])
|
||||
|
||||
**Core value:** [Current core value from PROJECT.md]
|
||||
**Current focus:** [Next phase name]
|
||||
```
|
||||
|
||||
Update the date and current focus to reflect the transition.
|
||||
|
||||
</step>
|
||||
|
||||
<step name="review_accumulated_context">
|
||||
|
||||
Review and update Accumulated Context section in STATE.md.
|
||||
|
||||
**Decisions:**
|
||||
|
||||
- Note recent decisions from this phase (3-5 max)
|
||||
- Full log lives in PROJECT.md Key Decisions table
|
||||
|
||||
**Blockers/Concerns:**
|
||||
|
||||
- Review blockers from completed phase
|
||||
- If addressed in this phase: Remove from list
|
||||
- If still relevant for future: Keep with "Phase X" prefix
|
||||
- Add any new concerns from completed phase's summaries
|
||||
|
||||
**Example:**
|
||||
|
||||
Before:
|
||||
|
||||
```markdown
|
||||
### Blockers/Concerns
|
||||
|
||||
- ⚠️ [Phase 1] Database schema not indexed for common queries
|
||||
- ⚠️ [Phase 2] WebSocket reconnection behavior on flaky networks unknown
|
||||
```
|
||||
|
||||
After (if database indexing was addressed in Phase 2):
|
||||
|
||||
```markdown
|
||||
### Blockers/Concerns
|
||||
|
||||
- ⚠️ [Phase 2] WebSocket reconnection behavior on flaky networks unknown
|
||||
```
|
||||
|
||||
**Step complete when:**
|
||||
|
||||
- [ ] Recent decisions noted (full log in PROJECT.md)
|
||||
- [ ] Resolved blockers removed from list
|
||||
- [ ] Unresolved blockers kept with phase prefix
|
||||
- [ ] New concerns from completed phase added
|
||||
|
||||
</step>
|
||||
|
||||
<step name="update_session_continuity_after_transition">
|
||||
|
||||
Update Session Continuity section in STATE.md to reflect transition completion.
|
||||
|
||||
**Format:**
|
||||
|
||||
```markdown
|
||||
Last session: [today]
|
||||
Stopped at: Phase [X] complete, ready to plan Phase [X+1]
|
||||
Resume file: None
|
||||
```
|
||||
|
||||
**Step complete when:**
|
||||
|
||||
- [ ] Last session timestamp updated to current date and time
|
||||
- [ ] Stopped at describes phase completion and next phase
|
||||
- [ ] Resume file confirmed as None (transitions don't use resume files)
|
||||
|
||||
</step>
|
||||
|
||||
<step name="offer_next_phase">
|
||||
|
||||
**MANDATORY: Verify milestone status before presenting next steps.**
|
||||
|
||||
**Use the transition result from `gsd-tools.cjs query phase.complete`:**
|
||||
|
||||
The `is_last_phase` field from the phase complete result tells you directly:
|
||||
- `is_last_phase: false` → More phases remain → Go to **Route A**
|
||||
- `is_last_phase: true` → Last phase done → **Check for workstream collisions first**
|
||||
|
||||
The `next_phase` and `next_phase_name` fields give you the next phase details.
|
||||
|
||||
If you need additional context, use:
|
||||
```bash
|
||||
ROADMAP=$(gsd_run query roadmap.analyze)
|
||||
```
|
||||
|
||||
This returns all phases with goals, disk status, and completion info.
|
||||
|
||||
---
|
||||
|
||||
**Workstream collision check (when `is_last_phase: true`):**
|
||||
|
||||
Before routing to Route B, check whether other workstreams are still active.
|
||||
This prevents one workstream from advancing or completing the milestone while
|
||||
other workstreams are still working on their phases.
|
||||
|
||||
**Skip this check if NOT in workstream mode** (i.e., `GSD_WORKSTREAM` is not set / flat mode).
|
||||
In flat mode, go directly to **Route B**.
|
||||
|
||||
```bash
|
||||
# Only check if we're in workstream mode
|
||||
if [ -n "$GSD_WORKSTREAM" ]; then
|
||||
WS_LIST=$(gsd_run query workstream.list --raw)
|
||||
fi
|
||||
```
|
||||
|
||||
Parse the JSON result. The output has `{ mode, workstreams: [...] }`.
|
||||
Each workstream entry has: `name`, `status`, `current_phase`, `phase_count`, `completed_phases`.
|
||||
|
||||
Filter out the current workstream (`$GSD_WORKSTREAM`) and any workstreams with
|
||||
status containing "milestone complete" or "archived" (case-insensitive).
|
||||
The remaining entries are **other active workstreams**.
|
||||
|
||||
- **If other active workstreams exist** → Go to **Route B1**
|
||||
- **If NO other active workstreams** (or flat mode) → Go to **Route B**
|
||||
|
||||
---
|
||||
|
||||
**Route A: More phases remain in milestone**
|
||||
|
||||
Read ROADMAP.md to get the next phase's name and goal.
|
||||
|
||||
**Check if next phase has CONTEXT.md:**
|
||||
|
||||
```bash
|
||||
ls .planning/phases/*[X+1]*/*-CONTEXT.md 2>/dev/null || true
|
||||
```
|
||||
|
||||
**If next phase exists:**
|
||||
|
||||
<if mode="yolo">
|
||||
|
||||
**If CONTEXT.md exists:**
|
||||
|
||||
```
|
||||
Phase [X] marked complete.
|
||||
|
||||
Next: Phase [X+1] — [Name]
|
||||
|
||||
⚡ Auto-continuing: Plan Phase [X+1] in detail
|
||||
```
|
||||
|
||||
Exit skill and invoke SlashCommand("/gsd:plan-phase [X+1] --auto ${GSD_WS}")
|
||||
|
||||
**If CONTEXT.md does NOT exist:**
|
||||
|
||||
```
|
||||
Phase [X] marked complete.
|
||||
|
||||
Next: Phase [X+1] — [Name]
|
||||
|
||||
⚡ Auto-continuing: Discuss Phase [X+1] first
|
||||
```
|
||||
|
||||
Exit skill and invoke SlashCommand("/gsd:discuss-phase [X+1] --auto ${GSD_WS}")
|
||||
|
||||
</if>
|
||||
|
||||
<if mode="interactive" OR="custom with gates.confirm_transition true">
|
||||
|
||||
**If CONTEXT.md does NOT exist:**
|
||||
|
||||
```
|
||||
## ✓ Phase [X] Complete
|
||||
|
||||
---
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**Phase [X+1]: [Name]** — [Goal from ROADMAP.md]
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`/gsd:discuss-phase [X+1] ${GSD_WS}` — gather context and clarify approach
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:plan-phase [X+1] ${GSD_WS}` — skip discussion, plan directly
|
||||
- `/gsd:plan-phase --research-phase [X+1] ${GSD_WS}` — investigate unknowns
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
**If CONTEXT.md exists:**
|
||||
|
||||
```
|
||||
## ✓ Phase [X] Complete
|
||||
|
||||
---
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**Phase [X+1]: [Name]** — [Goal from ROADMAP.md]
|
||||
<sub>✓ Context gathered, ready to plan</sub>
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`/gsd:plan-phase [X+1] ${GSD_WS}`
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- `/gsd:discuss-phase [X+1] ${GSD_WS}` — revisit context
|
||||
- `/gsd:plan-phase --research-phase [X+1] ${GSD_WS}` — investigate unknowns
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
</if>
|
||||
|
||||
---
|
||||
|
||||
**Route B1: Workstream done, other workstreams still active**
|
||||
|
||||
This route is reached when `is_last_phase: true` AND the collision check found
|
||||
other active workstreams. Do NOT suggest completing the milestone or advancing
|
||||
to the next milestone — other workstreams are still working.
|
||||
|
||||
**Clear auto-advance chain flag** — workstream boundary is the natural stopping point:
|
||||
|
||||
```bash
|
||||
gsd_run query config-set workflow._auto_chain_active false
|
||||
```
|
||||
|
||||
<if mode="yolo">
|
||||
|
||||
Override auto-advance: do NOT auto-continue to milestone completion.
|
||||
Present the blocking information and stop.
|
||||
|
||||
</if>
|
||||
|
||||
Present (all modes):
|
||||
|
||||
```
|
||||
## ✓ Phase {X}: {Phase Name} Complete
|
||||
|
||||
This workstream's phases are complete. Other workstreams are still active:
|
||||
|
||||
| Workstream | Status | Phase | Progress |
|
||||
|------------|--------|-------|----------|
|
||||
| {name} | {status} | {current_phase} | {completed_phases}/{phase_count} |
|
||||
| ... | ... | ... | ... |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
Archive this workstream:
|
||||
|
||||
`/gsd:workstreams complete {current_ws_name} ${GSD_WS}`
|
||||
|
||||
See overall milestone progress:
|
||||
|
||||
`/gsd:workstreams progress ${GSD_WS}`
|
||||
|
||||
<sub>Milestone completion will be available once all workstreams finish.</sub>
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
Do NOT suggest `/gsd:complete-milestone` or `/gsd:new-milestone`.
|
||||
Do NOT auto-invoke any further slash commands.
|
||||
|
||||
**Stop here.** The user must explicitly decide what to do next.
|
||||
|
||||
---
|
||||
|
||||
**Route B: Milestone complete (all phases done)**
|
||||
|
||||
**This route is only reached when:**
|
||||
- `is_last_phase: true` AND no other active workstreams exist (or flat mode)
|
||||
|
||||
**Clear auto-advance chain flag** — milestone boundary is the natural stopping point:
|
||||
|
||||
```bash
|
||||
gsd_run query config-set workflow._auto_chain_active false
|
||||
```
|
||||
|
||||
<if mode="yolo">
|
||||
|
||||
```
|
||||
Phase {X} marked complete.
|
||||
|
||||
🎉 Milestone {version} is 100% complete — all {N} phases finished!
|
||||
|
||||
⚡ Auto-continuing: Complete milestone and archive
|
||||
```
|
||||
|
||||
Exit skill and invoke SlashCommand("/gsd:complete-milestone {version} ${GSD_WS}")
|
||||
|
||||
</if>
|
||||
|
||||
<if mode="interactive" OR="custom with gates.confirm_transition true">
|
||||
|
||||
```
|
||||
## ✓ Phase {X}: {Phase Name} Complete
|
||||
|
||||
🎉 Milestone {version} is 100% complete — all {N} phases finished!
|
||||
|
||||
---
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**Complete Milestone {version}** — archive and prepare for next
|
||||
|
||||
`/clear` then:
|
||||
|
||||
`/gsd:complete-milestone {version} ${GSD_WS}`
|
||||
|
||||
---
|
||||
|
||||
**Also available:**
|
||||
- Review accomplishments before archiving
|
||||
|
||||
---
|
||||
```
|
||||
|
||||
</if>
|
||||
|
||||
</step>
|
||||
|
||||
</process>
|
||||
|
||||
<implicit_tracking>
|
||||
Progress tracking is IMPLICIT: planning phase N implies phases 1-(N-1) complete. No separate progress step—forward motion IS progress.
|
||||
</implicit_tracking>
|
||||
|
||||
<partial_completion>
|
||||
|
||||
If user wants to move on but phase isn't fully complete:
|
||||
|
||||
```
|
||||
Phase [X] has incomplete plans:
|
||||
- {phase}-02-PLAN.md (not executed)
|
||||
- {phase}-03-PLAN.md (not executed)
|
||||
|
||||
Options:
|
||||
1. Mark complete anyway (plans weren't needed)
|
||||
2. Defer work to later phase
|
||||
3. Stay and finish current phase
|
||||
```
|
||||
|
||||
Respect user judgment — they know if work matters.
|
||||
|
||||
**If marking complete with incomplete plans:**
|
||||
|
||||
- Update ROADMAP: "2/3 plans complete" (not "3/3")
|
||||
- Note in transition message which plans were skipped
|
||||
|
||||
</partial_completion>
|
||||
|
||||
<success_criteria>
|
||||
|
||||
Transition is complete when:
|
||||
|
||||
- [ ] Current phase plan summaries verified (all exist or user chose to skip)
|
||||
- [ ] Any stale handoffs deleted
|
||||
- [ ] ROADMAP.md updated with completion status and plan count
|
||||
- [ ] PROJECT.md evolved (requirements, decisions, description if needed)
|
||||
- [ ] STATE.md updated (position, project reference, context, session)
|
||||
- [ ] Progress table updated
|
||||
- [ ] User knows next steps
|
||||
|
||||
</success_criteria>
|
||||
Reference in New Issue
Block a user