@wrongstack/core 0.264.0 → 0.267.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/{agent-bridge-D8sa1vtv.d.ts → agent-bridge-STJ3JwwK.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-c9DLkaas.d.ts → agent-subagent-runner-CzPGP3jA.d.ts} +131 -11
  3. package/dist/{brain-O1IdKPaK.d.ts → brain-Cdg77tVN.d.ts} +103 -2
  4. package/dist/{compactor-BBy0rCtB.d.ts → compactor-iMZ84CXq.d.ts} +19 -1
  5. package/dist/{config-Dz2F3H2K.d.ts → config-Du3pYYln.d.ts} +132 -13
  6. package/dist/{context-BGSpZNSE.d.ts → context-dT5Ueund.d.ts} +90 -12
  7. package/dist/coordination/index.d.ts +78 -22
  8. package/dist/coordination/index.js +695 -273
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/{default-config-CXsDvOmP.d.ts → default-config-B0cj-Hry.d.ts} +11 -1
  11. package/dist/defaults/index.d.ts +28 -28
  12. package/dist/defaults/index.js +2327 -965
  13. package/dist/defaults/index.js.map +1 -1
  14. package/dist/execution/index.d.ts +16 -16
  15. package/dist/execution/index.js +1500 -371
  16. package/dist/execution/index.js.map +1 -1
  17. package/dist/execution/prompt-enhancer.d.ts +2 -2
  18. package/dist/execution/prompt-enhancer.js +1 -1
  19. package/dist/execution/prompt-enhancer.js.map +1 -1
  20. package/dist/extension/index.d.ts +6 -6
  21. package/dist/{goal-preamble-DzjFuN3p.d.ts → goal-preamble-SulMTowG.d.ts} +33 -12
  22. package/dist/{goal-store-CxWmCGbH.d.ts → goal-store-CABDwdFE.d.ts} +1 -1
  23. package/dist/{index-CbLSI66_.d.ts → index-Bms0m4oy.d.ts} +5 -5
  24. package/dist/{index-CYIQrXVF.d.ts → index-DtCVWel4.d.ts} +8 -8
  25. package/dist/index-IEuxQd-E.d.ts +82 -0
  26. package/dist/index.d.ts +261 -57
  27. package/dist/index.js +4799 -2212
  28. package/dist/index.js.map +1 -1
  29. package/dist/infrastructure/index.d.ts +6 -6
  30. package/dist/infrastructure/index.js +84 -9
  31. package/dist/infrastructure/index.js.map +1 -1
  32. package/dist/kernel/index.d.ts +9 -9
  33. package/dist/kernel/index.js +1 -1
  34. package/dist/kernel/index.js.map +1 -1
  35. package/dist/{mcp-servers-DC4QRPUI.d.ts → mcp-servers-C2cBTxUR.d.ts} +3 -3
  36. package/dist/models/index.d.ts +5 -5
  37. package/dist/models/index.js +104 -31
  38. package/dist/models/index.js.map +1 -1
  39. package/dist/{models-registry-B_siPxqN.d.ts → models-registry-BqGZNJQ-.d.ts} +1 -1
  40. package/dist/{multi-agent-coordinator-CK5Jdj9K.d.ts → multi-agent-coordinator-B8R43uPz.d.ts} +1 -1
  41. package/dist/{null-fleet-bus-DgvD4SCO.d.ts → null-fleet-bus-CnXa5oTH.d.ts} +14 -9
  42. package/dist/observability/index.d.ts +2 -2
  43. package/dist/{parallel-eternal-engine-bK0JQBR_.d.ts → parallel-eternal-engine-DdNnw9BQ.d.ts} +11 -9
  44. package/dist/{path-resolver-BPEDlN38.d.ts → path-resolver-COIMLCQL.d.ts} +3 -3
  45. package/dist/{permission-4yvGmMRB.d.ts → permission-B75JAi3-.d.ts} +1 -1
  46. package/dist/{permission-policy-C6XpsBOy.d.ts → permission-policy-DlR9eJAM.d.ts} +2 -2
  47. package/dist/{pipeline-CXCeMz8J.d.ts → pipeline-BfD2k1rT.d.ts} +3 -3
  48. package/dist/{plan-templates-BvzRBkJc.d.ts → plan-templates-DSIKCXZN.d.ts} +32 -8
  49. package/dist/provider-model-resolve-BNRsNuJx.d.ts +107 -0
  50. package/dist/{provider-runner-C5aQpDWE.d.ts → provider-runner-CX7iIvox.d.ts} +3 -3
  51. package/dist/{retry-policy-CFhdtRzz.d.ts → retry-policy-BilV1ujH.d.ts} +1 -1
  52. package/dist/sdd/index.d.ts +8 -8
  53. package/dist/sdd/index.js +286 -105
  54. package/dist/sdd/index.js.map +1 -1
  55. package/dist/secret-vault-BAKpgFw_.d.ts +57 -0
  56. package/dist/{secret-vault-CxiVLbt1.d.ts → secret-vault-gkvEZZfE.d.ts} +43 -4
  57. package/dist/security/index.d.ts +6 -68
  58. package/dist/security/index.js +296 -95
  59. package/dist/security/index.js.map +1 -1
  60. package/dist/{selector-gIuhRTkN.d.ts → selector-Bc7eWtT3.d.ts} +1 -1
  61. package/dist/{session-event-bridge-DkvvrpDt.d.ts → session-event-bridge-D-araDEz.d.ts} +1 -1
  62. package/dist/{session-reader-KdfVwkKP.d.ts → session-reader-D7Dapswh.d.ts} +1 -1
  63. package/dist/storage/index.d.ts +112 -15
  64. package/dist/storage/index.js +491 -156
  65. package/dist/storage/index.js.map +1 -1
  66. package/dist/tools/index.d.ts +4 -2
  67. package/dist/tools/index.js.map +1 -1
  68. package/dist/types/index.d.ts +21 -21
  69. package/dist/types/index.js +1523 -450
  70. package/dist/types/index.js.map +1 -1
  71. package/dist/utils/index.d.ts +455 -407
  72. package/dist/utils/index.js +2191 -1203
  73. package/dist/utils/index.js.map +1 -1
  74. package/dist/{wstack-paths-CJjEwPXn.d.ts → wstack-paths-hOpNLmvf.d.ts} +2 -0
  75. package/package.json +1 -1
  76. package/skills/api-design/SKILL.md +1 -1
  77. package/skills/audit-log/SKILL.md +6 -6
  78. package/skills/bug-hunter/SKILL.md +5 -5
  79. package/skills/chimera/SKILL.md +4 -4
  80. package/skills/docker-deploy/SKILL.md +1 -1
  81. package/skills/git-flow/SKILL.md +3 -3
  82. package/skills/multi-agent/SKILL.md +3 -3
  83. package/skills/node-modern/SKILL.md +1 -0
  84. package/skills/observability/SKILL.md +2 -2
  85. package/skills/output-standards/SKILL.md +51 -28
  86. package/skills/refactor-planner/SKILL.md +3 -3
  87. package/skills/security-scanner/SKILL.md +4 -3
  88. package/skills/tech-stack/SKILL.md +1 -2
  89. package/dist/llm-selector-DzxuZnNz.d.ts +0 -58
  90. package/dist/secret-vault-BJDY28ev.d.ts +0 -25
@@ -1,4 +1,4 @@
1
- import { B as BridgeTransport, a as BridgeMessage, A as AgentBridge, b as AgentBridgeConfig } from './agent-subagent-runner-c9DLkaas.js';
1
+ import { B as BridgeTransport, a as BridgeMessage, A as AgentBridge, b as AgentBridgeConfig } from './agent-subagent-runner-CzPGP3jA.js';
2
2
 
3
3
  /**
4
4
  * In-memory pub/sub transport for agent-to-agent messaging.
@@ -1,12 +1,12 @@
1
- import { c as ToolCallPipelinePayload, d as ToolWrapper, E as ExtensionRegistry, S as SystemPromptContributor, e as ToolRegistry, P as ProviderRegistry, A as AgentPipelines, f as ToolExecutorLike, g as AgentInit, h as AgentInput, R as RunResult } from './index-CbLSI66_.js';
2
- import { C as Container, R as ReadonlyPipeline, a as Renderer } from './pipeline-CXCeMz8J.js';
3
- import { E as EventBus, a as EventName, L as Listener } from './brain-O1IdKPaK.js';
4
- import { R as RetryPolicy, E as ErrorHandler } from './retry-policy-CFhdtRzz.js';
1
+ import { c as ToolCallPipelinePayload, d as ToolWrapper, E as ExtensionRegistry, S as SystemPromptContributor, e as ToolRegistry, P as ProviderRegistry, A as AgentPipelines, f as ToolExecutorLike, g as AgentInit, h as AgentInput, R as RunResult } from './index-Bms0m4oy.js';
2
+ import { C as Container, R as ReadonlyPipeline, a as Renderer } from './pipeline-BfD2k1rT.js';
3
+ import { E as EventBus, a as EventName, L as Listener } from './brain-Cdg77tVN.js';
4
+ import { R as RetryPolicy, E as ErrorHandler } from './retry-policy-BilV1ujH.js';
5
5
  import { L as Logger } from './logger-B63L5bTg.js';
6
6
  import { T as Tracer } from './observability-D-HZN_mF.js';
7
- import { P as PermissionPolicy } from './permission-4yvGmMRB.js';
8
- import { U as Usage, C as Context, J as JSONSchema, R as Request, b as Response, g as ContentBlock, n as TextBlock, T as Tool, P as Provider, o as RunOptions } from './context-BGSpZNSE.js';
9
- import { W as WireFamily, H as HookEvent, e as HookMatcher, I as InProcessHook, h as Config } from './config-Dz2F3H2K.js';
7
+ import { P as PermissionPolicy } from './permission-B75JAi3-.js';
8
+ import { U as Usage, C as Context, J as JSONSchema, R as Request, b as Response, g as ContentBlock, o as TextBlock, T as Tool, P as Provider, p as RunOptions } from './context-dT5Ueund.js';
9
+ import { W as WireFamily, H as HookEvent, f as HookMatcher, I as InProcessHook, i as Config } from './config-Du3pYYln.js';
10
10
 
11
11
  /**
12
12
  * Single fleet-wide event with subagent attribution. Whatever a child
@@ -130,6 +130,23 @@ declare class FleetUsageAggregator {
130
130
  }
131
131
 
132
132
  type BudgetKind = 'tool_calls' | 'iterations' | 'tokens' | 'timeout' | 'idle_timeout' | 'cost';
133
+ /**
134
+ * Fraction of the wall-clock `timeoutMs` window at which a PROACTIVE extension
135
+ * is negotiated — BEFORE the deadline is actually crossed. The coordinator
136
+ * watchdog (`executeWithTimeout`) arms at `timeoutMs * TIMEOUT_PREEMPT_FRACTION`
137
+ * so a still-progressing subagent gets its ceiling raised while it is below the
138
+ * limit, and never enters a "timed out" state. Reactive enforcement at the real
139
+ * deadline still stands for the no-progress / denied case. Shared so the asking
140
+ * side and any future caller agree on the same lead point.
141
+ */
142
+ declare const TIMEOUT_PREEMPT_FRACTION = 0.85;
143
+ /**
144
+ * Hard safety net for budget negotiation decisions. If no listener responds to
145
+ * `budget.threshold_reached` within this window the negotiation defaults to
146
+ * `'stop'`. Exported so the coordinator's watchdog can reuse the same ceiling
147
+ * without hardcoding a second copy.
148
+ */
149
+ declare const DECISION_TIMEOUT_MS = 60000;
133
150
  declare class BudgetExceededError extends Error {
134
151
  readonly kind: BudgetKind;
135
152
  readonly limit: number;
@@ -215,7 +232,18 @@ type BudgetThresholdHandler = (info: {
215
232
  used: number;
216
233
  limit: number;
217
234
  requestDecision: () => Promise<BudgetThresholdDecision>;
218
- }) => 'throw' | 'continue' | Promise<BudgetThresholdDecision>;
235
+ /**
236
+ * Direct grant/deny hooks for SYNCHRONOUS policy or recording handlers that
237
+ * decide in-process without a wired `budget.threshold_reached` listener
238
+ * (e.g. the coordinator watchdog). `extend` patches the limits in place;
239
+ * `deny` records the intent to stop. Production listener-driven handlers use
240
+ * `requestDecision()` instead and can ignore these.
241
+ */
242
+ extend?: (extra: Partial<BudgetLimits>) => void;
243
+ deny?: () => void;
244
+ }) => 'throw' | 'continue' | 'stop' | {
245
+ extend: Partial<BudgetLimits>;
246
+ } | Promise<BudgetThresholdDecision>;
219
247
  /**
220
248
  * Per-subagent budget enforcement. Each subagent gets its own instance so a
221
249
  * runaway agent can't drain the cost ceiling of its siblings. All record/check
@@ -237,6 +265,12 @@ type BudgetThresholdHandler = (info: {
237
265
  */
238
266
  declare class SubagentBudget {
239
267
  readonly limits: Readonly<BudgetLimits>;
268
+ /** Patch one or more budget limits in-place after construction.
269
+ * Used by the coordinator watchdog when granting an extension.
270
+ * All fields are optional — only provided fields are updated.
271
+ * This is the single write path for limit mutations so that future
272
+ * validation or side-effects live in one place (M1). */
273
+ patchLimits(ext: Partial<BudgetLimits>): void;
240
274
  private iterations;
241
275
  private toolCalls;
242
276
  private tokenInput;
@@ -263,6 +297,32 @@ declare class SubagentBudget {
263
297
  * Used to emit `budget.threshold_reached` events in `'auto'` mode.
264
298
  */
265
299
  _events?: EventBus | undefined;
300
+ /**
301
+ * Guard against dual-path races between the coordinator watchdog
302
+ * (`executeWithTimeout`) and the budget's own `checkTimeout()`.
303
+ * Both paths detect `elapsed >= timeoutMs` and can emit
304
+ * `budget.threshold_reached` for kind `'timeout'` simultaneously.
305
+ * Set to the current `timeoutMs` ceiling by the coordinator BEFORE
306
+ * calling `onThreshold`, and cleared after the negotiation resolves.
307
+ * `checkTimeout()` skips its wall-clock check while this is set so
308
+ * the coordinator's watchdog is the sole source of wall-clock timeout
309
+ * events — `checkTimeout()` focuses exclusively on `idle_timeout`.
310
+ */
311
+ private _watchdogActive;
312
+ /** Returns the timeout ceiling currently being negotiated by the watchdog,
313
+ * or `undefined` when no wall-clock negotiation is in flight.
314
+ * Used by `executeWithTimeout` to detect a stale lock (M3). */
315
+ get watchdogActive(): number | undefined;
316
+ /** Called by the coordinator watchdog BEFORE calling `onThreshold` so that
317
+ * `checkTimeout()` skips its wall-clock check for this ceiling. Prevents
318
+ * the budget's own `checkTimeout()` from emitting a second
319
+ * `budget.threshold_reached` event while the watchdog is already
320
+ * negotiating the same wall-clock deadline (C1). */
321
+ setWatchdogNegotiation(timeoutMs: number): void;
322
+ /** Clears the watchdog guard after negotiation resolves. Called in the
323
+ * `finally` block of both the pre-empt and deadline branches so it fires
324
+ * on every exit path: grant, deny, throw, or error. */
325
+ clearWatchdogNegotiation(): void;
266
326
  /**
267
327
  * Negotiation mode — controls whether a threshold hit tries to emit
268
328
  * `budget.threshold_reached` and wait for a coordinator decision, or
@@ -320,6 +380,24 @@ declare class SubagentBudget {
320
380
  * Returns the kinds that were found to be exceeded (for logging/debugging).
321
381
  */
322
382
  private checkLimits;
383
+ /**
384
+ * Invoke `onThreshold` once for `entry` on the NO-LISTENER path and report
385
+ * whether it decided synchronously. Returns `true` when the handler returned
386
+ * a synchronous decision (already honored — an `extend` patched the limits),
387
+ * or `false` when it returned a Promise (async; the caller hard-stops, since
388
+ * there is no listener to resolve the negotiation). The handler is given the
389
+ * full info shape (`requestDecision` plus direct `extend`/`deny`) so both
390
+ * recording handlers and policy handlers work without a wired listener.
391
+ */
392
+ private _invokeHandlerSync;
393
+ /**
394
+ * Emit `budget.threshold_reached` and resolve to the listener's verdict.
395
+ * Resolves to `'stop'` immediately when there is no listener (or no bus) so
396
+ * no negotiation can hang and no fallback timer leaks. Mirrors the
397
+ * coordinator watchdog's own request path so both agree on the no-listener
398
+ * default.
399
+ */
400
+ private _busRequestDecision;
323
401
  /**
324
402
  * Per-kind in-flight negotiation Promises. Each budget kind can have its
325
403
  * own concurrent negotiation — e.g. iterations and timeout can both
@@ -415,6 +493,15 @@ interface SubagentConfig {
415
493
  * default reaper for delegated subagents (see `applyRosterBudget`).
416
494
  */
417
495
  idleTimeoutMs?: number | undefined;
496
+ /**
497
+ * Fraction of `timeoutMs` at which the proactive pre-empt fires (0.0–1.0).
498
+ * At this point the watchdog negotiates a ceiling extension while the
499
+ * agent is still under its limit, so a progressing agent gets its
500
+ * ceiling raised before ever entering a timed-out state.
501
+ * Defaults to `TIMEOUT_PREEMPT_FRACTION` (0.85). Lower values fire earlier;
502
+ * higher values fire closer to the deadline. Ignored when `timeoutMs` is unset.
503
+ */
504
+ preemptFraction?: number | undefined;
418
505
  tools?: string[] | undefined;
419
506
  /**
420
507
  * Tools to explicitly disable for this subagent. These tools will be
@@ -423,6 +510,17 @@ interface SubagentConfig {
423
510
  * fully enforce (e.g., preventing delegation by removing the delegate tool).
424
511
  */
425
512
  disabledTools?: string[] | undefined;
513
+ /**
514
+ * Capability allowlist for this subagent's `AutoApprovePermissionPolicy`.
515
+ * Subagents run non-interactively, so the policy auto-approves only tools
516
+ * whose declared capabilities intersect this list; everything else is
517
+ * denied by the subagent guard. Defaults (when omitted) to the read-only
518
+ * safe set `['fs.read', 'net.outbound']`. Widen it per-spawn when a task
519
+ * legitimately needs more — e.g. `/techstack` adds `'fs.write'` so the
520
+ * subagent can write its report. Never grant `shell.*` unless the task
521
+ * truly requires arbitrary command execution.
522
+ */
523
+ allowedCapabilities?: readonly string[] | undefined;
426
524
  model?: string | undefined;
427
525
  priority?: number | undefined;
428
526
  /**
@@ -732,6 +830,13 @@ interface SlashCommand {
732
830
  * If absent, `/help <name>` falls back to `description`.
733
831
  */
734
832
  help?: string | undefined;
833
+ /**
834
+ * When true, this command does not appear in the slash-picker list
835
+ * triggered by typing `/` alone. It is still dispatchable and
836
+ * searchable when the user types a matching prefix (e.g. `/f`).
837
+ * Defaults to false.
838
+ */
839
+ hidden?: boolean | undefined;
735
840
  /**
736
841
  * Execute the command.
737
842
  * @param args Everything after the command name (trimmed by dispatch).
@@ -966,8 +1071,23 @@ interface Plugin {
966
1071
  * defaultConfig: { ttl: 3600, maxSize: 100 }
967
1072
  */
968
1073
  defaultConfig?: Record<string, unknown>;
969
- setup(api: PluginAPI): void | Promise<void>;
970
- teardown?(api: PluginAPI): void | Promise<void>;
1074
+ /**
1075
+ * Called by the host to activate the plugin. Receives the `PluginAPI`
1076
+ * and an optional `AbortSignal` the plugin should respect for
1077
+ * cancellation and timeout. `setup` must complete before the plugin is
1078
+ * considered loaded; if it times out the plugin is rejected.
1079
+ */
1080
+ setup(api: PluginAPI, opts?: {
1081
+ signal?: AbortSignal | undefined;
1082
+ }): void | Promise<void>;
1083
+ /**
1084
+ * Called by the host during unload. Receives the same `PluginAPI` instance
1085
+ * the plugin saw during `setup` and an optional `AbortSignal`. Teardown
1086
+ * is best-effort — a timeout does not prevent other plugins from unloading.
1087
+ */
1088
+ teardown?(api: PluginAPI, opts?: {
1089
+ signal?: AbortSignal | undefined;
1090
+ }): void | Promise<void>;
971
1091
  /**
972
1092
  * Optional health check. Called by the host (e.g. `/diag plugins` slash
973
1093
  * command or health endpoint) to surface plugin status. Return
@@ -1084,4 +1204,4 @@ interface AgentRunnerOptions {
1084
1204
  */
1085
1205
  declare function makeAgentSubagentRunner(opts: AgentRunnerOptions): SubagentRunner;
1086
1206
 
1087
- export { type ProviderFactory as $, type AgentBridge as A, type BridgeTransport as B, type CoordinatorStatus as C, type DoneCondition as D, type BudgetThresholdDecision as E, FleetBus as F, type BudgetThresholdHandler as G, BudgetThresholdSignal as H, type BudgetUsage as I, type CoordinatorEvents as J, type FleetEvent as K, type FleetHandler as L, type MultiAgentCoordinator as M, type PluginDependency as N, SubagentBudget as O, type PluginAPI as P, type SubagentContext as Q, type SubagentError as R, type SubagentConfig as S, type TaskSpec as T, type SubagentErrorKind as U, type SubagentRunContext as V, type SubagentRunOutcome as W, type SubagentUsageSnapshot as X, type TaskDelegation as Y, makeAgentSubagentRunner as Z, withDisabledToolFiltering as _, type BridgeMessage as a, type AgentBridgeConfig as b, type MultiAgentConfig as c, type SubagentRunner as d, type SpawnResult as e, type TaskResult as f, Agent as g, type AgentFactory as h, type FleetUsage as i, FleetUsageAggregator as j, type SlashCommand as k, type PluginPipelines as l, type ToolRegistryView as m, type ProviderRegistryView as n, type MCPRegistryView as o, type SlashCommandRegistryView as p, type SessionWriterView as q, type MetricsSinkView as r, type PluginCapabilities as s, type Plugin as t, type AgentFactoryResult as u, type AgentRunnerOptions as v, BudgetExceededError as w, type BudgetKind as x, type BudgetLimits as y, type BudgetNegotiationMode as z };
1207
+ export { makeAgentSubagentRunner as $, type AgentBridge as A, type BridgeTransport as B, type CoordinatorStatus as C, type DoneCondition as D, type BudgetNegotiationMode as E, FleetBus as F, type BudgetThresholdDecision as G, type BudgetThresholdHandler as H, BudgetThresholdSignal as I, type BudgetUsage as J, type CoordinatorEvents as K, DECISION_TIMEOUT_MS as L, type MultiAgentCoordinator as M, type FleetEvent as N, type FleetHandler as O, type PluginAPI as P, SubagentBudget as Q, type SubagentContext as R, type SubagentConfig as S, type TaskSpec as T, type SubagentError as U, type SubagentErrorKind as V, type SubagentRunContext as W, type SubagentRunOutcome as X, type SubagentUsageSnapshot as Y, TIMEOUT_PREEMPT_FRACTION as Z, type TaskDelegation as _, type BridgeMessage as a, withDisabledToolFiltering as a0, type ProviderFactory as a1, type AgentBridgeConfig as b, type MultiAgentConfig as c, type SubagentRunner as d, type SpawnResult as e, type TaskResult as f, Agent as g, type AgentFactory as h, type FleetUsage as i, FleetUsageAggregator as j, type SlashCommand as k, type PluginPipelines as l, type ToolRegistryView as m, type ProviderRegistryView as n, type MCPRegistryView as o, type SlashCommandRegistryView as p, type SessionWriterView as q, type MetricsSinkView as r, type PluginCapabilities as s, type PluginDependency as t, type Plugin as u, type AgentFactoryResult as v, type AgentRunnerOptions as w, BudgetExceededError as x, type BudgetKind as y, type BudgetLimits as z };
@@ -1,4 +1,4 @@
1
- import { U as Usage, C as Context, j as ToolProgressEvent, T as Tool } from './context-BGSpZNSE.js';
1
+ import { U as Usage, C as Context, j as ToolProgressEvent, T as Tool, k as ToolOutputMetadata } from './context-dT5Ueund.js';
2
2
 
3
3
  type MemoryScope = 'project-agents' | 'project-memory' | 'user-memory';
4
4
  type MemoryType = 'fact' | 'decision' | 'convention' | 'preference' | 'reference' | 'anti_pattern';
@@ -256,8 +256,16 @@ interface EventMap {
256
256
  id: string;
257
257
  event: ToolProgressEvent;
258
258
  };
259
+ /** Cache hit on session store load — used by observability layers. */
260
+ 'storage.cache_hit': {
261
+ sessionId: string;
262
+ store: string;
263
+ filePath: string;
264
+ operation: string;
265
+ durationMs: number;
266
+ };
259
267
  /**
260
- * Fired when a tool call needs user confirmation and no confirmHandler
268
+ * Fired when a tool call needs confirmation
261
269
  * is registered on the executor. The TUI renders a confirmation dialog
262
270
  * from this event. Resolution is driven by calling the resolve function
263
271
  * passed in the payload with a decision string ('yes' | 'no' | 'always' | 'deny').
@@ -279,6 +287,43 @@ interface EventMap {
279
287
  pattern: string;
280
288
  decision: 'always' | 'deny';
281
289
  };
290
+ /**
291
+ * Fired when the agent loop detects that the model is repeating the same
292
+ * response shape over and over — a tight loop that would otherwise burn
293
+ * iterations indefinitely. The loop breaks with status `max_iterations`
294
+ * after `repeatCount` consecutive identical iterations.
295
+ *
296
+ * Two flavours caught by the same safety valve:
297
+ * - `kind: 'tool'` — the same tool(s) called with effectively the same
298
+ * inputs (catches k2p7's tendency to retry identical tool calls when
299
+ * a tool returns an unexpected empty result).
300
+ * - `kind: 'message'` — the same assistant text repeated, with no tool
301
+ * calls. K2P7 and other weak-instruction-following models can echo
302
+ * their last assistant turn verbatim across many iterations in
303
+ * autonomous-continue mode. The fingerprint also matches this case
304
+ * so the safety valve catches it too.
305
+ * - `kind: 'mixed'` — both: the response contains tool calls AND text,
306
+ * and the combined fingerprint (tool names + text) repeats.
307
+ *
308
+ * UIs can render a warning chip. The `kind` field is additive — older
309
+ * subscribers that only read `tools` continue to work.
310
+ */
311
+ 'tool.loop_detected': {
312
+ ctx: Context;
313
+ /** Comma-separated tool names involved in the loop, or empty string for pure message loops. */
314
+ tools: string;
315
+ /** Number of consecutive identical iterations detected. */
316
+ repeatCount: number;
317
+ /** 0-based iteration index where the loop was detected. */
318
+ iteration: number;
319
+ /**
320
+ * Shape of the loop. `tool` = identical tool calls; `message` = identical
321
+ * text-only response; `mixed` = both tool calls and text repeated.
322
+ * Defaults to `tool` for backward compatibility with subscribers that
323
+ * pre-date the field.
324
+ */
325
+ kind?: 'tool' | 'message' | 'mixed' | undefined;
326
+ };
282
327
  /**
283
328
  * `output` is a truncated preview of the tool's serialized result text
284
329
  * (capped at ~400 chars by the emitter). UIs render this inline in the
@@ -318,6 +363,13 @@ interface EventMap {
318
363
  * actual lines the model received and forwards it here. Undefined
319
364
  * for tools without a meaningful line count. */
320
365
  outputLines?: number | undefined;
366
+ /**
367
+ * Parsed context-management metadata for the result the model saw. This is
368
+ * intentionally compact: file/symbol/error/path-integrity hints, not the
369
+ * full output body. Compaction uses it to distinguish seen information from
370
+ * information later referenced by the assistant.
371
+ */
372
+ metadata?: ToolOutputMetadata | undefined;
321
373
  };
322
374
  /**
323
375
  * Fired by the `delegate` tool right before it hands work to a subagent
@@ -445,6 +497,21 @@ interface EventMap {
445
497
  load: number;
446
498
  /** Provider's max context window in tokens. */
447
499
  maxContext: number;
500
+ /** Budget snapshot used for the compaction decision. */
501
+ budget?: {
502
+ maxContext: number;
503
+ inputTokens: number;
504
+ availableInputTokens: number;
505
+ remainingInputTokens: number;
506
+ reservedOutputTokens: number;
507
+ reservedSafetyTokens: number;
508
+ load: number;
509
+ overflowTokens: number;
510
+ } | undefined;
511
+ /** Adaptive trigger signals observed alongside token pressure. */
512
+ signals?: {
513
+ repeatedReadCount?: number | undefined;
514
+ } | undefined;
448
515
  /** Full compaction report from the compactor. */
449
516
  report: {
450
517
  before: number;
@@ -470,6 +537,19 @@ interface EventMap {
470
537
  level: 'warn' | 'soft' | 'hard';
471
538
  tokens: number;
472
539
  maxContext: number;
540
+ budget?: {
541
+ maxContext: number;
542
+ inputTokens: number;
543
+ availableInputTokens: number;
544
+ remainingInputTokens: number;
545
+ reservedOutputTokens: number;
546
+ reservedSafetyTokens: number;
547
+ load: number;
548
+ overflowTokens: number;
549
+ } | undefined;
550
+ signals?: {
551
+ repeatedReadCount?: number | undefined;
552
+ } | undefined;
473
553
  load: number;
474
554
  fatal: boolean;
475
555
  };
@@ -801,6 +881,27 @@ interface EventMap {
801
881
  durationMs?: number;
802
882
  traceId?: string;
803
883
  };
884
+ /**
885
+ * Real-time client status event. Emitted by TUI/CLI/WebUI to report current
886
+ * session stats (tool calls, tokens, model, mode, cost). Broadcast immediately
887
+ * to all WebUI clients via setup-events.ts and written to status.json for
888
+ * external watchers.
889
+ */
890
+ 'client.status': {
891
+ clientType: string;
892
+ clientId: string;
893
+ projectHash: string;
894
+ agentCount: number;
895
+ model: string;
896
+ mode: string;
897
+ toolCalls: number;
898
+ inputTokens: number;
899
+ outputTokens: number;
900
+ cacheTokens: number;
901
+ costUsd: number;
902
+ timestamp: number;
903
+ projectSlug: string;
904
+ };
804
905
  error: {
805
906
  err: Error;
806
907
  phase: string;
@@ -1,4 +1,4 @@
1
- import { C as Context } from './context-BGSpZNSE.js';
1
+ import { C as Context } from './context-dT5Ueund.js';
2
2
 
3
3
  interface CompactRepairReport {
4
4
  removedToolUses: string[];
@@ -39,6 +39,24 @@ interface CompactReport {
39
39
  * session log). Undefined when no range was collapsed this pass.
40
40
  */
41
41
  collapsedDigest?: string | undefined;
42
+ /**
43
+ * Compact state digest derived from tool-output instrumentation. It carries
44
+ * intent, path integrity, referenced tool results, active errors and implicit
45
+ * facts without copying full tool outputs back into the context window.
46
+ */
47
+ evidenceDigest?: string | undefined;
48
+ /**
49
+ * Deterministic post-compaction sanity check. This is deliberately local and
50
+ * cheap; LLM self-verification can be layered on top, but the compactor still
51
+ * records whether the compacted context retained an intent anchor and path
52
+ * trail.
53
+ */
54
+ quality?: {
55
+ ok: boolean;
56
+ hasIntent: boolean;
57
+ hasPathTrail: boolean;
58
+ issues: string[];
59
+ } | undefined;
42
60
  }
43
61
  interface Compactor {
44
62
  compact(ctx: Context, opts?: {
@@ -1,4 +1,4 @@
1
- import { k as Capabilities, f as Permission } from './context-BGSpZNSE.js';
1
+ import { l as Capabilities, f as Permission } from './context-dT5Ueund.js';
2
2
 
3
3
  type ContextWindowModeId = 'balanced' | 'frugal' | 'deep' | 'archival';
4
4
  type ContextWindowAggressiveOn = 'hard' | 'soft' | 'warn';
@@ -181,7 +181,7 @@ type ModelsDevPayload = Record<string, ModelsDevProvider>;
181
181
  * Canonical wire-format families WrongStack knows how to speak natively.
182
182
  * Used by the provider registry to pick a transport.
183
183
  */
184
- type WireFamily = 'anthropic' | 'openai' | 'openai-compatible' | 'google' | 'unsupported';
184
+ type WireFamily = 'anthropic' | 'anthropic-oauth' | 'openai' | 'openai-compatible' | 'openai-codex' | 'github-copilot' | 'google' | 'unsupported';
185
185
  interface ResolvedProvider {
186
186
  id: string;
187
187
  name: string;
@@ -224,6 +224,25 @@ interface ModelsRegistry {
224
224
  ageSeconds(): Promise<number>;
225
225
  }
226
226
 
227
+ /**
228
+ * Token-saving mode tier levels. Controls how aggressively the system prompt
229
+ * is compacted to reduce per-request token consumption.
230
+ *
231
+ * - 'off' — Full prompt, all tools, complete guidance (no reduction)
232
+ * - 'minimal' — TIER1 tools only (~10), stripped guidance (~3-4k tokens saved)
233
+ * - 'light' — Core + memory tools (~14), common patterns, minimal guidance
234
+ * - 'medium' — Most development tools (~24), some guidance (default when `true`)
235
+ * - 'aggressive' — Maximum savings before tools become unusable (~4-5k tokens saved)
236
+ */
237
+ type TokenSavingTier = 'off' | 'minimal' | 'light' | 'medium' | 'aggressive';
238
+ /**
239
+ * Normalize a TokenSavingTier value, handling backward-compatible boolean inputs.
240
+ * - `true` → 'medium' (existing behavior)
241
+ * - `false` → 'off'
242
+ * - string values are returned as-is after validation
243
+ * - `undefined` → 'off'
244
+ */
245
+ declare function normalizeTokenSavingTier(val?: TokenSavingTier | boolean): TokenSavingTier;
227
246
  interface ContextConfig {
228
247
  /** Context-window policy mode. Controls compaction thresholds and preservation depth. */
229
248
  mode?: ContextWindowModeId | undefined;
@@ -252,6 +271,30 @@ interface ContextConfig {
252
271
  /** Enable LLM-driven selective compaction (default: false for backward compat). */
253
272
  llmSelector?: boolean | undefined;
254
273
  }
274
+ /**
275
+ * Runtime configuration for the process circuit breaker (the one owned by the
276
+ * ProcessRegistry that gates `bash`/`exec`). Toggle via `/settings breaker`.
277
+ *
278
+ * The breaker itself is a low-level primitive (`packages/tools/.../circuit-breaker.ts`)
279
+ * that is on by default; this section controls whether the registry actually
280
+ * participates in it and how it auto-recovers.
281
+ */
282
+ interface CircuitBreakerRuntimeConfig {
283
+ /**
284
+ * Enable circuit-breaker protection. When false (the default), the breaker
285
+ * is bypassed — `bash`/`exec` calls always proceed regardless of failure
286
+ * history. When true, the breaker trips on repeated failures / slow calls /
287
+ * bursts and blocks further calls until it recovers.
288
+ */
289
+ enabled?: boolean | undefined;
290
+ /**
291
+ * When the breaker trips, automatically kill all tracked processes AND
292
+ * reset the breaker to closed after this delay (ms). 0 = disabled (manual
293
+ * recovery only via `/kill reset`). Only effective when `enabled` is true.
294
+ * While armed, the statusline shows a live countdown to the kill/reset.
295
+ */
296
+ autoKillResetMs?: number | undefined;
297
+ }
255
298
  interface ToolsConfig {
256
299
  defaultExecutionStrategy: 'parallel' | 'sequential' | 'smart';
257
300
  maxIterations: number;
@@ -263,6 +306,14 @@ interface ToolsConfig {
263
306
  * limit by 100 when hit. Set to false to require user confirmation.
264
307
  */
265
308
  autoExtendLimit?: boolean | undefined;
309
+ /**
310
+ * When true, file tools (read/write/edit/grep/glob/install) are confined to
311
+ * the project root and `set_working_dir` may not leave it. Default: false —
312
+ * tools may access paths outside the project root, still subject to each
313
+ * tool's permission tier (writes/edits prompt for confirmation). Toggle via
314
+ * `/settings` ("Filesystem access").
315
+ */
316
+ restrictToProjectRoot?: boolean | undefined;
266
317
  }
267
318
  interface ProviderApiKey {
268
319
  /** Short human-readable label (e.g. "personal", "work", "rate-limit-backup"). */
@@ -274,14 +325,42 @@ interface ProviderApiKey {
274
325
  apiKey: string;
275
326
  /** ISO-8601 timestamp the key was added. */
276
327
  createdAt: string;
328
+ /**
329
+ * How this credential was obtained.
330
+ * - `api_key` — manually pasted API key (default)
331
+ * - `oauth` — OAuth 2.0 device-code / authorization-code flow
332
+ * - `session_token` — extracted from browser session (ChatGPT web, etc.)
333
+ */
334
+ authMethod?: 'api_key' | 'oauth' | 'session_token' | undefined;
335
+ /** ISO-8601 expiry. When set, the token manager will refresh before this time. */
336
+ expiresAt?: string | undefined;
337
+ /**
338
+ * OAuth refresh token. Stored encrypted by the secret-vault walker because
339
+ * the field name contains `Token` (case-insensitive match by vault).
340
+ */
341
+ refreshToken?: string | undefined;
342
+ /** Token type as returned by the OAuth endpoint (e.g. "bearer"). */
343
+ tokenType?: string | undefined;
344
+ /** OAuth scope string (e.g. "openai.models.read openai.models.use"). */
345
+ scope?: string | undefined;
346
+ /**
347
+ * ChatGPT account id, extracted from the OAuth access-token JWT
348
+ * (`https://api.openai.com/auth`.chatgpt_account_id). Sent as the
349
+ * `chatgpt-account-id` header by the `openai-codex` wire family. Cached
350
+ * here for display/diagnostics; the provider re-derives it from the live
351
+ * token at request time so it can never go stale after a refresh.
352
+ */
353
+ accountId?: string | undefined;
277
354
  }
278
355
  interface ProviderConfig {
279
356
  type: string;
280
357
  /**
281
- * Legacy single-key field. Still honored as a fallback when `apiKeys`
282
- * is empty. When `apiKeys`/`activeKey` are present, the config loader
283
- * mirrors the active entry into this field so downstream consumers
284
- * (provider construction, wire adapters) need no changes.
358
+ * Legacy single-key field. Still honored as a read fallback when `apiKeys`
359
+ * is empty (for configs not yet migrated to multi-key format). After key
360
+ * management operations (`writeKeysBack`), this field is **cleared** to
361
+ * prevent accidental serialization of the plaintext key. Consumers that
362
+ * need the active API key should use `resolveActiveApiKey()` (cli) or
363
+ * resolve from `apiKeys[]` directly — never read `cfg.apiKey` in new code.
285
364
  */
286
365
  apiKey?: string | undefined;
287
366
  /** Multiple keys for the same provider — pick one with `activeKey`. */
@@ -309,6 +388,23 @@ interface ProviderConfig {
309
388
  * capability overrides. The model id is the key, not a fully qualified id.
310
389
  */
311
390
  customModels?: Record<string, CustomModelDefinition>;
391
+ /**
392
+ * Per-provider OAuth configuration. When present, `wstack auth login <id>`
393
+ * uses this instead of prompting for a raw API key. Set by the catalog or
394
+ * by the user via `/settings`.
395
+ */
396
+ oauthConfig?: {
397
+ /** OAuth client id registered with the provider. */
398
+ clientId?: string | undefined;
399
+ /** Device authorization endpoint (RFC 8628). */
400
+ deviceCodeEndpoint?: string | undefined;
401
+ /** Token endpoint for code exchange and refresh. */
402
+ tokenEndpoint?: string | undefined;
403
+ /** Authorization server URL shown to the user for opening in browser. */
404
+ authorizationEndpoint?: string | undefined;
405
+ /** Default OAuth scopes to request. */
406
+ scopes?: string[] | undefined;
407
+ } | undefined;
312
408
  }
313
409
  /**
314
410
  * One entry in the per-task model matrix. Pins a catalog role, a phase, or
@@ -338,6 +434,14 @@ interface MCPServerConfig {
338
434
  permission?: Permission | undefined;
339
435
  startupTimeoutMs?: number | undefined;
340
436
  requestTimeoutMs?: number | undefined;
437
+ /**
438
+ * Lazy connect: when true, the server process is NOT spawned at boot. Its
439
+ * tools are registered from a cached manifest (discovered on the first ever
440
+ * connect) and the server only spawns when one of its tools is actually
441
+ * called, then auto-sleeps after an idle period. Default (false/undefined) =
442
+ * eager connect at boot.
443
+ */
444
+ lazy?: boolean | undefined;
341
445
  }
342
446
  interface LogConfig {
343
447
  level: 'error' | 'warn' | 'info' | 'debug' | 'trace';
@@ -375,13 +479,23 @@ interface FeaturesConfig {
375
479
  /** Discover + load skills from disk. */
376
480
  skills: boolean;
377
481
  /**
378
- * Token-saving mode: when enabled, non-essential tools are omitted,
379
- * skill descriptions are trimmed, and the system prompt is shortened
380
- * to reduce per-request token consumption without compromising core
381
- * functionality. Enable with `--token-saving-mode` or
382
- * `features.tokenSavingMode: true` in config.
482
+ * Token-saving mode tier. Controls how aggressively the system prompt
483
+ * is compacted to reduce per-request token consumption.
484
+ *
485
+ * - 'off' — Full prompt, all tools, complete guidance
486
+ * - 'minimal' — TIER1 tools only, stripped guidance (~3-4k tokens saved)
487
+ * - 'light' — Core + memory tools, common patterns, minimal guidance
488
+ * - 'medium' — Most development tools, some guidance
489
+ * - 'aggressive' — Maximum savings before tools become unusable (~4-5k tokens)
490
+ *
491
+ * Boolean values are accepted for backward compatibility:
492
+ * - `true` → 'medium'
493
+ * - `false` → 'off'
494
+ *
495
+ * Enable via CLI: `--token-saving-tier <level>` or `--token-saving-mode` (maps to 'medium').
496
+ * Configure via: `features.tokenSavingMode: "minimal"` in config.
383
497
  */
384
- tokenSavingMode?: boolean | undefined;
498
+ tokenSavingMode?: TokenSavingTier | boolean | undefined;
385
499
  /**
386
500
  * Allow tools to read/write paths outside the project root directory.
387
501
  * When true (default), tools can access any path on the filesystem.
@@ -563,6 +677,11 @@ interface Config {
563
677
  configScope?: 'global' | 'project' | undefined;
564
678
  /** Automatic codebase symbol-index maintenance (session-start + live updates). */
565
679
  indexing?: IndexingConfig | undefined;
680
+ /**
681
+ * Process circuit-breaker protection (gates `bash`/`exec` on repeated
682
+ * failures). Default off — toggle with `/settings breaker on|off`.
683
+ */
684
+ circuitBreaker?: CircuitBreakerRuntimeConfig | undefined;
566
685
  /** Saved launch preferences — restored on next boot for one-line confirmation. */
567
686
  launch?: LaunchConfig | undefined;
568
687
  /**
@@ -631,4 +750,4 @@ interface ConfigStore {
631
750
  watch(cb: (next: Readonly<Config>, prev: Readonly<Config>) => void): () => void;
632
751
  }
633
752
 
634
- export { type AutonomyConfig as A, type SessionLoggingConfig as B, type ContextWindowAggressiveOn as C, DEFAULT_CONTEXT_WINDOW_MODE_ID as D, type SyncCategory as E, type FeaturesConfig as F, formatContextWindowModeList as G, type HookEvent as H, type InProcessHook as I, getContextWindowMode as J, isContextWindowModeId as K, type LaunchConfig as L, type ModelsRegistry as M, listContextWindowModes as N, resolveContextWindowPolicy as O, type ProviderConfig as P, type ResolvedProvider as R, type ShellHook as S, type ToolsConfig as T, type WireFamily as W, type ModelsDevPayload as a, type ResolvedModel as b, type MCPServerConfig as c, type ModelMatrixEntry as d, type HookMatcher as e, type HookEntry as f, type ContextWindowPolicy as g, type Config as h, type ConfigStore as i, type ConfigLoader as j, type SyncConfig as k, type HookInput as l, type HookOutcome as m, CONTEXT_WINDOW_MODES as n, type ContextConfig as o, type ContextWindowConfigLike as p, type ContextWindowMode as q, type ContextWindowModeId as r, type ContextWindowThresholds as s, type CustomModelDefinition as t, type IndexingConfig as u, type LogConfig as v, type ModelsDevModel as w, type ModelsDevProvider as x, type PluginConfig as y, type ProviderApiKey as z };
753
+ export { type AutonomyConfig as A, type ProviderApiKey as B, type ContextWindowAggressiveOn as C, DEFAULT_CONTEXT_WINDOW_MODE_ID as D, type SessionLoggingConfig as E, type FeaturesConfig as F, type SyncCategory as G, type HookEvent as H, type InProcessHook as I, type ToolsConfig as J, formatContextWindowModeList as K, type LaunchConfig as L, type ModelsRegistry as M, getContextWindowMode as N, isContextWindowModeId as O, type ProviderConfig as P, listContextWindowModes as Q, type ResolvedProvider as R, type ShellHook as S, type TokenSavingTier as T, normalizeTokenSavingTier as U, resolveContextWindowPolicy as V, type WireFamily as W, type ModelsDevPayload as a, type ResolvedModel as b, type MCPServerConfig as c, type ModelMatrixEntry as d, type ModelsDevModel as e, type HookMatcher as f, type HookEntry as g, type ContextWindowPolicy as h, type Config as i, type ConfigStore as j, type ConfigLoader as k, type SyncConfig as l, type HookInput as m, type HookOutcome as n, CONTEXT_WINDOW_MODES as o, type CircuitBreakerRuntimeConfig as p, type ContextConfig as q, type ContextWindowConfigLike as r, type ContextWindowMode as s, type ContextWindowModeId as t, type ContextWindowThresholds as u, type CustomModelDefinition as v, type IndexingConfig as w, type LogConfig as x, type ModelsDevProvider as y, type PluginConfig as z };