@wrongstack/tui 0.303.0 → 0.305.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -315,6 +315,12 @@ var pastel = Object.freeze({
315
315
  // Greys
316
316
  gray: "#7f849c",
317
317
  grey: "#7f849c",
318
+ // Lifted grey used for comment tokens sitting on a diff wash. `gray` falls
319
+ // below WCAG AA on `diffAddBg`/`diffDelBg`; this clears both. MUST exist in
320
+ // this map — `softColor` passes unknown names through untouched and Ink /
321
+ // chalk then silently drop them, rendering the token with no color at all.
322
+ grayBright: "#a6adc8",
323
+ greyBright: "#a6adc8",
318
324
  // Bright variants — a touch lighter / shifted within the same family
319
325
  blackBright: "#585b70",
320
326
  redBright: "#eba0ac",
@@ -334,8 +340,32 @@ var pastel = Object.freeze({
334
340
  flamingo: "#f2cdcd"
335
341
  });
336
342
  var catppuccin = pastel;
343
+ var SYNTAX_TOKEN = Object.freeze({
344
+ keyword: "brand",
345
+ string: "success",
346
+ comment: "textMuted",
347
+ commentOnWash: "textSecondary",
348
+ number: "warn",
349
+ literal: "warn",
350
+ property: "accent",
351
+ variable: "accent",
352
+ command: "accent",
353
+ flag: "warn",
354
+ decorator: "brand",
355
+ diffAdd: "success",
356
+ diffDel: "error",
357
+ diffMeta: "accent"
358
+ });
359
+ var SYNTAX_PREFIX = "syntax.";
360
+ function resolveSyntaxColor(role, palette = theme) {
361
+ return palette.syntax?.[role] ?? palette[SYNTAX_TOKEN[role]];
362
+ }
337
363
  function softColor(color) {
338
364
  if (!color) return color;
365
+ if (color.startsWith(SYNTAX_PREFIX)) {
366
+ const role = color.slice(SYNTAX_PREFIX.length);
367
+ return role in SYNTAX_TOKEN ? resolveSyntaxColor(role) : color;
368
+ }
339
369
  return pastel[color] ?? color;
340
370
  }
341
371
  function detectSupportsBackground(env = process.env, isTTY = process.stdout.isTTY ?? false) {
@@ -408,6 +438,9 @@ function setActiveTheme(name) {
408
438
  }
409
439
  const t = theme;
410
440
  const p = preset;
441
+ for (const k of Object.keys(t)) {
442
+ if (!(k in p)) delete t[k];
443
+ }
411
444
  for (const k of Object.keys(p)) {
412
445
  t[k] = p[k];
413
446
  }
@@ -459,7 +492,9 @@ var themePresets = Object.freeze({
459
492
  brand: "#bb9af7",
460
493
  surface: "#16161e",
461
494
  surfaceRaised: "#1a1b26",
462
- monitor: { ...baseTheme.monitor, fleet: "#7dcfff", agents: "#bb9af7", goal: "#9ece6a" }
495
+ diffAddBg: "#1c3326",
496
+ diffDelBg: "#37202b",
497
+ monitor: { fleet: "#7dcfff", agents: "#bb9af7", worktree: "#9ece6a", phase: "#7dcfff" }
463
498
  }),
464
499
  nord: Object.freeze({
465
500
  ...baseTheme,
@@ -478,7 +513,9 @@ var themePresets = Object.freeze({
478
513
  brand: "#b48ead",
479
514
  surface: "#2e3440",
480
515
  surfaceRaised: "#3b4252",
481
- monitor: { ...baseTheme.monitor, fleet: "#88c0d0", agents: "#b48ead", goal: "#a3be8c" }
516
+ diffAddBg: "#2f4034",
517
+ diffDelBg: "#442f35",
518
+ monitor: { fleet: "#88c0d0", agents: "#b48ead", worktree: "#a3be8c", phase: "#88c0d0" }
482
519
  }),
483
520
  cyberpunk: Object.freeze({
484
521
  ...baseTheme,
@@ -497,7 +534,9 @@ var themePresets = Object.freeze({
497
534
  brand: "#ff00aa",
498
535
  surface: "#0d0d1a",
499
536
  surfaceRaised: "#16162a",
500
- monitor: { ...baseTheme.monitor, fleet: "#00f0ff", agents: "#ff00aa", goal: "#00ff66" }
537
+ diffAddBg: "#0d2e1f",
538
+ diffDelBg: "#2e0d1c",
539
+ monitor: { fleet: "#00f0ff", agents: "#ff00aa", worktree: "#00ff66", phase: "#00f0ff" }
501
540
  }),
502
541
  dracula: Object.freeze({
503
542
  ...baseTheme,
@@ -516,7 +555,9 @@ var themePresets = Object.freeze({
516
555
  brand: "#ff79c6",
517
556
  surface: "#282a36",
518
557
  surfaceRaised: "#44475a",
519
- monitor: { ...baseTheme.monitor, fleet: "#8be9fd", agents: "#ff79c6", goal: "#50fa7b" }
558
+ diffAddBg: "#26402e",
559
+ diffDelBg: "#43262e",
560
+ monitor: { fleet: "#8be9fd", agents: "#ff79c6", worktree: "#50fa7b", phase: "#8be9fd" }
520
561
  }),
521
562
  "gruvbox-dark": Object.freeze({
522
563
  ...baseTheme,
@@ -537,7 +578,7 @@ var themePresets = Object.freeze({
537
578
  surfaceRaised: "#3c3836",
538
579
  diffAddBg: "#1f3a1f",
539
580
  diffDelBg: "#3a1f1f",
540
- monitor: { ...baseTheme.monitor, fleet: "#83a598", agents: "#d3869b", goal: "#b8bb26" }
581
+ monitor: { fleet: "#83a598", agents: "#d3869b", worktree: "#b8bb26", phase: "#83a598" }
541
582
  }),
542
583
  "solarized-dark": Object.freeze({
543
584
  ...baseTheme,
@@ -558,7 +599,7 @@ var themePresets = Object.freeze({
558
599
  surfaceRaised: "#073642",
559
600
  diffAddBg: "#0e3a30",
560
601
  diffDelBg: "#3a1a1a",
561
- monitor: { ...baseTheme.monitor, fleet: "#268bd2", agents: "#d33682", goal: "#859900" }
602
+ monitor: { fleet: "#268bd2", agents: "#d33682", worktree: "#859900", phase: "#268bd2" }
562
603
  }),
563
604
  "one-dark": Object.freeze({
564
605
  ...baseTheme,
@@ -579,7 +620,7 @@ var themePresets = Object.freeze({
579
620
  surfaceRaised: "#282c34",
580
621
  diffAddBg: "#1f3a26",
581
622
  diffDelBg: "#3a2226",
582
- monitor: { ...baseTheme.monitor, fleet: "#61afef", agents: "#c678dd", goal: "#98c379" }
623
+ monitor: { fleet: "#61afef", agents: "#c678dd", worktree: "#98c379", phase: "#61afef" }
583
624
  }),
584
625
  monokai: Object.freeze({
585
626
  ...baseTheme,
@@ -600,7 +641,7 @@ var themePresets = Object.freeze({
600
641
  surfaceRaised: "#272822",
601
642
  diffAddBg: "#1f3318",
602
643
  diffDelBg: "#3a1f25",
603
- monitor: { ...baseTheme.monitor, fleet: "#66d9ef", agents: "#ae81ff", goal: "#a6e22e" }
644
+ monitor: { fleet: "#66d9ef", agents: "#ae81ff", worktree: "#a6e22e", phase: "#66d9ef" }
604
645
  }),
605
646
  "rose-pine": Object.freeze({
606
647
  ...baseTheme,
@@ -621,7 +662,7 @@ var themePresets = Object.freeze({
621
662
  surfaceRaised: "#1f1d2e",
622
663
  diffAddBg: "#1f3538",
623
664
  diffDelBg: "#3a2530",
624
- monitor: { ...baseTheme.monitor, fleet: "#9ccfd8", agents: "#c4a7e7", goal: "#31748f" }
665
+ monitor: { fleet: "#9ccfd8", agents: "#c4a7e7", worktree: "#31748f", phase: "#9ccfd8" }
625
666
  }),
626
667
  kanagawa: Object.freeze({
627
668
  ...baseTheme,
@@ -642,7 +683,7 @@ var themePresets = Object.freeze({
642
683
  surfaceRaised: "#1f1f28",
643
684
  diffAddBg: "#1f2d1f",
644
685
  diffDelBg: "#321e22",
645
- monitor: { ...baseTheme.monitor, fleet: "#7fb4ca", agents: "#957fb8", goal: "#98bb6e" }
686
+ monitor: { fleet: "#7fb4ca", agents: "#957fb8", worktree: "#98bb6e", phase: "#7fb4ca" }
646
687
  }),
647
688
  "ayu-dark": Object.freeze({
648
689
  ...baseTheme,
@@ -663,7 +704,7 @@ var themePresets = Object.freeze({
663
704
  surfaceRaised: "#14181f",
664
705
  diffAddBg: "#1c2a1f",
665
706
  diffDelBg: "#2e1c20",
666
- monitor: { ...baseTheme.monitor, fleet: "#59c2ff", agents: "#d4b5ff", goal: "#aad94c" }
707
+ monitor: { fleet: "#59c2ff", agents: "#d4b5ff", worktree: "#aad94c", phase: "#59c2ff" }
667
708
  }),
668
709
  everforest: Object.freeze({
669
710
  ...baseTheme,
@@ -684,7 +725,7 @@ var themePresets = Object.freeze({
684
725
  surfaceRaised: "#343f44",
685
726
  diffAddBg: "#1f3326",
686
727
  diffDelBg: "#331f25",
687
- monitor: { ...baseTheme.monitor, fleet: "#7fbbb3", agents: "#d699b6", goal: "#a7c080" }
728
+ monitor: { fleet: "#7fbbb3", agents: "#d699b6", worktree: "#a7c080", phase: "#7fbbb3" }
688
729
  }),
689
730
  "night-owl": Object.freeze({
690
731
  ...baseTheme,
@@ -705,7 +746,7 @@ var themePresets = Object.freeze({
705
746
  surfaceRaised: "#0b253a",
706
747
  diffAddBg: "#0e2e26",
707
748
  diffDelBg: "#2e1722",
708
- monitor: { ...baseTheme.monitor, fleet: "#82aaff", agents: "#c792ea", goal: "#c3e88d" }
749
+ monitor: { fleet: "#82aaff", agents: "#c792ea", worktree: "#c3e88d", phase: "#82aaff" }
709
750
  }),
710
751
  synthwave: Object.freeze({
711
752
  ...baseTheme,
@@ -726,7 +767,508 @@ var themePresets = Object.freeze({
726
767
  surfaceRaised: "#241b46",
727
768
  diffAddBg: "#1f3530",
728
769
  diffDelBg: "#3a1f30",
729
- monitor: { ...baseTheme.monitor, fleet: "#36f9f6", agents: "#b56cff", goal: "#72f1b8" }
770
+ monitor: { fleet: "#36f9f6", agents: "#b56cff", worktree: "#72f1b8", phase: "#36f9f6" }
771
+ }),
772
+ "github-dark": Object.freeze({
773
+ ...baseTheme,
774
+ textPrimary: "#c9d1d9",
775
+ textSecondary: "#b1bac4",
776
+ textMuted: "#8b949e",
777
+ brandPrimary: "#d29922",
778
+ brandAccent: "#bc8cff",
779
+ accent: "#58a6ff",
780
+ user: "#d29922",
781
+ assistant: "#58a6ff",
782
+ tool: "#39c5cf",
783
+ success: "#3fb950",
784
+ warn: "#d29922",
785
+ error: "#f85149",
786
+ borderDefault: "#30363d",
787
+ borderSubtle: "#21262d",
788
+ borderActive: "#58a6ff",
789
+ brand: "#bc8cff",
790
+ surface: "#0d1117",
791
+ surfaceRaised: "#161b22",
792
+ diffAddBg: "#0d2f18",
793
+ diffDelBg: "#3d1418",
794
+ monitor: { fleet: "#58a6ff", agents: "#bc8cff", worktree: "#3fb950", phase: "#39c5cf" }
795
+ }),
796
+ "material-ocean": Object.freeze({
797
+ ...baseTheme,
798
+ textPrimary: "#a6accd",
799
+ textSecondary: "#8f93a2",
800
+ textMuted: "#4b526d",
801
+ brandPrimary: "#f78c6c",
802
+ brandAccent: "#c792ea",
803
+ accent: "#89ddff",
804
+ user: "#ffcb6b",
805
+ assistant: "#89ddff",
806
+ tool: "#82aaff",
807
+ success: "#c3e88d",
808
+ warn: "#ffcb6b",
809
+ error: "#f07178",
810
+ borderDefault: "#3b3f51",
811
+ borderSubtle: "#1f2233",
812
+ borderActive: "#89ddff",
813
+ brand: "#c792ea",
814
+ surface: "#0f111a",
815
+ surfaceRaised: "#1a1c25",
816
+ diffAddBg: "#17301f",
817
+ diffDelBg: "#331b21",
818
+ monitor: { fleet: "#89ddff", agents: "#c792ea", worktree: "#c3e88d", phase: "#82aaff" }
819
+ }),
820
+ nightfox: Object.freeze({
821
+ ...baseTheme,
822
+ textPrimary: "#cdcecf",
823
+ textSecondary: "#aeafb0",
824
+ textMuted: "#71839b",
825
+ brandPrimary: "#f4a261",
826
+ brandAccent: "#9d79d6",
827
+ accent: "#719cd6",
828
+ user: "#dbc074",
829
+ assistant: "#63cdcf",
830
+ tool: "#719cd6",
831
+ success: "#81b29a",
832
+ warn: "#dbc074",
833
+ error: "#c94f6d",
834
+ borderDefault: "#39506d",
835
+ borderSubtle: "#29394f",
836
+ borderActive: "#719cd6",
837
+ brand: "#9d79d6",
838
+ surface: "#192330",
839
+ surfaceRaised: "#212e3f",
840
+ diffAddBg: "#1d3025",
841
+ diffDelBg: "#33202a",
842
+ monitor: { fleet: "#719cd6", agents: "#9d79d6", worktree: "#81b29a", phase: "#63cdcf" }
843
+ }),
844
+ oxocarbon: Object.freeze({
845
+ ...baseTheme,
846
+ textPrimary: "#f2f4f8",
847
+ textSecondary: "#dde1e6",
848
+ textMuted: "#82868b",
849
+ brandPrimary: "#ff7eb6",
850
+ brandAccent: "#be95ff",
851
+ accent: "#78a9ff",
852
+ user: "#3ddbd9",
853
+ assistant: "#78a9ff",
854
+ tool: "#3ddbd9",
855
+ success: "#42be65",
856
+ warn: "#ff7eb6",
857
+ error: "#ee5396",
858
+ borderDefault: "#393939",
859
+ borderSubtle: "#262626",
860
+ borderActive: "#be95ff",
861
+ brand: "#be95ff",
862
+ surface: "#161616",
863
+ surfaceRaised: "#262626",
864
+ diffAddBg: "#17301f",
865
+ diffDelBg: "#33182a",
866
+ monitor: { fleet: "#78a9ff", agents: "#be95ff", worktree: "#42be65", phase: "#3ddbd9" }
867
+ }),
868
+ "catppuccin-macchiato": Object.freeze({
869
+ ...baseTheme,
870
+ textPrimary: "#cad3f5",
871
+ textSecondary: "#b8c0e0",
872
+ textMuted: "#6e738d",
873
+ brandPrimary: "#f5a97f",
874
+ brandAccent: "#f5bde6",
875
+ accent: "#8bd5ca",
876
+ user: "#eed49f",
877
+ assistant: "#8aadf4",
878
+ tool: "#8bd5ca",
879
+ success: "#a6da95",
880
+ warn: "#eed49f",
881
+ error: "#ed8796",
882
+ borderDefault: "#5b6078",
883
+ borderSubtle: "#363a4f",
884
+ borderActive: "#eed49f",
885
+ brand: "#c6a0f6",
886
+ surface: "#1e2030",
887
+ surfaceRaised: "#24273a",
888
+ diffAddBg: "#26402f",
889
+ diffDelBg: "#3f242c",
890
+ monitor: { fleet: "#8bd5ca", agents: "#c6a0f6", worktree: "#a6da95", phase: "#8aadf4" }
891
+ }),
892
+ "catppuccin-frappe": Object.freeze({
893
+ ...baseTheme,
894
+ textPrimary: "#c6d0f5",
895
+ textSecondary: "#b5bfe2",
896
+ textMuted: "#737994",
897
+ brandPrimary: "#ef9f76",
898
+ brandAccent: "#f4b8e4",
899
+ accent: "#81c8be",
900
+ user: "#e5c890",
901
+ assistant: "#8caaee",
902
+ tool: "#81c8be",
903
+ success: "#a6d189",
904
+ warn: "#e5c890",
905
+ error: "#e78284",
906
+ borderDefault: "#626880",
907
+ borderSubtle: "#414559",
908
+ borderActive: "#e5c890",
909
+ brand: "#ca9ee6",
910
+ surface: "#292c3c",
911
+ surfaceRaised: "#303446",
912
+ diffAddBg: "#2c4034",
913
+ diffDelBg: "#422a32",
914
+ monitor: { fleet: "#81c8be", agents: "#ca9ee6", worktree: "#a6d189", phase: "#8caaee" }
915
+ }),
916
+ "gruvbox-material": Object.freeze({
917
+ ...baseTheme,
918
+ textPrimary: "#d4be98",
919
+ textSecondary: "#c5b18d",
920
+ textMuted: "#928374",
921
+ brandPrimary: "#e78a4e",
922
+ brandAccent: "#d3869b",
923
+ accent: "#7daea3",
924
+ user: "#d8a657",
925
+ assistant: "#89b482",
926
+ tool: "#7daea3",
927
+ success: "#a9b665",
928
+ warn: "#d8a657",
929
+ error: "#ea6962",
930
+ borderDefault: "#45403d",
931
+ borderSubtle: "#3c3836",
932
+ borderActive: "#e78a4e",
933
+ brand: "#d3869b",
934
+ surface: "#282828",
935
+ surfaceRaised: "#32302f",
936
+ diffAddBg: "#26332a",
937
+ diffDelBg: "#3a2426",
938
+ monitor: { fleet: "#7daea3", agents: "#d3869b", worktree: "#a9b665", phase: "#89b482" }
939
+ }),
940
+ "tokyo-night-storm": Object.freeze({
941
+ ...baseTheme,
942
+ textPrimary: "#c0caf5",
943
+ textSecondary: "#a9b1d6",
944
+ textMuted: "#565f89",
945
+ brandPrimary: "#ff9e64",
946
+ brandAccent: "#bb9af7",
947
+ accent: "#7aa2f7",
948
+ user: "#e0af68",
949
+ assistant: "#7dcfff",
950
+ tool: "#73daca",
951
+ success: "#9ece6a",
952
+ warn: "#e0af68",
953
+ error: "#f7768e",
954
+ borderDefault: "#3b4261",
955
+ borderSubtle: "#292e42",
956
+ borderActive: "#7aa2f7",
957
+ brand: "#bb9af7",
958
+ surface: "#1f2335",
959
+ surfaceRaised: "#24283b",
960
+ diffAddBg: "#20372c",
961
+ diffDelBg: "#3b2331",
962
+ monitor: { fleet: "#7aa2f7", agents: "#bb9af7", worktree: "#9ece6a", phase: "#7dcfff" }
963
+ }),
964
+ "rose-pine-moon": Object.freeze({
965
+ ...baseTheme,
966
+ textPrimary: "#e0def4",
967
+ // Between Rosé Pine's `text` and `subtle` — `subtle` (#908caa) alone falls
968
+ // under WCAG AA once a comment is lifted onto a diff wash.
969
+ textSecondary: "#c4c1d8",
970
+ textMuted: "#6e6a86",
971
+ brandPrimary: "#f6c177",
972
+ brandAccent: "#ea9a97",
973
+ accent: "#9ccfd8",
974
+ user: "#f6c177",
975
+ assistant: "#c4a7e7",
976
+ tool: "#3e8fb0",
977
+ success: "#3e8fb0",
978
+ warn: "#f6c177",
979
+ error: "#eb6f92",
980
+ borderDefault: "#44415a",
981
+ borderSubtle: "#393552",
982
+ borderActive: "#ea9a97",
983
+ brand: "#c4a7e7",
984
+ surface: "#232136",
985
+ surfaceRaised: "#2a273f",
986
+ diffAddBg: "#22403e",
987
+ diffDelBg: "#3a2836",
988
+ monitor: { fleet: "#9ccfd8", agents: "#c4a7e7", worktree: "#3e8fb0", phase: "#9ccfd8" }
989
+ }),
990
+ zenburn: Object.freeze({
991
+ ...baseTheme,
992
+ textPrimary: "#dcdccc",
993
+ textSecondary: "#c0c0a8",
994
+ textMuted: "#8f8f7f",
995
+ brandPrimary: "#dfaf8f",
996
+ brandAccent: "#dc8cc3",
997
+ accent: "#8cd0d3",
998
+ user: "#f0dfaf",
999
+ assistant: "#93e0e3",
1000
+ tool: "#8cd0d3",
1001
+ success: "#7f9f7f",
1002
+ warn: "#f0dfaf",
1003
+ error: "#cc9393",
1004
+ borderDefault: "#5f5f5f",
1005
+ borderSubtle: "#4a4a4a",
1006
+ borderActive: "#f0dfaf",
1007
+ brand: "#dc8cc3",
1008
+ surface: "#3f3f3f",
1009
+ surfaceRaised: "#4f4f4f",
1010
+ // Zenburn's base (#3f3f3f) is the lightest of any preset here, so a wash
1011
+ // blended toward it leaves the muted green/red markers under 3:1. These
1012
+ // sit well below the base on purpose.
1013
+ diffAddBg: "#2b3a2a",
1014
+ diffDelBg: "#42292a",
1015
+ monitor: { fleet: "#8cd0d3", agents: "#dc8cc3", worktree: "#7f9f7f", phase: "#93e0e3" }
1016
+ }),
1017
+ palenight: Object.freeze({
1018
+ ...baseTheme,
1019
+ // Palenight's canonical fg (#a6accd) is dim enough that using it as the
1020
+ // PRIMARY leaves no headroom for a readable secondary; shift both up one
1021
+ // step and keep #a6accd as the secondary.
1022
+ textPrimary: "#babed8",
1023
+ textSecondary: "#a6accd",
1024
+ textMuted: "#676e95",
1025
+ brandPrimary: "#f78c6c",
1026
+ brandAccent: "#c792ea",
1027
+ accent: "#82aaff",
1028
+ user: "#ffcb6b",
1029
+ assistant: "#89ddff",
1030
+ tool: "#82aaff",
1031
+ success: "#c3e88d",
1032
+ warn: "#ffcb6b",
1033
+ error: "#f07178",
1034
+ borderDefault: "#4a4f6a",
1035
+ borderSubtle: "#3a3f58",
1036
+ borderActive: "#82aaff",
1037
+ brand: "#c792ea",
1038
+ surface: "#292d3e",
1039
+ surfaceRaised: "#34324a",
1040
+ diffAddBg: "#2b4033",
1041
+ diffDelBg: "#43293a",
1042
+ monitor: { fleet: "#82aaff", agents: "#c792ea", worktree: "#c3e88d", phase: "#89ddff" }
1043
+ }),
1044
+ horizon: Object.freeze({
1045
+ ...baseTheme,
1046
+ textPrimary: "#d5d8da",
1047
+ textSecondary: "#bbbdbf",
1048
+ textMuted: "#6c6f93",
1049
+ brandPrimary: "#f09383",
1050
+ brandAccent: "#ee64ac",
1051
+ accent: "#26bbd9",
1052
+ user: "#fab795",
1053
+ assistant: "#59e1e3",
1054
+ tool: "#26bbd9",
1055
+ success: "#29d398",
1056
+ warn: "#fab795",
1057
+ error: "#e95678",
1058
+ borderDefault: "#3d3f4c",
1059
+ borderSubtle: "#2e303e",
1060
+ borderActive: "#e95678",
1061
+ brand: "#ee64ac",
1062
+ surface: "#1c1e26",
1063
+ surfaceRaised: "#232530",
1064
+ diffAddBg: "#16362e",
1065
+ diffDelBg: "#3a1f2a",
1066
+ monitor: { fleet: "#26bbd9", agents: "#ee64ac", worktree: "#29d398", phase: "#59e1e3" }
1067
+ }),
1068
+ sonokai: Object.freeze({
1069
+ ...baseTheme,
1070
+ textPrimary: "#e3e1e4",
1071
+ textSecondary: "#c9c6cb",
1072
+ textMuted: "#848089",
1073
+ brandPrimary: "#ef9062",
1074
+ brandAccent: "#ab9df2",
1075
+ accent: "#7accd7",
1076
+ user: "#e5c463",
1077
+ assistant: "#7accd7",
1078
+ tool: "#9ecd6f",
1079
+ success: "#9ecd6f",
1080
+ warn: "#e5c463",
1081
+ error: "#f85e84",
1082
+ borderDefault: "#4b484d",
1083
+ borderSubtle: "#3b383e",
1084
+ borderActive: "#ef9062",
1085
+ brand: "#ab9df2",
1086
+ surface: "#2d2a2e",
1087
+ surfaceRaised: "#37343a",
1088
+ diffAddBg: "#2c3a2b",
1089
+ diffDelBg: "#43262f",
1090
+ monitor: { fleet: "#7accd7", agents: "#ab9df2", worktree: "#9ecd6f", phase: "#7accd7" }
1091
+ }),
1092
+ "edge-dark": Object.freeze({
1093
+ ...baseTheme,
1094
+ textPrimary: "#c5cdd9",
1095
+ textSecondary: "#adb6c2",
1096
+ textMuted: "#7f8490",
1097
+ brandPrimary: "#deb974",
1098
+ brandAccent: "#d38aea",
1099
+ accent: "#6cb6eb",
1100
+ user: "#deb974",
1101
+ assistant: "#5dbbc1",
1102
+ tool: "#6cb6eb",
1103
+ success: "#a0c980",
1104
+ warn: "#deb974",
1105
+ error: "#ec7279",
1106
+ borderDefault: "#464957",
1107
+ borderSubtle: "#363a4d",
1108
+ borderActive: "#6cb6eb",
1109
+ brand: "#d38aea",
1110
+ surface: "#2b2d3a",
1111
+ surfaceRaised: "#333648",
1112
+ diffAddBg: "#29392c",
1113
+ diffDelBg: "#3d2830",
1114
+ monitor: { fleet: "#6cb6eb", agents: "#d38aea", worktree: "#a0c980", phase: "#5dbbc1" }
1115
+ }),
1116
+ moonfly: Object.freeze({
1117
+ ...baseTheme,
1118
+ textPrimary: "#bdbdbd",
1119
+ textSecondary: "#a8a8a8",
1120
+ textMuted: "#767676",
1121
+ brandPrimary: "#de935f",
1122
+ brandAccent: "#cf87e8",
1123
+ accent: "#80a0ff",
1124
+ user: "#e3c78a",
1125
+ assistant: "#79dac8",
1126
+ tool: "#80a0ff",
1127
+ success: "#8cc85f",
1128
+ warn: "#e3c78a",
1129
+ error: "#ff5454",
1130
+ borderDefault: "#3a3a3a",
1131
+ borderSubtle: "#262626",
1132
+ borderActive: "#80a0ff",
1133
+ brand: "#cf87e8",
1134
+ surface: "#080808",
1135
+ surfaceRaised: "#1c1c1c",
1136
+ diffAddBg: "#10301d",
1137
+ diffDelBg: "#331414",
1138
+ monitor: { fleet: "#80a0ff", agents: "#cf87e8", worktree: "#8cc85f", phase: "#79dac8" }
1139
+ }),
1140
+ melange: Object.freeze({
1141
+ ...baseTheme,
1142
+ textPrimary: "#ece1d7",
1143
+ textSecondary: "#c1a78e",
1144
+ textMuted: "#867462",
1145
+ brandPrimary: "#e49b5d",
1146
+ brandAccent: "#cf9bc2",
1147
+ accent: "#a3a9ce",
1148
+ user: "#ebc06d",
1149
+ assistant: "#89b3b6",
1150
+ tool: "#a3a9ce",
1151
+ success: "#85b695",
1152
+ warn: "#ebc06d",
1153
+ error: "#d47766",
1154
+ borderDefault: "#4d4640",
1155
+ borderSubtle: "#3a352f",
1156
+ borderActive: "#e49b5d",
1157
+ brand: "#cf9bc2",
1158
+ surface: "#292522",
1159
+ surfaceRaised: "#34302c",
1160
+ diffAddBg: "#2f3a30",
1161
+ diffDelBg: "#3f2b28",
1162
+ monitor: { fleet: "#a3a9ce", agents: "#cf9bc2", worktree: "#85b695", phase: "#89b3b6" }
1163
+ }),
1164
+ poimandres: Object.freeze({
1165
+ ...baseTheme,
1166
+ // Same shift as palenight — #a6accd becomes the secondary so the lifted
1167
+ // on-wash comment clears AA.
1168
+ textPrimary: "#c4cbe0",
1169
+ textSecondary: "#a6accd",
1170
+ textMuted: "#506477",
1171
+ brandPrimary: "#f087bd",
1172
+ brandAccent: "#a684ff",
1173
+ accent: "#5de4c7",
1174
+ user: "#fffac2",
1175
+ assistant: "#89ddff",
1176
+ tool: "#5de4c7",
1177
+ success: "#5fb3a1",
1178
+ warn: "#fffac2",
1179
+ error: "#d0679d",
1180
+ borderDefault: "#3b4056",
1181
+ borderSubtle: "#252b37",
1182
+ borderActive: "#5de4c7",
1183
+ brand: "#a684ff",
1184
+ surface: "#1b1e28",
1185
+ surfaceRaised: "#252b37",
1186
+ diffAddBg: "#14352f",
1187
+ diffDelBg: "#35202c",
1188
+ monitor: { fleet: "#5de4c7", agents: "#a684ff", worktree: "#5fb3a1", phase: "#89ddff" }
1189
+ }),
1190
+ "vitesse-dark": Object.freeze({
1191
+ ...baseTheme,
1192
+ textPrimary: "#dbd7ca",
1193
+ textSecondary: "#bfbaaa",
1194
+ textMuted: "#758575",
1195
+ brandPrimary: "#dfab5c",
1196
+ brandAccent: "#d3869b",
1197
+ accent: "#6394bf",
1198
+ user: "#e6cc77",
1199
+ assistant: "#5eaab5",
1200
+ tool: "#6394bf",
1201
+ success: "#4d9375",
1202
+ warn: "#e6cc77",
1203
+ error: "#cb7676",
1204
+ borderDefault: "#333333",
1205
+ borderSubtle: "#222222",
1206
+ borderActive: "#dfab5c",
1207
+ brand: "#d3869b",
1208
+ surface: "#121212",
1209
+ surfaceRaised: "#1c1c1c",
1210
+ diffAddBg: "#16301f",
1211
+ diffDelBg: "#331d1d",
1212
+ monitor: { fleet: "#6394bf", agents: "#d3869b", worktree: "#4d9375", phase: "#5eaab5" }
1213
+ }),
1214
+ aura: Object.freeze({
1215
+ ...baseTheme,
1216
+ textPrimary: "#edecee",
1217
+ textSecondary: "#cdccce",
1218
+ textMuted: "#6d6d6d",
1219
+ brandPrimary: "#ffca85",
1220
+ brandAccent: "#f694ff",
1221
+ accent: "#82e2ff",
1222
+ user: "#ffca85",
1223
+ assistant: "#82e2ff",
1224
+ tool: "#a277ff",
1225
+ success: "#61ffca",
1226
+ warn: "#ffca85",
1227
+ error: "#ff6767",
1228
+ borderDefault: "#3b334b",
1229
+ borderSubtle: "#262433",
1230
+ borderActive: "#a277ff",
1231
+ brand: "#f694ff",
1232
+ surface: "#15141b",
1233
+ surfaceRaised: "#1c1b22",
1234
+ diffAddBg: "#14382c",
1235
+ diffDelBg: "#351d23",
1236
+ monitor: { fleet: "#82e2ff", agents: "#a277ff", worktree: "#61ffca", phase: "#f694ff" }
1237
+ }),
1238
+ "dark-plus": Object.freeze({
1239
+ ...baseTheme,
1240
+ textPrimary: "#d4d4d4",
1241
+ textSecondary: "#cccccc",
1242
+ textMuted: "#858585",
1243
+ brandPrimary: "#ce9178",
1244
+ brandAccent: "#c586c0",
1245
+ accent: "#569cd6",
1246
+ user: "#dcdcaa",
1247
+ assistant: "#9cdcfe",
1248
+ tool: "#4ec9b0",
1249
+ success: "#89d185",
1250
+ warn: "#cca700",
1251
+ error: "#f44747",
1252
+ borderDefault: "#3c3c3c",
1253
+ borderSubtle: "#2d2d30",
1254
+ borderActive: "#569cd6",
1255
+ brand: "#c586c0",
1256
+ surface: "#1e1e1e",
1257
+ surfaceRaised: "#252526",
1258
+ diffAddBg: "#16351f",
1259
+ diffDelBg: "#3a1d20",
1260
+ monitor: { fleet: "#569cd6", agents: "#c586c0", worktree: "#89d185", phase: "#4ec9b0" },
1261
+ // The one preset that genuinely disagrees with the derived defaults:
1262
+ // VS Code colors strings orange and comments green, the inverse of the
1263
+ // usual green-string / grey-comment convention the defaults assume.
1264
+ // `commentOnWash` is a lifted green rather than the default
1265
+ // `textSecondary`, so the comment stays green on a diff wash instead of
1266
+ // switching to grey mid-file.
1267
+ syntax: {
1268
+ string: "#ce9178",
1269
+ comment: "#6a9955",
1270
+ commentOnWash: "#9fc98b"
1271
+ }
730
1272
  })
731
1273
  });
732
1274
  var THEME_OPTIONS = [
@@ -796,6 +1338,106 @@ var THEME_OPTIONS = [
796
1338
  id: "synthwave",
797
1339
  name: "Synthwave '84",
798
1340
  description: "Hot pink + neon cyan on deep purple \u2014 80s retro glow"
1341
+ },
1342
+ {
1343
+ id: "github-dark",
1344
+ name: "GitHub Dark",
1345
+ description: "GitHub's default dark \u2014 crisp blue on near-black"
1346
+ },
1347
+ {
1348
+ id: "material-ocean",
1349
+ name: "Material Ocean",
1350
+ description: "Deepest Material variant \u2014 ink blue with pastel accents"
1351
+ },
1352
+ {
1353
+ id: "nightfox",
1354
+ name: "Nightfox",
1355
+ description: "Balanced slate blue with muted sage and rose"
1356
+ },
1357
+ {
1358
+ id: "oxocarbon",
1359
+ name: "Oxocarbon",
1360
+ description: "IBM Carbon-derived \u2014 neutral greys, electric blue & pink"
1361
+ },
1362
+ {
1363
+ id: "catppuccin-macchiato",
1364
+ name: "Catppuccin Macchiato",
1365
+ description: "Warmer, one shade lighter than Mocha"
1366
+ },
1367
+ {
1368
+ id: "catppuccin-frappe",
1369
+ name: "Catppuccin Frapp\xE9",
1370
+ description: "The lightest Catppuccin dark \u2014 gentle midday contrast"
1371
+ },
1372
+ {
1373
+ id: "gruvbox-material",
1374
+ name: "Gruvbox Material",
1375
+ description: "Softened Gruvbox \u2014 same warmth, lower eye strain"
1376
+ },
1377
+ {
1378
+ id: "tokyo-night-storm",
1379
+ name: "Tokyo Night Storm",
1380
+ description: "Tokyo Night on a lifted blue-grey base"
1381
+ },
1382
+ {
1383
+ id: "rose-pine-moon",
1384
+ name: "Ros\xE9 Pine Moon",
1385
+ description: "Ros\xE9 Pine at dusk \u2014 deeper base, same soft accents"
1386
+ },
1387
+ {
1388
+ id: "zenburn",
1389
+ name: "Zenburn",
1390
+ description: "The classic low-contrast grey \u2014 desaturated and calm"
1391
+ },
1392
+ {
1393
+ id: "palenight",
1394
+ name: "Palenight",
1395
+ description: "Material Palenight \u2014 indigo base, candy accents"
1396
+ },
1397
+ {
1398
+ id: "horizon",
1399
+ name: "Horizon",
1400
+ description: "Warm coral and mint on charcoal \u2014 sunset gradient"
1401
+ },
1402
+ {
1403
+ id: "sonokai",
1404
+ name: "Sonokai",
1405
+ description: "Monokai Pro descendant \u2014 punchy on warm graphite"
1406
+ },
1407
+ {
1408
+ id: "edge-dark",
1409
+ name: "Edge Dark",
1410
+ description: "Clean, evenly-weighted palette on desaturated navy"
1411
+ },
1412
+ {
1413
+ id: "moonfly",
1414
+ name: "Moonfly",
1415
+ description: "Near-black base with high-chroma accents \u2014 maximum contrast"
1416
+ },
1417
+ {
1418
+ id: "melange",
1419
+ name: "Melange",
1420
+ description: "Warm sepia and clay \u2014 the least blue dark theme here"
1421
+ },
1422
+ {
1423
+ id: "poimandres",
1424
+ name: "Poimandres",
1425
+ description: "Teal-forward, low-saturation \u2014 mint on deep indigo"
1426
+ },
1427
+ {
1428
+ id: "vitesse-dark",
1429
+ name: "Vitesse Dark",
1430
+ description: "Anthony Fu's minimal palette \u2014 muted, print-like"
1431
+ },
1432
+ {
1433
+ id: "aura",
1434
+ name: "Aura Dark",
1435
+ description: "Vivid purple and spring green on near-black violet"
1436
+ },
1437
+ {
1438
+ id: "dark-plus",
1439
+ name: "VS Code Dark+",
1440
+ description: "Visual Studio Code's default \u2014 familiar blue/orange/teal"
799
1441
  }
800
1442
  ];
801
1443
 
@@ -5081,7 +5723,8 @@ function buildTodoPreviewRows(todos, width, maxRows = 2) {
5081
5723
  const shown = ordered.slice(0, maxRows);
5082
5724
  const textWidth = Math.max(4, width - 5);
5083
5725
  const rows = shown.map((todo) => {
5084
- const label = todo.status === "in_progress" && todo.activeForm ? todo.activeForm : todo.content;
5726
+ const base = todo.status === "in_progress" && todo.activeForm ? todo.activeForm : todo.content;
5727
+ const label = todo.blockedBy?.[0] ? `${base} \u2014 waiting on ${todo.blockedBy[0]}` : base;
5085
5728
  if (todo.status === "completed") {
5086
5729
  return {
5087
5730
  id: todo.id,
@@ -6141,6 +6784,7 @@ import {
6141
6784
  moveTask,
6142
6785
  removeTask,
6143
6786
  transferTaskToBoard,
6787
+ transitionTask,
6144
6788
  updateTask
6145
6789
  } from "@wrongstack/kanban";
6146
6790
  import { applySessionKanbanTaskToSource } from "@wrongstack/tools/session-kanban";
@@ -6149,6 +6793,7 @@ import { useEffect as useEffect9, useMemo as useMemo4, useState as useState10 }
6149
6793
  // src/kanban-audit.ts
6150
6794
  var DEFAULT_REVIEW_STALE_AFTER_MS = 72 * 60 * 60 * 1e3;
6151
6795
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "archived"]);
6796
+ var BOARD_SOFT_MAX_BYTES = 512 * 1024;
6152
6797
  function auditKanbanBoard(board, options) {
6153
6798
  const now = toEpoch(options.now);
6154
6799
  if (now === null) throw new TypeError("Kanban audit requires a valid current time");
@@ -6160,15 +6805,16 @@ function auditKanbanBoard(board, options) {
6160
6805
  );
6161
6806
  const lifecycleOrder = resolveLifecycleOrder(auditableBoard);
6162
6807
  const managed = isManagedBoard(auditableBoard);
6163
- const requireDueDate = managed || options.requireDueDate === true;
6808
+ const requireDueDate = options.requireDueDate === true;
6164
6809
  const issues = [];
6165
6810
  for (const task of board.tasks) {
6166
- if (lifecycleOrder.length > 1) addLifecycleIssue(issues, task, lifecycleOrder);
6167
6811
  if (TERMINAL_STATUSES.has(task.status)) continue;
6168
6812
  addRequiredDetailIssues(issues, task, requireDueDate, managed);
6169
6813
  addRunningIssue(issues, task, now, liveIdentities);
6170
6814
  addReviewIssue(issues, task, now, reviewStaleAfterMs);
6815
+ if (lifecycleOrder.length > 1) addLifecycleIssue(issues, task, lifecycleOrder);
6171
6816
  }
6817
+ addBoardSizeIssue(issues, board);
6172
6818
  issues.sort(compareIssues);
6173
6819
  return {
6174
6820
  generatedAt: new Date(now).toISOString(),
@@ -6209,7 +6855,7 @@ function addRequiredDetailIssues(issues, task, requireDueDate, managed) {
6209
6855
  if (!hasAssignee) {
6210
6856
  pushIssue(issues, task, "missing-assignee", "warning", "Assign an owner");
6211
6857
  }
6212
- if (requireDueDate && (!hasText(task.dueDate) || !Number.isFinite(Date.parse(task.dueDate)))) {
6858
+ if (requireDueDate && toEpoch(task.dueDate) === null) {
6213
6859
  pushIssue(issues, task, "missing-due-date", "warning", "Set a valid due date");
6214
6860
  }
6215
6861
  if (!hasTextItem(task.labels) && (managed || !hasTextItem(task.tags))) {
@@ -6234,6 +6880,25 @@ function addRequiredDetailIssues(issues, task, requireDueDate, managed) {
6234
6880
  pushIssue(issues, task, "missing-success-criteria", "warning", "Add success criteria");
6235
6881
  }
6236
6882
  }
6883
+ function addBoardSizeIssue(issues, board) {
6884
+ const bytes = boardByteSize(board);
6885
+ if (bytes <= BOARD_SOFT_MAX_BYTES) return;
6886
+ issues.push({
6887
+ id: `${board.id}:board-oversized`,
6888
+ taskId: board.id,
6889
+ taskTitle: board.title,
6890
+ code: "board-oversized",
6891
+ severity: "warning",
6892
+ message: `Board is ~${Math.round(bytes / 1024)} KB across ${board.tasks.length} cards; archive completed cards before it stops syncing to HQ`
6893
+ });
6894
+ }
6895
+ function boardByteSize(board) {
6896
+ try {
6897
+ return JSON.stringify(board)?.length ?? 0;
6898
+ } catch {
6899
+ return 0;
6900
+ }
6901
+ }
6237
6902
  function addRunningIssue(issues, task, now, liveIdentities) {
6238
6903
  const assignment = task.assignment;
6239
6904
  const running = task.status === "in_progress" || assignment?.status === "running";
@@ -6390,7 +7055,7 @@ function normalizeIdentities(values) {
6390
7055
  return normalized;
6391
7056
  }
6392
7057
  function normalizeIdentity(value) {
6393
- return value.trim().toLocaleLowerCase();
7058
+ return value.trim().toLowerCase();
6394
7059
  }
6395
7060
  function firstText(...values) {
6396
7061
  for (const value of values) {
@@ -6536,6 +7201,25 @@ function KanbanPanel({
6536
7201
  });
6537
7202
  return;
6538
7203
  }
7204
+ if (prompt.kind === "transitionTask") {
7205
+ const comment = prompt.buffer.trim();
7206
+ if (!comment) return;
7207
+ const target = prompt.to;
7208
+ const task = prompt.task;
7209
+ setPrompt(null);
7210
+ await runMutation(async () => {
7211
+ if (!board) return null;
7212
+ const actor = sessionId ?? "tui-operator";
7213
+ const result = await transitionTask(projectRoot, board.id, task.id, {
7214
+ to: target,
7215
+ actor,
7216
+ comment
7217
+ });
7218
+ if (result) await syncSource(result.board, task.id, false, task);
7219
+ return result ? `Transitioned "${task.title}" \u2192 ${target}` : "Transition failed (task or board not found)";
7220
+ });
7221
+ return;
7222
+ }
6539
7223
  const value = prompt.buffer.trim();
6540
7224
  if (!value) return;
6541
7225
  const kind = prompt.kind;
@@ -6635,28 +7319,46 @@ function KanbanPanel({
6635
7319
  return;
6636
7320
  }
6637
7321
  if (key.rightArrow && board && activeTask) {
6638
- const nextColumn = adjacentColumn(sortedColumns, activeTask.columnId, 1);
6639
- if (nextColumn) {
6640
- void runMutation(async () => {
6641
- const nextBoard2 = await moveTask(projectRoot, board.id, activeTask.id, nextColumn.id);
6642
- await syncSource(nextBoard2, activeTask.id);
6643
- return `Moved to ${nextColumn.title}`;
6644
- });
7322
+ if (isManagedBoard2(board)) {
7323
+ const current = stageForColumn(board, activeTask.columnId);
7324
+ const target = current ? nextManagedStage(current) : null;
7325
+ if (target) {
7326
+ setPrompt({ kind: "transitionTask", task: activeTask, to: target, buffer: "" });
7327
+ } else {
7328
+ setNotice("Task is already at the final stage (done).");
7329
+ }
7330
+ } else {
7331
+ const nextColumn = adjacentColumn(sortedColumns, activeTask.columnId, 1);
7332
+ if (nextColumn) {
7333
+ void runMutation(async () => {
7334
+ const nextBoard2 = await moveTask(projectRoot, board.id, activeTask.id, nextColumn.id);
7335
+ await syncSource(nextBoard2, activeTask.id);
7336
+ return `Moved to ${nextColumn.title}`;
7337
+ });
7338
+ }
6645
7339
  }
6646
7340
  return;
6647
7341
  }
6648
7342
  if (key.leftArrow && board && activeTask) {
6649
- const prevColumn = adjacentColumn(sortedColumns, activeTask.columnId, -1);
6650
- if (prevColumn) {
6651
- void runMutation(async () => {
6652
- const nextBoard2 = await moveTask(projectRoot, board.id, activeTask.id, prevColumn.id);
6653
- await syncSource(nextBoard2, activeTask.id);
6654
- return `Moved to ${prevColumn.title}`;
6655
- });
7343
+ if (isManagedBoard2(board)) {
7344
+ setNotice("Managed boards advance forward only; use the kanban tool to repair backward.");
7345
+ } else {
7346
+ const prevColumn = adjacentColumn(sortedColumns, activeTask.columnId, -1);
7347
+ if (prevColumn) {
7348
+ void runMutation(async () => {
7349
+ const nextBoard2 = await moveTask(projectRoot, board.id, activeTask.id, prevColumn.id);
7350
+ await syncSource(nextBoard2, activeTask.id);
7351
+ return `Moved to ${prevColumn.title}`;
7352
+ });
7353
+ }
6656
7354
  }
6657
7355
  return;
6658
7356
  }
6659
7357
  if (shortcutsEnabled && (input === " " || input === "D") && board && activeTask) {
7358
+ if (isManagedBoard2(board)) {
7359
+ setNotice("Managed cards advance via \u2192 or t (transition). Use a non-managed board for direct status edits.");
7360
+ return;
7361
+ }
6660
7362
  void runMutation(async () => {
6661
7363
  const nextBoard2 = await updateTask(projectRoot, board.id, activeTask.id, {
6662
7364
  status: "completed",
@@ -6668,6 +7370,10 @@ function KanbanPanel({
6668
7370
  return;
6669
7371
  }
6670
7372
  if (shortcutsEnabled && input === "b" && board && activeTask) {
7373
+ if (isManagedBoard2(board)) {
7374
+ setNotice('Managed cards advance via \u2192 or t (transition); "blocked" is a status, not a lifecycle stage.');
7375
+ return;
7376
+ }
6671
7377
  void runMutation(async () => {
6672
7378
  const nextBoard2 = await updateTask(projectRoot, board.id, activeTask.id, {
6673
7379
  status: "blocked"
@@ -6677,6 +7383,16 @@ function KanbanPanel({
6677
7383
  });
6678
7384
  return;
6679
7385
  }
7386
+ if (shortcutsEnabled && input === "t" && board && activeTask && isManagedBoard2(board)) {
7387
+ const current = stageForColumn(board, activeTask.columnId);
7388
+ const target = current ? nextManagedStage(current) : null;
7389
+ if (!target) {
7390
+ setNotice("Task is already at the final stage (done).");
7391
+ } else {
7392
+ setPrompt({ kind: "transitionTask", task: activeTask, to: target, buffer: "" });
7393
+ }
7394
+ return;
7395
+ }
6680
7396
  if (shortcutsEnabled && input === "x" && activeTask) {
6681
7397
  setPrompt({ kind: "confirmDeleteTask", task: activeTask });
6682
7398
  return;
@@ -6766,6 +7482,22 @@ function PromptLine({ prompt }) {
6766
7482
  '"? y/n'
6767
7483
  ] });
6768
7484
  }
7485
+ if (prompt.kind === "transitionTask") {
7486
+ return /* @__PURE__ */ jsxs14(Text, { children: [
7487
+ /* @__PURE__ */ jsxs14(Text, { color: "magenta", children: [
7488
+ prompt.to.toUpperCase(),
7489
+ ' "',
7490
+ prompt.task.title,
7491
+ '":',
7492
+ " "
7493
+ ] }),
7494
+ prompt.buffer,
7495
+ /* @__PURE__ */ jsxs14(Text, { dimColor: true, children: [
7496
+ "_ ",
7497
+ /* @__PURE__ */ jsx15(Text, { dimColor: true, children: "(Esc cancel \xB7 Enter confirm \u2014 comment required)" })
7498
+ ] })
7499
+ ] });
7500
+ }
6769
7501
  const label = prompt.kind === "createBoard" ? "New board title" : "New task title";
6770
7502
  return /* @__PURE__ */ jsxs14(Text, { children: [
6771
7503
  /* @__PURE__ */ jsxs14(Text, { color: "cyan", children: [
@@ -6882,6 +7614,20 @@ function BoardColumns({
6882
7614
  ] }) : null
6883
7615
  ] });
6884
7616
  }
7617
+ function isManagedBoard2(board) {
7618
+ return board?.lifecycle?.mode === "managed";
7619
+ }
7620
+ var MANAGED_STAGE_ORDER = [
7621
+ "backlog",
7622
+ "todo",
7623
+ "running",
7624
+ "review",
7625
+ "done"
7626
+ ];
7627
+ function nextManagedStage(current) {
7628
+ const idx = MANAGED_STAGE_ORDER.indexOf(current);
7629
+ return idx >= 0 && idx < MANAGED_STAGE_ORDER.length - 1 ? MANAGED_STAGE_ORDER[idx + 1] : null;
7630
+ }
6885
7631
  function stageForColumn(board, columnId) {
6886
7632
  const policy = board.lifecycle;
6887
7633
  if (policy?.mode !== "managed") return null;
@@ -6977,7 +7723,7 @@ function TaskDetail({
6977
7723
  "C/T target: ",
6978
7724
  target.title
6979
7725
  ] }) : null,
6980
- /* @__PURE__ */ jsx15(Text, { dimColor: true, children: "space done | b block | x delete" })
7726
+ /* @__PURE__ */ jsx15(Text, { dimColor: true, children: board.lifecycle?.mode === "managed" ? "\u2192/t transition | x delete" : "space done | b block | x delete" })
6981
7727
  ] })
6982
7728
  ] });
6983
7729
  }
@@ -10545,20 +11291,20 @@ import React2 from "react";
10545
11291
 
10546
11292
  // src/highlight.ts
10547
11293
  var C = {
10548
- keyword: "magenta",
10549
- string: "green",
10550
- comment: "gray",
10551
- number: "yellow",
10552
- literal: "yellow",
11294
+ keyword: "syntax.keyword",
11295
+ string: "syntax.string",
11296
+ comment: "syntax.comment",
11297
+ number: "syntax.number",
11298
+ literal: "syntax.literal",
10553
11299
  // true/false/null
10554
- property: "cyan",
10555
- variable: "cyan",
10556
- command: "cyan",
10557
- flag: "yellow",
10558
- decorator: "magenta",
10559
- diffAdd: "green",
10560
- diffDel: "red",
10561
- diffMeta: "cyan"
11300
+ property: "syntax.property",
11301
+ variable: "syntax.variable",
11302
+ command: "syntax.command",
11303
+ flag: "syntax.flag",
11304
+ decorator: "syntax.decorator",
11305
+ diffAdd: "syntax.diffAdd",
11306
+ diffDel: "syntax.diffDel",
11307
+ diffMeta: "syntax.diffMeta"
10562
11308
  };
10563
11309
  var TS_KEYWORDS = /* @__PURE__ */ new Set([
10564
11310
  "const",
@@ -13303,8 +14049,8 @@ function formatDiffStats(added, removed) {
13303
14049
  function applyWashTokens(tokens, onWash) {
13304
14050
  if (!onWash) return tokens;
13305
14051
  return tokens.map((t) => {
13306
- if (t.color !== "gray") return t;
13307
- return { ...t, color: "grayBright", dim: false };
14052
+ if (t.color !== "syntax.comment") return t;
14053
+ return { ...t, color: "syntax.commentOnWash", dim: false };
13308
14054
  });
13309
14055
  }
13310
14056
  function renderTokens(tokens, onWash = false) {
@@ -17212,22 +17958,6 @@ function estimateTextRows(text, contentWidth, maxRows) {
17212
17958
  rows += Math.max(1, Math.ceil(displayWidth(safeText.slice(lineStart)) / width));
17213
17959
  return Math.min(maxRows, Math.max(1, rows));
17214
17960
  }
17215
- function estimateSageKvRows(cells, contentWidth) {
17216
- if (cells.length === 0) return 0;
17217
- const gap = 2;
17218
- let rows = 1;
17219
- let usedColumns = 0;
17220
- for (const cell of cells) {
17221
- const cellWidth = displayWidth(cell) + gap;
17222
- if (usedColumns > 0 && usedColumns + cellWidth > contentWidth) {
17223
- rows += 1;
17224
- usedColumns = cellWidth;
17225
- } else {
17226
- usedColumns += cellWidth;
17227
- }
17228
- }
17229
- return rows;
17230
- }
17231
17961
  function estimateRenderGroupRows(group, contentWidth, showSageMemoryInject) {
17232
17962
  if (group.type === "tool-group") return group.data.entries.length + 2;
17233
17963
  const { entry } = group;
@@ -17235,34 +17965,13 @@ function estimateRenderGroupRows(group, contentWidth, showSageMemoryInject) {
17235
17965
  const { cleanOutput, sageLines } = resolveEntrySage(entry.output, entry.sageLines);
17236
17966
  const memoryLines = sageLines.slice(1);
17237
17967
  const panelContentWidth = Math.max(1, contentWidth - 4);
17238
- const sagePanelRows = showSageMemoryInject === false || memoryLines.length === 0 ? 0 : 2 + estimateTextRows(
17239
- `\u{1F9E0} SAGE MEMORY INJECTED \xB7 ${entry.name} ${memoryLines.length} ${memoryLines.length === 1 ? "memory" : "memories"}${entry.sageStats ? ` \xB7 ${entry.sageStats}` : ""}`,
17240
- panelContentWidth,
17241
- MAX_TEXT_ESTIMATE_ROWS
17242
- ) + memoryLines.reduce((rows, line) => {
17968
+ const sagePanelRows = showSageMemoryInject === false || memoryLines.length === 0 ? 0 : 4 + memoryLines.reduce((sum, line) => {
17243
17969
  const parsed = parseSageMemoryLine(line);
17244
- if (!parsed) {
17245
- return rows + estimateTextRows(line, panelContentWidth, MAX_TEXT_ESTIMATE_ROWS);
17246
- }
17247
- const labelRow = estimateTextRows(
17248
- parsed.labels.length > 0 ? parsed.labels.map((l) => `[${l}]`).join("") : "[memory]",
17249
- panelContentWidth,
17250
- MAX_TEXT_ESTIMATE_ROWS
17251
- );
17252
- const bodyRow = estimateTextRows(
17253
- parsed.text,
17254
- panelContentWidth,
17255
- MAX_TEXT_ESTIMATE_ROWS
17256
- );
17257
- const kvCells = [];
17258
- kvCells.push(`id: ${parsed.id}`);
17259
- if (parsed.anchor) kvCells.push(`anchor: ${parsed.anchor}`);
17260
- if (parsed.relation) kvCells.push(`relation: ${parsed.relation}`);
17261
- if (parsed.tags && parsed.tags.length > 0)
17262
- kvCells.push(`tags: ${parsed.tags.join(", ")}`);
17263
- const kvRows = estimateSageKvRows(kvCells, panelContentWidth);
17264
- const gap = rows > 0 ? 1 : 0;
17265
- return rows + labelRow + bodyRow + kvRows + gap;
17970
+ const bodySource = parsed ? parsed.text : line;
17971
+ const bodyWidth = displayWidth(sanitizeTerminalText(bodySource));
17972
+ const bodyRows = Math.max(1, Math.ceil(bodyWidth / panelContentWidth));
17973
+ const kvRows = panelContentWidth < 48 ? 2 : 1;
17974
+ return sum + 1 + bodyRows + kvRows;
17266
17975
  }, 0);
17267
17976
  if (entry.resultRenderMode === "simple") return 3 + sagePanelRows;
17268
17977
  if (STRUCTURED_DIFF_TOOLS.has(entry.name)) {
@@ -19025,11 +19734,23 @@ var Entry = React4.memo(function Entry2({
19025
19734
  function SageMemoryBlock({
19026
19735
  sageLines,
19027
19736
  toolName,
19028
- stats
19737
+ stats,
19738
+ compact = false
19029
19739
  }) {
19030
19740
  if (!sageLines || sageLines.length < 2) return null;
19031
19741
  const memoryLines = sageLines.slice(1);
19032
19742
  if (memoryLines.length === 0) return null;
19743
+ if (compact) {
19744
+ const first = parseSageMemoryLine(memoryLines[0] ?? "");
19745
+ const preview = first ? sanitizeTerminalText(first.text).slice(0, 72) : sanitizeTerminalText(memoryLines[0] ?? "").slice(0, 72);
19746
+ const labels = first?.labels?.length ? first.labels.map((l) => `[${l}]`).join("") : "";
19747
+ return /* @__PURE__ */ jsx68(Box, { flexDirection: "row", marginTop: 0, children: /* @__PURE__ */ jsxs65(Text, { color: theme.accent, children: [
19748
+ `\u{1F9E0} ${memoryLines.length} SAGE \xB7 ${toolName}`,
19749
+ stats ? ` \xB7 ${stats}` : "",
19750
+ labels ? ` ${labels}` : "",
19751
+ preview ? ` \u2014 ${preview}${preview.length >= 72 ? "\u2026" : ""}` : ""
19752
+ ] }) });
19753
+ }
19033
19754
  return /* @__PURE__ */ jsxs65(
19034
19755
  Box,
19035
19756
  {
@@ -20237,12 +20958,12 @@ var TOKEN_SAVING_TIERS = [
20237
20958
  "aggressive"
20238
20959
  ];
20239
20960
  var TOKEN_SAVING_TIER_DESCS = {
20240
- auto: "By window \u2014 full tools, lean prompt on small models (cache-safe)",
20241
- off: "All tools enabled (full prompt)",
20242
- minimal: "~2.5\u20132.7k tokens \u2014 core tools only",
20243
- light: "~2.3\u20132.4k tokens \u2014 core + patterns",
20244
- medium: "~1.4\u20131.5k tokens \u2014 most tools enabled",
20245
- aggressive: "~1k tokens \u2014 many tools, trimmed prompt"
20961
+ auto: "Medium direct surface; prompt adapts to the model window",
20962
+ off: "Every enabled catalog tool is sent directly; full prompt",
20963
+ minimal: "Essential direct tools; compact prompt and guidance",
20964
+ light: "Essential direct tools; retains common workflow guidance",
20965
+ medium: "Essential + regular development tools; moderate trimming",
20966
+ aggressive: "Smallest direct surface and most compact prompt"
20246
20967
  };
20247
20968
  var FLEET_CHAT_MODES = ["off", "full"];
20248
20969
  var FLEET_CHAT_MODE_DESCS = {
@@ -20815,7 +21536,7 @@ var SETTINGS_DEFAULTS = Object.freeze({
20815
21536
  showAgentSwarmPanel: "bottom",
20816
21537
  panelPositions: DEFAULT_PANEL_POSITIONS,
20817
21538
  readSymbols: false,
20818
- showSageMemoryInject: false,
21539
+ showSageMemoryInject: true,
20819
21540
  sageMemoryInjectThreshold: 0.85,
20820
21541
  nextStepsTool: false
20821
21542
  });
@@ -21612,11 +22333,15 @@ function buildMissionRows(todos, maxRows) {
21612
22333
  const rank = (t) => t.status === "in_progress" ? 0 : t.status === "pending" ? 1 : 2;
21613
22334
  const ordered = [...list].sort((a, b) => rank(a) - rank(b));
21614
22335
  const shown = ordered.slice(0, maxRows);
21615
- const rows = shown.map((t) => ({
21616
- id: t.id,
21617
- status: t.status,
21618
- label: t.status === "in_progress" && t.activeForm ? t.activeForm : t.content
21619
- }));
22336
+ const rows = shown.map((t) => {
22337
+ const base = t.status === "in_progress" && t.activeForm ? t.activeForm : t.content;
22338
+ const blocker = t.blockedBy?.[0];
22339
+ return {
22340
+ id: t.id,
22341
+ status: t.status,
22342
+ label: blocker ? `${base} \u2014 waiting on ${blocker}` : base
22343
+ };
22344
+ });
21620
22345
  return { rows, overflow: ordered.length - shown.length, done, total };
21621
22346
  }
21622
22347
  function DialRow({
@@ -22567,7 +23292,8 @@ function TodosPanelSidebar({ todos, width }) {
22567
23292
  children: /* @__PURE__ */ jsx79(SidebarPanelCard, { innerWidth: inner, marginBottom: 0, children: ordered.length === 0 ? /* @__PURE__ */ jsx79(Text, { color: theme.textMuted, children: "no todos" }) : ordered.map((t) => {
22568
23293
  const icon = t.status === "completed" ? glyphs.success : t.status === "in_progress" ? "\u25CF" : "\u25CB";
22569
23294
  const color = t.status === "completed" ? theme.success : t.status === "in_progress" ? theme.accent : theme.textMuted;
22570
- const label = t.status === "in_progress" && t.activeForm ? t.activeForm : t.content;
23295
+ const base = t.status === "in_progress" && t.activeForm ? t.activeForm : t.content;
23296
+ const label = t.blockedBy?.[0] ? `${base} \u2014 waiting on ${t.blockedBy[0]}` : base;
22571
23297
  return /* @__PURE__ */ jsx79(
22572
23298
  SidebarWorklistRow,
22573
23299
  {
@@ -23473,7 +24199,7 @@ function ThemePicker({
23473
24199
  const isSelected = i === selected;
23474
24200
  return /* @__PURE__ */ jsxs80(Text, { inverse: isSelected, ...isSelected ? { color: "cyan" } : {}, children: [
23475
24201
  isSelected ? "\u203A " : " ",
23476
- /* @__PURE__ */ jsx83(Text, { bold: true, children: opt.name.padEnd(18) }),
24202
+ /* @__PURE__ */ jsx83(Text, { bold: true, children: opt.name.padEnd(21) }),
23477
24203
  /* @__PURE__ */ jsx83(Text, { dimColor: true, children: opt.description }),
23478
24204
  isActive ? /* @__PURE__ */ jsx83(Text, { color: "green", children: " [active]" }) : null
23479
24205
  ] }, opt.id);
@@ -23492,10 +24218,12 @@ import { Fragment as Fragment30, jsx as jsx84, jsxs as jsxs81 } from "react/jsx-
23492
24218
  var CHROME_ROWS6 = 15;
23493
24219
  var MAX_PICKER_ITEMS2 = 15;
23494
24220
  function toolActionLabel(enabled) {
23495
- return enabled ? "Enter makes this tool passive" : "Enter re-enables this tool";
24221
+ return enabled ? "Enter disables this tool" : "Enter re-enables this tool";
23496
24222
  }
23497
- function statusBadge2(enabled) {
23498
- return enabled ? /* @__PURE__ */ jsx84(Text, { color: "green", children: "\u25CF active" }) : /* @__PURE__ */ jsx84(Text, { color: "red", children: "\u25CB passive" });
24223
+ function statusBadge2(exposure) {
24224
+ if (exposure === "direct") return /* @__PURE__ */ jsx84(Text, { color: "green", children: "\u25CF direct" });
24225
+ if (exposure === "lazy") return /* @__PURE__ */ jsx84(Text, { color: "cyan", children: "\u25C7 lazy" });
24226
+ return /* @__PURE__ */ jsx84(Text, { color: "red", children: "\u25CB disabled" });
23499
24227
  }
23500
24228
  function rwBadge(mutating) {
23501
24229
  return mutating ? /* @__PURE__ */ jsx84(Text, { color: "yellow", children: "mut" }) : /* @__PURE__ */ jsx84(Text, { color: "cyan", children: "ro" });
@@ -23589,8 +24317,9 @@ function ToolsPicker({
23589
24317
  visibleSelected = selected;
23590
24318
  }
23591
24319
  const rows = buildRows2(visibleItems);
23592
- const enabledCount = items.filter((item) => item.enabled).length;
23593
- const passiveCount = total - enabledCount;
24320
+ const directCount = items.filter((item) => item.exposure === "direct").length;
24321
+ const lazyCount = items.filter((item) => item.exposure === "lazy").length;
24322
+ const disabledCount = items.filter((item) => item.exposure === "disabled").length;
23594
24323
  const selectedItem = visibleItems[visibleSelected];
23595
24324
  const win = windowRows3(rows, visibleSelected, maxVisible);
23596
24325
  const displayRows = win.rows;
@@ -23599,8 +24328,8 @@ function ToolsPicker({
23599
24328
  const hasFilter = filterActive;
23600
24329
  return /* @__PURE__ */ jsxs81(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: [
23601
24330
  /* @__PURE__ */ jsx84(Text, { bold: true, color: "green", children: "\u2501\u2501 Tools \u2501\u2501" }),
23602
- /* @__PURE__ */ jsx84(Text, { dimColor: true, children: hasFilter ? `Filter: ${filter} (${visibleItems.length} match${visibleItems.length === 1 ? "" : "es"}) \xB7 Backspace edit \xB7 Esc clear` : `\u2191/\u2193 select \xB7 type to filter \xB7 Enter toggles \xB7 Esc close \xB7 ${enabledCount} active / ${passiveCount} passive` }),
23603
- /* @__PURE__ */ jsx84(Text, { dimColor: true, children: "Passive tools stay listed for this session so you can select them and re-enable them later." }),
24331
+ /* @__PURE__ */ jsx84(Text, { dimColor: true, children: hasFilter ? `Filter: ${filter} (${visibleItems.length} match${visibleItems.length === 1 ? "" : "es"}) \xB7 Backspace edit \xB7 Esc clear` : `\u2191/\u2193 select \xB7 type to filter \xB7 Enter toggles \xB7 Esc close \xB7 ${directCount} direct / ${lazyCount} lazy / ${disabledCount} disabled` }),
24332
+ /* @__PURE__ */ jsx84(Text, { dimColor: true, children: "Lazy tools stay executable through discovery gateways without sending every schema to the provider." }),
23604
24333
  /* @__PURE__ */ jsx84(Box, { marginTop: 1, flexDirection: "column", children: total === 0 ? /* @__PURE__ */ jsx84(Text, { dimColor: true, children: busy ? "Loading tools\u2026" : "No tools registered." }) : visibleItems.length === 0 ? /* @__PURE__ */ jsxs81(Text, { dimColor: true, children: [
23605
24334
  'No tools match "',
23606
24335
  filter,
@@ -23617,7 +24346,7 @@ function ToolsPicker({
23617
24346
  wrap: "truncate-end",
23618
24347
  children: [
23619
24348
  focused ? "\u203A " : " ",
23620
- statusBadge2(item.enabled),
24349
+ statusBadge2(item.exposure),
23621
24350
  " ",
23622
24351
  /* @__PURE__ */ jsx84(Text, { bold: true, children: fitCell(item.name, columnWidths.name) }),
23623
24352
  " ",
@@ -23628,7 +24357,6 @@ function ToolsPicker({
23628
24357
  " ",
23629
24358
  rwBadge(item.mutating),
23630
24359
  " ",
23631
- " ",
23632
24360
  fitCell(item.permission, columnWidths.permission),
23633
24361
  " ",
23634
24362
  /* @__PURE__ */ jsxs81(Text, { color: item.descMode === "simple" ? "yellow" : void 0, children: [
@@ -23646,7 +24374,13 @@ function ToolsPicker({
23646
24374
  selectedItem ? /* @__PURE__ */ jsxs81(Box, { marginTop: 1, flexDirection: "column", children: [
23647
24375
  /* @__PURE__ */ jsxs81(Text, { children: [
23648
24376
  /* @__PURE__ */ jsx84(Text, { color: selectedItem.enabled ? "green" : "red", children: toolActionLabel(selectedItem.enabled) }),
23649
- /* @__PURE__ */ jsx84(Text, { dimColor: true, children: ` \xB7 ${selectedItem.mutating ? "Mutating" : "Read-only"} \xB7 permission: ${selectedItem.permission} \xB7 descriptions: ${selectedItem.descMode}` })
24377
+ /* @__PURE__ */ jsx84(
24378
+ Text,
24379
+ {
24380
+ dimColor: true,
24381
+ children: ` \xB7 ${selectedItem.mutating ? "Mutating" : "Read-only"} \xB7 permission: ${selectedItem.permission} \xB7 descriptions: ${selectedItem.descMode}`
24382
+ }
24383
+ )
23650
24384
  ] }),
23651
24385
  /* @__PURE__ */ jsx84(Text, { dimColor: true, wrap: "truncate-end", children: selectedItem.description || "No description provided." })
23652
24386
  ] }) : null,
@@ -26775,7 +27509,9 @@ function createInitialState(options) {
26775
27509
  showModelReasoning: true,
26776
27510
  showAgentSwarmPanel: "bottom",
26777
27511
  panelPositions: DEFAULT_PANEL_POSITIONS,
26778
- showSageMemoryInject: false,
27512
+ // Default on: compact one-line chip (see SageMemoryBlock). Full bordered
27513
+ // panel remains available when operators expand inject visibility later.
27514
+ showSageMemoryInject: true,
26779
27515
  sageMemoryInjectThreshold: 0.85,
26780
27516
  nextStepsTool: false,
26781
27517
  readSymbols: false
@@ -31539,7 +32275,7 @@ import {
31539
32275
  updateBoard,
31540
32276
  updateTask as updateTask2
31541
32277
  } from "@wrongstack/kanban";
31542
- var USAGE2 = "Usage:\n /kanban \u2014 open the project kanban panel\n /kanban create <title> \u2014 create a board, then open the panel\n /kanban add <title> [--column X] \u2014 add a task to the active board\n /kanban use <boardId|title|tag> \u2014 open the panel on a specific board\n /kanban boards \u2014 list every board in the project\n /kanban health \u2014 show kanban queue health summary\n /kanban audit [boardId|all] \u2014 show kanban cleaner audit (all boards if omitted)\n /kanban boundary <board> show [--task ID]\n /kanban boundary <board> allow|deny <kind> <access> <path> [--task ID] [--enforcement confirm|block] [--shell allow|confirm|block]\n /kanban boundary <board> clear [--task ID]\n /kanban help \u2014 show this help";
32278
+ var USAGE2 = "Usage:\n /kanban \u2014 open the project kanban panel\n /kanban create <title> \u2014 create a board, then open the panel\n /kanban add <title> [--column X] [--desc <text>] \u2014 add a task to the active board (managed boards require --desc)\n /kanban use <boardId|title|tag> \u2014 open the panel on a specific board\n /kanban boards \u2014 list every board in the project\n /kanban health \u2014 show kanban queue health summary\n /kanban audit [boardId|all] \u2014 show kanban cleaner audit (all boards if omitted)\n /kanban boundary <board> show [--task ID]\n /kanban boundary <board> allow|deny <kind> <access> <path> [--task ID] [--enforcement confirm|block] [--shell allow|confirm|block]\n /kanban boundary <board> clear [--task ID]\n /kanban help \u2014 show this help";
31543
32279
  var KANBAN_PANEL_ACTION = "toggleKanbanPanel";
31544
32280
  function createKanbanSlashCommand(deps) {
31545
32281
  return {
@@ -31587,15 +32323,26 @@ function createKanbanSlashCommand(deps) {
31587
32323
  message: "No kanban board found. Use `/kanban create <title>` to make one first."
31588
32324
  };
31589
32325
  }
31590
- const created = await addTaskToBoard(deps.projectRoot, target, parsed.title);
32326
+ if (target.managed && !parsed.description) {
32327
+ return {
32328
+ message: `"${target.boardTitle}" is a managed board \u2014 every card needs a description. Try: /kanban add "${parsed.title}" --desc "<what the task is>"`
32329
+ };
32330
+ }
32331
+ const created = await addTaskToBoard(
32332
+ deps.projectRoot,
32333
+ target,
32334
+ parsed.title,
32335
+ parsed.description
32336
+ );
31591
32337
  if (!created) {
31592
32338
  return {
31593
32339
  message: `Failed to add task to "${target.boardTitle}" \u2014 no writable column found.`
31594
32340
  };
31595
32341
  }
31596
32342
  deps.onPanelOpen?.current?.(KANBAN_PANEL_ACTION);
32343
+ const columnHint = target.managed ? " (backlog)" : "";
31597
32344
  return {
31598
- message: `Added task "${created.title}" to "${target.boardTitle}" \u2192 ${created.columnId}. Opening panel\u2026`
32345
+ message: `Added task "${created.title}" to "${target.boardTitle}" \u2192 ${created.columnId}${columnHint}. Opening panel\u2026`
31599
32346
  };
31600
32347
  }
31601
32348
  if (parsed.kind === "use") {
@@ -31661,6 +32408,7 @@ function parseKanbanArgs(raw) {
31661
32408
  if (head === "add" || head === "add-task" || head === "task") {
31662
32409
  let title = "";
31663
32410
  let column = null;
32411
+ let description = null;
31664
32412
  for (let i = 1; i < tokens.length; i++) {
31665
32413
  const tok = tokens[i] ?? "";
31666
32414
  if (tok === "--column" || tok === "-c") {
@@ -31675,11 +32423,28 @@ function parseKanbanArgs(raw) {
31675
32423
  column = tok.slice("--column=".length);
31676
32424
  continue;
31677
32425
  }
32426
+ if (tok === "--desc" || tok === "-d") {
32427
+ const next = tokens[i + 1];
32428
+ if (next) {
32429
+ description = next;
32430
+ i++;
32431
+ }
32432
+ continue;
32433
+ }
32434
+ if (tok.startsWith("--desc=")) {
32435
+ description = tok.slice("--desc=".length);
32436
+ continue;
32437
+ }
31678
32438
  title = title ? `${title} ${tok}` : tok;
31679
32439
  }
31680
32440
  title = title.trim();
31681
32441
  if (!title) return { kind: "help" };
31682
- return { kind: "add", title, column };
32442
+ return {
32443
+ kind: "add",
32444
+ title,
32445
+ column,
32446
+ ...description ? { description } : {}
32447
+ };
31683
32448
  }
31684
32449
  if (head === "use" || head === "open-board" || head === "focus") {
31685
32450
  const query = tokens.slice(1).join(" ").trim();
@@ -31792,9 +32557,7 @@ function renderBoundaryPolicy(policy) {
31792
32557
  if (!policy?.enabled) return "unrestricted";
31793
32558
  const lines = [
31794
32559
  `mode ${policy.enforcement} \xB7 shell ${policy.shellAccess}`,
31795
- ...policy.allow.map(
31796
- (selector) => `ALLOW ${selector.access} ${selector.kind}:${selector.path}`
31797
- ),
32560
+ ...policy.allow.map((selector) => `ALLOW ${selector.access} ${selector.kind}:${selector.path}`),
31798
32561
  ...(policy.deny ?? []).map(
31799
32562
  (selector) => `DENY ${selector.access} ${selector.kind}:${selector.path}`
31800
32563
  )
@@ -31871,13 +32634,17 @@ async function resolveAddTarget(deps, column) {
31871
32634
  if (!preferred) return null;
31872
32635
  const board = await getBoard3(deps.projectRoot, preferred.id);
31873
32636
  if (!board) return null;
32637
+ const managed = board.lifecycle?.mode === "managed";
31874
32638
  const firstColumn = board.columns[0];
31875
- const targetColumn = resolveColumn(board.columns, column) ?? firstColumn;
32639
+ const backlogColumnId = managed ? board.lifecycle?.columns?.backlog : void 0;
32640
+ const backlogColumn = backlogColumnId ? board.columns.find((c) => c.id === backlogColumnId) : void 0;
32641
+ const targetColumn = managed ? backlogColumn ?? firstColumn : resolveColumn(board.columns, column) ?? firstColumn;
31876
32642
  if (!targetColumn) return null;
31877
32643
  return {
31878
32644
  boardId: board.id,
31879
32645
  boardTitle: board.title,
31880
- columnId: targetColumn.id
32646
+ columnId: targetColumn.id,
32647
+ managed
31881
32648
  };
31882
32649
  }
31883
32650
  function resolveColumn(columns, hint) {
@@ -31912,7 +32679,15 @@ function renderHealthReport(health2) {
31912
32679
  c.queued > 0 ? ` + ${c.queued} currently queued for assignment (subset)` : "",
31913
32680
  "",
31914
32681
  " **Per-status counts**",
31915
- ` ready ${c.ready} \xB7 running ${c.running} \xB7 review ${c.review} \xB7 failed ${c.failed} \xB7 completed ${c.completed}`,
32682
+ // `startable`, not `ready`. `counts.ready` tallies the stored status field,
32683
+ // which no dispatcher writes, so it printed a permanent 0 while
32684
+ // `ready_tasks` on the same board returned work. `counts.startable` is the
32685
+ // derived answer and agrees with `listReadyTasks`.
32686
+ //
32687
+ // `lifecycleTotal` above still sums `c.ready` on purpose: that is the
32688
+ // single-count partition, and `startable` overlaps `pending`/`ready`, so
32689
+ // swapping it there would double-count. These two lines are meant to differ.
32690
+ ` startable ${c.startable} \xB7 running ${c.running} \xB7 review ${c.review} \xB7 failed ${c.failed} \xB7 completed ${c.completed}`,
31916
32691
  ` pending ${c.pending} \xB7 archived ${c.archived} \xB7 blocked ${c.blocked}` + (c.queued > 0 ? ` \xB7 queued ${c.queued}` : ""),
31917
32692
  ""
31918
32693
  ].filter((line) => line !== "");
@@ -32038,10 +32813,11 @@ function renderAuditReport(rows, multi) {
32038
32813
  function severityRank2(severity) {
32039
32814
  return severity === "error" ? 0 : 1;
32040
32815
  }
32041
- async function addTaskToBoard(cwd, target, title) {
32816
+ async function addTaskToBoard(cwd, target, title, description) {
32042
32817
  const input = {
32043
32818
  title,
32044
- columnId: target.columnId
32819
+ columnId: target.columnId,
32820
+ ...description ? { description } : {}
32045
32821
  };
32046
32822
  const result = await addTask2(cwd, target.boardId, input);
32047
32823
  if (!result) return null;