{"id":843,"date":"2026-07-12T21:16:26","date_gmt":"2026-07-12T13:16:26","guid":{"rendered":"https:\/\/blog.itsmygo.uk\/2026\/07\/12\/openspec-%e5%8e%9f%e5%a7%8b%e7%a2%bc%e8%a7%a3%e8%ae%80%ef%bc%9a%e8%ae%93-cli-%e6%88%90%e7%82%ba-ai-agent-%e7%9a%84%e3%80%8c%e7%a2%ba%e5%ae%9a%e6%80%a7%e7%8b%80%e6%85%8b%e6%a9%9f%e3%80%8d\/"},"modified":"2026-07-12T21:16:26","modified_gmt":"2026-07-12T13:16:26","slug":"openspec-%e5%8e%9f%e5%a7%8b%e7%a2%bc%e8%a7%a3%e8%ae%80%ef%bc%9a%e8%ae%93-cli-%e6%88%90%e7%82%ba-ai-agent-%e7%9a%84%e3%80%8c%e7%a2%ba%e5%ae%9a%e6%80%a7%e7%8b%80%e6%85%8b%e6%a9%9f%e3%80%8d","status":"publish","type":"post","link":"https:\/\/blog.itsmygo.uk\/wordpress\/2026\/07\/12\/openspec-%e5%8e%9f%e5%a7%8b%e7%a2%bc%e8%a7%a3%e8%ae%80%ef%bc%9a%e8%ae%93-cli-%e6%88%90%e7%82%ba-ai-agent-%e7%9a%84%e3%80%8c%e7%a2%ba%e5%ae%9a%e6%80%a7%e7%8b%80%e6%85%8b%e6%a9%9f%e3%80%8d\/","title":{"rendered":"OpenSpec \u539f\u59cb\u78bc\u89e3\u8b80\uff1a\u8b93 CLI \u6210\u70ba AI Agent \u7684\u300c\u78ba\u5b9a\u6027\u72c0\u614b\u6a5f\u300d"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">OpenSpec \u662f\u4e00\u500b\u70ba AI coding assistant \u6253\u9020\u7684 spec-driven development\uff08SDD\uff09\u5de5\u5177\u3002\u5b83\u7684\u91ce\u5fc3\u4e0d\u662f\u518d\u5beb\u4e00\u500b\u300c\u66f4\u8070\u660e\u7684 prompt\u300d\uff0c\u800c\u662f\u53cd\u904e\u4f86\u601d\u8003\u4e00\u500b\u554f\u984c\uff1a<strong>\u7576\u751f\u6210\u5167\u5bb9\u7684\u4e3b\u9ad4\u662f\u4e0d\u78ba\u5b9a\u7684 LLM \u6642\uff0c\u5de5\u7a0b\u7cfb\u7d71\u8a72\u628a\u54ea\u4e9b\u6771\u897f\u7559\u7d66\u7a0b\u5f0f\u78bc\u3001\u54ea\u4e9b\u6771\u897f\u7559\u7d66\u6a21\u578b\uff1f<\/strong> OpenSpec \u7684\u7b54\u6848\u5f88\u6e05\u695a\u2014\u2014\u7528\u4e00\u652f TypeScript CLI \u627f\u64d4\u6240\u6709\u300c\u78ba\u5b9a\u6027\u300d\u8077\u8cac\uff08\u4f9d\u8cf4\u6392\u5e8f\u3001\u72c0\u614b\u5075\u6e2c\u3001\u683c\u5f0f\u5951\u7d04\u3001\u591a\u5de5\u5177\u8f49\u63a5\uff09\uff0c\u628a\u300c\u5275\u9020\u6027\u300d\u8077\u8cac\uff08\u5beb proposal\u3001\u8a2d\u8a08 spec\u3001\u62c6 task\uff09\u7559\u7d66 AI\u3002\u8b80\u5b8c\u9019\u4efd\u539f\u59cb\u78bc\uff0c\u4f60\u6703\u5b78\u5230\u5982\u4f55\u8a2d\u8a08\u4e00\u500b\u300c\u7d66 AI \u7528\u7684\u5de5\u5177\u300d\uff1a\u5b83\u7684\u4ecb\u9762\u5951\u7d04\u3001\u72c0\u614b\u7ba1\u7406\u8207 prompt \u5206\u5de5\uff0c\u90fd\u548c\u300c\u7d66\u4eba\u7528\u7684\u5de5\u5177\u300d\u6709\u672c\u8cea\u5dee\u7570\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\">OpenSpec GitHub Repository<\/a> \u2014 \u5c08\u6848\u539f\u59cb\u78bc\uff0c\u5305\u542b\u672c\u6587\u89e3\u8b80\u7684 artifact graph\u3001command adapter\u3001schema \u8207 prompt \u8a2d\u8a08\u5be6\u4f5c<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5c08\u6848\u6982\u89bd<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSpec \u4ee5 npm \u5957\u4ef6 <code>@fission-ai\/openspec<\/code> \u767c\u5e03\uff0c\u662f\u4e00\u652f\u7d14 TypeScript\uff08ESM\uff09CLI \u5de5\u5177\uff0c\u6838\u5fc3\u4f9d\u8cf4\u7cbe\u7c21\uff1a<code>commander<\/code>\uff08\u547d\u4ee4\u5217\u6846\u67b6\uff09\u3001<code>zod<\/code>\uff08schema \u9a57\u8b49\uff09\u3001<code>yaml<\/code>\u3001<code>fast-glob<\/code>\u3001<code>@inquirer\/prompts<\/code>\uff08\u4e92\u52d5\uff09\u3002\u5b83\u4e0d\u542b\u4efb\u4f55 LLM \u547c\u53eb\u2014\u2014\u9019\u9ede\u975e\u5e38\u95dc\u9375\uff1aOpenSpec \u672c\u8eab\u300c\u4e0d\u662f AI\u300d\uff0c\u5b83\u662f\u88ab\u5404\u7a2e AI coding \u5de5\u5177\uff08Claude Code\u3001Cursor\u3001Copilot\u2026\uff09\u7576\u4f5c\u5916\u90e8\u5de5\u5177\u547c\u53eb\u7684 CLI\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b83\u7684\u5de5\u4f5c\u6d41\u662f\u628a\u4e00\u6b21\u300c\u8b8a\u66f4\uff08change\uff09\u300d\u62c6\u89e3\u6210\u4e00\u9023\u4e32\u6709\u4f9d\u8cf4\u95dc\u4fc2\u7684\u7522\u7269\uff08artifact\uff09\uff1a<code>proposal.md<\/code>\uff08\u70ba\u4ec0\u9ebc\uff09\u2192 <code>specs\/**\/*.md<\/code>\uff08\u8981\u505a\u4ec0\u9ebc\uff09\u2192 <code>design.md<\/code>\uff08\u600e\u9ebc\u505a\uff09\u2192 <code>tasks.md<\/code>\uff08\u5be6\u4f5c\u6e05\u55ae\uff09\u3002AI \u4f9d\u5e8f\u751f\u6210\u9019\u4e9b\u6a94\u6848\uff0cOpenSpec \u8ca0\u8cac\u544a\u8a34 AI\u300c\u73fe\u5728\u8a72\u505a\u54ea\u4e00\u6b65\u3001\u4e0a\u4e00\u6b65\u7684\u7522\u7269\u5728\u54ea\u3001\u9019\u4e00\u6b65\u7684\u683c\u5f0f\u9577\u4ec0\u9ebc\u6a23\u300d\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u67b6\u69cb\u7e3d\u89bd<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u539f\u59cb\u78bc\u96c6\u4e2d\u5728 <code>src\/<\/code>\uff0c\u7d04 170 \u500b\u6a94\u6848\uff0c\u5206\u5c64\u6e05\u6670\uff1a<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>\u76ee\u9304<\/th>\n<th>\u8077\u8cac<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>src\/cli\/<\/code> <code>src\/commands\/<\/code><\/td>\n<td>CLI \u9032\u5165\u9ede\u8207\u5404\u5b50\u547d\u4ee4\uff08status \/ instructions \/ validate \/ new change\u2026\uff09<\/td>\n<\/tr>\n<tr>\n<td><code>src\/core\/artifact-graph\/<\/code><\/td>\n<td><strong>\u6838\u5fc3\u5f15\u64ce<\/strong>\uff1aartifact \u4f9d\u8cf4\u5716\u3001\u62d3\u64b2\u6392\u5e8f\u3001\u72c0\u614b\u5075\u6e2c\u3001\u6307\u4ee4\u8f09\u5165<\/td>\n<\/tr>\n<tr>\n<td><code>src\/core\/schemas\/<\/code> <code>src\/core\/validation\/<\/code><\/td>\n<td>Zod schema \u8207 spec \u5167\u5bb9\u9a57\u8b49<\/td>\n<\/tr>\n<tr>\n<td><code>src\/core\/command-generation\/<\/code><\/td>\n<td>\u628a\u5de5\u4f5c\u6d41\u6307\u4ee4\u8f49\u8b6f\u6210 28 \u7a2e AI \u5de5\u5177\u5404\u81ea\u7684\u6a94\u6848\u683c\u5f0f<\/td>\n<\/tr>\n<tr>\n<td><code>src\/core\/parsers\/<\/code><\/td>\n<td>Markdown \u2192 \u7d50\u69cb\u5316 spec\/change \u7684\u89e3\u6790<\/td>\n<\/tr>\n<tr>\n<td><code>src\/core\/templates\/workflows\/<\/code><\/td>\n<td>\u5404\u5de5\u4f5c\u6d41\u7684 <strong>prompt \u6a21\u677f<\/strong>\uff08skill \/ slash command \u5167\u5bb9\uff09<\/td>\n<\/tr>\n<tr>\n<td><code>schemas\/<\/code><\/td>\n<td>\u5167\u5efa\u7684 <code>spec-driven<\/code> workflow schema\uff08YAML\uff09\u8207 markdown \u6a21\u677f<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">\u8a2d\u8a08\u4e0a\u6709\u4e00\u689d\u660e\u986f\u7684\u5206\u754c\u7dda\uff1a<strong><code>core\/<\/code> \u662f\u7d14\u51fd\u5f0f\u8207\u78ba\u5b9a\u6027\u908f\u8f2f\uff0c<code>templates\/workflows\/<\/code> \u662f\u8981\u9935\u7d66 LLM \u7684\u81ea\u7136\u8a9e\u8a00\u6307\u4ee4<\/strong>\u3002\u9019\u689d\u7dda\u5c31\u662f\u6574\u500b\u5c08\u6848\u54f2\u5b78\u7684\u7e2e\u5f71\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u6838\u5fc3\u8a2d\u8a08\u89e3\u6790<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\u8a2d\u8a08\u4e00\uff1aArtifact \u4f9d\u8cf4\u5716 + \u62d3\u64b2\u6392\u5e8f\uff0c\u628a\u300c\u5de5\u4f5c\u6d41\u300d\u8b8a\u6210\u8cc7\u6599\u7d50\u69cb<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSpec \u6c92\u6709\u628a\u5de5\u4f5c\u6d41\u5beb\u6b7b\u6210 <code>if proposal then spec then design<\/code> \u7684\u7a0b\u5f0f\u6d41\u7a0b\uff0c\u800c\u662f\u628a\u5b83\u62bd\u8c61\u6210\u4e00\u5f35<strong>\u6709\u5411\u4f9d\u8cf4\u5716<\/strong>\uff1a\u6bcf\u500b artifact \u5ba3\u544a\u81ea\u5df1 <code>requires<\/code> \u54ea\u4e9b\u524d\u7f6e artifact\uff0c\u5716\u5f15\u64ce\u8ca0\u8cac\u7b97\u51fa\u5efa\u69cb\u9806\u5e8f\u8207\u300c\u73fe\u5728\u53ef\u4ee5\u505a\u54ea\u4e9b\u300d\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/artifact-graph\/graph.ts\"><code>src\/core\/artifact-graph\/graph.ts<\/code><\/a> \u2014 <code>ArtifactGraph<\/code> \u985e\u5225\uff0c\u5de5\u4f5c\u6d41\u7684\u8cc7\u6599\u7d50\u69cb\u5316\u6838\u5fc3<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ \u7528 Kahn's algorithm \u7b97\u62d3\u64b2\u9806\u5e8f<\/span>\ngetBuildOrder(): string&#91;] {\n  <span class=\"hljs-keyword\">const<\/span> inDegree = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Map<\/span>&lt;string, number&gt;();\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n  <span class=\"hljs-comment\">\/\/ Start with roots (in-degree 0), sorted for determinism<\/span>\n  <span class=\"hljs-keyword\">const<\/span> queue = &#91;...this.artifacts.keys()]\n    .filter(<span class=\"hljs-function\"><span class=\"hljs-params\">id<\/span> =&gt;<\/span> inDegree.get(id) === <span class=\"hljs-number\">0<\/span>)\n    .sort();\n  <span class=\"hljs-comment\">\/\/ ...\u6bcf\u6b21\u53d6\u51fa\u7bc0\u9ede\u5f8c\uff0c\u628a\u65b0\u8b8a\u70ba ready \u7684\u7bc0\u9ede sort \u518d\u5165\u5217<\/span>\n  queue.push(...newlyReady.sort());\n}\n\ngetNextArtifacts(completed: CompletedSet): string&#91;] {\n  <span class=\"hljs-keyword\">const<\/span> ready: string&#91;] = &#91;];\n  <span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">const<\/span> artifact <span class=\"hljs-keyword\">of<\/span> <span class=\"hljs-keyword\">this<\/span>.artifacts.values()) {\n    <span class=\"hljs-keyword\">if<\/span> (completed.has(artifact.id)) <span class=\"hljs-keyword\">continue<\/span>;\n    <span class=\"hljs-keyword\">const<\/span> allDepsCompleted = artifact.requires.every(<span class=\"hljs-function\"><span class=\"hljs-params\">req<\/span> =&gt;<\/span> completed.has(req));\n    <span class=\"hljs-keyword\">if<\/span> (allDepsCompleted) ready.push(artifact.id);\n  }\n  <span class=\"hljs-keyword\">return<\/span> ready.sort(); <span class=\"hljs-comment\">\/\/ \u6392\u5e8f\u78ba\u4fdd\u6c7a\u5b9a\u6027<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u503c\u5f97\u6ce8\u610f\u7684\u7d30\u7bc0\uff1a<strong>\u6bcf\u500b\u5730\u65b9\u90fd <code>.sort()<\/code><\/strong>\u3002\u4f5c\u8005\u523b\u610f\u5728 Kahn&#8217;s algorithm \u7684\u5165\u5217\u74b0\u7bc0\u6392\u5e8f\uff0c\u8b93\u76f8\u540c\u8f38\u5165\u6c38\u9060\u7522\u51fa\u76f8\u540c\u9806\u5e8f\u3002\u5c0d\u4e00\u500b\u8981\u9935\u7d66 LLM\u3001\u4e14\u9700\u8981\u53ef\u6e2c\u8a66\/\u53ef\u91cd\u73fe\u7684\u5de5\u5177\u800c\u8a00\uff0c\u6c7a\u5b9a\u6027\uff08determinism\uff09\u4e0d\u662f\u53ef\u6709\u53ef\u7121\u7684\u2014\u2014\u5b83\u8b93 AI \u7684\u884c\u70ba\u53ef\u9810\u671f\u3001\u8b93 snapshot \u6e2c\u8a66\u7a69\u5b9a\u3002\u9019\u662f\u300c\u70ba AI \u8a2d\u8a08\u5de5\u5177\u300d\u6642\u5f88\u5bb9\u6613\u88ab\u5ffd\u7565\u537b\u6975\u91cd\u8981\u7684\u4e00\u8ab2\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u8a2d\u8a08\u4e8c\uff1a\u72c0\u614b\u4e0d\u843d\u5730\uff0c\u76f4\u63a5\u5f9e\u6a94\u6848\u7cfb\u7d71\u63a8\u5c0e<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5927\u90e8\u5206\u5de5\u4f5c\u6d41\u5f15\u64ce\u6703\u7dad\u8b77\u4e00\u4efd <code>state.json<\/code> \u8a18\u9304\u300c\u54ea\u4e9b\u6b65\u9a5f\u505a\u5b8c\u4e86\u300d\u3002OpenSpec \u53cd\u5176\u9053\u800c\u884c\u2014\u2014<strong>\u5b83\u6c92\u6709\u72c0\u614b\u6a94\uff0c\u5b8c\u6210\u8207\u5426\u76f4\u63a5\u770b\u7522\u7269\u6a94\u6848\u5b58\u4e0d\u5b58\u5728<\/strong>\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/artifact-graph\/state.ts\"><code>src\/core\/artifact-graph\/state.ts<\/code><\/a> \u2014 \u5f9e change \u76ee\u9304\u6383\u63cf\u6a94\u6848\uff0c\u63a8\u5c0e\u51fa\u5df2\u5b8c\u6210\u7684 artifact \u96c6\u5408<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">detectCompleted<\/span>(<span class=\"hljs-params\">graph: ArtifactGraph, changeDir: string<\/span>): <span class=\"hljs-title\">CompletedSet<\/span> <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> completed = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Set<\/span>&lt;string&gt;();\n  <span class=\"hljs-keyword\">if<\/span> (!fs.existsSync(changeDir)) <span class=\"hljs-keyword\">return<\/span> completed;\n  <span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">const<\/span> artifact <span class=\"hljs-keyword\">of<\/span> graph.getAllArtifacts()) {\n    <span class=\"hljs-keyword\">if<\/span> (isArtifactComplete(artifact.generates, changeDir)) {\n      completed.add(artifact.id);\n    }\n  }\n  <span class=\"hljs-keyword\">return<\/span> completed;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u642d\u914d <a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/artifact-graph\/outputs.ts\"><code>src\/core\/artifact-graph\/outputs.ts<\/code><\/a> \u652f\u63f4 glob\uff08<code>specs\/**\/*.md<\/code> \u9019\u7a2e\u7522\u7269\u7528 <code>fast-glob<\/code> \u5224\u65b7\u662f\u5426\u81f3\u5c11\u5b58\u5728\u4e00\u500b\u6a94\u6848\uff09\uff0c\u5b8c\u6210\u72c0\u614b\u5b8c\u5168\u7531\u6a94\u6848\u7cfb\u7d71\u9019\u500b\u300c\u55ae\u4e00\u771f\u76f8\u4f86\u6e90\u300d\u6c7a\u5b9a\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u9019\u500b\u8a2d\u8a08\u7684\u5a01\u529b\u5728\u65bc\uff1a<strong>\u6a94\u6848\u7cfb\u7d71\u5c31\u662f\u72c0\u614b\uff0cgit \u5c31\u662f\u7248\u672c\u63a7\u5236\uff0c\u4eba\u985e\u624b\u52d5\u6539\u6a94\u6848\u4e5f\u6703\u88ab\u6b63\u78ba\u53cd\u6620<\/strong>\u3002\u6c92\u6709\u72c0\u614b\u540c\u6b65\u3001\u6c92\u6709 state \u640d\u6bc0\u3001\u6c92\u6709\u300c\u6a94\u6848\u5b58\u5728\u4f46 state \u8aaa\u6c92\u505a\u300d\u7684\u4e0d\u4e00\u81f4\u3002\u5c0d\u4e00\u500b\u300cbrownfield \u53cb\u5584\u3001\u8981\u8ddf\u4eba\u985e\u8207 AI \u5171\u540c\u7de8\u8f2f\u300d\u7684\u5de5\u5177\uff0c\u9019\u7a2e\u7121\u72c0\u614b\u8a2d\u8a08\u628a\u8907\u96dc\u5ea6\u964d\u5230\u6700\u4f4e\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u8a2d\u8a08\u4e09\uff1aSchema-driven workflow\u2014\u2014\u5de5\u4f5c\u6d41\u672c\u8eab\u662f\u53ef\u63d2\u62d4\u7684\u8cc7\u6599<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5de5\u4f5c\u6d41\u4e0d\u662f\u5beb\u6b7b\u5728\u7a0b\u5f0f\u88e1\u7684\uff0c\u800c\u662f\u4e00\u4efd YAML schema\uff0c\u7528 Zod \u5b9a\u7fa9\u7d50\u69cb\u4e26\u9a57\u8b49\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/artifact-graph\/types.ts\"><code>src\/core\/artifact-graph\/types.ts<\/code><\/a> \u2014 \u7528 Zod \u5b9a\u7fa9 artifact schema\uff0c\u4e26\u7531 <code>z.infer<\/code> \u53cd\u63a8 TypeScript \u578b\u5225<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> ArtifactSchema = z.object({\n  <span class=\"hljs-attr\">id<\/span>: z.string().min(<span class=\"hljs-number\">1<\/span>, { <span class=\"hljs-attr\">error<\/span>: <span class=\"hljs-string\">'Artifact ID is required'<\/span> }),\n  <span class=\"hljs-attr\">generates<\/span>: z.string().min(<span class=\"hljs-number\">1<\/span>, { <span class=\"hljs-attr\">error<\/span>: <span class=\"hljs-string\">'generates field is required'<\/span> }),\n  <span class=\"hljs-attr\">description<\/span>: z.string(),\n  <span class=\"hljs-attr\">template<\/span>: z.string().min(<span class=\"hljs-number\">1<\/span>, { <span class=\"hljs-attr\">error<\/span>: <span class=\"hljs-string\">'template field is required'<\/span> }),\n  <span class=\"hljs-attr\">instruction<\/span>: z.string().optional(),\n  <span class=\"hljs-attr\">requires<\/span>: z.array(z.string()).default(&#91;]),\n});\n<span class=\"hljs-keyword\">export<\/span> type Artifact = z.infer&lt;<span class=\"hljs-keyword\">typeof<\/span> ArtifactSchema&gt;;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u9019\u88e1\u6709\u5169\u500b\u503c\u5f97\u5b78\u7684\u9ede\u3002\u5176\u4e00\u662f <strong>schema \u5373\u578b\u5225\u7684 single source of truth<\/strong>\uff1a\u7528 Zod \u5ba3\u544a\u4e00\u6b21\uff0c\u57f7\u884c\u671f\u9a57\u8b49\u8207\u7de8\u8b6f\u671f\u578b\u5225\u540c\u6642\u5f97\u5230\uff0c\u675c\u7d55\u300c\u578b\u5225\u8207\u9a57\u8b49\u908f\u8f2f\u4e0d\u540c\u6b65\u300d\u3002\u5176\u4e8c\u662f <code>schemas\/spec-driven\/schema.yaml<\/code> \u9019\u4efd\u5167\u5efa schema \u628a\u6bcf\u500b artifact \u8a72\u600e\u9ebc\u5beb\u7684 <code>instruction<\/code> \u76f4\u63a5\u5167\u5d4c\u5728 YAML \u88e1\uff08proposal \u8981\u6709 Why\/What Changes\/Capabilities\u2026\u3001spec \u7684 scenario\u300c\u5fc5\u9808\u525b\u597d\u7528 4 \u500b <code>#<\/code>\u300d\uff09\u3002<strong>\u5de5\u4f5c\u6d41\u7684\u898f\u5247\u3001\u9806\u5e8f\u3001\u7522\u7269\u3001\u7d66 AI \u7684\u6307\u5f15\uff0c\u5168\u90e8\u662f\u8cc7\u6599\u800c\u975e\u7a0b\u5f0f\u78bc\u3002<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u914d\u5408 <a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/artifact-graph\/resolver.ts\"><code>src\/core\/artifact-graph\/resolver.ts<\/code><\/a> \u7684\u4e09\u5c64\u89e3\u6790\u9806\u5e8f\uff08project-local \u2192 user override \u2192 package built-in\uff09\uff0c\u4f7f\u7528\u8005\u53ef\u4ee5\u5728\u5c08\u6848\u5167\u3001\u6216\u5168\u57df\u8986\u5beb\u6389\u5167\u5efa\u5de5\u4f5c\u6d41\uff0c\u5b8c\u5168\u4e0d\u9700\u6539\u52d5 OpenSpec \u539f\u59cb\u78bc\uff1a<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">\/\/ Resolution order:\n\/\/ 1. Project-local: <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">projectRoot<\/span>&gt;<\/span>\/openspec\/schemas\/<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>\/schema.yaml\n\/\/ 2. User override:  ${XDG_DATA_HOME}\/openspec\/schemas\/<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>\/schema.yaml\n\/\/ 3. Package built-in: <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">package<\/span>&gt;<\/span>\/schemas\/<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>\/schema.yaml\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u9019\u662f\u4e00\u7a2e\u6a19\u6e96\u537b\u597d\u7528\u7684\u64f4\u5c55\u9ede\u8a2d\u8a08\uff1a\u8d8a\u9760\u8fd1\u4f7f\u7528\u8005\u3001\u8d8a\u5177\u9ad4\u7684\u8a2d\u5b9a\u512a\u5148\u7d1a\u8d8a\u9ad8\uff08cascade \/ override \u6a21\u5f0f\uff09\uff0c\u548c CSS\u3001<code>.gitconfig<\/code>\u3001ESLint config \u7684\u601d\u8def\u4e00\u8108\u76f8\u627f\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u8a2d\u8a08\u56db\uff1aCLI \u4f5c\u70ba AI \u7684\u5de5\u5177\u4ecb\u9762\u2014\u2014\u56b4\u683c\u7684\u300cAgent Contract\u300d<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u9019\u662f OpenSpec \u6700\u7368\u5230\u7684\u8a2d\u8a08\u3002AI agent \u4e0d\u662f\u8b80 OpenSpec \u7684\u8aaa\u660e\u6587\u4ef6\u4f86\u4f7f\u7528\u5b83\uff0c\u800c\u662f<strong>\u547c\u53eb CLI \u4e26\u89e3\u6790 JSON \u8f38\u51fa<\/strong>\u3002\u56e0\u6b64 OpenSpec \u70ba <code>--json<\/code> \u6a21\u5f0f\u5b9a\u7fa9\u4e86\u4e00\u4efd\u6975\u5176\u56b4\u8b39\u7684\u6a5f\u5668\u53ef\u8b80\u5951\u7d04\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/docs\/agent-contract.md\"><code>docs\/agent-contract.md<\/code><\/a> \u2014 \u9010\u4e00\u5c0d\u7167 <code>src\/<\/code> \u539f\u59cb\u78bc\u5beb\u6210\u7684 CLI \u6a5f\u5668\u4ecb\u9762\u5951\u7d04\uff0c\u662f\u300c\u70ba AI \u8a2d\u8a08 API\u300d\u7684\u6559\u79d1\u66f8\u7d1a\u7bc4\u4f8b<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u5951\u7d04\u4e2d\u5e7e\u500b\u95dc\u9375\u7d04\u5b9a\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>\u4e00\u6b21\u547c\u53eb = \u4e00\u4efd JSON \u6587\u4ef6<\/strong>\uff1a<code>--json<\/code> \u6a21\u5f0f\u4e0b stdout \u53ea\u6703\u6709\u4e00\u4efd 2-space pretty-print \u7684 JSON\uff1b\u6240\u6709\u4eba\u985e\u53ef\u8b80\u7684 prose\u3001spinner\u3001banner \u4e00\u5f8b\u8d70 stderr\u3002\u9019\u8b93 AI \u80fd\u7121\u8166 <code>JSON.parse(stdout)<\/code>\uff0c\u4e0d\u5fc5\u904e\u6ffe\u96dc\u8a0a\u3002<\/li>\n\n\n<li><strong>\u5931\u6557\u4e5f\u6709\u7d50\u69cb<\/strong>\uff1a\u547d\u4ee4\u5931\u6557\u6642\uff0cstdout \u4ecd\u8f38\u51fa\u8a72\u547d\u4ee4\u7684 null-shape \u52a0\u4e0a <code>status: [diagnostic]<\/code>\uff0c\u4e26\u4ee5 exit code 1 \u7d50\u675f\u3002\u8a3a\u65b7\u8a0a\u606f\u7528\u7d71\u4e00\u7684\u4fe1\u5c01\u683c\u5f0f\uff08<code>severity<\/code> \/ <code>code<\/code> \/ <code>message<\/code> \/ <code>target<\/code> \/ <code>fix<\/code>\uff09\u3002<\/li>\n\n\n<li><strong>\u53ef\u9810\u671f\u7684\u9000\u5834\u78bc<\/strong>\uff1a\u6210\u529f\uff08\u542b\u5065\u5eb7\u6aa2\u67e5\u767c\u73fe\uff09exit 0\uff1b<code>--json<\/code> \u5931\u6557 exit 1\uff1b\u4f7f\u7528\u8005\u53d6\u6d88 exit 130\u3002<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u5728 <a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/commands\/workflow\/status.ts\"><code>src\/commands\/workflow\/status.ts<\/code><\/a> \u53ef\u4ee5\u770b\u5230\u9019\u5957\u7d04\u5b9a\u5982\u4f55\u88ab\u843d\u5be6\u2014\u2014\u9023 spinner \u90fd\u8981\u5c0f\u5fc3\u4e0d\u8207 stderr \u6253\u67b6\uff1a<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ The root resolves (and the store banner prints) before the spinner starts<\/span>\n<span class=\"hljs-comment\">\/\/ so the two do not fight over stderr.<\/span>\n<span class=\"hljs-keyword\">const<\/span> root = <span class=\"hljs-keyword\">await<\/span> resolveRootForCommand(options, { <span class=\"hljs-attr\">json<\/span>: options.json });\n<span class=\"hljs-keyword\">const<\/span> spinner = options.json ? <span class=\"hljs-literal\">undefined<\/span> : ora(<span class=\"hljs-string\">'Loading change status...'<\/span>).start();\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>openspec status --change X --json<\/code> \u56de\u50b3 <code>artifacts<\/code>\uff08\u5404 artifact \u7684 <code>done<\/code>\/<code>ready<\/code>\/<code>blocked<\/code> \u72c0\u614b\uff09\u3001<code>applyRequires<\/code>\uff08\u5be6\u4f5c\u524d\u5fc5\u9808\u5b8c\u6210\u54ea\u4e9b\uff09\u3001<code>artifactPaths<\/code>\uff08\u5404\u7522\u7269\u7684\u89e3\u6790\u8def\u5f91\uff09\uff1b<code>openspec instructions &lt;artifact&gt; --json<\/code> \u56de\u50b3\u8a72\u6b65\u9a5f\u7684 <code>template<\/code>\u3001<code>instruction<\/code>\u3001<code>dependencies<\/code>\u3002<strong>AI \u7684\u6bcf\u4e00\u6b65\u90fd\u7531 CLI \u544a\u77e5\uff0c\u4e0d\u9760 AI \u81ea\u5df1\u8a18\u61b6\u6216\u81c6\u6e2c\u8def\u5f91\u3002<\/strong> \u9019\u5c31\u662f\u628a\u4e0d\u78ba\u5b9a\u7684 LLM \u7d81\u5b9a\u5728\u78ba\u5b9a\u7684\u8ecc\u9053\u4e0a\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u8a2d\u8a08\u4e94\uff1aAdapter + Registry\uff0c\u4e00\u4efd\u6307\u4ee4\u7522\u51fa 28 \u7a2e\u5de5\u5177\u683c\u5f0f<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSpec \u8981\u652f\u63f4 Claude Code\u3001Cursor\u3001Copilot\u3001Gemini\u3001Windsurf\u2026\u6578\u5341\u7a2e AI \u5de5\u5177\uff0c\u6bcf\u7a2e\u5de5\u5177\u7684 slash command \/ skill \u6a94\u6848\u653e\u5728\u4e0d\u540c\u8def\u5f91\u3001\u7528\u4e0d\u540c frontmatter \u683c\u5f0f\u3002\u4f5c\u8005\u7528\u7d93\u5178\u7684 <strong>Adapter \u6a21\u5f0f<\/strong>\u628a\u300c\u5167\u5bb9\u300d\u8207\u300c\u683c\u5f0f\u300d\u5fb9\u5e95\u89e3\u8026\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/command-generation\/types.ts\"><code>src\/core\/command-generation\/types.ts<\/code><\/a> \u2014 \u5b9a\u7fa9 tool-agnostic \u7684 <code>CommandContent<\/code> \u8207 per-tool \u7684 <code>ToolCommandAdapter<\/code> \u4ecb\u9762<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">export <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">ToolCommandAdapter<\/span> <\/span>{\n  toolId: string;\n  getFilePath(commandId: string): string;      <span class=\"hljs-comment\">\/\/ \u6bcf\u500b\u5de5\u5177\u7684\u6a94\u6848\u8def\u5f91\u898f\u5247<\/span>\n  formatFile(content: CommandContent): string;  <span class=\"hljs-comment\">\/\/ \u6bcf\u500b\u5de5\u5177\u7684 frontmatter \u683c\u5f0f<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u6bcf\u500b\u5de5\u5177\u53ea\u9700\u5be6\u4f5c\u9019\u5169\u500b\u65b9\u6cd5\uff0c\u4f8b\u5982 <a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/command-generation\/adapters\/claude.ts\"><code>src\/core\/command-generation\/adapters\/claude.ts<\/code><\/a>\uff1a<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> claudeAdapter: ToolCommandAdapter = {\n  <span class=\"hljs-attr\">toolId<\/span>: <span class=\"hljs-string\">'claude'<\/span>,\n  getFilePath(commandId) {\n    <span class=\"hljs-keyword\">return<\/span> path.join(<span class=\"hljs-string\">'.claude'<\/span>, <span class=\"hljs-string\">'commands'<\/span>, <span class=\"hljs-string\">'opsx'<\/span>, <span class=\"hljs-string\">`<span class=\"hljs-subst\">${commandId}<\/span>.md`<\/span>);\n  },\n  formatFile(content) {\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">`---\\nname: <span class=\"hljs-subst\">${escapeYamlValue(content.name)}<\/span>\\n...\\n---\\n\\n<span class=\"hljs-subst\">${content.body}<\/span>\\n`<\/span>;\n  },\n};\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u800c <a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/command-generation\/registry.ts\"><code>src\/core\/command-generation\/registry.ts<\/code><\/a> \u7528 class \u7684 <strong>static initializer block<\/strong> \u5728\u8f09\u5165\u6642\u4e00\u6b21\u8a3b\u518a\u6240\u6709 adapter\uff1a<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CommandAdapterRegistry<\/span> <\/span>{\n  private <span class=\"hljs-keyword\">static<\/span> adapters = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Map<\/span>&lt;string, ToolCommandAdapter&gt;();\n  <span class=\"hljs-keyword\">static<\/span> {\n    CommandAdapterRegistry.register(claudeAdapter);\n    CommandAdapterRegistry.register(cursorAdapter);\n    <span class=\"hljs-comment\">\/\/ ...28 \u500b adapter<\/span>\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>generator.ts<\/code> \u53ea\u8981 <code>adapter.getFilePath()<\/code> + <code>adapter.formatFile()<\/code> \u5c31\u80fd\u7522\u51fa\u4efb\u4f55\u5de5\u5177\u7684\u6a94\u6848\uff0c\u5b8c\u5168\u4e0d care \u662f\u54ea\u500b\u5de5\u5177\u3002<strong>\u65b0\u589e\u4e00\u7a2e AI \u5de5\u5177 = \u65b0\u589e\u4e00\u500b adapter \u6a94\u6848 + \u5728 registry \u8a3b\u518a\u4e00\u884c\uff0c\u5176\u9918\u7a0b\u5f0f\u78bc\u96f6\u6539\u52d5<\/strong>\u2014\u2014\u9019\u5c31\u662f Open\/Closed Principle \u7684\u6f02\u4eae\u5be6\u8e10\uff0c\u4e5f\u89e3\u91cb\u4e86\u70ba\u4f55\u9019\u500b\u5c08\u6848\u80fd\u5feb\u901f\u8ddf\u4e0a\u5c64\u51fa\u4e0d\u7aae\u7684 AI coding \u5de5\u5177\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u8a2d\u8a08\u516d\uff1a\u628a\u751f\u6210\u5167\u5bb9\u7684\u7d50\u69cb\u300c\u7576\u8cc7\u6599\u50b3\u300d\uff0c\u800c\u975e\u585e\u9032 prompt<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5728 <a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/artifact-graph\/instruction-loader.ts\"><code>src\/core\/artifact-graph\/instruction-loader.ts<\/code><\/a> \u5b9a\u7fa9\u7684 <code>ArtifactInstructions<\/code> \u4ecb\u9762\uff0c\u900f\u9732\u4e86\u4e00\u500b\u7d30\u81a9\u7684\u5206\u5de5\u54f2\u5b78\u3002\u5b83\u628a\u8981\u7d66 AI \u7684\u6771\u897f\u5206\u6210\u5e7e\u985e\uff0c\u800c\u4e14\u5728\u578b\u5225\u8a3b\u89e3\u88e1\u660e\u78ba\u6a19\u793a\u300c\u9019\u662f\u7d66\u4f60\u7576\u7d04\u675f\u7528\u7684\uff0c\u4e0d\u8981\u5beb\u9032\u8f38\u51fa\u6a94\u6848\u300d\uff1a<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">export<\/span> interface ArtifactInstructions {\n  <span class=\"hljs-attr\">instruction<\/span>: string | <span class=\"hljs-literal\">undefined<\/span>;  <span class=\"hljs-comment\">\/\/ schema \u5c0d\u9019\u985e artifact \u7684\u6307\u5f15<\/span>\n  context: string | <span class=\"hljs-literal\">undefined<\/span>;      <span class=\"hljs-comment\">\/\/ \u5c08\u6848\u80cc\u666f\uff08constraints for AI, NOT to be included in output\uff09<\/span>\n  rules: string&#91;] | <span class=\"hljs-literal\">undefined<\/span>;      <span class=\"hljs-comment\">\/\/ artifact \u5c08\u5c6c\u898f\u5247\uff08constraints for AI, NOT in output\uff09<\/span>\n  template: string;                 <span class=\"hljs-comment\">\/\/ \u8f38\u51fa\u7684\u7d50\u69cb\u7bc4\u672c\uff08this IS the output format\uff09<\/span>\n  dependencies: DependencyInfo&#91;];   <span class=\"hljs-comment\">\/\/ \u8981\u8b80\u4f86\u7576\u4e0a\u4e0b\u6587\u7684\u5df2\u5b8c\u6210\u7522\u7269<\/span>\n  unlocks: string&#91;];                <span class=\"hljs-comment\">\/\/ \u5b8c\u6210\u5f8c\u6703\u89e3\u9396\u54ea\u4e9b artifact<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><code>context<\/code>\/<code>rules<\/code> \u662f\u300c\u7d04\u675f\u300d\uff0c<code>template<\/code> \u662f\u300c\u8f38\u51fa\u683c\u5f0f\u300d\uff0c<code>dependencies<\/code> \u662f\u300c\u4e0a\u4e0b\u6587\u4f86\u6e90\u300d\u2014\u2014\u4e09\u8005\u89d2\u8272\u5206\u660e\u5730\u9935\u7d66\u6a21\u578b\uff0c\u800c\u4e0d\u662f\u63c9\u6210\u4e00\u5927\u5718 prompt\u3002\u9019\u7a2e\u7d50\u69cb\u5316\u7684\u8cc7\u8a0a\u4f9b\u7d66\uff0c\u8b93 AI \u66f4\u4e0d\u5bb9\u6613\u641e\u6df7\u300c\u8a72\u9075\u5b88\u7684\u898f\u5247\u300d\u8207\u300c\u8a72\u7522\u51fa\u7684\u5167\u5bb9\u300d\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prompt \u8a2d\u8a08\u89e3\u8b80<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSpec \u7684 prompt \u96c6\u4e2d\u5728 <code>src\/core\/templates\/workflows\/<\/code>\uff0c\u9019\u4e9b\u662f\u5b89\u88dd\u6642\u6703\u88ab command-generation \u8f49\u8b6f\u6210\u5404\u5de5\u5177 slash command \u7684\u6307\u4ee4\u5167\u5bb9\u3002\u4ee5 propose \u5de5\u4f5c\u6d41\u70ba\u4f8b\uff1a<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/src\/core\/templates\/workflows\/propose.ts\"><code>src\/core\/templates\/workflows\/propose.ts<\/code><\/a> \u2014 \u4e00\u6b21\u751f\u6210\u5b8c\u6574 change\uff08proposal + design + spec + tasks\uff09\u7684 skill \u6307\u4ee4<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u9019\u4efd prompt \u7684\u8a2d\u8a08\u610f\u5716\u975e\u5e38\u6e05\u695a\uff1a<strong>\u5b83\u4e0d\u544a\u8a34 AI\u300c\u600e\u9ebc\u5beb\u4e00\u4efd\u597d\u7684 proposal\u300d\uff0c\u800c\u662f\u544a\u8a34 AI\u300c\u600e\u9ebc\u8ddf openspec CLI \u4e92\u52d5\u4f86\u5b8c\u6210\u5de5\u4f5c\u300d<\/strong>\u3002\u6838\u5fc3\u6b65\u9a5f\u88ab\u5beb\u6210\u4e00\u500b\u660e\u78ba\u7684\u8ff4\u5708\uff1a<\/p>\n\n\n<div class=\"cbc-code-wrapper\"><div class=\"cbc-code-bar\"><button class=\"cbc-copy-button\">Copy<\/button><\/div><pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">1. \u82e5\u8f38\u5165\u4e0d\u660e\u78ba\uff0c\u7528 AskUserQuestion \u5de5\u5177\u554f\u6e05\u695a\u8981\u505a\u4ec0\u9ebc\uff08\u4e0d\u51c6\u64c5\u81ea\u958b\u5de5\uff09\n2. openspec new change \"<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>\"        \u2190 \u5efa\u7acb\u9aa8\u67b6\n3. openspec status --change X --json    \u2190 \u53d6\u5f97 applyRequires \u8207 artifact \u72c0\u614b\n4. \u4f9d dependency order \u8ff4\u5708\uff1a\n   a. openspec instructions <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">id<\/span>&gt;<\/span> --json \u2190 \u53d6\u5f97\u8a72\u6b65\u9a5f template\/instruction\/dependencies\n      \u8b80\u53d6\u5df2\u5b8c\u6210\u7684 dependency \u6a94\u6848\u7576\u4e0a\u4e0b\u6587\n      \u4f9d template \u5beb\u6a94\u5230 resolvedOutputPath\n   b. \u6bcf\u5beb\u5b8c\u4e00\u500b\u5c31\u91cd\u8dd1 status --json \u78ba\u8a8d\uff0c\u76f4\u5230 applyRequires \u5168\u90e8 done\n5. openspec status --change X           \u2190 \u986f\u793a\u6700\u7d42\u72c0\u614b\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">\u5e7e\u500b prompt \u5de5\u7a0b\u4e0a\u503c\u5f97\u501f\u93e1\u7684\u624b\u6cd5\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>\u628a\u5de5\u5177\u7576\u72c0\u614b\u4f86\u6e90\uff0c\u800c\u975e\u8b93\u6a21\u578b\u8a18\u61b6<\/strong>\uff1a\u6bcf\u5beb\u5b8c\u4e00\u6b65\u5c31\u91cd\u65b0 <code>openspec status --json<\/code> \u67e5\u4e00\u6b21\uff0c\u660e\u78ba\u8981\u6c42\u300c\u6aa2\u67e5\u6bcf\u500b <code>applyRequires<\/code> \u7684 artifact ID \u662f\u5426 <code>status: \"done\"<\/code>\u300d\u3002\u9019\u907f\u514d\u4e86 LLM \u5c0d\u300c\u6211\u505a\u5230\u54ea\u4e86\u300d\u7522\u751f\u5e7b\u89ba\u3002<\/li>\n\n\n<li><strong>\u5f37\u5236\u6f84\u6e05\u3001\u7981\u6b62\u81c6\u6e2c<\/strong>\uff1a<code>IMPORTANT: Do NOT proceed without understanding what the user wants to build.<\/code> \u7528\u5927\u5beb\u7948\u4f7f\u53e5\u628a\u300c\u4e0d\u78ba\u5b9a\u5c31\u554f\u300d\u8b8a\u6210\u786c\u898f\u5247\u3002<\/li>\n\n\n<li><strong>\u660e\u78ba\u6307\u6d3e\u5de5\u5177<\/strong>\uff1a\u6307\u540d\u8981\u7528 <code>AskUserQuestion<\/code>\u3001<code>TodoWrite<\/code> \u9019\u4e9b agent \u5167\u5efa\u5de5\u5177\uff0c\u800c\u975e\u6cdb\u6cdb\u5730\u8aaa\u300c\u8ffd\u8e64\u9032\u5ea6\u300d\u3002<\/li>\n\n\n<li><strong>\u5206\u96e2\u7d04\u675f\u8207\u8f38\u51fa<\/strong>\uff1aprompt \u660e\u767d\u544a\u8a34 AI\u300c<code>context<\/code> \u548c <code>rules<\/code> \u662f\u7d66\u4f60\u7684\u7d04\u675f\uff0c\u4e0d\u8981\u8907\u88fd\u9032\u8f38\u51fa\u6a94\u6848\uff1b<code>template<\/code> \u624d\u662f\u8f38\u51fa\u7d50\u69cb\u300d\uff0c\u547c\u61c9\u8a2d\u8a08\u516d\u7684\u578b\u5225\u8a3b\u89e3\u3002<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u6574\u9ad4\u4f86\u770b\uff0cOpenSpec \u7684 prompt \u54f2\u5b78\u662f\uff1a<strong>\u628a LLM \u7576\u6210\u4e00\u500b\u9700\u8981\u5916\u90e8\u8a18\u61b6\u8207\u5916\u90e8\u88c1\u6c7a\u7684\u57f7\u884c\u8005<\/strong>\u3002\u51e1\u662f\u53ef\u4ee5\u7531 CLI \u78ba\u5b9a\u56de\u7b54\u7684\uff08\u9806\u5e8f\u3001\u8def\u5f91\u3001\u5b8c\u6210\u8207\u5426\u3001\u683c\u5f0f\uff09\uff0c\u4e00\u5f8b\u8b93 AI \u53bb\u67e5 CLI\uff1b\u53ea\u6709\u771f\u6b63\u9700\u8981\u5275\u9020\u529b\u7684\u90e8\u5206\uff08\u5167\u5bb9\uff09\u624d\u4ea4\u7d66\u6a21\u578b\u81ea\u7531\u767c\u63ee\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u8a2d\u8a08\u7406\u5ff5\u8403\u53d6<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><strong>\u78ba\u5b9a\u6027\u8207\u5275\u9020\u6027\u5206\u5de5<\/strong>\uff1a\u628a\u5de5\u4f5c\u6d41\u62c6\u6210\u300cCLI \u8ca0\u8cac\u7684\u78ba\u5b9a\u6027\u908f\u8f2f\uff08\u6392\u5e8f\/\u72c0\u614b\/\u8def\u5f91\/\u683c\u5f0f\u5951\u7d04\uff09\u300d\u8207\u300cLLM \u8ca0\u8cac\u7684\u5275\u9020\u6027\u751f\u6210\uff08\u5167\u5bb9\uff09\u300d\u3002\u51e1\u80fd\u7531\u7a0b\u5f0f\u78ba\u5b9a\u7684\uff0c\u5c31\u5225\u8b93\u6a21\u578b\u731c\u2014\u2014\u9019\u662f\u99d5\u99ad LLM \u4e0d\u78ba\u5b9a\u6027\u7684\u6839\u672c\u7b56\u7565\u3002<\/li>\n\n\n<li><strong>\u72c0\u614b\u5373\u6a94\u6848\u7cfb\u7d71<\/strong>\uff1a\u80fd\u7528\u300c\u7522\u7269\u662f\u5426\u5b58\u5728\u300d\u63a8\u5c0e\u72c0\u614b\uff0c\u5c31\u4e0d\u8981\u53e6\u5916\u7dad\u8b77 state \u6a94\u3002\u55ae\u4e00\u771f\u76f8\u4f86\u6e90\u7701\u6389\u4e86\u540c\u6b65\u3001\u640d\u6bc0\u8207\u4e0d\u4e00\u81f4\uff0c\u9084\u5929\u7136\u652f\u63f4\u4eba\u985e\u624b\u52d5\u7de8\u8f2f\u8207 git \u7248\u63a7\u3002<\/li>\n\n\n<li><strong>\u5de5\u4f5c\u6d41\u5373\u8cc7\u6599<\/strong>\uff1a\u7528 Zod + YAML schema \u628a\u6d41\u7a0b\u3001\u4f9d\u8cf4\u3001\u7522\u7269\u3001\u6307\u5f15\u5168\u90e8\u5ba3\u544a\u6210\u8cc7\u6599\uff0c\u914d\u5408 project\/user\/package \u4e09\u5c64 override\uff0c\u8b93\u5de5\u5177\u7121\u9700\u6539\u78bc\u5373\u53ef\u88ab\u5ba2\u88fd\u3002schema \u540c\u6642\u662f\u578b\u5225\u7684 single source of truth\u3002<\/li>\n\n\n<li><strong>\u70ba AI \u8a2d\u8a08 API \u8981\u50cf\u8a2d\u8a08\u5354\u5b9a<\/strong>\uff1astdout \u53ea\u653e\u4e00\u4efd JSON\u3001\u96dc\u8a0a\u8d70 stderr\u3001\u5931\u6557\u4e5f\u6709\u7d50\u69cb\u5316 shape\u3001\u9000\u5834\u78bc\u53ef\u9810\u671f\u3002\u628a <code>docs\/agent-contract.md<\/code> \u9019\u7a2e\u300c\u9010\u884c\u5c0d\u7167\u539f\u59cb\u78bc\u7684\u5951\u7d04\u6587\u4ef6\u300d\u7576\u6210\u4e00\u7b49\u516c\u6c11\u4f86\u7dad\u8b77\u3002<\/li>\n\n\n<li><strong>Adapter + Registry \u61c9\u5c0d\u788e\u7247\u5316\u751f\u614b<\/strong>\uff1a\u9762\u5c0d\u6578\u5341\u500b\u7570\u8cea\u6574\u5408\u76ee\u6a19\uff0c\u7528\u7d71\u4e00\u4ecb\u9762 + \u8a3b\u518a\u8868\u628a\u300c\u5167\u5bb9\u300d\u8207\u300c\u683c\u5f0f\u300d\u89e3\u8026\uff0c\u65b0\u589e\u6574\u5408\u53ea\u662f\u52a0\u4e00\u500b\u6a94\u6848\u3002\u9019\u8b93\u5c08\u6848\u80fd\u4f4e\u6210\u672c\u5730\u8ddf\u4e0a\u5feb\u901f\u6f14\u5316\u7684\u5916\u90e8\u751f\u614b\u3002<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">\u5ef6\u4f38\u601d\u8003<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u5982\u679c\u4f60\u6b63\u5728\u6253\u9020\u4efb\u4f55\u300cAI agent \u6703\u547c\u53eb\u300d\u7684\u5de5\u5177\u6216\u670d\u52d9\uff0cOpenSpec \u7684\u601d\u8def\u53ef\u4ee5\u76f4\u63a5\u501f\u93e1\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li><strong>\u8a2d\u8a08\u4e00\u500b <code>--json<\/code> \u5951\u7d04<\/strong>\uff1a\u8b93\u4f60\u7684 CLI\/API \u5728\u7d66 agent \u7528\u6642\u8f38\u51fa\u4e7e\u6de8\u3001\u53ef parse\u3001\u5931\u6557\u4e5f\u6709\u7d50\u69cb\u7684 JSON\uff0c\u4e26\u628a\u5b83\u6587\u4ef6\u5316\u6210\u5951\u7d04\u3002\u9019\u6bd4\u8b93 agent \u8b80\u4f60\u7684 README \u53bb\u731c\u7528\u6cd5\u53ef\u9760\u592a\u591a\u3002<\/li>\n\n\n<li><strong>\u628a\u300c\u8a72\u505a\u4ec0\u9ebc\u300d\u8b8a\u6210\u53ef\u67e5\u8a62\u7684\u72c0\u614b\u7aef\u9ede<\/strong>\uff1a\u8207\u5176\u5728 system prompt \u585e\u4e00\u5927\u6bb5\u6d41\u7a0b\u8aaa\u660e\uff0c\u4e0d\u5982\u63d0\u4f9b\u4e00\u500b <code>status<\/code> \u7aef\u9ede\u8b93 agent \u96a8\u6642\u67e5\u300c\u73fe\u5728\u8a72\u505a\u54ea\u4e00\u6b65\u3001\u524d\u7f6e\u689d\u4ef6\u6eff\u8db3\u4e86\u55ce\u300d\uff0c\u7528\u5916\u90e8\u72c0\u614b\u58d3\u5236 LLM \u7684\u8a18\u61b6\u5e7b\u89ba\u3002<\/li>\n\n\n<li><strong>\u7528\u4f9d\u8cf4\u5716\u63cf\u8ff0\u591a\u6b65\u9a5f\u5de5\u4f5c\u6d41<\/strong>\uff1a\u4efb\u4f55\u6709\u524d\u5f8c\u4f9d\u8cf4\u7684 pipeline\uff08\u8cc7\u6599\u8655\u7406\u3001\u5be9\u6279\u6d41\u3001\u90e8\u7f72\u6d41\u7a0b\uff09\u90fd\u53ef\u4ee5\u62bd\u8c61\u6210 artifact graph\uff0c\u7528\u62d3\u64b2\u6392\u5e8f\u7b97\u51fa\u53ef\u57f7\u884c\u6b65\u9a5f\uff0c\u4e26\u8a18\u5f97\u5728\u6392\u5e8f\u4e2d\u52a0\u5165\u6c7a\u5b9a\u6027 tie-break\u3002<\/li>\n\n\n<li><strong>\u9762\u5c0d\u788e\u7247\u5316\u6574\u5408\uff0c\u5148\u5b9a\u7fa9\u4ecb\u9762\u518d\u8ac7\u5be6\u4f5c<\/strong>\uff1a\u82e5\u4f60\u8981\u5c0d\u63a5\u591a\u500b\u5916\u90e8\u7cfb\u7d71\uff08\u901a\u77e5\u6e20\u9053\u3001\u96f2\u7aef\u4f9b\u61c9\u5546\u3001AI \u5de5\u5177\uff09\uff0c\u5148\u62bd\u51fa\u6700\u5c0f adapter \u4ecb\u9762\uff08\u672c\u4f8b\u53ea\u6709\u5169\u500b\u65b9\u6cd5\uff09\uff0c\u7528 registry \u6536\u6582\uff0c\u8b93\u300c\u65b0\u589e\u6574\u5408\u300d\u8b8a\u6210\u4f4e\u98a8\u96aa\u7684\u52a0\u6cd5\u3002<\/li>\n\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Vibe Coding\uff1a\u628a\u89c0\u5ff5\u8b8a\u6210\u7a0b\u5f0f\u78bc<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u4ee5\u4e0b\u662f\u4f60\u53ef\u4ee5\u76f4\u63a5\u7d66 AI\uff08Claude\u3001Cursor\u3001Copilot\u2026\uff09\u7684 prompt \u6307\u4ee4\uff0c\u5c07\u672c\u6587\u4ecb\u7d39\u7684\u8a2d\u8a08\u89c0\u5ff5\u61c9\u7528\u5230\u4f60\u7684\u5c08\u6848\u4e2d\u3002\u4f7f\u7528\u6642\u53ea\u9700\u628a\u65b9\u62ec\u865f\u7684\u90e8\u5206\u66ff\u63db\u6210\u4f60\u81ea\u5df1\u5c08\u6848\u7684\u5167\u5bb9\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u70ba\u5de5\u5177\u8a2d\u8a08 <code>--json<\/code> Agent Contract<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u5834\u666f<\/strong>\uff1a\u4f60\u6709\u4e00\u652f\u6703\u88ab AI agent \u547c\u53eb\u7684 CLI \u6216\u5167\u90e8\u5de5\u5177\uff0c\u76ee\u524d\u8f38\u51fa\u628a\u4eba\u985e\u53ef\u8b80\u7684 prose\u3001spinner\u3001log \u6df7\u5728\u4e00\u8d77\uff0cagent \u5f88\u96e3\u7a69\u5b9a\u89e3\u6790\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u7d66 AI \u7684\u6307\u4ee4<\/strong>\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u6211\u8981\u628a <code>[\u4f60\u7684 CLI \u540d\u7a31]<\/code> \u6539\u9020\u6210 AI agent \u53cb\u5584\u7684\u5de5\u5177\uff0c\u53c3\u8003 OpenSpec \u7684\u300cagent contract\u300d\u8a2d\u8a08\u3002\u8acb\u5e6b\u6211\u70ba\u6bcf\u500b\u5b50\u547d\u4ee4\u52a0\u4e0a <code>--json<\/code> \u6a21\u5f0f\uff0c\u4e26\u9075\u5b88\u4ee5\u4e0b\u5951\u7d04\uff1a(1) <code>--json<\/code> \u4e0b stdout **\u53ea**\u8f38\u51fa\u4e00\u4efd 2-space pretty-print \u7684 JSON\uff0c\u6240\u6709 spinner\uff0fbanner\uff0f\u4eba\u985e\u53ef\u8b80\u8a0a\u606f\u4e00\u5f8b\u6539\u8d70 stderr\uff1b(2) \u547d\u4ee4\u5931\u6557\u6642 stdout \u4ecd\u8f38\u51fa\u8a72\u547d\u4ee4\u7684 null-shape \u52a0\u4e00\u500b\u7d50\u69cb\u5316 <code>status<\/code> \u8a3a\u65b7\u6b04\u4f4d\uff08\u6b04\u4f4d\u7528 <code>severity<\/code>\uff0f<code>code<\/code>\uff0f<code>message<\/code>\uff0f<code>target<\/code>\uff0f<code>fix<\/code> \u7684\u7d71\u4e00\u4fe1\u5c01\u683c\u5f0f\uff09\uff0c\u4e26\u4ee5 exit code 1 \u7d50\u675f\uff1b(3) \u9000\u5834\u78bc\u8981\u53ef\u9810\u671f\uff1a\u6210\u529f 0\u3001<code>--json<\/code> \u5931\u6557 1\u3001\u4f7f\u7528\u8005\u53d6\u6d88 130\u3002\u6539\u5b8c\u5f8c\u5e6b\u6211\u5beb\u4e00\u4efd <code>agent-contract.md<\/code>\uff0c\u9010\u4e00\u5c0d\u7167\u539f\u59cb\u78bc\u63cf\u8ff0\u6bcf\u500b\u547d\u4ee4\u7684\u8f38\u5165\u3001JSON \u8f38\u51fa shape \u8207\u9000\u5834\u78bc\u3002<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u6548\u679c<\/strong>\uff1aAI \u6703\u91cd\u69cb CLI \u7684\u8f38\u51fa\u5c64\uff08\u628a stdout\/stderr \u5206\u6d41\uff09\uff0c\u70ba\u6bcf\u500b\u547d\u4ee4\u5b9a\u7fa9\u7a69\u5b9a\u7684 JSON schema \u8207\u932f\u8aa4\u4fe1\u5c01\uff0c\u4e26\u7522\u51fa\u4e00\u4efd\u53ef\u7dad\u8b77\u7684\u6a5f\u5668\u4ecb\u9762\u5951\u7d04\u6587\u4ef6\uff0c\u8b93\u4e0b\u6e38 agent \u80fd\u7121\u8166 <code>JSON.parse(stdout)<\/code>\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u7528 Zod schema \u7576\u300c\u578b\u5225\u7684\u55ae\u4e00\u771f\u76f8\u4f86\u6e90\u300d<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u5834\u666f<\/strong>\uff1a\u5c08\u6848\u88e1\u540c\u4e00\u4efd\u8cc7\u6599\u7d50\u69cb\u540c\u6642\u6709 TypeScript <code>interface<\/code> \u548c\u53e6\u5916\u624b\u5beb\u7684\u9a57\u8b49\u908f\u8f2f\uff0c\u5169\u8005\u5e38\u5e38\u4e0d\u540c\u6b65\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u7d66 AI \u7684\u6307\u4ee4<\/strong>\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u8acb\u628a <code>[\u4f60\u7684\u578b\u5225\uff0f\u8a2d\u5b9a\u6a94\u7d50\u69cb]<\/code> \u6539\u6210\u7528 Zod \u5b9a\u7fa9\u7684 single source of truth\uff0c\u4eff\u7167 OpenSpec \u7684\u505a\u6cd5\uff1a\u7528 <code>z.object({...})<\/code> \u5ba3\u544a schema\uff08\u6bcf\u500b\u6b04\u4f4d\u5e36\u4e0a\u6709\u610f\u7fa9\u7684 <code>error<\/code> \u8a0a\u606f\u8207 <code>.default()<\/code>\uff09\uff0c\u518d\u7528 <code>type X = z.infer&lt;typeof XSchema&gt;<\/code> \u53cd\u63a8 TypeScript \u578b\u5225\uff0c\u522a\u6389\u539f\u672c\u624b\u5beb\u7684 <code>interface<\/code>\u3002\u6240\u6709\u5916\u90e8\u8f38\u5165\uff08\u8a2d\u5b9a\u6a94\u3001API payload\u3001CLI \u53c3\u6578\uff09\u9032\u4f86\u6642\u90fd\u5148\u904e <code>XSchema.parse()<\/code>\uff0c\u8b93\u57f7\u884c\u671f\u9a57\u8b49\u8207\u7de8\u8b6f\u671f\u578b\u5225\u5171\u7528\u540c\u4e00\u4efd\u5ba3\u544a\u3002<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u6548\u679c<\/strong>\uff1aAI \u6703\u628a\u91cd\u8907\u7684\u578b\u5225\u5ba3\u544a\u8207\u9a57\u8b49\u908f\u8f2f\u6536\u6582\u6210\u55ae\u4e00 Zod schema\uff0c\u675c\u7d55\u300c\u578b\u5225\u6539\u4e86\u4f46\u9a57\u8b49\u6c92\u6539\u300d\u7684\u4e0d\u4e00\u81f4\uff0c\u4e26\u5728\u8cc7\u6599\u908a\u754c\u88dc\u4e0a runtime \u9a57\u8b49\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u628a\u591a\u6b65\u9a5f\u5de5\u4f5c\u6d41\u62bd\u8c61\u6210\u4f9d\u8cf4\u5716 + \u62d3\u64b2\u6392\u5e8f<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u5834\u666f<\/strong>\uff1a\u4f60\u6709\u4e00\u6bb5\u7528 <code>if\/else<\/code> \u786c\u4e32\u8d77\u4f86\u7684\u591a\u6b65\u9a5f\u6d41\u7a0b\uff08\u8cc7\u6599 pipeline\u3001\u5be9\u6279\u6d41\u3001\u90e8\u7f72\u6d41\u7a0b\uff09\uff0c\u6b65\u9a5f\u9593\u6709\u524d\u5f8c\u4f9d\u8cf4\uff0c\u6bcf\u52a0\u4e00\u6b65\u90fd\u8981\u6539\u6d41\u7a0b\u63a7\u5236\u78bc\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u7d66 AI \u7684\u6307\u4ee4<\/strong>\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u6211\u9019\u6bb5\u6d41\u7a0b <code>[\u8cbc\u4e0a\u76ee\u524d\u7684\u6d41\u7a0b\u7a0b\u5f0f\u78bc\u6216\u6b65\u9a5f\u63cf\u8ff0]<\/code> \u76ee\u524d\u662f\u5beb\u6b7b\u7684\u9806\u5e8f\u3002\u8acb\u4eff\u7167 OpenSpec \u7684 artifact graph \u8a2d\u8a08\uff0c\u628a\u5b83\u91cd\u69cb\u6210\u4e00\u5f35\u6709\u5411\u4f9d\u8cf4\u5716\uff1a\u6bcf\u500b\u6b65\u9a5f\u5ba3\u544a\u81ea\u5df1 <code>requires<\/code> \u54ea\u4e9b\u524d\u7f6e\u6b65\u9a5f\uff0c\u518d\u5beb\u4e00\u500b\u7528 Kahn&#8217;s algorithm \u7b97 build order \u7684\u51fd\u5f0f\uff0c\u4ee5\u53ca\u4e00\u500b <code>getNextArtifacts(completed)<\/code> \u56de\u50b3\u300c\u76ee\u524d\u6240\u6709\u524d\u7f6e\u689d\u4ef6\u90fd\u6eff\u8db3\u3001\u53ef\u4ee5\u57f7\u884c\u300d\u7684\u6b65\u9a5f\u3002**\u95dc\u9375\u8981\u6c42**\uff1a\u5728\u62d3\u64b2\u6392\u5e8f\u7684\u6bcf\u500b\u5165\u5217\u74b0\u7bc0\u90fd\u5c0d\u5019\u9078\u7bc0\u9ede <code>.sort()<\/code>\uff0c\u78ba\u4fdd\u76f8\u540c\u8f38\u5165\u6c38\u9060\u7522\u51fa\u76f8\u540c\u9806\u5e8f\uff08\u6c7a\u5b9a\u6027 tie-break\uff09\uff0c\u9019\u6a23\u624d\u597d\u5beb snapshot \u6e2c\u8a66\u3002<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u6548\u679c<\/strong>\uff1aAI \u6703\u628a\u547d\u4ee4\u5f0f\u7684\u6d41\u7a0b\u63a7\u5236\u6539\u6210\u5ba3\u544a\u5f0f\u7684\u4f9d\u8cf4\u5716\uff0c\u65b0\u589e\u6b65\u9a5f\u53ea\u9700\u5ba3\u544a\u4f9d\u8cf4\u800c\u4e0d\u52d5\u6392\u5e8f\u908f\u8f2f\uff0c\u4e26\u7522\u51fa\u53ef\u91cd\u73fe\u3001\u53ef\u6e2c\u8a66\u7684\u57f7\u884c\u9806\u5e8f\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u7528\u300c\u72c0\u614b\u5373\u6a94\u6848\u7cfb\u7d71\u300d\u53d6\u4ee3 state \u6a94<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u5834\u666f<\/strong>\uff1a\u4f60\u7684\u5de5\u5177\u7dad\u8b77\u4e00\u4efd <code>state.json<\/code> \u8a18\u9304\u300c\u54ea\u4e9b\u6b65\u9a5f\u505a\u5b8c\u4e86\u300d\uff0c\u4f46\u5e38\u51fa\u73fe state \u8207\u5be6\u969b\u7522\u7269\u4e0d\u4e00\u81f4\u3001\u4eba\u5de5\u6539\u4e86\u6a94\u6848\u4f46 state \u6c92\u66f4\u65b0\u7684\u554f\u984c\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u7d66 AI \u7684\u6307\u4ee4<\/strong>\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u8acb\u5e6b\u6211\u79fb\u9664 <code>[\u4f60\u7684 state.json\uff0f\u72c0\u614b\u8a18\u9304\u6a5f\u5236]<\/code>\uff0c\u6539\u7528 OpenSpec \u7684\u300c\u72c0\u614b\u5373\u6a94\u6848\u7cfb\u7d71\u300d\u8a2d\u8a08\uff1a\u5b8c\u6210\u8207\u5426\u76f4\u63a5\u5f9e**\u7522\u7269\u6a94\u6848\u662f\u5426\u5b58\u5728**\u63a8\u5c0e\uff0c\u800c\u4e0d\u662f\u984d\u5916\u8a18\u9304\u3002\u5beb\u4e00\u500b <code>detectCompleted()<\/code> \u6383\u63cf\u7522\u7269\u76ee\u9304\uff0c\u5c0d\u6bcf\u500b\u6b65\u9a5f\u6aa2\u67e5\u5b83\u5ba3\u544a\u7684 <code>generates<\/code> \u7522\u7269\uff08\u652f\u63f4 glob\uff0c\u4f8b\u5982 <code>output\/**\/*.json<\/code> \u7528 fast-glob \u5224\u65b7\u662f\u5426\u81f3\u5c11\u5b58\u5728\u4e00\u500b\u6a94\u6848\uff09\u662f\u5426\u5b58\u5728\uff0c\u56de\u50b3\u5df2\u5b8c\u6210\u96c6\u5408\u3002\u76ee\u6a19\u662f\u8b93\u6a94\u6848\u7cfb\u7d71\u6210\u70ba\u55ae\u4e00\u771f\u76f8\u4f86\u6e90\uff0c\u5929\u7136\u652f\u63f4 git \u7248\u63a7\u8207\u4eba\u5de5\u624b\u52d5\u7de8\u8f2f\u3002<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u6548\u679c<\/strong>\uff1aAI \u6703\u628a\u72c0\u614b\u7ba1\u7406\u5f9e\u7368\u7acb state \u6a94\u6539\u70ba\u5c0d\u6a94\u6848\u7cfb\u7d71\u7684\u5373\u6642\u63a8\u5c0e\uff0c\u6d88\u9664\u72c0\u614b\u540c\u6b65\u8207\u4e0d\u4e00\u81f4\u554f\u984c\uff0c\u4e26\u8b93\u6d41\u7a0b\u5c0d\u4eba\u5de5\u4ecb\u5165\u8207\u7248\u63a7\u53cb\u5584\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u7528 Adapter + Registry \u61c9\u5c0d\u788e\u7247\u5316\u6574\u5408<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u5834\u666f<\/strong>\uff1a\u4f60\u8981\u5c0d\u63a5\u591a\u500b\u7570\u8cea\u7684\u5916\u90e8\u76ee\u6a19\uff08\u591a\u5bb6\u901a\u77e5\u6e20\u9053\u3001\u591a\u7a2e\u96f2\u7aef\u4f9b\u61c9\u5546\u3001\u591a\u500b AI \u5de5\u5177\uff09\uff0c\u6bcf\u500b\u76ee\u6a19\u683c\u5f0f\uff0f\u8def\u5f91\u90fd\u4e0d\u540c\uff0c\u7a0b\u5f0f\u88e1\u585e\u6eff\u4e86 <code>switch (tool)<\/code>\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u7d66 AI \u7684\u6307\u4ee4<\/strong>\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u6211\u9700\u8981\u628a <code>[\u4f60\u7684\u5167\u5bb9\uff0f\u8cc7\u6599]<\/code> \u8f38\u51fa\u6210 <code>[\u5217\u51fa\u76ee\u6a19\u7cfb\u7d71\uff0c\u4f8b\u5982 Slack\uff0fEmail\uff0fWebhook]<\/code> \u7b49\u591a\u7a2e\u683c\u5f0f\uff0c\u76ee\u524d\u662f\u4e00\u5806 <code>switch<\/code> \u5224\u65b7\u3002\u8acb\u7528 Adapter + Registry \u6a21\u5f0f\u91cd\u69cb\uff1a(1) \u5b9a\u7fa9\u4e00\u500b tool-agnostic \u7684\u5167\u5bb9\u578b\u5225\u548c\u4e00\u500b\u6700\u5c0f <code>Adapter<\/code> \u4ecb\u9762\uff08\u53c3\u8003 OpenSpec \u53ea\u6709 <code>getFilePath()<\/code> \u548c <code>formatFile()<\/code> \u5169\u500b\u65b9\u6cd5\uff0c\u4f60\u9019\u908a\u62bd\u51fa\u5c0d\u61c9\u7684\u6700\u5c0f\u65b9\u6cd5\u96c6\uff09\uff1b(2) \u6bcf\u500b\u76ee\u6a19\u5be6\u4f5c\u6210\u7368\u7acb\u7684 adapter \u6a94\u6848\uff1b(3) \u7528\u4e00\u500b <code>Registry<\/code> class \u7684 static initializer block \u5728\u8f09\u5165\u6642\u8a3b\u518a\u6240\u6709 adapter\u3002\u6838\u5fc3\u7522\u51fa\u908f\u8f2f\u53ea\u4f9d\u8cf4\u4ecb\u9762\u3001\u5b8c\u5168\u4e0d care \u662f\u54ea\u500b\u76ee\u6a19\u3002\u9019\u6a23\u65b0\u589e\u4e00\u500b\u6574\u5408 = \u52a0\u4e00\u500b adapter \u6a94 + registry \u8a3b\u518a\u4e00\u884c\uff0c\u7b26\u5408 Open\/Closed Principle\u3002<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u6548\u679c<\/strong>\uff1aAI \u6703\u628a\u6563\u843d\u7684\u689d\u4ef6\u5206\u652f\u6536\u6582\u6210\u7d71\u4e00\u4ecb\u9762 + \u8a3b\u518a\u8868\uff0c\u8b93\u300c\u5167\u5bb9\u300d\u8207\u300c\u683c\u5f0f\u300d\u89e3\u8026\uff0c\u65b0\u589e\u6574\u5408\u8b8a\u6210\u4f4e\u98a8\u96aa\u7684\u52a0\u6cd5\uff0c\u5176\u9918\u7a0b\u5f0f\u78bc\u96f6\u6539\u52d5\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\u5728 prompt \u88e1\u5206\u96e2\u300c\u7d04\u675f\u300d\u8207\u300c\u8f38\u51fa\u683c\u5f0f\u300d<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u5834\u666f<\/strong>\uff1a\u4f60\u5728\u5beb\u7d66 AI agent \u7684 system prompt \u6216 skill \u6307\u4ee4\uff0cAI \u5e38\u628a\u300c\u8a72\u9075\u5b88\u7684\u898f\u5247\u300d\u8aa4\u7576\u6210\u5167\u5bb9\u5beb\u9032\u7522\u51fa\u6a94\u6848\u3002<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u7d66 AI \u7684\u6307\u4ee4<\/strong>\uff1a<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">\u8acb\u5e6b\u6211\u91cd\u5beb\u9019\u4efd\u7d66 AI \u7684\u6307\u4ee4 <code>[\u8cbc\u4e0a\u4f60\u7684 prompt\uff0fskill]<\/code>\uff0c\u5957\u7528 OpenSpec \u7684 prompt \u5206\u5de5\u54f2\u5b78\uff1a(1) \u628a\u8cc7\u8a0a\u660e\u78ba\u5206\u6210\u4e09\u985e\u4e26\u6a19\u8a3b\u89d2\u8272\u2014\u2014<code>context<\/code>\uff0f<code>rules<\/code> \u662f\u300c\u7d66\u4f60\u7684\u7d04\u675f\uff0c**\u4e0d\u8981**\u5beb\u9032\u8f38\u51fa\u300d\u3001<code>template<\/code> \u624d\u662f\u300c\u8f38\u51fa\u7684\u7d50\u69cb\u7bc4\u672c\u300d\u3001<code>dependencies<\/code> \u662f\u300c\u8981\u8b80\u4f86\u7576\u4e0a\u4e0b\u6587\u7684\u65e2\u6709\u7522\u7269\u300d\uff1b(2) \u628a\u5de5\u5177\u7576\u5916\u90e8\u72c0\u614b\u4f86\u6e90\u800c\u975e\u8b93\u6a21\u578b\u8a18\u61b6\uff0c\u6bcf\u5b8c\u6210\u4e00\u6b65\u5c31\u8981\u6c42 AI \u91cd\u65b0\u67e5\u4e00\u6b21 <code>[\u4f60\u7684 status \u547d\u4ee4\uff0f\u72c0\u614b\u7aef\u9ede]<\/code> \u78ba\u8a8d\u9032\u5ea6\uff0c\u907f\u514d\u5e7b\u89ba\uff1b(3) \u5c0d\u4e0d\u78ba\u5b9a\u7684\u8f38\u5165\u7528\u5927\u5beb\u7948\u4f7f\u53e5\u5f37\u5236\u6f84\u6e05\uff08\u4f8b\u5982 <code>IMPORTANT: Do NOT proceed without ...<\/code>\uff09\uff0c\u7981\u6b62\u64c5\u81ea\u81c6\u6e2c\u3002<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\u6548\u679c<\/strong>\uff1aAI \u6703\u628a prompt \u91cd\u69cb\u6210\u89d2\u8272\u5206\u660e\u7684\u7d50\u69cb\u5316\u6307\u4ee4\uff0c\u660e\u78ba\u5340\u9694\u7d04\u675f\u8207\u8f38\u51fa\u3001\u7528\u5916\u90e8\u72c0\u614b\u58d3\u5236\u8a18\u61b6\u5e7b\u89ba\u3001\u4e26\u628a\u300c\u4e0d\u78ba\u5b9a\u5c31\u554f\u300d\u8b8a\u6210\u786c\u898f\u5247\uff0c\u8b93 agent \u884c\u70ba\u66f4\u53ef\u9810\u671f\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u5ef6\u4f38\u95b1\u8b80<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/docs\/getting-started.md\">OpenSpec Getting Started \u5b98\u65b9\u6587\u4ef6<\/a> \u2014 \u5b98\u65b9\u5165\u9580\u6307\u5357\uff0c\u8aaa\u660e\u300cCLI \u5de5\u5177\u300d\u8207\u300cslash command\u300d\u5169\u500b\u534a\u908a\u5982\u4f55\u5206\u5de5\uff0c\u662f\u7406\u89e3\u672c\u6587\u67b6\u69cb\u8a2d\u8a08\u7684\u6700\u4f73\u5c0d\u7167\u3002<\/li>\n\n\n<li><a href=\"https:\/\/github.com\/Fission-AI\/OpenSpec\/blob\/main\/docs\/agent-contract.md\">OpenSpec Agent Contract \u5951\u7d04\u6587\u4ef6<\/a> \u2014 \u672c\u6587\u8a2d\u8a08\u56db\u7684\u4e00\u624b\u4f86\u6e90\uff0c\u9010\u884c\u5c0d\u7167\u539f\u59cb\u78bc\u5b9a\u7fa9 <code>--json<\/code> \u8f38\u51fa shape \u8207\u9000\u5834\u78bc\uff0c\u300c\u70ba AI \u8a2d\u8a08 API\u300d\u7684\u6559\u79d1\u66f8\u7d1a\u7bc4\u4f8b\u3002<\/li>\n\n\n<li><a href=\"https:\/\/github.blog\/ai-and-ml\/generative-ai\/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit\/\">Spec-driven development with AI\uff08GitHub Blog\uff09<\/a> \u2014 GitHub \u5b98\u65b9\u5c0d SDD \u65b9\u6cd5\u8ad6\u7684\u5b8c\u6574\u95e1\u8ff0\uff0c\u5e6b\u4f60\u7406\u89e3 OpenSpec \u6240\u8655\u7684\u6574\u500b spec-driven \u751f\u614b\u8108\u7d61\u3002<\/li>\n\n\n<li><a href=\"https:\/\/ranthebuilder.cloud\/blog\/i-tested-three-spec-driven-ai-tools-here-s-my-honest-take\/\">I Tested Three Spec-Driven AI Tools\uff08\u5be6\u6e2c\u6bd4\u8f03\uff09<\/a> \u2014 \u958b\u767c\u8005\u5be6\u6e2c OpenSpec\u3001Spec Kit \u7b49\u5de5\u5177\u7684\u8aa0\u5be6\u5fc3\u5f97\uff0c\u770b\u770b\u4e0d\u540c SDD \u8a2d\u8a08\u53d6\u6368\u5728\u771f\u5be6\u4f7f\u7528\u4e0b\u7684\u5dee\u7570\u3002<\/li>\n\n\n<li><a href=\"https:\/\/blog.arcjet.com\/designing-a-cli-for-ai-agents\/\">Designing a CLI for AI agents\uff08Arcjet Blog\uff09<\/a> \u2014 \u6df1\u5165\u63a2\u8a0e\u70ba agent \u8a2d\u8a08 CLI \u7684\u539f\u5247\uff08stdout \u5373 API \u5951\u7d04\u3001\u7d50\u69cb\u5316\u932f\u8aa4\u3001\u9000\u5834\u78bc\uff09\uff0c\u8207\u672c\u6587\u8a2d\u8a08\u56db\u5f7c\u6b64\u5370\u8b49\u3002<\/li>\n\n\n<li><a href=\"https:\/\/dev.to\/codinsonn\/the-joy-of-single-sources-of-truth-277o\">Zod and the Joy of Single Sources of Truth<\/a> \u2014 \u8a73\u89e3\u5982\u4f55\u7528 Zod \u7684 <code>z.infer<\/code> \u8b93 schema \u540c\u6642\u7576\u9a57\u8b49\u8207\u578b\u5225\u7684\u55ae\u4e00\u771f\u76f8\u4f86\u6e90\uff0c\u5c0d\u61c9\u672c\u6587\u8a2d\u8a08\u4e09\u3002<\/li>\n\n<\/ul>\n\n\n<div class=\"wp-like-post__wrapper\" style=\"\"><button type=\"button\" class=\"wp-like-post__button \" style=\"height: 30px; color: #000000;\" data-post-id=\"843\" data-total-likes=\"0\" data-likes-from-user=\"0\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" width=\"30\" height=\"30\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6.633 10.5c.806 0 1.533-.446 2.031-1.08a9.041 9.041 0 012.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 00.322-1.672V3a.75.75 0 01.75-.75A2.25 2.25 0 0116.5 4.5c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 01-2.649 7.521c-.388.482-.987.729-1.605.729H13.48c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 00-1.423-.23H5.904M14.25 9h2.25M5.904 18.75c.083.205.173.405.27.602.197.4-.078.898-.523.898h-.908c-.889 0-1.713-.518-1.972-1.368a12 12 0 01-.521-3.507c0-1.553.295-3.036.831-4.398C3.387 10.203 4.167 9.75 5 9.75h1.053c.472 0 .745.556.5.96a8.958 8.958 0 00-1.302 4.665c0 1.194.232 2.333.654 3.375z\" \/><\/svg><\/button><div class=\"wp-like-post__count\"\">0<\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>OpenSpec \u662f\u4e00\u500b\u70ba AI coding assistant \u6253\u9020\u7684 spec-driven devel [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rolpb_likes":0,"footnotes":""},"categories":[874],"tags":[430,669,532,26,571],"class_list":["post-843","post","type-post","status-publish","format-standard","hentry","category-cli-tool","tag-ai-agent","tag-cli","tag-spec-driven-development","tag-typescript","tag-571"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":7}},"_links":{"self":[{"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/posts\/843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/comments?post=843"}],"version-history":[{"count":0,"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/posts\/843\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/media?parent=843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/categories?post=843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.itsmygo.uk\/wordpress\/wp-json\/wp\/v2\/tags?post=843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}