switchroom 0.20.12 → 0.20.13
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.
- package/dist/agent-scheduler/index.js +1 -0
- package/dist/auth-broker/index.js +5 -1
- package/dist/cli/notion-write-pretool.mjs +1 -0
- package/dist/cli/self-improve-stop.mjs +13 -1
- package/dist/cli/switchroom.js +1472 -89
- package/dist/host-control/main.js +6 -2
- package/dist/vault/approvals/kernel-server.js +5 -1
- package/dist/vault/broker/server.js +5 -1
- package/package.json +7 -4
- package/skills/switchroom-release/SKILL.md +3 -2
- package/telegram-plugin/bunfig.toml +9 -5
- package/telegram-plugin/dist/gateway/gateway.js +169 -68
- package/telegram-plugin/gateway/captured-answer-resume.ts +23 -1
- package/telegram-plugin/gateway/gateway.ts +1 -0
- package/telegram-plugin/gateway/outbound-send-path.ts +111 -6
- package/telegram-plugin/gateway/outbox-sweep.ts +69 -0
- package/telegram-plugin/gateway/stream-render.ts +4 -0
- package/telegram-plugin/hooks/audience-classify.d.mts +26 -0
- package/telegram-plugin/hooks/audience-classify.mjs +193 -0
- package/telegram-plugin/hooks/silent-end-interrupt-stop.mjs +31 -1
- package/telegram-plugin/hooks/silent-end-scan.mjs +8 -1
- package/telegram-plugin/outbox.ts +69 -3
- package/telegram-plugin/silent-end.ts +48 -5
- package/telegram-plugin/tests/captured-answer-resume.test.ts +26 -11
- package/telegram-plugin/tests/hindsight-bank-preload.test.ts +50 -0
- package/telegram-plugin/tests/outbox-live-path-review-4490.test.ts +613 -0
- package/telegram-plugin/tests/outbox-self-improve-review.test.ts +401 -0
|
@@ -11433,6 +11433,7 @@ var init_schema = __esm(() => {
|
|
|
11433
11433
|
}).describe("Per-operation LLM override. Every field optional; an unset field (or " + "an omitted op block) inherits the global `hindsight.llm.*`, which is " + "already the engine's fallback — switchroom emits only the vars set.");
|
|
11434
11434
|
HindsightConfigSchema = exports_external.object({
|
|
11435
11435
|
gpu: exports_external.boolean().optional().describe("Force GPU passthrough for the hindsight container on (`true`) or off " + "(`false`), overriding host autodetection in BOTH directions. Absent " + "(the default) → autodetect from the persisted host-capabilities " + "verdict (`~/.switchroom/host-capabilities.json`), which enables " + "`--gpus all` only when that file proves BOTH a GPU and the nvidia " + "container toolkit. Set `true` when that verdict is wrong or unreadable " + "and you know the host has a working toolkit — switchroom cannot verify " + "it for you, and `docker run --gpus all` hard-fails container create on " + "a host without one. Set `false` to pin the container to CPU on a GPU " + "host. This is also the declarative opt-out for the recreate-time GPU " + "drop guard (`switchroom memory setup --recreate` refuses to silently " + "turn a GPU container into a CPU one). `--gpu`/`--no-gpu` on `memory " + "setup` override this for a single run."),
|
|
11436
|
+
mem_limit: exports_external.string().regex(/^\d+(\.\d+)?\s*[bkmgt]?b?$/i, "hindsight.mem_limit must be a docker memory size, e.g. `24g` or `16384m`").optional().describe("Hard memory cap for the hindsight container — docker `--memory` on the " + "`memory setup` path and `mem_limit:` in the emitted compose snippet. A " + "docker size string (`24g`, `16384m`). Absent → switchroom's default " + "(`HINDSIGHT_DEFAULT_MEM_LIMIT`, 16g). This is a docker HostConfig flag, " + "not a container env var, which is why it is a first-class field here " + "rather than an `env:` key. **Move it together with " + "`env.SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS`**: Postgres pins the " + "buffer pool as unreclaimable shared memory inside this cap, so a cap " + "that does not clear `shared_buffers` by the container's app working " + "set plus its page-cache floor puts Postgres in a near-OOM " + "configuration. switchroom warns, naming both numbers, when it does " + "not. A value below the container's memory RESERVATION (4g) is " + "rejected outright — docker will not create such a container."),
|
|
11436
11437
|
cp_access_key: exports_external.string().min(1).optional().describe("Access key for the hindsight control-plane DASHBOARD (upstream " + "`HINDSIGHT_CP_ACCESS_KEY`, port 9999). Literal or — strongly preferred " + "— a `vault:` reference such as `vault:hindsight_cp_access_key`, read " + "through the broker at container-launch time. This is the ONLY thing " + "that arms the dashboard's login: upstream's middleware short-circuits " + "to `next()` when the var is unset, so an unset key means the dashboard " + "has no authentication at all, not weak authentication. Because of that, " + "leaving it unset is FAIL-CLOSED: switchroom pins " + "`HINDSIGHT_CP_HOSTNAME=127.0.0.1` so the loginless dashboard is " + "reachable only from the host, and warns. Set this to serve the " + "dashboard on the LAN/tailnet."),
|
|
11437
11438
|
llm: exports_external.object({
|
|
11438
11439
|
provider: exports_external.string().min(1).optional().describe("Hindsight LLM provider (upstream `HINDSIGHT_API_LLM_PROVIDER`). " + "Defaults to `claude-code` (subscription-honest, broker-fed OAuth). " + "Any litellm-routable provider the upstream image supports is valid. " + "Serves as the GLOBAL default for every op absent a per-op override."),
|
|
@@ -21558,7 +21559,7 @@ function allocateAgentUid(name) {
|
|
|
21558
21559
|
}
|
|
21559
21560
|
|
|
21560
21561
|
// src/build-info.ts
|
|
21561
|
-
var VERSION = "0.20.
|
|
21562
|
+
var VERSION = "0.20.13";
|
|
21562
21563
|
|
|
21563
21564
|
// src/setup/hindsight-recall-passthrough.ts
|
|
21564
21565
|
var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
|
|
@@ -21708,6 +21709,7 @@ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 12288;
|
|
|
21708
21709
|
function pgMib(mib) {
|
|
21709
21710
|
return `${mib}MB`;
|
|
21710
21711
|
}
|
|
21712
|
+
var HINDSIGHT_PG_MIN_NON_BUFFER_MIB = HINDSIGHT_PG_APP_ANON_MIB + HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
|
|
21711
21713
|
var HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV = "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE";
|
|
21712
21714
|
var HINDSIGHT_PG_SHARED_BUFFERS_ENV = "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS";
|
|
21713
21715
|
var HINDSIGHT_PG_FSYNC_ENV = "SWITCHROOM_HINDSIGHT_PG_FSYNC";
|
|
@@ -21755,6 +21757,7 @@ var HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY = 0.3;
|
|
|
21755
21757
|
var HINDSIGHT_DEFAULT_LLM_SUPPORTS_MAX_ITEMS = "false";
|
|
21756
21758
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
|
|
21757
21759
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_HALFLIFE_DAYS = 30;
|
|
21760
|
+
var HINDSIGHT_DEFAULT_TEXT_SEARCH_EXTENSION = "pg_search";
|
|
21758
21761
|
var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
21759
21762
|
[
|
|
21760
21763
|
"HINDSIGHT_API_RECALL_MAX_CANDIDATES_PER_SOURCE",
|
|
@@ -21820,7 +21823,8 @@ var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
|
21820
21823
|
[
|
|
21821
21824
|
"HINDSIGHT_API_GRAPH_SEED_MIN_SIMILARITY",
|
|
21822
21825
|
String(HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY)
|
|
21823
|
-
]
|
|
21826
|
+
],
|
|
21827
|
+
["HINDSIGHT_API_TEXT_SEARCH_EXTENSION", HINDSIGHT_DEFAULT_TEXT_SEARCH_EXTENSION]
|
|
21824
21828
|
];
|
|
21825
21829
|
var HINDSIGHT_PERF_DEFAULTS_GPU = [
|
|
21826
21830
|
["HINDSIGHT_API_RERANKER_LOCAL_FP16", HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16],
|
|
@@ -4873,6 +4873,7 @@ var init_schema = __esm(() => {
|
|
|
4873
4873
|
}).describe("Per-operation LLM override. Every field optional; an unset field (or " + "an omitted op block) inherits the global `hindsight.llm.*`, which is " + "already the engine's fallback — switchroom emits only the vars set.");
|
|
4874
4874
|
HindsightConfigSchema = exports_external.object({
|
|
4875
4875
|
gpu: exports_external.boolean().optional().describe("Force GPU passthrough for the hindsight container on (`true`) or off " + "(`false`), overriding host autodetection in BOTH directions. Absent " + "(the default) → autodetect from the persisted host-capabilities " + "verdict (`~/.switchroom/host-capabilities.json`), which enables " + "`--gpus all` only when that file proves BOTH a GPU and the nvidia " + "container toolkit. Set `true` when that verdict is wrong or unreadable " + "and you know the host has a working toolkit — switchroom cannot verify " + "it for you, and `docker run --gpus all` hard-fails container create on " + "a host without one. Set `false` to pin the container to CPU on a GPU " + "host. This is also the declarative opt-out for the recreate-time GPU " + "drop guard (`switchroom memory setup --recreate` refuses to silently " + "turn a GPU container into a CPU one). `--gpu`/`--no-gpu` on `memory " + "setup` override this for a single run."),
|
|
4876
|
+
mem_limit: exports_external.string().regex(/^\d+(\.\d+)?\s*[bkmgt]?b?$/i, "hindsight.mem_limit must be a docker memory size, e.g. `24g` or `16384m`").optional().describe("Hard memory cap for the hindsight container — docker `--memory` on the " + "`memory setup` path and `mem_limit:` in the emitted compose snippet. A " + "docker size string (`24g`, `16384m`). Absent → switchroom's default " + "(`HINDSIGHT_DEFAULT_MEM_LIMIT`, 16g). This is a docker HostConfig flag, " + "not a container env var, which is why it is a first-class field here " + "rather than an `env:` key. **Move it together with " + "`env.SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS`**: Postgres pins the " + "buffer pool as unreclaimable shared memory inside this cap, so a cap " + "that does not clear `shared_buffers` by the container's app working " + "set plus its page-cache floor puts Postgres in a near-OOM " + "configuration. switchroom warns, naming both numbers, when it does " + "not. A value below the container's memory RESERVATION (4g) is " + "rejected outright — docker will not create such a container."),
|
|
4876
4877
|
cp_access_key: exports_external.string().min(1).optional().describe("Access key for the hindsight control-plane DASHBOARD (upstream " + "`HINDSIGHT_CP_ACCESS_KEY`, port 9999). Literal or — strongly preferred " + "— a `vault:` reference such as `vault:hindsight_cp_access_key`, read " + "through the broker at container-launch time. This is the ONLY thing " + "that arms the dashboard's login: upstream's middleware short-circuits " + "to `next()` when the var is unset, so an unset key means the dashboard " + "has no authentication at all, not weak authentication. Because of that, " + "leaving it unset is FAIL-CLOSED: switchroom pins " + "`HINDSIGHT_CP_HOSTNAME=127.0.0.1` so the loginless dashboard is " + "reachable only from the host, and warns. Set this to serve the " + "dashboard on the LAN/tailnet."),
|
|
4877
4878
|
llm: exports_external.object({
|
|
4878
4879
|
provider: exports_external.string().min(1).optional().describe("Hindsight LLM provider (upstream `HINDSIGHT_API_LLM_PROVIDER`). " + "Defaults to `claude-code` (subscription-honest, broker-fed OAuth). " + "Any litellm-routable provider the upstream image supports is valid. " + "Serves as the GLOBAL default for every op absent a per-op override."),
|
|
@@ -19603,6 +19604,7 @@ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 12288;
|
|
|
19603
19604
|
function pgMib(mib) {
|
|
19604
19605
|
return `${mib}MB`;
|
|
19605
19606
|
}
|
|
19607
|
+
var HINDSIGHT_PG_MIN_NON_BUFFER_MIB = HINDSIGHT_PG_APP_ANON_MIB + HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
|
|
19606
19608
|
var HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV = "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE";
|
|
19607
19609
|
var HINDSIGHT_PG_SHARED_BUFFERS_ENV = "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS";
|
|
19608
19610
|
var HINDSIGHT_PG_FSYNC_ENV = "SWITCHROOM_HINDSIGHT_PG_FSYNC";
|
|
@@ -19650,6 +19652,7 @@ var HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY = 0.3;
|
|
|
19650
19652
|
var HINDSIGHT_DEFAULT_LLM_SUPPORTS_MAX_ITEMS = "false";
|
|
19651
19653
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
|
|
19652
19654
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_HALFLIFE_DAYS = 30;
|
|
19655
|
+
var HINDSIGHT_DEFAULT_TEXT_SEARCH_EXTENSION = "pg_search";
|
|
19653
19656
|
var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
19654
19657
|
[
|
|
19655
19658
|
"HINDSIGHT_API_RECALL_MAX_CANDIDATES_PER_SOURCE",
|
|
@@ -19715,7 +19718,8 @@ var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
|
19715
19718
|
[
|
|
19716
19719
|
"HINDSIGHT_API_GRAPH_SEED_MIN_SIMILARITY",
|
|
19717
19720
|
String(HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY)
|
|
19718
|
-
]
|
|
19721
|
+
],
|
|
19722
|
+
["HINDSIGHT_API_TEXT_SEARCH_EXTENSION", HINDSIGHT_DEFAULT_TEXT_SEARCH_EXTENSION]
|
|
19719
19723
|
];
|
|
19720
19724
|
var HINDSIGHT_PERF_DEFAULTS_GPU = [
|
|
19721
19725
|
["HINDSIGHT_API_RERANKER_LOCAL_FP16", HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16],
|
|
@@ -4469,6 +4469,7 @@ var init_schema = __esm(() => {
|
|
|
4469
4469
|
}).describe("Per-operation LLM override. Every field optional; an unset field (or " + "an omitted op block) inherits the global `hindsight.llm.*`, which is " + "already the engine's fallback — switchroom emits only the vars set.");
|
|
4470
4470
|
HindsightConfigSchema = exports_external.object({
|
|
4471
4471
|
gpu: exports_external.boolean().optional().describe("Force GPU passthrough for the hindsight container on (`true`) or off " + "(`false`), overriding host autodetection in BOTH directions. Absent " + "(the default) → autodetect from the persisted host-capabilities " + "verdict (`~/.switchroom/host-capabilities.json`), which enables " + "`--gpus all` only when that file proves BOTH a GPU and the nvidia " + "container toolkit. Set `true` when that verdict is wrong or unreadable " + "and you know the host has a working toolkit — switchroom cannot verify " + "it for you, and `docker run --gpus all` hard-fails container create on " + "a host without one. Set `false` to pin the container to CPU on a GPU " + "host. This is also the declarative opt-out for the recreate-time GPU " + "drop guard (`switchroom memory setup --recreate` refuses to silently " + "turn a GPU container into a CPU one). `--gpu`/`--no-gpu` on `memory " + "setup` override this for a single run."),
|
|
4472
|
+
mem_limit: exports_external.string().regex(/^\d+(\.\d+)?\s*[bkmgt]?b?$/i, "hindsight.mem_limit must be a docker memory size, e.g. `24g` or `16384m`").optional().describe("Hard memory cap for the hindsight container — docker `--memory` on the " + "`memory setup` path and `mem_limit:` in the emitted compose snippet. A " + "docker size string (`24g`, `16384m`). Absent → switchroom's default " + "(`HINDSIGHT_DEFAULT_MEM_LIMIT`, 16g). This is a docker HostConfig flag, " + "not a container env var, which is why it is a first-class field here " + "rather than an `env:` key. **Move it together with " + "`env.SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS`**: Postgres pins the " + "buffer pool as unreclaimable shared memory inside this cap, so a cap " + "that does not clear `shared_buffers` by the container's app working " + "set plus its page-cache floor puts Postgres in a near-OOM " + "configuration. switchroom warns, naming both numbers, when it does " + "not. A value below the container's memory RESERVATION (4g) is " + "rejected outright — docker will not create such a container."),
|
|
4472
4473
|
cp_access_key: exports_external.string().min(1).optional().describe("Access key for the hindsight control-plane DASHBOARD (upstream " + "`HINDSIGHT_CP_ACCESS_KEY`, port 9999). Literal or — strongly preferred " + "— a `vault:` reference such as `vault:hindsight_cp_access_key`, read " + "through the broker at container-launch time. This is the ONLY thing " + "that arms the dashboard's login: upstream's middleware short-circuits " + "to `next()` when the var is unset, so an unset key means the dashboard " + "has no authentication at all, not weak authentication. Because of that, " + "leaving it unset is FAIL-CLOSED: switchroom pins " + "`HINDSIGHT_CP_HOSTNAME=127.0.0.1` so the loginless dashboard is " + "reachable only from the host, and warns. Set this to serve the " + "dashboard on the LAN/tailnet."),
|
|
4473
4474
|
llm: exports_external.object({
|
|
4474
4475
|
provider: exports_external.string().min(1).optional().describe("Hindsight LLM provider (upstream `HINDSIGHT_API_LLM_PROVIDER`). " + "Defaults to `claude-code` (subscription-honest, broker-fed OAuth). " + "Any litellm-routable provider the upstream image supports is valid. " + "Serves as the GLOBAL default for every op absent a per-op override."),
|
|
@@ -20016,6 +20017,7 @@ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 12288;
|
|
|
20016
20017
|
function pgMib(mib) {
|
|
20017
20018
|
return `${mib}MB`;
|
|
20018
20019
|
}
|
|
20020
|
+
var HINDSIGHT_PG_MIN_NON_BUFFER_MIB = HINDSIGHT_PG_APP_ANON_MIB + HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
|
|
20019
20021
|
var HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV = "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE";
|
|
20020
20022
|
var HINDSIGHT_PG_SHARED_BUFFERS_ENV = "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS";
|
|
20021
20023
|
var HINDSIGHT_PG_FSYNC_ENV = "SWITCHROOM_HINDSIGHT_PG_FSYNC";
|
|
@@ -20063,6 +20065,7 @@ var HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY = 0.3;
|
|
|
20063
20065
|
var HINDSIGHT_DEFAULT_LLM_SUPPORTS_MAX_ITEMS = "false";
|
|
20064
20066
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
|
|
20065
20067
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_HALFLIFE_DAYS = 30;
|
|
20068
|
+
var HINDSIGHT_DEFAULT_TEXT_SEARCH_EXTENSION = "pg_search";
|
|
20066
20069
|
var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
20067
20070
|
[
|
|
20068
20071
|
"HINDSIGHT_API_RECALL_MAX_CANDIDATES_PER_SOURCE",
|
|
@@ -20128,7 +20131,8 @@ var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
|
20128
20131
|
[
|
|
20129
20132
|
"HINDSIGHT_API_GRAPH_SEED_MIN_SIMILARITY",
|
|
20130
20133
|
String(HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY)
|
|
20131
|
-
]
|
|
20134
|
+
],
|
|
20135
|
+
["HINDSIGHT_API_TEXT_SEARCH_EXTENSION", HINDSIGHT_DEFAULT_TEXT_SEARCH_EXTENSION]
|
|
20132
20136
|
];
|
|
20133
20137
|
var HINDSIGHT_PERF_DEFAULTS_GPU = [
|
|
20134
20138
|
["HINDSIGHT_API_RERANKER_LOCAL_FP16", HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16],
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "switchroom",
|
|
3
3
|
"//version": "NOT the release version — source of truth is the git tag, resolved by scripts/build.mjs:resolveVersion() (see CLAUDE.md > Standard release process). This field is stale by design and only the Layer-4 dev/non-tag fallback for build.mjs + src/cli/resolve-version.ts; do NOT bump it expecting a release to pick it up. npm-pack tarball naming needs a real version — do that as an UNCOMMITTED pack-time bump (see release step 6), never a committed one.",
|
|
4
|
-
"version": "0.20.
|
|
4
|
+
"version": "0.20.13",
|
|
5
5
|
"description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"build": "node scripts/build.mjs",
|
|
25
25
|
"build:cli": "node scripts/build.mjs && bun build --compile --target=bun-linux-x64 --minify bin/switchroom.ts --outfile switchroom-linux-amd64",
|
|
26
26
|
"pretest": "npm run build",
|
|
27
|
-
"test": "vitest run && bun test telegram-plugin/tests/agent-state-dir-preload.test.ts telegram-plugin/tests/catch-all-forwarded-history.test.ts telegram-plugin/tests/history.test.ts telegram-plugin/tests/boot-briefing-builder.test.ts telegram-plugin/tests/cross-turn-card-gate.test.ts telegram-plugin/tests/emission-authority-open-gate.test.ts telegram-plugin/tests/emission-authority-ping-gate.test.ts telegram-plugin/tests/emission-authority-card-drain-gate.test.ts telegram-plugin/tests/per-topic-current-turn.test.ts telegram-plugin/tests/history-reaper.test.ts telegram-plugin/tests/ipc-server-client.test.ts telegram-plugin/tests/ipc-server-race.test.ts telegram-plugin/tests/ipc-server-buzz-dedup.test.ts telegram-plugin/tests/ipc-server-query-pending-permission.test.ts telegram-plugin/tests/ipc-server-check-pre-approved.test.ts telegram-plugin/tests/rollout-narration-edit-socket.test.ts telegram-plugin/tests/gateway-bridge.test.ts telegram-plugin/tests/gateway-startup-mutex.test.ts telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts telegram-plugin/tests/boot-card-dedupe.test.ts telegram-plugin/tests/boot-card-reason.test.ts telegram-plugin/tests/progress-update.test.ts telegram-plugin/tests/progress-fallback-cap.test.ts telegram-plugin/tests/progress-cap.test.ts telegram-plugin/tests/quota-cache.test.ts telegram-plugin/tests/unhandled-rejection-policy.test.ts telegram-plugin/tests/registry-turns.test.ts telegram-plugin/registry/subagents.test.ts telegram-plugin/registry/subagents-bugs.test.ts telegram-plugin/tests/subagent-watcher-parent-turn-key.test.ts telegram-plugin/tests/worker-origin-gap-dispatch.test.ts telegram-plugin/tests/subagent-nested-dispatch.test.ts telegram-plugin/tests/nested-worker-visibility-harness.test.ts telegram-plugin/tests/turns-writer.test.ts telegram-plugin/tests/resume-inbound-builder.test.ts telegram-plugin/registry/api-registry.test.ts telegram-plugin/registry/turns-schema.test.ts telegram-plugin/tests/idle-footer-wiring.test.ts telegram-plugin/tests/subagent-tracker-hooks.test.ts telegram-plugin/tests/gateway-update-placeholder-dispatch.test.ts telegram-plugin/tests/status-query-telemetry.test.ts telegram-plugin/tests/reaction-trigger.test.ts telegram-plugin/tests/reaction-trigger-flow.test.ts telegram-plugin/gateway/webhook-ingest-server.test.ts telegram-plugin/tests/skill-proposal-card.test.ts",
|
|
27
|
+
"test": "vitest run && bun test telegram-plugin/tests/agent-state-dir-preload.test.ts telegram-plugin/tests/hindsight-bank-preload.test.ts telegram-plugin/tests/catch-all-forwarded-history.test.ts telegram-plugin/tests/history.test.ts telegram-plugin/tests/boot-briefing-builder.test.ts telegram-plugin/tests/cross-turn-card-gate.test.ts telegram-plugin/tests/emission-authority-open-gate.test.ts telegram-plugin/tests/emission-authority-ping-gate.test.ts telegram-plugin/tests/emission-authority-card-drain-gate.test.ts telegram-plugin/tests/per-topic-current-turn.test.ts telegram-plugin/tests/history-reaper.test.ts telegram-plugin/tests/ipc-server-client.test.ts telegram-plugin/tests/ipc-server-race.test.ts telegram-plugin/tests/ipc-server-buzz-dedup.test.ts telegram-plugin/tests/ipc-server-query-pending-permission.test.ts telegram-plugin/tests/ipc-server-check-pre-approved.test.ts telegram-plugin/tests/rollout-narration-edit-socket.test.ts telegram-plugin/tests/gateway-bridge.test.ts telegram-plugin/tests/gateway-startup-mutex.test.ts telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts telegram-plugin/tests/boot-card-dedupe.test.ts telegram-plugin/tests/boot-card-reason.test.ts telegram-plugin/tests/progress-update.test.ts telegram-plugin/tests/progress-fallback-cap.test.ts telegram-plugin/tests/progress-cap.test.ts telegram-plugin/tests/quota-cache.test.ts telegram-plugin/tests/unhandled-rejection-policy.test.ts telegram-plugin/tests/registry-turns.test.ts telegram-plugin/registry/subagents.test.ts telegram-plugin/registry/subagents-bugs.test.ts telegram-plugin/tests/subagent-watcher-parent-turn-key.test.ts telegram-plugin/tests/worker-origin-gap-dispatch.test.ts telegram-plugin/tests/subagent-nested-dispatch.test.ts telegram-plugin/tests/nested-worker-visibility-harness.test.ts telegram-plugin/tests/turns-writer.test.ts telegram-plugin/tests/resume-inbound-builder.test.ts telegram-plugin/registry/api-registry.test.ts telegram-plugin/registry/turns-schema.test.ts telegram-plugin/tests/idle-footer-wiring.test.ts telegram-plugin/tests/subagent-tracker-hooks.test.ts telegram-plugin/tests/gateway-update-placeholder-dispatch.test.ts telegram-plugin/tests/status-query-telemetry.test.ts telegram-plugin/tests/reaction-trigger.test.ts telegram-plugin/tests/reaction-trigger-flow.test.ts telegram-plugin/gateway/webhook-ingest-server.test.ts telegram-plugin/tests/skill-proposal-card.test.ts",
|
|
28
28
|
"test:vitest": "vitest run",
|
|
29
|
-
"test:bun": "bun test telegram-plugin/tests/agent-state-dir-preload.test.ts telegram-plugin/tests/catch-all-forwarded-history.test.ts src/vault/grants.test.ts src/vault/grants-db.test.ts src/vault/write-grants.test.ts src/vault/broker/server-grants.test.ts src/vault/broker/server-write-grants.test.ts src/vault/broker/server-scope-persist.test.ts src/vault/broker/server-tokenless-scope.test.ts src/vault/broker/server-mint-grant-passphrase-attest.test.ts src/vault/broker/server-passphrase-attest.test.ts src/vault/broker/server-mint-grant-posture-attest.test.ts src/vault/broker/server-admin-only-keys.test.ts src/vault/broker/client-token.test.ts src/vault/broker/server-unlock.test.ts src/vault/broker/auto-unlock.test.ts src/vault/broker/drift-detection.test.ts tests/vault-broker-passphrase.test.ts src/cli/vault-get-broker.test.ts src/vault/resolver-via-broker.test.ts src/vault/broker/scope.test.ts src/vault/broker/server.test.ts src/litellm/provision-apply-e2e.test.ts src/drive/disconnect.test.ts src/drive/grants.test.ts src/drive/oauth.test.ts src/drive/onboarding.test.ts src/drive/reconciler.test.ts src/drive/vault-slots.test.ts src/drive/wrapper.test.ts src/vault/approvals/kernel.test.ts src/vault/approvals/approval-origin.test.ts src/vault/approvals/self-approval-bypass.test.ts src/vault/approvals/schema-idempotent.test.ts src/vault/broker/server-approvals.test.ts telegram-plugin/tests/boot-probes.test.ts telegram-plugin/tests/boot-version-string.test.ts telegram-plugin/tests/history.test.ts telegram-plugin/tests/boot-briefing-builder.test.ts telegram-plugin/tests/cross-turn-card-gate.test.ts telegram-plugin/tests/emission-authority-open-gate.test.ts telegram-plugin/tests/emission-authority-ping-gate.test.ts telegram-plugin/tests/emission-authority-card-drain-gate.test.ts telegram-plugin/tests/per-topic-current-turn.test.ts telegram-plugin/tests/history-reaper.test.ts telegram-plugin/tests/ipc-server-client.test.ts telegram-plugin/tests/ipc-server-race.test.ts telegram-plugin/tests/ipc-server-buzz-dedup.test.ts telegram-plugin/tests/ipc-server-query-pending-permission.test.ts telegram-plugin/tests/ipc-server-check-pre-approved.test.ts telegram-plugin/tests/rollout-narration-edit-socket.test.ts telegram-plugin/tests/gateway-bridge.test.ts telegram-plugin/tests/gateway-startup-mutex.test.ts telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts telegram-plugin/tests/boot-card-dedupe.test.ts telegram-plugin/tests/boot-card-reason.test.ts telegram-plugin/tests/progress-update.test.ts telegram-plugin/tests/progress-fallback-cap.test.ts telegram-plugin/tests/progress-cap.test.ts telegram-plugin/tests/quota-cache.test.ts telegram-plugin/tests/silent-reply-guard.test.ts telegram-plugin/tests/unhandled-rejection-policy.test.ts telegram-plugin/tests/registry-turns.test.ts telegram-plugin/registry/subagents.test.ts telegram-plugin/registry/subagents-bugs.test.ts telegram-plugin/tests/subagent-watcher-parent-turn-key.test.ts telegram-plugin/tests/worker-origin-gap-dispatch.test.ts telegram-plugin/tests/subagent-nested-dispatch.test.ts telegram-plugin/tests/nested-worker-visibility-harness.test.ts telegram-plugin/tests/turns-writer.test.ts telegram-plugin/tests/resume-inbound-builder.test.ts telegram-plugin/tests/subagent-tracker-hooks.test.ts telegram-plugin/tests/resolve-calling-subagent.test.ts telegram-plugin/tests/gateway-update-placeholder-dispatch.test.ts telegram-plugin/tests/status-query-telemetry.test.ts telegram-plugin/tests/reaction-trigger.test.ts telegram-plugin/tests/reaction-trigger-flow.test.ts telegram-plugin/tests/subagent-watcher-workflow-visibility.test.ts telegram-plugin/uat/load-env.test.ts telegram-plugin/uat/feed-matcher.test.ts telegram-plugin/uat/uat-driver.test.ts telegram-plugin/gateway/webhook-ingest-server.test.ts telegram-plugin/tests/skill-proposal-card.test.ts",
|
|
29
|
+
"test:bun": "bun test telegram-plugin/tests/agent-state-dir-preload.test.ts telegram-plugin/tests/hindsight-bank-preload.test.ts telegram-plugin/tests/catch-all-forwarded-history.test.ts src/vault/grants.test.ts src/vault/grants-db.test.ts src/vault/write-grants.test.ts src/vault/broker/server-grants.test.ts src/vault/broker/server-write-grants.test.ts src/vault/broker/server-scope-persist.test.ts src/vault/broker/server-tokenless-scope.test.ts src/vault/broker/server-mint-grant-passphrase-attest.test.ts src/vault/broker/server-passphrase-attest.test.ts src/vault/broker/server-mint-grant-posture-attest.test.ts src/vault/broker/server-admin-only-keys.test.ts src/vault/broker/client-token.test.ts src/vault/broker/server-unlock.test.ts src/vault/broker/auto-unlock.test.ts src/vault/broker/drift-detection.test.ts tests/vault-broker-passphrase.test.ts src/cli/vault-get-broker.test.ts src/vault/resolver-via-broker.test.ts src/vault/broker/scope.test.ts src/vault/broker/server.test.ts src/litellm/provision-apply-e2e.test.ts src/drive/disconnect.test.ts src/drive/grants.test.ts src/drive/oauth.test.ts src/drive/onboarding.test.ts src/drive/reconciler.test.ts src/drive/vault-slots.test.ts src/drive/wrapper.test.ts src/vault/approvals/kernel.test.ts src/vault/approvals/approval-origin.test.ts src/vault/approvals/self-approval-bypass.test.ts src/vault/approvals/schema-idempotent.test.ts src/vault/broker/server-approvals.test.ts telegram-plugin/tests/boot-probes.test.ts telegram-plugin/tests/boot-version-string.test.ts telegram-plugin/tests/history.test.ts telegram-plugin/tests/boot-briefing-builder.test.ts telegram-plugin/tests/cross-turn-card-gate.test.ts telegram-plugin/tests/emission-authority-open-gate.test.ts telegram-plugin/tests/emission-authority-ping-gate.test.ts telegram-plugin/tests/emission-authority-card-drain-gate.test.ts telegram-plugin/tests/per-topic-current-turn.test.ts telegram-plugin/tests/history-reaper.test.ts telegram-plugin/tests/ipc-server-client.test.ts telegram-plugin/tests/ipc-server-race.test.ts telegram-plugin/tests/ipc-server-buzz-dedup.test.ts telegram-plugin/tests/ipc-server-query-pending-permission.test.ts telegram-plugin/tests/ipc-server-check-pre-approved.test.ts telegram-plugin/tests/rollout-narration-edit-socket.test.ts telegram-plugin/tests/gateway-bridge.test.ts telegram-plugin/tests/gateway-startup-mutex.test.ts telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts telegram-plugin/tests/boot-card-dedupe.test.ts telegram-plugin/tests/boot-card-reason.test.ts telegram-plugin/tests/progress-update.test.ts telegram-plugin/tests/progress-fallback-cap.test.ts telegram-plugin/tests/progress-cap.test.ts telegram-plugin/tests/quota-cache.test.ts telegram-plugin/tests/silent-reply-guard.test.ts telegram-plugin/tests/unhandled-rejection-policy.test.ts telegram-plugin/tests/registry-turns.test.ts telegram-plugin/registry/subagents.test.ts telegram-plugin/registry/subagents-bugs.test.ts telegram-plugin/tests/subagent-watcher-parent-turn-key.test.ts telegram-plugin/tests/worker-origin-gap-dispatch.test.ts telegram-plugin/tests/subagent-nested-dispatch.test.ts telegram-plugin/tests/nested-worker-visibility-harness.test.ts telegram-plugin/tests/turns-writer.test.ts telegram-plugin/tests/resume-inbound-builder.test.ts telegram-plugin/tests/subagent-tracker-hooks.test.ts telegram-plugin/tests/resolve-calling-subagent.test.ts telegram-plugin/tests/gateway-update-placeholder-dispatch.test.ts telegram-plugin/tests/status-query-telemetry.test.ts telegram-plugin/tests/reaction-trigger.test.ts telegram-plugin/tests/reaction-trigger-flow.test.ts telegram-plugin/tests/subagent-watcher-workflow-visibility.test.ts telegram-plugin/uat/load-env.test.ts telegram-plugin/uat/feed-matcher.test.ts telegram-plugin/uat/uat-driver.test.ts telegram-plugin/gateway/webhook-ingest-server.test.ts telegram-plugin/tests/skill-proposal-card.test.ts",
|
|
30
30
|
"test:watch": "vitest",
|
|
31
|
-
"lint": "tsc --noEmit && node scripts/check-plugin-references.mjs && bash scripts/check-bot-api-wrapping.sh && node scripts/check-bun-test-imports.mjs && node scripts/check-test-runner-coverage.mjs && node scripts/check-bun-module-mock-scope.mjs && node scripts/check-no-pii-secrets.mjs && node scripts/check-vault-test-hermeticity.mjs && node scripts/check-auth-test-hermeticity.mjs && node scripts/check-agent-state-dir-hermeticity.mjs && node scripts/check-no-broadcast-delivery.mjs && node scripts/check-stale-tool-descriptions.mjs && node scripts/check-mcp-instructions-budget.mjs && node scripts/check-web-subscription-honest.mjs && node scripts/check-no-unpinned-npx-playwright.mjs && node scripts/check-gateway-line-ratchet.mjs && node scripts/check-retry-flood-hooks.mjs && node scripts/check-callback-ctx-wrapping.mjs && node scripts/check-status-pin-single-path.mjs && node scripts/check-litellm-config-guard.mjs && node scripts/check-release-asset-names.mjs && node scripts/check-agent-attribution-trailers.mjs && node scripts/check-hindsight-write-redaction.mjs && bun scripts/check-secret-pattern-parity.ts && bun scripts/check-hostd-template-guard.ts",
|
|
31
|
+
"lint": "tsc --noEmit && node scripts/check-plugin-references.mjs && bash scripts/check-bot-api-wrapping.sh && node scripts/check-bun-test-imports.mjs && node scripts/check-test-runner-coverage.mjs && node scripts/check-bun-module-mock-scope.mjs && node scripts/check-no-pii-secrets.mjs && node scripts/check-bench-baseline-anonymised.mjs && node scripts/check-vault-test-hermeticity.mjs && node scripts/check-auth-test-hermeticity.mjs && node scripts/check-agent-state-dir-hermeticity.mjs && node scripts/check-hindsight-bank-hermeticity.mjs && node scripts/check-no-broadcast-delivery.mjs && node scripts/check-stale-tool-descriptions.mjs && node scripts/check-mcp-instructions-budget.mjs && node scripts/check-web-subscription-honest.mjs && node scripts/check-no-unpinned-npx-playwright.mjs && node scripts/check-gateway-line-ratchet.mjs && node scripts/check-retry-flood-hooks.mjs && node scripts/check-callback-ctx-wrapping.mjs && node scripts/check-status-pin-single-path.mjs && node scripts/check-litellm-config-guard.mjs && node scripts/check-release-asset-names.mjs && node scripts/check-changelog-entry.mjs && node scripts/check-agent-attribution-trailers.mjs && node scripts/check-hindsight-write-redaction.mjs && bun scripts/check-secret-pattern-parity.ts && bun scripts/check-hostd-template-guard.ts",
|
|
32
32
|
"lint:tsc": "tsc --noEmit",
|
|
33
33
|
"lint:hindsight-write-redaction": "node scripts/check-hindsight-write-redaction.mjs",
|
|
34
34
|
"lint:secret-pattern-parity": "bun scripts/check-secret-pattern-parity.ts",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"lint:no-pii": "node scripts/check-no-pii-secrets.mjs",
|
|
41
41
|
"lint:auth-test-hermeticity": "node scripts/check-auth-test-hermeticity.mjs",
|
|
42
42
|
"lint:agent-state-dir-hermeticity": "node scripts/check-agent-state-dir-hermeticity.mjs",
|
|
43
|
+
"lint:hindsight-bank-hermeticity": "node scripts/check-hindsight-bank-hermeticity.mjs",
|
|
43
44
|
"lint:web-subscription-honest": "node scripts/check-web-subscription-honest.mjs",
|
|
44
45
|
"lint:no-broadcast-delivery": "node scripts/check-no-broadcast-delivery.mjs",
|
|
45
46
|
"lint:gateway-line-ratchet": "node scripts/check-gateway-line-ratchet.mjs",
|
|
@@ -49,8 +50,10 @@
|
|
|
49
50
|
"lint:mcp-instructions-budget": "node scripts/check-mcp-instructions-budget.mjs",
|
|
50
51
|
"lint:litellm-config-guard": "node scripts/check-litellm-config-guard.mjs",
|
|
51
52
|
"lint:release-asset-contract": "node scripts/check-release-asset-names.mjs",
|
|
53
|
+
"lint:changelog-entry": "node scripts/check-changelog-entry.mjs",
|
|
52
54
|
"lint:agent-attribution-trailers": "node scripts/check-agent-attribution-trailers.mjs",
|
|
53
55
|
"lint:hostd-template-guard": "bun scripts/check-hostd-template-guard.ts",
|
|
56
|
+
"lint:bench-baseline-anonymised": "node scripts/check-bench-baseline-anonymised.mjs",
|
|
54
57
|
"prepublishOnly": "npm run build && npm run lint && npm test"
|
|
55
58
|
},
|
|
56
59
|
"dependencies": {
|
|
@@ -22,12 +22,13 @@ Cut a release of `switchroom/switchroom` and get it live on the fleet. This is a
|
|
|
22
22
|
1. `git fetch origin`, confirm `main` is at the commit you want released.
|
|
23
23
|
2. `gh pr list --state open` — confirm no PR meant for this release is still open. Ask the operator if unsure.
|
|
24
24
|
3. Confirm CI on `main` is green (`gh run list --branch main --limit 3`).
|
|
25
|
-
4. Read `CHANGELOG.md` — the `## Unreleased` section is the staging area for this release's notes.
|
|
25
|
+
4. Read `CHANGELOG.md` — the `## Unreleased` section is the **continuously-maintained** staging area for this release's notes. Every PR since the last release stages its own entry there as it merges, enforced by `scripts/check-changelog-entry.mjs` (part of `npm run lint`), so by release time this section should already read as a near-complete draft — you tidy and summarise, you do NOT author it from scratch. **An empty (or missing) `## Unreleased` at release time is now an ANOMALY, not the normal state:** it means either there genuinely is nothing to release, OR the enforcement was bypassed (`no-changelog` labels / `[skip changelog]` tokens on their own line on PRs that should have staged entries). Before assuming the former, cross-check against `git log <last-tag>..origin/main` — if real shippable work landed but Unreleased is bare, investigate and reconstruct rather than shipping a hollow release (this is exactly the v0.20.12 failure mode the enforcement exists to prevent).
|
|
26
26
|
5. Pick the next version: read the latest tag (`git tag --list 'v*' --sort=-v:refname | head -1`) and bump the patch (or minor if the operator asks). Confirm with the operator which.
|
|
27
27
|
|
|
28
28
|
## Step 1 — Consolidate the changelog (the release commit is CHANGELOG-only)
|
|
29
29
|
|
|
30
|
-
-
|
|
30
|
+
- The section is maintained continuously (see pre-flight 4), so this step is now a **rename + tidy**, not authorship: change the `## Unreleased` header to `## vX.Y.Z — <one-line summary>`, then read through the staged entries and lightly edit for grouping/summary. If Unreleased was empty or thin, STOP and resolve the anomaly (pre-flight 4) before proceeding — do not invent a release note.
|
|
31
|
+
- **Re-seed a fresh empty `## Unreleased` block at the top** (header + the convention HTML comment) immediately below `# Changelog`, so the staging area exists for the next cycle and `scripts/check-changelog-entry.mjs` keeps enforcing it. (Copy the comment block from the section you just renamed.)
|
|
31
32
|
- The release commit touches **CHANGELOG.md only**. Do NOT bump `package.json` (placeholder discipline).
|
|
32
33
|
- Branch protection blocks direct push to `main`, so: create a `release/vX.Y.Z` branch, push it, open a `chore: release vX.Y.Z` PR (base `main`), arm auto-merge (squash, delete-branch) on green CI.
|
|
33
34
|
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
# `bun-test-run` job (scripts/bun-test-ci.sh) and `bun run --cwd telegram-plugin`.
|
|
3
3
|
#
|
|
4
4
|
# bun reads the bunfig.toml in its CWD only, so this file exists purely to load
|
|
5
|
-
# the same state
|
|
6
|
-
# two in sync; `npm run lint:agent-state-dir-hermeticity`
|
|
7
|
-
#
|
|
8
|
-
# tests/vitest-setup/agent-state-dir-guard.mjs
|
|
5
|
+
# the same shared-state hermeticity preloads as the repo-root bunfig.toml. Keep
|
|
6
|
+
# the two in sync; `npm run lint:agent-state-dir-hermeticity` and
|
|
7
|
+
# `npm run lint:hindsight-bank-hermeticity` fail if either bunfig stops loading
|
|
8
|
+
# either guard. Rationale lives in tests/vitest-setup/agent-state-dir-guard.mjs
|
|
9
|
+
# and tests/vitest-setup/hindsight-bank-guard.mjs.
|
|
9
10
|
[test]
|
|
10
|
-
preload = [
|
|
11
|
+
preload = [
|
|
12
|
+
"../tests/vitest-setup/agent-state-dir-guard.mjs",
|
|
13
|
+
"../tests/vitest-setup/hindsight-bank-guard.mjs",
|
|
14
|
+
]
|
|
@@ -22025,6 +22025,7 @@ var init_schema = __esm(() => {
|
|
|
22025
22025
|
}).describe("Per-operation LLM override. Every field optional; an unset field (or " + "an omitted op block) inherits the global `hindsight.llm.*`, which is " + "already the engine's fallback \u2014 switchroom emits only the vars set.");
|
|
22026
22026
|
HindsightConfigSchema = exports_external.object({
|
|
22027
22027
|
gpu: exports_external.boolean().optional().describe("Force GPU passthrough for the hindsight container on (`true`) or off " + "(`false`), overriding host autodetection in BOTH directions. Absent " + "(the default) \u2192 autodetect from the persisted host-capabilities " + "verdict (`~/.switchroom/host-capabilities.json`), which enables " + "`--gpus all` only when that file proves BOTH a GPU and the nvidia " + "container toolkit. Set `true` when that verdict is wrong or unreadable " + "and you know the host has a working toolkit \u2014 switchroom cannot verify " + "it for you, and `docker run --gpus all` hard-fails container create on " + "a host without one. Set `false` to pin the container to CPU on a GPU " + "host. This is also the declarative opt-out for the recreate-time GPU " + "drop guard (`switchroom memory setup --recreate` refuses to silently " + "turn a GPU container into a CPU one). `--gpu`/`--no-gpu` on `memory " + "setup` override this for a single run."),
|
|
22028
|
+
mem_limit: exports_external.string().regex(/^\d+(\.\d+)?\s*[bkmgt]?b?$/i, "hindsight.mem_limit must be a docker memory size, e.g. `24g` or `16384m`").optional().describe("Hard memory cap for the hindsight container \u2014 docker `--memory` on the " + "`memory setup` path and `mem_limit:` in the emitted compose snippet. A " + "docker size string (`24g`, `16384m`). Absent \u2192 switchroom's default " + "(`HINDSIGHT_DEFAULT_MEM_LIMIT`, 16g). This is a docker HostConfig flag, " + "not a container env var, which is why it is a first-class field here " + "rather than an `env:` key. **Move it together with " + "`env.SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS`**: Postgres pins the " + "buffer pool as unreclaimable shared memory inside this cap, so a cap " + "that does not clear `shared_buffers` by the container's app working " + "set plus its page-cache floor puts Postgres in a near-OOM " + "configuration. switchroom warns, naming both numbers, when it does " + "not. A value below the container's memory RESERVATION (4g) is " + "rejected outright \u2014 docker will not create such a container."),
|
|
22028
22029
|
cp_access_key: exports_external.string().min(1).optional().describe("Access key for the hindsight control-plane DASHBOARD (upstream " + "`HINDSIGHT_CP_ACCESS_KEY`, port 9999). Literal or \u2014 strongly preferred " + "\u2014 a `vault:` reference such as `vault:hindsight_cp_access_key`, read " + "through the broker at container-launch time. This is the ONLY thing " + "that arms the dashboard's login: upstream's middleware short-circuits " + "to `next()` when the var is unset, so an unset key means the dashboard " + "has no authentication at all, not weak authentication. Because of that, " + "leaving it unset is FAIL-CLOSED: switchroom pins " + "`HINDSIGHT_CP_HOSTNAME=127.0.0.1` so the loginless dashboard is " + "reachable only from the host, and warns. Set this to serve the " + "dashboard on the LAN/tailnet."),
|
|
22029
22030
|
llm: exports_external.object({
|
|
22030
22031
|
provider: exports_external.string().min(1).optional().describe("Hindsight LLM provider (upstream `HINDSIGHT_API_LLM_PROVIDER`). " + "Defaults to `claude-code` (subscription-honest, broker-fed OAuth). " + "Any litellm-routable provider the upstream image supports is valid. " + "Serves as the GLOBAL default for every op absent a per-op override."),
|
|
@@ -79042,6 +79043,17 @@ import { homedir as homedir9 } from "node:os";
|
|
|
79042
79043
|
// hooks/audience-classify.mjs
|
|
79043
79044
|
var AUDIENCE_USER = "user";
|
|
79044
79045
|
var AUDIENCE_INTERNAL = "internal";
|
|
79046
|
+
function decideCaptureAudience(signals) {
|
|
79047
|
+
if (signals?.reviewOriginated === true) {
|
|
79048
|
+
return signals?.reviewTextIsCard === true ? AUDIENCE_USER : AUDIENCE_INTERNAL;
|
|
79049
|
+
}
|
|
79050
|
+
const threw = signals?.replyToolThrewThisTurn === true;
|
|
79051
|
+
if (!threw)
|
|
79052
|
+
return AUDIENCE_USER;
|
|
79053
|
+
if (signals?.openInboundObligation !== false)
|
|
79054
|
+
return AUDIENCE_USER;
|
|
79055
|
+
return AUDIENCE_INTERNAL;
|
|
79056
|
+
}
|
|
79045
79057
|
function resolveRecordAudience(value) {
|
|
79046
79058
|
return value === AUDIENCE_INTERNAL ? AUDIENCE_INTERNAL : AUDIENCE_USER;
|
|
79047
79059
|
}
|
|
@@ -79068,6 +79080,31 @@ function formatReplyThrowFraming(s) {
|
|
|
79068
79080
|
return `telegram gateway: outbox provenance framing nonce=${s.turnNonce} ` + `turnId=${s.turnId ?? "unknown"} chatId=${s.chatId ?? "unresolved"} ` + `sha=${(s.textSha256 ?? "").slice(0, 12)} source=${s.source ?? "unknown"} ` + `audience=user replyToolThrew=true \u2014 captured prose delivered with its ` + `provenance stated, not suppressed
|
|
79069
79081
|
`;
|
|
79070
79082
|
}
|
|
79083
|
+
var SELF_IMPROVEMENT_TITLE = "\uD83D\uDD27 **Self-improvement**";
|
|
79084
|
+
function isSelfImprovementCard(text4) {
|
|
79085
|
+
if (typeof text4 !== "string")
|
|
79086
|
+
return false;
|
|
79087
|
+
return text4.trimStart().startsWith(SELF_IMPROVEMENT_TITLE);
|
|
79088
|
+
}
|
|
79089
|
+
function shouldFrameSelfImprovement(record, opts) {
|
|
79090
|
+
if (opts?.frameEnabled === false)
|
|
79091
|
+
return false;
|
|
79092
|
+
return record?.reviewOriginated === true;
|
|
79093
|
+
}
|
|
79094
|
+
function applySelfImprovementFraming(text4) {
|
|
79095
|
+
const body = typeof text4 === "string" ? text4 : "";
|
|
79096
|
+
if (body.trim().length === 0)
|
|
79097
|
+
return body;
|
|
79098
|
+
if (isSelfImprovementCard(body))
|
|
79099
|
+
return body;
|
|
79100
|
+
return `${SELF_IMPROVEMENT_TITLE}
|
|
79101
|
+
|
|
79102
|
+
${body}`;
|
|
79103
|
+
}
|
|
79104
|
+
function formatSelfImprovementFraming(s) {
|
|
79105
|
+
return `telegram gateway: outbox self-improvement framing nonce=${s.turnNonce} ` + `turnId=${s.turnId ?? "unknown"} chatId=${s.chatId ?? "unresolved"} ` + `sha=${(s.textSha256 ?? "").slice(0, 12)} source=${s.source ?? "unknown"} ` + `reviewOriginated=true \u2014 review-turn prose delivered with its self-improvement ` + `title, never as raw unlabelled reasoning
|
|
79106
|
+
`;
|
|
79107
|
+
}
|
|
79071
79108
|
function formatInternalSuppression(s) {
|
|
79072
79109
|
return `telegram gateway: outbox audience suppression nonce=${s.turnNonce} ` + `turnId=${s.turnId ?? "unknown"} chatId=${s.chatId ?? "unresolved"} ` + `sha=${(s.textSha256 ?? "").slice(0, 12)} ageMs=${s.ageMs ?? 0} ` + `source=${s.source ?? "unknown"} pastWindow=${s.pastWindow === true} ` + `audience=internal \u2014 internal prose withheld from chat, journaled terminally
|
|
79073
79110
|
`;
|
|
@@ -79254,7 +79291,8 @@ function decideOutboxSweep(input) {
|
|
|
79254
79291
|
quietMs = OUTBOX_QUIET_MS,
|
|
79255
79292
|
maxAgeMs = OUTBOX_MAX_AGE_MS,
|
|
79256
79293
|
shownLedgerHit = false,
|
|
79257
|
-
provenanceFraming = true
|
|
79294
|
+
provenanceFraming = true,
|
|
79295
|
+
selfImprovementFraming = true
|
|
79258
79296
|
} = input;
|
|
79259
79297
|
if (deliveredNonces.has(record.turnNonce))
|
|
79260
79298
|
return { action: "skip-journaled" };
|
|
@@ -79270,11 +79308,14 @@ function decideOutboxSweep(input) {
|
|
|
79270
79308
|
const delayed = age > maxAgeMs;
|
|
79271
79309
|
const prefix = (delayed ? "(delayed) " : "") + routePrefix;
|
|
79272
79310
|
const framed = shouldFrameReplyThrow(record, { frameEnabled: provenanceFraming });
|
|
79273
|
-
const
|
|
79311
|
+
const provenanceBody = framed ? applyReplyThrowFraming(record.text) : record.text;
|
|
79312
|
+
const selfImproveFramed = shouldFrameSelfImprovement(record, { frameEnabled: selfImprovementFraming }) && !isSelfImprovementCard(record.text);
|
|
79313
|
+
const body = selfImproveFramed ? applySelfImprovementFraming(provenanceBody) : provenanceBody;
|
|
79274
79314
|
return {
|
|
79275
79315
|
action: delayed ? "send-delayed" : "send",
|
|
79276
79316
|
text: prefix + body,
|
|
79277
|
-
...framed &&
|
|
79317
|
+
...framed && provenanceBody !== record.text ? { framedProvenance: "reply-throw" } : {},
|
|
79318
|
+
...selfImproveFramed && body !== provenanceBody ? { framedSelfImprovement: "self-improve" } : {}
|
|
79278
79319
|
};
|
|
79279
79320
|
}
|
|
79280
79321
|
function resolveOutboxChat(record, deps) {
|
|
@@ -79605,7 +79646,10 @@ function journalExternalDelivery(args, stateDir, now = Date.now()) {
|
|
|
79605
79646
|
ts: now,
|
|
79606
79647
|
deliverySource: args.deliverySource ?? "reply-tool",
|
|
79607
79648
|
...args.replyAlreadyDeliveredThisTurn == null ? {} : { replyAlreadyDeliveredThisTurn: args.replyAlreadyDeliveredThisTurn },
|
|
79608
|
-
...args.framedProvenance == null ? {} : { framedProvenance: args.framedProvenance }
|
|
79649
|
+
...args.framedProvenance == null ? {} : { framedProvenance: args.framedProvenance },
|
|
79650
|
+
...args.audience == null ? {} : { audience: args.audience },
|
|
79651
|
+
...args.suppressedAudience == null ? {} : { suppressedAudience: args.suppressedAudience },
|
|
79652
|
+
...args.framedSelfImprovement == null ? {} : { framedSelfImprovement: args.framedSelfImprovement }
|
|
79609
79653
|
}, stateDir);
|
|
79610
79654
|
clearOutboxRecord(nonce, stateDir);
|
|
79611
79655
|
}
|
|
@@ -80285,7 +80329,8 @@ function decideCapturedProseDelivery(args, deps) {
|
|
|
80285
80329
|
deliver: true,
|
|
80286
80330
|
text: text4,
|
|
80287
80331
|
reason: "captured-prose",
|
|
80288
|
-
...state3.replyToolThrewThisTurn === true ? { replyToolThrewThisTurn: true } : {}
|
|
80332
|
+
...state3.replyToolThrewThisTurn === true ? { replyToolThrewThisTurn: true } : {},
|
|
80333
|
+
...state3.reviewOriginated === true ? { reviewOriginated: true } : {}
|
|
80289
80334
|
};
|
|
80290
80335
|
}
|
|
80291
80336
|
function settleCapturedProseDelivery(outcome, effects) {
|
|
@@ -81366,67 +81411,104 @@ async function deliverCapturedProse(deps, args) {
|
|
|
81366
81411
|
const { chatId, threadId, statusKeyStr, registryKey, originTurnId, text: text4, turnDurationMs } = args;
|
|
81367
81412
|
const now = Date.now();
|
|
81368
81413
|
const framed = shouldFrameReplyThrow({ replyToolThrewThisTurn: args.replyToolThrewThisTurn }, { frameEnabled: process.env.SWITCHROOM_TG_OUTBOX_PROVENANCE_FRAMING !== "0" });
|
|
81414
|
+
const audienceGateEnabled = process.env.SWITCHROOM_TG_OUTBOX_AUDIENCE_GATE !== "0";
|
|
81415
|
+
const audience = decideCaptureAudience({
|
|
81416
|
+
reviewOriginated: args.reviewOriginated === true,
|
|
81417
|
+
reviewTextIsCard: isSelfImprovementCard(text4)
|
|
81418
|
+
});
|
|
81419
|
+
const suppressed = audienceGateEnabled && audience === AUDIENCE_INTERNAL;
|
|
81420
|
+
const selfImproveFramed = !suppressed && shouldFrameSelfImprovement({ reviewOriginated: args.reviewOriginated }, { frameEnabled: process.env.SWITCHROOM_TG_OUTBOX_SELF_IMPROVE_FRAMING !== "0" }) && !isSelfImprovementCard(text4);
|
|
81369
81421
|
let outcome;
|
|
81370
|
-
|
|
81371
|
-
|
|
81372
|
-
|
|
81373
|
-
|
|
81374
|
-
|
|
81375
|
-
|
|
81376
|
-
|
|
81377
|
-
|
|
81378
|
-
|
|
81379
|
-
|
|
81380
|
-
|
|
81381
|
-
|
|
81382
|
-
|
|
81383
|
-
|
|
81384
|
-
|
|
81385
|
-
|
|
81386
|
-
|
|
81387
|
-
|
|
81422
|
+
if (suppressed) {
|
|
81423
|
+
journalExternalDelivery({
|
|
81424
|
+
turnNonce: originTurnId,
|
|
81425
|
+
text: text4,
|
|
81426
|
+
replyAlreadyDeliveredThisTurn: false,
|
|
81427
|
+
audience,
|
|
81428
|
+
suppressedAudience: AUDIENCE_INTERNAL
|
|
81429
|
+
});
|
|
81430
|
+
process.stderr.write(formatInternalSuppression({
|
|
81431
|
+
turnNonce: originTurnId,
|
|
81432
|
+
turnId: originTurnId,
|
|
81433
|
+
chatId,
|
|
81434
|
+
textSha256: sha256Hex(text4),
|
|
81435
|
+
source: "captured-prose-bridge"
|
|
81436
|
+
}));
|
|
81437
|
+
outcome = "suppressed-internal";
|
|
81438
|
+
} else {
|
|
81439
|
+
const already = outboundDedup.check(chatId, threadId, text4, now, registryKey);
|
|
81440
|
+
if (already == null) {
|
|
81441
|
+
let out = normalizeParagraphBreaks(repairEscapedWhitespace(framed ? applyReplyThrowFraming(text4) : text4));
|
|
81442
|
+
out = selfImproveFramed ? applySelfImprovementFraming(out) : out;
|
|
81443
|
+
out = redactOutboundText(out, "captured_prose");
|
|
81444
|
+
const chunks = splitMarkdownChunks(out, RICH_MESSAGE_MAX_CHARS);
|
|
81445
|
+
const sentIds = [];
|
|
81446
|
+
try {
|
|
81447
|
+
let liveThreadId = threadId;
|
|
81448
|
+
for (const c of chunks) {
|
|
81449
|
+
const sent = await retryWithThreadFallback(robustApiCall, (tid) => {
|
|
81450
|
+
const opts = {
|
|
81451
|
+
link_preview_options: { is_disabled: true },
|
|
81452
|
+
...tid != null ? { message_thread_id: tid } : {}
|
|
81453
|
+
};
|
|
81454
|
+
return bot.api.sendRichMessage(chatId, richMessage(c), opts);
|
|
81455
|
+
}, { threadId: liveThreadId, chat_id: chatId, verb: "captured-prose.sendMessage" });
|
|
81456
|
+
if (liveThreadId != null && sent.message_thread_id == null) {
|
|
81457
|
+
liveThreadId = undefined;
|
|
81458
|
+
}
|
|
81459
|
+
sentIds.push(sent.message_id);
|
|
81388
81460
|
}
|
|
81389
|
-
sentIds.
|
|
81390
|
-
|
|
81391
|
-
|
|
81392
|
-
|
|
81393
|
-
|
|
81394
|
-
|
|
81395
|
-
|
|
81396
|
-
|
|
81397
|
-
|
|
81398
|
-
|
|
81399
|
-
|
|
81400
|
-
|
|
81401
|
-
outboundDedup.record(chatId, threadId, text4, now, registryKey);
|
|
81402
|
-
journalExternalDelivery({
|
|
81403
|
-
turnNonce: originTurnId,
|
|
81404
|
-
text: text4,
|
|
81405
|
-
tgMessageId: sentIds[sentIds.length - 1],
|
|
81406
|
-
replyAlreadyDeliveredThisTurn: false,
|
|
81407
|
-
...framed ? { framedProvenance: "reply-throw" } : {}
|
|
81408
|
-
});
|
|
81409
|
-
process.stderr.write(`telegram gateway: captured-prose delivery \u2014 sent ${out.length} chars recovered from ` + `transcript scan (chat=${chatId} origin=${originTurnId})
|
|
81410
|
-
`);
|
|
81411
|
-
if (framed) {
|
|
81412
|
-
process.stderr.write(formatReplyThrowFraming({
|
|
81461
|
+
if (HISTORY_ENABLED && sentIds.length > 0) {
|
|
81462
|
+
try {
|
|
81463
|
+
recordOutbound2({
|
|
81464
|
+
chat_id: chatId,
|
|
81465
|
+
thread_id: threadId ?? null,
|
|
81466
|
+
message_ids: sentIds,
|
|
81467
|
+
texts: chunks
|
|
81468
|
+
});
|
|
81469
|
+
} catch {}
|
|
81470
|
+
}
|
|
81471
|
+
outboundDedup.record(chatId, threadId, text4, now, registryKey);
|
|
81472
|
+
journalExternalDelivery({
|
|
81413
81473
|
turnNonce: originTurnId,
|
|
81414
|
-
|
|
81415
|
-
|
|
81416
|
-
|
|
81417
|
-
|
|
81418
|
-
|
|
81474
|
+
text: text4,
|
|
81475
|
+
tgMessageId: sentIds[sentIds.length - 1],
|
|
81476
|
+
replyAlreadyDeliveredThisTurn: false,
|
|
81477
|
+
...framed ? { framedProvenance: "reply-throw" } : {},
|
|
81478
|
+
...selfImproveFramed ? { framedSelfImprovement: "self-improve" } : {},
|
|
81479
|
+
audience
|
|
81480
|
+
});
|
|
81481
|
+
process.stderr.write(`telegram gateway: captured-prose delivery \u2014 sent ${out.length} chars recovered from ` + `transcript scan (chat=${chatId} origin=${originTurnId})
|
|
81482
|
+
`);
|
|
81483
|
+
if (framed) {
|
|
81484
|
+
process.stderr.write(formatReplyThrowFraming({
|
|
81485
|
+
turnNonce: originTurnId,
|
|
81486
|
+
turnId: originTurnId,
|
|
81487
|
+
chatId,
|
|
81488
|
+
textSha256: sha256Hex(text4),
|
|
81489
|
+
source: "captured-prose-bridge"
|
|
81490
|
+
}));
|
|
81491
|
+
}
|
|
81492
|
+
if (selfImproveFramed) {
|
|
81493
|
+
process.stderr.write(formatSelfImprovementFraming({
|
|
81494
|
+
turnNonce: originTurnId,
|
|
81495
|
+
turnId: originTurnId,
|
|
81496
|
+
chatId,
|
|
81497
|
+
textSha256: sha256Hex(text4),
|
|
81498
|
+
source: "captured-prose-bridge"
|
|
81499
|
+
}));
|
|
81500
|
+
}
|
|
81501
|
+
outcome = "sent";
|
|
81502
|
+
} catch (err) {
|
|
81503
|
+
process.stderr.write(`telegram gateway: captured-prose delivery failed: ${err.message} \u2014 ` + `arming the silent-end re-prompt net (recordUndeliveredTurnEnd) so the ` + `answer is recoverable (chat=${chatId} origin=${originTurnId})
|
|
81504
|
+
`);
|
|
81505
|
+
outcome = "failed";
|
|
81419
81506
|
}
|
|
81420
|
-
|
|
81421
|
-
|
|
81422
|
-
process.stderr.write(`telegram gateway: captured-prose delivery failed: ${err.message} \u2014 ` + `arming the silent-end re-prompt net (recordUndeliveredTurnEnd) so the ` + `answer is recoverable (chat=${chatId} origin=${originTurnId})
|
|
81507
|
+
} else {
|
|
81508
|
+
process.stderr.write(`telegram gateway: captured-prose delivery skipped \u2014 this answer already went out ` + `(dedup age=${already.ageMs}ms chat=${chatId} origin=${originTurnId}); settling bookkeeping
|
|
81423
81509
|
`);
|
|
81424
|
-
outcome = "
|
|
81510
|
+
outcome = "skipped-dedup";
|
|
81425
81511
|
}
|
|
81426
|
-
} else {
|
|
81427
|
-
process.stderr.write(`telegram gateway: captured-prose delivery skipped \u2014 this answer already went out ` + `(dedup age=${already.ageMs}ms chat=${chatId} origin=${originTurnId}); settling bookkeeping
|
|
81428
|
-
`);
|
|
81429
|
-
outcome = "skipped-dedup";
|
|
81430
81512
|
}
|
|
81431
81513
|
const settlement = settleCapturedProseDelivery(outcome, {
|
|
81432
81514
|
closeObligation: () => {
|
|
@@ -83909,6 +83991,7 @@ function handleSessionEvent(deps, ev) {
|
|
|
83909
83991
|
originTurnId: turn.turnId,
|
|
83910
83992
|
text: proseDecision.text,
|
|
83911
83993
|
replyToolThrewThisTurn: proseDecision.replyToolThrewThisTurn === true,
|
|
83994
|
+
reviewOriginated: proseDecision.reviewOriginated === true,
|
|
83912
83995
|
turnDurationMs
|
|
83913
83996
|
});
|
|
83914
83997
|
} else {
|
|
@@ -87898,6 +87981,7 @@ var HINDSIGHT_PG_DEFAULT_EFFECTIVE_CACHE_SIZE_MIB = 12288;
|
|
|
87898
87981
|
function pgMib(mib) {
|
|
87899
87982
|
return `${mib}MB`;
|
|
87900
87983
|
}
|
|
87984
|
+
var HINDSIGHT_PG_MIN_NON_BUFFER_MIB = HINDSIGHT_PG_APP_ANON_MIB + HINDSIGHT_PG_PAGE_CACHE_FLOOR_MIB;
|
|
87901
87985
|
var HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE_ENV = "SWITCHROOM_HINDSIGHT_PG_EFFECTIVE_CACHE_SIZE";
|
|
87902
87986
|
var HINDSIGHT_PG_SHARED_BUFFERS_ENV = "SWITCHROOM_HINDSIGHT_PG_SHARED_BUFFERS";
|
|
87903
87987
|
var HINDSIGHT_PG_FSYNC_ENV = "SWITCHROOM_HINDSIGHT_PG_FSYNC";
|
|
@@ -87945,6 +88029,7 @@ var HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY = 0.3;
|
|
|
87945
88029
|
var HINDSIGHT_DEFAULT_LLM_SUPPORTS_MAX_ITEMS = "false";
|
|
87946
88030
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_FUNCTION = "exponential";
|
|
87947
88031
|
var HINDSIGHT_DEFAULT_RECENCY_DECAY_HALFLIFE_DAYS = 30;
|
|
88032
|
+
var HINDSIGHT_DEFAULT_TEXT_SEARCH_EXTENSION = "pg_search";
|
|
87948
88033
|
var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
87949
88034
|
[
|
|
87950
88035
|
"HINDSIGHT_API_RECALL_MAX_CANDIDATES_PER_SOURCE",
|
|
@@ -88010,7 +88095,8 @@ var HINDSIGHT_PERF_DEFAULTS_UNGATED = [
|
|
|
88010
88095
|
[
|
|
88011
88096
|
"HINDSIGHT_API_GRAPH_SEED_MIN_SIMILARITY",
|
|
88012
88097
|
String(HINDSIGHT_DEFAULT_GRAPH_SEED_MIN_SIMILARITY)
|
|
88013
|
-
]
|
|
88098
|
+
],
|
|
88099
|
+
["HINDSIGHT_API_TEXT_SEARCH_EXTENSION", HINDSIGHT_DEFAULT_TEXT_SEARCH_EXTENSION]
|
|
88014
88100
|
];
|
|
88015
88101
|
var HINDSIGHT_PERF_DEFAULTS_GPU = [
|
|
88016
88102
|
["HINDSIGHT_API_RERANKER_LOCAL_FP16", HINDSIGHT_DEFAULT_RERANKER_LOCAL_FP16],
|
|
@@ -94212,6 +94298,7 @@ function hydrateResumeLedger(ledger, turnId, snapshot, hasLanded) {
|
|
|
94212
94298
|
}
|
|
94213
94299
|
function createCapturedResumeDispatcher(ports) {
|
|
94214
94300
|
const stderr = ports.stderr ?? (() => {});
|
|
94301
|
+
const hasOutboundWithText3 = ports.hasOutboundWithText ?? hasOutboundWithText2;
|
|
94215
94302
|
const inFlight = new Set;
|
|
94216
94303
|
function deliver(o, snapshot) {
|
|
94217
94304
|
return ports.deliverAnswer({
|
|
@@ -94223,7 +94310,7 @@ function createCapturedResumeDispatcher(ports) {
|
|
|
94223
94310
|
replyToMessageId: o.messageId,
|
|
94224
94311
|
resume: {
|
|
94225
94312
|
snapshot,
|
|
94226
|
-
hydrate: (ledger, turnId) => hydrateResumeLedger(ledger, turnId, snapshot, (txt) => ports.historyEnabled &&
|
|
94313
|
+
hydrate: (ledger, turnId) => hydrateResumeLedger(ledger, turnId, snapshot, (txt) => ports.historyEnabled && hasOutboundWithText3(o.chatId, txt, o.threadId ?? null, o.openedAt))
|
|
94227
94314
|
}
|
|
94228
94315
|
});
|
|
94229
94316
|
}
|
|
@@ -103030,6 +103117,8 @@ async function sweepOutbox(deps) {
|
|
|
103030
103117
|
const escalateInternalSuppression = deps.escalateInternalSuppression ?? log;
|
|
103031
103118
|
const provenanceFramingEnabled = deps.provenanceFramingEnabled?.() ?? process.env.SWITCHROOM_TG_OUTBOX_PROVENANCE_FRAMING !== "0";
|
|
103032
103119
|
const logProvenanceFraming = deps.logProvenanceFraming ?? log;
|
|
103120
|
+
const selfImprovementFramingEnabled = deps.selfImprovementFramingEnabled?.() ?? process.env.SWITCHROOM_TG_OUTBOX_SELF_IMPROVE_FRAMING !== "0";
|
|
103121
|
+
const logSelfImprovementFraming = deps.logSelfImprovementFraming ?? log;
|
|
103033
103122
|
for (const record2 of records) {
|
|
103034
103123
|
summary.scanned++;
|
|
103035
103124
|
if (shouldSuppressForAudience(record2, { gateEnabled: audienceGateEnabled })) {
|
|
@@ -103075,7 +103164,8 @@ async function sweepOutbox(deps) {
|
|
|
103075
103164
|
routePrefix,
|
|
103076
103165
|
quietMs: deps.quietMs ?? OUTBOX_QUIET_MS,
|
|
103077
103166
|
shownLedgerHit: isShownBlock(record2.turnNonce, record2.text, deps.stateDir),
|
|
103078
|
-
provenanceFraming: provenanceFramingEnabled
|
|
103167
|
+
provenanceFraming: provenanceFramingEnabled,
|
|
103168
|
+
selfImprovementFraming: selfImprovementFramingEnabled
|
|
103079
103169
|
});
|
|
103080
103170
|
if (decision.action !== "send" && decision.action !== "send-delayed") {
|
|
103081
103171
|
summary.skipped++;
|
|
@@ -103119,7 +103209,8 @@ async function sweepOutbox(deps) {
|
|
|
103119
103209
|
ts: now,
|
|
103120
103210
|
deliverySource: "sweep",
|
|
103121
103211
|
replyAlreadyDeliveredThisTurn: record2.replyAlreadyDeliveredThisTurn === true,
|
|
103122
|
-
...decision.framedProvenance != null ? { framedProvenance: decision.framedProvenance } : {}
|
|
103212
|
+
...decision.framedProvenance != null ? { framedProvenance: decision.framedProvenance } : {},
|
|
103213
|
+
...decision.framedSelfImprovement != null ? { framedSelfImprovement: decision.framedSelfImprovement } : {}
|
|
103123
103214
|
}, deps.stateDir);
|
|
103124
103215
|
if (decision.framedProvenance != null) {
|
|
103125
103216
|
summary.provenanceFramed = (summary.provenanceFramed ?? 0) + 1;
|
|
@@ -103131,6 +103222,16 @@ async function sweepOutbox(deps) {
|
|
|
103131
103222
|
source: record2.source
|
|
103132
103223
|
}));
|
|
103133
103224
|
}
|
|
103225
|
+
if (decision.framedSelfImprovement != null) {
|
|
103226
|
+
summary.selfImprovementFramed = (summary.selfImprovementFramed ?? 0) + 1;
|
|
103227
|
+
logSelfImprovementFraming(formatSelfImprovementFraming({
|
|
103228
|
+
turnNonce: record2.turnNonce,
|
|
103229
|
+
turnId: turnIdFromNonce(record2.turnNonce),
|
|
103230
|
+
chatId: resolvedChat.chatId,
|
|
103231
|
+
textSha256: record2.textSha256,
|
|
103232
|
+
source: record2.source
|
|
103233
|
+
}));
|
|
103234
|
+
}
|
|
103134
103235
|
if (deps.recordOutbound != null && sendResult.chunks.length > 0) {
|
|
103135
103236
|
try {
|
|
103136
103237
|
deps.recordOutbound(resolvedChat.chatId, resolvedChat.threadId, sendResult.chunks.map((c) => c.messageId), sendResult.chunks.map((c) => c.text));
|
|
@@ -103337,10 +103438,10 @@ function startOutboxSweep(deps) {
|
|
|
103337
103438
|
}
|
|
103338
103439
|
|
|
103339
103440
|
// ../src/build-info.ts
|
|
103340
|
-
var VERSION2 = "0.20.
|
|
103341
|
-
var COMMIT_SHA = "
|
|
103342
|
-
var COMMIT_DATE = "2026-08-
|
|
103343
|
-
var LATEST_PR =
|
|
103441
|
+
var VERSION2 = "0.20.13";
|
|
103442
|
+
var COMMIT_SHA = "a73b0fd2";
|
|
103443
|
+
var COMMIT_DATE = "2026-08-07T03:01:37Z";
|
|
103444
|
+
var LATEST_PR = 4502;
|
|
103344
103445
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
103345
103446
|
|
|
103346
103447
|
// gateway/boot-version.ts
|