Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .repository-projection.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"projection": "deixic-code",
"projectionSchemaVersion": 1,
"sourceRepository": "dx-corp/mono",
"sourceSha": "f1457cd20a4b86478bcc70b0152230aaa8a17dea",
"sourceSha": "d42a9af9edd2a1c5b5ec9076c68bc30a3b83a83e",
"destinationRepository": "dx-corp/code",
"priorProjectedBase": "6a1ee9a7f2d6d82fa7f55c3a1dc7c7d8e95c964f",
"priorProjectedBase": "151f172cbc14fbc955f0f221d0b757910e158152",
"definitionDigest": "cb9d429542ebb0a2de9b42a7aad60d9d8696a648ceba47c30f05c0b285ca0db7",
"toolDigest": "c9112982c70b80737d8faac67d58b06d55bde0dc297eb1009c1b02296f34f4a9",
"contentDigest": "2ee4dc7a3e288db3224383edce5c9dede750c4e7733a87436b0fb14c221b58c0",
"contentDigest": "81d79f31e8f1483766e9eb0012fe456a12bb8d3b38162bc7fa515a95af275ba0",
"publicationEligible": true
}
10 changes: 9 additions & 1 deletion scripts/capture-tui.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,21 @@ def __init__(self, root, binary, columns, rows, fixture=None):
self.config.write_text(
'set -g default-terminal "xterm-256color"\nset -g escape-time 0\nset -g status off\n'
)
self.workspace = root / "release-planner"
self.workspace = root / ("security-policy" if fixture and fixture.scene == "compliance" else "release-planner")
self.workspace.mkdir()
if fixture:
(self.workspace / "README.md").write_text(
"# Release checklist\n\nA small workspace for planning a team release.\n\n"
"1. Choose a release owner.\n2. Review the changes.\n3. Run the checks.\n4. Publish the release.\n5. Write a short release note.\n"
)
if fixture and fixture.scene == "compliance":
(self.workspace / "SECURITY.md").write_text("# Security policy\n\nWe acknowledge reports within two business days.\n")
(self.workspace / "test_security_policy.py").write_text(
"from pathlib import Path\nimport unittest\n\n"
"class SecurityPolicyTest(unittest.TestCase):\n"
" def test_private_reporting(self):\n self.assertIn('security@acme.example', Path('SECURITY.md').read_text())\n"
" def test_response_commitment(self):\n self.assertIn('two business days', Path('SECURITY.md').read_text())\n"
)
self.env = {
"PATH": os.environ.get("PATH", "/usr/bin:/bin"),
"HOME": str(root),
Expand Down
11 changes: 11 additions & 0 deletions scripts/test-capture-tui.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ def test_light_scenes_select_real_palette_and_reduced_motion_is_explicit(self):
self.assertIn({"text": "/dex motion-off"}, reduced["steps"])
self.assertEqual(reduced["steps"][-1], {"wait": "Dex appreciates the boop"})

def test_compliance_fixture_refuses_unproven_success(self):
from tui_capture_fixture import CaptureFixture
with CaptureFixture("compliance") as fixture:
base = fixture.environment()["MAESTRO_IDENTITY_URL"]
fixture.turn = 3
request = urllib.request.Request(base + "/v1/chat/completions", data=json.dumps({"messages": []}).encode(), headers={"Content-Type": "application/json"})
with self.assertRaises(urllib.error.HTTPError) as raised:
urllib.request.urlopen(request, timeout=3)
self.assertEqual(raised.exception.code, 409)
self.assertIn(b"requires actual passing regression test", raised.exception.read())

def test_fixture_serves_only_local_scripted_contracts(self):
from tui_capture_fixture import CaptureFixture

Expand Down
32 changes: 30 additions & 2 deletions scripts/tui_capture_fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,35 @@ def do_POST(self):
if self.path in {"/v1/chat/completions", "/v1/responses"}:
responses = self.path == "/v1/responses"
fixture.turn += 1
if fixture.scene == "streaming":
if fixture.scene == "compliance":
request = json.loads(request_body)
messages = request.get("input", []) if responses else request.get("messages", [])
results = [str(message.get("content", message.get("output", ""))) for message in messages
if message.get("role") == "tool" or message.get("type") == "function_call_output"]
def tool(name, args):
return {"role": "assistant", "tool_calls": [{"index": 0, "id": f"compliance-{fixture.turn}", "type": "function", "function": {"name": name, "arguments": json.dumps(args)}}]}
if fixture.turn == 1:
delta = tool("read", {"path": "SECURITY.md"})
finish = "tool_calls"
elif fixture.turn == 2:
if not any("Security policy" in result for result in results):
self.send_error(409, "requires actual security file read")
return
delta = tool("write", {"path": "SECURITY.md", "content": "# Security policy\n\nReport vulnerabilities privately to security@acme.example.\nWe acknowledge reports within two business days.\n"})
finish = "tool_calls"
elif fixture.turn == 3:
delta = tool("bash", {"command": "python3 -m unittest test_security_policy -v"})
finish = "tool_calls"
elif fixture.turn == 4:
if not any("OK" in result and "test_private_reporting" in result for result in results):
self.send_error(409, "requires actual passing regression test")
return
delta = {"role": "assistant", "content": "Fixed SECURITY.md after your approval.\n\n- Added a private vulnerability reporting address.\n- Kept the two-business-day response commitment.\n- Read the file in the regression test: 2 tests pass.\n\nThe local change is ready for review. Production publication and the SOC 2 control re-test are still pending."}
finish = "stop"
else:
self.send_error(409, "capture fixture exhausted")
return
elif fixture.scene == "streaming":
self.send_response(200)
self.send_header("Content-Type", "text/event-stream")
self.end_headers()
Expand Down Expand Up @@ -62,7 +90,7 @@ def do_POST(self):
self.wfile.flush()
fixture.stopped.wait(20)
return
if fixture.scene == "long-conversation":
elif fixture.scene == "long-conversation":
delta = {
"role": "assistant",
"content": "Release review\n\n"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"scenario": "compliance",
"scenario_sha256": "41a647918bd724893856779f19a413561b6ac014e9755e20d69a189f6489af54",
"binary": "/Users/jonathanhaas/Documents/Codex/2026-10-05/lo/work/maestro-target/debug/maestro",
"columns": 120,
"rows": 40,
"font": "/System/Library/Fonts/Menlo.ttc",
"font_sha256": "f2d400484a6aace67980730ec0a9ef24ce9e535a2604f118e6fdc2510021b85f",
"font_size": 18,
"terminal_palette": {
"default": "#e6e4e0",
"black": "#1b1c1e",
"red": "#d28b87",
"green": "#a0b69a",
"brown": "#c9b58c",
"blue": "#96a9c7",
"magenta": "#b0a2cb",
"cyan": "#93b6b3",
"white": "#d8d6d2",
"brightblack": "#85868b",
"brightred": "#e3a19b",
"brightgreen": "#b3c8ac",
"brightbrown": "#ddc9a1",
"brightblue": "#acbdd8",
"brightmagenta": "#c3b5de",
"brightcyan": "#a8cbc8",
"brightwhite": "#f4f2ee"
},
"status": "passed",
"binary_sha256": "8a94378908f17bce6249a022b61b7bc6f367a90b24302b0e1e6b272c03ed0287",
"backend": "local-scripted-fixture",
"binary_version": "deixic-code 0.10.111",
"cursor": [
2,
36
],
"identity_requests": 3,
"model_requests": 4
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions test/fixtures/tui-capture/compliance.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "compliance",
Comment thread
evalops-mirror[bot] marked this conversation as resolved.
"steps": [
{"wait": "(?s)Dex.*GPT-6 Astra.*security-policy"},
{"text": "Fix SECURITY.md and run its tests."},
{"wait": "Fix SECURITY.md and run its tests"},
{"key": "Enter"},
{"wait": "Action Approval Required"},
{"key": "Enter"},
{"wait": "Action Approval Required"},
{"key": "Enter"},
{"wait": "2 tests pass"},
{"absent": "Working|Thinking"},
{"wait": "Dex · finished"}
]
}
2 changes: 1 addition & 1 deletion vendor/dex-loop/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@ pub use agent_codemode::{ModelBinding, ModelOperation, OutputBlock};
pub use codemode_output::validate_codemode_blocks;

mod grc_context;
pub use grc_context::{GRC_CONTEXT_BYTES, GRC_GRAPH_TOOL_NAME, GRC_RESULT_BYTES};
pub use grc_context::{GRC_CONTEXT_BYTES, GRC_GRAPH_TOOL_NAME};
13 changes: 11 additions & 2 deletions vendor/dex-loop/tests/grc_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
mod support;
use dex_loop::{
Budget, CancellationToken, Exit, GRC_CONTEXT_BYTES, GRC_GRAPH_TOOL_NAME, Message, Outcome,
Output,
};
use serde_json::json;
use support::{FakeLog, FakeModel, FakeTools, call, engine, read_tool, text};
Expand Down Expand Up @@ -40,8 +41,16 @@ async fn grc_parallel_then_successive_reads_execute_once_and_replay_the_same_his
.history()
.iter()
.filter_map(|e| match &e.message {
Message::Tool { name, outcome, .. } if name.as_str() == GRC_GRAPH_TOOL_NAME => {
Some((outcome, e.message.size()))
Message::Tool {
name,
outcome,
output,
..
} if name.as_str() == GRC_GRAPH_TOOL_NAME => {
let Output::Text(text) = output else {
panic!("the GRC fixture must produce inline text");
};
Some((outcome, text.len()))
}
_ => None,
})
Expand Down
Loading