switchroom 0.21.3 → 0.21.5
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/bin/handoff-briefing.sh +23 -1
- package/dist/cli/switchroom.js +79 -16
- package/dist/host-control/main.js +1 -1
- package/package.json +4 -2
- package/telegram-plugin/dist/gateway/gateway.js +406 -121
- package/telegram-plugin/gateway/gateway.ts +24 -22
- package/telegram-plugin/gateway/inbound-router.ts +77 -26
- package/telegram-plugin/gateway/orphaned-db-sweep.ts +315 -0
- package/telegram-plugin/gateway/system-message-observer.ts +25 -6
- package/telegram-plugin/history.ts +328 -62
- package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +19 -4
- package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +8 -2
- package/telegram-plugin/shared/bot-runtime.ts +119 -2
- package/telegram-plugin/tests/card-history-lane.test.ts +171 -2
- package/telegram-plugin/tests/orphaned-db-sweep.test.ts +721 -0
- package/telegram-plugin/tests/reply-to-buffer-fallback.test.ts +209 -4
- package/telegram-plugin/tests/system-message-observer.test.ts +84 -1
package/bin/handoff-briefing.sh
CHANGED
|
@@ -136,6 +136,7 @@ if [ -n "$TELEGRAM_STATE" ] && [ -d "$TELEGRAM_STATE" ]; then
|
|
|
136
136
|
# under `2>/dev/null`, so the breadcrumb is a debug/manual-run diagnostic.
|
|
137
137
|
TELEGRAM_ROWS=$(python3 - "$HISTORY_DB" "$MAX_MESSAGES" "$TARGET_CHAT_ID" "$TARGET_THREAD_ID" <<'PYEOF'
|
|
138
138
|
import sys, sqlite3, datetime
|
|
139
|
+
from urllib.parse import quote
|
|
139
140
|
|
|
140
141
|
db_path = sys.argv[1]
|
|
141
142
|
limit = int(sys.argv[2])
|
|
@@ -143,7 +144,28 @@ target_chat = sys.argv[3] if len(sys.argv) > 3 else ""
|
|
|
143
144
|
target_thread = sys.argv[4] if len(sys.argv) > 4 else ""
|
|
144
145
|
|
|
145
146
|
try:
|
|
146
|
-
|
|
147
|
+
# READ-ONLY, ALWAYS. `sqlite3.connect(path)` defaults to READ-WRITE, which
|
|
148
|
+
# makes this briefing assembler a writer on the gateway's live WAL DB. A
|
|
149
|
+
# read-write connection that closes as the LAST connection runs SQLite's
|
|
150
|
+
# checkpoint-and-delete path and UNLINKS `history.db-wal` / `-shm` — and
|
|
151
|
+
# this script runs at agent boot, precisely when the gateway is down or
|
|
152
|
+
# starting and this process IS the last connection. Any handle still
|
|
153
|
+
# mapped to those inodes then writes into deleted files: every INSERT
|
|
154
|
+
# reports success and every row is gone at the next restart (the
|
|
155
|
+
# `/proc/<pid>/fd/N -> history.db-wal (deleted)` signature that #4595
|
|
156
|
+
# sweeps for after the fact).
|
|
157
|
+
#
|
|
158
|
+
# `mode=ro` removes that primitive entirely: a read-only connection cannot
|
|
159
|
+
# checkpoint and cannot unlink a sidecar. It still reads a WAL database
|
|
160
|
+
# correctly in every boot state we care about — sidecars present, `-shm`
|
|
161
|
+
# absent, and `-shm` absent with an unwritable directory (SQLite falls back
|
|
162
|
+
# to a heap wal-index rather than failing). Every statement below is a
|
|
163
|
+
# SELECT or a PRAGMA table_info, so nothing here needs write access.
|
|
164
|
+
#
|
|
165
|
+
# The path is percent-encoded: a `?` or `#` in the state dir would
|
|
166
|
+
# otherwise be parsed as the URI's query/fragment delimiter and silently
|
|
167
|
+
# truncate the filename.
|
|
168
|
+
conn = sqlite3.connect("file:" + quote(db_path) + "?mode=ro", uri=True)
|
|
147
169
|
conn.row_factory = sqlite3.Row
|
|
148
170
|
cur = conn.cursor()
|
|
149
171
|
|
package/dist/cli/switchroom.js
CHANGED
|
@@ -2120,7 +2120,7 @@ var init_esm = __esm(() => {
|
|
|
2120
2120
|
});
|
|
2121
2121
|
|
|
2122
2122
|
// src/build-info.ts
|
|
2123
|
-
var VERSION = "0.21.
|
|
2123
|
+
var VERSION = "0.21.5", COMMIT_SHA = "a9aceb2f";
|
|
2124
2124
|
|
|
2125
2125
|
// src/cli/resolve-version.ts
|
|
2126
2126
|
import { existsSync, readFileSync } from "node:fs";
|
|
@@ -63125,6 +63125,17 @@ function rollbackHint(installDir, previousVersion) {
|
|
|
63125
63125
|
function alreadySelfUpdated(env2) {
|
|
63126
63126
|
return env2[SELF_UPDATE_ENV_SENTINEL] === "1";
|
|
63127
63127
|
}
|
|
63128
|
+
function describeBinaryProbeFailure(opts) {
|
|
63129
|
+
const { probe: probe2, path: path7, subject } = opts;
|
|
63130
|
+
switch (probe2.kind) {
|
|
63131
|
+
case "not-executable":
|
|
63132
|
+
return `could not EXECUTE ${subject} at ${path7} (${probe2.detail}). This is a ` + `property of WHERE it was staged, not of the artifact \u2014 the usual causes ` + `are a staging directory mounted \`noexec\`, a lost execute bit, or an ` + `architecture this kernel cannot run. The download's sha256 already ` + `matched the release's checksums file, so re-downloading will not help.`;
|
|
63133
|
+
case "ran-but-failed":
|
|
63134
|
+
return `${subject} at ${path7} ran but exited non-zero for \`--version\` ` + `(${probe2.detail}) \u2014 the artifact itself is faulty.`;
|
|
63135
|
+
case "no-version":
|
|
63136
|
+
return `${subject} at ${path7} ran and exited 0 but printed no parseable version ` + `(${probe2.detail}) \u2014 the artifact itself is faulty.`;
|
|
63137
|
+
}
|
|
63138
|
+
}
|
|
63128
63139
|
async function fetchLatestReleaseTag(io) {
|
|
63129
63140
|
try {
|
|
63130
63141
|
return parseLatestReleaseTag(await io.httpGetText(GITHUB_LATEST_RELEASE_URL));
|
|
@@ -63278,10 +63289,14 @@ async function performSelfUpdate(opts) {
|
|
|
63278
63289
|
throw new Error(`self-update: SHA256 mismatch for ${assetName} (expected ${expected}, got ${actual}) \u2014 ` + `refusing to install. The installed CLI is unchanged.`);
|
|
63279
63290
|
}
|
|
63280
63291
|
io.chmodExec(tmp);
|
|
63281
|
-
const proved = io.
|
|
63282
|
-
if (!proved) {
|
|
63292
|
+
const proved = io.probeBinary(tmp);
|
|
63293
|
+
if (!proved.ok) {
|
|
63283
63294
|
io.remove(tmp);
|
|
63284
|
-
throw new Error(`self-update:
|
|
63295
|
+
throw new Error(`self-update: ${describeBinaryProbeFailure({
|
|
63296
|
+
probe: proved,
|
|
63297
|
+
path: tmp,
|
|
63298
|
+
subject: `the downloaded ${plan.to} binary`
|
|
63299
|
+
})} Refusing to install it. The installed CLI is unchanged.`);
|
|
63285
63300
|
}
|
|
63286
63301
|
const payload = await installAssetPayload({
|
|
63287
63302
|
tag: plan.to,
|
|
@@ -64920,6 +64935,7 @@ async function defaultLoadDecisions() {
|
|
|
64920
64935
|
"exec",
|
|
64921
64936
|
"switchroom-vault-broker",
|
|
64922
64937
|
"sqlite3",
|
|
64938
|
+
"-readonly",
|
|
64923
64939
|
"-separator",
|
|
64924
64940
|
SEP2,
|
|
64925
64941
|
GRANTS_DB_CONTAINER_PATH,
|
|
@@ -84377,7 +84393,8 @@ function detectGatewayFindings(agent, logText, logName = `logs/${agent}/gateway-
|
|
|
84377
84393
|
const gw_hits = {
|
|
84378
84394
|
"duplicate-delivery-represent": 0,
|
|
84379
84395
|
"represent-escalation": 0,
|
|
84380
|
-
"reply-delivery-failure": 0
|
|
84396
|
+
"reply-delivery-failure": 0,
|
|
84397
|
+
"orphaned-db-handle": 0
|
|
84381
84398
|
};
|
|
84382
84399
|
const lines = logText.split(`
|
|
84383
84400
|
`);
|
|
@@ -84435,7 +84452,8 @@ var init_detect = __esm(() => {
|
|
|
84435
84452
|
GATEWAY_SIGNATURES = {
|
|
84436
84453
|
"duplicate-delivery-represent": /represent duplicate-send/,
|
|
84437
84454
|
"represent-escalation": /obligation escalation/,
|
|
84438
|
-
"reply-delivery-failure": /tg-post method=sendRichMessage[^\n]*status=err(?![a-z])
|
|
84455
|
+
"reply-delivery-failure": /tg-post method=sendRichMessage[^\n]*status=err(?![a-z])/,
|
|
84456
|
+
"orphaned-db-handle": /orphaned-db-sweep DETECTED \d+ deleted-inode DB handle/
|
|
84439
84457
|
};
|
|
84440
84458
|
});
|
|
84441
84459
|
|
|
@@ -84499,6 +84517,12 @@ var init_mapping = __esm(() => {
|
|
|
84499
84517
|
job_spec: "talk-to-agents-from-anywhere",
|
|
84500
84518
|
signature: "reply-delivery-failure:sendRichMessage-err"
|
|
84501
84519
|
},
|
|
84520
|
+
"orphaned-db-handle": {
|
|
84521
|
+
failure_mode: "success-theater",
|
|
84522
|
+
severity: 3,
|
|
84523
|
+
job_spec: "survive-reboots-and-real-life",
|
|
84524
|
+
signature: "orphaned-db-handle:deleted-inode-writes"
|
|
84525
|
+
},
|
|
84502
84526
|
"hang-long-stalled": {
|
|
84503
84527
|
failure_mode: "partial",
|
|
84504
84528
|
severity: 2,
|
|
@@ -86288,6 +86312,7 @@ function readLastMessages(historyDbPath) {
|
|
|
86288
86312
|
} catch {}
|
|
86289
86313
|
try {
|
|
86290
86314
|
const out = execFileSync11("sqlite3", [
|
|
86315
|
+
"-readonly",
|
|
86291
86316
|
historyDbPath,
|
|
86292
86317
|
"SELECT role, MAX(ts) FROM messages GROUP BY role;"
|
|
86293
86318
|
], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
@@ -92344,7 +92369,7 @@ function scrubSqlite(path2, values, dryRun) {
|
|
|
92344
92369
|
for (const { value } of values) {
|
|
92345
92370
|
const esc = value.replace(/'/g, "''");
|
|
92346
92371
|
try {
|
|
92347
|
-
const out = execFileSync17("sqlite3", [path2, `SELECT COUNT(*) FROM messages WHERE text LIKE '%${esc}%'`], { encoding: "utf8", timeout: 1e4 });
|
|
92372
|
+
const out = execFileSync17("sqlite3", ["-readonly", path2, `SELECT COUNT(*) FROM messages WHERE text LIKE '%${esc}%'`], { encoding: "utf8", timeout: 1e4 });
|
|
92348
92373
|
const n = parseInt(out.trim(), 10);
|
|
92349
92374
|
if (!Number.isNaN(n))
|
|
92350
92375
|
matches += n;
|
|
@@ -106609,7 +106634,7 @@ function readTopicsFromHistory(dbPath, chatId, limit) {
|
|
|
106609
106634
|
fail2("`switchroom telegram topics` requires the Bun runtime (history DB uses bun:sqlite). " + "Run via `bun run dev` or via the installed `switchroom` CLI (bun-bundled).");
|
|
106610
106635
|
}
|
|
106611
106636
|
const { Database: Database2 } = metaRequire("bun:sqlite");
|
|
106612
|
-
const db = new Database2(dbPath, { create: false });
|
|
106637
|
+
const db = new Database2(dbPath, { create: false, readonly: true });
|
|
106613
106638
|
try {
|
|
106614
106639
|
const aggregateRows = db.prepare(`
|
|
106615
106640
|
SELECT
|
|
@@ -115306,6 +115331,11 @@ import { Readable } from "node:stream";
|
|
|
115306
115331
|
import { pipeline } from "node:stream/promises";
|
|
115307
115332
|
import { spawnSync as spawnSync18 } from "node:child_process";
|
|
115308
115333
|
var HTTP_TIMEOUT_MS = 60000;
|
|
115334
|
+
function firstLine2(s) {
|
|
115335
|
+
const line = `${s ?? ""}`.split(`
|
|
115336
|
+
`).map((l) => l.trim()).find((l) => l.length > 0) ?? "";
|
|
115337
|
+
return line.length > 200 ? `${line.slice(0, 197)}...` : line;
|
|
115338
|
+
}
|
|
115309
115339
|
function defaultSelfUpdateIO() {
|
|
115310
115340
|
return {
|
|
115311
115341
|
async httpGetText(url) {
|
|
@@ -115345,17 +115375,40 @@ function defaultSelfUpdateIO() {
|
|
|
115345
115375
|
}
|
|
115346
115376
|
return hash2.digest("hex");
|
|
115347
115377
|
},
|
|
115348
|
-
|
|
115349
|
-
const r = spawnSync18(path7, ["version"], {
|
|
115378
|
+
probeBinary(path7) {
|
|
115379
|
+
const r = spawnSync18(path7, ["--version"], {
|
|
115350
115380
|
encoding: "utf-8",
|
|
115351
115381
|
timeout: 30000,
|
|
115352
115382
|
env: { ...process.env, SWITCHROOM_SELF_UPDATED: "" }
|
|
115353
115383
|
});
|
|
115354
|
-
if (r.
|
|
115355
|
-
|
|
115384
|
+
if (r.error) {
|
|
115385
|
+
const code = r.error.code;
|
|
115386
|
+
return {
|
|
115387
|
+
ok: false,
|
|
115388
|
+
kind: "not-executable",
|
|
115389
|
+
detail: code ? `${code}: ${r.error.message}` : r.error.message
|
|
115390
|
+
};
|
|
115391
|
+
}
|
|
115392
|
+
if (r.signal) {
|
|
115393
|
+
return { ok: false, kind: "not-executable", detail: `killed by signal ${r.signal}` };
|
|
115394
|
+
}
|
|
115395
|
+
if (r.status !== 0) {
|
|
115396
|
+
return {
|
|
115397
|
+
ok: false,
|
|
115398
|
+
kind: "ran-but-failed",
|
|
115399
|
+
detail: `exit ${r.status}${firstLine2(r.stderr) ? `: ${firstLine2(r.stderr)}` : ""}`
|
|
115400
|
+
};
|
|
115401
|
+
}
|
|
115356
115402
|
const out = `${r.stdout ?? ""}`.trim();
|
|
115357
115403
|
const m = out.match(/\d+\.\d+\.\d+/);
|
|
115358
|
-
|
|
115404
|
+
if (!m) {
|
|
115405
|
+
return {
|
|
115406
|
+
ok: false,
|
|
115407
|
+
kind: "no-version",
|
|
115408
|
+
detail: out ? `printed ${JSON.stringify(firstLine2(out))}` : "printed nothing"
|
|
115409
|
+
};
|
|
115410
|
+
}
|
|
115411
|
+
return { ok: true, version: m[0] };
|
|
115359
115412
|
},
|
|
115360
115413
|
mkdirp(dir) {
|
|
115361
115414
|
mkdirSync49(dir, { recursive: true });
|
|
@@ -116807,11 +116860,21 @@ async function runHostCliUpgrade(opts, io = defaultIo(), log = () => {}) {
|
|
|
116807
116860
|
} catch (err) {
|
|
116808
116861
|
return { ok: false, error: err.message };
|
|
116809
116862
|
}
|
|
116810
|
-
const proven = io.selfUpdate.
|
|
116811
|
-
if (!proven
|
|
116863
|
+
const proven = io.selfUpdate.probeBinary(binary);
|
|
116864
|
+
if (!proven.ok) {
|
|
116865
|
+
return {
|
|
116866
|
+
ok: false,
|
|
116867
|
+
error: `swapped ${binary} but ${describeBinaryProbeFailure({
|
|
116868
|
+
probe: proven,
|
|
116869
|
+
path: binary,
|
|
116870
|
+
subject: "the installed binary"
|
|
116871
|
+
})} ${result.message}`
|
|
116872
|
+
};
|
|
116873
|
+
}
|
|
116874
|
+
if (`v${proven.version.replace(/^v/, "")}` !== pin) {
|
|
116812
116875
|
return {
|
|
116813
116876
|
ok: false,
|
|
116814
|
-
error: `swapped ${binary} but it reports ${proven
|
|
116877
|
+
error: `swapped ${binary} but it reports ${proven.version}, not ${pin} \u2014 ` + `the install did not land. ${result.message}`
|
|
116815
116878
|
};
|
|
116816
116879
|
}
|
|
116817
116880
|
return { ok: true, version: pin, binaryPath: binary };
|
|
@@ -21565,7 +21565,7 @@ function allocateAgentUid(name) {
|
|
|
21565
21565
|
}
|
|
21566
21566
|
|
|
21567
21567
|
// src/build-info.ts
|
|
21568
|
-
var VERSION = "0.21.
|
|
21568
|
+
var VERSION = "0.21.5";
|
|
21569
21569
|
|
|
21570
21570
|
// src/setup/hindsight-recall-passthrough.ts
|
|
21571
21571
|
var HINDSIGHT_RECALL_TAG_WEIGHT_SEED = Object.freeze({ sidechain: 0.8 });
|
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.21.
|
|
4
|
+
"version": "0.21.5",
|
|
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": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"test:vitest": "vitest run",
|
|
29
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-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",
|
|
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-ctx-send-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-foreign-db-readonly.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",
|
|
@@ -46,10 +46,12 @@
|
|
|
46
46
|
"lint:gateway-line-ratchet": "node scripts/check-gateway-line-ratchet.mjs",
|
|
47
47
|
"lint:retry-flood-hooks": "node scripts/check-retry-flood-hooks.mjs",
|
|
48
48
|
"lint:callback-ctx-wrapping": "node scripts/check-callback-ctx-wrapping.mjs",
|
|
49
|
+
"lint:ctx-send-wrapping": "node scripts/check-ctx-send-wrapping.mjs",
|
|
49
50
|
"lint:status-pin-single-path": "node scripts/check-status-pin-single-path.mjs",
|
|
50
51
|
"lint:mcp-instructions-budget": "node scripts/check-mcp-instructions-budget.mjs",
|
|
51
52
|
"lint:litellm-config-guard": "node scripts/check-litellm-config-guard.mjs",
|
|
52
53
|
"lint:release-asset-contract": "node scripts/check-release-asset-names.mjs",
|
|
54
|
+
"lint:foreign-db-readonly": "node scripts/check-foreign-db-readonly.mjs",
|
|
53
55
|
"lint:changelog-entry": "node scripts/check-changelog-entry.mjs",
|
|
54
56
|
"changelog:generate": "node scripts/gen-changelog-entry.mjs",
|
|
55
57
|
"lint:agent-attribution-trailers": "node scripts/check-agent-attribution-trailers.mjs",
|