switchroom 0.20.10 → 0.20.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/agent-scheduler/index.js +68 -3
  2. package/dist/auth-broker/index.js +211 -46
  3. package/dist/cli/notion-write-pretool.mjs +68 -3
  4. package/dist/cli/self-improve-apply-guard-pretool.mjs +357 -92
  5. package/dist/cli/self-improve-stop.mjs +889 -7
  6. package/dist/cli/skill-validate-pretool.mjs +82 -3
  7. package/dist/cli/switchroom.js +5063 -2961
  8. package/dist/host-control/main.js +93 -27
  9. package/dist/vault/approvals/kernel-server.js +92 -26
  10. package/dist/vault/broker/server.js +92 -26
  11. package/examples/personal-google-workspace-mcp/compose.yaml +1 -1
  12. package/package.json +1 -1
  13. package/profiles/_shared/agent-self-service.md.hbs +15 -22
  14. package/profiles/_shared/delegation-golden-rule.md.hbs +1 -1
  15. package/profiles/_shared/dev-protocol.md.hbs +1 -1
  16. package/profiles/_shared/execution-discipline.md.hbs +4 -4
  17. package/profiles/_shared/vault-protocol.md.hbs +2 -18
  18. package/profiles/default/CLAUDE.md.hbs +3 -5
  19. package/skills/switchroom-architecture/telegram.md +0 -1
  20. package/skills/switchroom-cli/SKILL.md +0 -1
  21. package/telegram-plugin/README.md +2 -11
  22. package/telegram-plugin/auto-fallback-fleet.ts +37 -2
  23. package/telegram-plugin/bridge/bridge.ts +0 -12
  24. package/telegram-plugin/chat-lock.ts +1 -1
  25. package/telegram-plugin/dist/bridge/bridge.js +0 -12
  26. package/telegram-plugin/dist/gateway/gateway.js +1454 -976
  27. package/telegram-plugin/dist/server.js +0 -12
  28. package/telegram-plugin/fallback-card-collapse.ts +1 -0
  29. package/telegram-plugin/gateway/auth-command.ts +11 -1
  30. package/telegram-plugin/gateway/callback-query-handlers.ts +100 -0
  31. package/telegram-plugin/gateway/eval-case-proposal-card.ts +86 -0
  32. package/telegram-plugin/gateway/fleet-fallback-notice-cooldown.test.ts +74 -0
  33. package/telegram-plugin/gateway/fleet-fallback-notice-cooldown.ts +71 -0
  34. package/telegram-plugin/gateway/gateway.ts +109 -149
  35. package/telegram-plugin/gateway/ipc-protocol.ts +43 -0
  36. package/telegram-plugin/gateway/ipc-server.ts +28 -0
  37. package/telegram-plugin/gateway/liveness-wiring.ts +6 -1
  38. package/telegram-plugin/gateway/narrative-lane.ts +33 -2
  39. package/telegram-plugin/gateway/privacy-reset.test.ts +216 -0
  40. package/telegram-plugin/gateway/privacy-reset.ts +87 -0
  41. package/telegram-plugin/gateway/privacy-state.test.ts +165 -0
  42. package/telegram-plugin/gateway/privacy-state.ts +206 -0
  43. package/telegram-plugin/gateway/self-improve-proposal-wiring.ts +176 -0
  44. package/telegram-plugin/gateway/stale-pin-sweep-wiring.ts +24 -14
  45. package/telegram-plugin/gateway/stale-pin-sweep.test.ts +123 -26
  46. package/telegram-plugin/gateway/stale-pin-sweep.ts +52 -35
  47. package/telegram-plugin/gateway/status-pin-store.ts +10 -9
  48. package/telegram-plugin/gateway/stream-render.ts +4 -4
  49. package/telegram-plugin/gateway/throttle-tier-wiring.ts +15 -4
  50. package/telegram-plugin/gateway/turn-record-status.ts +32 -1
  51. package/telegram-plugin/hooks/hooks.json +13 -12
  52. package/telegram-plugin/hooks/narration-classify.mjs +1 -2
  53. package/telegram-plugin/hooks/silent-end-scan.mjs +1 -1
  54. package/telegram-plugin/slot-banner-driver.ts +42 -5
  55. package/telegram-plugin/status-pin.ts +2 -5
  56. package/telegram-plugin/tests/auto-fallback-fleet.test.ts +24 -0
  57. package/telegram-plugin/tests/backstop-exactly-once.test.ts +8 -2
  58. package/telegram-plugin/tests/framework-fallback-duration-guard.test.ts +125 -0
  59. package/telegram-plugin/tests/gateway-handler-registration-wiring.test.ts +2 -0
  60. package/telegram-plugin/tests/narrative-lane-golden.test.ts +97 -0
  61. package/telegram-plugin/tests/pin-message-tool-retired.test.ts +64 -0
  62. package/telegram-plugin/tests/privacy-reset-call-sites.test.ts +120 -0
  63. package/telegram-plugin/tests/status-pin-boot-recovery.test.ts +38 -0
  64. package/telegram-plugin/tests/status-pin-store.test.ts +25 -0
  65. package/telegram-plugin/tests/throttle-tier.test.ts +16 -0
  66. package/telegram-plugin/tests/turn-flush-safety.test.ts +67 -0
  67. package/telegram-plugin/tests/worker-activity-feed.test.ts +40 -1
  68. package/telegram-plugin/throttle-tier.ts +12 -3
  69. package/telegram-plugin/turn-flush-safety.ts +97 -0
  70. package/telegram-plugin/worker-activity-feed.ts +1 -1
  71. package/vendor/hindsight-memory/scripts/recall.py +140 -0
  72. package/vendor/hindsight-memory/scripts/retain.py +306 -0
  73. package/vendor/hindsight-memory/scripts/subagent_retain.py +29 -1
  74. package/vendor/hindsight-memory/scripts/tests/test_private_mode.py +415 -0
  75. package/vendor/hindsight-memory/scripts/tests/test_recall_latency_instrumentation.py +277 -0
  76. package/vendor/hindsight-memory/scripts/tests/test_self_improve_correction_tag.py +167 -0
@@ -10994,7 +10994,7 @@ var init_observation_scopes = __esm(() => {
10994
10994
  });
10995
10995
 
10996
10996
  // src/config/schema.ts
10997
- var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, BuzzChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleServiceTokenSchema, 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;
10997
+ var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, BuzzChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleServiceTokenSchema, 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, ConfigRepoConfigSchema, SwitchroomConfigSchema;
10998
10998
  var init_schema = __esm(() => {
10999
10999
  init_zod();
11000
11000
  init_observation_scopes();
@@ -11444,7 +11444,7 @@ var init_schema = __esm(() => {
11444
11444
  reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
11445
11445
  consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
11446
11446
  }).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."),
11447
- 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 — 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 — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — 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 — 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 — 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 — 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 — 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 — 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 — 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 — 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; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced; and " + "HINDSIGHT_API_TEMPORAL_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis, made live by switchroom's " + "temporal-language image patch (which ended a 200+-locale auto-detection " + "pass that blocked the shared asyncio loop on every recall); " + "comma-separated, unset means the image's baked `en`, set e.g. `en,es` to " + "restore i18n parsing; and " + "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS — the max chars of query text " + "dateparser.search_dates() is handed during temporal analysis (0 = " + "unlimited), made live by switchroom's temporal-offload image patch " + "(which moved the synchronous extraction off the shared asyncio loop onto " + "a single-worker thread and bounds its input, ending multi-second loop " + "stalls on multi-KB consolidation queries); unset means the image's baked " + "2000, set 0 to restore an unbounded full scan), 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 — 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 — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
11447
+ 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 — 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 — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — 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 — 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 — 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 — 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 — 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 — 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 — 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 — 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; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced; and " + "HINDSIGHT_API_TEMPORAL_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis, made live by switchroom's " + "temporal-language image patch (which ended a 200+-locale auto-detection " + "pass that blocked the shared asyncio loop on every recall); " + "comma-separated, unset means the image's baked `en`, set e.g. `en,es` to " + "restore i18n parsing; and " + "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS — the max chars of query text " + "dateparser.search_dates() is handed during temporal analysis (0 = " + "unlimited), made live by switchroom's temporal-offload image patch " + "(which moved the synchronous extraction off the shared asyncio loop onto " + "a single-worker thread and bounds its input, ending multi-second loop " + "stalls on multi-KB consolidation queries); unset means the image's baked " + "2000, set 0 to restore an unbounded full scan); and " + "HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE — the Postgres " + "text-search regconfig the native BM25 arms and the search_vector index " + "write run to_tsvector/to_tsquery against; unset means upstream's " + "always-safe `english`, set `hindsight_english` to use switchroom's " + "junk-stopping config (dict + stopword file provisioned durably by the " + "image entrypoint, recall degrading to semantic-only if it is ever " + "missing); 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 — 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 — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
11448
11448
  });
11449
11449
  MicrosoftWorkspaceConfigSchema = exports_external.object({
11450
11450
  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 — omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
@@ -11691,8 +11691,10 @@ var init_schema = __esm(() => {
11691
11691
  bot_username: exports_external.string().optional().describe("Per-agent Telegram bot username (without leading @) when it doesn't " + "contain the agent slug. Replaces the default 'username includes slug' " + "preflight check with an exact (case-insensitive) match. Use when an " + "agent and its bot have intentionally divergent names (e.g. agent " + "'lawgpt' paired with bot '@meken_law_bot')."),
11692
11692
  timezone: exports_external.string().regex(TIMEZONE_REGEX, "timezone must be an IANA zone name like 'Australia/Melbourne' or 'UTC' " + "(three-letter aliases like EST/PST and bare offsets like UTC+10 are not accepted)").optional().describe("Per-agent IANA timezone override. Wins over any profile/defaults " + "value and over the top-level switchroom.timezone global. Controls " + "the UserPromptSubmit timezone hook's emitted local time and the " + "agent container's `environment.TZ` in compose."),
11693
11693
  auth: exports_external.object({
11694
- override: exports_external.string().min(1).optional().describe("Per-agent override of the fleet-wide `auth.active`. Edge-case use only — " + "this agent talks to the named account regardless of fleet active. See RFC H §4.5.")
11695
- }).optional().describe("Account routing for switchroom-auth-broker. RFC H schema uses " + "fleet-wide `auth.active` plus per-agent `override:` for edge cases. " + "Pre-RFC-H `auth.accounts: [..]` and `auth_label:` are migrated in-place " + "on first apply (see src/auth/migrate-schema.ts)."),
11694
+ override: exports_external.string().min(1).optional().describe("Per-agent override of the fleet-wide `auth.active`. Edge-case use only — " + "this agent talks to the named account regardless of fleet active. See RFC H §4.5."),
11695
+ strict: exports_external.boolean().optional().describe("Requires `override`. When true, the pin is a hard binding, not a " + "routing preference: the broker NEVER serves this agent from any " + "other account — no failover to `auth.fallback_order` while the " + "pinned account is quota-walled or exhausted. The agent rides out " + "the wall on its own account (surfacing the normal 429/quota " + "cards) instead of silently borrowing fleet quota. Use for " + "accounts that must never cross a billing/compliance boundary " + "(e.g. an employer-provided subscription)."),
11696
+ exclusive: exports_external.boolean().optional().describe("Requires `override`. When true, the pinned account belongs to " + "THIS agent alone: the broker refuses to serve it to any other " + "agent or consumer, refuses `auth use <label>` (set-active) onto " + "it, and refuses pinning another agent to it. Config that routes " + "others to the account (`auth.active`, `auth.fallback_order`, " + "another agent's `override`, a consumer pin) is rejected at load. " + "Usually paired with `strict: true` for full two-way isolation.")
11697
+ }).optional().describe("Account routing for switchroom-auth-broker. RFC H schema uses " + "fleet-wide `auth.active` plus per-agent `override:` for edge cases, " + "with optional `strict:` (never borrow another account) and " + "`exclusive:` (no one else may use the pinned account) hardening. " + "Pre-RFC-H `auth.accounts: [..]` and `auth_label:` are migrated in-place " + "on first apply (see src/auth/migrate-schema.ts)."),
11696
11698
  dm_only: exports_external.boolean().optional().describe("Mark this agent as a DM-only bot — has its own bot_token and lives " + "exclusively in a private chat with the operator. Suppresses " + "scaffolding's default behavior of inheriting the global " + "telegram.forum_chat_id into the agent's access.json `groups` entry " + "(the forum chat the bot isn't a member of, which would otherwise " + "trigger a 'boot-probe-failed: 400 chat not found' warning every " + "restart). topic_name is still schema-required but unused — set it " + "to a display label like 'DM' for /switchroom status output."),
11697
11699
  topic_name: exports_external.string().describe("Telegram forum topic display name"),
11698
11700
  topic_emoji: exports_external.string().optional().describe("Emoji for the topic (e.g., '\uD83C\uDFCB️')"),
@@ -11767,6 +11769,17 @@ var init_schema = __esm(() => {
11767
11769
  tmp_size: exports_external.string().regex(/^\d+(\.\d+)?[kmgKMG]?$/, "tmp_size must be a Docker size string like '1g', '4g', '512m'").refine((v) => parseFloat(v) > 0, "tmp_size must be greater than zero").optional()
11768
11770
  }).optional()
11769
11771
  }).superRefine((agent, ctx) => {
11772
+ if (agent.auth && !agent.auth.override) {
11773
+ for (const flag of ["strict", "exclusive"]) {
11774
+ if (agent.auth[flag]) {
11775
+ ctx.addIssue({
11776
+ code: exports_external.ZodIssueCode.custom,
11777
+ message: `\`auth.${flag}: true\` requires \`auth.override: <account>\` — there is no pinned account for it to apply to.`,
11778
+ path: ["auth", flag]
11779
+ });
11780
+ }
11781
+ }
11782
+ }
11770
11783
  if (agent.dm_only !== true)
11771
11784
  return;
11772
11785
  const tg = agent.channels?.telegram;
@@ -11879,6 +11892,15 @@ var init_schema = __esm(() => {
11879
11892
  profile_bank: exports_external.string().describe("Hindsight bank holding this user's memory profile (author via " + "`switchroom memory profile add <bank> ...`)."),
11880
11893
  person_id: exports_external.string().optional().describe("Free-text display name projected into the inbound `<channel>` " + 'tag\'s `user` attribute (e.g. "Lisa") so an agent can greet by ' + "name instead of only seeing the raw Telegram id/username. NOT a " + "stable identity system — just a label. Resolution is boot-time-only " + "(no hot-reload; a config change needs an agent restart) and " + "chat-scoped (a resolved name is only shown in a chat/group the " + "person is actually a member of, per that chat's access.json " + "membership — never broadcast into every chat the agent operates " + "in). Keep this broadly safe to show, the same discipline as " + "picking a `profile_bank` name: there is no automated enforcement " + "that a `person_id` stays safe if a group's membership changes " + "later — see docs/configuration.md.")
11881
11894
  });
11895
+ ConfigRepoConfigSchema = exports_external.object({
11896
+ enabled: exports_external.boolean().default(false).describe("Master switch for config-repo change control. Default false (opt-in). " + "When false the `config-repo sync` verb still runs on demand but the " + "doctor check and (later) the scheduled tick treat the feature as off."),
11897
+ path: exports_external.string().regex(/^[a-zA-Z0-9~._\-/]+$/, "config_repo.path must not contain shell-special characters ($, `, \", ', \\, etc.)").default("~/.switchroom-config").describe("Filesystem path to the operator's private config repo. Must be a git " + "repo (else `switchroom doctor` FAILs). Tilde-expanded at read time."),
11898
+ push: exports_external.boolean().default(true).describe("When true, `config-repo sync` pushes after committing (subject to the " + "`require_private` gate). When false, it commits locally only — useful " + "for offline hosts or a review-before-push workflow."),
11899
+ remote: exports_external.string().min(1).default("origin").describe("Git remote name to push to. Default `origin`."),
11900
+ require_private: exports_external.boolean().default(true).describe("Refuse to PUSH unless the GitHub API confirms the remote repo is " + "private. On a public remote — or when the API is unreachable — the " + "push is skipped (commits still land locally) and a WARN is emitted. " + "Fail-safe against exfiltrating memory files / workspace state to a " + "repo that has been flipped public. Default true."),
11901
+ interval_minutes: exports_external.number().int().min(5).max(59).default(30).describe("Cadence (minutes) of the scheduled `config-repo sync` tick installed " + "by `switchroom config-repo --install-cron`. Rendered as a cron " + "`*/N * * * *` minute field, so it must be 5..59 (the 5-min floor " + "matches the rest of the fleet's cron floor). Default 30 (Ken's " + "approved cadence). Changing it takes effect on the next " + "`--install-cron` / `switchroom update` reconcile."),
11902
+ include_vault_backup: exports_external.enum(["off", "daily", "every_tick"]).default("daily").describe("Whether the scheduled tick also runs `switchroom vault backup` " + "(an encrypted vault/memory snapshot into <path>/vault-backups/) " + "before the sync. `off`: sync only. `daily`: an extra once-per-day " + "cron leg runs `vault backup && config-repo sync` (the 30-min legs " + "stay sync-only). `every_tick`: every tick runs the backup first. " + "Default `daily` — the first automated vault backup on this host.")
11903
+ });
11882
11904
  SwitchroomConfigSchema = exports_external.object({
11883
11905
  switchroom: exports_external.object({
11884
11906
  version: exports_external.literal(1).describe("Config schema version"),
@@ -11891,6 +11913,7 @@ var init_schema = __esm(() => {
11891
11913
  memory: MemoryBackendConfigSchema.optional(),
11892
11914
  hindsight: HindsightConfigSchema.optional().describe("Fleet-singleton Hindsight (memory backend) configuration. Currently " + "just the LLM knob (provider + model) used for retain/reflect/" + "consolidation. Both fields optional; when unset the container falls " + "back to provider=claude-code + the hard-coded HINDSIGHT_DEFAULT_MODEL " + "so nothing changes for operators who don't set it. Read at container " + "launch by startHindsight() (src/setup/hindsight.ts) — takes effect on " + "the next `switchroom apply` / `memory setup --recreate`."),
11893
11915
  vault: VaultConfigSchema.optional(),
11916
+ config_repo: ConfigRepoConfigSchema.optional().describe("Change control for the operator's private ~/.switchroom-config git repo " + "(backup + audit trail of live host config, agent workspace state, and " + "mirrored personal skills). Consumed by `switchroom config-repo sync` and " + "the `config repo` doctor check. Optional and OFF by default."),
11894
11917
  auth: exports_external.object({
11895
11918
  active: exports_external.string().min(1).optional().describe("Fleet-wide active Anthropic account label. Every agent without " + "an explicit `agent.auth.override` uses this account. See " + "docs/auth.md for the full model. Set by `switchroom auth use <label>`."),
11896
11919
  fallback_order: exports_external.array(exports_external.string().min(1)).optional().describe("Ordered list of account labels for `switchroom auth rotate` to cycle " + "through when the active account hits a quota event. First entry is " + "normally the same as `auth.active`. When unset, `rotate` is a no-op."),
@@ -11958,6 +11981,48 @@ var init_schema = __esm(() => {
11958
11981
  for (const [name, a] of Object.entries(cfg.agents ?? {})) {
11959
11982
  checkServes(a.serves, ["agents", name, "serves"]);
11960
11983
  }
11984
+ for (const [name, a] of Object.entries(cfg.agents ?? {})) {
11985
+ const agentAuth = a.auth;
11986
+ if (!agentAuth?.exclusive || !agentAuth.override)
11987
+ continue;
11988
+ const acct = agentAuth.override;
11989
+ if (cfg.auth?.active === acct) {
11990
+ ctx.addIssue({
11991
+ code: exports_external.ZodIssueCode.custom,
11992
+ message: `account '${acct}' is exclusive to agent '${name}' ` + `(agents.${name}.auth.exclusive) — it cannot be the fleet \`auth.active\``,
11993
+ path: ["auth", "active"]
11994
+ });
11995
+ }
11996
+ const fbIdx = (cfg.auth?.fallback_order ?? []).indexOf(acct);
11997
+ if (fbIdx !== -1) {
11998
+ ctx.addIssue({
11999
+ code: exports_external.ZodIssueCode.custom,
12000
+ message: `account '${acct}' is exclusive to agent '${name}' ` + `(agents.${name}.auth.exclusive) — it cannot appear in \`auth.fallback_order\``,
12001
+ path: ["auth", "fallback_order", fbIdx]
12002
+ });
12003
+ }
12004
+ for (const [other, oa] of Object.entries(cfg.agents ?? {})) {
12005
+ if (other === name)
12006
+ continue;
12007
+ const otherOverride = oa.auth?.override;
12008
+ if (otherOverride === acct) {
12009
+ ctx.addIssue({
12010
+ code: exports_external.ZodIssueCode.custom,
12011
+ message: `account '${acct}' is exclusive to agent '${name}' ` + `(agents.${name}.auth.exclusive) — agent '${other}' cannot pin it`,
12012
+ path: ["agents", other, "auth", "override"]
12013
+ });
12014
+ }
12015
+ }
12016
+ (cfg.auth?.consumers ?? []).forEach((c, i) => {
12017
+ if (c.account === acct) {
12018
+ ctx.addIssue({
12019
+ code: exports_external.ZodIssueCode.custom,
12020
+ message: `account '${acct}' is exclusive to agent '${name}' ` + `(agents.${name}.auth.exclusive) — consumer '${c.name}' cannot pin it`,
12021
+ path: ["auth", "consumers", i, "account"]
12022
+ });
12023
+ }
12024
+ });
12025
+ }
11961
12026
  const microsoftAccounts = cfg.microsoft_accounts;
11962
12027
  for (const [name, a] of Object.entries(cfg.agents ?? {})) {
11963
12028
  const mw = a.microsoft_workspace;
@@ -21493,7 +21558,28 @@ function allocateAgentUid(name) {
21493
21558
  }
21494
21559
 
21495
21560
  // src/build-info.ts
21496
- var VERSION = "0.20.10";
21561
+ var VERSION = "0.20.12";
21562
+
21563
+ // src/setup/hindsight-recall-passthrough.ts
21564
+ var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
21565
+ var HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT = "Relevant memories from past conversations (prioritize recent when " + "conflicting). Only use memories that are directly useful to continue " + "this conversation; ignore the rest:";
21566
+ var RECALL_PASSTHROUGH_DEFAULTS = Object.freeze({
21567
+ budget: "low",
21568
+ maxTokens: 1024,
21569
+ preferObservations: true,
21570
+ contextTurns: 2,
21571
+ roles: ["user", "assistant"],
21572
+ promptPreamble: HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT,
21573
+ tags: [],
21574
+ tagsMatch: "any",
21575
+ tagGroups: {},
21576
+ tagWeights: HINDSIGHT_RECALL_TAG_WEIGHT_SEED,
21577
+ additionalBankFilters: {},
21578
+ transcriptFallback: true,
21579
+ transcriptTailBytes: 262144,
21580
+ maxQueryChars: 800,
21581
+ parallel: true
21582
+ });
21497
21583
 
21498
21584
  // src/setup/hindsight-recall-tunables.ts
21499
21585
  var RECALL_DEADLINE_HEADROOM_SECONDS = 2;
@@ -21770,7 +21856,8 @@ var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
21770
21856
  "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT",
21771
21857
  "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S",
21772
21858
  "HINDSIGHT_API_TEMPORAL_LANGUAGES",
21773
- "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS"
21859
+ "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS",
21860
+ "HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE"
21774
21861
  ]);
21775
21862
  var HINDSIGHT_WORKER_SLOT_TYPES = [
21776
21863
  "consolidation",
@@ -22192,27 +22279,6 @@ init_vault();
22192
22279
  // src/setup/onboarding.ts
22193
22280
  init_paths();
22194
22281
 
22195
- // src/setup/hindsight-recall-passthrough.ts
22196
- var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
22197
- var HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT = "Relevant memories from past conversations (prioritize recent when " + "conflicting). Only use memories that are directly useful to continue " + "this conversation; ignore the rest:";
22198
- var RECALL_PASSTHROUGH_DEFAULTS = Object.freeze({
22199
- budget: "low",
22200
- maxTokens: 1024,
22201
- preferObservations: true,
22202
- contextTurns: 2,
22203
- roles: ["user", "assistant"],
22204
- promptPreamble: HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT,
22205
- tags: [],
22206
- tagsMatch: "any",
22207
- tagGroups: {},
22208
- tagWeights: HINDSIGHT_RECALL_TAG_WEIGHT_SEED,
22209
- additionalBankFilters: {},
22210
- transcriptFallback: true,
22211
- transcriptTailBytes: 262144,
22212
- maxQueryChars: 800,
22213
- parallel: true
22214
- });
22215
-
22216
22282
  // src/repos/bare-clone.ts
22217
22283
  init_paths();
22218
22284
 
@@ -4434,7 +4434,7 @@ var init_observation_scopes = __esm(() => {
4434
4434
  });
4435
4435
 
4436
4436
  // src/config/schema.ts
4437
- var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, BuzzChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleServiceTokenSchema, 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;
4437
+ var CodeRepoEntrySchema, AgentBindMountSchema, HttpDiffPollSchema, PollSpecSchema, TelegramMessageActionSchema, WebhookActionSchema, ActionSpecSchema, ScheduleEntrySchema, AgentSoulSchema, AgentToolsSchema, ObservationScopesSchema, ObservationScopeStrategySchema, AntiConfabulationDirectiveSchema, AgentMemorySchema, HookEntrySchema, AgentHooksSchema, SubagentSchema, SessionSchema, SessionContinuitySchema, webhookDispatchRule, TelegramChannelSchema, BuzzChannelSchema, ChannelsSchema, TIMEZONE_REGEX, ApproverIdSchema, GoogleWorkspaceTierSchema, GoogleServiceTokenSchema, 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, ConfigRepoConfigSchema, SwitchroomConfigSchema;
4438
4438
  var init_schema = __esm(() => {
4439
4439
  init_zod();
4440
4440
  init_observation_scopes();
@@ -4884,7 +4884,7 @@ var init_schema = __esm(() => {
4884
4884
  reflect: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `reflect` LLM op (synthesis / mental-model " + "refresh). Emits `HINDSIGHT_API_REFLECT_LLM_*`. Absent → uses global."),
4885
4885
  consolidation: HindsightPerOpLlmSchema.optional().describe("Per-op override for the `consolidation` LLM op (background memory " + "merge). Emits `HINDSIGHT_API_CONSOLIDATION_LLM_*`. Absent → global.")
4886
4886
  }).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."),
4887
- 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 — 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 — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — 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 — 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 — 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 — 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 — 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 — 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 — 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 — 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; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced; and " + "HINDSIGHT_API_TEMPORAL_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis, made live by switchroom's " + "temporal-language image patch (which ended a 200+-locale auto-detection " + "pass that blocked the shared asyncio loop on every recall); " + "comma-separated, unset means the image's baked `en`, set e.g. `en,es` to " + "restore i18n parsing; and " + "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS — the max chars of query text " + "dateparser.search_dates() is handed during temporal analysis (0 = " + "unlimited), made live by switchroom's temporal-offload image patch " + "(which moved the synchronous extraction off the shared asyncio loop onto " + "a single-worker thread and bounds its input, ending multi-second loop " + "stalls on multi-KB consolidation queries); unset means the image's baked " + "2000, set 0 to restore an unbounded full scan), 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 — 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 — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
4887
+ 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 — 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 — a per-deployment " + "`bank-pattern:priority,...` map; unset means upstream's flat " + "created_at FIFO across banks; and " + "HINDSIGHT_CE_DECISIVE_RELATIVE_GAP — 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 — 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 — 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 — 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 — 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 — 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 — 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 — 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; and " + "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S — the rollback/tuning knob for " + "switchroom's MM-refresh-debounce image patch: the minimum seconds " + "between consolidation-triggered refreshes of one mental model; unset " + "means the image's baked 3600, 0 restores upstream's " + "refresh-every-round behaviour; explicit and cron-scheduled refreshes " + "are never debounced; and " + "HINDSIGHT_API_TEMPORAL_LANGUAGES — the language set dateparser is " + "restricted to during temporal query analysis, made live by switchroom's " + "temporal-language image patch (which ended a 200+-locale auto-detection " + "pass that blocked the shared asyncio loop on every recall); " + "comma-separated, unset means the image's baked `en`, set e.g. `en,es` to " + "restore i18n parsing; and " + "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS — the max chars of query text " + "dateparser.search_dates() is handed during temporal analysis (0 = " + "unlimited), made live by switchroom's temporal-offload image patch " + "(which moved the synchronous extraction off the shared asyncio loop onto " + "a single-worker thread and bounds its input, ending multi-second loop " + "stalls on multi-KB consolidation queries); unset means the image's baked " + "2000, set 0 to restore an unbounded full scan); and " + "HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE — the Postgres " + "text-search regconfig the native BM25 arms and the search_vector index " + "write run to_tsvector/to_tsquery against; unset means upstream's " + "always-safe `english`, set `hindsight_english` to use switchroom's " + "junk-stopping config (dict + stopword file provisioned durably by the " + "image entrypoint, recall degrading to semantic-only if it is ever " + "missing); 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 — 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 — a blanket " + "passthrough would collide with the vars startHindsight() derives " + "itself (HINDSIGHT_API_PORT, the retain token/deadline budget).")
4888
4888
  });
4889
4889
  MicrosoftWorkspaceConfigSchema = exports_external.object({
4890
4890
  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 — omit it to use " + "switchroom's shipped default Microsoft app (zero-config). " + "Set it only to bring your own Entra app (BYO)."),
@@ -5131,8 +5131,10 @@ var init_schema = __esm(() => {
5131
5131
  bot_username: exports_external.string().optional().describe("Per-agent Telegram bot username (without leading @) when it doesn't " + "contain the agent slug. Replaces the default 'username includes slug' " + "preflight check with an exact (case-insensitive) match. Use when an " + "agent and its bot have intentionally divergent names (e.g. agent " + "'lawgpt' paired with bot '@meken_law_bot')."),
5132
5132
  timezone: exports_external.string().regex(TIMEZONE_REGEX, "timezone must be an IANA zone name like 'Australia/Melbourne' or 'UTC' " + "(three-letter aliases like EST/PST and bare offsets like UTC+10 are not accepted)").optional().describe("Per-agent IANA timezone override. Wins over any profile/defaults " + "value and over the top-level switchroom.timezone global. Controls " + "the UserPromptSubmit timezone hook's emitted local time and the " + "agent container's `environment.TZ` in compose."),
5133
5133
  auth: exports_external.object({
5134
- override: exports_external.string().min(1).optional().describe("Per-agent override of the fleet-wide `auth.active`. Edge-case use only — " + "this agent talks to the named account regardless of fleet active. See RFC H §4.5.")
5135
- }).optional().describe("Account routing for switchroom-auth-broker. RFC H schema uses " + "fleet-wide `auth.active` plus per-agent `override:` for edge cases. " + "Pre-RFC-H `auth.accounts: [..]` and `auth_label:` are migrated in-place " + "on first apply (see src/auth/migrate-schema.ts)."),
5134
+ override: exports_external.string().min(1).optional().describe("Per-agent override of the fleet-wide `auth.active`. Edge-case use only — " + "this agent talks to the named account regardless of fleet active. See RFC H §4.5."),
5135
+ strict: exports_external.boolean().optional().describe("Requires `override`. When true, the pin is a hard binding, not a " + "routing preference: the broker NEVER serves this agent from any " + "other account — no failover to `auth.fallback_order` while the " + "pinned account is quota-walled or exhausted. The agent rides out " + "the wall on its own account (surfacing the normal 429/quota " + "cards) instead of silently borrowing fleet quota. Use for " + "accounts that must never cross a billing/compliance boundary " + "(e.g. an employer-provided subscription)."),
5136
+ exclusive: exports_external.boolean().optional().describe("Requires `override`. When true, the pinned account belongs to " + "THIS agent alone: the broker refuses to serve it to any other " + "agent or consumer, refuses `auth use <label>` (set-active) onto " + "it, and refuses pinning another agent to it. Config that routes " + "others to the account (`auth.active`, `auth.fallback_order`, " + "another agent's `override`, a consumer pin) is rejected at load. " + "Usually paired with `strict: true` for full two-way isolation.")
5137
+ }).optional().describe("Account routing for switchroom-auth-broker. RFC H schema uses " + "fleet-wide `auth.active` plus per-agent `override:` for edge cases, " + "with optional `strict:` (never borrow another account) and " + "`exclusive:` (no one else may use the pinned account) hardening. " + "Pre-RFC-H `auth.accounts: [..]` and `auth_label:` are migrated in-place " + "on first apply (see src/auth/migrate-schema.ts)."),
5136
5138
  dm_only: exports_external.boolean().optional().describe("Mark this agent as a DM-only bot — has its own bot_token and lives " + "exclusively in a private chat with the operator. Suppresses " + "scaffolding's default behavior of inheriting the global " + "telegram.forum_chat_id into the agent's access.json `groups` entry " + "(the forum chat the bot isn't a member of, which would otherwise " + "trigger a 'boot-probe-failed: 400 chat not found' warning every " + "restart). topic_name is still schema-required but unused — set it " + "to a display label like 'DM' for /switchroom status output."),
5137
5139
  topic_name: exports_external.string().describe("Telegram forum topic display name"),
5138
5140
  topic_emoji: exports_external.string().optional().describe("Emoji for the topic (e.g., '\uD83C\uDFCB️')"),
@@ -5207,6 +5209,17 @@ var init_schema = __esm(() => {
5207
5209
  tmp_size: exports_external.string().regex(/^\d+(\.\d+)?[kmgKMG]?$/, "tmp_size must be a Docker size string like '1g', '4g', '512m'").refine((v) => parseFloat(v) > 0, "tmp_size must be greater than zero").optional()
5208
5210
  }).optional()
5209
5211
  }).superRefine((agent, ctx) => {
5212
+ if (agent.auth && !agent.auth.override) {
5213
+ for (const flag of ["strict", "exclusive"]) {
5214
+ if (agent.auth[flag]) {
5215
+ ctx.addIssue({
5216
+ code: exports_external.ZodIssueCode.custom,
5217
+ message: `\`auth.${flag}: true\` requires \`auth.override: <account>\` — there is no pinned account for it to apply to.`,
5218
+ path: ["auth", flag]
5219
+ });
5220
+ }
5221
+ }
5222
+ }
5210
5223
  if (agent.dm_only !== true)
5211
5224
  return;
5212
5225
  const tg = agent.channels?.telegram;
@@ -5319,6 +5332,15 @@ var init_schema = __esm(() => {
5319
5332
  profile_bank: exports_external.string().describe("Hindsight bank holding this user's memory profile (author via " + "`switchroom memory profile add <bank> ...`)."),
5320
5333
  person_id: exports_external.string().optional().describe("Free-text display name projected into the inbound `<channel>` " + 'tag\'s `user` attribute (e.g. "Lisa") so an agent can greet by ' + "name instead of only seeing the raw Telegram id/username. NOT a " + "stable identity system — just a label. Resolution is boot-time-only " + "(no hot-reload; a config change needs an agent restart) and " + "chat-scoped (a resolved name is only shown in a chat/group the " + "person is actually a member of, per that chat's access.json " + "membership — never broadcast into every chat the agent operates " + "in). Keep this broadly safe to show, the same discipline as " + "picking a `profile_bank` name: there is no automated enforcement " + "that a `person_id` stays safe if a group's membership changes " + "later — see docs/configuration.md.")
5321
5334
  });
5335
+ ConfigRepoConfigSchema = exports_external.object({
5336
+ enabled: exports_external.boolean().default(false).describe("Master switch for config-repo change control. Default false (opt-in). " + "When false the `config-repo sync` verb still runs on demand but the " + "doctor check and (later) the scheduled tick treat the feature as off."),
5337
+ path: exports_external.string().regex(/^[a-zA-Z0-9~._\-/]+$/, "config_repo.path must not contain shell-special characters ($, `, \", ', \\, etc.)").default("~/.switchroom-config").describe("Filesystem path to the operator's private config repo. Must be a git " + "repo (else `switchroom doctor` FAILs). Tilde-expanded at read time."),
5338
+ push: exports_external.boolean().default(true).describe("When true, `config-repo sync` pushes after committing (subject to the " + "`require_private` gate). When false, it commits locally only — useful " + "for offline hosts or a review-before-push workflow."),
5339
+ remote: exports_external.string().min(1).default("origin").describe("Git remote name to push to. Default `origin`."),
5340
+ require_private: exports_external.boolean().default(true).describe("Refuse to PUSH unless the GitHub API confirms the remote repo is " + "private. On a public remote — or when the API is unreachable — the " + "push is skipped (commits still land locally) and a WARN is emitted. " + "Fail-safe against exfiltrating memory files / workspace state to a " + "repo that has been flipped public. Default true."),
5341
+ interval_minutes: exports_external.number().int().min(5).max(59).default(30).describe("Cadence (minutes) of the scheduled `config-repo sync` tick installed " + "by `switchroom config-repo --install-cron`. Rendered as a cron " + "`*/N * * * *` minute field, so it must be 5..59 (the 5-min floor " + "matches the rest of the fleet's cron floor). Default 30 (Ken's " + "approved cadence). Changing it takes effect on the next " + "`--install-cron` / `switchroom update` reconcile."),
5342
+ include_vault_backup: exports_external.enum(["off", "daily", "every_tick"]).default("daily").describe("Whether the scheduled tick also runs `switchroom vault backup` " + "(an encrypted vault/memory snapshot into <path>/vault-backups/) " + "before the sync. `off`: sync only. `daily`: an extra once-per-day " + "cron leg runs `vault backup && config-repo sync` (the 30-min legs " + "stay sync-only). `every_tick`: every tick runs the backup first. " + "Default `daily` — the first automated vault backup on this host.")
5343
+ });
5322
5344
  SwitchroomConfigSchema = exports_external.object({
5323
5345
  switchroom: exports_external.object({
5324
5346
  version: exports_external.literal(1).describe("Config schema version"),
@@ -5331,6 +5353,7 @@ var init_schema = __esm(() => {
5331
5353
  memory: MemoryBackendConfigSchema.optional(),
5332
5354
  hindsight: HindsightConfigSchema.optional().describe("Fleet-singleton Hindsight (memory backend) configuration. Currently " + "just the LLM knob (provider + model) used for retain/reflect/" + "consolidation. Both fields optional; when unset the container falls " + "back to provider=claude-code + the hard-coded HINDSIGHT_DEFAULT_MODEL " + "so nothing changes for operators who don't set it. Read at container " + "launch by startHindsight() (src/setup/hindsight.ts) — takes effect on " + "the next `switchroom apply` / `memory setup --recreate`."),
5333
5355
  vault: VaultConfigSchema.optional(),
5356
+ config_repo: ConfigRepoConfigSchema.optional().describe("Change control for the operator's private ~/.switchroom-config git repo " + "(backup + audit trail of live host config, agent workspace state, and " + "mirrored personal skills). Consumed by `switchroom config-repo sync` and " + "the `config repo` doctor check. Optional and OFF by default."),
5334
5357
  auth: exports_external.object({
5335
5358
  active: exports_external.string().min(1).optional().describe("Fleet-wide active Anthropic account label. Every agent without " + "an explicit `agent.auth.override` uses this account. See " + "docs/auth.md for the full model. Set by `switchroom auth use <label>`."),
5336
5359
  fallback_order: exports_external.array(exports_external.string().min(1)).optional().describe("Ordered list of account labels for `switchroom auth rotate` to cycle " + "through when the active account hits a quota event. First entry is " + "normally the same as `auth.active`. When unset, `rotate` is a no-op."),
@@ -5398,6 +5421,48 @@ var init_schema = __esm(() => {
5398
5421
  for (const [name, a] of Object.entries(cfg.agents ?? {})) {
5399
5422
  checkServes(a.serves, ["agents", name, "serves"]);
5400
5423
  }
5424
+ for (const [name, a] of Object.entries(cfg.agents ?? {})) {
5425
+ const agentAuth = a.auth;
5426
+ if (!agentAuth?.exclusive || !agentAuth.override)
5427
+ continue;
5428
+ const acct = agentAuth.override;
5429
+ if (cfg.auth?.active === acct) {
5430
+ ctx.addIssue({
5431
+ code: exports_external.ZodIssueCode.custom,
5432
+ message: `account '${acct}' is exclusive to agent '${name}' ` + `(agents.${name}.auth.exclusive) — it cannot be the fleet \`auth.active\``,
5433
+ path: ["auth", "active"]
5434
+ });
5435
+ }
5436
+ const fbIdx = (cfg.auth?.fallback_order ?? []).indexOf(acct);
5437
+ if (fbIdx !== -1) {
5438
+ ctx.addIssue({
5439
+ code: exports_external.ZodIssueCode.custom,
5440
+ message: `account '${acct}' is exclusive to agent '${name}' ` + `(agents.${name}.auth.exclusive) — it cannot appear in \`auth.fallback_order\``,
5441
+ path: ["auth", "fallback_order", fbIdx]
5442
+ });
5443
+ }
5444
+ for (const [other, oa] of Object.entries(cfg.agents ?? {})) {
5445
+ if (other === name)
5446
+ continue;
5447
+ const otherOverride = oa.auth?.override;
5448
+ if (otherOverride === acct) {
5449
+ ctx.addIssue({
5450
+ code: exports_external.ZodIssueCode.custom,
5451
+ message: `account '${acct}' is exclusive to agent '${name}' ` + `(agents.${name}.auth.exclusive) — agent '${other}' cannot pin it`,
5452
+ path: ["agents", other, "auth", "override"]
5453
+ });
5454
+ }
5455
+ }
5456
+ (cfg.auth?.consumers ?? []).forEach((c, i) => {
5457
+ if (c.account === acct) {
5458
+ ctx.addIssue({
5459
+ code: exports_external.ZodIssueCode.custom,
5460
+ message: `account '${acct}' is exclusive to agent '${name}' ` + `(agents.${name}.auth.exclusive) — consumer '${c.name}' cannot pin it`,
5461
+ path: ["auth", "consumers", i, "account"]
5462
+ });
5463
+ }
5464
+ });
5465
+ }
5401
5466
  const microsoftAccounts = cfg.microsoft_accounts;
5402
5467
  for (const [name, a] of Object.entries(cfg.agents ?? {})) {
5403
5468
  const mw = a.microsoft_workspace;
@@ -19390,6 +19455,27 @@ function allocateAgentUid(name) {
19390
19455
  return AGENT_UID_MIN + u32 % range;
19391
19456
  }
19392
19457
 
19458
+ // src/setup/hindsight-recall-passthrough.ts
19459
+ var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
19460
+ var HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT = "Relevant memories from past conversations (prioritize recent when " + "conflicting). Only use memories that are directly useful to continue " + "this conversation; ignore the rest:";
19461
+ var RECALL_PASSTHROUGH_DEFAULTS = Object.freeze({
19462
+ budget: "low",
19463
+ maxTokens: 1024,
19464
+ preferObservations: true,
19465
+ contextTurns: 2,
19466
+ roles: ["user", "assistant"],
19467
+ promptPreamble: HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT,
19468
+ tags: [],
19469
+ tagsMatch: "any",
19470
+ tagGroups: {},
19471
+ tagWeights: HINDSIGHT_RECALL_TAG_WEIGHT_SEED,
19472
+ additionalBankFilters: {},
19473
+ transcriptFallback: true,
19474
+ transcriptTailBytes: 262144,
19475
+ maxQueryChars: 800,
19476
+ parallel: true
19477
+ });
19478
+
19393
19479
  // src/setup/hindsight-recall-tunables.ts
19394
19480
  var RECALL_DEADLINE_HEADROOM_SECONDS = 2;
19395
19481
  var MIN_RECALL_HOOK_TIMEOUT_SECONDS = RECALL_DEADLINE_HEADROOM_SECONDS + 1;
@@ -19665,7 +19751,8 @@ var HINDSIGHT_PERF_OVERRIDE_ONLY_KEYS = new Set([
19665
19751
  "HINDSIGHT_API_CONSOLIDATION_RECALL_MAX_CONCURRENT",
19666
19752
  "HINDSIGHT_MM_REFRESH_MIN_INTERVAL_S",
19667
19753
  "HINDSIGHT_API_TEMPORAL_LANGUAGES",
19668
- "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS"
19754
+ "HINDSIGHT_API_TEMPORAL_MAX_QUERY_CHARS",
19755
+ "HINDSIGHT_API_TEXT_SEARCH_EXTENSION_NATIVE_LANGUAGE"
19669
19756
  ]);
19670
19757
  var HINDSIGHT_WORKER_SLOT_TYPES = [
19671
19758
  "consolidation",
@@ -20087,27 +20174,6 @@ init_vault();
20087
20174
  // src/setup/onboarding.ts
20088
20175
  init_paths();
20089
20176
 
20090
- // src/setup/hindsight-recall-passthrough.ts
20091
- var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
20092
- var HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT = "Relevant memories from past conversations (prioritize recent when " + "conflicting). Only use memories that are directly useful to continue " + "this conversation; ignore the rest:";
20093
- var RECALL_PASSTHROUGH_DEFAULTS = Object.freeze({
20094
- budget: "low",
20095
- maxTokens: 1024,
20096
- preferObservations: true,
20097
- contextTurns: 2,
20098
- roles: ["user", "assistant"],
20099
- promptPreamble: HINDSIGHT_RECALL_PROMPT_PREAMBLE_DEFAULT,
20100
- tags: [],
20101
- tagsMatch: "any",
20102
- tagGroups: {},
20103
- tagWeights: HINDSIGHT_RECALL_TAG_WEIGHT_SEED,
20104
- additionalBankFilters: {},
20105
- transcriptFallback: true,
20106
- transcriptTailBytes: 262144,
20107
- maxQueryChars: 800,
20108
- parallel: true
20109
- });
20110
-
20111
20177
  // src/repos/bare-clone.ts
20112
20178
  init_paths();
20113
20179