* fix(#2308): make new-milestone workstream-aware; stop clobbering shared PROJECT.md Step 4 rewrote the `## Current Milestone` heading in the shared root PROJECT.md unconditionally. references/workstream-flag.md marks PROJECT.md `# Shared`, and per-workstream milestone state already lives in the workstream's own STATE.md / ROADMAP.md / REQUIREMENTS.md. With parallel milestones — the sanctioned design — whichever workstream ran new-milestone last silently won the shared heading. Step 4 is now skipped when a workstream is active; step 6 no longer stages PROJECT.md in that mode (cmdCommit returns nothing_to_commit rather than failing when a staged path is unchanged). Also fixes a second defect found while diagnosing this, same root cause (the workflow was workstream-unaware): step 1 parsed only --reset-phase-numbers and the milestone name, so GSD_WS was never set — yet ${GSD_WS} was interpolated at the routing lines. It always expanded to empty, so `/gsd:new-milestone --ws x` suggested `/gsd:discuss-phase [N]` with the workstream scope silently dropped, violating the routing-propagation contract. Step 1 now parses --ws using the established idiom from verify-work.md. Guard is keyed on GSD_WS, not $GSD_WORKSTREAM: the runtime launcher does not export the latter and it is only priority 2 of 5 in resolution, so it would miss the --ws flag case that is the actual repro. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SLufH5sDuqA1AiEGu45cuA * test(#2308): regenerate install goldens for the new-milestone workflow change gsd-core/workflows/ ships as an installed artifact, so new-milestone.md's content hash is pinned in all 18 runtime golden fixtures. Only that hash changed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SLufH5sDuqA1AiEGu45cuA * fix(#2308): address review — inert step-6 guard, dropped Evolution repair, tautological tests Independent review found the first pass was partly cosmetic: 1. The step-6 `if [ -n "$GSD_WS" ]` branch was INERT. GSD_WS is assigned in step 1's shell and each step's bash block runs in its own shell — this file already proves it, since step 5 round-trips OUTGOING_MILESTONE through a file for exactly that reason (#2288). The guard read an unset variable, always took the flat branch, and staged PROJECT.md anyway. Rather than re-deriving GSD_WS in step 6, the branch is removed entirely: step 4 Part A's guard is what protects the shared heading, so post-guard the only content PROJECT.md can carry is Part B's idempotent Evolution backfill — which must be staged, not stranded. A regression test now asserts no cross-step GSD_WS branch returns. 2. Skipping ALL of step 4 also dropped the `## Evolution` structural repair — a shared, idempotent backfill that is not workstream state. A pre-Evolution project running only `--ws` would never get the section that transition and complete-milestone expect. Step 4 is now split: Part A (milestone-state write) is workstream-guarded; Part B (Evolution) always runs. 3. The tests were tautological prose-pinning — including one asserting a comment mentions "#2308". The step-6 test asserted the guard's TEXT was present, so it passed on the inert guard it existed to catch. Replaced with executable tests that extract the step-1 and step-6 fences and run them under bash with stubbed gsd_run, asserting real parse and --files behavior. 4. --ws is now stripped from the milestone name (step 1 previously left "--ws search" in the remaining text), and documented in argument-hint, help/modes/full.md, and docs/COMMANDS.md. 5. Changeset no longer overstates: --ws reaches the prose guard and routing hints only, not the SDK calls (state.milestone-switch/phases.clear/init.new-milestone still take no ${GSD_WS} — out of scope here). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SLufH5sDuqA1AiEGu45cuA * chore(#2308): regenerate SKILL.md, goldens, and size baseline for the argument-hint change skills/gsd-new-milestone/SKILL.md is generated from commands/gsd/new-milestone.md, so documenting --ws in the argument-hint made it stale (caught by lint:ci's gen-plugin-skills --check). Regenerated it plus the install goldens and workflow size baseline, since commands/, skills/, and gsd-core/workflows/ all ship. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SLufH5sDuqA1AiEGu45cuA * docs(#2308): backfill PR number 2338 into changeset Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SLufH5sDuqA1AiEGu45cuA --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
5
.changeset/serene-herons-rally.md
Normal file
5
.changeset/serene-herons-rally.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 2338
|
||||
---
|
||||
**`/gsd:new-milestone --ws <name>` no longer overwrites the shared PROJECT.md milestone heading** — in workstream mode the shared `.planning/PROJECT.md` had its `## Current Milestone` heading rewritten with one workstream's milestone, so with parallel workstreams whichever ran last silently won the shared heading. The milestone-state write in Step 4 is now skipped when a workstream is active, and the commit no longer stages PROJECT.md. The `--ws` flag is also now parsed into `${GSD_WS}`, which previously expanded to empty and silently dropped workstream scope from the suggested next-step routing hints.
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gsd:new-milestone
|
||||
description: Start a new milestone cycle — update PROJECT.md and route to requirements
|
||||
argument-hint: "[milestone name, e.g., 'v1.1 Notifications']"
|
||||
argument-hint: "[milestone name, e.g., 'v1.1 Notifications'] [--ws <name>]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
|
||||
@@ -483,6 +483,7 @@ Start next version cycle.
|
||||
|----------|----------|-------------|
|
||||
| `name` | No | Milestone name |
|
||||
| `--reset-phase-numbers` | No | Restart the new milestone at Phase 1 and archive old phase dirs before roadmapping |
|
||||
| `--ws <name>` | No | Scope the milestone to a workstream; skips the shared `PROJECT.md` write |
|
||||
|
||||
**Prerequisites:** Previous milestone completed
|
||||
**Produces:** Updated `PROJECT.md`, new `REQUIREMENTS.md`, new `ROADMAP.md`
|
||||
@@ -491,6 +492,7 @@ Start next version cycle.
|
||||
/gsd-new-milestone # Interactive
|
||||
/gsd-new-milestone "v2.0 Mobile" # Named milestone
|
||||
/gsd-new-milestone --reset-phase-numbers "v2.0 Mobile" # Restart milestone numbering at 1
|
||||
/gsd-new-milestone --ws search "v2.0 Search" # Scope to a workstream
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -250,11 +250,13 @@ Start a new milestone through unified flow.
|
||||
- Requirements definition with scoping
|
||||
- Roadmap creation with phase breakdown
|
||||
- Optional `--reset-phase-numbers` flag restarts numbering at Phase 1 and archives old phase dirs first for safety
|
||||
- Optional `--ws <name>` flag scopes the milestone to a workstream and skips the shared `PROJECT.md` write
|
||||
|
||||
Mirrors `/gsd:new-project` flow for brownfield projects (existing PROJECT.md).
|
||||
|
||||
Usage: `/gsd:new-milestone "v2.0 Features"`
|
||||
Usage: `/gsd:new-milestone --reset-phase-numbers "v2.0 Features"`
|
||||
Usage: `/gsd:new-milestone --ws search "v2.0 Search"`
|
||||
|
||||
**`/gsd:complete-milestone <version>`**
|
||||
Archive completed milestone and prepare for next version.
|
||||
|
||||
@@ -22,10 +22,20 @@ Valid GSD subagent types (use exact names — do not fall back to 'general-purpo
|
||||
## 1. Load Context
|
||||
|
||||
Parse `$ARGUMENTS` before doing anything else:
|
||||
- `--reset-phase-numbers` flag → opt into restarting roadmap phase numbering at `1`
|
||||
- remaining text → use as milestone name if present
|
||||
|
||||
If the flag is absent, keep the current behavior of continuing phase numbering from the previous milestone.
|
||||
- `--reset-phase-numbers` flag → opt into restarting roadmap phase numbering at `1`. If absent, keep the current behavior of continuing phase numbering from the previous milestone.
|
||||
- `--ws <name>` flag → active workstream scope, parsed into `GSD_WS`
|
||||
- remaining text, with `--ws <name>` stripped → use as milestone name if present, captured into `MILESTONE_ARG`
|
||||
|
||||
Parse `GSD_WS` and `MILESTONE_ARG` using the established idiom (see `verify-work.md`):
|
||||
|
||||
```bash
|
||||
GSD_WS=""
|
||||
echo "$ARGUMENTS" | grep -qE -- '--ws[[:space:]]+[^[:space:]]+' && GSD_WS=$(echo "$ARGUMENTS" | grep -oE -- '--ws[[:space:]]+[^[:space:]]+')
|
||||
MILESTONE_ARG=$(echo "$ARGUMENTS" | sed -E 's/--ws[[:space:]]+[^[:space:]]+//g' | xargs)
|
||||
```
|
||||
|
||||
`GSD_WS` must chain to every downstream routing suggestion in this workflow (Step 4's shared-file guard, and the `/gsd:discuss-phase`/`/gsd:plan-phase` routing hints below) per the routing-propagation contract in `references/workstream-flag.md` — never let it silently drop.
|
||||
|
||||
- Read PROJECT.md (existing project, validated requirements, decisions)
|
||||
- Read MILESTONES.md (what shipped previously)
|
||||
@@ -135,6 +145,10 @@ AskUserQuestion:
|
||||
|
||||
## 4. Update PROJECT.md
|
||||
|
||||
PROJECT.md is shared across workstreams (`references/workstream-flag.md` marks it `# Shared` in the directory diagram). This step has two independently-scoped parts — only Part A is workstream-guarded.
|
||||
|
||||
**Part A — milestone-state write (skip when a workstream is active).** Skip Part A if `GSD_WS` is non-empty (parsed in Step 1). The active workstream's own `.planning/workstreams/<name>/STATE.md`/`ROADMAP.md`/`REQUIREMENTS.md` already carry this milestone's state. Writing a `## Current Milestone` heading here would clobber the shared file, and with parallel milestones across workstreams, whichever workstream runs `new-milestone` last would silently win the shared heading (#2308). In flat mode (`GSD_WS` empty), run Part A exactly as before:
|
||||
|
||||
Add/update:
|
||||
|
||||
```markdown
|
||||
@@ -150,7 +164,7 @@ Add/update:
|
||||
|
||||
Update Active requirements section and "Last updated" footer.
|
||||
|
||||
Ensure the `## Evolution` section exists in PROJECT.md. If missing (projects created before this feature), add it before the footer:
|
||||
**Part B — Evolution structural repair (always runs, regardless of `GSD_WS`).** `## Evolution` is a shared, idempotent structural section, not workstream state — a pre-Evolution project must be backfilled whether or not a workstream is active, so this part is NOT covered by Part A's skip. Ensure the `## Evolution` section exists in PROJECT.md. If missing (projects created before this feature), add it before the footer:
|
||||
|
||||
```markdown
|
||||
## Evolution
|
||||
@@ -247,6 +261,8 @@ Stage the phase archive move + source removal so they land in the same commit as
|
||||
git add .planning/milestones/ .planning/phases/ 2>/dev/null || true
|
||||
```
|
||||
|
||||
Stage PROJECT.md in both modes. Step 4's Part A guard — not this commit — is what protects the shared `## Current Milestone` heading (#2308): when a workstream is active Part A never writes it, so the only change PROJECT.md can carry here is Part B's idempotent `## Evolution` backfill, which must be committed rather than stranded as a dangling edit. Do NOT reintroduce a `[ -n "$GSD_WS" ]` branch around this commit: `GSD_WS` is set in Step 1's shell and each step's bash block runs in its own shell (the same reason Step 5 round-trips `OUTGOING_MILESTONE` through a file), so such a guard reads an unset variable, always takes the flat-mode branch, and only appears to work.
|
||||
|
||||
```bash
|
||||
gsd_run query commit "docs: start milestone v[X.Y] [Name]" --files .planning/PROJECT.md .planning/STATE.md
|
||||
```
|
||||
@@ -659,7 +675,7 @@ Also: `/gsd:plan-phase [N] ${GSD_WS}` — skip discussion, plan directly
|
||||
</process>
|
||||
|
||||
<success_criteria>
|
||||
- [ ] PROJECT.md updated with Current Milestone section
|
||||
- [ ] PROJECT.md updated with Current Milestone section (skipped when a workstream is active — shared file, see Step 4)
|
||||
- [ ] STATE.md reset for new milestone
|
||||
- [ ] MILESTONE-CONTEXT.md consumed and deleted (if existed)
|
||||
- [ ] Research completed (if selected) — 4 parallel agents, milestone-aware
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gsd-new-milestone
|
||||
description: "Start a new milestone cycle — update PROJECT.md and route to requirements"
|
||||
argument-hint: "[milestone name, e.g., 'v1.1 Notifications']"
|
||||
argument-hint: "[milestone name, e.g., 'v1.1 Notifications'] [--ws <name>]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0",
|
||||
"gsd-core/workflows/help/modes/full.md": "bf7b148215259e6e",
|
||||
"gsd-core/workflows/help/modes/full.md": "80d03a09b561766b",
|
||||
"gsd-core/workflows/help/modes/topic.md": "0bf9ab39d7044d69",
|
||||
"gsd-core/workflows/import.md": "41c62ae199209a68",
|
||||
"gsd-core/workflows/inbox.md": "a448220c548f27bc",
|
||||
@@ -263,7 +263,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "c81444eb0b2e038b",
|
||||
"gsd-core/workflows/milestone-summary.md": "c4620853fe489126",
|
||||
"gsd-core/workflows/mvp-phase.md": "5f0e355ff4583d67",
|
||||
"gsd-core/workflows/new-milestone.md": "949e6046ebdfe0e0",
|
||||
"gsd-core/workflows/new-milestone.md": "7505d35307065c10",
|
||||
"gsd-core/workflows/new-project.md": "f336b2da5c3963f0",
|
||||
"gsd-core/workflows/new-workspace.md": "21bfae58b9cc2990",
|
||||
"gsd-core/workflows/next.md": "8beefb4335dd7c41",
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"commands/gsd-mempalace-recall.md": "38716c0983a3ef9c",
|
||||
"commands/gsd-milestone-summary.md": "ff5e11e6b33d4b5e",
|
||||
"commands/gsd-mvp-phase.md": "ffc5905aed8f450a",
|
||||
"commands/gsd-new-milestone.md": "e9ddaec1dd29d023",
|
||||
"commands/gsd-new-milestone.md": "82d075372a862d9a",
|
||||
"commands/gsd-new-project.md": "56552a324cff669e",
|
||||
"commands/gsd-next.md": "d9f43d56e1bca2ca",
|
||||
"commands/gsd-ns-context.md": "011c44e7aa46e64a",
|
||||
@@ -321,7 +321,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0",
|
||||
"gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50",
|
||||
"gsd-core/workflows/help/modes/full.md": "b26853b9911ad97b",
|
||||
"gsd-core/workflows/help/modes/full.md": "110608f0352bb0a3",
|
||||
"gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d",
|
||||
"gsd-core/workflows/import.md": "3d3fa603ceb8bc9f",
|
||||
"gsd-core/workflows/inbox.md": "437f981ef9ae7b26",
|
||||
@@ -334,7 +334,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "83d750aade709983",
|
||||
"gsd-core/workflows/milestone-summary.md": "e0cdfddbd39a9043",
|
||||
"gsd-core/workflows/mvp-phase.md": "344dd300e0cc1e74",
|
||||
"gsd-core/workflows/new-milestone.md": "bc020226377af22a",
|
||||
"gsd-core/workflows/new-milestone.md": "83bf5593e94c3377",
|
||||
"gsd-core/workflows/new-project.md": "5ffeef49fe73013e",
|
||||
"gsd-core/workflows/new-workspace.md": "017688423110ed66",
|
||||
"gsd-core/workflows/next.md": "13fb800f2472d970",
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
"commands/gsd-mempalace-recall.md": "38716c0983a3ef9c",
|
||||
"commands/gsd-milestone-summary.md": "908509042caf5beb",
|
||||
"commands/gsd-mvp-phase.md": "1ef0d7c2871be49a",
|
||||
"commands/gsd-new-milestone.md": "8ce4861325cd3862",
|
||||
"commands/gsd-new-milestone.md": "0ec387159e1f7182",
|
||||
"commands/gsd-new-project.md": "d68b36481d09bfd4",
|
||||
"commands/gsd-next.md": "e976ddf80b6cb425",
|
||||
"commands/gsd-ns-context.md": "011c44e7aa46e64a",
|
||||
@@ -320,7 +320,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0",
|
||||
"gsd-core/workflows/help/modes/full.md": "8381c11db152a8a6",
|
||||
"gsd-core/workflows/help/modes/full.md": "2388596fd5bcbd07",
|
||||
"gsd-core/workflows/help/modes/topic.md": "6e42db16f1568be9",
|
||||
"gsd-core/workflows/import.md": "cc21f3da36403ed3",
|
||||
"gsd-core/workflows/inbox.md": "91aac6360e1a8672",
|
||||
@@ -333,7 +333,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "b11ca99a885e93ef",
|
||||
"gsd-core/workflows/milestone-summary.md": "99636900c216c8d2",
|
||||
"gsd-core/workflows/mvp-phase.md": "254baac57e85dca7",
|
||||
"gsd-core/workflows/new-milestone.md": "841285575c6e795f",
|
||||
"gsd-core/workflows/new-milestone.md": "33f43349346e86df",
|
||||
"gsd-core/workflows/new-project.md": "26907d3cf3630ed0",
|
||||
"gsd-core/workflows/new-workspace.md": "26615bf710f0a324",
|
||||
"gsd-core/workflows/next.md": "1193222c5618d3db",
|
||||
|
||||
@@ -249,7 +249,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0",
|
||||
"gsd-core/workflows/help/modes/full.md": "91c6683e5b5ff4f8",
|
||||
"gsd-core/workflows/help/modes/full.md": "3d55c7266241f79d",
|
||||
"gsd-core/workflows/help/modes/topic.md": "6e42db16f1568be9",
|
||||
"gsd-core/workflows/import.md": "6e8acff8c3918795",
|
||||
"gsd-core/workflows/inbox.md": "91aac6360e1a8672",
|
||||
@@ -262,7 +262,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "a45a9aa5c10aeeed",
|
||||
"gsd-core/workflows/milestone-summary.md": "ad8e69fcb3463ce4",
|
||||
"gsd-core/workflows/mvp-phase.md": "344dd300e0cc1e74",
|
||||
"gsd-core/workflows/new-milestone.md": "7ec178aa9f921569",
|
||||
"gsd-core/workflows/new-milestone.md": "fef60fedb5db9eb7",
|
||||
"gsd-core/workflows/new-project.md": "0ea70b800c86fde1",
|
||||
"gsd-core/workflows/new-workspace.md": "04356c9b675da7c9",
|
||||
"gsd-core/workflows/next.md": "ef30b829a6d5c5f6",
|
||||
@@ -384,7 +384,7 @@
|
||||
"skills/gsd-mempalace-recall/SKILL.md": "c3f412d5a64f3921",
|
||||
"skills/gsd-milestone-summary/SKILL.md": "33d51a325d314f3a",
|
||||
"skills/gsd-mvp-phase/SKILL.md": "f9a1348c6c297579",
|
||||
"skills/gsd-new-milestone/SKILL.md": "ac99ffb8a966fe9d",
|
||||
"skills/gsd-new-milestone/SKILL.md": "24c97f2814d30501",
|
||||
"skills/gsd-new-project/SKILL.md": "e4d930027074d3b6",
|
||||
"skills/gsd-next/SKILL.md": "13e394affe675498",
|
||||
"skills/gsd-ns-context/SKILL.md": "3102e7ad9b60f182",
|
||||
|
||||
@@ -253,7 +253,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0",
|
||||
"gsd-core/workflows/help/modes/default.md": "86f7a14ad06e2f6f",
|
||||
"gsd-core/workflows/help/modes/full.md": "a53e85333cf61c36",
|
||||
"gsd-core/workflows/help/modes/full.md": "e4f1ae9d0902dda0",
|
||||
"gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d",
|
||||
"gsd-core/workflows/import.md": "96ec687c5cfe84ac",
|
||||
"gsd-core/workflows/inbox.md": "437f981ef9ae7b26",
|
||||
@@ -266,7 +266,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "14c4995c73a671c7",
|
||||
"gsd-core/workflows/milestone-summary.md": "20e56b9e3902e1d2",
|
||||
"gsd-core/workflows/mvp-phase.md": "3e3936e1f247ac7c",
|
||||
"gsd-core/workflows/new-milestone.md": "a85761d8c9f760be",
|
||||
"gsd-core/workflows/new-milestone.md": "38370e363174b1da",
|
||||
"gsd-core/workflows/new-project.md": "66bf6135f54ece0e",
|
||||
"gsd-core/workflows/new-workspace.md": "f5eed5dd9a21878f",
|
||||
"gsd-core/workflows/next.md": "3f8b61a35587a021",
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"commands/gsd-mempalace-recall.md": "6efef238d8c62569",
|
||||
"commands/gsd-milestone-summary.md": "e3a36fbd695a1833",
|
||||
"commands/gsd-mvp-phase.md": "671791ba61c4654a",
|
||||
"commands/gsd-new-milestone.md": "00b5d757991941c7",
|
||||
"commands/gsd-new-milestone.md": "288fa7dfcec18094",
|
||||
"commands/gsd-new-project.md": "490195d5003d3d17",
|
||||
"commands/gsd-next.md": "dbec71acc9d5d2a2",
|
||||
"commands/gsd-ns-context.md": "cc8954f405ae7916",
|
||||
@@ -321,7 +321,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0",
|
||||
"gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50",
|
||||
"gsd-core/workflows/help/modes/full.md": "67e3dffe34ddc9bc",
|
||||
"gsd-core/workflows/help/modes/full.md": "5eefc87999cde1a6",
|
||||
"gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d",
|
||||
"gsd-core/workflows/import.md": "3d3fa603ceb8bc9f",
|
||||
"gsd-core/workflows/inbox.md": "437f981ef9ae7b26",
|
||||
@@ -334,7 +334,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "83d750aade709983",
|
||||
"gsd-core/workflows/milestone-summary.md": "e0cdfddbd39a9043",
|
||||
"gsd-core/workflows/mvp-phase.md": "344dd300e0cc1e74",
|
||||
"gsd-core/workflows/new-milestone.md": "bc020226377af22a",
|
||||
"gsd-core/workflows/new-milestone.md": "83bf5593e94c3377",
|
||||
"gsd-core/workflows/new-project.md": "278e0b88dd1d2ea0",
|
||||
"gsd-core/workflows/new-workspace.md": "017688423110ed66",
|
||||
"gsd-core/workflows/next.md": "13fb800f2472d970",
|
||||
|
||||
@@ -356,7 +356,7 @@
|
||||
"gsd-core/workflows/help.md": "08e1349950c5602a",
|
||||
"gsd-core/workflows/help/modes/brief.md": "da44b130d1afe556",
|
||||
"gsd-core/workflows/help/modes/default.md": "4bb3082d28026eea",
|
||||
"gsd-core/workflows/help/modes/full.md": "773717d0699320b8",
|
||||
"gsd-core/workflows/help/modes/full.md": "9a512db0dce1a315",
|
||||
"gsd-core/workflows/help/modes/topic.md": "b7c7e4a8800bc3ea",
|
||||
"gsd-core/workflows/import.md": "cb3c8f9d09edb434",
|
||||
"gsd-core/workflows/inbox.md": "61b8b10e7a74b2e9",
|
||||
@@ -369,7 +369,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "2edab7d924b296ff",
|
||||
"gsd-core/workflows/milestone-summary.md": "a53b30a84f904b50",
|
||||
"gsd-core/workflows/mvp-phase.md": "100dded5c7b4cb86",
|
||||
"gsd-core/workflows/new-milestone.md": "f30f968a4f0912ed",
|
||||
"gsd-core/workflows/new-milestone.md": "f8fac345bb136e04",
|
||||
"gsd-core/workflows/new-project.md": "a9dbf207833897cc",
|
||||
"gsd-core/workflows/new-workspace.md": "3630b78e83b1e491",
|
||||
"gsd-core/workflows/next.md": "7097a9607a981086",
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0",
|
||||
"gsd-core/workflows/help/modes/full.md": "bd1bca7960fadd61",
|
||||
"gsd-core/workflows/help/modes/full.md": "fb46abb57e525863",
|
||||
"gsd-core/workflows/help/modes/topic.md": "0bf9ab39d7044d69",
|
||||
"gsd-core/workflows/import.md": "f4fa65e332b00f7e",
|
||||
"gsd-core/workflows/inbox.md": "a448220c548f27bc",
|
||||
@@ -264,7 +264,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "b426a450e5d90cc3",
|
||||
"gsd-core/workflows/milestone-summary.md": "8a53906253984a62",
|
||||
"gsd-core/workflows/mvp-phase.md": "93304b26c92e4418",
|
||||
"gsd-core/workflows/new-milestone.md": "9909214a1782b31f",
|
||||
"gsd-core/workflows/new-milestone.md": "a7d8835c192e9b7d",
|
||||
"gsd-core/workflows/new-project.md": "5c34f0cb064568bd",
|
||||
"gsd-core/workflows/new-workspace.md": "403796bdf6318515",
|
||||
"gsd-core/workflows/next.md": "81c08abb34b2da88",
|
||||
@@ -359,7 +359,7 @@
|
||||
"skills/gsd-mempalace-recall/SKILL.md": "89523db66f834b2f",
|
||||
"skills/gsd-milestone-summary/SKILL.md": "5ca1dabfe0cd85f0",
|
||||
"skills/gsd-mvp-phase/SKILL.md": "60ac3c3fa6a6a19b",
|
||||
"skills/gsd-new-milestone/SKILL.md": "e5eafe44e271bb92",
|
||||
"skills/gsd-new-milestone/SKILL.md": "65670b65fb89d928",
|
||||
"skills/gsd-new-project/SKILL.md": "4ce68352221126c6",
|
||||
"skills/gsd-next/SKILL.md": "16507fc39a3a0684",
|
||||
"skills/gsd-ns-context/SKILL.md": "d61edde87ae53105",
|
||||
|
||||
@@ -321,7 +321,7 @@
|
||||
"gsd-core/workflows/help.md": "08e1349950c5602a",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "b88ff431fffe40ae",
|
||||
"gsd-core/workflows/help/modes/full.md": "d30803f316abd6fa",
|
||||
"gsd-core/workflows/help/modes/full.md": "9ae8b1e8908c7ead",
|
||||
"gsd-core/workflows/help/modes/topic.md": "cee80e0adfa3b06c",
|
||||
"gsd-core/workflows/import.md": "5d5fb8e51f6a243a",
|
||||
"gsd-core/workflows/inbox.md": "797c287852eb8957",
|
||||
@@ -334,7 +334,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "3118100462eee628",
|
||||
"gsd-core/workflows/milestone-summary.md": "6c76386b500cc5d3",
|
||||
"gsd-core/workflows/mvp-phase.md": "50b189c5f4503369",
|
||||
"gsd-core/workflows/new-milestone.md": "efba76f3dd38d87c",
|
||||
"gsd-core/workflows/new-milestone.md": "68143de8032d8a41",
|
||||
"gsd-core/workflows/new-project.md": "a2b559fba00904eb",
|
||||
"gsd-core/workflows/new-workspace.md": "9e76e96253d54a57",
|
||||
"gsd-core/workflows/next.md": "174356dcfd7c6c32",
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "8874dac94eb68ae6",
|
||||
"gsd-core/workflows/help/modes/full.md": "cad4eed3907e8a58",
|
||||
"gsd-core/workflows/help/modes/full.md": "a9351cf72f580a87",
|
||||
"gsd-core/workflows/help/modes/topic.md": "6e42db16f1568be9",
|
||||
"gsd-core/workflows/import.md": "c6a19584809ea635",
|
||||
"gsd-core/workflows/inbox.md": "91aac6360e1a8672",
|
||||
@@ -263,7 +263,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "420caa00abbd73f5",
|
||||
"gsd-core/workflows/milestone-summary.md": "353fffb60749d892",
|
||||
"gsd-core/workflows/mvp-phase.md": "4d102523b5d81f95",
|
||||
"gsd-core/workflows/new-milestone.md": "75944be19e6eda0a",
|
||||
"gsd-core/workflows/new-milestone.md": "dec95592513880e1",
|
||||
"gsd-core/workflows/new-project.md": "291d623166b97754",
|
||||
"gsd-core/workflows/new-workspace.md": "5c78c58ad84e886b",
|
||||
"gsd-core/workflows/next.md": "8e1fa29751d96564",
|
||||
@@ -392,7 +392,7 @@
|
||||
"skills/gsd/gsd-ns-project/skills/import/SKILL.md": "bf781c7a0d83c2cd",
|
||||
"skills/gsd/gsd-ns-project/skills/ingest-docs/SKILL.md": "a38273c6b6604830",
|
||||
"skills/gsd/gsd-ns-project/skills/milestone-summary/SKILL.md": "c4bda5737f1137f8",
|
||||
"skills/gsd/gsd-ns-project/skills/new-milestone/SKILL.md": "47586c1fc8aa0645",
|
||||
"skills/gsd/gsd-ns-project/skills/new-milestone/SKILL.md": "384b6754a950e6eb",
|
||||
"skills/gsd/gsd-ns-project/skills/new-project/SKILL.md": "8f22ba75717b3c88",
|
||||
"skills/gsd/gsd-ns-project/skills/onboard/SKILL.md": "1d8d06ac1f27dacd",
|
||||
"skills/gsd/gsd-ns-project/skills/profile-user/SKILL.md": "5a8e01bc7b873a20",
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"command/gsd-mempalace-recall.md": "d358cdd89c935877",
|
||||
"command/gsd-milestone-summary.md": "4ab29b777f62f0bb",
|
||||
"command/gsd-mvp-phase.md": "273a1c26ca13274b",
|
||||
"command/gsd-new-milestone.md": "a315b3205c5d3470",
|
||||
"command/gsd-new-milestone.md": "dbf06cebb4c10039",
|
||||
"command/gsd-new-project.md": "f2763e2ccbb70ebe",
|
||||
"command/gsd-next.md": "dfdcfb2fd79957fa",
|
||||
"command/gsd-ns-context.md": "9a2b55b64f2e1e4b",
|
||||
@@ -321,7 +321,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0",
|
||||
"gsd-core/workflows/help/modes/full.md": "c41d1012b4577fe4",
|
||||
"gsd-core/workflows/help/modes/full.md": "08101a965254f10e",
|
||||
"gsd-core/workflows/help/modes/topic.md": "0bf9ab39d7044d69",
|
||||
"gsd-core/workflows/import.md": "f8bbe6f2c0e08a78",
|
||||
"gsd-core/workflows/inbox.md": "a073396097c89c01",
|
||||
@@ -334,7 +334,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "c3d6418d64ba2994",
|
||||
"gsd-core/workflows/milestone-summary.md": "25775eeb4e2747be",
|
||||
"gsd-core/workflows/mvp-phase.md": "a97708464f103300",
|
||||
"gsd-core/workflows/new-milestone.md": "9da5203fabe324c4",
|
||||
"gsd-core/workflows/new-milestone.md": "f3f76acd32311959",
|
||||
"gsd-core/workflows/new-project.md": "6d8cd0b4fe813374",
|
||||
"gsd-core/workflows/new-workspace.md": "f58d6a8c0c7796a1",
|
||||
"gsd-core/workflows/next.md": "888297a0b21888ea",
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0",
|
||||
"gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50",
|
||||
"gsd-core/workflows/help/modes/full.md": "9706b4bee6829f82",
|
||||
"gsd-core/workflows/help/modes/full.md": "91e115f058b6d3cf",
|
||||
"gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d",
|
||||
"gsd-core/workflows/import.md": "3d3fa603ceb8bc9f",
|
||||
"gsd-core/workflows/inbox.md": "437f981ef9ae7b26",
|
||||
@@ -327,7 +327,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "83d750aade709983",
|
||||
"gsd-core/workflows/milestone-summary.md": "e0cdfddbd39a9043",
|
||||
"gsd-core/workflows/mvp-phase.md": "344dd300e0cc1e74",
|
||||
"gsd-core/workflows/new-milestone.md": "bc020226377af22a",
|
||||
"gsd-core/workflows/new-milestone.md": "83bf5593e94c3377",
|
||||
"gsd-core/workflows/new-project.md": "1ec88027a8e5a2fe",
|
||||
"gsd-core/workflows/new-workspace.md": "017688423110ed66",
|
||||
"gsd-core/workflows/next.md": "13fb800f2472d970",
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"command/gsd-mempalace-recall.md": "d358cdd89c935877",
|
||||
"command/gsd-milestone-summary.md": "86a827271bc647c5",
|
||||
"command/gsd-mvp-phase.md": "d45fd76cb9cff3ef",
|
||||
"command/gsd-new-milestone.md": "64c9dc73425a66a2",
|
||||
"command/gsd-new-milestone.md": "613902b46d2ba6ef",
|
||||
"command/gsd-new-project.md": "0086f0de26002219",
|
||||
"command/gsd-next.md": "b0ef81652d72d894",
|
||||
"command/gsd-ns-context.md": "9a2b55b64f2e1e4b",
|
||||
@@ -321,7 +321,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "be05e56b2c5ee2c0",
|
||||
"gsd-core/workflows/help/modes/full.md": "de70e34ebd257ce9",
|
||||
"gsd-core/workflows/help/modes/full.md": "7e68200aeb086535",
|
||||
"gsd-core/workflows/help/modes/topic.md": "0bf9ab39d7044d69",
|
||||
"gsd-core/workflows/import.md": "67fbf389ab8e57b4",
|
||||
"gsd-core/workflows/inbox.md": "a073396097c89c01",
|
||||
@@ -334,7 +334,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "6aa5a52741af0b3e",
|
||||
"gsd-core/workflows/milestone-summary.md": "321ea8a6a206f38f",
|
||||
"gsd-core/workflows/mvp-phase.md": "b4d688baa4c60dfc",
|
||||
"gsd-core/workflows/new-milestone.md": "66d00a85528a2170",
|
||||
"gsd-core/workflows/new-milestone.md": "72010b09ae067366",
|
||||
"gsd-core/workflows/new-project.md": "a3850644ef65bea6",
|
||||
"gsd-core/workflows/new-workspace.md": "3d82392388ee24c7",
|
||||
"gsd-core/workflows/next.md": "6719a37b8ce2ac4f",
|
||||
|
||||
4
tests/fixtures/golden-install-parity/pi.json
vendored
4
tests/fixtures/golden-install-parity/pi.json
vendored
@@ -217,7 +217,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0",
|
||||
"gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50",
|
||||
"gsd-core/workflows/help/modes/full.md": "584e50ea86a86b6f",
|
||||
"gsd-core/workflows/help/modes/full.md": "99d5387021de656f",
|
||||
"gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d",
|
||||
"gsd-core/workflows/import.md": "3d3fa603ceb8bc9f",
|
||||
"gsd-core/workflows/inbox.md": "437f981ef9ae7b26",
|
||||
@@ -230,7 +230,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "83d750aade709983",
|
||||
"gsd-core/workflows/milestone-summary.md": "e0cdfddbd39a9043",
|
||||
"gsd-core/workflows/mvp-phase.md": "344dd300e0cc1e74",
|
||||
"gsd-core/workflows/new-milestone.md": "bc020226377af22a",
|
||||
"gsd-core/workflows/new-milestone.md": "83bf5593e94c3377",
|
||||
"gsd-core/workflows/new-project.md": "4c32c69910d55ec0",
|
||||
"gsd-core/workflows/new-workspace.md": "017688423110ed66",
|
||||
"gsd-core/workflows/next.md": "13fb800f2472d970",
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "7ca77077085452f5",
|
||||
"gsd-core/workflows/help/modes/full.md": "9d620deed3bf9011",
|
||||
"gsd-core/workflows/help/modes/full.md": "6022991e0f56fd1d",
|
||||
"gsd-core/workflows/help/modes/topic.md": "6e42db16f1568be9",
|
||||
"gsd-core/workflows/import.md": "e56c18a984396066",
|
||||
"gsd-core/workflows/inbox.md": "91aac6360e1a8672",
|
||||
@@ -263,7 +263,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "2328da6a2f180f07",
|
||||
"gsd-core/workflows/milestone-summary.md": "97ddfc40c6bce906",
|
||||
"gsd-core/workflows/mvp-phase.md": "5ca64695120d250c",
|
||||
"gsd-core/workflows/new-milestone.md": "a65c567f1f38cc73",
|
||||
"gsd-core/workflows/new-milestone.md": "6bee4870688f0170",
|
||||
"gsd-core/workflows/new-project.md": "493ae04534a80f97",
|
||||
"gsd-core/workflows/new-workspace.md": "0d59bb987430003e",
|
||||
"gsd-core/workflows/next.md": "c13515a80c20d37d",
|
||||
@@ -391,7 +391,7 @@
|
||||
"skills/gsd-ns-project/skills/import/SKILL.md": "88f83921a85e536b",
|
||||
"skills/gsd-ns-project/skills/ingest-docs/SKILL.md": "eb85e654917a503a",
|
||||
"skills/gsd-ns-project/skills/milestone-summary/SKILL.md": "33d51a325d314f3a",
|
||||
"skills/gsd-ns-project/skills/new-milestone/SKILL.md": "ac99ffb8a966fe9d",
|
||||
"skills/gsd-ns-project/skills/new-milestone/SKILL.md": "24c97f2814d30501",
|
||||
"skills/gsd-ns-project/skills/new-project/SKILL.md": "9d5c27ebfa2c4746",
|
||||
"skills/gsd-ns-project/skills/onboard/SKILL.md": "46460b479b7524bf",
|
||||
"skills/gsd-ns-project/skills/profile-user/SKILL.md": "78ca46045e85223f",
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
"gsd-core/workflows/help.md": "08e1349950c5602a",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "ed7368e0d1b8644a",
|
||||
"gsd-core/workflows/help/modes/full.md": "249beacac5798123",
|
||||
"gsd-core/workflows/help/modes/full.md": "01a34fdde96bf138",
|
||||
"gsd-core/workflows/help/modes/topic.md": "8a5344e56fa64ab9",
|
||||
"gsd-core/workflows/import.md": "31af58468db15daf",
|
||||
"gsd-core/workflows/inbox.md": "e9ea37b2d46dc5b4",
|
||||
@@ -263,7 +263,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "713561638fb1b88e",
|
||||
"gsd-core/workflows/milestone-summary.md": "a0063cfbe08f2250",
|
||||
"gsd-core/workflows/mvp-phase.md": "8ed9f4552350ede8",
|
||||
"gsd-core/workflows/new-milestone.md": "fd0f56ebd91dc2db",
|
||||
"gsd-core/workflows/new-milestone.md": "9a3a99448397cee4",
|
||||
"gsd-core/workflows/new-project.md": "32ce66cbeaa26cc5",
|
||||
"gsd-core/workflows/new-workspace.md": "6b6fbad18d30f783",
|
||||
"gsd-core/workflows/next.md": "2163195861877de5",
|
||||
|
||||
@@ -250,7 +250,7 @@
|
||||
"gsd-core/workflows/help.md": "08e1349950c5602a",
|
||||
"gsd-core/workflows/help/modes/brief.md": "fa2675516b40e2e3",
|
||||
"gsd-core/workflows/help/modes/default.md": "6a253f1756f74e95",
|
||||
"gsd-core/workflows/help/modes/full.md": "8f1bf0e563a02255",
|
||||
"gsd-core/workflows/help/modes/full.md": "670392a80cbcbd7d",
|
||||
"gsd-core/workflows/help/modes/topic.md": "cee80e0adfa3b06c",
|
||||
"gsd-core/workflows/import.md": "029cacf530aca86b",
|
||||
"gsd-core/workflows/inbox.md": "797c287852eb8957",
|
||||
@@ -263,7 +263,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "0a2a653ed1603784",
|
||||
"gsd-core/workflows/milestone-summary.md": "1fdbae19ad06a0a3",
|
||||
"gsd-core/workflows/mvp-phase.md": "e3c4cade4fe69408",
|
||||
"gsd-core/workflows/new-milestone.md": "7043ae90a2bc0401",
|
||||
"gsd-core/workflows/new-milestone.md": "f2b8fdcd1a19d378",
|
||||
"gsd-core/workflows/new-project.md": "0ff192c54373ab8a",
|
||||
"gsd-core/workflows/new-workspace.md": "8c2b60fbbf241e03",
|
||||
"gsd-core/workflows/next.md": "d48cea140a5153cb",
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"commands/gsd-mempalace-recall.md": "5ac67fa4b7f2b03b",
|
||||
"commands/gsd-milestone-summary.md": "f8fa9c357c08b74b",
|
||||
"commands/gsd-mvp-phase.md": "cba67bcb55250e5f",
|
||||
"commands/gsd-new-milestone.md": "53cb82c66bbc808c",
|
||||
"commands/gsd-new-milestone.md": "8d52385b21cadd20",
|
||||
"commands/gsd-new-project.md": "952d7601b800ad8d",
|
||||
"commands/gsd-next.md": "7d3a2cb0bd12043a",
|
||||
"commands/gsd-ns-context.md": "011c44e7aa46e64a",
|
||||
@@ -321,7 +321,7 @@
|
||||
"gsd-core/workflows/help.md": "5d040504b9ab35e3",
|
||||
"gsd-core/workflows/help/modes/brief.md": "924860e1f07defb0",
|
||||
"gsd-core/workflows/help/modes/default.md": "08a02976c0c5cc50",
|
||||
"gsd-core/workflows/help/modes/full.md": "1810842c75f73fb2",
|
||||
"gsd-core/workflows/help/modes/full.md": "dda8f6d101b0870d",
|
||||
"gsd-core/workflows/help/modes/topic.md": "5c160093f3cbf35d",
|
||||
"gsd-core/workflows/import.md": "3d3fa603ceb8bc9f",
|
||||
"gsd-core/workflows/inbox.md": "437f981ef9ae7b26",
|
||||
@@ -334,7 +334,7 @@
|
||||
"gsd-core/workflows/map-codebase.md": "83d750aade709983",
|
||||
"gsd-core/workflows/milestone-summary.md": "e0cdfddbd39a9043",
|
||||
"gsd-core/workflows/mvp-phase.md": "344dd300e0cc1e74",
|
||||
"gsd-core/workflows/new-milestone.md": "bc020226377af22a",
|
||||
"gsd-core/workflows/new-milestone.md": "83bf5593e94c3377",
|
||||
"gsd-core/workflows/new-project.md": "fdb53bee6b4178ad",
|
||||
"gsd-core/workflows/new-workspace.md": "017688423110ed66",
|
||||
"gsd-core/workflows/next.md": "13fb800f2472d970",
|
||||
@@ -434,7 +434,7 @@
|
||||
"skills/gsd-ns-project/skills/import/SKILL.md": "0a734021e0b86481",
|
||||
"skills/gsd-ns-project/skills/ingest-docs/SKILL.md": "0fadb4f9c69aa61d",
|
||||
"skills/gsd-ns-project/skills/milestone-summary/SKILL.md": "c77f6c8ce7c57db9",
|
||||
"skills/gsd-ns-project/skills/new-milestone/SKILL.md": "3aad804c48d77474",
|
||||
"skills/gsd-ns-project/skills/new-milestone/SKILL.md": "c7c20da62ac3f6e1",
|
||||
"skills/gsd-ns-project/skills/new-project/SKILL.md": "e3cfd1fdbc2c3406",
|
||||
"skills/gsd-ns-project/skills/onboard/SKILL.md": "84519552f7396347",
|
||||
"skills/gsd-ns-project/skills/profile-user/SKILL.md": "f57ad5e5c5899100",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
const { test, describe, beforeEach, afterEach } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const { execSync } = require('child_process');
|
||||
const { execSync, execFileSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { runGsdTools, createTempProject, createTempGitProject, cleanup } = require('./helpers.cjs');
|
||||
@@ -563,3 +563,162 @@ test('execute-phase.md: awk extracts resolves_phase from YAML frontmatter', () =
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ────────────────────────────────────────────────────────────────────────
|
||||
// #2308 / #2334 follow-up: new-milestone.md must not clobber the shared
|
||||
// PROJECT.md when a workstream is active, and must propagate ${GSD_WS} to
|
||||
// downstream routing. Step 1 and Step 6's bash fences are extracted and
|
||||
// EXECUTED (not grepped) so these tests fail on an inert guard — e.g. the
|
||||
// step-6 conditional merely being PRESENT (`if [ -n "$GSD_WS" ]`) is not
|
||||
// enough if GSD_WS was never re-derived and is always empty at runtime.
|
||||
// ────────────────────────────────────────────────────────────────────────
|
||||
describe('new-milestone.md: workstream-aware PROJECT.md guard (#2308)', () => {
|
||||
const workflowPath = path.join(__dirname, '..', 'gsd-core', 'workflows', 'new-milestone.md');
|
||||
const content = fs.readFileSync(workflowPath, 'utf8');
|
||||
|
||||
// Locate the first ```bash fence strictly between two headings.
|
||||
function extractFenceBetween(markdown, startHeading, endHeading) {
|
||||
const startIdx = markdown.indexOf(startHeading);
|
||||
const endIdx = markdown.indexOf(endHeading);
|
||||
assert.ok(startIdx !== -1, `heading not found: ${startHeading}`);
|
||||
assert.ok(endIdx !== -1, `heading not found: ${endHeading}`);
|
||||
assert.ok(startIdx < endIdx, `${startHeading} must precede ${endHeading}`);
|
||||
const section = markdown.slice(startIdx, endIdx);
|
||||
const match = section.match(/```bash\r?\n([\s\S]*?)```/);
|
||||
assert.ok(match, `no bash fence found between "${startHeading}" and "${endHeading}"`);
|
||||
return match[1];
|
||||
}
|
||||
|
||||
// Step 6 has multiple ```bash fences; locate the one containing `marker`.
|
||||
function extractFenceContaining(markdown, startHeading, endHeading, marker) {
|
||||
const startIdx = markdown.indexOf(startHeading);
|
||||
const endIdx = markdown.indexOf(endHeading);
|
||||
assert.ok(startIdx !== -1 && endIdx !== -1 && startIdx < endIdx, 'headings not found in order');
|
||||
const section = markdown.slice(startIdx, endIdx);
|
||||
const fenceRe = /```bash\r?\n([\s\S]*?)```/g;
|
||||
let m;
|
||||
while ((m = fenceRe.exec(section)) !== null) {
|
||||
if (m[1].includes(marker)) return m[1];
|
||||
}
|
||||
assert.fail(`no bash fence containing "${marker}" found between "${startHeading}" and "${endHeading}"`);
|
||||
return null;
|
||||
}
|
||||
|
||||
describe('step 1: --ws parsing is real, executable shell (not prose)', () => {
|
||||
const step1Fence = extractFenceBetween(content, '## 1. Load Context', '## 2. Gather Milestone Goals');
|
||||
|
||||
function runStep1(argumentsValue) {
|
||||
const script = `ARGUMENTS=${JSON.stringify(argumentsValue)}\n${step1Fence}\n` +
|
||||
'printf \'GSD_WS=[%s]\\nMILESTONE_ARG=[%s]\\n\' "$GSD_WS" "$MILESTONE_ARG"';
|
||||
const out = execFileSync('bash', ['-c', script], { encoding: 'utf8' });
|
||||
return {
|
||||
gsdWs: /GSD_WS=\[(.*)\]/.exec(out)[1],
|
||||
milestoneArg: /MILESTONE_ARG=\[(.*)\]/.exec(out)[1],
|
||||
};
|
||||
}
|
||||
|
||||
test('parses --ws <name> into GSD_WS and strips it from the milestone name (finding 6)', () => {
|
||||
const { gsdWs, milestoneArg } = runStep1('--ws search v2.0 Search');
|
||||
assert.strictEqual(gsdWs, '--ws search');
|
||||
assert.strictEqual(milestoneArg, 'v2.0 Search');
|
||||
});
|
||||
|
||||
test('leaves GSD_WS empty when --ws is absent, milestone name unaffected', () => {
|
||||
const { gsdWs, milestoneArg } = runStep1('v2.0 Search');
|
||||
assert.strictEqual(gsdWs, '');
|
||||
assert.strictEqual(milestoneArg, 'v2.0 Search');
|
||||
});
|
||||
});
|
||||
|
||||
describe('step 6: commit stages PROJECT.md in both modes, with no cross-step guard', () => {
|
||||
const step6CommitFence = extractFenceContaining(
|
||||
content,
|
||||
'## 6. Cleanup and Commit',
|
||||
'## 7. Load Context and Resolve Models',
|
||||
'docs: start milestone v[X.Y] [Name]'
|
||||
);
|
||||
|
||||
function runStep6Commit(argumentsValue) {
|
||||
const gsdRunStub = 'gsd_run() { printf "%s\\n" "gsd_run_call:$*"; }\n';
|
||||
const script = `ARGUMENTS=${JSON.stringify(argumentsValue)}\n${gsdRunStub}${step6CommitFence}`;
|
||||
return execFileSync('bash', ['-c', script], { encoding: 'utf8' });
|
||||
}
|
||||
|
||||
// Step 4 Part A's guard — not this commit — is what protects the shared
|
||||
// heading. Part B's Evolution backfill DOES write PROJECT.md in workstream
|
||||
// mode, so a ws-mode branch that dropped PROJECT.md from --files would
|
||||
// strand that edit uncommitted.
|
||||
for (const [mode, args] of [['ws', '--ws search v2.0 Search'], ['flat', 'v2.0 Search']]) {
|
||||
test(`${mode} mode: --files stages PROJECT.md so Part B's Evolution backfill is committed`, () => {
|
||||
const out = runStep6Commit(args);
|
||||
assert.ok(
|
||||
out.includes('--files .planning/PROJECT.md .planning/STATE.md'),
|
||||
`expected PROJECT.md + STATE.md --files in ${mode} mode, got: ${out}`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
test('does not guard the commit on GSD_WS — a cross-step variable is always empty here', () => {
|
||||
// Regression guard for the inert-guard trap: GSD_WS is assigned in Step
|
||||
// 1's shell, and each step's bash block runs in its own shell (the same
|
||||
// reason Step 5 round-trips OUTGOING_MILESTONE through a file). A
|
||||
// `[ -n "$GSD_WS" ]` branch here reads an unset variable, always takes
|
||||
// the flat branch, and only appears to work.
|
||||
assert.ok(
|
||||
!/\[\s*-n\s*"\$GSD_WS"\s*\]/.test(step6CommitFence),
|
||||
`step 6 must not branch on a cross-step GSD_WS; got fence:\n${step6CommitFence}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('routing interpolations still propagate ${GSD_WS} at the documented lines', () => {
|
||||
assert.ok(
|
||||
content.includes('/gsd:new-milestone --reset-phase-numbers ${GSD_WS}'),
|
||||
'reset-phase-numbers rerun hint should propagate ${GSD_WS}'
|
||||
);
|
||||
assert.ok(
|
||||
content.includes('/gsd:discuss-phase [N] ${GSD_WS}'),
|
||||
'discuss-phase routing hint should propagate ${GSD_WS}'
|
||||
);
|
||||
assert.ok(
|
||||
content.includes('/gsd:plan-phase [N] ${GSD_WS}'),
|
||||
'plan-phase routing hint should propagate ${GSD_WS}'
|
||||
);
|
||||
});
|
||||
|
||||
test('success criteria reflects PROJECT.md update is skipped in workstream mode', () => {
|
||||
assert.match(
|
||||
content,
|
||||
/PROJECT\.md updated with Current Milestone section.*skipped.*workstream/i,
|
||||
'success criteria should note the PROJECT.md step is skipped in workstream mode'
|
||||
);
|
||||
});
|
||||
|
||||
test('step 4 scopes the workstream skip to the milestone-state write only; Evolution repair always runs (finding 2)', () => {
|
||||
const step4Idx = content.indexOf('## 4. Update PROJECT.md');
|
||||
const step5Idx = content.indexOf('## 5. Update STATE.md');
|
||||
assert.ok(step4Idx !== -1 && step5Idx !== -1 && step4Idx < step5Idx, 'steps 4 and 5 should be locatable');
|
||||
const step4Body = content.slice(step4Idx, step5Idx);
|
||||
|
||||
const partAIdx = step4Body.indexOf('Part A');
|
||||
const partBIdx = step4Body.indexOf('Part B');
|
||||
assert.ok(partAIdx !== -1 && partBIdx !== -1 && partAIdx < partBIdx, 'step 4 should have distinct Part A / Part B sections');
|
||||
|
||||
const partABody = step4Body.slice(partAIdx, partBIdx);
|
||||
const partBBody = step4Body.slice(partBIdx);
|
||||
|
||||
assert.match(partABody, /skip/i, 'Part A should describe the workstream skip');
|
||||
assert.ok(partABody.includes('GSD_WS'), 'Part A guard should be keyed on GSD_WS');
|
||||
assert.match(
|
||||
step4Body,
|
||||
/shared/i,
|
||||
'step 4 should justify the guard by pointing at PROJECT.md being the shared file'
|
||||
);
|
||||
|
||||
// The Evolution structural repair must be reachable OUTSIDE Part A's skip,
|
||||
// and Part B's own text must state it is unconditional.
|
||||
assert.ok(!partABody.includes('## Evolution'), 'Evolution repair must NOT be nested inside the guarded Part A');
|
||||
assert.ok(partBBody.includes('## Evolution'), 'Part B must contain the Evolution section template');
|
||||
assert.match(partBBody, /always runs/i, 'Part B must state it always runs regardless of GSD_WS');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"map-codebase.md": 20833,
|
||||
"milestone-summary.md": 11842,
|
||||
"mvp-phase.md": 13626,
|
||||
"new-milestone.md": 35045,
|
||||
"new-milestone.md": 37581,
|
||||
"new-project.md": 66182,
|
||||
"new-workspace.md": 11298,
|
||||
"next.md": 20138,
|
||||
|
||||
Reference in New Issue
Block a user