import json
import os
import sqlite3
import subprocess
import sys
import tempfile
def main():
goosedump_bin = os.environ.get("GOOSEDUMP_BIN", "")
if not goosedump_bin:
print("FAIL GOOSEDUMP_BIN not set")
sys.exit(1)
pass_count = 0
fail_count = 0
def passed(name):
nonlocal pass_count
pass_count += 1
print(f"PASS {name}")
def failed(name, reason):
nonlocal fail_count
fail_count += 1
print(f"FAIL {name} -- {reason}")
def run(args, env=None, cwd=None):
result = subprocess.run(
[goosedump_bin] + args,
capture_output=True,
text=True,
env=env,
cwd=cwd,
)
return result.returncode, result.stdout, result.stderr
def expect_success(name, args, env, cwd, contains):
status, stdout, stderr = run(args, env=env, cwd=cwd)
if status != 0:
failed(name, f"expected status 0, got {status} stderr={stderr[:200]}")
return
if contains is not None and contains not in stdout:
failed(name, f"expected output to contain '{contains}'. stdout: {stdout[:400]}")
return
passed(name)
def expect_not_contains(name, args, env, cwd, not_contains):
status, stdout, stderr = run(args, env=env, cwd=cwd)
if status != 0:
failed(name, f"expected status 0, got {status} stderr={stderr[:200]}")
return
if not_contains in stdout:
failed(name, f"output must not contain '{not_contains}'. stdout: {stdout[:400]}")
return
passed(name)
def expect_failure(name, args, env, cwd):
status, stdout, stderr = run(args, env=env, cwd=cwd)
if status != 0:
passed(name)
else:
failed(name, f"expected failure but got success. stdout: {stdout[:200]}")
def expect_stdout(name, args, env, cwd, *patterns):
status, stdout, stderr = run(args, env=env, cwd=cwd)
if status != 0:
failed(name, f"expected status 0, got {status} stderr={stderr[:200]}")
return
for p in patterns:
if p not in stdout:
failed(name, f"output missing '{p}'. stdout: {stdout[:400]}")
return
passed(name)
with tempfile.TemporaryDirectory() as tmpdir:
oc_dir = os.path.join(tmpdir, "opencode")
os.makedirs(oc_dir)
oc_db = os.path.join(oc_dir, "opencode.db")
conn = sqlite3.connect(oc_db)
conn.execute(
"CREATE TABLE message(session_id TEXT, id TEXT, data TEXT, time_created INTEGER)"
)
conn.execute(
"CREATE TABLE part(session_id TEXT, message_id TEXT, data TEXT, time_created INTEGER)"
)
sid1 = "sesh-alpha"
conn.execute(
"INSERT INTO message VALUES(?, ?, ?, ?)",
(
sid1,
"msg-a",
json.dumps({"role": "user", "id": "entry-alpha", "parentID": ""}),
1000,
),
)
conn.execute(
"INSERT INTO part VALUES(?, ?, ?, ?)",
(
sid1,
"msg-a",
json.dumps({"type": "text", "text": "search keyword FOXTROT-ALPHA"}),
1000,
),
)
conn.execute(
"INSERT INTO message VALUES(?, ?, ?, ?)",
(
sid1,
"msg-b",
json.dumps(
{"role": "assistant", "id": "entry-bravo", "parentID": "entry-alpha"}
),
2000,
),
)
conn.execute(
"INSERT INTO part VALUES(?, ?, ?, ?)",
(
sid1,
"msg-b",
json.dumps({"type": "reasoning", "text": "need to read a file"}),
2000,
),
)
conn.execute(
"INSERT INTO part VALUES(?, ?, ?, ?)",
(
sid1,
"msg-b",
json.dumps({"type": "text", "text": "found FOXTROT-ALPHA in source"}),
2001,
),
)
conn.execute(
"INSERT INTO part VALUES(?, ?, ?, ?)",
(
sid1,
"msg-b",
json.dumps(
{
"type": "tool",
"name": "read",
"arguments": {
"filePath": "src/main.rs",
"description": "read tool",
},
}
),
2002,
),
)
sid2 = "sesh-bravo"
conn.execute(
"INSERT INTO message VALUES(?, ?, ?, ?)",
(
sid2,
"msg-c",
json.dumps({"role": "user", "id": "entry-charlie", "parentID": ""}),
3000,
),
)
conn.execute(
"INSERT INTO part VALUES(?, ?, ?, ?)",
(
sid2,
"msg-c",
json.dumps({"type": "text", "text": "query about TANGO-SIERRA"}),
3000,
),
)
conn.commit()
conn.close()
crush_db = os.path.join(tmpdir, "crush.db")
conn = sqlite3.connect(crush_db)
conn.execute(
"CREATE TABLE messages(session_id TEXT, role TEXT, parts TEXT, created_at TEXT)"
)
csid = "sesh-crush"
conn.execute(
"INSERT INTO messages VALUES(?, ?, ?, ?)",
(
csid,
"user",
json.dumps([{"type": "text", "text": "explain ZULU-NOVEMBER"}]),
"2026-01-01T00:00:00Z",
),
)
conn.execute(
"INSERT INTO messages VALUES(?, ?, ?, ?)",
(
csid,
"assistant",
json.dumps(
[
{
"type": "text",
"text": "ZULU-NOVEMBER is a code pattern",
},
{
"type": "tool_use",
"name": "grep",
"input": {"pattern": "ZULU", "filePath": "lib.rs"},
},
]
),
"2026-01-01T00:00:01Z",
),
)
conn.commit()
conn.close()
with open(os.path.join(tmpdir, ".crush.json"), "w") as f:
json.dump({"data_directory": "."}, f)
pi_dir = os.path.join(tmpdir, "pi-sessions")
os.makedirs(pi_dir)
pi_file = os.path.join(pi_dir, "pi-sesh.jsonl")
with open(pi_file, "w") as f:
f.write(
json.dumps(
{
"type": "session",
"id": "sesh-pi",
"cwd": "/tmp/project",
}
)
+ "\n"
)
f.write(
json.dumps(
{
"type": "message",
"id": "pi-entry-1",
"parentId": "",
"message": {
"role": "user",
"content": [
{"type": "text", "text": "find VICTOR-WHISKEY"}
],
},
}
)
+ "\n"
)
f.write(
json.dumps(
{
"type": "message",
"id": "pi-entry-2",
"parentId": "pi-entry-1",
"message": {
"role": "assistant",
"content": [
{
"type": "thinking",
"text": "searching for VICTOR-WHISKEY",
},
{
"type": "text",
"text": "found VICTOR-WHISKEY in file",
},
{
"type": "toolCall",
"name": "bash",
"arguments": {
"command": "grep VICTOR src/*.rs"
},
},
],
},
}
)
+ "\n"
)
f.write(
json.dumps(
{
"type": "message",
"id": "pi-entry-3",
"parentId": "pi-entry-2",
"message": {
"role": "bashExecution",
"command": "grep VICTOR src/*.rs",
"content": [
{
"type": "text",
"text": "src/main.rs:123: VICTOR-WHISKEY",
}
],
},
}
)
+ "\n"
)
goose_sessions_dir = os.path.join(tmpdir, "goose", "sessions")
os.makedirs(goose_sessions_dir)
goose_db = os.path.join(goose_sessions_dir, "sessions.db")
conn = sqlite3.connect(goose_db)
conn.execute("CREATE TABLE sessions(id TEXT PRIMARY KEY, name TEXT, working_dir TEXT, updated_at TIMESTAMP)")
conn.execute(
"CREATE TABLE messages(id INTEGER PRIMARY KEY AUTOINCREMENT, message_id TEXT, session_id TEXT, role TEXT, content_json TEXT, created_timestamp INTEGER)"
)
gsid = "sesh-goose"
conn.execute(
"INSERT INTO sessions VALUES(?, ?, ?, ?)",
(gsid, "Review Session", "/tmp/project", "2026-06-10T00:00:00Z"),
)
conn.execute(
"INSERT INTO messages VALUES(?, ?, ?, ?, ?, ?)",
(
1,
"msg-1",
gsid,
"user",
json.dumps([{"type": "text", "text": "find YANKEE-ECHO"}]),
1000,
),
)
conn.execute(
"INSERT INTO messages VALUES(?, ?, ?, ?, ?, ?)",
(
2,
"msg-2",
gsid,
"assistant",
json.dumps([
{"type": "thinking", "thinking": "searching for YANKEE-ECHO", "signature": ""},
{"type": "text", "text": "let me search for that"},
]),
2000,
),
)
conn.execute(
"INSERT INTO messages VALUES(?, ?, ?, ?, ?, ?)",
(
3,
"msg-3",
gsid,
"assistant",
json.dumps([
{"type": "toolRequest", "id": "call_00", "toolCall": {"status": "success", "value": {"name": "grep", "arguments": {"pattern": "YANKEE"}}}},
]),
3000,
),
)
conn.execute(
"INSERT INTO messages VALUES(?, ?, ?, ?, ?, ?)",
(
4,
"msg-4",
gsid,
"user",
json.dumps([
{"type": "toolResponse", "id": "call_00", "toolResult": {"status": "success", "value": {"name": "grep", "content": [{"type": "text", "text": "src/main.rs:42: YANKEE-ECHO"}]}}},
]),
4000,
),
)
conn.commit()
conn.close()
base_env = os.environ.copy()
base_env["XDG_DATA_HOME"] = tmpdir
base_env["PI_CODING_AGENT_SESSION_DIR"] = pi_dir
expect_stdout(
"opencode: list contexts",
["opencode"],
base_env,
None,
"Sessions:",
"sesh-alpha",
"sesh-bravo",
)
expect_stdout(
"opencode: display messages",
["opencode", "sesh-alpha"],
base_env,
None,
"entryId: entry-alpha (user)",
"FOXTROT-ALPHA",
"entryId: entry-bravo (assistant)",
)
expect_stdout(
"opencode: compact display",
["opencode", "sesh-alpha", "--compact"],
base_env,
None,
"entryId: entry-alpha (user/text)",
"entryId: entry-bravo (assistant)",
"tools: read(path=src/main.rs)",
)
expect_success(
"opencode: grep literal match",
["opencode", "sesh-alpha", "--grep", "FOXTROT-ALPHA"],
base_env,
None,
"FOXTROT-ALPHA",
)
expect_success(
"opencode: grep no match",
["opencode", "sesh-alpha", "--grep", "NONEXISTENT-ZZ"],
base_env,
None,
"no results",
)
expect_success(
"opencode: ranked search",
["opencode", "sesh-alpha", "--grep", "FOXTROT", "--rank"],
base_env,
None,
"results for",
)
expect_stdout(
"opencode: ID filter",
["opencode", "sesh-alpha", "--ids", "entry-alpha"],
base_env,
None,
"entryId: entry-alpha (user)",
)
expect_not_contains(
"opencode: ID filter excludes other",
["opencode", "sesh-alpha", "--ids", "entry-alpha"],
base_env,
None,
"entry-bravo",
)
expect_stdout(
"opencode: lineage scope",
["opencode", "sesh-alpha", "--scope", "lineage"],
base_env,
None,
"entryId: entry-alpha (user)",
"entryId: entry-bravo (assistant)",
)
expect_stdout(
"crush: list contexts",
["crush"],
base_env,
tmpdir,
"Sessions:",
"sesh-crush",
)
expect_stdout(
"crush: display messages",
["crush", "sesh-crush"],
base_env,
tmpdir,
"entryId: crush-0 (user)",
"ZULU-NOVEMBER",
"entryId: crush-1 (assistant)",
"code pattern",
)
expect_stdout(
"pi: list contexts",
["pi"],
base_env,
None,
"Sessions:",
"sesh-pi",
)
expect_stdout(
"pi: display messages",
["pi", "sesh-pi"],
base_env,
None,
"entryId: pi-entry-1 (user)",
"VICTOR-WHISKEY",
"entryId: pi-entry-2 (assistant)",
"entryId: pi-entry-3 (bash)",
"grep VICTOR src/*.rs",
)
expect_stdout(
"goose: list contexts",
["goose"],
base_env,
None,
"Sessions:",
"sesh-goose",
"Review Session",
)
expect_stdout(
"goose: display messages",
["goose", "sesh-goose"],
base_env,
None,
"entryId: goose-1 (user)",
"YANKEE-ECHO",
"entryId: goose-2 (assistant)",
"let me search",
"entryId: goose-3 (assistant)",
"grep: pattern=YANKEE",
"entryId: goose-4 (tool/grep)",
"YANKEE-ECHO",
)
expect_stdout(
"goose: compact display",
["goose", "sesh-goose", "--compact"],
base_env,
None,
"entryId: goose-1 (user/text)",
"entryId: goose-2 (assistant)",
"entryId: goose-3 (assistant)",
"entryId: goose-4 (tool/grep)",
)
expect_success(
"goose: grep match",
["goose", "sesh-goose", "--grep", "YANKEE-ECHO"],
base_env,
None,
"YANKEE-ECHO",
)
expect_stdout(
"goose: lineage scope",
["goose", "sesh-goose", "--scope", "lineage"],
base_env,
None,
"entryId: goose-1 (user)",
"entryId: goose-4 (tool/grep)",
)
expect_failure(
"cli: unknown client",
["bogus"],
base_env,
None,
)
expect_failure(
"cli: --grep without context-id",
["opencode", "--grep", "foo"],
base_env,
None,
)
expect_failure(
"cli: --rank without --grep",
["opencode", "sesh-alpha", "--rank"],
base_env,
None,
)
expect_failure(
"cli: --page without --rank",
["opencode", "sesh-alpha", "--page", "1"],
base_env,
None,
)
expect_failure(
"cli: invalid --scope",
["opencode", "sesh-alpha", "--scope", "bogus"],
base_env,
None,
)
expect_failure(
"cli: --page zero",
[
"opencode",
"sesh-alpha",
"--grep",
"FOXTROT",
"--rank",
"--page",
"0",
],
base_env,
None,
)
print(f"SUMMARY pass={pass_count} fail={fail_count} tmp={tmpdir}")
if fail_count != 0:
sys.exit(1)
if __name__ == "__main__":
main()