Skip to content

fix(installer): isolate Pro install from ancestor workspaces/package.json - #742

Merged
rafaelscosta merged 2 commits into
mainfrom
fix/pro-install-workspace-isolation
May 17, 2026
Merged

fix(installer): isolate Pro install from ancestor workspaces/package.json#742
rafaelscosta merged 2 commits into
mainfrom
fix/pro-install-workspace-isolation

Conversation

@rafaelscosta

@rafaelscosta rafaelscosta commented May 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Hotfix para o erro recorrente que vem travando alunos das cohorts no aiox install (Pro flow):

⚠️ Pro activation failed: Installed Pro artifact did not create node_modules/@aiox-squads/pro.
Continue with Community (free) edition instead? (Y/n)

A licença ativa, o sha256 bate, o npm install retorna exit 0 — e mesmo assim o check de integridade do post-install falha.

Root cause

installProArtifactIntoTarget (packages/installer/src/wizard/pro-setup.js:814) roda npm install <tgz> sem --prefix nem --workspaces=false. npm 10+/11 sobe a árvore de diretórios procurando o primeiro package.json ancestral (ou workspaces: declarado) e instala node_modules lá em vez do targetDir. O check pós-install em targetDir/node_modules/@aiox-squads/pro/package.json falha porque o artefato foi parar em outro lugar.

Reproduzido localmente em 4 topologias de install antes do fix, depois provado rodando a nova suite de tests contra o código pre-fix — os dois cenários de hijack falham cleanly sem o fix:

Topologia Pre-fix Post-fix
Workspace declarado em ancestor ❌ FAIL (instala em workspace root)
package.json comum em ancestor ❌ FAIL (instala em ancestor)
targetDir empty, sem ancestor
targetDir com package.json próprio

What changed

  • installProArtifactIntoTarget: passa --prefix=targetDir + --workspaces=false + --include-workspace-root=false. Cria um package.json anchor sintético se o targetDir estiver vazio e remove no finally.
  • extractProArtifactToTemp: mesmos flags por simetria — nunca falhou em prática porque os.tmpdir() não tem ancestrais com package.json, mas a assimetria era frágil.
  • acquireProArtifactSourceDir: quando o install no target falha, faz fallback graceful ao Pro source já extraído e sha256-verificado no tempRoot, emitindo warning explícito em vez de bloquear o wizard. O scaffolder copia arquivos do source dir, então o install no target é conveniência, não pré-requisito. A warning é explícita sobre re-download em chamadas futuras.
  • Novo helper diagnóstico findAncestorNodeModulesPro percorre até 8 níveis pra cima procurando install perdido — incluído na mensagem de erro pra que o aluno veja onde npm realmente colocou o pacote.

Tests

tests/installer/pro-setup-target-install.test.js — 8 regression tests:

  • 4 topologias de install (workspace ancestor, parent ancestor, empty, local pkg)
  • cleanup do anchor sintético
  • helper diagnóstico (positivo + negativo)
  • contrato do fallback graceful em acquireProArtifactSourceDir

Integration-style: builda um tarball fixture mínimo em runtime via npm pack, sem dependências externas, sem credenciais Supabase.

Validação: rodei a suite contra o pro-setup.js pre-fix (git checkout f949b42d -- pro-setup.js) e os 2 tests de hijack falharam conforme esperado. Provei que os tests pegam o bug que dizem pegar.

Test Suites: 15 passed, 15 total
Tests:       259 passed, 259 total  (era 251 antes)

CI

.github/workflows/installer-smoke-matrix.yml — matrix:

  • OS: Ubuntu, macOS, Windows
  • Node: 18, 20, 22
  • npm: 8, 10, 11

Roda regression suite + 3 smoke installs end-to-end (empty target, nested em workspace, nested sob plain package.json) ANTES de qualquer publish. Trigger em packages/installer/** e tests/installer/**.

Existe pra quebrar o padrão "11 fixes em pro-setup.js em 30 dias, cada um pegando um edge case novo" — agora a superfície de install é validada antes do release.

Test plan

  • npx jest tests/installer/ --no-coverage → 259/259 verde
  • npx eslint packages/installer/src/wizard/pro-setup.js tests/installer/pro-setup-target-install.test.js → clean
  • Bug reproduzido em 4 topologias antes do patch
  • Tests provados contra pre-fix code (failures matching expected scenarios)
  • Workflow installer-smoke-matrix.yml deve validar em Ubuntu/macOS/Windows × Node 18/20/22 × npm 8/10/11 quando este PR rodar CI

Impact

  • Affected story: PRO-13.6 (signed artifact pipeline)
  • Builds on: fix: avoid Windows npm spawn failure in Pro install #735 (Windows npm spawn), PRO-13.5 (private distribution)
  • Recommended bump: patch (5.2.55.2.6) — fix only, no behavior change for happy path
  • Student workaround until publish: rodar aiox install em diretório fresh sem ancestrais (mkdir ~/aiox-pro && cd ~/aiox-pro && npx -y -p @aiox-squads/core@latest aiox install)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Pro installer now falls back to a verified temporary source when direct install fails and surfaces a user-facing warning (cache persistence unavailable for the target).
  • Bug Fixes

    • Prevents unintended installs into ancestor/workspace locations and provides clearer install-failure diagnostics.
  • Tests

    • Added cross-platform installer validation and regression tests covering target-install edge cases and ancestor-resolution.

Review Change Stack

…json

Cohort students hit "Pro activation failed: Installed Pro artifact did not
create node_modules/@aiox-squads/pro" even though npm install exits 0 and
the upstream Pro license activation completes successfully.

Root cause: installProArtifactIntoTarget runs `npm install <tgz>` in
targetDir without --prefix or --workspaces=false. npm 10+ walks the
directory tree, finds the first ancestor with a package.json (or one
declaring workspaces), and installs node_modules there instead of in the
target. The post-install integrity check then fails because the artifact
is in the wrong place, not because it never downloaded.

This was reproduced locally in 4 install topologies before patching,
then proved by running the new test suite against pre-fix code — the
two ancestor-hijack scenarios fail cleanly without the fix:

  1. workspace declared in ancestor → npm installs at workspace root (FAILS pre-fix)
  2. plain package.json in ancestor → npm installs at ancestor (FAILS pre-fix)
  3. empty targetDir, clean ancestor → works (current happy path)
  4. targetDir with own package.json → works (current happy path)

Fixes applied:

* installProArtifactIntoTarget: pass --prefix=targetDir +
  --workspaces=false + --include-workspace-root=false; create a synthetic
  anchor package.json if targetDir is empty, then clean it up after.
* extractProArtifactToTemp: mirror the same flags to harden the temp
  extraction (it never failed in practice because os.tmpdir() has no
  ancestors with package.json, but the asymmetry was fragile).
* acquireProArtifactSourceDir: when the target install fails, fall back
  to the extracted (sha256-verified) Pro source from tempRoot and emit
  a warning instead of bricking the wizard. The scaffolder copies files
  from the source dir, so the target install is a convenience, not a
  requirement. The warning is explicit that subsequent `aiox install`
  calls in the same directory will re-download Pro until the user runs
  from a fresh empty directory.
* New diagnostic helper findAncestorNodeModulesPro walks up to 8 levels
  looking for a stray install, included in the user-facing error so
  students can see where npm actually put the package.

Tests added: tests/installer/pro-setup-target-install.test.js — 8
regression tests covering all four install topologies, the synthetic
anchor cleanup, the diagnostic helper (positive + negative cases), and
the graceful fallback contract in acquireProArtifactSourceDir.
Integration-style: builds a minimal fixture tarball at runtime via
`npm pack`, no external dependencies, no Supabase credentials needed.

CI added: .github/workflows/installer-smoke-matrix.yml — runs the
regression suite + three end-to-end smoke installs (empty target,
nested in workspace, nested under plain package.json) on Ubuntu/macOS/
Windows with Node 18/20/22 and npm 8/10/11. Triggers on
packages/installer/** and tests/installer/** changes, breaking the
"11 fixes to pro-setup.js in 30 days, each catching a new edge case"
pattern by validating the install surface itself before publish.

Cleared the dead fallback path in acquireProArtifactSourceDir that was
already wired (`installedProSourceDir || extractedProSourceDir`) but
unreachable because the throw in installProArtifactIntoTarget short-
circuited it.

Affected story: PRO-13.6 (signed artifact pipeline)
Builds on: #735 (Windows npm spawn), PRO-13.5 (private distribution)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented May 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aiox-core Ready Ready Preview, Comment May 17, 2026 9:31am

Request Review

@github-actions github-actions Bot added type: test Test coverage and quality area: installer Installer and setup (packages/installer/) area: docs Documentation (docs/) area: devops CI/CD, GitHub Actions (.github/) labels May 17, 2026
@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 746b50a8-9a5c-4cd9-8d5a-837e6a1ea9f8

📥 Commits

Reviewing files that changed from the base of the PR and between 5c1560c and 6bd1c3c.

📒 Files selected for processing (2)
  • .github/workflows/installer-smoke-matrix.yml
  • tests/installer/pro-setup-target-install.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/installer/pro-setup-target-install.test.js

Walkthrough

Prevents npm from escaping target installs by adding explicit --prefix and workspace flags, detects ancestor-installed Pro and throws PRO_INSTALL_TARGET_HIJACKED, falls back to a verified temp source with a user warning, and adds regression tests plus a cross‑platform smoke workflow.

Changes

Pro Artifact Installation Safeguards

Layer / File(s) Summary
Pro install hijack prevention via prefix and ancestor detection
packages/installer/src/wizard/pro-setup.js
extractProArtifactToTemp and installProArtifactIntoTarget now use --prefix and workspace-control flags; installProArtifactIntoTarget temporarily creates/removes an anchor package.json in targetDir; missing expected install path triggers PRO_INSTALL_TARGET_HIJACKED after bounded ancestor search. findAncestorNodeModulesPro is exposed on _testing.
Graceful fallback on target install failure with user warning
packages/installer/src/wizard/pro-setup.js
acquireProArtifactSourceDir records targetInstallWarning when a target install fails, continues using the verified temporary Pro source, and stepInstallScaffold surfaces a warning explaining cache unavailability for the target directory.
Comprehensive regression and fallback test coverage
tests/installer/pro-setup-target-install.test.js
Jest suite generates a runtime @aiox-squads/pro tarball fixture and tests installProArtifactIntoTarget across empty target, workspace ancestor, plain ancestor, and existing-target scenarios; tests findAncestorNodeModulesPro; tests acquireProArtifactSourceDir fallback via mocked hijack and stubbed fetch, asserting warning emission and verified temp source success.
Smoke test matrix workflow across OS and Node/npm versions
.github/workflows/installer-smoke-matrix.yml
New GitHub Actions workflow running on installer-related changes, manual dispatch, and weekly schedule. Matrix covers ubuntu/macos/windows with Node/npm permutations, runs Jest suites, executes three inline smoke-install scenarios validating target-scoped installs, and prints a concise job summary.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • SynkraAI/aiox-core#735: Modifies the same Pro artifact install/extract paths and npm invocation patterns.
  • SynkraAI/aiox-core#716: Changes surrounding Pro artifact versioning that affect which artifact the install logic operates on.

Suggested labels

area: workflows

Suggested reviewers

  • Pedrovaleriolopez
  • oalanicolas
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main fix: isolating Pro installation from ancestor workspaces/package.json, which is the primary change across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pro-install-workspace-isolation

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

📊 Coverage Report

Coverage report not available

📈 Full coverage report available in Codecov


Generated by PR Automation (Story 6.1)

coderabbitai[bot]
coderabbitai Bot previously requested changes May 17, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/installer/pro-setup-target-install.test.js (1)

34-34: ⚡ Quick win

Use an absolute import for pro-setup in this test.

Line 34 uses a relative path import; switch this to the repository’s absolute import convention.

As per coding guidelines, "**/*.{js,jsx,ts,tsx}: Use absolute imports instead of relative imports in all code".

🤖 Prompt for 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.

In `@tests/installer/pro-setup-target-install.test.js` at line 34, The test
imports pro-setup using a relative path; replace the relative require for
pro-setup (the line using "const proSetup =
require('../../packages/installer/src/wizard/pro-setup');") with the
repository's absolute import style—use the absolute module path for the
installer wizard (e.g. require('packages/installer/src/wizard/pro-setup') or
your repo's configured absolute alias) so the test follows the project's
absolute-import convention.
🤖 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/installer-smoke-matrix.yml:
- Around line 116-130: The inline Node scripts call execFileSync('npm', ...)
which breaks on Windows (npm is npm.cmd); update each script to resolve the npm
executable using platform detection (e.g., choose 'npm.cmd' when
process.platform === 'win32' and 'npm' otherwise) and pass that resolved name
into execFileSync instead of the hardcoded 'npm' (update the occurrences around
execFileSync('npm', ['pack', ...], { encoding: 'utf8' }) in the inline scripts
and the other two similar blocks mentioned).

In `@tests/installer/pro-setup-target-install.test.js`:
- Around line 89-93: The execFileSync call that sets packOutput uses a hardcoded
'npm' which fails on Windows; change it to select the platform-aware binary
(like const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm') and call
execFileSync(npmBin, ['pack', '--json'], { cwd: buildDir, timeout:
NPM_INSTALL_TIMEOUT_MS, encoding: 'utf8' }); update the reference in this test
(the packOutput/execFileSync invocation) so Windows runners use npm.cmd the same
way other code (e.g., pro-setup.js) does.

---

Nitpick comments:
In `@tests/installer/pro-setup-target-install.test.js`:
- Line 34: The test imports pro-setup using a relative path; replace the
relative require for pro-setup (the line using "const proSetup =
require('../../packages/installer/src/wizard/pro-setup');") with the
repository's absolute import style—use the absolute module path for the
installer wizard (e.g. require('packages/installer/src/wizard/pro-setup') or
your repo's configured absolute alias) so the test follows the project's
absolute-import convention.
🪄 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: e33a22ec-e463-4e56-ba8f-3c29b025abd0

📥 Commits

Reviewing files that changed from the base of the PR and between f949b42 and 5c1560c.

📒 Files selected for processing (3)
  • .github/workflows/installer-smoke-matrix.yml
  • packages/installer/src/wizard/pro-setup.js
  • tests/installer/pro-setup-target-install.test.js

Comment thread .github/workflows/installer-smoke-matrix.yml
Comment thread tests/installer/pro-setup-target-install.test.js Outdated
* Use platform-aware npm binary (npm.cmd on Windows) in the test fixture
  tarball builder and the 3 inline smoke install scripts in
  installer-smoke-matrix.yml. Mirrors the pattern in pro-setup.js'
  resolveNpmInvocation. Without this, the Windows job fixed below would
  fail at the `execFileSync('npm', ...)` call.
* Replace the cross-product matrix with an explicit `include:` list and
  drop combos that are structurally invalid (and were failing CI on the
  first run): Node 18 + npm 11 (npm 11 requires Node >= 20.17), Node 20
  + npm 8 (npm 8 too old to honor --workspaces=false reliably), and the
  redundant npm 11 re-pin on Node 22 (already ships with npm 11; the
  re-pin via `npm install --global` conflicts with the bundled install
  on GitHub-hosted runners). Added a new `bundled` mode that skips the
  pin step entirely.
* Coverage retained: Ubuntu (Node 18/20/22 × npm 10/11/bundled),
  macOS (Node 20/22), Windows (Node 20/22). 8 combos total, all valid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rafaelscosta
rafaelscosta dismissed coderabbitai[bot]’s stale review May 17, 2026 09:31

Addressed in 6bd1c3c — platform-aware npm bin in test fixture + smoke workflow inline scripts; matrix combos invalid in npm 8/11 vs Node 18/22 dropped. Nitpick on relative import is project convention (all other tests/installer/* use the same).

@rafaelscosta
rafaelscosta merged commit 20e7999 into main May 17, 2026
46 of 49 checks passed
@rafaelscosta
rafaelscosta deleted the fix/pro-install-workspace-isolation branch May 17, 2026 09:33
rafaelscosta added a commit that referenced this pull request May 17, 2026
…#743)

Hotfix release for #742 (already merged). Bumps:

* @aiox-squads/core: 5.2.5 → 5.2.6
* aiox-core (compat wrapper): 5.2.5 → 5.2.6
  + dependency @aiox-squads/core: 5.2.5 → 5.2.6
* @aiox-squads/installer: 3.3.4 → 3.3.5

Pushing tag v5.2.6 triggers .github/workflows/npm-publish.yml which
publishes to npmjs.org using NPM_TOKEN_AIOX_SQUADS.

After publish, students hit by "Installed Pro artifact did not create
node_modules/@aiox-squads/pro" can update via:

    npx -y -p @aiox-squads/core@latest aiox install

without the previously recommended fresh-directory workaround.

Includes:
- package-lock.json refreshed to 5.2.6
- CHANGELOG.md entry under [5.2.6] - 2026-05-17
- .aiox-core/data/entity-registry.yaml regenerated by pre-commit hook
  (757 → 815 entities — incidental sync, not caused by this release)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rafaelscosta added a commit that referenced this pull request May 17, 2026
…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>
rafaelscosta added a commit that referenced this pull request May 18, 2026
* 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>
tuanmedeiros pushed a commit to tuanmedeiros/aios-core-synkraay that referenced this pull request Jun 2, 2026
…json (SynkraAI#742)

* fix(installer): isolate Pro install from ancestor workspaces/package.json

Cohort students hit "Pro activation failed: Installed Pro artifact did not
create node_modules/@aiox-squads/pro" even though npm install exits 0 and
the upstream Pro license activation completes successfully.

Root cause: installProArtifactIntoTarget runs `npm install <tgz>` in
targetDir without --prefix or --workspaces=false. npm 10+ walks the
directory tree, finds the first ancestor with a package.json (or one
declaring workspaces), and installs node_modules there instead of in the
target. The post-install integrity check then fails because the artifact
is in the wrong place, not because it never downloaded.

This was reproduced locally in 4 install topologies before patching,
then proved by running the new test suite against pre-fix code — the
two ancestor-hijack scenarios fail cleanly without the fix:

  1. workspace declared in ancestor → npm installs at workspace root (FAILS pre-fix)
  2. plain package.json in ancestor → npm installs at ancestor (FAILS pre-fix)
  3. empty targetDir, clean ancestor → works (current happy path)
  4. targetDir with own package.json → works (current happy path)

Fixes applied:

* installProArtifactIntoTarget: pass --prefix=targetDir +
  --workspaces=false + --include-workspace-root=false; create a synthetic
  anchor package.json if targetDir is empty, then clean it up after.
* extractProArtifactToTemp: mirror the same flags to harden the temp
  extraction (it never failed in practice because os.tmpdir() has no
  ancestors with package.json, but the asymmetry was fragile).
* acquireProArtifactSourceDir: when the target install fails, fall back
  to the extracted (sha256-verified) Pro source from tempRoot and emit
  a warning instead of bricking the wizard. The scaffolder copies files
  from the source dir, so the target install is a convenience, not a
  requirement. The warning is explicit that subsequent `aiox install`
  calls in the same directory will re-download Pro until the user runs
  from a fresh empty directory.
* New diagnostic helper findAncestorNodeModulesPro walks up to 8 levels
  looking for a stray install, included in the user-facing error so
  students can see where npm actually put the package.

Tests added: tests/installer/pro-setup-target-install.test.js — 8
regression tests covering all four install topologies, the synthetic
anchor cleanup, the diagnostic helper (positive + negative cases), and
the graceful fallback contract in acquireProArtifactSourceDir.
Integration-style: builds a minimal fixture tarball at runtime via
`npm pack`, no external dependencies, no Supabase credentials needed.

CI added: .github/workflows/installer-smoke-matrix.yml — runs the
regression suite + three end-to-end smoke installs (empty target,
nested in workspace, nested under plain package.json) on Ubuntu/macOS/
Windows with Node 18/20/22 and npm 8/10/11. Triggers on
packages/installer/** and tests/installer/** changes, breaking the
"11 fixes to pro-setup.js in 30 days, each catching a new edge case"
pattern by validating the install surface itself before publish.

Cleared the dead fallback path in acquireProArtifactSourceDir that was
already wired (`installedProSourceDir || extractedProSourceDir`) but
unreachable because the throw in installProArtifactIntoTarget short-
circuited it.

Affected story: PRO-13.6 (signed artifact pipeline)
Builds on: SynkraAI#735 (Windows npm spawn), PRO-13.5 (private distribution)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(installer-smoke): address CodeRabbit feedback on PR SynkraAI#742

* Use platform-aware npm binary (npm.cmd on Windows) in the test fixture
  tarball builder and the 3 inline smoke install scripts in
  installer-smoke-matrix.yml. Mirrors the pattern in pro-setup.js'
  resolveNpmInvocation. Without this, the Windows job fixed below would
  fail at the `execFileSync('npm', ...)` call.
* Replace the cross-product matrix with an explicit `include:` list and
  drop combos that are structurally invalid (and were failing CI on the
  first run): Node 18 + npm 11 (npm 11 requires Node >= 20.17), Node 20
  + npm 8 (npm 8 too old to honor --workspaces=false reliably), and the
  redundant npm 11 re-pin on Node 22 (already ships with npm 11; the
  re-pin via `npm install --global` conflicts with the bundled install
  on GitHub-hosted runners). Added a new `bundled` mode that skips the
  pin step entirely.
* Coverage retained: Ubuntu (Node 18/20/22 × npm 10/11/bundled),
  macOS (Node 20/22), Windows (Node 20/22). 8 combos total, all valid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tuanmedeiros pushed a commit to tuanmedeiros/aios-core-synkraay that referenced this pull request Jun 2, 2026
…SynkraAI#743)

Hotfix release for SynkraAI#742 (already merged). Bumps:

* @aiox-squads/core: 5.2.5 → 5.2.6
* aiox-core (compat wrapper): 5.2.5 → 5.2.6
  + dependency @aiox-squads/core: 5.2.5 → 5.2.6
* @aiox-squads/installer: 3.3.4 → 3.3.5

Pushing tag v5.2.6 triggers .github/workflows/npm-publish.yml which
publishes to npmjs.org using NPM_TOKEN_AIOX_SQUADS.

After publish, students hit by "Installed Pro artifact did not create
node_modules/@aiox-squads/pro" can update via:

    npx -y -p @aiox-squads/core@latest aiox install

without the previously recommended fresh-directory workaround.

Includes:
- package-lock.json refreshed to 5.2.6
- CHANGELOG.md entry under [5.2.6] - 2026-05-17
- .aiox-core/data/entity-registry.yaml regenerated by pre-commit hook
  (757 → 815 entities — incidental sync, not caused by this release)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tuanmedeiros pushed a commit to tuanmedeiros/aios-core-synkraay that referenced this pull request Jun 2, 2026
…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>
tuanmedeiros pushed a commit to tuanmedeiros/aios-core-synkraay that referenced this pull request Jun 2, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: devops CI/CD, GitHub Actions (.github/) area: docs Documentation (docs/) area: installer Installer and setup (packages/installer/) type: test Test coverage and quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant