| name | deliver |
| description | Merge feature branches, tag release, cleanup. Triggered by /gse:deliver. |
GSE-One Deliver — Delivery
Arguments: $ARGUMENTS
Options
| Flag / Sub-command | Description |
|---|
| (no args) | Deliver all completed tasks for the current sprint |
--dry-run | Show merge plan without executing |
--skip-tag | Skip version tagging |
--skip-cleanup | Skip branch and worktree cleanup |
--help | Show this command's usage summary |
Prerequisites
Before executing, read:
.gse/status.yaml — current sprint and lifecycle state
.gse/config.yaml — git strategy, tag_on_deliver, post_tag_hook, backup_retention_days
.gse/backlog.yaml — all tasks and their statuses (must all be done, reviewed, or delivered)
Workflow
Step 0.0 — Delivery Map (pedagogical preview)
Before any check or Gate, display once a short map of what /gse:deliver will do, with each step's default behaviour drawn from config.yaml. Goal: the user knows what to expect, sees the defaults, and recognises each subsequent Gate as a documented step rather than an unexpected interruption.
DELIVERY MAP
Step 1 — Pre-flight (review status, conflicts, uncommitted, REQ→TST coverage)
Step 1.5 — Test evidence per TASK + declared test levels (spec §9.3.1)
Step 2 — Merge features into integration branch — default: {merge_strategy_default}
Step 3 — Merge integration into main — default: merge --no-ff
Step 4 — Tag release — default: {tag_on_deliver}
Step 5 — Cleanup feature branches and worktrees — default: {cleanup_on_deliver}
Step 6 — Release notes
Step 7 — Post-tag hook — {post_tag_hook or "none configured"}
Step 8 — Cleanup backup tags older than {backup_retention_days}d
Step 9 — Finalize (snapshot plan, refresh health, regenerate dashboard)
Gates you may see: pre-flight blockers (uncommitted, missing tests),
merge-strategy confirmations, conflict resolution. Each Gate has a
default — pressing the recommended option moves forward.
For beginners (P9), substitute jargon with plain language: "Delivery has 9 steps. I'll combine your work into the main branch, tag a version, and clean up. I'll ask you to confirm choices for merging and tagging — the suggested option is usually the right one."
This map is purely informational — it asks nothing of the user, blocks nothing, and does not duplicate any later Gate. Skip the map only when --dry-run is set (the dry-run output is itself a delivery map). Rationale: in observed sessions, users perceived the 5-7 sequential Gates as chattiness because they had no upfront framing; this single block reframes the same Gates as steps in a known process.
Step 0 — Safety: Backup Tags
Before any destructive operation, create three classes of backup tags, aligned with spec §10.6 and design §5.15:
Tag class 1 — merge reversal (created BEFORE the merge into the integration branch):
git tag gse-backup/sprint-{NN}-pre-merge-{type}-{name} $(git rev-parse gse/sprint-{NN}/integration)
This tags the integration branch ref at its state before each merge. To revert a problematic merge:
git checkout gse/sprint-{NN}/integration && git reset --hard gse-backup/sprint-{NN}-pre-merge-{type}-{name}
Tag class 2 — branch recovery (created BEFORE each feature branch is deleted in Step 5 cleanup):
git tag gse-backup/sprint-{NN}-{type}-{name}-deleted $(git rev-parse gse/sprint-{NN}/{type}/{name})
This tags the feature branch ref at its last commit. To recreate an accidentally-deleted feature branch:
git checkout -b gse/sprint-{NN}/{type}/{name} gse-backup/sprint-{NN}-{type}-{name}-deleted
Tag class 3 — main-merge reversal (created at the start of Step 3 — Merge Sprint into Main, BEFORE the merge into main):
git tag gse-backup/sprint-{NN}-pre-main-merge $(git rev-parse main)
This tags main at its state before the sprint delivery merge — the highest-stakes operation of the cycle. To undo the delivery merge:
git checkout main && git reset --hard gse-backup/sprint-{NN}-pre-main-merge
All three tag classes are retained for 30 days by default (configurable via config.yaml → git.backup_retention_days). Cleanup happens at the next /gse:deliver (see Step 8 — Cleanup Backup Tags).
This ensures rollback is always possible.
Step 1 — Pre-flight Checks
Verify delivery readiness:
-
Review status — Check that all sprint TASKs are ready for delivery (backlog.yaml TASK status: reviewed or status: done — both are terminal "ready to merge" statuses per spec §12.3 Status lifecycle). If any task has status: in-progress, status: planned, status: review, or status: fixing:
- Report: "Task TASK-{ID} is not complete (status: {status})."
- Present Gate: Wait / Deliver partial / Discuss
-
Merge conflict detection — For each feature branch, check for conflicts:
git merge-tree $(git merge-base gse/sprint-{NN}/integration gse/sprint-{NN}/{type}/{name}) gse/sprint-{NN}/integration gse/sprint-{NN}/{type}/{name}
Report any conflicts found with affected files.
-
Uncommitted changes — For each active worktree, check for uncommitted work:
- If uncommitted changes exist: report and present Gate: Commit / Stash / Discard / Discuss
-
Requirements coverage (REQ→TST traceability) — For each REQ- in docs/sprints/sprint-{NN}/reqs.md, verify that at least one TST- artefact traces to it:
- Uncovered REQ with priority
must → Hard guardrail: block delivery. Report: "Requirement REQ-{NNN} ({description}) has no test covering it. Tests must be written before delivery." For beginners: "One of the things the app should do hasn't been verified yet. I need to add a check for it first."
- Uncovered REQ with priority
should or could → Soft guardrail: warn. Report: "Requirement REQ-{NNN} has no test. This is acceptable but noted." Add a RVW- finding.
- All must-priority REQs covered → Proceed.
Step 1.5 — Test Execution Evidence
For each TASK in the sprint that implements at least one must-priority REQ (via traces.implements in backlog.yaml), read test_evidence.status (per §12.3 Backlog schema):
Guardrail 1 — Unexecuted tests before DELIVER (per spec §9.3.1).
-
test_evidence.status: pass → Proceed silently.
-
test_evidence.status in {absent, fail, skipped} → Hard guardrail: block delivery. Present Gate with 4 options:
- Run tests now (recommended default) — invoke
/gse:tests --run inline for the affected TASKs; re-read evidence; re-evaluate guardrail. If evidence becomes pass for all, Proceed.
- Deliver partial — deliver only the TASKs whose REQs have
test_evidence.status: pass; the others stay in the sprint, move to pool, or get re-planned (user choice). Requires DEC- documenting the partial scope.
- Reclassify as spike / deferred — the TASK is reclassified (
artefact_type: spike or moves to pool with priority: could), requires DEC- documenting the justification.
- Discuss — explain the implications at the user's expertise level (P9).
For beginners: "Before I can deliver, I need to verify that what you asked for actually works. Some tests haven't run yet. Should I run them now?"
Guardrail 2 — Unexecuted test strategy (per spec §9.3.1).
Read docs/sprints/sprint-{NN}/test-strategy.md if it exists. Identify declared test levels by scanning H2 sections (## Unit Tests, ## Integration Tests, ## E2E Tests, ## Policy Tests); a level is declared if its H2 section contains at least one ### TST-NNN entry. Then list all TCP- campaign reports in docs/sprints/sprint-{NN}/test-reports/ and determine covered levels — a level is covered if at least one TCP- campaign executed at least one TST- entry of that level (cross-reference each TST's declared level — the per-TST Level bullet in the single strategy document, or the level: frontmatter field for standalone TST files; see the sprint/tests.md ID-convention note).
-
All declared levels covered → Proceed silently.
-
At least one declared level has no TCP- covering it → Hard guardrail: block delivery. Present Gate with 4 options:
- Run the missing level now (recommended default) — invoke
/gse:tests --run --level <level> for each uncovered level; re-evaluate guardrail. If all declared levels now have TCP- coverage, Proceed.
- Deliver partial — deliver the sprint without the uncovered level; the uncovered level becomes a backlog item for the next sprint via
/gse:backlog --add. Requires DEC- documenting the deferred scope.
- Reclassify the level as deferred — update
test-strategy.md to mark the level explicitly skipped for this sprint (add an Inform note inside the H2 section). Requires DEC- documenting the justification.
- Discuss — explain the implications (test-pyramid gap, residual risk of untested level) at the user's expertise level (P9).
For beginners: "Your test strategy says we'll also do {level} tests, but no {level} test has actually run this sprint. Should I run them now?"
Guardrail 3 — Stale test evidence (per spec §9.3.1).
- Stale evidence (
test_evidence.timestamp predates latest feature-branch commit) → Soft guardrail: warn, suggest re-running. Non-blocking.
This step enforces the three canonical Test-Specific Guardrails defined in spec §9.3.1 and the contract of spec §6.3 — Test Execution and Evidence, canonical run step 5 — "Write test_evidence on each covered TASK". It is the consumer of the test_evidence field and the test-strategy / test-reports coherence check.
Step 1.6 — Minimal Integrity Pass (Lightweight mode only)
Runs only when the project lifecycle mode is lightweight (.gse/config.yaml). Full mode is already covered by the complete devil's advocate pass in /gse:review; Micro mode is excluded by design (Gate-only tier for throwaway experiments — see spec §13.2 mode comparison).
Lightweight has no REVIEW activity, so this is the only P16 integrity net before the code reaches main. Keep it minimal — this is NOT a review:
- Spawn the devil-advocate in
delivery-integrity mode ("$([ -s .gse/registry ] && cat .gse/registry || cat ~/.gse-one)/agents/devil-advocate.md") in a fresh sub-agent context (same isolation contract as review.md Step 3 — inline fallback allowed with the Inform note, execution mode traced).
- Input: the sprint diff (
git diff main...HEAD --stat + changed files) and the sprint artefacts.
- The mode's restricted checklist (see agent file): referenced libraries/packages/APIs actually exist (
pip show / npm list / docs URL), version compatibility, unverified critical assertions (P15 — claims tagged Verified without evidence, or untagged critical claims). Maximum 5 findings, most critical first.
- Routing: HIGH findings → Gate before proceeding to Step 2 (Fix now / Accept the risk — recorded as a DEC- / Discuss). MEDIUM/LOW findings → Inform, appended to the release notes (Step 6).
- Record
DA execution: isolated | inline-degraded alongside the findings.
Step 2 — Merge Features into Sprint Branch
For each feature branch (in dependency order):
-
Present merge strategy Gate — Adaptive presentation by expertise level:
- beginner: "How should I combine this work? Clean summary (one commit per feature) vs Full history (keep all commits)"
- intermediate: "Merge strategy for
{branch}: squash (clean history) / merge (preserve commits) / rebase (linear history)"
- expert: "Strategy for
{branch}: squash / merge --no-ff / rebase / discuss"
-
Execute chosen merge:
- squash:
git checkout gse/sprint-{NN}/integration && git merge --squash gse/sprint-{NN}/{type}/{name} && git commit
- merge:
git checkout gse/sprint-{NN}/integration && git merge --no-ff gse/sprint-{NN}/{type}/{name}
- rebase:
git checkout gse/sprint-{NN}/{type}/{name} && git rebase gse/sprint-{NN}/integration && git checkout gse/sprint-{NN}/integration && git merge --ff-only gse/sprint-{NN}/{type}/{name}
-
If merge fails due to conflicts:
- Report conflicting files
- Present Gate: Resolve (attempt auto-resolution) / Manual (pause for user) / Abort (undo merge) / Discuss
Step 3 — Merge Sprint into Main
-
Present merge strategy Gate:
- merge —
git merge --no-ff gse/sprint-{NN}/integration (default, preserves sprint boundary)
- squash — Collapse entire sprint into one commit
- defer — Keep sprint branch, do not merge yet
- discuss — Explore options
-
Execute the chosen strategy (the class-3 backup tag from Step 0 is created first):
git checkout main
git tag gse-backup/sprint-{NN}-pre-main-merge $(git rev-parse main)
git merge --no-ff gse/sprint-{NN}/integration -m "gse(deliver): sprint S{NN} delivery"
Step 4 — Tag Release
If config.yaml field tag_on_deliver is true (and --skip-tag was not specified):
- Determine version by analyzing sprint content:
- major — Breaking changes or major new features
- minor — New features, non-breaking
- patch — Bug fixes, documentation, refactoring only
- Read last tag to compute next version
- Create annotated tag:
git tag -a v{version} -m "Release v{version} — Sprint {NN}"
- Remote backup prompt — If no git remote is configured (
git remote returns empty):
Your project has no remote. Push to GitHub/GitLab to protect
your work against local disk failure?
1. Yes, help me set up a remote
2. Not now
3. Discuss
This is an Inform-tier suggestion, not a blocker.
Step 5 — Cleanup
Unless --skip-cleanup was specified:
-
Delete merged feature branches:
git branch -d gse/sprint-{NN}/{type}/{name}
-
Remove worktree directories:
git worktree remove .worktrees/sprint-{NN}-{type}-{name}
-
Sprint branch cleanup — Present Gate:
- Delete —
git branch -d gse/sprint-{NN}/integration (merged, safe)
- Keep — Retain for reference
- Default: delete if fully merged
-
Update TASKs in backlog.yaml:
status: delivered
delivered_at: {timestamp}
git.branch_status: deleted
git.worktree_status: removed
Step 6 — Release Notes
Generate release notes at docs/sprints/sprint-{NN}/release.md using the authoritative template plugin/templates/sprint/release.md — instantiate its gse: frontmatter (type: release, sprint, version, tag, commit, traces.implements: [all delivered TASK IDs], timestamps) and fill its sections from sprint data:
- Overview — one-paragraph summary of the sprint delivery
- What's New — delivered TASKs distributed across the template's Features / Improvements / Bug Fixes bullet subsections, each bullet citing the TASK/REQ ids it implements
- Quality Summary — fill the template table rows: test coverage, tests passed, review findings open, health score (from
status.yaml → health), security findings
- Known Issues — unresolved findings or accepted risks (with their DEC- reference) and workarounds
- Sprint History — append the current sprint's goal and completed item count
Do not invent an ad-hoc skeleton — the template is the single authority for structure.
Step 7 — Post-Delivery Hook
If config.yaml field post_tag_hook is configured:
- Execute the hook command
- If hook succeeds: report success
- If hook fails: present Gate:
- Retry — Re-execute the hook
- Rollback — Remove tag, undo merge (class-3 backup tag:
git checkout main && git reset --hard gse-backup/sprint-{NN}-pre-main-merge)
- Investigate — Examine hook output and diagnose
- Discuss — Explore alternatives
Step 8 — Cleanup Backup Tags
Remove backup tags older than backup_retention_days (default: 30):
- List tags matching
gse-backup/* with git tag -l "gse-backup/*"
- For each tag older than the retention period, delete it with
git tag -d <tag>
Step 9 — Finalize
9.1 Generate sprint plan snapshot — Read .gse/plan.yaml and produce a read-only archive at docs/sprints/sprint-{NN}/plan-summary.md using the plan-summary.md template. Inherit the artefact ID from plan.yaml.id (typically PLN-NNN) into the snapshot's frontmatter gse.id field — this preserves P6 traceability across the live-plan → archive transition. The snapshot contains: goal, mode, budget (total/consumed/remaining), tasks delivered (from backlog.yaml), activity flow (from workflow.completed + workflow.skipped with reasons), scope changes (from coherence.scope_changes), coherence summary (alerts raised and whether resolved), risks, and outcome metrics (velocity, findings density, review/fix rounds, P16 counters at close — calibration data, per the template's ## Outcome Metrics section). This file is read-only after archiving (mutated by no one); its consumers are /gse:plan --strategic (velocity calibration), /gse:compound Axe 2 (process-deviation analysis + calibration falsifiability review), coach trend axes, and human sprint history.
9.2 Set plan.yaml.status: completed and update plan.yaml.updated to the current timestamp.
9.3 Update status.yaml activity-local state only:
- Refresh all 8 health dimension scores exactly as specified in
/gse:health Step 2 — Calculate Dimensions (same canonical formulas as /gse:review Step 6; final snapshot for the delivered sprint), written under health.dimensions.* with health.score and health.last_computed updated. This ensures the dashboard health radar reflects the state at delivery time.
- (Cursor fields
last_activity, last_activity_timestamp, and current_phase are maintained centrally by the orchestrator after the activity closes — see plugin/agents/gse-orchestrator.md — section "Sprint Plan Maintenance", and gse-one-implementation-design.md §10.1 — Sprint Plan Lifecycle (v0.53.0). The LC02→LC03 transition is determined by the orchestrator when last_activity == deliver AND plan.yaml.status == completed — both conditions are materialized by Step 9.2 above before Step 9.3 closes.)
9.4 Report delivery summary:
- Tasks delivered
- Version tagged (if applicable)
- Branches cleaned
- Plan snapshot:
docs/sprints/sprint-{NN}/plan-summary.md
- Next step: propose
/gse:compound
9.5 Regenerate dashboard — Run python3 "$([ -s .gse/registry ] && cat .gse/registry || cat ~/.gse-one)/tools/dashboard.py" to update docs/dashboard.html with delivery status and release info.