diff --git a/.github/workflows/substrate-sync.yml b/.github/workflows/substrate-sync.yml new file mode 100644 index 0000000..c961108 --- /dev/null +++ b/.github/workflows/substrate-sync.yml @@ -0,0 +1,42 @@ +# Asserts the agent skill substrate is actually reachable in this checkout. +# +# Skills arrive as an npm dependency (`neo-agent-skills`) and are projected into `.claude/skills` +# by that package's postinstall linker, as symlinks into `node_modules`. No skill bytes are +# committed here, so there is nothing to compare trees against — the only question worth asking is +# whether the projection happened. +# +# It is worth asking because it can silently not happen: `npm ci --ignore-scripts` skips both +# `postinstall` and `prepare`, and is already deliberate practice in three of this repo's workflows. +# That yields a resolved dependency and zero reachable skills — dependency resolution is not the +# same as skills being reachable, and only this check tells them apart. +# +# Freshness is deliberately NOT checked here. `npm outdated` and dependabot are the ecosystem-native +# surface; a bespoke lag gate is the machinery class that got the previous design rebuilt. + +name: substrate-sync + +permissions: + contents: read + +# No path filter, deliberately: a path-skipped workflow reports *pending* rather than success and can +# therefore never be bound as a required status check. +on: + pull_request: + push: + branches: [main] + +jobs: + substrate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '24' + + - name: Install + run: npm ci + + - name: Assert skills are materialized and unshadowed + run: npx --no-install neo-agent-skills-materialize --check diff --git a/.gitignore b/.gitignore index a938d02..08099d8 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,9 @@ chroma-neo-memory-core/ # Playwright test results test/playwright/test-results/ # Single-file Playwright runs via npx -test-results/ \ No newline at end of file +test-results/ +# Skill substrate arrives as the neo-agent-skills npm dependency and is materialized by its +# postinstall linker as symlinks into node_modules. Both paths are projection, never committed +# bytes (neomjs/neo#17798). +.agents/skills +.claude/skills/ diff --git a/package-lock.json b/package-lock.json index 2252d17..695261c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "marked": "^18.0.5", "mermaid": "^11.16.0", "monaco-editor": "0.50.0", + "neo-agent-skills": "^0.1.1", "parse5": "^8.0.1", "postcss": "^8.5.16", "sass": "^1.101.0", @@ -6130,6 +6131,19 @@ "node": ">= 0.6" } }, + "node_modules/neo-agent-skills": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/neo-agent-skills/-/neo-agent-skills-0.1.1.tgz", + "integrity": "sha512-y6cgogGzPwdhxj32FyjLae3Ld/qeiX48UZeIgEazLGSH2YQLwS6YoZV236Wu9hWhPrcAFP9AmA+rB4YMKBummA==", + "dev": true, + "license": "MIT", + "bin": { + "neo-agent-skills-materialize": "scripts/materialize-harness-skills.mjs" + }, + "engines": { + "node": ">=24.0.0" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", diff --git a/package.json b/package.json index 6d21984..9bdab74 100644 --- a/package.json +++ b/package.json @@ -4,70 +4,71 @@ "private": true, "type": "module", "scripts": { - "postinstall" : "node ./buildScripts/linkMarkedForWorkerScope.mjs && node ./buildScripts/pullDevIndexData.mjs", - "add-config" : "node ./node_modules/neo.mjs/buildScripts/create/addConfig.mjs", - "build-all" : "node ./node_modules/neo.mjs/buildScripts/build/all.mjs -f -n", - "build-all-questions" : "node ./node_modules/neo.mjs/buildScripts/build/all.mjs -f", - "build-dist-esm" : "node ./node_modules/neo.mjs/buildScripts/build/esmodules.mjs", - "build-highlightjs" : "node ./node_modules/neo.mjs/buildScripts/build/highlightJs.mjs", - "build-themes" : "node ./node_modules/neo.mjs/buildScripts/build/themes.mjs -f", - "build-threads" : "node ./node_modules/neo.mjs/buildScripts/webpack/buildThreads.mjs -f", - "bundle-parse5" : "node ./node_modules/neo.mjs/buildScripts/build/parse5.mjs", - "check-data-tracking" : "node ./buildScripts/checkDataTracking.mjs", - "check-reactive-tags" : "node ./node_modules/neo.mjs/buildScripts/helpers/checkReactiveTags.mjs", - "convert-design-tokens" : "node ./node_modules/neo.mjs/buildScripts/helpers/convertDesignTokens.mjs", - "create-app" : "node ./node_modules/neo.mjs/buildScripts/create/app.mjs", - "create-app-minimal" : "node ./node_modules/neo.mjs/buildScripts/create/appMinimal.mjs", - "create-class" : "node ./node_modules/neo.mjs/buildScripts/create/class.mjs", - "create-component" : "node ./node_modules/neo.mjs/buildScripts/create/component.mjs", - "devindex:add" : "node ./apps/devindex/services/cli.mjs add", - "devindex:cleanup" : "node ./apps/devindex/services/cli.mjs cleanup", - "devindex:optin" : "node ./apps/devindex/services/cli.mjs optin", - "devindex:pull-data" : "node ./buildScripts/pullDevIndexData.mjs", - "devindex:optout" : "node ./apps/devindex/services/cli.mjs optout", - "devindex:spider" : "node ./apps/devindex/services/cli.mjs spider", - "devindex:update" : "node ./apps/devindex/services/cli.mjs update --limit 200", - "generate-docs-json" : "node ./node_modules/neo.mjs/buildScripts/docs/jsdocx.mjs", - "server-start" : "webpack serve -c ./node_modules/neo.mjs/buildScripts/webpack/webpack.server.config.mjs --open", - "test-e2e" : "playwright test -c test/playwright/playwright.config.e2e.mjs", - "test-unit" : "playwright test -c test/playwright/playwright.config.unit.mjs", - "watch-themes" : "node ./node_modules/neo.mjs/buildScripts/helpers/watchThemes.mjs" + "postinstall": "node ./buildScripts/linkMarkedForWorkerScope.mjs && node ./buildScripts/pullDevIndexData.mjs && neo-agent-skills-materialize", + "add-config": "node ./node_modules/neo.mjs/buildScripts/create/addConfig.mjs", + "build-all": "node ./node_modules/neo.mjs/buildScripts/build/all.mjs -f -n", + "build-all-questions": "node ./node_modules/neo.mjs/buildScripts/build/all.mjs -f", + "build-dist-esm": "node ./node_modules/neo.mjs/buildScripts/build/esmodules.mjs", + "build-highlightjs": "node ./node_modules/neo.mjs/buildScripts/build/highlightJs.mjs", + "build-themes": "node ./node_modules/neo.mjs/buildScripts/build/themes.mjs -f", + "build-threads": "node ./node_modules/neo.mjs/buildScripts/webpack/buildThreads.mjs -f", + "bundle-parse5": "node ./node_modules/neo.mjs/buildScripts/build/parse5.mjs", + "check-data-tracking": "node ./buildScripts/checkDataTracking.mjs", + "check-reactive-tags": "node ./node_modules/neo.mjs/buildScripts/helpers/checkReactiveTags.mjs", + "convert-design-tokens": "node ./node_modules/neo.mjs/buildScripts/helpers/convertDesignTokens.mjs", + "create-app": "node ./node_modules/neo.mjs/buildScripts/create/app.mjs", + "create-app-minimal": "node ./node_modules/neo.mjs/buildScripts/create/appMinimal.mjs", + "create-class": "node ./node_modules/neo.mjs/buildScripts/create/class.mjs", + "create-component": "node ./node_modules/neo.mjs/buildScripts/create/component.mjs", + "devindex:add": "node ./apps/devindex/services/cli.mjs add", + "devindex:cleanup": "node ./apps/devindex/services/cli.mjs cleanup", + "devindex:optin": "node ./apps/devindex/services/cli.mjs optin", + "devindex:pull-data": "node ./buildScripts/pullDevIndexData.mjs", + "devindex:optout": "node ./apps/devindex/services/cli.mjs optout", + "devindex:spider": "node ./apps/devindex/services/cli.mjs spider", + "devindex:update": "node ./apps/devindex/services/cli.mjs update --limit 200", + "generate-docs-json": "node ./node_modules/neo.mjs/buildScripts/docs/jsdocx.mjs", + "server-start": "webpack serve -c ./node_modules/neo.mjs/buildScripts/webpack/webpack.server.config.mjs --open", + "test-e2e": "playwright test -c test/playwright/playwright.config.e2e.mjs", + "test-unit": "playwright test -c test/playwright/playwright.config.unit.mjs", + "watch-themes": "node ./node_modules/neo.mjs/buildScripts/helpers/watchThemes.mjs" }, "dependencies": { "neo.mjs": "^13.1.0" }, "devDependencies": { "@fortawesome/fontawesome-free": "^7.3.0", - "@playwright/test" : "^1.61.1", - "acorn" : "^8.17.0", - "astring" : "^1.9.0", - "autoprefixer" : "^10.5.2", - "chalk" : "^5.6.2", - "commander" : "^15.0.0", - "cssnano" : "^7.1.9", - "dotenv" : "^17.4.2", - "envinfo" : "^7.21.0", - "esbuild" : "^0.28.1", - "fast-glob" : "^3.3.3", - "fs-extra" : "^11.3.6", - "gray-matter" : "^4.0.3", - "highlightjs-line-numbers.js" : "^2.9.1", - "html-minifier-terser" : "^7.2.0", - "inquirer" : "^13.4.3", - "js-yaml" : "^5.2.0", - "jsdoc-api" : "^9.3.6", - "marked" : "^18.0.5", - "mermaid" : "^11.16.0", - "monaco-editor" : "0.50.0", - "parse5" : "^8.0.1", - "postcss" : "^8.5.16", - "sass" : "^1.101.0", - "terser" : "^5.48.0", - "url" : "^0.11.4", - "webpack" : "^5.108.3", - "webpack-cli" : "^7.1.0", - "webpack-dev-server" : "^6.0.0", - "webpack-hook-plugin" : "^1.0.7", - "ws" : "^8.21.0" + "@playwright/test": "^1.61.1", + "acorn": "^8.17.0", + "astring": "^1.9.0", + "autoprefixer": "^10.5.2", + "chalk": "^5.6.2", + "commander": "^15.0.0", + "cssnano": "^7.1.9", + "dotenv": "^17.4.2", + "envinfo": "^7.21.0", + "esbuild": "^0.28.1", + "fast-glob": "^3.3.3", + "fs-extra": "^11.3.6", + "gray-matter": "^4.0.3", + "highlightjs-line-numbers.js": "^2.9.1", + "html-minifier-terser": "^7.2.0", + "inquirer": "^13.4.3", + "js-yaml": "^5.2.0", + "jsdoc-api": "^9.3.6", + "marked": "^18.0.5", + "mermaid": "^11.16.0", + "monaco-editor": "0.50.0", + "neo-agent-skills": "^0.1.1", + "parse5": "^8.0.1", + "postcss": "^8.5.16", + "sass": "^1.101.0", + "terser": "^5.48.0", + "url": "^0.11.4", + "webpack": "^5.108.3", + "webpack-cli": "^7.1.0", + "webpack-dev-server": "^6.0.0", + "webpack-hook-plugin": "^1.0.7", + "ws": "^8.21.0" } }