Files
Wyatt Fang 30fecaae5e release(codestable): ship skill workflow v1.0.2 (#41)
收敛 CodeStable 主入口、runtime preflight、goal driver 与 skill 工程化评测闭环。

- 根 cs 对行动请求同轮直转,咨询与介绍保持非执行
- feature/issue/refactor/epic/docs 按仓库事实恢复,旧 stage skill 保留兼容薄壳
- repo-local runtime 支持版本检测、安全自动同步和显式 refresh-runtime
- 完成 Codex/Claude marketplace 1.0.2、升级文档和回归/评测证据

验证:215 tests passed;package/runtime/diff checks passed;独立 review 与 QA 无 unresolved blocking/important findings。
2026-07-10 15:23:56 +08:00

59 lines
1.5 KiB
Python

import csv
import os
import subprocess
import sys
from taskhub import storage
from taskhub.services import tasks
def run_cli(tmp_path, *args):
repo_root = os.getcwd()
env = dict(
os.environ,
TASKHUB_DB=str(tmp_path / "taskhub.db"),
PYTHONPATH=repo_root + os.pathsep + os.environ.get("PYTHONPATH", ""),
)
return subprocess.run(
[sys.executable, "-m", "taskhub.cli", *args],
cwd=tmp_path,
env=env,
text=True,
capture_output=True,
check=True,
)
def read_rows(path):
with path.open(newline="", encoding="utf-8") as f:
return list(csv.DictReader(f))
def test_export_uses_csv_escaping_and_empty_due_date(tmp_path):
db_path = tmp_path / "taskhub.db"
conn = storage.connect(db_path)
storage.migrate(conn)
title = 'deploy, "prod"\nphase 2'
tasks.create_task(conn, title, notes='needs, "review"\nsoon')
out_path = tmp_path / "tasks.csv"
run_cli(tmp_path, "export", str(out_path))
rows = read_rows(out_path)
assert rows[0]["title"] == title
assert rows[0]["dueDate"] == ""
assert "None" not in out_path.read_text(encoding="utf-8")
def test_export_empty_task_list_still_writes_header(tmp_path):
db_path = tmp_path / "taskhub.db"
conn = storage.connect(db_path)
storage.migrate(conn)
out_path = tmp_path / "empty.csv"
run_cli(tmp_path, "export", str(out_path))
assert out_path.read_text(encoding="utf-8").splitlines() == [
"id,title,status,assignee,dueDate"
]