Processus de release Pastura

VérifiéPrudence

Gère la release de Pastura : version, notes TestFlight/App Store, validation et exécution du script de release.

Spar Skills Guide Bot
DevOpsAvancé
06/08/2026
Claude Code
#release-management#ios#testflight#fastlane#app-store-connect

Recommandé pour

Synthèse automatique

Pilote une livraison TestFlight de Pastura en proposant le numéro de version, en rédigeant les notes de version et en encadrant l’archivage, l’envoi et le tag via scripts/release.sh.

Points forts

  • Impose une confirmation explicite avant l’envoi irréversible vers App Store Connect.
  • Propose le numéro de version à partir des commits depuis le dernier tag et le fait valider par l’opérateur.
  • Sépare les décisions humaines du script reproductible release.sh pour l’archivage, l’export, l’envoi et le tag.
  • Documente les prérequis de signature, de clé API ASC et d’installation fastlane avant la première livraison.

Limites

  • Très spécifique au dépôt Pastura : scripts/release.sh, ADR-014, fastlane/.env et équipe Apple donnée.
  • Suppose que l’amorçage manuel de l’App Store Connect, du compte Xcode et de bundle install est déjà effectué.
  • Ne réalise pas les modifications de code nécessaires à la version, qui doivent passer par une PR /orchestrate séparée.
Quand l'utiliser

À utiliser lorsqu’il faut préparer et publier une version TestFlight ou App Store de Pastura, avec validation du numéro de version et des notes.

Quand l'éviter

À ne pas utiliser pour modifier le code de l’application, créer une branche ou publier une version d’un autre projet.

Analyse de sécurité

Prudence
Score qualité88/100

The skill is a well-scoped release runbook: it drives a deterministic local script to upload a build and push a tag, plus an optional decoupled GitHub Release flow. All irreversible actions (upload, tag push, public publish) sit behind a dry-run and an explicit operator confirmation/draft review, and secret handling is described rather than performed (key kept outside the repo, revocation documented). Risk is therefore driven by the power of the tools (remote writes, credential-adjacent config, remote tag deletion), not by malicious or obfuscated behavior.

Points d'attention
  • •Executes `scripts/release.sh` for real runs, which archives the app, exports an .ipa, uploads to App Store Connect via fastlane, and pushes an annotated git tag to origin — irreversible external/remote-write side effects. Mitigated by a dry-run (Step 4), an explicit mandatory confirmation gate (Step 5), and the script not being in the permission allowlist.
  • •Publishes public GitHub Releases (`gh release create ... --draft` then `gh release edit --draft=false`), which notifies watchers and is indexed; gated by a draft-review pause, which is reasonable.
  • •Documents destructive recovery commands (`git push origin :refs/tags/...`, `git tag -d`, `gh release delete --yes`, `--cleanup-tag` deliberately omitted) — scoped and intentional, but they are remote-ref deletions a human could misapply.
  • •Handles credential material conceptually: App Store Connect `.p8` key referenced via `fastlane/.env` (gitignored, outside repo), with instructions not to export in shell rc and a revocation procedure. No secret values are embedded and nothing is exfiltrated; this is good hygiene rather than a risk.
  • •Uses Bash/Write/Agent broadly but for legitimate release engineering (git log, jq over gallery JSON, greps over preset YAML, mktemp notes files). No curl|sh, no base64 payloads, no safety-disabling, no attempts to redirect the auditor.
  • •Invokes repo-local `scripts/release.sh` (archive, export, fastlane upload to App Store Connect, and pushing an annotated git tag) whose actual contents are not included in the skill, so the safety of the underlying mechanism cannot be verified from this text alone.
  • •Performs irreversible external actions (TestFlight upload, remote tag push, `gh release create/edit --draft=false`) — these are gated behind an explicit mandatory confirmation step and a `--dry-run` preflight, which mitigates but does not eliminate the risk.
  • •Recovery section documents destructive remote commands (`git push origin :refs/tags/...`, `git tag -d`, `gh release delete`) that a wrong diagnosis could misapply; the skill does bound them to specific failure states and warns against `--cleanup-tag`.
  • •Reads App Store Connect credentials from `fastlane/.env` and `~/.appstoreconnect/private_keys/`; the skill handles this responsibly (gitignored, outside repo, revocation procedure, `*.p8` ignore + precommit gate) and never instructs sending credentials anywhere.
  • •Uses the Agent tool to spawn a 'Fable subagent' for copywriting; correctly requires explicit operator approval before spawning.
  • •No prompt-injection or role-manipulation attempts were present in the skill body.
Comment cette analyse est faite

Exemples

Cut a release
Cut a Pastura release: inspect commits since the last tag, propose the version bump, draft the TestFlight release notes, and wait for my confirmation before running the release script.
Draft release notes
Prepare the release notes for the next Pastura TestFlight build based on the changes since the last release tag.
Upload a specific version
Run the Pastura release pipeline for version 1.5, including the gated archive and TestFlight upload, after I confirm.

name: release description: Cut a Pastura release — version bump, TestFlight and App Store release notes, then a gated scripts/release.sh archive/upload/tag. Use when asked to cut or ship a release, upload a build to TestFlight, or run the release pipeline. allowed-tools: Read, Grep, Glob, Bash, Write, Agent, AskUserQuestion argument-hint: "[X.Y]"

/release

Drive one TestFlight release of Pastura. This skill is the interactive judgment layer over the deterministic mechanism in scripts/release.sh (ADR-014). The script owns preflight → archive → symbol check → export → upload → tag; this skill owns the human decisions around it: the version bump, the release notes, and the mandatory confirmation before the irreversible upload.

Not an /orchestrate task. /release drives an external release (App Store Connect), not repo file edits. It does not create branches or commit tracked files. The one push it triggers — the annotated release tag, inside scripts/release.sh — is a deliberate, benign exception to the "/orchestrate is the only entry point for pushes" rule (see CLAUDE.md § Development Workflow): a tag ref is not branch-protected, touches no tracked files, and is gated behind the confirmation below. Any code change a release needs (a version bump) is a separate /orchestrate PR — see Step 2.

Run from the repository root.

One-time bootstrap (must be done before the first release)

These are human-only, performed once (ADR-014 § bootstrap). The full step-by-step walkthrough is docs/release-setup.md; verify the checklist below holds before starting:

  • App Store Connect app record exists for app.pastura.Pastura.
  • An ASC API key (.p8) is generated and stored outside the repo (fastlane reads ~/.appstoreconnect/private_keys/). Its identifiers live in fastlane/.env (gitignored, project-scoped — fastlane auto-loads it via dotenv; do NOT export them in ~/.zshrc): ASC_KEY_ID, ASC_ISSUER_ID, ASC_KEY_PATH. Copy from fastlane/.env.example.
  • An Apple ID signed into Xcode whose account can sign for distribution (automatic signing, team 52G26234A3). Distribution signing is cloud-managed — no local distribution cert is needed; release.sh passes -allowProvisioningUpdates to resolve the App Store profile + cloud cert via that session.
  • bundle install has been run once so Gemfile.lock pins fastlane.

Confirm with the operator that these hold before continuing. The encryption export-compliance declaration is already in place (INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO, ADR-005 §8.6) — no action needed.

Step 1 — Decide the version

Read the commits since the last release tag and propose a version bump:

LAST_TAG="$(git describe --tags --abbrev=0 2>/dev/null || echo '(none)')"
git log --pretty='- %s' "${LAST_TAG}..HEAD" 2>/dev/null || git log --pretty='- %s' -n 20

Propose major / minor from the change content (breaking → major, anything else → minor) and ask the operator to confirm the target X.Y. If $ARGUMENTS already carries a version, treat it as the proposal and still confirm. The Steps 4 and 6 commands run in later, separate Bash tool calls that inherit no shell state from here, so every value they carry must be substituted concretely — never left as a shell variable that would expand empty in the later call. This covers the version and the --notes-file path (produced and echoed in Step 3): write the confirmed X.Y, and substitute Step 3's echoed path, in place of the X.Y and /REPLACE-WITH-NOTES-PATH placeholders those commands show. Both placeholders are values release.sh rejects when left unsubstituted — X.Y fails the version validator (it does not start with a digit), and /REPLACE-WITH-NOTES-PATH fails the --notes-file existence check — so an unsubstituted value dies fast — the version at argument validation, and (once the version is substituted) the path at the Step 4 dry-run — instead of binding a plausible wrong value and surfacing it only after the archive, past the Step 5 gate.

Two components is the shape (ADR-014 § Decision, item 4). Pastura ships 1.0, 1.1, … so a fixes-only release is still a minor bump (1.1 → 1.2), not a third component. Reserve X.Y.Z for a hotfix on a version already published to the App Store: release.sh accepts either shape, but a normal release never carries a third component.

Step 2 — Ensure the version is on a green main (sequencing)

scripts/release.sh releases only from a checkout that equals origin/main and is CI-green, and it asserts the archived MARKETING_VERSION equals --version. So the target version must already be the MARKETING_VERSION on main.

  • If the chosen version already matches main's MARKETING_VERSION (a re-release or notes/build-only change): proceed to Step 3.
  • If the version needs to change: it is a code edit — bump it in a separate /orchestrate PR, merge it, and wait for main CI to go green, then return here. Bump only the app target's two MARKETING_VERSION entries (Debug + Release, the ones near PRODUCT_BUNDLE_IDENTIFIER = app.pastura.Pastura) — not the PasturaTests / PasturaUITests entries. The build number (git rev-list --count HEAD) advances automatically with the bump commit, so the release.sh build-number guard is satisfied for free.

Do not try to bump and release in one local step — a local bump commit would make HEAD diverge from origin/main and fail preflight.

Step 3 — Synthesize and review the release notes

Turn the commit subjects (Step 1) into concise tester-facing "What to Test" prose. These notes are published to TestFlight testers, so:

  • Keep only tester-facing changes — new features and user-visible fixes. Drop internal-only commits entirely: refactors, chores, docs, tests, CI, tooling. A build of only internal work gets a single "internal improvements" line, not a padded list.
  • Drop all PR/issue numbers, SHAs, and emoji prefixes — those live in git history / a GitHub Release, not tester notes.
  • Write plainly — no marketing adjectives, no effusive openers / closers, no AI-tell rhythms (rule-of-three triads, em-dash pile-ups). State what changed and what to check, like a short developer note to a peer.

Three cuts before writing

Apply in order. Each carries a mechanical check — run it; do not reason from the commit log alone. Every cut below exists because a plausible-sounding claim failed its check.

Cut 1 — by what the update delivers, not by where the file lives. The question is "can the user do something now that they could not before?", not "is the file in the app bundle". Gallery scenarios (docs/gallery/) are fetched at runtime by URLSessionGalleryService, so any that already ran on the previous version reached users without this update — leave them out.

The exception is gallery content the previous version gated (ADR-020 EngineSchemaVersion.isCompatible: D2 rejects an unknown phase kind, D3 rejects min_engine_version > current). That does arrive with the update, so name the scenarios. Compute the set — never assume it is non-empty:

LAST_TAG="$(git describe --tags --abbrev=0)"; [ -n "$LAST_TAG" ] || exit 1
OLD="$(git show "$LAST_TAG":Pastura/Pastura/Models/PhaseType.swift)"
jq -r '[.. |objects|select(has("phases")).phases[]]|unique[]' docs/gallery/gallery.json |
  while read -r p; do
    printf '%s' "$OLD" | grep -qE "\"${p}\"|case ${p}$" || echo "D2 gated: $p"
  done
jq '[.. |objects|select(has("min_engine_version")).min_engine_version]' docs/gallery/gallery.json

Both details are load-bearing and both fail silently toward "nothing gated": re-derive LAST_TAG here (Bash calls share no shell state, and an empty one makes git show :path read the index and exit 0), and match raw values, not case identifiers (case speakAll = "speak_all").

No D2 gated: line and an empty array ⇒ nothing was gated ⇒ write no unlock line at all; a raised ENGINE_SCHEMA_VERSION alone gates nothing. When one is earned, name the scenarios, keep mechanism words out, and echo what the app showed: 「このシナリオの実行にはより新しいバージョンの Pastura が必要です。アプリを更新してください。」

Cut 2 — advertise only capabilities a shipped scenario exercises. A new engine capability no bundled preset uses is an authoring feature; a player cannot encounter it, so listing it as a headline feature promises nothing. Substitute a real key before reading the result — an unsubstituted run returns zero hits, i.e. the suppressing answer:

CAP='secret:'   # ← replace per capability; a placeholder yields a false "not shipped"
grep -l "$CAP" Pastura/Pastura/Resources/Presets/*.yaml

No hits ⇒ it belongs on an editor/author line, or nowhere.

Cut 3 — by likelihood of encounter. Itemize fixes a tester could plausibly hit or should re-check; fold the rest — unusual configuration, malformed input, internal-consistency repairs — into a single "other minor fixes" line.

Use the app's own wording. Feature and phase names must match the ja values in Localizable.xcstrings, not internal identifiers: whisper is 密談, narrate is 実況. "ラン" is developer vocabulary — the UI says 実行 / シミュレーション.

Two surfaces, two texts

--notes-file reaches TestFlight only (see the --notes-file paragraph below). The App Store "What's New" is a separate App Store Connect field, entered by hand per locale — Pastura ships ja + en-US — in App Store Connect when the build is submitted. No step of this skill performs that submission; the text is signed off at the Step 5 gate below, and release.sh never touches it. Write both from one shared body: TestFlight adds internal-behaviour detail and a "確認してほしいこと" list covering every new feature group; the App Store text drops both, since to a general user they read as instructions, or as defect reports. Both texts go to the Step 5 gate — the App Store one is the copy that reaches the public.

The first build is the exception: with no prior release to diff, write a brief app intro + what to test rather than a changelog.

The operator must review the final notes at the gate (Step 5) — they go to humans and are not content-safety-screened. Never ship raw commit subjects unreviewed (a subject can carry a token, internal URL, or unpolished text).

Write the finalized notes to a temp file so release.sh ships them verbatim as the TestFlight changelog:

NOTES_FILE="$(mktemp -t pastura-release-notes)"
cat > "$NOTES_FILE" <<'NOTES'
<the reviewed tester-facing prose from above>
NOTES
echo "$NOTES_FILE"   # ← the concrete path; substitute it into Steps 4 and 6

Binding and reading $NOTES_FILE within this single tool call is fine — the no-shell-state rule (Step 1) is about later, separate calls, so the path must be carried into Steps 4 and 6 by substituting the echoed value, not by reusing the variable.

Pass --notes-file with the echoed path to release.sh in Steps 4 and 6 — substitute that concrete path in place of the /REPLACE-WITH-NOTES-PATH placeholder those commands show (per Step 1). Without --notes-file, the script falls back to raw commit subjects (build_notes) — exactly what this step exists to prevent — so always pass the file once notes are prepared. A given --notes-file path that is missing or points to an empty file is a hard error, so that fallback never fires silently once a real path is passed. The one gap it does not cover is an empty path string: --notes-file "" reads to release.sh as "flag never passed" and takes the silent fallback — which is exactly why Steps 4/6 carry a guaranteed-nonexistent literal placeholder, not a bare $NOTES_FILE that would expand empty in those later calls.

Step 4 — Dry-run the preflight

scripts/release.sh --version X.Y --notes-file /REPLACE-WITH-NOTES-PATH --dry-run

This runs the full preflight (HEAD == origin/main, every required check green — the required list is derived from the branch ruleset) and prints the planned version / build / tag plus a "What to Test" preview — with --notes-file that preview is your reviewed prose, so a missing/empty notes file fails here (fail-fast) rather than mid-upload, and the Step 5 gate reviews the exact text that will ship. It then stops before any archive or upload. Resolve any preflight failure (usually: main not green yet, or HEAD not synced) before continuing. scripts/release.sh is not in the permission allowlist, so the first invocation prompts for approval — that prompt is itself a safety gate for an irreversible action.

Step 5 — Confirmation gate (MANDATORY)

Before the real run, present to the operator and get explicit approval:

  • target version and computed build number and tag
  • the final "What to Test" notes (Step 3) for sign-off
  • the final App Store "What's New" text, per locale (Step 3), if this version is headed for submission — it is the only public-facing copy the skill produces, and no later step gates it
  • confirmation that the one-time bootstrap holds (env vars set, key in place)

Only on explicit "yes" proceed. This is the last reversible point — the upload that follows cannot be undone.

Step 6 — Release

scripts/release.sh --version X.Y --notes-file /REPLACE-WITH-NOTES-PATH

The script archives, re-checks the ADR-005 §8.5 Ollama-symbol guard on the signed binary, exports an app-store .ipa, uploads via fastlane (waiting for ASC processing), and — only on a successful upload — creates and pushes the annotated tag v<version>+<build>. Report the result and that the build is processing on TestFlight.

Step 7 — Promote to a public GitHub Release (at App Store publish)

Optional and decoupled — NOT part of the per-build flow above. Steps 1–6 cut one TestFlight build and tag it; this step is run separately, by hand, and only when a version actually ships publicly. Do not wire it into scripts/release.sh — most TestFlight builds never go public, so a Release per build would be pre-release clutter.

Exercised twice — v1.0+522 and v1.1+671. ADR-014's scope still covers TestFlight upload only, so nothing here is automated. Read v1.1+671 as the reference shape; v1.0+522 predates this spec (its own sections, no ## Features / ## Fixes) and is voice reference only.

Trigger: a build has been approved and released on the App Store (an App Store Connect–side event this repo does not observe). Each /release run already tagged its build v<version>+<build>; this step attaches a public GitHub Release to the tag of the build that went live — titled Pastura <version> (the public marketing version, no build suffix), marked --latest, never a pre-release.

What the body is

A curated, user-facing highlights document — not a changelog. The --generate-notes PR list is material the author reads, never text that gets published: for 1.1 it ran to 149 lines of commit subjects, which no one reads. Nothing of it survives into the body except the facts you rewrite by hand; the ## What's Changed list is not kept at all, because the **Full Changelog** compare link already reaches every PR.

Its base is the previous public release: because public releases are the only GitHub Releases in this design, gh release list returns them directly, so "previous GitHub Release" == "previous public release" automatically even though many TestFlight tags sit in between. Pass --exclude-drafts so a leftover draft from an aborted run (below) cannot become the base.

Body structure

In this order. Omit a section that has no qualifying items — a fixes-only release carries no ## Features, and vice versa.

  1. Opening line, italic. One or two sentences, written fresh for this release (see below).
  2. This is the X.Y release of Pastura, <one clause placing it>. followed by a short factual summary paragraph naming the two or three things the release is actually about. For a hotfix X.Y.Z, say what it fixes instead of placing it in the sequence.
  3. ## Features
  4. ## Fixes
  5. **Full Changelog**: https://github.com/<owner>/<repo>/compare/<PREV>...<TAG>
  6. ## Get it — fixed boilerplate, unchanged every release (the App Store URL is the one in README.md):
    - Download on the App Store: https://apps.apple.com/app/pastura-local-llms-simulator/id6788409688
    - Product story, design, and FAQ: https://pastura.app
    - Source and docs: this repository's [README.md](./README.md).
    
  7. Closing line, italic. Written fresh, same as the opener.

Bullet format inside a section:

- **Bold lead:** One or two factual sentences. (#1070, #1078, #1081)

The lead differs by section. In ## Features it is a noun phrase naming the thing itself — the phase, the field, the screen — followed by a colon, not a headline written about it. In ## Fixes it is the symptom instead, stated as a clause that ends its own sentence rather than taking a colon: what broke is what a reader recognises. The v1.1 body is the worked example of both.

Order bullets by impact within the section: what a user touches first, then correctness, then the rest. Fold every low-impact item into a single trailing - **Smaller fixes:** bullet carrying their numbers, rather than giving each its own line.

What goes in

Only what reached users. Work merged but not wired into the shipping app — an in-progress port, an evaluated-but-unshipped backend spike — is invisible to every reader of this page and is omitted entirely, along with docs, chore, CI and dependency commits. This is Step 3's Cut 1 (judge by what the update delivers, not by where the file lives) applied to this surface.

Inheritance from Step 3 is partial — name it exactly:

| Step 3 rule | Applies here? | |---|---| | Write plainly (no marketing adjectives, no effusive openers/closers, no AI-tell rhythms) | Yes — and it is the rule most easily lost. The sole exception is the two authored lines below. | | Cut 1 — by what the update delivers | Yes, as above. | | Cut 3 — fold by likelihood of encounter | Yes — it is what the trailing "Smaller fixes" bullet implements. | | Drop all PR/issue numbers | No. That rule exists because tester notes are not a changelog; here the numbers are the point. |

Verify a claim before writing it, the same as Step 3's cuts: a bullet paraphrasing a commit subject is a claim about behaviour, and a subject can be shorthand for something narrower.

The two authored lines

They carry the release's voice; the body between them is deliberately flat. Both are written fresh each release — no line is reused, including 1.0's tagline, which belongs to 1.0. Set both in italics so they read as distinct from the factual body.

Because they matter out of proportion to their length, offer to delegate them to a Fable subagent — the operator's global rules require explicit approval before any Fable spawn, so it is an ask, never a default. If the operator declines, draft them in-session and say so at the draft review so they can be rewritten. Give the subagent the finished body plus the previous releases' opening and closing lines as voice reference, and withhold your own candidates so its output stays independent. Ask for several options of each rather than one.

Recipe — draft, review, publish

The draft is the review pause. A public Release notifies watchers and is indexed, so it inherits this skill's confirmation-gate discipline (Step 5): the operator reviews the rendered draft — links and emphasis included — and only then is it published.

The three blocks below are separate Bash calls — the Write tool sits between 1 and 2, the operator's review between 2 and 3 — so substitute the tag, title and body path concretely in each, exactly as Step 1 requires of Steps 4/6. gh api expands {owner}/{repo} itself, so no repo variable is needed. The literal /REPLACE-WITH-BODY-PATH fails --notes-file's existence check rather than binding an empty value.

# 1. Material only. Read-only — creates nothing, so there is no throwaway
#    draft to clean up if you stop here.
PREV=$(gh release list --exclude-drafts --limit 1 --json tagName -q '.[0].tagName')
gh api -X POST "repos/{owner}/{repo}/releases/generate-notes" \
  -f tag_name="v<version>+<build>" -f previous_tag_name="$PREV" --jq '.body'
# 2. Write the body per the structure above with the Write tool, to a path
#    OUTSIDE the checkout ($TMPDIR / `mktemp -t pastura-release-body`) — this
#    step runs on a tree that equals origin/main, where a stray file can be
#    swept into an unrelated commit. Then create the DRAFT from it. gh
#    resolves a draft by tag for later view/edit even though its URL shows
#    `untagged-…` (confirmed on the 1.1 run).
gh release create "v<version>+<build>" --title "Pastura <version>" \
  --latest --draft --notes-file /REPLACE-WITH-BODY-PATH
# 3. Operator reviews the rendered draft in the GitHub UI. Only then:
gh release edit "v<version>+<build>" --latest --draft=false

Confirm the publish landed with gh release list --exclude-drafts --limit 1 --json tagName,isLatest — isLatest exists there but not on gh release view, which fails with Unknown JSON field.

(Step 3 keeps its shorter notes file in an inline heredoc; this body is long and multi-section, which is what CLAUDE.md § Git Conventions routes to a file written with the Write tool.)

PREV is non-empty from 1.1 onward, so previous_tag_name always has a base; 1.0 was hand-written with no prior release and is not a case that recurs.

Aborted run: if the flow dies between create and publish, a draft Release lingers (and gh release list without --exclude-drafts would see it). Delete it before re-running: gh release delete "$TAG" --yes (no --cleanup-tag — the git tag from release.sh must survive).

Failure → recovery

Map the failure point to the recovery — the build number is commit-derived, so the right move differs by where it failed:

| Failure point | State | Recovery | |---|---|---| | preflight / archive / export / upload before ASC ingest | nothing ingested, no tag (tag is last) | fix the cause and re-run /release — the build number is unchanged and that is fine | | upload fails after ASC has ingested the build | the build number now collides with an ingested build; a naive re-run is correctly blocked by release.sh's strict-exceeds guard | land a new commit on main (a no-op commit or a MARKETING_VERSION bump) via /orchestrate, wait for green, then re-/release. This is a new green-main cycle, not an in-place retry — the build number must advance | | tag pushed but the release must be retracted | tag exists locally + remotely | git tag -d v<version>+<build> and git push origin :refs/tags/v<version>+<build> | | public GitHub Release (Step 7) published then must be retracted | Release is public; git tag is fine | gh release delete v<version>+<build> --yes (no --cleanup-tag — keep the tag). Re-cutting can re-promote it |

ASC API key revocation (leak response)

If the .p8 API key is ever exposed (committed, shared, lost): revoke it immediately in App Store Connect → Users and Access → Integrations → App Store Connect API → (select the key) → Revoke, then generate a fresh key and update ASC_KEY_ID / ASC_ISSUER_ID / ASC_KEY_PATH. The scripts/p8-precommit-gate.sh gate and the *.p8 gitignore are the preventative layers (ADR-014 § Secrets); revocation is the response.

Du fichier au premier essai

Le téléchargement contient exactement le contenu affiché sur cette fiche. Cette copie peut différer de la dernière version du dépôt source.

Consulter la source et ses fichiers annexes

Ce téléchargement contient uniquement SKILL.md. Les scripts, références, modèles et dépendances éventuels ne sont pas inclus. Récupérez les fichiers nécessaires depuis la source en conservant leur arborescence avant de poursuivre.

1. Télécharger le fichier

Télécharger SKILL.md

Depuis la racine d’un projet de test, enregistrez le fichier sous .skill-downloads/pastura-release-process-msh3us1h/SKILL.md, ou utilisez la commande suivante. Ce dossier sert à examiner la skill avant son installation.

Commande pour macOS/Linux ou WSL : un shell POSIX et curl sont nécessaires. Sous Windows sans WSL, utilisez le bouton de téléchargement et créez le dossier manuellement.

mkdir -p '.skill-downloads/pastura-release-process-msh3us1h' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/pastura-release-process-msh3us1h/download' --output '.skill-downloads/pastura-release-process-msh3us1h/SKILL.md.part' && mv '.skill-downloads/pastura-release-process-msh3us1h/SKILL.md.part' '.skill-downloads/pastura-release-process-msh3us1h/SKILL.md'

2. Vérifier les prérequis

Lisez SKILL.md avant de l’utiliser. Si le fichier cite des scripts ou services externes, examinez-les et préparez les accès nécessaires dans votre environnement de test.

Outils déclarés par l’auteur (à vérifier dans votre agent) : Read, Grep, Glob, Bash, Write, Agent, AskUserQuestion

Aucune section de prérequis reconnue dans ce fichier. Cela ne signifie pas qu’il est autonome : les bibliothèques, outils et accès peuvent être cités ailleurs dans le contenu ou dans le dépôt source.

Les plateformes de la fiche sont des indications du catalogue. Les chemins ci-dessous suivent la documentation des outils ; ils ne prouvent pas que cette skill y a été exécutée. Aucune version minimale de ces outils n’est attestée pour cette fiche.

3. Charger la skill

Après vérification, copiez le dossier complet dans le projet avec l’une des commandes ci-dessous, puis ouvrez une nouvelle session de l’outil. La commande s’arrête si un dossier du même nom existe déjà : comparez les fichiers avant de le remplacer.

Claude Code
test -f '.skill-downloads/pastura-release-process-msh3us1h/SKILL.md' && test -s '.skill-downloads/pastura-release-process-msh3us1h/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/release' && cp -R '.skill-downloads/pastura-release-process-msh3us1h' '.claude/skills/release'

OpenSkills

OpenSkills doit déjà être installé. La procédure locale install/read est contrôlée avec OpenSkills 1.5.0, qui exige Node.js ≥ 20.6.0. Aucun slug du catalogue n’est résolu automatiquement.

Installation officielle d’OpenSkills
openskills install './.skill-downloads/pastura-release-process-msh3us1h'

openskills read 'pastura-release-process-msh3us1h'

La lecture doit afficher le contenu du fichier installé et son dossier de base. Elle ne lance ni la skill ni ses dépendances.

Pour un agent qui lit AGENTS.md, synchronisez ensuite l’index. Cette commande modifie AGENTS.md : relisez le diff avant de l’utiliser.

openskills sync

Mode manuel ou autre outil : joignez SKILL.md à une conversation, ou ouvrez-le dans un agent capable de lire les fichiers. Ajoutez les ressources annexes nécessaires. Il n’existe pas de dossier universel reconnu par tous les outils.

4. Faire un premier essai

Utilisez une entrée courte et fictive : un endpoint d’API, un petit document ou un brief d’interface. Dans une nouvelle conversation, joignez le fichier ou donnez son chemin à l’agent, puis adaptez cette demande :

Lis .skill-downloads/pastura-release-process-msh3us1h/SKILL.md et applique ses instructions à cet exemple : [décrire une entrée de test]. Indique les fichiers, dépendances ou accès qui manquent. Produis le résultat demandé par la skill sans inventer de données ni exécuter de script non examiné.

Résultat attendu : une sortie correspondant aux instructions de la skill, ou une liste précise des prérequis manquants. Une simple confirmation de lecture ne valide pas le premier usage. Si une ressource externe est indisponible, ce parcours reste à tester.

Skills similaires