fix(release): harden npm-publish pipeline + document release SOP - #744
Conversation
Three real failure modes observed during the v5.2.5/5.2.6 releases, each
fixed and documented so the next release does not re-discover them.
## npm-publish.yml
### Race: publish_legacy_aiox_core ran in parallel with publish
The legacy compat wrapper `aiox-core@X.Y.Z` declares
`@aiox-squads/core@X.Y.Z` as a runtime dependency. The smoke test step
runs `npx --yes aiox-core@X.Y.Z --version`, which transitively installs
the scoped package. With both jobs in parallel, `npx` raced against npm
CDN propagation of the scoped package and timed out after 90s — making
the entire job appear failed even though the publish step inside it
had already printed "✅ Published aiox-core@X.Y.Z".
Fix: `publish_legacy_aiox_core` now `needs: [test, build, publish]`,
serializing the legacy publish behind the scoped publish.
### Smoke test legacy npx: timeout too short, no diagnostics
Bumped retry budget 6×15s (90s) → 16×15s (240s). Added a second
visibility check for the scoped dependency before invoking `npx` so we
distinguish "compat not visible" from "scoped dep not visible". Captured
last `npx` stderr in the timeout message instead of failing silently.
### Notify: aggregated bool hid which step failed
Replaced with a structured summary that distinguishes hard fail (scoped
publish) from soft warnings (workspace, legacy, smoke). Only the scoped
publish is treated as release-blocking; the rest are informational and
can be republished out-of-band.
## installer-smoke-matrix.yml
### Windows path mangling in node -e via Git Bash
`${{ github.workspace }}` on a Windows runner expands to
`D:\a\aiox-core\aiox-core`. Interpolated into a `node -e "..."` script
running on Git Bash, the backslashes were interpreted as escape
sequences (`\a` → `a`), producing `D:aaiox-coreaiox-core` and
`Cannot find module ...`.
Fix: pass workspace path via `WORKSPACE_DIR` env var, read inside the
script as `process.env.WORKSPACE_DIR`. Applied to all 3 smoke install
steps.
## docs/guides/release-procedure.md
New SOP capturing the entire release pipeline:
- Pre-flight checks (lint, tests, tokens)
- 4-site version bump coordination (root, compat, installer, lock)
- Two-system branch protection bypass dance (modern ruleset +
legacy branch protection both enforce CODEOWNERS independently;
`gh pr merge --admin` bypasses neither in isolation)
- Atomic bypass→merge→restore as one shell block
- Tag-driven publish trigger
- Post-publish verification (registry sanity + artifact inspection)
- Known CI quirks with mitigations
- Rollback procedure (deprecate, don't unpublish)
- Failure modes seen in production with root causes
The SOP cites real PR numbers and incidents so future operators know
why each step exists.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedPull request was closed or merged during review WalkthroughThis PR fixes Windows path escaping in three installer smoke-test Node scripts, tightens NPM publish orchestration and softens some failure semantics while extending package-propagation polling, and adds a comprehensive release-procedure SOP document. ChangesInstaller Smoke Test Windows Path Fix
NPM Publish Workflow Job Orchestration and Failure Handling
Release Procedure SOP Documentation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📊 Coverage ReportCoverage report not available
Generated by PR Automation (Story 6.1) |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/npm-publish.yml:
- Around line 581-594: The release summary unconditionally adds
"`@aiox-squads/core`@${VERSION}" to the PUBLISHED array and prints the success
block for both PUBLISH_RESULT="success" and "skipped", causing a false
"published" message when the publish job was skipped; update the script so the
scoped package is only added to PUBLISHED when PUBLISH_RESULT = "success" (use
PUBLISH_RESULT to gate adding "`@aiox-squads/core`@${VERSION}" to the PUBLISHED
array) and change the echo/print condition to run only when PUBLISH_RESULT =
"success" (remove "skipped" from the success check), ensuring PUBLISHED and the
success message accurately reflect actual publish results.
In `@docs/guides/release-procedure.md`:
- Around line 81-115: The current script can leave protections relaxed because
it reuses raw ruleset snapshots (which contain read-only fields that GitHub
rejects on PUT) and lacks a trap cleanup; fix by (1) creating sanitized restore
payloads using jq to remove read-only fields (e.g., delete(.id, .node_id,
.created_at, .updated_at, .owner, .repository) or similar) for the ruleset
restore file (/tmp/aiox-core-ruleset-*.json) and likewise extracting only
allowed fields for required_pull_request_reviews
(/tmp/aiox-core-prr-restore.json), (2) wrap the sequence in set -e and a trap
'restore' EXIT function that always PUTs the sanitized ruleset to
repos/SynkraAI/aiox-core/rulesets/13330052 and PATCHes
repos/SynkraAI/aiox-core/branches/main/protection/required_pull_request_reviews,
and (3) ensure the merge step (AIOX_ACTIVE_AGENT=devops gh pr merge <PR#>
--squash --admin --delete-branch) runs between the bypass DELETE/PUT and the
guaranteed restore in the trap so no failure leaves protection relaxed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2b40f2d7-0d97-4496-b3a8-87b29ac3db94
📒 Files selected for processing (3)
.github/workflows/installer-smoke-matrix.yml.github/workflows/npm-publish.ymldocs/guides/release-procedure.md
Two real bugs caught:
## notify step printed "Successfully published" for skipped scoped publish
The previous condition gated the success block on
`PUBLISH_RESULT = success OR skipped` AND pre-seeded the PUBLISHED array
with `@aiox-squads/core@${VERSION}` unconditionally. Result: a workflow
run where `publish` was skipped (e.g. manual dispatch excluding `core`)
would falsely report the scoped package as published.
Fix: PUBLISHED is now built only from jobs that actually succeeded.
A separate branch handles the all-skipped case explicitly. The
success message only renders when something was actually published.
## SOP bypass dance: snapshot reuse could leave protections relaxed
The documented procedure piped the raw `gh api .../rulesets/...`
output back into `gh api -X PUT`. The raw response includes read-only
fields (`id`, `node_id`, `created_at`, `updated_at`, `_links`, `url`)
that GitHub rejects with HTTP 422 on PUT — meaning the restore could
silently fail and leave production in a relaxed state.
Two fixes layered for safety:
1. Snapshot is now separated from restore payload. Raw snapshot stays
on disk only as a diff baseline. Sanitized restore payload is
derived via `jq '{name, target, enforcement, conditions,
bypass_actors, rules}'` — only writable fields.
2. The bypass→merge→restore sequence is wrapped in `set -e` + a
`trap 'restore_protections' EXIT`. The trap fires on ANY exit
(success, failure, signal) and idempotently re-applies the
sanitized restore payloads. If a restore step itself fails, the
trap emits `::error::` annotations so the failure surfaces in the
GitHub Actions UI.
The previous documentation worked in practice because `gh api --input`
tolerates read-only fields in some paths, but that behavior is not
guaranteed. The new procedure is defensively correct under network
failures, manual interrupts, and edge-case API rejections.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addressed in f422d85. (1) notify: PUBLISHED array only populated from jobs with result=success; success message only renders when something actually published; explicit branches for all-skipped vs no-publish-but-not-all-skipped. (2) SOP: snapshot now separated from restore payload (sanitized via jq projection of writable fields only); bypass→merge→restore wrapped in set -e + trap EXIT with idempotent restore + ::error:: annotation if restore itself fails.
…leshooting (#745) * docs: align ecosystem with release-procedure SOP + Issue 10 troubleshooting Cross-cutting cleanup so the operator/student/agent ecosystem references the canonical release SOP (introduced in PR #744) consistently and exposes the npm-hijack troubleshooting path to students. ## docs/guides/installation-troubleshooting.md Added Issue 10: "Pro activation failed: Installed Pro artifact did not create node_modules/@aiox-squads/pro" — the exact error that affected cohorts for 30 days before PR #742 shipped. Documents symptom, root cause (npm hijack into ancestor with package.json/workspaces), fix (5.2.6+), and a two-tier recovery procedure (simple retry first, then cache cleanup + residual-install removal if state is fouled). ## docs/guides/aiox-pro-access.md "Erros comuns" section gains an explicit entry for the install failure with a direct link to Issue 10 above. Previously the guide only covered auth-side errors; students hitting the install-side error googled into silence. ## .aiox-core/development/tasks/publish-npm.md ## .aiox-core/development/tasks/release-management.md Both converted to slim wrappers that delegate to docs/guides/release-procedure.md as the authoritative source. The full procedures previously inlined here (757 and 257 lines respectively) were missing the gotchas paid for in 11 patches across 30 days: two- system branch protection bypass, publish race conditions, Windows path escape in node -e, npm CDN propagation budget, payload sanitization for ruleset PUT, trap EXIT for atomic restore. Maintaining the full content in two files would have drifted immediately; the wrappers keep the task IDs that agent workflows reference while pointing at the one source of truth. ## .aiox-core/development/agents/devops.md Added a "Release Procedure (NON-NEGOTIABLE Reference)" section to the DevOps Guide. When @devops is invoked for a release, push, or publish that ends with a tag push to @aiox-squads/*, the agent now has explicit instruction to load and follow the SOP. Captures the institutional memory items most likely to bite (two-system protection, 4-site version bump, publish_legacy race, smoke timeout, Windows path escape) so the agent does not re-discover them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address CodeRabbit feedback on PR #745 Four real issues caught: 1. devops.md L584 referenced `*publish` which is not in the agent's declared commands list. Replaced with `*push` followed by version-bump intent, which matches the actual command surface. 2. release-management.md L43 + publish-npm.md L32 + release-procedure.md L170 had `git tag -a vX.Y.Z origin/main -m "<notes>"` — options mixed with positional args. Reordered to `git tag -a -m "<notes>" vX.Y.Z origin/main` (options before tag name, ref last) as the idiomatic form. Both forms work in modern git, but the linted form is more robust against argument parsing edge cases. 3. installation-troubleshooting.md L260: fenced output block was missing language tag — failing MD040 linter. Added `text`. 4. installation-troubleshooting.md L276 (CodeRabbit nitpick, addressed in full): the cleanup snippets were bash-only and assumed macOS/Linux. Students hitting the original error on Windows had no recovery path. Added labelled PowerShell and Command Prompt variants alongside the bash version, all three with equivalent behavior: purge stray `node_modules/@aiox-squads/pro` directories + clear the npx cache + retry the install with `-p @aiox-squads/core@latest`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(release): bump to 5.2.7 — consolidate PRs #744-#750 from 5.2.6 Consolidates 7 PRs merged after the 5.2.6 release. None of them required an immediate hotfix on their own, but together they unblock cohort students from a real CI/CD failure mode (#739 Bug 1) and remove three sources of registry drift. ## What ships in 5.2.7 - **#744** (66b302a) — Pipeline hardening: `publish_legacy_aiox_core` race fix, smoke timeout 90s→240s with dual visibility check, structured notify summary, Windows path escape fix via WORKSPACE_DIR env var. Plus the canonical `docs/guides/release-procedure.md` SOP. - **#745** (342ef63) — Ecosystem alignment: `installation-troubleshooting.md` Issue 10 (install-side recovery for the npm-hijack symptom), aiox-pro-access.md link, slim wrappers for publish-npm.md/release-management.md tasks pointing at the SOP, devops.md Release Procedure section. - **#746** (ef7a352) — Internal `.aiox-core/package.json` rebranded `@aiox-fullstack/core@4.31.1` → `@aiox-squads/core-internal@5.2.7` (private, no phantom peerDeps). New `scripts/validate-aiox-core-namespace.js` (5-rule gate) wired into `validate:publish`. Closes #739 Bug 2. - **#747** (e5cd355) — 70 substitutions across 17 files realigning legacy `aiox-core/{templates,checklists,agents,tasks,workflows,agent-teams}/<X>` references to current `.aiox-core/...` layout. Unblocks `@po *validate-story-draft`. Closes #741. - **#748** (1f97f6f) — IDS `extractPurpose()` rewritten as strict priority chain (frontmatter → ## Purpose → ## Overview → # Title → fallback). Removed body-level regex that picked up example transcripts as purposes. New `syncSelfRegistryEntry()` writes sentinel `sha256:<self-reference>` checksum for the registry's own record. - **#749** (70fa5e2) — `looksLikePlaceholder()` filter excludes 16 garbage purposes (`{Brief...}`, `{{TASK_TITLE}}`, `${context.componentName}`). - **#750** (21782cc) — Installer honors `--ci` / `--yes` / `--skipPrompts` flags at the CLAUDE.md merge prompt. Non-interactive runs no longer block waiting for keyboard input. Closes #739 Bug 1. ## Version sites bumped (5 — up from 4 in the previous SOP) - `package.json` (root): 5.2.6 → 5.2.7 - `compat/aiox-core/package.json`: version + dep["@aiox-squads/core"] 5.2.6 → 5.2.7 - `packages/installer/package.json`: 3.3.5 → 3.3.6 (#750 touched installer src) - `.aiox-core/package.json` (internal): 5.2.6 → 5.2.7 (validate-aiox-core-namespace enforces lockstep with root — new in 5.2.7, first release under the gate) - `package-lock.json` refresh - `CHANGELOG.md`: new [5.2.7] entry - `docs/guides/release-procedure.md`: bump the "4 sites" rule to "5 sites" reflecting the validate-aiox-core-namespace gate added in PR #746 ## Validation - `npm run lint` → exit 0 - `npm run test:ci` → 8510 passed (151 skipped), 344/355 suites, 229s - `npx jest tests/installer/ --no-coverage` → 276/276 pass - `npm run validate:publish` → PASS (12911 files; namespace sync verified) Pro install hijack fix (#742) shipped in 5.2.6 and remains in production — this release does not re-iterate it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: address CodeRabbit nitpick on release-procedure.md lockstep wording PR #751 CodeRabbit review flagged that the "Bump all five version sites in lockstep" wording was ambiguous — the table below explicitly treats `packages/installer/package.json` as conditional ("patch bump if installer changed; otherwise leave"). Operators reading only line 36 could over-bump the installer. Reworded to distinguish: - Root + internal manifest + compat: MUST stay in lockstep at same version - packages/installer: bumped ONLY when installer source changed (not every release) Also explicit on the two failure-mode detection layers: - Smoke tests (catch silent publish mismatches) - validate-aiox-core-namespace.js wired into validate:publish (rule 4 enforces lockstep) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…kraAI#744) * fix(release): harden npm-publish pipeline + document release SOP Three real failure modes observed during the v5.2.5/5.2.6 releases, each fixed and documented so the next release does not re-discover them. ## npm-publish.yml ### Race: publish_legacy_aiox_core ran in parallel with publish The legacy compat wrapper `aiox-core@X.Y.Z` declares `@aiox-squads/core@X.Y.Z` as a runtime dependency. The smoke test step runs `npx --yes aiox-core@X.Y.Z --version`, which transitively installs the scoped package. With both jobs in parallel, `npx` raced against npm CDN propagation of the scoped package and timed out after 90s — making the entire job appear failed even though the publish step inside it had already printed "✅ Published aiox-core@X.Y.Z". Fix: `publish_legacy_aiox_core` now `needs: [test, build, publish]`, serializing the legacy publish behind the scoped publish. ### Smoke test legacy npx: timeout too short, no diagnostics Bumped retry budget 6×15s (90s) → 16×15s (240s). Added a second visibility check for the scoped dependency before invoking `npx` so we distinguish "compat not visible" from "scoped dep not visible". Captured last `npx` stderr in the timeout message instead of failing silently. ### Notify: aggregated bool hid which step failed Replaced with a structured summary that distinguishes hard fail (scoped publish) from soft warnings (workspace, legacy, smoke). Only the scoped publish is treated as release-blocking; the rest are informational and can be republished out-of-band. ## installer-smoke-matrix.yml ### Windows path mangling in node -e via Git Bash `${{ github.workspace }}` on a Windows runner expands to `D:\a\aiox-core\aiox-core`. Interpolated into a `node -e "..."` script running on Git Bash, the backslashes were interpreted as escape sequences (`\a` → `a`), producing `D:aaiox-coreaiox-core` and `Cannot find module ...`. Fix: pass workspace path via `WORKSPACE_DIR` env var, read inside the script as `process.env.WORKSPACE_DIR`. Applied to all 3 smoke install steps. ## docs/guides/release-procedure.md New SOP capturing the entire release pipeline: - Pre-flight checks (lint, tests, tokens) - 4-site version bump coordination (root, compat, installer, lock) - Two-system branch protection bypass dance (modern ruleset + legacy branch protection both enforce CODEOWNERS independently; `gh pr merge --admin` bypasses neither in isolation) - Atomic bypass→merge→restore as one shell block - Tag-driven publish trigger - Post-publish verification (registry sanity + artifact inspection) - Known CI quirks with mitigations - Rollback procedure (deprecate, don't unpublish) - Failure modes seen in production with root causes The SOP cites real PR numbers and incidents so future operators know why each step exists. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address CodeRabbit feedback on PR SynkraAI#744 Two real bugs caught: ## notify step printed "Successfully published" for skipped scoped publish The previous condition gated the success block on `PUBLISH_RESULT = success OR skipped` AND pre-seeded the PUBLISHED array with `@aiox-squads/core@${VERSION}` unconditionally. Result: a workflow run where `publish` was skipped (e.g. manual dispatch excluding `core`) would falsely report the scoped package as published. Fix: PUBLISHED is now built only from jobs that actually succeeded. A separate branch handles the all-skipped case explicitly. The success message only renders when something was actually published. ## SOP bypass dance: snapshot reuse could leave protections relaxed The documented procedure piped the raw `gh api .../rulesets/...` output back into `gh api -X PUT`. The raw response includes read-only fields (`id`, `node_id`, `created_at`, `updated_at`, `_links`, `url`) that GitHub rejects with HTTP 422 on PUT — meaning the restore could silently fail and leave production in a relaxed state. Two fixes layered for safety: 1. Snapshot is now separated from restore payload. Raw snapshot stays on disk only as a diff baseline. Sanitized restore payload is derived via `jq '{name, target, enforcement, conditions, bypass_actors, rules}'` — only writable fields. 2. The bypass→merge→restore sequence is wrapped in `set -e` + a `trap 'restore_protections' EXIT`. The trap fires on ANY exit (success, failure, signal) and idempotently re-applies the sanitized restore payloads. If a restore step itself fails, the trap emits `::error::` annotations so the failure surfaces in the GitHub Actions UI. The previous documentation worked in practice because `gh api --input` tolerates read-only fields in some paths, but that behavior is not guaranteed. The new procedure is defensively correct under network failures, manual interrupts, and edge-case API rejections. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…leshooting (SynkraAI#745) * docs: align ecosystem with release-procedure SOP + Issue 10 troubleshooting Cross-cutting cleanup so the operator/student/agent ecosystem references the canonical release SOP (introduced in PR SynkraAI#744) consistently and exposes the npm-hijack troubleshooting path to students. ## docs/guides/installation-troubleshooting.md Added Issue 10: "Pro activation failed: Installed Pro artifact did not create node_modules/@aiox-squads/pro" — the exact error that affected cohorts for 30 days before PR SynkraAI#742 shipped. Documents symptom, root cause (npm hijack into ancestor with package.json/workspaces), fix (5.2.6+), and a two-tier recovery procedure (simple retry first, then cache cleanup + residual-install removal if state is fouled). ## docs/guides/aiox-pro-access.md "Erros comuns" section gains an explicit entry for the install failure with a direct link to Issue 10 above. Previously the guide only covered auth-side errors; students hitting the install-side error googled into silence. ## .aiox-core/development/tasks/publish-npm.md ## .aiox-core/development/tasks/release-management.md Both converted to slim wrappers that delegate to docs/guides/release-procedure.md as the authoritative source. The full procedures previously inlined here (757 and 257 lines respectively) were missing the gotchas paid for in 11 patches across 30 days: two- system branch protection bypass, publish race conditions, Windows path escape in node -e, npm CDN propagation budget, payload sanitization for ruleset PUT, trap EXIT for atomic restore. Maintaining the full content in two files would have drifted immediately; the wrappers keep the task IDs that agent workflows reference while pointing at the one source of truth. ## .aiox-core/development/agents/devops.md Added a "Release Procedure (NON-NEGOTIABLE Reference)" section to the DevOps Guide. When @devops is invoked for a release, push, or publish that ends with a tag push to @aiox-squads/*, the agent now has explicit instruction to load and follow the SOP. Captures the institutional memory items most likely to bite (two-system protection, 4-site version bump, publish_legacy race, smoke timeout, Windows path escape) so the agent does not re-discover them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: address CodeRabbit feedback on PR SynkraAI#745 Four real issues caught: 1. devops.md L584 referenced `*publish` which is not in the agent's declared commands list. Replaced with `*push` followed by version-bump intent, which matches the actual command surface. 2. release-management.md L43 + publish-npm.md L32 + release-procedure.md L170 had `git tag -a vX.Y.Z origin/main -m "<notes>"` — options mixed with positional args. Reordered to `git tag -a -m "<notes>" vX.Y.Z origin/main` (options before tag name, ref last) as the idiomatic form. Both forms work in modern git, but the linted form is more robust against argument parsing edge cases. 3. installation-troubleshooting.md L260: fenced output block was missing language tag — failing MD040 linter. Added `text`. 4. installation-troubleshooting.md L276 (CodeRabbit nitpick, addressed in full): the cleanup snippets were bash-only and assumed macOS/Linux. Students hitting the original error on Windows had no recovery path. Added labelled PowerShell and Command Prompt variants alongside the bash version, all three with equivalent behavior: purge stray `node_modules/@aiox-squads/pro` directories + clear the npx cache + retry the install with `-p @aiox-squads/core@latest`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…m 5.2.6 (SynkraAI#751) * chore(release): bump to 5.2.7 — consolidate PRs SynkraAI#744-SynkraAI#750 from 5.2.6 Consolidates 7 PRs merged after the 5.2.6 release. None of them required an immediate hotfix on their own, but together they unblock cohort students from a real CI/CD failure mode (SynkraAI#739 Bug 1) and remove three sources of registry drift. ## What ships in 5.2.7 - **SynkraAI#744** (d949918) — Pipeline hardening: `publish_legacy_aiox_core` race fix, smoke timeout 90s→240s with dual visibility check, structured notify summary, Windows path escape fix via WORKSPACE_DIR env var. Plus the canonical `docs/guides/release-procedure.md` SOP. - **SynkraAI#745** (b728a39) — Ecosystem alignment: `installation-troubleshooting.md` Issue 10 (install-side recovery for the npm-hijack symptom), aiox-pro-access.md link, slim wrappers for publish-npm.md/release-management.md tasks pointing at the SOP, devops.md Release Procedure section. - **SynkraAI#746** (dea939e) — Internal `.aiox-core/package.json` rebranded `@aiox-fullstack/core@4.31.1` → `@aiox-squads/core-internal@5.2.7` (private, no phantom peerDeps). New `scripts/validate-aiox-core-namespace.js` (5-rule gate) wired into `validate:publish`. Closes SynkraAI#739 Bug 2. - **SynkraAI#747** (e874103) — 70 substitutions across 17 files realigning legacy `aiox-core/{templates,checklists,agents,tasks,workflows,agent-teams}/<X>` references to current `.aiox-core/...` layout. Unblocks `@po *validate-story-draft`. Closes SynkraAI#741. - **SynkraAI#748** (e8f8761) — IDS `extractPurpose()` rewritten as strict priority chain (frontmatter → ## Purpose → ## Overview → # Title → fallback). Removed body-level regex that picked up example transcripts as purposes. New `syncSelfRegistryEntry()` writes sentinel `sha256:<self-reference>` checksum for the registry's own record. - **SynkraAI#749** (6113083) — `looksLikePlaceholder()` filter excludes 16 garbage purposes (`{Brief...}`, `{{TASK_TITLE}}`, `${context.componentName}`). - **SynkraAI#750** (1d16b51) — Installer honors `--ci` / `--yes` / `--skipPrompts` flags at the CLAUDE.md merge prompt. Non-interactive runs no longer block waiting for keyboard input. Closes SynkraAI#739 Bug 1. ## Version sites bumped (5 — up from 4 in the previous SOP) - `package.json` (root): 5.2.6 → 5.2.7 - `compat/aiox-core/package.json`: version + dep["@aiox-squads/core"] 5.2.6 → 5.2.7 - `packages/installer/package.json`: 3.3.5 → 3.3.6 (SynkraAI#750 touched installer src) - `.aiox-core/package.json` (internal): 5.2.6 → 5.2.7 (validate-aiox-core-namespace enforces lockstep with root — new in 5.2.7, first release under the gate) - `package-lock.json` refresh - `CHANGELOG.md`: new [5.2.7] entry - `docs/guides/release-procedure.md`: bump the "4 sites" rule to "5 sites" reflecting the validate-aiox-core-namespace gate added in PR SynkraAI#746 ## Validation - `npm run lint` → exit 0 - `npm run test:ci` → 8510 passed (151 skipped), 344/355 suites, 229s - `npx jest tests/installer/ --no-coverage` → 276/276 pass - `npm run validate:publish` → PASS (12911 files; namespace sync verified) Pro install hijack fix (SynkraAI#742) shipped in 5.2.6 and remains in production — this release does not re-iterate it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: address CodeRabbit nitpick on release-procedure.md lockstep wording PR SynkraAI#751 CodeRabbit review flagged that the "Bump all five version sites in lockstep" wording was ambiguous — the table below explicitly treats `packages/installer/package.json` as conditional ("patch bump if installer changed; otherwise leave"). Operators reading only line 36 could over-bump the installer. Reworded to distinguish: - Root + internal manifest + compat: MUST stay in lockstep at same version - packages/installer: bumped ONLY when installer source changed (not every release) Also explicit on the two failure-mode detection layers: - Smoke tests (catch silent publish mismatches) - validate-aiox-core-namespace.js wired into validate:publish (rule 4 enforces lockstep) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Captures three real failure modes observed during v5.2.5 and v5.2.6 releases and prevents them from biting future releases. Companion to PR #742 (the original Pro install hotfix) and PR #743 (the 5.2.6 release bump).
What changed
npm-publish.yml
Race condition fix:
publish_legacy_aiox_corenowneeds: [test, build, publish]instead of[test, build]. Was running in parallel withpublisheven though the compat wrapper transitively depends on the scoped package, causing the smoke npx step to race against npm CDN propagation.Smoke test resilience: legacy npx smoke retry budget 6×15s → 16×15s (90s → 240s). Now checks BOTH
aiox-coreand@aiox-squads/corevisibility before invokingnpx. Captures lastnpxstderr in the timeout error.Notify clarity: replaced the aggregated bool with a structured summary that distinguishes hard fail (scoped publish) from soft warnings (workspace, legacy compat, smoke tests). Hard fail blocks; soft warnings just inform.
installer-smoke-matrix.yml
${{ github.workspace }}interpolated intonode -e "..."on Git Bash for Windows turnedD:\a\aiox-core\aiox-coreintoD:aaiox-coreaiox-corebecause\abecomes an escape sequence. Now passes viaWORKSPACE_DIRenv var. Applied to all 3 smoke install steps.docs/guides/release-procedure.md (NEW)
Full SOP for
@devops: pre-flight checks → version bump coordination → branch + PR → branch protection bypass dance (two systems, both enforce CODEOWNERS, must be relaxed/restored atomically) → tag + push → post-publish verification → known quirks → rollback. Cites incidents and PRs so the next operator knows WHY each step exists.Validation
@aiox-squads/core@5.2.6from public npm + Pro 0.4.3 tgz in worst-case dir (workspace ancestor) → fix works, no escape, package installed at targetTest plan
This PR doesn't change runtime behavior of any package — only workflow files and documentation. Standard CI passes will indicate it's safe.
The real validation is in the NEXT release: when v5.2.7 or later ships, the legacy smoke test should complete cleanly within 240s and the Windows smoke matrix combos should pass.
🤖 Generated with Claude Code
Summary by CodeRabbit
Note: Internal infrastructure and process improvements; no direct user-facing feature changes.