switchroom 0.19.43 → 0.19.44

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.
@@ -21547,7 +21547,7 @@ var init_observation_scopes = __esm(() => {
21547
21547
  });
21548
21548
 
21549
21549
  // ../src/config/schema.ts
21550
- var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
21550
+ var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleWorkspaceConfigSchema, LiteLLMConfigSchema, HindsightPerOpLlmSchema, HindsightConfigSchema, MicrosoftWorkspaceConfigSchema, NotionWorkspaceConfigSchema, AgentGoogleWorkspaceConfigSchema, MicrosoftAccountEmailSchema, MicrosoftToolTokenSchema, MicrosoftAccountBindingSchema, AgentMicrosoftWorkspaceConfigSchema, AgentNotionWorkspaceConfigSchema, ReactionsSchema, ReactionDispatchSchema, releaseBlockFields, ReleaseBlock, RootReleaseBlock, NetworkIsolationSchema, servesField, knowsField, profileFields, ProfileSchema, _omitExtends, defaultsFields, AgentDefaultsSchema, AgentSchema, TelegramConfigSchema, MemoryBackendConfigSchema, VaultConfigSchema, QuotaConfigSchema, AutoReleaseCheckSchema, HostControlConfigSchema, WebServiceConfigSchema, FleetHealthConfigSchema, HostdConfigSchema, CronEgressSchema, CronConfigSchema, UserSchema, SwitchroomConfigSchema;
21551
21551
  var init_schema = __esm(() => {
21552
21552
  init_zod();
21553
21553
  init_observation_scopes();
@@ -21664,6 +21664,7 @@ var init_schema = __esm(() => {
21664
21664
  }).optional();
21665
21665
  ObservationScopesSchema = exports_external.enum(OBSERVATION_SCOPES).optional().describe("Operator PIN for the per-row observation scope, overriding the " + 'default `curated` strategy (see docs/configuration.md). "shared" ' + "forces Hindsight's consolidation to write EVERY observation into ONE " + "global untagged scope \u2014 what several agents pooling one bank want so " + "their observations merge rather than sitting in parallel silos. " + '"combined" is the pin form of opting out (restores the pre-#4035 ' + "engine default). UNSET does NOT mean 'nothing on the wire': the " + "`curated` strategy still computes a scope per retain. Applies to " + "every retain path (Stop hook, " + "sidechain, boot reconcile, queue drain, backfill, session-handoff " + "mirror) and is carried on the queued payload, so a retain that fails " + "now and drains later still lands in this scope. Accepted values: " + `${OBSERVATION_SCOPES.join(", ")}. ` + "Cascade: override (per-agent wins over default).");
21666
21666
  ObservationScopeStrategySchema = exports_external.enum(OBSERVATION_SCOPE_STRATEGIES).optional().describe("Per-retain strategy that decides how the observation scope is " + 'computed when no `observation_scopes` pin is set. "curated" ' + "(the default since #4035) strips volatile per-session provenance " + "tags from each retain's consolidation scope \u2014 keeping the stable " + "semantic ones on the source fact \u2014 so an agent's observations dedup " + "and merge across sessions instead of pocketing one-per-session. " + '"shared" sends every retain to the one global untagged scope. ' + '"combined" / "off" opt OUT: no per-row scope goes on the wire, ' + "restoring the pre-feature engine default (byte-identical to an " + "unconfigured client). OMITTED BY DEFAULT: unset leaves the plugin's " + "own default (`curated`) in force. A manual `observation_scopes` pin " + "wins over this strategy. Accepted values: " + `${OBSERVATION_SCOPE_STRATEGIES.join(", ")}. ` + "Cascade: override (per-agent wins over default).");
21667
+ AntiConfabulationDirectiveSchema = exports_external.union([exports_external.boolean(), exports_external.string().min(1)]).optional().describe("The seeded anti-confabulation directive: reflect has no relevance " + "floor (`min_scores` is a /recall-only parameter), so a bank holding " + "nothing relevant still yields a confident answer, and a question that " + "presupposes a decision reliably produces one. Directives ARE applied " + "during reflect, so this is the lever. Unset or true (the default) " + "seeds and maintains switchroom's own text; false disables seeding and " + "leaves any existing directive untouched; a string is operator-authored " + "text that wins outright. Switchroom only ever upgrades directive text " + "byte-equal to a default it shipped, so editing the directive in the " + "bank is also a permanent override. " + "Cascade: override (per-agent wins over default).");
21667
21668
  AgentMemorySchema = exports_external.object({
21668
21669
  collection: exports_external.string().describe("Hindsight collection name for this agent"),
21669
21670
  auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
@@ -21699,6 +21700,7 @@ var init_schema = __esm(() => {
21699
21700
  empathy: exports_external.number().int().min(1).max(5).optional().describe("How much the bank weights emotional/relational context (1-5; engine default 3).")
21700
21701
  }).optional().describe("Personality traits (1-5 each) steering how this bank frames recall, " + "reflect, and observation synthesis \u2014 a coach leans empathy-high, a " + "lawyer/analyst leans skepticism/literalism-high. Maps to the engine's " + "flat `disposition_skepticism`/`_literalism`/`_empathy` fields. " + "Cascade: per-key merge (an agent overrides individual traits and " + "inherits the rest, matching `recall`)."),
21701
21702
  directive_capture_nudge: exports_external.boolean().optional().describe("Deterministic directive-capture nudge (issue #2848 Stage B). When " + "on (switchroom default true \u2014 Stage A measured a ~55% miss rate on " + "durable corrections), the auto-recall hook regex-detects correction " + '/ standing-rule-shaped inbound ("always/never \u2026", "from now on \u2026", ' + `"stop doing \u2026", a stated preference, "that's wrong, it's \u2026") and ` + "appends a terse advisory to the turn's context telling the model to " + "persist the rule with mcp__hindsight__create_directive if it IS " + "durable. Detection is pure regex \u2014 the model does the judgment " + "in-session and calls create_directive itself (no model callsite, no " + "silent hook-side write). Set false to disable per-agent. " + "Cascade: override (per-agent wins over default)."),
21703
+ anti_confabulation_directive: AntiConfabulationDirectiveSchema,
21702
21704
  observation_scopes: ObservationScopesSchema,
21703
21705
  observation_scope_strategy: ObservationScopeStrategySchema,
21704
21706
  recall: exports_external.object({
@@ -21969,7 +21971,7 @@ var init_schema = __esm(() => {
21969
21971
  reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent \u2192 uses global."),
21970
21972
  consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent \u2192 global.")
21971
21973
  }).optional().describe("LLM knob for the hindsight container. The flat `provider`/`model` set " + "the global default (backward-compatible); optional `retain`/`reflect`/" + "`consolidation` blocks override individual ops. All fields optional; " + "unset fields fall back to the hard-coded defaults."),
21972
- env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS \u2014 switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY \u2014 a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP \u2014 the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS \u2014 only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS \u2014 the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS \u2014 the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY \u2014 the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE \u2014 the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT \u2014 upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS \u2014 a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED \u2014 a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
21974
+ env: exports_external.record(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional().describe("Operator overrides for switchroom's capability-gated Hindsight " + "performance defaults. Only the keys switchroom actually manages are " + "honoured (`HINDSIGHT_PERF_ENV_KEYS` in " + "src/setup/hindsight-perf-defaults.ts: RERANKER_LOCAL_FP16, " + "RERANKER_LOCAL_BATCH_SIZE, LLM_MAX_CONCURRENT, " + "RETAIN/CONSOLIDATION_LLM_MAX_CONCURRENT, LLM_STRICT_SCHEMA, " + "LLM_MAX_RETRIES, CONSOLIDATION_LLM_PARALLELISM, " + "MAX_OBSERVATIONS_PER_SCOPE, " + "RECALL_MAX_CANDIDATES_PER_SOURCE, LINK_EXPANSION_PER_ENTITY_LIMIT, " + "LINK_EXPANSION_TIMEOUT, LLM_REASONING_EFFORT, " + "RERANKER_LOCAL_BUCKET_BATCHING, RERANKER_MAX_CANDIDATES, " + "RERANKER_LOCAL_MAX_CONCURRENT, RECALL_MAX_CONCURRENT, " + "REFLECT_WALL_TIMEOUT, WORKER_CONSOLIDATION_RESERVED_SLOTS, " + "WORKER_CONSOLIDATION_SLOT_LIMIT, " + "CONSOLIDATION_MAX_MEMORIES_PER_ROUND, GRAPH_SEED_MIN_SIMILARITY, " + "LLM_SUPPORTS_MAX_ITEMS, RECENCY_DECAY_FUNCTION, " + "RECENCY_DECAY_HALFLIFE_DAYS \u2014 switchroom defaults recall's recency " + "curve to `exponential` with a 30-day half-life so a fact retained " + "today outranks a stale one, instead of upstream's near-flat " + "linear/365-day window), the override-only keys " + "switchroom manages but ships NO default for " + "(`HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS`: " + "HINDSIGHT_API_WORKER_CONSOLIDATION_BANK_PRIORITY \u2014 a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP \u2014 the rollback knob for " + "switchroom's CE-saturation damping patch, a float; >= ~0.65 backs the " + "damping out entirely, unset means the patch's own derived gap; and " + "HINDSIGHT_API_RECENCY_DECAY_LINEAR_WINDOW_DAYS \u2014 only read when the " + "decay function is `linear`, so switchroom ships no default for it but " + "still honours an operator who flips the function back; and " + "HINDSIGHT_API_WORKER_MAX_SLOTS \u2014 the worker poller's TOTAL in-flight " + "task budget, the pool WORKER_CONSOLIDATION_RESERVED_SLOTS reserves out of; " + "unset means upstream's own default; and " + "HINDSIGHT_API_WORKER_RETAIN_RESERVED_SLOTS \u2014 the reserved slot FLOOR for the " + "retain (memory write) lane, carved from that same total; unset means " + "upstream's own 0, i.e. no floor and retain competes for the shared " + "pool; and " + "the pre-0.8.6 name HINDSIGHT_API_WORKER_<TYPE>_MAX_SLOTS is still " + "accepted for every operation type and normalised to " + "..._RESERVED_SLOTS on the way in, because setting both names for " + "one type is a hard boot failure in the engine and switchroom " + "therefore emits only the canonical name; and " + "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY \u2014 the cosine-similarity floor a " + "candidate must reach to be returned by the semantic retrieval arm at " + "all (0..1); unset means upstream's own 0.3, and where it should sit " + "depends on the bank's embedding model and phrasing diversity, so " + "switchroom ships no opinion; and " + "HINDSIGHT_MCP_RECALL_BUDGET_MODE \u2014 the rollback knob for switchroom's " + "mcp-recall-token-budget image patch; `legacy` restores upstream's " + "exact pre-patch recall returns, anything else or unset is the " + "honest-envelope mode; and " + "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT \u2014 upstream's own per-op reflect " + "temperature knob, made live by switchroom's reflect-temperature image " + "patch; a float, or `none` to omit the kwarg (provider default, " + "upstream's accidental pre-patch behaviour); unset means the image's " + "baked default 0.1; and " + "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT \u2014 the background " + "half of switchroom's recall-admission split (#3660): of the " + "RECALL_MAX_CONCURRENT admission slots, at most this many may be held " + "by background consolidation recalls at once, so foreground per-turn " + "recall always keeps the remainder; must be >= 1 and strictly less " + "than RECALL_MAX_CONCURRENT or the engine refuses to boot; unset " + "means the image's derived default min(2, RECALL_MAX_CONCURRENT - 1); " + "1 biases hard toward the interactive lane while a consolidation " + "backlog drains), plus the " + "embedded-PostgreSQL (pg0) sizing keys switchroom manages in " + "src/setup/hindsight-pg-defaults.ts (`HINDSIGHT_PG_ENV_KEYS`: " + "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE, " + "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS \u2014 a postgres size string such " + "as `4GB`, or the sentinel `off` to leave pg0's own default for that " + "one knob). A value set here " + "REPLACES switchroom's default and is emitted even when the gating " + "capability is absent, so an operator can always force a knob. Other " + "`HINDSIGHT_API_*` keys are deliberately IGNORED \u2014 a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
21973
21975
  });
21974
21976
  MicrosoftWorkspaceConfigSchema = exports_external.object({
21975
21977
  microsoft_client_id: exports_external.string().min(1).optional().describe("Microsoft OAuth application (client) ID from Entra portal " + "(literal string or vault reference e.g. " + "'vault:microsoft-oauth-client-id'). OPTIONAL \u2014 omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
@@ -22103,6 +22105,7 @@ var init_schema = __esm(() => {
22103
22105
  isolation: exports_external.enum(["default", "strict"]).optional(),
22104
22106
  profile: exports_external.string().optional(),
22105
22107
  directive_capture_nudge: exports_external.boolean().optional(),
22108
+ anti_confabulation_directive: AntiConfabulationDirectiveSchema,
22106
22109
  observation_scopes: ObservationScopesSchema,
22107
22110
  observation_scope_strategy: ObservationScopeStrategySchema,
22108
22111
  recall: exports_external.object({
@@ -30147,7 +30150,7 @@ var init_turn_flush_suppression = () => {};
30147
30150
 
30148
30151
  // ../src/agents/generation-stamp.ts
30149
30152
  import { createHash as createHash6 } from "node:crypto";
30150
- import { existsSync as existsSync32, readFileSync as readFileSync31, writeFileSync as writeFileSync28 } from "node:fs";
30153
+ import { existsSync as existsSync33, readFileSync as readFileSync32, writeFileSync as writeFileSync28 } from "node:fs";
30151
30154
  import { join as join41 } from "node:path";
30152
30155
  function sha256Text(s) {
30153
30156
  return createHash6("sha256").update(s, "utf-8").digest("hex");
@@ -30159,11 +30162,11 @@ function hashManagedClaudeMd(content3) {
30159
30162
  }
30160
30163
  function hashStampedFileOnDisk(agentDir, rel) {
30161
30164
  const p = join41(agentDir, rel);
30162
- if (!existsSync32(p))
30165
+ if (!existsSync33(p))
30163
30166
  return null;
30164
30167
  let content3;
30165
30168
  try {
30166
- content3 = readFileSync31(p, "utf-8");
30169
+ content3 = readFileSync32(p, "utf-8");
30167
30170
  } catch {
30168
30171
  return null;
30169
30172
  }
@@ -30171,10 +30174,10 @@ function hashStampedFileOnDisk(agentDir, rel) {
30171
30174
  }
30172
30175
  function readGenerationStamp(agentDir) {
30173
30176
  const p = join41(agentDir, GENERATION_STAMP_FILE);
30174
- if (!existsSync32(p))
30177
+ if (!existsSync33(p))
30175
30178
  return null;
30176
30179
  try {
30177
- const parsed = JSON.parse(readFileSync31(p, "utf-8"));
30180
+ const parsed = JSON.parse(readFileSync32(p, "utf-8"));
30178
30181
  if (parsed?.version !== 1 || typeof parsed.files !== "object" || parsed.files === null || Array.isArray(parsed.files)) {
30179
30182
  return null;
30180
30183
  }
@@ -35984,19 +35987,19 @@ function renderAuthLine(state7, agentName3, now = Date.now()) {
35984
35987
  }
35985
35988
 
35986
35989
  // gateway/quota-cache.ts
35987
- import { existsSync as existsSync44, readFileSync as readFileSync44, writeFileSync as writeFileSync37, mkdirSync as mkdirSync39 } from "fs";
35988
- import { join as join54, dirname as dirname22 } from "path";
35990
+ import { existsSync as existsSync45, readFileSync as readFileSync45, writeFileSync as writeFileSync37, mkdirSync as mkdirSync39 } from "fs";
35991
+ import { join as join53, dirname as dirname22 } from "path";
35989
35992
  function defaultCachePath() {
35990
- return process.env.SWITCHROOM_QUOTA_CACHE_PATH ?? join54(process.env.HOME ?? "/tmp", ".switchroom", "quota-cache.json");
35993
+ return process.env.SWITCHROOM_QUOTA_CACHE_PATH ?? join53(process.env.HOME ?? "/tmp", ".switchroom", "quota-cache.json");
35991
35994
  }
35992
35995
  function readQuotaCache(opts = {}) {
35993
35996
  const path3 = opts.path ?? defaultCachePath();
35994
35997
  const now = opts.now ?? Date.now();
35995
- if (!existsSync44(path3))
35998
+ if (!existsSync45(path3))
35996
35999
  return null;
35997
36000
  let entry;
35998
36001
  try {
35999
- entry = JSON.parse(readFileSync44(path3, "utf8"));
36002
+ entry = JSON.parse(readFileSync45(path3, "utf8"));
36000
36003
  } catch {
36001
36004
  return null;
36002
36005
  }
@@ -36033,8 +36036,8 @@ var init_quota_cache = __esm(() => {
36033
36036
  });
36034
36037
 
36035
36038
  // gateway/boot-probes.ts
36036
- import { readFileSync as readFileSync45, readdirSync as readdirSync12, existsSync as existsSync45 } from "fs";
36037
- import { join as join55 } from "path";
36039
+ import { readFileSync as readFileSync46, readdirSync as readdirSync12, existsSync as existsSync46 } from "fs";
36040
+ import { join as join54 } from "path";
36038
36041
  import { execFile as execFileCb } from "child_process";
36039
36042
  import { promisify } from "util";
36040
36043
  async function withTimeout(label, p, timeoutMs = PROBE_TIMEOUT_MS) {
@@ -36076,11 +36079,11 @@ function mapPlan(billingType, hasExtra) {
36076
36079
  }
36077
36080
  async function probeAccount(agentDir) {
36078
36081
  return withTimeout("Account", (async () => {
36079
- const claudeDir = join55(agentDir, ".claude");
36080
- const claudeJsonPath = join55(claudeDir, ".claude.json");
36082
+ const claudeDir = join54(agentDir, ".claude");
36083
+ const claudeJsonPath = join54(claudeDir, ".claude.json");
36081
36084
  let cfg = {};
36082
36085
  try {
36083
- const raw = readFileSync45(claudeJsonPath, "utf8");
36086
+ const raw = readFileSync46(claudeJsonPath, "utf8");
36084
36087
  cfg = JSON.parse(raw);
36085
36088
  } catch {
36086
36089
  return { status: "fail", label: "Account", detail: "no .claude.json" };
@@ -36098,12 +36101,12 @@ async function probeAccount(agentDir) {
36098
36101
  let tokenStr = "";
36099
36102
  let status = "ok";
36100
36103
  for (const candidate of [
36101
- join55(claudeDir, ".oauth-token.meta.json"),
36102
- join55(claudeDir, "accounts", "default", ".oauth-token.meta.json")
36104
+ join54(claudeDir, ".oauth-token.meta.json"),
36105
+ join54(claudeDir, "accounts", "default", ".oauth-token.meta.json")
36103
36106
  ]) {
36104
- if (existsSync45(candidate)) {
36107
+ if (existsSync46(candidate)) {
36105
36108
  try {
36106
- const meta = JSON.parse(readFileSync45(candidate, "utf8"));
36109
+ const meta = JSON.parse(readFileSync46(candidate, "utf8"));
36107
36110
  if (meta.expiresAt) {
36108
36111
  tokenStr = " \u00b7 " + formatDaysFromNow(meta.expiresAt);
36109
36112
  const daysLeft = Math.round((meta.expiresAt - Date.now()) / 86400000);
@@ -36278,9 +36281,9 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
36278
36281
  if (!cgroup)
36279
36282
  return null;
36280
36283
  const procsPath = `/sys/fs/cgroup${cgroup}/cgroup.procs`;
36281
- if (!existsSync45(procsPath))
36284
+ if (!existsSync46(procsPath))
36282
36285
  return null;
36283
- const pidsRaw = readFileSync45(procsPath, "utf-8");
36286
+ const pidsRaw = readFileSync46(procsPath, "utf-8");
36284
36287
  const pids = pidsRaw.split(`
36285
36288
  `).map((s) => s.trim()).filter(Boolean);
36286
36289
  if (pids.length === 0)
@@ -36293,7 +36296,7 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
36293
36296
  let rss = 0;
36294
36297
  let comm = "";
36295
36298
  try {
36296
- const status = readFileSync45(`/proc/${pid}/status`, "utf-8");
36299
+ const status = readFileSync46(`/proc/${pid}/status`, "utf-8");
36297
36300
  const rssLine = status.split(`
36298
36301
  `).find((l) => l.startsWith("VmRSS:"));
36299
36302
  if (rssLine) {
@@ -36305,7 +36308,7 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
36305
36308
  continue;
36306
36309
  }
36307
36310
  try {
36308
- comm = readFileSync45(`/proc/${pid}/comm`, "utf-8").trim();
36311
+ comm = readFileSync46(`/proc/${pid}/comm`, "utf-8").trim();
36309
36312
  } catch {}
36310
36313
  candidates.push({ pid, rss, comm });
36311
36314
  }
@@ -36485,9 +36488,9 @@ async function probeQuota(claudeConfigDir, _agentDir, fetchImpl = fetch, opts =
36485
36488
  let claudeDirForProbe = null;
36486
36489
  for (const candidate of [
36487
36490
  claudeConfigDir,
36488
- join55(claudeConfigDir, "accounts", "default")
36491
+ join54(claudeConfigDir, "accounts", "default")
36489
36492
  ]) {
36490
- if (existsSync45(join55(candidate, ".oauth-token"))) {
36493
+ if (existsSync46(join54(candidate, ".oauth-token"))) {
36491
36494
  claudeDirForProbe = candidate;
36492
36495
  break;
36493
36496
  }
@@ -36552,7 +36555,7 @@ async function probeHindsight(bankName, fetchImpl = fetch) {
36552
36555
  }
36553
36556
  function readContainerBootTimeMsForProbe() {
36554
36557
  try {
36555
- const stat1 = readFileSync45("/proc/1/stat", "utf8");
36558
+ const stat1 = readFileSync46("/proc/1/stat", "utf8");
36556
36559
  const lastParen = stat1.lastIndexOf(")");
36557
36560
  if (lastParen < 0)
36558
36561
  return null;
@@ -36560,7 +36563,7 @@ function readContainerBootTimeMsForProbe() {
36560
36563
  const starttimeTicks = Number(after[19]);
36561
36564
  if (!Number.isFinite(starttimeTicks))
36562
36565
  return null;
36563
- const procStat = readFileSync45("/proc/stat", "utf8");
36566
+ const procStat = readFileSync46("/proc/stat", "utf8");
36564
36567
  const btimeLine = procStat.split(`
36565
36568
  `).find((l) => l.startsWith("btime "));
36566
36569
  if (!btimeLine)
@@ -36658,7 +36661,7 @@ async function probeUds(label, socketPath, opts = {}) {
36658
36661
  }
36659
36662
  return withTimeout(label, (async () => {
36660
36663
  if (!opts.connectImpl) {
36661
- if (!existsSync45(socketPath)) {
36664
+ if (!existsSync46(socketPath)) {
36662
36665
  return {
36663
36666
  status: "fail",
36664
36667
  label,
@@ -36722,7 +36725,7 @@ async function probeSkills(agentDir, opts = {}) {
36722
36725
  return withTimeout("Skills", (async () => {
36723
36726
  const fs3 = opts.fs ?? realSkillsFs;
36724
36727
  const max = opts.maxNamesShown ?? 3;
36725
- const skillsDir = join55(agentDir, ".claude", "skills");
36728
+ const skillsDir = join54(agentDir, ".claude", "skills");
36726
36729
  if (!fs3.exists(skillsDir)) {
36727
36730
  return { status: "ok", label: "Skills", detail: "no skills dir" };
36728
36731
  }
@@ -36737,17 +36740,17 @@ async function probeSkills(agentDir, opts = {}) {
36737
36740
  }
36738
36741
  const dangling = [];
36739
36742
  for (const name of entries) {
36740
- const skillPath = join55(skillsDir, name);
36743
+ const skillPath = join54(skillsDir, name);
36741
36744
  if (!fs3.exists(skillPath)) {
36742
36745
  dangling.push(name);
36743
36746
  continue;
36744
36747
  }
36745
- const skillMd = join55(skillPath, "SKILL.md");
36748
+ const skillMd = join54(skillPath, "SKILL.md");
36746
36749
  if (!fs3.exists(skillMd) && !fs3.exists(skillPath + ".md")) {
36747
36750
  continue;
36748
36751
  }
36749
36752
  }
36750
- const overlayDir = opts.overlaySkillsDir ?? join55(agentDir, "skills.d");
36753
+ const overlayDir = opts.overlaySkillsDir ?? join54(agentDir, "skills.d");
36751
36754
  const overlaySlugs = new Set;
36752
36755
  if (fs3.exists(overlayDir)) {
36753
36756
  let overlayEntries = [];
@@ -36789,8 +36792,8 @@ function renderBucketedSkills(switchroom, agent) {
36789
36792
  }
36790
36793
  async function probeConnections(agentDir, opts = {}) {
36791
36794
  return withTimeout("Connections", (async () => {
36792
- const path3 = join55(agentDir, ".claude", "connection-health.json");
36793
- const read = opts.readFileImpl ?? ((p) => readFileSync45(p, "utf8"));
36795
+ const path3 = join54(agentDir, ".claude", "connection-health.json");
36796
+ const read = opts.readFileImpl ?? ((p) => readFileSync46(p, "utf8"));
36794
36797
  let issues = [];
36795
36798
  try {
36796
36799
  const parsed = JSON.parse(read(path3));
@@ -36830,7 +36833,7 @@ async function probeDrift(agentDir, opts = {}) {
36830
36833
  }
36831
36834
  } catch {}
36832
36835
  try {
36833
- const raw = readFileSync45(join55(agentDir, ".switchroom-drift.json"), "utf8");
36836
+ const raw = readFileSync46(join54(agentDir, ".switchroom-drift.json"), "utf8");
36834
36837
  const report = JSON.parse(raw);
36835
36838
  if (report?.version === 1 && Array.isArray(report.findings)) {
36836
36839
  const gen = report.generatedAt ? Date.parse(report.generatedAt) : NaN;
@@ -36877,24 +36880,24 @@ var init_boot_probes = __esm(() => {
36877
36880
  execFile = promisify(execFileCb);
36878
36881
  realProcFs = {
36879
36882
  readdir: (p) => readdirSync12(p),
36880
- readFile: (p) => readFileSync45(p, "utf-8")
36883
+ readFile: (p) => readFileSync46(p, "utf-8")
36881
36884
  };
36882
36885
  realSchedulerFs = {
36883
- readFile: (p) => readFileSync45(p, "utf-8"),
36886
+ readFile: (p) => readFileSync46(p, "utf-8"),
36884
36887
  mtimeMs: (p) => {
36885
36888
  const { statSync: statSync17 } = __require("fs");
36886
36889
  return statSync17(p).mtimeMs;
36887
36890
  },
36888
- exists: (p) => existsSync45(p)
36891
+ exists: (p) => existsSync46(p)
36889
36892
  };
36890
36893
  realSkillsFs = {
36891
36894
  readdir: (p) => readdirSync12(p),
36892
- exists: (p) => existsSync45(p)
36895
+ exists: (p) => existsSync46(p)
36893
36896
  };
36894
36897
  });
36895
36898
 
36896
36899
  // gateway/boot-issue-cache.ts
36897
- import { existsSync as existsSync46, readFileSync as readFileSync46, writeFileSync as writeFileSync38, mkdirSync as mkdirSync40, renameSync as renameSync22 } from "fs";
36900
+ import { existsSync as existsSync47, readFileSync as readFileSync47, writeFileSync as writeFileSync38, mkdirSync as mkdirSync40, renameSync as renameSync22 } from "fs";
36898
36901
  import { dirname as dirname23 } from "path";
36899
36902
  function fingerprintProbe(key, r) {
36900
36903
  if (r.status === "ok")
@@ -36974,11 +36977,11 @@ function diffProbes(probes, cache, opts = {}) {
36974
36977
  return out;
36975
36978
  }
36976
36979
  function loadCache(path3, now = Date.now) {
36977
- if (!existsSync46(path3))
36980
+ if (!existsSync47(path3))
36978
36981
  return { ...EMPTY_CACHE, probes: {} };
36979
36982
  let raw;
36980
36983
  try {
36981
- raw = readFileSync46(path3, "utf-8");
36984
+ raw = readFileSync47(path3, "utf-8");
36982
36985
  } catch {
36983
36986
  return { ...EMPTY_CACHE, probes: {} };
36984
36987
  }
@@ -37037,7 +37040,7 @@ var init_boot_issue_cache = __esm(() => {
37037
37040
 
37038
37041
  // gateway/config-snapshot.ts
37039
37042
  import { createHash as createHash7 } from "crypto";
37040
- import { existsSync as existsSync47, readFileSync as readFileSync47, writeFileSync as writeFileSync39, mkdirSync as mkdirSync41, renameSync as renameSync23 } from "fs";
37043
+ import { existsSync as existsSync48, readFileSync as readFileSync48, writeFileSync as writeFileSync39, mkdirSync as mkdirSync41, renameSync as renameSync23 } from "fs";
37041
37044
  import { dirname as dirname24 } from "path";
37042
37045
  function hashStringArray(items) {
37043
37046
  if (!items || items.length === 0)
@@ -37102,11 +37105,11 @@ function renderConfigChangeDim(dim) {
37102
37105
  }
37103
37106
  }
37104
37107
  function loadSnapshot(path3, now = Date.now) {
37105
- if (!existsSync47(path3))
37108
+ if (!existsSync48(path3))
37106
37109
  return null;
37107
37110
  let raw;
37108
37111
  try {
37109
- raw = readFileSync47(path3, "utf-8");
37112
+ raw = readFileSync48(path3, "utf-8");
37110
37113
  } catch {
37111
37114
  return null;
37112
37115
  }
@@ -37147,13 +37150,13 @@ var init_config_snapshot = __esm(() => {
37147
37150
  });
37148
37151
 
37149
37152
  // gateway/boot-card-msgid.ts
37150
- import { readFileSync as readFileSync48, writeFileSync as writeFileSync40 } from "node:fs";
37153
+ import { readFileSync as readFileSync49, writeFileSync as writeFileSync40 } from "node:fs";
37151
37154
  function bootCardChatKey(chatId, threadId) {
37152
37155
  return `${chatId}:${threadId ?? ""}`;
37153
37156
  }
37154
37157
  function readStore(path3) {
37155
37158
  try {
37156
- const parsed = JSON.parse(readFileSync48(path3, "utf8"));
37159
+ const parsed = JSON.parse(readFileSync49(path3, "utf8"));
37157
37160
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
37158
37161
  return parsed;
37159
37162
  }
@@ -37190,8 +37193,8 @@ __export(exports_boot_card, {
37190
37193
  readRoutingMode: () => readRoutingMode,
37191
37194
  containerBootStartMs: () => containerBootStartMs
37192
37195
  });
37193
- import { join as join56 } from "path";
37194
- import { readFileSync as readFileSync49, statSync as statSync17 } from "fs";
37196
+ import { join as join55 } from "path";
37197
+ import { readFileSync as readFileSync50, statSync as statSync17 } from "fs";
37195
37198
  function resolvePersonaName(slug, loadConfig3) {
37196
37199
  try {
37197
37200
  const config = loadConfig3 ? loadConfig3() : loadConfig();
@@ -37213,7 +37216,7 @@ function shouldSkipDuplicateBootCard(gate, site) {
37213
37216
  }
37214
37217
  return { skip: false };
37215
37218
  }
37216
- function containerBootStartMs(fsImpl = { readFileSync: readFileSync49 }) {
37219
+ function containerBootStartMs(fsImpl = { readFileSync: readFileSync50 }) {
37217
37220
  try {
37218
37221
  const btimeLine = fsImpl.readFileSync("/proc/stat", "utf-8").split(`
37219
37222
  `).find((l) => l.startsWith("btime "));
@@ -37234,8 +37237,8 @@ function containerBootStartMs(fsImpl = { readFileSync: readFileSync49 }) {
37234
37237
  return null;
37235
37238
  }
37236
37239
  }
37237
- function readRoutingMode(agentDir, bootStartMs, fsImpl = { readFileSync: readFileSync49, statSync: statSync17 }) {
37238
- const path3 = join56(agentDir, ".routing-mode");
37240
+ function readRoutingMode(agentDir, bootStartMs, fsImpl = { readFileSync: readFileSync50, statSync: statSync17 }) {
37241
+ const path3 = join55(agentDir, ".routing-mode");
37239
37242
  try {
37240
37243
  const raw = fsImpl.readFileSync(path3, "utf-8");
37241
37244
  const line = raw.split(`
@@ -37342,7 +37345,7 @@ function renderBootCard(opts) {
37342
37345
  return stackCardLines(flatLines);
37343
37346
  }
37344
37347
  async function runAllProbes(opts) {
37345
- const claudeDir = join56(opts.agentDir, ".claude");
37348
+ const claudeDir = join55(opts.agentDir, ".claude");
37346
37349
  const probes = {};
37347
37350
  const slug = opts.agentSlug ?? opts.agentName;
37348
37351
  await Promise.allSettled([
@@ -39140,7 +39143,7 @@ __export(exports_materialize_bot_token, {
39140
39143
  materializeBotToken: () => materializeBotToken,
39141
39144
  BotTokenMaterializeError: () => BotTokenMaterializeError
39142
39145
  });
39143
- import { existsSync as existsSync56 } from "node:fs";
39146
+ import { existsSync as existsSync57 } from "node:fs";
39144
39147
  function pickConfiguredToken(config, agentName3) {
39145
39148
  if (agentName3) {
39146
39149
  const agent = config.agents?.[agentName3];
@@ -39154,7 +39157,7 @@ function tryDirectVaultRead4(ref, config, passphrase) {
39154
39157
  if (!passphrase)
39155
39158
  return null;
39156
39159
  const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
39157
- if (!existsSync56(vaultPath))
39160
+ if (!existsSync57(vaultPath))
39158
39161
  return null;
39159
39162
  try {
39160
39163
  const secrets = openVault(passphrase, vaultPath);
@@ -39309,18 +39312,18 @@ var import_runner3 = __toESM(require_mod3(), 1);
39309
39312
  import { randomBytes as randomBytes13, createHash as createHash8 } from "crypto";
39310
39313
  import { execFileSync as execFileSync9, execSync as execSync2, spawn as spawn2 } from "child_process";
39311
39314
  import {
39312
- readFileSync as readFileSync60,
39315
+ readFileSync as readFileSync61,
39313
39316
  writeFileSync as writeFileSync50,
39314
39317
  mkdirSync as mkdirSync51,
39315
39318
  readdirSync as readdirSync16,
39316
39319
  rmSync as rmSync8,
39317
39320
  statSync as statSync23,
39318
39321
  renameSync as renameSync27,
39319
- realpathSync as realpathSync4,
39322
+ realpathSync as realpathSync5,
39320
39323
  chmodSync as chmodSync14,
39321
39324
  openSync as openSync15,
39322
39325
  closeSync as closeSync15,
39323
- existsSync as existsSync57,
39326
+ existsSync as existsSync58,
39324
39327
  unlinkSync as unlinkSync31,
39325
39328
  appendFileSync as appendFileSync9
39326
39329
  } from "fs";
@@ -39376,7 +39379,7 @@ function fsyncPathSync(path) {
39376
39379
 
39377
39380
  // gateway/gateway.ts
39378
39381
  import { homedir as homedir20 } from "os";
39379
- import { join as join69, sep as sep4, basename as basename17 } from "path";
39382
+ import { join as join68, sep as sep4, basename as basename17 } from "path";
39380
39383
 
39381
39384
  // plugin-logger.ts
39382
39385
  import { appendFileSync, mkdirSync, renameSync as renameSync2, statSync, existsSync } from "fs";
@@ -85592,9 +85595,66 @@ async function discoverModels(agentName3, opts = {}) {
85592
85595
  }
85593
85596
 
85594
85597
  // ../src/agents/scaffold.ts
85595
- import { dirname as dirname18, isAbsolute, join as join44, relative, resolve as resolve8 } from "node:path";
85596
85598
  init_atomic();
85597
85599
 
85600
+ // ../src/util/shipped-assets.ts
85601
+ import { existsSync as existsSync32, readFileSync as readFileSync31, realpathSync as realpathSync2 } from "node:fs";
85602
+ import { dirname as dirname18, resolve as resolve7 } from "node:path";
85603
+ var FHS_SHARE_ROOTS = [
85604
+ "/usr/local/share/switchroom",
85605
+ "/usr/share/switchroom"
85606
+ ];
85607
+ var PROFILES_ASSET = {
85608
+ asset: "profiles",
85609
+ envVar: "SWITCHROOM_PROFILES_ROOT"
85610
+ };
85611
+ function orderedCandidates(spec, probe) {
85612
+ const out = [];
85613
+ const push2 = (path2, source) => {
85614
+ if (!out.some((c) => c.path === path2))
85615
+ out.push({ path: path2, source });
85616
+ };
85617
+ if (probe.bundleDir) {
85618
+ push2(resolve7(probe.bundleDir, "../..", spec.asset), "npm");
85619
+ push2(resolve7(probe.bundleDir, spec.asset), "image");
85620
+ }
85621
+ if (probe.execPath) {
85622
+ push2(resolve7(dirname18(probe.execPath), "../share/switchroom", spec.asset), "sea-sibling");
85623
+ }
85624
+ for (const root of FHS_SHARE_ROOTS) {
85625
+ push2(resolve7(root, spec.asset), "fhs");
85626
+ }
85627
+ return out;
85628
+ }
85629
+ function resolveShippedAsset(spec, probe) {
85630
+ const env = probe.env ?? process.env;
85631
+ const override = env[spec.envVar]?.trim();
85632
+ if (override) {
85633
+ const path2 = canonicalise(resolve7(override), probe);
85634
+ return { path: path2, candidates: [path2], source: "env" };
85635
+ }
85636
+ const exists = probe.exists ?? existsSync32;
85637
+ const candidates = orderedCandidates(spec, probe);
85638
+ for (const c of candidates) {
85639
+ if (exists(c.path)) {
85640
+ return {
85641
+ path: canonicalise(c.path, probe),
85642
+ candidates: candidates.map((x) => x.path),
85643
+ source: c.source
85644
+ };
85645
+ }
85646
+ }
85647
+ return { path: null, candidates: candidates.map((x) => x.path), source: "none" };
85648
+ }
85649
+ function canonicalise(path2, probe) {
85650
+ const realpath = probe.realpath ?? realpathSync2;
85651
+ try {
85652
+ return realpath(path2);
85653
+ } catch {
85654
+ return path2;
85655
+ }
85656
+ }
85657
+
85598
85658
  // ../src/agents/agent-uid.ts
85599
85659
  init_peercred();
85600
85660
 
@@ -85641,37 +85701,29 @@ var AUDIT_ROOT = join42(homedir11(), ".switchroom", "audit");
85641
85701
 
85642
85702
  // ../src/agents/profiles.ts
85643
85703
  var import_handlebars = __toESM(require_lib(), 1);
85644
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync29, existsSync as existsSync33, readdirSync as readdirSync8, statSync as statSync13, copyFileSync, mkdirSync as mkdirSync32, realpathSync as realpathSync2 } from "node:fs";
85645
- import { resolve as resolve7, join as join43, sep as pathSep } from "node:path";
85646
- function resolveProfilesRoot() {
85647
- const envOverride = process.env.SWITCHROOM_PROFILES_ROOT?.trim();
85648
- if (envOverride) {
85649
- return resolve7(envOverride);
85650
- }
85651
- const candidates = [
85652
- resolve7(import.meta.dirname, "../../profiles"),
85653
- resolve7(import.meta.dirname, "profiles")
85654
- ];
85655
- for (const candidate of candidates) {
85656
- if (existsSync33(candidate)) {
85657
- return candidate;
85658
- }
85659
- }
85660
- return candidates[0];
85704
+ import { readFileSync as readFileSync33, writeFileSync as writeFileSync29, existsSync as existsSync34, readdirSync as readdirSync8, statSync as statSync13, copyFileSync, mkdirSync as mkdirSync32, realpathSync as realpathSync3 } from "node:fs";
85705
+ import { resolve as resolve8, join as join43, sep as pathSep } from "node:path";
85706
+ function resolveProfilesRootDetailed() {
85707
+ return resolveShippedAsset(PROFILES_ASSET, {
85708
+ bundleDir: import.meta.dirname,
85709
+ execPath: process.execPath
85710
+ });
85661
85711
  }
85662
- var PROFILES_ROOT = resolveProfilesRoot();
85712
+ var PROFILES_RESOLUTION = resolveProfilesRootDetailed();
85713
+ var PROFILES_ROOT = PROFILES_RESOLUTION.path ?? PROFILES_RESOLUTION.candidates[0];
85714
+ var PROFILES_ROOT_SEARCH = PROFILES_RESOLUTION.candidates;
85663
85715
  import_handlebars.default.registerHelper("json", (value) => {
85664
85716
  return new import_handlebars.default.SafeString(JSON.stringify(value, null, 2));
85665
85717
  });
85666
85718
  import_handlebars.default.registerHelper("isNumber", (value) => {
85667
85719
  return typeof value === "number" && Number.isFinite(value);
85668
85720
  });
85669
- var SHARED_FRAGMENTS_DIR = resolve7(PROFILES_ROOT, "_shared");
85721
+ var SHARED_FRAGMENTS_DIR = resolve8(PROFILES_ROOT, "_shared");
85670
85722
  var SHARED_FRAGMENTS = ["vault-protocol", "agent-self-service", "execution-discipline", "reply-discipline", "dev-protocol"];
85671
85723
  for (const name of SHARED_FRAGMENTS) {
85672
85724
  const fragPath = join43(SHARED_FRAGMENTS_DIR, `${name}.md.hbs`);
85673
- if (existsSync33(fragPath)) {
85674
- import_handlebars.default.registerPartial(name, readFileSync32(fragPath, "utf-8"));
85725
+ if (existsSync34(fragPath)) {
85726
+ import_handlebars.default.registerPartial(name, readFileSync33(fragPath, "utf-8"));
85675
85727
  }
85676
85728
  }
85677
85729
 
@@ -85874,7 +85926,8 @@ var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
85874
85926
  "HINDSIGHT_API_SEMANTIC_MIN_SIMILARITY",
85875
85927
  "HINDSIGHT_MCP_RECALL_BUDGET_MODE",
85876
85928
  "HINDSIGHT_API_LLM_TEMPERATURE_REFLECT",
85877
- "HINDSIGHT_API_RETAIN_WALL_TIMEOUT"
85929
+ "HINDSIGHT_API_RETAIN_WALL_TIMEOUT",
85930
+ "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT"
85878
85931
  ]);
85879
85932
  var HINDSIGHT_WORKER_SLOT_TYPES = [
85880
85933
  "consolidation",
@@ -85969,6 +86022,15 @@ var DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and
85969
86022
  ` + `- Hindsight's own errors, retries, backlogs, or internal state \u2014 the memory
85970
86023
  ` + ` system's self-reports are not memories.
85971
86024
  ` + `- Restatements of the user's current request or the task in progress.
86025
+ ` + `- The assistant's own answers, summaries, recaps, or reflect output. Before
86026
+ ` + ` extracting, ask: does anything in this transcript support this claim OTHER
86027
+ ` + ` than the assistant having asserted it? If not, drop it \u2014 a model's own
86028
+ ` + ` synthesis re-extracted as a fact is how a guess becomes permanent.
86029
+ ` + ` Concretely, never produce a fact whose only support is the assistant
86030
+ ` + ` stating a date, a version, an attribution, a total, or a decision that the
86031
+ ` + ` user never confirmed and no tool output shows. An unverified claim recalls
86032
+ ` + ` later as though it had been established, which is worse than not
86033
+ ` + ` remembering it at all.
85972
86034
  ` + `- Volatile state written as a timeless assertion. A version, count, size,
85973
86035
  ` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
85974
86036
  ` + ` claim is true only at the instant it was said. Concretely, never produce a
@@ -86124,6 +86186,64 @@ var SUPERSEDED_RETAIN_MISSIONS = [
86124
86186
  ` + `
86125
86187
  ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
86126
86188
  ` + `nothing durable remains, return an empty facts list.
86189
+ `,
86190
+ `Extract durable facts that will still be true and useful weeks from now, once this session is forgotten.
86191
+ ` + `
86192
+ ` + `DURABILITY GATE. Emit a candidate ONLY if it is one of these five classes:
86193
+ ` + `- PREFERENCE \u2014 what the user likes, wants, or always does; a standing rule or correction.
86194
+ ` + `- DECISION \u2014 a settled choice that changes how future work is done, including a choice NOT to do something. A decision about the mechanics of the CURRENT task (which worker to dispatch, which branch to rebase, which PR to merge now, what to do next) is process narration, not a durable decision \u2014 drop it unless it establishes a standing rule or permanently changes a system.
86195
+ ` + `- FINDING \u2014 a root cause, a measurement, or verified behaviour of a system. Include the number.
86196
+ ` + `- OUTCOME \u2014 a completed result that changed the world: what shipped, what a thing turned out to be. Not the act of shipping it.
86197
+ ` + `- RELATIONSHIP \u2014 who a person is, what a project or tool is, and how they connect.
86198
+ ` + `If a candidate fits none of the five, it is not a memory. Drop it; do not reword it into one.
86199
+ ` + `
86200
+ ` + `A preference revealed by a request is durable \u2014 record the preference (what the user likes, wants, or always does), not the request itself.
86201
+ ` + `
86202
+ ` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
86203
+ ` + `candidate a file path, a command/process/agent/session id, a temp directory, or
86204
+ ` + `the location where some output was written? If yes, drop it \u2014 it is transcript
86205
+ ` + `exhaust, not memory.
86206
+ ` + `
86207
+ ` + `NEVER extract:
86208
+ ` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
86209
+ ` + ` text resembles any of these: "File created successfully at /path/to/file",
86210
+ ` + ` "A background command with ID bctz4yskm is running, and its output will be
86211
+ ` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
86212
+ ` + ` and is running in the background", "User executed a Bash command to sleep for
86213
+ ` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
86214
+ ` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
86215
+ ` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
86216
+ ` + ` assistant used X to query Y", "ran a search", "sent the message").
86217
+ ` + `- The act of delegating, dispatching, spawning, launching, steering or merging
86218
+ ` + ` work \u2014 including when it succeeded. "X was dispatched and completed" is the
86219
+ ` + ` session describing itself. Record only what the work LEARNED or CHANGED.
86220
+ ` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
86221
+ ` + ` running) \u2014 retain the outcome only once the task completes or a decision is made.
86222
+ ` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
86223
+ ` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
86224
+ ` + ` reset assistant state").
86225
+ ` + `- Hindsight's own errors, retries, backlogs, or internal state \u2014 the memory
86226
+ ` + ` system's self-reports are not memories.
86227
+ ` + `- Restatements of the user's current request or the task in progress.
86228
+ ` + `- Volatile state written as a timeless assertion. A version, count, size,
86229
+ ` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
86230
+ ` + ` claim is true only at the instant it was said. Concretely, never produce a
86231
+ ` + ` fact whose text resembles any of these: "Switchroom fleet is running image
86232
+ ` + ` version v0.18.19", "The switchroom repo is at /path/to/fleet, version
86233
+ ` + ` v0.19.5", "Bank overlord has 43155 pending consolidations", "The build is
86234
+ ` + ` currently green". If the claim is worth keeping, put the date INSIDE the
86235
+ ` + ` fact text ("As of 2026-07-19 the fleet was running v0.18.19"); if you
86236
+ ` + ` cannot date it, drop it. An undated one is recalled forever as though it
86237
+ ` + ` were still true, which is worse than not remembering it at all.
86238
+ ` + `- Transient state (unread counts, build status, what is running right now) unless
86239
+ ` + ` the fact is explicitly dated, in which case record it as a dated observation.
86240
+ ` + `- Greetings, acknowledgements, and routine operational chatter.
86241
+ ` + `
86242
+ ` + `Write each fact so it stands alone: name the thing, the number, and the date. A
86243
+ ` + `sentence that only makes sense while reading this transcript is not durable.
86244
+ ` + `
86245
+ ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
86246
+ ` + `nothing durable remains, return an empty facts list.
86127
86247
  `
86128
86248
  ];
86129
86249
  var DEFAULT_OBSERVATIONS_MISSION = `Synthesise durable, standing knowledge about the people, projects, and systems this agent works with: preferences and standing rules, roles and relationships, skills and recurring patterns, technical and operational decisions with their rationale, and the state of long-running work once it lands.
@@ -86201,6 +86321,22 @@ var PROFILE_MEMORY_DEFAULTS = {
86201
86321
  var warnedMissingPool = new Set;
86202
86322
  var warnedMissingDefault = new Set;
86203
86323
 
86324
+ // ../src/memory/hindsight-retain-provenance.ts
86325
+ var RETAIN_PROVENANCE_TAG = "source:transcript";
86326
+ var RETAIN_TAGS_DEFAULT = Object.freeze([
86327
+ "{session_id}",
86328
+ RETAIN_PROVENANCE_TAG
86329
+ ]);
86330
+
86331
+ // ../src/memory/hindsight-seed-directives.ts
86332
+ var ANTI_CONFABULATION_DIRECTIVE = `When the retrieved memories do not support an answer, say so instead of composing one.
86333
+ ` + `
86334
+ ` + `- If nothing retrieved scores meaningfully above zero, or what came back is off-topic, the honest answer is that the bank does not know. Say that plainly, and say what would settle it.
86335
+ ` + `- Never assert a date, a version, a number, an attribution, a decision, or an outcome that no retrieved memory states. A question that presupposes something is not evidence for it: asked when a decision was made, when the bank records no such decision, answer that none is recorded \u2014 do not supply one.
86336
+ ` + `- Keep what the bank RECORDED separate from what you INFER. State inferences as inferences, and say which memory a recorded fact came from.
86337
+ ` + `- Treat a memory that was extracted from a conversation transcript as an unverified claim, not an established fact \u2014 it may be an assistant's own earlier guess. If it is the only support for an answer, say that it is.
86338
+ ` + "- Partial knowledge with its gaps named is more useful than a fluent answer that fills them in.";
86339
+
86204
86340
  // ../src/telegram/state.ts
86205
86341
  init_paths();
86206
86342
 
@@ -86238,7 +86374,6 @@ var RECALL_PASSTHROUGH_DEFAULTS = Object.freeze({
86238
86374
  init_paths();
86239
86375
 
86240
86376
  // ../src/agents/scaffold.ts
86241
- var REPO_ROOT = resolve8(import.meta.dirname, "../..");
86242
86377
  var SWITCHROOM_DEFAULT_MAIN_MODEL = "claude-sonnet-5";
86243
86378
  var SWITCHROOM_DEFAULT_THINKING_EFFORT = "low";
86244
86379
  function resolveMainModel(model) {
@@ -86798,7 +86933,7 @@ init_overlay_loader();
86798
86933
  init_merge();
86799
86934
  init_timezone();
86800
86935
  var import_yaml4 = __toESM(require_dist(), 1);
86801
- import { readFileSync as readFileSync33, existsSync as existsSync34 } from "node:fs";
86936
+ import { readFileSync as readFileSync34, existsSync as existsSync35 } from "node:fs";
86802
86937
  import { homedir as homedir12 } from "node:os";
86803
86938
  import { resolve as resolve9 } from "node:path";
86804
86939
 
@@ -86874,7 +87009,7 @@ function findConfigFile2(startDir) {
86874
87009
  resolve9(userDir, "clerk.yml")
86875
87010
  ].filter(Boolean);
86876
87011
  for (const path2 of searchPaths) {
86877
- if (existsSync34(path2)) {
87012
+ if (existsSync35(path2)) {
86878
87013
  return path2;
86879
87014
  }
86880
87015
  }
@@ -86882,12 +87017,12 @@ function findConfigFile2(startDir) {
86882
87017
  }
86883
87018
  function loadConfig2(configPath) {
86884
87019
  const filePath = configPath ?? findConfigFile2();
86885
- if (!existsSync34(filePath)) {
87020
+ if (!existsSync35(filePath)) {
86886
87021
  throw new ConfigError2(`Config file not found: ${filePath}`);
86887
87022
  }
86888
87023
  let raw;
86889
87024
  try {
86890
- raw = readFileSync33(filePath, "utf-8");
87025
+ raw = readFileSync34(filePath, "utf-8");
86891
87026
  } catch (err) {
86892
87027
  throw new ConfigError2(`Failed to read config file: ${filePath}`, [
86893
87028
  ` ${err.message}`
@@ -87417,15 +87552,15 @@ function topicForRecipient(args) {
87417
87552
  }
87418
87553
 
87419
87554
  // ../src/agents/perf.ts
87420
- import { existsSync as existsSync35, readFileSync as readFileSync34 } from "node:fs";
87555
+ import { existsSync as existsSync36, readFileSync as readFileSync35 } from "node:fs";
87421
87556
  function readTurnUsages(jsonlPath, lastN) {
87422
- if (!existsSync35(jsonlPath))
87557
+ if (!existsSync36(jsonlPath))
87423
87558
  return [];
87424
87559
  if (lastN <= 0)
87425
87560
  return [];
87426
87561
  let raw;
87427
87562
  try {
87428
- raw = readFileSync34(jsonlPath, "utf-8");
87563
+ raw = readFileSync35(jsonlPath, "utf-8");
87429
87564
  } catch {
87430
87565
  return [];
87431
87566
  }
@@ -87517,7 +87652,7 @@ function numField(obj, key) {
87517
87652
 
87518
87653
  // gateway/context-occupancy.ts
87519
87654
  import { mkdirSync as mkdirSync33, writeFileSync as writeFileSync30 } from "node:fs";
87520
- import { join as join45 } from "node:path";
87655
+ import { join as join44 } from "node:path";
87521
87656
  var CONTEXT_OCCUPANCY_FILENAME = "context-occupancy.json";
87522
87657
  var TIGHT_FRACTION = 0.8;
87523
87658
  function buildContextOccupancy(occupancy, cap, now) {
@@ -87540,7 +87675,7 @@ function buildContextOccupancy(occupancy, cap, now) {
87540
87675
  }
87541
87676
  function writeContextOccupancySnapshot(stateDir, snapshot, deps) {
87542
87677
  try {
87543
- const path2 = join45(stateDir, CONTEXT_OCCUPANCY_FILENAME);
87678
+ const path2 = join44(stateDir, CONTEXT_OCCUPANCY_FILENAME);
87544
87679
  (deps?.mkdir ?? ((p, o) => mkdirSync33(p, o)))(stateDir, { recursive: true });
87545
87680
  (deps?.writeFile ?? ((p, d) => writeFileSync30(p, d)))(path2, JSON.stringify(snapshot, null, 2) + `
87546
87681
  `);
@@ -87696,7 +87831,7 @@ function nextCompactNotify(state6, ev) {
87696
87831
  }
87697
87832
 
87698
87833
  // gateway/hostd-dispatch.ts
87699
- import { existsSync as existsSync36 } from "node:fs";
87834
+ import { existsSync as existsSync37 } from "node:fs";
87700
87835
  import { randomBytes as randomBytes10 } from "node:crypto";
87701
87836
  init_loader();
87702
87837
  var _hostdEnabled2;
@@ -87720,13 +87855,13 @@ function hostdSocketPath2(agentName3) {
87720
87855
  function hostdWillBeUsed2(agentName3) {
87721
87856
  if (!isHostdEnabled2())
87722
87857
  return false;
87723
- return existsSync36(hostdSocketPath2(agentName3));
87858
+ return existsSync37(hostdSocketPath2(agentName3));
87724
87859
  }
87725
87860
  async function tryHostdDispatch2(agentName3, req, timeoutMs = 5000) {
87726
87861
  if (!isHostdEnabled2())
87727
87862
  return "not-configured";
87728
87863
  const sockPath = hostdSocketPath2(agentName3);
87729
- if (!existsSync36(sockPath))
87864
+ if (!existsSync37(sockPath))
87730
87865
  return "not-configured";
87731
87866
  try {
87732
87867
  return await hostdRequest({ socketPath: sockPath, timeoutMs }, req);
@@ -87755,7 +87890,7 @@ async function pollHostdStatus(agentName3, targetRequestId, opts) {
87755
87890
  if (!isHostdEnabled2())
87756
87891
  return "not-configured";
87757
87892
  const sockPath = hostdSocketPath2(agentName3);
87758
- if (!existsSync36(sockPath))
87893
+ if (!existsSync37(sockPath))
87759
87894
  return "not-configured";
87760
87895
  const now = opts.now ?? Date.now;
87761
87896
  const sleep2 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
@@ -88721,7 +88856,7 @@ function createGatewayStalePinSweeper(w) {
88721
88856
 
88722
88857
  // gateway/webhook-ingest-server.ts
88723
88858
  import net4 from "node:net";
88724
- import { chmodSync as chmodSync10, existsSync as existsSync37, unlinkSync as unlinkSync18 } from "node:fs";
88859
+ import { chmodSync as chmodSync10, existsSync as existsSync38, unlinkSync as unlinkSync18 } from "node:fs";
88725
88860
  var MAX_REQUEST_BYTES = 1024 * 1024;
88726
88861
  function fdOf(conn) {
88727
88862
  const handle = conn._handle;
@@ -88733,7 +88868,7 @@ function startWebhookIngestServer(opts) {
88733
88868
  const log = opts.log ?? ((s) => process.stderr.write(s));
88734
88869
  const allowed = new Set(opts.allowedUids);
88735
88870
  try {
88736
- if (existsSync37(opts.socketPath))
88871
+ if (existsSync38(opts.socketPath))
88737
88872
  unlinkSync18(opts.socketPath);
88738
88873
  } catch (err) {
88739
88874
  log(`webhook-ingest-server: could not unlink stale socket: ${err.message}
@@ -88826,7 +88961,7 @@ function startWebhookIngestServer(opts) {
88826
88961
  server.close();
88827
88962
  } catch {}
88828
88963
  try {
88829
- if (existsSync37(opts.socketPath))
88964
+ if (existsSync38(opts.socketPath))
88830
88965
  unlinkSync18(opts.socketPath);
88831
88966
  } catch {}
88832
88967
  }
@@ -88835,12 +88970,12 @@ function startWebhookIngestServer(opts) {
88835
88970
 
88836
88971
  // ../src/web/webhook-gateway-record.ts
88837
88972
  import { appendFileSync as appendFileSync8, mkdirSync as mkdirSync36 } from "fs";
88838
- import { join as join49 } from "path";
88973
+ import { join as join48 } from "path";
88839
88974
  import { homedir as homedir14 } from "os";
88840
88975
 
88841
88976
  // ../src/web/webhook-handler.ts
88842
- import { appendFileSync as appendFileSync7, existsSync as existsSync39, mkdirSync as mkdirSync34, readFileSync as readFileSync35, writeFileSync as writeFileSync31 } from "fs";
88843
- import { join as join47 } from "path";
88977
+ import { appendFileSync as appendFileSync7, existsSync as existsSync40, mkdirSync as mkdirSync34, readFileSync as readFileSync36, writeFileSync as writeFileSync31 } from "fs";
88978
+ import { join as join46 } from "path";
88844
88979
 
88845
88980
  // ../src/util/log-rotation.ts
88846
88981
  import * as fs2 from "node:fs";
@@ -89178,9 +89313,9 @@ var DEDUP_MAX = 1000;
89178
89313
  var DEDUP_TTL_MS = 24 * 60 * 60 * 1000;
89179
89314
  function loadDedupFile(path3) {
89180
89315
  try {
89181
- if (!existsSync39(path3))
89316
+ if (!existsSync40(path3))
89182
89317
  return {};
89183
- const raw = JSON.parse(readFileSync35(path3, "utf-8"));
89318
+ const raw = JSON.parse(readFileSync36(path3, "utf-8"));
89184
89319
  return typeof raw.deliveries === "object" && raw.deliveries !== null ? raw.deliveries : {};
89185
89320
  } catch {
89186
89321
  return {};
@@ -89202,8 +89337,8 @@ var agentDedupCache = new Map;
89202
89337
  function createFileDedupStore(resolveAgentDir) {
89203
89338
  return {
89204
89339
  check(agent, deliveryId, now) {
89205
- const telegramDir = join47(resolveAgentDir(agent), "telegram");
89206
- const filePath = join47(telegramDir, "webhook-dedup.json");
89340
+ const telegramDir = join46(resolveAgentDir(agent), "telegram");
89341
+ const filePath = join46(telegramDir, "webhook-dedup.json");
89207
89342
  if (!agentDedupCache.has(agent)) {
89208
89343
  agentDedupCache.set(agent, loadDedupFile(filePath));
89209
89344
  }
@@ -89224,8 +89359,8 @@ var tokenBuckets = new Map;
89224
89359
  var throttleIssueWindow = new Map;
89225
89360
 
89226
89361
  // ../src/web/webhook-dispatch.ts
89227
- import { existsSync as existsSync40, mkdirSync as mkdirSync35, readFileSync as readFileSync36, writeFileSync as writeFileSync32 } from "fs";
89228
- import { join as join48 } from "path";
89362
+ import { existsSync as existsSync41, mkdirSync as mkdirSync35, readFileSync as readFileSync37, writeFileSync as writeFileSync32 } from "fs";
89363
+ import { join as join47 } from "path";
89229
89364
  import { homedir as homedir13 } from "os";
89230
89365
 
89231
89366
  // ../src/agent-scheduler/ipc-client.ts
@@ -89524,9 +89659,9 @@ function cooldownKey(source, eventType, repo, number, ruleIndex) {
89524
89659
  }
89525
89660
  function loadCooldownFile(path3) {
89526
89661
  try {
89527
- if (!existsSync40(path3))
89662
+ if (!existsSync41(path3))
89528
89663
  return {};
89529
- const raw = JSON.parse(readFileSync36(path3, "utf-8"));
89664
+ const raw = JSON.parse(readFileSync37(path3, "utf-8"));
89530
89665
  return typeof raw.dispatches === "object" && raw.dispatches !== null ? raw.dispatches : {};
89531
89666
  } catch {
89532
89667
  return {};
@@ -89545,8 +89680,8 @@ function createFileCooldownStore(resolveAgentDir) {
89545
89680
  isCoolingDown(agent, key, cooldownMs, now) {
89546
89681
  if (cooldownMs <= 0)
89547
89682
  return false;
89548
- const telegramDir = join48(resolveAgentDir(agent), "telegram");
89549
- const filePath = join48(telegramDir, "webhook-cooldown.json");
89683
+ const telegramDir = join47(resolveAgentDir(agent), "telegram");
89684
+ const filePath = join47(telegramDir, "webhook-cooldown.json");
89550
89685
  if (!cache.has(agent)) {
89551
89686
  cache.set(agent, loadCooldownFile(filePath));
89552
89687
  }
@@ -89603,9 +89738,9 @@ async function defaultInject(socketPath, agentName3, inbound) {
89603
89738
  }
89604
89739
  function injectWebhookInbound(agent, prompt, ctx, deps = {}) {
89605
89740
  const log = deps.log ?? ((s) => process.stderr.write(s));
89606
- const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join48(homedir13(), ".switchroom", "agents", a));
89741
+ const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join47(homedir13(), ".switchroom", "agents", a));
89607
89742
  const now = (deps.now ?? Date.now)();
89608
- const socketPath = join48(resolveAgentDir(agent), "telegram", "gateway.sock");
89743
+ const socketPath = join47(resolveAgentDir(agent), "telegram", "gateway.sock");
89609
89744
  const inbound = {
89610
89745
  type: "inbound",
89611
89746
  chatId: ctx.chatId,
@@ -89677,7 +89812,7 @@ function evaluateDispatch(args, deps = {}) {
89677
89812
  const log = deps.log ?? ((s) => process.stderr.write(s));
89678
89813
  const now = (deps.now ?? Date.now)();
89679
89814
  const nowDate = deps.nowDate ?? (() => new Date(now));
89680
- const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join48(homedir13(), ".switchroom", "agents", a));
89815
+ const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join47(homedir13(), ".switchroom", "agents", a));
89681
89816
  const cooldownStore = deps.cooldownStore ?? createFileCooldownStore(resolveAgentDir);
89682
89817
  if (!DISPATCH_SOURCES.includes(args.source))
89683
89818
  return 0;
@@ -89755,10 +89890,10 @@ var CONSOLIDATION_COMPLETED_EVENT = "consolidation.completed";
89755
89890
  function recordWebhookEvent(rec, deps = {}) {
89756
89891
  const log = deps.log ?? ((s) => process.stderr.write(s));
89757
89892
  const now = rec.ts || (deps.now ?? Date.now)();
89758
- const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join49(homedir14(), ".switchroom", "agents", a));
89893
+ const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join48(homedir14(), ".switchroom", "agents", a));
89759
89894
  const dedupStore = deps.dedupStore ?? createFileDedupStore(resolveAgentDir);
89760
89895
  const agent = rec.agent;
89761
- const telegramDir = join49(resolveAgentDir(agent), "telegram");
89896
+ const telegramDir = join48(resolveAgentDir(agent), "telegram");
89762
89897
  if (rec.source === "github" && rec.delivery_id) {
89763
89898
  const originalTs = dedupStore.check(agent, rec.delivery_id, now);
89764
89899
  if (originalTs !== undefined) {
@@ -89767,7 +89902,7 @@ function recordWebhookEvent(rec, deps = {}) {
89767
89902
  return { status: "deduped", ts: originalTs };
89768
89903
  }
89769
89904
  }
89770
- const logPath = join49(telegramDir, "webhook-events.jsonl");
89905
+ const logPath = join48(telegramDir, "webhook-events.jsonl");
89771
89906
  try {
89772
89907
  mkdirSync36(telegramDir, { recursive: true });
89773
89908
  rotateWebhookLogIfNeeded(logPath);
@@ -94030,14 +94165,14 @@ function purgeStaleTurnsForChat(chatId, keys, purger, isStale = () => true) {
94030
94165
  // gateway/compaction-marker.ts
94031
94166
  import { statSync as statSync15, unlinkSync as unlinkSync21 } from "node:fs";
94032
94167
  import { homedir as homedir15 } from "node:os";
94033
- import { join as join50 } from "node:path";
94168
+ import { join as join49 } from "node:path";
94034
94169
  var COMPACTION_MARKER_FILE = "compaction-in-flight.json";
94035
94170
  function resolveTelegramStateDir() {
94036
- return process.env.TELEGRAM_STATE_DIR ?? join50(homedir15(), ".claude", "channels", "telegram");
94171
+ return process.env.TELEGRAM_STATE_DIR ?? join49(homedir15(), ".claude", "channels", "telegram");
94037
94172
  }
94038
94173
  function readCompactionMarkerAgeMs(stateDir, now) {
94039
94174
  try {
94040
- const st = statSync15(join50(stateDir, COMPACTION_MARKER_FILE));
94175
+ const st = statSync15(join49(stateDir, COMPACTION_MARKER_FILE));
94041
94176
  return (now ?? Date.now()) - st.mtimeMs;
94042
94177
  } catch {
94043
94178
  return null;
@@ -94045,7 +94180,7 @@ function readCompactionMarkerAgeMs(stateDir, now) {
94045
94180
  }
94046
94181
  function removeCompactionMarker(stateDir) {
94047
94182
  try {
94048
- unlinkSync21(join50(stateDir, COMPACTION_MARKER_FILE));
94183
+ unlinkSync21(join49(stateDir, COMPACTION_MARKER_FILE));
94049
94184
  } catch {}
94050
94185
  }
94051
94186
 
@@ -94867,26 +95002,26 @@ function skillProposalKeyboard(id) {
94867
95002
  // ../src/self-improve/skill-proposals.ts
94868
95003
  import {
94869
95004
  closeSync as closeSync9,
94870
- existsSync as existsSync41,
95005
+ existsSync as existsSync42,
94871
95006
  mkdirSync as mkdirSync37,
94872
95007
  openSync as openSync9,
94873
- readFileSync as readFileSync37,
95008
+ readFileSync as readFileSync38,
94874
95009
  writeSync as writeSync6
94875
95010
  } from "node:fs";
94876
- import { join as join51 } from "node:path";
95011
+ import { join as join50 } from "node:path";
94877
95012
  import { randomUUID as randomUUID5 } from "node:crypto";
94878
95013
  var PROPOSALS_FILE2 = "skill-proposals.jsonl";
94879
95014
  var REJECTED_FILE2 = "skill-proposals-rejected.jsonl";
94880
95015
  var REJECTION_TTL_MS2 = 90 * 24 * 60 * 60 * 1000;
94881
95016
  var PROPOSAL_SIM_THRESHOLD = 0.5;
94882
95017
  function proposalsPath2(stateDir) {
94883
- return join51(stateDir, PROPOSALS_FILE2);
95018
+ return join50(stateDir, PROPOSALS_FILE2);
94884
95019
  }
94885
95020
  function rejectedPath2(stateDir) {
94886
- return join51(stateDir, REJECTED_FILE2);
95021
+ return join50(stateDir, REJECTED_FILE2);
94887
95022
  }
94888
95023
  function ensureDir3(stateDir) {
94889
- if (!existsSync41(stateDir)) {
95024
+ if (!existsSync42(stateDir)) {
94890
95025
  mkdirSync37(stateDir, { recursive: true, mode: 493 });
94891
95026
  }
94892
95027
  }
@@ -94900,11 +95035,11 @@ function appendLine2(path3, obj) {
94900
95035
  }
94901
95036
  }
94902
95037
  function readLines2(path3, isValid2) {
94903
- if (!existsSync41(path3))
95038
+ if (!existsSync42(path3))
94904
95039
  return [];
94905
95040
  let raw;
94906
95041
  try {
94907
- raw = readFileSync37(path3, "utf-8");
95042
+ raw = readFileSync38(path3, "utf-8");
94908
95043
  } catch {
94909
95044
  return [];
94910
95045
  }
@@ -95501,7 +95636,7 @@ function escapeBody2(s) {
95501
95636
  }
95502
95637
 
95503
95638
  // gateway/pid-file.ts
95504
- import { writeFileSync as writeFileSync33, readFileSync as readFileSync38, unlinkSync as unlinkSync22, renameSync as renameSync18 } from "node:fs";
95639
+ import { writeFileSync as writeFileSync33, readFileSync as readFileSync39, unlinkSync as unlinkSync22, renameSync as renameSync18 } from "node:fs";
95505
95640
  function writePidFile(path3, record) {
95506
95641
  const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
95507
95642
  writeFileSync33(tmp, JSON.stringify(record), "utf-8");
@@ -95520,10 +95655,10 @@ import {
95520
95655
  writeFile as writeFileAsync,
95521
95656
  readFile as readFileAsync
95522
95657
  } from "node:fs/promises";
95523
- import { readFileSync as readFileSync39 } from "node:fs";
95658
+ import { readFileSync as readFileSync40 } from "node:fs";
95524
95659
  function readCurrentBootId() {
95525
95660
  try {
95526
- const stat = readFileSync39("/proc/1/stat", "utf-8");
95661
+ const stat = readFileSync40("/proc/1/stat", "utf-8");
95527
95662
  const lastParen = stat.lastIndexOf(")");
95528
95663
  if (lastParen < 0)
95529
95664
  return null;
@@ -95726,7 +95861,7 @@ function safeCount(fn) {
95726
95861
  }
95727
95862
 
95728
95863
  // gateway/session-marker.ts
95729
- import { writeFileSync as writeFileSync34, readFileSync as readFileSync40, renameSync as renameSync19, unlinkSync as unlinkSync23 } from "node:fs";
95864
+ import { writeFileSync as writeFileSync34, readFileSync as readFileSync41, renameSync as renameSync19, unlinkSync as unlinkSync23 } from "node:fs";
95730
95865
  function writeSessionMarker(path3, marker) {
95731
95866
  const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
95732
95867
  writeFileSync34(tmp, JSON.stringify(marker), "utf-8");
@@ -95734,7 +95869,7 @@ function writeSessionMarker(path3, marker) {
95734
95869
  }
95735
95870
  function readSessionMarker(path3) {
95736
95871
  try {
95737
- const raw = readFileSync40(path3, "utf-8");
95872
+ const raw = readFileSync41(path3, "utf-8");
95738
95873
  const parsed = JSON.parse(raw);
95739
95874
  if (typeof parsed.pid === "number" && typeof parsed.startedAtMs === "number" && Number.isFinite(parsed.pid) && Number.isFinite(parsed.startedAtMs)) {
95740
95875
  return { pid: parsed.pid, startedAtMs: parsed.startedAtMs };
@@ -95756,7 +95891,7 @@ function shouldFireRestartBanner(input) {
95756
95891
  }
95757
95892
 
95758
95893
  // gateway/clean-shutdown-marker.ts
95759
- import { writeFileSync as writeFileSync35, readFileSync as readFileSync41, renameSync as renameSync20, unlinkSync as unlinkSync24 } from "node:fs";
95894
+ import { writeFileSync as writeFileSync35, readFileSync as readFileSync42, renameSync as renameSync20, unlinkSync as unlinkSync24 } from "node:fs";
95760
95895
  var DEFAULT_MAX_AGE_MS = 60000;
95761
95896
  function writeCleanShutdownMarker(path3, marker) {
95762
95897
  const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
@@ -95765,7 +95900,7 @@ function writeCleanShutdownMarker(path3, marker) {
95765
95900
  }
95766
95901
  function readCleanShutdownMarker(path3) {
95767
95902
  try {
95768
- const raw = readFileSync41(path3, "utf-8");
95903
+ const raw = readFileSync42(path3, "utf-8");
95769
95904
  const parsed = JSON.parse(raw);
95770
95905
  if (typeof parsed.ts === "number" && Number.isFinite(parsed.ts) && typeof parsed.signal === "string" && parsed.signal.length > 0) {
95771
95906
  const out = { ts: parsed.ts, signal: parsed.signal };
@@ -96137,16 +96272,16 @@ function classifyAdminGate(text4, myAgentName) {
96137
96272
 
96138
96273
  // subagent-watcher.ts
96139
96274
  import {
96140
- existsSync as existsSync42,
96275
+ existsSync as existsSync43,
96141
96276
  openSync as openSync10,
96142
96277
  readSync as readSync2,
96143
96278
  statSync as statSync16,
96144
96279
  closeSync as closeSync10,
96145
96280
  watch,
96146
96281
  readdirSync as readdirSync10,
96147
- readFileSync as readFileSync42
96282
+ readFileSync as readFileSync43
96148
96283
  } from "fs";
96149
- import { join as join52 } from "path";
96284
+ import { join as join51 } from "path";
96150
96285
 
96151
96286
  // session-tail.ts
96152
96287
  function sanitizeCwdToProjectName2(cwd) {
@@ -96496,7 +96631,7 @@ function backfillJsonlAgentId(db3, jsonlPath, agentId, log) {
96496
96631
  const metaPath = jsonlPath.replace(/\.jsonl$/, ".meta.json");
96497
96632
  let meta;
96498
96633
  try {
96499
- const raw = readFileSync42(metaPath, "utf8");
96634
+ const raw = readFileSync43(metaPath, "utf8");
96500
96635
  meta = JSON.parse(raw);
96501
96636
  } catch {
96502
96637
  log?.(`subagent-watcher: backfill skip ${agentId} \u2014 meta.json not readable at ${metaPath}`);
@@ -96951,7 +97086,7 @@ function startSubagentWatcher(config) {
96951
97086
  clearTimeout(ref.ref);
96952
97087
  });
96953
97088
  const fs3 = config.fs ?? {
96954
- existsSync: existsSync42,
97089
+ existsSync: existsSync43,
96955
97090
  readdirSync: readdirSync10,
96956
97091
  statSync: statSync16,
96957
97092
  openSync: openSync10,
@@ -97469,8 +97604,8 @@ function startSubagentWatcher(config) {
97469
97604
  if (stopped)
97470
97605
  return;
97471
97606
  pruneVanishedDirWatchers();
97472
- const claudeHome = join52(agentDir, ".claude");
97473
- const projectsRoot = join52(claudeHome, "projects");
97607
+ const claudeHome = join51(agentDir, ".claude");
97608
+ const projectsRoot = join51(claudeHome, "projects");
97474
97609
  if (!fs3.existsSync(projectsRoot))
97475
97610
  return;
97476
97611
  let projectDirs;
@@ -97504,7 +97639,7 @@ function startSubagentWatcher(config) {
97504
97639
  continue;
97505
97640
  }
97506
97641
  warnedForeignSlugs.delete(pDir);
97507
- const projectPath = join52(projectsRoot, pDir);
97642
+ const projectPath = join51(projectsRoot, pDir);
97508
97643
  let sessionDirs;
97509
97644
  try {
97510
97645
  sessionDirs = fs3.readdirSync(projectPath);
@@ -97514,7 +97649,7 @@ function startSubagentWatcher(config) {
97514
97649
  for (const sDir of sessionDirs) {
97515
97650
  if (sDir.endsWith(".jsonl"))
97516
97651
  continue;
97517
- const subagentsPath = join52(projectPath, sDir, "subagents");
97652
+ const subagentsPath = join51(projectPath, sDir, "subagents");
97518
97653
  if (!fs3.existsSync(subagentsPath))
97519
97654
  continue;
97520
97655
  const watchAndScan = (dirPath) => {
@@ -97523,7 +97658,7 @@ function startSubagentWatcher(config) {
97523
97658
  const w = fs3.watch(dirPath, (_event, filename) => {
97524
97659
  if (!filename || !filename.toString().startsWith("agent-") || !filename.toString().endsWith(".jsonl"))
97525
97660
  return;
97526
- const filePath = join52(dirPath, filename.toString());
97661
+ const filePath = join51(dirPath, filename.toString());
97527
97662
  if (!knownFiles.has(filePath)) {
97528
97663
  scanSubagentsDir(dirPath);
97529
97664
  }
@@ -97537,7 +97672,7 @@ function startSubagentWatcher(config) {
97537
97672
  scanSubagentsDir(dirPath);
97538
97673
  };
97539
97674
  watchAndScan(subagentsPath);
97540
- const workflowsPath = join52(subagentsPath, "workflows");
97675
+ const workflowsPath = join51(subagentsPath, "workflows");
97541
97676
  if (fs3.existsSync(workflowsPath)) {
97542
97677
  let wfDirs;
97543
97678
  try {
@@ -97547,7 +97682,7 @@ function startSubagentWatcher(config) {
97547
97682
  }
97548
97683
  for (const wfDir of wfDirs) {
97549
97684
  try {
97550
- const wfPath = join52(workflowsPath, wfDir);
97685
+ const wfPath = join51(workflowsPath, wfDir);
97551
97686
  if (!fs3.statSync(wfPath).isDirectory())
97552
97687
  continue;
97553
97688
  watchAndScan(wfPath);
@@ -97567,7 +97702,7 @@ function startSubagentWatcher(config) {
97567
97702
  for (const e of entries) {
97568
97703
  if (!e.startsWith("agent-") || !e.endsWith(".jsonl"))
97569
97704
  continue;
97570
- const filePath = join52(subagentsPath, e);
97705
+ const filePath = join51(subagentsPath, e);
97571
97706
  if (knownFiles.has(filePath))
97572
97707
  continue;
97573
97708
  const agentId = e.slice("agent-".length, -".jsonl".length);
@@ -97697,19 +97832,19 @@ function startSubagentWatcher(config) {
97697
97832
  import {
97698
97833
  mkdirSync as mkdirSync38,
97699
97834
  writeFileSync as writeFileSync36,
97700
- readFileSync as readFileSync43,
97835
+ readFileSync as readFileSync44,
97701
97836
  readdirSync as readdirSync11,
97702
97837
  unlinkSync as unlinkSync25,
97703
- existsSync as existsSync43,
97838
+ existsSync as existsSync44,
97704
97839
  renameSync as renameSync21
97705
97840
  } from "node:fs";
97706
- import { join as join53, resolve as resolve10 } from "node:path";
97841
+ import { join as join52, resolve as resolve10 } from "node:path";
97707
97842
  import { homedir as homedir16 } from "node:os";
97708
97843
  function registryDir() {
97709
- return resolve10(process.env.SWITCHROOM_WORKTREE_DIR ?? join53(homedir16(), ".switchroom", "worktrees"));
97844
+ return resolve10(process.env.SWITCHROOM_WORKTREE_DIR ?? join52(homedir16(), ".switchroom", "worktrees"));
97710
97845
  }
97711
97846
  function recordPath(id) {
97712
- return join53(registryDir(), `${id}.json`);
97847
+ return join52(registryDir(), `${id}.json`);
97713
97848
  }
97714
97849
  function ensureDir4() {
97715
97850
  mkdirSync38(registryDir(), { recursive: true });
@@ -97725,7 +97860,7 @@ function writeRecord(record) {
97725
97860
  function readRecord(id) {
97726
97861
  const path3 = recordPath(id);
97727
97862
  try {
97728
- const raw = readFileSync43(path3, "utf8");
97863
+ const raw = readFileSync44(path3, "utf8");
97729
97864
  return JSON.parse(raw);
97730
97865
  } catch {
97731
97866
  return null;
@@ -97755,11 +97890,11 @@ function touchHeartbeat(id, onAfterRead) {
97755
97890
  writeRecord({ ...rec, heartbeatAt: new Date().toISOString() });
97756
97891
  }
97757
97892
  function recordExists(id) {
97758
- return existsSync43(recordPath(id));
97893
+ return existsSync44(recordPath(id));
97759
97894
  }
97760
97895
 
97761
97896
  // worktree-watch-cwds.ts
97762
- import { realpathSync as realpathSync3 } from "node:fs";
97897
+ import { realpathSync as realpathSync4 } from "node:fs";
97763
97898
  import { basename as basename13 } from "node:path";
97764
97899
  var identityEscalated = false;
97765
97900
  function defaultDeriveName(agentDir) {
@@ -97785,7 +97920,7 @@ function ownedWorktreeCwds(opts) {
97785
97920
  }
97786
97921
  return [];
97787
97922
  }
97788
- const rp = opts.realpath ?? realpathSync3;
97923
+ const rp = opts.realpath ?? realpathSync4;
97789
97924
  try {
97790
97925
  return opts.listRecords().filter((r) => r.ownerAgent === resolved).map((r) => {
97791
97926
  try {
@@ -97884,20 +98019,20 @@ function determineRestartReason(opts) {
97884
98019
  }
97885
98020
 
97886
98021
  // gateway/update-announce.ts
97887
- import { existsSync as existsSync48, mkdirSync as mkdirSync42, openSync as openSync11, closeSync as closeSync11, readFileSync as readFileSync50 } from "node:fs";
97888
- import { join as join58 } from "node:path";
98022
+ import { existsSync as existsSync49, mkdirSync as mkdirSync42, openSync as openSync11, closeSync as closeSync11, readFileSync as readFileSync51 } from "node:fs";
98023
+ import { join as join57 } from "node:path";
97889
98024
  import { homedir as homedir18 } from "node:os";
97890
98025
 
97891
98026
  // ../src/host-control/audit-reader.ts
97892
98027
  import { homedir as homedir17 } from "node:os";
97893
- import { join as join57 } from "node:path";
98028
+ import { join as join56 } from "node:path";
97894
98029
 
97895
98030
  // ../src/host-control/audit-rotation-config.ts
97896
98031
  var DEFAULT_HOSTD_AUDIT_MAX_BYTES = 32 * 1024 * 1024;
97897
98032
 
97898
98033
  // ../src/host-control/audit-reader.ts
97899
98034
  function defaultAuditLogPath(home2 = homedir17()) {
97900
- return join57(home2, ".switchroom", "host-control-audit.log");
98035
+ return join56(home2, ".switchroom", "host-control-audit.log");
97901
98036
  }
97902
98037
  var AUDIT_READ_WINDOW_BYTES = 4 * 1024 * 1024;
97903
98038
  function parseAuditLine(line) {
@@ -98031,8 +98166,8 @@ init_status_no_truncate();
98031
98166
  var DEFAULT_LOOKBACK_MS = 10 * 60 * 1000;
98032
98167
  function readLastTerminalUpdateAudit(opts = {}) {
98033
98168
  const path3 = opts.auditLogPath ?? defaultAuditLogPath();
98034
- const exists = opts.exists ?? existsSync48;
98035
- const readFile = opts.readFile ?? ((p) => readFileSync50(p, "utf-8"));
98169
+ const exists = opts.exists ?? existsSync49;
98170
+ const readFile = opts.readFile ?? ((p) => readFileSync51(p, "utf-8"));
98036
98171
  if (!exists(path3))
98037
98172
  return null;
98038
98173
  let raw;
@@ -98096,15 +98231,15 @@ function renderUpdateOutcomeLine(entry) {
98096
98231
  `);
98097
98232
  }
98098
98233
  function claimUpdateAnnouncement(requestId, opts = {}) {
98099
- const stateDir = opts.stateDir ?? process.env.TELEGRAM_STATE_DIR ?? join58(homedir18(), ".switchroom");
98100
- const dir = join58(stateDir, "update-announced");
98234
+ const stateDir = opts.stateDir ?? process.env.TELEGRAM_STATE_DIR ?? join57(homedir18(), ".switchroom");
98235
+ const dir = join57(stateDir, "update-announced");
98101
98236
  try {
98102
98237
  mkdirSync42(dir, { recursive: true });
98103
98238
  } catch {
98104
98239
  return false;
98105
98240
  }
98106
98241
  const safeId = requestId.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 200);
98107
- const path3 = join58(dir, safeId);
98242
+ const path3 = join57(dir, safeId);
98108
98243
  try {
98109
98244
  const fd = openSync11(path3, "wx");
98110
98245
  closeSync11(fd);
@@ -98124,7 +98259,7 @@ function maybeRenderUpdateAnnouncement(opts = {}) {
98124
98259
 
98125
98260
  // issues-card.ts
98126
98261
  init_card_format();
98127
- import { readFileSync as readFileSync51, writeFileSync as writeFileSync41 } from "node:fs";
98262
+ import { readFileSync as readFileSync52, writeFileSync as writeFileSync41 } from "node:fs";
98128
98263
  var SEVERITY_EMOJI = {
98129
98264
  info: "\u2139\ufe0f",
98130
98265
  warn: "\u26a0\ufe0f",
@@ -98216,7 +98351,7 @@ function extractRetryAfterSecs2(err) {
98216
98351
  var COOLDOWN_JITTER_MS2 = 500;
98217
98352
  function readPersistedMessageId(path3, log) {
98218
98353
  try {
98219
- const raw = readFileSync51(path3, "utf8");
98354
+ const raw = readFileSync52(path3, "utf8");
98220
98355
  const parsed = JSON.parse(raw);
98221
98356
  const v = parsed.messageId;
98222
98357
  if (typeof v === "number" && Number.isInteger(v) && v > 0)
@@ -98325,24 +98460,24 @@ function createIssuesCardHandle(opts) {
98325
98460
  }
98326
98461
 
98327
98462
  // issues-watcher.ts
98328
- import { existsSync as existsSync50, statSync as statSync19 } from "node:fs";
98329
- import { join as join60 } from "node:path";
98463
+ import { existsSync as existsSync51, statSync as statSync19 } from "node:fs";
98464
+ import { join as join59 } from "node:path";
98330
98465
 
98331
98466
  // ../src/issues/store.ts
98332
98467
  import {
98333
98468
  closeSync as closeSync12,
98334
- existsSync as existsSync49,
98469
+ existsSync as existsSync50,
98335
98470
  mkdirSync as mkdirSync43,
98336
98471
  openSync as openSync12,
98337
98472
  readdirSync as readdirSync13,
98338
- readFileSync as readFileSync52,
98473
+ readFileSync as readFileSync53,
98339
98474
  renameSync as renameSync24,
98340
98475
  statSync as statSync18,
98341
98476
  unlinkSync as unlinkSync26,
98342
98477
  writeFileSync as writeFileSync42,
98343
98478
  writeSync as writeSync7
98344
98479
  } from "node:fs";
98345
- import { join as join59 } from "node:path";
98480
+ import { join as join58 } from "node:path";
98346
98481
  import { randomBytes as randomBytes11 } from "node:crypto";
98347
98482
  import { execSync } from "node:child_process";
98348
98483
 
@@ -98361,12 +98496,12 @@ init_redact();
98361
98496
  var ISSUES_FILE = "issues.jsonl";
98362
98497
  var ISSUES_LOCK = "issues.lock";
98363
98498
  function readAll(stateDir) {
98364
- const path3 = join59(stateDir, ISSUES_FILE);
98365
- if (!existsSync49(path3))
98499
+ const path3 = join58(stateDir, ISSUES_FILE);
98500
+ if (!existsSync50(path3))
98366
98501
  return [];
98367
98502
  let raw;
98368
98503
  try {
98369
- raw = readFileSync52(path3, "utf-8");
98504
+ raw = readFileSync53(path3, "utf-8");
98370
98505
  } catch {
98371
98506
  return [];
98372
98507
  }
@@ -98398,7 +98533,7 @@ function list2(stateDir, opts = {}) {
98398
98533
  });
98399
98534
  }
98400
98535
  function resolve11(stateDir, fingerprint, nowFn = Date.now) {
98401
- if (!existsSync49(join59(stateDir, ISSUES_FILE)))
98536
+ if (!existsSync50(join58(stateDir, ISSUES_FILE)))
98402
98537
  return 0;
98403
98538
  return withLock(stateDir, () => {
98404
98539
  const all2 = readAll(stateDir);
@@ -98416,7 +98551,7 @@ function resolve11(stateDir, fingerprint, nowFn = Date.now) {
98416
98551
  });
98417
98552
  }
98418
98553
  function writeAll(stateDir, events) {
98419
- const path3 = join59(stateDir, ISSUES_FILE);
98554
+ const path3 = join58(stateDir, ISSUES_FILE);
98420
98555
  sweepOrphanTmpFiles(stateDir);
98421
98556
  const tmp = `${path3}.tmp-${process.pid}-${randomBytes11(4).toString("hex")}`;
98422
98557
  const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
@@ -98438,7 +98573,7 @@ function sweepOrphanTmpFiles(stateDir) {
98438
98573
  for (const entry of entries) {
98439
98574
  if (!entry.startsWith(TMP_PREFIX))
98440
98575
  continue;
98441
- const tmpPath2 = join59(stateDir, entry);
98576
+ const tmpPath2 = join58(stateDir, entry);
98442
98577
  try {
98443
98578
  const stat = statSync18(tmpPath2);
98444
98579
  if (stat.mtimeMs < cutoff) {
@@ -98450,7 +98585,7 @@ function sweepOrphanTmpFiles(stateDir) {
98450
98585
  var LOCK_RETRY_MS = 25;
98451
98586
  var LOCK_TIMEOUT_MS = 1e4;
98452
98587
  function withLock(stateDir, fn) {
98453
- const lockPath = join59(stateDir, ISSUES_LOCK);
98588
+ const lockPath = join58(stateDir, ISSUES_LOCK);
98454
98589
  const startedAt = Date.now();
98455
98590
  let fd = null;
98456
98591
  while (fd === null) {
@@ -98485,7 +98620,7 @@ function withLock(stateDir, fn) {
98485
98620
  function tryStealStaleLock(lockPath) {
98486
98621
  let pidStr;
98487
98622
  try {
98488
- pidStr = readFileSync52(lockPath, "utf-8").trim();
98623
+ pidStr = readFileSync53(lockPath, "utf-8").trim();
98489
98624
  } catch {
98490
98625
  return true;
98491
98626
  }
@@ -98535,7 +98670,7 @@ function isIssueEvent(v) {
98535
98670
  // issues-watcher.ts
98536
98671
  var DEFAULT_POLL_INTERVAL_MS2 = 2000;
98537
98672
  function startIssuesWatcher(opts) {
98538
- const path3 = join60(opts.stateDir, ISSUES_FILE);
98673
+ const path3 = join59(opts.stateDir, ISSUES_FILE);
98539
98674
  const log = opts.log ?? (() => {});
98540
98675
  const intervalMs = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
98541
98676
  const setIntervalFn = opts.setInterval ?? setInterval;
@@ -98583,7 +98718,7 @@ function startIssuesWatcher(opts) {
98583
98718
  };
98584
98719
  }
98585
98720
  function defaultSignatureProvider(path3) {
98586
- if (!existsSync50(path3))
98721
+ if (!existsSync51(path3))
98587
98722
  return null;
98588
98723
  try {
98589
98724
  const stat = statSync19(path3);
@@ -99295,7 +99430,7 @@ function readBashCommand(inputPreview) {
99295
99430
 
99296
99431
  // gateway/scoped-grant-store.ts
99297
99432
  init_atomic();
99298
- import { join as join61 } from "node:path";
99433
+ import { join as join60 } from "node:path";
99299
99434
 
99300
99435
  // scoped-approval.ts
99301
99436
  var SCOPED_APPROVAL_DEFAULT_TTL_MS2 = 30 * 60 * 1000;
@@ -99337,7 +99472,7 @@ function scopedGrantPersistEnabled(env = process.env) {
99337
99472
  return env.SWITCHROOM_SCOPED_GRANT_PERSIST !== "0";
99338
99473
  }
99339
99474
  function createScopedGrantStore(stateDir, env = process.env, log = (l) => process.stderr.write(l)) {
99340
- const filePath = join61(stateDir, "scoped-grants.json");
99475
+ const filePath = join60(stateDir, "scoped-grants.json");
99341
99476
  const enabled7 = scopedGrantPersistEnabled(env);
99342
99477
  let unreadable = false;
99343
99478
  function read() {
@@ -99715,8 +99850,8 @@ function isDiffPreApproved(agentName3, unifiedDiff, deps) {
99715
99850
 
99716
99851
  // credits-watch.ts
99717
99852
  init_card_format();
99718
- import { readFileSync as readFileSync53, writeFileSync as writeFileSync43, existsSync as existsSync51, mkdirSync as mkdirSync44 } from "fs";
99719
- import { join as join62 } from "path";
99853
+ import { readFileSync as readFileSync54, writeFileSync as writeFileSync43, existsSync as existsSync52, mkdirSync as mkdirSync44 } from "fs";
99854
+ import { join as join61 } from "path";
99720
99855
  var STATE_FILE = "credits-watch.json";
99721
99856
  var DEFAULT_CREDIT_FATAL_REASONS = new Set;
99722
99857
  var KNOWN_CREDIT_REASONS = [
@@ -99738,12 +99873,12 @@ function emptyCreditState() {
99738
99873
  return { lastNotifiedReason: null, lastNotifiedAt: 0 };
99739
99874
  }
99740
99875
  function readClaudeJsonOverage(claudeConfigDir) {
99741
- const path3 = join62(claudeConfigDir, ".claude.json");
99742
- if (!existsSync51(path3))
99876
+ const path3 = join61(claudeConfigDir, ".claude.json");
99877
+ if (!existsSync52(path3))
99743
99878
  return null;
99744
99879
  let raw;
99745
99880
  try {
99746
- raw = readFileSync53(path3, "utf-8");
99881
+ raw = readFileSync54(path3, "utf-8");
99747
99882
  } catch {
99748
99883
  return null;
99749
99884
  }
@@ -99821,11 +99956,11 @@ function humanizeReason(reason) {
99821
99956
  }
99822
99957
  }
99823
99958
  function loadCreditState(stateDir) {
99824
- const path3 = join62(stateDir, STATE_FILE);
99825
- if (!existsSync51(path3))
99959
+ const path3 = join61(stateDir, STATE_FILE);
99960
+ if (!existsSync52(path3))
99826
99961
  return emptyCreditState();
99827
99962
  try {
99828
- const raw = readFileSync53(path3, "utf-8");
99963
+ const raw = readFileSync54(path3, "utf-8");
99829
99964
  const parsed = JSON.parse(raw);
99830
99965
  if (parsed && typeof parsed === "object" && (parsed.lastNotifiedReason === null || typeof parsed.lastNotifiedReason === "string") && typeof parsed.lastNotifiedAt === "number" && Number.isFinite(parsed.lastNotifiedAt)) {
99831
99966
  return {
@@ -99838,7 +99973,7 @@ function loadCreditState(stateDir) {
99838
99973
  }
99839
99974
  function saveCreditState(stateDir, state7) {
99840
99975
  mkdirSync44(stateDir, { recursive: true });
99841
- const path3 = join62(stateDir, STATE_FILE);
99976
+ const path3 = join61(stateDir, STATE_FILE);
99842
99977
  writeFileSync43(path3, JSON.stringify(state7, null, 2) + `
99843
99978
  `, { mode: 384 });
99844
99979
  }
@@ -99846,8 +99981,8 @@ function saveCreditState(stateDir, state7) {
99846
99981
  // quota-watch.ts
99847
99982
  init_auth_snapshot_format();
99848
99983
  init_card_format();
99849
- import { readFileSync as readFileSync54, writeFileSync as writeFileSync44, existsSync as existsSync52, mkdirSync as mkdirSync45 } from "fs";
99850
- import { join as join63 } from "path";
99984
+ import { readFileSync as readFileSync55, writeFileSync as writeFileSync44, existsSync as existsSync53, mkdirSync as mkdirSync45 } from "fs";
99985
+ import { join as join62 } from "path";
99851
99986
  var STATE_FILE2 = "quota-watch.json";
99852
99987
  function emptyQuotaWatchState() {
99853
99988
  return {};
@@ -100085,11 +100220,11 @@ function buildRecoveryMessage(agentName3, snap) {
100085
100220
  `);
100086
100221
  }
100087
100222
  function loadQuotaWatchState(stateDir) {
100088
- const path3 = join63(stateDir, STATE_FILE2);
100089
- if (!existsSync52(path3))
100223
+ const path3 = join62(stateDir, STATE_FILE2);
100224
+ if (!existsSync53(path3))
100090
100225
  return emptyQuotaWatchState();
100091
100226
  try {
100092
- const raw = readFileSync54(path3, "utf-8");
100227
+ const raw = readFileSync55(path3, "utf-8");
100093
100228
  const parsed = JSON.parse(raw);
100094
100229
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
100095
100230
  return emptyQuotaWatchState();
@@ -100107,7 +100242,7 @@ function loadQuotaWatchState(stateDir) {
100107
100242
  }
100108
100243
  function saveQuotaWatchState(stateDir, state7) {
100109
100244
  mkdirSync45(stateDir, { recursive: true });
100110
- const path3 = join63(stateDir, STATE_FILE2);
100245
+ const path3 = join62(stateDir, STATE_FILE2);
100111
100246
  writeFileSync44(path3, JSON.stringify(state7, null, 2) + `
100112
100247
  `, { mode: 384 });
100113
100248
  }
@@ -100156,27 +100291,27 @@ init_auth_snapshot_format2();
100156
100291
  // gateway/turn-active-marker.ts
100157
100292
  import {
100158
100293
  closeSync as closeSync13,
100159
- existsSync as existsSync53,
100294
+ existsSync as existsSync54,
100160
100295
  mkdirSync as mkdirSync46,
100161
100296
  openSync as openSync13,
100162
- readFileSync as readFileSync55,
100297
+ readFileSync as readFileSync56,
100163
100298
  statSync as statSync20,
100164
100299
  unlinkSync as unlinkSync27,
100165
100300
  utimesSync as utimesSync2,
100166
100301
  writeFileSync as writeFileSync45
100167
100302
  } from "node:fs";
100168
- import { join as join64 } from "node:path";
100303
+ import { join as join63 } from "node:path";
100169
100304
  var TURN_ACTIVE_MARKER_FILE2 = "turn-active.json";
100170
100305
  var TURN_ACTIVE_HARD_TTL_MS2 = 10 * 60000;
100171
100306
  var TURN_ACTIVE_IDLE_SWEEP_MS = 60000;
100172
100307
  function removeTurnActiveMarker2(stateDir) {
100173
100308
  try {
100174
- unlinkSync27(join64(stateDir, TURN_ACTIVE_MARKER_FILE2));
100309
+ unlinkSync27(join63(stateDir, TURN_ACTIVE_MARKER_FILE2));
100175
100310
  } catch {}
100176
100311
  }
100177
100312
  function sweepStaleTurnActiveMarker(stateDir, opts) {
100178
- const path3 = join64(stateDir, TURN_ACTIVE_MARKER_FILE2);
100179
- if (!existsSync53(path3))
100313
+ const path3 = join63(stateDir, TURN_ACTIVE_MARKER_FILE2);
100314
+ if (!existsSync54(path3))
100180
100315
  return false;
100181
100316
  const now = opts.now ?? Date.now();
100182
100317
  try {
@@ -100188,7 +100323,7 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
100188
100323
  return false;
100189
100324
  let payload = null;
100190
100325
  try {
100191
- payload = readFileSync55(path3, "utf8");
100326
+ payload = readFileSync56(path3, "utf8");
100192
100327
  } catch {}
100193
100328
  unlinkSync27(path3);
100194
100329
  if (opts.onRemove) {
@@ -100206,7 +100341,7 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
100206
100341
  }
100207
100342
  }
100208
100343
  function readTurnActiveMarkerAgeMs2(stateDir, now) {
100209
- const path3 = join64(stateDir, TURN_ACTIVE_MARKER_FILE2);
100344
+ const path3 = join63(stateDir, TURN_ACTIVE_MARKER_FILE2);
100210
100345
  try {
100211
100346
  const st = statSync20(path3);
100212
100347
  return (now ?? Date.now()) - st.mtimeMs;
@@ -100220,11 +100355,11 @@ function effectiveTurnAgeMs(markerAgeMs, turnStartedAt, now) {
100220
100355
 
100221
100356
  // gateway/gateway-heartbeat.ts
100222
100357
  import { mkdirSync as mkdirSync47, utimesSync as utimesSync3, writeFileSync as writeFileSync46 } from "node:fs";
100223
- import { join as join65 } from "node:path";
100358
+ import { join as join64 } from "node:path";
100224
100359
  var GATEWAY_HEARTBEAT_FILE = "gateway-heartbeat";
100225
100360
  var GATEWAY_HEARTBEAT_INTERVAL_MS = 15000;
100226
100361
  function touchGatewayHeartbeat(stateDir) {
100227
- const path3 = join65(stateDir, GATEWAY_HEARTBEAT_FILE);
100362
+ const path3 = join64(stateDir, GATEWAY_HEARTBEAT_FILE);
100228
100363
  const now = new Date;
100229
100364
  try {
100230
100365
  utimesSync3(path3, now, now);
@@ -100250,12 +100385,12 @@ import {
100250
100385
  fsyncSync as fsyncSync5,
100251
100386
  mkdirSync as mkdirSync48,
100252
100387
  openSync as openSync14,
100253
- readFileSync as readFileSync56,
100388
+ readFileSync as readFileSync57,
100254
100389
  renameSync as renameSync25,
100255
100390
  unlinkSync as unlinkSync28,
100256
100391
  writeFileSync as writeFileSync47
100257
100392
  } from "node:fs";
100258
- import { join as join66 } from "node:path";
100393
+ import { join as join65 } from "node:path";
100259
100394
  var BOOT_BEACON_FILE = "gateway-beacon.json";
100260
100395
  var HOST_BOOT_ID_PATH = "/proc/sys/kernel/random/boot_id";
100261
100396
  var CGROUP_MEMORY_EVENTS_PATH = "/sys/fs/cgroup/memory.events";
@@ -100332,7 +100467,7 @@ function serializeBootBeacon(beacon) {
100332
100467
  }
100333
100468
  function readTextOrNull(path3) {
100334
100469
  try {
100335
- return readFileSync56(path3, "utf-8");
100470
+ return readFileSync57(path3, "utf-8");
100336
100471
  } catch {
100337
100472
  return null;
100338
100473
  }
@@ -100354,7 +100489,7 @@ function sampleBeaconHost(paths = {}) {
100354
100489
  return sample3;
100355
100490
  }
100356
100491
  function writeBootBeaconFile(stateDir, beacon) {
100357
- const path3 = join66(stateDir, BOOT_BEACON_FILE);
100492
+ const path3 = join65(stateDir, BOOT_BEACON_FILE);
100358
100493
  const tmp = `${path3}.tmp-${process.pid}`;
100359
100494
  let fd;
100360
100495
  try {
@@ -100731,10 +100866,10 @@ function startOutboxSweep(deps) {
100731
100866
  }
100732
100867
 
100733
100868
  // ../src/build-info.ts
100734
- var VERSION2 = "0.19.43";
100735
- var COMMIT_SHA = "4aaf442f";
100736
- var COMMIT_DATE = "2026-08-01T10:38:38Z";
100737
- var LATEST_PR = 4159;
100869
+ var VERSION2 = "0.19.44";
100870
+ var COMMIT_SHA = "82d3b0b2";
100871
+ var COMMIT_DATE = "2026-08-01T23:02:10Z";
100872
+ var LATEST_PR = 4186;
100738
100873
  var COMMITS_AHEAD_OF_TAG = 0;
100739
100874
 
100740
100875
  // gateway/boot-version.ts
@@ -100812,11 +100947,11 @@ init_peercred();
100812
100947
  import * as net5 from "node:net";
100813
100948
  import * as fs3 from "node:fs";
100814
100949
  import { homedir as homedir19 } from "node:os";
100815
- import { join as join67 } from "node:path";
100950
+ import { join as join66 } from "node:path";
100816
100951
  var DEFAULT_TIMEOUT_MS4 = 2000;
100817
100952
  var UNLOCK_TIMEOUT_MS = 30000;
100818
- var LEGACY_SOCKET_PATH2 = join67(homedir19(), ".switchroom", "vault-broker.sock");
100819
- var OPERATOR_SOCKET_PATH2 = join67(homedir19(), ".switchroom", "broker-operator", "sock");
100953
+ var LEGACY_SOCKET_PATH2 = join66(homedir19(), ".switchroom", "vault-broker.sock");
100954
+ var OPERATOR_SOCKET_PATH2 = join66(homedir19(), ".switchroom", "broker-operator", "sock");
100820
100955
  function defaultBrokerSocketPath2() {
100821
100956
  if (fs3.existsSync(OPERATOR_SOCKET_PATH2))
100822
100957
  return OPERATOR_SOCKET_PATH2;
@@ -101699,7 +101834,7 @@ function resolveVaultApprovalPosture(broker) {
101699
101834
 
101700
101835
  // registry/turns-schema.ts
101701
101836
  import { chmodSync as chmodSync12, mkdirSync as mkdirSync49 } from "fs";
101702
- import { join as join68 } from "path";
101837
+ import { join as join67 } from "path";
101703
101838
  var DatabaseClass3 = null;
101704
101839
  function loadDatabaseClass3() {
101705
101840
  if (DatabaseClass3 != null)
@@ -101771,9 +101906,9 @@ function applySchema(db3) {
101771
101906
  }
101772
101907
  function openTurnsDb(agentDir) {
101773
101908
  const Database = loadDatabaseClass3();
101774
- const dir = join68(agentDir, "telegram");
101909
+ const dir = join67(agentDir, "telegram");
101775
101910
  mkdirSync49(dir, { recursive: true, mode: 448 });
101776
- const path3 = join68(dir, "registry.db");
101911
+ const path3 = join67(dir, "registry.db");
101777
101912
  const db3 = new Database(path3, { create: true });
101778
101913
  applySchema(db3);
101779
101914
  try {
@@ -102118,7 +102253,7 @@ function selectResumeBuilder(endedVia, opts) {
102118
102253
  }
102119
102254
 
102120
102255
  // gateway/bridge-dead-watchdog.ts
102121
- import { readFileSync as readFileSync58, writeFileSync as writeFileSync48, renameSync as renameSync26, unlinkSync as unlinkSync29 } from "node:fs";
102256
+ import { readFileSync as readFileSync59, writeFileSync as writeFileSync48, renameSync as renameSync26, unlinkSync as unlinkSync29 } from "node:fs";
102122
102257
 
102123
102258
  // gateway/cron-session.ts
102124
102259
  var CRON_IDENTITY_SUFFIX2 = "-cron";
@@ -102151,7 +102286,7 @@ function readFreshCrashLogTail(path3, opts = {}) {
102151
102286
  const nowMs3 = opts.nowMs ?? Date.now();
102152
102287
  const freshWindowMs = opts.freshWindowMs ?? CRASH_LOG_FRESH_WINDOW_MS;
102153
102288
  const maxLines = opts.maxLines ?? CRASH_LOG_TAIL_LINES;
102154
- const readFile = opts.readFile ?? ((p) => readFileSync58(p, "utf8"));
102289
+ const readFile = opts.readFile ?? ((p) => readFileSync59(p, "utf8"));
102155
102290
  let raw;
102156
102291
  try {
102157
102292
  raw = readFile(path3);
@@ -102178,7 +102313,7 @@ function writeBridgeDeadEscalationMarker(path3, marker) {
102178
102313
  function consumeBridgeDeadEscalationMarker(path3, nowMs3 = Date.now(), maxAgeMs = ESCALATION_MARKER_MAX_AGE_MS) {
102179
102314
  let marker = null;
102180
102315
  try {
102181
- const parsed = JSON.parse(readFileSync58(path3, "utf8"));
102316
+ const parsed = JSON.parse(readFileSync59(path3, "utf8"));
102182
102317
  if (typeof parsed.ts === "number" && Number.isFinite(parsed.ts) && typeof parsed.reason === "string") {
102183
102318
  const age = nowMs3 - parsed.ts;
102184
102319
  if (age >= 0 && age < maxAgeMs) {
@@ -102331,7 +102466,7 @@ function createBridgeDeadWatchdog(opts) {
102331
102466
  }
102332
102467
 
102333
102468
  // gateway/boot-probes.ts
102334
- import { readFileSync as readFileSync59, readdirSync as readdirSync14, existsSync as existsSync55 } from "fs";
102469
+ import { readFileSync as readFileSync60, readdirSync as readdirSync14, existsSync as existsSync56 } from "fs";
102335
102470
  init_quota_cache();
102336
102471
  init_generation_stamp();
102337
102472
  init_quota_check();
@@ -102340,7 +102475,7 @@ import { promisify as promisify2 } from "util";
102340
102475
  var execFile2 = promisify2(execFileCb2);
102341
102476
  var realProcFs2 = {
102342
102477
  readdir: (p) => readdirSync14(p),
102343
- readFile: (p) => readFileSync59(p, "utf-8")
102478
+ readFile: (p) => readFileSync60(p, "utf-8")
102344
102479
  };
102345
102480
  function findAgentProcessInContainer2(fs4 = realProcFs2) {
102346
102481
  let entries;
@@ -102590,7 +102725,7 @@ if (isGatewayMain) {
102590
102725
  shutdownAnalytics();
102591
102726
  });
102592
102727
  }
102593
- var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join69(homedir20(), ".claude", "channels", "telegram");
102728
+ var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join68(homedir20(), ".claude", "channels", "telegram");
102594
102729
  var permCardStore = createPermissionCardStore(STATE_DIR);
102595
102730
  var BLOCKED_APPROVALS_DIR = process.env.SWITCHROOM_BLOCKED_APPROVALS_DIR ?? "/state/blocked-approvals";
102596
102731
  var AGENT_NAME = process.env.SWITCHROOM_AGENT_NAME ?? "agent";
@@ -102629,7 +102764,7 @@ function alwaysAllowDrainDeps() {
102629
102764
  return {
102630
102765
  readConfigText: () => {
102631
102766
  const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
102632
- return readFileSync60(cfgPath, "utf8");
102767
+ return readFileSync61(cfgPath, "utf8");
102633
102768
  },
102634
102769
  resolveAllowList: (_configText, agentName3) => {
102635
102770
  const cfg = loadConfig2();
@@ -102690,11 +102825,11 @@ function scheduleAlwaysAllowPersistDrain() {
102690
102825
  }, ALWAYS_ALLOW_DRAIN_INTERVAL_MS);
102691
102826
  timer3.unref?.();
102692
102827
  }
102693
- var ACCESS_FILE = join69(STATE_DIR, "access.json");
102694
- var APPROVED_DIR = join69(STATE_DIR, "approved");
102695
- var ENV_FILE = join69(STATE_DIR, ".env");
102696
- var INBOX_DIR = join69(STATE_DIR, "inbox");
102697
- var PEOPLE_FILE = join69(STATE_DIR, "people.json");
102828
+ var ACCESS_FILE = join68(STATE_DIR, "access.json");
102829
+ var APPROVED_DIR = join68(STATE_DIR, "approved");
102830
+ var ENV_FILE = join68(STATE_DIR, ".env");
102831
+ var INBOX_DIR = join68(STATE_DIR, "inbox");
102832
+ var PEOPLE_FILE = join68(STATE_DIR, "people.json");
102698
102833
  function triggerSelfRestart(targetAgent, reason, delayMs = 300) {
102699
102834
  const isDocker = process.env.SWITCHROOM_RUNTIME === "docker";
102700
102835
  const selfAgent = process.env.SWITCHROOM_AGENT_NAME;
@@ -102759,7 +102894,7 @@ function formatBootVersion() {
102759
102894
  }
102760
102895
  try {
102761
102896
  chmodSync14(ENV_FILE, 384);
102762
- for (const line of readFileSync60(ENV_FILE, "utf8").split(`
102897
+ for (const line of readFileSync61(ENV_FILE, "utf8").split(`
102763
102898
  `)) {
102764
102899
  const m = line.match(/^(\w+)=(.*)$/);
102765
102900
  if (m && process.env[m[1]] === undefined)
@@ -102780,7 +102915,7 @@ var bot;
102780
102915
  var lastGetUpdatesHeartbeatMs = Date.now();
102781
102916
  var GRAMMY_VERSION = (() => {
102782
102917
  try {
102783
- const raw = readFileSync60(new URL("../../node_modules/grammy/package.json", import.meta.url), "utf8");
102918
+ const raw = readFileSync61(new URL("../../node_modules/grammy/package.json", import.meta.url), "utf8");
102784
102919
  return JSON.parse(raw).version ?? "unknown";
102785
102920
  } catch {
102786
102921
  return "unknown";
@@ -102819,12 +102954,12 @@ function assertSendable(f) {
102819
102954
  }
102820
102955
  let real, stateReal;
102821
102956
  try {
102822
- real = realpathSync4(f);
102823
- stateReal = realpathSync4(STATE_DIR);
102957
+ real = realpathSync5(f);
102958
+ stateReal = realpathSync5(STATE_DIR);
102824
102959
  } catch {
102825
102960
  throw new Error(`refusing to send file \u2014 cannot resolve real path: ${f}`);
102826
102961
  }
102827
- const inbox = join69(stateReal, "inbox");
102962
+ const inbox = join68(stateReal, "inbox");
102828
102963
  if (real.startsWith(stateReal + sep4) && !real.startsWith(inbox + sep4)) {
102829
102964
  throw new Error(`refusing to send channel state: ${f}`);
102830
102965
  }
@@ -102843,7 +102978,7 @@ function assertSendable(f) {
102843
102978
  }
102844
102979
  function readAccessFile() {
102845
102980
  try {
102846
- const raw = readFileSync60(ACCESS_FILE, "utf8");
102981
+ const raw = readFileSync61(ACCESS_FILE, "utf8");
102847
102982
  const parsed = JSON.parse(raw);
102848
102983
  const allowFrom = validateStringArray("allowFrom", parsed.allowFrom ?? []);
102849
102984
  const groups = {};
@@ -102905,7 +103040,7 @@ function loadAccess() {
102905
103040
  }
102906
103041
  function readPeopleFile() {
102907
103042
  try {
102908
- const raw = readFileSync60(PEOPLE_FILE, "utf8");
103043
+ const raw = readFileSync61(PEOPLE_FILE, "utf8");
102909
103044
  const parsed = JSON.parse(raw);
102910
103045
  if (!Array.isArray(parsed.entries))
102911
103046
  return [];
@@ -102949,7 +103084,7 @@ var HISTORY_ENABLED = HISTORY_ACCESS.historyEnabled !== false;
102949
103084
  if (isGatewayMain && HISTORY_ENABLED) {
102950
103085
  try {
102951
103086
  initHistory(STATE_DIR, HISTORY_ACCESS.historyRetentionDays ?? 30);
102952
- process.stderr.write(`telegram gateway: history capture enabled at ${join69(STATE_DIR, "history.db")}
103087
+ process.stderr.write(`telegram gateway: history capture enabled at ${join68(STATE_DIR, "history.db")}
102953
103088
  `);
102954
103089
  } catch (err) {
102955
103090
  process.stderr.write(`telegram gateway: history init failed (${err.message}) \u2014 capture disabled
@@ -102968,12 +103103,12 @@ if (isGatewayMain)
102968
103103
  let markerTurnKey = null;
102969
103104
  let markerAgeMs = null;
102970
103105
  try {
102971
- const markerPath = join69(STATE_DIR, TURN_ACTIVE_MARKER_FILE2);
102972
- if (existsSync57(markerPath)) {
103106
+ const markerPath = join68(STATE_DIR, TURN_ACTIVE_MARKER_FILE2);
103107
+ if (existsSync58(markerPath)) {
102973
103108
  const st = statSync23(markerPath);
102974
103109
  markerAgeMs = Date.now() - st.mtimeMs;
102975
103110
  try {
102976
- const payload = JSON.parse(readFileSync60(markerPath, "utf8"));
103111
+ const payload = JSON.parse(readFileSync61(markerPath, "utf8"));
102977
103112
  if (typeof payload.turnKey === "string" && payload.turnKey.length > 0) {
102978
103113
  markerTurnKey = payload.turnKey;
102979
103114
  }
@@ -102993,10 +103128,10 @@ if (isGatewayMain)
102993
103128
  process.stderr.write(`telegram gateway: turn-registry boot-reaper stamped ${reaped} orphaned turn(s)` + `${timeoutTurnKey ? ` (turnKey=${timeoutTurnKey} as 'timeout', markerAgeMs=${markerAgeMs})` : " as 'restart'"}
102994
103129
  `);
102995
103130
  } else {
102996
- process.stderr.write(`telegram gateway: turn-registry initialized at ${join69(agentDir, "telegram", "registry.db")}
103131
+ process.stderr.write(`telegram gateway: turn-registry initialized at ${join68(agentDir, "telegram", "registry.db")}
102997
103132
  `);
102998
103133
  }
102999
- const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(join69(STATE_DIR, "bridge-dead-escalation.json"));
103134
+ const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(join68(STATE_DIR, "bridge-dead-escalation.json"));
103000
103135
  if (bridgeDeadMarker != null) {
103001
103136
  bridgeDeadPriorStreak = bridgeDeadMarker.count ?? 1;
103002
103137
  process.stderr.write(`telegram gateway: boot: prior restart was a bridge-dead escalation (reason=${bridgeDeadMarker.reason}` + `, consecutive=${bridgeDeadPriorStreak}` + `${bridgeDeadMarker.crashTail ? `, crashTail=${bridgeDeadMarker.crashTail}` : ""})
@@ -103009,7 +103144,7 @@ if (isGatewayMain)
103009
103144
  const pending2 = findLatestTurnIfInterrupted(turnsDb);
103010
103145
  const selfAgent = process.env.SWITCHROOM_AGENT_NAME ?? "";
103011
103146
  if (pending2 != null && selfAgent) {
103012
- const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join69(STATE_DIR, "clean-shutdown.json");
103147
+ const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join68(STATE_DIR, "clean-shutdown.json");
103013
103148
  const bootResumeCleanMarker = readCleanShutdownMarker(bootResumeMarkerPath);
103014
103149
  const bootResumeForceAlways = process.env.SWITCHROOM_BOOT_RESUME_ALWAYS === "1";
103015
103150
  const bootResumeMode = parseBootResumeMode(process.env.SWITCHROOM_BOOT_RESUME);
@@ -103122,7 +103257,7 @@ if (isGatewayMain)
103122
103257
  `);
103123
103258
  }
103124
103259
  }
103125
- const pendingEnvPath = join69(agentDir, ".pending-turn.env");
103260
+ const pendingEnvPath = join68(agentDir, ".pending-turn.env");
103126
103261
  try {
103127
103262
  if (pending2 != null) {
103128
103263
  const lines = [
@@ -103142,7 +103277,7 @@ if (isGatewayMain)
103142
103277
  renameSync27(pendingEnvTmp, pendingEnvPath);
103143
103278
  process.stderr.write(`telegram gateway: pending-turn env written to ${pendingEnvPath} turnKey=${pending2.turn_key} endedVia=${pending2.ended_via ?? "open"}
103144
103279
  `);
103145
- } else if (existsSync57(pendingEnvPath)) {
103280
+ } else if (existsSync58(pendingEnvPath)) {
103146
103281
  rmSync8(pendingEnvPath, { force: true });
103147
103282
  process.stderr.write(`telegram gateway: pending-turn env cleared (clean previous shutdown)
103148
103283
  `);
@@ -103250,7 +103385,7 @@ function checkApprovals() {
103250
103385
  return;
103251
103386
  }
103252
103387
  for (const senderId of files) {
103253
- const file = join69(APPROVED_DIR, senderId);
103388
+ const file = join68(APPROVED_DIR, senderId);
103254
103389
  bot.api.sendMessage(senderId, "Paired! Say hi to Claude.").then(() => rmSync8(file, { force: true }), (err) => {
103255
103390
  process.stderr.write(`telegram gateway: failed to send approval confirm: ${err}
103256
103391
  `);
@@ -103425,12 +103560,12 @@ function noteAgentOutputAt(key, ts) {
103425
103560
  lastAgentOutputAt.delete(oldest);
103426
103561
  }
103427
103562
  }
103428
- var OBLIGATION_STORE_PATH = join69(STATE_DIR, "obligations.json");
103563
+ var OBLIGATION_STORE_PATH = join68(STATE_DIR, "obligations.json");
103429
103564
  var obligationStoreFs = {
103430
- readFileSync: (p) => readFileSync60(p, "utf8"),
103565
+ readFileSync: (p) => readFileSync61(p, "utf8"),
103431
103566
  writeFileSync: (p, d) => writeFileSync50(p, d),
103432
103567
  renameSync: (a, b) => renameSync27(a, b),
103433
- existsSync: (p) => existsSync57(p),
103568
+ existsSync: (p) => existsSync58(p),
103434
103569
  fsyncFileSync: fsyncPathSync,
103435
103570
  fsyncDirSync: fsyncPathSync,
103436
103571
  unlinkSync: unlinkSync31
@@ -105773,28 +105908,28 @@ var PIN_STATUS_WHILE_WORKING = (() => {
105773
105908
  })();
105774
105909
  var statusPinClaims = new Map;
105775
105910
  var statusPinRightsCache = new PinRightsCache2;
105776
- var STATUS_PIN_STORE_PATH = join69(STATE_DIR, "status-pins.json");
105911
+ var STATUS_PIN_STORE_PATH = join68(STATE_DIR, "status-pins.json");
105777
105912
  var statusPinStoreFs = {
105778
- readFileSync: (p) => readFileSync60(p, "utf8"),
105913
+ readFileSync: (p) => readFileSync61(p, "utf8"),
105779
105914
  writeFileSync: (p, d) => writeFileSync50(p, d),
105780
105915
  renameSync: (a, b) => renameSync27(a, b),
105781
- existsSync: (p) => existsSync57(p)
105916
+ existsSync: (p) => existsSync58(p)
105782
105917
  };
105783
105918
  var statusPinPersistEnabled = !STATIC && PIN_STATUS_WHILE_WORKING;
105784
- var ACTIVITY_CARD_STORE_PATH = join69(STATE_DIR, "activity-cards-pending.json");
105919
+ var ACTIVITY_CARD_STORE_PATH = join68(STATE_DIR, "activity-cards-pending.json");
105785
105920
  var activityCardStoreFs = {
105786
- readFileSync: (p) => readFileSync60(p, "utf8"),
105921
+ readFileSync: (p) => readFileSync61(p, "utf8"),
105787
105922
  writeFileSync: (p, d) => writeFileSync50(p, d),
105788
105923
  renameSync: (a, b) => renameSync27(a, b),
105789
- existsSync: (p) => existsSync57(p)
105924
+ existsSync: (p) => existsSync58(p)
105790
105925
  };
105791
105926
  var activityCardPersistEnabled = !STATIC;
105792
- var QUEUED_CARD_STORE_PATH = join69(STATE_DIR, "queued-cards-pending.json");
105927
+ var QUEUED_CARD_STORE_PATH = join68(STATE_DIR, "queued-cards-pending.json");
105793
105928
  var queuedCardStoreFs = {
105794
- readFileSync: (p) => readFileSync60(p, "utf8"),
105929
+ readFileSync: (p) => readFileSync61(p, "utf8"),
105795
105930
  writeFileSync: (p, d) => writeFileSync50(p, d),
105796
105931
  renameSync: (a, b) => renameSync27(a, b),
105797
- existsSync: (p) => existsSync57(p)
105932
+ existsSync: (p) => existsSync58(p)
105798
105933
  };
105799
105934
  var queuedCardPersistEnabled = !STATIC;
105800
105935
  function persistQueuedCard(key, chatId, threadId, messageId) {
@@ -106081,7 +106216,7 @@ async function unpinAllStatusPins() {
106081
106216
  }
106082
106217
  }
106083
106218
  var stalePinSweepEligible = false;
106084
- var STALE_PIN_SWEEP_STORE_PATH = join69(STATE_DIR, "stale-pin-sweep.json");
106219
+ var STALE_PIN_SWEEP_STORE_PATH = join68(STATE_DIR, "stale-pin-sweep.json");
106085
106220
  var stalePinSweeper = createGatewayStalePinSweeper({
106086
106221
  telegram: { handle: () => lockedBot, call: robustApiCall },
106087
106222
  claims: () => statusPinClaims.values(),
@@ -106090,9 +106225,9 @@ var stalePinSweeper = createGatewayStalePinSweeper({
106090
106225
  store: {
106091
106226
  path: STALE_PIN_SWEEP_STORE_PATH,
106092
106227
  fs: {
106093
- readFileSync: (p) => readFileSync60(p, "utf-8"),
106228
+ readFileSync: (p) => readFileSync61(p, "utf-8"),
106094
106229
  writeFileSync: (p, data) => atomicWriteFileSync(p, data, 384),
106095
- existsSync: (p) => existsSync57(p)
106230
+ existsSync: (p) => existsSync58(p)
106096
106231
  }
106097
106232
  },
106098
106233
  allowUnpinAllForumTopic: process.env.SWITCHROOM_PIN_SWEEP_UNPIN_ALL_TOPIC == null ? undefined : process.env.SWITCHROOM_PIN_SWEEP_UNPIN_ALL_TOPIC === "1"
@@ -106122,12 +106257,12 @@ var getPinnedProgressCardMessageId = null;
106122
106257
  var completeProgressCardTurn = null;
106123
106258
  var subagentWatcher = null;
106124
106259
  var workerActivityFeed = null;
106125
- var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join69(STATE_DIR, "gateway.sock");
106260
+ var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join68(STATE_DIR, "gateway.sock");
106126
106261
  if (isGatewayMain)
106127
106262
  mkdirSync51(STATE_DIR, { recursive: true, mode: 448 });
106128
- var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ?? join69(STATE_DIR, "gateway.pid.json");
106129
- var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ?? join69(STATE_DIR, "gateway-session.json");
106130
- var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join69(STATE_DIR, "clean-shutdown.json");
106263
+ var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ?? join68(STATE_DIR, "gateway.pid.json");
106264
+ var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ?? join68(STATE_DIR, "gateway-session.json");
106265
+ var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join68(STATE_DIR, "clean-shutdown.json");
106131
106266
  var GATEWAY_STARTED_AT_MS = Date.now();
106132
106267
  var BOOT_CARD_ENABLED = process.env.SWITCHROOM_BOOT_CARD !== "false";
106133
106268
  var activeBootCard = null;
@@ -106156,7 +106291,7 @@ function ensureIssuesCard(chatId, threadId) {
106156
106291
  bot: botApi,
106157
106292
  log: (msg) => process.stderr.write(`telegram gateway: ${msg}
106158
106293
  `),
106159
- persistPath: join69(stateDir, "issues-card.json")
106294
+ persistPath: join68(stateDir, "issues-card.json")
106160
106295
  });
106161
106296
  activeIssuesWatcher = startIssuesWatcher({
106162
106297
  stateDir,
@@ -106361,13 +106496,13 @@ if (isGatewayMain)
106361
106496
  var inboundSpool;
106362
106497
  if (isGatewayMain)
106363
106498
  inboundSpool = STATIC ? undefined : createInboundSpool({
106364
- path: join69(STATE_DIR, "inbound-spool.jsonl"),
106499
+ path: join68(STATE_DIR, "inbound-spool.jsonl"),
106365
106500
  fs: {
106366
106501
  appendFileSync: (p, d) => appendFileSync9(p, d),
106367
- readFileSync: (p) => readFileSync60(p, "utf8"),
106502
+ readFileSync: (p) => readFileSync61(p, "utf8"),
106368
106503
  writeFileSync: (p, d) => writeFileSync50(p, d),
106369
106504
  renameSync: (a, b) => renameSync27(a, b),
106370
- existsSync: (p) => existsSync57(p),
106505
+ existsSync: (p) => existsSync58(p),
106371
106506
  statSizeSync: (p) => statSync23(p).size,
106372
106507
  fsyncFileSync: fsyncPathSync,
106373
106508
  fsyncDirSync: fsyncPathSync
@@ -106431,13 +106566,13 @@ async function maybeRedeliverUndeliveredAnswer() {
106431
106566
  let transcriptText;
106432
106567
  try {
106433
106568
  const projectsDir = getProjectsDirForCwd();
106434
- const path3 = join69(projectsDir, `${sessionId}.jsonl`);
106435
- if (!existsSync57(path3)) {
106569
+ const path3 = join68(projectsDir, `${sessionId}.jsonl`);
106570
+ if (!existsSync58(path3)) {
106436
106571
  process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript not found for turnKey=${turn.turn_key} session=${sessionId} (${path3}); skipping
106437
106572
  `);
106438
106573
  return;
106439
106574
  }
106440
- transcriptText = readFileSync60(path3, "utf8");
106575
+ transcriptText = readFileSync61(path3, "utf8");
106441
106576
  } catch (err) {
106442
106577
  process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript read failed turnKey=${turn.turn_key}: ${err.message}
106443
106578
  `);
@@ -106596,8 +106731,8 @@ var bridgeDeadWatchdog = createBridgeDeadWatchdog({
106596
106731
  isSessionAlive: () => findAgentProcessInContainer2()?.comm === "claude",
106597
106732
  isShuttingDown: () => shuttingDown,
106598
106733
  escalate: (reason) => triggerSelfRestart(process.env.SWITCHROOM_AGENT_NAME ?? "", reason, 1500),
106599
- crashLogPath: join69(STATE_DIR, "bridge-crash.log"),
106600
- markerPath: join69(STATE_DIR, "bridge-dead-escalation.json"),
106734
+ crashLogPath: join68(STATE_DIR, "bridge-crash.log"),
106735
+ markerPath: join68(STATE_DIR, "bridge-dead-escalation.json"),
106601
106736
  log: (line) => process.stderr.write(`${line}
106602
106737
  `),
106603
106738
  priorStreak: bridgeDeadPriorStreak,
@@ -106703,8 +106838,8 @@ if (isGatewayMain)
106703
106838
  probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
106704
106839
  tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
106705
106840
  dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
106706
- configSnapshotPath: join69(resolvedAgentDirForCard, ".config-snapshot.json"),
106707
- bootCardStatePath: join69(resolvedAgentDirForCard, ".boot-card-msgid.json"),
106841
+ configSnapshotPath: join68(resolvedAgentDirForCard, ".config-snapshot.json"),
106842
+ bootCardStatePath: join68(resolvedAgentDirForCard, ".boot-card-msgid.json"),
106708
106843
  floodStatePath: FLOOD_STATE_PATH,
106709
106844
  ...updateOutcomeLine ? { updateOutcomeLine } : {}
106710
106845
  }, ackMsgId).then((handle) => {
@@ -107371,7 +107506,7 @@ if (isGatewayMain)
107371
107506
  const receiverUid = receiverUidRaw ? Number(receiverUidRaw) : NaN;
107372
107507
  if (Number.isInteger(receiverUid))
107373
107508
  allowedUids.push(receiverUid);
107374
- const socketPath = join69(STATE_DIR, "webhook.sock");
107509
+ const socketPath = join68(STATE_DIR, "webhook.sock");
107375
107510
  const webhookInject = (agentName3, inbound) => {
107376
107511
  const msg = inbound;
107377
107512
  const delivered = ipcServer.sendToAgent(agentName3, msg);
@@ -107622,9 +107757,9 @@ function redactOutboundText(text5, site) {
107622
107757
  var VOICE_OUT_DEFAULT_CHUNK_CHARS = 600;
107623
107758
  var VOICE_OUT_HARD_CHUNK_CAP = 4096;
107624
107759
  var voiceOnDemandCache = new VoiceOnDemandCache({
107625
- persistPath: join69(STATE_DIR, "voice-ondemand.json")
107760
+ persistPath: join68(STATE_DIR, "voice-ondemand.json")
107626
107761
  });
107627
- var VOICE_CACHE_DIR = join69(STATE_DIR, "voice-cache");
107762
+ var VOICE_CACHE_DIR = join68(STATE_DIR, "voice-cache");
107628
107763
  var voicePreSynthQueue = new PreSynthQueue({
107629
107764
  runJob: async (job) => {
107630
107765
  const sidecarToken = await materializeSidecarToken2();
@@ -108026,11 +108161,11 @@ async function executeSendGif(rawArgs) {
108026
108161
  };
108027
108162
  }
108028
108163
  async function publishToTelegraph(text5, shortName, authorName) {
108029
- const accountPath = join69(STATE_DIR, "telegraph-account.json");
108164
+ const accountPath = join68(STATE_DIR, "telegraph-account.json");
108030
108165
  let account = null;
108031
108166
  try {
108032
- if (existsSync57(accountPath)) {
108033
- const raw = readFileSync60(accountPath, "utf-8");
108167
+ if (existsSync58(accountPath)) {
108168
+ const raw = readFileSync61(accountPath, "utf-8");
108034
108169
  const parsed = JSON.parse(raw);
108035
108170
  if (parsed.shortName && parsed.accessToken) {
108036
108171
  account = parsed;
@@ -108166,7 +108301,7 @@ _The secret was NOT saved. The agent can re-request with \`request_secret\`._`,
108166
108301
  }
108167
108302
  function readLiveSwitchroomConfigText() {
108168
108303
  const cfgPath = process.env.SWITCHROOM_CONFIG ?? findConfigFile2();
108169
- return readFileSync60(cfgPath, "utf8");
108304
+ return readFileSync61(cfgPath, "utf8");
108170
108305
  }
108171
108306
  async function executeReact(args) {
108172
108307
  if (!args.chat_id)
@@ -109579,7 +109714,7 @@ function restartMarkerPath() {
109579
109714
  const agentDir = resolveAgentDirFromEnv();
109580
109715
  if (!agentDir)
109581
109716
  return null;
109582
- return join69(agentDir, "restart-pending.json");
109717
+ return join68(agentDir, "restart-pending.json");
109583
109718
  }
109584
109719
  function writeRestartMarker(marker) {
109585
109720
  const p = restartMarkerPath();
@@ -109605,7 +109740,7 @@ function readRestartMarker() {
109605
109740
  if (!p)
109606
109741
  return null;
109607
109742
  try {
109608
- return JSON.parse(readFileSync60(p, "utf8"));
109743
+ return JSON.parse(readFileSync61(p, "utf8"));
109609
109744
  } catch {
109610
109745
  return null;
109611
109746
  }
@@ -109754,7 +109889,7 @@ var _dockerReachable;
109754
109889
  function isDockerReachable() {
109755
109890
  if (_dockerReachable !== undefined)
109756
109891
  return _dockerReachable;
109757
- if (!existsSync57("/var/run/docker.sock")) {
109892
+ if (!existsSync58("/var/run/docker.sock")) {
109758
109893
  _dockerReachable = false;
109759
109894
  return _dockerReachable;
109760
109895
  }
@@ -109771,7 +109906,7 @@ function _resetDockerReachableCache() {
109771
109906
  }
109772
109907
  function spawnSwitchroomDetached(args, onFailure) {
109773
109908
  const fullArgs = SWITCHROOM_CONFIG ? ["--config", SWITCHROOM_CONFIG, ...args] : args;
109774
- const logPath = join69(STATE_DIR, "detached-spawn.log");
109909
+ const logPath = join68(STATE_DIR, "detached-spawn.log");
109775
109910
  let outFd = null;
109776
109911
  try {
109777
109912
  mkdirSync51(STATE_DIR, { recursive: true });
@@ -109802,7 +109937,7 @@ function spawnSwitchroomDetached(args, onFailure) {
109802
109937
  return;
109803
109938
  let tail = "";
109804
109939
  try {
109805
- const full = readFileSync60(logPath, "utf8");
109940
+ const full = readFileSync61(logPath, "utf8");
109806
109941
  tail = full.split(`
109807
109942
  `).slice(-30).join(`
109808
109943
  `).trim();
@@ -110064,10 +110199,10 @@ ${preBlock(formatSwitchroomOutput(detail))}`, { html: true });
110064
110199
  }
110065
110200
  function readRecentDenialsForAgent(agentName3, windowMs, limit) {
110066
110201
  try {
110067
- const auditPath = join69(homedir20(), ".switchroom", "vault-audit.log");
110068
- if (!existsSync57(auditPath))
110202
+ const auditPath = join68(homedir20(), ".switchroom", "vault-audit.log");
110203
+ if (!existsSync58(auditPath))
110069
110204
  return [];
110070
- const raw = readFileSync60(auditPath, "utf8");
110205
+ const raw = readFileSync61(auditPath, "utf8");
110071
110206
  return recentDenialsFromAuditLog(raw, { agentName: agentName3, windowMs, limit });
110072
110207
  } catch {
110073
110208
  return [];
@@ -110118,7 +110253,7 @@ async function buildAgentMetadata(agentName3) {
110118
110253
  try {
110119
110254
  const agentDir = resolveAgentDirFromEnv();
110120
110255
  if (agentDir) {
110121
- const raw = readFileSync60(join69(agentDir, ".claude", ".claude.json"), "utf8");
110256
+ const raw = readFileSync61(join68(agentDir, ".claude", ".claude.json"), "utf8");
110122
110257
  claudeJson = JSON.parse(raw);
110123
110258
  }
110124
110259
  } catch {}
@@ -110247,7 +110382,7 @@ function buildModelDeps(restartCtx) {
110247
110382
  try {
110248
110383
  const agentDir = resolveAgentDirFromEnv();
110249
110384
  if (agentDir) {
110250
- const local = await fetchQuota2({ claudeConfigDir: join69(agentDir, ".claude") });
110385
+ const local = await fetchQuota2({ claudeConfigDir: join68(agentDir, ".claude") });
110251
110386
  if (local.ok)
110252
110387
  return formatQuotaLine2(local.data);
110253
110388
  }
@@ -110494,9 +110629,9 @@ function effortMenuReplyMarkup(reply) {
110494
110629
  function flushAgentHandoff(agentDir) {
110495
110630
  let removed = 0;
110496
110631
  for (const fname of [".handoff.md", ".handoff-topic"]) {
110497
- const p = join69(agentDir, fname);
110632
+ const p = join68(agentDir, fname);
110498
110633
  try {
110499
- if (existsSync57(p)) {
110634
+ if (existsSync58(p)) {
110500
110635
  unlinkSync31(p);
110501
110636
  removed++;
110502
110637
  }
@@ -110552,7 +110687,7 @@ async function handleNewCommand(ctx) {
110552
110687
  writeRestartMarker({ chat_id: chatId, thread_id: threadId ?? null, ack_message_id: ackId, ts: Date.now() });
110553
110688
  if (agentDir != null) {
110554
110689
  try {
110555
- writeFileSync50(join69(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
110690
+ writeFileSync50(join68(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
110556
110691
  `, "utf8");
110557
110692
  } catch (err) {
110558
110693
  process.stderr.write(`telegram gateway: failed to write force-fresh marker: ${err}
@@ -110665,16 +110800,16 @@ function buildFolderPickerDeps() {
110665
110800
  };
110666
110801
  }
110667
110802
  var lockoutOps = {
110668
- readFileSync: (p, enc) => readFileSync60(p, enc),
110803
+ readFileSync: (p, enc) => readFileSync61(p, enc),
110669
110804
  writeFileSync: (p, data, opts) => writeFileSync50(p, data, opts),
110670
- existsSync: (p) => existsSync57(p),
110805
+ existsSync: (p) => existsSync58(p),
110671
110806
  mkdirSync: (p, opts) => mkdirSync51(p, opts),
110672
- joinPath: (...parts) => join69(...parts)
110807
+ joinPath: (...parts) => join68(...parts)
110673
110808
  };
110674
110809
  var FLEET_FALLBACK_DEDUP_MS = 30000;
110675
110810
  function isAuthBrokerSocketReachable() {
110676
110811
  try {
110677
- return existsSync57(resolveAuthBrokerSocketPath2());
110812
+ return existsSync58(resolveAuthBrokerSocketPath2());
110678
110813
  } catch {
110679
110814
  return false;
110680
110815
  }
@@ -110929,7 +111064,7 @@ async function runCreditWatch() {
110929
111064
  if (!agentDir)
110930
111065
  return;
110931
111066
  const agentName3 = getMyAgentName();
110932
- const claudeConfigDir = join69(agentDir, ".claude");
111067
+ const claudeConfigDir = join68(agentDir, ".claude");
110933
111068
  const stateDir = STATE_DIR;
110934
111069
  const reason = readClaudeJsonOverage(claudeConfigDir);
110935
111070
  const prev = loadCreditState(stateDir);
@@ -112685,7 +112820,7 @@ Send \`/auth ${parsed.provider} cancel\` to abort.`, { html: true });
112685
112820
  await switchroomReply(ctx, "**/usage:** cannot resolve agent dir.", { html: true });
112686
112821
  return;
112687
112822
  }
112688
- const result = await fetchQuota2({ claudeConfigDir: join69(agentDir, ".claude") });
112823
+ const result = await fetchQuota2({ claudeConfigDir: join68(agentDir, ".claude") });
112689
112824
  if (!result.ok) {
112690
112825
  await switchroomReply(ctx, `**/usage:** ${escapeHtmlForTg2(result.reason)}`, { html: true });
112691
112826
  return;
@@ -113072,7 +113207,7 @@ ${interimLabel}` : interimLabel
113072
113207
  const unifiedDiff = (() => {
113073
113208
  try {
113074
113209
  const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
113075
- const raw = readFileSync60(cfgPath, "utf8");
113210
+ const raw = readFileSync61(cfgPath, "utf8");
113076
113211
  return synthesizeAllowRuleDiff({ agentName: agentName3, rule: chosen.rule, configText: raw });
113077
113212
  } catch (err) {
113078
113213
  process.stderr.write(`telegram gateway: always-allow diff synth failed: ${err.message}
@@ -113941,7 +114076,7 @@ async function startGateway() {
113941
114076
  return;
113942
114077
  }
113943
114078
  })();
113944
- const resolvedAgentDirForBootCard = agentDir ?? join69(homedir20(), ".switchroom", "agents", agentSlug);
114079
+ const resolvedAgentDirForBootCard = agentDir ?? join68(homedir20(), ".switchroom", "agents", agentSlug);
113945
114080
  const handle = await startBootCard(chatId, threadId, botApiForCard, {
113946
114081
  agentName: agentDisplayName,
113947
114082
  agentSlug,
@@ -113955,8 +114090,8 @@ async function startGateway() {
113955
114090
  probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
113956
114091
  tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
113957
114092
  dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
113958
- configSnapshotPath: join69(resolvedAgentDirForBootCard, ".config-snapshot.json"),
113959
- bootCardStatePath: join69(resolvedAgentDirForBootCard, ".boot-card-msgid.json"),
114093
+ configSnapshotPath: join68(resolvedAgentDirForBootCard, ".config-snapshot.json"),
114094
+ bootCardStatePath: join68(resolvedAgentDirForBootCard, ".boot-card-msgid.json"),
113960
114095
  floodStatePath: FLOOD_STATE_PATH,
113961
114096
  ...updateOutcomeLine ? { updateOutcomeLine } : {}
113962
114097
  }, ackMsgId);
@@ -113989,7 +114124,7 @@ async function startGateway() {
113989
114124
  if (smAgentDir) {
113990
114125
  const resolutionTimeoutMs = resolveSessionModelResolutionTimeoutMs(process.env.SWITCHROOM_SESSION_MODEL_RESOLUTION_TIMEOUT_MS);
113991
114126
  const resolved = await waitForSessionModelResolution({
113992
- barrierExists: () => existsSync57(join69(smAgentDir, ".session-model-resolved")),
114127
+ barrierExists: () => existsSync58(join68(smAgentDir, ".session-model-resolved")),
113993
114128
  timeoutMs: resolutionTimeoutMs
113994
114129
  });
113995
114130
  if (!resolved) {
@@ -113997,10 +114132,10 @@ async function startGateway() {
113997
114132
  process.stderr.write(`telegram gateway: gw /model relaunch UNRESOLVED agent=${getMyAgentName()} target=${target} (barrier timeout after ${resolutionTimeoutMs}ms)
113998
114133
  `);
113999
114134
  } else {
114000
- const activePath = join69(smAgentDir, ".active-session-model");
114001
- if (existsSync57(activePath)) {
114135
+ const activePath = join68(smAgentDir, ".active-session-model");
114136
+ if (existsSync58(activePath)) {
114002
114137
  try {
114003
- const launched = readFileSync60(activePath, "utf8").trim();
114138
+ const launched = readFileSync61(activePath, "utf8").trim();
114004
114139
  const configured = (() => {
114005
114140
  const d = switchroomExecJson(["agent", "list"]);
114006
114141
  const raw = d?.agents?.find((a) => a.name === getMyAgentName())?.model ?? null;
@@ -114033,24 +114168,24 @@ async function startGateway() {
114033
114168
  deliverModelSwitchBootNotice({
114034
114169
  ...modelBootCardDeps,
114035
114170
  confirmation,
114036
- hasSessionModelAlert: existsSync57(join69(smAgentDir, ".session-model-alert"))
114171
+ hasSessionModelAlert: existsSync58(join68(smAgentDir, ".session-model-alert"))
114037
114172
  });
114038
114173
  }
114039
114174
  } catch {}
114040
114175
  }
114041
- const activeEffortPath = join69(smAgentDir, ".active-session-effort");
114042
- if (existsSync57(activeEffortPath)) {
114176
+ const activeEffortPath = join68(smAgentDir, ".active-session-effort");
114177
+ if (existsSync58(activeEffortPath)) {
114043
114178
  try {
114044
- const launchedEffort = readFileSync60(activeEffortPath, "utf8").trim();
114179
+ const launchedEffort = readFileSync61(activeEffortPath, "utf8").trim();
114045
114180
  const configuredEffort = getConfiguredEffortForPersist();
114046
114181
  sessionEffortOverride = launchedEffort.length > 0 && launchedEffort !== configuredEffort ? launchedEffort : null;
114047
114182
  } catch {}
114048
114183
  }
114049
- const alertPath = join69(smAgentDir, ".session-model-alert");
114050
- if (existsSync57(alertPath)) {
114184
+ const alertPath = join68(smAgentDir, ".session-model-alert");
114185
+ if (existsSync58(alertPath)) {
114051
114186
  let alertText = null;
114052
114187
  try {
114053
- alertText = readFileSync60(alertPath, "utf8").trim();
114188
+ alertText = readFileSync61(alertPath, "utf8").trim();
114054
114189
  } catch {
114055
114190
  alertText = null;
114056
114191
  }