@indigoai-us/hq-cli 5.125.0 → 5.126.0

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 (57) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/assets/bot-workers/setup/skills/joining-a-team.md +125 -0
  3. package/assets/bot-workers/setup/skills/your-business.md +270 -0
  4. package/assets/bot-workers/setup/worker.yaml +189 -58
  5. package/dist/command-catalog.generated.d.ts +407 -4
  6. package/dist/command-catalog.generated.js +522 -4
  7. package/dist/command-registration-plan.d.ts +6 -0
  8. package/dist/command-registration-plan.js +1 -0
  9. package/dist/commands/bot.d.ts +10 -0
  10. package/dist/commands/bot.js +6 -0
  11. package/dist/commands/lanes.d.ts +75 -0
  12. package/dist/commands/lanes.js +2032 -0
  13. package/dist/commands/mesh.js +37 -9
  14. package/dist/commands/onboard-create-identity.d.ts +26 -0
  15. package/dist/commands/onboard-create-identity.js +23 -0
  16. package/dist/commands/onboard.js +13 -4
  17. package/dist/lib/bot/progress.d.ts +6 -0
  18. package/dist/lib/bot/progress.js +16 -0
  19. package/dist/lib/bot/runtime/grok.d.ts +30 -7
  20. package/dist/lib/bot/runtime/grok.js +86 -8
  21. package/dist/lib/bot/runtime/index.js +15 -8
  22. package/dist/lib/bot/runtime/messages-stream.d.ts +12 -3
  23. package/dist/lib/bot/runtime/messages-stream.js +49 -3
  24. package/dist/lib/lanes/accounts.d.ts +43 -0
  25. package/dist/lib/lanes/accounts.js +128 -0
  26. package/dist/lib/lanes/config.d.ts +56 -0
  27. package/dist/lib/lanes/config.js +351 -0
  28. package/dist/lib/lanes/errors.d.ts +39 -0
  29. package/dist/lib/lanes/errors.js +72 -0
  30. package/dist/lib/lanes/index.d.ts +19 -0
  31. package/dist/lib/lanes/index.js +12 -0
  32. package/dist/lib/lanes/liveness.d.ts +89 -0
  33. package/dist/lib/lanes/liveness.js +273 -0
  34. package/dist/lib/lanes/registry.d.ts +103 -0
  35. package/dist/lib/lanes/registry.js +247 -0
  36. package/dist/lib/lanes/store.d.ts +64 -0
  37. package/dist/lib/lanes/store.js +627 -0
  38. package/dist/lib/lanes/throttle.d.ts +89 -0
  39. package/dist/lib/lanes/throttle.js +297 -0
  40. package/dist/lib/lanes/types.d.ts +193 -0
  41. package/dist/lib/lanes/types.js +217 -0
  42. package/dist/lib/mesh/live/daemon/config.d.ts +27 -0
  43. package/dist/lib/mesh/live/daemon/config.js +75 -0
  44. package/dist/lib/mesh/live/daemon/index.d.ts +4 -3
  45. package/dist/lib/mesh/live/daemon/index.js +3 -3
  46. package/dist/lib/mesh/live/daemon/install.d.ts +143 -1
  47. package/dist/lib/mesh/live/daemon/install.js +444 -2
  48. package/dist/lib/mesh/live/daemon/paths.d.ts +2 -0
  49. package/dist/lib/mesh/live/daemon/paths.js +2 -0
  50. package/dist/lib/scan-packages/index.js +17 -12
  51. package/dist/lib/work-context/config.d.ts +20 -0
  52. package/dist/lib/work-context/config.js +26 -5
  53. package/dist/lib/work-context/reconcile.js +28 -7
  54. package/dist/lib/work-context/windows-acl.d.ts +123 -0
  55. package/dist/lib/work-context/windows-acl.js +425 -0
  56. package/dist/utils/pack-contributions.js +5 -4
  57. package/package.json +1 -1
@@ -3089,11 +3089,11 @@ export const COMMAND_CATALOG = [
3089
3089
  },
3090
3090
  {
3091
3091
  "flags": "--email <email>",
3092
- "description": "Your email (must match Cognito sign-in)"
3092
+ "description": "Your email (default: your HQ sign-in's email; must match it)"
3093
3093
  },
3094
3094
  {
3095
3095
  "flags": "--person-name <name>",
3096
- "description": "Your display name"
3096
+ "description": "Your display name (default: the name on your HQ sign-in)"
3097
3097
  },
3098
3098
  {
3099
3099
  "flags": "--hq-root <path>",
@@ -8398,12 +8398,17 @@ export const COMMAND_CATALOG = [
8398
8398
  "hidden": false,
8399
8399
  "usage": "[options]",
8400
8400
  "arguments": [],
8401
- "options": [],
8401
+ "options": [
8402
+ {
8403
+ "flags": "--hq-root <path>",
8404
+ "description": "HQ tree root (else HQ_ROOT / persisted trusted roots); the Windows task passes this explicitly"
8405
+ }
8406
+ ],
8402
8407
  "subcommands": []
8403
8408
  },
8404
8409
  {
8405
8410
  "name": "install",
8406
- "description": "Install LaunchAgent (macOS) or systemd user unit (Linux)",
8411
+ "description": "Install LaunchAgent (macOS), systemd user unit (Linux), or Scheduled Task (Windows)",
8407
8412
  "aliases": [],
8408
8413
  "hidden": false,
8409
8414
  "usage": "[options]",
@@ -8413,6 +8418,10 @@ export const COMMAND_CATALOG = [
8413
8418
  "flags": "--system-user <user>",
8414
8419
  "description": "Write a root-owned unit template for agent boxes (e.g. ec2-user)"
8415
8420
  },
8421
+ {
8422
+ "flags": "--hq-root <path>",
8423
+ "description": "HQ root to record for the service (else HQ_ROOT, else the nearest HQ root above cwd)"
8424
+ },
8416
8425
  {
8417
8426
  "flags": "--json",
8418
8427
  "description": "Print machine-readable JSON"
@@ -8469,6 +8478,515 @@ export const COMMAND_CATALOG = [
8469
8478
  }
8470
8479
  ]
8471
8480
  },
8481
+ {
8482
+ "name": "lanes",
8483
+ "description": "Create, supervise, and steer worker lanes; routed decision queue",
8484
+ "aliases": [],
8485
+ "hidden": false,
8486
+ "usage": "[options] [command]",
8487
+ "arguments": [],
8488
+ "options": [],
8489
+ "subcommands": [
8490
+ {
8491
+ "name": "create",
8492
+ "description": "Register a lane, run admission, and return immediately",
8493
+ "aliases": [],
8494
+ "hidden": false,
8495
+ "usage": "[options]",
8496
+ "arguments": [],
8497
+ "options": [
8498
+ {
8499
+ "flags": "--company <slug|uid>",
8500
+ "description": "Company slug or cloud uid"
8501
+ },
8502
+ {
8503
+ "flags": "--project <slug>",
8504
+ "description": "HQ project slug"
8505
+ },
8506
+ {
8507
+ "flags": "--story <id>",
8508
+ "description": "Story id from the project's prd.json"
8509
+ },
8510
+ {
8511
+ "flags": "--brief-file <path>",
8512
+ "description": "Path to the lane brief"
8513
+ },
8514
+ {
8515
+ "flags": "--worker <name>",
8516
+ "description": "HQ worker id from the registry"
8517
+ },
8518
+ {
8519
+ "flags": "--provider <name>",
8520
+ "description": "claude | codex | grok"
8521
+ },
8522
+ {
8523
+ "flags": "--account <id>",
8524
+ "description": "Provider account id"
8525
+ },
8526
+ {
8527
+ "flags": "--senior <ref>",
8528
+ "description": "session:<id> | lane:<id> | user"
8529
+ },
8530
+ {
8531
+ "flags": "--timeout <secs>",
8532
+ "description": "Deadline in seconds (warns, does not kill)"
8533
+ },
8534
+ {
8535
+ "flags": "--priority <n>",
8536
+ "description": "Queue priority; higher runs first"
8537
+ },
8538
+ {
8539
+ "flags": "--outpost <id>",
8540
+ "description": "Run on this Outpost instead of the local host"
8541
+ }
8542
+ ],
8543
+ "subcommands": []
8544
+ },
8545
+ {
8546
+ "name": "list",
8547
+ "description": "List lanes",
8548
+ "aliases": [],
8549
+ "hidden": false,
8550
+ "usage": "[options]",
8551
+ "arguments": [],
8552
+ "options": [
8553
+ {
8554
+ "flags": "--company <slug|uid>",
8555
+ "description": "Filter by company"
8556
+ },
8557
+ {
8558
+ "flags": "--project <slug>",
8559
+ "description": "Filter by project"
8560
+ },
8561
+ {
8562
+ "flags": "--story <id>",
8563
+ "description": "Filter by story"
8564
+ },
8565
+ {
8566
+ "flags": "--state <state>",
8567
+ "description": "Filter by state (queued|running|awaiting_input|blocked|done|failed|interrupted|cancelled|killed)"
8568
+ },
8569
+ {
8570
+ "flags": "--senior <ref>",
8571
+ "description": "Filter by senior ref"
8572
+ }
8573
+ ],
8574
+ "subcommands": []
8575
+ },
8576
+ {
8577
+ "name": "show",
8578
+ "description": "Show one lane",
8579
+ "aliases": [],
8580
+ "hidden": false,
8581
+ "usage": "[options] <lane-id>",
8582
+ "arguments": [
8583
+ {
8584
+ "name": "lane-id",
8585
+ "required": true,
8586
+ "variadic": false
8587
+ }
8588
+ ],
8589
+ "options": [],
8590
+ "subcommands": []
8591
+ },
8592
+ {
8593
+ "name": "message",
8594
+ "description": "Send a follow-up message to a lane",
8595
+ "aliases": [],
8596
+ "hidden": false,
8597
+ "usage": "[options] <lane-id>",
8598
+ "arguments": [
8599
+ {
8600
+ "name": "lane-id",
8601
+ "required": true,
8602
+ "variadic": false
8603
+ }
8604
+ ],
8605
+ "options": [
8606
+ {
8607
+ "flags": "--text <msg>",
8608
+ "description": "Message text"
8609
+ },
8610
+ {
8611
+ "flags": "--project <slug>",
8612
+ "description": "Re-point project attribution from this message"
8613
+ },
8614
+ {
8615
+ "flags": "--story <id>",
8616
+ "description": "Re-point story attribution from this message"
8617
+ }
8618
+ ],
8619
+ "subcommands": []
8620
+ },
8621
+ {
8622
+ "name": "reparent",
8623
+ "description": "Rewrite a lane's senior edge",
8624
+ "aliases": [],
8625
+ "hidden": false,
8626
+ "usage": "[options] <lane-id>",
8627
+ "arguments": [
8628
+ {
8629
+ "name": "lane-id",
8630
+ "required": true,
8631
+ "variadic": false
8632
+ }
8633
+ ],
8634
+ "options": [
8635
+ {
8636
+ "flags": "--senior <ref>",
8637
+ "description": "session:<id> | lane:<id> | user"
8638
+ },
8639
+ {
8640
+ "flags": "--reason <text>",
8641
+ "description": "Why the senior changed"
8642
+ }
8643
+ ],
8644
+ "subcommands": []
8645
+ },
8646
+ {
8647
+ "name": "logs",
8648
+ "description": "Print a lane's local logs",
8649
+ "aliases": [],
8650
+ "hidden": false,
8651
+ "usage": "[options] <lane-id>",
8652
+ "arguments": [
8653
+ {
8654
+ "name": "lane-id",
8655
+ "required": true,
8656
+ "variadic": false
8657
+ }
8658
+ ],
8659
+ "options": [
8660
+ {
8661
+ "flags": "--tail <n>",
8662
+ "description": "Last N lines"
8663
+ }
8664
+ ],
8665
+ "subcommands": []
8666
+ },
8667
+ {
8668
+ "name": "stop",
8669
+ "description": "Cancel a queued lane or kill a running one",
8670
+ "aliases": [],
8671
+ "hidden": false,
8672
+ "usage": "[options] <lane-id>",
8673
+ "arguments": [
8674
+ {
8675
+ "name": "lane-id",
8676
+ "required": true,
8677
+ "variadic": false
8678
+ }
8679
+ ],
8680
+ "options": [],
8681
+ "subcommands": []
8682
+ },
8683
+ {
8684
+ "name": "ask",
8685
+ "description": "Queue a mid-run question without blocking the lane",
8686
+ "aliases": [],
8687
+ "hidden": false,
8688
+ "usage": "[options]",
8689
+ "arguments": [],
8690
+ "options": [
8691
+ {
8692
+ "flags": "--question <text>",
8693
+ "description": "Question text"
8694
+ },
8695
+ {
8696
+ "flags": "--context <text>",
8697
+ "description": "Context for the audience"
8698
+ },
8699
+ {
8700
+ "flags": "--option <text>",
8701
+ "description": "Answer choice (repeatable)"
8702
+ },
8703
+ {
8704
+ "flags": "--recommended <text>",
8705
+ "description": "Recommended option"
8706
+ }
8707
+ ],
8708
+ "subcommands": []
8709
+ },
8710
+ {
8711
+ "name": "questions",
8712
+ "description": "Routed decision queue",
8713
+ "aliases": [],
8714
+ "hidden": false,
8715
+ "usage": "[options] [command]",
8716
+ "arguments": [],
8717
+ "options": [],
8718
+ "subcommands": [
8719
+ {
8720
+ "name": "list",
8721
+ "description": "List questions",
8722
+ "aliases": [],
8723
+ "hidden": false,
8724
+ "usage": "[options]",
8725
+ "arguments": [],
8726
+ "options": [
8727
+ {
8728
+ "flags": "--for <ref>",
8729
+ "description": "Who must decide (ref | me | user)"
8730
+ },
8731
+ {
8732
+ "flags": "--from <lane-id>",
8733
+ "description": "Which lane asked"
8734
+ },
8735
+ {
8736
+ "flags": "--company <slug|uid>",
8737
+ "description": "Filter by company"
8738
+ },
8739
+ {
8740
+ "flags": "--project <slug>",
8741
+ "description": "Filter by project"
8742
+ },
8743
+ {
8744
+ "flags": "--story <id>",
8745
+ "description": "Filter by story"
8746
+ },
8747
+ {
8748
+ "flags": "--status <status>",
8749
+ "description": "Filter by status (pending|answered|cancelled|expired)"
8750
+ }
8751
+ ],
8752
+ "subcommands": []
8753
+ },
8754
+ {
8755
+ "name": "show",
8756
+ "description": "Show one question",
8757
+ "aliases": [],
8758
+ "hidden": false,
8759
+ "usage": "[options] <question-id>",
8760
+ "arguments": [
8761
+ {
8762
+ "name": "question-id",
8763
+ "required": true,
8764
+ "variadic": false
8765
+ }
8766
+ ],
8767
+ "options": [],
8768
+ "subcommands": []
8769
+ },
8770
+ {
8771
+ "name": "answer",
8772
+ "description": "Answer a pending question",
8773
+ "aliases": [],
8774
+ "hidden": false,
8775
+ "usage": "[options] <question-id>",
8776
+ "arguments": [
8777
+ {
8778
+ "name": "question-id",
8779
+ "required": true,
8780
+ "variadic": false
8781
+ }
8782
+ ],
8783
+ "options": [
8784
+ {
8785
+ "flags": "--choice <label|N>",
8786
+ "description": "1-based index or option label"
8787
+ },
8788
+ {
8789
+ "flags": "--notes <text>",
8790
+ "description": "Free-text notes stored with the body"
8791
+ },
8792
+ {
8793
+ "flags": "--freeform",
8794
+ "description": "Allow a choice that is not on the menu"
8795
+ }
8796
+ ],
8797
+ "subcommands": []
8798
+ },
8799
+ {
8800
+ "name": "escalate",
8801
+ "description": "Advance a question one hop",
8802
+ "aliases": [],
8803
+ "hidden": false,
8804
+ "usage": "[options] <question-id>",
8805
+ "arguments": [
8806
+ {
8807
+ "name": "question-id",
8808
+ "required": true,
8809
+ "variadic": false
8810
+ }
8811
+ ],
8812
+ "options": [
8813
+ {
8814
+ "flags": "--note <text>",
8815
+ "description": "Note recorded with the escalation"
8816
+ }
8817
+ ],
8818
+ "subcommands": []
8819
+ },
8820
+ {
8821
+ "name": "cancel",
8822
+ "description": "Cancel a pending question",
8823
+ "aliases": [],
8824
+ "hidden": false,
8825
+ "usage": "[options] <question-id>",
8826
+ "arguments": [
8827
+ {
8828
+ "name": "question-id",
8829
+ "required": true,
8830
+ "variadic": false
8831
+ }
8832
+ ],
8833
+ "options": [
8834
+ {
8835
+ "flags": "--reason <text>",
8836
+ "description": "Why it was cancelled"
8837
+ }
8838
+ ],
8839
+ "subcommands": []
8840
+ }
8841
+ ]
8842
+ },
8843
+ {
8844
+ "name": "accounts",
8845
+ "description": "Provider account registry (configured vs logged in)",
8846
+ "aliases": [],
8847
+ "hidden": false,
8848
+ "usage": "[options] [command]",
8849
+ "arguments": [],
8850
+ "options": [],
8851
+ "subcommands": [
8852
+ {
8853
+ "name": "list",
8854
+ "description": "List accounts",
8855
+ "aliases": [],
8856
+ "hidden": false,
8857
+ "usage": "[options]",
8858
+ "arguments": [],
8859
+ "options": [
8860
+ {
8861
+ "flags": "--provider <name>",
8862
+ "description": "claude | codex | grok"
8863
+ }
8864
+ ],
8865
+ "subcommands": []
8866
+ },
8867
+ {
8868
+ "name": "login",
8869
+ "description": "Create a home, run the vendor login, and register the account",
8870
+ "aliases": [],
8871
+ "hidden": false,
8872
+ "usage": "[options] <provider> <account-id>",
8873
+ "arguments": [
8874
+ {
8875
+ "name": "provider",
8876
+ "required": true,
8877
+ "variadic": false
8878
+ },
8879
+ {
8880
+ "name": "account-id",
8881
+ "required": true,
8882
+ "variadic": false
8883
+ }
8884
+ ],
8885
+ "options": [
8886
+ {
8887
+ "flags": "--home <path>",
8888
+ "description": "Account home directory"
8889
+ }
8890
+ ],
8891
+ "subcommands": []
8892
+ },
8893
+ {
8894
+ "name": "enable",
8895
+ "description": "Enable an account without touching credentials",
8896
+ "aliases": [],
8897
+ "hidden": false,
8898
+ "usage": "[options] <provider> <account-id>",
8899
+ "arguments": [
8900
+ {
8901
+ "name": "provider",
8902
+ "required": true,
8903
+ "variadic": false
8904
+ },
8905
+ {
8906
+ "name": "account-id",
8907
+ "required": true,
8908
+ "variadic": false
8909
+ }
8910
+ ],
8911
+ "options": [],
8912
+ "subcommands": []
8913
+ },
8914
+ {
8915
+ "name": "disable",
8916
+ "description": "Disable an account without touching credentials",
8917
+ "aliases": [],
8918
+ "hidden": false,
8919
+ "usage": "[options] <provider> <account-id>",
8920
+ "arguments": [
8921
+ {
8922
+ "name": "provider",
8923
+ "required": true,
8924
+ "variadic": false
8925
+ },
8926
+ {
8927
+ "name": "account-id",
8928
+ "required": true,
8929
+ "variadic": false
8930
+ }
8931
+ ],
8932
+ "options": [
8933
+ {
8934
+ "flags": "--reason <text>",
8935
+ "description": "Why the account is disabled"
8936
+ }
8937
+ ],
8938
+ "subcommands": []
8939
+ }
8940
+ ]
8941
+ },
8942
+ {
8943
+ "name": "sessions",
8944
+ "description": "Session liveness from the work-mesh spool",
8945
+ "aliases": [],
8946
+ "hidden": false,
8947
+ "usage": "[options] [command]",
8948
+ "arguments": [],
8949
+ "options": [],
8950
+ "subcommands": [
8951
+ {
8952
+ "name": "list",
8953
+ "description": "List sessions",
8954
+ "aliases": [],
8955
+ "hidden": false,
8956
+ "usage": "[options]",
8957
+ "arguments": [],
8958
+ "options": [
8959
+ {
8960
+ "flags": "--state <state>",
8961
+ "description": "live | idle | ended | lost"
8962
+ },
8963
+ {
8964
+ "flags": "--company <slug>",
8965
+ "description": "Filter by session meta company_slug"
8966
+ }
8967
+ ],
8968
+ "subcommands": []
8969
+ },
8970
+ {
8971
+ "name": "show",
8972
+ "description": "Show one session's liveness",
8973
+ "aliases": [],
8974
+ "hidden": false,
8975
+ "usage": "[options] <session-id>",
8976
+ "arguments": [
8977
+ {
8978
+ "name": "session-id",
8979
+ "required": true,
8980
+ "variadic": false
8981
+ }
8982
+ ],
8983
+ "options": [],
8984
+ "subcommands": []
8985
+ }
8986
+ ]
8987
+ }
8988
+ ]
8989
+ },
8472
8990
  {
8473
8991
  "name": "bot",
8474
8992
  "description": "Personal local bots that run on this computer with your own model login",
@@ -400,6 +400,12 @@ export declare const REGISTRATION_PLAN: readonly [{
400
400
  readonly parent: "program";
401
401
  readonly module: "./commands/mesh.js";
402
402
  readonly exportName: "registerMeshCommand";
403
+ }, {
404
+ readonly type: "registrar";
405
+ readonly root: "lanes";
406
+ readonly parent: "program";
407
+ readonly module: "./commands/lanes.js";
408
+ readonly exportName: "registerLanesCommand";
403
409
  }, {
404
410
  readonly type: "registrar";
405
411
  readonly root: "bot";
@@ -69,6 +69,7 @@ export const REGISTRATION_PLAN = [
69
69
  { type: "registrar", root: "index", parent: "program", module: "./commands/index-cmd.js", exportName: "registerIndexCommand" },
70
70
  { type: "registrar", root: "doctor", parent: "program", module: "./commands/doctor.js", exportName: "registerDoctorCommand" },
71
71
  { type: "registrar", root: "mesh", parent: "program", module: "./commands/mesh.js", exportName: "registerMeshCommand" },
72
+ { type: "registrar", root: "lanes", parent: "program", module: "./commands/lanes.js", exportName: "registerLanesCommand" },
72
73
  { type: "registrar", root: "bot", parent: "program", module: "./commands/bot.js", exportName: "registerBotCommand" },
73
74
  ];
74
75
  async function executePlan(program, steps) {
@@ -27,6 +27,16 @@ export interface BotRow {
27
27
  lastHeartbeatOk: boolean | null;
28
28
  lastInboxPollAt: string | null;
29
29
  lastInboxPollOk: boolean | null;
30
+ /**
31
+ * The bot is mid-turn right now: it has taken a message and has not finished
32
+ * answering. Read from the bot's own in-flight marker on this machine, so it
33
+ * is true even while the model is still thinking and nothing has been posted
34
+ * yet. Surfaces are what show "thinking"; a progress post in the middle of a
35
+ * turn does not end it.
36
+ */
37
+ busy: boolean;
38
+ /** When the oldest turn still in flight started (ISO), else null. */
39
+ busySince: string | null;
30
40
  /** Present while the coding tool needs a new sign-in before the bot can work. */
31
41
  runtimeSignIn: RuntimeSignInIssue | null;
32
42
  daemonInstalled: boolean;
@@ -1,5 +1,6 @@
1
1
  import { OwnerContextCache, lookupOwnerContext } from "../lib/bot/owner-context.js";
2
2
  import { hasActivePromotion } from "../lib/bot/promotion-receipt.js";
3
+ import { readInflightTurns } from "../lib/bot/inflight.js";
3
4
  import { hasPromotionHold, promotionHoldSummary } from "../lib/bot/promotion-hold.js";
4
5
  /**
5
6
  * `hq bot` — personal local bots (local-bots US-003/US-004/US-005).
@@ -117,6 +118,8 @@ function rowFor(name, opts = {}) {
117
118
  const status = readBotStatus(dir);
118
119
  const pid = status?.pid ?? null;
119
120
  const processAlive = pid !== null && isPidAlive(pid) && status?.state === "running";
121
+ // Turns this bot has taken and not finished: what "thinking" means.
122
+ const inflightTurns = readInflightTurns(dir);
120
123
  let daemonInstalled = false;
121
124
  let daemonLoaded = false;
122
125
  if (opts.withDaemon !== false) {
@@ -147,6 +150,8 @@ function rowFor(name, opts = {}) {
147
150
  lastHeartbeatOk: status?.lastHeartbeatOk ?? null,
148
151
  lastInboxPollAt: status?.lastInboxPollAt ?? null,
149
152
  lastInboxPollOk: status?.lastInboxPollOk ?? null,
153
+ busy: processAlive && inflightTurns.length > 0,
154
+ busySince: processAlive ? (inflightTurns[0]?.startedAt ?? null) : null,
150
155
  runtimeSignIn: status?.runtimeSignIn ?? null,
151
156
  daemonInstalled,
152
157
  daemonLoaded,
@@ -723,6 +728,7 @@ async function runBotStatus(nameArg, opts) {
723
728
  else if (status?.lastInboxPollAt) {
724
729
  console.log(` inbox: last poll ${status.lastInboxPollAt}`);
725
730
  }
731
+ console.log(` answering: ${row.busy ? chalk.green(`yes${row.busySince ? `, since ${row.busySince}` : ""}`) : chalk.gray("no")}`);
726
732
  console.log(` launchd: ${row.daemonInstalled ? (row.daemonLoaded ? "installed, loaded" : "installed, not loaded") : "not installed"}`);
727
733
  console.log(` creds: ${creds ? `present for ${creds.entityUid}` : chalk.red("missing")}`);
728
734
  if (status) {