Skip to content

Commit 9430b40

Browse files
cowork-bot: pin workspace='default' contract for cron write tools (engraphis_remember/record_event) regression guard vs fleet-wide 'workspace Field required'
1 parent e8d4ac9 commit 9430b40

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""Regression: every cron-auto-fired WRITE memory tool must default workspace to 'default'.
2+
3+
The 2026-07 fleet-wide outage ("workspace Field required", 200+ occurrences in
4+
gateway.log) happened because ``engraphis_start_session`` hard-required ``workspace``
5+
while the scheduled fleet (hourly-dev-engineer, ops-heartbeat, dashboard-refresh,
6+
vault-cron-health, ...) calls these tools WITHOUT one. That single tool was fixed and
7+
locked by ``test_start_session_workspace_default.py``.
8+
9+
But the *same class* of outage hits every auto-fired WRITE tool the fleet calls without a
10+
workspace. ``engraphis_remember`` and ``engraphis_record_event`` are the actual memory
11+
*write* path: if either regresses to a required ``workspace`` (e.g. someone drops the
12+
``= "default"`` while adding a field, or re-tightens ``min_length=1`` into a required
13+
positional), the fleet silently loses ALL memory writes again — a strictly worse failure
14+
than the session tool, because the data never lands at all.
15+
16+
This test pins the (workspace defaults to 'default') contract for all three auto-fired
17+
write/session tools at two levels:
18+
* signature level — asserts the ``workspace`` parameter still carries the ``"default"``
19+
default (this is the *exact* thing that broke: a missing default), and
20+
* behavioral level — omitting ``workspace`` succeeds and lands the write in 'default'.
21+
22+
NOTE: ``engraphis_recall`` is deliberately excluded. It is a READ tool whose ``workspace``
23+
defaults to ``None`` (search-broadly semantics), so omitting it returns an empty/again
24+
result set rather than crashing with "workspace Field required". Do not "helpfully" add
25+
recall here — its None default is intentional and different from the write-path contract.
26+
"""
27+
import inspect
28+
import json
29+
30+
import pytest
31+
32+
pytest.importorskip("mcp", reason="optional 'mcp' extra not installed")
33+
34+
# Tools the scheduled fleet fires WITHOUT a workspace arg on the write path.
35+
CRON_WRITE_TOOLS = (
36+
"engraphis_start_session",
37+
"engraphis_remember",
38+
"engraphis_record_event",
39+
)
40+
41+
42+
def _module_with_memory_db(monkeypatch):
43+
import engraphis.mcp_server as srv
44+
from engraphis.service import MemoryService
45+
46+
monkeypatch.setattr(srv, "_service", MemoryService.create(":memory:"))
47+
return srv
48+
49+
50+
@pytest.mark.parametrize("tool_name", CRON_WRITE_TOOLS)
51+
def test_cron_write_tool_workspace_defaults_to_default(monkeypatch, tool_name):
52+
"""Signature guard: the exact regression (a removed/renamed default) fails right here."""
53+
srv = _module_with_memory_db(monkeypatch)
54+
param = inspect.signature(getattr(srv, tool_name)).parameters.get("workspace")
55+
assert param is not None, f"{tool_name} lost its 'workspace' parameter"
56+
assert param.default == "default", (
57+
f"{tool_name}.workspace default is {param.default!r}, not 'default' — cron calls "
58+
"that omit workspace will fail with 'workspace Field required' (fleet-wide "
59+
"memory-write outage)."
60+
)
61+
62+
63+
def test_remember_omitted_workspace_stores_in_default(monkeypatch):
64+
srv = _module_with_memory_db(monkeypatch)
65+
out = json.loads(srv.engraphis_remember(
66+
content="cron write path must not require an explicit workspace"))
67+
assert out["stored"] is True
68+
assert out["workspace"] == "default"
69+
70+
71+
def test_record_event_omitted_workspace_succeeds_in_default(monkeypatch):
72+
srv = _module_with_memory_db(monkeypatch)
73+
# The fleet always opens a session first, which provisions the 'default' workspace.
74+
started = json.loads(srv.engraphis_start_session())
75+
assert started["workspace"] == "default"
76+
77+
omitted = json.loads(srv.engraphis_record_event(
78+
kind="ops_probe", content="hourly-dev-engineer regression event (omitted ws)"))
79+
# record_event returns {"id","kind"}; a required-workspace regression would instead
80+
# surface as an "Error: ... workspace Field required" string that fails json.loads or
81+
# carries no id.
82+
assert isinstance(omitted, dict) and omitted.get("id"), (
83+
f"record_event with omitted workspace did not return an id: {omitted!r}")
84+
assert omitted["kind"] == "ops_probe"
85+
86+
# The omitted-workspace path must behave like passing workspace="default" explicitly
87+
# (parity check; combined with the signature guard above this pins "omitted -> default"
88+
# without depending on retrieval-ranking heuristics).
89+
explicit = json.loads(srv.engraphis_record_event(
90+
kind="ops_probe", content="hourly-dev-engineer regression event (explicit default)",
91+
workspace="default"))
92+
assert isinstance(explicit, dict) and explicit.get("id"), (
93+
f"record_event with workspace='default' did not return an id: {explicit!r}")

0 commit comments

Comments
 (0)