switchroom 0.19.32 → 0.19.33

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.
@@ -18486,12 +18486,12 @@ function assertPositive(value, label) {
18486
18486
  var _warnedReads = new Set;
18487
18487
 
18488
18488
  // src/setup/hindsight-pg-defaults.ts
18489
- var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 8 * 1024;
18489
+ var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 16 * 1024;
18490
18490
  var HINDSIGHT_PG_APP_ANON_MIB = 2560;
18491
18491
  var HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048;
18492
18492
  var HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB = HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION - HINDSIGHT_PG_APP_ANON_MIB - HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
18493
- var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 1536;
18494
- var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 4096;
18493
+ var HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 3072;
18494
+ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 7168;
18495
18495
  function pgMib(mib) {
18496
18496
  return `${mib}MB`;
18497
18497
  }
@@ -18666,7 +18666,17 @@ var HINDSIGHT_HEALTHCHECK_CMD = `python3 -c '${HINDSIGHT_HEALTHCHECK_PY}'`;
18666
18666
  var DOCKER_PROBE_TIMEOUT_MS = 60 * 1000;
18667
18667
 
18668
18668
  // src/memory/hindsight.ts
18669
- var DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and useful weeks from now: user preferences and standing rules, ongoing projects and recurring commitments, technical and architectural decisions with their rationale, and people/tool relationships. A preference revealed by a request is durable — record the preference (what the user likes, wants, or always does), not the request itself.
18669
+ var DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and useful weeks from now, once this session is forgotten.
18670
+ ` + `
18671
+ ` + `DURABILITY GATE. Emit a candidate ONLY if it is one of these five classes:
18672
+ ` + `- PREFERENCE — what the user likes, wants, or always does; a standing rule or correction.
18673
+ ` + `- DECISION — 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 — drop it unless it establishes a standing rule or permanently changes a system.
18674
+ ` + `- FINDING — a root cause, a measurement, or verified behaviour of a system. Include the number.
18675
+ ` + `- OUTCOME — a completed result that changed the world: what shipped, what a thing turned out to be. Not the act of shipping it.
18676
+ ` + `- RELATIONSHIP — who a person is, what a project or tool is, and how they connect.
18677
+ ` + `If a candidate fits none of the five, it is not a memory. Drop it; do not reword it into one.
18678
+ ` + `
18679
+ ` + `A preference revealed by a request is durable — record the preference (what the user likes, wants, or always does), not the request itself.
18670
18680
  ` + `
18671
18681
  ` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
18672
18682
  ` + `candidate a file path, a command/process/agent/session id, a temp directory, or
@@ -18683,6 +18693,9 @@ var DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and
18683
18693
  ` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
18684
18694
  ` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
18685
18695
  ` + ` assistant used X to query Y", "ran a search", "sent the message").
18696
+ ` + `- The act of delegating, dispatching, spawning, launching, steering or merging
18697
+ ` + ` work — including when it succeeded. "X was dispatched and completed" is the
18698
+ ` + ` session describing itself. Record only what the work LEARNED or CHANGED.
18686
18699
  ` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
18687
18700
  ` + ` running) — retain the outcome only once the task completes or a decision is made.
18688
18701
  ` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
@@ -18705,8 +18718,12 @@ var DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and
18705
18718
  ` + ` the fact is explicitly dated, in which case record it as a dated observation.
18706
18719
  ` + `- Greetings, acknowledgements, and routine operational chatter.
18707
18720
  ` + `
18721
+ ` + `Write each fact so it stands alone: name the thing, the number, and the date. A
18722
+ ` + `sentence that only makes sense while reading this transcript is not durable.
18723
+ ` + `
18708
18724
  ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
18709
- ` + "nothing durable remains, return an empty facts list.";
18725
+ ` + `nothing durable remains, return an empty facts list.
18726
+ `;
18710
18727
  var SUPERSEDED_RETAIN_MISSIONS = [
18711
18728
  "Extract technical decisions, architectural choices, user preferences, project context, and people/tool relationships. Ignore routine greetings and transient operational details.",
18712
18729
  "Extract user preferences, ongoing projects, recurring commitments, " + "important context, and durable facts that should help across future " + "conversations. Skip one-off chatter and temporary task noise.",
@@ -18753,7 +18770,96 @@ var SUPERSEDED_RETAIN_MISSIONS = [
18753
18770
  ` + `- Greetings, acknowledgements, and routine operational chatter.
18754
18771
  ` + `
18755
18772
  ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
18756
- ` + "nothing durable remains, return an empty facts list."
18773
+ ` + "nothing durable remains, return an empty facts list.",
18774
+ `Extract durable facts that will still be true and useful weeks from now: user preferences and standing rules, ongoing projects and recurring commitments, technical and architectural decisions with their rationale, and people/tool relationships. A preference revealed by a request is durable — record the preference (what the user likes, wants, or always does), not the request itself.
18775
+ ` + `
18776
+ ` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
18777
+ ` + `candidate a file path, a command/process/agent/session id, a temp directory, or
18778
+ ` + `the location where some output was written? If yes, drop it — it is transcript
18779
+ ` + `exhaust, not memory.
18780
+ ` + `
18781
+ ` + `NEVER extract:
18782
+ ` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
18783
+ ` + ` text resembles any of these: "File created successfully at /path/to/file",
18784
+ ` + ` "A background command with ID bctz4yskm is running, and its output will be
18785
+ ` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
18786
+ ` + ` and is running in the background", "User executed a Bash command to sleep for
18787
+ ` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
18788
+ ` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
18789
+ ` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
18790
+ ` + ` assistant used X to query Y", "ran a search", "sent the message").
18791
+ ` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
18792
+ ` + ` running) — retain the outcome only once the task completes or a decision is made.
18793
+ ` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
18794
+ ` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
18795
+ ` + ` reset assistant state").
18796
+ ` + `- Hindsight's own errors, retries, backlogs, or internal state — the memory
18797
+ ` + ` system's self-reports are not memories.
18798
+ ` + `- Restatements of the user's current request or the task in progress.
18799
+ ` + `- Volatile state written as a timeless assertion. A version, count, size,
18800
+ ` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
18801
+ ` + ` claim is true only at the instant it was said. Concretely, never produce a
18802
+ ` + ` fact whose text resembles any of these: "Switchroom fleet is running image
18803
+ ` + ` version v0.18.19", "The switchroom repo is at /path/to/fleet, version
18804
+ ` + ` v0.19.5", "Bank overlord has 43155 pending consolidations", "The build is
18805
+ ` + ` currently green". If the claim is worth keeping, put the date INSIDE the
18806
+ ` + ` fact text ("As of 2026-07-19 the fleet was running v0.18.19"); if you
18807
+ ` + ` cannot date it, drop it. An undated one is recalled forever as though it
18808
+ ` + ` were still true, which is worse than not remembering it at all.
18809
+ ` + `- Transient state (unread counts, build status, what is running right now) unless
18810
+ ` + ` the fact is explicitly dated, in which case record it as a dated observation.
18811
+ ` + `- Greetings, acknowledgements, and routine operational chatter.
18812
+ ` + `
18813
+ ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
18814
+ ` + "nothing durable remains, return an empty facts list.",
18815
+ `Extract durable facts that will still be true and useful weeks from now, once this session is forgotten.
18816
+ ` + `
18817
+ ` + `DURABILITY GATE. Emit a candidate ONLY if it is one of these five classes:
18818
+ ` + `- PREFERENCE — what the user likes, wants, or always does; a standing rule or correction.
18819
+ ` + `- DECISION — 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 — drop it unless it establishes a standing rule or permanently changes a system.
18820
+ ` + `- FINDING — a root cause, a measurement, or verified behaviour of a system. Include the number.
18821
+ ` + `- OUTCOME — a completed result that changed the world: what shipped, what a thing turned out to be. Not the act of shipping it.
18822
+ ` + `- RELATIONSHIP — who a person is, what a project or tool is, and how they connect.
18823
+ ` + `If a candidate fits none of the five, it is not a memory. Drop it; do not reword it into one.
18824
+ ` + `
18825
+ ` + `A preference revealed by a request is durable — record the preference (what the user likes, wants, or always does), not the request itself.
18826
+ ` + `
18827
+ ` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
18828
+ ` + `candidate a file path, a command/process/agent/session id, a temp directory, or
18829
+ ` + `the location where some output was written? If yes, drop it — it is transcript
18830
+ ` + `exhaust, not memory.
18831
+ ` + `
18832
+ ` + `NEVER extract:
18833
+ ` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
18834
+ ` + ` text resembles any of these: "File created successfully at /path/to/file",
18835
+ ` + ` "A background command with ID bctz4yskm is running, and its output will be
18836
+ ` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
18837
+ ` + ` and is running in the background", "User executed a Bash command to sleep for
18838
+ ` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
18839
+ ` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
18840
+ ` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
18841
+ ` + ` assistant used X to query Y", "ran a search", "sent the message").
18842
+ ` + `- The act of delegating, dispatching, spawning, launching, steering or merging
18843
+ ` + ` work — including when it succeeded. "X was dispatched and completed" is the
18844
+ ` + ` session describing itself. Record only what the work LEARNED or CHANGED.
18845
+ ` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
18846
+ ` + ` running) — retain the outcome only once the task completes or a decision is made.
18847
+ ` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
18848
+ ` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
18849
+ ` + ` reset assistant state").
18850
+ ` + `- Hindsight's own errors, retries, backlogs, or internal state — the memory
18851
+ ` + ` system's self-reports are not memories.
18852
+ ` + `- Restatements of the user's current request or the task in progress.
18853
+ ` + `- Transient state (unread counts, build status, what is running right now) unless
18854
+ ` + ` the fact is explicitly dated, in which case record it as a dated observation.
18855
+ ` + `- Greetings, acknowledgements, and routine operational chatter.
18856
+ ` + `
18857
+ ` + `Write each fact so it stands alone: name the thing, the number, and the date. A
18858
+ ` + `sentence that only makes sense while reading this transcript is not durable.
18859
+ ` + `
18860
+ ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
18861
+ ` + `nothing durable remains, return an empty facts list.
18862
+ `
18757
18863
  ];
18758
18864
  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.
18759
18865
  ` + `
@@ -2120,7 +2120,7 @@ var init_esm = __esm(() => {
2120
2120
  });
2121
2121
 
2122
2122
  // src/build-info.ts
2123
- var VERSION = "0.19.32", COMMIT_SHA = "5ccce0a7";
2123
+ var VERSION = "0.19.33", COMMIT_SHA = "4ccbde6b";
2124
2124
 
2125
2125
  // src/cli/resolve-version.ts
2126
2126
  import { existsSync, readFileSync } from "node:fs";
@@ -15789,9 +15789,9 @@ function hindsightPgEnv(overrides = new Map) {
15789
15789
  }
15790
15790
  return out;
15791
15791
  }
15792
- var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION, HINDSIGHT_PG_APP_ANON_MIB = 2560, HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048, HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB, HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 1536, HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 4096, HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV = "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE", HINDSIGHT_PG_SHARED_BUFFERS_ENV = "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS", HINDSIGHT_PG_DEFAULTS, HINDSIGHT_PG_ENV_KEYS;
15792
+ var HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION, HINDSIGHT_PG_APP_ANON_MIB = 2560, HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB = 2048, HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB, HINDSIGHT_PG_DEFAULT_SHARED_BUFFERS_MIB = 3072, HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 7168, HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV = "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE", HINDSIGHT_PG_SHARED_BUFFERS_ENV = "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS", HINDSIGHT_PG_DEFAULTS, HINDSIGHT_PG_ENV_KEYS;
15793
15793
  var init_hindsight_pg_defaults = __esm(() => {
15794
- HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 8 * 1024;
15794
+ HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION = 16 * 1024;
15795
15795
  HINDSIGHT_PG_SHARED_BUFFERS_BUDGET_MIB = HINDSIGHT_PG_MEM_LIMIT_MIB_FOR_DERIVATION - HINDSIGHT_PG_APP_ANON_MIB - HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
15796
15796
  HINDSIGHT_PG_DEFAULTS = [
15797
15797
  [
@@ -16967,7 +16967,7 @@ async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFA
16967
16967
  atomicWriteFileSync2(configPath, tail, mode);
16968
16968
  return { added: true, reason: "added" };
16969
16969
  }
16970
- var HINDSIGHT_DEFAULT_API_PORT = 18888, HINDSIGHT_DEFAULT_UI_PORT = 9999, HINDSIGHT_DEFAULT_MCP_URL, HINDSIGHT_DEFAULT_API_BASE_URL, HINDSIGHT_CONSUMER_NAME = "hindsight", HINDSIGHT_DEFAULT_WORKER_ID = "switchroom-hindsight", HINDSIGHT_DATA_VOLUME = "switchroom-hindsight-data", HINDSIGHT_DEFAULT_UID = 11000, HINDSIGHT_IMAGE_REPO = "ghcr.io/switchroom/switchroom-hindsight", HINDSIGHT_IMAGE, HINDSIGHT_DEFAULT_MODEL = "claude-sonnet-5", HINDSIGHT_DEFAULT_LITELLM_MODEL = "openrouter/google/gemini-3.1-flash-lite", HINDSIGHT_DEFAULT_MCP_STATELESS = true, HINDSIGHT_BROKER_SOCK_VOLUME, HINDSIGHT_CREDS_MIRROR_VOLUME, HINDSIGHT_CRED_DIR = "/run/claude-creds", HINDSIGHT_RETAIN_CHUNK_SIZE = 3000, HINDSIGHT_DEFAULT_RETAIN_MAX_COMPLETION_TOKENS = 16384, HINDSIGHT_RETAIN_MIN_TOKENS_PER_SECOND = 80.6, HINDSIGHT_RETAIN_CLIENT_DEADLINE_S, HINDSIGHT_DEFAULT_MEM_LIMIT = "8g", HINDSIGHT_DEFAULT_MEM_RESERVATION = "4g", HINDSIGHT_DEFAULT_PIDS_LIMIT = 1000, HINDSIGHT_DEFAULT_SHM_SIZE = "2g", HINDSIGHT_HEALTHCHECK_PY = 'import urllib.request,sys; sys.exit(0 if urllib.request.urlopen("http://localhost:8888/health",timeout=4).getcode()==200 else 1)', HINDSIGHT_HEALTHCHECK_CMD, DOCKER_PROBE_TIMEOUT_MS, defaultDockerProbe = (args) => {
16970
+ var HINDSIGHT_DEFAULT_API_PORT = 18888, HINDSIGHT_DEFAULT_UI_PORT = 9999, HINDSIGHT_DEFAULT_MCP_URL, HINDSIGHT_DEFAULT_API_BASE_URL, HINDSIGHT_CONSUMER_NAME = "hindsight", HINDSIGHT_DEFAULT_WORKER_ID = "switchroom-hindsight", HINDSIGHT_DATA_VOLUME = "switchroom-hindsight-data", HINDSIGHT_DEFAULT_UID = 11000, HINDSIGHT_IMAGE_REPO = "ghcr.io/switchroom/switchroom-hindsight", HINDSIGHT_IMAGE, HINDSIGHT_DEFAULT_MODEL = "claude-sonnet-5", HINDSIGHT_DEFAULT_LITELLM_MODEL = "openrouter/google/gemini-3.1-flash-lite", HINDSIGHT_DEFAULT_MCP_STATELESS = true, HINDSIGHT_BROKER_SOCK_VOLUME, HINDSIGHT_CREDS_MIRROR_VOLUME, HINDSIGHT_CRED_DIR = "/run/claude-creds", HINDSIGHT_RETAIN_CHUNK_SIZE = 3000, HINDSIGHT_DEFAULT_RETAIN_MAX_COMPLETION_TOKENS = 16384, HINDSIGHT_RETAIN_MIN_TOKENS_PER_SECOND = 80.6, HINDSIGHT_RETAIN_CLIENT_DEADLINE_S, HINDSIGHT_DEFAULT_MEM_LIMIT = "16g", HINDSIGHT_DEFAULT_MEM_RESERVATION = "4g", HINDSIGHT_DEFAULT_PIDS_LIMIT = 1000, HINDSIGHT_DEFAULT_SHM_SIZE = "2g", HINDSIGHT_HEALTHCHECK_PY = 'import urllib.request,sys; sys.exit(0 if urllib.request.urlopen("http://localhost:8888/health",timeout=4).getcode()==200 else 1)', HINDSIGHT_HEALTHCHECK_CMD, DOCKER_PROBE_TIMEOUT_MS, defaultDockerProbe = (args) => {
16971
16971
  try {
16972
16972
  return execFileSync("docker", args, {
16973
16973
  stdio: "pipe",
@@ -17662,7 +17662,17 @@ var HINDSIGHT_SHIM_CLI_PATH = "/usr/local/bin/switchroom", HINDSIGHT_SHIM_AGENT_
17662
17662
  var init_hindsight2 = __esm(() => {
17663
17663
  init_users();
17664
17664
  init_hindsight();
17665
- DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and useful weeks from now: user preferences and standing rules, ongoing projects and recurring commitments, technical and architectural decisions with their rationale, and people/tool relationships. A preference revealed by a request is durable \u2014 record the preference (what the user likes, wants, or always does), not the request itself.
17665
+ DEFAULT_RETAIN_MISSION = `Extract durable facts that will still be true and useful weeks from now, once this session is forgotten.
17666
+ ` + `
17667
+ ` + `DURABILITY GATE. Emit a candidate ONLY if it is one of these five classes:
17668
+ ` + `- PREFERENCE \u2014 what the user likes, wants, or always does; a standing rule or correction.
17669
+ ` + `- 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.
17670
+ ` + `- FINDING \u2014 a root cause, a measurement, or verified behaviour of a system. Include the number.
17671
+ ` + `- OUTCOME \u2014 a completed result that changed the world: what shipped, what a thing turned out to be. Not the act of shipping it.
17672
+ ` + `- RELATIONSHIP \u2014 who a person is, what a project or tool is, and how they connect.
17673
+ ` + `If a candidate fits none of the five, it is not a memory. Drop it; do not reword it into one.
17674
+ ` + `
17675
+ ` + `A preference revealed by a request is durable \u2014 record the preference (what the user likes, wants, or always does), not the request itself.
17666
17676
  ` + `
17667
17677
  ` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
17668
17678
  ` + `candidate a file path, a command/process/agent/session id, a temp directory, or
@@ -17679,6 +17689,9 @@ var init_hindsight2 = __esm(() => {
17679
17689
  ` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
17680
17690
  ` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
17681
17691
  ` + ` assistant used X to query Y", "ran a search", "sent the message").
17692
+ ` + `- The act of delegating, dispatching, spawning, launching, steering or merging
17693
+ ` + ` work \u2014 including when it succeeded. "X was dispatched and completed" is the
17694
+ ` + ` session describing itself. Record only what the work LEARNED or CHANGED.
17682
17695
  ` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
17683
17696
  ` + ` running) \u2014 retain the outcome only once the task completes or a decision is made.
17684
17697
  ` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
@@ -17701,8 +17714,12 @@ var init_hindsight2 = __esm(() => {
17701
17714
  ` + ` the fact is explicitly dated, in which case record it as a dated observation.
17702
17715
  ` + `- Greetings, acknowledgements, and routine operational chatter.
17703
17716
  ` + `
17717
+ ` + `Write each fact so it stands alone: name the thing, the number, and the date. A
17718
+ ` + `sentence that only makes sense while reading this transcript is not durable.
17719
+ ` + `
17704
17720
  ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
17705
- ` + "nothing durable remains, return an empty facts list.";
17721
+ ` + `nothing durable remains, return an empty facts list.
17722
+ `;
17706
17723
  SUPERSEDED_RETAIN_MISSIONS = [
17707
17724
  "Extract technical decisions, architectural choices, user preferences, project context, and people/tool relationships. Ignore routine greetings and transient operational details.",
17708
17725
  "Extract user preferences, ongoing projects, recurring commitments, " + "important context, and durable facts that should help across future " + "conversations. Skip one-off chatter and temporary task noise.",
@@ -17749,7 +17766,96 @@ var init_hindsight2 = __esm(() => {
17749
17766
  ` + `- Greetings, acknowledgements, and routine operational chatter.
17750
17767
  ` + `
17751
17768
  ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
17752
- ` + "nothing durable remains, return an empty facts list."
17769
+ ` + "nothing durable remains, return an empty facts list.",
17770
+ `Extract durable facts that will still be true and useful weeks from now: user preferences and standing rules, ongoing projects and recurring commitments, technical and architectural decisions with their rationale, and people/tool relationships. A preference revealed by a request is durable \u2014 record the preference (what the user likes, wants, or always does), not the request itself.
17771
+ ` + `
17772
+ ` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
17773
+ ` + `candidate a file path, a command/process/agent/session id, a temp directory, or
17774
+ ` + `the location where some output was written? If yes, drop it \u2014 it is transcript
17775
+ ` + `exhaust, not memory.
17776
+ ` + `
17777
+ ` + `NEVER extract:
17778
+ ` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
17779
+ ` + ` text resembles any of these: "File created successfully at /path/to/file",
17780
+ ` + ` "A background command with ID bctz4yskm is running, and its output will be
17781
+ ` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
17782
+ ` + ` and is running in the background", "User executed a Bash command to sleep for
17783
+ ` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
17784
+ ` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
17785
+ ` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
17786
+ ` + ` assistant used X to query Y", "ran a search", "sent the message").
17787
+ ` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
17788
+ ` + ` running) \u2014 retain the outcome only once the task completes or a decision is made.
17789
+ ` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
17790
+ ` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
17791
+ ` + ` reset assistant state").
17792
+ ` + `- Hindsight's own errors, retries, backlogs, or internal state \u2014 the memory
17793
+ ` + ` system's self-reports are not memories.
17794
+ ` + `- Restatements of the user's current request or the task in progress.
17795
+ ` + `- Volatile state written as a timeless assertion. A version, count, size,
17796
+ ` + ` backlog, status, or any "X is running Y" / "X is at Y" / "X is currently Y"
17797
+ ` + ` claim is true only at the instant it was said. Concretely, never produce a
17798
+ ` + ` fact whose text resembles any of these: "Switchroom fleet is running image
17799
+ ` + ` version v0.18.19", "The switchroom repo is at /path/to/fleet, version
17800
+ ` + ` v0.19.5", "Bank overlord has 43155 pending consolidations", "The build is
17801
+ ` + ` currently green". If the claim is worth keeping, put the date INSIDE the
17802
+ ` + ` fact text ("As of 2026-07-19 the fleet was running v0.18.19"); if you
17803
+ ` + ` cannot date it, drop it. An undated one is recalled forever as though it
17804
+ ` + ` were still true, which is worse than not remembering it at all.
17805
+ ` + `- Transient state (unread counts, build status, what is running right now) unless
17806
+ ` + ` the fact is explicitly dated, in which case record it as a dated observation.
17807
+ ` + `- Greetings, acknowledgements, and routine operational chatter.
17808
+ ` + `
17809
+ ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
17810
+ ` + "nothing durable remains, return an empty facts list.",
17811
+ `Extract durable facts that will still be true and useful weeks from now, once this session is forgotten.
17812
+ ` + `
17813
+ ` + `DURABILITY GATE. Emit a candidate ONLY if it is one of these five classes:
17814
+ ` + `- PREFERENCE \u2014 what the user likes, wants, or always does; a standing rule or correction.
17815
+ ` + `- 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.
17816
+ ` + `- FINDING \u2014 a root cause, a measurement, or verified behaviour of a system. Include the number.
17817
+ ` + `- OUTCOME \u2014 a completed result that changed the world: what shipped, what a thing turned out to be. Not the act of shipping it.
17818
+ ` + `- RELATIONSHIP \u2014 who a person is, what a project or tool is, and how they connect.
17819
+ ` + `If a candidate fits none of the five, it is not a memory. Drop it; do not reword it into one.
17820
+ ` + `
17821
+ ` + `A preference revealed by a request is durable \u2014 record the preference (what the user likes, wants, or always does), not the request itself.
17822
+ ` + `
17823
+ ` + `A TOOL RESULT IS NOT A FACT. Before extracting, ask: is the subject of this
17824
+ ` + `candidate a file path, a command/process/agent/session id, a temp directory, or
17825
+ ` + `the location where some output was written? If yes, drop it \u2014 it is transcript
17826
+ ` + `exhaust, not memory.
17827
+ ` + `
17828
+ ` + `NEVER extract:
17829
+ ` + `- Tool results verbatim or paraphrased. Concretely, never produce a fact whose
17830
+ ` + ` text resembles any of these: "File created successfully at /path/to/file",
17831
+ ` + ` "A background command with ID bctz4yskm is running, and its output will be
17832
+ ` + ` written to /tmp/...", "Async agent a745598ba84e71df1 was launched successfully
17833
+ ` + ` and is running in the background", "User executed a Bash command to sleep for
17834
+ ` + ` 200 seconds", "The assistant used grep to locate 'truncateSync' in src/foo.ts".
17835
+ ` + `- Anything mentioning a path under /tmp, a scratchpad directory, or a .tmp file.
17836
+ ` + `- Agent tool-use traces or narration of what the assistant did (e.g. "the
17837
+ ` + ` assistant used X to query Y", "ran a search", "sent the message").
17838
+ ` + `- The act of delegating, dispatching, spawning, launching, steering or merging
17839
+ ` + ` work \u2014 including when it succeeded. "X was dispatched and completed" is the
17840
+ ` + ` session describing itself. Record only what the work LEARNED or CHANGED.
17841
+ ` + `- In-flight workflow/process narration (a sub-task started, paused, or is still
17842
+ ` + ` running) \u2014 retain the outcome only once the task completes or a decision is made.
17843
+ ` + `- Operation, request, batch, agent, command or session IDs, UUIDs, hashes, or error codes.
17844
+ ` + `- Slash commands the user typed and their effects (e.g. "User issued /clear to
17845
+ ` + ` reset assistant state").
17846
+ ` + `- Hindsight's own errors, retries, backlogs, or internal state \u2014 the memory
17847
+ ` + ` system's self-reports are not memories.
17848
+ ` + `- Restatements of the user's current request or the task in progress.
17849
+ ` + `- Transient state (unread counts, build status, what is running right now) unless
17850
+ ` + ` the fact is explicitly dated, in which case record it as a dated observation.
17851
+ ` + `- Greetings, acknowledgements, and routine operational chatter.
17852
+ ` + `
17853
+ ` + `Write each fact so it stands alone: name the thing, the number, and the date. A
17854
+ ` + `sentence that only makes sense while reading this transcript is not durable.
17855
+ ` + `
17856
+ ` + `If a candidate fact matches an exclusion, drop it rather than rewording it. If
17857
+ ` + `nothing durable remains, return an empty facts list.
17858
+ `
17753
17859
  ];
17754
17860
  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.
17755
17861
  ` + `
@@ -37563,6 +37669,34 @@ var init_via_claude = __esm(() => {
37563
37669
  ];
37564
37670
  });
37565
37671
 
37672
+ // src/cli/self-invoke.ts
37673
+ function isCompiledBinaryPath(scriptPath) {
37674
+ if (!scriptPath)
37675
+ return false;
37676
+ return scriptPath.startsWith(BUNFS_POSIX_PREFIX) || BUNFS_WINDOWS_RE.test(scriptPath);
37677
+ }
37678
+ function resolveSelfInvocation(probe = {}) {
37679
+ const execPath = probe.execPath ?? process.execPath;
37680
+ const scriptPath = probe.scriptPath ?? process.argv[1] ?? "";
37681
+ if (isCompiledBinaryPath(scriptPath)) {
37682
+ if (execPath)
37683
+ return { command: execPath, prefixArgs: [], compiled: true };
37684
+ return { command: "switchroom", prefixArgs: [], compiled: true };
37685
+ }
37686
+ if (!execPath || !scriptPath) {
37687
+ return { command: "switchroom", prefixArgs: [], compiled: false };
37688
+ }
37689
+ return { command: execPath, prefixArgs: [scriptPath], compiled: false };
37690
+ }
37691
+ function selfInvokeArgv(args, probe = {}) {
37692
+ const inv = resolveSelfInvocation(probe);
37693
+ return { command: inv.command, argv: [...inv.prefixArgs, ...args] };
37694
+ }
37695
+ var BUNFS_POSIX_PREFIX = "/$bunfs", BUNFS_WINDOWS_RE;
37696
+ var init_self_invoke = __esm(() => {
37697
+ BUNFS_WINDOWS_RE = /^[a-z]:[/\\]~BUN[/\\]/i;
37698
+ });
37699
+
37566
37700
  // src/vault/migrate-layout.ts
37567
37701
  import {
37568
37702
  copyFileSync as copyFileSync7,
@@ -39405,6 +39539,12 @@ function parseAuditLine2(line) {
39405
39539
  entry.m = o.m;
39406
39540
  if (typeof o.prior_pin === "string")
39407
39541
  entry.prior_pin = o.prior_pin;
39542
+ if (Array.isArray(o.prior_pin_observed) && o.prior_pin_observed.every((v) => typeof v === "string")) {
39543
+ entry.prior_pin_observed = o.prior_pin_observed;
39544
+ }
39545
+ if (typeof o.prior_pin_source === "string") {
39546
+ entry.prior_pin_source = o.prior_pin_source;
39547
+ }
39408
39548
  return entry;
39409
39549
  }
39410
39550
  function filterEntries(entries, filters) {
@@ -50611,12 +50751,13 @@ function findUnwritableAgentDirs(config, opts) {
50611
50751
  }
50612
50752
  return unwritable;
50613
50753
  }
50614
- function buildSelfElevateArgv() {
50754
+ function buildSelfElevateArgv(probe2 = {}) {
50615
50755
  const passthrough = process.argv.slice(2);
50756
+ const self = resolveSelfInvocation(probe2);
50616
50757
  return [
50617
50758
  `--preserve-env=${SELF_ELEVATE_PRESERVED_ENV.join(",")}`,
50618
- process.execPath,
50619
- process.argv[1] ?? "",
50759
+ self.command,
50760
+ ...self.prefixArgs,
50620
50761
  ...passthrough,
50621
50762
  "--skip-self-elevate"
50622
50763
  ];
@@ -50795,6 +50936,7 @@ var init_apply = __esm(() => {
50795
50936
  init_fleet_defaults();
50796
50937
  init_connection_health();
50797
50938
  init_update_prompt_hook();
50939
+ init_self_invoke();
50798
50940
  init_compose();
50799
50941
  init_external_spend();
50800
50942
  init_write_compose();
@@ -77566,6 +77708,7 @@ function suggestVaultKeys(requested, available, max = 3) {
77566
77708
  // src/cli/vault-broker.ts
77567
77709
  init_loader();
77568
77710
  init_loader();
77711
+ init_self_invoke();
77569
77712
  init_client();
77570
77713
  import { readFileSync as readFileSync40, existsSync as existsSync44, unlinkSync as unlinkSync11 } from "node:fs";
77571
77714
  import { spawn as spawn4 } from "node:child_process";
@@ -82024,11 +82167,11 @@ function registerVaultBrokerCommand(vaultCmd, program3) {
82024
82167
  console.log(" To unlock it: `switchroom vault broker unlock`.");
82025
82168
  process.exit(0);
82026
82169
  } else {
82027
- const self = process.argv[1];
82028
82170
  const args = ["vault", "broker", "start", "--foreground"];
82029
82171
  if (parentOpts.config)
82030
82172
  args.unshift("--config", parentOpts.config);
82031
- const child = spawn4(process.execPath, [self, ...args], {
82173
+ const self = resolveSelfInvocation();
82174
+ const child = spawn4(self.command, [...self.prefixArgs, ...args], {
82032
82175
  detached: true,
82033
82176
  stdio: "ignore"
82034
82177
  });
@@ -91795,6 +91938,7 @@ function defaultSelfUpdateIO() {
91795
91938
  }
91796
91939
 
91797
91940
  // src/cli/update.ts
91941
+ init_self_invoke();
91798
91942
  init_component_versions();
91799
91943
  function defaultPersistPin(configPath) {
91800
91944
  return (pin) => {
@@ -91867,6 +92011,11 @@ function planUpdate(opts) {
91867
92011
  const composePath = opts.composePath ?? DEFAULT_COMPOSE_PATH2;
91868
92012
  const runner = opts.runner ?? defaultRunner2;
91869
92013
  const scriptPath = opts.scriptPath ?? process.argv[1] ?? "";
92014
+ const self = resolveSelfInvocation({
92015
+ execPath: opts.execPath ?? process.execPath,
92016
+ scriptPath
92017
+ });
92018
+ const selfArgv = (...args) => [...self.prefixArgs, ...args];
91870
92019
  const steps = [];
91871
92020
  const hostdContext = typeof opts.hostdContext === "boolean" ? opts.hostdContext : isHostdContext();
91872
92021
  steps.push({
@@ -91943,13 +92092,7 @@ function planUpdate(opts) {
91943
92092
  name: "regen-compose-for-release-override",
91944
92093
  description: "Regenerate compose with the --channel/--pin override so pull-images grabs the right tag",
91945
92094
  run: () => {
91946
- const r = runner(process.execPath, [
91947
- scriptPath,
91948
- "apply",
91949
- "--compose-only",
91950
- "--non-interactive",
91951
- ...releaseOverrideArgs
91952
- ]);
92095
+ const r = runner(self.command, selfArgv("apply", "--compose-only", "--non-interactive", ...releaseOverrideArgs));
91953
92096
  if (r.status !== 0) {
91954
92097
  throw new Error("regen-compose-for-release-override failed");
91955
92098
  }
@@ -91999,13 +92142,7 @@ function planUpdate(opts) {
91999
92142
  name: "apply-config",
92000
92143
  description: "switchroom apply \u2014 refresh per-agent scaffolds + compose",
92001
92144
  run: () => {
92002
- const r = runner(process.execPath, [
92003
- scriptPath,
92004
- "apply",
92005
- "--non-interactive",
92006
- "--no-doctor",
92007
- ...releaseOverrideArgs
92008
- ]);
92145
+ const r = runner(self.command, selfArgv("apply", "--non-interactive", "--no-doctor", ...releaseOverrideArgs));
92009
92146
  if (r.status !== 0)
92010
92147
  throw new Error("switchroom apply failed");
92011
92148
  }
@@ -92026,7 +92163,7 @@ function planUpdate(opts) {
92026
92163
  skipReason: !hostControlEnabled ? "host_control.enabled is not true \u2014 daemon not in use" : opts.skipImages ? "--skip-images flag set" : hostdContext ? "deferred (hostd-context): finish host-side via `switchroom hostd install` \u2014 update_apply cannot recreate its own hostd container without SIGKILLing itself (#2458)" : undefined,
92027
92164
  isHostdDeferred: hostControlEnabled && !opts.skipImages && hostdContext,
92028
92165
  run: () => {
92029
- const r = runner(process.execPath, [scriptPath, "hostd", "install"]);
92166
+ const r = runner(self.command, selfArgv("hostd", "install"));
92030
92167
  if (r.status !== 0)
92031
92168
  throw new Error("switchroom hostd install failed");
92032
92169
  }
@@ -92047,7 +92184,7 @@ function planUpdate(opts) {
92047
92184
  skipReason: !webServiceManaged ? "web_service.managed is not true \u2014 web container not in use (legacy systemd unit)" : opts.skipImages ? "--skip-images flag set" : hostdContext ? "deferred (hostd-context): finish host-side via `switchroom webd install` \u2014 update_apply cannot recreate the web container without SIGKILLing the hostd container it shares a compose project with (#2458)" : undefined,
92048
92185
  isHostdDeferred: webServiceManaged && !opts.skipImages && hostdContext,
92049
92186
  run: () => {
92050
- const r = runner(process.execPath, [scriptPath, "webd", "install"]);
92187
+ const r = runner(self.command, selfArgv("webd", "install"));
92051
92188
  if (r.status !== 0)
92052
92189
  throw new Error("switchroom webd install failed");
92053
92190
  }
@@ -92071,7 +92208,7 @@ function planUpdate(opts) {
92071
92208
  const setupArgs = ["memory", "setup", "--recreate"];
92072
92209
  if (pinTag)
92073
92210
  setupArgs.push("--tag", pinTag);
92074
- const r = runner(process.execPath, [scriptPath, ...setupArgs]);
92211
+ const r = runner(self.command, selfArgv(...setupArgs));
92075
92212
  if (r.status !== 0)
92076
92213
  throw new Error("switchroom memory setup --recreate failed");
92077
92214
  }
@@ -92184,7 +92321,7 @@ function planUpdate(opts) {
92184
92321
  name: "doctor",
92185
92322
  description: "switchroom doctor \u2014 surface post-bounce diagnostics",
92186
92323
  run: () => {
92187
- runner(process.execPath, [scriptPath, "doctor"]);
92324
+ runner(self.command, selfArgv("doctor"));
92188
92325
  }
92189
92326
  });
92190
92327
  return steps;
@@ -92720,6 +92857,7 @@ function recoverPinJournal(configPath, opts = {}) {
92720
92857
 
92721
92858
  // src/cli/rollout.ts
92722
92859
  init_operator_uid();
92860
+ init_self_invoke();
92723
92861
  init_atomic();
92724
92862
  init_resolve_version();
92725
92863
  init_audit_reader();
@@ -93155,6 +93293,10 @@ function createRolloutDeps(params) {
93155
93293
  const { configPath, scriptPath, hostdCtx } = params;
93156
93294
  const spawn6 = params.spawn ?? spawnSync18;
93157
93295
  const warn = params.warn ?? ((line) => process.stderr.write(line));
93296
+ const self = resolveSelfInvocation({
93297
+ execPath: params.execPath ?? process.execPath,
93298
+ scriptPath
93299
+ });
93158
93300
  const dockerRun = (args) => {
93159
93301
  let r;
93160
93302
  try {
@@ -93189,7 +93331,7 @@ function createRolloutDeps(params) {
93189
93331
  };
93190
93332
  return {
93191
93333
  run: (args, opts) => {
93192
- const r = spawn6(process.execPath, [scriptPath, ...args], {
93334
+ const r = spawn6(self.command, [...self.prefixArgs, ...args], {
93193
93335
  stdio: "inherit",
93194
93336
  env: opts?.env ? { ...process.env, ...opts.env } : process.env,
93195
93337
  timeout: ROLLOUT_RUN_TIMEOUT_MS,
@@ -93351,7 +93493,7 @@ function registerRolloutCommand(program3) {
93351
93493
  return;
93352
93494
  }
93353
93495
  const configPath = getConfigPath(program3);
93354
- const scriptPath = process.argv[1] ?? "switchroom";
93496
+ const scriptPath = process.argv[1] ?? "";
93355
93497
  const deps = createRolloutDeps({ configPath, scriptPath, hostdCtx });
93356
93498
  process.stdout.write(`${opts.allowDowngrade ? "Rolling back" : "Rolling"} ${requested.length} agent(s) to ${target}\u2026
93357
93499
  `);
@@ -101008,6 +101150,7 @@ function scanBundleForSecrets(files) {
101008
101150
  // src/cli/skill.ts
101009
101151
  init_loader();
101010
101152
  init_helpers();
101153
+ init_self_invoke();
101011
101154
  init_source();
101012
101155
  var SKILL_NAME_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/;
101013
101156
  var SH_SCRIPT_RE2 = /^scripts\/[A-Za-z0-9_.-]+\.sh$/;
@@ -101346,9 +101489,9 @@ function registerSkillCommand(program3) {
101346
101489
  writePayload(poolDir, name, files);
101347
101490
  console.log(source_default.green(`
101348
101491
  \u2713 Wrote ${name} to ${currentDir}`));
101349
- const applyBin = process.argv[1] ?? "switchroom";
101492
+ const self = selfInvokeArgv(["apply", "--non-interactive"]);
101350
101493
  console.log(source_default.gray(`Running \`switchroom apply --non-interactive\`...`));
101351
- const r = spawnSync20(process.argv0, [applyBin, "apply", "--non-interactive"], { stdio: "inherit" });
101494
+ const r = spawnSync20(self.command, self.argv, { stdio: "inherit" });
101352
101495
  if (r.status !== 0) {
101353
101496
  console.error(source_default.yellow(`(warning: \`switchroom apply\` exited ${r.status} \u2014 skill is ` + `in the pool but symlinks may not be refreshed. Re-run manually.)`));
101354
101497
  }