@wrongstack/core 0.292.1 → 0.293.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 (51) hide show
  1. package/dist/coordination/index.js.map +2 -2
  2. package/dist/core/fallback-profile-manager.d.ts +0 -2
  3. package/dist/core/fallback-profile-manager.d.ts.map +1 -1
  4. package/dist/core/system-prompt-builder.d.ts.map +1 -1
  5. package/dist/defaults/index.js +346 -317
  6. package/dist/defaults/index.js.map +4 -4
  7. package/dist/execution/compaction-core.d.ts +3 -0
  8. package/dist/execution/compaction-core.d.ts.map +1 -1
  9. package/dist/execution/compactor.d.ts +4 -0
  10. package/dist/execution/compactor.d.ts.map +1 -1
  11. package/dist/execution/index.js +133 -49
  12. package/dist/execution/index.js.map +4 -4
  13. package/dist/execution/intelligent-compactor.d.ts +5 -1
  14. package/dist/execution/intelligent-compactor.d.ts.map +1 -1
  15. package/dist/execution/selective-compactor.d.ts +4 -0
  16. package/dist/execution/selective-compactor.d.ts.map +1 -1
  17. package/dist/goal/phase-orchestrator.d.ts +4 -0
  18. package/dist/goal/phase-orchestrator.d.ts.map +1 -1
  19. package/dist/hooks/runner.d.ts +0 -2
  20. package/dist/hooks/runner.d.ts.map +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +116 -109
  24. package/dist/index.js.map +2 -2
  25. package/dist/models/alibaba-token-plan-catalog.d.ts +85 -0
  26. package/dist/models/alibaba-token-plan-catalog.d.ts.map +1 -0
  27. package/dist/models/index.d.ts +1 -0
  28. package/dist/models/index.d.ts.map +1 -1
  29. package/dist/models/index.js +200 -15
  30. package/dist/models/index.js.map +4 -4
  31. package/dist/models/llm-selector.d.ts +4 -0
  32. package/dist/models/llm-selector.d.ts.map +1 -1
  33. package/dist/models/models-registry.d.ts +8 -0
  34. package/dist/models/models-registry.d.ts.map +1 -1
  35. package/dist/security/index.js +0 -23
  36. package/dist/security/index.js.map +2 -2
  37. package/dist/security/permission-policy.d.ts +0 -23
  38. package/dist/security/permission-policy.d.ts.map +1 -1
  39. package/dist/storage/config-loader.d.ts.map +1 -1
  40. package/dist/storage/index.js +6 -5
  41. package/dist/storage/index.js.map +2 -2
  42. package/dist/tools/index.js.map +2 -2
  43. package/dist/types/config.d.ts +9 -16
  44. package/dist/types/config.d.ts.map +1 -1
  45. package/dist/types/index.js +2 -3
  46. package/dist/types/index.js.map +2 -2
  47. package/dist/utils/index.js +15 -0
  48. package/dist/utils/index.js.map +2 -2
  49. package/dist/utils/merge-models-payload.d.ts +9 -0
  50. package/dist/utils/merge-models-payload.d.ts.map +1 -1
  51. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2380,8 +2380,8 @@ function resolveTokenSavingTier(val, maxContext) {
2380
2380
  return "off";
2381
2381
  }
2382
2382
  if (maxContext < 32e3) return "medium";
2383
- if (maxContext < 96e3) return "light";
2384
- return "off";
2383
+ if (maxContext < 128e3) return "light";
2384
+ return "minimal";
2385
2385
  }
2386
2386
  return normalizeTokenSavingTier(val);
2387
2387
  }
@@ -2391,7 +2391,6 @@ function resolveFleetChatVerbosity(autonomy) {
2391
2391
  if (explicit && FLEET_CHAT_VERBOSITY_VALUES.includes(explicit)) {
2392
2392
  return explicit;
2393
2393
  }
2394
- if (autonomy?.streamFleet === false) return "off";
2395
2394
  return "off";
2396
2395
  }
2397
2396
  var DEFAULT_TUI_THINKING_WORD = "thinking";
@@ -2741,11 +2740,20 @@ var DefaultSystemPromptBuilder = class {
2741
2740
  const layer5 = await this.buildMode();
2742
2741
  const layer6 = ctx.subagent ? "" : await this.buildActivePlan();
2743
2742
  const core = [
2744
- tagBlock({ type: "text", text: layer1 }, "identity"),
2745
- tagBlock({ type: "text", text: layer2 }, "tool-usage")
2743
+ tagBlock(
2744
+ { type: "text", text: layer1, cache_control: { type: "ephemeral" } },
2745
+ "identity"
2746
+ ),
2747
+ tagBlock(
2748
+ { type: "text", text: layer2, cache_control: { type: "ephemeral" } },
2749
+ "tool-usage"
2750
+ )
2746
2751
  ];
2747
2752
  const session = [
2748
- tagBlock({ type: "text", text: layer3WithDir }, "environment")
2753
+ tagBlock(
2754
+ { type: "text", text: layer3WithDir, cache_control: { type: "ephemeral" } },
2755
+ "environment"
2756
+ )
2749
2757
  ];
2750
2758
  const volatile = [];
2751
2759
  if (layer4.trim()) {
@@ -4848,15 +4856,30 @@ function mergeCustomModelDefs(providerCustomModels, configModels) {
4848
4856
  }
4849
4857
 
4850
4858
  // src/utils/merge-models-payload.ts
4859
+ var REMOVE_PROVIDERS_KEY = "_removeProviders";
4860
+ var REMOVE_MODELS_KEY = "_removeModels";
4851
4861
  function mergeModelsPayload(base, overlay) {
4862
+ const removeProviders = Array.isArray(overlay[REMOVE_PROVIDERS_KEY]) ? overlay[REMOVE_PROVIDERS_KEY] : [];
4863
+ const removeModels = overlay[REMOVE_MODELS_KEY] && typeof overlay[REMOVE_MODELS_KEY] === "object" ? overlay[REMOVE_MODELS_KEY] : {};
4852
4864
  const out = {};
4853
4865
  for (const [id, provider] of Object.entries(base)) {
4854
4866
  out[id] = cloneProvider(provider);
4855
4867
  }
4856
4868
  for (const [id, ovProvider] of Object.entries(overlay)) {
4869
+ if (id === REMOVE_PROVIDERS_KEY || id === REMOVE_MODELS_KEY) continue;
4857
4870
  const existing = out[id];
4858
4871
  out[id] = existing ? mergeProvider(existing, ovProvider) : cloneProvider(ovProvider);
4859
4872
  }
4873
+ for (const providerId of removeProviders) {
4874
+ delete out[providerId];
4875
+ }
4876
+ for (const [providerId, modelIds] of Object.entries(removeModels)) {
4877
+ const provider = out[providerId];
4878
+ if (!provider || !provider.models) continue;
4879
+ for (const modelId of modelIds) {
4880
+ delete provider.models[modelId];
4881
+ }
4882
+ }
4860
4883
  return out;
4861
4884
  }
4862
4885
  function mergeProvider(base, overlay) {
@@ -7212,9 +7235,10 @@ var BEHAVIOR_DEFAULTS = {
7212
7235
  prompts: true,
7213
7236
  // 'auto' → resolveTokenSavingTier picks a concrete tier from the model's
7214
7237
  // context window ONCE per session (cache-safe): lean prompt on small
7215
- // windows (<32k medium, <96k light) where the fixed identity+tool prose is
7216
- // a big fraction; full prompt (off) on 96k+ so nothing changes for the
7217
- // common large-window case. Explicit tiers are respected verbatim.
7238
+ // windows (<32k medium, <128k light) where the fixed identity+tool prose
7239
+ // is a big fraction; minimal trimming on >=128k so modern large-window
7240
+ // models still get cost savings without capability loss. Explicit tiers
7241
+ // are respected verbatim.
7218
7242
  tokenSavingMode: "auto",
7219
7243
  allowOutsideProjectRoot: true
7220
7244
  },
@@ -7282,7 +7306,7 @@ var BEHAVIOR_DEFAULTS = {
7282
7306
  // Mirrored from the top-level yolo default so the autonomy subsystem
7283
7307
  // (which reads autonomy.yolo) stays consistent with config.yolo.
7284
7308
  yolo: false,
7285
- streamFleet: true,
7309
+ fleetChatVerbosity: "off",
7286
7310
  chime: false,
7287
7311
  confirmExit: true,
7288
7312
  mouseMode: false,
@@ -7300,7 +7324,7 @@ var BEHAVIOR_DEFAULTS = {
7300
7324
  // silently omitted, and surfaced as a per-request warning. Users who
7301
7325
  // want a specific effort can opt in via `/settings` or the WebUI panel.
7302
7326
  reasoning: { mode: "auto" },
7303
- cache: {}
7327
+ cache: { ttl: "1h" }
7304
7328
  }
7305
7329
  };
7306
7330
  function isPlainRecord(value) {
@@ -39644,25 +39668,30 @@ var WHITESPACE_COLLAPSE_PATTERN = /\s+/g;
39644
39668
  function compactionDebugEnabled() {
39645
39669
  return process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1";
39646
39670
  }
39671
+ var _debugLogger;
39672
+ function setCompactionDebugLogger(logger) {
39673
+ _debugLogger = logger;
39674
+ }
39647
39675
  function emitCompactionMetrics(event, metrics) {
39648
39676
  if (!compactionDebugEnabled()) return;
39649
- console.log(
39650
- JSON.stringify({
39651
- level: "debug",
39652
- event,
39653
- messageCount: metrics.messageCount,
39654
- preserveStart: metrics.preserveStart,
39655
- fastPathIterations: metrics.fastPathIterations,
39656
- fastPathInnerIterations: metrics.fastPathInnerIterations,
39657
- // Ratios — anything > 2.0 indicates the inner loop is running more than expected
39658
- fastPathInnerPerOuter: metrics.fastPathIterations > 0 ? metrics.fastPathInnerIterations / metrics.fastPathIterations : 0,
39659
- fullPassIterations: metrics.fullPassIterations,
39660
- fullPassInnerIterations: metrics.fullPassInnerIterations,
39661
- fullPassInnerPerOuter: metrics.fullPassIterations > 0 ? metrics.fullPassInnerIterations / metrics.fullPassIterations : 0,
39662
- tokensSaved: metrics.tokensSaved,
39663
- changed: metrics.changed
39664
- })
39665
- );
39677
+ const ctx = {
39678
+ event,
39679
+ messageCount: metrics.messageCount,
39680
+ preserveStart: metrics.preserveStart,
39681
+ fastPathIterations: metrics.fastPathIterations,
39682
+ fastPathInnerIterations: metrics.fastPathInnerIterations,
39683
+ fastPathInnerPerOuter: metrics.fastPathIterations > 0 ? metrics.fastPathInnerIterations / metrics.fastPathIterations : 0,
39684
+ fullPassIterations: metrics.fullPassIterations,
39685
+ fullPassInnerIterations: metrics.fullPassInnerIterations,
39686
+ fullPassInnerPerOuter: metrics.fullPassIterations > 0 ? metrics.fullPassInnerIterations / metrics.fullPassIterations : 0,
39687
+ tokensSaved: metrics.tokensSaved,
39688
+ changed: metrics.changed
39689
+ };
39690
+ if (_debugLogger) {
39691
+ _debugLogger.debug(`compaction: ${event}`, ctx);
39692
+ } else {
39693
+ console.log(JSON.stringify({ level: "debug", ...ctx }));
39694
+ }
39666
39695
  }
39667
39696
  var estimateMessages = estimateMessageTokens;
39668
39697
  function hasTextContent(m) {
@@ -39694,18 +39723,20 @@ function findPreserveStart(messages, preserveK) {
39694
39723
  preserveStart--;
39695
39724
  }
39696
39725
  if (compactionDebugEnabled()) {
39697
- console.log(
39698
- JSON.stringify({
39699
- level: "debug",
39700
- event: "compaction.find_preserve_start.ended",
39701
- messageCount: messages.length,
39702
- preserveK,
39703
- preserveStart,
39704
- pairRepairIterations,
39705
- pairRepairInnerIterations,
39706
- pairRepairInnerPerOuter: pairRepairIterations > 0 ? pairRepairInnerIterations / pairRepairIterations : 0
39707
- })
39708
- );
39726
+ const ctx = {
39727
+ event: "compaction.find_preserve_start.ended",
39728
+ messageCount: messages.length,
39729
+ preserveK,
39730
+ preserveStart,
39731
+ pairRepairIterations,
39732
+ pairRepairInnerIterations,
39733
+ pairRepairInnerPerOuter: pairRepairIterations > 0 ? pairRepairInnerIterations / pairRepairIterations : 0
39734
+ };
39735
+ if (_debugLogger) {
39736
+ _debugLogger.debug("compaction: find_preserve_start.ended", ctx);
39737
+ } else {
39738
+ console.log(JSON.stringify({ level: "debug", ...ctx }));
39739
+ }
39709
39740
  }
39710
39741
  return preserveStart;
39711
39742
  }
@@ -39820,16 +39851,18 @@ function eliseOldToolResults(messages, opts) {
39820
39851
  if (compactionDebugEnabled()) {
39821
39852
  const ratio = fullPassInnerIterations / fullPassIterations;
39822
39853
  if (ratio > 10) {
39823
- console.error(
39824
- JSON.stringify({
39825
- level: "error",
39826
- event: "compaction.elision.regression",
39827
- message: `fullPassInnerPerOuter=${ratio.toFixed(2)} exceeds threshold 10 \u2014 possible O(n\xB7m) regression`,
39828
- messageCount: messages.length,
39829
- fullPassIterations,
39830
- fullPassInnerIterations
39831
- })
39832
- );
39854
+ const ctx = {
39855
+ event: "compaction.elision.regression",
39856
+ message: `fullPassInnerPerOuter=${ratio.toFixed(2)} exceeds threshold 10 \u2014 possible O(n\xB7m) regression`,
39857
+ messageCount: messages.length,
39858
+ fullPassIterations,
39859
+ fullPassInnerIterations
39860
+ };
39861
+ if (_debugLogger) {
39862
+ _debugLogger.error(`compaction: elision.regression \u2014 ratio ${ratio.toFixed(2)}`, ctx);
39863
+ } else {
39864
+ console.error(JSON.stringify({ level: "error", ...ctx }));
39865
+ }
39833
39866
  }
39834
39867
  }
39835
39868
  }
@@ -40789,10 +40822,13 @@ var HybridCompactor = class {
40789
40822
  preserveK;
40790
40823
  eliseThreshold;
40791
40824
  smart;
40825
+ logger;
40792
40826
  constructor(opts = {}) {
40793
40827
  this.preserveK = opts.preserveK ?? 5;
40794
40828
  this.eliseThreshold = opts.eliseThreshold ?? 2e3;
40795
40829
  this.smart = opts.smart ?? false;
40830
+ this.logger = opts.logger ?? noOpLogger;
40831
+ setCompactionDebugLogger(this.logger);
40796
40832
  }
40797
40833
  async compact(ctx, opts = {}) {
40798
40834
  const beforeTokens = estimateMessages(ctx.messages);
@@ -43950,6 +43986,7 @@ var IntelligentCompactor = class {
43950
43986
  summarizerPrompt;
43951
43987
  summarizerModel;
43952
43988
  oneShotOrchestrator;
43989
+ logger;
43953
43990
  constructor(opts) {
43954
43991
  this.provider = opts.provider;
43955
43992
  this.warnThreshold = opts.warnThreshold ?? 0.5;
@@ -43961,6 +43998,8 @@ var IntelligentCompactor = class {
43961
43998
  this.summarizerPrompt = opts.summarizerPrompt ?? readBundledInstructionText("llm/intelligent-compactor-summarizer.md");
43962
43999
  this.summarizerModel = opts.summarizerModel;
43963
44000
  this.oneShotOrchestrator = opts.oneShotOrchestrator;
44001
+ this.logger = opts.logger ?? noOpLogger;
44002
+ setCompactionDebugLogger(this.logger);
43964
44003
  }
43965
44004
  async compact(ctx, opts = {}) {
43966
44005
  const beforeTokens = estimateMessages(ctx.messages);
@@ -44756,11 +44795,13 @@ var LLMSelector = class {
44756
44795
  systemPrompt;
44757
44796
  maxOutputTokens;
44758
44797
  oneShotOrchestrator;
44798
+ logger;
44759
44799
  constructor(opts) {
44760
44800
  this.provider = opts.provider;
44761
44801
  this.model = opts.model ?? "unknown";
44802
+ this.logger = opts.logger ?? noOpLogger;
44762
44803
  if (this.model === "unknown" && (process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1")) {
44763
- console.warn(
44804
+ this.logger.warn(
44764
44805
  "[LLMSelector] model not set \u2014 selector will use the provider default. Set `model` explicitly in LLMSelectorOptions to silence this warning."
44765
44806
  );
44766
44807
  }
@@ -44810,14 +44851,9 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
44810
44851
  }
44811
44852
  } catch (err) {
44812
44853
  if (err instanceof Error) {
44813
- console.warn(
44814
- JSON.stringify({
44815
- level: "warn",
44816
- event: "llm_selector.call_failed",
44817
- message: `selector call failed, using recency fallback: ${err.message}`,
44818
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
44819
- })
44820
- );
44854
+ this.logger.warn(`selector call failed, using recency fallback: ${err.message}`, {
44855
+ event: "llm_selector.call_failed"
44856
+ });
44821
44857
  }
44822
44858
  return this.fallbackSelect(messages, effectiveBudget);
44823
44859
  } finally {
@@ -44924,6 +44960,7 @@ var SelectiveCompactor = class {
44924
44960
  eliseThreshold;
44925
44961
  summarizerModel;
44926
44962
  summarizerPrompt;
44963
+ logger;
44927
44964
  constructor(opts) {
44928
44965
  this.provider = opts.provider;
44929
44966
  this.selector = opts.selector ?? new LLMSelector({ provider: opts.provider, model: opts.selectorModel, maxOutputTokens: opts.selectorMaxOutputTokens });
@@ -44934,8 +44971,10 @@ var SelectiveCompactor = class {
44934
44971
  this.preserveK = opts.preserveK ?? 4;
44935
44972
  this.eliseThreshold = opts.eliseThreshold ?? 300;
44936
44973
  this.summarizerModel = opts.summarizerModel ?? opts.selectorModel;
44974
+ this.logger = opts.logger ?? noOpLogger;
44975
+ setCompactionDebugLogger(this.logger);
44937
44976
  if (this.summarizerModel === void 0 && (process.env["NODE_ENV"] === "development" || process.env["WRONGSTACK_DEBUG"] === "1")) {
44938
- console.warn(
44977
+ this.logger.warn(
44939
44978
  "[SelectiveCompactor] summarizerModel not set \u2014 will fall back to ctx.model at summarize time. Set `summarizerModel` explicitly to silence this warning."
44940
44979
  );
44941
44980
  }
@@ -48104,6 +48143,7 @@ var DefaultModelsRegistry = class {
48104
48143
  overlayUrl;
48105
48144
  overlayFile;
48106
48145
  overlayCacheFile;
48146
+ logger;
48107
48147
  constructor(opts) {
48108
48148
  this.cacheFile = opts.cacheFile;
48109
48149
  this.url = opts.url ?? process.env[ENV_URL_KEY] ?? DEFAULT_URL;
@@ -48117,6 +48157,7 @@ var DefaultModelsRegistry = class {
48117
48157
  this.overlayUrl = opts.overlayUrl;
48118
48158
  this.overlayFile = opts.overlayFile;
48119
48159
  this.overlayCacheFile = opts.overlayCacheFile ?? (opts.overlayUrl ? path49.join(path49.dirname(opts.cacheFile), "models-overlay-cache.json") : void 0);
48160
+ this.logger = opts.logger ?? noOpLogger;
48120
48161
  }
48121
48162
  async load(opts = {}) {
48122
48163
  if (this.payload && !opts.force) return this.payload;
@@ -48165,16 +48206,18 @@ var DefaultModelsRegistry = class {
48165
48206
  if (cached2 && this.isWithinMaxStaleAge(cached2.fetchedAt)) {
48166
48207
  this.fetchedAt = new Date(cached2.fetchedAt);
48167
48208
  const ageSeconds = Math.floor((Date.now() - this.fetchedAt.getTime()) / 1e3);
48168
- console.warn(
48169
- `ModelsRegistry: models.dev unavailable (${toErrorMessage(err)}); using stale cache from ${formatAge(ageSeconds)} ago. Run \`wstack models refresh\` to retry.`
48209
+ this.logger.warn(
48210
+ `ModelsRegistry: models.dev unavailable (${toErrorMessage(err)}); using stale cache from ${formatAge(ageSeconds)} ago. Run \`wstack models refresh\` to retry.`,
48211
+ { event: "models_registry.stale_cache_fallback" }
48170
48212
  );
48171
48213
  return cached2.payload;
48172
48214
  }
48173
48215
  if (overlayAvailable) {
48174
- console.warn(
48216
+ this.logger.warn(
48175
48217
  `ModelsRegistry: models.dev unavailable (${toErrorMessage(
48176
48218
  err
48177
- )}); serving curated overlay only.`
48219
+ )}); serving curated overlay only.`,
48220
+ { event: "models_registry.overlay_only_fallback" }
48178
48221
  );
48179
48222
  return {};
48180
48223
  }
@@ -48270,8 +48313,9 @@ var DefaultModelsRegistry = class {
48270
48313
  const cached2 = await this.readCacheAt(this.overlayCacheFile);
48271
48314
  if (cached2 && this.isWithinMaxStaleAge(cached2.fetchedAt)) {
48272
48315
  const ageSeconds = Math.floor((Date.now() - new Date(cached2.fetchedAt).getTime()) / 1e3);
48273
- console.warn(
48274
- `ModelsRegistry: overlay unavailable; using stale overlay from ${formatAge(ageSeconds)} ago.`
48316
+ this.logger.warn(
48317
+ `ModelsRegistry: overlay unavailable; using stale overlay from ${formatAge(ageSeconds)} ago.`,
48318
+ { event: "models_registry.overlay_stale_fallback", ageSeconds }
48275
48319
  );
48276
48320
  return cached2.payload;
48277
48321
  }
@@ -49425,9 +49469,6 @@ var DefaultPermissionPolicy = class {
49425
49469
  loaded = false;
49426
49470
  trustFile;
49427
49471
  yolo;
49428
- yoloDestructive;
49429
- /** Deprecated compatibility flag; no longer gates YOLO calls. */
49430
- confirmDestructive;
49431
49472
  /**
49432
49473
  * Session-scoped "soft deny" map. When the user presses 'n' (block once),
49433
49474
  * the tool+pattern is added here. If the LLM retries in the same session,
@@ -49480,8 +49521,6 @@ var DefaultPermissionPolicy = class {
49480
49521
  constructor(opts) {
49481
49522
  this.trustFile = opts.trustFile;
49482
49523
  this.yolo = opts.yolo ?? false;
49483
- this.yoloDestructive = opts.yoloDestructive ?? opts.forceAllYolo ?? false;
49484
- this.confirmDestructive = opts.confirmDestructive ?? false;
49485
49524
  this.promptDelegate = opts.promptDelegate;
49486
49525
  }
49487
49526
  /**
@@ -49502,24 +49541,6 @@ var DefaultPermissionPolicy = class {
49502
49541
  getYolo() {
49503
49542
  return this.yolo;
49504
49543
  }
49505
- /** Toggle the destructive YOLO override at runtime. */
49506
- setYoloDestructive(enabled) {
49507
- if (this.yoloDestructive !== enabled) this._evalCache.clear();
49508
- this.yoloDestructive = enabled;
49509
- }
49510
- /** Check whether the destructive YOLO override is active. */
49511
- getYoloDestructive() {
49512
- return this.yoloDestructive;
49513
- }
49514
- /** Toggle deprecated destructive confirmation compatibility flag. */
49515
- setConfirmDestructive(enabled) {
49516
- if (this.confirmDestructive !== enabled) this._evalCache.clear();
49517
- this.confirmDestructive = enabled;
49518
- }
49519
- /** Check deprecated destructive confirmation compatibility flag. */
49520
- getConfirmDestructive() {
49521
- return this.confirmDestructive;
49522
- }
49523
49544
  /** Read-only diagnostics for policy inspector/editor surfaces. */
49524
49545
  getPolicyDiagnostics() {
49525
49546
  return this.policyDiagnostics.map((diagnostic) => ({ ...diagnostic }));
@@ -54880,6 +54901,7 @@ var PhaseOrchestrator = class {
54880
54901
  taskRetryCounts = /* @__PURE__ */ new Map();
54881
54902
  // ── Git-worktree isolation (optional) ──────────────────────────────────────
54882
54903
  worktrees;
54904
+ logger;
54883
54905
  /** Per-phase worktree handles, keyed by phase id. */
54884
54906
  phaseWorktrees = /* @__PURE__ */ new Map();
54885
54907
  /** Serializes all merges back to the base branch (one at a time). */
@@ -54891,6 +54913,7 @@ var PhaseOrchestrator = class {
54891
54913
  this.ctx = opts.ctx;
54892
54914
  this.events = opts.events ?? this.createNoopEventBus();
54893
54915
  this.worktrees = opts.worktrees;
54916
+ this.logger = opts.logger ?? noOpLogger;
54894
54917
  this.opts = {
54895
54918
  maxConcurrentPhases: opts.maxConcurrentPhases ?? 1,
54896
54919
  maxConcurrentTasks: opts.maxConcurrentTasks ?? 2,
@@ -54963,12 +54986,7 @@ var PhaseOrchestrator = class {
54963
54986
  await Promise.allSettled([...this.phaseMergePromise.values()]);
54964
54987
  await this.mergeQueue.catch((err) => {
54965
54988
  const msg = toErrorMessage(err);
54966
- console.warn(JSON.stringify({
54967
- level: "warn",
54968
- event: "orchestrator.merge_queue_failed",
54969
- message: msg,
54970
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
54971
- }));
54989
+ this.logger.warn(msg, { event: "orchestrator.merge_queue_failed" });
54972
54990
  });
54973
54991
  }
54974
54992
  /** Pause: active phases continue, but no new phase starts. */
@@ -54980,12 +54998,7 @@ var PhaseOrchestrator = class {
54980
54998
  this.paused = false;
54981
54999
  this.tick().catch((err) => {
54982
55000
  const msg = toErrorMessage(err);
54983
- console.error(JSON.stringify({
54984
- level: "error",
54985
- event: "orchestrator.tick_failed",
54986
- message: msg,
54987
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
54988
- }));
55001
+ this.logger.error(msg, { event: "orchestrator.tick_failed" });
54989
55002
  });
54990
55003
  }
54991
55004
  /** Stop completely, including active phases. */
@@ -55206,13 +55219,7 @@ var PhaseOrchestrator = class {
55206
55219
  await Promise.allSettled(depPromises);
55207
55220
  this.mergeQueue = this.mergeQueue.then(() => this.mergeOne(phase, handle)).catch((err) => {
55208
55221
  const msg = toErrorMessage(err);
55209
- console.error(JSON.stringify({
55210
- level: "error",
55211
- event: "orchestrator.merge_failed",
55212
- phaseId: phase.id,
55213
- message: msg,
55214
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
55215
- }));
55222
+ this.logger.error(msg, { event: "orchestrator.merge_failed", phaseId: phase.id });
55216
55223
  this.markPhaseMergeFailed(phase, msg);
55217
55224
  });
55218
55225
  await this.mergeQueue;
@@ -57135,7 +57142,7 @@ var HookRunner = class {
57135
57142
  return this.registry.list(event).filter((e) => hookMatcherMatches(e.matcher, toolName));
57136
57143
  }
57137
57144
  async invoke(entry, payload, env) {
57138
- const allowNonPolicy = this.opts.allowNonPolicy ?? this.opts.allowShell ?? true;
57145
+ const allowNonPolicy = this.opts.allowNonPolicy ?? true;
57139
57146
  if (!allowNonPolicy && !entry.policy) return null;
57140
57147
  let result;
57141
57148
  if (entry.kind === "inprocess") {