{{ message }}
Repository navigation
2415 lines (2144 loc) · 99.5 KB
/
Copy pathv3-ci.yml
File metadata and controls
2415 lines (2144 loc) · 99.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
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'
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'
workflow_dispatch:
env:
NODE_VERSION: '20'
PNPM_VERSION: '8'
jobs:
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: 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: Install workspace + build memory (pnpm — needed for workspace:* protocol)
working-directory: v3
run: |
pnpm install --frozen-lockfile
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
You can’t perform that action at this time.
