switchroom 0.17.6 → 0.17.10
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 +38 -4
- package/dist/auth-broker/index.js +302 -203
- package/dist/cli/notion-write-pretool.mjs +35 -2
- package/dist/cli/switchroom.js +1178 -576
- package/dist/host-control/main.js +148 -14
- package/dist/vault/approvals/kernel-server.js +140 -55
- package/dist/vault/broker/server.js +142 -57
- package/package.json +1 -1
- package/profiles/_base/start.sh.hbs +50 -6
- package/profiles/default/CLAUDE.md +116 -0
- package/skills/mental-model-curator/SKILL.md +162 -0
- package/telegram-plugin/bridge/bridge.ts +80 -1
- package/telegram-plugin/bridge/ipc-client.ts +19 -0
- package/telegram-plugin/bridge/permission-ledger.ts +61 -0
- package/telegram-plugin/consolidation-legibility.ts +279 -0
- package/telegram-plugin/dist/bridge/bridge.js +85 -1
- package/telegram-plugin/dist/gateway/gateway.js +2565 -610
- package/telegram-plugin/dist/server.js +86 -2
- package/telegram-plugin/feed-heartbeat-climb.ts +206 -0
- package/telegram-plugin/gateway/activity-card-store.ts +293 -0
- package/telegram-plugin/gateway/gateway.ts +1376 -82
- package/telegram-plugin/gateway/inbound-spool.ts +22 -0
- package/telegram-plugin/gateway/mental-model-propose-card.ts +69 -0
- package/telegram-plugin/gateway/mental-model-propose-diff.ts +171 -0
- package/telegram-plugin/gateway/mental-model-propose-inbound-builders.ts +147 -0
- package/telegram-plugin/gateway/mental-model-propose-resolve.ts +201 -0
- package/telegram-plugin/gateway/missed-approvals-card.ts +161 -0
- package/telegram-plugin/gateway/missed-approvals-store.ts +167 -0
- package/telegram-plugin/gateway/permission-rearm.ts +115 -0
- package/telegram-plugin/gateway/scoped-grant-store.ts +89 -0
- package/telegram-plugin/memory-legibility.ts +217 -0
- package/telegram-plugin/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/telegram-plugin/scoped-approval.ts +59 -0
- package/telegram-plugin/silent-end.ts +78 -0
- package/telegram-plugin/subagent-watcher.ts +60 -6
- package/telegram-plugin/tests/activity-card-store.test.ts +436 -0
- package/telegram-plugin/tests/activity-card-wiring.test.ts +88 -0
- package/telegram-plugin/tests/consolidation-legibility.test.ts +224 -0
- package/telegram-plugin/tests/emission-authority-facade.test.ts +25 -10
- package/telegram-plugin/tests/feed-heartbeat-liveness-open.test.ts +33 -9
- package/telegram-plugin/tests/gateway-boot-marker-clear.test.ts +3 -3
- package/telegram-plugin/tests/inbound-spool.test.ts +105 -0
- package/telegram-plugin/tests/memory-legibility.test.ts +216 -0
- package/telegram-plugin/tests/mental-model-propose-callback-gate.test.ts +67 -0
- package/telegram-plugin/tests/mental-model-propose-card.test.ts +56 -0
- package/telegram-plugin/tests/mental-model-propose-diff.test.ts +201 -0
- package/telegram-plugin/tests/mental-model-propose-inbound-builders.test.ts +68 -0
- package/telegram-plugin/tests/mental-model-propose-resolve.test.ts +157 -0
- package/telegram-plugin/tests/missed-approvals-card.test.ts +145 -0
- package/telegram-plugin/tests/missed-approvals-store.test.ts +147 -0
- package/telegram-plugin/tests/missed-approvals-wiring.test.ts +89 -0
- package/telegram-plugin/tests/permission-ledger.test.ts +166 -0
- package/telegram-plugin/tests/permission-no-repeat-wiring.test.ts +1 -1
- package/telegram-plugin/tests/permission-rearm-wiring.test.ts +175 -0
- package/telegram-plugin/tests/permission-rearm.test.ts +126 -0
- package/telegram-plugin/tests/scoped-grant-persist.test.ts +223 -0
- package/telegram-plugin/tests/silent-end-transport.test.ts +290 -0
- package/telegram-plugin/tests/silent-turn-climb-transport.test.ts +337 -0
- package/telegram-plugin/tests/subagent-watcher.test.ts +139 -0
- package/telegram-plugin/tests/worktree-watch-cwds.test.ts +103 -0
- package/telegram-plugin/uat/assertions.ts +88 -4
- package/telegram-plugin/uat/feed-matcher.test.ts +69 -0
- package/telegram-plugin/uat/scenarios/fuzz-liveness-climb-dm.test.ts +155 -0
- package/telegram-plugin/uat/scenarios/jtbd-directive-capture-nudge-dm.test.ts +185 -0
- package/telegram-plugin/uat/scenarios/jtbd-liveness-climb-channel.test.ts +192 -0
- package/telegram-plugin/uat/scenarios/jtbd-liveness-climb-dm.test.ts +220 -0
- package/telegram-plugin/uat/scenarios/jtbd-liveness-narration-channel.test.ts +137 -0
- package/telegram-plugin/uat/scenarios/jtbd-liveness-narration-dm.test.ts +148 -0
- package/telegram-plugin/uat/scenarios/jtbd-memory-legibility-channel.test.ts +66 -0
- package/telegram-plugin/uat/scenarios/jtbd-memory-legibility-dm.test.ts +61 -0
- package/telegram-plugin/uat/scenarios/silent-end-recovery-channel.test.ts +136 -0
- package/telegram-plugin/uat/scenarios/silent-end-recovery-dm.test.ts +24 -2
- package/telegram-plugin/worktree-watch-cwds.ts +60 -0
- package/vendor/hindsight-memory/hooks/hooks.json +9 -0
- package/vendor/hindsight-memory/scripts/__pycache__/directive_verify.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/__pycache__/drain_pending.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/__pycache__/recall.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/__pycache__/retain.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/__pycache__/session_end.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/directive_verify.py +445 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/__init__.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/bank.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/client.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/config.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/content.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/daemon.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/directives.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/gateway_ipc.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/llm.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/pending.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/state.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/__pycache__/switchroom_envelope.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/lib/config.py +37 -0
- package/vendor/hindsight-memory/scripts/lib/directives.py +88 -0
- package/vendor/hindsight-memory/scripts/lib/switchroom_envelope.py +77 -0
- package/vendor/hindsight-memory/scripts/recall.py +153 -4
- package/vendor/hindsight-memory/scripts/retain.py +17 -0
- package/vendor/hindsight-memory/scripts/setup_hooks.py +9 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/__init__.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_config_client_casts.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_config_client_casts.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directive_capture_nudge.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directive_capture_nudge.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directive_verify.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directive_verify.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directives.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directives.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_gateway_ipc.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_gateway_ipc.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_context_slice.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_context_slice.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_integration.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_integration.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_tag_filters.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_tag_filters.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_topic_filter.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_topic_filter.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_trivial_skip.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_trivial_skip.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_retain_window.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_retain_window.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_sender_routing.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_sender_routing.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/__pycache__/test_switchroom_envelope.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/scripts/tests/test_directive_capture_nudge.py +185 -0
- package/vendor/hindsight-memory/scripts/tests/test_directive_verify.py +516 -0
- package/vendor/hindsight-memory/scripts/tests/test_directives.py +49 -0
- package/vendor/hindsight-memory/scripts/tests/test_retain_window.py +66 -1
- package/vendor/hindsight-memory/scripts/tests/test_switchroom_envelope.py +69 -0
- package/vendor/hindsight-memory/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/conftest.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_bank.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_bank.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_client.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_client.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_config.cpython-313-pytest-9.0.3.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_config.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_config.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_content.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_content.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_drain_pending.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_drain_pending.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_hooks.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_hooks.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_manifest.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_manifest.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_pending.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_pending.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_recall_exit_codes.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_recall_exit_codes.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_session_end_pending.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_session_end_pending.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_state.cpython-313-pytest-9.1.1.pyc +0 -0
- package/vendor/hindsight-memory/tests/__pycache__/test_state.cpython-313.pyc +0 -0
- package/vendor/hindsight-memory/tests/test_recall_exit_codes.py +49 -2
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Switchroom #2903 Fix 6.3 — the `<channel source="...">` envelope grammar is
|
|
2
|
+
extracted from directive_verify.py into lib/switchroom_envelope.py so the
|
|
3
|
+
coupling between the vendored Python guard and the switchroom gateway's TS wire
|
|
4
|
+
format is explicit and testable in ONE place.
|
|
5
|
+
|
|
6
|
+
Pins the grammar so a TS-side format change that breaks these regexes is caught
|
|
7
|
+
by a failing Python test rather than silently disabling the synthetic-inbound
|
|
8
|
+
guard.
|
|
9
|
+
|
|
10
|
+
Stdlib-only.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import sys
|
|
15
|
+
import unittest
|
|
16
|
+
|
|
17
|
+
SCRIPTS_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
|
18
|
+
if SCRIPTS_DIR not in sys.path:
|
|
19
|
+
sys.path.insert(0, SCRIPTS_DIR)
|
|
20
|
+
|
|
21
|
+
from lib.switchroom_envelope import ( # noqa: E402
|
|
22
|
+
HUMAN_INBOUND_SOURCES,
|
|
23
|
+
envelope_source,
|
|
24
|
+
is_synthetic_inbound,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TestEnvelopeSource(unittest.TestCase):
|
|
29
|
+
def test_extracts_open_form(self):
|
|
30
|
+
self.assertEqual(
|
|
31
|
+
envelope_source('<channel source="telegram" chat_id="1">hi</channel>'),
|
|
32
|
+
"telegram",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def test_extracts_self_closing_form(self):
|
|
36
|
+
self.assertEqual(envelope_source('<channel source="reaction"/>'), "reaction")
|
|
37
|
+
|
|
38
|
+
def test_lowercases(self):
|
|
39
|
+
self.assertEqual(envelope_source('<channel source="Cron">x</channel>'), "cron")
|
|
40
|
+
|
|
41
|
+
def test_none_when_no_envelope(self):
|
|
42
|
+
self.assertIsNone(envelope_source("From now on, use British spelling."))
|
|
43
|
+
|
|
44
|
+
def test_none_on_non_string(self):
|
|
45
|
+
for bad in (None, 123, [], {}):
|
|
46
|
+
self.assertIsNone(envelope_source(bad))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class TestSyntheticClassification(unittest.TestCase):
|
|
50
|
+
def test_telegram_is_human(self):
|
|
51
|
+
self.assertIn("telegram", HUMAN_INBOUND_SOURCES)
|
|
52
|
+
self.assertFalse(is_synthetic_inbound('<channel source="telegram">hi</channel>'))
|
|
53
|
+
|
|
54
|
+
def test_no_envelope_is_human(self):
|
|
55
|
+
self.assertFalse(is_synthetic_inbound("hello there"))
|
|
56
|
+
|
|
57
|
+
def test_new_source_defaults_to_synthetic(self):
|
|
58
|
+
# Whitelist posture: an UNKNOWN/new source is treated as machine-authored
|
|
59
|
+
# by default, not accidentally classified human.
|
|
60
|
+
self.assertTrue(is_synthetic_inbound('<channel source="brand_new_channel">x</channel>'))
|
|
61
|
+
|
|
62
|
+
def test_known_synthetic_sources(self):
|
|
63
|
+
for src in ("cron", "reaction", "resume_interrupted", "vault_grant_approved"):
|
|
64
|
+
with self.subTest(src=src):
|
|
65
|
+
self.assertTrue(is_synthetic_inbound(f'<channel source="{src}">x</channel>'))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == "__main__":
|
|
69
|
+
unittest.main()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/vendor/hindsight-memory/tests/__pycache__/test_drain_pending.cpython-313-pytest-9.1.1.pyc
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -37,8 +37,10 @@ executes.
|
|
|
37
37
|
|
|
38
38
|
import json
|
|
39
39
|
import os
|
|
40
|
+
import shutil
|
|
40
41
|
import subprocess
|
|
41
42
|
import sys
|
|
43
|
+
import tempfile
|
|
42
44
|
import textwrap
|
|
43
45
|
|
|
44
46
|
|
|
@@ -48,6 +50,52 @@ SCRIPTS_DIR = os.path.abspath(
|
|
|
48
50
|
RECALL_PY = os.path.join(SCRIPTS_DIR, "recall.py")
|
|
49
51
|
|
|
50
52
|
|
|
53
|
+
def _dir_is_exec_capable(path):
|
|
54
|
+
"""Return True iff a file created under ``path`` can be executed.
|
|
55
|
+
|
|
56
|
+
pytest's ``tmp_path`` defaults to the system temp dir, which on
|
|
57
|
+
hardened hosts / CI containers is frequently mounted ``noexec``
|
|
58
|
+
(verify with ``findmnt -T /tmp``). recall.py invokes the
|
|
59
|
+
``switchroom`` CLI *by name* via ``subprocess.run`` — that resolves
|
|
60
|
+
to our on-PATH shim, which must therefore live on an
|
|
61
|
+
exec-capable filesystem or the call dies with PermissionError and
|
|
62
|
+
the shim never runs. Probe the real invariant rather than assuming.
|
|
63
|
+
"""
|
|
64
|
+
try:
|
|
65
|
+
probe = os.path.join(path, ".exec_probe.sh")
|
|
66
|
+
with open(probe, "w") as fh:
|
|
67
|
+
fh.write("#!/usr/bin/env bash\nexit 0\n")
|
|
68
|
+
os.chmod(probe, 0o755)
|
|
69
|
+
rc = subprocess.run([probe], capture_output=True).returncode
|
|
70
|
+
os.unlink(probe)
|
|
71
|
+
return rc == 0
|
|
72
|
+
except (OSError, PermissionError):
|
|
73
|
+
return False
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _make_exec_bindir(tmp_path):
|
|
77
|
+
"""Create the shim ``bin`` directory on an exec-capable filesystem.
|
|
78
|
+
|
|
79
|
+
Prefer ``tmp_path`` itself (keeps everything colocated); fall back
|
|
80
|
+
to a self-cleaning temp dir next to this test file — which lives in
|
|
81
|
+
the repo checkout, an exec-capable ext4/overlay mount — when the
|
|
82
|
+
default temp root is ``noexec``.
|
|
83
|
+
"""
|
|
84
|
+
if _dir_is_exec_capable(str(tmp_path)):
|
|
85
|
+
bindir = tmp_path / "bin"
|
|
86
|
+
bindir.mkdir(exist_ok=True)
|
|
87
|
+
return bindir
|
|
88
|
+
fallback_root = tempfile.mkdtemp(
|
|
89
|
+
prefix="sw-recall-bin-", dir=os.path.dirname(__file__)
|
|
90
|
+
)
|
|
91
|
+
import atexit
|
|
92
|
+
|
|
93
|
+
atexit.register(shutil.rmtree, fallback_root, ignore_errors=True)
|
|
94
|
+
import pathlib
|
|
95
|
+
|
|
96
|
+
return pathlib.Path(fallback_root)
|
|
97
|
+
|
|
98
|
+
|
|
51
99
|
def _run_recall_with_injected_fault(
|
|
52
100
|
tmp_path,
|
|
53
101
|
debug=False,
|
|
@@ -105,8 +153,7 @@ def _run_recall_with_injected_fault(
|
|
|
105
153
|
# Path manipulation for the switchroom shim. We always isolate
|
|
106
154
|
# PATH so the test doesn't accidentally invoke a real `switchroom`
|
|
107
155
|
# on the host — that would write to a real state dir.
|
|
108
|
-
bindir = tmp_path
|
|
109
|
-
bindir.mkdir(exist_ok=True)
|
|
156
|
+
bindir = _make_exec_bindir(tmp_path)
|
|
110
157
|
if switchroom_shim is not None:
|
|
111
158
|
sw = bindir / "switchroom"
|
|
112
159
|
sw.write_text(switchroom_shim)
|