@hiroleague/taskmanager 0.0.2 → 0.0.3

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 (121) hide show
  1. package/dist/assets/architecture-YZFGNWBL-DoE0KxgG.js +1 -0
  2. package/dist/assets/architectureDiagram-Q4EWVU46-DeuBhy7X.js +36 -0
  3. package/dist/assets/{blockDiagram-DXYQGD6D-DQzEOPT2.js → blockDiagram-DXYQGD6D-BDBy9ns9.js} +1 -1
  4. package/dist/assets/{c4Diagram-AHTNJAMY-B2Yfcwbo.js → c4Diagram-AHTNJAMY-CpqJj_8a.js} +1 -1
  5. package/dist/assets/channel-PHRyjspt.js +1 -0
  6. package/dist/assets/{chunk-2KRD3SAO-C2e-_49I.js → chunk-2KRD3SAO-DEpUsxdZ.js} +1 -1
  7. package/dist/assets/chunk-336JU56O-BGQvSwLk.js +2 -0
  8. package/dist/assets/chunk-426QAEUC-Cl9nQN9c.js +1 -0
  9. package/dist/assets/{chunk-4TB4RGXK-AZq3s1Dh.js → chunk-4TB4RGXK-Dq7aiIrZ.js} +2 -2
  10. package/dist/assets/{chunk-5FUZZQ4R-XEga0hMC.js → chunk-5FUZZQ4R-B_HuuUjf.js} +1 -1
  11. package/dist/assets/{chunk-5PVQY5BW-BrmXs2Gs.js → chunk-5PVQY5BW-cGfZCZGU.js} +2 -2
  12. package/dist/assets/{chunk-67CJDMHE-B1-M78qu.js → chunk-67CJDMHE-BMYAVZfw.js} +1 -1
  13. package/dist/assets/{chunk-7N4EOEYR-D7mYFpz-.js → chunk-7N4EOEYR-Ct-EY7Nc.js} +1 -1
  14. package/dist/assets/{chunk-AA7GKIK3-VWI9k39i.js → chunk-AA7GKIK3-Bd4HFpeo.js} +1 -1
  15. package/dist/assets/{chunk-CIAEETIT-hnu4zamm.js → chunk-CIAEETIT-CrFUkPMT.js} +1 -1
  16. package/dist/assets/{chunk-EDXVE4YY-DxUqDyxy.js → chunk-EDXVE4YY-DMDyt0NF.js} +1 -1
  17. package/dist/assets/{chunk-ENJZ2VHE-BgZKYo1l.js → chunk-ENJZ2VHE-DrWzOrpd.js} +1 -1
  18. package/dist/assets/{chunk-FOC6F5B3-BJsh9nO9.js → chunk-FOC6F5B3-Bemzq96j.js} +1 -1
  19. package/dist/assets/{chunk-ICPOFSXX-BNR1V8rT.js → chunk-ICPOFSXX-DkUVjrLw.js} +5 -5
  20. package/dist/assets/{chunk-K5T4RW27-BLIPdXaZ.js → chunk-K5T4RW27-ALKIf000.js} +5 -5
  21. package/dist/assets/{chunk-KGLVRYIC-DvaW2TkT.js → chunk-KGLVRYIC-Bg6HNTZ-.js} +1 -1
  22. package/dist/assets/{chunk-LIHQZDEY-CUsM0M11.js → chunk-LIHQZDEY-DeyGongE.js} +1 -1
  23. package/dist/assets/{chunk-ORNJ4GCN-CfluNV0_.js → chunk-ORNJ4GCN-Bx83s1bJ.js} +1 -1
  24. package/dist/assets/{chunk-OYMX7WX6-CkWzw4JX.js → chunk-OYMX7WX6-BqRUtRpL.js} +1 -1
  25. package/dist/assets/{chunk-U2HBQHQK-DTJPeU7W.js → chunk-U2HBQHQK-DogcerR6.js} +1 -1
  26. package/dist/assets/{chunk-X2U36JSP-CrTnmMqG.js → chunk-X2U36JSP-CwVWdmZV.js} +1 -1
  27. package/dist/assets/chunk-XPW4576I-DQpNCogT.js +32 -0
  28. package/dist/assets/{chunk-YZCP3GAM-9wq0QKUn.js → chunk-YZCP3GAM-crQSbji9.js} +1 -1
  29. package/dist/assets/{chunk-ZZ45TVLE-D3I1kLlo.js → chunk-ZZ45TVLE-Bk1S1YtS.js} +1 -1
  30. package/dist/assets/classDiagram-6PBFFD2Q-B_TabGaU.js +1 -0
  31. package/dist/assets/classDiagram-v2-HSJHXN6E-CGnZkUWw.js +1 -0
  32. package/dist/assets/clone-D4ka472w.js +1 -0
  33. package/dist/assets/{cose-bilkent-S5V4N54A-BygGvZGW.js → cose-bilkent-S5V4N54A-RBTHUit8.js} +1 -1
  34. package/dist/assets/cytoscape.esm-BGJwlmkf.js +321 -0
  35. package/dist/assets/dagre-B32eYLtm.js +1 -0
  36. package/dist/assets/{dagre-KV5264BT-lveZDhBf.js → dagre-KV5264BT-nX7tuXXn.js} +1 -1
  37. package/dist/assets/diagram-5BDNPKRD-DRxMXlQr.js +10 -0
  38. package/dist/assets/diagram-G4DWMVQ6-CoojevGm.js +24 -0
  39. package/dist/assets/diagram-MMDJMWI5-CWtJyfVW.js +43 -0
  40. package/dist/assets/diagram-TYMM5635-CsDJC4Hq.js +24 -0
  41. package/dist/assets/{erDiagram-SMLLAGMA-dx09stuy.js → erDiagram-SMLLAGMA-Cf7Xtd9A.js} +2 -2
  42. package/dist/assets/{flatten-B2BZ0pzY.js → flatten-CYX_pHZ7.js} +1 -1
  43. package/dist/assets/{flowDiagram-DWJPFMVM-CJi2WISS.js → flowDiagram-DWJPFMVM-DQaeR16a.js} +3 -3
  44. package/dist/assets/{ganttDiagram-T4ZO3ILL-OCTvbRxF.js → ganttDiagram-T4ZO3ILL-8EIcztcH.js} +1 -1
  45. package/dist/assets/gitGraph-7Q5UKJZL-BH9A1SAZ.js +1 -0
  46. package/dist/assets/{gitGraphDiagram-UUTBAWPF-Bjj94M12.js → gitGraphDiagram-UUTBAWPF-DO9ODqYw.js} +1 -1
  47. package/dist/assets/graphlib-bPBqlJKT.js +1 -0
  48. package/dist/assets/identity-Me9aart9.js +1 -0
  49. package/dist/assets/index-oKG1C41_.js +273 -0
  50. package/dist/assets/info-OMHHGYJF-BvKR-zWh.js +1 -0
  51. package/dist/assets/infoDiagram-42DDH7IO-pRTXCm5C.js +2 -0
  52. package/dist/assets/isEmpty-Cu0k-j1j.js +1 -0
  53. package/dist/assets/{ishikawaDiagram-UXIWVN3A-Cnc1bwBo.js → ishikawaDiagram-UXIWVN3A-BP2YE5QI.js} +2 -2
  54. package/dist/assets/{journeyDiagram-VCZTEJTY-BkMxoaPq.js → journeyDiagram-VCZTEJTY-B3l2juoL.js} +1 -1
  55. package/dist/assets/{kanban-definition-6JOO6SKY-CwHbIze0.js → kanban-definition-6JOO6SKY-BpIpEOZZ.js} +4 -4
  56. package/dist/assets/{line-DNzQATGr.js → line-otOkzGl8.js} +1 -1
  57. package/dist/assets/mermaid-parser.core-xWsW24Gq.js +4 -0
  58. package/dist/assets/{mindmap-definition-QFDTVHPH-DswAJiEd.js → mindmap-definition-QFDTVHPH-B9khyC7X.js} +3 -3
  59. package/dist/assets/packet-4T2RLAQJ-D8Dw3nmf.js +1 -0
  60. package/dist/assets/pie-ZZUOXDRM-ZghowlAE.js +1 -0
  61. package/dist/assets/{pieDiagram-DEJITSTG-DgQTCddl.js → pieDiagram-DEJITSTG-v32hL3i7.js} +1 -1
  62. package/dist/assets/{quadrantDiagram-34T5L4WZ-c0iZxo2I.js → quadrantDiagram-34T5L4WZ-DIL3GDFt.js} +1 -1
  63. package/dist/assets/radar-PYXPWWZC-D-PK3JOd.js +1 -0
  64. package/dist/assets/reduce-CImcgAcU.js +1 -0
  65. package/dist/assets/{requirementDiagram-MS252O5E-D1moa23Z.js → requirementDiagram-MS252O5E-D8os2-4y.js} +2 -2
  66. package/dist/assets/{sankeyDiagram-XADWPNL6-woJZoQ58.js → sankeyDiagram-XADWPNL6-BV70D4l5.js} +1 -1
  67. package/dist/assets/{sequenceDiagram-FGHM5R23-Dvhj7HGn.js → sequenceDiagram-FGHM5R23-Cwu8hQW1.js} +1 -1
  68. package/dist/assets/stateDiagram-FHFEXIEX-oYUWv7Fb.js +1 -0
  69. package/dist/assets/stateDiagram-v2-QKLJ7IA2-CFUTpFu-.js +1 -0
  70. package/dist/assets/{timeline-definition-GMOUNBTQ-z-IncVmK.js → timeline-definition-GMOUNBTQ-CxSdKxpL.js} +1 -1
  71. package/dist/assets/treeView-SZITEDCU-uVgaJQzG.js +1 -0
  72. package/dist/assets/treemap-W4RFUUIX-Dcad_9AN.js +1 -0
  73. package/dist/assets/vennDiagram-DHZGUBPP-D4wgD7QI.js +34 -0
  74. package/dist/assets/wardley-RL74JXVD-CFXrK8mx.js +1 -0
  75. package/dist/assets/{wardleyDiagram-NUSXRM2D-D-kouujI.js → wardleyDiagram-NUSXRM2D-5Q201ea3.js} +1 -1
  76. package/dist/assets/{xychartDiagram-5P7HB3ND-D1lnM0pL.js → xychartDiagram-5P7HB3ND-BPZv_axd.js} +3 -3
  77. package/dist/index.html +16 -12
  78. package/package.json +2 -4
  79. package/src/cli/bootstrap/launcher.ts +19 -5
  80. package/src/cli/bootstrap/program.test.ts +46 -0
  81. package/src/cli/bootstrap/program.ts +50 -1
  82. package/src/cli/lib/launcherUi.test.ts +74 -0
  83. package/src/cli/lib/launcherUi.ts +47 -0
  84. package/src/shared/skillsInstall.ts +2 -3
  85. package/dist/assets/architecture-YZFGNWBL-C1MoQeSs.js +0 -1
  86. package/dist/assets/architectureDiagram-Q4EWVU46-DUEfvDBu.js +0 -36
  87. package/dist/assets/channel-yBmN_ln0.js +0 -1
  88. package/dist/assets/classDiagram-6PBFFD2Q-Dx_f-9b7.js +0 -1
  89. package/dist/assets/classDiagram-v2-HSJHXN6E-CSfvZ-nt.js +0 -1
  90. package/dist/assets/clone-CXokakwV.js +0 -1
  91. package/dist/assets/cytoscape.esm-BIYWHPG0.js +0 -321
  92. package/dist/assets/dagre-Do0eD9eI.js +0 -1
  93. package/dist/assets/diagram-5BDNPKRD-Dq5yM_uY.js +0 -10
  94. package/dist/assets/diagram-G4DWMVQ6-D-SYOmKm.js +0 -24
  95. package/dist/assets/diagram-MMDJMWI5-lU5t9BZA.js +0 -43
  96. package/dist/assets/diagram-TYMM5635-6tfUbY3R.js +0 -24
  97. package/dist/assets/gitGraph-7Q5UKJZL-BXTuQaDM.js +0 -1
  98. package/dist/assets/graphlib-BIlXYGdM.js +0 -1
  99. package/dist/assets/identity-D4WOnl_h.js +0 -1
  100. package/dist/assets/index-CZZuue3D.js +0 -304
  101. package/dist/assets/info-OMHHGYJF-BeeKt8-X.js +0 -1
  102. package/dist/assets/infoDiagram-42DDH7IO-wq_opQKO.js +0 -2
  103. package/dist/assets/mermaid-parser.core-DrLhKJ48.js +0 -4
  104. package/dist/assets/packet-4T2RLAQJ-DQ-H9_jd.js +0 -1
  105. package/dist/assets/pie-ZZUOXDRM-BSj0Jsyj.js +0 -1
  106. package/dist/assets/radar-PYXPWWZC-B7-oRPFL.js +0 -1
  107. package/dist/assets/reduce-Uumu9GdR.js +0 -1
  108. package/dist/assets/stateDiagram-FHFEXIEX-Dx5CjenB.js +0 -1
  109. package/dist/assets/stateDiagram-v2-QKLJ7IA2-C_PkrTdc.js +0 -1
  110. package/dist/assets/treeView-SZITEDCU-CFXle9Az.js +0 -1
  111. package/dist/assets/treemap-W4RFUUIX-CAW3vWh8.js +0 -1
  112. package/dist/assets/vennDiagram-DHZGUBPP-CT1ehozU.js +0 -34
  113. package/dist/assets/wardley-RL74JXVD-7q3ju4kc.js +0 -1
  114. package/scripts/postinstall-message.mjs +0 -160
  115. /package/dist/assets/{chunk-4BX2VUAB-ean5NKtU.js → chunk-4BX2VUAB-C70mcfQR.js} +0 -0
  116. /package/dist/assets/{chunk-55IACEB6-CvSRyJqy.js → chunk-55IACEB6-CWfnqcLM.js} +0 -0
  117. /package/dist/assets/{chunk-BSJP7CBP-D8kBlJsf.js → chunk-BSJP7CBP-B0LrXV9y.js} +0 -0
  118. /package/dist/assets/{chunk-FMBD7UC4-DrNhFt1N.js → chunk-FMBD7UC4-_mV71Mwu.js} +0 -0
  119. /package/dist/assets/{chunk-QZHKN3VN-Csp3OYJY.js → chunk-QZHKN3VN-t2nrsegL.js} +0 -0
  120. /package/dist/assets/{katex-8mXVa4k3.js → katex-B2dtGfSp.js} +0 -0
  121. /package/dist/assets/{rough.esm-DtEqI08j.js → rough.esm-DEh6Frf9.js} +0 -0
package/dist/index.html CHANGED
@@ -25,23 +25,27 @@
25
25
  } catch (e) {}
26
26
  })();
27
27
  </script>
28
- <script type="module" crossorigin src="/assets/index-CZZuue3D.js"></script>
28
+ <script type="module" crossorigin src="/assets/index-oKG1C41_.js"></script>
29
29
  <link rel="modulepreload" crossorigin href="/assets/chunk-CFjPhJqf.js">
30
30
  <link rel="modulepreload" crossorigin href="/assets/src-C47h8eAM.js">
31
- <link rel="modulepreload" crossorigin href="/assets/chunk-ICPOFSXX-BNR1V8rT.js">
31
+ <link rel="modulepreload" crossorigin href="/assets/chunk-ICPOFSXX-DkUVjrLw.js">
32
32
  <link rel="modulepreload" crossorigin href="/assets/dist-BXMOO6xX.js">
33
- <link rel="modulepreload" crossorigin href="/assets/identity-D4WOnl_h.js">
34
- <link rel="modulepreload" crossorigin href="/assets/chunk-5PVQY5BW-BrmXs2Gs.js">
35
- <link rel="modulepreload" crossorigin href="/assets/chunk-U2HBQHQK-DTJPeU7W.js">
36
- <link rel="modulepreload" crossorigin href="/assets/chunk-X2U36JSP-CrTnmMqG.js">
37
- <link rel="modulepreload" crossorigin href="/assets/chunk-ZZ45TVLE-D3I1kLlo.js">
38
- <link rel="modulepreload" crossorigin href="/assets/rough.esm-DtEqI08j.js">
39
- <link rel="modulepreload" crossorigin href="/assets/chunk-5FUZZQ4R-XEga0hMC.js">
40
- <link rel="modulepreload" crossorigin href="/assets/chunk-BSJP7CBP-D8kBlJsf.js">
33
+ <link rel="modulepreload" crossorigin href="/assets/identity-Me9aart9.js">
34
+ <link rel="modulepreload" crossorigin href="/assets/chunk-5PVQY5BW-cGfZCZGU.js">
35
+ <link rel="modulepreload" crossorigin href="/assets/chunk-U2HBQHQK-DogcerR6.js">
36
+ <link rel="modulepreload" crossorigin href="/assets/isEmpty-Cu0k-j1j.js">
37
+ <link rel="modulepreload" crossorigin href="/assets/chunk-X2U36JSP-CwVWdmZV.js">
38
+ <link rel="modulepreload" crossorigin href="/assets/chunk-ZZ45TVLE-Bk1S1YtS.js">
39
+ <link rel="modulepreload" crossorigin href="/assets/rough.esm-DEh6Frf9.js">
40
+ <link rel="modulepreload" crossorigin href="/assets/chunk-5FUZZQ4R-B_HuuUjf.js">
41
41
  <link rel="modulepreload" crossorigin href="/assets/path-CIRGLb_6.js">
42
42
  <link rel="modulepreload" crossorigin href="/assets/array-BCJ35G43.js">
43
- <link rel="modulepreload" crossorigin href="/assets/line-DNzQATGr.js">
44
- <link rel="modulepreload" crossorigin href="/assets/chunk-ENJZ2VHE-BgZKYo1l.js">
43
+ <link rel="modulepreload" crossorigin href="/assets/line-otOkzGl8.js">
44
+ <link rel="modulepreload" crossorigin href="/assets/chunk-BSJP7CBP-B0LrXV9y.js">
45
+ <link rel="modulepreload" crossorigin href="/assets/chunk-ENJZ2VHE-DrWzOrpd.js">
46
+ <link rel="modulepreload" crossorigin href="/assets/chunk-336JU56O-BGQvSwLk.js">
47
+ <link rel="modulepreload" crossorigin href="/assets/chunk-426QAEUC-Cl9nQN9c.js">
48
+ <link rel="modulepreload" crossorigin href="/assets/chunk-XPW4576I-DQpNCogT.js">
45
49
  <link rel="stylesheet" crossorigin href="/assets/index-hMFTu7sr.css">
46
50
  </head>
47
51
  <body>
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@hiroleague/taskmanager",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "type": "module",
5
- "description": "Local-only task board app (Bun + Hono + React)",
5
+ "description": "Task Manager for Solo Builders and AI Agents, working as a team",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
@@ -22,7 +22,6 @@
22
22
  "skills",
23
23
  "LICENSE",
24
24
  "README.md",
25
- "scripts/postinstall-message.mjs",
26
25
  "scripts/stubs/node-domexception"
27
26
  ],
28
27
  "overrides": {
@@ -33,7 +32,6 @@
33
32
  "hirotm": "./src/cli/bin/hirotm.ts"
34
33
  },
35
34
  "scripts": {
36
- "postinstall": "node scripts/postinstall-message.mjs",
37
35
  "app": "bun run src/cli/bin/hirotaskmanager.ts",
38
36
  "cli": "bun run src/cli/bin/hirotm.ts",
39
37
  "dev": "concurrently -k -n api,web -c blue,green \"npm run dev:server\" \"npm run dev:client\"",
@@ -29,6 +29,8 @@ import {
29
29
  formatTextPrompt,
30
30
  isAuthInitialized,
31
31
  paintValue,
32
+ printSetupContinuePrompt,
33
+ printSetupNextSteps,
32
34
  printPassphraseHint,
33
35
  printRecoveryKey,
34
36
  printRecoveryKeyExitHint,
@@ -319,7 +321,7 @@ async function waitForRecoveryKeyFile(authDir: string): Promise<string> {
319
321
  return key;
320
322
  }
321
323
 
322
- async function waitForEnterToExitLauncher(): Promise<void> {
324
+ async function waitForEnterKey(): Promise<void> {
323
325
  const rl = createInterface({
324
326
  input: process.stdin,
325
327
  output: process.stdout,
@@ -383,9 +385,21 @@ export function createHirotaskmanagerProgram(): Command {
383
385
  },
384
386
  };
385
387
 
386
- // Safety net: copy bundled skills to ~/.taskmanager/skills/ if
387
- // postinstall was skipped (--ignore-scripts, CI, bunx) or stale.
388
- ensureBundledSkills();
388
+ // Registry installs can skip lifecycle hooks, so setup itself must
389
+ // print the exact `npx skills` commands users should run next.
390
+ const skillsInstalled = ensureBundledSkills();
391
+ if (shouldRunSetup) {
392
+ printSetupNextSteps({
393
+ profileName: selectedProfile,
394
+ skillsInstalled,
395
+ });
396
+ if (setupResult.setupMeta.justFinishedInteractiveSetup) {
397
+ // Keep setup blocked here so users see the required skills step
398
+ // before the server starts and the browser steals focus.
399
+ printSetupContinuePrompt();
400
+ await waitForEnterKey();
401
+ }
402
+ }
389
403
 
390
404
  const launcherConfig = setupResult.config;
391
405
 
@@ -471,7 +485,7 @@ export function createHirotaskmanagerProgram(): Command {
471
485
  const recoveryKey = await waitForRecoveryKeyFile(authDir);
472
486
  printRecoveryKey(recoveryKey);
473
487
  printRecoveryKeyExitHint(runningUrl);
474
- await waitForEnterToExitLauncher();
488
+ await waitForEnterKey();
475
489
  }
476
490
  } finally {
477
491
  if (previousSilentStartup === undefined) {
@@ -0,0 +1,46 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import {
3
+ getHirotmLauncherSetupCommand,
4
+ shouldRequireLauncherSetupForHirotm,
5
+ } from "./program";
6
+
7
+ describe("shouldRequireLauncherSetupForHirotm", () => {
8
+ test("requires launcher setup for installed mode without a saved profile", () => {
9
+ expect(
10
+ shouldRequireLauncherSetupForHirotm({
11
+ runtimeKind: "installed",
12
+ hasInstalledProfileConfig: false,
13
+ }),
14
+ ).toBe(true);
15
+ });
16
+
17
+ test("allows installed mode once the profile config exists", () => {
18
+ expect(
19
+ shouldRequireLauncherSetupForHirotm({
20
+ runtimeKind: "installed",
21
+ hasInstalledProfileConfig: true,
22
+ }),
23
+ ).toBe(false);
24
+ });
25
+
26
+ test("never blocks dev mode on launcher setup", () => {
27
+ expect(
28
+ shouldRequireLauncherSetupForHirotm({
29
+ runtimeKind: "dev",
30
+ hasInstalledProfileConfig: false,
31
+ }),
32
+ ).toBe(false);
33
+ });
34
+ });
35
+
36
+ describe("getHirotmLauncherSetupCommand", () => {
37
+ test("uses the plain launcher command for the default profile", () => {
38
+ expect(getHirotmLauncherSetupCommand("default")).toBe("hirotaskmanager");
39
+ });
40
+
41
+ test("includes the selected profile for named profiles", () => {
42
+ expect(getHirotmLauncherSetupCommand("work")).toBe(
43
+ "hirotaskmanager --profile work",
44
+ );
45
+ });
46
+ });
@@ -8,8 +8,56 @@ import { registerStatusCommands } from "../commands/statuses";
8
8
  import { registerTaskCommands } from "../commands/tasks";
9
9
  import { registerTrashCommands } from "../commands/trash";
10
10
  import { createDefaultCliContext } from "../handlers/context";
11
+ import { hasCliConfigFile, resolveProfileName, resolveRuntimeKind } from "../lib/config";
11
12
  import { syncCliOutputFormatFromGlobals } from "../lib/cliFormat";
12
- import { exitWithError, resetCliOutputFormat } from "../lib/output";
13
+ import { CliError, exitWithError, resetCliOutputFormat } from "../lib/output";
14
+ import { CLI_ERR } from "../types/errors";
15
+
16
+ export function shouldRequireLauncherSetupForHirotm(options: {
17
+ runtimeKind: "installed" | "dev";
18
+ hasInstalledProfileConfig: boolean;
19
+ }): boolean {
20
+ return (
21
+ options.runtimeKind === "installed" &&
22
+ options.hasInstalledProfileConfig === false
23
+ );
24
+ }
25
+
26
+ export function getHirotmLauncherSetupCommand(profileName: string): string {
27
+ return profileName === "default"
28
+ ? "hirotaskmanager"
29
+ : `hirotaskmanager --profile ${profileName}`;
30
+ }
31
+
32
+ function ensureInstalledProfileIsReadyForHirotm(): void {
33
+ const runtimeKind = resolveRuntimeKind();
34
+ const profileName = resolveProfileName({ kind: "installed" });
35
+ const hasInstalledProfileConfig = hasCliConfigFile({
36
+ profile: profileName,
37
+ kind: "installed",
38
+ });
39
+ if (
40
+ !shouldRequireLauncherSetupForHirotm({
41
+ runtimeKind,
42
+ hasInstalledProfileConfig,
43
+ })
44
+ ) {
45
+ return;
46
+ }
47
+
48
+ const setupCommand = getHirotmLauncherSetupCommand(profileName);
49
+ // Package managers can skip lifecycle scripts, so actionable `hirotm`
50
+ // commands must direct users back to the launcher for first-run setup.
51
+ throw new CliError(
52
+ `No installed TaskManager profile found for "${profileName}". Run \`${setupCommand}\` first to create and configure this profile.`,
53
+ 2,
54
+ {
55
+ code: CLI_ERR.missingRequired,
56
+ profile: profileName,
57
+ hint: `Run \`${setupCommand}\` first.`,
58
+ },
59
+ );
60
+ }
13
61
 
14
62
  /**
15
63
  * Build the hirotm Commander program.
@@ -45,6 +93,7 @@ export function createHirotmProgram(): Command {
45
93
  quiet?: boolean;
46
94
  };
47
95
  syncCliOutputFormatFromGlobals(opts);
96
+ ensureInstalledProfileIsReadyForHirotm();
48
97
  });
49
98
 
50
99
  const ctx = createDefaultCliContext();
@@ -0,0 +1,74 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { printSetupContinuePrompt, printSetupNextSteps } from "./launcherUi";
3
+
4
+ async function captureConsoleLog(
5
+ run: () => Promise<void> | void,
6
+ ): Promise<string> {
7
+ const originalLog = console.log;
8
+ const lines: string[] = [];
9
+ console.log = (...args: unknown[]) => {
10
+ lines.push(args.map(String).join(" "));
11
+ };
12
+ try {
13
+ await run();
14
+ } finally {
15
+ console.log = originalLog;
16
+ }
17
+ return `${lines.join("\n")}\n`;
18
+ }
19
+
20
+ describe("printSetupNextSteps", () => {
21
+ test("prints a prominent table with required repo skills install guidance", async () => {
22
+ const stdout = await captureConsoleLog(async () => {
23
+ printSetupNextSteps({
24
+ profileName: "default",
25
+ skillsInstalled: false,
26
+ });
27
+ });
28
+
29
+ expect(stdout).toContain("+-");
30
+ expect(stdout).toContain("REQUIRED BEFORE USING hirotm");
31
+ expect(stdout).toContain("Install AI agent skills now. The hirotm CLI depends on these skills.");
32
+ expect(stdout).toContain("hirotm --help");
33
+ expect(stdout).toContain("1. Repo skills : npx skills add hiro-league/hirotaskmanager");
34
+ expect(stdout).toContain("2. Update later : npx skills update");
35
+ expect(stdout).toContain("npx skills add hiro-league/hirotaskmanager");
36
+ expect(stdout).not.toContain("npx skills add \"$HOME/.taskmanager/skills\"");
37
+ });
38
+
39
+ test("prints local skills command when bundled skills were copied", async () => {
40
+ const stdout = await captureConsoleLog(async () => {
41
+ printSetupNextSteps({
42
+ profileName: "default",
43
+ skillsInstalled: true,
44
+ });
45
+ });
46
+
47
+ expect(stdout).toContain("npx skills add hiro-league/hirotaskmanager");
48
+ expect(stdout).toContain("2. Local skills : npx skills add \"$HOME/.taskmanager/skills\"");
49
+ expect(stdout).toContain("3. Update later : npx skills update");
50
+ expect(stdout).toContain("npx skills add \"$HOME/.taskmanager/skills\"");
51
+ expect(stdout).toContain("npx skills update");
52
+ });
53
+
54
+ test("prints profile-specific CLI guidance for named profiles", async () => {
55
+ const stdout = await captureConsoleLog(async () => {
56
+ printSetupNextSteps({
57
+ profileName: "work",
58
+ skillsInstalled: false,
59
+ });
60
+ });
61
+
62
+ expect(stdout).toContain("hirotm --profile work --help");
63
+ });
64
+ });
65
+
66
+ describe("printSetupContinuePrompt", () => {
67
+ test("prints a separate enter-to-continue message", async () => {
68
+ const stdout = await captureConsoleLog(() => {
69
+ printSetupContinuePrompt();
70
+ });
71
+
72
+ expect(stdout).toContain("Press Enter to continue and start TaskManager...");
73
+ });
74
+ });
@@ -39,6 +39,18 @@ function paintWarning(text: string): string {
39
39
  return paint(out, text, ansi.bold + ansi.yellow);
40
40
  }
41
41
 
42
+ function printAsciiTable(lines: readonly string[]): void {
43
+ const innerWidth = Math.max(76, ...lines.map((line) => line.length));
44
+ const border = ` +-${"-".repeat(innerWidth)}-+`;
45
+ line();
46
+ line(border);
47
+ for (const entry of lines) {
48
+ line(` | ${entry.padEnd(innerWidth)} |`);
49
+ }
50
+ line(border);
51
+ line();
52
+ }
53
+
42
54
  export type SpinnerHandle = {
43
55
  stop: (finalText?: string | null) => void;
44
56
  };
@@ -126,6 +138,41 @@ export function printSavedProfileSummary(opts: {
126
138
  );
127
139
  }
128
140
 
141
+ export function printSetupNextSteps(opts: {
142
+ profileName: string;
143
+ skillsInstalled: boolean;
144
+ }): void {
145
+ const cliHelpCommand =
146
+ opts.profileName === "default"
147
+ ? "hirotm --help"
148
+ : `hirotm --profile ${opts.profileName} --help`;
149
+ const skillLines = [
150
+ "1. Repo skills : npx skills add hiro-league/hirotaskmanager",
151
+ ];
152
+ if (opts.skillsInstalled) {
153
+ skillLines.push("2. Local skills : npx skills add \"$HOME/.taskmanager/skills\"");
154
+ skillLines.push("3. Update later : npx skills update");
155
+ } else {
156
+ skillLines.push("2. Update later : npx skills update");
157
+ }
158
+ const lines = [
159
+ "REQUIRED BEFORE USING hirotm",
160
+ "Install AI agent skills now. The hirotm CLI depends on these skills.",
161
+ "",
162
+ ...skillLines,
163
+ "",
164
+ `After skills install: ${cliHelpCommand}`,
165
+ ];
166
+
167
+ // Package managers may block postinstall hooks, so setup must surface the
168
+ // exact skills commands in a standalone table before startup continues.
169
+ printAsciiTable(lines);
170
+ }
171
+
172
+ export function printSetupContinuePrompt(): void {
173
+ line("Press Enter to continue and start TaskManager...");
174
+ }
175
+
129
176
  export async function printPassphraseHint(): Promise<void> {
130
177
  // Keep the browser handoff to one line because the recovery key prints later from the server.
131
178
  const text =
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Copies bundled skills/ from the installed package into ~/.taskmanager/skills/.
3
- * Used as a safety net in the launcher when postinstall didn't run (e.g.
4
- * --ignore-scripts, CI). The postinstall-message.mjs script has equivalent
5
- * plain-Node logic that runs at npm/bun install time.
3
+ * Used by the launcher because package-manager lifecycle scripts may be blocked
4
+ * or skipped entirely (trusted-package checks, --ignore-scripts, CI).
6
5
  */
7
6
  import {
8
7
  cpSync,
@@ -1 +0,0 @@
1
- import"./chunk-K5T4RW27-BLIPdXaZ.js";import{n as e}from"./chunk-7N4EOEYR-D7mYFpz-.js";export{e as createArchitectureServices};