diff --git a/.aiox-core/install-manifest.yaml b/.aiox-core/install-manifest.yaml index 2750ab68ad..0dfe06141f 100644 --- a/.aiox-core/install-manifest.yaml +++ b/.aiox-core/install-manifest.yaml @@ -8,7 +8,7 @@ # - File types for categorization # version: 5.2.6 -generated_at: "2026-05-17T12:22:51.608Z" +generated_at: "2026-05-17T13:13:35.812Z" generator: scripts/generate-install-manifest.js file_count: 1128 files: @@ -1297,9 +1297,9 @@ files: type: data size: 9590 - path: data/entity-registry.yaml - hash: sha256:7a1dc65b0661069cdccf8babb7c3320320281f10a8e5258a3cba26b8953df5ad + hash: sha256:5dac372c022f1da390b923a2ce2c719deb2ed3916464925be788b26596f31fdf type: data - size: 572193 + size: 574327 - path: data/learned-patterns.yaml hash: sha256:24ac0b160615583a0ff783d3da8af80b7f94191575d6db2054ec8e10a3f945dc type: data @@ -3697,9 +3697,9 @@ files: type: monitor size: 818 - path: package.json - hash: sha256:049326a853153ea930a49c1d083d5fa9a5eb5d05c3198f0322dbd831fe151b2e + hash: sha256:d1cc33f580e68ec3c3e5dfb95f152852d587472d086d55fa643e8aabd0c29f77 type: other - size: 2529 + size: 1445 - path: product/checklists/accessibility-wcag-checklist.md hash: sha256:56126182b25e9b7bdde43f75315e33167eb49b1f9a9cb0e9a37bc068af40aeab type: checklist diff --git a/.aiox-core/package.json b/.aiox-core/package.json index ea49119f36..d9a79ce12a 100644 --- a/.aiox-core/package.json +++ b/.aiox-core/package.json @@ -1,34 +1,11 @@ { - "name": "@aiox-fullstack/core", - "version": "4.31.1", - "description": "AIOX-FullStack Core - Meta-agent and component generation system", + "name": "@aiox-squads/core-internal", + "version": "5.2.6", + "description": "Internal package manifest for AIOX framework — declares runtime dependencies consumed by scripts under .aiox-core/. This is NOT published independently; it ships inside @aiox-squads/core (the top-level package). Kept name-distinct from the parent (`-internal` suffix) to avoid npm registry confusion. Version follows the parent package.", + "private": true, "main": "index.js", - "module": "index.esm.js", - "types": "index.d.ts", - "bin": { - "aiox-core": "bin/aiox-core.js" - }, - "files": [ - "lib/", - "bin/", - "templates/", - "utils/", - "tasks/", - "docs/", - "elicitation/", - "index.js", - "index.esm.js", - "index.d.ts", - "README.md", - "LICENSE" - ], "scripts": { - "build": "node ../tools/build-core.js", - "test": "npm run test:unit && npm run test:integration", - "test:unit": "jest tests/unit", - "test:integration": "jest tests/integration", - "lint": "eslint .", - "typecheck": "tsc --noEmit" + "test": "echo 'Use parent package test scripts'" }, "dependencies": { "ajv": "^8.17.1", @@ -47,39 +24,19 @@ "tar": "^7.5.7", "validator": "^13.15.15" }, - "peerDependencies": { - "@aiox-fullstack/memory": "^4.31.0", - "@aiox-fullstack/security": "^4.31.0", - "@aiox-fullstack/performance": "^4.31.0", - "@aiox-fullstack/telemetry": "^4.31.0" - }, - "peerDependenciesMeta": { - "@aiox-fullstack/memory": { - "optional": true - }, - "@aiox-fullstack/security": { - "optional": true - }, - "@aiox-fullstack/performance": { - "optional": true - }, - "@aiox-fullstack/telemetry": { - "optional": true - } - }, "keywords": [ "aiox", - "meta-agent", - "component-generation", + "aiox-squads", + "framework", "ai-orchestration", - "fullstack", - "development-tools" + "internal-manifest" ], - "author": "AIOX Fullstack Team", + "author": "AIOX Squads", "license": "MIT", "repository": { "type": "git", - "url": "git+https://github.com/SynkraAI/aiox-core.git" + "url": "git+https://github.com/SynkraAI/aiox-core.git", + "directory": ".aiox-core" }, "bugs": { "url": "https://github.com/SynkraAI/aiox-core/issues" @@ -88,21 +45,5 @@ "engines": { "node": ">=18.0.0", "npm": ">=9.0.0" - }, - "publishConfig": { - "access": "public", - "registry": "https://registry.npmjs.org/" - }, - "exports": { - ".": { - "types": "./index.d.ts", - "import": "./index.esm.js", - "require": "./index.js" - }, - "./templates": "./templates/", - "./utils": "./utils/", - "./tasks": "./tasks/", - "./docs": "./docs/", - "./elicitation": "./elicitation/" } } diff --git a/.claude/skills/AIOX/agents/devops/SKILL.md b/.claude/skills/AIOX/agents/devops/SKILL.md index bfc7f81715..c180143768 100644 --- a/.claude/skills/AIOX/agents/devops/SKILL.md +++ b/.claude/skills/AIOX/agents/devops/SKILL.md @@ -589,6 +589,19 @@ Type `*help` to see all commands. - ❌ Creating PR before quality gates pass - ❌ Skipping CodeRabbit CRITICAL issues +### Release Procedure (NON-NEGOTIABLE Reference) + +When invoked with `*release`, `*push` followed by version-bump intent, or any task that ends with a tag push to `@aiox-squads/*`, **load and follow `docs/guides/release-procedure.md` as the canonical SOP before touching anything**. It is the authoritative playbook — the task templates `publish-npm.md` and `release-management.md` are thin wrappers around it. + +The SOP captures lessons paid for in 11 patches across 30 days: +- Two-system branch protection on `main` (modern ruleset id `13330052` + legacy `required_pull_request_reviews`); `gh pr merge --admin` bypasses neither alone — you must relax both and restore both atomically with `trap EXIT` + sanitized payloads (raw GitHub API responses include read-only fields that PUT rejects). +- 4-site version bump coordination (`package.json`, `compat/aiox-core/package.json` + its dep, `packages/installer/package.json`, `package-lock.json` + `CHANGELOG.md`). +- The `publish_legacy_aiox_core` job depends on `publish` completing (compat wrapper transitively depends on the scoped package — race against npm CDN propagation has bitten us). +- npm propagation budget for the legacy smoke (240s with dual visibility check). +- Windows path escape in workflow `node -e` interpolations of `${{ github.workspace }}` (use env vars). + +Skipping the SOP because "it's just a patch release" is how the next 30-day patch storm starts. + ### Related Agents - **@dev (Dex)** - Delegates push operations to me diff --git a/.codex/agents/devops.md b/.codex/agents/devops.md index 41fca70e16..a6576998ee 100644 --- a/.codex/agents/devops.md +++ b/.codex/agents/devops.md @@ -579,6 +579,19 @@ Type `*help` to see all commands. - ❌ Creating PR before quality gates pass - ❌ Skipping CodeRabbit CRITICAL issues +### Release Procedure (NON-NEGOTIABLE Reference) + +When invoked with `*release`, `*push` followed by version-bump intent, or any task that ends with a tag push to `@aiox-squads/*`, **load and follow `docs/guides/release-procedure.md` as the canonical SOP before touching anything**. It is the authoritative playbook — the task templates `publish-npm.md` and `release-management.md` are thin wrappers around it. + +The SOP captures lessons paid for in 11 patches across 30 days: +- Two-system branch protection on `main` (modern ruleset id `13330052` + legacy `required_pull_request_reviews`); `gh pr merge --admin` bypasses neither alone — you must relax both and restore both atomically with `trap EXIT` + sanitized payloads (raw GitHub API responses include read-only fields that PUT rejects). +- 4-site version bump coordination (`package.json`, `compat/aiox-core/package.json` + its dep, `packages/installer/package.json`, `package-lock.json` + `CHANGELOG.md`). +- The `publish_legacy_aiox_core` job depends on `publish` completing (compat wrapper transitively depends on the scoped package — race against npm CDN propagation has bitten us). +- npm propagation budget for the legacy smoke (240s with dual visibility check). +- Windows path escape in workflow `node -e` interpolations of `${{ github.workspace }}` (use env vars). + +Skipping the SOP because "it's just a patch release" is how the next 30-day patch storm starts. + ### Related Agents - **@dev (Dex)** - Delegates push operations to me diff --git a/.gemini/rules/AIOX/agents/devops.md b/.gemini/rules/AIOX/agents/devops.md index 41fca70e16..a6576998ee 100644 --- a/.gemini/rules/AIOX/agents/devops.md +++ b/.gemini/rules/AIOX/agents/devops.md @@ -579,6 +579,19 @@ Type `*help` to see all commands. - ❌ Creating PR before quality gates pass - ❌ Skipping CodeRabbit CRITICAL issues +### Release Procedure (NON-NEGOTIABLE Reference) + +When invoked with `*release`, `*push` followed by version-bump intent, or any task that ends with a tag push to `@aiox-squads/*`, **load and follow `docs/guides/release-procedure.md` as the canonical SOP before touching anything**. It is the authoritative playbook — the task templates `publish-npm.md` and `release-management.md` are thin wrappers around it. + +The SOP captures lessons paid for in 11 patches across 30 days: +- Two-system branch protection on `main` (modern ruleset id `13330052` + legacy `required_pull_request_reviews`); `gh pr merge --admin` bypasses neither alone — you must relax both and restore both atomically with `trap EXIT` + sanitized payloads (raw GitHub API responses include read-only fields that PUT rejects). +- 4-site version bump coordination (`package.json`, `compat/aiox-core/package.json` + its dep, `packages/installer/package.json`, `package-lock.json` + `CHANGELOG.md`). +- The `publish_legacy_aiox_core` job depends on `publish` completing (compat wrapper transitively depends on the scoped package — race against npm CDN propagation has bitten us). +- npm propagation budget for the legacy smoke (240s with dual visibility check). +- Windows path escape in workflow `node -e` interpolations of `${{ github.workspace }}` (use env vars). + +Skipping the SOP because "it's just a patch release" is how the next 30-day patch storm starts. + ### Related Agents - **@dev (Dex)** - Delegates push operations to me diff --git a/.kimi/skills/aiox-devops/SKILL.md b/.kimi/skills/aiox-devops/SKILL.md index 5ebdcb1218..8e79b9e047 100644 --- a/.kimi/skills/aiox-devops/SKILL.md +++ b/.kimi/skills/aiox-devops/SKILL.md @@ -663,6 +663,19 @@ Type `*help` to see all commands. - ❌ Creating PR before quality gates pass - ❌ Skipping CodeRabbit CRITICAL issues +### Release Procedure (NON-NEGOTIABLE Reference) + +When invoked with `*release`, `*push` followed by version-bump intent, or any task that ends with a tag push to `@aiox-squads/*`, **load and follow `docs/guides/release-procedure.md` as the canonical SOP before touching anything**. It is the authoritative playbook — the task templates `publish-npm.md` and `release-management.md` are thin wrappers around it. + +The SOP captures lessons paid for in 11 patches across 30 days: +- Two-system branch protection on `main` (modern ruleset id `13330052` + legacy `required_pull_request_reviews`); `gh pr merge --admin` bypasses neither alone — you must relax both and restore both atomically with `trap EXIT` + sanitized payloads (raw GitHub API responses include read-only fields that PUT rejects). +- 4-site version bump coordination (`package.json`, `compat/aiox-core/package.json` + its dep, `packages/installer/package.json`, `package-lock.json` + `CHANGELOG.md`). +- The `publish_legacy_aiox_core` job depends on `publish` completing (compat wrapper transitively depends on the scoped package — race against npm CDN propagation has bitten us). +- npm propagation budget for the legacy smoke (240s with dual visibility check). +- Windows path escape in workflow `node -e` interpolations of `${{ github.workspace }}` (use env vars). + +Skipping the SOP because "it's just a patch release" is how the next 30-day patch storm starts. + ### Related Agents - **@dev (Dex)** - Delegates push operations to me diff --git a/bin/utils/validate-publish.js b/bin/utils/validate-publish.js index e041aebcda..6b03783a10 100644 --- a/bin/utils/validate-publish.js +++ b/bin/utils/validate-publish.js @@ -16,7 +16,7 @@ const fs = require('fs'); const path = require('path'); -const { execSync } = require('child_process'); +const { execSync, execFileSync } = require('child_process'); const PROJECT_ROOT = path.join(__dirname, '..', '..'); const MIN_FILE_COUNT = 50; @@ -116,7 +116,7 @@ console.log('--- Dependency Completeness (INS-4.12) ---\n'); try { const depValidatorPath = path.join(PROJECT_ROOT, 'scripts', 'validate-aiox-core-deps.js'); if (fs.existsSync(depValidatorPath)) { - execSync(`node "${depValidatorPath}"`, { + execFileSync('node', [depValidatorPath], { encoding: 'utf8', cwd: PROJECT_ROOT, timeout: 30000, @@ -132,6 +132,34 @@ try { passed = false; } +// Check 5 (#739 Bug 2 follow-up): .aiox-core/package.json namespace + version sync +// +// Fail-closed: this validator is required, not optional. If it's missing +// from the working tree we ABORT the publish — historically the silent-skip +// pattern is what let the namespace drift ship in the first place. +console.log(''); +console.log('--- Internal Manifest Namespace Sync (Issue #739) ---\n'); +const nsValidatorPath = path.join(PROJECT_ROOT, 'scripts', 'validate-aiox-core-namespace.js'); +if (!fs.existsSync(nsValidatorPath)) { + console.error('FAIL: scripts/validate-aiox-core-namespace.js is required but not found'); + console.error(' This validator was introduced for Issue #739 Bug 2 and is mandatory.'); + console.error(' Restore the file or revert the deletion that removed it.'); + passed = false; +} else { + try { + execFileSync('node', [nsValidatorPath], { + encoding: 'utf8', + cwd: PROJECT_ROOT, + timeout: 10000, + stdio: 'inherit', + }); + } catch (_nsErr) { + console.error('FAIL: .aiox-core/package.json namespace/version drift detected'); + console.error(' Fix: Run "node scripts/validate-aiox-core-namespace.js" to see details'); + passed = false; + } +} + // Summary console.log(''); if (passed) { diff --git a/package.json b/package.json index 101b52776d..2cd19e9520 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,8 @@ "sync:ide:cursor": "node .aiox-core/infrastructure/scripts/ide-sync/index.js sync --ide cursor", "validate:publish": "node bin/utils/validate-publish.js", "prepublishOnly": "node bin/utils/validate-publish.js && npm run generate:manifest && npm run validate:manifest", - "prepare": "husky" + "prepare": "husky", + "validate:aiox-core-namespace": "node scripts/validate-aiox-core-namespace.js" }, "dependencies": { "@clack/prompts": "^0.11.0", diff --git a/scripts/validate-aiox-core-namespace.js b/scripts/validate-aiox-core-namespace.js new file mode 100755 index 0000000000..4320d16960 --- /dev/null +++ b/scripts/validate-aiox-core-namespace.js @@ -0,0 +1,96 @@ +#!/usr/bin/env node +/** + * .aiox-core/package.json namespace + version sync validator + * + * Story #739 (Bug 2 follow-up): the internal `.aiox-core/package.json` + * manifest drifted to the legacy `@aiox-fullstack/core@4.31.1` namespace + * while the surface package moved to `@aiox-squads/core@5.x`. Several + * releases shipped stale internal metadata that confused tooling and + * misled operators investigating upgrade issues. + * + * This validator runs in the pre-publish surface to catch the drift + * before it ships again. + * + * Validation rules: + * 1. `.aiox-core/package.json` MUST exist. + * 2. `name` MUST end with `-internal` (it is NOT a published package on + * its own — `private: true` + suffix avoids npm registry confusion + * with the parent surface). + * 3. `private` MUST be true. + * 4. `version` MUST equal the root `package.json` version (single source + * of truth: the parent surface drives the framework version). + * 5. No `peerDependencies` referencing the legacy `@aiox-fullstack/*` + * namespace. + * + * Exit codes: 0 = PASS, 1 = FAIL + * Usage: node scripts/validate-aiox-core-namespace.js + */ + +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +const ROOT = path.resolve(__dirname, '..'); +const INTERNAL_PKG = path.join(ROOT, '.aiox-core', 'package.json'); +const ROOT_PKG = path.join(ROOT, 'package.json'); + +function fail(msg) { + console.error(`FAIL: ${msg}`); + process.exit(1); +} + +function main() { + if (!fs.existsSync(INTERNAL_PKG)) { + fail('.aiox-core/package.json not found'); + } + if (!fs.existsSync(ROOT_PKG)) { + fail('root package.json not found'); + } + + const internal = JSON.parse(fs.readFileSync(INTERNAL_PKG, 'utf8')); + const root = JSON.parse(fs.readFileSync(ROOT_PKG, 'utf8')); + + if (!internal.name) { + fail('.aiox-core/package.json missing `name` field'); + } + const EXPECTED_SCOPE = '@aiox-squads/'; + if (!internal.name.startsWith(EXPECTED_SCOPE)) { + fail( + `.aiox-core/package.json name "${internal.name}" must start with "${EXPECTED_SCOPE}" ` + + '(current org scope — names like `@aiox-fullstack/*` are legacy, see Story #739)', + ); + } + if (!internal.name.endsWith('-internal')) { + fail( + `.aiox-core/package.json name "${internal.name}" must end with "-internal" ` + + '(internal manifest, not a separately-published package — see Story #739)', + ); + } + if (internal.private !== true) { + fail('.aiox-core/package.json must declare `"private": true` (internal-only)'); + } + if (internal.version !== root.version) { + fail( + `version drift: .aiox-core/package.json version "${internal.version}" ` + + `does not match root package.json version "${root.version}". ` + + 'They must move in lockstep — root is SOT.', + ); + } + + const peerDeps = internal.peerDependencies || {}; + const legacyPeers = Object.keys(peerDeps).filter((d) => d.startsWith('@aiox-fullstack/')); + if (legacyPeers.length > 0) { + fail( + `legacy @aiox-fullstack/* peerDependencies in .aiox-core/package.json: ${legacyPeers.join(', ')}. ` + + 'These packages do not exist; drop the peerDependencies block or rename to the current namespace.', + ); + } + + console.log( + `PASS: .aiox-core/package.json is in sync with root (name=${internal.name}, version=${internal.version})`, + ); + process.exit(0); +} + +main();