23f7624596
🔄 Automated Rollback Manager / 🔄 Execute Rollback (push) Blocked by required conditions
🔄 Automated Rollback Manager / ✅ Post-Rollback Verification (push) Blocked by required conditions
🔄 Automated Rollback Manager / 📊 Rollback Monitoring (push) Blocked by required conditions
🔄 Automated Rollback Manager / ⏳ Manual Rollback Approval (push) Blocked by required conditions
V3 CI/CD Pipeline / MCP protocol smoke / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Memory import smoke / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / windows-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / windows-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / macos-latest (push) Waiting to run
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / windows-latest (push) Waiting to run
V3 CI/CD Pipeline / Witness verify (signed manifest) / macos-latest (push) Blocked by required conditions
V3 CI/CD Pipeline / Witness verify (signed manifest) / ubuntu-latest (push) Blocked by required conditions
V3 CI/CD Pipeline / Witness verify (signed manifest) / windows-latest (push) Blocked by required conditions
V3 CI/CD Pipeline / Publish to npm (alpha) (push) Blocked by required conditions
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / macos-latest / Node 22 (push) Waiting to run
V3 CI/CD Pipeline / Plugin hooks smoke / macos-latest / Node 22 (push) Waiting to run
ADR-166 MCP Bridge Security Lock / Static-source security lock (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / Compose default binds loopback + Mongo has auth (push) Failing after 2s
CodeQL Advanced / Analyze (rust) (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / plugin-agent-federation bindHost default (push) Failing after 1s
ADR-166 MCP Bridge Security Lock / Runtime behavior — 401 + terminal gate + fail-closed (push) Failing after 4s
business-pods-smoke / smoke (push) Failing after 1s
all-plugins-smoke / smoke-all (push) Failing after 2s
CI/CD Pipeline / Security & Code Quality (push) Failing after 1s
CI/CD Pipeline / Test Suite (ubuntu-latest) (push) Failing after 1s
CI/CD Pipeline / Build & Package (macos-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (ubuntu-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (windows-latest) (push) Has been skipped
CI/CD Pipeline / Deploy & Release (push) Waiting to run
CI/CD Pipeline / CI Status (push) Waiting to run
CI/CD Pipeline / Documentation & Examples (push) Failing after 1s
Clone Tracker (14-day rolling) / Snapshot clones for ruflo ecosystem (push) Failing after 1s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
federation-peer-rust / stable-noop (push) Failing after 1s
metaharness-ci / score (push) Failing after 1s
metaharness-ci / router-compat (push) Failing after 0s
metaharness-ci / similarity-tests (push) Failing after 0s
no-agentbbs-smoke / smoke-without-agentbbs (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (windows-latest) (push) Has been skipped
codex-integration-audit / Codex integration audit (push) Failing after 1s
helpers-manifest-guard / guard (push) Failing after 1s
🔗 Cross-Agent Integration Tests / 🤝 Agent Coordination Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🧠 Memory Sharing Integration (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🛡️ Fault Tolerance Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / ⚡ Performance Integration Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 📊 Integration Test Report (push) Waiting to run
metaharness-ci / mcp-scan (push) Failing after 1s
metaharness-ci / eject-dryrun (push) Failing after 1s
metaharness-ci / metaharness-real-data (push) Failing after 0s
no-cli-optdep-bloat-2561 / guard (push) Failing after 1s
no-metaharness-smoke / smoke-without-metaharness (push) Failing after 1s
no-phantom-agentic-flow-subpath / guard (push) Failing after 1s
🔄 Automated Rollback Manager / 🚨 Failure Detection (push) Failing after 1s
V3 CI/CD Pipeline / Plugin hooks smoke / ubuntu-latest / Node 22 (push) Failing after 1s
V3 CI/CD Pipeline / ruflo-graph-intelligence build + test smoke (#2044, ADR-123) (push) Failing after 1s
CVE Audit Gate / Audit root (critical-blocking) (push) Failing after 2s
cost-tracker-smoke / smoke (push) Failing after 3s
oia-audit-weekly / audit (push) Failing after 2s
ruflo-agent-smoke / ruflo-agent structural smoke (push) Failing after 1s
📊 Status Badges Update / 📊 Update Status Badges (push) Failing after 1s
V3 CI/CD Pipeline / Static regression guards (#2267 YAML + (push) Failing after 1s
V3 CI/CD Pipeline / Test V3 Packages (push) Failing after 0s
V3 CI/CD Pipeline / agent_execute provider routing smoke (#2042) (push) Failing after 0s
CVE Audit Gate / Audit v3 (critical-blocking) (push) Failing after 1s
federation-peer-rust / stable-native (push) Failing after 2s
🔗 Cross-Agent Integration Tests / 🚀 Integration Test Setup (push) Failing after 2s
neural-trader-smoke / runtime-smoke (push) Failing after 1s
🔄 Automated Rollback Manager / 🔍 Pre-Rollback Validation (push) Waiting to run
V3 CI/CD Pipeline / Build V3 (macos-latest) (push) Has been skipped
V3 CI/CD Pipeline / Build V3 (ubuntu-latest) (push) Has been skipped
V3 CI/CD Pipeline / Type Check V3 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 24 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 22 (push) Failing after 2s
V3 CI/CD Pipeline / browser rvf create flag smoke (#2015) (push) Failing after 0s
V3 CI/CD Pipeline / Dependency review (#2046) (push) Has been skipped
V3 CI/CD Pipeline / Supply-chain audit (#2046) (push) Failing after 0s
V3 CI/CD Pipeline / witness marker drift smoke (#2021) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader backtest signing smoke (#2068, ADR-126 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / kg-extract type-import classification smoke (#2049) (push) Failing after 0s
V3 CI/CD Pipeline / witness verify precondition smoke (#1880) (push) Failing after 2s
V3 CI/CD Pipeline / neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5) (push) Failing after 0s
V3 CI/CD Pipeline / neural-trader feature attribution smoke (#2068, ADR-126 Phase 6) (push) Failing after 0s
V3 CI/CD Pipeline / plugin-registry signature verification smoke (#1922, CWE-347) (push) Failing after 4s
V3 CI/CD Pipeline / memory stats legacy-DB smoke (#2120) (push) Failing after 4s
V3 CI/CD Pipeline / github deprecated actions smoke (#2089, ADR-127 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / graph query + pathfinder smoke (ADR-130 P2+P5) (push) Has been skipped
V3 CI/CD Pipeline / graph trajectory hooks smoke (ADR-130 P3) (push) Has been skipped
V3 CI/CD Pipeline / graph plugin adapter smoke (ADR-130 P4) (push) Has been skipped
V3 CI/CD Pipeline / graph benchmark (ADR-130 P6) (push) Has been skipped
V3 CI/CD Pipeline / statusline generator delegation smoke (#2195) (push) Failing after 1s
V3 CI/CD Pipeline / wizard init regression guard (#2206 (push) Failing after 1s
V3 CI/CD Pipeline / memory no-stray-db smoke (ADR-125 P7) (push) Failing after 1s
V3 CI/CD Pipeline / github-safe injection smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github actions pin smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github attribution opt-in smoke (#2089, ADR-127 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / pre-bash hook safety smoke (#2017) (push) Failing after 1s
V3 CI/CD Pipeline / Memory import smoke / ubuntu-latest (push) Failing after 0s
V3 CI/CD Pipeline / MCP protocol smoke / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / ruvllm WASM auto-init smoke (#2086) (push) Failing after 4s
V3 CI/CD Pipeline / MCP paired-tool round-trip smoke (#1889) (push) Failing after 1s
V3 CI/CD Pipeline / Plugin package install-safety (#1902/#1903/#1904) (push) Failing after 1s
V3 CI/CD Pipeline / Tool description discoverability (ADR-112) (push) Failing after 3s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (22) (push) Failing after 1s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (24) (push) Failing after 1s
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Vector-index dimension audit (#1947) (push) Failing after 0s
V3 CI/CD Pipeline / Hook-command install safety (#1921) (push) Failing after 1s
V3 CI/CD Pipeline / ToolOutputGuardrail smoke (ADR-131, (push) Failing after 1s
V3 CI/CD Pipeline / init-bundle invariants smoke (#2095, ADR-128 Phase 5) (push) Failing after 1s
V3 CI/CD Pipeline / wasm provider bridge smoke (ADR-129 P1) (push) Failing after 2s
V3 CI/CD Pipeline / wasm gallery CRUD smoke (ADR-129 P3) (push) Failing after 1s
V3 CI/CD Pipeline / wasm plugin bridge smoke (ADR-129 P4) (push) Failing after 0s
V3 CI/CD Pipeline / wasm compose smoke (ADR-129 P2) (push) Failing after 4s
V3 CI/CD Pipeline / graph schema smoke (ADR-130 P1) (push) Failing after 0s
Validate Marketplace / validate (push) Failing after 1s
🔍 Verification Pipeline / 🚀 Setup Verification (push) Failing after 1s
🔍 Verification Pipeline / 🛡️ Security Verification (push) Has been skipped
🔍 Verification Pipeline / 📝 Code Quality (push) Has been skipped
🔍 Verification Pipeline / 🧪 Test Verification (${{ matrix.os }}, Node ${{ matrix.node }}) (push) Has been skipped
🔍 Verification Pipeline / 🏗️ Build Verification (push) Has been skipped
🔍 Verification Pipeline / 📚 Documentation Verification (push) Has been skipped
🔍 Verification Pipeline / ⚡ Performance Verification (push) Waiting to run
🔍 Verification Pipeline / 📊 Verification Report (push) Waiting to run
CVE Audit Gate / High-severity report (warn only) (push) Has been cancelled
2707 lines
114 KiB
YAML
2707 lines
114 KiB
YAML
name: V3 CI/CD Pipeline
|
||
|
||
on:
|
||
push:
|
||
branches: [main, develop, v3]
|
||
paths:
|
||
- 'v3/**'
|
||
- '.github/workflows/v3-ci.yml'
|
||
# Witness-verify + plugin-hooks-smoke depend on these scripts;
|
||
# path filter keeps CI in sync with their changes.
|
||
- 'plugins/ruflo-core/scripts/witness/**'
|
||
- 'plugins/ruflo-core/scripts/test-hooks.mjs'
|
||
- 'verification/**'
|
||
# scripts/*.mjs audits (tool-descriptions, plugin-packages, hook-commands)
|
||
- 'scripts/**'
|
||
# hook-command audit (#1921) — every plugin hooks.json + the ruflo-hook shims
|
||
- '**/hooks/hooks.json'
|
||
- '**/scripts/ruflo-hook.sh'
|
||
# pre-bash hook safety (#2017) — both handler copies trigger the smoke
|
||
- '**/.claude/helpers/hook-handler.cjs'
|
||
# ruflo-browser rvf create flag (#2015) — TS source, plugin shell
|
||
# scripts, agent-facing recipes all guarded by the same smoke.
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/browser-session-tools.ts'
|
||
- 'plugins/ruflo-browser/**'
|
||
# ruflo-graph-intelligence (#2044, ADR-123) — outside v3 workspace,
|
||
# has its own lockfile + tests; needs to be CI-guarded on every change.
|
||
- 'plugins/ruflo-graph-intelligence/**'
|
||
# Supply-chain hardening (#2046) — every package.json + lockfile +
|
||
# allowlist edit triggers the supply-chain audit.
|
||
- '**/package.json'
|
||
- '**/package-lock.json'
|
||
- '**/pnpm-lock.yaml'
|
||
- '.github/supply-chain/**'
|
||
- 'scripts/audit-supply-chain.mjs'
|
||
# Knowledge-graph plugin (#2049) — kg-extract type-import classifier
|
||
# + kg-traverse controller wiring drift fast when SKILL.md edits
|
||
# silently revert the bug-fix shape.
|
||
- 'plugins/ruflo-knowledge-graph/**'
|
||
- 'scripts/smoke-kg-extract-type-imports.mjs'
|
||
# Neural-trader portfolio CG (#2068, ADR-126 Phase 3) — drift fast
|
||
# when the adapter, skill, or runtime mirror diverge from the
|
||
# ADR-123 Wedge 8 contract.
|
||
- 'plugins/ruflo-neural-trader/src/sublinear-adapter.ts'
|
||
- 'plugins/ruflo-neural-trader/src/sublinear-adapter.mjs'
|
||
- 'plugins/ruflo-neural-trader/skills/trader-portfolio-cg/**'
|
||
- 'scripts/smoke-neural-trader-portfolio-cg.mjs'
|
||
# Neural-trader backtest signing (#2068, ADR-126 Phase 4) — Ed25519
|
||
# tamper-evidence for paper→live promotion; verifier MUST pin to a
|
||
# trusted key (CWE-347 / #1922 pattern).
|
||
- 'plugins/ruflo-neural-trader/src/signed-artifact.ts'
|
||
- 'plugins/ruflo-neural-trader/src/signed-artifact.mjs'
|
||
- 'plugins/ruflo-neural-trader/skills/trader-backtest/**'
|
||
- 'plugins/ruflo-neural-trader/skills/trader-cloud-backtest/**'
|
||
- 'scripts/smoke-neural-trader-backtest-signing.mjs'
|
||
# Neural-trader SendMessage risk-gate pipeline (#2068, ADR-126 Phase 5) —
|
||
# structural gate: trading-strategist refuses --broker without an
|
||
# explicit risk-analyst RiskDecision approval.
|
||
- 'plugins/ruflo-neural-trader/src/pipeline-messages.ts'
|
||
- 'plugins/ruflo-neural-trader/agents/market-analyst.md'
|
||
- 'plugins/ruflo-neural-trader/agents/trading-strategist.md'
|
||
- 'plugins/ruflo-neural-trader/agents/risk-analyst.md'
|
||
- 'plugins/ruflo-neural-trader/agents/backtest-engineer.md'
|
||
- 'scripts/smoke-neural-trader-pipeline.mjs'
|
||
# Neural-trader feature attribution (#2068, ADR-126 Phase 6) —
|
||
# regulator-grade interpretability via single-entry PageRank.
|
||
# Same signing scheme as Phase 4; ranking is seed-reproducible.
|
||
- 'plugins/ruflo-neural-trader/src/signed-attribution.ts'
|
||
- 'plugins/ruflo-neural-trader/src/signed-attribution.mjs'
|
||
- 'plugins/ruflo-neural-trader/skills/trader-explain/**'
|
||
- 'scripts/smoke-neural-trader-feature-attribution.mjs'
|
||
# Plugin-registry CWE-347 regression smoke (#1922) — `discovery.ts`
|
||
# signature verifier + the smoke fixture must stay in lockstep.
|
||
- 'v3/@claude-flow/cli/src/plugins/store/discovery.ts'
|
||
- 'v3/@claude-flow/cli/src/transfer/ipfs/client.ts'
|
||
- 'v3/@claude-flow/cli/scripts/publish-registry.ts'
|
||
- 'scripts/smoke-plugin-registry-signature.mjs'
|
||
# ruvllm WASM auto-init regression smoke (#2086) — the
|
||
# `loadRuvllmWasm()` helper in `ruvllm-tools.ts` and the
|
||
# `ruvllm_status` un-init diagnostic path must stay in lockstep.
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/ruvllm-tools.ts'
|
||
- 'v3/@claude-flow/cli/src/ruvector/ruvllm-wasm.ts'
|
||
- 'scripts/smoke-ruvllm-wasm-auto-init.mjs'
|
||
# agent_execute provider routing (#2042) — executeAgentTask must
|
||
# not regress to inline Anthropic fetch, and the OpenRouter branch
|
||
# in callAnthropicMessages must stay wired.
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/agent-execute-core.ts'
|
||
- 'scripts/smoke-agent-execute-providers.mjs'
|
||
# memory stats legacy-DB regression guard (#2120) — the WHERE
|
||
# status='active' filter must accept NULL too, and the schema
|
||
# backfill must promote NULL→'active' on existing DBs.
|
||
- 'v3/@claude-flow/cli/src/memory/memory-bridge.ts'
|
||
- 'v3/@claude-flow/cli/src/memory/memory-initializer.ts'
|
||
- 'v3/@claude-flow/cli/src/commands/status.ts'
|
||
- 'scripts/smoke-memory-stats-legacy-db.mjs'
|
||
# ADR-125 Phase 7 — no stray DB artifacts after `npm test` in
|
||
# @claude-flow/memory. vitest.setup.ts must wipe *.db / *.rvf /
|
||
# *.redb files written by agentdb / @ruvector/rvf bindings.
|
||
- 'v3/@claude-flow/memory/vitest.setup.ts'
|
||
- 'v3/@claude-flow/memory/vitest.config.ts'
|
||
- 'v3/@claude-flow/memory/vitest.config.mts'
|
||
- 'scripts/smoke-memory-no-stray-db.mjs'
|
||
# GitHub skills/agents/helpers surface (#2089, ADR-127) — injection
|
||
# smoke + actions pin smoke gate every change to the .github surface.
|
||
- '.claude/agents/github/**'
|
||
- '.claude/skills/github-*/**'
|
||
- 'v3/@claude-flow/cli/.claude/commands/github/**'
|
||
- '.claude/helpers/github-safe.js'
|
||
- 'v3/@claude-flow/cli/.claude/helpers/github-safe.js'
|
||
- 'scripts/smoke-github-safe-injection.mjs'
|
||
- 'scripts/smoke-github-actions-pins.mjs'
|
||
- 'scripts/smoke-deprecated-actions.mjs'
|
||
- 'scripts/smoke-attribution-opt-in.mjs'
|
||
- '.github/supply-chain/allowed-deps.json'
|
||
# Init-bundle invariants smoke (#2095, ADR-128) — orphan dirs, SKILLS_MAP
|
||
# completeness, and plugin-init agent dedup are all guarded by Phase 5.
|
||
- 'v3/@claude-flow/cli/.claude/**'
|
||
- 'v3/@claude-flow/cli/src/init/**'
|
||
- 'plugins/*/agents/**'
|
||
- 'plugins/*/skills/**'
|
||
- 'plugins/*/commands/**'
|
||
- 'scripts/smoke-init-bundle-invariants.mjs'
|
||
# ADR-129 — rvagent full integration (P1-P4)
|
||
- 'v3/@claude-flow/cli/src/ruvector/agent-wasm.ts'
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/wasm-agent-tools.ts'
|
||
- 'scripts/smoke-wasm-provider-bridge.mjs'
|
||
- 'scripts/smoke-wasm-rvf-compose.mjs'
|
||
- 'scripts/smoke-wasm-gallery-crud.mjs'
|
||
- 'scripts/smoke-wasm-plugin-bridge.mjs'
|
||
# ADR-130 — graph intelligence integration (P1-P6)
|
||
- 'v3/@claude-flow/cli/src/memory/memory-initializer.ts'
|
||
- 'v3/@claude-flow/cli/src/memory/embedding-quantization.ts'
|
||
- 'v3/@claude-flow/cli/src/memory/graph-edge-writer.ts'
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/agentdb-tools.ts'
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/hooks-tools.ts'
|
||
- 'plugins/ruflo-graph-intelligence/src/adapters/knowledge-graph-adapter.ts'
|
||
- 'scripts/smoke-graph-schema-migration.mjs'
|
||
- 'scripts/smoke-graph-query-dispatch.mjs'
|
||
- 'scripts/smoke-trajectory-graph-edges.mjs'
|
||
- 'scripts/smoke-graph-plugin-adapter.mjs'
|
||
- 'scripts/smoke-graph-pathfinder.mjs'
|
||
- 'scripts/benchmark-graph.mjs'
|
||
# statusline generator delegation regression guard (#2195)
|
||
- 'v3/@claude-flow/cli/src/init/statusline-generator.ts'
|
||
- '.claude/helpers/statusline.cjs'
|
||
- 'scripts/smoke-statusline-generator-delegation.mjs'
|
||
# wizard init regression guard (#2206 #2207 #2208)
|
||
- 'v3/@claude-flow/cli/src/init/mcp-generator.ts'
|
||
- 'v3/@claude-flow/cli/src/init/executor.ts'
|
||
- 'scripts/smoke-wizard-init-regression.mjs'
|
||
pull_request:
|
||
branches: [main, develop]
|
||
paths:
|
||
- 'v3/**'
|
||
- 'plugins/ruflo-core/scripts/witness/**'
|
||
- 'plugins/ruflo-core/scripts/test-hooks.mjs'
|
||
- 'scripts/**'
|
||
- '**/hooks/hooks.json'
|
||
- '**/scripts/ruflo-hook.sh'
|
||
- '**/.claude/helpers/hook-handler.cjs'
|
||
# ruflo-browser rvf create flag (#2015)
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/browser-session-tools.ts'
|
||
- 'plugins/ruflo-browser/**'
|
||
# ruflo-graph-intelligence (#2044, ADR-123)
|
||
- 'plugins/ruflo-graph-intelligence/**'
|
||
# Supply-chain hardening (#2046) — every dep + lockfile change is
|
||
# CVE-audited, allowlist-checked, integrity-checked.
|
||
- '**/package.json'
|
||
- '**/package-lock.json'
|
||
- '**/pnpm-lock.yaml'
|
||
- '.github/supply-chain/**'
|
||
- 'scripts/audit-supply-chain.mjs'
|
||
# Knowledge-graph plugin (#2049)
|
||
- 'plugins/ruflo-knowledge-graph/**'
|
||
- 'scripts/smoke-kg-extract-type-imports.mjs'
|
||
# Neural-trader portfolio CG (#2068, ADR-126 Phase 3)
|
||
- 'plugins/ruflo-neural-trader/src/sublinear-adapter.ts'
|
||
- 'plugins/ruflo-neural-trader/src/sublinear-adapter.mjs'
|
||
- 'plugins/ruflo-neural-trader/skills/trader-portfolio-cg/**'
|
||
- 'scripts/smoke-neural-trader-portfolio-cg.mjs'
|
||
# Neural-trader backtest signing (#2068, ADR-126 Phase 4)
|
||
- 'plugins/ruflo-neural-trader/src/signed-artifact.ts'
|
||
- 'plugins/ruflo-neural-trader/src/signed-artifact.mjs'
|
||
- 'plugins/ruflo-neural-trader/skills/trader-backtest/**'
|
||
- 'plugins/ruflo-neural-trader/skills/trader-cloud-backtest/**'
|
||
- 'scripts/smoke-neural-trader-backtest-signing.mjs'
|
||
# Neural-trader SendMessage risk-gate pipeline (#2068, ADR-126 Phase 5)
|
||
- 'plugins/ruflo-neural-trader/src/pipeline-messages.ts'
|
||
- 'plugins/ruflo-neural-trader/agents/market-analyst.md'
|
||
- 'plugins/ruflo-neural-trader/agents/trading-strategist.md'
|
||
- 'plugins/ruflo-neural-trader/agents/risk-analyst.md'
|
||
- 'plugins/ruflo-neural-trader/agents/backtest-engineer.md'
|
||
- 'scripts/smoke-neural-trader-pipeline.mjs'
|
||
# Neural-trader feature attribution (#2068, ADR-126 Phase 6)
|
||
- 'plugins/ruflo-neural-trader/src/signed-attribution.ts'
|
||
- 'plugins/ruflo-neural-trader/src/signed-attribution.mjs'
|
||
- 'plugins/ruflo-neural-trader/skills/trader-explain/**'
|
||
- 'scripts/smoke-neural-trader-feature-attribution.mjs'
|
||
# Plugin-registry CWE-347 regression (#1922)
|
||
- 'v3/@claude-flow/cli/src/plugins/store/discovery.ts'
|
||
- 'v3/@claude-flow/cli/src/transfer/ipfs/client.ts'
|
||
- 'v3/@claude-flow/cli/scripts/publish-registry.ts'
|
||
- 'scripts/smoke-plugin-registry-signature.mjs'
|
||
# ruvllm WASM auto-init regression (#2086)
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/ruvllm-tools.ts'
|
||
- 'v3/@claude-flow/cli/src/ruvector/ruvllm-wasm.ts'
|
||
- 'scripts/smoke-ruvllm-wasm-auto-init.mjs'
|
||
# agent_execute provider routing (#2042)
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/agent-execute-core.ts'
|
||
- 'scripts/smoke-agent-execute-providers.mjs'
|
||
# memory stats legacy-DB regression (#2120)
|
||
- 'v3/@claude-flow/cli/src/memory/memory-bridge.ts'
|
||
- 'v3/@claude-flow/cli/src/memory/memory-initializer.ts'
|
||
- 'v3/@claude-flow/cli/src/commands/status.ts'
|
||
- 'scripts/smoke-memory-stats-legacy-db.mjs'
|
||
# ADR-125 Phase 7 — no stray DB artifacts after npm test
|
||
- 'v3/@claude-flow/memory/vitest.setup.ts'
|
||
- 'v3/@claude-flow/memory/vitest.config.ts'
|
||
- 'v3/@claude-flow/memory/vitest.config.mts'
|
||
- 'scripts/smoke-memory-no-stray-db.mjs'
|
||
# GitHub skills/agents/helpers surface (#2089, ADR-127)
|
||
- '.claude/agents/github/**'
|
||
- '.claude/skills/github-*/**'
|
||
- 'v3/@claude-flow/cli/.claude/commands/github/**'
|
||
- '.claude/helpers/github-safe.js'
|
||
- 'v3/@claude-flow/cli/.claude/helpers/github-safe.js'
|
||
- 'scripts/smoke-github-safe-injection.mjs'
|
||
- 'scripts/smoke-github-actions-pins.mjs'
|
||
- 'scripts/smoke-deprecated-actions.mjs'
|
||
- 'scripts/smoke-attribution-opt-in.mjs'
|
||
- '.github/supply-chain/allowed-deps.json'
|
||
# Init-bundle invariants smoke (#2095, ADR-128)
|
||
- 'v3/@claude-flow/cli/.claude/**'
|
||
- 'v3/@claude-flow/cli/src/init/**'
|
||
- 'plugins/*/agents/**'
|
||
- 'plugins/*/skills/**'
|
||
- 'plugins/*/commands/**'
|
||
- 'scripts/smoke-init-bundle-invariants.mjs'
|
||
# ADR-129 — rvagent full integration (P1-P4)
|
||
- 'v3/@claude-flow/cli/src/ruvector/agent-wasm.ts'
|
||
- 'v3/@claude-flow/cli/src/mcp-tools/wasm-agent-tools.ts'
|
||
- 'scripts/smoke-wasm-provider-bridge.mjs'
|
||
- 'scripts/smoke-wasm-rvf-compose.mjs'
|
||
- 'scripts/smoke-wasm-gallery-crud.mjs'
|
||
- 'scripts/smoke-wasm-plugin-bridge.mjs'
|
||
# witness manifests / fix list — so witness-verify runs on PRs that
|
||
# touch them (otherwise a stale per-OS manifest only fails post-merge).
|
||
- 'verification/**'
|
||
# statusline generator delegation regression guard (#2195)
|
||
- 'v3/@claude-flow/cli/src/init/statusline-generator.ts'
|
||
- '.claude/helpers/statusline.cjs'
|
||
- 'scripts/smoke-statusline-generator-delegation.mjs'
|
||
# wizard init regression guard (#2206 #2207 #2208)
|
||
- 'v3/@claude-flow/cli/src/init/mcp-generator.ts'
|
||
- 'v3/@claude-flow/cli/src/init/executor.ts'
|
||
- 'scripts/smoke-wizard-init-regression.mjs'
|
||
workflow_dispatch:
|
||
|
||
env:
|
||
NODE_VERSION: '20'
|
||
PNPM_VERSION: '8'
|
||
|
||
jobs:
|
||
# #2267 + #2257 regression guards — fast, no install, run first so any
|
||
# YAML or router regression is caught at PR-time, not at scheduled cron.
|
||
static-regression-guards:
|
||
name: Static regression guards (#2267 YAML + #2257 router + #2562 lockfile)
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions/setup-node@v4
|
||
with: { node-version: '22' }
|
||
# js-yaml + tsx are needed by the smokes — install only those.
|
||
- name: Install smoke deps
|
||
run: npm install --no-save --no-package-lock js-yaml tsx
|
||
- name: "#2267 — every .github/workflows/*.yml must parse"
|
||
run: node scripts/smoke-workflows-yaml.mjs
|
||
- name: "#2257 — router patterns must be word-boundary-anchored"
|
||
run: node --import tsx scripts/smoke-router-regex.mjs
|
||
# #2562 — FAST lockfile-drift guard. Editing any v3 workspace manifest
|
||
# (esp. v3/@claude-flow/cli deps) without regenerating v3/pnpm-lock.yaml
|
||
# makes --frozen-lockfile fail in EVERY downstream install job (~34 red
|
||
# jobs, cascading — the #2540→#2552→#2562 recurrence). `--lockfile-only`
|
||
# verifies lock↔manifest consistency in seconds WITHOUT downloading
|
||
# anything, failing once here with a clear fix instead of 34× later.
|
||
- name: Setup pnpm (lockfile guard)
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
- name: "#2562 — v3/pnpm-lock.yaml must match workspace package.json (frozen-lockfile drift)"
|
||
working-directory: v3
|
||
run: |
|
||
if pnpm install --frozen-lockfile --lockfile-only 2>lock-err.log; then
|
||
echo "✓ v3/pnpm-lock.yaml is consistent with all workspace manifests"
|
||
else
|
||
echo "::error title=Lockfile drift::v3/pnpm-lock.yaml is OUT OF SYNC with a package.json. Editing v3 workspace deps requires regenerating the lock in the SAME commit."
|
||
echo "::error title=How to fix::Run cd v3 && pnpm install --lockfile-only && git add pnpm-lock.yaml then commit."
|
||
echo "--- pnpm reported ---"
|
||
grep -A25 "OUTDATED_LOCKFILE\|not up to date\|don't match" lock-err.log | head -40 || cat lock-err.log | head -40
|
||
exit 1
|
||
fi
|
||
|
||
test:
|
||
name: Test V3 Packages
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install dependencies
|
||
working-directory: v3
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
- name: Build (so workspace dist/ exists for runtime imports)
|
||
# Some test suites do `await import('@claude-flow/X')` and Vite's
|
||
# import-analysis pass needs dist/ files at the resolved path.
|
||
# --no-bail keeps building past unrelated failures.
|
||
working-directory: v3
|
||
run: pnpm --recursive --no-bail run build || true
|
||
|
||
- name: "ADR-176/177 — self-learning proof artifacts must stay valid"
|
||
# Guard the committed evidence that makes the flywheel claim honest:
|
||
# the proof-of-mechanism + REAL compounding lineage must replay
|
||
# independently (rehash + re-run accept/v1+sig, no service logs), the
|
||
# lineage must reconstruct to >=2 promotions back to the immutable root,
|
||
# and the shipped config champion must verify against the baked pubkey.
|
||
working-directory: v3/@claude-flow/cli
|
||
run: node scripts/smoke-flywheel-proof.mjs
|
||
|
||
- name: "ADR-176 — clean-room replay acceptance test (offline, identical hashes)"
|
||
# Replay a PROMOTED generation from its receipt alone: recompute every
|
||
# hash bit-identically and re-run accept/v1+sig to reproduce promoted=true,
|
||
# with network access trapped. Proves promotions are reproducible without
|
||
# trusting any service log.
|
||
working-directory: v3/@claude-flow/cli
|
||
run: node scripts/replay-generation.mjs
|
||
|
||
- name: Run tests
|
||
working-directory: v3
|
||
# Tolerate exit code 139 (SIGSEGV) ONLY when it occurs at process
|
||
# shutdown after all tests reported. Native bindings sometimes
|
||
# segfault during onnxruntime-node / ruvector cleanup; this is a
|
||
# known issue tracked elsewhere and shouldn't block CI when the
|
||
# actual test outcomes were captured. Any other non-zero exit
|
||
# (real test failures, vitest errors, etc.) still fails the job.
|
||
run: |
|
||
set +e
|
||
pnpm test
|
||
EXIT=$?
|
||
set -e
|
||
if [ "$EXIT" -eq 139 ]; then
|
||
echo "::warning::pnpm test exited with SIGSEGV (139) after tests completed — tolerated as native-binding cleanup race"
|
||
exit 0
|
||
fi
|
||
exit "$EXIT"
|
||
|
||
- name: Upload coverage
|
||
if: always()
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: v3-coverage
|
||
path: v3/__tests__/coverage/
|
||
|
||
typecheck:
|
||
name: Type Check V3
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install dependencies
|
||
working-directory: v3
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
- name: Type check
|
||
working-directory: v3
|
||
run: pnpm typecheck
|
||
continue-on-error: true
|
||
|
||
build:
|
||
name: Build V3 (${{ matrix.os }})
|
||
runs-on: ${{ matrix.os }}
|
||
needs: [test]
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install dependencies
|
||
working-directory: v3
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
- name: Build
|
||
working-directory: v3
|
||
run: pnpm build
|
||
|
||
- name: Upload build artifacts
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: v3-build-${{ matrix.os }}
|
||
path: v3/@claude-flow/*/dist/
|
||
|
||
smoke-install-no-bsqlite:
|
||
# Regression guard for ruvnet/ruflo#1867 — ensures @claude-flow/memory
|
||
# installs and loads when better-sqlite3 fails to build (e.g. Node 26
|
||
# without prebuilds). Reproduces the user-visible failure mode by
|
||
# installing with --omit=optional.
|
||
#
|
||
# Independent of the workspace `build` job because we only need to
|
||
# build a single package (memory) — no workspace-wide dist required.
|
||
#
|
||
# Cross-platform: ubuntu + macos (Windows excluded because the smoke
|
||
# script uses bash-specific patterns and runs in user environments
|
||
# that typically use WSL/git-bash anyway. The runtime fallback path
|
||
# the smoke verifies is platform-independent — a passing run on
|
||
# Linux+macOS proves the JS code path works everywhere.)
|
||
name: Smoke (no better-sqlite3) / ${{ matrix.os }} / Node ${{ matrix.node }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [ubuntu-latest, macos-latest]
|
||
node: ['22', '24']
|
||
# macos-latest's bundled Python 3.12 removed distutils, breaking
|
||
# node-gyp on Node 24's hnswlib-node + better-sqlite3 builds. Drop
|
||
# that one combo until the macOS image ships a compatible setup.
|
||
# (Linux Node 24 + macOS Node 22 still cover the cross-product.)
|
||
exclude:
|
||
- os: macos-latest
|
||
node: '24'
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js ${{ matrix.node }}
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ matrix.node }}
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Guard #2590 — onnxruntime-node postinstall must be skipped
|
||
# Regression guard for ruvnet/ruflo#2590 — onnxruntime-node's postinstall
|
||
# fetches a GPU nupkg from nuget.org that ETIMEDOUTs from GitHub runners,
|
||
# taking `pnpm install --frozen-lockfile` down. The fix requires BOTH:
|
||
# 1) v3/package.json → pnpm.neverBuiltDependencies contains "onnxruntime-node"
|
||
# 2) this workflow's memory-smoke install uses --ignore-scripts
|
||
# If either regresses, this step fails BEFORE the flaky network install.
|
||
run: |
|
||
set -euo pipefail
|
||
# (1) neverBuiltDependencies gate
|
||
node -e '
|
||
const j = require("./v3/package.json");
|
||
const list = (j.pnpm && j.pnpm.neverBuiltDependencies) || [];
|
||
if (!list.includes("onnxruntime-node")) {
|
||
console.error("REGRESSION #2590: v3/package.json pnpm.neverBuiltDependencies missing onnxruntime-node");
|
||
console.error(" got:", JSON.stringify(list));
|
||
process.exit(1);
|
||
}
|
||
console.log("ok: onnxruntime-node in pnpm.neverBuiltDependencies");
|
||
'
|
||
# (2) workflow install step must pass --ignore-scripts (belt-and-braces)
|
||
if ! grep -qE "pnpm install --frozen-lockfile --ignore-scripts" .github/workflows/v3-ci.yml; then
|
||
echo "REGRESSION #2590: memory-smoke install step lost --ignore-scripts"
|
||
exit 1
|
||
fi
|
||
echo "ok: --ignore-scripts present on memory-smoke pnpm install"
|
||
|
||
- name: Install workspace + build memory (pnpm — needed for workspace:* protocol)
|
||
working-directory: v3
|
||
run: |
|
||
pnpm install --frozen-lockfile --ignore-scripts
|
||
pnpm --filter @claude-flow/memory... run build
|
||
|
||
- name: Pack memory tarball
|
||
id: pack
|
||
working-directory: v3/@claude-flow/memory
|
||
run: |
|
||
# pnpm pack rewrites workspace:* → resolved versions (npm pack doesn't).
|
||
# Pack to RUNNER_TEMP so the path works on both ubuntu and macos.
|
||
TARBALL=$(pnpm pack --pack-destination "$RUNNER_TEMP" 2>&1 | grep -E "\.tgz$" | head -1)
|
||
[ -z "$TARBALL" ] && { echo "pnpm pack produced no tarball"; exit 1; }
|
||
echo "tarball=$TARBALL" >> "$GITHUB_OUTPUT"
|
||
|
||
- name: Install with --omit=optional (simulates Node 26 native build failure)
|
||
run: |
|
||
mkdir -p "$RUNNER_TEMP/smoke"
|
||
cd "$RUNNER_TEMP/smoke"
|
||
npm init -y >/dev/null
|
||
npm pkg set type=module
|
||
npm install "${{ steps.pack.outputs.tarball }}" --omit=optional --no-audit --no-fund
|
||
|
||
- name: Assert better-sqlite3 was NOT installed
|
||
run: |
|
||
if [ -d "$RUNNER_TEMP/smoke/node_modules/better-sqlite3" ]; then
|
||
echo "FAIL: better-sqlite3 installed despite --omit=optional — smoke setup is wrong"
|
||
exit 1
|
||
fi
|
||
echo "ok: better-sqlite3 absent (regression scenario active)"
|
||
|
||
- name: Run smoke script
|
||
run: |
|
||
cp v3/@claude-flow/memory/scripts/smoke-no-bsqlite.mjs "$RUNNER_TEMP/smoke/"
|
||
cd "$RUNNER_TEMP/smoke"
|
||
node smoke-no-bsqlite.mjs
|
||
|
||
plugin-hooks-smoke:
|
||
# Regression guard for ruvnet/ruflo#1859 + #1862 — drives each PostToolUse
|
||
# hook from plugins/ruflo-core/hooks/hooks.json with synthetic Claude-Code
|
||
# JSON against the locally built CLI. Catches:
|
||
# - hooks calling flags the CLI doesn't accept (#1862's --format true)
|
||
# - CLI parser ambiguity recording the wrong value (#1859's "true" filename)
|
||
#
|
||
# Independent of the workspace `build` job — only the cli package needs
|
||
# to be built. We use `pnpm --filter @claude-flow/cli...` to scope.
|
||
name: Plugin hooks smoke / ${{ matrix.os }} / Node ${{ matrix.node }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
# Cross-platform: ubuntu + macos. Windows excluded because the
|
||
# plugin's hooks.json uses `/bin/bash -c '...'` and the synthetic
|
||
# JSON-on-stdin pipeline assumes POSIX shell. On Windows users
|
||
# run Claude Code via WSL or git-bash, which the test would also
|
||
# need to simulate; out of scope for this regression guard.
|
||
os: [ubuntu-latest, macos-latest]
|
||
# Node 22 is the project's documented baseline (engines.node: '>=20')
|
||
# but Node 20 had environment-specific issues with multi-line stdin
|
||
# round-tripping that didn't reproduce on Node 22 or locally — same
|
||
# CLI binary, same hooks.json. Tracked as a follow-up; for now the
|
||
# regression guard runs on the version users are actually on.
|
||
node: ['22']
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js ${{ matrix.node }}
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ matrix.node }}
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install + build cli (scoped, tolerates unrelated workspace failures)
|
||
working-directory: v3
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
# --no-bail keeps building past unrelated package failures
|
||
# (e.g. plugin-agent-federation TS error). We then assert the
|
||
# specific dist file we need was produced.
|
||
pnpm --recursive --no-bail run build || true
|
||
test -f @claude-flow/cli/bin/cli.js \
|
||
|| (echo "cli build did not produce bin/cli.js"; exit 1)
|
||
test -f @claude-flow/cli/dist/src/commands/hooks.js \
|
||
|| (echo "cli build did not produce hooks.js"; exit 1)
|
||
|
||
- name: Run plugin hooks smoke against local CLI build
|
||
run: |
|
||
node plugins/ruflo-core/scripts/test-hooks.mjs \
|
||
"node $GITHUB_WORKSPACE/v3/@claude-flow/cli/bin/cli.js"
|
||
|
||
browser-rvf-create-flags-smoke:
|
||
# Regression guard for ruvnet/ruflo#2015 — the ruflo-browser
|
||
# `browser_session_record` MCP tool wraps `ruvector rvf create`.
|
||
# ruvector@0.2.25 makes `-d, --dimension <n>` required, so before
|
||
# this fix every session-record call failed with
|
||
# `error: required option '-d, --dimension <n>' not specified`
|
||
# and the wrapper returned `{ success: false, error: "rvf create
|
||
# failed" }`.
|
||
#
|
||
# This smoke scans every place we shell out to `rvf create
|
||
# --kind browser-session` across the repo (TS source, compiled
|
||
# dist, shell scripts, agent-facing markdown recipes) and fails
|
||
# if any call is missing the dimension flag.
|
||
name: browser rvf create flag smoke (#2015)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: 8
|
||
|
||
- name: Build CLI (so the compiled dist is scanned alongside src)
|
||
# The CLI uses `workspace:*` deps which only pnpm understands — npm
|
||
# install errors with EUNSUPPORTEDPROTOCOL. Install at the v3
|
||
# workspace root (mirrors the Build V3 job) and build everything in
|
||
# topological order so cli-core/memory/neural dist exist before cli.
|
||
# `continue-on-error: true` keeps the smoke usable even when CLI src
|
||
# has unrelated TS errors — the static scan will report any missing
|
||
# dist file it cares about, which is the contract we actually want.
|
||
continue-on-error: true
|
||
run: |
|
||
cd v3
|
||
pnpm install --frozen-lockfile
|
||
pnpm -r build
|
||
|
||
- name: Static scan of every rvf create call site
|
||
run: node scripts/smoke-browser-rvf-create-flags.mjs
|
||
|
||
graph-intelligence-build-smoke:
|
||
# Regression guard for #2044 / ADR-123 — the ruflo-graph-intelligence
|
||
# plugin lives outside the v3 pnpm workspace (it has its own
|
||
# package-lock.json) so it does not pick up the workspace's
|
||
# frozen-lockfile / -r build path. This job installs + builds + tests
|
||
# the plugin in isolation so the eleven sublinear wedges are verified
|
||
# on every push and PR.
|
||
name: ruflo-graph-intelligence build + test smoke (#2044, ADR-123)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Install plugin dependencies (npm — plugin is outside v3 workspace)
|
||
working-directory: plugins/ruflo-graph-intelligence
|
||
run: npm ci --no-audit --no-fund --legacy-peer-deps
|
||
|
||
- name: Type-check
|
||
working-directory: plugins/ruflo-graph-intelligence
|
||
run: npx tsc --noEmit
|
||
|
||
- name: Build
|
||
working-directory: plugins/ruflo-graph-intelligence
|
||
run: npx tsc
|
||
|
||
- name: Run vitest
|
||
working-directory: plugins/ruflo-graph-intelligence
|
||
run: npx vitest run
|
||
|
||
supply-chain-audit:
|
||
# Supply-chain hardening (#2046, follow-up to ADR-123).
|
||
#
|
||
# Five layers of defence run by scripts/audit-supply-chain.mjs:
|
||
# 1. CVE — `npm audit --audit-level=high` on each shipped package.
|
||
# HIGH/CRITICAL findings in DIRECT deps fail CI.
|
||
# 2. Lockfile integrity — every entry must have a SHA-512 `integrity`
|
||
# hash. Missing or weak hashes are a tamper vector.
|
||
# 3. Top-level allowlist — new direct deps require an explicit
|
||
# `.github/supply-chain/allowed-deps.json` addition. Block silent
|
||
# additions via maintainer compromise or typo'd PRs.
|
||
# 4. Typosquat reject — names matching the policy block-list fail
|
||
# regardless of whether the package actually exists upstream.
|
||
# 5. Publisher trust snapshot — logs npm maintainer identity for our
|
||
# critical upstream deps so unexpected handover is visible in CI
|
||
# logs (not a hard fail; informational).
|
||
#
|
||
# This job runs on every PR that touches a package.json, lockfile,
|
||
# allowlist, or the audit script itself. It also runs on pushes to main
|
||
# so direct-to-main changes (rare) are caught.
|
||
name: Supply-chain audit (#2046)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Install ruflo-graph-intelligence deps (for npm audit)
|
||
working-directory: plugins/ruflo-graph-intelligence
|
||
run: npm ci --no-audit --no-fund --legacy-peer-deps
|
||
|
||
- name: Install @claude-flow/browser deps (for npm audit)
|
||
working-directory: v3/@claude-flow/browser
|
||
run: npm install --no-audit --no-fund --legacy-peer-deps --no-workspaces
|
||
|
||
- name: Run supply-chain audit
|
||
run: node scripts/audit-supply-chain.mjs
|
||
|
||
- name: Test audit script itself
|
||
run: node scripts/__tests__/audit-supply-chain.test.mjs
|
||
|
||
dependency-review:
|
||
# GitHub's official dependency-review-action — runs only on PRs and
|
||
# flags any new vulnerable dependency added by the PR vs the base
|
||
# branch. Configured to fail on `high` severity and to forbid
|
||
# known-bad licenses (GPL-style + non-OSI).
|
||
#
|
||
# **Setup requirement**: this action needs GitHub's Dependency Graph
|
||
# feature enabled at the repo level. Toggle at
|
||
# https://github.com/ruvnet/ruflo/settings/security_analysis under
|
||
# "Dependency graph". Until that toggle is on, the action errors
|
||
# with "Dependency review is not supported on this repository" — so
|
||
# this job is marked continue-on-error to keep the CVE/audit/codeowner
|
||
# layers of supply-chain hardening usable in the meantime.
|
||
#
|
||
# https://github.com/actions/dependency-review-action
|
||
name: Dependency review (#2046)
|
||
runs-on: ubuntu-latest
|
||
if: github.event_name == 'pull_request'
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
# `continue-on-error` is at the STEP (not job) level so the action's
|
||
# "Dependency review is not supported on this repository" error from
|
||
# the off-by-default Dependency Graph feature doesn't show as a PR
|
||
# check failure. Once the repo owner toggles Dependency Graph on at
|
||
# Settings → Security and analysis, remove this line to make the
|
||
# action gating again.
|
||
- name: Dependency Review
|
||
continue-on-error: true
|
||
uses: actions/dependency-review-action@v4
|
||
with:
|
||
fail-on-severity: high
|
||
comment-summary-in-pr: on-failure
|
||
# Block licenses we cannot ship:
|
||
deny-licenses: AGPL-3.0, GPL-3.0, SSPL-1.0
|
||
# Block known-compromised package versions via pURL (package-url)
|
||
# format — this is the action's required input shape per its docs.
|
||
# https://github.com/actions/dependency-review-action#configuration-options
|
||
deny-packages: pkg:npm/event-stream@3.3.6, pkg:npm/flatmap-stream, pkg:npm/ua-parser-js@0.7.29, pkg:npm/ua-parser-js@0.8.0, pkg:npm/ua-parser-js@1.0.0, pkg:npm/colors@1.4.1, pkg:npm/faker@6.6.6
|
||
|
||
witness-marker-drift-smoke:
|
||
# Regression guard for ruvnet/ruflo#2021 — the slow witness-verify
|
||
# job below catches marker drift but only as a post-build check on
|
||
# cross-platform matrix. Direct pushes to main (e.g. the alpha.43
|
||
# release chain) bypass PR-time gating and a bad marker can sneak
|
||
# through, leaving the scheduled 12h cron to file a HIGH issue.
|
||
#
|
||
# This smoke runs verify.mjs's marker-presence layer (no signature
|
||
# check, no build, no native deps) on every push and pull-request.
|
||
# If a cited file exists on disk and the marker string is missing,
|
||
# fail immediately and name the specific fix id that drifted.
|
||
#
|
||
# The full witness-verify job stays — it adds the signature layer
|
||
# and the cross-platform dist build. This smoke is the fast gate
|
||
# that fails before that.
|
||
name: witness marker drift smoke (#2021)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Scan every witness marker for drift
|
||
run: node scripts/smoke-witness-marker-drift.mjs
|
||
|
||
witness-verify-precondition-smoke:
|
||
# Regression guard for ruvnet/ruflo#1880 — the 12h scheduled witness
|
||
# verification runs in a source-only checkout (no `npm ci`, no
|
||
# `npm run build`). Before this fix, that environment exited 1
|
||
# (real verification failure) because `@noble/ed25519` wasn't
|
||
# installed and 87+ dist files referenced by the manifest didn't
|
||
# exist on disk — so the scheduled runner filed a "verification
|
||
# broken" issue every 12 hours even though nothing was actually
|
||
# wrong with the signed manifest.
|
||
#
|
||
# verify.mjs now reserves exit 2 for precondition failures
|
||
# (missing dep, source-only checkout) and exit 1 strictly for real
|
||
# failures (signature invalid, dist file regressed). This smoke
|
||
# drives both shapes through and asserts the contract holds:
|
||
# - missing @noble/ed25519 → exit 2 + named in the error
|
||
# - all-manifest-files missing → exit 2 + precondition tag
|
||
# - built tree → exit is NEVER 2
|
||
#
|
||
# Independent job so a precondition contract break is named clearly
|
||
# in the CI summary. Wired into witness-verify's `needs:` below.
|
||
name: witness verify precondition smoke (#1880)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Install root dependencies (provides @noble/ed25519 for Case 3)
|
||
run: npm ci --legacy-peer-deps
|
||
|
||
- name: Drive precondition + built-tree shapes through verify.mjs
|
||
shell: bash
|
||
run: node scripts/smoke-witness-verify-precondition.mjs
|
||
|
||
kg-extract-type-imports-smoke:
|
||
# Regression guard for ruvnet/ruflo#2049 — `kg-extract` previously
|
||
# treated TypeScript `import type` and value imports as the same edge
|
||
# type, producing phantom runtime cycles in the knowledge graph (a
|
||
# 51-service codebase reported a non-existent `findings ⇄ finding-actions`
|
||
# cycle driven entirely by a one-way type-only import).
|
||
#
|
||
# This smoke runs two layers:
|
||
# 1. Static contract check on plugins/ruflo-knowledge-graph/skills/{kg-extract,kg-traverse}/SKILL.md
|
||
# — assert kg-extract declares `type-depends-on` as a separate relation
|
||
# with weight ≤ 0.1, and that neither skill references the
|
||
# compiled-out `agentdb_semantic-route` controller.
|
||
# 2. Behavioural fixture: write a tiny TS scenario with one type-only
|
||
# cycle + one value-import edge to /tmp, run the documented regex
|
||
# classifier, and assert the cycle is NOT counted as a value edge.
|
||
#
|
||
# If a future PR softens either layer (re-introduces semantic-route in
|
||
# allowed-tools, drops the type-depends-on relation, or weakens the
|
||
# regex), this smoke catches it.
|
||
name: kg-extract type-import classification smoke (#2049)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run kg-extract type-import smoke
|
||
run: node scripts/smoke-kg-extract-type-imports.mjs
|
||
|
||
neural-trader-portfolio-cg-smoke:
|
||
# Regression guard for ruvnet/ruflo#2068 — ADR-126 Phase 3.
|
||
#
|
||
# Phase 3 wires the Conjugate-Gradient portfolio path that ADR-123
|
||
# Wedge 8 promises a 40-60× speedup over the legacy Neumann series.
|
||
# The contract is load-bearing on three artifacts that must stay
|
||
# in lockstep:
|
||
# 1. `src/sublinear-adapter.ts` — the typed adapter shape
|
||
# (SublinearAdapter, solveCG, isMcpAvailable, SolveResult)
|
||
# that conforms to ADR-123 §262-289.
|
||
# 2. `src/sublinear-adapter.mjs` — the runtime mirror that the
|
||
# smoke + bench import directly (the plugin has no build step).
|
||
# 3. `skills/trader-portfolio-cg/SKILL.md` — frontmatter must
|
||
# declare `mcp__ruflo-sublinear__solve` in allowed-tools and
|
||
# write to the canonical `trading-risk` namespace.
|
||
#
|
||
# The smoke runs three layers:
|
||
# [1/3] STATIC ADAPTER CONTRACT — class shape, method signatures,
|
||
# SolveResult fields, MCP tool name, symmetric-input validation.
|
||
# [2/3] STATIC SKILL CONTRACT — frontmatter, allowed-tools, namespace,
|
||
# disable-flag documentation, Neumann fallback path.
|
||
# [3/3] RUNTIME CORRECTNESS — solves the textbook 2×2 SPD case
|
||
# A=[[4,1],[1,3]], b=[1,2] → x=[1/11, 7/11] within 1e-6, and
|
||
# exercises the degraded paths (non-square, non-symmetric).
|
||
#
|
||
# If a future PR drops solveCG, removes the MCP tool from allowed-tools,
|
||
# changes the namespace, or breaks the local CG kernel, this smoke
|
||
# catches it before merge.
|
||
name: neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run portfolio CG smoke
|
||
run: node scripts/smoke-neural-trader-portfolio-cg.mjs
|
||
|
||
neural-trader-backtest-signing-smoke:
|
||
# Regression guard for ruvnet/ruflo#2068 — ADR-126 Phase 4.
|
||
#
|
||
# Phase 4 wires Ed25519-signed backtest artifacts so the paper→live
|
||
# promotion gate has cryptographic tamper evidence. The signing scheme
|
||
# mirrors the CWE-347 plugin-registry pattern (#1922): canonical body
|
||
# = JSON.stringify without signature fields; verifier pins to a
|
||
# caller-supplied `trustedPublicKey`, NOT to the served self-asserted
|
||
# `witnessPublicKey` field (which an attacker can swap freely).
|
||
#
|
||
# Three load-bearing artifacts must stay in lockstep:
|
||
# 1. `src/signed-artifact.ts` — the typed signer/verifier contract.
|
||
# 2. `src/signed-artifact.mjs` — the runtime mirror imported by the
|
||
# smoke + (future) skill harnesses (the plugin has no build step).
|
||
# 3. `skills/trader-backtest/SKILL.md` + `skills/trader-cloud-backtest/SKILL.md`
|
||
# — the call sites that sign before store + verify before promote.
|
||
#
|
||
# The smoke runs three layers:
|
||
# [1/3] STATIC CONTRACT — verifier pins to trustedPublicKey (NOT to
|
||
# artifact.witnessPublicKey), canonical body strips BOTH
|
||
# signature fields, .ts and .mjs runtime mirrors agree.
|
||
# [2/3] CRYPTO ROUND-TRIP with real Ed25519 — happy path, tampered
|
||
# body fails, empty sig/pubkey fails, swapped served pubkey
|
||
# still verifies (pin is real), wrong trusted pubkey fails.
|
||
# [3/3] CALL-SITE BYTE check — trader-cloud-backtest/SKILL.md calls
|
||
# verifyBacktestArtifact AND documents the fail-closed branch;
|
||
# trader-backtest/SKILL.md references the signer + degraded
|
||
# warning + RUFLO_WITNESS_KEY_PATH env var.
|
||
#
|
||
# If a future PR drops the verify call, reverts to pinning the served
|
||
# field, or removes the fail-closed branch, this smoke catches it
|
||
# before merge.
|
||
name: neural-trader backtest signing smoke (#2068, ADR-126 Phase 4)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Install root deps (for @noble/ed25519)
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
|
||
- name: Run backtest signing smoke
|
||
run: node scripts/smoke-neural-trader-backtest-signing.mjs
|
||
|
||
neural-trader-pipeline-smoke:
|
||
# Regression guard for ruvnet/ruflo#2068 — ADR-126 Phase 5.
|
||
#
|
||
# Phase 5 refactors the four neural-trader agents (market-analyst,
|
||
# trading-strategist, risk-analyst, backtest-engineer) into a typed
|
||
# SendMessage pipeline with risk-analyst as a structural BLOCKING
|
||
# GATE. The live broker call (`npx neural-trader --broker <name>`)
|
||
# cannot fire without an explicit RiskDecision approval event from
|
||
# risk-analyst for the proposal's signalId.
|
||
#
|
||
# Six load-bearing artifacts must stay in lockstep:
|
||
# 1. `src/pipeline-messages.ts` — the three TypeScript message
|
||
# schemas (RegimeVerdict, SignalProposal, RiskDecision) +
|
||
# PipelineMessage discriminated union.
|
||
# 2-5. `agents/{market-analyst,trading-strategist,risk-analyst,backtest-engineer}.md`
|
||
# — frontmatter `name:` fields + Comms protocol sections with
|
||
# the correct upstream/downstream wiring.
|
||
# 6. `trading-strategist.md` — the structural risk-gate guard at
|
||
# step 5 of the Strategy Development Workflow that refuses
|
||
# `--broker` calls without a risk-analyst approval.
|
||
#
|
||
# The smoke runs four layers:
|
||
# [1/4] AGENT FRONTMATTER — each .md declares `name: <agent>` so
|
||
# the agent is SendMessage-addressable.
|
||
# [2/4] COMMS PROTOCOL — each .md has a "Comms protocol" section
|
||
# with the correct upstream/downstream references; backtest-
|
||
# engineer documents its orthogonal-lane status.
|
||
# [3/4] STRUCTURAL RISK-GATE — trading-strategist.md contains
|
||
# explicit refusal logic: mentions `--broker`, requires
|
||
# RiskDecision approval, declares REFUSAL, emits [ERROR],
|
||
# marks the gate as NON-NEGOTIABLE/structural.
|
||
# [4/4] BEHAVIORAL MOCK — drives a mock pipeline through a guard
|
||
# function that mirrors the trading-strategist guard. Happy
|
||
# path approves and executes; missing approval / rejected
|
||
# decision / mismatched signalId are ALL refused.
|
||
#
|
||
# If a future PR drops the guard, removes a `name` field, breaks
|
||
# the pipeline-messages schema, or rewrites a comms section without
|
||
# the upstream/downstream wiring, this smoke catches it before merge.
|
||
name: neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run pipeline risk-gate smoke
|
||
run: node scripts/smoke-neural-trader-pipeline.mjs
|
||
|
||
neural-trader-feature-attribution-smoke:
|
||
# Regression guard for ruvnet/ruflo#2068 — ADR-126 Phase 6.
|
||
#
|
||
# Phase 6 ships regulator-grade feature attribution for LSTM /
|
||
# Transformer trading signals. Given a `signalId`, the `trader-explain`
|
||
# skill builds a feature-contribution graph, runs single-entry forward-
|
||
# push PageRank from the signal output node (via
|
||
# `mcp__ruflo-sublinear__page-rank-entry` when registered, local seeded
|
||
# power-iteration fallback otherwise), and stores the top-K ranked
|
||
# features as a `SignedAttributionArtifact` (the Phase 4 signing
|
||
# scheme — same Ed25519 + CWE-347 trusted-pin pattern).
|
||
#
|
||
# Three load-bearing artifacts must stay in lockstep:
|
||
# 1. `src/signed-attribution.ts` — the typed signer/verifier/PR
|
||
# contract.
|
||
# 2. `src/signed-attribution.mjs` — the runtime mirror imported by
|
||
# the smoke + skill harnesses (zero build step).
|
||
# 3. `skills/trader-explain/SKILL.md` — the call site that builds
|
||
# the graph + signs the result + persists to `trading-analysis`.
|
||
#
|
||
# The smoke runs three layers:
|
||
# [1/3] STATIC CONTRACT — TS/MJS export shape, verifier pins to
|
||
# trustedPublicKey (CWE-347), graphMetadata.seed is part of
|
||
# the typed shape, skill writes to `trading-analysis`, skill
|
||
# documents the local fallback + the --explain fallback.
|
||
# [2/3] CRYPTO ROUND-TRIP — Ed25519 signing fixture, tampered
|
||
# feature score fails, tampered seed fails (seed is signed-in),
|
||
# swapped served pubkey still verifies (pin is real).
|
||
# [3/3] REPRODUCIBILITY — same seed → byte-identical PageRank
|
||
# scores + identical top-K ordering. Different seed → scores
|
||
# differ (proves the seed is load-bearing, not dead weight).
|
||
# Mass conservation: scores sum to ~1.
|
||
#
|
||
# If a future PR breaks any of these properties — drops the verify
|
||
# call, removes the seed from graphMetadata, reverts the seeded
|
||
# initializer, drops the local fallback, or rewrites the skill
|
||
# without the `trading-analysis` namespace — this smoke catches it
|
||
# before merge.
|
||
name: neural-trader feature attribution smoke (#2068, ADR-126 Phase 6)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Install root deps (for @noble/ed25519)
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
|
||
- name: Run feature attribution smoke
|
||
run: node scripts/smoke-neural-trader-feature-attribution.mjs
|
||
|
||
plugin-registry-signature-smoke:
|
||
# Regression guard for ruvnet/ruflo#1922 (CWE-347 — improper verification
|
||
# of cryptographic signature). The plugin-registry signature verifier in
|
||
# v3/@claude-flow/cli/src/plugins/store/discovery.ts used to be a stub
|
||
# that returned `true` whenever the served `registryPublicKey` field
|
||
# started with `"ed25519"`. The call site only `console.warn`ed on
|
||
# failure and continued. With `requireVerification: true` (the default),
|
||
# a network adversary on the path to an IPFS gateway could swap the
|
||
# served registry and have a user install attacker-controlled plugin
|
||
# tarballs with filesystem+network+hooks permissions.
|
||
#
|
||
# This smoke runs three layers:
|
||
# 1. Static contract check on discovery.ts — must import
|
||
# `verifyEd25519Signature`, must strip both signature fields before
|
||
# stringifying, must pin to caller-supplied `expectedPublicKey`
|
||
# (not the served `registryPublicKey`), call site must `await` +
|
||
# fail-closed.
|
||
# 2. Crypto round-trip with real Ed25519, matching the signRegistry()
|
||
# scheme in scripts/publish-registry.ts — valid signature passes,
|
||
# tampered body fails, empty fields fail, swapped served key
|
||
# doesn't defeat the trusted pin.
|
||
# 3. Call-site byte check — the `requireVerification` block must
|
||
# `await` the verifier AND `return` on failure (not just warn).
|
||
#
|
||
# If a future PR reverts to prefix-matching, drops the await, or
|
||
# silently warns, this smoke catches it before merge.
|
||
name: plugin-registry signature verification smoke (#1922, CWE-347)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Install root deps (for @noble/ed25519)
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
|
||
- name: Run plugin-registry signature smoke
|
||
run: node scripts/smoke-plugin-registry-signature.mjs
|
||
|
||
ruvllm-wasm-auto-init-smoke:
|
||
# Regression guard for ruvnet/ruflo#2086 — ruvllm WASM bootstrap not
|
||
# exposed via MCP. Reporter: @seo-yas. Every `ruvllm_*` MCP tool that
|
||
# touches the WASM runtime calls `loadRuvllmWasm()` in
|
||
# `v3/@claude-flow/cli/src/mcp-tools/ruvllm-tools.ts`. That helper used
|
||
# to just `import(...)` the module and never call `initRuvllmWasm()`,
|
||
# leaving `_wasmReady=false`. Result: `ruvllm_status` reported
|
||
# `wasm.initialized=false` even after `ruvllm_sona_create` and
|
||
# downstream sona/microlora/hnsw operations silently failed or
|
||
# returned empty results.
|
||
#
|
||
# The fix wires `initRuvllmWasm()` into `loadRuvllmWasm()` (it's
|
||
# idempotent — `_wasmReady` short-circuits subsequent calls).
|
||
# `ruvllm_status` keeps a separate un-init `loadRuvllmWasmModule()`
|
||
# path so diagnostics still report uninitialized state without
|
||
# eagerly bootstrapping.
|
||
#
|
||
# This smoke statically asserts:
|
||
# 1. `loadRuvllmWasm()` awaits `mod.initRuvllmWasm()`.
|
||
# 2. `loadRuvllmWasmModule()` exists and does NOT init.
|
||
# 3. `ruvllm_status` handler uses the un-init loader.
|
||
# 4. Every WASM-touching ruvllm_* tool either routes through
|
||
# `loadRuvllmWasm()` or looks up a pre-initialized instance.
|
||
# 5. No new ruvllm_* tools have been added that bypass the gate.
|
||
name: ruvllm WASM auto-init smoke (#2086)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run ruvllm WASM auto-init smoke
|
||
run: node scripts/smoke-ruvllm-wasm-auto-init.mjs
|
||
|
||
agent-execute-providers-smoke:
|
||
# Regression guard for ruvnet/ruflo#2042 — agent_execute hardcoded
|
||
# the Anthropic SDK and ignored the v3 provider system. Reporter:
|
||
# @ummcke00. Fix routes executeAgentTask through callAnthropicMessages
|
||
# which dispatches Anthropic / OpenRouter / Ollama by env var.
|
||
name: agent_execute provider routing smoke (#2042)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run agent_execute providers smoke
|
||
run: node scripts/smoke-agent-execute-providers.mjs
|
||
|
||
memory-stats-legacy-db-smoke:
|
||
# Regression guard for ruvnet/ruflo#2120 — `ruflo memory stats` and
|
||
# `listEntries` returned 0 entries against a populated
|
||
# `.swarm/memory.db` on WSL2 (reporter: @alexandrelealbess on
|
||
# alpha.81). Root cause: the `WHERE status = 'active'` filter
|
||
# excluded rows where the status column was NULL (legacy DBs
|
||
# created before the status column existed, or via the auto-memory
|
||
# bridge path that didn't set status).
|
||
#
|
||
# Fix: (1) accept `status IS NULL` alongside `'active'` in both
|
||
# bridgeListEntries and listEntries; (2) backfill `UPDATE
|
||
# memory_entries SET status = 'active' WHERE status IS NULL` in
|
||
# ensureSchemaColumns; (3) broaden `isInitialized()` in
|
||
# `status.ts` to also accept `.swarm/memory.db` existence.
|
||
#
|
||
# This smoke builds a 251-entry DB with all-NULL status (mirroring
|
||
# the reporter's setup), runs listEntries, and asserts total === 251
|
||
# AND that the backfill promoted all rows to 'active'.
|
||
name: memory stats legacy-DB smoke (#2120)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Setup pnpm (workspace-aware install)
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: 8
|
||
|
||
- name: Install root deps (sql.js for the smoke fixture)
|
||
# The smoke creates a `.swarm/memory.db` fixture using `sql.js`
|
||
# imported from the repo root. Root has no `workspace:*` deps,
|
||
# so plain npm works here.
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
|
||
- name: Install workspace deps + build CLI (pnpm — `workspace:*` protocol)
|
||
# `cd v3/@claude-flow/cli && npm install` errors with
|
||
# `EUNSUPPORTEDPROTOCOL: Unsupported URL Type "workspace:"` because
|
||
# npm doesn't understand workspace:*. The pnpm workspace root is
|
||
# `v3/pnpm-workspace.yaml`. The CLI's tsc references project-refs to
|
||
# @claude-flow/swarm (and others), so those must be built first —
|
||
# `pnpm --filter @claude-flow/cli build` alone fails with TS6305.
|
||
# `--recursive --no-bail` builds the whole graph in topological order
|
||
# past unrelated package failures; we then assert the specific dist
|
||
# file the smoke imports.
|
||
working-directory: v3
|
||
run: |
|
||
pnpm install --frozen-lockfile=false --ignore-scripts
|
||
pnpm --recursive --no-bail run build || true
|
||
test -f @claude-flow/cli/dist/src/memory/memory-initializer.js \
|
||
|| (echo "CLI build did not produce memory-initializer.js"; exit 1)
|
||
|
||
- name: Run memory stats legacy-DB smoke
|
||
run: node scripts/smoke-memory-stats-legacy-db.mjs
|
||
|
||
memory-no-stray-db-smoke:
|
||
# Regression guard for ADR-125 Phase 7 — vitest.setup.ts in
|
||
# @claude-flow/memory must wipe any *.db / *.db-journal / *.db-wal /
|
||
# *.rvf / *.redb files written by agentdb / @ruvector/rvf native
|
||
# bindings during the test run. This smoke:
|
||
# 1. records `git status --porcelain` baseline in v3/@claude-flow/memory
|
||
# 2. runs `npm test` inside that package
|
||
# 3. asserts no net-new DB-like artifacts appeared after the run
|
||
# A failure here means vitest.setup.ts stopped cleaning up, or a new
|
||
# binding started writing to a path not covered by LEAK_SUFFIXES.
|
||
name: memory no-stray-db smoke (ADR-125 P7)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v4
|
||
with:
|
||
version: 8
|
||
|
||
- name: Install workspace deps (pnpm — @claude-flow/memory pulled in workspace:* deps)
|
||
# @claude-flow/memory now depends on sibling workspace packages via
|
||
# workspace:* protocol, so plain npm install fails with
|
||
# EUNSUPPORTEDPROTOCOL. We MUST run install scripts (no --ignore-scripts)
|
||
# because the smoke runs `npm test` which opens better-sqlite3 via
|
||
# native bindings — the .node addon comes from better-sqlite3's
|
||
# prebuild-install postinstall step.
|
||
working-directory: v3
|
||
run: |
|
||
pnpm install --frozen-lockfile=false
|
||
pnpm --recursive --no-bail run build || true
|
||
# Belt-and-suspenders: explicit rebuild in case prebuild-install was skipped
|
||
pnpm rebuild better-sqlite3 || true
|
||
|
||
- name: Run memory no-stray-db smoke
|
||
run: node scripts/smoke-memory-no-stray-db.mjs
|
||
|
||
github-safe-injection-smoke:
|
||
# Regression guard for ruvnet/ruflo#2089 — ADR-127 Phase 1.
|
||
#
|
||
# Drives adversarial PR/issue bodies (backticks, $(), semicolons,
|
||
# >256KB, empty) through github-safe.js and asserts the body lands in a
|
||
# temp file verbatim rather than being passed inline to `gh`. Inline
|
||
# interpolation of untrusted body content into shell arguments is the
|
||
# prompt-injection vector closed by the swarm-pr.md / swarm-issue.md
|
||
# fix in Phase 2. This smoke ensures github-safe.js itself always writes
|
||
# the temp file and passes --body-file rather than --body.
|
||
#
|
||
# Runs against both copies:
|
||
# - .claude/helpers/github-safe.js (dogfood)
|
||
# - v3/@claude-flow/cli/.claude/helpers/ (init-template)
|
||
name: github-safe injection smoke (#2089, ADR-127 Phase 1)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run github-safe injection smoke
|
||
run: node scripts/smoke-github-safe-injection.mjs
|
||
|
||
github-actions-pins-smoke:
|
||
# Static contract guard for ruvnet/ruflo#2089 — ADR-127 Phase 1.
|
||
#
|
||
# Scans every `uses:` line in:
|
||
# .claude/agents/github/*.md
|
||
# .claude/skills/github-[name]/SKILL.md
|
||
# v3/@claude-flow/cli/.claude/commands/github/[name].md
|
||
#
|
||
# Asserts each ref is either SHA-pinned (40-hex) or present in
|
||
# .github/supply-chain/allowed-deps.json actions.allowed[].
|
||
#
|
||
# This smoke catches any future commit that copies @v3 snippets from
|
||
# blog posts into the skill files — the most common doc-drift pattern.
|
||
# Phase 3 upgrades all @v3 refs to @v4; this smoke is the regression
|
||
# gate that prevents them from drifting back.
|
||
name: github actions pin smoke (#2089, ADR-127 Phase 1)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run github actions pin smoke
|
||
run: node scripts/smoke-github-actions-pins.mjs
|
||
|
||
github-deprecated-actions-smoke:
|
||
# Regression guard for ruvnet/ruflo#2089 — ADR-127 Phase 3.
|
||
#
|
||
# Scans every `uses:` line in the same scope as the pins smoke and
|
||
# fails if any deprecated action ref is still present:
|
||
# - actions/checkout@v3 (v4 available since Nov 2023)
|
||
# - actions/setup-node@v3 (v4 available since Nov 2023)
|
||
# - actions/create-release@* (deprecated; replaced by gh CLI)
|
||
# - actions/upload-release-asset@* (deprecated; replaced by gh CLI)
|
||
# - softprops/action-gh-release@v1 (v1 has known CVEs; use @v2)
|
||
#
|
||
# Phase 3 bumps all @v3 refs to @v4. This smoke is the regression gate
|
||
# that prevents them from drifting back via copy-paste from blog posts
|
||
# or AI-generated snippets that still reference the old versions.
|
||
name: github deprecated actions smoke (#2089, ADR-127 Phase 3)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run deprecated-actions smoke
|
||
run: node scripts/smoke-deprecated-actions.mjs
|
||
|
||
github-attribution-opt-in-smoke:
|
||
# Regression guard for ruvnet/ruflo#2089 — ADR-127 Phase 4.
|
||
#
|
||
# Phase 4 removes hardcoded "Generated with Claude Code" attribution
|
||
# strings from the static github command templates. Attribution is now
|
||
# opt-in via --attribution / options.attribution=true (#1670 / #2089).
|
||
# Hard-wired footers silently added a third-party Co-Authored-By line
|
||
# to every user's commits and were impossible to undo without rewriting
|
||
# git history.
|
||
#
|
||
# This smoke scans the same three trees as the pins smoke and fails if
|
||
# the "Generated with" emoji pattern reappears — preventing copy-paste
|
||
# regression from blog posts or AI-generated snippets.
|
||
name: github attribution opt-in smoke (#2089, ADR-127 Phase 4)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run attribution opt-in smoke
|
||
run: node scripts/smoke-attribution-opt-in.mjs
|
||
|
||
pre-bash-hook-smoke:
|
||
# Regression guard for ruvnet/ruflo#2017 — the `pre-bash` PreToolUse hook
|
||
# in `.claude/helpers/hook-handler.cjs` is a security gate that refuses to
|
||
# run dangerous commands (`rm -rf /`, fork bombs, etc.). In 3.6.30 it
|
||
# silently exited 0 on every dangerous payload because the handler read
|
||
# the wrong stdin field (`toolInput` object instead of
|
||
# `toolInput.command` string), `.toLowerCase()` threw TypeError, and the
|
||
# global safety-timer try/catch swallowed it — printing a misleading
|
||
# "[OK] Command validated" while letting the dangerous command through.
|
||
#
|
||
# This smoke drives real Claude-Code-shaped PreToolUse JSON into BOTH
|
||
# the published template (v3/@claude-flow/cli/.claude/helpers/) and the
|
||
# repo's dogfood copy (.claude/helpers/), and fails on any of:
|
||
# - dangerous command + exit 0 (the security bypass)
|
||
# - "[OK] Command validated" on a dangerous input (the misleading log)
|
||
# - "[WARN] Hook X encountered an error" anywhere (silent-swallow shape)
|
||
#
|
||
# Independent job (not nested in plugin-hooks-smoke) so the gate is
|
||
# individually visible and the CI summary names the failure clearly.
|
||
name: pre-bash hook safety smoke (#2017)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Drive Claude-Code-shaped PreToolUse JSON through both handler copies
|
||
shell: bash
|
||
run: node scripts/smoke-pre-bash-hook.mjs
|
||
|
||
mcp-protocol-smoke:
|
||
# Regression guard for ruvnet/ruflo#1874 — boots the HTTP MCP server,
|
||
# sends a real `initialize` request, and validates the response wire
|
||
# format against the MCP spec (YYYY-MM-DD protocolVersion string,
|
||
# not a {major,minor,patch} object). This was the missing layer that
|
||
# let #1874 ship — the existing in-process unit tests asserted the
|
||
# wrong shape, so test+prod agreed on a non-spec format that broke
|
||
# Claude Code's Zod validator.
|
||
name: MCP protocol smoke / ${{ matrix.os }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [ubuntu-latest, macos-latest]
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Build mcp + shared packages (static scan needs dist)
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
pnpm --filter @claude-flow/mcp... --filter @claude-flow/shared... run build
|
||
|
||
- name: Run MCP protocol-shape compliance scan
|
||
shell: bash
|
||
run: node plugins/ruflo-core/scripts/test-mcp-protocol.mjs
|
||
|
||
memory-import-smoke:
|
||
# Regression guard for ruvnet/ruflo#1883 + #1884 — drives the import-side
|
||
# invariants that single-component tests missed:
|
||
# #1883 — memory_import_claude(allProjects=false) failed on WSL because
|
||
# project-hash derivation was POSIX-only. Verified via candidate
|
||
# set including the Claude-Code Windows hash form.
|
||
# #1884 — import handler skipped validateMemoryInput, producing keys
|
||
# memory_delete then rejected. Verified via property test
|
||
# against 27 adversarial inputs covering the full
|
||
# dangerous-character set.
|
||
# Static dist scan + property test combined cover the bug class.
|
||
name: Memory import smoke / ${{ matrix.os }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [ubuntu-latest, macos-latest]
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Build packages (static scan needs cli dist)
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
# Mirror witness-verify pattern — recursive + no-bail so unrelated
|
||
# package failures don't block this guard. The smoke script
|
||
# explicitly checks for memory-tools.js dist and fails loudly if
|
||
# the cli build itself didn't produce it.
|
||
pnpm --recursive --no-bail run build || true
|
||
|
||
- name: Run memory-import regression guards (#1883 + #1884)
|
||
shell: bash
|
||
run: node plugins/ruflo-core/scripts/test-memory-import.mjs
|
||
|
||
mcp-roundtrip-smoke:
|
||
# Regression guard for ruvnet/ruflo#1889 — paired MCP tool round-trip.
|
||
# When two MCP tools form a store/search pair, the contract is that
|
||
# data written by one MUST be retrievable by the other. The original
|
||
# bug: pattern-store wrote to memory-store-fallback while pattern-search
|
||
# only queried ReasoningBank (always empty), so writes were silently
|
||
# lost. Static dist-scan asserts both fallback paths are present;
|
||
# behavioural probe runs with an internal 30s timeout so CI never hangs
|
||
# on slow memory-backend init.
|
||
name: MCP paired-tool round-trip smoke (#1889)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Build cli (smoke needs dist)
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
pnpm --recursive --no-bail run build || true
|
||
|
||
- name: Run #1889 round-trip smoke
|
||
shell: bash
|
||
run: node plugins/ruflo-core/scripts/test-mcp-roundtrips.mjs
|
||
|
||
- name: Run #1863 cli-no-crash smoke
|
||
shell: bash
|
||
# Drives `task create` → `task status` + a few command formatters
|
||
# and asserts none crash with an unhandled exception. Catches the
|
||
# class where callMCPTool<{...}>() types a response field as
|
||
# non-optional but the server omits it → `.join()` on undefined.
|
||
run: node plugins/ruflo-core/scripts/test-cli-no-crash.mjs
|
||
|
||
- name: Run ADR-095 G2 consensus-transport guard
|
||
shell: bash
|
||
# Asserts @claude-flow/swarm ships a real pluggable ConsensusTransport
|
||
# (not the implicit single-process EventEmitter): required exports
|
||
# present, LocalTransport round-trip works, Ed25519 sign/verify is
|
||
# real (no `return true` stub regression). ADR-095 G2.
|
||
run: node plugins/ruflo-core/scripts/test-consensus-transport.mjs
|
||
|
||
tool-descriptions-audit:
|
||
# ADR-112 — gate: every MCP tool description must include "Use when …"
|
||
# guidance so Claude knows when to pick Ruflo's tool over native
|
||
# (Bash, Read, Grep, Glob, Task, TodoWrite, WebFetch). Baseline lives
|
||
# in verification/mcp-tool-baseline.json and is monotone-decreasing —
|
||
# the script fails the build if the no-guidance count goes UP. Run
|
||
# `node scripts/audit-tool-descriptions.mjs --update-baseline` after
|
||
# landing a description-improvement PR to lock the new floor.
|
||
name: Tool description discoverability (ADR-112)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run tool-description audit
|
||
shell: bash
|
||
run: node scripts/audit-tool-descriptions.mjs
|
||
|
||
- name: Run CLI ↔ MCP tool coverage audit (#1916)
|
||
# Fails if a `ruflo <cmd>` subcommand callMCPTool()s a tool that isn't
|
||
# registered in src/mcp-tools/*.ts (it would die with `MCP tool not
|
||
# found`). Monotone-decreasing baseline at verification/cli-mcp-tool-
|
||
# baseline.json — new dangling references fail; fixing one and running
|
||
# `node scripts/audit-cli-mcp-tools.mjs --update-baseline` lowers the floor.
|
||
shell: bash
|
||
run: node scripts/audit-cli-mcp-tools.mjs
|
||
|
||
plugin-package-audit:
|
||
# Regression guard for #1902/#1903/#1904 — plugin package.json install
|
||
# safety. Checks: (A) no unpublished @claude-flow/* hard dep / non-optional
|
||
# peer, (B) no bare-stable peer range that can't resolve a 3.x prerelease
|
||
# publish, (C) every main/module/exports path is covered by `files`,
|
||
# (D) after building each plugin, every main/module/exports path exists on
|
||
# disk (#1904). The build step is what makes check D live.
|
||
name: Plugin package install-safety (#1902/#1903/#1904)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install root deps (semver for audit-wrapper-dep-ranges)
|
||
# The audit-wrapper-dep-ranges.mjs script imports `semver` from the
|
||
# repo root node_modules. Run a root npm install BEFORE the audit
|
||
# job's main install/build step.
|
||
shell: bash
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
|
||
- name: Install workspace + build plugins (so check D — exports-exist-after-build — is live)
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
for d in plugins/*/; do
|
||
if [ -f "$d/package.json" ] && node -e "process.exit(require('./'+process.argv[1]+'package.json').scripts?.build?0:1)" "$d"; then
|
||
echo "::group::build $d"
|
||
( cd "$d" && pnpm install --frozen-lockfile 2>/dev/null || pnpm install 2>/dev/null || true; pnpm run build || true )
|
||
echo "::endgroup::"
|
||
fi
|
||
done
|
||
|
||
- name: Run plugin package audit
|
||
shell: bash
|
||
run: node scripts/audit-plugin-packages.mjs
|
||
|
||
- name: Run package dep-overlap audit (#1147 / #2018)
|
||
# Static guard for the "Invalid Version: " npm 11.x crash. Any package
|
||
# declaring the same dep name in both optionalDependencies AND
|
||
# peerDependencies trips arborist's dedupe pass when a transitive
|
||
# carries a "-dev." prerelease tag. Fail CI on the overlap.
|
||
shell: bash
|
||
run: node scripts/audit-package-dep-overlap.mjs
|
||
|
||
- name: Run wrapper dep-range audit (#2127)
|
||
# Catches stale alpha-tagged dep ranges in the ruflo wrapper and the
|
||
# claude-flow umbrella that point at sibling packages we publish.
|
||
# #2127 shipped with `ruflo → @claude-flow/cli@^3.7.0-alpha.11` even
|
||
# after cli moved to stable 3.10.0 — a pre-release range against a
|
||
# stable dep widens arborist's dedupe walk and can surface as the
|
||
# "Invalid Version: (empty)" crash on some npm/Node combos.
|
||
shell: bash
|
||
run: node scripts/audit-wrapper-dep-ranges.mjs
|
||
|
||
- name: Run umbrella version-lockstep audit (#2151)
|
||
# Asserts @claude-flow/cli, claude-flow, and ruflo all share the
|
||
# same version. #2151 reported ruflo@3.10.2 + cli@3.10.1 drift —
|
||
# `npx ruflo --version` printed the bundled CLI's 3.10.1, not the
|
||
# wrapper's 3.10.2. CLAUDE.md publish rules already require lockstep;
|
||
# this audit enforces it so drift can't reach a release.
|
||
shell: bash
|
||
run: node scripts/audit-umbrella-version-lockstep.mjs
|
||
|
||
- name: Run better-sqlite3 override audit (#2219)
|
||
# agentdb pins better-sqlite3 as an OPTIONAL dep at ^11.8.1, which has
|
||
# no Node 24/25/26 prebuild → the optional native build fails silently
|
||
# on those runtimes and AgentDB drops to a non-persistent backend
|
||
# (silent write loss). Asserts both the root umbrella and the ruflo
|
||
# wrapper override better-sqlite3 to >=12.8.0 (which ships Node 20–26
|
||
# prebuilds). Root overrides do NOT reach the published wrapper (#2112),
|
||
# so both must carry it.
|
||
shell: bash
|
||
run: node scripts/audit-better-sqlite3-override.mjs
|
||
|
||
- name: Run plugin-hooks cross-platform audit (#2132)
|
||
# Catches /bin/bash literals, POSIX-only pipelines (jq, xargs, tr),
|
||
# and .sh script invocations in plugin hooks.json files — patterns
|
||
# that fail on native Windows (exit 126).
|
||
# Files with "_platform": "posix" are exempt (Mac/Linux-only, verified
|
||
# to have a companion ruflo-hook.cjs Windows shim). New hooks.json
|
||
# files without the marker are scanned strictly.
|
||
# Strict (no continue-on-error) — fixed in PR fix/2132-windows-hooks.
|
||
shell: bash
|
||
run: node scripts/audit-plugin-hooks-cross-platform.mjs
|
||
|
||
- name: Run env-var-precedence audit (ADR-125 / ADR-130)
|
||
# Guards the "CLI flag > ENV var > default" precedence rule added in
|
||
# ADR-125 (rvagent integration) and ADR-130 (graph intelligence).
|
||
# Scans v3/cli/src and plugins/ for any CLAUDE_FLOW_* / RUFLO_* env
|
||
# var read that lacks a documented CLI-flag override path or is not
|
||
# registered as an intentional escape hatch (CI/credential/process
|
||
# signal). Fails closed (exit 1) — prevents future contributors from
|
||
# silently ignoring explicit CLI flags when an env var is set.
|
||
# Strict (no continue-on-error).
|
||
shell: bash
|
||
run: node scripts/audit-env-var-precedence.mjs
|
||
|
||
cli-npx-install-smoke:
|
||
# Regression guard for ruvnet/ruflo#1147 and #2018 — both report:
|
||
# $ npx @claude-flow/cli@latest …
|
||
# npm error Invalid Version:
|
||
# Caused by an optionalDependencies/peerDependencies overlap deep in the
|
||
# dep tree (see scripts/audit-package-dep-overlap.mjs for the static
|
||
# guard). This is the BEHAVIOURAL guard: pack the locally-built CLI,
|
||
# install the tarball into a scratch project, fail if `npm install`
|
||
# prints "Invalid Version" or exits non-zero. Runs on Node 22 + 24 so
|
||
# the newer npm shipped with Node 24 (where the bug surfaces) is
|
||
# actually exercised.
|
||
name: CLI npx-install smoke (#1147 / #2018) / Node ${{ matrix.node }}
|
||
runs-on: ubuntu-latest
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
node: ['22', '24']
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js ${{ matrix.node }}
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ matrix.node }}
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Build cli (smoke packs from its dist/)
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
pnpm --recursive --no-bail run build || true
|
||
test -f @claude-flow/cli/bin/cli.js \
|
||
|| (echo "cli build did not produce bin/cli.js"; exit 1)
|
||
|
||
- name: Pack, install, and run cli (asserts no 'Invalid Version' crash)
|
||
shell: bash
|
||
run: node scripts/smoke-cli-npx-install.mjs
|
||
|
||
windows-hook-shim-smoke:
|
||
# Smoke test for ruvnet/ruflo#2132 — ruflo-hook.cjs cross-platform shim.
|
||
# Proves that plugins/ruflo-core/scripts/ruflo-hook.cjs can be invoked
|
||
# via `node ruflo-hook.cjs <subcommand>`, always exits 0, and accepts
|
||
# stdin JSON input without crashing.
|
||
# Runs on all 3 OS to prove cross-platform behaviour.
|
||
name: Windows hook shim smoke (#2132) / ${{ matrix.os }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run ruflo-hook.cjs smoke
|
||
shell: bash
|
||
run: node scripts/smoke-ruflo-hook-cjs.mjs
|
||
|
||
windows-init-hooks-smoke:
|
||
# Smoke test for ruvnet/ruflo#2132 — init-time platform detection.
|
||
# Proves ruflo init generates correct hook commands per platform:
|
||
# - windows-latest: node-based (no /bin/bash, no | jq)
|
||
# - ubuntu/macos: POSIX-compatible (sh-based, no cmd.exe patterns)
|
||
# Also verifies ruflo-hook.cjs is always deployed to .claude/helpers/.
|
||
name: Windows init hooks smoke (#2132) / ${{ matrix.os }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Build CLI
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
pnpm --recursive --no-bail run build || true
|
||
# --no-bail lets unrelated workspace failures pass; assert the
|
||
# one dist file the smoke needs is actually produced.
|
||
test -f @claude-flow/cli/bin/cli.js \
|
||
|| (echo "::error::cli build did not produce bin/cli.js"; exit 1)
|
||
|
||
- name: Run init hooks smoke
|
||
shell: bash
|
||
run: node scripts/smoke-windows-init-hooks.mjs
|
||
|
||
windows-hook-execution-smoke:
|
||
# End-to-end validation for ruvnet/ruflo#2132 — simulates a Claude Code
|
||
# PostToolUse hook firing. Asserts exit code != 126 ("cannot execute
|
||
# binary file") and no POSIX-only pipeline patterns in the generated
|
||
# settings.json hook commands.
|
||
# Primary target: windows-latest (the OS that originally broke).
|
||
# Also runs on ubuntu/macos to catch POSIX regression.
|
||
name: Windows hook execution smoke (#2132) / ${{ matrix.os }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Build CLI
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
pnpm --recursive --no-bail run build || true
|
||
|
||
- name: Run Windows hook execution smoke
|
||
shell: bash
|
||
run: node scripts/smoke-windows-hook-execution.mjs
|
||
|
||
hook-command-audit:
|
||
# Regression guard for #1921 (and #1147) — plugin hooks.json must not
|
||
# invoke a bare `npx <pkg>@alpha hooks …` per fire. The fix is
|
||
# scripts/ruflo-hook.sh (prefers a local `ruflo`/`claude-flow` binary,
|
||
# falls back to `npx --prefer-offline`, always exits 0).
|
||
name: Hook-command install safety (#1921)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run hook-command audit
|
||
shell: bash
|
||
run: node scripts/audit-hook-commands.mjs
|
||
|
||
- name: Run hook-handler prompt-resolution audit (#1944)
|
||
shell: bash
|
||
run: node scripts/audit-hook-handler-prompt.mjs
|
||
|
||
- name: Run fix-invariants audit (presence-check guard for #1939, #1941, #1943, #1945, #1946, #1951, #1953, #1968)
|
||
shell: bash
|
||
run: node scripts/audit-fix-invariants.mjs
|
||
|
||
- name: Run neural-trader install-safety audit (#1974)
|
||
shell: bash
|
||
run: node scripts/audit-neural-trader-safety.mjs
|
||
|
||
- name: Lint the ruflo-hook shims
|
||
shell: bash
|
||
run: |
|
||
# Every shim must be valid bash and exit 0 even when no CLI is
|
||
# reachable (the #1921 contract). Probe with an empty PATH (invoke
|
||
# bash by full path since PATH= can't find it otherwise).
|
||
BASH="$(command -v bash)"
|
||
for sh in $(git ls-files '**/scripts/ruflo-hook.sh'); do
|
||
echo "checking $sh"
|
||
bash -n "$sh"
|
||
PATH= "$BASH" "$sh" modify-bash </dev/null || { echo "::error::$sh did not exit 0 with no CLI on PATH"; exit 1; }
|
||
done
|
||
|
||
vector-dim-audit:
|
||
# Regression guard for #1947 / #1942 / #1952 — `vector_indexes` rows for
|
||
# the `default` and `patterns` namespaces must use `dimensions = 384` to
|
||
# match the default ONNX embedding model (Xenova/all-MiniLM-L6-v2). A
|
||
# mismatched dim (the historical 768) is silent: HNSW rejects every
|
||
# `memory_store --vector` insert and `memory_search` always returns 0.
|
||
name: Vector-index dimension audit (#1947)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run vector-dim audit
|
||
shell: bash
|
||
run: node scripts/audit-vector-dim.mjs
|
||
|
||
tool-output-guardrail-smoke:
|
||
# Smoke test for ADR-131 / ruvnet/ruflo#2149 — ToolOutputGuardrail
|
||
# detects the four canonical OWASP ASI01 (Agent Goal Hijacking) attack
|
||
# shapes (instruction override, ChatML/Llama frame injection, exfiltration)
|
||
# and enforces the documented default policy (critical→reject,
|
||
# high→redact, medium→flag, low/none→allow).
|
||
#
|
||
# The exhaustive behavioural surface is the package's vitest suite; this
|
||
# smoke runs against the *built* dist/index.js to catch missing exports
|
||
# or accidental relaxation of the default policy.
|
||
name: ToolOutputGuardrail smoke (ADR-131, #2149)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Build @claude-flow/security
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
pnpm --filter @claude-flow/security run build
|
||
test -f @claude-flow/security/dist/index.js \
|
||
|| (echo "::error::@claude-flow/security/dist/index.js missing after build"; exit 1)
|
||
|
||
- name: Run guardrail smoke
|
||
shell: bash
|
||
run: node scripts/smoke-tool-output-guardrail.mjs
|
||
|
||
witness-verify:
|
||
# Cryptographic regression guard: runs `ruflo verify --manifest` against
|
||
# the local build to confirm every documented fix in verification.md.json
|
||
# still has its marker present. Catches silent regression of any of the
|
||
# 81+ fixes without requiring per-fix smoke tests.
|
||
#
|
||
# The smoke jobs above (smoke-install-no-bsqlite, plugin-hooks-smoke)
|
||
# exercise *behavior*; this job validates *presence* — both layers
|
||
# combined are what gates `publish`.
|
||
#
|
||
# Builds the cli + memory + security packages specifically (the ones
|
||
# whose dist files are referenced by witness markers). Avoids depending
|
||
# on the workspace `build` job so unrelated package failures don't
|
||
# block this regression guard.
|
||
#
|
||
# Cross-platform: ubuntu + macos + windows. The standalone verifier
|
||
# is pure JS (only @noble/ed25519) — no native deps, no shell calls.
|
||
# Catches platform-specific JSON canonicalization or path-resolution
|
||
# bugs (e.g. CRLF normalization on Windows breaking the manifest
|
||
# hash) before they reach users.
|
||
name: Witness verify (signed manifest) / ${{ matrix.os }}
|
||
runs-on: ${{ matrix.os }}
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||
needs: [smoke-install-no-bsqlite, plugin-hooks-smoke, pre-bash-hook-smoke, witness-verify-precondition-smoke, witness-marker-drift-smoke, browser-rvf-create-flags-smoke, mcp-protocol-smoke, memory-import-smoke, tool-descriptions-audit, mcp-roundtrip-smoke, plugin-package-audit, cli-npx-install-smoke, hook-command-audit, vector-dim-audit, windows-hook-shim-smoke, windows-init-hooks-smoke, windows-hook-execution-smoke]
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install + build packages witness markers reference
|
||
working-directory: v3
|
||
shell: bash
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
# --no-bail tolerates unrelated package failures. The standalone
|
||
# verify.mjs below checks specific dist files exist; if a
|
||
# marker-cited file is missing, witness-verify reports it.
|
||
pnpm --recursive --no-bail run build || true
|
||
|
||
- name: Verify witness manifest (via standalone plugin script — no CLI dep)
|
||
# `shell: bash` makes Windows use git-bash so the same script
|
||
# works across all 3 OSes. RUNNER_TEMP is set on every runner.
|
||
shell: bash
|
||
run: |
|
||
# Use the project-agnostic verifier from ruflo-core plugin. This
|
||
# is the same script external adopters use — dogfooding ensures
|
||
# the plugin pathway works and avoids CI-specific cli build
|
||
# issues (e.g. missing @ruvector/sona, sharp native postinstall).
|
||
# Capture both streams; analyze regardless of exit code so we
|
||
# always see WHY a verification failed.
|
||
# OS-specific manifest path (verification/<os>/manifest.md.json).
|
||
# Each runner reads its own snapshot — Linux runner reads
|
||
# verification/linux/, macOS reads verification/macos/, etc.
|
||
case "$RUNNER_OS" in
|
||
Linux) OS_DIR=linux ;;
|
||
macOS) OS_DIR=macos ;;
|
||
Windows) OS_DIR=windows ;;
|
||
*) OS_DIR=linux ;;
|
||
esac
|
||
MANIFEST="verification/$OS_DIR/manifest.md.json"
|
||
echo "verifying: $MANIFEST"
|
||
set +e
|
||
node plugins/ruflo-core/scripts/witness/verify.mjs \
|
||
--manifest "$MANIFEST" \
|
||
--json > "$RUNNER_TEMP/witness-result.json" 2> "$RUNNER_TEMP/witness-result.err"
|
||
VERIFY_EXIT=$?
|
||
set -e
|
||
echo "--- verify.mjs exit code: $VERIFY_EXIT ---"
|
||
echo "--- stderr ---"
|
||
cat "$RUNNER_TEMP/witness-result.err" || true
|
||
echo "--- summary ---"
|
||
node -e "
|
||
const fs = require('fs');
|
||
const raw = fs.readFileSync(process.env.RUNNER_TEMP + '/witness-result.json', 'utf8');
|
||
if (!raw.trim()) { console.error('verify.mjs produced no JSON output'); process.exit(1); }
|
||
const r = JSON.parse(raw);
|
||
console.log(JSON.stringify({signature: r.signature, summary: r.summary}, null, 2));
|
||
const failures = (r.results || []).filter(x => x.status !== 'pass' && x.status !== 'drift');
|
||
if (failures.length) {
|
||
console.error('non-pass fixes:');
|
||
for (const f of failures) console.error(' ' + f.status + ': ' + f.id + ' (' + f.file + ')');
|
||
}
|
||
if (!r.ok) { console.error('witness verify FAILED'); process.exit(1); }
|
||
if (r.summary.regressed > 0) { console.error('regressed fixes:', r.summary.regressed); process.exit(1); }
|
||
console.log('witness verify ok:', r.summary.pass, 'pass,', r.summary.drift, 'drift');
|
||
"
|
||
|
||
- name: Performance verification (lightweight capabilities only)
|
||
# Soft gate: appends to verification/<os>/performance.jsonl. Skips
|
||
# install_no_optional + memory_round_trip in CI to keep the matrix
|
||
# fast — those are slow + network/disk-bound and add minutes.
|
||
# Local devs run the full suite with `--capabilities all` (omitted).
|
||
shell: bash
|
||
run: |
|
||
case "$RUNNER_OS" in
|
||
Linux) OS_DIR=linux ;;
|
||
macOS) OS_DIR=macos ;;
|
||
Windows) OS_DIR=windows ;;
|
||
esac
|
||
node plugins/ruflo-core/scripts/witness/perf.mjs \
|
||
--output "verification/$OS_DIR/performance.jsonl" \
|
||
--capabilities install_pack,memory_load,witness_verify \
|
||
--baseline || echo "perf bench errored — non-blocking"
|
||
|
||
- name: History summary (ADR-103 — surface regression-introduction commits)
|
||
# Soft gate: prints transitions since the previous snapshot. The
|
||
# `summary` subcommand exits non-zero on any newly-regressed fix.
|
||
shell: bash
|
||
run: |
|
||
case "$RUNNER_OS" in
|
||
Linux) OS_DIR=linux ;;
|
||
macOS) OS_DIR=macos ;;
|
||
Windows) OS_DIR=windows ;;
|
||
*) OS_DIR=linux ;;
|
||
esac
|
||
HISTORY="verification/$OS_DIR/history.jsonl"
|
||
if [ -f "$HISTORY" ]; then
|
||
node plugins/ruflo-core/scripts/witness/history.mjs \
|
||
--history "$HISTORY" \
|
||
summary
|
||
else
|
||
echo "$HISTORY not present — skipping temporal diff"
|
||
fi
|
||
|
||
publish:
|
||
name: Publish to npm (alpha)
|
||
runs-on: ubuntu-latest
|
||
needs: [build, smoke-install-no-bsqlite, plugin-hooks-smoke, witness-verify]
|
||
if: github.ref == 'refs/heads/v3' && github.event_name == 'push'
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: ${{ env.NODE_VERSION }}
|
||
registry-url: 'https://registry.npmjs.org'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install dependencies
|
||
working-directory: v3
|
||
run: pnpm install --frozen-lockfile
|
||
|
||
- name: Build
|
||
working-directory: v3
|
||
run: pnpm build
|
||
|
||
- name: Publish alpha
|
||
working-directory: v3
|
||
run: pnpm publish:alpha
|
||
env:
|
||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||
|
||
init-bundle-invariants-smoke:
|
||
# Regression guard for ruvnet/ruflo#2095 — ADR-128 Phase 5.
|
||
#
|
||
# Statically asserts three invariants of the @claude-flow/cli init bundle:
|
||
#
|
||
# 1. NO ORPHANED DIRECTORIES — every subdirectory under
|
||
# v3/@claude-flow/cli/.claude/{commands,agents}/ is reachable from
|
||
# COMMANDS_MAP or AGENTS_MAP in executor.ts.
|
||
#
|
||
# 2. SKILLS_MAP COMPLETENESS — every skill referenced in SKILLS_MAP
|
||
# has a SKILL.md (or README.md) inside the package's .claude/skills/.
|
||
#
|
||
# 3. NO INIT-PLUGIN AGENT COLLISION — no .md in the init-template
|
||
# agents/ shares a basename with any plugin agent. Enforces the
|
||
# "plugin is canonical" dedup rule from ADR-128 Phase 2.
|
||
#
|
||
# Zero runtime deps; pure Node.js readFileSync + readdirSync.
|
||
name: init-bundle invariants smoke (#2095, ADR-128 Phase 5)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run init-bundle invariants smoke
|
||
run: node scripts/smoke-init-bundle-invariants.mjs
|
||
|
||
wasm-provider-bridge-smoke:
|
||
# ADR-129 Phase 1 — JsModelProvider routes WasmAgent through the v3
|
||
# provider system. Pre-P1: set_model_provider() was never called and
|
||
# the echo-stub bypass competed with the WASM runtime. P1 fix:
|
||
# attachJsModelProvider() is called at agent-creation time.
|
||
# Static-only smoke: no build, no API keys required.
|
||
name: wasm provider bridge smoke (ADR-129 P1)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run wasm provider bridge smoke
|
||
run: node scripts/smoke-wasm-provider-bridge.mjs
|
||
|
||
wasm-compose-smoke:
|
||
# ADR-129 Phase 2 — wasm_agent_compose MCP tool + addMcpTools bridge.
|
||
# Fixes the silent drop of template.mcp_tools in buildRvfFromTemplate.
|
||
# Static-only smoke: no build, no API keys required.
|
||
name: wasm compose smoke (ADR-129 P2)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run wasm compose smoke
|
||
run: node scripts/smoke-wasm-rvf-compose.mjs
|
||
|
||
wasm-gallery-crud-smoke:
|
||
# ADR-129 Phase 3 — 16 new MCP tools (10 gallery CRUD + 6 agent
|
||
# introspection), with AIDefence gate on wasm_gallery_import.
|
||
# Static-only smoke: no build, no API keys required.
|
||
name: wasm gallery CRUD smoke (ADR-129 P3)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run wasm gallery CRUD smoke
|
||
run: node scripts/smoke-wasm-gallery-crud.mjs
|
||
|
||
wasm-plugin-bridge-smoke:
|
||
# ADR-129 Phase 4 — plugin manifest "rvagent" field + includePlugins
|
||
# in wasm_agent_compose. Static + behavioral fixture smoke.
|
||
name: wasm plugin bridge smoke (ADR-129 P4)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Run wasm plugin bridge smoke
|
||
run: node scripts/smoke-wasm-plugin-bridge.mjs
|
||
|
||
graph-schema-smoke:
|
||
# ADR-130 Phase 1 — graph_edges schema + PQ encoder + edge writer
|
||
name: graph schema smoke (ADR-130 P1)
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install root deps (sql.js for smoke scripts)
|
||
# The smoke scripts use `await import('sql.js')` (bare ESM specifier),
|
||
# which resolves from root node_modules. pnpm install inside v3/ alone
|
||
# does not reliably expose sql.js to scripts run from the repo root.
|
||
# Same pattern as the #2120 memory-stats smoke job.
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
|
||
- name: Build better-sqlite3 native binding for graph-edge-writer
|
||
# --ignore-scripts above skipped better-sqlite3's prebuild-install,
|
||
# leaving node_modules/better-sqlite3 on disk without the .node
|
||
# binary. The graph-edge-writer does `await import('better-sqlite3')`
|
||
# which Node resolves from the importing module's nearest
|
||
# node_modules — that ends up being the *root* tree (closer than
|
||
# v3/.pnpm), so the broken root copy wins and _openDb returns null
|
||
# → insertGraphEdge returns false → TEST 2/3/5 all fail. Rebuild it.
|
||
run: npm rebuild better-sqlite3
|
||
|
||
- name: Install v3 workspace deps and build
|
||
run: |
|
||
cd v3
|
||
pnpm install --frozen-lockfile
|
||
pnpm -r build
|
||
|
||
- name: Run graph schema smoke
|
||
run: node scripts/smoke-graph-schema-migration.mjs
|
||
|
||
graph-query-smoke:
|
||
# ADR-130 Phase 2+5 — agentdb_graph-query + agentdb_graph-pathfinder dispatch
|
||
name: graph query + pathfinder smoke (ADR-130 P2+P5)
|
||
runs-on: ubuntu-latest
|
||
needs: graph-schema-smoke
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
|
||
- name: Install root deps (sql.js for the smoke fixture)
|
||
# Same pattern as the graph-schema-smoke job — sql.js is a root
|
||
# transitive dep, not declared in any workspace package.json.
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
|
||
- name: Build better-sqlite3 native binding
|
||
# See graph-schema-smoke comment — same root-resolution hazard.
|
||
run: npm rebuild better-sqlite3
|
||
|
||
- name: Install v3 workspace deps and build
|
||
run: |
|
||
cd v3
|
||
pnpm install --frozen-lockfile
|
||
pnpm -r build
|
||
|
||
- name: Symlink sql.js into v3/node_modules
|
||
run: |
|
||
mkdir -p v3/node_modules
|
||
ln -sfn "$(pwd)/node_modules/sql.js" v3/node_modules/sql.js
|
||
|
||
- name: Run graph query dispatch smoke
|
||
run: node scripts/smoke-graph-query-dispatch.mjs
|
||
- name: Run graph pathfinder smoke
|
||
run: node scripts/smoke-graph-pathfinder.mjs
|
||
|
||
graph-trajectory-smoke:
|
||
# ADR-130 Phase 3 — SONA trajectory-to-graph hooks
|
||
name: graph trajectory hooks smoke (ADR-130 P3)
|
||
runs-on: ubuntu-latest
|
||
needs: graph-schema-smoke
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
- name: Install root deps (sql.js for smoke scripts)
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
- name: Build better-sqlite3 native binding
|
||
# See graph-schema-smoke comment — same root-resolution hazard.
|
||
run: npm rebuild better-sqlite3
|
||
- name: Install dependencies and build
|
||
run: |
|
||
cd v3
|
||
pnpm install --frozen-lockfile
|
||
pnpm -r build
|
||
- name: Run trajectory graph edges smoke
|
||
# #2312 root cause (fixed): memory-bridge's rescueAgentdbEmbedder
|
||
# patched agentdb.embedder.embed to delegate to generateEmbedding —
|
||
# which is bridge-first, so the patched embed re-entered itself via
|
||
# bridgeGenerateEmbedding in an unbounded async cycle (heap OOM at
|
||
# the V8 limit, SIGABRT 134; SONA/EWC were innocent). The rescue now
|
||
# delegates to generateLocalEmbedding (a bridge-free leaf), so this
|
||
# smoke gates again at default heap — verified green in a node:22
|
||
# Linux container at 512 MB with a cold model cache.
|
||
run: node scripts/smoke-trajectory-graph-edges.mjs
|
||
|
||
graph-plugin-adapter-smoke:
|
||
# ADR-130 Phase 4 — plugin adapter contract (GraphEdgesSource)
|
||
name: graph plugin adapter smoke (ADR-130 P4)
|
||
runs-on: ubuntu-latest
|
||
needs: graph-schema-smoke
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
- name: Install root deps (sql.js for smoke scripts)
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
- name: Build better-sqlite3 native binding
|
||
# See graph-schema-smoke comment — same root-resolution hazard.
|
||
run: npm rebuild better-sqlite3
|
||
- name: Install dependencies and build
|
||
run: |
|
||
cd v3
|
||
pnpm install --frozen-lockfile
|
||
pnpm -r build
|
||
- name: Run graph plugin adapter smoke
|
||
run: node scripts/smoke-graph-plugin-adapter.mjs
|
||
|
||
graph-benchmark:
|
||
# ADR-130 Phase 6 — graph write/query throughput benchmark
|
||
name: graph benchmark (ADR-130 P6)
|
||
runs-on: ubuntu-latest
|
||
needs: [graph-query-smoke, graph-trajectory-smoke, graph-plugin-adapter-smoke]
|
||
timeout-minutes: 40
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
cache: 'pnpm'
|
||
cache-dependency-path: v3/pnpm-lock.yaml
|
||
- name: Install root deps (sql.js for smoke scripts)
|
||
run: npm install --legacy-peer-deps --no-audit --no-fund --ignore-scripts
|
||
- name: Build better-sqlite3 native binding
|
||
# See graph-schema-smoke comment — same root-resolution hazard.
|
||
run: npm rebuild better-sqlite3
|
||
- name: Install dependencies and build
|
||
run: |
|
||
cd v3
|
||
pnpm install --frozen-lockfile
|
||
pnpm -r build
|
||
- name: Run graph benchmark
|
||
run: node scripts/benchmark-graph.mjs
|
||
|
||
statusline-generator-delegation-smoke:
|
||
# Regression guard for ruvnet/ruflo#2195 — the statusline generator
|
||
# previously re-implemented all data readers locally with fragile file
|
||
# probes that returned wrong values (DDD 0/5, intelligence 1%, ADR 87/87).
|
||
#
|
||
# The fix delegates to 'npx @claude-flow/cli@latest hooks statusline --json'
|
||
# as the single source of truth and counts ADRs in BOTH directories
|
||
# (v3/implementation/adrs/ + v3/docs/adr/).
|
||
#
|
||
# Two guards:
|
||
# [1/2] STATIC — assert generator still delegates to the CLI command
|
||
# and does NOT contain the old fragile heuristics.
|
||
# [2/2] SMOKE — build the CLI, run the generated .cjs with --json,
|
||
# assert all numeric fields are within valid ranges and that
|
||
# the known-bad fallback values (domainsCompleted=0 when patterns>0,
|
||
# intelligencePct=1 when system is healthy) are not present.
|
||
name: statusline generator delegation smoke (#2195)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Guard 1 — static delegation contract
|
||
shell: bash
|
||
run: |
|
||
echo "Checking that statusline-generator.ts delegates to 'hooks statusline --json'..."
|
||
grep -q "hooks statusline --json" v3/@claude-flow/cli/src/init/statusline-generator.ts \
|
||
|| { echo "::error::statusline-generator.ts no longer delegates to 'hooks statusline --json' — regression of #2195"; exit 1; }
|
||
echo "ok: delegation pattern found"
|
||
|
||
echo "Checking that the old fragile heuristics are NOT present..."
|
||
# The buggy fallback computed domains from file-based pattern counts —
|
||
# this produced domainsCompleted=0 when AgentDB had 26k+ patterns.
|
||
! grep -q "getLearningStats\b" v3/@claude-flow/cli/src/init/statusline-generator.ts \
|
||
|| { echo "::error::statusline-generator.ts still has getLearningStats (old local reader) — regression of #2195"; exit 1; }
|
||
! grep -q "getV3Progress\b" v3/@claude-flow/cli/src/init/statusline-generator.ts \
|
||
|| { echo "::error::statusline-generator.ts still has getV3Progress (old local reader) — regression of #2195"; exit 1; }
|
||
echo "ok: old local-reader heuristics removed"
|
||
|
||
echo "Checking that both ADR directories are counted..."
|
||
grep -q "v3/docs/adr" v3/@claude-flow/cli/src/init/statusline-generator.ts \
|
||
|| { echo "::error::statusline-generator.ts missing v3/docs/adr ADR directory — regression of #2195 ADR-count bug"; exit 1; }
|
||
grep -q "v3/implementation/adrs" v3/@claude-flow/cli/src/init/statusline-generator.ts \
|
||
|| { echo "::error::statusline-generator.ts missing v3/implementation/adrs ADR directory"; exit 1; }
|
||
echo "ok: both ADR directories present"
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Install and build CLI
|
||
working-directory: v3
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
pnpm --recursive --no-bail run build || true
|
||
test -f @claude-flow/cli/dist/src/init/statusline-generator.js \
|
||
|| { echo "::error::statusline-generator.js not built"; exit 1; }
|
||
|
||
- name: "Guard 2 — smoke: generate .cjs and validate output ranges"
|
||
shell: bash
|
||
run: node scripts/smoke-statusline-generator-delegation.mjs
|
||
|
||
wizard-init-regression-guard:
|
||
# Regression guard for ruvnet/ruflo#2206 #2207 #2208 — three init-wizard
|
||
# bugs that collectively broke every new user install:
|
||
#
|
||
# #2206: mcp-generator registered the server under key 'ruflo', causing all
|
||
# 33 ruflo plugins to fail with "Unknown tool mcp__claude-flow__*".
|
||
# The key must be 'claude-flow'; the command args (ruflo@latest) are
|
||
# correct and must NOT change.
|
||
#
|
||
# #2207: detectExistingRufloMCP only checked for 'ruflo' in mcpServers.
|
||
# After #2206, the key becomes 'claude-flow', so the detector would
|
||
# NEVER recognise a prior install. Both keys must be accepted. Also
|
||
# guarded: bare .claude/settings.json must NOT be a false positive.
|
||
#
|
||
# #2208: init --force silently destroyed existing CLAUDE.md without backup,
|
||
# causing data loss. A .pre-ruflo backup must be created before
|
||
# any overwrite; timestamped fallback when a backup already exists.
|
||
#
|
||
# Three guards (static + runtime each):
|
||
# [1/3] STATIC #2206 — mcp-generator source must write 'claude-flow' key
|
||
# [2/3] RUNTIME #2206 + #2208 — build CLI, run init in tmp dir, assert
|
||
# .mcp.json has 'claude-flow' key and CLAUDE.md.pre-ruflo was created
|
||
# [3/3] RUNTIME #2207 — bare .claude/settings.json must NOT trigger
|
||
# the duplicate-detection guard (false-positive check)
|
||
name: wizard init regression guard (#2206 #2207 #2208)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '22'
|
||
|
||
- name: Guard 1 — static #2206 server key contract
|
||
shell: bash
|
||
run: |
|
||
echo "=== Guard 1: mcp-generator must write the claude-flow key ==="
|
||
|
||
echo "Checking mcp-generator uses 'claude-flow' as the server key..."
|
||
grep -qE "mcpServers\['claude-flow'\]|mcpServers\[\"claude-flow\"\]" \
|
||
v3/@claude-flow/cli/src/init/mcp-generator.ts \
|
||
|| { echo "::error::mcp-generator no longer writes 'claude-flow' server key — #2206 regression"; exit 1; }
|
||
echo "ok: 'claude-flow' key found"
|
||
|
||
echo "Checking mcp-generator does NOT use bare 'ruflo' as the server key..."
|
||
! grep -qE "mcpServers\['ruflo'\]|mcpServers\[\"ruflo\"\]" \
|
||
v3/@claude-flow/cli/src/init/mcp-generator.ts \
|
||
|| { echo "::error::mcp-generator writes 'ruflo' server key — breaks mcp__claude-flow__* tool naming (#2206)"; exit 1; }
|
||
echo "ok: bare 'ruflo' server key absent"
|
||
|
||
echo "Checking command args still invoke ruflo@latest (must NOT change)..."
|
||
grep -q "ruflo@latest" v3/@claude-flow/cli/src/init/mcp-generator.ts \
|
||
|| { echo "::error::mcp-generator no longer invokes ruflo@latest — command args must be preserved (#2206)"; exit 1; }
|
||
echo "ok: ruflo@latest invocation present"
|
||
|
||
echo "Guard 1 passed."
|
||
|
||
- name: Setup pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: ${{ env.PNPM_VERSION }}
|
||
|
||
- name: Install and build CLI
|
||
working-directory: v3
|
||
run: |
|
||
pnpm install --frozen-lockfile
|
||
pnpm --recursive --no-bail run build || true
|
||
test -f @claude-flow/cli/dist/src/init/executor.js \
|
||
|| { echo "::error::executor.js not built — CLI build failed"; exit 1; }
|
||
test -f @claude-flow/cli/dist/src/init/mcp-generator.js \
|
||
|| { echo "::error::mcp-generator.js not built"; exit 1; }
|
||
|
||
- name: Guard 2 — runtime #2206 server key + #2208 CLAUDE.md backup
|
||
shell: bash
|
||
run: |
|
||
echo "=== Guard 2: generated .mcp.json key and CLAUDE.md backup ==="
|
||
|
||
TMP=$(mktemp -d)
|
||
cd "$TMP"
|
||
|
||
# Seed CLAUDE.md with sentinel content so #2208 backup is observable
|
||
printf '# Sentinel Project Content — do not lose\n' > CLAUDE.md
|
||
|
||
# Run init --force (non-interactive); ignore non-zero exit from
|
||
# optional components that need extra deps (skills, helpers, etc.)
|
||
HOME="$TMP" node "$GITHUB_WORKSPACE/v3/@claude-flow/cli/bin/cli.js" \
|
||
init --force 2>&1 || true
|
||
|
||
echo "--- .mcp.json contents ---"
|
||
cat .mcp.json 2>/dev/null || echo "(not found)"
|
||
|
||
# #2206: 'claude-flow' key must exist
|
||
node -e "
|
||
const cfg = JSON.parse(require('fs').readFileSync('.mcp.json','utf-8'));
|
||
if (!cfg.mcpServers || !('claude-flow' in cfg.mcpServers)) {
|
||
console.error('FAIL: .mcp.json missing claude-flow server key (#2206)');
|
||
process.exit(1);
|
||
}
|
||
console.log('ok: claude-flow key present in .mcp.json');
|
||
" || { echo "::error::generated .mcp.json missing 'claude-flow' server key (#2206)"; exit 1; }
|
||
|
||
# #2206: stray 'ruflo' key must NOT exist
|
||
node -e "
|
||
const cfg = JSON.parse(require('fs').readFileSync('.mcp.json','utf-8'));
|
||
if (cfg.mcpServers && 'ruflo' in cfg.mcpServers) {
|
||
console.error('FAIL: .mcp.json has stray ruflo server key (#2206)');
|
||
process.exit(1);
|
||
}
|
||
console.log('ok: stray ruflo key absent');
|
||
" || { echo "::error::generated .mcp.json has stray 'ruflo' server key (#2206)"; exit 1; }
|
||
|
||
# #2208: CLAUDE.md.pre-ruflo backup must exist with sentinel content
|
||
BACKUP=$(ls CLAUDE.md.pre-ruflo* 2>/dev/null | head -1)
|
||
if [ -z "$BACKUP" ]; then
|
||
echo "::error::init --force did not create CLAUDE.md.pre-ruflo backup (#2208)"
|
||
exit 1
|
||
fi
|
||
echo "ok: backup file created: $BACKUP"
|
||
grep -q "Sentinel Project Content" "$BACKUP" \
|
||
|| { echo "::error::CLAUDE.md backup missing original sentinel content (#2208)"; exit 1; }
|
||
echo "ok: backup contains original content"
|
||
|
||
echo "Guard 2 passed."
|
||
|
||
- name: Guard 3 — runtime #2207 false-positive check
|
||
shell: bash
|
||
run: |
|
||
echo "=== Guard 3: bare .claude/settings.json must NOT trigger duplicate detection ==="
|
||
|
||
TMP=$(mktemp -d)
|
||
cd "$TMP"
|
||
|
||
# Simulate Claude Code's own project settings.json with NO ruflo registration
|
||
mkdir -p .claude
|
||
echo '{"env": {}, "hooks": {}}' > .claude/settings.json
|
||
|
||
# Run init WITHOUT --force; use a custom HOME with no ~/.claude.json
|
||
# so the real user's global config doesn't interfere
|
||
FAKE_HOME=$(mktemp -d)
|
||
OUT=$(HOME="$FAKE_HOME" node "$GITHUB_WORKSPACE/v3/@claude-flow/cli/bin/cli.js" \
|
||
init 2>&1 || true)
|
||
|
||
echo "--- init output ---"
|
||
echo "$OUT"
|
||
|
||
# The init must NOT claim "already initialized" due to the bare settings.json
|
||
if echo "$OUT" | grep -qi "existing 'ruflo' MCP registration\|existing 'claude-flow' MCP registration"; then
|
||
echo "::error::init false-positives on bare .claude/settings.json (#2207)"
|
||
exit 1
|
||
fi
|
||
echo "ok: no false-positive on bare .claude/settings.json"
|
||
|
||
rm -rf "$FAKE_HOME"
|
||
echo "Guard 3 passed."
|