Release Orchestrator
End-to-end release procedure for the shared-version @haklex/* package family. This skill supersedes .claude/commands/release.md.
Operating Contract
| Rule |
Requirement |
| Autonomy |
Infer release metadata from repository state. Do not ask for package lists, semver level, downstream branch, or confirmation unless a stop condition is reached. |
| Versioning |
All @haklex/* packages share one version, read from packages/rich-editor/package.json. |
| Default mode |
Use incremental unless invocation text contains full, 全量, or standalone all, or unless semver classification reaches major. |
| Publish set |
In incremental, publish the tri-directional closure of changed packages, not merely CHANGED_PKGS. |
| Peer safety |
Treat duplicate runtime copies of lexical, React, lucide-react, shiki, and @lexical/* as release-blocking defects. |
| Downstream |
Update downstream default branches directly after validation. Do not open PRs unless direct push is blocked and the user confirms the fallback. |
| Destructive actions |
Do not discard, reset, restore, force-remove, or silently overwrite user-owned changes. Preserve state and ask before destructive recovery. |
Required Reading Order
Read the relevant reference files before acting. If performing a full release, read all of them.
| Stage |
Reference |
| Repository and downstream layout |
references/repo-layout.md |
| Release mode, change detection, semver, peer audit |
references/release-analysis.md |
| Publish-set closure, build, publish, registry polling, CLI smoke |
references/publish-pipeline.md |
| GitHub release, downstream propagation, third-party pin reconciliation, smoke tests |
references/downstream-propagation.md |
| Stop conditions, safe recovery, common mistakes, real-world anchors |
references/failure-recovery-and-anchors.md |
Execution Flow
flowchart TD
A[Clean haklex worktree] --> B[Find last release]
B --> C[Detect mode and changed packages]
C --> D{No releasable trigger?}
D -->|Yes| Z[Stop: report no package diff]
D -->|No| E[Classify shared semver bump]
E --> F{Major bump?}
F -->|Yes| G[Switch to full mode]
F -->|No| H[Keep selected mode]
G --> I[Peer dependency audit]
H --> I
I --> J[Compute publish set]
J --> K[Bump and build all packages]
K --> L[Publish selected set in topo order]
L --> M[Registry poll and CLI smoke]
M --> N[Commit, tag, push haklex]
N --> O[Publish GitHub release]
O --> P[Update downstream worktrees]
P --> Q[Install, dedup gate, typecheck, build, smoke]
Q --> R{All downstream green?}
R -->|Yes| S[Push downstream default branches]
R -->|No| T[Stop with preserved failure state]
Helper Scripts
Scripts are advisory automation for repeatable checks. They do not replace judgment, and they do not edit files destructively.
| Script |
Purpose |
| scripts/release-context.sh |
Derive LAST, local version, source changes, peer-drift triggers, catch-up triggers, and CHANGED_PKGS. |
| scripts/peer-audit.sh |
Detect always-peer libraries under dependencies, internal @haklex/* peer pins using workspace:*, and divergent third-party peer floors. |
| scripts/publish-set.sh |
Compute PUBLISH_SET for full or tri-directional incremental mode. |
| scripts/registry-peer-floors.sh |
Aggregate non-@haklex/* peer floors from published registry manifests. |
| scripts/downstream-dispatch.sh |
Emit downstream manifest rewrite rows for @haklex/* pins and third-party peer-floor reconciliation. |
| scripts/duplicate-runtime-invariant.sh |
Assert a single resolved version for runtime-anchored libraries in a downstream worktree. |
Phase Index
| Phase |
Action |
Primary Reference |
| 0.5 |
Detect incremental vs full mode |
release-analysis.md |
| 1 |
Pre-flight and releasable trigger detection |
release-analysis.md |
| 2 |
Shared semver classification |
release-analysis.md |
| 3 |
Peer dependency audit |
release-analysis.md |
| 4 |
Build, publish-set closure, topological publish, registry polling |
publish-pipeline.md |
| 4.5 |
@haklex/rich-litexml-cli binary smoke |
publish-pipeline.md |
| 5 |
Commit, tag, and push haklex release commit |
publish-pipeline.md |
| 5.5 |
Publish GitHub release |
downstream-propagation.md |
| 6 |
Downstream worktrees, pin rewrites, peer-floor reconciliation |
downstream-propagation.md |
| 7 |
Downstream smoke tests and duplicate-runtime invariant |
downstream-propagation.md |
| 8 |
Failure handling or direct downstream push |
failure-recovery-and-anchors.md |
| 9 |
Final summary |
failure-recovery-and-anchors.md |
Non-Negotiable Checks
| Check |
Command / Script |
| Last release SHA |
git log --grep='^release: v' -n1 --format=%H |
| Context detection |
./.claude/skills/release-orchestrator/scripts/release-context.sh |
| Peer audit |
./.claude/skills/release-orchestrator/scripts/peer-audit.sh "$LAST" |
| Publish set |
./.claude/skills/release-orchestrator/scripts/publish-set.sh "$MODE" "$LAST" $CHANGED_PKGS |
| Bump |
pnpm bumpp -r <patch|minor|major> --no-git --no-tag |
| Build |
pnpm run build:packages |
| Publish one package |
pnpm --filter @haklex/<pkg> publish --no-git-checks |
| Registry poll |
until npm view @haklex/<pkg>@$NEW_VERSION version; do sleep 5; done |
| CLI smoke |
npx --yes -p @haklex/rich-litexml-cli@$CLI_VER litexml '<p>x</p>' --format json --compact |
| GitHub release |
gh release create "v$NEW_VERSION" --title "v$NEW_VERSION" --notes-file "$NOTE" --verify-tag |
| Duplicate-runtime gate |
./.claude/skills/release-orchestrator/scripts/duplicate-runtime-invariant.sh |
Stop Conditions
- Haklex worktree is dirty before release mutation.
MODE=incremental but CHANGED_PKGS is empty.
- No
src/** change, no non-@haklex/* peer-range advance, and no registry catch-up trigger.
gh is missing or unauthenticated before Phase 5.5.
- Any package remains unavailable from npm after the registry-poll window.
- Phase 3 detects internal
@haklex/* peerDependencies using workspace:*.
- Phase 3 detects divergent third-party peer floors across sibling packages.
- Downstream default branch cannot be derived from
origin/HEAD.
- Downstream rebase conflicts or direct push is rejected.
- Duplicate-runtime invariant reports more than one resolved version for any runtime-anchored library.
- Any recovery path would discard, overwrite, reset, restore, or force-delete user-owned changes.
1---2name: release-orchestrator3description: Use when releasing @haklex/* packages or propagating published haklex versions into Yohaku, mx-core, mx-space, or related downstream consumers.4---56# Release Orchestrator78End-to-end release procedure for the shared-version `@haklex/*` package family. This skill supersedes `.claude/commands/release.md`.910## Operating Contract1112| Rule | Requirement |13| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |14| Autonomy | Infer release metadata from repository state. Do not ask for package lists, semver level, downstream branch, or confirmation unless a stop condition is reached. |15| Versioning | All `@haklex/*` packages share one version, read from `packages/rich-editor/package.json`. |16| Default mode | Use `incremental` unless invocation text contains `full`, `全量`, or standalone `all`, or unless semver classification reaches `major`. |17| Publish set | In `incremental`, publish the tri-directional closure of changed packages, not merely `CHANGED_PKGS`. |18| Peer safety | Treat duplicate runtime copies of `lexical`, React, `lucide-react`, `shiki`, and `@lexical/*` as release-blocking defects. |19| Downstream | Update downstream default branches directly after validation. Do not open PRs unless direct push is blocked and the user confirms the fallback. |20| Destructive actions | Do not discard, reset, restore, force-remove, or silently overwrite user-owned changes. Preserve state and ask before destructive recovery. |2122## Required Reading Order2324Read the relevant reference files before acting. If performing a full release, read all of them.2526| Stage | Reference |27| ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |28| Repository and downstream layout | [references/repo-layout.md](references/repo-layout.md) |29| Release mode, change detection, semver, peer audit | [references/release-analysis.md](references/release-analysis.md) |30| Publish-set closure, build, publish, registry polling, CLI smoke | [references/publish-pipeline.md](references/publish-pipeline.md) |31| GitHub release, downstream propagation, third-party pin reconciliation, smoke tests | [references/downstream-propagation.md](references/downstream-propagation.md) |32| Stop conditions, safe recovery, common mistakes, real-world anchors | [references/failure-recovery-and-anchors.md](references/failure-recovery-and-anchors.md) |3334## Execution Flow3536```mermaid37flowchart TD38 A[Clean haklex worktree] --> B[Find last release]39 B --> C[Detect mode and changed packages]40 C --> D{No releasable trigger?}41 D -->|Yes| Z[Stop: report no package diff]42 D -->|No| E[Classify shared semver bump]43 E --> F{Major bump?}44 F -->|Yes| G[Switch to full mode]45 F -->|No| H[Keep selected mode]46 G --> I[Peer dependency audit]47 H --> I48 I --> J[Compute publish set]49 J --> K[Bump and build all packages]50 K --> L[Publish selected set in topo order]51 L --> M[Registry poll and CLI smoke]52 M --> N[Commit, tag, push haklex]53 N --> O[Publish GitHub release]54 O --> P[Update downstream worktrees]55 P --> Q[Install, dedup gate, typecheck, build, smoke]56 Q --> R{All downstream green?}57 R -->|Yes| S[Push downstream default branches]58 R -->|No| T[Stop with preserved failure state]59```6061## Helper Scripts6263Scripts are advisory automation for repeatable checks. They do not replace judgment, and they do not edit files destructively.6465| Script | Purpose |66| -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |67| [scripts/release-context.sh](scripts/release-context.sh) | Derive `LAST`, local version, source changes, peer-drift triggers, catch-up triggers, and `CHANGED_PKGS`. |68| [scripts/peer-audit.sh](scripts/peer-audit.sh) | Detect always-peer libraries under `dependencies`, internal `@haklex/*` peer pins using `workspace:*`, and divergent third-party peer floors. |69| [scripts/publish-set.sh](scripts/publish-set.sh) | Compute `PUBLISH_SET` for `full` or tri-directional `incremental` mode. |70| [scripts/registry-peer-floors.sh](scripts/registry-peer-floors.sh) | Aggregate non-`@haklex/*` peer floors from published registry manifests. |71| [scripts/downstream-dispatch.sh](scripts/downstream-dispatch.sh) | Emit downstream manifest rewrite rows for `@haklex/*` pins and third-party peer-floor reconciliation. |72| [scripts/duplicate-runtime-invariant.sh](scripts/duplicate-runtime-invariant.sh) | Assert a single resolved version for runtime-anchored libraries in a downstream worktree. |7374## Phase Index7576| Phase | Action | Primary Reference |77| ----- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- |78| 0.5 | Detect `incremental` vs `full` mode | [release-analysis.md](references/release-analysis.md) |79| 1 | Pre-flight and releasable trigger detection | [release-analysis.md](references/release-analysis.md) |80| 2 | Shared semver classification | [release-analysis.md](references/release-analysis.md) |81| 3 | Peer dependency audit | [release-analysis.md](references/release-analysis.md) |82| 4 | Build, publish-set closure, topological publish, registry polling | [publish-pipeline.md](references/publish-pipeline.md) |83| 4.5 | `@haklex/rich-litexml-cli` binary smoke | [publish-pipeline.md](references/publish-pipeline.md) |84| 5 | Commit, tag, and push haklex release commit | [publish-pipeline.md](references/publish-pipeline.md) |85| 5.5 | Publish GitHub release | [downstream-propagation.md](references/downstream-propagation.md) |86| 6 | Downstream worktrees, pin rewrites, peer-floor reconciliation | [downstream-propagation.md](references/downstream-propagation.md) |87| 7 | Downstream smoke tests and duplicate-runtime invariant | [downstream-propagation.md](references/downstream-propagation.md) |88| 8 | Failure handling or direct downstream push | [failure-recovery-and-anchors.md](references/failure-recovery-and-anchors.md) |89| 9 | Final summary | [failure-recovery-and-anchors.md](references/failure-recovery-and-anchors.md) |9091## Non-Negotiable Checks9293| Check | Command / Script |94| ---------------------- | --------------------------------------------------------------------------------------------- |95| Last release SHA | `git log --grep='^release: v' -n1 --format=%H` |96| Context detection | `./.claude/skills/release-orchestrator/scripts/release-context.sh` |97| Peer audit | `./.claude/skills/release-orchestrator/scripts/peer-audit.sh "$LAST"` |98| Publish set | `./.claude/skills/release-orchestrator/scripts/publish-set.sh "$MODE" "$LAST" $CHANGED_PKGS` |99| Bump | `pnpm bumpp -r <patch\|minor\|major> --no-git --no-tag` |100| Build | `pnpm run build:packages` |101| Publish one package | `pnpm --filter @haklex/<pkg> publish --no-git-checks` |102| Registry poll | `until npm view @haklex/<pkg>@$NEW_VERSION version; do sleep 5; done` |103| CLI smoke | `npx --yes -p @haklex/rich-litexml-cli@$CLI_VER litexml '<p>x</p>' --format json --compact` |104| GitHub release | `gh release create "v$NEW_VERSION" --title "v$NEW_VERSION" --notes-file "$NOTE" --verify-tag` |105| Duplicate-runtime gate | `./.claude/skills/release-orchestrator/scripts/duplicate-runtime-invariant.sh` |106107## Stop Conditions108109- Haklex worktree is dirty before release mutation.110- `MODE=incremental` but `CHANGED_PKGS` is empty.111- No `src/**` change, no non-`@haklex/*` peer-range advance, and no registry catch-up trigger.112- `gh` is missing or unauthenticated before Phase 5.5.113- Any package remains unavailable from npm after the registry-poll window.114- Phase 3 detects internal `@haklex/*` `peerDependencies` using `workspace:*`.115- Phase 3 detects divergent third-party peer floors across sibling packages.116- Downstream default branch cannot be derived from `origin/HEAD`.117- Downstream rebase conflicts or direct push is rejected.118- Duplicate-runtime invariant reports more than one resolved version for any runtime-anchored library.119- Any recovery path would discard, overwrite, reset, restore, or force-delete user-owned changes.