@wrongstack/cli 1.0.24 → 1.0.27

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 (146) hide show
  1. package/data/providers.json +44 -0
  2. package/dist/{acp-AJWSKWE5.js → acp-M4565YUW.js} +33 -20
  3. package/dist/ascii-mode-SG4PRNLP.js +7 -0
  4. package/dist/{auth-GRBZ7Y3D.js → auth-TE55JF4Z.js} +14 -14
  5. package/dist/{bench-N5K7Z5O3.js → bench-GTLPM22B.js} +2 -2
  6. package/dist/boot/append-system-prompt.d.ts +10 -0
  7. package/dist/boot/ascii-mode.d.ts +12 -0
  8. package/dist/boot/container-wiring.d.ts +4 -2
  9. package/dist/boot/dispatch-singleshot.d.ts +12 -1
  10. package/dist/boot/dispatch-webui.d.ts +2 -0
  11. package/dist/boot/goal-tui-default.d.ts +10 -0
  12. package/dist/boot/mcp-config-flag.d.ts +22 -0
  13. package/dist/boot/piped-stdin.d.ts +40 -0
  14. package/dist/boot/restricted-mode.d.ts +15 -0
  15. package/dist/boot/safe-mode.d.ts +30 -0
  16. package/dist/boot/single-shot-budget.d.ts +30 -0
  17. package/dist/boot/stream-json.d.ts +36 -0
  18. package/dist/boot/structured-output.d.ts +16 -0
  19. package/dist/boot/system-prompt-builder.d.ts +2 -0
  20. package/dist/boot/tool-restriction-flags.d.ts +36 -0
  21. package/dist/boot/worktree-sessions.d.ts +21 -0
  22. package/dist/boot-provider-selection.d.ts +67 -0
  23. package/dist/boot.d.ts +1 -38
  24. package/dist/{chunk-LFMVHT3R.js → chunk-2ERX3RPN.js} +11 -13
  25. package/dist/chunk-4TVYGG6G.js +62 -0
  26. package/dist/chunk-5JYDKG5B.js +154 -0
  27. package/dist/{chunk-3VXYY5JC.js → chunk-5UZBUV2H.js} +3 -19
  28. package/dist/chunk-CZTXF6HY.js +140 -0
  29. package/dist/{chunk-DRM7PSW7.js → chunk-ENRYW73H.js} +527 -381
  30. package/dist/{chunk-SKPDE62W.js → chunk-EPR42SWM.js} +36 -6
  31. package/dist/{chunk-YBUCXXYZ.js → chunk-F5DCFAKI.js} +1 -1
  32. package/dist/chunk-HDMFKTT3.js +157 -0
  33. package/dist/{chunk-PGKJ2OQP.js → chunk-HFZH2XJN.js} +5 -5
  34. package/dist/chunk-HLSHFXTO.js +97 -0
  35. package/dist/{chunk-QFPQXKCG.js → chunk-KOEO4CJG.js} +21 -6
  36. package/dist/chunk-LBPLTTZ6.js +105 -0
  37. package/dist/{chunk-3OCUS3VN.js → chunk-LDCGZJTC.js} +4 -4
  38. package/dist/chunk-LKPEBZBE.js +143 -0
  39. package/dist/chunk-N57IU5FG.js +58 -0
  40. package/dist/{chunk-2EBVTYJR.js → chunk-NRXWOMK7.js} +17 -3
  41. package/dist/chunk-PZQBGUVZ.js +18 -0
  42. package/dist/{chunk-MHEBWVXL.js → chunk-Q4INH2DG.js} +46 -2
  43. package/dist/{chunk-5SEYGOCH.js → chunk-RDGGWMTI.js} +2 -2
  44. package/dist/{chunk-BLD5DSVA.js → chunk-RGFWGUAB.js} +27 -15
  45. package/dist/{chunk-ZZRSG7VK.js → chunk-RZ4ZDRYA.js} +3 -3
  46. package/dist/{chunk-S4FFHDJG.js → chunk-SDJCLEK6.js} +6 -2
  47. package/dist/{chunk-U46QR4WR.js → chunk-TI7KLHYX.js} +132 -3
  48. package/dist/chunk-X756ZS72.js +329 -0
  49. package/dist/{chunk-JF2MULWF.js → chunk-YHYINL47.js} +47 -15
  50. package/dist/{cli-context-34Q5IJRA.js → cli-context-C7RBSWHF.js} +434 -327
  51. package/dist/{cli-main-AELJDBGU.js → cli-main-TQTH73ZK.js} +2948 -2315
  52. package/dist/cli-update-notice.d.ts +2 -1
  53. package/dist/config-doctor.d.ts +1 -1
  54. package/dist/{diag-doctor-WIFJH3XH.js → diag-doctor-BIZAFIAT.js} +2 -2
  55. package/dist/{execution-PYC5FCS4.js → execution-3STBD2U7.js} +2167 -1831
  56. package/dist/execution-chimera-review.d.ts +18 -1
  57. package/dist/fleet/host-types.d.ts +3 -1
  58. package/dist/goal-commands.d.ts +47 -0
  59. package/dist/goal-host.d.ts +1 -14
  60. package/dist/{hq-JTUTFI4L.js → hq-44F4OQH2.js} +9 -8
  61. package/dist/hq-fleet-control.d.ts +36 -0
  62. package/dist/hq-live-status.d.ts +22 -0
  63. package/dist/hq-publisher.d.ts +18 -0
  64. package/dist/hq-server/routes/command-handlers.d.ts +12 -1
  65. package/dist/hq-server/routes/data-handlers.d.ts +1 -1
  66. package/dist/hq-server/socket-credentials.d.ts +63 -0
  67. package/dist/hq-server/upgrade-handler.d.ts +2 -0
  68. package/dist/hq-server/ws.d.ts +24 -0
  69. package/dist/{hq-server-PC7GZMPT.js → hq-server-UIB24LU6.js} +2 -2
  70. package/dist/{hq-service-NW56MUP2.js → hq-service-BMMJAHRT.js} +4 -4
  71. package/dist/import-claude-code-AYG24RG2.js +268 -0
  72. package/dist/index.js +12 -8
  73. package/dist/live-settings-input.d.ts +1 -0
  74. package/dist/{mailbox-serve-WDOCH6KR.js → mailbox-serve-GNGXEQ2R.js} +3 -3
  75. package/dist/{modeldiag-36OGAL5C.js → modeldiag-W7XAE625.js} +9 -9
  76. package/dist/{per-subcommand-help-XE77MTGJ.js → per-subcommand-help-QDAQASPZ.js} +2 -2
  77. package/dist/permission-prompt.d.ts +14 -0
  78. package/dist/permission-rules-view.d.ts +18 -0
  79. package/dist/{permissions-CFDLXETM.js → permissions-PL27UHYD.js} +67 -45
  80. package/dist/{plugin-usage-S5LVGMBW.js → plugin-usage-CIGOOTX3.js} +2 -2
  81. package/dist/{plugins-RHBIVLI7.js → plugins-HQTXUD6A.js} +4 -2
  82. package/dist/preflight.d.ts +1 -1
  83. package/dist/{projects-LMNAGGEU.js → projects-T4CZCA25.js} +3 -6
  84. package/dist/provider-helpers.d.ts +7 -11
  85. package/dist/{providers-models-2CFG46RD.js → providers-models-5Z2PJTEW.js} +5 -5
  86. package/dist/release-asset-download.d.ts +10 -0
  87. package/dist/release-attestation.d.ts +28 -0
  88. package/dist/remote/remote-session.d.ts +64 -0
  89. package/dist/remote/remote-target.d.ts +69 -0
  90. package/dist/remote-GB5VXCCT.js +576 -0
  91. package/dist/{replay-Z3FTJEMM.js → replay-DEI566CW.js} +2 -2
  92. package/dist/services/commit-message.d.ts +2 -1
  93. package/dist/session-move-P2EC2COA.js +44 -0
  94. package/dist/session-move.d.ts +20 -0
  95. package/dist/session-stats.d.ts +10 -0
  96. package/dist/{sessions-config-IQUH2GXT.js → sessions-config-XHLXJ5C3.js} +109 -10
  97. package/dist/short-circuit-flags-5TNTJPQR.js +10 -0
  98. package/dist/slash-commands/command-context.d.ts +15 -5
  99. package/dist/slash-commands/goal-refiner.d.ts +4 -49
  100. package/dist/slash-commands/mcp.d.ts +2 -1
  101. package/dist/slash-commands/permissions.d.ts +4 -0
  102. package/dist/slash-commands/settings-context-mutations.d.ts +5 -0
  103. package/dist/slash-commands/settings-limits-mutations.d.ts +12 -0
  104. package/dist/slash-commands/theme.d.ts +15 -1
  105. package/dist/standalone-auto-update-TOTRGCSA.js +249 -0
  106. package/dist/standalone-auto-update.d.ts +65 -0
  107. package/dist/standalone-update-LZO3MNLH.js +24 -0
  108. package/dist/standalone-update.d.ts +37 -1
  109. package/dist/subcommands/handlers/import-claude-code.d.ts +52 -0
  110. package/dist/subcommands/handlers/permissions.d.ts +9 -3
  111. package/dist/subcommands/handlers/remote.d.ts +6 -0
  112. package/dist/subcommands/handlers/sessions-fleet.d.ts +0 -12
  113. package/dist/subcommands/handlers/version-help.d.ts +5 -0
  114. package/dist/{subcommands-ZTSIN7LG.js → subcommands-BHQYLDSD.js} +2 -2
  115. package/dist/tui-resume-callback.d.ts +18 -0
  116. package/dist/{typesafe-HVEVPA6R.js → typesafe-U7YB2RRV.js} +5 -5
  117. package/dist/{typesafe-topic-replay-4W73BOLV.js → typesafe-topic-replay-ZILIU3WS.js} +18 -2
  118. package/dist/{update-7XIOEXTD.js → update-TDZX4IL2.js} +4 -4
  119. package/dist/{update-check-2POMBHFB.js → update-check-J5ZVKS73.js} +3 -3
  120. package/dist/version-JB2UAV2A.js +11 -0
  121. package/dist/version-help-XJJQ7YSH.js +10 -0
  122. package/dist/webui-server/route-contexts.d.ts +1 -1
  123. package/dist/webui-server/session-start-payload.d.ts +5 -1
  124. package/dist/{webui-server-L2SICPTB.js → webui-server-GCXIO3JY.js} +515 -365
  125. package/dist/webui-server-lifecycle.d.ts +57 -0
  126. package/dist/webui-server-options.d.ts +10 -0
  127. package/dist/webui-server.d.ts +0 -14
  128. package/dist/wiring/brain-and-orchestration.d.ts +3 -1
  129. package/dist/wiring/cli-prompt-and-tools-setup.d.ts +9 -0
  130. package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
  131. package/dist/wiring/command-host-state.d.ts +2 -0
  132. package/dist/wiring/hq-telemetry.d.ts +12 -0
  133. package/dist/wiring/lifecycle-plugins.d.ts +4 -2
  134. package/dist/wiring/metrics.d.ts +9 -1
  135. package/dist/wiring/pipeline.d.ts +2 -7
  136. package/dist/wiring/plugins.d.ts +3 -0
  137. package/dist/wiring/provider-status.d.ts +1 -0
  138. package/dist/wiring/provider-utility-tools.d.ts +3 -1
  139. package/package.json +29 -28
  140. package/dist/chunk-2BKFWIER.js +0 -98
  141. package/dist/chunk-424ORSE7.js +0 -56
  142. package/dist/chunk-OWNC7LMD.js +0 -78
  143. package/dist/chunk-QBBF7GIK.js +0 -65
  144. package/dist/short-circuit-flags-SDT53OML.js +0 -10
  145. package/dist/standalone-update-MW47J3AK.js +0 -164
  146. package/dist/version-help-WZ623NWM.js +0 -10
@@ -19,6 +19,18 @@ type Config = ExecuteDeps['core']['config'];
19
19
  * direct test.
20
20
  */
21
21
  export declare function normalizeFileKeyForCitation(raw: string, cwd: string): string;
22
+ /**
23
+ * Operator-facing store-maintenance knobs, read live from `config` so a hot
24
+ * config edit is picked up on the next review completion. Deliberately narrower
25
+ * than core's `ReviewStoreMaintenanceOptions`: the CLI owns *reading config*,
26
+ * core owns *interpreting it* (day→ms, `0` = disabled, garbage = default).
27
+ */
28
+ type ChimeraStoreMaintenanceOptions = {
29
+ /** Cap for non-terminal (`open`/`actioned`) review rows, in days. */
30
+ openRetentionDays?: number | undefined;
31
+ /** Cap for non-terminal (`active`/`triaged`/`in_progress`) findings, in days. */
32
+ activeRetentionDays?: number | undefined;
33
+ };
22
34
  type InstallChimeraReviewHandlerOptions = {
23
35
  events: Events;
24
36
  director: Director | null | undefined;
@@ -36,7 +48,12 @@ type InstallChimeraReviewHandlerOptions = {
36
48
  * `packages/core/src/coordination/provider-status-tracker.ts`.
37
49
  */
38
50
  statusTracker?: ProviderModelStatusTracker | undefined;
39
- persistReview?: ((payload: ChimeraReviewCompletePayload, projectDir: string) => Promise<void>) | undefined;
51
+ /**
52
+ * Persistence seam, injectable for tests. The third argument carries the
53
+ * operator's store-maintenance knobs resolved from `config` at call time, so
54
+ * a hot config edit applies to the next completion. Test doubles may ignore it.
55
+ */
56
+ persistReview?: ((payload: ChimeraReviewCompletePayload, projectDir: string, maintenance?: ChimeraStoreMaintenanceOptions) => Promise<void>) | undefined;
40
57
  trackWork: (work: Promise<void>) => void;
41
58
  /** Optional session-teardown chain — the wildcard listener disposer is
42
59
  * pushed here so the registration is released when the session ends. */
@@ -3,7 +3,7 @@ import type { BrainArbiter, ProviderModelStatusTracker } from '@wrongstack/core/
3
3
  import type { HookRunner } from '@wrongstack/core/hooks';
4
4
  import type { Container, EventBus } from '@wrongstack/core/kernel';
5
5
  import type { ProviderRegistry, ToolRegistry } from '@wrongstack/core/registry';
6
- import type { ConfigStore, ModelsRegistry, Renderer, SecretScrubber, SessionWriter, SkillLoader, SystemPromptBuilder, TokenCounter } from '@wrongstack/core/types';
6
+ import type { ConfigStore, ModelsRegistry, Renderer, SecretScrubber, SessionWriter, SkillLoader, SystemPromptBuilder, TokenCounter, Tracer } from '@wrongstack/core/types';
7
7
  export interface MultiAgentDeps {
8
8
  container: Container;
9
9
  toolRegistry: ToolRegistry;
@@ -23,6 +23,8 @@ export interface MultiAgentDeps {
23
23
  projectRoot: string;
24
24
  cwd: string;
25
25
  secretScrubber: SecretScrubber;
26
+ /** OTLP tracer shared with the leader, so worker runs join its traces. */
27
+ tracer?: Tracer | undefined;
26
28
  /** Loader used to resolve the roster's per-role skill names. */
27
29
  skillLoader?: SkillLoader | undefined;
28
30
  renderer?: Renderer | undefined;
@@ -0,0 +1,47 @@
1
+ /** Async `fs.access`-style existence check — never throws. */
2
+ export declare function pathExists(p: string): Promise<boolean>;
3
+ /**
4
+ * Cap on captured command output. Verification commands (`pnpm test` across
5
+ * a large monorepo) can emit tens of MB on a verbose run — accumulating the
6
+ * full transcript spikes the host heap for output nothing ever reads in
7
+ * full. runCmd keeps the TAIL (the failure summary lives at the end of a
8
+ * test run); gitText keeps the head (its commands are tiny).
9
+ */
10
+ export declare const MAX_CMD_OUTPUT = 200000;
11
+ /** Run a git command, returning trimmed stdout (empty string on failure). */
12
+ export declare function gitText(args: string[], cwd: string): Promise<{
13
+ code: number;
14
+ out: string;
15
+ }>;
16
+ export declare function isGitRepo(cwd: string): Promise<boolean>;
17
+ export declare const GOAL_BASE_SAFE_CMDS: ReadonlySet<string>;
18
+ export declare let goalAllowed: Set<string>;
19
+ /**
20
+ * Extend/trim the autonomous goal command allowlist from the user's exec
21
+ * policy. Mirrors `configureExecPolicy` but keeps goal's narrower base.
22
+ * Idempotent (always rebuilt from the base).
23
+ */
24
+ export declare function configureGoalPolicy(opts?: {
25
+ allow?: readonly string[] | undefined;
26
+ deny?: readonly string[] | undefined;
27
+ }): void;
28
+ /** Reset the goal allowlist to its built-in base (tests / re-init). */
29
+ export declare function resetGoalPolicy(): void;
30
+ /** Whether `cmd` may run in autonomous goal verification. */
31
+ export declare function isGoalCommandAllowed(cmd: string): boolean;
32
+ export declare const DESTRUCTIVE_PATTERNS: readonly RegExp[];
33
+ /** Run an arbitrary command, capturing combined stdout+stderr. */
34
+ export declare function runCmd(cmd: string, args: string[], cwd: string, shell?: boolean): Promise<{
35
+ code: number;
36
+ out: string;
37
+ }>;
38
+ /**
39
+ * Detect the project's package manager from lockfiles at the repo root.
40
+ * Async so the verify-step boot path doesn't block the event loop on `stat`
41
+ * for missing files in CWD or in monorepo setups where the lockfile lives
42
+ * several levels up.
43
+ */
44
+ export declare function detectPackageManager(root: string): Promise<string>;
45
+ /** Read package.json scripts for a directory (empty on any failure). */
46
+ export declare function readScripts(cwd: string): Promise<Record<string, string>>;
47
+ //# sourceMappingURL=goal-commands.d.ts.map
@@ -1,3 +1,4 @@
1
+ export { configureGoalPolicy, isGoalCommandAllowed, resetGoalPolicy } from './goal-commands.js';
1
2
  /**
2
3
  * Goal host wiring for the CLI.
3
4
  *
@@ -20,19 +21,6 @@ import { type PhaseGraph, type PhaseProgress } from '@wrongstack/core/goal';
20
21
  import type { EventBus } from '@wrongstack/core/kernel';
21
22
  import type { Config, TaskNode } from '@wrongstack/core/types';
22
23
  import type { MultiAgentHost } from './multi-agent.js';
23
- /**
24
- * Extend/trim the autonomous goal command allowlist from the user's exec
25
- * policy. Mirrors `configureExecPolicy` but keeps goal's narrower base.
26
- * Idempotent (always rebuilt from the base).
27
- */
28
- export declare function configureGoalPolicy(opts?: {
29
- allow?: readonly string[] | undefined;
30
- deny?: readonly string[] | undefined;
31
- }): void;
32
- /** Reset the goal allowlist to its built-in base (tests / re-init). */
33
- export declare function resetGoalPolicy(): void;
34
- /** Whether `cmd` may run in autonomous goal verification. */
35
- export declare function isGoalCommandAllowed(cmd: string): boolean;
36
24
  export interface GoalHostDeps {
37
25
  multiAgentHost: MultiAgentHost;
38
26
  /** Read the *current* Config lazily (it may be patched, e.g. YOLO toggles). */
@@ -103,5 +91,4 @@ export interface GoalHostHooks {
103
91
  onWorktree: (action: 'list' | 'merge' | 'prune' | 'clean', target?: string) => Promise<string>;
104
92
  }
105
93
  export declare function createGoalHost(deps: GoalHostDeps): GoalHostHooks;
106
- export {};
107
94
  //# sourceMappingURL=goal-host.d.ts.map
@@ -1,6 +1,3 @@
1
- import {
2
- parseTokenTtlValue
3
- } from "./chunk-UZ2TMHNH.js";
4
1
  import {
5
2
  resolveHqPasswordInput
6
3
  } from "./chunk-AUQDGU5D.js";
@@ -11,6 +8,9 @@ import {
11
8
  import {
12
9
  parseHqIpAllowlist
13
10
  } from "./chunk-Q7E3BPDU.js";
11
+ import {
12
+ parseTokenTtlValue
13
+ } from "./chunk-UZ2TMHNH.js";
14
14
 
15
15
  // src/subcommands/handlers/hq.ts
16
16
  import {
@@ -316,7 +316,7 @@ var hqCmd = async (args, deps) => {
316
316
  return hqAlertsCmd(args.slice(1), deps);
317
317
  }
318
318
  if (sub === "service") {
319
- const { hqServiceCmd } = await import("./hq-service-NW56MUP2.js");
319
+ const { hqServiceCmd } = await import("./hq-service-BMMJAHRT.js");
320
320
  return hqServiceCmd(args.slice(1), deps);
321
321
  }
322
322
  if (sub === "help" || sub === "--help") {
@@ -329,7 +329,7 @@ var hqCmd = async (args, deps) => {
329
329
  return 1;
330
330
  };
331
331
  async function startServer(deps) {
332
- const { startHqServer } = await import("./hq-server-PC7GZMPT.js");
332
+ const { startHqServer } = await import("./hq-server-UIB24LU6.js");
333
333
  const dataDir = resolveDataDir(deps);
334
334
  const flags = deps.flags ?? {};
335
335
  const rawPublicUrl = typeof flags["hq-public-url"] === "string" ? flags["hq-public-url"] : process.env.WRONGSTACK_HQ_PUBLIC_URL;
@@ -549,8 +549,9 @@ async function hqTokenCmd(args, deps) {
549
549
  }
550
550
  var TOKEN_CAPABILITIES = {
551
551
  // `control.approve` is grantable but never default — see
552
- // DEFAULT_TOKEN_CAPABILITIES below.
553
- browser: ["control.enqueue", "control.approve"],
552
+ // DEFAULT_TOKEN_CAPABILITIES below. `control.approve.once` is the narrower
553
+ // grant: yes/no on a single prompt, no persistent `always`/`deny` policy.
554
+ browser: ["control.enqueue", "control.approve", "control.approve.once"],
554
555
  client: ["telemetry.publish", "control.execute"]
555
556
  };
556
557
  var DEFAULT_TOKEN_CAPABILITIES = {
@@ -1003,4 +1004,4 @@ export {
1003
1004
  hqCmd,
1004
1005
  resolveAuditActor
1005
1006
  };
1006
- //# sourceMappingURL=hq-JTUTFI4L.js.map
1007
+ //# sourceMappingURL=hq-44F4OQH2.js.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * HQ's fleet commands (`abort fleet`, `abort <agent>`) against a Director.
3
+ *
4
+ * Shared by the CLI host's own HQ connection and the embedded WebUI's per-tab
5
+ * presence, so both apply the same scoping rule.
6
+ *
7
+ * @module hq-fleet-control
8
+ */
9
+ import { type Director } from '@wrongstack/core/coordination';
10
+ export interface HqFleetScope {
11
+ /**
12
+ * `true` when several conversations share this Director (the WebUI host,
13
+ * one per tab). Then `abort fleet` may only ever reach the named session's
14
+ * workers — stopping another tab's fleet is worse than stopping nothing.
15
+ *
16
+ * A single-conversation host (TUI, REPL, one-shot) keeps the process-wide
17
+ * sweep as its fallback: after an in-place `/resume` the leader's older
18
+ * workers still carry the boot session as their origin, so a strictly
19
+ * scoped sweep would find none and silently leave them running.
20
+ */
21
+ multiConversation: boolean;
22
+ }
23
+ /** Stop the named session's workers; returns how many were stopped. */
24
+ export declare function killHqSessionFleet(director: Director | null, sessionId: string | undefined, scope: HqFleetScope): Promise<number>;
25
+ /** Terminate one subagent by id. Ids are process-unique, so no session check. */
26
+ export declare function terminateHqAgent(director: Director | null, subagentId: string): Promise<boolean>;
27
+ /** Spawn a roster (or ad-hoc) subagent owned by `sessionId`. */
28
+ export declare function spawnHqAgent(director: Director | null, sessionId: string, role: string, task?: string, maxIterations?: number): Promise<string>;
29
+ /** The three HQ fleet hooks, bound to a Director that may appear later. */
30
+ export interface HqFleetControl {
31
+ killFleet(sessionId?: string): Promise<number>;
32
+ terminateAgent(subagentId: string): Promise<boolean>;
33
+ spawnAgent(role: string, task?: string, maxIterations?: number, sessionId?: string): Promise<string>;
34
+ }
35
+ export declare function createHqFleetControl(getDirector: () => Director | null, defaultSessionId: () => string, scope: HqFleetScope): HqFleetControl;
36
+ //# sourceMappingURL=hq-fleet-control.d.ts.map
@@ -0,0 +1,22 @@
1
+ /**
2
+ * What THIS process's HQ connection is doing right now.
3
+ *
4
+ * `/hq status` used to describe only the configuration, which answers "where
5
+ * would a new session connect", not "is this terminal on HQ". The CLI host's
6
+ * telemetry registers a probe here; one host per process, so a module slot is
7
+ * the honest shape.
8
+ *
9
+ * @module hq-live-status
10
+ */
11
+ export interface HqLiveConnectionStatus {
12
+ clientId: string;
13
+ projectId: string;
14
+ connected: boolean;
15
+ queuedFrames: number;
16
+ sessionId?: string | undefined;
17
+ }
18
+ /** Install the probe; returns an uninstall that only removes THIS probe. */
19
+ export declare function setHqLiveStatusProbe(next: () => HqLiveConnectionStatus | undefined): () => void;
20
+ /** `undefined` when no host registered, or HQ is off for this process. */
21
+ export declare function readHqLiveStatus(): HqLiveConnectionStatus | undefined;
22
+ //# sourceMappingURL=hq-live-status.d.ts.map
@@ -10,7 +10,25 @@ export interface CliHqConnection {
10
10
  }
11
11
  interface CliHqConnectionOptions extends CliHqPublisherOptions {
12
12
  onConnect?: ((publisher: HqPublisher) => void) | undefined;
13
+ /**
14
+ * Called when a publisher is retired without an immediate replacement —
15
+ * HQ was turned off (or its endpoint removed) in the live config. Hosts
16
+ * stop the bridges they bound in `onConnect`.
17
+ */
18
+ onDisconnect?: (() => void) | undefined;
13
19
  retryIntervalMs?: number | undefined;
20
+ /**
21
+ * The LIVE app config. `appConfig` is a snapshot taken at boot; with this
22
+ * set, `/hq set|token|on|off|clear` take effect on the running connection
23
+ * within one retry interval instead of at the next session start.
24
+ */
25
+ getAppConfig?: (() => CliHqPublisherOptions['appConfig']) | undefined;
26
+ /**
27
+ * `false` for an AUXILIARY connection in a process whose host connection
28
+ * already syncs the project's Kanban boards. Two syncs in one process are
29
+ * two writers applying the same remote snapshots to the same board files.
30
+ */
31
+ ownKanbanSync?: boolean | undefined;
14
32
  }
15
33
  export declare function createCliHqPublisher(options: CliHqPublisherOptions): HqPublisher | undefined;
16
34
  export declare function startCliHqConnection(options: CliHqConnectionOptions): CliHqConnection;
@@ -1,7 +1,18 @@
1
1
  import type * as http from 'node:http';
2
- import type { HqCommandAuditLog } from '@wrongstack/core/hq';
2
+ import type { HqCommand, HqCommandAuditLog } from '@wrongstack/core/hq';
3
3
  import type { TrustBoundary } from '@wrongstack/core/security';
4
4
  import type { WebSocket } from 'ws';
5
5
  import type { ConnectedClient, HqRouterMutableAuth, HqSessionEntry } from '../types.js';
6
6
  export declare function handleApiCommand(req: http.IncomingMessage, res: http.ServerResponse, url: URL, mutableAuth: HqRouterMutableAuth, sessions: Map<string, HqSessionEntry>, clients: Map<WebSocket, ConnectedClient>, browsers: Set<WebSocket>, auditLog: HqCommandAuditLog, trustBoundary: TrustBoundary): Promise<void>;
7
+ /**
8
+ * Whether a credential may answer a prompt.
9
+ *
10
+ * `control.approve` answers anything. `control.approve.once` — what the mobile
11
+ * login carries — may release or refuse THIS call, or answer an ask_user
12
+ * question, but never send `always`/`deny`, which write persistent policy onto
13
+ * the machine: that is not a decision to hand to a phone's cookie. Before this
14
+ * the mobile session had no answer rights at all while its Attention view
15
+ * offered Allow/Deny buttons, so every tap came back 403.
16
+ */
17
+ export declare function credentialMayAnswer(capabilities: readonly string[] | undefined, command: HqCommand): boolean;
7
18
  //# sourceMappingURL=command-handlers.d.ts.map
@@ -3,6 +3,6 @@ import type { createHqPersistence } from '@wrongstack/core/hq';
3
3
  import type { WebSocket } from 'ws';
4
4
  import type { ConnectedClient } from '../types.js';
5
5
  export declare function handleApiProjectDetail(_req: http.IncomingMessage, res: http.ServerResponse, url: URL, clients: Map<WebSocket, ConnectedClient>): Promise<void>;
6
- export declare function handleApiEvents(req: http.IncomingMessage, res: http.ServerResponse, persistence: ReturnType<typeof createHqPersistence>): Promise<void>;
6
+ export declare function handleApiEvents(req: http.IncomingMessage, res: http.ServerResponse, persistence: ReturnType<typeof createHqPersistence>, resolveMachineClientIds?: (machineId: string) => ReadonlySet<string>): Promise<void>;
7
7
  export declare function handleApiTrendsCost(req: http.IncomingMessage, res: http.ServerResponse, persistence: ReturnType<typeof createHqPersistence>): Promise<void>;
8
8
  //# sourceMappingURL=data-handlers.d.ts.map
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Credential enforcement for HQ sockets that are ALREADY open.
3
+ *
4
+ * Neither side of a WebSocket re-presents its credential after the upgrade,
5
+ * so every rule here is the only enforcement that credential gets once the
6
+ * socket is live: revocation notices, expiry that happens with the clock
7
+ * rather than with an auth.json write, and client tokens that stopped being
8
+ * live.
9
+ *
10
+ * @module hq-server/socket-credentials
11
+ */
12
+ import { type HqToken } from '@wrongstack/core/hq';
13
+ import { WebSocket } from 'ws';
14
+ import type { HqRouterMutableAuth, HqSessionEntry } from './types.js';
15
+ export interface HqSocketCredentialState {
16
+ mutableAuth: HqRouterMutableAuth;
17
+ sessions: Map<string, HqSessionEntry>;
18
+ browsers: Set<WebSocket>;
19
+ /** Session that authorized each cookie-authenticated browser socket. */
20
+ browserSocketSessions: Map<WebSocket, string>;
21
+ /** Token each `/ws/client` socket authenticated with (absent in open mode). */
22
+ clientSocketTokens: Map<WebSocket, HqToken | undefined>;
23
+ /**
24
+ * Browser-token verifier each bare loopback `?token=` `/ws/browser` socket
25
+ * authenticated with. Those sockets have no session, so the session sweep
26
+ * never saw them: one kept streaming after its token expired by the clock
27
+ * (H-3, security-check 2026-09-26). Optional for callers that predate it.
28
+ */
29
+ browserSocketTokenKeys?: Map<WebSocket, string> | undefined;
30
+ }
31
+ export interface HqSocketCredentialEnforcer {
32
+ /**
33
+ * Tell the browsers a token revocation can concern.
34
+ *
35
+ * This ONLY announces; it deliberately does not close. The auth.json
36
+ * watcher owns eviction and does it precisely (it deletes the sessions
37
+ * whose `tokenId` is no longer live, and distinguishes a password change
38
+ * from a token change). Because the revocation hook fires from
39
+ * `authState.apply`, which the watcher calls before its close loop, the
40
+ * browser still learns why it is about to be disconnected.
41
+ *
42
+ * A socket bound to a password (or mobile) session, or to a session minted
43
+ * from a DIFFERENT token, is untouched by the revocation — telling it anyway
44
+ * made every password-signed dashboard re-validate and, having no stored
45
+ * token to re-mint, sign itself out. A socket with no recorded session
46
+ * authenticated with a bare `?token=` the server cannot attribute, so it is
47
+ * told and re-validates on its own (fail closed).
48
+ */
49
+ announceRevokedTokens(keys: readonly string[], ids: readonly string[]): void;
50
+ /** Close every `/ws/client` socket whose credential is no longer live. */
51
+ closeUnauthorizedClientSockets(): void;
52
+ /**
53
+ * Credentials also die with the clock. The watcher reacts to file changes
54
+ * only, so before this a client token or a token-backed browser session
55
+ * that reached its `expiresAt` kept its open socket (telemetry in, commands
56
+ * out) until the process restarted.
57
+ */
58
+ sweepExpiredSocketCredentials(now?: number): void;
59
+ /** Close the browser sockets bound to a session that was just removed. */
60
+ closeSessionSockets(sessionId: string, reason: string): void;
61
+ }
62
+ export declare function createHqSocketCredentialEnforcer(state: HqSocketCredentialState): HqSocketCredentialEnforcer;
63
+ //# sourceMappingURL=socket-credentials.d.ts.map
@@ -28,6 +28,8 @@ interface HqUpgradeHandlerDeps {
28
28
  * the revocation path treats that absence as "affected" (fail closed).
29
29
  */
30
30
  browserSocketSessions: Map<WebSocket, string>;
31
+ /** Browser-token verifier behind each bare `?token=` browser socket (H-3). */
32
+ browserSocketTokenKeys?: Map<WebSocket, string> | undefined;
31
33
  browsers: Set<WebSocket>;
32
34
  eventLog: import('@wrongstack/core/hq').HqEventEnvelope[];
33
35
  transcripts: Map<string, TranscriptRing>;
@@ -10,6 +10,30 @@ export { fanoutKanbanDelta } from './ws-client-events.js';
10
10
  export { detectLeaderLoss } from './ws-leader.js';
11
11
  export { handleClientResume } from './ws-resume.js';
12
12
  export declare function handleBrowser(ws: WebSocket, snapshotBroadcaster: HqSnapshotBroadcaster, browsers: Set<WebSocket>, eventLog: HqEventEnvelope[]): void;
13
+ /**
14
+ * Resolve every command the disconnecting client never picked up.
15
+ *
16
+ * The queue lives on the per-socket `ConnectedClient`, so it dies with the
17
+ * socket: a command enqueued in the window between the operator's dispatch and
18
+ * the next 500 ms `command_poll` is simply gone, and nothing re-queues it on
19
+ * the replacement connection. Left alone, its audit row stayed `queued`
20
+ * forever — the Control rail showed a command as pending that will never run,
21
+ * which is the one thing an operator must not have to guess about.
22
+ *
23
+ * `status: 'queued'` in the audit log is the exact undelivered set: the poll
24
+ * handler flips a command to `delivered` the moment it is put on the wire, so
25
+ * anything still `queued` never reached the client. Delivered-but-unacked
26
+ * commands are deliberately left alone — those DID run, and the ack may simply
27
+ * have been in flight when the socket closed.
28
+ *
29
+ * EVERY path that removes a client from `clients` must call this. The socket's
30
+ * own `close` handler finds the client through `clients.get(ws)`, so a path
31
+ * that deletes the entry first — the heartbeat-timeout eviction, the
32
+ * sessionless-surface eviction, the supersede loop — leaves that handler with
33
+ * nothing to resolve, and the rows it owned stayed `queued` forever. Those are
34
+ * exactly the cases (a hung client, a zombie socket) where commands strand.
35
+ */
36
+ export declare function failUndeliveredCommands(lostClient: ConnectedClient, browsers: Set<WebSocket>, auditLog: HqCommandAuditLog | undefined): void;
13
37
  export declare function handleClient(ws: WebSocket, clients: Map<WebSocket, ConnectedClient>, browsers: Set<WebSocket>, eventLog: HqEventEnvelope[], auth: {
14
38
  token?: HqToken | undefined;
15
39
  getOperatorPolicy: () => Partial<HqRedactionPolicy> | undefined;
@@ -10,7 +10,7 @@ import {
10
10
  readLocalSubagentTranscript,
11
11
  sanitizeApiError,
12
12
  startHqServer
13
- } from "./chunk-DRM7PSW7.js";
13
+ } from "./chunk-ENRYW73H.js";
14
14
  import "./chunk-HXJYHAR4.js";
15
15
  import "./chunk-5EA6OTLJ.js";
16
16
  import "./chunk-Q7E3BPDU.js";
@@ -27,4 +27,4 @@ export {
27
27
  sanitizeApiError,
28
28
  startHqServer
29
29
  };
30
- //# sourceMappingURL=hq-server-PC7GZMPT.js.map
30
+ //# sourceMappingURL=hq-server-UIB24LU6.js.map
@@ -4,10 +4,10 @@ import {
4
4
  import {
5
5
  detectUpdatePackageManager,
6
6
  detectUpdatePackageName
7
- } from "./chunk-QFPQXKCG.js";
7
+ } from "./chunk-KOEO4CJG.js";
8
8
  import "./chunk-U3SS4NRH.js";
9
- import "./chunk-ZZRSG7VK.js";
10
- import "./chunk-YBUCXXYZ.js";
9
+ import "./chunk-RZ4ZDRYA.js";
10
+ import "./chunk-F5DCFAKI.js";
11
11
 
12
12
  // src/hq-service.ts
13
13
  import { spawn } from "node:child_process";
@@ -511,4 +511,4 @@ export {
511
511
  hqServiceCmd,
512
512
  renderHqServiceAssets
513
513
  };
514
- //# sourceMappingURL=hq-service-NW56MUP2.js.map
514
+ //# sourceMappingURL=hq-service-BMMJAHRT.js.map