Files
msd-core/docs/how-to/update-gsd.md
Tom Boucher cf15682d1c enhance(#3028): responsive Markdown separators instead of fixed-width rules (#3789)
* feat(#3028): responsive Markdown separators instead of fixed-width rules

Stage banners, checkpoints, completion and error panels used fixed-width
runs of box-drawing characters -- a 53-column heavy rule and a 62-column
double-line box. Those runs are ordinary text to a Markdown-rendering
host, so in a narrower pane they wrap and the border comes apart from
the heading it framed.

Shipped content now emits an ATX heading for a titled section and a
blank-line-delimited --- for a break between sections, both of which
adapt to the available width. The same convention is applied to the
three code sites that built these strings at runtime: the UAT
checkpoint renderer, the milestone-close audit report, and the TDD
review checkpoint table.

Removing the box also removes its only reason to exist -- the
east-asian-width padding helpers that kept its right border aligned
(checkpointBoxLine, displayWidth, isWideCodePoint, ZERO_WIDTH_MARK_RE,
CHECKPOINT_BOX_WIDTH). RTL directional isolation is unchanged.

The convention is specified in gsd-core/references/ui-brand.md and
enforced across all shipped content by tests/responsive-separators.test.cjs.

Refs #3028

* test(#3028): pin the heading form in checkpoint and audit-report assertions

These suites asserted the exact box borders and the 62-column padded
banner interior. With the box gone they assert the ### heading form,
the --- break and the bolded instruction line, and each now carries a
positive assertion that no box character remains -- which is what pins
the fix rather than merely tolerating it.

Language coverage is converted, not dropped: Japanese, Chinese, Korean,
Hindi and Arabic all still assert their rendered banner, and the Arabic
case still asserts the RTL directional isolates the box removal must
not disturb. Adds a case for a banner longer than the old inner width,
which previously produced a ragged border and now has none.

Refs #3028

* chore(#3028): acknowledge execute-plan.md growth from the checkpoint display spec

The checkpoint_protocol display spec described the drawn box; it now
describes the heading, the --- break and the bolded action prompt,
which costs 22 bytes (40111 -> 40133, 827 under the cap).

Appended to the existing #3370 fragment rather than filed as a new one:
a growth ack keys on the bare filename and #3370 already declares
execute-plan.md, so a second source naming it would be a hard
duplicate-key error. Same supersede-by-append route #3370 took for the
spent #2652 fragment.

Refs #3028

* docs(#3028): state the load-bearing half of the separator rule, and amend the zh-CN reference

Review found three things.

The rule as first written demanded a blank line above AND below every
---. Only the one above is load-bearing: it is what stops CommonMark
reading the rule as a setext underline for the line above. The one below
is cosmetic, because a thematic break is a leaf block. The rule now says
that, with the reason, instead of asserting a stricter form the content
does not keep.

The zh-CN reference had received the mechanical box-to-heading swap but
none of the prose behind it: it still claimed a 62-character checkpoint
width and still listed --- among forbidden mixed banner styles, so it
contradicted the convention it was translating. It now carries the
separator section, the setext reasoning, the unconditional-vs-per-runtime
rationale and a corrected anti-pattern list, in Chinese.

The user guide asserted that a heading is not a degradation anywhere.
That is an assertion, not a demonstration. It now says what was actually
traded away in a plain terminal, points at the recorded rationale, and
invites the report that would justify the capability flag instead.

Refs #3028

* chore(#3028): backfill changeset PR number

Refs #3028

---------

Co-authored-by: sim <sim@local>
2026-08-23 22:38:12 -04:00

7.5 KiB

How to update GSD Core

Update an existing GSD Core install to the latest release, preview the changelog before committing, and recover any local customisations that the update would overwrite.

What you need: The same runtime GSD is installed for. The update command re-runs the installer under the hood, so it needs Node.js and npx available (same requirement as the original install).


The standard update path

From inside your AI runtime, run:

/gsd-update

GSD will:

  1. Detect the installed version and install scope (global or local).
  2. Check npm for the latest release of @opengsd/gsd-core.
  3. Fetch the changelog and show you what changed between your installed version and the latest.
  4. Ask for confirmation before touching anything.
  5. Back up any user-added files found inside GSD-managed directories to gsd-user-files-backup/.
  6. Run the installer (npx @opengsd/gsd-core@latest --<runtime> --<scope>).
  7. Clear the update-check cache so the statusline indicator resets.
  8. Offer to restore the user-added files it backed up in step 5.
  9. Report whether locally modified GSD files were backed up to gsd-local-patches/.

Restart your runtime after the update to pick up new commands and agents.


Flags

Flag What it does
--sync After updating, sync skills from the GSD registry
--reapply After updating, merge locally modified GSD files back in from gsd-local-patches/
--next / --rc Target the @next RC dist-tag instead of @latest (installs or refreshes a release candidate; see ADR #660)
/gsd-update --sync        # Update and sync skills
/gsd-update --reapply     # Update and reapply local patches
/gsd-update --next        # Install from the @next RC dist-tag

Install or refresh a release candidate

GSD publishes release candidates on the @next npm dist-tag (established by ADR #660). To install or refresh from that channel:

/gsd-update --next
# or equivalently:
/gsd-update --rc

The full update flow applies — scope/runtime detection, changelog preview, custom-file backup, and cache clearing all run normally. The only difference is that check-latest-version.cjs resolves the @next tag and npx installs from @opengsd/gsd-core@next.

Only latest and next are supported channels; no arbitrary dist-tag can be passed (the script enforces an allowlist and exits with code 2 on an invalid tag).

Omitting --next/--rc keeps targeting @latest (stable channel, no change in behavior).


Reviewing the changelog before updating

/gsd-update always shows the changelog diff between your installed version and the latest before it asks for confirmation. You do not need to visit GitHub separately. The output looks like:

## GSD Update Available

Installed: 1.39.0
Latest:    1.41.0

### What's New

---

[changelog entries for 1.40.0 and 1.41.0]

---

Proceed with update? [Yes, update now / No, cancel]

If the changelog cannot be fetched (no network access, npm outage), the update still proceeds after confirmation — it does not block on changelog availability.


Recovering local customisations

Files you added inside GSD-managed directories

If you placed custom files inside directories that GSD owns (for example, custom agents prefixed with gsd- or extra files in commands/gsd/), the installer detects them and copies them to gsd-user-files-backup/ before wiping those directories.

After the new version is installed, the update offers to put them back. You get a list of what was backed up, then a choice:

  • Restore them now — each file is copied back to its original location and the update reports what it restored.
  • Leave them in the backup — nothing is copied; the backup stays exactly where it is.

Either way the backup is never deleted, so declining is not destructive and you can restore later.

Before copying anything back, the restore runs a compatibility pass against the version that was just installed and attaches a warning to any file that looks like it may no longer work — one that references a workflow or /gsd: command the new release retired, or a skill missing its name / description frontmatter. Warnings are advisory: the file is still restored, with the warning shown next to it, so you can decide whether to fix it.

Two cases are skipped rather than restored, because restoring would destroy something:

  • The new release now ships a file at that exact path (your custom file would overwrite GSD's).
  • A different file is already sitting at that path (restoring would overwrite your current version).

Both stay in the backup and are reported with the reason.

To restore later — or after an update where you declined — run the same operation directly:

node <config-dir>/gsd-core/bin/gsd-tools.cjs restore-custom-files --config-dir <config-dir> --apply

Drop --apply to preview what would be restored without writing anything.

Files you placed outside GSD-managed directories — custom agents not prefixed with gsd-, custom commands outside commands/gsd/, your CLAUDE.md files, and custom hooks — are never touched by the installer.

GSD files you modified directly

If you edited a file that GSD installed (for example, tweaking an agent's system prompt), the installer detects the modification via a hash comparison against its manifest, backs the file up to gsd-local-patches/, and then replaces it with the new version. After the update:

/gsd-update --reapply

This merges your modifications from gsd-local-patches/ back into the newly installed files.

If you skipped --reapply after a previous update and want to apply patches now:

/gsd-update --reapply

It is safe to run --reapply on its own without triggering a new download — if you are already on the latest version, GSD skips the install step and goes straight to reapplying patches.


When npm is unavailable

If npx @opengsd/gsd-core@latest fails due to an npm outage, network restrictions, or because you are working from the source repository, use the manual update procedure in docs/manual-update.md. That document covers pulling the latest commit, building the hooks dist, and running node bin/install.js directly.


If you are already on the latest version

/gsd-update exits early with a confirmation message — no download, no install, no restart needed.


Installer migrations

Each GSD release may include installer migrations that rename, move, or retire managed files. The migration layer runs automatically before the new package payload is written. Migrations that would affect files you have modified prompt for confirmation rather than acting silently. For the full design and runtime-configuration contract registry, see docs/installer-migrations.md.


CLI version-skew warning

GSD warns (to stderr, non-blocking) when the resolved gsd-tools.cjs is outside your project root while a project-local install exists — a sign that a global install (often a retired @gsd-build/sdk canary) is shadowing your project-local GSD. The warning names the resolved path and, for the @gsd-build/sdk case, gives the removal command:

npm uninstall -g @gsd-build/sdk

If you see this warning, remove the stale global package so gsd_run resolves the project-local install.