zudo-text

検索したい単語を入力

いつでも検索バーを開ける

l-make-mcp-release

Release the public zudotext-mcp npm package end to end from its private source repository: prepare a version, verify and land it, push the MCP-only tag, watch trusted publication, and smoke the regist...

/l-make-mcp-release

Publish @takazudo/zudotext-mcp publicly on npm from its permanently private source repository. The tag workflow also creates an authenticated GitHub Release mirror for maintainers.

This skill is deliberately separate from an unqualified zudo-text release, which means the desktop app. The desktop release is not automated by a project-local skill yet, so stop and explain that limitation when it is requested. Never reinterpret it as permission to publish the MCP package.

Autonomy and boundary

Without --confirm, the invocation authorizes the complete MCP release, including the final tag push and monitoring its workflow. With --confirm, perform all safe preparation and verification, show the exact tag and commit, then stop before pushing the tag.

The npm name/version pair is the irreversible boundary. Do not delete or move a published tag or attempt to reuse a published npm version. Fix forward with a new version.

Inputs

  • No version argument:

    • If no zudotext-mcp-v* tag exists, release the valid version already in packages/zudotext-mcp/package.json; this establishes the first baseline.

    • Otherwise infer patch, minor, or major from MCP-relevant commits since the newest MCP tag: breaking changes require major, feat requires minor, and all other releasable changes require patch.

  • major, minor, or patch: bump that component from the newest MCP tag.

  • An exact semantic version: use it after verifying it is newer than the newest MCP tag and is not already tagged or released.

  • --confirm: stop before the tag push.

  • resume <VERSION> --sha <MAIN_SHA>: finish a release whose preparation PR is already merged at <MAIN_SHA> but whose tag push or publication was interrupted. See "Resume a prepared, unpublished release"; it never bumps, merges, or picks a different commit.

  • cancel: close an unmerged release PR and delete its untagged release branch after checking the exact targets. Never remove a published release or tag.

For a no-argument inferred major bump, stop and ask whether to publish the major now or choose an explicit version. This is the only default-path version strategy pause.

For inferred or keyword bumps, require the package version to equal the newest MCP tag's version before calculating the next version. If it differs, stop and reconcile the abandoned or partial preparation explicitly; never overwrite it with a computed version that could be lower. An exact version must also be strictly greater than both the package version and newest tag. The no-tag first release is the exception: an exact version equal to the valid current package version establishes the baseline without rewriting it.

A prepared unpublished version is the other continuation case: when the package version is greater than the newest tag, allow that exact current version only if its tag and GitHub Release are absent and npm already contains the same verified tarball integrity. This resumes a bootstrap or interrupted release without bumping again.

Preconditions

Run all checks before changing files:

  1. Require branch main, a clean working tree, successful gh auth status, and local main not behind origin/main after fetching main and tags. (resume replaces this check with its own exact-SHA rule; see below.)

  2. Read the current package version and newest tag matching the strict pattern zudotext-mcp-v<semver>. Ignore desktop-app and unrelated package tags.

  3. Require .github/workflows/release-zudotext-mcp.yml and verify that the target tag and GitHub Release do not already exist. Check the public npm registry for the package/version too.

  4. For later releases, inspect commits in the tag-to-HEAD range only for packages/zudotext-mcp/, its bundled workspace dependencies packages/cloud-crypto/ and packages/file-utils/, and .github/workflows/release-zudotext-mcp.yml. Inspect pnpm-lock.yaml semantically: count a lockfile-only commit only when it changes the packages/zudotext-mcp importer or a resolved package reachable from that importer's runtime/bundled dependency closure. A shared lockfile touch by itself is not MCP-relevant. If the scoped range is empty and no exact higher version was requested, stop: unrelated app changes do not justify an MCP release.

  5. Summarize the target version, base tag, categorized commits, files that will change, and the final tag. In default mode this is visibility, not a confirmation gate.

Prepare a later version

Skip this section for the first release when the package already contains the target version and no release tag exists.

  1. Create release/zudotext-mcp-v<VERSION> from current main.

  2. Run:

    pnpm --dir packages/zudotext-mcp release:version -- <VERSION>
    pnpm --filter @takazudo/zudotext-mcp exec vitest run src/server-inventory.test.ts -u
  3. Confirm the version script updated every guarded static consumer listed in packages/zudotext-mcp/RELEASING.md. Review the inventory diff; the snapshot should change only when the tool surface truly changed.

  4. Run the verification gate below, commit the reviewed release files, push the branch, open a PR against main, and wait for required CI. Merge only when green, delete the release branch, then update local main and capture its exact commit SHA. Do not tag a pre-merge branch commit.

Resume a prepared, unpublished release

Use resume <VERSION> --sha <MAIN_SHA> only when the version commit is already merged into main and the release stopped before or during publication. <MAIN_SHA> must be the full 40-character commit, and the target is exactly that commit. Never substitute a later main commit (for example, one that only changed this skill), never bump again, and never merge another release PR.

Resume replaces precondition 1: instead of a checkout of main, it works from a clean, detached HEAD at <MAIN_SHA>, and <MAIN_SHA> must be an ancestor of the freshly fetched origin/main. Preconditions 2 and 3 still apply. The reconcile script checks the tag, release, run and npm state, and step 2 checks the package and README versions.

Every path runs the same steps in the same order. Only step 3 depends on the state, so no later step reads a variable that an earlier path skipped setting. The exact commands are in resume-handoff.md, the one canonical copy. Run its blocks yourself, or fill in its placeholders and post it when handing off (see "Cloud sessions and ref-write restrictions"). Never post a hand-off rewritten from memory.

Shell state does not carry between steps: separate tool calls start in a fresh process, with no variables and an unknown working directory. Step 0 therefore writes an env file, and every later step begins with source "$TOOLS/env" and cd "$MAIN". Every gh command passes --repo zudolab/zudo-text.

  1. Pin the reviewed tools outside the repository. Copy resume-check.sh, resume-check.test.sh, require-clean.sh and sri.sh from the reviewed commit of this skill into a new TOOLS=$(mktemp -d) with git show <TOOL_SHA>:.claude/skills/l-make-mcp-release/<file>, run resume-check.test.sh there, and record MAIN, TARGET, VERSION, TOOL_SHA and TOOLS in $TOOLS/env. The release worktree in step 2 checks out <MAIN_SHA>, which may predate these helpers, so never run them from a checkout path.

  2. Reconcile first, with the fail-closed script. It writes nothing in check mode:

    bash "$TOOLS/resume-check.sh" <VERSION> <MAIN_SHA>

    It stops on any mismatch, and on any lookup that is not a confirmed answer:

    • The SHA is abbreviated or is not on origin/main.

    • A local tag zudotext-mcp-v<VERSION> peels to another commit, or git show-ref fails with anything other than "absent" (exit 1).

    • The remote tag peels to another commit. It reads both refs/tags/<tag> and refs/tags/<tag>^{}, so an annotated tag is compared by its commit, not by its tag object.

    • Any release workflow run for the tag ran at another commit. The script inspects every run for the tag before counting runs at <MAIN_SHA>, and stops when the reply spans more than one page.

    • npm is published without the tag or release, or a release exists while npm lacks the version.

    • Any git, npm or GitHub lookup fails. A non-zero gh exit stops even when usable-looking output arrived; the one exception is the release lookup's HTTP 404, which gh reports with exit 1 and which counts as "no release" only with GitHub's own Not Found body. Only npm's E404 "No match found for version", confirmed by the package's own version list, counts as unpublished. Network, auth, rate-limit or unparsable replies never count as absence.

    • An HTTP 200 release reply is not a non-draft release for exactly that tag whose only asset is zudotext-mcp-v<VERSION>.tgz. A status code alone is never evidence of a release.

    It prints the state on success:

    • STATE=fresh: step 3 pushes the tag.

    • STATE=tagged: the tag is already at <MAIN_SHA>. Step 3 is skipped, and step 4 verifies that tag's run.

    • STATE=published: step 3 is skipped, and steps 2 and 4 verify what was published. Any mismatch is a stop, and the fix is a higher version.

  3. Verify the exact source in an isolated worktree that this run owns. This runs for every state, including STATE=published, because step 4 compares the published bytes with this tarball.

    WT_PARENT=$(mktemp -d) || exit 1
    WT="$WT_PARENT/zudotext-mcp-resume"
    source "$TOOLS/env" && cd "$MAIN" || exit 1
    WTLIST=$(git worktree list --porcelain) || exit 1
    if grep -qxF "worktree $WT" <<<"$WTLIST"; then exit 1; fi
    git worktree add --detach "$WT" <MAIN_SHA> || exit 1

    Capture a command's output and exit status before testing the output. A pipeline or $(...) inside a test (cmd | grep -q, [ -z "$(cmd)" ]) reads a failed command as "nothing found", so it never decides whether to continue or to clean up.

    In $WT:

    • Run pnpm install --frozen-lockfile.

    • Check that the package and README versions are <VERSION>, reading each into a variable first.

    • Run the verification gate below with --expected-tag zudotext-mcp-v<VERSION>.

    • Record the local integrity with bash "$TOOLS/sri.sh" packages/zudotext-mcp/dist/release/zudotext-mcp-v<VERSION>.tgz. It stops on a missing or empty tarball and on malformed output.

    • Require bash "$TOOLS/require-clean.sh" "$WT" to print CLEAN=. It stops when git status fails, so a failed status with empty output is never read as clean.

    Keep the gate output as evidence. Never reuse, overwrite or remove a worktree or directory this run did not create.

  4. Push only the tag, only from STATE=fresh. Run it from the main checkout, not from $WT: the repository's pre-push hook refuses pushes from any linked worktree. Use the same script:

    bash "$TOOLS/resume-check.sh" <VERSION> <MAIN_SHA> --push-tag

    The script:

    • re-runs every reconcile check;

    • creates the tag only when it is absent locally, and reuses an existing local tag only when it peels to <MAIN_SHA>;

    • never pushes after a failed git tag;

    • pushes the single ref refs/tags/zudotext-mcp-v<VERSION>;

    • re-reads the remote tag and requires its peeled commit to be <MAIN_SHA> (STATE=pushed).

  5. Verify publication, for every state. Run every check in "Publish and watch" for that exact tag and SHA, and reconcile the integrity three ways:

    • npm's dist.integrity for <VERSION>;

    • sri.sh of the mirror asset zudotext-mcp-v<VERSION>.tgz, downloaded into a new temporary directory;

    • the local integrity from step 2.

    Require npm's value to be a well-formed sha512- integrity before comparing. npm and the mirror asset must match; a mismatch there is a failed release. A local integrity that differs from both is a stop for investigation, reported with all three values. It is never reported as a match, and it is never repaired by republishing.

  6. Clean up only what this run created. $WT and $WT_PARENT are always set by step 2, because every path runs it. Keep the evidence (state lines, gate output, the three integrity values) first. Remove them only after require-clean.sh "$WT" prints CLEAN=, and without --force: git worktree remove "$WT" && rmdir "$WT_PARENT". Remove any temporary download directory from step 4 the same way, by the exact path this run created.

  7. Check every exit status. A non-zero exit from any step stops the resume with the step's first error recorded. Never retry a different route around it.

Resume never runs a direct npm publish, creates or changes credentials, grants or repository permissions, or deletes or moves a tag or release. resume-check.test.sh next to this file covers these cases offline:

  • abbreviated or off-main SHA;

  • stale or matching local tag, and a local show-ref error;

  • annotated remote tag at the right or wrong commit;

  • npm network error;

  • GitHub release or run lookup errors, a gh failure behind a 200 body, and a 404 without GitHub's body;

  • a same-tag run at another commit;

  • a malformed or incomplete 200 release reply;

  • published npm without a tag, and a complete publication;

  • a fresh push;

  • require-clean.sh on a clean, dirty or non-repository directory, and a failed git status with empty output;

  • sri.sh against an independent sha512, and on an empty or missing file or a failed hash.

resume-handoff.sim.sh runs the six blocks of resume-handoff.md end to end against a throwaway origin and stubbed gh, npm and pnpm. It runs each block as its own bash process from /, with temporary paths that contain spaces, and covers the fresh, tagged and published states, a pinned bundle that passes its own suite, owned-only cleanup and a surviving unrelated directory. Run both after changing either file.

Cloud sessions and ref-write restrictions

A Claude Code cloud (web) session may be able to write only its assigned branch. Pushing a tag can then fail with a disconnect (send-pack: unexpected disconnect while reading sideband packet), and creating the ref through the GitHub API can return HTTP 403 Write access to this GitHub API path is not permitted through this proxy. That is an environment boundary, not a flake. Do not retry with another route (API, MCP tool, different remote, bash -c wrapper) to get past it.

When the tag cannot be written:

  1. Stop before the tag. Record the first failure verbatim and the state: merged <MAIN_SHA>, the absent tag, and the npm version still unpublished.

  2. Hand off to the user's local agent by posting resume-handoff.md with its placeholders filled: <VERSION>, the full <MAIN_SHA>, the reviewed <TOOL_SHA> and a <TOOL_REF> that contains it. Do not paraphrase or shorten it. If an earlier hand-off is wrong, mark it superseded where it was posted, and don't leave two live hand-offs.

  3. Main now advertises an unpublished version in the Settings installer constant. Say so. If the owner postpones the release, open a PR that restores the previous version's static consumers instead of leaving main pointing at it.

Verification gate

From repository root, run:

pnpm --filter @takazudo/zudotext-mcp test
pnpm --filter @takazudo/zudotext-mcp typecheck
pnpm --dir packages/zudotext-mcp release:verify -- \
  --expected-tag "zudotext-mcp-v<VERSION>"

Require a clean tracked working tree afterward. The generated packages/zudotext-mcp/dist/release/ output is ignored build evidence, not a file to commit.

Immediately before publishing, re-check that:

  • HEAD is the intended clean main commit and is present on origin/main;

  • package and README versions match <VERSION>;

  • the tag and release are still absent; and

  • the verification gate succeeded for that exact tag.

npm credentials

The tag workflow publishes with the NPM_TOKEN repository secret (an npm Automation token, or a granular token with "bypass 2FA" that can publish @takazudo/zudotext-mcp). Before the tag push, confirm the secret exists with gh secret list --repo zudolab/zudo-text; never read, print, or store its value. If it is missing, stop before the tag and ask the owner to add it. See packages/zudotext-mcp/RELEASING.md "npm credentials".

Publish and watch

Unless --confirm was passed:

git tag "zudotext-mcp-v<VERSION>" <MAIN_SHA>
git push origin "zudotext-mcp-v<VERSION>"

Find the run created by the just-completed push and require all of its identity fields to match: workflow path .github/workflows/release-zudotext-mcp.yml, workflow name Release zudotext-mcp, event push, head branch/ref zudotext-mcp-v<VERSION>, and head SHA <MAIN_SHA>. If multiple attempts or runs share the SHA, select the current attempt for that exact tag and inspect its creation time/run ID. Do not use a sibling tag, older attempt, or branch CI run as release evidence.

After it succeeds, require all of the following:

  1. npm view @takazudo/zudotext-mcp@<VERSION> reports the exact version and the registry dist.integrity matches the locally verified tarball.

  2. A fresh temporary-prefix install of @takazudo/zudotext-mcp@<VERSION> succeeds, and its installed zudotext-mcp --version prints <VERSION>.

  3. gh release view zudotext-mcp-v<VERSION> reports a published, non-draft maintainer mirror at the exact tag.

  4. The mirror contains exactly the expected package asset zudotext-mcp-v<VERSION>.tgz (apart from GitHub-generated source archives).

  5. The repository remains clean on main.

Report the npm package/version, integrity, tag SHA, workflow URL/result, mirror release URL/asset, and installed version. A credentialed live-workspace verification is a separate post-release lane; never call missing credentials a package-release failure.

Failure recovery

  • Before npm or tag publication: leave or repair the release PR/branch; no immutable release exists.

  • NPM_TOKEN is missing or rejected (E401/E403/E404 on npm publish): the tag's run fails before any GitHub Release. The tagged workflow cannot be repaired in place, so after the owner fixes the secret, rerun that run only if the fix was secret-side; otherwise fix forward with a higher version.

  • Workflow failure after tag push: retain the tag and diagnose the exact run. If tagged contents or tagged workflow source need a change, fix forward with a higher version. If the failure is transient infrastructure and the exact tag still points to the intended immutable SHA, rerun that workflow attempt only after proving there is no conflicting release or asset. Never move, delete, or recreate the tag.

  • Workflow success but install smoke failure: preserve the release as evidence, file a blocking issue, and prepare a higher patch version.

  • Timeout or ambiguous state: inspect the tag, release, and exact-SHA workflow before retrying any mutation.

The package's canonical implementation details remain in packages/zudotext-mcp/RELEASING.md; follow that document if it becomes stricter than this orchestration skill.