schub 0.1.0 → 0.1.2

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.
Files changed (50) hide show
  1. package/README.md +68 -0
  2. package/dist/index.js +1573 -597
  3. package/package.json +3 -1
  4. package/skills/create-proposal/SKILL.md +33 -0
  5. package/skills/create-tasks/SKILL.md +40 -0
  6. package/skills/implement-task/SKILL.md +84 -0
  7. package/skills/review-proposal/SKILL.md +37 -0
  8. package/skills/setup-project/SKILL.md +29 -0
  9. package/src/App.test.tsx +93 -0
  10. package/src/App.tsx +62 -10
  11. package/src/changes.ts +86 -28
  12. package/src/clipboard.ts +5 -0
  13. package/src/commands/adr.test.ts +69 -0
  14. package/src/commands/adr.ts +107 -0
  15. package/src/commands/changes.test.ts +171 -0
  16. package/src/commands/changes.ts +163 -0
  17. package/src/commands/cookbook.test.ts +71 -0
  18. package/src/commands/cookbook.ts +95 -0
  19. package/src/commands/eject.test.ts +74 -0
  20. package/src/commands/eject.ts +100 -0
  21. package/src/commands/init.test.ts +78 -0
  22. package/src/commands/init.ts +144 -0
  23. package/src/commands/project.test.ts +113 -0
  24. package/src/commands/project.ts +75 -0
  25. package/src/commands/review.test.ts +100 -0
  26. package/src/commands/review.ts +231 -0
  27. package/src/commands/tasks-create.test.ts +172 -0
  28. package/src/commands/tasks-list.test.ts +177 -0
  29. package/src/commands/tasks.ts +172 -0
  30. package/src/components/PlanView.test.tsx +113 -0
  31. package/src/components/PlanView.tsx +95 -26
  32. package/src/components/StatusView.test.tsx +380 -0
  33. package/src/components/StatusView.tsx +233 -83
  34. package/src/features/tasks/constants.ts +2 -0
  35. package/src/features/tasks/create.ts +15 -7
  36. package/src/features/tasks/filesystem.test.ts +78 -0
  37. package/src/features/tasks/filesystem.ts +61 -7
  38. package/src/ide.ts +7 -0
  39. package/src/index.test.ts +23 -0
  40. package/src/index.ts +60 -383
  41. package/src/init.test.ts +43 -0
  42. package/src/init.ts +27 -0
  43. package/src/project.ts +5 -32
  44. package/src/schub-root.ts +33 -0
  45. package/src/templates.ts +18 -0
  46. package/src/terminal.test.ts +46 -0
  47. package/templates/create-proposal/cookbook-template.md +37 -0
  48. package/templates/review-proposal/q&a-template.md +5 -1
  49. package/templates/templates-parity.test.ts +45 -0
  50. package/templates/setup-project/review-me-template.md +0 -18
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ var __export = (target, all) => {
30
30
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
31
31
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
32
32
 
33
- // ../../../node_modules/.bun/react@19.2.3/node_modules/react/cjs/react.development.js
33
+ // ../../node_modules/.bun/react@19.2.3/node_modules/react/cjs/react.development.js
34
34
  var require_react_development = __commonJS((exports, module) => {
35
35
  (function() {
36
36
  function defineDeprecationWarning(methodName, info) {
@@ -853,7 +853,7 @@ See https://react.dev/link/invalid-hook-call for tips about how to debug and fix
853
853
  })();
854
854
  });
855
855
 
856
- // ../../../node_modules/.bun/react@19.2.3/node_modules/react/index.js
856
+ // ../../node_modules/.bun/react@19.2.3/node_modules/react/index.js
857
857
  var require_react = __commonJS((exports, module) => {
858
858
  var react_development = __toESM(require_react_development());
859
859
  if (false) {} else {
@@ -861,7 +861,7 @@ var require_react = __commonJS((exports, module) => {
861
861
  }
862
862
  });
863
863
 
864
- // ../../../node_modules/.bun/signal-exit@3.0.7/node_modules/signal-exit/signals.js
864
+ // ../../node_modules/.bun/signal-exit@3.0.7/node_modules/signal-exit/signals.js
865
865
  var require_signals = __commonJS((exports, module) => {
866
866
  module.exports = [
867
867
  "SIGABRT",
@@ -878,7 +878,7 @@ var require_signals = __commonJS((exports, module) => {
878
878
  }
879
879
  });
880
880
 
881
- // ../../../node_modules/.bun/signal-exit@3.0.7/node_modules/signal-exit/index.js
881
+ // ../../node_modules/.bun/signal-exit@3.0.7/node_modules/signal-exit/index.js
882
882
  var require_signal_exit = __commonJS((exports, module) => {
883
883
  var process3 = global.process;
884
884
  var processOk = function(process4) {
@@ -1031,26 +1031,26 @@ var require_signal_exit = __commonJS((exports, module) => {
1031
1031
  var processEmit;
1032
1032
  });
1033
1033
 
1034
- // ../../../node_modules/.bun/react-reconciler@0.33.0+83d5fd7b249dbeef/node_modules/react-reconciler/cjs/react-reconciler-constants.development.js
1034
+ // ../../node_modules/.bun/react-reconciler@0.33.0+83d5fd7b249dbeef/node_modules/react-reconciler/cjs/react-reconciler-constants.development.js
1035
1035
  var require_react_reconciler_constants_development = __commonJS((exports) => {
1036
1036
  exports.ConcurrentRoot = 1, exports.ContinuousEventPriority = 8, exports.DefaultEventPriority = 32, exports.DiscreteEventPriority = 2, exports.IdleEventPriority = 268435456, exports.LegacyRoot = 0, exports.NoEventPriority = 0;
1037
1037
  });
1038
1038
 
1039
- // ../../../node_modules/.bun/react-reconciler@0.33.0+83d5fd7b249dbeef/node_modules/react-reconciler/constants.js
1039
+ // ../../node_modules/.bun/react-reconciler@0.33.0+83d5fd7b249dbeef/node_modules/react-reconciler/constants.js
1040
1040
  var require_constants = __commonJS((exports, module) => {
1041
1041
  if (false) {} else {
1042
1042
  module.exports = require_react_reconciler_constants_development();
1043
1043
  }
1044
1044
  });
1045
1045
 
1046
- // ../../../node_modules/.bun/emoji-regex@10.6.0/node_modules/emoji-regex/index.js
1046
+ // ../../node_modules/.bun/emoji-regex@10.6.0/node_modules/emoji-regex/index.js
1047
1047
  var require_emoji_regex = __commonJS((exports, module) => {
1048
1048
  module.exports = () => {
1049
1049
  return /[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26D3\uFE0F?(?:\u200D\uD83D\uDCA5)?|\u26F9(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF43\uDF45-\uDF4A\uDF4C-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDF44(?:\u200D\uD83D\uDFEB)?|\uDF4B(?:\u200D\uD83D\uDFE9)?|\uDFC3(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E-\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4\uDEB5](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE41\uDE43\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED8\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC26(?:\u200D(?:\u2B1B|\uD83D\uDD25))?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFC-\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFB-\uDFFE])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFB-\uDFFE])))?))?|\uDD75(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?|\uDE42(?:\u200D[\u2194\u2195]\uFE0F?)?|\uDEB6(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3C-\uDD3E\uDDB8\uDDB9\uDDCD\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE8A\uDE8E-\uDEC2\uDEC6\uDEC8\uDECD-\uDEDC\uDEDF-\uDEEA\uDEEF]|\uDDCE(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1|\uDDD1\u200D\uD83E\uDDD2(?:\u200D\uD83E\uDDD2)?|\uDDD2(?:\u200D\uD83E\uDDD2)?))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g;
1050
1050
  };
1051
1051
  });
1052
1052
 
1053
- // ../../../node_modules/.bun/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.development.js
1053
+ // ../../node_modules/.bun/scheduler@0.27.0/node_modules/scheduler/cjs/scheduler.development.js
1054
1054
  var require_scheduler_development = __commonJS((exports) => {
1055
1055
  (function() {
1056
1056
  function performWorkUntilDeadline() {
@@ -1305,7 +1305,7 @@ var require_scheduler_development = __commonJS((exports) => {
1305
1305
  })();
1306
1306
  });
1307
1307
 
1308
- // ../../../node_modules/.bun/scheduler@0.27.0/node_modules/scheduler/index.js
1308
+ // ../../node_modules/.bun/scheduler@0.27.0/node_modules/scheduler/index.js
1309
1309
  var require_scheduler = __commonJS((exports, module) => {
1310
1310
  var scheduler_development = __toESM(require_scheduler_development());
1311
1311
  if (false) {} else {
@@ -1313,7 +1313,7 @@ var require_scheduler = __commonJS((exports, module) => {
1313
1313
  }
1314
1314
  });
1315
1315
 
1316
- // ../../../node_modules/.bun/react-reconciler@0.33.0+83d5fd7b249dbeef/node_modules/react-reconciler/cjs/react-reconciler.development.js
1316
+ // ../../node_modules/.bun/react-reconciler@0.33.0+83d5fd7b249dbeef/node_modules/react-reconciler/cjs/react-reconciler.development.js
1317
1317
  var require_react_reconciler_development = __commonJS((exports, module) => {
1318
1318
  var React = __toESM(require_react());
1319
1319
  var Scheduler = __toESM(require_scheduler());
@@ -11763,14 +11763,14 @@ No matching component was found for:
11763
11763
  }, module.exports.default = module.exports, Object.defineProperty(module.exports, "__esModule", { value: true });
11764
11764
  });
11765
11765
 
11766
- // ../../../node_modules/.bun/react-reconciler@0.33.0+83d5fd7b249dbeef/node_modules/react-reconciler/index.js
11766
+ // ../../node_modules/.bun/react-reconciler@0.33.0+83d5fd7b249dbeef/node_modules/react-reconciler/index.js
11767
11767
  var require_react_reconciler = __commonJS((exports, module) => {
11768
11768
  if (false) {} else {
11769
11769
  module.exports = require_react_reconciler_development();
11770
11770
  }
11771
11771
  });
11772
11772
 
11773
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/constants.js
11773
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/constants.js
11774
11774
  var require_constants2 = __commonJS((exports, module) => {
11775
11775
  var BINARY_TYPES = ["nodebuffer", "arraybuffer", "fragments"];
11776
11776
  var hasBlob = typeof Blob !== "undefined";
@@ -11790,7 +11790,7 @@ var require_constants2 = __commonJS((exports, module) => {
11790
11790
  };
11791
11791
  });
11792
11792
 
11793
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/buffer-util.js
11793
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/buffer-util.js
11794
11794
  var require_buffer_util = __commonJS((exports, module) => {
11795
11795
  var { EMPTY_BUFFER } = require_constants2();
11796
11796
  var FastBuffer = Buffer[Symbol.species];
@@ -11868,7 +11868,7 @@ var require_buffer_util = __commonJS((exports, module) => {
11868
11868
  }
11869
11869
  });
11870
11870
 
11871
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/limiter.js
11871
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/limiter.js
11872
11872
  var require_limiter = __commonJS((exports, module) => {
11873
11873
  var kDone = Symbol("kDone");
11874
11874
  var kRun = Symbol("kRun");
@@ -11900,7 +11900,7 @@ var require_limiter = __commonJS((exports, module) => {
11900
11900
  module.exports = Limiter;
11901
11901
  });
11902
11902
 
11903
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/permessage-deflate.js
11903
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/permessage-deflate.js
11904
11904
  var require_permessage_deflate = __commonJS((exports, module) => {
11905
11905
  var zlib = __require("zlib");
11906
11906
  var bufferUtil = require_buffer_util();
@@ -12164,7 +12164,7 @@ var require_permessage_deflate = __commonJS((exports, module) => {
12164
12164
  }
12165
12165
  });
12166
12166
 
12167
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/validation.js
12167
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/validation.js
12168
12168
  var require_validation = __commonJS((exports, module) => {
12169
12169
  var { isUtf8 } = __require("buffer");
12170
12170
  var { hasBlob } = require_constants2();
@@ -12351,7 +12351,7 @@ var require_validation = __commonJS((exports, module) => {
12351
12351
  }
12352
12352
  });
12353
12353
 
12354
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/receiver.js
12354
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/receiver.js
12355
12355
  var require_receiver = __commonJS((exports, module) => {
12356
12356
  var { Writable } = __require("stream");
12357
12357
  var PerMessageDeflate = require_permessage_deflate();
@@ -12732,7 +12732,7 @@ var require_receiver = __commonJS((exports, module) => {
12732
12732
  module.exports = Receiver;
12733
12733
  });
12734
12734
 
12735
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/sender.js
12735
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/sender.js
12736
12736
  var require_sender = __commonJS((exports, module) => {
12737
12737
  var { Duplex } = __require("stream");
12738
12738
  var { randomFillSync } = __require("crypto");
@@ -13086,7 +13086,7 @@ var require_sender = __commonJS((exports, module) => {
13086
13086
  }
13087
13087
  });
13088
13088
 
13089
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/event-target.js
13089
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/event-target.js
13090
13090
  var require_event_target = __commonJS((exports, module) => {
13091
13091
  var { kForOnEventAttribute, kListener } = require_constants2();
13092
13092
  var kCode = Symbol("kCode");
@@ -13237,7 +13237,7 @@ var require_event_target = __commonJS((exports, module) => {
13237
13237
  }
13238
13238
  });
13239
13239
 
13240
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/extension.js
13240
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/extension.js
13241
13241
  var require_extension = __commonJS((exports, module) => {
13242
13242
  var { tokenChars } = require_validation();
13243
13243
  function push(dest, name, elem) {
@@ -13402,7 +13402,7 @@ var require_extension = __commonJS((exports, module) => {
13402
13402
  module.exports = { format, parse };
13403
13403
  });
13404
13404
 
13405
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/websocket.js
13405
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/websocket.js
13406
13406
  var require_websocket = __commonJS((exports, module) => {
13407
13407
  var EventEmitter = __require("events");
13408
13408
  var https = __require("https");
@@ -14164,7 +14164,7 @@ var require_websocket = __commonJS((exports, module) => {
14164
14164
  }
14165
14165
  });
14166
14166
 
14167
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/stream.js
14167
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/stream.js
14168
14168
  var require_stream = __commonJS((exports, module) => {
14169
14169
  var WebSocket = require_websocket();
14170
14170
  var { Duplex } = __require("stream");
@@ -14267,7 +14267,7 @@ var require_stream = __commonJS((exports, module) => {
14267
14267
  module.exports = createWebSocketStream;
14268
14268
  });
14269
14269
 
14270
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/subprotocol.js
14270
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/subprotocol.js
14271
14271
  var require_subprotocol = __commonJS((exports, module) => {
14272
14272
  var { tokenChars } = require_validation();
14273
14273
  function parse(header) {
@@ -14312,7 +14312,7 @@ var require_subprotocol = __commonJS((exports, module) => {
14312
14312
  module.exports = { parse };
14313
14313
  });
14314
14314
 
14315
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/websocket-server.js
14315
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/lib/websocket-server.js
14316
14316
  var require_websocket_server = __commonJS((exports, module) => {
14317
14317
  var EventEmitter = __require("events");
14318
14318
  var http = __require("http");
@@ -14614,7 +14614,7 @@ var require_websocket_server = __commonJS((exports, module) => {
14614
14614
  }
14615
14615
  });
14616
14616
 
14617
- // ../../../node_modules/.bun/ws@8.19.0/node_modules/ws/wrapper.mjs
14617
+ // ../../node_modules/.bun/ws@8.19.0/node_modules/ws/wrapper.mjs
14618
14618
  var import_stream, import_receiver, import_sender, import_websocket, import_websocket_server, wrapper_default;
14619
14619
  var init_wrapper = __esm(() => {
14620
14620
  import_stream = __toESM(require_stream(), 1);
@@ -14625,7 +14625,7 @@ var init_wrapper = __esm(() => {
14625
14625
  wrapper_default = import_websocket.default;
14626
14626
  });
14627
14627
 
14628
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/devtools-window-polyfill.js
14628
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/devtools-window-polyfill.js
14629
14629
  var customGlobal;
14630
14630
  var init_devtools_window_polyfill = __esm(() => {
14631
14631
  init_wrapper();
@@ -14678,7 +14678,7 @@ var init_devtools_window_polyfill = __esm(() => {
14678
14678
  ];
14679
14679
  });
14680
14680
 
14681
- // ../../../node_modules/.bun/react-devtools-core@6.1.5/node_modules/react-devtools-core/dist/backend.js
14681
+ // ../../node_modules/.bun/react-devtools-core@6.1.5/node_modules/react-devtools-core/dist/backend.js
14682
14682
  var require_backend = __commonJS((exports, module) => {
14683
14683
  (function webpackUniversalModuleDefinition(root, factory) {
14684
14684
  if (typeof exports === "object" && typeof module === "object")
@@ -28724,7 +28724,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
28724
28724
  });
28725
28725
  });
28726
28726
 
28727
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/devtools.js
28727
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/devtools.js
28728
28728
  var exports_devtools = {};
28729
28729
  var import_react_devtools_core;
28730
28730
  var init_devtools = __esm(() => {
@@ -28734,7 +28734,7 @@ var init_devtools = __esm(() => {
28734
28734
  import_react_devtools_core.default.connectToDevTools();
28735
28735
  });
28736
28736
 
28737
- // ../../../node_modules/.bun/cli-boxes@3.0.0/node_modules/cli-boxes/boxes.json
28737
+ // ../../node_modules/.bun/cli-boxes@3.0.0/node_modules/cli-boxes/boxes.json
28738
28738
  var require_boxes = __commonJS((exports, module) => {
28739
28739
  module.exports = {
28740
28740
  single: {
@@ -28820,14 +28820,14 @@ var require_boxes = __commonJS((exports, module) => {
28820
28820
  };
28821
28821
  });
28822
28822
 
28823
- // ../../../node_modules/.bun/cli-boxes@3.0.0/node_modules/cli-boxes/index.js
28823
+ // ../../node_modules/.bun/cli-boxes@3.0.0/node_modules/cli-boxes/index.js
28824
28824
  var require_cli_boxes = __commonJS((exports, module) => {
28825
28825
  var cliBoxes = require_boxes();
28826
28826
  module.exports = cliBoxes;
28827
28827
  module.exports.default = cliBoxes;
28828
28828
  });
28829
28829
 
28830
- // ../../../node_modules/.bun/mimic-fn@2.1.0/node_modules/mimic-fn/index.js
28830
+ // ../../node_modules/.bun/mimic-fn@2.1.0/node_modules/mimic-fn/index.js
28831
28831
  var require_mimic_fn = __commonJS((exports, module) => {
28832
28832
  var mimicFn = (to, from) => {
28833
28833
  for (const prop of Reflect.ownKeys(from)) {
@@ -28839,7 +28839,7 @@ var require_mimic_fn = __commonJS((exports, module) => {
28839
28839
  module.exports.default = mimicFn;
28840
28840
  });
28841
28841
 
28842
- // ../../../node_modules/.bun/onetime@5.1.2/node_modules/onetime/index.js
28842
+ // ../../node_modules/.bun/onetime@5.1.2/node_modules/onetime/index.js
28843
28843
  var require_onetime = __commonJS((exports, module) => {
28844
28844
  var mimicFn = require_mimic_fn();
28845
28845
  var calledFunctions = new WeakMap;
@@ -28874,7 +28874,7 @@ var require_onetime = __commonJS((exports, module) => {
28874
28874
  };
28875
28875
  });
28876
28876
 
28877
- // ../../../node_modules/.bun/escape-string-regexp@2.0.0/node_modules/escape-string-regexp/index.js
28877
+ // ../../node_modules/.bun/escape-string-regexp@2.0.0/node_modules/escape-string-regexp/index.js
28878
28878
  var require_escape_string_regexp = __commonJS((exports, module) => {
28879
28879
  var matchOperatorsRegex = /[|\\{}()[\]^$+*?.-]/g;
28880
28880
  module.exports = (string) => {
@@ -28885,7 +28885,7 @@ var require_escape_string_regexp = __commonJS((exports, module) => {
28885
28885
  };
28886
28886
  });
28887
28887
 
28888
- // ../../../node_modules/.bun/stack-utils@2.0.6/node_modules/stack-utils/index.js
28888
+ // ../../node_modules/.bun/stack-utils@2.0.6/node_modules/stack-utils/index.js
28889
28889
  var require_stack_utils = __commonJS((exports, module) => {
28890
28890
  var escapeStringRegexp = require_escape_string_regexp();
28891
28891
  var cwd = typeof process === "object" && process && typeof process.cwd === "function" ? process.cwd() : ".";
@@ -29123,7 +29123,7 @@ var require_stack_utils = __commonJS((exports, module) => {
29123
29123
  module.exports = StackUtils;
29124
29124
  });
29125
29125
 
29126
- // ../../../node_modules/.bun/react@19.2.3/node_modules/react/index.js
29126
+ // ../../node_modules/.bun/react@19.2.3/node_modules/react/index.js
29127
29127
  var require_react2 = __commonJS((exports, module) => {
29128
29128
  var react_development = __toESM(require_react_development());
29129
29129
  if (false) {} else {
@@ -29131,7 +29131,7 @@ var require_react2 = __commonJS((exports, module) => {
29131
29131
  }
29132
29132
  });
29133
29133
 
29134
- // ../../../node_modules/.bun/react@19.2.3/node_modules/react/cjs/react-jsx-dev-runtime.development.js
29134
+ // ../../node_modules/.bun/react@19.2.3/node_modules/react/cjs/react-jsx-dev-runtime.development.js
29135
29135
  var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
29136
29136
  var React10 = __toESM(require_react());
29137
29137
  (function() {
@@ -29346,7 +29346,7 @@ React keys must be passed directly to JSX without using spread:
29346
29346
  })();
29347
29347
  });
29348
29348
 
29349
- // ../../../node_modules/.bun/react@19.2.3/node_modules/react/jsx-dev-runtime.js
29349
+ // ../../node_modules/.bun/react@19.2.3/node_modules/react/jsx-dev-runtime.js
29350
29350
  var require_jsx_dev_runtime = __commonJS((exports, module) => {
29351
29351
  var react_jsx_dev_runtime_development = __toESM(require_react_jsx_dev_runtime_development());
29352
29352
  if (false) {} else {
@@ -29354,19 +29354,15 @@ var require_jsx_dev_runtime = __commonJS((exports, module) => {
29354
29354
  }
29355
29355
  });
29356
29356
 
29357
- // src/index.ts
29358
- import { dirname as dirname5 } from "path";
29359
- var {spawnSync } = globalThis.Bun;
29360
-
29361
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render.js
29357
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render.js
29362
29358
  import { Stream } from "node:stream";
29363
29359
  import process12 from "node:process";
29364
29360
 
29365
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/ink.js
29361
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/ink.js
29366
29362
  var import_react13 = __toESM(require_react(), 1);
29367
29363
  import process11 from "node:process";
29368
29364
 
29369
- // ../../../node_modules/.bun/es-toolkit@1.44.0/node_modules/es-toolkit/dist/function/debounce.mjs
29365
+ // ../../node_modules/.bun/es-toolkit@1.44.0/node_modules/es-toolkit/dist/function/debounce.mjs
29370
29366
  function debounce(func, debounceMs, { signal, edges } = {}) {
29371
29367
  let pendingThis = undefined;
29372
29368
  let pendingArgs = null;
@@ -29428,7 +29424,7 @@ function debounce(func, debounceMs, { signal, edges } = {}) {
29428
29424
  return debounced;
29429
29425
  }
29430
29426
 
29431
- // ../../../node_modules/.bun/es-toolkit@1.44.0/node_modules/es-toolkit/dist/compat/function/debounce.mjs
29427
+ // ../../node_modules/.bun/es-toolkit@1.44.0/node_modules/es-toolkit/dist/compat/function/debounce.mjs
29432
29428
  function debounce2(func, debounceMs = 0, options = {}) {
29433
29429
  if (typeof options !== "object") {
29434
29430
  options = {};
@@ -29472,7 +29468,7 @@ function debounce2(func, debounceMs = 0, options = {}) {
29472
29468
  return debounced;
29473
29469
  }
29474
29470
 
29475
- // ../../../node_modules/.bun/es-toolkit@1.44.0/node_modules/es-toolkit/dist/compat/function/throttle.mjs
29471
+ // ../../node_modules/.bun/es-toolkit@1.44.0/node_modules/es-toolkit/dist/compat/function/throttle.mjs
29476
29472
  function throttle(func, throttleMs = 0, options = {}) {
29477
29473
  const { leading = true, trailing = true } = options;
29478
29474
  return debounce2(func, throttleMs, {
@@ -29481,7 +29477,7 @@ function throttle(func, throttleMs = 0, options = {}) {
29481
29477
  trailing
29482
29478
  });
29483
29479
  }
29484
- // ../../../node_modules/.bun/ansi-escapes@7.2.0/node_modules/ansi-escapes/base.js
29480
+ // ../../node_modules/.bun/ansi-escapes@7.2.0/node_modules/ansi-escapes/base.js
29485
29481
  var exports_base = {};
29486
29482
  __export(exports_base, {
29487
29483
  setCwd: () => setCwd,
@@ -29522,7 +29518,7 @@ __export(exports_base, {
29522
29518
  import process2 from "node:process";
29523
29519
  import os from "node:os";
29524
29520
 
29525
- // ../../../node_modules/.bun/environment@1.1.0/node_modules/environment/index.js
29521
+ // ../../node_modules/.bun/environment@1.1.0/node_modules/environment/index.js
29526
29522
  var isBrowser = globalThis.window?.document !== undefined;
29527
29523
  var isNode = globalThis.process?.versions?.node !== undefined;
29528
29524
  var isBun = globalThis.process?.versions?.bun !== undefined;
@@ -29540,7 +29536,7 @@ var isLinux = platform === "Linux" || globalThis.navigator?.platform?.startsWith
29540
29536
  var isIos = platform === "iOS" || globalThis.navigator?.platform === "MacIntel" && globalThis.navigator?.maxTouchPoints > 1 || /iPad|iPhone|iPod/.test(globalThis.navigator?.platform);
29541
29537
  var isAndroid = platform === "Android" || globalThis.navigator?.platform === "Android" || globalThis.navigator?.userAgent?.includes(" Android ") === true || globalThis.process?.platform === "android";
29542
29538
 
29543
- // ../../../node_modules/.bun/ansi-escapes@7.2.0/node_modules/ansi-escapes/base.js
29539
+ // ../../node_modules/.bun/ansi-escapes@7.2.0/node_modules/ansi-escapes/base.js
29544
29540
  var ESC = "\x1B[";
29545
29541
  var OSC = "\x1B]";
29546
29542
  var BEL = "\x07";
@@ -29676,13 +29672,13 @@ var ConEmu = {
29676
29672
  setCwd: (cwd = cwdFunction()) => wrapOsc(`${OSC}9;9;${cwd}${BEL}`)
29677
29673
  };
29678
29674
  var setCwd = (cwd = cwdFunction()) => iTerm.setCwd(cwd) + ConEmu.setCwd(cwd);
29679
- // ../../../node_modules/.bun/is-in-ci@2.0.0/node_modules/is-in-ci/index.js
29675
+ // ../../node_modules/.bun/is-in-ci@2.0.0/node_modules/is-in-ci/index.js
29680
29676
  import { env } from "node:process";
29681
29677
  var check = (key) => (key in env) && env[key] !== "0" && env[key] !== "false";
29682
29678
  var isInCi = check("CI") || check("CONTINUOUS_INTEGRATION");
29683
29679
  var is_in_ci_default = isInCi;
29684
29680
 
29685
- // ../../../node_modules/.bun/auto-bind@5.0.1/node_modules/auto-bind/index.js
29681
+ // ../../node_modules/.bun/auto-bind@5.0.1/node_modules/auto-bind/index.js
29686
29682
  var getAllProperties = (object) => {
29687
29683
  const properties = new Set;
29688
29684
  do {
@@ -29715,10 +29711,10 @@ function autoBind(self2, { include, exclude } = {}) {
29715
29711
  return self2;
29716
29712
  }
29717
29713
 
29718
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/ink.js
29714
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/ink.js
29719
29715
  var import_signal_exit2 = __toESM(require_signal_exit(), 1);
29720
29716
 
29721
- // ../../../node_modules/.bun/patch-console@2.0.0/node_modules/patch-console/dist/index.js
29717
+ // ../../node_modules/.bun/patch-console@2.0.0/node_modules/patch-console/dist/index.js
29722
29718
  import { PassThrough } from "node:stream";
29723
29719
  var consoleMethods = [
29724
29720
  "assert",
@@ -29764,10 +29760,10 @@ var patchConsole = (callback) => {
29764
29760
  };
29765
29761
  var dist_default = patchConsole;
29766
29762
 
29767
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/ink.js
29763
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/ink.js
29768
29764
  var import_constants2 = __toESM(require_constants(), 1);
29769
29765
 
29770
- // ../../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/binaries/yoga-wasm-base64-esm.js
29766
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/binaries/yoga-wasm-base64-esm.js
29771
29767
  var loadYoga = (() => {
29772
29768
  var _scriptDir = import.meta.url;
29773
29769
  return function(loadYoga2) {
@@ -31072,7 +31068,7 @@ var loadYoga = (() => {
31072
31068
  })();
31073
31069
  var yoga_wasm_base64_esm_default = loadYoga;
31074
31070
 
31075
- // ../../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/generated/YGEnums.js
31071
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/generated/YGEnums.js
31076
31072
  var Align = /* @__PURE__ */ function(Align2) {
31077
31073
  Align2[Align2["Auto"] = 0] = "Auto";
31078
31074
  Align2[Align2["FlexStart"] = 1] = "FlexStart";
@@ -31275,7 +31271,7 @@ var constants = {
31275
31271
  };
31276
31272
  var YGEnums_default = constants;
31277
31273
 
31278
- // ../../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/wrapAssembly.js
31274
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/wrapAssembly.js
31279
31275
  function wrapAssembly(lib) {
31280
31276
  function patch(prototype, name, fn) {
31281
31277
  const original = prototype[name];
@@ -31377,11 +31373,11 @@ function wrapAssembly(lib) {
31377
31373
  };
31378
31374
  }
31379
31375
 
31380
- // ../../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/index.js
31376
+ // ../../node_modules/.bun/yoga-layout@3.2.1/node_modules/yoga-layout/dist/src/index.js
31381
31377
  var Yoga = wrapAssembly(await yoga_wasm_base64_esm_default());
31382
31378
  var src_default = Yoga;
31383
31379
 
31384
- // ../../../node_modules/.bun/ansi-regex@6.2.2/node_modules/ansi-regex/index.js
31380
+ // ../../node_modules/.bun/ansi-regex@6.2.2/node_modules/ansi-regex/index.js
31385
31381
  function ansiRegex({ onlyFirst = false } = {}) {
31386
31382
  const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
31387
31383
  const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
@@ -31390,7 +31386,7 @@ function ansiRegex({ onlyFirst = false } = {}) {
31390
31386
  return new RegExp(pattern, onlyFirst ? undefined : "g");
31391
31387
  }
31392
31388
 
31393
- // ../../../node_modules/.bun/strip-ansi@7.1.2/node_modules/strip-ansi/index.js
31389
+ // ../../node_modules/.bun/strip-ansi@7.1.2/node_modules/strip-ansi/index.js
31394
31390
  var regex = ansiRegex();
31395
31391
  function stripAnsi(string) {
31396
31392
  if (typeof string !== "string") {
@@ -31399,7 +31395,7 @@ function stripAnsi(string) {
31399
31395
  return string.replace(regex, "");
31400
31396
  }
31401
31397
 
31402
- // ../../../node_modules/.bun/get-east-asian-width@1.4.0/node_modules/get-east-asian-width/lookup.js
31398
+ // ../../node_modules/.bun/get-east-asian-width@1.4.0/node_modules/get-east-asian-width/lookup.js
31403
31399
  function isAmbiguous(x) {
31404
31400
  return x === 161 || x === 164 || x === 167 || x === 168 || x === 170 || x === 173 || x === 174 || x >= 176 && x <= 180 || x >= 182 && x <= 186 || x >= 188 && x <= 191 || x === 198 || x === 208 || x === 215 || x === 216 || x >= 222 && x <= 225 || x === 230 || x >= 232 && x <= 234 || x === 236 || x === 237 || x === 240 || x === 242 || x === 243 || x >= 247 && x <= 250 || x === 252 || x === 254 || x === 257 || x === 273 || x === 275 || x === 283 || x === 294 || x === 295 || x === 299 || x >= 305 && x <= 307 || x === 312 || x >= 319 && x <= 322 || x === 324 || x >= 328 && x <= 331 || x === 333 || x === 338 || x === 339 || x === 358 || x === 359 || x === 363 || x === 462 || x === 464 || x === 466 || x === 468 || x === 470 || x === 472 || x === 474 || x === 476 || x === 593 || x === 609 || x === 708 || x === 711 || x >= 713 && x <= 715 || x === 717 || x === 720 || x >= 728 && x <= 731 || x === 733 || x === 735 || x >= 768 && x <= 879 || x >= 913 && x <= 929 || x >= 931 && x <= 937 || x >= 945 && x <= 961 || x >= 963 && x <= 969 || x === 1025 || x >= 1040 && x <= 1103 || x === 1105 || x === 8208 || x >= 8211 && x <= 8214 || x === 8216 || x === 8217 || x === 8220 || x === 8221 || x >= 8224 && x <= 8226 || x >= 8228 && x <= 8231 || x === 8240 || x === 8242 || x === 8243 || x === 8245 || x === 8251 || x === 8254 || x === 8308 || x === 8319 || x >= 8321 && x <= 8324 || x === 8364 || x === 8451 || x === 8453 || x === 8457 || x === 8467 || x === 8470 || x === 8481 || x === 8482 || x === 8486 || x === 8491 || x === 8531 || x === 8532 || x >= 8539 && x <= 8542 || x >= 8544 && x <= 8555 || x >= 8560 && x <= 8569 || x === 8585 || x >= 8592 && x <= 8601 || x === 8632 || x === 8633 || x === 8658 || x === 8660 || x === 8679 || x === 8704 || x === 8706 || x === 8707 || x === 8711 || x === 8712 || x === 8715 || x === 8719 || x === 8721 || x === 8725 || x === 8730 || x >= 8733 && x <= 8736 || x === 8739 || x === 8741 || x >= 8743 && x <= 8748 || x === 8750 || x >= 8756 && x <= 8759 || x === 8764 || x === 8765 || x === 8776 || x === 8780 || x === 8786 || x === 8800 || x === 8801 || x >= 8804 && x <= 8807 || x === 8810 || x === 8811 || x === 8814 || x === 8815 || x === 8834 || x === 8835 || x === 8838 || x === 8839 || x === 8853 || x === 8857 || x === 8869 || x === 8895 || x === 8978 || x >= 9312 && x <= 9449 || x >= 9451 && x <= 9547 || x >= 9552 && x <= 9587 || x >= 9600 && x <= 9615 || x >= 9618 && x <= 9621 || x === 9632 || x === 9633 || x >= 9635 && x <= 9641 || x === 9650 || x === 9651 || x === 9654 || x === 9655 || x === 9660 || x === 9661 || x === 9664 || x === 9665 || x >= 9670 && x <= 9672 || x === 9675 || x >= 9678 && x <= 9681 || x >= 9698 && x <= 9701 || x === 9711 || x === 9733 || x === 9734 || x === 9737 || x === 9742 || x === 9743 || x === 9756 || x === 9758 || x === 9792 || x === 9794 || x === 9824 || x === 9825 || x >= 9827 && x <= 9829 || x >= 9831 && x <= 9834 || x === 9836 || x === 9837 || x === 9839 || x === 9886 || x === 9887 || x === 9919 || x >= 9926 && x <= 9933 || x >= 9935 && x <= 9939 || x >= 9941 && x <= 9953 || x === 9955 || x === 9960 || x === 9961 || x >= 9963 && x <= 9969 || x === 9972 || x >= 9974 && x <= 9977 || x === 9979 || x === 9980 || x === 9982 || x === 9983 || x === 10045 || x >= 10102 && x <= 10111 || x >= 11094 && x <= 11097 || x >= 12872 && x <= 12879 || x >= 57344 && x <= 63743 || x >= 65024 && x <= 65039 || x === 65533 || x >= 127232 && x <= 127242 || x >= 127248 && x <= 127277 || x >= 127280 && x <= 127337 || x >= 127344 && x <= 127373 || x === 127375 || x === 127376 || x >= 127387 && x <= 127404 || x >= 917760 && x <= 917999 || x >= 983040 && x <= 1048573 || x >= 1048576 && x <= 1114109;
31405
31401
  }
@@ -31410,7 +31406,7 @@ function isWide(x) {
31410
31406
  return x >= 4352 && x <= 4447 || x === 8986 || x === 8987 || x === 9001 || x === 9002 || x >= 9193 && x <= 9196 || x === 9200 || x === 9203 || x === 9725 || x === 9726 || x === 9748 || x === 9749 || x >= 9776 && x <= 9783 || x >= 9800 && x <= 9811 || x === 9855 || x >= 9866 && x <= 9871 || x === 9875 || x === 9889 || x === 9898 || x === 9899 || x === 9917 || x === 9918 || x === 9924 || x === 9925 || x === 9934 || x === 9940 || x === 9962 || x === 9970 || x === 9971 || x === 9973 || x === 9978 || x === 9981 || x === 9989 || x === 9994 || x === 9995 || x === 10024 || x === 10060 || x === 10062 || x >= 10067 && x <= 10069 || x === 10071 || x >= 10133 && x <= 10135 || x === 10160 || x === 10175 || x === 11035 || x === 11036 || x === 11088 || x === 11093 || x >= 11904 && x <= 11929 || x >= 11931 && x <= 12019 || x >= 12032 && x <= 12245 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12353 && x <= 12438 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12773 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 42124 || x >= 42128 && x <= 42182 || x >= 43360 && x <= 43388 || x >= 44032 && x <= 55203 || x >= 63744 && x <= 64255 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 94176 && x <= 94180 || x >= 94192 && x <= 94198 || x >= 94208 && x <= 101589 || x >= 101631 && x <= 101662 || x >= 101760 && x <= 101874 || x >= 110576 && x <= 110579 || x >= 110581 && x <= 110587 || x === 110589 || x === 110590 || x >= 110592 && x <= 110882 || x === 110898 || x >= 110928 && x <= 110930 || x === 110933 || x >= 110948 && x <= 110951 || x >= 110960 && x <= 111355 || x >= 119552 && x <= 119638 || x >= 119648 && x <= 119670 || x === 126980 || x === 127183 || x === 127374 || x >= 127377 && x <= 127386 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x === 127568 || x === 127569 || x >= 127584 && x <= 127589 || x >= 127744 && x <= 127776 || x >= 127789 && x <= 127797 || x >= 127799 && x <= 127868 || x >= 127870 && x <= 127891 || x >= 127904 && x <= 127946 || x >= 127951 && x <= 127955 || x >= 127968 && x <= 127984 || x === 127988 || x >= 127992 && x <= 128062 || x === 128064 || x >= 128066 && x <= 128252 || x >= 128255 && x <= 128317 || x >= 128331 && x <= 128334 || x >= 128336 && x <= 128359 || x === 128378 || x === 128405 || x === 128406 || x === 128420 || x >= 128507 && x <= 128591 || x >= 128640 && x <= 128709 || x === 128716 || x >= 128720 && x <= 128722 || x >= 128725 && x <= 128728 || x >= 128732 && x <= 128735 || x === 128747 || x === 128748 || x >= 128756 && x <= 128764 || x >= 128992 && x <= 129003 || x === 129008 || x >= 129292 && x <= 129338 || x >= 129340 && x <= 129349 || x >= 129351 && x <= 129535 || x >= 129648 && x <= 129660 || x >= 129664 && x <= 129674 || x >= 129678 && x <= 129734 || x === 129736 || x >= 129741 && x <= 129756 || x >= 129759 && x <= 129770 || x >= 129775 && x <= 129784 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
31411
31407
  }
31412
31408
 
31413
- // ../../../node_modules/.bun/get-east-asian-width@1.4.0/node_modules/get-east-asian-width/index.js
31409
+ // ../../node_modules/.bun/get-east-asian-width@1.4.0/node_modules/get-east-asian-width/index.js
31414
31410
  function validate(codePoint) {
31415
31411
  if (!Number.isSafeInteger(codePoint)) {
31416
31412
  throw new TypeError(`Expected a code point, got \`${typeof codePoint}\`.`);
@@ -31424,7 +31420,7 @@ function eastAsianWidth(codePoint, { ambiguousAsWide = false } = {}) {
31424
31420
  return 1;
31425
31421
  }
31426
31422
 
31427
- // ../../../node_modules/.bun/string-width@7.2.0/node_modules/string-width/index.js
31423
+ // ../../node_modules/.bun/string-width@7.2.0/node_modules/string-width/index.js
31428
31424
  var import_emoji_regex = __toESM(require_emoji_regex(), 1);
31429
31425
  var segmenter = new Intl.Segmenter;
31430
31426
  var defaultIgnorableCodePointRegex = /^\p{Default_Ignorable_Code_Point}$/u;
@@ -31473,7 +31469,7 @@ function stringWidth(string, options = {}) {
31473
31469
  return width;
31474
31470
  }
31475
31471
 
31476
- // ../../../node_modules/.bun/ansi-styles@6.2.3/node_modules/ansi-styles/index.js
31472
+ // ../../node_modules/.bun/ansi-styles@6.2.3/node_modules/ansi-styles/index.js
31477
31473
  var ANSI_BACKGROUND_OFFSET = 10;
31478
31474
  var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
31479
31475
  var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
@@ -31650,7 +31646,7 @@ function assembleStyles() {
31650
31646
  var ansiStyles = assembleStyles();
31651
31647
  var ansi_styles_default = ansiStyles;
31652
31648
 
31653
- // ../../../node_modules/.bun/wrap-ansi@9.0.2/node_modules/wrap-ansi/index.js
31649
+ // ../../node_modules/.bun/wrap-ansi@9.0.2/node_modules/wrap-ansi/index.js
31654
31650
  var ESCAPES = new Set([
31655
31651
  "\x1B",
31656
31652
  "›"
@@ -31812,13 +31808,13 @@ function wrapAnsi(string, columns, options) {
31812
31808
  `);
31813
31809
  }
31814
31810
 
31815
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/reconciler.js
31811
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/reconciler.js
31816
31812
  var import_react_reconciler = __toESM(require_react_reconciler(), 1);
31817
31813
  var import_constants = __toESM(require_constants(), 1);
31818
31814
  import process3 from "node:process";
31819
31815
  var import_react = __toESM(require_react(), 1);
31820
31816
 
31821
- // ../../../node_modules/.bun/widest-line@5.0.0/node_modules/widest-line/index.js
31817
+ // ../../node_modules/.bun/widest-line@5.0.0/node_modules/widest-line/index.js
31822
31818
  function widestLine(string) {
31823
31819
  let lineWidth = 0;
31824
31820
  for (const line of string.split(`
@@ -31828,7 +31824,7 @@ function widestLine(string) {
31828
31824
  return lineWidth;
31829
31825
  }
31830
31826
 
31831
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/measure-text.js
31827
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/measure-text.js
31832
31828
  var cache = new Map;
31833
31829
  var measureText = (text) => {
31834
31830
  if (text.length === 0) {
@@ -31850,7 +31846,7 @@ var measureText = (text) => {
31850
31846
  };
31851
31847
  var measure_text_default = measureText;
31852
31848
 
31853
- // ../../../node_modules/.bun/is-fullwidth-code-point@5.1.0/node_modules/is-fullwidth-code-point/index.js
31849
+ // ../../node_modules/.bun/is-fullwidth-code-point@5.1.0/node_modules/is-fullwidth-code-point/index.js
31854
31850
  function isFullwidthCodePoint(codePoint) {
31855
31851
  if (!Number.isInteger(codePoint)) {
31856
31852
  return false;
@@ -31858,7 +31854,7 @@ function isFullwidthCodePoint(codePoint) {
31858
31854
  return isFullWidth(codePoint) || isWide(codePoint);
31859
31855
  }
31860
31856
 
31861
- // ../../../node_modules/.bun/slice-ansi@7.1.2/node_modules/slice-ansi/index.js
31857
+ // ../../node_modules/.bun/slice-ansi@7.1.2/node_modules/slice-ansi/index.js
31862
31858
  var ESCAPES2 = new Set([27, 155]);
31863
31859
  var CODE_POINT_0 = "0".codePointAt(0);
31864
31860
  var CODE_POINT_9 = "9".codePointAt(0);
@@ -31989,7 +31985,7 @@ function sliceAnsi(string, start, end) {
31989
31985
  return returnValue;
31990
31986
  }
31991
31987
 
31992
- // ../../../node_modules/.bun/string-width@8.1.0/node_modules/string-width/index.js
31988
+ // ../../node_modules/.bun/string-width@8.1.0/node_modules/string-width/index.js
31993
31989
  var segmenter2 = new Intl.Segmenter;
31994
31990
  var zeroWidthClusterRegex = /^(?:\p{Default_Ignorable_Code_Point}|\p{Control}|\p{Mark}|\p{Surrogate})+$/v;
31995
31991
  var leadingNonPrintingRegex = /^[\p{Default_Ignorable_Code_Point}\p{Control}\p{Format}\p{Mark}\p{Surrogate}]+/v;
@@ -32043,7 +32039,7 @@ function stringWidth2(input, options = {}) {
32043
32039
  return width;
32044
32040
  }
32045
32041
 
32046
- // ../../../node_modules/.bun/cli-truncate@5.1.1/node_modules/cli-truncate/index.js
32042
+ // ../../node_modules/.bun/cli-truncate@5.1.1/node_modules/cli-truncate/index.js
32047
32043
  function getIndexOfNearestSpace(string, wantedIndex, shouldSearchRight) {
32048
32044
  if (string.charAt(wantedIndex) === " ") {
32049
32045
  return wantedIndex;
@@ -32169,7 +32165,7 @@ function cliTruncate(text, columns, options = {}) {
32169
32165
  throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${position}`);
32170
32166
  }
32171
32167
 
32172
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/wrap-text.js
32168
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/wrap-text.js
32173
32169
  var cache2 = {};
32174
32170
  var wrapText = (text, maxWidth, wrapType) => {
32175
32171
  const cacheKey = text + String(maxWidth) + String(wrapType);
@@ -32199,7 +32195,7 @@ var wrapText = (text, maxWidth, wrapType) => {
32199
32195
  };
32200
32196
  var wrap_text_default = wrapText;
32201
32197
 
32202
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/squash-text-nodes.js
32198
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/squash-text-nodes.js
32203
32199
  var squashTextNodes = (node) => {
32204
32200
  let text = "";
32205
32201
  for (let index = 0;index < node.childNodes.length; index++) {
@@ -32224,7 +32220,7 @@ var squashTextNodes = (node) => {
32224
32220
  };
32225
32221
  var squash_text_nodes_default = squashTextNodes;
32226
32222
 
32227
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/dom.js
32223
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/dom.js
32228
32224
  var createNode = (nodeName) => {
32229
32225
  const node = {
32230
32226
  nodeName,
@@ -32339,7 +32335,7 @@ var setTextNodeValue = (node, text) => {
32339
32335
  markNodeAsDirty(node);
32340
32336
  };
32341
32337
 
32342
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/styles.js
32338
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/styles.js
32343
32339
  var applyPositionStyles = (node, style) => {
32344
32340
  if ("position" in style) {
32345
32341
  node.setPositionType(style.position === "absolute" ? src_default.POSITION_TYPE_ABSOLUTE : src_default.POSITION_TYPE_RELATIVE);
@@ -32560,7 +32556,7 @@ var styles2 = (node, style = {}) => {
32560
32556
  };
32561
32557
  var styles_default = styles2;
32562
32558
 
32563
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/reconciler.js
32559
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/reconciler.js
32564
32560
  if (process3.env["DEV"] === "true") {
32565
32561
  try {
32566
32562
  await Promise.resolve().then(() => (init_devtools(), exports_devtools));
@@ -32794,7 +32790,7 @@ var reconciler_default = import_react_reconciler.default({
32794
32790
  }
32795
32791
  });
32796
32792
 
32797
- // ../../../node_modules/.bun/indent-string@5.0.0/node_modules/indent-string/index.js
32793
+ // ../../node_modules/.bun/indent-string@5.0.0/node_modules/indent-string/index.js
32798
32794
  function indentString(string, count = 1, options = {}) {
32799
32795
  const {
32800
32796
  indent = " ",
@@ -32819,16 +32815,16 @@ function indentString(string, count = 1, options = {}) {
32819
32815
  return string.replace(regex2, indent.repeat(count));
32820
32816
  }
32821
32817
 
32822
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/get-max-width.js
32818
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/get-max-width.js
32823
32819
  var getMaxWidth = (yogaNode) => {
32824
32820
  return yogaNode.getComputedWidth() - yogaNode.getComputedPadding(src_default.EDGE_LEFT) - yogaNode.getComputedPadding(src_default.EDGE_RIGHT) - yogaNode.getComputedBorder(src_default.EDGE_LEFT) - yogaNode.getComputedBorder(src_default.EDGE_RIGHT);
32825
32821
  };
32826
32822
  var get_max_width_default = getMaxWidth;
32827
32823
 
32828
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render-border.js
32824
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render-border.js
32829
32825
  var import_cli_boxes = __toESM(require_cli_boxes(), 1);
32830
32826
 
32831
- // ../../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
32827
+ // ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/ansi-styles/index.js
32832
32828
  var ANSI_BACKGROUND_OFFSET2 = 10;
32833
32829
  var wrapAnsi162 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
32834
32830
  var wrapAnsi2562 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
@@ -33005,7 +33001,7 @@ function assembleStyles2() {
33005
33001
  var ansiStyles2 = assembleStyles2();
33006
33002
  var ansi_styles_default2 = ansiStyles2;
33007
33003
 
33008
- // ../../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js
33004
+ // ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/vendor/supports-color/index.js
33009
33005
  import process4 from "node:process";
33010
33006
  import os2 from "node:os";
33011
33007
  import tty from "node:tty";
@@ -33137,7 +33133,7 @@ var supportsColor = {
33137
33133
  };
33138
33134
  var supports_color_default = supportsColor;
33139
33135
 
33140
- // ../../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/utilities.js
33136
+ // ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/utilities.js
33141
33137
  function stringReplaceAll(string, substring, replacer) {
33142
33138
  let index = string.indexOf(substring);
33143
33139
  if (index === -1) {
@@ -33170,7 +33166,7 @@ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
33170
33166
  return returnValue;
33171
33167
  }
33172
33168
 
33173
- // ../../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/index.js
33169
+ // ../../node_modules/.bun/chalk@5.6.2/node_modules/chalk/source/index.js
33174
33170
  var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
33175
33171
  var GENERATOR = Symbol("GENERATOR");
33176
33172
  var STYLER = Symbol("STYLER");
@@ -33317,7 +33313,7 @@ var chalk = createChalk();
33317
33313
  var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
33318
33314
  var source_default = chalk;
33319
33315
 
33320
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/colorize.js
33316
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/colorize.js
33321
33317
  var rgbRegex = /^rgb\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/;
33322
33318
  var ansiRegex2 = /^ansi256\(\s?(\d+)\s?\)$/;
33323
33319
  var isNamedColor = (color) => {
@@ -33359,7 +33355,7 @@ var colorize = (str, color, type) => {
33359
33355
  };
33360
33356
  var colorize_default = colorize;
33361
33357
 
33362
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render-border.js
33358
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render-border.js
33363
33359
  var renderBorder = (x, y, node, output) => {
33364
33360
  if (node.style.borderStyle) {
33365
33361
  const width = node.yogaNode.getComputedWidth();
@@ -33422,7 +33418,7 @@ var renderBorder = (x, y, node, output) => {
33422
33418
  };
33423
33419
  var render_border_default = renderBorder;
33424
33420
 
33425
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render-background.js
33421
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render-background.js
33426
33422
  var renderBackground = (x, y, node, output) => {
33427
33423
  if (!node.style.backgroundColor) {
33428
33424
  return;
@@ -33445,7 +33441,7 @@ var renderBackground = (x, y, node, output) => {
33445
33441
  };
33446
33442
  var render_background_default = renderBackground;
33447
33443
 
33448
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render-node-to-output.js
33444
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render-node-to-output.js
33449
33445
  var applyPaddingToText = (node, text) => {
33450
33446
  const yogaNode = node.childNodes[0]?.yogaNode;
33451
33447
  if (yogaNode) {
@@ -33555,7 +33551,7 @@ var renderNodeToOutput = (node, output, options) => {
33555
33551
  };
33556
33552
  var render_node_to_output_default = renderNodeToOutput;
33557
33553
 
33558
- // ../../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js
33554
+ // ../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js
33559
33555
  var ESCAPES3 = new Set([27, 155]);
33560
33556
  var CSI = "[".codePointAt(0);
33561
33557
  var OSC2 = "]".codePointAt(0);
@@ -33597,7 +33593,7 @@ function ansiCodesToString(codes) {
33597
33593
  function isIntensityCode(code) {
33598
33594
  return code.code === ansi_styles_default.bold.open || code.code === ansi_styles_default.dim.open;
33599
33595
  }
33600
- // ../../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/reduce.js
33596
+ // ../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/reduce.js
33601
33597
  function reduceAnsiCodes2(codes) {
33602
33598
  return reduceAnsiCodesIncremental([], codes);
33603
33599
  }
@@ -33622,7 +33618,7 @@ function reduceAnsiCodesIncremental(codes, newCodes) {
33622
33618
  return ret;
33623
33619
  }
33624
33620
 
33625
- // ../../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/undo.js
33621
+ // ../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/undo.js
33626
33622
  function undoAnsiCodes2(codes) {
33627
33623
  return reduceAnsiCodes2(codes).reverse().map((code) => ({
33628
33624
  ...code,
@@ -33630,7 +33626,7 @@ function undoAnsiCodes2(codes) {
33630
33626
  }));
33631
33627
  }
33632
33628
 
33633
- // ../../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/diff.js
33629
+ // ../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/diff.js
33634
33630
  function diffAnsiCodes(from, to) {
33635
33631
  const endCodesInTo = new Set(to.map((code) => code.endCode));
33636
33632
  const startCodesInTo = new Set(to.map((code) => code.code));
@@ -33645,7 +33641,7 @@ function diffAnsiCodes(from, to) {
33645
33641
  ...to.filter((code) => !startCodesInFrom.has(code.code))
33646
33642
  ];
33647
33643
  }
33648
- // ../../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/styledChars.js
33644
+ // ../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/styledChars.js
33649
33645
  function styledCharsFromTokens(tokens) {
33650
33646
  let codes = [];
33651
33647
  const ret = [];
@@ -33677,7 +33673,7 @@ function styledCharsToString(chars) {
33677
33673
  }
33678
33674
  return ret;
33679
33675
  }
33680
- // ../../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/tokenize.js
33676
+ // ../../node_modules/.bun/@alcalzone+ansi-tokenize@0.2.3/node_modules/@alcalzone/ansi-tokenize/build/tokenize.js
33681
33677
  function parseLinkCode(string, offset) {
33682
33678
  string = string.slice(offset);
33683
33679
  for (let index = 1;index < linkStartCodePrefixCharCodes.length; index++) {
@@ -33788,7 +33784,7 @@ function tokenize2(str, endChar = Number.POSITIVE_INFINITY) {
33788
33784
  }
33789
33785
  return ret;
33790
33786
  }
33791
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/output.js
33787
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/output.js
33792
33788
  class Output {
33793
33789
  width;
33794
33790
  height;
@@ -33928,7 +33924,7 @@ class Output {
33928
33924
  }
33929
33925
  }
33930
33926
 
33931
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/renderer.js
33927
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/renderer.js
33932
33928
  var renderer = (node, isScreenReaderEnabled) => {
33933
33929
  if (node.yogaNode) {
33934
33930
  if (isScreenReaderEnabled) {
@@ -33983,10 +33979,10 @@ var renderer = (node, isScreenReaderEnabled) => {
33983
33979
  };
33984
33980
  var renderer_default = renderer;
33985
33981
 
33986
- // ../../../node_modules/.bun/cli-cursor@4.0.0/node_modules/cli-cursor/index.js
33982
+ // ../../node_modules/.bun/cli-cursor@4.0.0/node_modules/cli-cursor/index.js
33987
33983
  import process6 from "node:process";
33988
33984
 
33989
- // ../../../node_modules/.bun/restore-cursor@4.0.0/node_modules/restore-cursor/index.js
33985
+ // ../../node_modules/.bun/restore-cursor@4.0.0/node_modules/restore-cursor/index.js
33990
33986
  var import_onetime = __toESM(require_onetime(), 1);
33991
33987
  var import_signal_exit = __toESM(require_signal_exit(), 1);
33992
33988
  import process5 from "node:process";
@@ -33997,7 +33993,7 @@ var restoreCursor = import_onetime.default(() => {
33997
33993
  });
33998
33994
  var restore_cursor_default = restoreCursor;
33999
33995
 
34000
- // ../../../node_modules/.bun/cli-cursor@4.0.0/node_modules/cli-cursor/index.js
33996
+ // ../../node_modules/.bun/cli-cursor@4.0.0/node_modules/cli-cursor/index.js
34001
33997
  var isHidden = false;
34002
33998
  var cliCursor = {};
34003
33999
  cliCursor.show = (writableStream = process6.stderr) => {
@@ -34027,7 +34023,7 @@ cliCursor.toggle = (force, writableStream) => {
34027
34023
  };
34028
34024
  var cli_cursor_default = cliCursor;
34029
34025
 
34030
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/log-update.js
34026
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/log-update.js
34031
34027
  var createStandard = (stream, { showCursor = false } = {}) => {
34032
34028
  let previousLineCount = 0;
34033
34029
  let previousOutput = "";
@@ -34144,16 +34140,16 @@ var create = (stream, { showCursor = false, incremental = false } = {}) => {
34144
34140
  var logUpdate = { create };
34145
34141
  var log_update_default = logUpdate;
34146
34142
 
34147
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/instances.js
34143
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/instances.js
34148
34144
  var instances = new WeakMap;
34149
34145
  var instances_default = instances;
34150
34146
 
34151
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/App.js
34147
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/App.js
34152
34148
  var import_react12 = __toESM(require_react(), 1);
34153
34149
  import { EventEmitter as EventEmitter2 } from "node:events";
34154
34150
  import process10 from "node:process";
34155
34151
 
34156
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/AppContext.js
34152
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/AppContext.js
34157
34153
  var import_react2 = __toESM(require_react(), 1);
34158
34154
  var AppContext = import_react2.createContext({
34159
34155
  exit() {}
@@ -34161,7 +34157,7 @@ var AppContext = import_react2.createContext({
34161
34157
  AppContext.displayName = "InternalAppContext";
34162
34158
  var AppContext_default = AppContext;
34163
34159
 
34164
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/StdinContext.js
34160
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/StdinContext.js
34165
34161
  var import_react3 = __toESM(require_react(), 1);
34166
34162
  import { EventEmitter } from "node:events";
34167
34163
  import process7 from "node:process";
@@ -34175,7 +34171,7 @@ var StdinContext = import_react3.createContext({
34175
34171
  StdinContext.displayName = "InternalStdinContext";
34176
34172
  var StdinContext_default = StdinContext;
34177
34173
 
34178
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/StdoutContext.js
34174
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/StdoutContext.js
34179
34175
  var import_react4 = __toESM(require_react(), 1);
34180
34176
  import process8 from "node:process";
34181
34177
  var StdoutContext = import_react4.createContext({
@@ -34185,7 +34181,7 @@ var StdoutContext = import_react4.createContext({
34185
34181
  StdoutContext.displayName = "InternalStdoutContext";
34186
34182
  var StdoutContext_default = StdoutContext;
34187
34183
 
34188
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/StderrContext.js
34184
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/StderrContext.js
34189
34185
  var import_react5 = __toESM(require_react(), 1);
34190
34186
  import process9 from "node:process";
34191
34187
  var StderrContext = import_react5.createContext({
@@ -34195,7 +34191,7 @@ var StderrContext = import_react5.createContext({
34195
34191
  StderrContext.displayName = "InternalStderrContext";
34196
34192
  var StderrContext_default = StderrContext;
34197
34193
 
34198
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/FocusContext.js
34194
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/FocusContext.js
34199
34195
  var import_react6 = __toESM(require_react(), 1);
34200
34196
  var FocusContext = import_react6.createContext({
34201
34197
  activeId: undefined,
@@ -34212,19 +34208,19 @@ var FocusContext = import_react6.createContext({
34212
34208
  FocusContext.displayName = "InternalFocusContext";
34213
34209
  var FocusContext_default = FocusContext;
34214
34210
 
34215
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/ErrorOverview.js
34211
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/ErrorOverview.js
34216
34212
  var import_react11 = __toESM(require_react(), 1);
34217
34213
  var import_stack_utils = __toESM(require_stack_utils(), 1);
34218
34214
  import * as fs from "node:fs";
34219
34215
  import { cwd } from "node:process";
34220
34216
 
34221
- // ../../../node_modules/.bun/convert-to-spaces@2.0.1/node_modules/convert-to-spaces/dist/index.js
34217
+ // ../../node_modules/.bun/convert-to-spaces@2.0.1/node_modules/convert-to-spaces/dist/index.js
34222
34218
  var convertToSpaces = (input, spaces = 2) => {
34223
34219
  return input.replace(/^\t+/gm, ($1) => " ".repeat($1.length * spaces));
34224
34220
  };
34225
34221
  var dist_default2 = convertToSpaces;
34226
34222
 
34227
- // ../../../node_modules/.bun/code-excerpt@4.0.0/node_modules/code-excerpt/dist/index.js
34223
+ // ../../node_modules/.bun/code-excerpt@4.0.0/node_modules/code-excerpt/dist/index.js
34228
34224
  var generateLineNumbers = (line, around) => {
34229
34225
  const lineNumbers = [];
34230
34226
  const min = line - around;
@@ -34250,20 +34246,20 @@ var codeExcerpt = (source, line, options = {}) => {
34250
34246
  };
34251
34247
  var dist_default3 = codeExcerpt;
34252
34248
 
34253
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Box.js
34249
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Box.js
34254
34250
  var import_react9 = __toESM(require_react(), 1);
34255
34251
 
34256
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/AccessibilityContext.js
34252
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/AccessibilityContext.js
34257
34253
  var import_react7 = __toESM(require_react(), 1);
34258
34254
  var accessibilityContext = import_react7.createContext({
34259
34255
  isScreenReaderEnabled: false
34260
34256
  });
34261
34257
 
34262
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/BackgroundContext.js
34258
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/BackgroundContext.js
34263
34259
  var import_react8 = __toESM(require_react(), 1);
34264
34260
  var backgroundContext = import_react8.createContext(undefined);
34265
34261
 
34266
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Box.js
34262
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Box.js
34267
34263
  var Box = import_react9.forwardRef(({ children, backgroundColor, "aria-label": ariaLabel, "aria-hidden": ariaHidden, "aria-role": role, "aria-state": ariaState, ...style }, ref) => {
34268
34264
  const { isScreenReaderEnabled } = import_react9.useContext(accessibilityContext);
34269
34265
  const label = ariaLabel ? import_react9.default.createElement("ink-text", null, ariaLabel) : undefined;
@@ -34291,7 +34287,7 @@ var Box = import_react9.forwardRef(({ children, backgroundColor, "aria-label": a
34291
34287
  Box.displayName = "Box";
34292
34288
  var Box_default = Box;
34293
34289
 
34294
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Text.js
34290
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Text.js
34295
34291
  var import_react10 = __toESM(require_react(), 1);
34296
34292
  function Text({ color, backgroundColor, dimColor = false, bold = false, italic = false, underline = false, strikethrough = false, inverse = false, wrap = "wrap", children, "aria-label": ariaLabel, "aria-hidden": ariaHidden = false }) {
34297
34293
  const { isScreenReaderEnabled } = import_react10.useContext(accessibilityContext);
@@ -34334,7 +34330,7 @@ function Text({ color, backgroundColor, dimColor = false, bold = false, italic =
34334
34330
  return import_react10.default.createElement("ink-text", { style: { flexGrow: 0, flexShrink: 1, flexDirection: "row", textWrap: wrap }, internal_transform: transform }, isScreenReaderEnabled && ariaLabel ? ariaLabel : children);
34335
34331
  }
34336
34332
 
34337
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/ErrorOverview.js
34333
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/ErrorOverview.js
34338
34334
  var cleanupPath = (path) => {
34339
34335
  return path?.replace(`file://${cwd()}/`, "");
34340
34336
  };
@@ -34368,7 +34364,7 @@ function ErrorOverview({ error }) {
34368
34364
  })));
34369
34365
  }
34370
34366
 
34371
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/App.js
34367
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/App.js
34372
34368
  var tab = "\t";
34373
34369
  var shiftTab = "\x1B[Z";
34374
34370
  var escape = "\x1B";
@@ -34613,7 +34609,7 @@ Read about how to prevent this error on https://github.com/vadimdemedes/ink/#isr
34613
34609
  };
34614
34610
  }
34615
34611
 
34616
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/ink.js
34612
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/ink.js
34617
34613
  var noop = () => {};
34618
34614
 
34619
34615
  class Ink {
@@ -34864,7 +34860,7 @@ class Ink {
34864
34860
  }
34865
34861
  }
34866
34862
 
34867
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render.js
34863
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/render.js
34868
34864
  var render = (node, options) => {
34869
34865
  const inkOptions = {
34870
34866
  stdout: process12.stdout,
@@ -34907,18 +34903,18 @@ var getInstance = (stdout, createInstance) => {
34907
34903
  }
34908
34904
  return instance;
34909
34905
  };
34910
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Static.js
34906
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Static.js
34911
34907
  var import_react14 = __toESM(require_react(), 1);
34912
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Transform.js
34908
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Transform.js
34913
34909
  var import_react15 = __toESM(require_react(), 1);
34914
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Newline.js
34910
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Newline.js
34915
34911
  var import_react16 = __toESM(require_react(), 1);
34916
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Spacer.js
34912
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/components/Spacer.js
34917
34913
  var import_react17 = __toESM(require_react(), 1);
34918
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-input.js
34914
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-input.js
34919
34915
  var import_react19 = __toESM(require_react(), 1);
34920
34916
 
34921
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/parse-keypress.js
34917
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/parse-keypress.js
34922
34918
  import { Buffer as Buffer2 } from "node:buffer";
34923
34919
  var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/;
34924
34920
  var fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
@@ -35100,12 +35096,12 @@ var parseKeypress = (s = "") => {
35100
35096
  };
35101
35097
  var parse_keypress_default = parseKeypress;
35102
35098
 
35103
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-stdin.js
35099
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-stdin.js
35104
35100
  var import_react18 = __toESM(require_react(), 1);
35105
35101
  var useStdin = () => import_react18.useContext(StdinContext_default);
35106
35102
  var use_stdin_default = useStdin;
35107
35103
 
35108
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-input.js
35104
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-input.js
35109
35105
  var useInput = (inputHandler, options = {}) => {
35110
35106
  const { stdin, setRawMode, internal_exitOnCtrlC, internal_eventEmitter } = use_stdin_default();
35111
35107
  import_react19.useEffect(() => {
@@ -35164,19 +35160,19 @@ var useInput = (inputHandler, options = {}) => {
35164
35160
  }, [options.isActive, stdin, internal_exitOnCtrlC, inputHandler]);
35165
35161
  };
35166
35162
  var use_input_default = useInput;
35167
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-app.js
35163
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-app.js
35168
35164
  var import_react20 = __toESM(require_react(), 1);
35169
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-stdout.js
35165
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-stdout.js
35170
35166
  var import_react21 = __toESM(require_react(), 1);
35171
35167
  var useStdout = () => import_react21.useContext(StdoutContext_default);
35172
35168
  var use_stdout_default = useStdout;
35173
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-stderr.js
35169
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-stderr.js
35174
35170
  var import_react22 = __toESM(require_react(), 1);
35175
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-focus.js
35171
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-focus.js
35176
35172
  var import_react23 = __toESM(require_react(), 1);
35177
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-focus-manager.js
35173
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-focus-manager.js
35178
35174
  var import_react24 = __toESM(require_react(), 1);
35179
- // ../../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-is-screen-reader-enabled.js
35175
+ // ../../node_modules/.bun/ink@6.6.0+e2d5e1b7eef6ce72/node_modules/ink/build/hooks/use-is-screen-reader-enabled.js
35180
35176
  var import_react25 = __toESM(require_react(), 1);
35181
35177
  // src/index.ts
35182
35178
  var import_react29 = __toESM(require_react2(), 1);
@@ -35187,8 +35183,7 @@ var import_react28 = __toESM(require_react(), 1);
35187
35183
  // package.json
35188
35184
  var package_default = {
35189
35185
  name: "schub",
35190
- version: "0.1.0",
35191
- private: true,
35186
+ version: "0.1.2",
35192
35187
  type: "module",
35193
35188
  bin: {
35194
35189
  schub: "./src/index.ts"
@@ -35196,10 +35191,12 @@ var package_default = {
35196
35191
  files: [
35197
35192
  "dist",
35198
35193
  "src",
35194
+ "skills",
35199
35195
  "templates"
35200
35196
  ],
35201
35197
  scripts: {
35202
35198
  schub: "bun ./src/index.ts",
35199
+ prepublishOnly: "npm run build",
35203
35200
  build: "bun build ./src/index.ts --outdir dist --target node",
35204
35201
  lint: "bunx @biomejs/biome lint .",
35205
35202
  format: "bunx @biomejs/biome format --write .",
@@ -35219,21 +35216,49 @@ var package_default = {
35219
35216
  }
35220
35217
  };
35221
35218
 
35219
+ // src/clipboard.ts
35220
+ import { spawnSync } from "node:child_process";
35221
+ var copyToClipboard = (value) => {
35222
+ spawnSync("pbcopy", [], { input: value });
35223
+ };
35224
+
35222
35225
  // src/components/PlanView.tsx
35226
+ import { dirname as dirname2 } from "node:path";
35223
35227
  var import_react26 = __toESM(require_react(), 1);
35224
35228
 
35225
35229
  // src/features/tasks/constants.ts
35226
35230
  var TASK_STATUSES = ["backlog", "ready", "wip", "blocked", "done", "archived"];
35227
35231
  // src/features/tasks/create.ts
35228
35232
  import { existsSync as existsSync2, mkdirSync, readdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
35229
- import { join } from "node:path";
35233
+ import { join as join2 } from "node:path";
35230
35234
  import { fileURLToPath } from "node:url";
35231
- var TASK_TEMPLATE_PATH = fileURLToPath(new URL("../../../templates/create-tasks/task-template.md", import.meta.url));
35232
- var readTaskTemplate = () => {
35235
+
35236
+ // src/templates.ts
35237
+ import { statSync } from "node:fs";
35238
+ import { join } from "node:path";
35239
+ var isFile = (path) => {
35240
+ try {
35241
+ return statSync(path).isFile();
35242
+ } catch {
35243
+ return false;
35244
+ }
35245
+ };
35246
+ var resolveTemplatePath = (schubDir, templatePath, bundledPath) => {
35247
+ const localPath = join(schubDir, "templates", templatePath);
35248
+ if (isFile(localPath)) {
35249
+ return localPath;
35250
+ }
35251
+ return bundledPath;
35252
+ };
35253
+
35254
+ // src/features/tasks/create.ts
35255
+ var BUNDLED_TASK_TEMPLATE_PATH = fileURLToPath(new URL("../../../templates/create-tasks/task-template.md", import.meta.url));
35256
+ var readTaskTemplate = (schubDir) => {
35257
+ const templatePath = resolveTemplatePath(schubDir, join2("create-tasks", "task-template.md"), BUNDLED_TASK_TEMPLATE_PATH);
35233
35258
  try {
35234
- return readFileSync2(TASK_TEMPLATE_PATH, "utf8");
35259
+ return readFileSync2(templatePath, "utf8");
35235
35260
  } catch {
35236
- throw new Error(`[ERROR] Template not found: ${TASK_TEMPLATE_PATH}`);
35261
+ throw new Error(`[ERROR] Template not found: ${templatePath}`);
35237
35262
  }
35238
35263
  };
35239
35264
  var createTask = (schubDir, options) => {
@@ -35254,8 +35279,8 @@ var createTask = (schubDir, options) => {
35254
35279
  if (!titles.length) {
35255
35280
  throw new Error("Provide at least one --title.");
35256
35281
  }
35257
- const changeDir = join(schubDir, "changes", normalizedChangeId);
35258
- const proposalPath = join(changeDir, "proposal.md");
35282
+ const changeDir = join2(schubDir, "changes", normalizedChangeId);
35283
+ const proposalPath = join2(changeDir, "proposal.md");
35259
35284
  if (!existsSync2(proposalPath)) {
35260
35285
  throw new Error(`Required change files missing:
35261
35286
  - ${proposalPath}
@@ -35272,7 +35297,7 @@ Add a '**Status**: Accepted' line before scaffolding tasks.`);
35272
35297
  throw new Error(`Proposal status is '${proposalStatus}' in ${proposalPath}.
35273
35298
  Mark the proposal as Accepted before scaffolding tasks.`);
35274
35299
  }
35275
- const tasksRoot = join(schubDir, "tasks");
35300
+ const tasksRoot = join2(schubDir, "tasks");
35276
35301
  const existingNumbers = new Set;
35277
35302
  if (existsSync2(tasksRoot)) {
35278
35303
  const scan = (dir) => {
@@ -35281,7 +35306,7 @@ Mark the proposal as Accepted before scaffolding tasks.`);
35281
35306
  const entries = readdirSync(dir, { withFileTypes: true });
35282
35307
  for (const entry of entries) {
35283
35308
  if (entry.isDirectory()) {
35284
- scan(join(dir, entry.name));
35309
+ scan(join2(dir, entry.name));
35285
35310
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
35286
35311
  const m = entry.name.match(/(?:^|-)T(\d{3})(?:_[^.]+)?\.md$/);
35287
35312
  if (m)
@@ -35292,9 +35317,9 @@ Mark the proposal as Accepted before scaffolding tasks.`);
35292
35317
  scan(tasksRoot);
35293
35318
  }
35294
35319
  let nextNumber = existingNumbers.size > 0 ? Math.max(...existingNumbers) + 1 : 1;
35295
- const statusDir = join(tasksRoot, status);
35320
+ const statusDir = join2(tasksRoot, status);
35296
35321
  mkdirSync(statusDir, { recursive: true });
35297
- const template = readTaskTemplate();
35322
+ const template = readTaskTemplate(schubDir);
35298
35323
  const createdPaths = [];
35299
35324
  for (const title of titles) {
35300
35325
  const taskId = `T${nextNumber.toString().padStart(3, "0")}`;
@@ -35302,7 +35327,7 @@ Mark the proposal as Accepted before scaffolding tasks.`);
35302
35327
  if (!slug)
35303
35328
  slug = "task";
35304
35329
  const filename = `${taskId}_${slug}.md`;
35305
- const taskPath = join(statusDir, filename);
35330
+ const taskPath = join2(statusDir, filename);
35306
35331
  const rendered = template.replace("{{TASK_ID}}", taskId).replace("{{TASK_TITLE}}", title).replace("{{CHANGE_ID}}", normalizedChangeId);
35307
35332
  if (existsSync2(taskPath) && !options.overwrite) {
35308
35333
  throw new Error(`Refusing to overwrite existing file: ${taskPath}`);
@@ -35314,8 +35339,8 @@ Mark the proposal as Accepted before scaffolding tasks.`);
35314
35339
  return createdPaths;
35315
35340
  };
35316
35341
  // src/features/tasks/filesystem.ts
35317
- import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync } from "node:fs";
35318
- import { dirname, join as join2, relative, resolve } from "node:path";
35342
+ import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
35343
+ import { dirname, join as join3, relative, resolve } from "node:path";
35319
35344
 
35320
35345
  // src/features/tasks/sorting.ts
35321
35346
  var taskNumber = (id) => {
@@ -35334,7 +35359,7 @@ var compareTasks = (left, right) => compareTaskIds(left.id, right.id);
35334
35359
  // src/features/tasks/filesystem.ts
35335
35360
  var isDirectory = (path) => {
35336
35361
  try {
35337
- return statSync(path).isDirectory();
35362
+ return statSync2(path).isDirectory();
35338
35363
  } catch {
35339
35364
  return false;
35340
35365
  }
@@ -35342,7 +35367,7 @@ var isDirectory = (path) => {
35342
35367
  var findSchubRoot = (startDir = process.cwd()) => {
35343
35368
  let current = resolve(startDir);
35344
35369
  while (true) {
35345
- const candidate = join2(current, ".schub");
35370
+ const candidate = join3(current, ".schub");
35346
35371
  if (existsSync3(candidate) && isDirectory(candidate)) {
35347
35372
  return candidate;
35348
35373
  }
@@ -35366,6 +35391,42 @@ var parseTaskFilename = (fileName) => {
35366
35391
  const titleSlug = baseName.slice(underscoreIndex + 1);
35367
35392
  return { id, title: titleSlug.replace(/-/g, " ") };
35368
35393
  };
35394
+ var parseChecklistCounts = (content) => {
35395
+ const lines = content.split(/\r?\n/);
35396
+ let inSteps = false;
35397
+ let checklistTotal = 0;
35398
+ let checklistRemaining = 0;
35399
+ for (const line of lines) {
35400
+ const headingMatch = line.match(/^##\s+(.*)$/);
35401
+ if (headingMatch) {
35402
+ const heading = headingMatch[1].trim().toLowerCase();
35403
+ if (heading === "steps") {
35404
+ inSteps = true;
35405
+ } else if (inSteps) {
35406
+ break;
35407
+ }
35408
+ continue;
35409
+ }
35410
+ if (!inSteps) {
35411
+ continue;
35412
+ }
35413
+ const checklistMatch = line.match(/^\s*-\s+\[( |x|X)\]/);
35414
+ if (!checklistMatch) {
35415
+ continue;
35416
+ }
35417
+ checklistTotal += 1;
35418
+ if (checklistMatch[1].toLowerCase() !== "x") {
35419
+ checklistRemaining += 1;
35420
+ }
35421
+ }
35422
+ if (checklistTotal === 0) {
35423
+ return null;
35424
+ }
35425
+ return {
35426
+ checklistRemaining,
35427
+ checklistTotal
35428
+ };
35429
+ };
35369
35430
  var parseTaskFile = (filePath, fallback) => {
35370
35431
  let content = "";
35371
35432
  try {
@@ -35373,9 +35434,6 @@ var parseTaskFile = (filePath, fallback) => {
35373
35434
  } catch {
35374
35435
  return { ...fallback, dependsOn: [] };
35375
35436
  }
35376
- const headerMatch = content.match(/^#\s*Task:\s*(\S+)\s+(.+)$/m);
35377
- const id = headerMatch?.[1] ?? fallback.id;
35378
- const title = headerMatch?.[2]?.trim() ?? fallback.title;
35379
35437
  const changeIdMatch = content.match(/^\*\*Change ID\*\*:\s*\[?`?([^\]`]+)`?]?/m);
35380
35438
  const changeId = changeIdMatch?.[1]?.trim();
35381
35439
  const dependsMatch = content.match(/^\*\*Depends on\*\*:\s*(.+)$/m);
@@ -35389,10 +35447,17 @@ var parseTaskFile = (filePath, fallback) => {
35389
35447
  }
35390
35448
  }
35391
35449
  }
35392
- return { id, title, dependsOn, changeId };
35450
+ const checklistCounts = parseChecklistCounts(content);
35451
+ return {
35452
+ id: fallback.id,
35453
+ title: fallback.title,
35454
+ dependsOn,
35455
+ changeId,
35456
+ ...checklistCounts ?? {}
35457
+ };
35393
35458
  };
35394
35459
  var listTasks = (schubDir, statuses = TASK_STATUSES) => {
35395
- const tasksRoot = join2(schubDir, "tasks");
35460
+ const tasksRoot = join3(schubDir, "tasks");
35396
35461
  if (!existsSync3(tasksRoot) || !isDirectory(tasksRoot)) {
35397
35462
  return [];
35398
35463
  }
@@ -35403,7 +35468,7 @@ var listTasks = (schubDir, statuses = TASK_STATUSES) => {
35403
35468
  if (!allowed.has(status)) {
35404
35469
  continue;
35405
35470
  }
35406
- const statusDir = join2(tasksRoot, status);
35471
+ const statusDir = join3(tasksRoot, status);
35407
35472
  if (!existsSync3(statusDir) || !isDirectory(statusDir)) {
35408
35473
  continue;
35409
35474
  }
@@ -35416,19 +35481,22 @@ var listTasks = (schubDir, statuses = TASK_STATUSES) => {
35416
35481
  if (!parsed) {
35417
35482
  continue;
35418
35483
  }
35419
- const filePath = join2(statusDir, entry.name);
35484
+ const filePath = join3(statusDir, entry.name);
35485
+ const parsedFile = parseTaskFile(filePath, parsed);
35420
35486
  tasks.push({
35421
35487
  id: parsed.id,
35422
35488
  title: parsed.title,
35423
35489
  status,
35424
- path: relative(repoRoot, filePath)
35490
+ path: relative(repoRoot, filePath),
35491
+ checklistRemaining: parsedFile.checklistRemaining,
35492
+ checklistTotal: parsedFile.checklistTotal
35425
35493
  });
35426
35494
  }
35427
35495
  }
35428
35496
  return tasks.sort(compareTasks);
35429
35497
  };
35430
35498
  var loadTaskDependencies = (schubDir, statuses = TASK_STATUSES) => {
35431
- const tasksRoot = join2(schubDir, "tasks");
35499
+ const tasksRoot = join3(schubDir, "tasks");
35432
35500
  if (!existsSync3(tasksRoot) || !isDirectory(tasksRoot)) {
35433
35501
  return [];
35434
35502
  }
@@ -35439,7 +35507,7 @@ var loadTaskDependencies = (schubDir, statuses = TASK_STATUSES) => {
35439
35507
  if (!allowed.has(status)) {
35440
35508
  continue;
35441
35509
  }
35442
- const statusDir = join2(tasksRoot, status);
35510
+ const statusDir = join3(tasksRoot, status);
35443
35511
  if (!existsSync3(statusDir) || !isDirectory(statusDir)) {
35444
35512
  continue;
35445
35513
  }
@@ -35452,16 +35520,18 @@ var loadTaskDependencies = (schubDir, statuses = TASK_STATUSES) => {
35452
35520
  if (!parsed) {
35453
35521
  continue;
35454
35522
  }
35455
- const filePath = join2(statusDir, entry.name);
35523
+ const filePath = join3(statusDir, entry.name);
35456
35524
  const parsedFile = parseTaskFile(filePath, parsed);
35457
35525
  const dependsOn = parsedFile.dependsOn.sort(compareTaskIds);
35458
35526
  tasks.push({
35459
- id: parsedFile.id,
35460
- title: parsedFile.title,
35527
+ id: parsed.id,
35528
+ title: parsed.title,
35461
35529
  status,
35462
35530
  path: relative(repoRoot, filePath),
35463
35531
  dependsOn,
35464
- changeId: parsedFile.changeId
35532
+ changeId: parsedFile.changeId,
35533
+ checklistRemaining: parsedFile.checklistRemaining,
35534
+ checklistTotal: parsedFile.checklistTotal
35465
35535
  });
35466
35536
  }
35467
35537
  }
@@ -35534,32 +35604,83 @@ var renderTaskGraphLines = (graph) => {
35534
35604
  });
35535
35605
  return lines;
35536
35606
  };
35607
+ // src/ide.ts
35608
+ import { spawn } from "node:child_process";
35609
+ import { resolve as resolve2 } from "node:path";
35610
+ var openInVsCode = (repoRoot, relativePath) => {
35611
+ const targetPath = resolve2(repoRoot, relativePath);
35612
+ spawn("code", ["-g", targetPath], { stdio: "ignore" }).unref();
35613
+ };
35614
+
35537
35615
  // src/components/PlanView.tsx
35538
35616
  var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
35539
35617
  var PLAN_TASK_STATUSES = ["backlog", "ready", "wip", "blocked"];
35540
35618
  var READY_TASK_STATUSES = ["backlog", "ready"];
35541
- function PlanView() {
35542
- const schubDir = import_react26.default.useMemo(() => findSchubRoot(), []);
35543
- const planData = import_react26.default.useMemo(() => {
35619
+ var DEFAULT_REFRESH_INTERVAL_MS = 1000;
35620
+ var buildPlanData = (schubDir) => {
35621
+ if (!schubDir) {
35622
+ return { visibleTasks: [], readyTasks: [], graphLines: [] };
35623
+ }
35624
+ const allTasks = loadTaskDependencies(schubDir);
35625
+ const visibleTasks = allTasks.filter((task) => PLAN_TASK_STATUSES.includes(task.status));
35626
+ const tasksById = new Map(allTasks.map((task) => [task.id, task]));
35627
+ const readyTasks = visibleTasks.filter((task) => {
35628
+ if (!READY_TASK_STATUSES.includes(task.status)) {
35629
+ return false;
35630
+ }
35631
+ return task.dependsOn.every((dependencyId) => tasksById.get(dependencyId)?.status === "done");
35632
+ });
35633
+ if (visibleTasks.length === 0) {
35634
+ return { visibleTasks, readyTasks, graphLines: [] };
35635
+ }
35636
+ const graph = buildTaskGraph(visibleTasks);
35637
+ const graphLines = renderTaskGraphLines(graph);
35638
+ return { visibleTasks, readyTasks, graphLines };
35639
+ };
35640
+ function PlanView({ refreshIntervalMs = DEFAULT_REFRESH_INTERVAL_MS, onCopyId }) {
35641
+ const schubDir = findSchubRoot();
35642
+ const [, setRefreshTick] = import_react26.default.useState(0);
35643
+ const planData = buildPlanData(schubDir);
35644
+ const [selection, setSelection] = import_react26.default.useState(0);
35645
+ const totalReadyTasks = planData.readyTasks.length;
35646
+ const repoRoot = schubDir ? dirname2(schubDir) : "";
35647
+ import_react26.default.useEffect(() => {
35544
35648
  if (!schubDir) {
35545
- return { visibleTasks: [], readyTasks: [], graphLines: [] };
35649
+ return;
35546
35650
  }
35547
- const allTasks = loadTaskDependencies(schubDir);
35548
- const visibleTasks = allTasks.filter((task) => PLAN_TASK_STATUSES.includes(task.status));
35549
- const tasksById = new Map(allTasks.map((task) => [task.id, task]));
35550
- const readyTasks = visibleTasks.filter((task) => {
35551
- if (!READY_TASK_STATUSES.includes(task.status)) {
35552
- return false;
35553
- }
35554
- return task.dependsOn.every((dependencyId) => tasksById.get(dependencyId)?.status === "done");
35555
- });
35556
- if (visibleTasks.length === 0) {
35557
- return { visibleTasks, readyTasks, graphLines: [] };
35651
+ const interval = setInterval(() => {
35652
+ setRefreshTick((current) => current + 1);
35653
+ }, refreshIntervalMs);
35654
+ return () => {
35655
+ clearInterval(interval);
35656
+ };
35657
+ }, [refreshIntervalMs, schubDir]);
35658
+ import_react26.default.useEffect(() => {
35659
+ if (totalReadyTasks === 0) {
35660
+ setSelection(0);
35661
+ return;
35662
+ }
35663
+ setSelection((current) => Math.min(current, totalReadyTasks - 1));
35664
+ }, [totalReadyTasks]);
35665
+ use_input_default((input, key) => {
35666
+ if (totalReadyTasks === 0) {
35667
+ return;
35668
+ }
35669
+ if (key.downArrow) {
35670
+ setSelection((current) => Math.min(current + 1, totalReadyTasks - 1));
35671
+ }
35672
+ if (key.upArrow) {
35673
+ setSelection((current) => Math.max(current - 1, 0));
35674
+ }
35675
+ if (input === "o") {
35676
+ const selectedTask = planData.readyTasks[selection];
35677
+ openInVsCode(repoRoot, selectedTask.path);
35558
35678
  }
35559
- const graph = buildTaskGraph(visibleTasks);
35560
- const graphLines = renderTaskGraphLines(graph);
35561
- return { visibleTasks, readyTasks, graphLines };
35562
- }, [schubDir]);
35679
+ if (input === "c") {
35680
+ const selectedTask = planData.readyTasks[selection];
35681
+ onCopyId(selectedTask.id);
35682
+ }
35683
+ });
35563
35684
  if (!schubDir) {
35564
35685
  return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
35565
35686
  flexDirection: "column",
@@ -35595,21 +35716,35 @@ function PlanView() {
35595
35716
  planData.readyTasks.length === 0 ? /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
35596
35717
  color: "gray",
35597
35718
  children: "No tasks ready for implementation."
35598
- }, undefined, false, undefined, this) : planData.readyTasks.map((task) => /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
35599
- children: [
35600
- /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
35601
- color: "white",
35602
- children: `${task.id}`
35603
- }, undefined, false, undefined, this),
35604
- /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
35605
- color: "gray",
35606
- children: [
35607
- " ",
35608
- trimTaskTitle(task.title)
35609
- ]
35610
- }, undefined, true, undefined, this)
35611
- ]
35612
- }, task.id, true, undefined, this))
35719
+ }, undefined, false, undefined, this) : planData.readyTasks.map((task, index) => {
35720
+ const selected = index === selection;
35721
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
35722
+ marginLeft: 1,
35723
+ children: [
35724
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
35725
+ color: selected ? "blue" : "gray",
35726
+ children: selected ? "" : " "
35727
+ }, undefined, false, undefined, this),
35728
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
35729
+ marginLeft: 1,
35730
+ children: [
35731
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
35732
+ color: "white",
35733
+ bold: selected,
35734
+ children: task.id
35735
+ }, undefined, false, undefined, this),
35736
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
35737
+ color: "gray",
35738
+ children: [
35739
+ " ",
35740
+ trimTaskTitle(task.title)
35741
+ ]
35742
+ }, undefined, true, undefined, this)
35743
+ ]
35744
+ }, undefined, true, undefined, this)
35745
+ ]
35746
+ }, task.id, true, undefined, this);
35747
+ })
35613
35748
  ]
35614
35749
  }, undefined, true, undefined, this),
35615
35750
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
@@ -35635,15 +35770,49 @@ function PlanView() {
35635
35770
  }
35636
35771
 
35637
35772
  // src/components/StatusView.tsx
35773
+ import { dirname as dirname5, normalize, sep } from "node:path";
35638
35774
  var import_react27 = __toESM(require_react(), 1);
35639
35775
 
35640
35776
  // src/changes.ts
35641
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync3, readFileSync as readFileSync4, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
35642
- import { basename, dirname as dirname2, join as join3, relative as relative2, resolve as resolve2 } from "node:path";
35777
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync3, readFileSync as readFileSync4, statSync as statSync4, writeFileSync as writeFileSync2 } from "node:fs";
35778
+ import { dirname as dirname4, join as join5, relative as relative2 } from "node:path";
35643
35779
  import { fileURLToPath as fileURLToPath2 } from "node:url";
35780
+
35781
+ // src/schub-root.ts
35782
+ import { statSync as statSync3 } from "node:fs";
35783
+ import { basename, dirname as dirname3, join as join4, resolve as resolve3 } from "node:path";
35644
35784
  var isDirectory2 = (path) => {
35645
35785
  try {
35646
- return statSync2(path).isDirectory();
35786
+ return statSync3(path).isDirectory();
35787
+ } catch {
35788
+ return false;
35789
+ }
35790
+ };
35791
+ var resolveSchubRoot = (startDir = process.cwd()) => {
35792
+ const start = resolve3(startDir);
35793
+ const fallback = join4(start, ".schub");
35794
+ let current = start;
35795
+ while (true) {
35796
+ if (basename(current) === ".schub" && isDirectory2(current)) {
35797
+ return current;
35798
+ }
35799
+ const candidate = join4(current, ".schub");
35800
+ if (isDirectory2(candidate)) {
35801
+ return candidate;
35802
+ }
35803
+ const parent = dirname3(current);
35804
+ if (parent === current) {
35805
+ return fallback;
35806
+ }
35807
+ current = parent;
35808
+ }
35809
+ };
35810
+
35811
+ // src/changes.ts
35812
+ var CHANGE_ID_PATTERN = /^(?:[Cc]\d{3}_)?[a-z0-9]+(?:-[a-z0-9]+)*$/;
35813
+ var isDirectory3 = (path) => {
35814
+ try {
35815
+ return statSync4(path).isDirectory();
35647
35816
  } catch {
35648
35817
  return false;
35649
35818
  }
@@ -35656,23 +35825,79 @@ var parseProposal = (content, changeId) => {
35656
35825
  status: statusMatch?.[1]?.trim() ?? "unknown"
35657
35826
  };
35658
35827
  };
35828
+ var normalizeChangeId = (value) => {
35829
+ const trimmed = value.trim();
35830
+ const match = trimmed.match(/^([Cc])(\d{3})_(.+)$/);
35831
+ if (match) {
35832
+ return `C${match[2]}_${match[3]}`;
35833
+ }
35834
+ return trimmed;
35835
+ };
35836
+ var isValidChangeId = (value) => CHANGE_ID_PATTERN.test(value.trim());
35837
+ var readChangeSummary = (schubDir, changeId) => {
35838
+ const trimmed = changeId.trim();
35839
+ if (!trimmed) {
35840
+ throw new Error("Provide --change-id.");
35841
+ }
35842
+ if (!isValidChangeId(trimmed)) {
35843
+ throw new Error(`Invalid change-id '${changeId}'. Use kebab-case or a C-prefixed id (e.g., C001_add-user-auth).`);
35844
+ }
35845
+ const normalized = normalizeChangeId(trimmed);
35846
+ const changeDir = join5(schubDir, "changes", normalized);
35847
+ const proposalPath = join5(changeDir, "proposal.md");
35848
+ if (!existsSync4(proposalPath)) {
35849
+ throw new Error(`Required change files missing:
35850
+ - ${proposalPath}
35851
+ Create the change proposal before scaffolding docs.`);
35852
+ }
35853
+ const content = readFileSync4(proposalPath, "utf8");
35854
+ const parsed = parseProposal(content, normalized);
35855
+ return {
35856
+ changeId: normalized,
35857
+ changeTitle: parsed.title,
35858
+ changeDir,
35859
+ proposalPath
35860
+ };
35861
+ };
35862
+ var updateChangeStatus = (schubDir, changeId, status) => {
35863
+ const nextStatus = status.trim();
35864
+ if (!nextStatus) {
35865
+ throw new Error("Provide --status.");
35866
+ }
35867
+ const summary = readChangeSummary(schubDir, changeId);
35868
+ const content = readFileSync4(summary.proposalPath, "utf8");
35869
+ const statusMatch = content.match(/^\*\*Status\*\*:\s*(.+)$/m);
35870
+ const previousStatus = statusMatch?.[1]?.trim();
35871
+ if (!previousStatus) {
35872
+ throw new Error(`Proposal status not found in ${summary.proposalPath}.
35873
+ Add a '**Status**: <value>' line before updating status.`);
35874
+ }
35875
+ const updated = content.replace(/^\*\*Status\*\*:\s*(.+)$/m, `**Status**: ${nextStatus}`);
35876
+ writeFileSync2(summary.proposalPath, updated, "utf8");
35877
+ return {
35878
+ changeId: summary.changeId,
35879
+ proposalPath: summary.proposalPath,
35880
+ previousStatus,
35881
+ status: nextStatus
35882
+ };
35883
+ };
35659
35884
  var changeNumber = (id) => {
35660
35885
  const match = id.match(/\d+/);
35661
35886
  return match ? Number(match[0]) : Number.POSITIVE_INFINITY;
35662
35887
  };
35663
35888
  var listChanges = (schubDir) => {
35664
- const changesRoot = join3(schubDir, "changes");
35665
- if (!existsSync4(changesRoot) || !isDirectory2(changesRoot)) {
35889
+ const changesRoot = join5(schubDir, "changes");
35890
+ if (!existsSync4(changesRoot) || !isDirectory3(changesRoot)) {
35666
35891
  return [];
35667
35892
  }
35668
- const repoRoot = dirname2(schubDir);
35893
+ const repoRoot = dirname4(schubDir);
35669
35894
  const entries = readdirSync3(changesRoot, { withFileTypes: true });
35670
35895
  const changes = [];
35671
35896
  for (const entry of entries) {
35672
35897
  if (!entry.isDirectory()) {
35673
35898
  continue;
35674
35899
  }
35675
- const proposalPath = join3(changesRoot, entry.name, "proposal.md");
35900
+ const proposalPath = join5(changesRoot, entry.name, "proposal.md");
35676
35901
  if (!existsSync4(proposalPath)) {
35677
35902
  continue;
35678
35903
  }
@@ -35693,10 +35918,123 @@ var listChanges = (schubDir) => {
35693
35918
  return a.id.localeCompare(b.id);
35694
35919
  });
35695
35920
  };
35696
- var PROPOSAL_TEMPLATE_PATH = fileURLToPath2(new URL("../templates/create-proposal/proposal-template.md", import.meta.url));
35921
+ var slugify = (value) => {
35922
+ let slug = value.trim().toLowerCase();
35923
+ slug = slug.replace(/[^a-z0-9]+/g, "-");
35924
+ slug = slug.replace(/-{2,}/g, "-");
35925
+ return slug.replace(/^-|-$/g, "");
35926
+ };
35927
+ var splitPrefixedChangeId = (changeId) => {
35928
+ const match = changeId.match(/^([Cc])(\d{3})_([a-z0-9]+(?:-[a-z0-9]+)*)$/);
35929
+ if (match) {
35930
+ return { prefix: match[2], slug: match[3] };
35931
+ }
35932
+ return { prefix: null, slug: changeId };
35933
+ };
35934
+ var nextChangePrefix = (schubDir) => {
35935
+ const changesRoot = join5(schubDir, "changes");
35936
+ const archiveRoot = join5(schubDir, "archive", "changes");
35937
+ const prefixes = [];
35938
+ const scan = (root) => {
35939
+ if (!existsSync4(root) || !isDirectory3(root))
35940
+ return;
35941
+ for (const entry of readdirSync3(root, { withFileTypes: true })) {
35942
+ if (!entry.isDirectory()) {
35943
+ continue;
35944
+ }
35945
+ const match = entry.name.match(/^[Cc](\d{3})_/);
35946
+ if (match) {
35947
+ prefixes.push(Number.parseInt(match[1], 10));
35948
+ }
35949
+ }
35950
+ };
35951
+ scan(changesRoot);
35952
+ scan(archiveRoot);
35953
+ const next = prefixes.length > 0 ? Math.max(...prefixes) + 1 : 1;
35954
+ return next.toString().padStart(3, "0");
35955
+ };
35956
+ var CHANGE_PREFIX = "C";
35957
+ var BUNDLED_PROPOSAL_TEMPLATE_PATH = fileURLToPath2(new URL("../templates/create-proposal/proposal-template.md", import.meta.url));
35958
+ var readProposalTemplate = (schubDir) => {
35959
+ const templatePath = resolveTemplatePath(schubDir, join5("create-proposal", "proposal-template.md"), BUNDLED_PROPOSAL_TEMPLATE_PATH);
35960
+ try {
35961
+ return readFileSync4(templatePath, "utf8");
35962
+ } catch {
35963
+ throw new Error(`[ERROR] Template not found: ${templatePath}`);
35964
+ }
35965
+ };
35966
+ var isValidSlug = (value) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value);
35967
+ var changeExists = (schubDir, changeId) => {
35968
+ const active = join5(schubDir, "changes", changeId);
35969
+ if (existsSync4(active)) {
35970
+ return true;
35971
+ }
35972
+ const archiveRoot = join5(schubDir, "archive", "changes");
35973
+ if (!existsSync4(archiveRoot) || !isDirectory3(archiveRoot)) {
35974
+ return false;
35975
+ }
35976
+ for (const entry of readdirSync3(archiveRoot, { withFileTypes: true })) {
35977
+ if (entry.isDirectory() && entry.name.includes(changeId)) {
35978
+ return true;
35979
+ }
35980
+ }
35981
+ return false;
35982
+ };
35983
+ var resolveChangeRoot = resolveSchubRoot;
35984
+ var createChange = (schubDir, options) => {
35985
+ let changeId = (options.changeId || "").trim();
35986
+ let title = (options.title || "").trim();
35987
+ const input = (options.input || "").trim();
35988
+ if (!changeId) {
35989
+ if (!title) {
35990
+ throw new Error("Provide --change-id or --title.");
35991
+ }
35992
+ changeId = slugify(title);
35993
+ if (!changeId) {
35994
+ throw new Error("Unable to derive change-id from title.");
35995
+ }
35996
+ console.warn(`[WARN] Derived change-id '${changeId}' from --title. Prefer verb-led ids.`);
35997
+ }
35998
+ const originalChangeId = changeId;
35999
+ const { prefix: existingPrefix, slug } = splitPrefixedChangeId(changeId);
36000
+ if (!isValidSlug(slug)) {
36001
+ throw new Error(`Invalid change-id '${changeId}'. Use kebab-case (lowercase letters/digits and hyphens).`);
36002
+ }
36003
+ if (!existingPrefix) {
36004
+ const prefix = nextChangePrefix(schubDir);
36005
+ changeId = `${CHANGE_PREFIX}${prefix}_${slug}`;
36006
+ console.error(`[INFO] Prefixed change-id with '${CHANGE_PREFIX}${prefix}_'.`);
36007
+ } else {
36008
+ changeId = `${CHANGE_PREFIX}${existingPrefix}_${slug}`;
36009
+ if (changeId !== originalChangeId) {
36010
+ console.error(`[INFO] Normalized change-id to '${changeId}'.`);
36011
+ }
36012
+ }
36013
+ if (!title) {
36014
+ title = slug.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
36015
+ }
36016
+ const changeDir = join5(schubDir, "changes", changeId);
36017
+ const proposalPath = join5(changeDir, "proposal.md");
36018
+ if (changeExists(schubDir, changeId) && !options.overwrite) {
36019
+ throw new Error(`Change '${changeId}' already exists under ${schubDir}. Choose a unique id or pass --overwrite.`);
36020
+ }
36021
+ const template = readProposalTemplate(schubDir);
36022
+ const today = new Date().toISOString().split("T")[0];
36023
+ const rendered = template.replace("{{CHANGE_TITLE}}", title).replace("{{CHANGE_ID}}", changeId).replace("{{DATE}}", today).replace("{{INPUT}}", input || "[no input provided]").replace("{{AGENT_ROOT}}", schubDir);
36024
+ if (existsSync4(proposalPath) && !options.overwrite) {
36025
+ throw new Error(`Refusing to overwrite existing file: ${proposalPath}`);
36026
+ }
36027
+ mkdirSync2(changeDir, { recursive: true });
36028
+ writeFileSync2(proposalPath, rendered, "utf8");
36029
+ return proposalPath;
36030
+ };
35697
36031
 
35698
36032
  // src/components/StatusView.tsx
35699
36033
  var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
36034
+ var DEFAULT_REFRESH_INTERVAL_MS2 = 1000;
36035
+ var ACTIVE_TASK_STATUSES = ["blocked", "wip", "ready", "backlog"];
36036
+ var CHANGE_TASK_STATUSES = [...ACTIVE_TASK_STATUSES, "done"];
36037
+ var AUTO_MARK_STATUSES = new Set(["accepted", "wip"]);
35700
36038
  var compareText = (left, right) => left.localeCompare(right, undefined, { sensitivity: "base" });
35701
36039
  var sortByStatusThenTitle = (left, right) => {
35702
36040
  const statusCompare = compareText(left.status, right.status);
@@ -35709,67 +36047,165 @@ var sortByStatusThenTitle = (left, right) => {
35709
36047
  }
35710
36048
  return compareText(left.id, right.id);
35711
36049
  };
35712
- function StatusView() {
35713
- const schubDir = import_react27.default.useMemo(() => findSchubRoot(), []);
35714
- const { pendingReview, pendingImplementation, drafts, blocked, wip, ready, backlog } = import_react27.default.useMemo(() => {
35715
- if (!schubDir) {
35716
- return {
35717
- pendingReview: [],
35718
- pendingImplementation: [],
35719
- drafts: [],
35720
- blocked: [],
35721
- wip: [],
35722
- ready: [],
35723
- backlog: []
35724
- };
36050
+ var isTaskItem = (item) => {
36051
+ const parts = normalize(item.path).split(sep);
36052
+ return parts.includes("tasks");
36053
+ };
36054
+ var formatChangeId = (value) => {
36055
+ const match = value.match(/^([Cc]\d{3})_/);
36056
+ return match ? match[1].toUpperCase() : value;
36057
+ };
36058
+ var canAutoMarkChange = (status) => AUTO_MARK_STATUSES.has(status.trim().toLowerCase());
36059
+ var autoMarkChangesDone = (schubDir) => {
36060
+ const allTasks = loadTaskDependencies(schubDir, CHANGE_TASK_STATUSES);
36061
+ const changeTaskCounts = new Map;
36062
+ for (const task of allTasks) {
36063
+ if (!task.changeId) {
36064
+ continue;
35725
36065
  }
35726
- const allTasks = loadTaskDependencies(schubDir, ["blocked", "wip", "ready", "backlog"]);
35727
- const blockedTasks = [];
35728
- const wipTasks = [];
35729
- const readyTasks = [];
35730
- const backlogTasks = [];
35731
- const activeChangeIds = new Set;
35732
- for (const task of allTasks) {
35733
- const s = task.status.toLowerCase();
35734
- if (s === "blocked")
35735
- blockedTasks.push(task);
35736
- else if (s === "wip")
35737
- wipTasks.push(task);
35738
- else if (s === "ready")
35739
- readyTasks.push(task);
35740
- else if (s === "backlog")
35741
- backlogTasks.push(task);
35742
- if (task.changeId) {
35743
- activeChangeIds.add(task.changeId);
35744
- }
35745
- }
35746
- const allChanges = listChanges(schubDir);
35747
- const pendingReviewChanges = [];
35748
- const pendingImplementationChanges = [];
35749
- const draftChanges = [];
35750
- for (const change of allChanges) {
35751
- const normalized = change.status.toLowerCase();
35752
- if (normalized.includes("review")) {
35753
- pendingReviewChanges.push(change);
35754
- } else if (activeChangeIds.has(change.id) || normalized.includes("implementing") || normalized.includes("accepted")) {
35755
- pendingImplementationChanges.push(change);
35756
- } else if (normalized.includes("draft")) {
35757
- draftChanges.push(change);
35758
- }
36066
+ const current = changeTaskCounts.get(task.changeId) ?? { completed: 0, total: 0 };
36067
+ const completed = current.completed + (task.status === "done" ? 1 : 0);
36068
+ changeTaskCounts.set(task.changeId, { completed, total: current.total + 1 });
36069
+ }
36070
+ if (changeTaskCounts.size === 0) {
36071
+ return;
36072
+ }
36073
+ for (const change of listChanges(schubDir)) {
36074
+ const counts = changeTaskCounts.get(change.id);
36075
+ if (!counts || counts.total === 0 || counts.completed !== counts.total) {
36076
+ continue;
36077
+ }
36078
+ if (canAutoMarkChange(change.status)) {
36079
+ updateChangeStatus(schubDir, change.id, "Done");
35759
36080
  }
36081
+ }
36082
+ };
36083
+ var buildStatusData = (schubDir) => {
36084
+ if (!schubDir) {
35760
36085
  return {
35761
- pendingReview: pendingReviewChanges.sort(sortByStatusThenTitle),
35762
- pendingImplementation: pendingImplementationChanges.sort(sortByStatusThenTitle),
35763
- drafts: draftChanges.sort(sortByStatusThenTitle),
35764
- blocked: blockedTasks.sort(sortByStatusThenTitle),
35765
- wip: wipTasks.sort(sortByStatusThenTitle),
35766
- ready: readyTasks.sort(sortByStatusThenTitle),
35767
- backlog: backlogTasks.sort(sortByStatusThenTitle)
36086
+ pendingReview: [],
36087
+ pendingImplementation: [],
36088
+ pendingImplementationNoTasks: [],
36089
+ drafts: [],
36090
+ blocked: [],
36091
+ wip: [],
36092
+ ready: [],
36093
+ backlog: [],
36094
+ pendingImplementationCounts: new Map
35768
36095
  };
35769
- }, [schubDir]);
35770
- const allItems = import_react27.default.useMemo(() => [...pendingReview, ...pendingImplementation, ...drafts, ...blocked, ...wip, ...ready, ...backlog], [pendingReview, pendingImplementation, drafts, blocked, wip, ready, backlog]);
36096
+ }
36097
+ const allTasks = loadTaskDependencies(schubDir, CHANGE_TASK_STATUSES);
36098
+ const blockedTasks = [];
36099
+ const wipTasks = [];
36100
+ const readyTasks = [];
36101
+ const backlogTasks = [];
36102
+ const activeChangeIds = new Set;
36103
+ const changeTaskCounts = new Map;
36104
+ for (const task of allTasks) {
36105
+ if (task.status === "blocked")
36106
+ blockedTasks.push(task);
36107
+ else if (task.status === "wip")
36108
+ wipTasks.push(task);
36109
+ else if (task.status === "ready")
36110
+ readyTasks.push(task);
36111
+ else if (task.status === "backlog")
36112
+ backlogTasks.push(task);
36113
+ if (task.changeId && task.status !== "done") {
36114
+ activeChangeIds.add(task.changeId);
36115
+ }
36116
+ if (task.changeId) {
36117
+ const current = changeTaskCounts.get(task.changeId) ?? { completed: 0, total: 0 };
36118
+ const completed = current.completed + (task.status === "done" ? 1 : 0);
36119
+ changeTaskCounts.set(task.changeId, { completed, total: current.total + 1 });
36120
+ }
36121
+ }
36122
+ const allChanges = listChanges(schubDir);
36123
+ const pendingReviewChanges = [];
36124
+ const pendingImplementationChanges = [];
36125
+ const draftChanges = [];
36126
+ for (const change of allChanges) {
36127
+ const normalized = change.status.toLowerCase();
36128
+ if (normalized.includes("review")) {
36129
+ pendingReviewChanges.push(change);
36130
+ continue;
36131
+ }
36132
+ const counts = changeTaskCounts.get(change.id);
36133
+ const allTasksCompleted = Boolean(counts && counts.total > 0 && counts.completed === counts.total);
36134
+ if (activeChangeIds.has(change.id)) {
36135
+ pendingImplementationChanges.push(change);
36136
+ continue;
36137
+ }
36138
+ if ((normalized.includes("implementing") || normalized.includes("accepted")) && !allTasksCompleted) {
36139
+ pendingImplementationChanges.push(change);
36140
+ continue;
36141
+ }
36142
+ if (normalized.includes("draft")) {
36143
+ draftChanges.push(change);
36144
+ }
36145
+ }
36146
+ const pendingImplementationWithTasks = [];
36147
+ const pendingImplementationNoTasks = [];
36148
+ const pendingImplementationCounts = new Map;
36149
+ for (const change of pendingImplementationChanges.sort(sortByStatusThenTitle)) {
36150
+ const counts = changeTaskCounts.get(change.id);
36151
+ if (counts && counts.total > 0) {
36152
+ pendingImplementationWithTasks.push(change);
36153
+ pendingImplementationCounts.set(change.id, `${counts.completed}/${counts.total}`);
36154
+ } else {
36155
+ pendingImplementationNoTasks.push(change);
36156
+ }
36157
+ }
36158
+ return {
36159
+ pendingReview: pendingReviewChanges.sort(sortByStatusThenTitle),
36160
+ pendingImplementation: pendingImplementationWithTasks,
36161
+ pendingImplementationNoTasks,
36162
+ drafts: draftChanges.sort(sortByStatusThenTitle),
36163
+ blocked: blockedTasks.sort(sortByStatusThenTitle),
36164
+ wip: wipTasks.sort(sortByStatusThenTitle),
36165
+ ready: readyTasks.sort(sortByStatusThenTitle),
36166
+ backlog: backlogTasks.sort(sortByStatusThenTitle),
36167
+ pendingImplementationCounts
36168
+ };
36169
+ };
36170
+ function StatusView({ refreshIntervalMs = DEFAULT_REFRESH_INTERVAL_MS2, onCopyId }) {
36171
+ const schubDir = findSchubRoot();
36172
+ const [, setRefreshTick] = import_react27.default.useState(0);
36173
+ const {
36174
+ pendingReview,
36175
+ pendingImplementation,
36176
+ pendingImplementationNoTasks,
36177
+ drafts,
36178
+ blocked,
36179
+ wip,
36180
+ ready,
36181
+ backlog,
36182
+ pendingImplementationCounts
36183
+ } = buildStatusData(schubDir);
36184
+ const repoRoot = schubDir ? dirname5(schubDir) : "";
36185
+ const allItems = [
36186
+ ...pendingReview,
36187
+ ...pendingImplementation,
36188
+ ...pendingImplementationNoTasks,
36189
+ ...drafts,
36190
+ ...blocked,
36191
+ ...wip,
36192
+ ...ready,
36193
+ ...backlog
36194
+ ];
35771
36195
  const [selection, setSelection] = import_react27.default.useState(0);
35772
36196
  const totalItems = allItems.length;
36197
+ import_react27.default.useEffect(() => {
36198
+ if (!schubDir) {
36199
+ return;
36200
+ }
36201
+ const interval = setInterval(() => {
36202
+ autoMarkChangesDone(schubDir);
36203
+ setRefreshTick((current) => current + 1);
36204
+ }, refreshIntervalMs);
36205
+ return () => {
36206
+ clearInterval(interval);
36207
+ };
36208
+ }, [refreshIntervalMs, schubDir]);
35773
36209
  import_react27.default.useEffect(() => {
35774
36210
  if (totalItems === 0) {
35775
36211
  setSelection(0);
@@ -35777,7 +36213,7 @@ function StatusView() {
35777
36213
  }
35778
36214
  setSelection((current) => Math.min(current, totalItems - 1));
35779
36215
  }, [totalItems]);
35780
- use_input_default((_input, key) => {
36216
+ use_input_default((input, key) => {
35781
36217
  if (totalItems === 0) {
35782
36218
  return;
35783
36219
  }
@@ -35787,6 +36223,14 @@ function StatusView() {
35787
36223
  if (key.upArrow) {
35788
36224
  setSelection((current) => Math.max(current - 1, 0));
35789
36225
  }
36226
+ if (input === "o") {
36227
+ const selectedItem = allItems[selection];
36228
+ openInVsCode(repoRoot, selectedItem.path);
36229
+ }
36230
+ if (input === "c") {
36231
+ const selectedItem = allItems[selection];
36232
+ onCopyId(selectedItem.id);
36233
+ }
35790
36234
  });
35791
36235
  if (!schubDir) {
35792
36236
  return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
@@ -35812,10 +36256,15 @@ function StatusView() {
35812
36256
  }, undefined, false, undefined, this)
35813
36257
  }, undefined, false, undefined, this);
35814
36258
  }
35815
- const renderRow = (item, index) => {
36259
+ const renderRow = (item, index, detail) => {
35816
36260
  const selected = index === selection;
35817
- const isTask = "path" in item && item.path.includes("tasks/");
35818
- const title = isTask ? trimTaskTitle(item.title) : "";
36261
+ const task = isTaskItem(item) ? item : null;
36262
+ const title = task ? trimTaskTitle(task.title) : "";
36263
+ const checklistIndicator = task && task.status === "wip" && typeof task.checklistTotal === "number" ? ` (${task.checklistRemaining ?? 0}/${task.checklistTotal})` : "";
36264
+ const changeTitle = item.title;
36265
+ const changeDetail = detail ? ` ${detail}` : "";
36266
+ const displayTitle = task ? `${title}${checklistIndicator}` : `${changeTitle}${changeDetail}`.trim();
36267
+ const displayId = task ? item.id : formatChangeId(item.id);
35819
36268
  return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
35820
36269
  marginLeft: 1,
35821
36270
  children: [
@@ -35829,13 +36278,13 @@ function StatusView() {
35829
36278
  /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
35830
36279
  color: "white",
35831
36280
  bold: selected,
35832
- children: item.id
36281
+ children: displayId
35833
36282
  }, undefined, false, undefined, this),
35834
- title ? /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
36283
+ displayTitle ? /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
35835
36284
  color: "gray",
35836
36285
  children: [
35837
36286
  " ",
35838
- title
36287
+ displayTitle
35839
36288
  ]
35840
36289
  }, undefined, true, undefined, this) : null
35841
36290
  ]
@@ -35844,11 +36293,11 @@ function StatusView() {
35844
36293
  }, item.id, true, undefined, this);
35845
36294
  };
35846
36295
  let currentIndex = 0;
35847
- const renderSection = (title, items) => {
36296
+ const renderSection = (title, items, detailById) => {
35848
36297
  if (items.length === 0)
35849
36298
  return null;
35850
36299
  const sectionStartIndex = currentIndex;
35851
- const sectionItems = items.map((item, i) => renderRow(item, sectionStartIndex + i));
36300
+ const sectionItems = items.map((item, i) => renderRow(item, sectionStartIndex + i, detailById?.get(item.id)));
35852
36301
  currentIndex += items.length;
35853
36302
  return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
35854
36303
  flexDirection: "column",
@@ -35877,14 +36326,14 @@ function StatusView() {
35877
36326
  children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
35878
36327
  bold: true,
35879
36328
  color: "white",
35880
- underline: true,
35881
36329
  children: "Change Proposals"
35882
36330
  }, undefined, false, undefined, this)
35883
36331
  }, undefined, false, undefined, this),
35884
36332
  renderSection("Pending Review", pendingReview),
35885
- renderSection("Pending Implementation", pendingImplementation),
36333
+ renderSection("Pending Implementation", pendingImplementation, pendingImplementationCounts),
36334
+ renderSection("No Tasks Defined", pendingImplementationNoTasks),
35886
36335
  renderSection("Drafts", drafts),
35887
- pendingReview.length === 0 && pendingImplementation.length === 0 && drafts.length === 0 && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
36336
+ pendingReview.length === 0 && pendingImplementation.length === 0 && pendingImplementationNoTasks.length === 0 && drafts.length === 0 && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
35888
36337
  marginLeft: 1,
35889
36338
  children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
35890
36339
  color: "gray",
@@ -35901,7 +36350,6 @@ function StatusView() {
35901
36350
  children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
35902
36351
  bold: true,
35903
36352
  color: "white",
35904
- underline: true,
35905
36353
  children: "Tasks"
35906
36354
  }, undefined, false, undefined, this)
35907
36355
  }, undefined, false, undefined, this),
@@ -35928,17 +36376,41 @@ var tabs = [
35928
36376
  { id: "status", label: "Status" },
35929
36377
  { id: "plan", label: "Plan" }
35930
36378
  ];
35931
- function App2() {
36379
+ var COPY_BANNER_TEXT = "Copied to clipboard !";
36380
+ var COPY_BANNER_TIMEOUT_MS = 1500;
36381
+ function App2({ copyToClipboard: copyToClipboard2 = copyToClipboard }) {
35932
36382
  const [mode, setMode] = import_react28.default.useState("status");
35933
36383
  const { stdout } = use_stdout_default();
35934
36384
  const [dimensions, setDimensions] = import_react28.default.useState(() => ({
35935
36385
  columns: stdout.columns,
35936
36386
  rows: stdout.rows
35937
36387
  }));
36388
+ const [copyBanner, setCopyBanner] = import_react28.default.useState(null);
35938
36389
  const versionLabel = `${package_default.version}`;
35939
36390
  const homeDir = homedir();
35940
- const schubDir = findSchubRoot(process.env.SCHUB_CWD ?? process.cwd());
35941
- const displaySchubDir = schubDir === homeDir ? "~" : schubDir.startsWith(`${homeDir}/`) ? `~${schubDir.slice(homeDir.length)}` : schubDir;
36391
+ const startDir = process.env.SCHUB_CWD ?? process.cwd();
36392
+ const schubDir = findSchubRoot(startDir);
36393
+ const displaySchubDir = (() => {
36394
+ const targetDir = schubDir ?? startDir;
36395
+ if (targetDir === homeDir) {
36396
+ return "~";
36397
+ }
36398
+ if (targetDir.startsWith(`${homeDir}/`)) {
36399
+ return `~${targetDir.slice(homeDir.length)}`;
36400
+ }
36401
+ return targetDir;
36402
+ })();
36403
+ import_react28.default.useEffect(() => {
36404
+ if (!copyBanner) {
36405
+ return;
36406
+ }
36407
+ const timeout = setTimeout(() => {
36408
+ setCopyBanner(null);
36409
+ }, COPY_BANNER_TIMEOUT_MS);
36410
+ return () => {
36411
+ clearTimeout(timeout);
36412
+ };
36413
+ }, [copyBanner]);
35942
36414
  import_react28.default.useEffect(() => {
35943
36415
  const handleResize = () => {
35944
36416
  setDimensions({ columns: stdout.columns, rows: stdout.rows });
@@ -35953,6 +36425,14 @@ function App2() {
35953
36425
  setMode((current) => current === "status" ? "plan" : "status");
35954
36426
  }
35955
36427
  });
36428
+ const handleCopyId = (value) => {
36429
+ copyToClipboard2(value);
36430
+ setCopyBanner(COPY_BANNER_TEXT);
36431
+ };
36432
+ const shortcuts = [
36433
+ { keyLabel: "o", label: "open file" },
36434
+ { keyLabel: "c", label: "copy" }
36435
+ ];
35956
36436
  return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
35957
36437
  backgroundColor: "black",
35958
36438
  flexDirection: "column",
@@ -35968,30 +36448,40 @@ function App2() {
35968
36448
  flexDirection: "row",
35969
36449
  justifyContent: "space-between",
35970
36450
  alignItems: "center",
35971
- children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
35972
- flexDirection: "row",
35973
- children: tabs.map((tab2) => {
35974
- const isSelected = mode === tab2.id;
35975
- return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
35976
- marginRight: 4,
35977
- borderStyle: "bold",
35978
- borderLeft: isSelected,
35979
- borderTop: false,
35980
- borderRight: false,
35981
- borderBottom: false,
35982
- borderLeftColor: "blueBright",
35983
- flexDirection: "row",
35984
- alignItems: "center",
35985
- paddingLeft: 1,
35986
- children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
35987
- color: isSelected ? "white" : "gray",
35988
- bold: isSelected,
35989
- children: tab2.label
35990
- }, undefined, false, undefined, this)
35991
- }, tab2.id, false, undefined, this);
35992
- })
35993
- }, undefined, false, undefined, this)
35994
- }, undefined, false, undefined, this)
36451
+ children: [
36452
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36453
+ flexDirection: "row",
36454
+ children: tabs.map((tab2) => {
36455
+ const isSelected = mode === tab2.id;
36456
+ return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36457
+ marginRight: 4,
36458
+ borderStyle: "bold",
36459
+ borderLeft: isSelected,
36460
+ borderTop: false,
36461
+ borderRight: false,
36462
+ borderBottom: false,
36463
+ borderLeftColor: "blueBright",
36464
+ flexDirection: "row",
36465
+ alignItems: "center",
36466
+ paddingLeft: 1,
36467
+ children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
36468
+ color: isSelected ? "white" : "gray",
36469
+ bold: isSelected,
36470
+ children: tab2.label
36471
+ }, undefined, false, undefined, this)
36472
+ }, tab2.id, false, undefined, this);
36473
+ })
36474
+ }, undefined, false, undefined, this),
36475
+ copyBanner ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36476
+ backgroundColor: "green",
36477
+ paddingX: 1,
36478
+ children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
36479
+ color: "black",
36480
+ children: copyBanner
36481
+ }, undefined, false, undefined, this)
36482
+ }, undefined, false, undefined, this) : null
36483
+ ]
36484
+ }, undefined, true, undefined, this)
35995
36485
  }, undefined, false, undefined, this),
35996
36486
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
35997
36487
  flexDirection: "column",
@@ -35999,7 +36489,11 @@ function App2() {
35999
36489
  paddingY: 1,
36000
36490
  flexGrow: 1,
36001
36491
  flexShrink: 1,
36002
- children: mode === "status" ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(StatusView, {}, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(PlanView, {}, undefined, false, undefined, this)
36492
+ children: mode === "status" ? /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(StatusView, {
36493
+ onCopyId: handleCopyId
36494
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(PlanView, {
36495
+ onCopyId: handleCopyId
36496
+ }, undefined, false, undefined, this)
36003
36497
  }, undefined, false, undefined, this),
36004
36498
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36005
36499
  flexDirection: "column",
@@ -36008,8 +36502,32 @@ function App2() {
36008
36502
  flexShrink: 0,
36009
36503
  children: [
36010
36504
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36011
- justifyContent: "flex-end",
36505
+ justifyContent: "space-between",
36012
36506
  children: [
36507
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36508
+ flexDirection: "row",
36509
+ children: shortcuts.map((shortcut) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36510
+ marginRight: 2,
36511
+ children: [
36512
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
36513
+ color: "gray",
36514
+ children: "["
36515
+ }, undefined, false, undefined, this),
36516
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
36517
+ color: "white",
36518
+ children: shortcut.keyLabel
36519
+ }, undefined, false, undefined, this),
36520
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
36521
+ color: "gray",
36522
+ children: [
36523
+ " ",
36524
+ shortcut.label,
36525
+ "]"
36526
+ ]
36527
+ }, undefined, true, undefined, this)
36528
+ ]
36529
+ }, shortcut.keyLabel, true, undefined, this))
36530
+ }, undefined, false, undefined, this),
36013
36531
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36014
36532
  marginRight: 2,
36015
36533
  children: [
@@ -36021,17 +36539,6 @@ function App2() {
36021
36539
  children: " switch mode"
36022
36540
  }, undefined, false, undefined, this)
36023
36541
  ]
36024
- }, undefined, true, undefined, this),
36025
- /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
36026
- children: [
36027
- /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
36028
- children: "ctrl+p"
36029
- }, undefined, false, undefined, this),
36030
- /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
36031
- color: "gray",
36032
- children: " commands"
36033
- }, undefined, false, undefined, this)
36034
- ]
36035
36542
  }, undefined, true, undefined, this)
36036
36543
  ]
36037
36544
  }, undefined, true, undefined, this),
@@ -36055,202 +36562,556 @@ function App2() {
36055
36562
  }, undefined, true, undefined, this);
36056
36563
  }
36057
36564
 
36058
- // src/changes.ts
36059
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync3, writeFileSync as writeFileSync3 } from "node:fs";
36060
- import { basename as basename2, dirname as dirname3, join as join4, relative as relative3, resolve as resolve3 } from "node:path";
36565
+ // src/commands/adr.ts
36566
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
36567
+ import { dirname as dirname6, join as join6 } from "node:path";
36061
36568
  import { fileURLToPath as fileURLToPath3 } from "node:url";
36062
- var isDirectory3 = (path) => {
36063
- try {
36064
- return statSync3(path).isDirectory();
36065
- } catch {
36066
- return false;
36569
+ var BUNDLED_ADR_TEMPLATE_PATH = fileURLToPath3(new URL("../../templates/create-proposal/adr-template.md", import.meta.url));
36570
+ var parseAdrCreateOptions = (args) => {
36571
+ let changeId;
36572
+ let title;
36573
+ let overwrite = false;
36574
+ const unknown = [];
36575
+ const rejectUnsupported = (flag) => {
36576
+ throw new Error(`Unsupported option: ${flag}.`);
36577
+ };
36578
+ for (let index = 0;index < args.length; index += 1) {
36579
+ const arg = args[index];
36580
+ if (arg === "--overwrite") {
36581
+ overwrite = true;
36582
+ continue;
36583
+ }
36584
+ if (arg === "--change-id") {
36585
+ changeId = args[index + 1];
36586
+ if (changeId === undefined) {
36587
+ throw new Error("Missing value for --change-id.");
36588
+ }
36589
+ index += 1;
36590
+ continue;
36591
+ }
36592
+ if (arg.startsWith("--change-id=")) {
36593
+ changeId = arg.slice("--change-id=".length);
36594
+ continue;
36595
+ }
36596
+ if (arg === "--title") {
36597
+ title = args[index + 1];
36598
+ if (title === undefined) {
36599
+ throw new Error("Missing value for --title.");
36600
+ }
36601
+ index += 1;
36602
+ continue;
36603
+ }
36604
+ if (arg.startsWith("--title=")) {
36605
+ title = arg.slice("--title=".length);
36606
+ continue;
36607
+ }
36608
+ if (arg === "--schub-root" || arg === "--agent-root") {
36609
+ rejectUnsupported(arg);
36610
+ }
36611
+ if (arg.startsWith("--schub-root=")) {
36612
+ rejectUnsupported("--schub-root");
36613
+ }
36614
+ if (arg.startsWith("--agent-root=")) {
36615
+ rejectUnsupported("--agent-root");
36616
+ }
36617
+ unknown.push(arg);
36618
+ }
36619
+ if (unknown.length > 0) {
36620
+ throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
36067
36621
  }
36622
+ if (!changeId) {
36623
+ throw new Error("Provide --change-id.");
36624
+ }
36625
+ return { changeId, title, overwrite };
36068
36626
  };
36069
- var slugify = (value) => {
36070
- let slug = value.trim().toLowerCase();
36071
- slug = slug.replace(/[^a-z0-9]+/g, "-");
36072
- slug = slug.replace(/-{2,}/g, "-");
36073
- return slug.replace(/^-|-$/g, "");
36627
+ var renderAdrTemplate = (template, title) => {
36628
+ const today = new Date().toISOString().split("T")[0];
36629
+ return template.split("[TITLE]").join(title).split("[YYYY-MM-DD]").join(today);
36074
36630
  };
36075
- var splitPrefixedChangeId = (changeId) => {
36076
- const match = changeId.match(/^([Cc])(\d{3})_([a-z0-9]+(?:-[a-z0-9]+)*)$/);
36077
- if (match) {
36078
- return { prefix: match[2], slug: match[3] };
36079
- }
36080
- return { prefix: null, slug: changeId };
36631
+ var runAdrCreate = (args, startDir) => {
36632
+ const options = parseAdrCreateOptions(args);
36633
+ const schubDir = resolveChangeRoot(startDir);
36634
+ const summary = readChangeSummary(schubDir, options.changeId);
36635
+ const adrTitle = options.title?.trim() || summary.changeTitle;
36636
+ const outputPath = join6(summary.changeDir, "adr.md");
36637
+ if (existsSync5(outputPath) && !options.overwrite) {
36638
+ throw new Error(`Refusing to overwrite existing file: ${outputPath}`);
36639
+ }
36640
+ const templatePath = resolveTemplatePath(schubDir, join6("create-proposal", "adr-template.md"), BUNDLED_ADR_TEMPLATE_PATH);
36641
+ const template = readFileSync5(templatePath, "utf8");
36642
+ const rendered = renderAdrTemplate(template, adrTitle || summary.changeId);
36643
+ mkdirSync3(dirname6(outputPath), { recursive: true });
36644
+ writeFileSync3(outputPath, rendered, "utf8");
36645
+ process.stdout.write(`[OK] Wrote ADR: ${outputPath}
36646
+ `);
36081
36647
  };
36082
- var nextChangePrefix = (schubDir) => {
36083
- const changesRoot = join4(schubDir, "changes");
36084
- const archiveRoot = join4(schubDir, "archive", "changes");
36085
- const prefixes = [];
36086
- const scan = (root) => {
36087
- if (!existsSync5(root) || !isDirectory3(root))
36088
- return;
36089
- for (const entry of readdirSync4(root, { withFileTypes: true })) {
36090
- if (!entry.isDirectory()) {
36091
- continue;
36648
+
36649
+ // src/commands/changes.ts
36650
+ var parseChangeCreateOptions = (args) => {
36651
+ let changeId;
36652
+ let title;
36653
+ let input;
36654
+ let overwrite = false;
36655
+ const unknown = [];
36656
+ const rejectUnsupported = (flag) => {
36657
+ throw new Error(`Unsupported option: ${flag}.`);
36658
+ };
36659
+ for (let index = 0;index < args.length; index += 1) {
36660
+ const arg = args[index];
36661
+ if (arg === "--overwrite") {
36662
+ overwrite = true;
36663
+ continue;
36664
+ }
36665
+ if (arg === "--change-id") {
36666
+ changeId = args[index + 1];
36667
+ if (changeId === undefined) {
36668
+ throw new Error("Missing value for --change-id.");
36092
36669
  }
36093
- const match = entry.name.match(/^[Cc](\d{3})_/);
36094
- if (match) {
36095
- prefixes.push(Number.parseInt(match[1], 10));
36670
+ index += 1;
36671
+ continue;
36672
+ }
36673
+ if (arg.startsWith("--change-id=")) {
36674
+ changeId = arg.slice("--change-id=".length);
36675
+ continue;
36676
+ }
36677
+ if (arg === "--title") {
36678
+ title = args[index + 1];
36679
+ if (title === undefined) {
36680
+ throw new Error("Missing value for --title.");
36096
36681
  }
36682
+ index += 1;
36683
+ continue;
36097
36684
  }
36098
- };
36099
- scan(changesRoot);
36100
- scan(archiveRoot);
36101
- const next = prefixes.length > 0 ? Math.max(...prefixes) + 1 : 1;
36102
- return next.toString().padStart(3, "0");
36103
- };
36104
- var CHANGE_PREFIX = "C";
36105
- var PROPOSAL_TEMPLATE_PATH2 = fileURLToPath3(new URL("../templates/create-proposal/proposal-template.md", import.meta.url));
36106
- var readProposalTemplate = () => {
36107
- try {
36108
- return readFileSync5(PROPOSAL_TEMPLATE_PATH2, "utf8");
36109
- } catch {
36110
- throw new Error(`[ERROR] Template not found: ${PROPOSAL_TEMPLATE_PATH2}`);
36685
+ if (arg.startsWith("--title=")) {
36686
+ title = arg.slice("--title=".length);
36687
+ continue;
36688
+ }
36689
+ if (arg === "--input") {
36690
+ input = args[index + 1];
36691
+ if (input === undefined) {
36692
+ throw new Error("Missing value for --input.");
36693
+ }
36694
+ index += 1;
36695
+ continue;
36696
+ }
36697
+ if (arg.startsWith("--input=")) {
36698
+ input = arg.slice("--input=".length);
36699
+ continue;
36700
+ }
36701
+ if (arg === "--schub-root" || arg === "--agent-root") {
36702
+ rejectUnsupported(arg);
36703
+ }
36704
+ if (arg.startsWith("--schub-root=")) {
36705
+ rejectUnsupported("--schub-root");
36706
+ }
36707
+ if (arg.startsWith("--agent-root=")) {
36708
+ rejectUnsupported("--agent-root");
36709
+ }
36710
+ unknown.push(arg);
36711
+ }
36712
+ if (unknown.length > 0) {
36713
+ throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
36111
36714
  }
36715
+ const options = { changeId, title, input, overwrite };
36716
+ return options;
36112
36717
  };
36113
- var isValidSlug = (value) => /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value);
36114
- var changeExists = (schubDir, changeId) => {
36115
- const active = join4(schubDir, "changes", changeId);
36116
- if (existsSync5(active)) {
36117
- return true;
36718
+ var parseChangeStatusOptions = (args) => {
36719
+ let changeId;
36720
+ let status;
36721
+ const unknown = [];
36722
+ const rejectUnsupported = (flag) => {
36723
+ throw new Error(`Unsupported option: ${flag}.`);
36724
+ };
36725
+ for (let index = 0;index < args.length; index += 1) {
36726
+ const arg = args[index];
36727
+ if (arg === "--change-id") {
36728
+ changeId = args[index + 1];
36729
+ if (changeId === undefined) {
36730
+ throw new Error("Missing value for --change-id.");
36731
+ }
36732
+ index += 1;
36733
+ continue;
36734
+ }
36735
+ if (arg.startsWith("--change-id=")) {
36736
+ changeId = arg.slice("--change-id=".length);
36737
+ continue;
36738
+ }
36739
+ if (arg === "--status") {
36740
+ status = args[index + 1];
36741
+ if (status === undefined) {
36742
+ throw new Error("Missing value for --status.");
36743
+ }
36744
+ index += 1;
36745
+ continue;
36746
+ }
36747
+ if (arg.startsWith("--status=")) {
36748
+ status = arg.slice("--status=".length);
36749
+ continue;
36750
+ }
36751
+ if (arg === "--schub-root" || arg === "--agent-root") {
36752
+ rejectUnsupported(arg);
36753
+ }
36754
+ if (arg.startsWith("--schub-root=")) {
36755
+ rejectUnsupported("--schub-root");
36756
+ }
36757
+ if (arg.startsWith("--agent-root=")) {
36758
+ rejectUnsupported("--agent-root");
36759
+ }
36760
+ unknown.push(arg);
36118
36761
  }
36119
- const archiveRoot = join4(schubDir, "archive", "changes");
36120
- if (!existsSync5(archiveRoot) || !isDirectory3(archiveRoot)) {
36121
- return false;
36762
+ if (unknown.length > 0) {
36763
+ throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
36122
36764
  }
36123
- for (const entry of readdirSync4(archiveRoot, { withFileTypes: true })) {
36124
- if (entry.isDirectory() && entry.name.includes(changeId)) {
36125
- return true;
36126
- }
36765
+ if (!changeId) {
36766
+ throw new Error("Provide --change-id.");
36127
36767
  }
36128
- return false;
36768
+ if (!status || !status.trim()) {
36769
+ throw new Error("Provide --status.");
36770
+ }
36771
+ const options = { changeId, status };
36772
+ return options;
36129
36773
  };
36130
- var resolveChangeRoot = (startDir = process.cwd()) => {
36131
- const start = resolve3(startDir);
36132
- const fallback = join4(start, ".schub");
36133
- let current = start;
36134
- while (true) {
36135
- if (basename2(current) === ".schub" && isDirectory3(current)) {
36136
- return current;
36774
+ var runChangesCreate = (args, startDir) => {
36775
+ const options = parseChangeCreateOptions(args);
36776
+ const schubDir = resolveChangeRoot(startDir);
36777
+ const proposalPath = createChange(schubDir, options);
36778
+ process.stdout.write(`[OK] Wrote proposal: ${proposalPath}
36779
+ `);
36780
+ };
36781
+ var runChangesStatus = (args, startDir) => {
36782
+ const options = parseChangeStatusOptions(args);
36783
+ const schubDir = resolveChangeRoot(startDir);
36784
+ const updated = updateChangeStatus(schubDir, options.changeId, options.status);
36785
+ process.stdout.write(`[OK] Updated status for ${updated.changeId}: ${updated.previousStatus} -> ${updated.status}
36786
+ `);
36787
+ };
36788
+
36789
+ // src/commands/cookbook.ts
36790
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "node:fs";
36791
+ import { dirname as dirname7, join as join7 } from "node:path";
36792
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
36793
+ var BUNDLED_COOKBOOK_TEMPLATE_PATH = fileURLToPath4(new URL("../../templates/create-proposal/cookbook-template.md", import.meta.url));
36794
+ var parseCookbookCreateOptions = (args) => {
36795
+ let changeId;
36796
+ let overwrite = false;
36797
+ const unknown = [];
36798
+ const rejectUnsupported = (flag) => {
36799
+ throw new Error(`Unsupported option: ${flag}.`);
36800
+ };
36801
+ for (let index = 0;index < args.length; index += 1) {
36802
+ const arg = args[index];
36803
+ if (arg === "--overwrite") {
36804
+ overwrite = true;
36805
+ continue;
36137
36806
  }
36138
- const candidate = join4(current, ".schub");
36139
- if (isDirectory3(candidate)) {
36140
- return candidate;
36807
+ if (arg === "--change-id") {
36808
+ changeId = args[index + 1];
36809
+ if (changeId === undefined) {
36810
+ throw new Error("Missing value for --change-id.");
36811
+ }
36812
+ index += 1;
36813
+ continue;
36141
36814
  }
36142
- const parent = dirname3(current);
36143
- if (parent === current) {
36144
- return fallback;
36815
+ if (arg.startsWith("--change-id=")) {
36816
+ changeId = arg.slice("--change-id=".length);
36817
+ continue;
36145
36818
  }
36146
- current = parent;
36819
+ if (arg === "--schub-root" || arg === "--agent-root") {
36820
+ rejectUnsupported(arg);
36821
+ }
36822
+ if (arg.startsWith("--schub-root=")) {
36823
+ rejectUnsupported("--schub-root");
36824
+ }
36825
+ if (arg.startsWith("--agent-root=")) {
36826
+ rejectUnsupported("--agent-root");
36827
+ }
36828
+ unknown.push(arg);
36829
+ }
36830
+ if (unknown.length > 0) {
36831
+ throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
36147
36832
  }
36148
- };
36149
- var createChange = (schubDir, options) => {
36150
- let changeId = (options.changeId || "").trim();
36151
- let title = (options.title || "").trim();
36152
- const input = (options.input || "").trim();
36153
36833
  if (!changeId) {
36154
- if (!title) {
36155
- throw new Error("Provide --change-id or --title.");
36834
+ throw new Error("Provide --change-id.");
36835
+ }
36836
+ return { changeId, overwrite };
36837
+ };
36838
+ var renderCookbookTemplate = (template, changeTitle, changeId) => {
36839
+ const today = new Date().toISOString().split("T")[0];
36840
+ return template.replace("{{CHANGE_TITLE}}", changeTitle).replace("{{CHANGE_ID}}", changeId).replace("{{DATE}}", today);
36841
+ };
36842
+ var runCookbookCreate = (args, startDir) => {
36843
+ const options = parseCookbookCreateOptions(args);
36844
+ const schubDir = resolveChangeRoot(startDir);
36845
+ const summary = readChangeSummary(schubDir, options.changeId);
36846
+ const outputPath = join7(summary.changeDir, "cookbook.md");
36847
+ if (existsSync6(outputPath) && !options.overwrite) {
36848
+ throw new Error(`Refusing to overwrite existing file: ${outputPath}`);
36849
+ }
36850
+ const templatePath = resolveTemplatePath(schubDir, join7("create-proposal", "cookbook-template.md"), BUNDLED_COOKBOOK_TEMPLATE_PATH);
36851
+ const template = readFileSync6(templatePath, "utf8");
36852
+ const rendered = renderCookbookTemplate(template, summary.changeTitle, summary.changeId);
36853
+ mkdirSync4(dirname7(outputPath), { recursive: true });
36854
+ writeFileSync4(outputPath, rendered, "utf8");
36855
+ process.stdout.write(`[OK] Wrote cookbook: ${outputPath}
36856
+ `);
36857
+ };
36858
+
36859
+ // src/commands/eject.ts
36860
+ import { cpSync, existsSync as existsSync7, mkdirSync as mkdirSync5, rmSync, statSync as statSync5 } from "node:fs";
36861
+ import { join as join8 } from "node:path";
36862
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
36863
+ var BUNDLED_SKILLS_ROOT = fileURLToPath5(new URL("../../skills", import.meta.url));
36864
+ var BUNDLED_TEMPLATES_ROOT = fileURLToPath5(new URL("../../templates", import.meta.url));
36865
+ var isDirectory4 = (path) => {
36866
+ try {
36867
+ return statSync5(path).isDirectory();
36868
+ } catch {
36869
+ return false;
36870
+ }
36871
+ };
36872
+ var parseEjectOptions = (args) => {
36873
+ let force = false;
36874
+ const unknown = [];
36875
+ const rejectUnsupported = (flag) => {
36876
+ throw new Error(`Unsupported option: ${flag}.`);
36877
+ };
36878
+ for (const arg of args) {
36879
+ if (arg === "--force") {
36880
+ force = true;
36881
+ continue;
36156
36882
  }
36157
- changeId = slugify(title);
36158
- if (!changeId) {
36159
- throw new Error("Unable to derive change-id from title.");
36883
+ if (arg === "--schub-root" || arg === "--agent-root") {
36884
+ rejectUnsupported(arg);
36160
36885
  }
36161
- console.warn(`[WARN] Derived change-id '${changeId}' from --title. Prefer verb-led ids.`);
36886
+ if (arg.startsWith("--schub-root=")) {
36887
+ rejectUnsupported("--schub-root");
36888
+ }
36889
+ if (arg.startsWith("--agent-root=")) {
36890
+ rejectUnsupported("--agent-root");
36891
+ }
36892
+ unknown.push(arg);
36162
36893
  }
36163
- const originalChangeId = changeId;
36164
- const { prefix: existingPrefix, slug } = splitPrefixedChangeId(changeId);
36165
- if (!isValidSlug(slug)) {
36166
- throw new Error(`Invalid change-id '${changeId}'. Use kebab-case (lowercase letters/digits and hyphens).`);
36894
+ if (unknown.length > 0) {
36895
+ throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
36167
36896
  }
36168
- if (!existingPrefix) {
36169
- const prefix = nextChangePrefix(schubDir);
36170
- changeId = `${CHANGE_PREFIX}${prefix}_${slug}`;
36171
- console.error(`[INFO] Prefixed change-id with '${CHANGE_PREFIX}${prefix}_'.`);
36172
- } else {
36173
- changeId = `${CHANGE_PREFIX}${existingPrefix}_${slug}`;
36174
- if (changeId !== originalChangeId) {
36175
- console.error(`[INFO] Normalized change-id to '${changeId}'.`);
36176
- }
36897
+ return { force };
36898
+ };
36899
+ var ensureBundledDir = (path) => {
36900
+ if (!isDirectory4(path)) {
36901
+ throw new Error(`[ERROR] Bundled assets missing: ${path}`);
36177
36902
  }
36178
- if (!title) {
36179
- title = slug.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
36903
+ };
36904
+ var removeExisting = (path) => {
36905
+ if (existsSync7(path)) {
36906
+ rmSync(path, { recursive: true, force: true });
36180
36907
  }
36181
- const changeDir = join4(schubDir, "changes", changeId);
36182
- const proposalPath = join4(changeDir, "proposal.md");
36183
- if (changeExists(schubDir, changeId) && !options.overwrite) {
36184
- throw new Error(`Change '${changeId}' already exists under ${schubDir}. Choose a unique id or pass --overwrite.`);
36908
+ };
36909
+ var copyDirectory = (source, destination) => {
36910
+ ensureBundledDir(source);
36911
+ cpSync(source, destination, { recursive: true });
36912
+ };
36913
+ var enforceOverwrite = (paths, force) => {
36914
+ const existing = paths.filter((path) => existsSync7(path));
36915
+ if (existing.length === 0) {
36916
+ return;
36185
36917
  }
36186
- const template = readProposalTemplate();
36187
- const today = new Date().toISOString().split("T")[0];
36188
- const rendered = template.replace("{{CHANGE_TITLE}}", title).replace("{{CHANGE_ID}}", changeId).replace("{{DATE}}", today).replace("{{INPUT}}", input || "[no input provided]").replace("{{AGENT_ROOT}}", schubDir);
36189
- if (existsSync5(proposalPath) && !options.overwrite) {
36190
- throw new Error(`Refusing to overwrite existing file: ${proposalPath}`);
36918
+ if (!force) {
36919
+ const lines = existing.map((path) => ` - ${path}`).join(`
36920
+ `);
36921
+ throw new Error(`[ERROR] Refusing to overwrite existing path(s):
36922
+ ${lines}
36923
+ Re-run with --force.`);
36924
+ }
36925
+ for (const path of existing) {
36926
+ removeExisting(path);
36191
36927
  }
36192
- mkdirSync3(changeDir, { recursive: true });
36193
- writeFileSync3(proposalPath, rendered, "utf8");
36194
- return proposalPath;
36195
36928
  };
36196
- // src/project.ts
36197
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync6, statSync as statSync4, writeFileSync as writeFileSync4 } from "node:fs";
36198
- import { basename as basename3, dirname as dirname4, join as join5, resolve as resolve4 } from "node:path";
36199
- import { fileURLToPath as fileURLToPath4 } from "node:url";
36200
- var TEMPLATE_FILES = {
36201
- "project-overview.md": "project-overview-template.md",
36202
- "project-setup.md": "project-setup-template.md",
36203
- "project-wow.md": "project-wow-template.md"
36929
+ var runEject = (args, startDir) => {
36930
+ const options = parseEjectOptions(args);
36931
+ const schubRoot = resolveSchubRoot(startDir);
36932
+ mkdirSync5(schubRoot, { recursive: true });
36933
+ const skillsTarget = join8(schubRoot, "skills");
36934
+ const templatesTarget = join8(schubRoot, "templates");
36935
+ enforceOverwrite([skillsTarget, templatesTarget], options.force);
36936
+ copyDirectory(BUNDLED_SKILLS_ROOT, skillsTarget);
36937
+ copyDirectory(BUNDLED_TEMPLATES_ROOT, templatesTarget);
36938
+ process.stdout.write(`[OK] Wrote ${skillsTarget}
36939
+ `);
36940
+ process.stdout.write(`[OK] Wrote ${templatesTarget}
36941
+ `);
36204
36942
  };
36205
- var TEMPLATES_ROOT = fileURLToPath4(new URL("../templates/setup-project", import.meta.url));
36206
- var isDirectory4 = (path) => {
36943
+
36944
+ // src/commands/init.ts
36945
+ import { cpSync as cpSync2, existsSync as existsSync8, mkdirSync as mkdirSync7, readdirSync as readdirSync4, statSync as statSync6 } from "node:fs";
36946
+ import { homedir as homedir2 } from "node:os";
36947
+ import { join as join10, resolve as resolve5 } from "node:path";
36948
+ import { createInterface } from "node:readline";
36949
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
36950
+
36951
+ // src/init.ts
36952
+ import { spawnSync as spawnSync2 } from "node:child_process";
36953
+ import { mkdirSync as mkdirSync6 } from "node:fs";
36954
+ import { join as join9, resolve as resolve4 } from "node:path";
36955
+ var resolveGitRoot = (startDir) => {
36956
+ const result = spawnSync2("git", ["rev-parse", "--show-toplevel"], {
36957
+ cwd: startDir,
36958
+ encoding: "utf8",
36959
+ stdio: ["ignore", "pipe", "ignore"]
36960
+ });
36961
+ if (result.status !== 0) {
36962
+ return null;
36963
+ }
36964
+ const output = result.stdout?.trim();
36965
+ return output ? resolve4(output) : null;
36966
+ };
36967
+ var initSchubRoot = (startDir = process.cwd()) => {
36968
+ const resolvedStart = resolve4(startDir);
36969
+ const gitRoot = resolveGitRoot(resolvedStart);
36970
+ const root = gitRoot ?? resolvedStart;
36971
+ const schubRoot = join9(root, ".schub");
36972
+ mkdirSync6(schubRoot, { recursive: true });
36973
+ return schubRoot;
36974
+ };
36975
+
36976
+ // src/commands/init.ts
36977
+ var PROVIDERS = [{ id: "codex", label: "Codex" }];
36978
+ var BUNDLED_SKILLS_ROOT2 = fileURLToPath6(new URL("../../skills", import.meta.url));
36979
+ var isDirectory5 = (path) => {
36207
36980
  try {
36208
- return statSync4(path).isDirectory();
36981
+ return statSync6(path).isDirectory();
36209
36982
  } catch {
36210
36983
  return false;
36211
36984
  }
36212
36985
  };
36213
- var resolveSchubRoot = (startDir) => {
36214
- let current = resolve4(startDir);
36215
- const fallback = join5(current, ".schub");
36216
- while (true) {
36217
- if (basename3(current) === ".schub" && isDirectory4(current)) {
36218
- return current;
36986
+ var readLine = (prompt) => new Promise((resolveInput) => {
36987
+ const terminal = createInterface({ input: process.stdin, output: process.stdout });
36988
+ terminal.question(prompt, (answer) => {
36989
+ terminal.close();
36990
+ resolveInput(answer.trim());
36991
+ });
36992
+ });
36993
+ var renderProviderList = (providers) => providers.map((provider, index) => ` ${index + 1}) ${provider.label}`).join(`
36994
+ `);
36995
+ var selectProviders = (input, providers = PROVIDERS) => {
36996
+ const tokens = input.split(/[, ]+/).map((token) => token.trim().toLowerCase()).filter(Boolean);
36997
+ const selected = new Set;
36998
+ for (const token of tokens) {
36999
+ const index = Number.parseInt(token, 10);
37000
+ if (!Number.isNaN(index) && index > 0 && index <= providers.length) {
37001
+ selected.add(providers[index - 1].id);
37002
+ continue;
36219
37003
  }
36220
- const candidate = join5(current, ".schub");
36221
- if (isDirectory4(candidate)) {
36222
- return candidate;
37004
+ const match = providers.find((provider) => provider.id === token || provider.label.toLowerCase() === token);
37005
+ if (match) {
37006
+ selected.add(match.id);
36223
37007
  }
36224
- const parent = dirname4(current);
36225
- if (parent === current) {
36226
- return fallback;
37008
+ }
37009
+ return Array.from(selected);
37010
+ };
37011
+ var promptForProviders = async () => {
37012
+ const list = renderProviderList(PROVIDERS);
37013
+ const answer = await readLine(`Select providers (comma separated):
37014
+ ${list}
37015
+ > `);
37016
+ return selectProviders(answer);
37017
+ };
37018
+ var resolveCodexSkillsRoot = (startDir) => {
37019
+ const resolvedStart = resolve5(startDir);
37020
+ const gitRoot = resolveGitRoot(resolvedStart);
37021
+ if (!gitRoot) {
37022
+ return join10(resolvedStart, ".codex", "skills");
37023
+ }
37024
+ const localCodexRoot = join10(gitRoot, ".codex");
37025
+ if (isDirectory5(localCodexRoot)) {
37026
+ return join10(localCodexRoot, "skills");
37027
+ }
37028
+ const home = process.env.HOME ?? homedir2();
37029
+ return join10(home, ".codex", "skills");
37030
+ };
37031
+ var installCodexSkills = (destination) => {
37032
+ mkdirSync7(destination, { recursive: true });
37033
+ const entries = readdirSync4(BUNDLED_SKILLS_ROOT2, { withFileTypes: true });
37034
+ const installed = [];
37035
+ const skipped = [];
37036
+ for (const entry of entries) {
37037
+ if (!entry.isDirectory()) {
37038
+ continue;
36227
37039
  }
36228
- current = parent;
37040
+ const source = join10(BUNDLED_SKILLS_ROOT2, entry.name);
37041
+ const target = join10(destination, entry.name);
37042
+ if (existsSync8(target)) {
37043
+ skipped.push(entry.name);
37044
+ continue;
37045
+ }
37046
+ cpSync2(source, target, { recursive: true });
37047
+ installed.push(entry.name);
37048
+ }
37049
+ return { installed, skipped };
37050
+ };
37051
+ var reportCodexInstall = (destination, installed, skipped) => {
37052
+ process.stdout.write(`[OK] Codex skills: ${destination}
37053
+ `);
37054
+ for (const skill of installed) {
37055
+ process.stdout.write(`[OK] Installed ${skill}
37056
+ `);
37057
+ }
37058
+ for (const skill of skipped) {
37059
+ process.stdout.write(`[SKIP] ${skill}
37060
+ `);
37061
+ }
37062
+ };
37063
+ var parseInitOptions = (args) => {
37064
+ if (args.length === 0) {
37065
+ return;
37066
+ }
37067
+ throw new Error(`Unknown option(s): ${args.join(", ")}`);
37068
+ };
37069
+ var runInit = async (args, startDir) => {
37070
+ parseInitOptions(args);
37071
+ const schubRoot = initSchubRoot(startDir);
37072
+ process.stdout.write(`[OK] Wrote ${schubRoot}
37073
+ `);
37074
+ const providers = await promptForProviders();
37075
+ if (providers.includes("codex")) {
37076
+ const destination = resolveCodexSkillsRoot(startDir);
37077
+ const { installed, skipped } = installCodexSkills(destination);
37078
+ reportCodexInstall(destination, installed, skipped);
36229
37079
  }
36230
37080
  };
37081
+
37082
+ // src/project.ts
37083
+ import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
37084
+ import { basename as basename2, dirname as dirname8, join as join11, resolve as resolve6 } from "node:path";
37085
+ import { fileURLToPath as fileURLToPath7 } from "node:url";
37086
+ var TEMPLATE_FILES = {
37087
+ "project-overview.md": "project-overview-template.md",
37088
+ "project-setup.md": "project-setup-template.md",
37089
+ "project-wow.md": "project-wow-template.md"
37090
+ };
37091
+ var TEMPLATES_ROOT = fileURLToPath7(new URL("../templates/setup-project", import.meta.url));
36231
37092
  var readTemplate = (path) => {
36232
37093
  try {
36233
- return readFileSync6(path, "utf8");
37094
+ return readFileSync7(path, "utf8");
36234
37095
  } catch {
36235
37096
  throw new Error(`[ERROR] Template not found: ${path}`);
36236
37097
  }
36237
37098
  };
36238
37099
  var writeOutput = (path, content, overwrite) => {
36239
- if (existsSync6(path) && !overwrite) {
37100
+ if (existsSync9(path) && !overwrite) {
36240
37101
  throw new Error(`[ERROR] Refusing to overwrite existing file: ${path}`);
36241
37102
  }
36242
- mkdirSync4(dirname4(path), { recursive: true });
36243
- writeFileSync4(path, content, "utf8");
37103
+ mkdirSync8(dirname8(path), { recursive: true });
37104
+ writeFileSync5(path, content, "utf8");
36244
37105
  };
36245
37106
  var deriveProjectName = (repoRoot) => {
36246
- const name = basename3(repoRoot).trim();
37107
+ const name = basename2(repoRoot).trim();
36247
37108
  return name || "Project";
36248
37109
  };
36249
37110
  var resolveRepoRoot = (startDir, schubRoot, repoRoot) => {
36250
37111
  if (repoRoot) {
36251
- return resolve4(startDir, repoRoot);
37112
+ return resolve6(startDir, repoRoot);
36252
37113
  }
36253
- return resolve4(schubRoot, "..");
37114
+ return resolve6(schubRoot, "..");
36254
37115
  };
36255
37116
  var createProject = (startDir, options) => {
36256
37117
  const schubRoot = resolveSchubRoot(startDir);
@@ -36259,99 +37120,95 @@ var createProject = (startDir, options) => {
36259
37120
  const overwrite = options.overwrite ?? false;
36260
37121
  const created = [];
36261
37122
  for (const [outputName, templateName] of Object.entries(TEMPLATE_FILES)) {
36262
- const templatePath = join5(TEMPLATES_ROOT, templateName);
37123
+ const bundledPath = join11(TEMPLATES_ROOT, templateName);
37124
+ const templatePath = resolveTemplatePath(schubRoot, join11("setup-project", templateName), bundledPath);
36263
37125
  const template = readTemplate(templatePath);
36264
37126
  const rendered = template.split("[Project Name]").join(projectName);
36265
- const outputPath = join5(schubRoot, outputName);
37127
+ const outputPath = join11(schubRoot, outputName);
36266
37128
  writeOutput(outputPath, rendered, overwrite);
36267
37129
  created.push(outputPath);
36268
37130
  }
36269
37131
  return created;
36270
37132
  };
36271
37133
 
36272
- // src/terminal.ts
36273
- var CLEAR_SCROLLBACK = "\x1B[3J";
36274
- var CLEAR_SCREEN = "\x1B[2J";
36275
- var CURSOR_HOME = "\x1B[H";
36276
- var BLACK_BACKGROUND = "\x1B[40m";
36277
- var RESET = "\x1B[0m";
36278
- var terminalPrelude = `${CLEAR_SCROLLBACK}${CLEAR_SCREEN}${CURSOR_HOME}${BLACK_BACKGROUND}`;
36279
- var terminalReset = RESET;
36280
- var applyTerminalPrelude = () => {
36281
- process.stdout.write(terminalPrelude);
36282
- };
36283
- var applyTerminalReset = () => {
36284
- process.stdout.write(terminalReset);
36285
- };
36286
-
36287
- // src/index.ts
36288
- var HELP_TEXT = `schub [command]
36289
-
36290
- Commands:
36291
- changes create Create a change proposal
36292
- project create Create project docs
36293
- tasks create Create task files for a change
36294
- tasks list List tasks
36295
- lint Run Biome lint checks
36296
- format Format files with Biome
36297
- ui Launch the interactive dashboard
36298
- `;
36299
- var getStartDir = () => process.env.SCHUB_CWD ?? process.cwd();
36300
- var getWorkspaceRoot = () => {
36301
- const schubDir = findSchubRoot(getStartDir());
36302
- return schubDir ? dirname5(schubDir) : getStartDir();
36303
- };
36304
- var resolveSchubDir = () => findSchubRoot(getStartDir());
36305
- var printHelp = (exitCode = 0) => {
36306
- process.stdout.write(`${HELP_TEXT}
36307
- `);
36308
- process.exitCode = exitCode;
36309
- };
36310
- var parseStatusFilter = (value) => {
36311
- if (!value) {
36312
- return [...TASK_STATUSES];
36313
- }
36314
- const normalized = value.split(",").map((status) => status.trim().toLowerCase()).filter(Boolean);
36315
- const allowed = new Set(TASK_STATUSES);
36316
- const invalid = normalized.filter((status) => !allowed.has(status));
36317
- if (invalid.length > 0) {
36318
- throw new Error(`Unknown status filter: ${invalid.join(", ")}`);
36319
- }
36320
- return normalized;
36321
- };
36322
- var parseTaskListOptions = (args) => {
36323
- let statusValue;
36324
- let json = false;
37134
+ // src/commands/project.ts
37135
+ var parseProjectCreateOptions = (args) => {
37136
+ let repoRoot;
37137
+ let projectName;
37138
+ let overwrite = false;
36325
37139
  const unknown = [];
37140
+ const rejectUnsupported = (flag) => {
37141
+ throw new Error(`Unsupported option: ${flag}.`);
37142
+ };
36326
37143
  for (let index = 0;index < args.length; index += 1) {
36327
37144
  const arg = args[index];
36328
- if (arg === "--json") {
36329
- json = true;
37145
+ if (arg === "--overwrite") {
37146
+ overwrite = true;
36330
37147
  continue;
36331
37148
  }
36332
- if (arg === "--status") {
36333
- statusValue = args[index + 1];
36334
- if (!statusValue) {
36335
- throw new Error("Missing value for --status.");
37149
+ if (arg === "--repo-root") {
37150
+ repoRoot = args[index + 1];
37151
+ if (repoRoot === undefined) {
37152
+ throw new Error("Missing value for --repo-root.");
36336
37153
  }
36337
37154
  index += 1;
36338
37155
  continue;
36339
37156
  }
36340
- if (arg.startsWith("--status=")) {
36341
- statusValue = arg.slice("--status=".length);
37157
+ if (arg.startsWith("--repo-root=")) {
37158
+ repoRoot = arg.slice("--repo-root=".length);
37159
+ continue;
37160
+ }
37161
+ if (arg === "--project-name") {
37162
+ projectName = args[index + 1];
37163
+ if (projectName === undefined) {
37164
+ throw new Error("Missing value for --project-name.");
37165
+ }
37166
+ index += 1;
37167
+ continue;
37168
+ }
37169
+ if (arg.startsWith("--project-name=")) {
37170
+ projectName = arg.slice("--project-name=".length);
36342
37171
  continue;
36343
37172
  }
37173
+ if (arg === "--schub-root" || arg === "--agent-root") {
37174
+ rejectUnsupported(arg);
37175
+ }
37176
+ if (arg.startsWith("--schub-root=")) {
37177
+ rejectUnsupported("--schub-root");
37178
+ }
37179
+ if (arg.startsWith("--agent-root=")) {
37180
+ rejectUnsupported("--agent-root");
37181
+ }
36344
37182
  unknown.push(arg);
36345
37183
  }
36346
37184
  if (unknown.length > 0) {
36347
37185
  throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
36348
37186
  }
36349
- return { statuses: parseStatusFilter(statusValue), json };
37187
+ return { repoRoot, projectName, overwrite };
36350
37188
  };
36351
- var parseChangeCreateOptions = (args) => {
37189
+ var runProjectCreate = (args, startDir) => {
37190
+ const options = parseProjectCreateOptions(args);
37191
+ const outputs = createProject(startDir, options);
37192
+ for (const output of outputs) {
37193
+ process.stdout.write(`[OK] Wrote ${output}
37194
+ `);
37195
+ }
37196
+ };
37197
+
37198
+ // src/commands/review.ts
37199
+ import { existsSync as existsSync10, mkdirSync as mkdirSync9, readFileSync as readFileSync8, unlinkSync, writeFileSync as writeFileSync6 } from "node:fs";
37200
+ import { dirname as dirname9, join as join12, resolve as resolve7 } from "node:path";
37201
+ import { fileURLToPath as fileURLToPath8 } from "node:url";
37202
+ var BUNDLED_REVIEW_TEMPLATE_PATH = fileURLToPath8(new URL("../../templates/review-proposal/review-me-template.md", import.meta.url));
37203
+ var BUNDLED_QNA_TEMPLATE_PATH = fileURLToPath8(new URL("../../templates/review-proposal/q&a-template.md", import.meta.url));
37204
+ var renderChangeTemplate = (template, changeTitle, changeId) => {
37205
+ const today = new Date().toISOString().split("T")[0];
37206
+ return template.replace("{{CHANGE_TITLE}}", changeTitle).replace("{{CHANGE_ID}}", changeId).replace("{{DATE}}", today);
37207
+ };
37208
+ var parseReviewCreateOptions = (args) => {
36352
37209
  let changeId;
36353
37210
  let title;
36354
- let input;
37211
+ let output;
36355
37212
  let overwrite = false;
36356
37213
  const unknown = [];
36357
37214
  const rejectUnsupported = (flag) => {
@@ -36387,16 +37244,16 @@ var parseChangeCreateOptions = (args) => {
36387
37244
  title = arg.slice("--title=".length);
36388
37245
  continue;
36389
37246
  }
36390
- if (arg === "--input") {
36391
- input = args[index + 1];
36392
- if (input === undefined) {
36393
- throw new Error("Missing value for --input.");
37247
+ if (arg === "--output") {
37248
+ output = args[index + 1];
37249
+ if (output === undefined) {
37250
+ throw new Error("Missing value for --output.");
36394
37251
  }
36395
37252
  index += 1;
36396
37253
  continue;
36397
37254
  }
36398
- if (arg.startsWith("--input=")) {
36399
- input = arg.slice("--input=".length);
37255
+ if (arg.startsWith("--output=")) {
37256
+ output = arg.slice("--output=".length);
36400
37257
  continue;
36401
37258
  }
36402
37259
  if (arg === "--schub-root" || arg === "--agent-root") {
@@ -36413,12 +37270,13 @@ var parseChangeCreateOptions = (args) => {
36413
37270
  if (unknown.length > 0) {
36414
37271
  throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
36415
37272
  }
36416
- const options = { changeId, title, input, overwrite };
36417
- return options;
37273
+ if (!changeId) {
37274
+ throw new Error("Provide --change-id.");
37275
+ }
37276
+ return { changeId, title, output, overwrite };
36418
37277
  };
36419
- var parseProjectCreateOptions = (args) => {
36420
- let repoRoot;
36421
- let projectName;
37278
+ var parseReviewCompleteOptions = (args) => {
37279
+ let changeId;
36422
37280
  let overwrite = false;
36423
37281
  const unknown = [];
36424
37282
  const rejectUnsupported = (flag) => {
@@ -36430,28 +37288,16 @@ var parseProjectCreateOptions = (args) => {
36430
37288
  overwrite = true;
36431
37289
  continue;
36432
37290
  }
36433
- if (arg === "--repo-root") {
36434
- repoRoot = args[index + 1];
36435
- if (repoRoot === undefined) {
36436
- throw new Error("Missing value for --repo-root.");
36437
- }
36438
- index += 1;
36439
- continue;
36440
- }
36441
- if (arg.startsWith("--repo-root=")) {
36442
- repoRoot = arg.slice("--repo-root=".length);
36443
- continue;
36444
- }
36445
- if (arg === "--project-name") {
36446
- projectName = args[index + 1];
36447
- if (projectName === undefined) {
36448
- throw new Error("Missing value for --project-name.");
37291
+ if (arg === "--change-id") {
37292
+ changeId = args[index + 1];
37293
+ if (changeId === undefined) {
37294
+ throw new Error("Missing value for --change-id.");
36449
37295
  }
36450
37296
  index += 1;
36451
37297
  continue;
36452
37298
  }
36453
- if (arg.startsWith("--project-name=")) {
36454
- projectName = arg.slice("--project-name=".length);
37299
+ if (arg.startsWith("--change-id=")) {
37300
+ changeId = arg.slice("--change-id=".length);
36455
37301
  continue;
36456
37302
  }
36457
37303
  if (arg === "--schub-root" || arg === "--agent-root") {
@@ -36468,7 +37314,103 @@ var parseProjectCreateOptions = (args) => {
36468
37314
  if (unknown.length > 0) {
36469
37315
  throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
36470
37316
  }
36471
- return { repoRoot, projectName, overwrite };
37317
+ if (!changeId) {
37318
+ throw new Error("Provide --change-id.");
37319
+ }
37320
+ return { changeId, overwrite };
37321
+ };
37322
+ var resolveReviewOutput = (schubDir, changeId, output) => {
37323
+ if (output) {
37324
+ return resolve7(schubDir, output);
37325
+ }
37326
+ return join12(schubDir, "changes", changeId, "REVIEW_ME.md");
37327
+ };
37328
+ var runReviewCreate = (args, startDir) => {
37329
+ const options = parseReviewCreateOptions(args);
37330
+ const schubDir = resolveChangeRoot(startDir);
37331
+ const trimmedId = options.changeId.trim();
37332
+ if (!isValidChangeId(trimmedId)) {
37333
+ throw new Error(`Invalid change-id '${options.changeId}'. Use kebab-case or a C-prefixed id (e.g., C001_add-user-auth).`);
37334
+ }
37335
+ const changeId = normalizeChangeId(trimmedId);
37336
+ const changeTitle = options.title?.trim() || readChangeSummary(schubDir, changeId).changeTitle;
37337
+ const outputPath = resolveReviewOutput(schubDir, changeId, options.output);
37338
+ if (existsSync10(outputPath) && !options.overwrite) {
37339
+ throw new Error(`Refusing to overwrite existing file: ${outputPath}`);
37340
+ }
37341
+ mkdirSync9(dirname9(outputPath), { recursive: true });
37342
+ const templatePath = resolveTemplatePath(schubDir, join12("review-proposal", "review-me-template.md"), BUNDLED_REVIEW_TEMPLATE_PATH);
37343
+ const template = readFileSync8(templatePath, "utf8");
37344
+ const rendered = renderChangeTemplate(template, changeTitle || changeId, changeId);
37345
+ writeFileSync6(outputPath, rendered, "utf8");
37346
+ process.stdout.write(`[OK] Wrote REVIEW_ME: ${outputPath}
37347
+ `);
37348
+ };
37349
+ var runReviewComplete = (args, startDir) => {
37350
+ const options = parseReviewCompleteOptions(args);
37351
+ const schubDir = resolveChangeRoot(startDir);
37352
+ const summary = readChangeSummary(schubDir, options.changeId);
37353
+ const reviewPath = join12(summary.changeDir, "REVIEW_ME.md");
37354
+ if (!existsSync10(reviewPath)) {
37355
+ throw new Error(`Review file not found: ${reviewPath}`);
37356
+ }
37357
+ const reviewContent = readFileSync8(reviewPath, "utf8");
37358
+ const templatePath = resolveTemplatePath(schubDir, join12("review-proposal", "q&a-template.md"), BUNDLED_QNA_TEMPLATE_PATH);
37359
+ const template = readFileSync8(templatePath, "utf8");
37360
+ const rendered = renderChangeTemplate(template, summary.changeTitle, summary.changeId).replace("{{REVIEW_CONTENT}}", reviewContent);
37361
+ const outputPath = join12(summary.changeDir, "Q&A.md");
37362
+ if (existsSync10(outputPath) && !options.overwrite) {
37363
+ throw new Error(`Refusing to overwrite existing file: ${outputPath}`);
37364
+ }
37365
+ writeFileSync6(outputPath, rendered, "utf8");
37366
+ unlinkSync(reviewPath);
37367
+ process.stdout.write(`[OK] Wrote Q&A: ${outputPath}
37368
+ `);
37369
+ process.stdout.write(`[NEXT] Ask the LLM to migrate the TODO block in ${outputPath} into the Q&A sections.
37370
+ `);
37371
+ };
37372
+
37373
+ // src/commands/tasks.ts
37374
+ var parseStatusFilter = (value) => {
37375
+ if (!value) {
37376
+ return [...TASK_STATUSES];
37377
+ }
37378
+ const normalized = value.split(",").map((status) => status.trim().toLowerCase()).filter(Boolean);
37379
+ const allowed = new Set(TASK_STATUSES);
37380
+ const invalid = normalized.filter((status) => !allowed.has(status));
37381
+ if (invalid.length > 0) {
37382
+ throw new Error(`Unknown status filter: ${invalid.join(", ")}`);
37383
+ }
37384
+ return normalized;
37385
+ };
37386
+ var parseTaskListOptions = (args) => {
37387
+ let statusValue;
37388
+ let json = false;
37389
+ const unknown = [];
37390
+ for (let index = 0;index < args.length; index += 1) {
37391
+ const arg = args[index];
37392
+ if (arg === "--json") {
37393
+ json = true;
37394
+ continue;
37395
+ }
37396
+ if (arg === "--status") {
37397
+ statusValue = args[index + 1];
37398
+ if (!statusValue) {
37399
+ throw new Error("Missing value for --status.");
37400
+ }
37401
+ index += 1;
37402
+ continue;
37403
+ }
37404
+ if (arg.startsWith("--status=")) {
37405
+ statusValue = arg.slice("--status=".length);
37406
+ continue;
37407
+ }
37408
+ unknown.push(arg);
37409
+ }
37410
+ if (unknown.length > 0) {
37411
+ throw new Error(`Unknown option(s): ${unknown.join(", ")}`);
37412
+ }
37413
+ return { statuses: parseStatusFilter(statusValue), json };
36472
37414
  };
36473
37415
  var parseTaskCreateOptions = (args) => {
36474
37416
  let changeId;
@@ -36542,8 +37484,7 @@ var parseTaskCreateOptions = (args) => {
36542
37484
  const options = { changeId, status, titles, overwrite };
36543
37485
  return options;
36544
37486
  };
36545
- var runTasksList = (args) => {
36546
- const schubDir = resolveSchubDir();
37487
+ var runTasksList = (schubDir, args) => {
36547
37488
  if (!schubDir) {
36548
37489
  throw new Error("No .schub directory found.");
36549
37490
  }
@@ -36554,50 +37495,61 @@ var runTasksList = (args) => {
36554
37495
  `);
36555
37496
  return;
36556
37497
  }
36557
- const lines = tasks.map((task) => `${task.id} ${task.title} (${task.status})`);
37498
+ const lines = tasks.map((task) => {
37499
+ const checklistSuffix = typeof task.checklistRemaining === "number" && typeof task.checklistTotal === "number" ? ` (${task.checklistRemaining}/${task.checklistTotal})` : "";
37500
+ return `${task.id} ${task.title} (${task.status})${checklistSuffix}`;
37501
+ });
36558
37502
  process.stdout.write(`${lines.join(`
36559
37503
  `)}
36560
37504
  `);
36561
37505
  };
36562
- var runTasksCreate = (args) => {
37506
+ var runTasksCreate = (args, startDir) => {
36563
37507
  const options = parseTaskCreateOptions(args);
36564
- const schubDir = resolveChangeRoot(getStartDir());
37508
+ const schubDir = resolveChangeRoot(startDir);
36565
37509
  const created = createTask(schubDir, options);
36566
37510
  for (const taskPath of created) {
36567
37511
  process.stdout.write(`[OK] Wrote task: ${taskPath}
36568
37512
  `);
36569
37513
  }
36570
37514
  };
36571
- var runBiome = (command) => {
36572
- const workspaceRoot = getWorkspaceRoot();
36573
- const biomeArgs = command === "lint" ? ["lint", "."] : ["format", ".", "--write"];
36574
- const result = spawnSync({
36575
- cmd: ["bunx", "@biomejs/biome", ...biomeArgs],
36576
- cwd: workspaceRoot,
36577
- env: process.env
36578
- });
36579
- if (result.stdout && result.stdout.length > 0) {
36580
- process.stdout.write(result.stdout);
36581
- }
36582
- if (result.stderr && result.stderr.length > 0) {
36583
- process.stderr.write(result.stderr);
36584
- }
36585
- process.exitCode = result.exitCode ?? 1;
37515
+ // src/terminal.ts
37516
+ var CLEAR_SCROLLBACK = "\x1B[3J";
37517
+ var CLEAR_SCREEN = "\x1B[2J";
37518
+ var CURSOR_HOME = "\x1B[H";
37519
+ var BLACK_BACKGROUND = "\x1B[40m";
37520
+ var RESET = "\x1B[0m";
37521
+ var terminalPrelude = `${CLEAR_SCROLLBACK}${CLEAR_SCREEN}${CURSOR_HOME}${BLACK_BACKGROUND}`;
37522
+ var terminalReset = RESET;
37523
+ var applyTerminalPrelude = () => {
37524
+ process.stdout.write(terminalPrelude);
36586
37525
  };
36587
- var runChangesCreate = (args) => {
36588
- const options = parseChangeCreateOptions(args);
36589
- const schubDir = resolveChangeRoot(getStartDir());
36590
- const proposalPath = createChange(schubDir, options);
36591
- process.stdout.write(`[OK] Wrote proposal: ${proposalPath}
36592
- `);
37526
+ var applyTerminalReset = () => {
37527
+ process.stdout.write(terminalReset);
36593
37528
  };
36594
- var runProjectCreate = (args) => {
36595
- const options = parseProjectCreateOptions(args);
36596
- const outputs = createProject(getStartDir(), options);
36597
- for (const output of outputs) {
36598
- process.stdout.write(`[OK] Wrote ${output}
37529
+
37530
+ // src/index.ts
37531
+ var HELP_TEXT = `schub [command]
37532
+
37533
+ Commands:
37534
+ changes create Create a change proposal
37535
+ changes status Update change proposal status
37536
+ project create Create project docs
37537
+ tasks create Create task files for a change
37538
+ tasks list List tasks
37539
+ review create Create REVIEW_ME for a change
37540
+ review complete Create Q&A from REVIEW_ME
37541
+ adr create Create an ADR for a change
37542
+ cookbook create Create a cookbook for a change
37543
+ init Initialize .schub and install Codex skills
37544
+ eject Copy bundled skills and templates into .schub
37545
+ ui Launch the interactive dashboard
37546
+ `;
37547
+ var getStartDir = () => process.env.SCHUB_CWD ?? process.cwd();
37548
+ var resolveSchubDir = () => findSchubRoot(getStartDir());
37549
+ var printHelp = (exitCode = 0) => {
37550
+ process.stdout.write(`${HELP_TEXT}
36599
37551
  `);
36600
- }
37552
+ process.exitCode = exitCode;
36601
37553
  };
36602
37554
  var registerTerminalReset = () => {
36603
37555
  process.once("exit", () => {
@@ -36609,7 +37561,7 @@ var runUi = () => {
36609
37561
  registerTerminalReset();
36610
37562
  render_default(import_react29.default.createElement(App2));
36611
37563
  };
36612
- var runCommand = () => {
37564
+ var runCommand = async () => {
36613
37565
  const args = process.argv.slice(2);
36614
37566
  if (args.length === 0) {
36615
37567
  runUi();
@@ -36623,31 +37575,57 @@ var runCommand = () => {
36623
37575
  switch (primary) {
36624
37576
  case "changes":
36625
37577
  if (secondary === "create") {
36626
- runChangesCreate(rest);
37578
+ runChangesCreate(rest, getStartDir());
37579
+ return;
37580
+ }
37581
+ if (secondary === "status") {
37582
+ runChangesStatus(rest, getStartDir());
36627
37583
  return;
36628
37584
  }
36629
37585
  break;
36630
37586
  case "project":
36631
37587
  if (secondary === "create") {
36632
- runProjectCreate(rest);
37588
+ runProjectCreate(rest, getStartDir());
36633
37589
  return;
36634
37590
  }
36635
37591
  break;
36636
37592
  case "tasks":
36637
37593
  if (secondary === "list") {
36638
- runTasksList(rest);
37594
+ runTasksList(resolveSchubDir(), rest);
37595
+ return;
37596
+ }
37597
+ if (secondary === "create") {
37598
+ runTasksCreate(rest, getStartDir());
36639
37599
  return;
36640
37600
  }
37601
+ break;
37602
+ case "review":
36641
37603
  if (secondary === "create") {
36642
- runTasksCreate(rest);
37604
+ runReviewCreate(rest, getStartDir());
37605
+ return;
37606
+ }
37607
+ if (secondary === "complete") {
37608
+ runReviewComplete(rest, getStartDir());
36643
37609
  return;
36644
37610
  }
36645
37611
  break;
36646
- case "lint":
36647
- runBiome("lint");
37612
+ case "adr":
37613
+ if (secondary === "create") {
37614
+ runAdrCreate(rest, getStartDir());
37615
+ return;
37616
+ }
37617
+ break;
37618
+ case "cookbook":
37619
+ if (secondary === "create") {
37620
+ runCookbookCreate(rest, getStartDir());
37621
+ return;
37622
+ }
37623
+ break;
37624
+ case "eject":
37625
+ runEject(args.slice(1), getStartDir());
36648
37626
  return;
36649
- case "format":
36650
- runBiome("format");
37627
+ case "init":
37628
+ await runInit(args.slice(1), getStartDir());
36651
37629
  return;
36652
37630
  case "ui":
36653
37631
  runUi();
@@ -36655,11 +37633,9 @@ var runCommand = () => {
36655
37633
  }
36656
37634
  printHelp(1);
36657
37635
  };
36658
- try {
36659
- runCommand();
36660
- } catch (error) {
37636
+ runCommand().catch((error) => {
36661
37637
  const message = error instanceof Error ? error.message : String(error);
36662
37638
  process.stderr.write(`${message}
36663
37639
  `);
36664
37640
  process.exitCode = 1;
36665
- }
37641
+ });