Checkpoint 3: deliver playable samples and complete native authoring workflows

This commit is contained in:
Emil
2026-09-18 04:29:41 +03:00
parent fad5eb4e55
commit d834cfad67
92 changed files with 8335 additions and 353 deletions
+33 -1
View File
@@ -40,6 +40,7 @@ def run(executable, project):
assert initialized["result"]["serverInfo"]["name"] == "faset-editor"
process.stdin.write('{"jsonrpc":"2.0","method":"notifications/initialized"}\n')
process.stdin.flush()
assert call("faset_schema_status")["stale"]
names = {tool["name"] for tool in request("tools/list")["result"]["tools"]}
assert {"faset_scene_edit", "faset_export", "faset_job_cancel", "faset_plugins"} <= names
assert "faset_runtime_query" not in names and "faset_editor_capture" not in names
@@ -78,7 +79,38 @@ def run(executable, project):
assert code == 0, errors
def disconnected_output(executable, project):
process = subprocess.Popen([executable, "--project", str(project), "--mcp"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, text=True, encoding="utf-8")
# Keep input open: output failure itself must close the transport. Before
# the fix this terminated the POSIX Editor with SIGPIPE (return code -13).
process.stdout.close()
try:
process.stdin.write(json.dumps({"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": {"protocolVersion": "2025-06-18"}}) + "\n")
process.stdin.flush()
assert process.wait(timeout=20) == 0, process.stderr.read()
finally:
if process.poll() is None:
process.kill()
process.wait()
process.stdin.close()
def eof_tail(executable, project):
# A final buffered request must still receive its reply when input closes.
message = json.dumps({"jsonrpc": "2.0", "id": "tail", "method": "ping"})
result = subprocess.run([executable, "--project", str(project), "--mcp"],
input=message, capture_output=True, text=True,
encoding="utf-8", timeout=20)
assert result.returncode == 0, result.stderr
assert json.loads(result.stdout)["id"] == "tail", result.stdout
with tempfile.TemporaryDirectory(prefix="faset-mcp-stdio-") as temporary:
run(sys.argv[1], pathlib.Path(temporary))
run(sys.argv[1], pathlib.Path(temporary))
print("Real MCP stdio lifecycle, clean stdout, revision conflict, retry, Undo/Redo, disk reopen and process shutdown passed")
disconnected_output(sys.argv[1], pathlib.Path(temporary))
eof_tail(sys.argv[1], pathlib.Path(temporary))
print("Real MCP stdio lifecycle, clean stdout, revision conflict, retry, Undo/Redo, disk reopen, broken output pipe and EOF shutdown passed")