@wrongstack/cli 1.0.19 → 1.0.26

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 (195) hide show
  1. package/data/providers.json +44 -0
  2. package/dist/{acp-INCNOH42.js → acp-LI665LO2.js} +18 -7
  3. package/dist/arg-parser.d.ts +1 -0
  4. package/dist/ascii-mode-SG4PRNLP.js +7 -0
  5. package/dist/{auth-YXK3EDUL.js → auth-TE55JF4Z.js} +68 -22
  6. package/dist/auth-menu/direct.d.ts +1 -0
  7. package/dist/auth-menu/local.d.ts +2 -0
  8. package/dist/auth-menu/oauth-menu.d.ts +3 -1
  9. package/dist/auth-menu/panel-service.d.ts +20 -0
  10. package/dist/{bench-YBU6BVQP.js → bench-GTLPM22B.js} +2 -2
  11. package/dist/boot/append-system-prompt.d.ts +10 -0
  12. package/dist/boot/ascii-mode.d.ts +12 -0
  13. package/dist/boot/config-backup-recovery.d.ts +2 -1
  14. package/dist/boot/container-wiring.d.ts +4 -2
  15. package/dist/boot/dispatch-singleshot.d.ts +4 -1
  16. package/dist/boot/dispatch-webui.d.ts +11 -0
  17. package/dist/boot/mcp-config-flag.d.ts +22 -0
  18. package/dist/boot/piped-stdin.d.ts +40 -0
  19. package/dist/boot/restricted-mode.d.ts +15 -0
  20. package/dist/boot/safe-mode.d.ts +30 -0
  21. package/dist/boot/short-circuit-desktop.d.ts +1 -0
  22. package/dist/boot/single-shot-budget.d.ts +30 -0
  23. package/dist/boot/stream-json.d.ts +36 -0
  24. package/dist/boot/structured-output.d.ts +16 -0
  25. package/dist/boot/system-prompt-builder.d.ts +2 -0
  26. package/dist/boot/tool-restriction-flags.d.ts +36 -0
  27. package/dist/boot/tui-project-picker-callback.d.ts +1 -1
  28. package/dist/boot/tui-settings-adapter.d.ts +15 -2
  29. package/dist/boot/worktree-sessions.d.ts +21 -0
  30. package/dist/{boot-auto-thin-MANHOYHE.js → boot-auto-thin-6Q56FY3F.js} +3 -2
  31. package/dist/boot-provider-selection.d.ts +67 -0
  32. package/dist/boot.d.ts +1 -38
  33. package/dist/{chunk-JY52HWL6.js → chunk-2EBVTYJR.js} +2 -2
  34. package/dist/{chunk-RDHFXOJM.js → chunk-2ERX3RPN.js} +112 -65
  35. package/dist/chunk-4TVYGG6G.js +62 -0
  36. package/dist/chunk-5JYDKG5B.js +154 -0
  37. package/dist/{chunk-KEPABQYT.js → chunk-5SEYGOCH.js} +8 -82
  38. package/dist/{chunk-3VXYY5JC.js → chunk-5UZBUV2H.js} +3 -19
  39. package/dist/chunk-BBHWW6LR.js +549 -0
  40. package/dist/chunk-BEHGRNOQ.js +58 -0
  41. package/dist/chunk-CZTXF6HY.js +140 -0
  42. package/dist/{chunk-JX6KL7OF.js → chunk-EPR42SWM.js} +39 -8
  43. package/dist/chunk-F5DCFAKI.js +36 -0
  44. package/dist/chunk-HLSHFXTO.js +97 -0
  45. package/dist/{chunk-CJTBLTS4.js → chunk-KJS5543T.js} +4 -3
  46. package/dist/{chunk-DE7BZDNK.js → chunk-KOEO4CJG.js} +27 -4
  47. package/dist/{chunk-SIS37L3W.js → chunk-L2RVEQWO.js} +211 -193
  48. package/dist/chunk-LBPLTTZ6.js +105 -0
  49. package/dist/chunk-LDCGZJTC.js +46 -0
  50. package/dist/chunk-LKPEBZBE.js +143 -0
  51. package/dist/chunk-LUMETJFO.js +171 -0
  52. package/dist/{chunk-KK2LB3ZS.js → chunk-OAVBM55Q.js} +9 -5
  53. package/dist/chunk-PZQBGUVZ.js +18 -0
  54. package/dist/{chunk-C3Z4N6A6.js → chunk-Q4INH2DG.js} +51 -3
  55. package/dist/chunk-R4QGL6GB.js +10 -0
  56. package/dist/{chunk-YLQEGYV4.js → chunk-RZ4ZDRYA.js} +14 -4
  57. package/dist/chunk-S4FFHDJG.js +93 -0
  58. package/dist/chunk-SFBFYIOW.js +271 -0
  59. package/dist/{chunk-RMQNCHGO.js → chunk-TI7KLHYX.js} +136 -11
  60. package/dist/{chunk-2ENZU66X.js → chunk-WQV2NP57.js} +5 -5
  61. package/dist/{chunk-B4JLSXZB.js → chunk-WSTVGC2C.js} +73 -45
  62. package/dist/chunk-X756ZS72.js +329 -0
  63. package/dist/{chunk-XJ7K67PP.js → chunk-YHYINL47.js} +63 -24
  64. package/dist/{chunk-2VMJ3E5Z.js → chunk-YTEOAWOJ.js} +6 -2
  65. package/dist/{chunk-GPPRNAKW.js → chunk-ZMX5HRLI.js} +2 -2
  66. package/dist/{cli-context-33F74CSZ.js → cli-context-UVGAN3NO.js} +496 -384
  67. package/dist/cli-entry-point.d.ts +2 -0
  68. package/dist/{cli-main-FNGMKPBA.js → cli-main-TN3KZ2P6.js} +3561 -2724
  69. package/dist/cli-update-notice.d.ts +2 -1
  70. package/dist/config-doctor.d.ts +10 -2
  71. package/dist/{config-transfer-2YF3CRTN.js → config-transfer-RUWLDCNK.js} +34 -13
  72. package/dist/{diag-doctor-ANPRUYFM.js → diag-doctor-BIZAFIAT.js} +2 -2
  73. package/dist/execute-deps.d.ts +2 -1
  74. package/dist/{execution-A6WJLSOC.js → execution-7QIP6GRY.js} +2384 -2055
  75. package/dist/fleet/host-types.d.ts +3 -1
  76. package/dist/goal-commands.d.ts +47 -0
  77. package/dist/goal-host.d.ts +1 -14
  78. package/dist/{hq-XQWQTRDA.js → hq-GLZ7QESM.js} +277 -261
  79. package/dist/hq-command-controller.d.ts +1 -1
  80. package/dist/{hq-server-IIBZQZU4.js → hq-server-YTKDVQPY.js} +2 -2
  81. package/dist/{hq-service-L5INQFM4.js → hq-service-BMMJAHRT.js} +11 -4
  82. package/dist/import-claude-code-32PCSIQI.js +236 -0
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.js +19 -10
  85. package/dist/kanban-supervisor-67ECABTD.js +7 -0
  86. package/dist/live-settings-input.d.ts +7 -0
  87. package/dist/{mailbox-serve-3GFOK2I7.js → mailbox-serve-NW5VZG7R.js} +3 -3
  88. package/dist/{mcp-DC5WSBOO.js → mcp-LBS45HWZ.js} +4 -4
  89. package/dist/modeldiag-36VODVIH.js +828 -0
  90. package/dist/{per-subcommand-help-DHTYU524.js → per-subcommand-help-QDAQASPZ.js} +3 -3
  91. package/dist/permission-prompt-mirror.d.ts +1 -1
  92. package/dist/permission-prompt.d.ts +16 -2
  93. package/dist/permission-rules-view.d.ts +18 -0
  94. package/dist/{permissions-CFDLXETM.js → permissions-PL27UHYD.js} +67 -45
  95. package/dist/plugin-config.d.ts +12 -0
  96. package/dist/plugin-management-types.d.ts +31 -0
  97. package/dist/plugin-management.d.ts +2 -30
  98. package/dist/plugin-package-install.d.ts +3 -0
  99. package/dist/{plugin-usage-M6KET4OZ.js → plugin-usage-CIGOOTX3.js} +6 -5
  100. package/dist/{plugins-WJLW6ULV.js → plugins-HQTXUD6A.js} +6 -3
  101. package/dist/preflight.d.ts +1 -1
  102. package/dist/{projects-LMNAGGEU.js → projects-T4CZCA25.js} +3 -6
  103. package/dist/provider-config-utils.d.ts +1 -6
  104. package/dist/provider-helpers.d.ts +7 -11
  105. package/dist/{providers-models-LFNZ5WI7.js → providers-models-5Z2PJTEW.js} +44 -34
  106. package/dist/release-asset-download.d.ts +13 -0
  107. package/dist/release-attestation.d.ts +28 -0
  108. package/dist/remote/remote-session.d.ts +64 -0
  109. package/dist/remote/remote-target.d.ts +69 -0
  110. package/dist/remote-O5WXHLWV.js +561 -0
  111. package/dist/{replay-Z3FTJEMM.js → replay-DEI566CW.js} +2 -2
  112. package/dist/services/commit-message.d.ts +2 -1
  113. package/dist/services/dispatch-classifier.d.ts +39 -5
  114. package/dist/session-move-P2EC2COA.js +44 -0
  115. package/dist/session-move.d.ts +20 -0
  116. package/dist/session-stats.d.ts +10 -0
  117. package/dist/{sessions-config-UL45XKX7.js → sessions-config-SXTTLNXA.js} +47 -9
  118. package/dist/settings-menu.d.ts +2 -0
  119. package/dist/short-circuit-flags-74Y5N6CF.js +10 -0
  120. package/dist/{simpleui-dist-CXSIDAXZ.js → simpleui-dist-7BQISSEP.js} +7 -3
  121. package/dist/skill-suggest-L2EVWB6R.js +290 -0
  122. package/dist/slash-commands/command-context.d.ts +15 -5
  123. package/dist/slash-commands/effort.d.ts +1 -1
  124. package/dist/slash-commands/fallback.d.ts +1 -1
  125. package/dist/slash-commands/gitid.d.ts +1 -1
  126. package/dist/slash-commands/goal-refiner.d.ts +4 -49
  127. package/dist/slash-commands/jev.d.ts +4 -0
  128. package/dist/slash-commands/mcp.d.ts +2 -1
  129. package/dist/slash-commands/openai-quota.d.ts +15 -0
  130. package/dist/slash-commands/permissions.d.ts +4 -0
  131. package/dist/slash-commands/sdd-task-mutations.d.ts +4 -0
  132. package/dist/slash-commands/settings-context-mutations.d.ts +5 -0
  133. package/dist/slash-commands/settings-keys.d.ts +2 -0
  134. package/dist/slash-commands/settings-limits-mutations.d.ts +12 -0
  135. package/dist/slash-commands/settings-reset.d.ts +6 -0
  136. package/dist/standalone-auto-update-TOTRGCSA.js +249 -0
  137. package/dist/standalone-auto-update.d.ts +65 -0
  138. package/dist/standalone-update-LZO3MNLH.js +24 -0
  139. package/dist/standalone-update.d.ts +55 -0
  140. package/dist/subcommands/handlers/hq-alerts.d.ts +3 -0
  141. package/dist/subcommands/handlers/hq-audit.d.ts +46 -0
  142. package/dist/subcommands/handlers/hq-data-dir.d.ts +13 -0
  143. package/dist/subcommands/handlers/import-claude-code.d.ts +42 -0
  144. package/dist/subcommands/handlers/permissions.d.ts +9 -3
  145. package/dist/subcommands/handlers/remote.d.ts +6 -0
  146. package/dist/subcommands/handlers/skill-suggest.d.ts +21 -0
  147. package/dist/subcommands/handlers/typesafe-brain-replay.d.ts +26 -0
  148. package/dist/subcommands/handlers/typesafe-judgment-check.d.ts +3 -0
  149. package/dist/subcommands/handlers/typesafe-topic-replay.d.ts +19 -0
  150. package/dist/subcommands/handlers/typesafe-triage-replay.d.ts +18 -0
  151. package/dist/subcommands/handlers/typesafe.d.ts +23 -0
  152. package/dist/subcommands/handlers/version-help.d.ts +5 -0
  153. package/dist/{subcommands-XSLXMIDP.js → subcommands-Q6ORSB2E.js} +2 -2
  154. package/dist/tui-resume-callback.d.ts +18 -0
  155. package/dist/typesafe-U7YB2RRV.js +316 -0
  156. package/dist/typesafe-brain-replay-C5276FVR.js +222 -0
  157. package/dist/typesafe-judgment-check-GGYYV5UF.js +29 -0
  158. package/dist/typesafe-topic-replay-ZILIU3WS.js +234 -0
  159. package/dist/typesafe-triage-replay-FGAW7QM7.js +215 -0
  160. package/dist/{update-5DPB4YD4.js → update-TDZX4IL2.js} +4 -3
  161. package/dist/{update-check-BS3DHTSI.js → update-check-J5ZVKS73.js} +3 -2
  162. package/dist/update-check.d.ts +1 -1
  163. package/dist/version-JB2UAV2A.js +11 -0
  164. package/dist/version-help-XJJQ7YSH.js +10 -0
  165. package/dist/version.d.ts +3 -2
  166. package/dist/webui-client-observability.d.ts +7 -0
  167. package/dist/webui-server/route-contexts.d.ts +1 -1
  168. package/dist/webui-server/session-start-payload.d.ts +5 -1
  169. package/dist/{webui-server-MRPGTTKL.js → webui-server-YTHLRFD2.js} +577 -370
  170. package/dist/webui-server-lifecycle.d.ts +57 -0
  171. package/dist/webui-server-options.d.ts +11 -0
  172. package/dist/webui-server.d.ts +1 -1
  173. package/dist/wiring/brain-and-orchestration.d.ts +3 -1
  174. package/dist/wiring/cli-prompt-and-tools-setup.d.ts +9 -0
  175. package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
  176. package/dist/wiring/domain-glossary.d.ts +5 -4
  177. package/dist/wiring/lifecycle-plugins.d.ts +4 -2
  178. package/dist/wiring/metrics.d.ts +9 -1
  179. package/dist/wiring/pipeline.d.ts +2 -7
  180. package/dist/wiring/plugins.d.ts +4 -1
  181. package/dist/wiring/provider-persisters.d.ts +24 -0
  182. package/dist/wiring/provider-runtime.d.ts +9 -1
  183. package/dist/wiring/provider-status.d.ts +1 -0
  184. package/dist/wiring/provider-utility-tools.d.ts +3 -1
  185. package/dist/wiring/runtime-dispatch-state.d.ts +3 -1
  186. package/package.json +28 -28
  187. package/dist/chunk-2CZEORLV.js +0 -54
  188. package/dist/chunk-672UXYL3.js +0 -65
  189. package/dist/chunk-6WRKAACA.js +0 -96
  190. package/dist/chunk-DR2OXU46.js +0 -174
  191. package/dist/chunk-JACOMTIH.js +0 -275
  192. package/dist/chunk-XJXDOF63.js +0 -28
  193. package/dist/modeldiag-CJSFHZ3J.js +0 -1356
  194. package/dist/short-circuit-flags-7GQIGMVD.js +0 -10
  195. package/dist/version-help-WXI42PZ3.js +0 -10
@@ -7,8 +7,8 @@ import {
7
7
  renderFocusedHelpToString,
8
8
  renderGenericHelp,
9
9
  subcommandsWithFocusedHelp
10
- } from "./chunk-JX6KL7OF.js";
11
- import "./chunk-2VMJ3E5Z.js";
10
+ } from "./chunk-EPR42SWM.js";
11
+ import "./chunk-YTEOAWOJ.js";
12
12
  export {
13
13
  deepSubcommandsWithFocusedHelp,
14
14
  renderBlockToString,
@@ -19,4 +19,4 @@ export {
19
19
  renderGenericHelp,
20
20
  subcommandsWithFocusedHelp
21
21
  };
22
- //# sourceMappingURL=per-subcommand-help-DHTYU524.js.map
22
+ //# sourceMappingURL=per-subcommand-help-QDAQASPZ.js.map
@@ -28,7 +28,7 @@
28
28
  */
29
29
  import type { ApprovalRegistry } from '@wrongstack/core/hq';
30
30
  import type { Tool } from '@wrongstack/core/types';
31
- type PromptDecision = 'yes' | 'no' | 'always' | 'deny';
31
+ type PromptDecision = 'yes' | 'no' | 'always' | 'always-exact' | 'always-command' | 'always-tool' | 'deny';
32
32
  type PromptDelegate = (tool: Tool, input: unknown, suggestedPattern: string) => Promise<PromptDecision>;
33
33
  type AbortablePromptDelegate = (tool: Tool, input: unknown, suggestedPattern: string, signal: AbortSignal) => Promise<PromptDecision>;
34
34
  /**
@@ -1,7 +1,15 @@
1
1
  import type { InputReader, Tool } from '@wrongstack/core/types';
2
- type PromptDecision = 'yes' | 'no' | 'always' | 'deny';
2
+ type PromptDecision = 'yes' | 'no' | 'always' | 'always-exact' | 'always-command' | 'always-tool' | 'deny';
3
3
  /** Signature the Agent expects for confirming tool calls. */
4
- export type ConfirmAwaiter = (tool: Tool, input: unknown, toolUseId: string, suggestedPattern: string) => Promise<'yes' | 'no' | 'always' | 'deny'>;
4
+ export type ConfirmAwaiter = (tool: Tool, input: unknown, toolUseId: string, suggestedPattern: string) => Promise<'yes' | 'no' | 'always' | 'always-exact' | 'always-command' | 'always-tool' | 'deny'>;
5
+ /**
6
+ * Approval "prompt" for a process with no terminal on stdin — a script, CI,
7
+ * `wstack "task" < /dev/null`, piped input. Nobody can answer, and the
8
+ * terminal prompt used to wait for a key that never came, so the run hung
9
+ * until it was killed. Refuse instead, and say on stderr (stdout may be a
10
+ * JSON payload) how to grant it up front.
11
+ */
12
+ export declare function makeHeadlessPromptDelegate(write?: (text: string) => void): (tool: Tool) => Promise<PromptDecision>;
5
13
  /**
6
14
  * The terminal approval prompt.
7
15
  *
@@ -16,6 +24,12 @@ export declare function makePromptDelegate(reader: InputReader): (tool: Tool, in
16
24
  * Create a ConfirmAwaiter for the CLI path. Wraps makePromptDelegate
17
25
  * with the ConfirmAwaiter type signature expected by the Agent.
18
26
  */
27
+ /**
28
+ * The terminal prompt when stdin is a terminal, the headless refusal
29
+ * otherwise. Both approval paths (policy prompt and executor confirm) go
30
+ * through this, so neither can wait on a keypress nobody can make.
31
+ */
32
+ export declare function makeStdinPromptDelegate(reader: InputReader, stdinIsTTY?: boolean): ReturnType<typeof makePromptDelegate>;
19
33
  export declare function makeConfirmAwaiter(reader: InputReader): ConfirmAwaiter;
20
34
  export {};
21
35
  //# sourceMappingURL=permission-prompt.d.ts.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Text views of the permission rule list and of one explained call, shared by
3
+ * `wstack permissions` and the in-session `/permissions` command.
4
+ */
5
+ import type { Context } from '@wrongstack/core/agent';
6
+ import type { PermissionPolicy, PermissionRule, PermissionTrace, Tool } from '@wrongstack/core/types';
7
+ export interface ExplainedCall {
8
+ trace: PermissionTrace;
9
+ rules: PermissionRule[];
10
+ /** The rule that decided the call. */
11
+ rule: PermissionRule | undefined;
12
+ }
13
+ /** Trace one call through the policy and the executor's gate, and name its rule. */
14
+ export declare function explainCall(policy: Pick<PermissionPolicy, 'explain' | 'listRules'>, tool: Tool, input: unknown, ctx: Context, yolo: boolean): Promise<ExplainedCall>;
15
+ export declare function describePermissionRule(rule: PermissionRule): string;
16
+ export declare function formatPermissionRules(rules: readonly PermissionRule[]): string;
17
+ export declare function formatExplainedCall({ trace, rule }: ExplainedCall): string;
18
+ //# sourceMappingURL=permission-rules-view.d.ts.map
@@ -1,23 +1,45 @@
1
+ import {
2
+ explainCall,
3
+ formatExplainedCall,
4
+ formatPermissionRules
5
+ } from "./chunk-4TVYGG6G.js";
1
6
 
2
7
  // src/subcommands/handlers/permissions.ts
3
- import { DefaultPermissionPolicy } from "@wrongstack/core/security";
8
+ import { compilePermissionRules } from "@wrongstack/core/security";
4
9
  import { resolveWstackPaths } from "@wrongstack/core/utils";
10
+ import { createProjectPermissionPolicy } from "@wrongstack/runtime";
5
11
  var permissionsCmd = async (args, deps) => {
6
12
  const subCmd = args[0];
7
13
  if (subCmd === "help" || subCmd === "--help" || subCmd === "-h" || !subCmd || subCmd === "explain" && !args[1]) {
8
- if (subCmd !== "explain" && subCmd !== "help" && subCmd !== void 0) {
9
- deps.renderer.writeError(`Unknown permissions subcommand: ${subCmd}
10
- `);
11
- }
12
14
  deps.renderer.write(usage());
13
- return subCmd && subCmd !== "explain" && subCmd !== "help" && subCmd !== void 0 ? 1 : 0;
15
+ return 0;
14
16
  }
15
- if (subCmd !== "explain") {
17
+ if (subCmd !== "explain" && subCmd !== "rules") {
16
18
  deps.renderer.writeError(`Unknown permissions subcommand: ${subCmd}
17
19
  `);
18
20
  deps.renderer.write(usage());
19
21
  return 1;
20
22
  }
23
+ const jsonOutput = deps.flags?.["json"] === true || args.includes("--json");
24
+ const built = buildPolicy(deps);
25
+ if (typeof built === "string") {
26
+ deps.renderer.writeError(`${built}
27
+ `);
28
+ return 1;
29
+ }
30
+ const { policy, ctx, yolo, yoloSource } = built;
31
+ if (subCmd === "rules") {
32
+ const rules = await compilePermissionRules(policy, ctx, { yolo });
33
+ if (jsonOutput) deps.renderer.write(`${JSON.stringify(rules, null, 2)}
34
+ `);
35
+ else
36
+ deps.renderer.writeLine(
37
+ `YOLO: ${yolo ? "on" : "off"} (${yoloSource})
38
+
39
+ ${formatPermissionRules(rules)}`
40
+ );
41
+ return 0;
42
+ }
21
43
  const toolName = args[1];
22
44
  if (!toolName) {
23
45
  deps.renderer.writeError("Missing tool name.\n");
@@ -27,7 +49,6 @@ var permissionsCmd = async (args, deps) => {
27
49
  const inputIdx = args.indexOf("--input");
28
50
  const flagInput = deps.flags?.["input"];
29
51
  const rawInput = typeof flagInput === "string" ? flagInput : inputIdx >= 0 && inputIdx + 1 < args.length ? args[inputIdx + 1] : void 0;
30
- const jsonOutput = deps.flags?.["json"] === true || args.includes("--json");
31
52
  let input = {};
32
53
  if (rawInput) {
33
54
  try {
@@ -50,67 +71,68 @@ var permissionsCmd = async (args, deps) => {
50
71
  );
51
72
  return 1;
52
73
  }
74
+ const explained = await explainCall(policy, tool, input, ctx, yolo);
75
+ if (jsonOutput) {
76
+ deps.renderer.write(
77
+ `${JSON.stringify({ ...explained.trace, rule: explained.rule }, null, 2)}
78
+ `
79
+ );
80
+ } else {
81
+ deps.renderer.writeLine(
82
+ `YOLO: ${yolo ? "on" : "off"} (${yoloSource})
83
+
84
+ ${formatExplainedCall(explained)}`
85
+ );
86
+ }
87
+ return 0;
88
+ };
89
+ function buildPolicy(deps) {
53
90
  const paths = resolveWstackPaths({ projectRoot: deps.projectRoot, userHome: deps.userHome });
54
- const trustFile = paths.projectTrust;
55
91
  const readSubjects = /* @__PURE__ */ new Set();
56
92
  const ctx = {
57
93
  projectRoot: deps.projectRoot,
58
94
  cwd: deps.cwd,
95
+ workingDir: deps.cwd,
96
+ meta: {},
97
+ provider: { id: deps.config.provider },
59
98
  hasRead(subject) {
60
99
  return readSubjects.has(subject);
61
100
  }
62
101
  };
63
- const policy = new DefaultPermissionPolicy({
64
- trustFile,
65
- yolo: deps.flags?.["yolo"] ?? false
66
- });
67
- await policy.reload();
68
- const trace = await policy.explain(tool, input, ctx);
69
- if (jsonOutput) {
70
- deps.renderer.write(JSON.stringify(trace, null, 2) + "\n");
71
- } else {
72
- deps.renderer.write(formatTrace(trace) + "\n");
102
+ const yoloFlag = deps.flags?.["yolo"];
103
+ const yolo = typeof yoloFlag === "boolean" ? yoloFlag : deps.config.yolo === true;
104
+ try {
105
+ const policy = createProjectPermissionPolicy({
106
+ projectRoot: deps.projectRoot,
107
+ trustFile: paths.projectTrust,
108
+ config: deps.config,
109
+ permission: { yolo }
110
+ })();
111
+ return { policy, ctx, yolo, yoloSource: typeof yoloFlag === "boolean" ? "--yolo" : "config" };
112
+ } catch (error) {
113
+ return error instanceof Error ? error.message : String(error);
73
114
  }
74
- return 0;
75
- };
76
- function formatTrace(trace) {
77
- const lines = [];
78
- lines.push(`Permission trace for "${trace.toolName}"`);
79
- lines.push(`Subject: ${trace.subject ?? "(none)"}`);
80
- lines.push("");
81
- for (let i = 0; i < trace.steps.length; i++) {
82
- const step = trace.steps[i];
83
- const winner = i === trace.winnerIndex ? " \u2190 WINNER" : "";
84
- const matched = step.matched ? "\u2713" : " ";
85
- lines.push(` ${matched} [${i}] ${step.rule}${winner}`);
86
- lines.push(` decision: ${step.decision} source: ${step.source}`);
87
- lines.push(` ${step.detail}`);
88
- if (i < trace.steps.length - 1) lines.push("");
89
- }
90
- lines.push("");
91
- lines.push(`Effective: ${trace.decision.permission} (source: ${trace.decision.source})`);
92
- if (trace.decision.reason) {
93
- lines.push(`Reason: ${trace.decision.reason}`);
94
- }
95
- if (trace.decision.riskTier) {
96
- lines.push(`Risk tier: ${trace.decision.riskTier}`);
97
- }
98
- return lines.join("\n");
99
115
  }
100
116
  function usage() {
101
117
  return `Usage:
118
+ wstack permissions rules [--json]
102
119
  wstack permissions explain <tool> --input '<json>' [--json]
103
120
 
104
121
  Examples:
122
+ wstack permissions rules
105
123
  wstack permissions explain bash --input '{"command":"rm -rf /"}'
106
124
  wstack permissions explain read --input '{"path":".env"}' --json
107
125
 
108
126
  Flags:
109
127
  --input <json> Tool input arguments as a JSON object
110
128
  --json Output as structured JSON instead of human-readable text
129
+ --yolo Show the rules as they apply with YOLO on
130
+
131
+ Inside a session, /permissions shows the same with that session\u2019s YOLO,
132
+ answers and /permissions allow|deny rules.
111
133
  `;
112
134
  }
113
135
  export {
114
136
  permissionsCmd
115
137
  };
116
- //# sourceMappingURL=permissions-CFDLXETM.js.map
138
+ //# sourceMappingURL=permissions-PL27UHYD.js.map
@@ -0,0 +1,12 @@
1
+ import type { PluginConfig } from '@wrongstack/core/types';
2
+ import type { PluginManagementDeps, PluginManagementResult } from './plugin-management-types.js';
3
+ export declare function readConfig(file: string): Promise<Record<string, unknown>>;
4
+ export declare function pluginName(p: string | PluginConfig): string;
5
+ export declare function upsertPlugin(spec: string, opts: {
6
+ enabled: boolean;
7
+ path?: string;
8
+ }, deps: PluginManagementDeps, verb: string): Promise<PluginManagementResult>;
9
+ export declare function errorResult(message: string): PluginManagementResult;
10
+ export declare function globalPluginsRoot(deps: PluginManagementDeps): string;
11
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
12
+ //# sourceMappingURL=plugin-config.d.ts.map
@@ -0,0 +1,31 @@
1
+ import type { Config, PluginConfig, PluginManagerConfig } from '@wrongstack/core/types';
2
+ export interface PluginManagementDeps {
3
+ config: Config;
4
+ configPath: string;
5
+ /** Override `~/.wrongstack` for tests. Defaults to the real home dir. */
6
+ globalRoot?: string | undefined;
7
+ /** Injectable package-manager runner for tests. */
8
+ runPackageManager?: ((pm: string, args: readonly string[], cwd: string) => Promise<PackageManagerRunResult>) | undefined;
9
+ }
10
+ export interface PackageManagerRunResult {
11
+ code: number | null;
12
+ stdout: string;
13
+ stderr: string;
14
+ }
15
+ export interface PluginManagementResult {
16
+ code: number;
17
+ level: 'output' | 'info' | 'error';
18
+ message: string;
19
+ patch?: {
20
+ plugins?: (string | PluginConfig)[] | undefined;
21
+ features?: Record<string, unknown>;
22
+ pluginManager?: PluginManagerConfig | undefined;
23
+ /**
24
+ * Full replacement `extensions` map (patchConfig is a SHALLOW merge,
25
+ * so per-plugin llm overrides must ship the whole merged object).
26
+ */
27
+ extensions?: Record<string, Record<string, unknown>> | undefined;
28
+ };
29
+ restartRequired?: boolean | undefined;
30
+ }
31
+ //# sourceMappingURL=plugin-management-types.d.ts.map
@@ -1,36 +1,8 @@
1
- import type { Config, PluginConfig, PluginManagerConfig } from '@wrongstack/core/types';
1
+ import type { Config } from '@wrongstack/core/types';
2
2
  import { PLUGIN_AUDIT_ENTRIES, type PluginAuditEntry } from '@wrongstack/plugins/plugin-audit-catalog';
3
+ import type { PluginManagementDeps, PluginManagementResult } from './plugin-management-types.js';
3
4
  export type { PluginAuditEntry };
4
5
  export { PLUGIN_AUDIT_ENTRIES };
5
- interface PluginManagementDeps {
6
- config: Config;
7
- configPath: string;
8
- /** Override `~/.wrongstack` for tests. Defaults to the real home dir. */
9
- globalRoot?: string | undefined;
10
- /** Injectable package-manager runner for tests. */
11
- runPackageManager?: ((pm: string, args: readonly string[], cwd: string) => Promise<PackageManagerRunResult>) | undefined;
12
- }
13
- interface PackageManagerRunResult {
14
- code: number | null;
15
- stdout: string;
16
- stderr: string;
17
- }
18
- interface PluginManagementResult {
19
- code: number;
20
- level: 'output' | 'info' | 'error';
21
- message: string;
22
- patch?: {
23
- plugins?: (string | PluginConfig)[] | undefined;
24
- features?: Record<string, unknown>;
25
- pluginManager?: PluginManagerConfig | undefined;
26
- /**
27
- * Full replacement `extensions` map (patchConfig is a SHALLOW merge,
28
- * so per-plugin llm overrides must ship the whole merged object).
29
- */
30
- extensions?: Record<string, Record<string, unknown>> | undefined;
31
- };
32
- restartRequired?: boolean | undefined;
33
- }
34
6
  export declare function runPluginManagementCommand(args: string[], deps: PluginManagementDeps): Promise<PluginManagementResult>;
35
7
  export declare function renderConfiguredPlugins(config: Config): string;
36
8
  export declare function renderPluginAuditReport(config: Config): string;
@@ -0,0 +1,3 @@
1
+ import type { PluginManagementDeps, PluginManagementResult } from './plugin-management-types.js';
2
+ export declare function installPluginPackage(spec: string, args: string[], deps: PluginManagementDeps): Promise<PluginManagementResult>;
3
+ //# sourceMappingURL=plugin-package-install.d.ts.map
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  runPluginManagementCommand
3
- } from "./chunk-SIS37L3W.js";
4
- import {
5
- restoreFlags
6
- } from "./chunk-CSAPOCBP.js";
3
+ } from "./chunk-L2RVEQWO.js";
7
4
  import {
8
5
  activeProfileConfigPath
9
6
  } from "./chunk-YMXXOOFN.js";
7
+ import {
8
+ restoreFlags
9
+ } from "./chunk-CSAPOCBP.js";
10
+ import "./chunk-WSTVGC2C.js";
10
11
 
11
12
  // src/subcommands/handlers/plugin-usage.ts
12
13
  var pluginCmd = async (args, deps) => {
@@ -40,4 +41,4 @@ export {
40
41
  pluginCmd,
41
42
  usageCmd
42
43
  };
43
- //# sourceMappingURL=plugin-usage-M6KET4OZ.js.map
44
+ //# sourceMappingURL=plugin-usage-CIGOOTX3.js.map
@@ -1,16 +1,19 @@
1
1
  import {
2
2
  BUILTIN_PLUGIN_FACTORIES,
3
+ BUILTIN_PLUGIN_NAME_HINTS,
3
4
  DEPRECATED_PLUGIN_NAMES,
4
5
  _resetDeprecatedWarningsForTests,
5
6
  builtinPluginNameFromSpec,
6
7
  pluginNameFromSpec,
7
8
  setupPlugins,
8
9
  warnIfDeprecatedPluginName
9
- } from "./chunk-XJ7K67PP.js";
10
+ } from "./chunk-YHYINL47.js";
10
11
  import "./chunk-EWKESL4L.js";
11
- import "./chunk-SIS37L3W.js";
12
+ import "./chunk-L2RVEQWO.js";
13
+ import "./chunk-WSTVGC2C.js";
12
14
  export {
13
15
  BUILTIN_PLUGIN_FACTORIES,
16
+ BUILTIN_PLUGIN_NAME_HINTS,
14
17
  DEPRECATED_PLUGIN_NAMES,
15
18
  _resetDeprecatedWarningsForTests,
16
19
  builtinPluginNameFromSpec,
@@ -18,4 +21,4 @@ export {
18
21
  setupPlugins,
19
22
  warnIfDeprecatedPluginName
20
23
  };
21
- //# sourceMappingURL=plugins-WJLW6ULV.js.map
24
+ //# sourceMappingURL=plugins-HQTXUD6A.js.map
@@ -39,7 +39,7 @@ export declare function applySessionShellDefault(): void;
39
39
  * callers get back the (possibly refreshed) `UpdateInfo`
40
40
  * so version-aware UI can render without re-fetching.
41
41
  */
42
- export declare function applyPrintUpdateNotice(initialUpdateInfo: UpdateInfo | undefined): Promise<UpdateInfo | undefined>;
42
+ export declare function applyPrintUpdateNotice(initialUpdateInfo: UpdateInfo | undefined, config?: Config | undefined): Promise<UpdateInfo | undefined>;
43
43
  /**
44
44
  * Seed the stream-debug singleton from persisted config so
45
45
  * `WireAdapter` picks it up on construction. Runtime toggles
@@ -1,8 +1,8 @@
1
1
 
2
2
  // src/subcommands/handlers/projects.ts
3
+ import { color } from "@wrongstack/core/utils";
3
4
  import * as fs from "node:fs/promises";
4
5
  import * as path from "node:path";
5
- import { color } from "@wrongstack/core/utils";
6
6
  var projectsCmd = async (_args, deps) => {
7
7
  const manifestPath = path.join(deps.paths.globalRoot, "projects.json");
8
8
  let entries;
@@ -18,10 +18,7 @@ var projectsCmd = async (_args, deps) => {
18
18
  return 0;
19
19
  }
20
20
  const sorted = [...entries].sort((a, b) => (b.lastSeen ?? "").localeCompare(a.lastSeen ?? ""));
21
- const slugWidth = Math.min(
22
- Math.max(...sorted.map((entry) => (entry.slug ?? "").length), 4),
23
- 40
24
- );
21
+ const slugWidth = Math.min(Math.max(...sorted.map((entry) => (entry.slug ?? "").length), 4), 40);
25
22
  for (const entry of sorted) {
26
23
  const slug = (entry.slug ?? "?").padEnd(slugWidth);
27
24
  const seen = entry.lastSeen ?? "";
@@ -33,4 +30,4 @@ var projectsCmd = async (_args, deps) => {
33
30
  export {
34
31
  projectsCmd
35
32
  };
36
- //# sourceMappingURL=projects-LMNAGGEU.js.map
33
+ //# sourceMappingURL=projects-T4CZCA25.js.map
@@ -1,6 +1,7 @@
1
1
  import { expectDefined } from '@wrongstack/core/utils';
2
2
  export { expectDefined };
3
3
  import type { ProviderApiKey, ProviderConfig, SecretVault } from '@wrongstack/core/types';
4
+ export { clearStaleProviderDefaults } from '@wrongstack/providers';
4
5
  /**
5
6
  * Normalize a ProviderConfig to the canonical `apiKeys[]` form.
6
7
  * Migrates the legacy single-key `apiKey` field on the fly so every
@@ -26,12 +27,6 @@ export declare function writeKeysBack(cfg: ProviderConfig, keys: ProviderApiKey[
26
27
  * when present on a freshly-loaded config it may contain a masked value.
27
28
  */
28
29
  export declare function resolveActiveApiKey(cfg: ProviderConfig): string | undefined;
29
- /**
30
- * Clear top-level provider/model defaults when provider mutations make them
31
- * stale. This prevents a removed provider, deleted final key, or edited model
32
- * allowlist from being accepted on the next boot and crashing provider setup.
33
- */
34
- export declare function clearStaleProviderDefaults(config: Record<string, unknown>): void;
35
30
  /**
36
31
  * Return the label of the active key, or the first key's label if no
37
32
  * active is pinned. Returns `undefined` when there are no keys at all.
@@ -1,4 +1,11 @@
1
+ /**
2
+ * Shared provider-config helpers used by the picker, main boot sequence,
3
+ * and subcommands. Keeps provider key detection and alias resolution in
4
+ * one place so the logic doesn't drift between call sites.
5
+ */
6
+ import { isKeylessLocalProvider } from '@wrongstack/core/models';
1
7
  import type { Config, ModelsRegistry, ProviderConfig, ResolvedProvider } from '@wrongstack/core/types';
8
+ export { isKeylessLocalProvider };
2
9
  /** Return the provider's visible model ids: models.dev plus anything the saved
3
10
  * config names that the catalog does not carry.
4
11
  *
@@ -23,17 +30,6 @@ import type { Config, ModelsRegistry, ProviderConfig, ResolvedProvider } from '@
23
30
  * request time rather than being silently unselectable, which is the better
24
31
  * failure: visible and actionable. */
25
32
  export declare function visibleModelIds(providerId: string, config: Config, catalogModelIds: string[], cfg?: ProviderConfig | undefined): string[];
26
- /**
27
- * Is this a keyless local gateway — a server on a loopback address that
28
- * declares no API-key env vars (omniroute, LiteLLM/vLLM/LM Studio/Ollama
29
- * running locally, …)? These need no credential, so they belong in the
30
- * picker even though `hasApiKey` returns false for them. Accepts the
31
- * minimal shape both call sites can supply.
32
- */
33
- export declare function isKeylessLocalProvider(provider: {
34
- apiBase?: string | undefined;
35
- envVars?: string[] | undefined;
36
- }): boolean;
37
33
  /**
38
34
  * Does this provider have an API key available — either in the
39
35
  * environment (via one of its known env vars) or stored in config
@@ -1,20 +1,26 @@
1
1
  import {
2
2
  visibleModelIds
3
- } from "./chunk-3VXYY5JC.js";
3
+ } from "./chunk-5UZBUV2H.js";
4
+ import {
5
+ mutateConfigProviders
6
+ } from "./chunk-LUMETJFO.js";
4
7
  import {
5
8
  activeProfileConfigPath
6
9
  } from "./chunk-YMXXOOFN.js";
7
- import {
8
- mutateConfigProviders
9
- } from "./chunk-DR2OXU46.js";
10
10
 
11
11
  // src/subcommands/handlers/providers-models.ts
12
12
  import * as fs from "node:fs/promises";
13
- import { decryptConfigSecrets, encryptConfigSecrets } from "@wrongstack/core/security";
13
+ import { decryptConfigSecretsForRewrite, encryptConfigSecrets } from "@wrongstack/core/security";
14
14
  import {
15
15
  ConfigError
16
16
  } from "@wrongstack/core/types";
17
- import { atomicWrite, color, expectDefined } from "@wrongstack/core/utils";
17
+ import {
18
+ atomicWrite,
19
+ backupConfigFile,
20
+ color,
21
+ expectDefined,
22
+ withFileLock
23
+ } from "@wrongstack/core/utils";
18
24
  var providersCmd = async (args, deps) => {
19
25
  const providerFlags = subcommandFlags(args, deps);
20
26
  const showAll = providerFlags["all"] === true || providerFlags["all"] === "true";
@@ -29,6 +35,7 @@ var providersCmd = async (args, deps) => {
29
35
  "openai-codex": [],
30
36
  "github-copilot": [],
31
37
  google: [],
38
+ "google-antigravity": [],
32
39
  unsupported: []
33
40
  };
34
41
  for (const p of all) byFamily[p.family].push(p);
@@ -508,34 +515,37 @@ async function modelsCaps(args, deps) {
508
515
  async function mutateModelsConfig(deps, mutator) {
509
516
  const vault = deps.vault;
510
517
  const configPath = activeProfileConfigPath(deps.paths, deps.config);
511
- let fileExists = true;
512
- let raw;
513
- try {
514
- raw = await fs.readFile(configPath, "utf8");
515
- } catch (err) {
516
- if (err.code !== "ENOENT") throw err;
517
- fileExists = false;
518
- raw = "{}";
519
- }
520
- let parsed;
521
- try {
522
- parsed = JSON.parse(raw);
523
- } catch (err) {
524
- if (fileExists) {
525
- throw new ConfigError({
526
- message: `Refusing to overwrite corrupt config at ${configPath} (${err.message}).`,
527
- code: "CONFIG_PARSE_FAILED",
528
- context: { filePath: configPath, operation: "mutateModelsConfig" }
529
- });
518
+ await withFileLock(configPath, async () => {
519
+ let fileExists = true;
520
+ let raw;
521
+ try {
522
+ raw = await fs.readFile(configPath, "utf8");
523
+ } catch (err) {
524
+ if (err.code !== "ENOENT") throw err;
525
+ fileExists = false;
526
+ raw = "{}";
527
+ }
528
+ let parsed;
529
+ try {
530
+ parsed = JSON.parse(raw);
531
+ } catch (err) {
532
+ if (fileExists) {
533
+ throw new ConfigError({
534
+ message: `Refusing to overwrite corrupt config at ${configPath} (${err.message}).`,
535
+ code: "CONFIG_PARSE_FAILED",
536
+ context: { filePath: configPath, operation: "mutateModelsConfig" }
537
+ });
538
+ }
539
+ parsed = {};
530
540
  }
531
- parsed = {};
532
- }
533
- const decrypted = decryptConfigSecrets(parsed, vault);
534
- const models = decrypted.models ?? {};
535
- mutator(models);
536
- decrypted.models = models;
537
- const encrypted = encryptConfigSecrets(decrypted, vault);
538
- await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
541
+ const decrypted = decryptConfigSecretsForRewrite(parsed, vault);
542
+ const models = decrypted.models ?? {};
543
+ mutator(models);
544
+ decrypted.models = models;
545
+ const encrypted = encryptConfigSecrets(decrypted, vault);
546
+ await backupConfigFile(configPath, { globalRoot: deps.paths.globalRoot });
547
+ await atomicWrite(configPath, JSON.stringify(encrypted, null, 2), { mode: 384 });
548
+ });
539
549
  }
540
550
  function parseSizeFlag(raw) {
541
551
  if (!raw) return void 0;
@@ -660,4 +670,4 @@ export {
660
670
  modelsCmd,
661
671
  providersCmd
662
672
  };
663
- //# sourceMappingURL=providers-models-LFNZ5WI7.js.map
673
+ //# sourceMappingURL=providers-models-5Z2PJTEW.js.map
@@ -0,0 +1,13 @@
1
+ /** Download one release asset without buffering beyond its configured ceiling. */
2
+ export declare function downloadReleaseAsset(url: string, timeoutMs: number, maxBytes: number): Promise<Buffer>;
3
+ /**
4
+ * Stream one release asset into `file` (created exclusively) and return its
5
+ * SHA-256. The background self-update uses this so a 100+ MB executable never
6
+ * sits in the session's heap. `file` is removed when the download fails.
7
+ */
8
+ export declare function downloadReleaseAssetToFile(url: string, file: string, options: {
9
+ timeoutMs: number;
10
+ maxBytes: number;
11
+ signal?: AbortSignal | undefined;
12
+ }): Promise<string>;
13
+ //# sourceMappingURL=release-asset-download.d.ts.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Build-provenance check for a downloaded standalone executable.
3
+ *
4
+ * SHA256SUMS comes from the same release as the binary, so it catches a
5
+ * corrupted download but not a forged one: whoever can upload the binary can
6
+ * upload a matching SHA256SUMS. The release workflow also attests every
7
+ * binary (`actions/attest-build-provenance`), and GitHub serves those
8
+ * attestations by digest. A binary is accepted only if one of them says this
9
+ * exact digest was built by `binaries.yml`, called from `release.yml`, for the
10
+ * push of the tag `v<version>` in this repository, on a GitHub-hosted runner.
11
+ * A build from a branch or a manual run is not a release and does not count.
12
+ *
13
+ * The Sigstore signature over the statement is not verified here: the
14
+ * statement is trusted as served by GitHub's API over TLS.
15
+ */
16
+ /** GitHub repository the standalone executables are released from. */
17
+ export declare const RELEASES_REPO = "WrongStack/WrongStack";
18
+ export interface AttestationSubject {
19
+ /** Release asset name, e.g. `wstack-windows-x64.exe`. */
20
+ assetName: string;
21
+ /** Lowercase hex SHA-256 of the downloaded bytes. */
22
+ sha256: string;
23
+ /** Release version without the `v`, e.g. `1.0.25`. */
24
+ version: string;
25
+ }
26
+ /** Throws unless GitHub holds a release attestation for `subject`. */
27
+ export declare function verifyReleaseAttestation(subject: AttestationSubject, signal?: AbortSignal): Promise<void>;
28
+ //# sourceMappingURL=release-attestation.d.ts.map