Skip to content

Add the xmd upgrade command #681

Description

@taras

Story

As someone running the standalone xmd binary on Unix, I want xmd upgrade to
replace it with a verified published release, so I can update safely without
repeating the installation command or guessing which asset matches my machine.

Command contract

xmd upgrade [<tag>] [--status] [--allow-downgrade] [--allow-prerelease]
  • With no tag, select the latest published stable GitHub Release. An opt-in
    never makes an implicit selection choose a prerelease.
  • A stable exact tag has the form vX.Y.Z. A prerelease exact tag has the form
    vX.Y.Z-<prerelease>, using SemVer prerelease identifiers and no build
    metadata. The binary's --version is the selected tag without the leading
    v.
  • --status reports the installed version, selected release, exact release URL and
    whether that release is newer, current or older. It performs no binary
    download, creates no temporary executable, takes no installation lock and
    changes nothing. Every completed comparison exits zero; lookup, validation
    and command-line failures exit one.
  • xmd upgrade <tag> --status may inspect an exact stable, prerelease or older tag without
    installation consent. --allow-downgrade and --allow-prerelease are
    therefore invalid with --status rather than ignored.
  • Installing an older version requires --allow-downgrade. Installing a
    prerelease requires its exact tag and --allow-prerelease. A consent option
    that does not apply to the selected release is a command-line refusal rather
    than a silently ignored flag.
  • An already-current binary succeeds as an observable no-op without downloading
    the binary, creating a temporary executable, taking replacement action or
    writing the installation.
  • A draft, missing or malformed release is never selectable. If the latest
    stable release lacks the required target asset or checksum, the command fails
    closed rather than falling back to an older release.

A successful installation names the previous version, installed version,
physical executable path and exact GitHub Release URL so the person can read its
release notes.

Installation provenance

Self-upgrade is available only to the standalone compiled release binary on a
supported Unix target. The compiled entrypoint supplies its own physical
executable identity, current version, platform, architecture and replacement
capability explicitly. Shared production modules do not inspect the active
runtime or infer installation provenance.

The compiled Windows binary, Deno source entrypoint, npm/Node package, Bun
entrypoint and repository development invocation expose the same command and
help but refuse before release lookup, binary download, temporary-file creation
or installation mutation. Each refusal explains who owns that installation and
gives its appropriate repair or update procedure. Windows directs the person to
the standalone installer or the exact release asset; synchronous Windows
self-replacement requires a separately settled supervisor and is not
approximated by a detached helper.

Reader-first executable command document

Implement the command's reader-facing policy as the packaged
upgrade-command.md document. It is a workflow, not a Markdown transcription of
install.sh: the installer remains the bootstrap and repair path, while this
document explains and decides the lifecycle of an existing installation.

Follow the reader-first executable workflow method in #668:

  • begin with a title naming the transformation;
  • explain the input, result, inert state and effect boundary in the
    introduction;
  • give each meaningful stage a visible heading, with the common path before
    exceptions;
  • explain a practical consequence immediately before the component that
    performs it;
  • keep schemas, bindings, classification and formatting machinery silent;
  • keep selection, comparison, bounds, choices, refusals and outcome presentation
    visible in Markdown; and
  • render the output and read it as the person running the command before calling
    the document complete.

The document earns its place by owning real policy: unsupported-installation
refusal, latest-versus-exact selection, SemVer comparison, consent, status mode,
already-current and installation branches, and the words each outcome presents.
It must not call one component that secretly selects, authorizes, installs and
formats everything. TypeScript eval blocks may parse, classify, compare and
format values; shell does not implement control flow or parsing.

The trusted host parses the fixed command-line grammar before the document
runs. It loads the exact packaged bytes under an internal command identity, with
an empty repository component search path and an invocation-owned in-memory
journal. Source and npm builds package the same document, and both compile sites
embed it. A missing packaged document fails rather than selecting repository
content or another policy.

Host boundary

The document receives fixed installation facts and two host-declared operations:

  1. A release-metadata reader performs the bounded read of published releases,
    validates the GitHub response and returns detached normalized release facts.
    Markdown selects and compares those facts.
  2. One installation operation accepts only a release identity admitted by that
    reader and performs the complete byte-bearing attempt: target-asset
    resolution, download, checksum and candidate verification, staging and final
    replacement. It returns detached completed facts for Markdown to present.

These operations are declared directly to canonical execution from factories
closed over one invocation's trusted host assembly. Their operational authority
and completion do not travel through a contextual API or middleware return
value. Public middleware may observe or refuse routing but cannot invoke a
replacement on a fabricated request, substitute another release, acknowledge a
phase, or manufacture successful completion. Repository-local components cannot
replace either operation.

Binary bytes, response handles, redirect credentials, physical temporary paths,
the installation lock and the staged executable remain private to the trusted
host. They never enter document props, bindings, interpolation, output or the
journal. The command document receives no general Files, Process, Service,
command or unrestricted Fetch capability merely because its host can upgrade
one executable.

The compiled Unix entrypoint supplies the real installation assembly. Every
other entrypoint supplies fixed refusal facts and no release or replacement
authority. A refusal branch reaches neither host operation.

Release resolution and integrity

  • Resolve releases from taras/executable.md over HTTPS. The latest selection
    is the latest published stable release, not a draft or prerelease.
  • Derive the target and asset name from the same supported release-target
    mapping used by release.yml; one table owns target, platform, architecture
    and artifact name.
  • Bind the selected release identity to its tag, canonical GitHub Release URL,
    target, asset name and checksums.txt from that same release. A later install
    accepts only an identity the invocation's metadata read admitted.
  • Validate every redirect and final response as part of the selected release's
    bounded anonymous GitHub download. An unrelated destination receives no
    credential or bytes and no outcome is accepted from it.
  • Download the target binary and checksums.txt into invocation-owned private
    temporary state only after the document has selected installation rather than
    status or no-op.
  • Require exactly one checksum entry for the selected asset and verify its
    SHA-256 digest before the candidate can become executable or replace anything.
  • Run the staged candidate with --version and require the exact selected
    version before replacement.
  • Keep the existing binary byte-identical when resolution, download, checksum
    verification, candidate validation or replacement preparation fails.

The trust boundary in this slice is the published GitHub Release reached over
HTTPS plus its same-release checksum set. Existing GitHub build attestations
remain release evidence but are not a second self-upgrade verification protocol.

The release specification records the asset, checksum, target-name and
availability guarantees on which xmd upgrade depends.

Safe Unix replacement

  • Resolve and validate the exact physical compiled executable supplied by the
    entrypoint; never replace whichever unrelated xmd appears first on PATH.
  • Refuse a symbolic-link destination, an unwritable parent, an unsupported
    filesystem or any topology in which the original executable cannot remain
    complete until commit. Do not follow a link or fall back to another path.
  • An installation attempt acquires one non-blocking OS-released exclusive lock
    for that physical installation before release lookup and holds it through the
    command document, replacement, reporting and complete teardown. A concurrent
    installation attempt refuses without staging or network access. --status
    takes no lock.
  • Stage beside the destination with the required executable mode and platform
    metadata. The candidate is complete and verified before the commit point.
  • The commit point is one same-filesystem atomic replacement. Before it, every
    failure leaves the original byte-identical; after it succeeds, the verified
    candidate is the installed executable and later invocations use it. A host
    that cannot offer that boundary refuses before staging.
  • The old process may continue running from its already loaded image. It owns
    this invocation's final output and exit status; no detached process authors a
    later result.
  • The command never invokes sudo, changes shell startup files, relocates the
    installation, modifies workflow or Agent-session state, or upgrades a package
    managed by another tool.

Authority, failure and cancellation

The explicit command invocation authorizes at most one installation attempt of
the physical compiled installation it is running from. It grants no recurring
background release polling and installs no daemon, scheduler or automatic-update behavior.

The host operation's accepted result is the only evidence that installation
completed. A routing response, rendered sentence or staged candidate cannot
settle the command. A refusal or failure before atomic replacement leaves the
old executable authoritative; successful atomic replacement makes the selected
candidate authoritative. Nothing reports success before that winner is known.

Cancellation closes the metadata request, download, candidate process and every
temporary resource, releases the installation lock after teardown, and preserves
the installed executable unless atomic replacement had already completed.
Invocation-owned temporary names cannot collide with another verification, build or
upgrade, and no cleanup runs in the background after command completion.

Help and documentation

  • Root help lists upgrade as a public command.
  • xmd upgrade --help is effect-free and explains latest selection, exact
    stable and prerelease tags, status-mode behavior, consent options, compiled
    Unix support, every installation refusal, verification and the physical
    replacement path.
  • The generated website CLI reference picks up the command through Generate website reference documentation from xmd CLI output #678 without
    adding a hand-maintained command or flag inventory.
  • Installation documentation explains when to use xmd upgrade and when to use
    npm, Deno, Bun, the standalone installer or a release asset instead.

Planner workflow-description interview

After writing the initial upgrade-command.md workflow, the Planner interviews
the user one stage at a time before finalizing the implementation plan. For each
stage it presents exactly:

  1. Current — the existing wording verbatim.
  2. Intent — the behavior that wording is trying to communicate.
  3. Proposed — clearer replacement wording.
  4. Feedback — one unresolved question or a request for approval.

The Planner keeps a visible count of approved sections and does not advance
until the user answers. A general rule is named and applied to every later
section; an approved earlier section affected by it is explicitly reopened and
never revised silently. If the interview reveals a product or architecture
change, planning stops, the decision returns to the Architect and the issue is
amended before wording continues. Planner handoff occurs only after the user has
approved the complete workflow description.

Acceptance

  1. A compiled Unix release binary upgrades from an older version to the latest
    stable published release and reports the exact release link.
  2. --status performs only the documented metadata read: no binary download,
    temporary executable, installation lock or mutation, and reports the installed version, selected release, exact release URL and a
    newer, current or older comparison with exit status zero.
  3. An already-current installation succeeds as an observable no-op and leaves
    the binary byte-identical without downloading it.
  4. Exact stable and prerelease tags follow the documented grammar. Installation
    of an older or prerelease release requires the applicable explicit consent;
    status inspection does not.
  5. npm/Node, Deno, Bun, source and compiled Windows entrypoints refuse before
    network or filesystem work and give installation-specific guidance.
  6. Unix asset selection uses the release target mapping; the mapping continues
    to cover the Windows artifact even though Windows self-replacement refuses.
  7. Missing assets, missing or duplicate checksum entries, checksum mismatch,
    candidate-version mismatch and unassociated redirects leave the existing
    executable byte-identical.
  8. The final Unix replacement is one same-filesystem atomic commit. Interruption
    never leaves a missing or partial executable presented as installed.
  9. Concurrent installation attempts for one physical executable cannot
    interleave; the loser refuses before lookup or staging, while status-mode
    invocations need no lock.
  10. A symbolic link, unwritable destination or unsupported replacement topology
    fails with an actionable explanation and never falls back to another path.
  11. The command document is packaged byte-identically for source, npm and
    compiled distributions, but only a compiled supported Unix host supplies
    installation authority.
  12. Generic and command help are effect-free. Status mode performs no effect
    beyond its documented metadata read.
  13. The packaged document visibly owns selection, comparison, consent,
    status mode, no-op, refusal and presentation instead of wrapping a host
    operation that owns the entire workflow.
  14. Focused evidence distinguishes authorized completion from a contextual or
    middleware acknowledgement, proves unsupported hosts reach no operation,
    and covers release selection, version ordering, integrity failure,
    cancellation, lock contention and Unix replacement.
  15. The rendered workflow is read as an operator, its headings tell the complete
    lifecycle, every component is explained by adjacent prose, hidden machinery
    renders nothing and failures say what happened, what did not and what to do
    next.
  16. The Planner completes Document reader-first executable workflow writing #668's section-by-section workflow-description
    interview and records the user's approval before implementation handoff.
  17. architecture.md, specs/release-process-spec.md, CLI and installation
    documentation, compiled assets and release.yml describe the same upgrade
    inputs, authority and guarantees.

Out of scope

  • Automatic or background updates.
  • Synchronous Windows self-replacement, a persistent Windows launcher or an
    asynchronous detached-helper completion protocol.
  • Updating npm, JSR, Bun, Homebrew or another package-manager installation.
  • Migrating workflow journals, retained Workspaces, Agent sessions or
    configuration between versions.
  • Replacing an arbitrary executable selected from PATH.
  • Translating install.sh into Markdown or shell orchestration.
  • Verifying GitHub attestations as a second self-upgrade trust protocol.
  • Bypassing release checksums, host permissions, package-manager ownership or
    operating-system replacement constraints.

Related work and delivery order

  • Document reader-first executable workflow writing #668 supplies the reader-first authoring and refinement method. Its guide need
    not merge first; this issue adopts the method directly.
  • Generate website reference documentation from xmd CLI output #678 generates the released website CLI reference and release backlinks. It
    may proceed independently and must discover upgrade from released help once
    the command exists.
  • The existing install.sh remains the bootstrap and repair path for standalone
    installations. Shared release-target and integrity utilities may support both
    paths, but neither duplicates the other's policy.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions