-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTaskfile.yml
More file actions
1080 lines (936 loc) · 45 KB
/
Copy pathTaskfile.yml
File metadata and controls
1080 lines (936 loc) · 45 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
version: "3"
# Auto-load .env at the project root so credential overrides
# (ZAI_API_KEY, ITERION_CLAUDE_CODE_MODEL, RESCUE_PROVIDER, …) are
# visible to every task without the operator having to `source .env`
# manually. .env stays gitignored — only the file at the repo root
# is read. When the file is absent task silently skips it; no error
# on fresh checkouts.
dotenv: [".env"]
vars:
BINARY: iterion
CMD: ./cmd/iterion
VERSION:
sh: node -p "require('./package.json').version" 2>/dev/null || echo "dev"
COMMIT:
sh: git rev-parse --short HEAD 2>/dev/null || echo ""
LDFLAGS: -X github.com/SocialGouv/iterion/pkg/internal/appinfo.Version=v{{.VERSION}} -X github.com/SocialGouv/iterion/pkg/internal/appinfo.Commit={{.COMMIT}}
tasks:
default:
desc: List available tasks
cmds:
- task --list-all
build:
desc: Build the iterion binary
deps: [studio:build, templates:dispatch-bots]
env:
CGO_ENABLED: "0"
cmds:
- go build -ldflags "{{.LDFLAGS}}" -o {{.BINARY}} {{.CMD}}
sources:
- "**/*.go"
- go.mod
- pkg/server/static/**
- pkg/cli/templates/dispatch_bots/**
generates:
- "{{.BINARY}}"
templates:dispatch-bots:
desc: "Sync the embedded dispatcher bot catalogue (pkg/cli/templates/dispatch_bots/) from bots/ + the default fallback template. The output is gitignored: re-run after editing any bot in bots/ or pkg/cli/templates/dispatch_bots_default.bot. Required before `task build` / `task test` (declared as a dep)."
cmds:
# Wipe-and-resync — but preserve .gitkeep so the directory keeps
# tracking even when no bot has been copied yet.
- find pkg/cli/templates/dispatch_bots -mindepth 1 ! -name .gitkeep -exec rm -rf {} +
- mkdir -p pkg/cli/templates/dispatch_bots/default
- cp pkg/cli/templates/dispatch_bots_default.bot pkg/cli/templates/dispatch_bots/default/main.bot
- cp -R bots/feature-dev pkg/cli/templates/dispatch_bots/feature-dev
- cp -R bots/whole-improve-loop pkg/cli/templates/dispatch_bots/whole-improve-loop
- cp -R bots/branch-improve-loop pkg/cli/templates/dispatch_bots/branch-improve-loop
- cp -R bots/whats-next pkg/cli/templates/dispatch_bots/whats-next
- cp -R bots/docs-refresh pkg/cli/templates/dispatch_bots/docs-refresh
- cp -R bots/sec-audit-source pkg/cli/templates/dispatch_bots/sec-audit-source
- cp -R bots/sec-audit-deps pkg/cli/templates/dispatch_bots/sec-audit-deps
- cp -R bots/secured-renovacy pkg/cli/templates/dispatch_bots/secured-renovacy
- cp -R bots/review-pr pkg/cli/templates/dispatch_bots/review-pr
sources:
- pkg/cli/templates/dispatch_bots_default.bot
- bots/feature-dev/**
- bots/whole-improve-loop/**
- bots/branch-improve-loop/**
- bots/whats-next/**
- bots/docs-refresh/**
- bots/sec-audit-source/**
- bots/sec-audit-deps/**
- bots/secured-renovacy/**
- bots/review-pr/**
generates:
- pkg/cli/templates/dispatch_bots/**
test:
desc: Run all unit tests
deps: [templates:dispatch-bots]
cmds:
- go test ./...
test:verbose:
desc: Run all unit tests with verbose output
deps: [templates:dispatch-bots]
cmds:
- go test -v ./...
test:race:
desc: Run tests with race detector
deps: [templates:dispatch-bots]
cmds:
- go test -race ./...
test:e2e:
desc: Run end-to-end tests
deps: [templates:dispatch-bots]
cmds:
## The budget bounds a HANG, not a slow machine. The ADR-058 v2 rollout
## added stub suites (docs-refresh's six scenarios, feature-dev's five)
## that grew the package to ~170s on a dev box; at the old 240s a loaded
## CI runner crossed it and produced a 4m panic dump naming whichever
## test was in flight — a flake that reads as a broken test. A hung test
## still trips 600s.
- go test -v -timeout 600s ./e2e/...
test:e2e:ui:
desc: Run the studio UI end-to-end tests (Playwright against the real server; skips when chromium isn't installed)
dir: studio
deps: [build]
cmds:
- corepack pnpm install --prefer-offline
## The suite needs a Playwright browser build, which is a ~120 MB
## download nobody should pay for implicitly. Without it the target
## reports how to install it and succeeds, so `task check` stays
## usable on a bare machine.
- |
if ! node e2e/guard.mjs; then
echo "task: [test:e2e:ui] skipped — no Playwright browser installed"
exit 0
fi
./node_modules/.bin/playwright test {{.CLI_ARGS}}
test:e2e:ui:install:
desc: Download the Playwright chromium build the studio UI e2e suite needs
dir: studio
cmds:
- corepack pnpm install --prefer-offline
- ./node_modules/.bin/playwright install chromium
test:goldens:
desc: Run bot golden replay tests (schema + invariant checks on recorded LLM fixtures; no API keys)
cmds:
- go test -count=1 -run 'TestGoldens' ./pkg/botreplay/...
test:goldens:record:
desc: Re-record bot golden fixtures against the real LLM (requires credentials; writes testdata/bot-goldens/). Run from the repo root.
cmds:
- go test -tags goldens_record -count=1 -run 'TestRecordGoldens' -timeout 30m ./pkg/botreplay/...
test:live:quality:unit:
desc: Run the live-e2e quality snapshot-engine unit tests (deterministic, no API keys, no cost). See docs/live-e2e-coverage.md.
cmds:
- go test -count=1 ./pkg/benchmark/quality/...
test:live:compile:
desc: Compile the live e2e test binary without running anything (build-gate the -tags live suite for free).
cmds:
- go test -tags live -count=1 -run '^$' ./e2e/...
test:live:
desc: Run all live e2e tests (requires claude CLI + ANTHROPIC_API_KEY + OPENAI_API_KEY)
cmds:
- go test -v -tags live -count=1 -run "TestLive_" -timeout 5h ./e2e/...
test:live:review:
desc: Run the session continuity review/fix live e2e test (requires claude CLI + ANTHROPIC_API_KEY + OPENAI_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_SessionContinuity_ReviewFix -timeout 3h ./e2e/...
test:live:kanban:
desc: Run the kanban board plan/implement/review live e2e test (requires claude CLI + ANTHROPIC_API_KEY + OPENAI_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_DualModel_PlanImplementReview -timeout 5h ./e2e/...
test:live:full:
desc: Run the exhaustive DSL coverage live e2e test (requires claude CLI + ANTHROPIC_API_KEY + OPENAI_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_Full_ExhaustiveDSLCoverage -timeout 5h ./e2e/...
test:live:coverage:
desc: Run the claw broad-tool-coverage live e2e test (requires ANTHROPIC_API_KEY; ~$0.03/run on Haiku 4.5)
cmds:
- go test -v -tags live -count=1 -run TestLive_ClawToolCoverage -timeout 15m ./e2e/...
test:live:session-inherit:
desc: Run the claude_code session-inherit validation live e2e test (requires claude CLI + ANTHROPIC_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_SessionInheritValidation -timeout 30m ./e2e/...
test:live:claw:
desc: Run the claw backend comprehensive coverage live e2e test (requires OPENAI_API_KEY + ANTHROPIC_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_ClawComprehensive -timeout 30m ./e2e/...
test:live:claw-builtin-tools:
desc: Run the claw built-in filesystem/shell tools live e2e test (requires ANTHROPIC_API_KEY + go in PATH)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_ClawBuiltinTools -timeout 15m ./e2e/...
test:live:claw-reasoning:
desc: Run the reasoning_effort propagation live e2e test (requires OPENAI_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_ClawReasoningEffort -timeout 10m ./e2e/...
test:live:claw-mcp:
desc: Run the MCP integration live e2e test (requires ANTHROPIC_API_KEY + go in PATH)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_ClawMCP -timeout 10m ./e2e/...
test:live:claw-long-context:
desc: Run the long-context live e2e test (requires ANTHROPIC_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_ClawLongContext -timeout 10m ./e2e/...
test:live:claw-read-image:
desc: Run the read_image (computer use) live e2e test (requires ANTHROPIC_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_Lite_ClawReadImage -timeout 5m ./e2e/...
test:live:vision-attachments:
desc: Run the attachments multimodal live e2e test (requires ANTHROPIC_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_VisionAttachments -timeout 5m ./e2e/...
test:live:feature-dev:
desc: Live e2e for feature_dev bot (requires claude CLI + OPENAI_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_FeatureDev -timeout 90m ./e2e/...
test:live:whole-improve-loop:
desc: Live e2e for whole_improve_loop bot (requires claude CLI + OPENAI_API_KEY)
cmds:
- go test -v -tags live -count=1 -run TestLive_VibeReviewAlternating -timeout 45m ./e2e/...
test:live:secured-renovacy:
desc: Live e2e for secured-renovacy bundle (requires claude CLI + docker + OPENAI_API_KEY; ~$10-50, up to 3h)
cmds:
- go test -v -tags live -count=1 -run "TestLive_SecuredRenovacy$" -timeout 3h ./e2e/...
test:live:bots:
desc: Run all three example-bot live tests in sequence (slow + costly)
cmds:
- task: test:live:whole-improve-loop
- task: test:live:feature-dev
- task: test:live:secured-renovacy
test:live:feature-dev-real:
desc: Live e2e for feature_dev against a real Go HTTP service fixture (20-60min, $5-15)
cmds:
- go test -v -tags live -count=1 -run "TestLive_FeatureDev_Real$" -timeout 2h ./e2e/...
test:live:whole-improve-loop-real:
desc: Live e2e for whole_improve_loop against a curated bug-mix fixture (30-90min, $10-30)
cmds:
- go test -v -tags live -count=1 -run "TestLive_VibeReviewAlternating_Real$" -timeout 3h ./e2e/...
test:live:secured-renovacy-real:
desc: Live e2e for secured-renovacy against polyglot CVE fixture incl. node-ipc malware (1-3h, $20-80)
cmds:
- go test -v -tags live -count=1 -run "TestLive_SecuredRenovacy_Real$" -timeout 4h ./e2e/...
test:live:secured-renovacy-protestware:
desc: Live e2e for secured-renovacy's anti-malware heuristic (single-package fixture, node-ipc@10.1.1, 5-15min, $2-5)
cmds:
- go test -v -tags live -count=1 -run "TestLive_SecuredRenovacy_Protestware$" -timeout 1h ./e2e/...
test:live:bots-real:
desc: Run all three real-scenario bot live tests in sequence (very slow + very costly)
cmds:
- task: test:live:whole-improve-loop-real
- task: test:live:feature-dev-real
- task: test:live:secured-renovacy-real
# ---- Per-bot / per-feature live e2e targets (real LLM cost; see docs/live-e2e-coverage.md) ----
test:live:bot:review-pr:
desc: 'Live e2e for review-pr — read-only diff review (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_ReviewPR$' -timeout 45m ./e2e/...
test:live:bot:whats-next:
desc: 'Live e2e for whats-next — roadmap + board issues (auto-resumed, isolated store) (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_WhatsNext$' -timeout 55m ./e2e/...
test:live:bot:docs-refresh:
desc: 'Live e2e for docs-refresh — doc/code drift fix loop (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_DocsRefresh$' -timeout 60m ./e2e/...
test:live:bot:adr-cartograph:
desc: 'Live e2e for adr-cartograph — author ADRs (isolated store) (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_AdrCartograph$' -timeout 60m ./e2e/...
test:live:bot:evolve:
desc: 'Live e2e for evolve — vision + backlog (auto-resumed, isolated store) (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_Evolve$' -timeout 60m ./e2e/...
test:live:bot:revi-converse:
desc: 'Live e2e for revi-converse — answer a question on a diff (no forge) (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_ReviConverse$' -timeout 30m ./e2e/...
test:live:bot:rgaa-audit:
desc: 'Live e2e for rgaa-audit — RGAA a11y audit (board disabled) (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_RgaaAudit$' -timeout 45m ./e2e/...
test:live:bot:branch-improve-loop:
desc: 'Live e2e for branch-improve-loop — fix a branch diff; docker+sandbox-full (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_BranchImproveLoop$' -timeout 100m ./e2e/...
test:live:bot:feature-gap-fill:
desc: 'Live e2e for feature-gap-fill — close a gap_spec; docker+sandbox-full (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_FeatureGapFill$' -timeout 100m ./e2e/...
test:live:bot:test-coverage:
desc: 'Live e2e for test-coverage — add tests; docker+sandbox-full (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_TestCoverage$' -timeout 100m ./e2e/...
test:live:bot:bmady:
desc: 'Live e2e for bmady — BMAD pipeline (auto-resumed gates) (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_Bmady$' -timeout 75m ./e2e/...
test:live:bot:devbox-setup:
desc: 'Live e2e for devbox-setup — author devbox.json; docker+sandbox-sec (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_DevboxSetup$' -timeout 70m ./e2e/...
test:live:bot:adr-rechallenge:
desc: 'Live e2e for adr-rechallenge — re-challenge an ADR (auto-resumed) (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_AdrRechallenge$' -timeout 45m ./e2e/...
test:live:bot:dep-update-guard:
desc: 'Live e2e for dep-update-guard — vet a Dependabot bump; docker+sandbox-sec (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_DepUpdateGuard$' -timeout 70m ./e2e/...
test:live:bot:sec-audit-source:
desc: 'Live e2e for sec-audit-source — SAST; docker+sandbox-sec (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_SecAuditSource$' -timeout 75m ./e2e/...
test:live:bot:sec-audit-deps:
desc: 'Live e2e for sec-audit-deps — SCA; docker+sandbox-sec (real cost). See docs/live-e2e-coverage.md.'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_SecAuditDeps$' -timeout 70m ./e2e/...
test:live:feat:cursors:
desc: 'Live e2e for the cursor calibration dials feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Cursors$' -timeout 15m ./e2e/...
test:live:feat:ultracode:
desc: 'Live e2e for the reasoning_effort: ultracode on opus-4-8 feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Ultracode$' -timeout 30m ./e2e/...
test:live:feat:supervisor:
desc: 'Live e2e for the concurrent watchdog supervisor feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Supervisor$' -timeout 30m ./e2e/...
test:live:feat:worktree:
desc: 'Live e2e for the worktree:auto finalization (tool-only, no creds) feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Worktree$' -timeout 5m ./e2e/...
test:live:feat:board-caps:
desc: 'Live e2e for the agent board.* capabilities feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_BoardCaps$' -timeout 12m ./e2e/...
test:live:feat:backend-autodetect:
desc: 'Live e2e for the backend auto-detection feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_BackendAutodetect$' -timeout 8m ./e2e/...
test:live:feat:budget:
desc: 'Live e2e for the budget enforcement (tiny cap) feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Budget$' -timeout 8m ./e2e/...
test:live:feat:permission:
desc: 'Live e2e for the permission gate deny mode feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Permission_Deny$' -timeout 8m ./e2e/...
test:live:feat:verified-action:
desc: 'Live e2e for the Verified Action recovery ladder feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_VerifiedAction$' -timeout 12m ./e2e/...
test:live:feat:router-llm:
desc: 'Live e2e for the LLM router dispatch feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_RouterLLM$' -timeout 12m ./e2e/...
test:live:feat:skills:
desc: 'Live e2e for the bundle skill mirroring feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Skills$' -timeout 8m ./e2e/...
test:live:feat:permission-ask:
desc: 'Live e2e for the permission gate ask mode (pauses) feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Permission_Ask$' -timeout 6m ./e2e/...
test:live:feat:rtk:
desc: 'Live e2e for the rtk command-output compression (needs rtk binary) feature (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Compress$' -timeout 3m ./e2e/...
test:live:feat:budget-resume:
desc: 'Live e2e for budget exceeded → raise cap → resume recovery (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_BudgetResume$' -timeout 10m ./e2e/...
test:live:feat:schedule:
desc: 'Live e2e for the schedule trigger → bot run (isolated, real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Schedule$' -timeout 8m ./e2e/...
test:live:feat:sandbox-net:
desc: 'Live e2e for sandbox network allowlist egress policy (docker + iterion-sandbox-full).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Sandbox_Network$' -timeout 12m ./e2e/...
test:live:feat:fork:
desc: 'Live e2e for run forking (parent run → fork at a turn → child run).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_Fork$' -timeout 8m ./e2e/...
test:live:bots:new:
desc: 'Run ALL 16 new per-bot live e2e tests sequentially (very slow + very costly).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Bot_' -timeout 8h ./e2e/...
test:live:feats:all:
desc: 'Run all TestLive_Feat_* feature live e2e tests (real cost).'
cmds:
- go test -v -tags live -count=1 -run 'TestLive_Feat_' -timeout 2h ./e2e/...
test:bundle:
desc: Bundle pack/open/compile integration tests (no live)
cmds:
- go test -v -count=1 -run TestBundle_ -timeout 60s ./e2e/...
test:repack-examples:
desc: Verify shipped .botz bundles match their source dirs (drift detector)
cmds:
- go test -v -count=1 -run TestBundle_SecuredRenovacy_RepackMatchesShippedBotz -timeout 30s ./e2e/...
fmt:
desc: Format Go source files
cmds:
- go fmt ./...
vet:
desc: Run go vet
cmds:
- go vet ./...
lint:
desc: Run fmt, vet, and golangci-lint
deps: [fmt, vet]
cmds:
- golangci-lint run
run:
desc: Build and run iterion (pass args after --)
deps: [build]
cmds:
- ./{{.BINARY}} {{.CLI_ARGS}}
install:
desc: Build and install iterion to $GOPATH/bin
deps: [studio:build]
env:
CGO_ENABLED: "0"
cmds:
- go install -ldflags "{{.LDFLAGS}}" {{.CMD}}
clean:
desc: Remove build artifacts
cmds:
- rm -f {{.BINARY}}
validate:
desc: Validate a .bot file (pass file after --)
deps: [build]
cmds:
- ./{{.BINARY}} validate {{.CLI_ARGS}}
diagram:
desc: Generate Mermaid diagram from a .bot file (pass file after --)
deps: [build]
cmds:
- ./{{.BINARY}} diagram {{.CLI_ARGS}}
check:
desc: Run all checks (lint + test + golden replay + studio + pi extension)
cmds:
- task: lint
- task: test
- task: test:goldens
- task: studio:check
- task: pi-ext:check
pi-ext:typecheck:
desc: Typecheck the iterion pi extension
dir: pi-extension
cmds:
- corepack pnpm install --prefer-offline
- ./node_modules/.bin/tsc --noEmit
pi-ext:build:
desc: Bundle the iterion pi extension into the embedded Go asset
dir: pi-extension
cmds:
- corepack pnpm install --prefer-offline
- ./node_modules/.bin/esbuild src/index.ts --bundle --format=esm --platform=node --target=node22 --external:@earendil-works/* --external:typebox --outfile=../pkg/backend/delegate/piext/asset/iterion-pi.js
pi-ext:check:
desc: Typecheck the pi extension and verify the embedded asset matches its source
dir: pi-extension
cmds:
- task: pi-ext:typecheck
# The asset is committed and compiled into the binary, so a stale one
# means every pi run silently loads yesterday's extension.
#
# Rebuild to a TEMP file and compare, rather than rebuilding in place and
# running `git diff`: the latter also fails on a legitimately uncommitted
# edit, which makes the guard fire during ordinary development and trains
# people to ignore it.
- |
set -e
tmp="$(mktemp -t iterion-pi-XXXXXX.js)"
trap 'rm -f "$tmp"' EXIT
./node_modules/.bin/esbuild src/index.ts --bundle --format=esm --platform=node --target=node22 \
--external:@earendil-works/* --external:typebox --outfile="$tmp" >/dev/null
if ! cmp -s "$tmp" ../pkg/backend/delegate/piext/asset/iterion-pi.js; then
echo "pi extension asset is stale: pi-extension/src does not match the embedded bundle."
echo "Run 'task pi-ext:build' and commit pkg/backend/delegate/piext/asset/iterion-pi.js."
exit 1
fi
studio:build:
desc: Build the studio frontend
dir: studio
method: checksum
env:
CI: "true"
cmds:
- corepack pnpm install --prefer-offline
- corepack pnpm exec vite build
- rm -rf ../pkg/server/static/assets ../pkg/server/static/index.html
# `cp -r dist/. <dest>` is the POSIX-portable form — works in
# bash, in zsh, AND in go-task's mvdan/sh interpreter (the
# `dist/*` glob was failing on Windows runners with
# "coreutils: target ... is not a directory" because mvdan/sh's
# built-in cp on Windows rejects the trailing-slash-with-glob
# combo even though the dir exists).
- mkdir -p ../pkg/server/static
- cp -R dist/. ../pkg/server/static
sources:
- src/**/*
- public/**/*
- index.html
- package.json
- pnpm-lock.yaml
- vite.config.ts
- tsconfig*.json
generates:
- ../pkg/server/static/index.html
- ../pkg/server/static/assets/**
studio:lint:
desc: Lint the studio frontend (eslint)
dir: studio
cmds:
- corepack pnpm install --prefer-offline
- corepack pnpm exec eslint .
studio:typecheck:
desc: Typecheck the studio frontend (tsc -b)
dir: studio
cmds:
- corepack pnpm install --prefer-offline
- corepack pnpm exec tsc -b
studio:test:
desc: Run the studio frontend unit tests (vitest)
dir: studio
cmds:
- corepack pnpm install --prefer-offline
- corepack pnpm exec vitest run
studio:check:
desc: Lint + typecheck + test the studio frontend
cmds:
- task: studio:lint
- task: studio:typecheck
- task: studio:test
openapi:gen:
desc: Regenerate the OpenAPI spec (openapi.json) + studio TS types (schema.ts) from code
cmds:
# Offline spec from the in-code route table — the single source of truth.
- go run -mod=vendor ./cmd/iterion openapi -o openapi.json
# Typed client surface for the studio, derived from that spec.
- corepack pnpm -C studio exec openapi-typescript ../openapi.json -o src/api/schema.ts
openapi:check:
desc: Fail if the committed OpenAPI spec / TS types drift from the code
cmds:
- task: openapi:gen
- cmd: |
if ! git diff --quiet -- openapi.json studio/src/api/schema.ts; then
echo "::error::OpenAPI spec / client drift — run 'task openapi:gen' and commit the result."
git --no-pager diff --stat -- openapi.json studio/src/api/schema.ts
exit 1
fi
studio:dev:
desc: Start studio in dev mode (Vite HMR + Go backend with auto-restart)
deps: [studio:dev:backend, studio:dev:frontend]
studio:dev:backend:
desc: Run Go studio backend with auto-restart on changes
# Build a STATIC iterion and run THAT (not `go run`) so the subprocesses
# the studio delegates to — the __mcp-board MCP server, the sandboxed
# __claw-runner, __mcp-ask-user — use this exact fresh binary instead of a
# stale `/usr/bin/iterion`. Under `go run`, os.Executable() is a volatile
# temp path, so proc.LocateIterionBinary / locateHostIterionBinary fall back
# to whatever is installed → capability skew (e.g. board MCP missing
# set_bot/list_labels). Running the built binary makes os.Executable() stable
# (repo ./iterion) and ITERION_BIN pins it; CGO_ENABLED=0 keeps it static so
# it execs inside sandbox containers (a dynamic nix-glibc build fails there).
# Net effect: dev-mode delegated capabilities always match the running code,
# with no `sudo cp ./iterion /usr/bin/iterion`.
env:
CGO_ENABLED: "0"
ITERION_BIN: "{{.ROOT_DIR}}/iterion"
cmds:
# NB: pass the script as a single quoted arg, NOT `sh -c '...'`. watchexec
# runs its command through a shell by default (`--shell` != none), so an
# explicit `sh -c '<script>'` gets its parts re-joined and re-shelled —
# the inner quoting is lost and only the bare word `go` survives as the
# script (→ `go` prints help, exit 2, backend never starts). Letting
# watchexec's own shell run the script keeps `&&`/`exec` working.
- watchexec -r -e go -w cmd -w pkg -w vendor -- 'go build -o {{.ROOT_DIR}}/iterion {{.CMD}} && exec {{.ROOT_DIR}}/iterion studio --no-browser --port 4891'
interactive: true
studio:dev:frontend:
desc: Run Vite dev server for studio frontend
dir: studio
cmds:
- corepack pnpm install --prefer-offline 2>/dev/null; corepack pnpm exec vite --port 5173 --open
interactive: true
studio:
desc: Build and run the studio (production mode)
deps: [build, studio:build]
cmds:
- ./{{.BINARY}} studio {{.CLI_ARGS}}
sdk:ts:install:
desc: Install dependencies for the TypeScript SDK
dir: sdks/typescript
cmds:
- corepack pnpm install --prefer-offline
sdk:ts:build:
desc: Build the TypeScript SDK (emits dist/)
dir: sdks/typescript
deps: [sdk:ts:install]
cmds:
- corepack pnpm run build
sdk:ts:test:
desc: Run the TypeScript SDK unit tests
dir: sdks/typescript
deps: [sdk:ts:install]
cmds:
- corepack pnpm exec vitest run
sdk:ts:typecheck:
desc: Typecheck the TypeScript SDK including tests
dir: sdks/typescript
deps: [sdk:ts:install]
cmds:
- corepack pnpm exec tsc -p tsconfig.test.json
sdk:ts:check:
desc: Build + typecheck + test the TypeScript SDK
cmds:
- task: sdk:ts:build
- task: sdk:ts:typecheck
- task: sdk:ts:test
# ── Desktop (Wails v2) ────────────────────────────────────────────────
# The desktop binary wraps the studio server in a native window.
# Wails CLI is required for `desktop:dev` and `desktop:build`. Install
# it once with `task desktop:install-tools`. The Go code lives under
# cmd/iterion-desktop/ and is gated by `//go:build desktop` so the
# default `go test ./...` does not require Wails to be installed.
desktop:install-deps:linux:
desc: Install the apt prerequisites + Wails CLI to build iterion-desktop on Debian/Ubuntu/Mint (idempotent)
cmds:
- ./scripts/desktop/install-linux-deps.sh
- task: desktop:install-tools
desktop:install-tools:
desc: Install Wails CLI and tools needed for desktop builds
cmds:
- go install github.com/wailsapp/wails/v2/cmd/wails@latest
desktop:package:linux:amd64:docker:
desc: Package Linux amd64 AppImage inside an Ubuntu 22.04 container (portable across distros)
cmds:
- ./scripts/desktop/build-appimage-in-docker.sh amd64
desktop:package:linux:arm64:docker:
desc: Package Linux arm64 AppImage inside an Ubuntu 22.04 container (portable across distros)
cmds:
- ./scripts/desktop/build-appimage-in-docker.sh arm64
desktop:dev:
desc: Run Iterion Desktop in dev mode (Wails)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
- |
# In devbox: prepend /usr/bin so system gcc/ld + apt pkg-config
# are picked over the Nix-wrapped variants (which don't see system
# webkit2gtk-4.1 / gtk+-3.0). On CI runners DEVBOX_PROJECT_ROOT
# is unset, so we keep setup-go's Go ahead of /usr/bin/go (the
# runner's preinstalled Go is often older than go.mod's directive).
if [ -n "$DEVBOX_PROJECT_ROOT" ]; then
export PATH="/usr/bin:$PATH"
fi
export PKG_CONFIG="${PKG_CONFIG:-/usr/bin/pkg-config}"
export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/share/pkgconfig"
wails dev -tags desktop,webkit2_41 -skipbindings -s
desktop:build:
desc: Build Iterion Desktop for the current platform (unsigned)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
- wails build -tags desktop,webkit2_41 -clean -trimpath -skipbindings -s -ldflags "{{.LDFLAGS}}"
desktop:build:darwin:arm64:
desc: Build Iterion Desktop for macOS arm64 (must run on macOS)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
- wails build -tags desktop -platform darwin/arm64 -clean -trimpath -skipbindings -s -ldflags "{{.LDFLAGS}}" -o iterion-desktop-darwin-arm64
desktop:build:darwin:amd64:
desc: Build Iterion Desktop for macOS amd64 (must run on macOS)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
- wails build -tags desktop -platform darwin/amd64 -clean -trimpath -skipbindings -s -ldflags "{{.LDFLAGS}}" -o iterion-desktop-darwin-amd64
desktop:build:darwin:universal:
desc: Build Iterion Desktop for macOS (universal binary, runs on Intel + Apple Silicon)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
# `-platform darwin/universal` makes Wails build both arch slices
# and lipo them into a single .app. The CI matrix prefers this
# over two separate jobs to dodge the macos-13 runner-pool queue
# (Intel hosted runners are scarce and frequently >20 min queued).
- wails build -tags desktop -platform darwin/universal -clean -trimpath -skipbindings -s -ldflags "{{.LDFLAGS}}" -o iterion-desktop-darwin-universal
desktop:build:windows:amd64:
desc: Build Iterion Desktop for Windows amd64 (must run on Windows)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
- wails build -tags desktop -platform windows/amd64 -clean -trimpath -skipbindings -s -ldflags "{{.LDFLAGS}}" -nsis -o iterion-desktop-windows-amd64.exe
desktop:build:windows:arm64:
desc: Build Iterion Desktop for Windows arm64 (must run on Windows)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
- wails build -tags desktop -platform windows/arm64 -clean -trimpath -skipbindings -s -ldflags "{{.LDFLAGS}}" -nsis -o iterion-desktop-windows-arm64.exe
desktop:build:linux:amd64:
desc: Build Iterion Desktop for Linux amd64 (production with DevTools enabled)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
- |
# See desktop:dev for the devbox vs CI PATH split.
if [ -n "$DEVBOX_PROJECT_ROOT" ]; then
export PATH="/usr/bin:$PATH"
fi
export PKG_CONFIG="${PKG_CONFIG:-/usr/bin/pkg-config}"
export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/share/pkgconfig"
# -devtools keeps Inspect Element / Ctrl+Shift+I available in release
# builds so users can debug WebView issues before native devtools
# menus are wired up. Stripping it later is a one-line change.
# -clean intentionally omitted: wails would wipe the entire
# build/bin/ directory before producing its own binary, racing the
# parallel cli:build:linux:amd64 task that lands its artefact in
# the same dir. Since wails always overwrites its own output file
# (-o iterion-desktop-linux-amd64) and the AppImage/deb scripts
# tear down their own staging dirs, dropping -clean is safe and
# lets the deb task fan out its sub-builds in parallel.
wails build -tags desktop,webkit2_41 -platform linux/amd64 -trimpath -skipbindings -s -devtools -ldflags "{{.LDFLAGS}}" -o iterion-desktop-linux-amd64
desktop:build:linux:arm64:
desc: Build Iterion Desktop for Linux arm64 (production with DevTools enabled)
deps: [studio:build]
dir: cmd/iterion-desktop
cmds:
- |
if [ -n "$DEVBOX_PROJECT_ROOT" ]; then
export PATH="/usr/bin:$PATH"
fi
export PKG_CONFIG="${PKG_CONFIG:-/usr/bin/pkg-config}"
export PKG_CONFIG_PATH="/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig"
# See desktop:build:linux:amd64 for why -clean is intentionally absent.
wails build -tags desktop,webkit2_41 -platform linux/arm64 -trimpath -skipbindings -s -devtools -ldflags "{{.LDFLAGS}}" -o iterion-desktop-linux-arm64
desktop:package:linux:amd64:
desc: Package Linux amd64 build as AppImage
deps: [desktop:build:linux:amd64]
cmds:
- |
# PATH override matters only when running inside devbox: linuxdeploy
# invokes ldconfig/dpkg-query, which the Nix wrappers can't find.
# On CI runners the default PATH already has /usr/bin first; the
# prepend is a no-op there.
export PATH="/usr/bin:$PATH"
./scripts/desktop/build-appimage.sh amd64
desktop:package:linux:arm64:
desc: Package Linux arm64 build as AppImage
deps: [desktop:build:linux:arm64]
cmds:
- |
export PATH="/usr/bin:$PATH"
./scripts/desktop/build-appimage.sh arm64
cli:build:linux:amd64:
desc: Build the iterion CLI for Linux amd64 (output build/bin/iterion-linux-amd64)
# Intentionally no sources/generates: the up-to-date heuristic
# mis-fires when the generated binary is removed out-of-band
# (clean checkouts, manual rm, CI artifacts purge), causing
# downstream `desktop:package:linux:*:deb` to fail with a
# "iterion-linux-amd64 not found" before the dep had a chance to
# rebuild it. A 10-second always-rebuild is the cheap fix.
deps: [studio:build]
env:
CGO_ENABLED: "0"
GOOS: linux
GOARCH: amd64
cmds:
- go build -trimpath -ldflags "{{.LDFLAGS}}" -o build/bin/iterion-linux-amd64 {{.CMD}}
cli:build:linux:arm64:
desc: Build the iterion CLI for Linux arm64 (output build/bin/iterion-linux-arm64)
deps: [studio:build]
env:
CGO_ENABLED: "0"
GOOS: linux
GOARCH: arm64
cmds:
- go build -trimpath -ldflags "{{.LDFLAGS}}" -o build/bin/iterion-linux-arm64 {{.CMD}}
desktop:package:linux:amd64:deb:
desc: Package Linux amd64 build as a Debian .deb (ships desktop + CLI; also produces AppImage)
# Both prerequisites can run in parallel because the wails build no
# longer passes -clean (see desktop:build:linux:amd64). cli:build and
# desktop:build write distinct filenames into build/bin/ and the
# AppImage / deb scripts manage their own staging dirs, so there is
# no contention. studio:build is shared between both prerequisites
# and Task dedupes it, so it runs once.
deps: [desktop:package:linux:amd64, cli:build:linux:amd64]
cmds:
- |
# dpkg-deb lives in /usr/bin and devbox's PATH may shadow it
# (Nix wrappers don't ship dpkg). The prepend is harmless on CI
# runners where /usr/bin already comes first.
export PATH="/usr/bin:$PATH"
./scripts/desktop/build-deb.sh amd64
desktop:package:linux:arm64:deb:
desc: Package Linux arm64 build as a Debian .deb (ships desktop + CLI; also produces AppImage)
deps: [desktop:package:linux:arm64, cli:build:linux:arm64]
cmds:
- |
export PATH="/usr/bin:$PATH"
./scripts/desktop/build-deb.sh arm64
# ── Fast .deb build (local dev only) ──────────────────────────────────
# Mirrors the desktop:package:linux:amd64:deb chain but skips the
# AppImage step (build-deb.sh consumes the raw binaries, not the
# AppImage) and disables Vite minification. Total wall time drops
# from ~90-150s to ~50-60s cold (~10-20s warm). The resulting .deb
# is stamped <semver>+fast.<commit> so it cannot be confused with a
# prod artifact via `dpkg -l`. See docs/desktop-build.md.
studio:build:fast:
desc: Build studio frontend WITHOUT minification — local dev only, do NOT ship
dir: studio
# `desktop:package:linux:amd64:deb:fast` deps on both
# `desktop:build:linux:amd64:fast` and `cli:build:linux:amd64:fast`,
# and both list `studio:build:fast` in their own `deps:`. Task v3
# parallelises sibling deps by default, and the default `run:` mode
# treats each invocation as independent — so without `run: once`
# studio:build:fast fires TWICE in parallel and the two
# `cp -R dist/. ../pkg/server/static` calls race on the same path,
# producing `cp: cannot create regular file …: File exists` from
# whichever cp lost. `run: once` collapses the two invocations into
# one (Task waits for the first to finish, then the second
# consumer reuses the result instead of re-running).
run: once
env:
CI: "true"
cmds:
- corepack pnpm install --prefer-offline
# Direct vite call (matches prod studio:build, which also bypasses
# `pnpm run build` and so already skips tsc -b). --minify false
# saves ~30-50s on cold builds; sourcemaps stay on (set in vite
# config) for debuggability.
- corepack pnpm exec vite build --minify false
- rm -rf ../pkg/server/static/assets ../pkg/server/static/index.html
- mkdir -p ../pkg/server/static
- cp -R dist/. ../pkg/server/static
# No method: checksum — Vite's incremental cache makes warm rebuild
# ~3-5s, and avoiding shared-output collisions with prod studio:build
# (same pkg/server/static dir) is worth more than 5s.
desktop:build:linux:amd64:fast:
desc: Build Iterion Desktop for Linux amd64 with the unminified SPA (local dev variant)
deps: [studio:build:fast]
dir: cmd/iterion-desktop
cmds:
- |
if [ -n "$DEVBOX_PROJECT_ROOT" ]; then
export PATH="/usr/bin:$PATH"
fi
export PKG_CONFIG="${PKG_CONFIG:-/usr/bin/pkg-config}"
export PKG_CONFIG_PATH="/usr/lib/x86_64-linux-gnu/pkgconfig:/usr/share/pkgconfig"
wails build -tags desktop,webkit2_41 -platform linux/amd64 -trimpath -skipbindings -s -devtools -ldflags "{{.LDFLAGS}}" -o iterion-desktop-linux-amd64
cli:build:linux:amd64:fast:
desc: Build the iterion CLI for Linux amd64 with the unminified SPA embedded (local dev variant)
# Mirrors cli:build:linux:amd64 but deps on studio:build:fast so the
# whole :fast subgraph hits studio:build:fast exactly once. Without
# this, Task would invoke both studio:build and studio:build:fast
# (different task names = no dedup) and they would race on
# pkg/server/static/.
deps: [studio:build:fast]
env:
CGO_ENABLED: "0"
GOOS: linux
GOARCH: amd64
cmds:
- go build -trimpath -ldflags "{{.LDFLAGS}}" -o build/bin/iterion-linux-amd64 {{.CMD}}
desktop:package:linux:amd64:deb:fast:
desc: Package Linux amd64 .deb without AppImage, unminified SPA, version-stamped +fast.<commit> (local dev only)
deps: [desktop:build:linux:amd64:fast, cli:build:linux:amd64:fast]
vars:
DEB_VERSION:
sh: 'echo "$(node -p "require(''./package.json'').version")+fast.{{.COMMIT}}"'
env:
VERSION: "{{.DEB_VERSION}}"
cmds:
- |
export PATH="/usr/bin:$PATH"
./scripts/desktop/build-deb.sh amd64
desktop:sign-release:
desc: Sign all desktop release artefacts with Ed25519 (requires UPDATER_ED25519_PRIVATE)
cmds:
- ./scripts/desktop/sign-release.sh
desktop:test:
desc: Run desktop-only Go unit tests (build tag `desktop` excluded — just the platform-neutral subset)
cmds:
- go test ./cmd/iterion-desktop/...
# --- Cloud-mode docker-compose (plan §F T-38, T-39) -------------
cloud:up:
desc: Bring up the cloud-mode local stack (Mongo + NATS + MinIO + iterion)
cmds:
- docker compose -f docker-compose.cloud.yml up -d --build
cloud:down:
desc: Tear down the cloud-mode stack including volumes
cmds:
- docker compose -f docker-compose.cloud.yml down -v
cloud:logs:
desc: Tail logs from every cloud-mode service
cmds:
- docker compose -f docker-compose.cloud.yml logs -f --tail=100