diff --git a/README.md b/README.md index cbf7064..d4791dd 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ **A runtime-neutral, evidence-driven software engineering workflow for AI coding agents.** +[简体中文](README.zh-CN.md) + Engineer Software helps an agent choose the smallest trustworthy next move: close an unclear contract, trace an unexplained failure, run one disposable probe, deliver a defined change, inspect structural redundancy, or draft local work items. Codex and DeepSeek Harness are two first-class diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..b463245 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,222 @@ +# Engineer Software 中文入口 + +[English README](README.md) + +**面向 AI 编程代理的、运行时无关且证据驱动的软件工程工作流。** + +## 30 秒理解 + +Engineer Software 是一个精简路由器:它先判断请求是否存在实质性的工程不确定性,再选择一个最小而聚焦的模块,并要求用新证据证明何时可以离开该模块。 + +- Codex 与 DeepSeek Harness 是两个一等运行入口。 +- 两个运行时共享同一份 canonical `SKILL.md`、`references/` 和路由评测。 +- Harness 的 `.dsh/skills/` 内容是从 Codex canonical source 生成的投影,不是手工维护的第二套工作流。 +- 普通解释、翻译、简单读码和明确的机械文件操作会绕过路由,不增加流程负担。 + +技术细节仍以英文 [README](README.md) 和 canonical [SKILL.md](plugins/engineer-software/skills/engineer-software/SKILL.md) 为准;本文件是中文用户入口,不复制维护完整技能正文。 + +## Codex:安装、升级、卸载与调用 + +### 安装 + +在 Codex 中添加 marketplace 并安装插件: + +```powershell +codex plugin marketplace add KirschBluteX/engineer-software +codex plugin add engineer-software@engineer-software +codex plugin list +``` + +安装后开始一个新任务,让技能目录刷新;对实质性软件工程请求直接描述目标即可,也可以显式调用 `$engineer-software`。 + +### 升级 + +```powershell +codex plugin marketplace upgrade engineer-software +codex plugin add engineer-software@engineer-software +codex plugin list +``` + +升级后重新开始任务。若 canonical 技能内容发生变化,仓库维护者会同步生成 Harness 投影。 + +### 卸载 + +使用已安装的 Codex 插件管理器移除(示例): + +```powershell +codex plugin remove engineer-software +codex plugin list +``` + +具体参数以本机 Codex CLI 的帮助输出为准;本项目不包装或模拟 Codex 管理器。 + +### 调用示例 + +```text +$engineer-software +请为现有 status 命令增加已经定义的 --json 输出,并给出实现和验证证据。 +``` + +如果请求只是解释一个函数或翻译文本,技能会按设计绕过,不会强行进入工程模块。 + +## DeepSeek Harness:安装、升级、卸载与项目级技能 + +Harness 运行时和 Engineer Software 技能是两层独立内容:先按官方方式运行 Harness,再把本项目生成的技能投影放入目标 workspace 的 `.dsh/skills/`。本项目不会替你安装或修改 Harness 本体。 + +### 1. 安装或首次运行 Harness + +官方 README 当前推荐通过 npm 按需运行。安装 Node.js 后执行: + +```powershell +npx @deepseek-ai/dsh web +``` + +这会下载并运行官方 npm 包,默认在 `http://127.0.0.1:3080` 启动 Web UI;它不会向 Engineer Software 仓库添加 Node 依赖,也不要求全局安装 `dsh`。请从官方 [DeepSeek Harness README](https://github.com/deepseek-ai/deepseek-harness#run) 核对最新入口。 + +### 2. 升级 Harness 运行时 + +官方文档目前没有定义单独的 `dsh upgrade` 命令。需要明确使用 npm 当前发布版本时,可以先查看版本,再用 npm 的 `latest` 标签启动: + +```powershell +npm view @deepseek-ai/dsh version +npx @deepseek-ai/dsh@latest web +``` + +`@latest` 是 npm 的版本选择机制,不是本项目发明的 Harness 升级 API。Harness 仍处于 developer preview;升级后应重新执行本文的技能同步和静态兼容检查。 + +### 3. 在项目中安装 Engineer Software 技能 + +DeepSeek Harness 官方技能加载契约支持项目根目录下的 `.dsh/skills//SKILL.md` 及其相对资源。本仓库已经提交由 canonical source 生成的: + +```text +.dsh/skills/engineer-software/SKILL.md +.dsh/skills/engineer-software/references/*.md +``` + +直接把本仓库作为 Harness workspace 时,只需检查默认投影: + +```powershell +python scripts/sync_harness_skill.py --check +python scripts/validate_harness.py --check +npx @deepseek-ai/dsh web +``` + +要把技能安装到另一个项目,请在 Engineer Software 仓库根目录将目标显式传给生成器: + +```powershell +$TargetProject = "C:\path\to\your-project" +python scripts/sync_harness_skill.py --write ` + --target "$TargetProject\.dsh\skills\engineer-software" +python scripts/validate_harness.py --check ` + --target "$TargetProject\.dsh\skills\engineer-software" +``` + +随后在 Harness 中选择 `$TargetProject` 对应的 workspace。提交生成文件前先审阅它们,并根据目标项目策略决定是否跟踪 `.dsh/skills/`。 + +### 4. 升级 Engineer Software 技能 + +先把 Engineer Software checkout 更新到你已审查的版本;对于正在跟踪远端分支的 checkout,可以使用 `git pull --ff-only`。随后对同一目标重复生成和检查: + +```powershell +git pull --ff-only +$TargetProject = "C:\path\to\your-project" +python scripts/sync_harness_skill.py --write ` + --target "$TargetProject\.dsh\skills\engineer-software" +python scripts/validate_harness.py --check ` + --target "$TargetProject\.dsh\skills\engineer-software" +``` + +如果目标就是本仓库,可省略 `--target`。生成器不会删除陈旧文件;若检查报告额外文件,应先审阅,再明确删除。不要直接编辑 `.dsh/skills/` 投影,也不要手工维护第二套 `SKILL.md` 或 references。 + +### 5. 卸载 + +按本文推荐的 `npx` 方式运行 Harness 时,不会创建需要本项目卸载的全局 Harness 包;停止运行中的进程即可。Engineer Software 的项目级卸载只删除该技能自己的目录,不要删除其他 `.dsh` 配置或技能: + +```powershell +Get-Item .dsh/skills/engineer-software +Remove-Item -LiteralPath .dsh/skills/engineer-software -Recurse +``` + +若安装在另一个项目,请在确认目标绝对路径后,对该项目中的 `.dsh/skills/engineer-software/` 执行同样操作。完整的用户级目录和故障排查见 [docs/compatibility.md](docs/compatibility.md)。 + +## 兼容边界与证据状态 + +本项目对照的是官方 [deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness),不是同名社区库,也不是 DeepSeek 官方插件、官方合作伙伴或官方贡献者。 + +| 项目 | 状态 | +| --- | --- | +| Codex marketplace/plugin 路径 | 保持原有路径,已在仓库校验中验证 | +| Harness `.dsh/skills` 项目级投影 | 已按官方文档做静态兼容验证 | +| canonical source 与 Harness 投影 | 字节一致性和相对 references 已检查 | +| Harness 版本稳定性 | **developer preview**,可能出现兼容性破坏变更 | +| live Harness/API 或模型路由 | **未验证**;当前交付不声称 live API 覆盖 | + +完整矩阵、官方来源、升级故障处理和用户级目录说明见 [docs/compatibility.md](docs/compatibility.md)。静态检查不需要 API key;真实模型会话仍由用户自己的 Harness 配置和权限决定。 + +## 六个路由模块 + +模块是可选的起点,不是必须走完的流水线: + +| 模块 | 何时使用 | 离开时应有的证据 | +| --- | --- | --- | +| **Shape Work** | 行为、范围、兼容性或验收条件仍不清楚 | 最小充分契约与明确排除项 | +| **Trace Failure** | 已有症状,但根因未知 | 可复现步骤与因果证据 | +| **Probe Choice** | 一个明确的设计决策需要一次性实验 | 观察结果及其决策后果 | +| **Deliver Change** | 目标和编辑边界已关闭 | 聚焦检查、实现结果和最终状态证据 | +| **Inspect Structure** | 问题是归属、重复或边界,而非单点修复 | owner/caller 追踪与边界建议 | +| **Manage Work Items** | 需要本地 PRD、任务拆分或验收清单 | 本地工件、依赖和验收条件 | + +## 验证 + +要求 Python 3.9 或更高版本。开发校验依赖在 `requirements-dev.txt` 中: + +```powershell +python -m pip install -r requirements-dev.txt +python scripts/validate_plugin.py plugins/engineer-software +python scripts/validate_evals.py +python scripts/validate_project.py +python scripts/validate_harness.py --check +python -m unittest discover -s tests -v +python -m compileall -q scripts tests +``` + +无需模型访问即可运行路由夹具: + +```powershell +python scripts/run_routing_eval.py --limit 5 +``` + +`validate_harness.py --live` 只有在本机安装了 `dsh` 时才会尝试读取版本;它也不等同于 live API 或模型行为认证。 + +## 常见问题 + +**为什么 Harness 找不到技能?** + +确认启动 workspace 是本仓库,并检查路径是否精确为 `.dsh/skills/engineer-software/SKILL.md`;然后运行 `python scripts/validate_harness.py --check`。从无关目录启动可能会选择不同项目根。 + +**为什么投影检查报告 drift?** + +只编辑 `plugins/engineer-software/skills/engineer-software/`,再运行 `python scripts/sync_harness_skill.py --write`。不要手工维护两份 `SKILL.md` 或 references。 + +**Harness 升级后加载失败怎么办?** + +记录 Harness 版本或 commit,重新运行静态 probe,并参考官方技能文档;这是 developer preview 的兼容性风险,不要从同名社区库猜 manifest 或安装命令。 + +**能否把 API key 写入仓库配置?** + +不能。静态检查不需要 key;模型凭据属于用户的运行时配置,不应出现在 README、fixtures、日志或提交中。 + +## 安全与隐私边界 + +本项目只提供指令和校验脚本,不包含 MCP server、hook、遥测、凭据存储或后台服务。宿主运行时仍可能访问用户授权的工具、代码和模型服务;请在提交前审阅生成文件,避免把 secrets、`.env`、session logs、个人数据或未验证截图放入仓库。 + +更多政策: [SECURITY.md](SECURITY.md) · [PRIVACY.md](PRIVACY.md) · [TERMS.md](TERMS.md)。 + +## 继续阅读 + +- [英文 README](README.md):项目首屏、完整示例和发布说明 +- [运行时兼容矩阵](docs/compatibility.md):官方 Harness 来源与边界 +- [贡献指南](CONTRIBUTING.md):canonical source、投影同步和检查门禁 +- [路线图](ROADMAP.md):精简的后续计划与非目标 + +欢迎先阅读 [英文 canonical skill](plugins/engineer-software/skills/engineer-software/SKILL.md),再按上面的运行时入口开始工作。 diff --git a/scripts/validate_project.py b/scripts/validate_project.py index eb5a603..bd78205 100644 --- a/scripts/validate_project.py +++ b/scripts/validate_project.py @@ -29,6 +29,7 @@ REQUIRED_REFERENCE_HEADINGS = ("## Enter", "## Execute", "## Exit") REQUIRED_PUBLIC_FILES = { "README.md", + "README.zh-CN.md", "LICENSE", "CHANGELOG.md", "CONTRIBUTING.md", @@ -40,6 +41,36 @@ "docs/compatibility.md", } SCAFFOLD_MARKER = "[TO" + "DO" +CHINESE_README_REQUIRED_LINKS = ( + "README.md", + "docs/compatibility.md", + "CONTRIBUTING.md", + "ROADMAP.md", + "SECURITY.md", + "PRIVACY.md", + "TERMS.md", +) +CHINESE_README_REQUIRED_PHRASES = ( + "30 秒理解", + "Codex", + "DeepSeek Harness", + ".dsh/skills", + "developer preview", + "live API", + "未验证", + "不是 DeepSeek 官方插件", + "Shape Work", + "Trace Failure", + "Probe Choice", + "Deliver Change", + "Inspect Structure", + "Manage Work Items", + "npx @deepseek-ai/dsh web", + "npx @deepseek-ai/dsh@latest web", + "--target", + "validate_project.py", + "validate_harness.py --check", +) def relative(path: Path) -> str: @@ -200,6 +231,7 @@ def validate_public_files(readme: str, license_text: str, errors: list[str]) -> "validate_evals.py", "runtime-neutral", ".dsh/skills", + "README.zh-CN.md", ): if phrase not in readme: errors.append(f"README must contain {phrase!r}") @@ -207,6 +239,35 @@ def validate_public_files(readme: str, license_text: str, errors: list[str]) -> errors.append("LICENSE is not the MIT License") +def validate_chinese_readme(text: str, errors: list[str]) -> None: + """Keep the Chinese entry point complete without duplicating the canonical skill.""" + if not text: + return + for phrase in CHINESE_README_REQUIRED_PHRASES: + if phrase not in text: + errors.append(f"README.zh-CN.md must contain {phrase!r}") + for target in CHINESE_README_REQUIRED_LINKS: + if f"]({target})" not in text: + errors.append(f"README.zh-CN.md must link to {target}") + + for raw in re.findall(r"\]\(([^)]+)\)", text): + target = raw.split("#", 1)[0].strip() + if target.startswith(("http://", "https://", "mailto:", "//")): + continue + if target.startswith("<") and target.endswith(">"): + target = target[1:-1] + if not target: + continue + candidate = (ROOT / target).resolve() + try: + candidate.relative_to(ROOT.resolve()) + except ValueError: + errors.append(f"README.zh-CN.md link escapes repository: {target}") + else: + if not candidate.is_file(): + errors.append(f"README.zh-CN.md links to missing file: {target}") + + def validate_repository_text(errors: list[str]) -> None: ignored_parts = {".git", "__pycache__", ".pytest_cache", ".venv", "venv", "runs", "dist"} ignored_files = {"validate_plugin.py", "validate_project.py"} @@ -237,6 +298,7 @@ def validate_project() -> list[str]: skill = read_text(SKILL_PATH, errors) metadata = read_text(SKILL_DIR / "agents" / "openai.yaml", errors) readme = read_text(ROOT / "README.md", errors) + chinese_readme = read_text(ROOT / "README.zh-CN.md", errors) license_text = read_text(ROOT / "LICENSE", errors) validate_marketplace(marketplace, errors) @@ -262,6 +324,7 @@ def validate_project() -> list[str]: errors.extend(f"routing preflight: {error}" for error in case_errors) validate_public_files(readme, license_text, errors) + validate_chinese_readme(chinese_readme, errors) validate_harness_projection(errors) validate_repository_text(errors) return errors diff --git a/tests/test_harness.py b/tests/test_harness.py index 04b3202..85a4350 100644 --- a/tests/test_harness.py +++ b/tests/test_harness.py @@ -17,6 +17,7 @@ sys.path.insert(0, str(ROOT / "scripts")) from sync_harness_skill import compare_projection, expected_files # noqa: E402 from validate_harness import OFFICIAL_SOURCES, static_errors # noqa: E402 +from validate_project import validate_chinese_readme # noqa: E402 class HarnessContractTests(unittest.TestCase): @@ -86,6 +87,14 @@ def test_readme_local_links_and_images_exist(self) -> None: with self.subTest(target=target): self.assertTrue((ROOT / target).is_file(), target) + def test_chinese_readme_links_and_boundaries(self) -> None: + english = (ROOT / "README.md").read_text(encoding="utf-8") + chinese = (ROOT / "README.zh-CN.md").read_text(encoding="utf-8") + self.assertIn("[简体中文](README.zh-CN.md)", english) + errors: list[str] = [] + validate_chinese_readme(chinese, errors) + self.assertEqual([], errors) + def test_cover_asset_is_reasonable_png(self) -> None: cover = ROOT / "plugins" / "engineer-software" / "assets" / "engineer-software-cover.png" data = cover.read_bytes()