@wrongstack/cli 0.302.2 → 0.303.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.
@@ -52,7 +52,7 @@ import {
52
52
  import "./chunk-7OCVIDC7.js";
53
53
 
54
54
  // src/execution.ts
55
- import * as path12 from "node:path";
55
+ import * as path13 from "node:path";
56
56
  import { effectiveFallbackChain as effectiveFallbackChain2, setQueuedMessagesSnapshot as setQueuedMessagesSnapshot2 } from "@wrongstack/core/agent";
57
57
  import { attachTodosCheckpoint as attachTodosCheckpoint2 } from "@wrongstack/core/storage";
58
58
  import { normalizeTokenSavingTier as normalizeTokenSavingTier2 } from "@wrongstack/core/types";
@@ -1851,6 +1851,57 @@ function createSettingsAdapter(ctx) {
1851
1851
  return { getSettings, saveSettings };
1852
1852
  }
1853
1853
 
1854
+ // src/boot/tui-theme-adapter.ts
1855
+ import * as fs4 from "node:fs/promises";
1856
+ import * as path9 from "node:path";
1857
+ import { atomicWrite as atomicWrite2 } from "@wrongstack/core/utils";
1858
+ var VALID_PRESETS = /* @__PURE__ */ new Set([
1859
+ "catppuccin",
1860
+ "tokyo-night",
1861
+ "nord",
1862
+ "cyberpunk",
1863
+ "dracula",
1864
+ "gruvbox-dark",
1865
+ "solarized-dark",
1866
+ "one-dark",
1867
+ "monokai",
1868
+ "rose-pine",
1869
+ "kanagawa",
1870
+ "ayu-dark",
1871
+ "everforest",
1872
+ "night-owl",
1873
+ "synthwave"
1874
+ ]);
1875
+ function createThemeAdapter({ configStore, wpaths }) {
1876
+ return {
1877
+ getThemePreset: () => {
1878
+ const live = configStore.get();
1879
+ const candidate = live.themePreset;
1880
+ return candidate && VALID_PRESETS.has(candidate) ? candidate : void 0;
1881
+ },
1882
+ saveThemePreset: async (preset) => {
1883
+ if (!VALID_PRESETS.has(preset)) {
1884
+ throw new Error(`Unknown theme preset: ${preset}`);
1885
+ }
1886
+ configStore.update({ themePreset: preset });
1887
+ const configPath = activeProfileConfigPath(wpaths, configStore.get());
1888
+ let parsed = {};
1889
+ try {
1890
+ const raw = await fs4.readFile(configPath, "utf8");
1891
+ parsed = JSON.parse(raw);
1892
+ } catch (err) {
1893
+ const e = err;
1894
+ if (e.code !== "ENOENT") {
1895
+ throw err;
1896
+ }
1897
+ }
1898
+ parsed.themePreset = preset;
1899
+ await fs4.mkdir(path9.dirname(configPath), { recursive: true });
1900
+ await atomicWrite2(configPath, JSON.stringify(parsed, null, 2), { mode: 384 });
1901
+ }
1902
+ };
1903
+ }
1904
+
1854
1905
  // src/brain-menu/panel-service.ts
1855
1906
  import { BUILTIN_COUNCIL_PERSONAS } from "@wrongstack/core/execution";
1856
1907
  var PERSONA_CATALOG = BUILTIN_COUNCIL_PERSONAS.map((persona) => ({
@@ -2664,7 +2715,7 @@ function createChimeraWorkRegistry() {
2664
2715
 
2665
2716
  // src/execution-chimera-cascade.ts
2666
2717
  import * as fsp from "node:fs/promises";
2667
- import * as path9 from "node:path";
2718
+ import * as path10 from "node:path";
2668
2719
  import { emitReviewIfChanged } from "@wrongstack/core/plugin";
2669
2720
 
2670
2721
  // src/chimera-review-task.ts
@@ -3027,7 +3078,7 @@ async function maybeReReviewCascade({
3027
3078
  const reReadFiles = [];
3028
3079
  for (const f of bundle.files) {
3029
3080
  try {
3030
- const absPath = path9.join(bundle.cwd, f.path);
3081
+ const absPath = path10.join(bundle.cwd, f.path);
3031
3082
  const content = await fsp.readFile(absPath, "utf8");
3032
3083
  reReadFiles.push({ path: f.path, status: "modified", content });
3033
3084
  } catch {
@@ -3096,7 +3147,7 @@ async function maybeReReviewCascade({
3096
3147
 
3097
3148
  // src/execution-chimera-review.ts
3098
3149
  import { randomUUID as randomUUID3 } from "node:crypto";
3099
- import path10 from "node:path";
3150
+ import path11 from "node:path";
3100
3151
  import { effectiveFallbackChain } from "@wrongstack/core/agent";
3101
3152
  import {
3102
3153
  CHIMERA_REVIEW_PROMPT,
@@ -3109,7 +3160,7 @@ import {
3109
3160
  function normalizeFileKeyForCitation(raw, cwd) {
3110
3161
  const forward = raw.replace(/\\/g, "/").replace(/^\.\//, "");
3111
3162
  const isAbsolute = forward.startsWith("/") || /^[a-zA-Z]:\//.test(forward);
3112
- const pathMod = process.platform === "win32" ? path10.win32 : path10;
3163
+ const pathMod = process.platform === "win32" ? path11.win32 : path11;
3113
3164
  const relative = isAbsolute ? pathMod.relative(cwd, forward).replace(/\\/g, "/").replace(/^\.\//, "") : forward;
3114
3165
  return process.platform === "win32" ? relative.toLowerCase() : relative;
3115
3166
  }
@@ -3307,7 +3358,7 @@ function installChimeraReviewHandler({
3307
3358
  const changedBasenameIndex = /* @__PURE__ */ new Map();
3308
3359
  for (const file of p.files) {
3309
3360
  const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
3310
- const basename7 = path10.basename(file.path).toLowerCase();
3361
+ const basename7 = path11.basename(file.path).toLowerCase();
3311
3362
  const bucket = changedBasenameIndex.get(basename7);
3312
3363
  if (bucket) bucket.push(normalized);
3313
3364
  else changedBasenameIndex.set(basename7, [normalized]);
@@ -3315,7 +3366,7 @@ function installChimeraReviewHandler({
3315
3366
  const droppedCitations = citedFindings.filter((finding) => {
3316
3367
  const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
3317
3368
  if (citedPaths.has(citedKey)) return false;
3318
- const basename7 = path10.basename(finding.location.file).toLowerCase();
3369
+ const basename7 = path11.basename(finding.location.file).toLowerCase();
3319
3370
  const bucket = changedBasenameIndex.get(basename7);
3320
3371
  return !(bucket && bucket.length === 1);
3321
3372
  });
@@ -3616,6 +3667,7 @@ import {
3616
3667
  } from "@wrongstack/core/utils";
3617
3668
  import { readClipboardImage, routeImagesForModel } from "@wrongstack/runtime";
3618
3669
  import { createAutoProceedLoopGuard } from "@wrongstack/tools/auto-proceed-loop-guard";
3670
+ import { todoTool } from "@wrongstack/tools/todo";
3619
3671
 
3620
3672
  // src/repl-auto-proceed.ts
3621
3673
  import { color as color6, estimateRequestTokensCalibrated } from "@wrongstack/core/utils";
@@ -3791,7 +3843,7 @@ async function runContextCompaction(opts, _signal) {
3791
3843
 
3792
3844
  // src/repl-client-registration.ts
3793
3845
  import * as crypto from "node:crypto";
3794
- import * as path11 from "node:path";
3846
+ import * as path12 from "node:path";
3795
3847
  import { getSharedProjectMailbox, resolveProjectDir } from "@wrongstack/core/coordination";
3796
3848
  import { wstackGlobalRoot } from "@wrongstack/core/utils";
3797
3849
  function registerReplClient(opts) {
@@ -3801,7 +3853,7 @@ function registerReplClient(opts) {
3801
3853
  const hqConnection = startCliHqConnection({
3802
3854
  clientKind: "repl",
3803
3855
  projectRoot: replProjectRoot,
3804
- projectName: path11.basename(replProjectRoot),
3856
+ projectName: path12.basename(replProjectRoot),
3805
3857
  appConfig: opts.appConfig,
3806
3858
  capabilities: ["telemetry.publish", "mailbox.summary"]
3807
3859
  });
@@ -3815,7 +3867,7 @@ function registerReplClient(opts) {
3815
3867
  clientMailbox.registerClient({
3816
3868
  clientId,
3817
3869
  sessionId: opts.getSessionId?.() ?? replProjectRoot,
3818
- name: `REPL [${path11.basename(replProjectRoot)}]`,
3870
+ name: `REPL [${path12.basename(replProjectRoot)}]`,
3819
3871
  source: "repl",
3820
3872
  pid: process.pid
3821
3873
  }).then(() => {
@@ -4117,10 +4169,14 @@ ${lines.join("\n")}
4117
4169
  if (resolved.source === "todo" && resolved.todoId) {
4118
4170
  const selected = todos.find((todo) => todo.id === resolved.todoId);
4119
4171
  if (selected?.status === "pending") {
4120
- opts.agent.ctx.state.replaceTodos(
4121
- todos.map(
4122
- (todo) => todo.id === resolved.todoId ? { ...todo, status: "in_progress" } : todo.status === "in_progress" ? { ...todo, status: "pending" } : todo
4123
- )
4172
+ await todoTool.execute(
4173
+ {
4174
+ todos: todos.map(
4175
+ (todo) => todo.id === resolved.todoId ? { ...todo, status: "in_progress" } : todo.status === "in_progress" ? { ...todo, status: "pending" } : todo
4176
+ )
4177
+ },
4178
+ opts.agent.ctx,
4179
+ { signal: AbortSignal.timeout(3e4) }
4124
4180
  );
4125
4181
  }
4126
4182
  }
@@ -4293,10 +4349,14 @@ ${color9.dim(taskList2)}
4293
4349
  if (resolved.source === "todo" && resolved.todoId) {
4294
4350
  const selected = opts.agent.ctx.todos.find((todo) => todo.id === resolved.todoId);
4295
4351
  if (selected?.status === "pending") {
4296
- opts.agent.ctx.state.replaceTodos(
4297
- opts.agent.ctx.todos.map(
4298
- (todo) => todo.id === resolved.todoId ? { ...todo, status: "in_progress" } : todo.status === "in_progress" ? { ...todo, status: "pending" } : todo
4299
- )
4352
+ await todoTool.execute(
4353
+ {
4354
+ todos: opts.agent.ctx.todos.map(
4355
+ (todo) => todo.id === resolved.todoId ? { ...todo, status: "in_progress" } : todo.status === "in_progress" ? { ...todo, status: "pending" } : todo
4356
+ )
4357
+ },
4358
+ opts.agent.ctx,
4359
+ { signal: AbortSignal.timeout(3e4) }
4300
4360
  );
4301
4361
  }
4302
4362
  }
@@ -4988,6 +5048,8 @@ async function execute(deps) {
4988
5048
  fleetStreamController,
4989
5049
  applyLiveSettings
4990
5050
  }),
5051
+ ...createThemeAdapter({ configStore, wpaths }),
5052
+ configStore,
4991
5053
  effectiveMaxContext,
4992
5054
  titleAnimation: config.autonomy?.["terminalTitleAnimation"] ?? true,
4993
5055
  chime: config.autonomy?.["chime"] ?? false,
@@ -5191,7 +5253,7 @@ async function execute(deps) {
5191
5253
  attachments,
5192
5254
  effectiveMaxContext,
5193
5255
  getEffectiveMaxContext,
5194
- projectName: path12.basename(projectRoot) || void 0,
5256
+ projectName: path13.basename(projectRoot) || void 0,
5195
5257
  projectRoot,
5196
5258
  appConfig: config,
5197
5259
  getSessionId: () => agent.ctx.session?.id ?? session.id,
@@ -5250,4 +5312,4 @@ export {
5250
5312
  execute,
5251
5313
  resolveReviewerFallbackModels
5252
5314
  };
5253
- //# sourceMappingURL=execution-LZRYRGDD.js.map
5315
+ //# sourceMappingURL=execution-MVOH6PAQ.js.map
@@ -1,5 +1,14 @@
1
1
  import type { SubagentConfig } from '@wrongstack/core/types';
2
2
  import type { MultiAgentDeps } from './host-types.js';
3
+ /** Skills whose bodies were requested but did not make it into the prompt. */
4
+ export interface SkillResolutionReport {
5
+ content: string;
6
+ selected: string[];
7
+ /** skill → why it was dropped, so the omission is never silent. */
8
+ dropped: Record<string, 'not-found' | 'missing-capability' | 'missing-tool' | 'budget' | 'empty'>;
9
+ }
10
+ export declare function resolveHostSubagentSkillResolution(deps: MultiAgentDeps, roster: Record<string, SubagentConfig>, subCfg: SubagentConfig, availableToolNames?: readonly string[]): Promise<SkillResolutionReport>;
11
+ /** Backwards-compatible wrapper for callers that only need the prompt text. */
3
12
  export declare function resolveHostSubagentSkillContent(deps: MultiAgentDeps, roster: Record<string, SubagentConfig>, subCfg: SubagentConfig, availableToolNames?: readonly string[]): Promise<string>;
4
13
  export declare function retrieveHostSubagentMemory(deps: MultiAgentDeps, getLeaderMode: (() => string | undefined) | undefined, subCfg: SubagentConfig, taskContext?: Record<string, unknown>): Promise<string[]>;
5
14
  //# sourceMappingURL=host-context.d.ts.map
@@ -5,7 +5,7 @@ export declare class HostLearningRoleTracker {
5
5
  private readonly roles;
6
6
  private readonly accessOrder;
7
7
  constructor(maxEntries?: number);
8
- record(subagentId: string, role: string): void;
9
- capture(result: TaskResult, deps: Pick<MultiAgentDeps, 'container' | 'projectRoot'>): void;
8
+ record(subagentId: string, role: string, skills?: readonly string[]): void;
9
+ capture(result: TaskResult, deps: Pick<MultiAgentDeps, 'container' | 'projectRoot'>, onCaptured?: (role: string) => void): void;
10
10
  }
11
11
  //# sourceMappingURL=host-learning-tracker.d.ts.map
@@ -1,4 +1,15 @@
1
1
  import type { TaskResult } from '@wrongstack/core/types';
2
2
  import type { MultiAgentDeps } from './host-types.js';
3
- export declare function captureCompletedTaskLearningForHost(result: TaskResult, deps: Pick<MultiAgentDeps, 'container' | 'projectRoot'>, subagentLearningRoles: ReadonlyMap<string, string>): void;
3
+ /** What a spawn recorded about the agent that will produce this result. */
4
+ export interface LearningSubject {
5
+ role: string;
6
+ skills: readonly string[];
7
+ }
8
+ export declare function captureCompletedTaskLearningForHost(result: TaskResult, deps: Pick<MultiAgentDeps, 'container' | 'projectRoot'>, subjects: ReadonlyMap<string, LearningSubject>,
9
+ /**
10
+ * Called when a capture persisted at least one directive. The auto-optimize
11
+ * scheduler uses it as its trigger, so distillation follows learning without
12
+ * anyone pressing a button.
13
+ */
14
+ onCaptured?: (role: string) => void): void;
4
15
  //# sourceMappingURL=host-learning.d.ts.map
@@ -9,7 +9,7 @@ export interface HostSubagentFactoryContext {
9
9
  sessionFactory?: DirectorSessionFactory | undefined;
10
10
  filterTools: (allow?: string[]) => Tool[];
11
11
  mailboxProjectDir: () => string;
12
- recordLearningRole: (subagentId: string, role: string) => void;
12
+ recordLearningRole: (subagentId: string, role: string, skills?: readonly string[]) => void;
13
13
  subagentToolRegistry: (allow?: string[]) => ToolRegistry;
14
14
  }
15
15
  export declare function createHostSubagentFactory(config: Config, host: HostSubagentFactoryContext): AgentFactory;
@@ -39,6 +39,9 @@ export declare class MultiAgentHost {
39
39
  * Bounded to 20 entries with LRU eviction to prevent unbounded memory growth. */
40
40
  private readonly acpRunnerCache;
41
41
  private readonly learningRoles;
42
+ /** Background distillation of captured learning into per-skill addenda. */
43
+ private learningOptimizer;
44
+ private learningSwept;
42
45
  /** Adaptive concurrency controller — created in buildDirector() when config has
43
46
  * adaptiveConcurrency.enabled = true. Monitors FleetBus for 429 errors and
44
47
  * automatically adjusts maxConcurrent to prevent rate limiting. */
@@ -202,6 +205,25 @@ export declare class MultiAgentHost {
202
205
  private emitLifecycleCompleted;
203
206
  private recordLearningRole;
204
207
  private captureCompletedTaskLearning;
208
+ /**
209
+ * Lazily built so a session that never spawns a subagent pays nothing, and
210
+ * so the policy is read from the live config rather than frozen at boot.
211
+ * Returns null when auto-optimization is switched off.
212
+ */
213
+ private getLearningOptimizer;
214
+ /**
215
+ * Resolve a model for the distillation pass. Uses the `memory-curator` slot
216
+ * of the model matrix when one is configured — curating learned knowledge is
217
+ * exactly that role's job — and the session default otherwise. A failure
218
+ * here is not fatal: the pass still writes the deterministic skill addenda.
219
+ */
220
+ private resolveOptimizerLlm;
221
+ /**
222
+ * Evaluate every role with learning data once per session. Without it, a
223
+ * role that became eligible before this session would wait for its next
224
+ * capture — which for a rarely-used role can be never.
225
+ */
226
+ private sweepLearningOptimization;
205
227
  status(): FleetHostStatus;
206
228
  /**
207
229
  * Read-only concurrency + lifetime spawn budget for `/fleet status` and
@@ -47,7 +47,7 @@ var hqCmd = async (args, deps) => {
47
47
  return 1;
48
48
  };
49
49
  async function startServer(deps) {
50
- const { startHqServer } = await import("./hq-server-KU2Z54QU.js");
50
+ const { startHqServer } = await import("./hq-server-DME6EWIO.js");
51
51
  const dataDir = resolveDataDir(deps);
52
52
  const flags = deps.flags ?? {};
53
53
  const host = typeof flags["host"] === "string" ? flags["host"] : HQ_CLI_DEFAULT_HOST;
@@ -612,4 +612,4 @@ export {
612
612
  hqCmd,
613
613
  resolveAuditActor
614
614
  };
615
- //# sourceMappingURL=hq-AHPAE7EN.js.map
615
+ //# sourceMappingURL=hq-CD77GVSS.js.map
@@ -15,7 +15,7 @@ import {
15
15
  readLocalSubagentTranscript,
16
16
  sanitizeApiError,
17
17
  startHqServer
18
- } from "./chunk-WOXUE2CN.js";
18
+ } from "./chunk-LUAFQIXT.js";
19
19
  import "./chunk-KE7E7DPX.js";
20
20
  import "./chunk-Q5GTM25S.js";
21
21
  import "./chunk-7OCVIDC7.js";
@@ -37,4 +37,4 @@ export {
37
37
  sanitizeApiError,
38
38
  startHqServer
39
39
  };
40
- //# sourceMappingURL=hq-server-KU2Z54QU.js.map
40
+ //# sourceMappingURL=hq-server-DME6EWIO.js.map
package/dist/index.js CHANGED
@@ -38,12 +38,12 @@ import {
38
38
  } from "./chunk-YMXXOOFN.js";
39
39
  import {
40
40
  runUpdateCommand
41
- } from "./chunk-BXQG3H2Y.js";
41
+ } from "./chunk-53STH6CX.js";
42
42
  import "./chunk-U3SS4NRH.js";
43
43
  import "./chunk-NUIHRGPY.js";
44
44
  import {
45
45
  DEFAULT_PORT
46
- } from "./chunk-WOXUE2CN.js";
46
+ } from "./chunk-LUAFQIXT.js";
47
47
  import "./chunk-KE7E7DPX.js";
48
48
  import "./chunk-Q5GTM25S.js";
49
49
  import {
@@ -761,7 +761,7 @@ async function isPortInUse(host, port) {
761
761
  }
762
762
  async function handleHqShortCircuit(flags) {
763
763
  if (flags["hq"] !== true) return null;
764
- const { startHqServer } = await import("./hq-server-KU2Z54QU.js");
764
+ const { startHqServer } = await import("./hq-server-DME6EWIO.js");
765
765
  const tunnelRequested = flags["tunnel"] === true;
766
766
  const host = typeof flags["host"] === "string" ? flags["host"] : tunnelRequested ? "127.0.0.1" : HQ_CLI_DEFAULT_HOST2;
767
767
  if (tunnelRequested && !isLoopbackHost(host)) {
@@ -2306,10 +2306,10 @@ function compactSingleLine(text) {
2306
2306
 
2307
2307
  // src/subcommands/index.ts
2308
2308
  var loaders = {
2309
- acp: async () => (await import("./acp-XCE4JJF3.js")).acpCmd,
2309
+ acp: async () => (await import("./acp-AQMGKW6O.js")).acpCmd,
2310
2310
  init: async () => (await import("./init-E2NDDOHI.js")).initCmd,
2311
2311
  auth: async () => (await import("./auth-K7CYVVKH.js")).authCmd,
2312
- update: async () => (await import("./update-LTDJGAFU.js")).updateCmd,
2312
+ update: async () => (await import("./update-VZSOZGYC.js")).updateCmd,
2313
2313
  sessions: async () => (await import("./sessions-config-YX2ZPAFM.js")).sessionsCmd,
2314
2314
  config: async () => (await import("./sessions-config-YX2ZPAFM.js")).configCmd,
2315
2315
  rewind: async () => (await import("./rewind-7RE6ONIC.js")).rewindCmd,
@@ -2319,7 +2319,7 @@ var loaders = {
2319
2319
  skills: async () => (await import("./tools-skills-UNKLOB7M.js")).skillsCmd,
2320
2320
  providers: async () => (await import("./providers-models-VV74TRQ2.js")).providersCmd,
2321
2321
  models: async () => (await import("./providers-models-VV74TRQ2.js")).modelsCmd,
2322
- mcp: async () => (await import("./mcp-E5EBGOHF.js")).mcpCmd,
2322
+ mcp: async () => (await import("./mcp-AX6ZAFJR.js")).mcpCmd,
2323
2323
  plugin: async () => (await import("./plugin-usage-PTEETL3J.js")).pluginCmd,
2324
2324
  plugins: async () => (await import("./plugin-usage-PTEETL3J.js")).pluginCmd,
2325
2325
  diag: async () => (await import("./diag-doctor-ZF5BF2MK.js")).diagCmd,
@@ -2333,7 +2333,7 @@ var loaders = {
2333
2333
  quick: async () => (await import("./quick-VIO2BEHS.js")).quickCmd,
2334
2334
  bench: async () => (await import("./bench-XNDUJOSZ.js")).benchCmd,
2335
2335
  chronicle: async () => (await import("./chronicle-63MFCZN6.js")).chronicleCmd,
2336
- hq: async () => (await import("./hq-AHPAE7EN.js")).hqCmd,
2336
+ hq: async () => (await import("./hq-CD77GVSS.js")).hqCmd,
2337
2337
  mailbox: async () => (await import("./mailbox-serve-DBOOOOWZ.js")).mailboxServeCmd,
2338
2338
  permissions: async () => (await import("./permissions-2PWBL4YU.js")).permissionsCmd,
2339
2339
  project: async () => (await import("./project-BLQ3ALVL.js")).projectCmd,
@@ -3132,7 +3132,7 @@ async function initializeCli(argv) {
3132
3132
  async function main(argv) {
3133
3133
  const cliCtx = await initializeCli(argv);
3134
3134
  if (typeof cliCtx === "number") return cliCtx;
3135
- const { runInteractive } = await import("./cli-main-PJMDZHDK.js");
3135
+ const { runInteractive } = await import("./cli-main-37XO26GK.js");
3136
3136
  return runInteractive(cliCtx);
3137
3137
  }
3138
3138
 
@@ -220,7 +220,8 @@ async function serveMcpStdio(deps) {
220
220
  permissionPolicy,
221
221
  secretScrubber: new DefaultSecretScrubber(),
222
222
  maxToolTimeoutMs: deps.config.tools?.maxToolTimeoutMs ?? 3e5,
223
- perIterationOutputCapBytes: 1e6
223
+ perIterationOutputCapBytes: 1e6,
224
+ requireKanbanGovernance: true
224
225
  });
225
226
  const allowed = await selectExposedTools(registry, ctx, permissionPolicy, whitelist);
226
227
  const allowedNames = new Set(allowed.map((t) => t.name));
@@ -414,4 +415,4 @@ function isRecord(value) {
414
415
  export {
415
416
  mcpCmd
416
417
  };
417
- //# sourceMappingURL=mcp-E5EBGOHF.js.map
418
+ //# sourceMappingURL=mcp-AX6ZAFJR.js.map
@@ -7,7 +7,10 @@ import type { SlashCommandContext } from './command-context.js';
7
7
  * show — display current customization for one or all roles
8
8
  * update — write new identity/learned content (prompts for content)
9
9
  * refresh — reset identity.md + learned.md to empty templates (keep config/knowledge)
10
- * consolidate optimize raw learned entries into a reviewed, consolidated document
10
+ * capture re-scan the last turn for ## LEARNED blocks
11
+ * optimize — distil captures into per-skill addenda + a consolidated document
12
+ * (alias: consolidate)
13
+ * skills — list skills with project affinity; show or pin one
11
14
  * reset — delete ALL project customizations for a role (rm -rf the dir)
12
15
  * reset-all — delete customizations for EVERY role
13
16
  */
@@ -0,0 +1,6 @@
1
+ import type { InputReader, SlashCommand } from '@wrongstack/core/types';
2
+ import type { SlashCommandContext } from './command-context.js';
3
+ export declare function buildThemeCommand(opts: SlashCommandContext & {
4
+ inputReader?: InputReader | undefined;
5
+ }): SlashCommand;
6
+ //# sourceMappingURL=theme.d.ts.map
@@ -7,6 +7,8 @@ export interface UpdateCommandDeps {
7
7
  userHome: string;
8
8
  renderer: Pick<TerminalRenderer, 'write'>;
9
9
  flags?: SubcommandDeps['flags'] | undefined;
10
+ /** Test seam for a Windows PATH lookup; production uses process.env. */
11
+ environment?: NodeJS.ProcessEnv | undefined;
10
12
  }
11
13
  /** `wrongstack update` — Update the CLI via the detected global package manager. */
12
14
  export declare function runUpdateCommand(args: string[], deps: UpdateCommandDeps): Promise<number>;
@@ -3,7 +3,7 @@ import {
3
3
  detectUpdatePackageName,
4
4
  runUpdateCommand,
5
5
  updateCmd
6
- } from "./chunk-BXQG3H2Y.js";
6
+ } from "./chunk-53STH6CX.js";
7
7
  import "./chunk-U3SS4NRH.js";
8
8
  import "./chunk-NUIHRGPY.js";
9
9
  import "./chunk-7OCVIDC7.js";
@@ -13,4 +13,4 @@ export {
13
13
  runUpdateCommand,
14
14
  updateCmd
15
15
  };
16
- //# sourceMappingURL=update-LTDJGAFU.js.map
16
+ //# sourceMappingURL=update-VZSOZGYC.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/cli",
3
- "version": "0.302.2",
3
+ "version": "0.303.0",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack CLI — terminal AI coding agent with provider catalog from models.dev. Provides `wrongstack` and `wstack` binaries.",
6
6
  "keywords": [
@@ -42,30 +42,30 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "ws": "^8.21.1",
45
- "@wrongstack/core": "0.302.2",
46
- "@wrongstack/kanban": "0.302.2",
47
- "@wrongstack/mcp": "0.302.2",
48
- "@wrongstack/acp": "0.302.2",
49
- "@wrongstack/plug-lsp": "0.302.2",
50
- "@wrongstack/runtime": "0.302.2",
51
- "@wrongstack/requirement-intake": "0.302.2",
52
- "@wrongstack/plugins": "0.302.2",
53
- "@wrongstack/sdd": "0.302.2",
54
- "@wrongstack/bench": "0.302.2",
55
- "@wrongstack/security-scanner": "0.302.2",
56
- "@wrongstack/providers": "0.302.2",
57
- "@wrongstack/simpleui": "0.302.2",
58
- "@wrongstack/sage": "0.302.2",
59
- "@wrongstack/techstack": "0.302.2",
60
- "@wrongstack/telegram": "0.302.2",
61
- "@wrongstack/tui": "0.302.2",
62
- "@wrongstack/tools": "0.302.2",
63
- "@wrongstack/webui-server": "0.302.2",
64
- "@wrongstack/webui": "0.302.2",
65
- "@wrongstack/webui-hq": "0.302.2"
45
+ "@wrongstack/acp": "0.303.0",
46
+ "@wrongstack/bench": "0.303.0",
47
+ "@wrongstack/core": "0.303.0",
48
+ "@wrongstack/plug-lsp": "0.303.0",
49
+ "@wrongstack/runtime": "0.303.0",
50
+ "@wrongstack/security-scanner": "0.303.0",
51
+ "@wrongstack/mcp": "0.303.0",
52
+ "@wrongstack/plugins": "0.303.0",
53
+ "@wrongstack/providers": "0.303.0",
54
+ "@wrongstack/sdd": "0.303.0",
55
+ "@wrongstack/kanban": "0.303.0",
56
+ "@wrongstack/requirement-intake": "0.303.0",
57
+ "@wrongstack/sage": "0.303.0",
58
+ "@wrongstack/simpleui": "0.303.0",
59
+ "@wrongstack/tui": "0.303.0",
60
+ "@wrongstack/tools": "0.303.0",
61
+ "@wrongstack/webui-hq": "0.303.0",
62
+ "@wrongstack/techstack": "0.303.0",
63
+ "@wrongstack/telegram": "0.303.0",
64
+ "@wrongstack/webui": "0.303.0",
65
+ "@wrongstack/webui-server": "0.303.0"
66
66
  },
67
67
  "optionalDependencies": {
68
- "@wrongstack/desktop": "0.302.2"
68
+ "@wrongstack/desktop": "0.303.0"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^26.1.2",