@cat-kit/agent-context 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/done.js +2 -0
  4. package/dist/commands/done.js.map +1 -0
  5. package/dist/commands/install.js.map +1 -1
  6. package/dist/commands/printer.js.map +1 -1
  7. package/dist/commands/status.js +2 -0
  8. package/dist/commands/status.js.map +1 -0
  9. package/dist/commands/sync.js.map +1 -1
  10. package/dist/commands/validate.js +2 -0
  11. package/dist/commands/validate.js.map +1 -0
  12. package/dist/content/actions.js +21 -16
  13. package/dist/content/actions.js.map +1 -1
  14. package/dist/content/index.js +4 -3
  15. package/dist/content/index.js.map +1 -1
  16. package/dist/context/archiver.js +2 -0
  17. package/dist/context/archiver.js.map +1 -0
  18. package/dist/context/reader.js +2 -0
  19. package/dist/context/reader.js.map +1 -0
  20. package/dist/context/validator.js +2 -0
  21. package/dist/context/validator.js.map +1 -0
  22. package/dist/runner.js.map +1 -1
  23. package/dist/stats.html +1 -1
  24. package/dist/tools.js.map +1 -1
  25. package/package.json +2 -2
  26. package/src/cli.ts +21 -2
  27. package/src/commands/done.ts +55 -0
  28. package/src/commands/install.ts +4 -4
  29. package/src/commands/printer.ts +1 -1
  30. package/src/commands/status.ts +35 -0
  31. package/src/commands/sync.ts +4 -4
  32. package/src/commands/validate.ts +28 -0
  33. package/src/content/actions.ts +24 -18
  34. package/src/content/index.ts +6 -5
  35. package/src/context/archiver.ts +45 -0
  36. package/src/context/index.ts +3 -0
  37. package/src/context/reader.ts +77 -0
  38. package/src/context/validator.ts +44 -0
  39. package/src/runner.ts +4 -4
  40. package/src/tools.ts +1 -1
  41. package/src/types.ts +29 -0
package/dist/cli.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{installCommand as e}from"./commands/install.js";import{syncCommand as t}from"./commands/sync.js";import{readFileSync as n}from"node:fs";import{Command as r}from"commander";const i=JSON.parse(n(new URL(`../package.json`,import.meta.url),`utf8`)),a=typeof i.version==`string`?i.version:`0.0.0`,o=new r;o.name(`agent-context`).description(`Agent Context Skills 安装工具`).version(a),o.command(`install`).description(`安装 ac-workflow Skill`).option(`--tools <tools>`,`指定目标工具,逗号分隔:claude,codex,cursor,antigravity,copilot`).option(`--yes`,`非交互模式:优先复用已安装工具,否则安装全部工具`).option(`--check`,`仅检查是否存在待更新内容,不写入文件`).action(e),o.command(`sync`).description(`同步已安装的 ac-workflow Skill`).option(`--tools <tools>`,`指定目标工具,逗号分隔:claude,codex,cursor,antigravity,copilot`).option(`--check`,`仅检查是否存在待更新内容,不写入文件`).action(t),o.parseAsync().catch(e=>{let t=e instanceof Error?e.message:String(e);console.error(`\n❌ ${t}`),process.exitCode=1});export{};
2
+ import{doneCommand as e}from"./commands/done.js";import{installCommand as t}from"./commands/install.js";import{statusCommand as n}from"./commands/status.js";import{syncCommand as r}from"./commands/sync.js";import{validateCommand as i}from"./commands/validate.js";import{readFileSync as a}from"node:fs";import{Command as o}from"commander";const s=JSON.parse(a(new URL(`../package.json`,import.meta.url),`utf8`)),c=typeof s.version==`string`?s.version:`0.0.0`,l=new o;l.name(`agent-context`).description(`Agent Context Skills 安装工具`).version(c),l.command(`install`).description(`安装 ac-workflow Skill`).option(`--tools <tools>`,`指定目标工具,逗号分隔:claude,codex,cursor,antigravity,copilot`).option(`--yes`,`非交互模式:优先复用已安装工具,否则安装全部工具`).option(`--check`,`仅检查是否存在待更新内容,不写入文件`).action(t),l.command(`sync`).description(`同步已安装的 ac-workflow Skill`).option(`--tools <tools>`,`指定目标工具,逗号分隔:claude,codex,cursor,antigravity,copilot`).option(`--check`,`仅检查是否存在待更新内容,不写入文件`).action(r),l.command(`validate`).description(`校验 .agent-context 目录结构`).action(i),l.command(`status`).description(`查看当前 agent-context 状态`).action(n),l.command(`done`).description(`归档当前已执行计划`).option(`--yes`,`跳过确认,直接归档`).action(e),l.parseAsync().catch(e=>{let t=e instanceof Error?e.message:String(e);console.error(`\n❌ ${t}`),process.exitCode=1});export{};
3
3
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'node:fs'\n\nimport { Command } from 'commander'\n\nimport { installCommand } from './commands/install'\nimport { syncCommand } from './commands/sync'\n\nconst packageJson = JSON.parse(\n readFileSync(new URL('../package.json', import.meta.url), 'utf8')\n) as { version?: string }\nconst packageVersion = typeof packageJson.version === 'string' ? packageJson.version : '0.0.0'\n\nconst program = new Command()\n\nprogram.name('agent-context').description('Agent Context Skills 安装工具').version(packageVersion)\n\nprogram\n .command('install')\n .description('安装 ac-workflow Skill')\n .option('--tools <tools>', '指定目标工具,逗号分隔:claude,codex,cursor,antigravity,copilot')\n .option('--yes', '非交互模式:优先复用已安装工具,否则安装全部工具')\n .option('--check', '仅检查是否存在待更新内容,不写入文件')\n .action(installCommand)\n\nprogram\n .command('sync')\n .description('同步已安装的 ac-workflow Skill')\n .option('--tools <tools>', '指定目标工具,逗号分隔:claude,codex,cursor,antigravity,copilot')\n .option('--check', '仅检查是否存在待更新内容,不写入文件')\n .action(syncCommand)\n\nprogram.parseAsync().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error)\n console.error(`\\n❌ ${message}`) // eslint-disable-line no-console\n process.exitCode = 1\n})\n"],"mappings":";mLASA,MAAM,EAAc,KAAK,MACvB,EAAa,IAAI,IAAI,kBAAmB,OAAO,KAAK,IAAI,CAAE,OAAO,CAClE,CACK,EAAiB,OAAO,EAAY,SAAY,SAAW,EAAY,QAAU,QAEjF,EAAU,IAAI,EAEpB,EAAQ,KAAK,gBAAgB,CAAC,YAAY,4BAA4B,CAAC,QAAQ,EAAe,CAE9F,EACG,QAAQ,UAAU,CAClB,YAAY,uBAAuB,CACnC,OAAO,kBAAmB,sDAAsD,CAChF,OAAO,QAAS,2BAA2B,CAC3C,OAAO,UAAW,qBAAqB,CACvC,OAAO,EAAe,CAEzB,EACG,QAAQ,OAAO,CACf,YAAY,2BAA2B,CACvC,OAAO,kBAAmB,sDAAsD,CAChF,OAAO,UAAW,qBAAqB,CACvC,OAAO,EAAY,CAEtB,EAAQ,YAAY,CAAC,MAAO,GAAmB,CAC7C,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CACtE,QAAQ,MAAM,OAAO,IAAU,CAC/B,QAAQ,SAAW,GACnB"}
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'node:fs'\n\nimport { Command } from 'commander'\n\nimport { doneCommand } from './commands/done.js'\nimport { installCommand } from './commands/install.js'\nimport { statusCommand } from './commands/status.js'\nimport { syncCommand } from './commands/sync.js'\nimport { validateCommand } from './commands/validate.js'\n\nconst packageJson = JSON.parse(\n readFileSync(new URL('../package.json', import.meta.url), 'utf8')\n) as { version?: string }\nconst packageVersion = typeof packageJson.version === 'string' ? packageJson.version : '0.0.0'\n\nconst program = new Command()\n\nprogram.name('agent-context').description('Agent Context Skills 安装工具').version(packageVersion)\n\nprogram\n .command('install')\n .description('安装 ac-workflow Skill')\n .option('--tools <tools>', '指定目标工具,逗号分隔:claude,codex,cursor,antigravity,copilot')\n .option('--yes', '非交互模式:优先复用已安装工具,否则安装全部工具')\n .option('--check', '仅检查是否存在待更新内容,不写入文件')\n .action(installCommand)\n\nprogram\n .command('sync')\n .description('同步已安装的 ac-workflow Skill')\n .option('--tools <tools>', '指定目标工具,逗号分隔:claude,codex,cursor,antigravity,copilot')\n .option('--check', '仅检查是否存在待更新内容,不写入文件')\n .action(syncCommand)\n\nprogram\n .command('validate')\n .description('校验 .agent-context 目录结构')\n .action(validateCommand)\n\nprogram\n .command('status')\n .description('查看当前 agent-context 状态')\n .action(statusCommand)\n\nprogram\n .command('done')\n .description('归档当前已执行计划')\n .option('--yes', '跳过确认,直接归档')\n .action(doneCommand)\n\nprogram.parseAsync().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error)\n console.error(`\\n❌ ${message}`) // eslint-disable-line no-console\n process.exitCode = 1\n})\n"],"mappings":";kVAYA,MAAM,EAAc,KAAK,MACvB,EAAa,IAAI,IAAI,kBAAmB,OAAO,KAAK,IAAI,CAAE,OAAO,CAClE,CACK,EAAiB,OAAO,EAAY,SAAY,SAAW,EAAY,QAAU,QAEjF,EAAU,IAAI,EAEpB,EAAQ,KAAK,gBAAgB,CAAC,YAAY,4BAA4B,CAAC,QAAQ,EAAe,CAE9F,EACG,QAAQ,UAAU,CAClB,YAAY,uBAAuB,CACnC,OAAO,kBAAmB,sDAAsD,CAChF,OAAO,QAAS,2BAA2B,CAC3C,OAAO,UAAW,qBAAqB,CACvC,OAAO,EAAe,CAEzB,EACG,QAAQ,OAAO,CACf,YAAY,2BAA2B,CACvC,OAAO,kBAAmB,sDAAsD,CAChF,OAAO,UAAW,qBAAqB,CACvC,OAAO,EAAY,CAEtB,EACG,QAAQ,WAAW,CACnB,YAAY,yBAAyB,CACrC,OAAO,EAAgB,CAE1B,EACG,QAAQ,SAAS,CACjB,YAAY,wBAAwB,CACpC,OAAO,EAAc,CAExB,EACG,QAAQ,OAAO,CACf,YAAY,YAAY,CACxB,OAAO,QAAS,YAAY,CAC5B,OAAO,EAAY,CAEtB,EAAQ,YAAY,CAAC,MAAO,GAAmB,CAC7C,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CACtE,QAAQ,MAAM,OAAO,IAAU,CAC/B,QAAQ,SAAW,GACnB"}
@@ -0,0 +1,2 @@
1
+ import{readRawContext as e}from"../context/reader.js";import{validate as t}from"../context/validator.js";import{archive as n}from"../context/archiver.js";import{basename as r}from"node:path";import{confirm as i}from"@inquirer/prompts";async function a(a){let{snapshot:o,currentPlanCount:s}=await e(process.cwd()),c=t(o,s);if(!c.valid){for(let e of c.errors)console.log(`❌ ${e}`);process.exitCode=1;return}if(!o||!o.currentPlan){console.log(`❌ 无当前计划`),process.exitCode=1;return}if(o.currentPlan.status!==`已执行`){console.log(`❌ 当前计划 plan-${o.currentPlan.number} 尚未执行,无法归档。`),process.exitCode=1;return}if(!a.yes&&!await i({message:`确认归档 plan-${o.currentPlan.number}?`})){console.log(`已取消`);return}let l=await n(o),u=r(l.archivedTo);console.log(`✅ 已归档: plan-${o.currentPlan.number} → done/${u}`),l.promoted!==null&&console.log(`📋 已晋升: plan-${l.promoted} 为新的当前计划`),l.remainingPreparing>0?console.log(`📋 待执行队列剩余 ${l.remainingPreparing} 个计划`):l.promoted===null&&console.log(`ℹ 无更多待执行计划`)}export{a as doneCommand};
2
+ //# sourceMappingURL=done.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"done.js","names":[],"sources":["../../src/commands/done.ts"],"sourcesContent":["import { basename } from 'node:path'\n\nimport { confirm } from '@inquirer/prompts'\n\nimport { archive, readRawContext, validate } from '../context/index.js'\n\nexport async function doneCommand(options: { yes?: boolean }): Promise<void> {\n const { snapshot, currentPlanCount } = await readRawContext(process.cwd())\n const result = validate(snapshot, currentPlanCount)\n\n if (!result.valid) {\n for (const error of result.errors) {\n console.log(`❌ ${error}`) // eslint-disable-line no-console\n }\n process.exitCode = 1\n return\n }\n\n if (!snapshot || !snapshot.currentPlan) {\n console.log('❌ 无当前计划') // eslint-disable-line no-console\n process.exitCode = 1\n return\n }\n\n if (snapshot.currentPlan.status !== '已执行') {\n console.log(`❌ 当前计划 plan-${snapshot.currentPlan.number} 尚未执行,无法归档。`) // eslint-disable-line no-console\n process.exitCode = 1\n return\n }\n\n if (!options.yes) {\n const confirmed = await confirm({\n message: `确认归档 plan-${snapshot.currentPlan.number}?`\n })\n if (!confirmed) {\n console.log('已取消') // eslint-disable-line no-console\n return\n }\n }\n\n const archiveResult = await archive(snapshot)\n const archiveName = basename(archiveResult.archivedTo)\n\n console.log(`✅ 已归档: plan-${snapshot.currentPlan.number} → done/${archiveName}`) // eslint-disable-line no-console\n\n if (archiveResult.promoted !== null) {\n console.log(`📋 已晋升: plan-${archiveResult.promoted} 为新的当前计划`) // eslint-disable-line no-console\n }\n\n if (archiveResult.remainingPreparing > 0) {\n console.log(`📋 待执行队列剩余 ${archiveResult.remainingPreparing} 个计划`) // eslint-disable-line no-console\n } else if (archiveResult.promoted === null) {\n console.log('ℹ 无更多待执行计划') // eslint-disable-line no-console\n }\n}\n"],"mappings":"2OAMA,eAAsB,EAAY,EAA2C,CAC3E,GAAM,CAAE,WAAU,oBAAqB,MAAM,EAAe,QAAQ,KAAK,CAAC,CACpE,EAAS,EAAS,EAAU,EAAiB,CAEnD,GAAI,CAAC,EAAO,MAAO,CACjB,IAAK,IAAM,KAAS,EAAO,OACzB,QAAQ,IAAI,KAAK,IAAQ,CAE3B,QAAQ,SAAW,EACnB,OAGF,GAAI,CAAC,GAAY,CAAC,EAAS,YAAa,CACtC,QAAQ,IAAI,UAAU,CACtB,QAAQ,SAAW,EACnB,OAGF,GAAI,EAAS,YAAY,SAAW,MAAO,CACzC,QAAQ,IAAI,eAAe,EAAS,YAAY,OAAO,aAAa,CACpE,QAAQ,SAAW,EACnB,OAGF,GAAI,CAAC,EAAQ,KAIP,CAHc,MAAM,EAAQ,CAC9B,QAAS,aAAa,EAAS,YAAY,OAAO,GACnD,CAAC,CACc,CACd,QAAQ,IAAI,MAAM,CAClB,OAIJ,IAAM,EAAgB,MAAM,EAAQ,EAAS,CACvC,EAAc,EAAS,EAAc,WAAW,CAEtD,QAAQ,IAAI,eAAe,EAAS,YAAY,OAAO,UAAU,IAAc,CAE3E,EAAc,WAAa,MAC7B,QAAQ,IAAI,gBAAgB,EAAc,SAAS,UAAU,CAG3D,EAAc,mBAAqB,EACrC,QAAQ,IAAI,cAAc,EAAc,mBAAmB,MAAM,CACxD,EAAc,WAAa,MACpC,QAAQ,IAAI,aAAa"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","names":[],"sources":["../../src/commands/install.ts"],"sourcesContent":["import { checkbox } from '@inquirer/prompts'\n\nimport { runInstall } from '../runner'\nimport { DEFAULT_TOOL_ORDER, detectConfiguredToolIds, getToolChoices, parseToolIds } from '../tools'\nimport type { ToolId } from '../types'\nimport { printCheckResult, printRunSummary } from './printer'\n\nexport interface InstallCommandOptions {\n tools?: string\n check?: boolean\n yes?: boolean\n}\n\nexport async function installCommand(options: InstallCommandOptions = {}): Promise<void> {\n const cwd = process.cwd()\n const tools = await resolveTools(cwd, options)\n const check = options.check ?? false\n const result = await runInstall({ cwd, tools, check })\n\n if (check) {\n printCheckResult(result, cwd)\n if (result.changed.length > 0) {\n process.exitCode = 1\n }\n return\n }\n\n printRunSummary(result, cwd)\n}\n\nasync function resolveTools(\n cwd: string,\n options: InstallCommandOptions\n): Promise<ToolId[] | undefined> {\n const raw = options.tools\n\n if (!raw || raw.trim().length === 0) {\n const configuredTools = detectConfiguredToolIds(cwd)\n\n if (options.yes) {\n return configuredTools.length > 0 ? configuredTools : [...DEFAULT_TOOL_ORDER]\n }\n\n return checkbox<ToolId>({\n message: '请选择要安装 ac-workflow Skill 的工具(可多选):',\n choices: getToolChoices().map((tool) => ({\n name: tool.name,\n value: tool.id,\n checked: configuredTools.includes(tool.id)\n })),\n required: true\n })\n }\n\n return parseToolIds(raw)\n}\n"],"mappings":"gRAaA,eAAsB,EAAe,EAAiC,EAAE,CAAiB,CACvF,IAAM,EAAM,QAAQ,KAAK,CACnB,EAAQ,MAAM,EAAa,EAAK,EAAQ,CACxC,EAAQ,EAAQ,OAAS,GACzB,EAAS,MAAM,EAAW,CAAE,MAAK,QAAO,QAAO,CAAC,CAEtD,GAAI,EAAO,CACT,EAAiB,EAAQ,EAAI,CACzB,EAAO,QAAQ,OAAS,IAC1B,QAAQ,SAAW,GAErB,OAGF,EAAgB,EAAQ,EAAI,CAG9B,eAAe,EACb,EACA,EAC+B,CAC/B,IAAM,EAAM,EAAQ,MAEpB,GAAI,CAAC,GAAO,EAAI,MAAM,CAAC,SAAW,EAAG,CACnC,IAAM,EAAkB,EAAwB,EAAI,CAMpD,OAJI,EAAQ,IACH,EAAgB,OAAS,EAAI,EAAkB,CAAC,GAAG,EAAmB,CAGxE,EAAiB,CACtB,QAAS,qCACT,QAAS,GAAgB,CAAC,IAAK,IAAU,CACvC,KAAM,EAAK,KACX,MAAO,EAAK,GACZ,QAAS,EAAgB,SAAS,EAAK,GAAG,CAC3C,EAAE,CACH,SAAU,GACX,CAAC,CAGJ,OAAO,EAAa,EAAI"}
1
+ {"version":3,"file":"install.js","names":[],"sources":["../../src/commands/install.ts"],"sourcesContent":["import { checkbox } from '@inquirer/prompts'\n\nimport { runInstall } from '../runner.js'\nimport { DEFAULT_TOOL_ORDER, detectConfiguredToolIds, getToolChoices, parseToolIds } from '../tools.js'\nimport type { ToolId } from '../types.js'\nimport { printCheckResult, printRunSummary } from './printer.js'\n\nexport interface InstallCommandOptions {\n tools?: string\n check?: boolean\n yes?: boolean\n}\n\nexport async function installCommand(options: InstallCommandOptions = {}): Promise<void> {\n const cwd = process.cwd()\n const tools = await resolveTools(cwd, options)\n const check = options.check ?? false\n const result = await runInstall({ cwd, tools, check })\n\n if (check) {\n printCheckResult(result, cwd)\n if (result.changed.length > 0) {\n process.exitCode = 1\n }\n return\n }\n\n printRunSummary(result, cwd)\n}\n\nasync function resolveTools(\n cwd: string,\n options: InstallCommandOptions\n): Promise<ToolId[] | undefined> {\n const raw = options.tools\n\n if (!raw || raw.trim().length === 0) {\n const configuredTools = detectConfiguredToolIds(cwd)\n\n if (options.yes) {\n return configuredTools.length > 0 ? configuredTools : [...DEFAULT_TOOL_ORDER]\n }\n\n return checkbox<ToolId>({\n message: '请选择要安装 ac-workflow Skill 的工具(可多选):',\n choices: getToolChoices().map((tool) => ({\n name: tool.name,\n value: tool.id,\n checked: configuredTools.includes(tool.id)\n })),\n required: true\n })\n }\n\n return parseToolIds(raw)\n}\n"],"mappings":"gRAaA,eAAsB,EAAe,EAAiC,EAAE,CAAiB,CACvF,IAAM,EAAM,QAAQ,KAAK,CACnB,EAAQ,MAAM,EAAa,EAAK,EAAQ,CACxC,EAAQ,EAAQ,OAAS,GACzB,EAAS,MAAM,EAAW,CAAE,MAAK,QAAO,QAAO,CAAC,CAEtD,GAAI,EAAO,CACT,EAAiB,EAAQ,EAAI,CACzB,EAAO,QAAQ,OAAS,IAC1B,QAAQ,SAAW,GAErB,OAGF,EAAgB,EAAQ,EAAI,CAG9B,eAAe,EACb,EACA,EAC+B,CAC/B,IAAM,EAAM,EAAQ,MAEpB,GAAI,CAAC,GAAO,EAAI,MAAM,CAAC,SAAW,EAAG,CACnC,IAAM,EAAkB,EAAwB,EAAI,CAMpD,OAJI,EAAQ,IACH,EAAgB,OAAS,EAAI,EAAkB,CAAC,GAAG,EAAmB,CAGxE,EAAiB,CACtB,QAAS,qCACT,QAAS,GAAgB,CAAC,IAAK,IAAU,CACvC,KAAM,EAAK,KACX,MAAO,EAAK,GACZ,QAAS,EAAgB,SAAS,EAAK,GAAG,CAC3C,EAAE,CACH,SAAU,GACX,CAAC,CAGJ,OAAO,EAAa,EAAI"}
@@ -1 +1 @@
1
- {"version":3,"file":"printer.js","names":[],"sources":["../../src/commands/printer.ts"],"sourcesContent":["import { relative } from 'node:path'\n\nimport type { RunResult } from '../types'\n\nexport function printRunSummary(result: RunResult, cwd: string): void {\n console.log(`\\n✅ ac-workflow ${result.mode} 完成`) // eslint-disable-line no-console\n\n if (result.created.length > 0) {\n console.log(`\\n新增 ${result.created.length} 个文件:`) // eslint-disable-line no-console\n for (const filePath of result.created) {\n console.log(`- ${relative(cwd, filePath)}`) // eslint-disable-line no-console\n }\n }\n\n if (result.updated.length > 0) {\n console.log(`\\n更新 ${result.updated.length} 个文件:`) // eslint-disable-line no-console\n for (const filePath of result.updated) {\n console.log(`- ${relative(cwd, filePath)}`) // eslint-disable-line no-console\n }\n }\n\n if (result.unchanged.length > 0) {\n console.log(`\\n无变更 ${result.unchanged.length} 个文件`) // eslint-disable-line no-console\n }\n}\n\nexport function printCheckResult(result: RunResult, cwd: string): void {\n if (result.changed.length === 0) {\n console.log('\\n✅ 检查通过:无需更新') // eslint-disable-line no-console\n return\n }\n\n console.log('\\n❌ 检查失败:以下文件需要更新') // eslint-disable-line no-console\n for (const filePath of result.changed) {\n console.log(`- ${relative(cwd, filePath)}`) // eslint-disable-line no-console\n }\n}\n"],"mappings":"qCAIA,SAAgB,EAAgB,EAAmB,EAAmB,CAGpE,GAFA,QAAQ,IAAI,mBAAmB,EAAO,KAAK,KAAK,CAE5C,EAAO,QAAQ,OAAS,EAAG,CAC7B,QAAQ,IAAI,QAAQ,EAAO,QAAQ,OAAO,OAAO,CACjD,IAAK,IAAM,KAAY,EAAO,QAC5B,QAAQ,IAAI,KAAK,EAAS,EAAK,EAAS,GAAG,CAI/C,GAAI,EAAO,QAAQ,OAAS,EAAG,CAC7B,QAAQ,IAAI,QAAQ,EAAO,QAAQ,OAAO,OAAO,CACjD,IAAK,IAAM,KAAY,EAAO,QAC5B,QAAQ,IAAI,KAAK,EAAS,EAAK,EAAS,GAAG,CAI3C,EAAO,UAAU,OAAS,GAC5B,QAAQ,IAAI,SAAS,EAAO,UAAU,OAAO,MAAM,CAIvD,SAAgB,EAAiB,EAAmB,EAAmB,CACrE,GAAI,EAAO,QAAQ,SAAW,EAAG,CAC/B,QAAQ,IAAI;aAAgB,CAC5B,OAGF,QAAQ,IAAI;iBAAoB,CAChC,IAAK,IAAM,KAAY,EAAO,QAC5B,QAAQ,IAAI,KAAK,EAAS,EAAK,EAAS,GAAG"}
1
+ {"version":3,"file":"printer.js","names":[],"sources":["../../src/commands/printer.ts"],"sourcesContent":["import { relative } from 'node:path'\n\nimport type { RunResult } from '../types.js'\n\nexport function printRunSummary(result: RunResult, cwd: string): void {\n console.log(`\\n✅ ac-workflow ${result.mode} 完成`) // eslint-disable-line no-console\n\n if (result.created.length > 0) {\n console.log(`\\n新增 ${result.created.length} 个文件:`) // eslint-disable-line no-console\n for (const filePath of result.created) {\n console.log(`- ${relative(cwd, filePath)}`) // eslint-disable-line no-console\n }\n }\n\n if (result.updated.length > 0) {\n console.log(`\\n更新 ${result.updated.length} 个文件:`) // eslint-disable-line no-console\n for (const filePath of result.updated) {\n console.log(`- ${relative(cwd, filePath)}`) // eslint-disable-line no-console\n }\n }\n\n if (result.unchanged.length > 0) {\n console.log(`\\n无变更 ${result.unchanged.length} 个文件`) // eslint-disable-line no-console\n }\n}\n\nexport function printCheckResult(result: RunResult, cwd: string): void {\n if (result.changed.length === 0) {\n console.log('\\n✅ 检查通过:无需更新') // eslint-disable-line no-console\n return\n }\n\n console.log('\\n❌ 检查失败:以下文件需要更新') // eslint-disable-line no-console\n for (const filePath of result.changed) {\n console.log(`- ${relative(cwd, filePath)}`) // eslint-disable-line no-console\n }\n}\n"],"mappings":"qCAIA,SAAgB,EAAgB,EAAmB,EAAmB,CAGpE,GAFA,QAAQ,IAAI,mBAAmB,EAAO,KAAK,KAAK,CAE5C,EAAO,QAAQ,OAAS,EAAG,CAC7B,QAAQ,IAAI,QAAQ,EAAO,QAAQ,OAAO,OAAO,CACjD,IAAK,IAAM,KAAY,EAAO,QAC5B,QAAQ,IAAI,KAAK,EAAS,EAAK,EAAS,GAAG,CAI/C,GAAI,EAAO,QAAQ,OAAS,EAAG,CAC7B,QAAQ,IAAI,QAAQ,EAAO,QAAQ,OAAO,OAAO,CACjD,IAAK,IAAM,KAAY,EAAO,QAC5B,QAAQ,IAAI,KAAK,EAAS,EAAK,EAAS,GAAG,CAI3C,EAAO,UAAU,OAAS,GAC5B,QAAQ,IAAI,SAAS,EAAO,UAAU,OAAO,MAAM,CAIvD,SAAgB,EAAiB,EAAmB,EAAmB,CACrE,GAAI,EAAO,QAAQ,SAAW,EAAG,CAC/B,QAAQ,IAAI;aAAgB,CAC5B,OAGF,QAAQ,IAAI;iBAAoB,CAChC,IAAK,IAAM,KAAY,EAAO,QAC5B,QAAQ,IAAI,KAAK,EAAS,EAAK,EAAS,GAAG"}
@@ -0,0 +1,2 @@
1
+ import{readRawContext as e}from"../context/reader.js";import{validate as t}from"../context/validator.js";async function n(){let{snapshot:n,currentPlanCount:r}=await e(process.cwd()),i=t(n,r);if(!i.valid){for(let e of i.errors)console.log(`❌ ${e}`);process.exitCode=1;return}if(i.context===null){console.log(`ℹ 无活跃上下文`);return}let a=i.context,o=a.currentPlan?`plan-${a.currentPlan.number} (${a.currentPlan.status})`:`无`,s=a.preparing.length>0?a.preparing.map(e=>`plan-${e.number}`).join(`, `):`无`;console.log(``),console.log(`Agent Context Status`),console.log(`────────────────────`),console.log(`当前计划: ${o}`),console.log(`待执行队列: ${s}`),console.log(`已归档: ${a.doneCount} 个`)}export{n as statusCommand};
2
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","names":[],"sources":["../../src/commands/status.ts"],"sourcesContent":["import { readRawContext, validate } from '../context/index.js'\n\nexport async function statusCommand(): Promise<void> {\n const { snapshot, currentPlanCount } = await readRawContext(process.cwd())\n const result = validate(snapshot, currentPlanCount)\n\n if (!result.valid) {\n for (const error of result.errors) {\n console.log(`❌ ${error}`) // eslint-disable-line no-console\n }\n process.exitCode = 1\n return\n }\n\n if (result.context === null) {\n console.log('ℹ 无活跃上下文') // eslint-disable-line no-console\n return\n }\n\n const ctx = result.context\n const current = ctx.currentPlan\n ? `plan-${ctx.currentPlan.number} (${ctx.currentPlan.status})`\n : '无'\n const preparing =\n ctx.preparing.length > 0\n ? ctx.preparing.map((p) => `plan-${p.number}`).join(', ')\n : '无'\n\n console.log('') // eslint-disable-line no-console\n console.log('Agent Context Status') // eslint-disable-line no-console\n console.log('────────────────────') // eslint-disable-line no-console\n console.log(`当前计划: ${current}`) // eslint-disable-line no-console\n console.log(`待执行队列: ${preparing}`) // eslint-disable-line no-console\n console.log(`已归档: ${ctx.doneCount} 个`) // eslint-disable-line no-console\n}\n"],"mappings":"yGAEA,eAAsB,GAA+B,CACnD,GAAM,CAAE,WAAU,oBAAqB,MAAM,EAAe,QAAQ,KAAK,CAAC,CACpE,EAAS,EAAS,EAAU,EAAiB,CAEnD,GAAI,CAAC,EAAO,MAAO,CACjB,IAAK,IAAM,KAAS,EAAO,OACzB,QAAQ,IAAI,KAAK,IAAQ,CAE3B,QAAQ,SAAW,EACnB,OAGF,GAAI,EAAO,UAAY,KAAM,CAC3B,QAAQ,IAAI,WAAW,CACvB,OAGF,IAAM,EAAM,EAAO,QACb,EAAU,EAAI,YAChB,QAAQ,EAAI,YAAY,OAAO,IAAI,EAAI,YAAY,OAAO,GAC1D,IACE,EACJ,EAAI,UAAU,OAAS,EACnB,EAAI,UAAU,IAAK,GAAM,QAAQ,EAAE,SAAS,CAAC,KAAK,KAAK,CACvD,IAEN,QAAQ,IAAI,GAAG,CACf,QAAQ,IAAI,uBAAuB,CACnC,QAAQ,IAAI,uBAAuB,CACnC,QAAQ,IAAI,UAAU,IAAU,CAChC,QAAQ,IAAI,UAAU,IAAY,CAClC,QAAQ,IAAI,WAAW,EAAI,UAAU,IAAI"}
@@ -1 +1 @@
1
- {"version":3,"file":"sync.js","names":[],"sources":["../../src/commands/sync.ts"],"sourcesContent":["import { detectConfiguredToolIds, parseToolIds } from '../tools'\nimport type { ToolId } from '../types'\nimport { runSync } from '../runner'\nimport { printCheckResult, printRunSummary } from './printer'\n\nexport interface SyncCommandOptions {\n tools?: string\n check?: boolean\n}\n\nexport async function syncCommand(options: SyncCommandOptions = {}): Promise<void> {\n const cwd = process.cwd()\n const tools = resolveTools(cwd, options.tools)\n const check = options.check ?? false\n const result = await runSync({ cwd, tools, check })\n\n if (check) {\n printCheckResult(result, cwd)\n if (result.changed.length > 0) {\n process.exitCode = 1\n }\n return\n }\n\n printRunSummary(result, cwd)\n}\n\nfunction resolveTools(cwd: string, raw?: string): ToolId[] | undefined {\n if (!raw || raw.trim().length === 0) {\n const configuredTools = detectConfiguredToolIds(cwd)\n\n if (configuredTools.length > 0) {\n return configuredTools\n }\n\n throw new Error('未检测到已安装的 Skill,请先执行 install 或通过 --tools 显式指定工具')\n }\n\n return parseToolIds(raw)\n}\n"],"mappings":"oLAUA,eAAsB,EAAY,EAA8B,EAAE,CAAiB,CACjF,IAAM,EAAM,QAAQ,KAAK,CACnB,EAAQ,EAAa,EAAK,EAAQ,MAAM,CACxC,EAAQ,EAAQ,OAAS,GACzB,EAAS,MAAM,EAAQ,CAAE,MAAK,QAAO,QAAO,CAAC,CAEnD,GAAI,EAAO,CACT,EAAiB,EAAQ,EAAI,CACzB,EAAO,QAAQ,OAAS,IAC1B,QAAQ,SAAW,GAErB,OAGF,EAAgB,EAAQ,EAAI,CAG9B,SAAS,EAAa,EAAa,EAAoC,CACrE,GAAI,CAAC,GAAO,EAAI,MAAM,CAAC,SAAW,EAAG,CACnC,IAAM,EAAkB,EAAwB,EAAI,CAEpD,GAAI,EAAgB,OAAS,EAC3B,OAAO,EAGT,MAAU,MAAM,iDAAiD,CAGnE,OAAO,EAAa,EAAI"}
1
+ {"version":3,"file":"sync.js","names":[],"sources":["../../src/commands/sync.ts"],"sourcesContent":["import { detectConfiguredToolIds, parseToolIds } from '../tools.js'\nimport type { ToolId } from '../types.js'\nimport { runSync } from '../runner.js'\nimport { printCheckResult, printRunSummary } from './printer.js'\n\nexport interface SyncCommandOptions {\n tools?: string\n check?: boolean\n}\n\nexport async function syncCommand(options: SyncCommandOptions = {}): Promise<void> {\n const cwd = process.cwd()\n const tools = resolveTools(cwd, options.tools)\n const check = options.check ?? false\n const result = await runSync({ cwd, tools, check })\n\n if (check) {\n printCheckResult(result, cwd)\n if (result.changed.length > 0) {\n process.exitCode = 1\n }\n return\n }\n\n printRunSummary(result, cwd)\n}\n\nfunction resolveTools(cwd: string, raw?: string): ToolId[] | undefined {\n if (!raw || raw.trim().length === 0) {\n const configuredTools = detectConfiguredToolIds(cwd)\n\n if (configuredTools.length > 0) {\n return configuredTools\n }\n\n throw new Error('未检测到已安装的 Skill,请先执行 install 或通过 --tools 显式指定工具')\n }\n\n return parseToolIds(raw)\n}\n"],"mappings":"oLAUA,eAAsB,EAAY,EAA8B,EAAE,CAAiB,CACjF,IAAM,EAAM,QAAQ,KAAK,CACnB,EAAQ,EAAa,EAAK,EAAQ,MAAM,CACxC,EAAQ,EAAQ,OAAS,GACzB,EAAS,MAAM,EAAQ,CAAE,MAAK,QAAO,QAAO,CAAC,CAEnD,GAAI,EAAO,CACT,EAAiB,EAAQ,EAAI,CACzB,EAAO,QAAQ,OAAS,IAC1B,QAAQ,SAAW,GAErB,OAGF,EAAgB,EAAQ,EAAI,CAG9B,SAAS,EAAa,EAAa,EAAoC,CACrE,GAAI,CAAC,GAAO,EAAI,MAAM,CAAC,SAAW,EAAG,CACnC,IAAM,EAAkB,EAAwB,EAAI,CAEpD,GAAI,EAAgB,OAAS,EAC3B,OAAO,EAGT,MAAU,MAAM,iDAAiD,CAGnE,OAAO,EAAa,EAAI"}
@@ -0,0 +1,2 @@
1
+ import{readRawContext as e}from"../context/reader.js";import{validate as t}from"../context/validator.js";async function n(){let{snapshot:n,currentPlanCount:r}=await e(process.cwd()),i=t(n,r);if(i.context===null){console.log(`ℹ 无 .agent-context 目录`);return}if(i.valid){console.log(`✅ 校验通过`);let e=i.context,t=e.currentPlan?`plan-${e.currentPlan.number} (${e.currentPlan.status})`:`无`;console.log(` 当前计划: ${t}`),console.log(` 待执行: ${e.preparing.length} 个`),console.log(` 已归档: ${e.doneCount} 个`);return}for(let e of i.errors)console.log(`❌ ${e}`);process.exitCode=1}export{n as validateCommand};
2
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","names":[],"sources":["../../src/commands/validate.ts"],"sourcesContent":["import { readRawContext, validate } from '../context/index.js'\n\nexport async function validateCommand(): Promise<void> {\n const { snapshot, currentPlanCount } = await readRawContext(process.cwd())\n const result = validate(snapshot, currentPlanCount)\n\n if (result.context === null) {\n console.log('ℹ 无 .agent-context 目录') // eslint-disable-line no-console\n return\n }\n\n if (result.valid) {\n console.log('✅ 校验通过') // eslint-disable-line no-console\n const ctx = result.context\n const current = ctx.currentPlan\n ? `plan-${ctx.currentPlan.number} (${ctx.currentPlan.status})`\n : '无'\n console.log(` 当前计划: ${current}`) // eslint-disable-line no-console\n console.log(` 待执行: ${ctx.preparing.length} 个`) // eslint-disable-line no-console\n console.log(` 已归档: ${ctx.doneCount} 个`) // eslint-disable-line no-console\n return\n }\n\n for (const error of result.errors) {\n console.log(`❌ ${error}`) // eslint-disable-line no-console\n }\n process.exitCode = 1\n}\n"],"mappings":"yGAEA,eAAsB,GAAiC,CACrD,GAAM,CAAE,WAAU,oBAAqB,MAAM,EAAe,QAAQ,KAAK,CAAC,CACpE,EAAS,EAAS,EAAU,EAAiB,CAEnD,GAAI,EAAO,UAAY,KAAM,CAC3B,QAAQ,IAAI,wBAAwB,CACpC,OAGF,GAAI,EAAO,MAAO,CAChB,QAAQ,IAAI,SAAS,CACrB,IAAM,EAAM,EAAO,QACb,EAAU,EAAI,YAChB,QAAQ,EAAI,YAAY,OAAO,IAAI,EAAI,YAAY,OAAO,GAC1D,IACJ,QAAQ,IAAI,WAAW,IAAU,CACjC,QAAQ,IAAI,UAAU,EAAI,UAAU,OAAO,IAAI,CAC/C,QAAQ,IAAI,UAAU,EAAI,UAAU,IAAI,CACxC,OAGF,IAAK,IAAM,KAAS,EAAO,OACzB,QAAQ,IAAI,KAAK,IAAQ,CAE3B,QAAQ,SAAW"}
@@ -1,4 +1,4 @@
1
- const e=[`init`,`plan`,`replan`,`implement`,`patch`,`done`],t={init:n,plan:r,replan:i,implement:a,patch:o,done:s};function n(){return`# init
1
+ const e=[`init`,`plan`,`replan`,`implement`,`patch`,`rush`],t={init:n,plan:r,replan:i,implement:a,patch:o,rush:s};function n(){return`# init
2
2
 
3
3
  初始化项目的 Agent Context 上下文。根据新旧项目类型处理 \`AGENTS.md\`,新项目会自动进入计划创建流程。
4
4
 
@@ -39,8 +39,9 @@ const e=[`init`,`plan`,`replan`,`implement`,`patch`,`done`],t={init:n,plan:r,rep
39
39
 
40
40
  ## 前置检查
41
41
 
42
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
42
43
  - 描述为空 → 拒绝执行。
43
- - 存在未归档的已执行当前计划 → 拒绝执行,提示先归档。
44
+ - 存在未归档的已执行当前计划 → 拒绝执行,提示先运行 \`agent-context done\` 归档。
44
45
  - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
45
46
 
46
47
  ## 执行步骤
@@ -88,6 +89,7 @@ const e=[`init`,`plan`,`replan`,`implement`,`patch`,`done`],t={init:n,plan:r,rep
88
89
 
89
90
  ## 前置检查
90
91
 
92
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
91
93
  - 描述为空 → 拒绝执行。
92
94
  - 无未实施计划 → 拒绝执行,提示使用 plan 创建。
93
95
  - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
@@ -108,7 +110,7 @@ const e=[`init`,`plan`,`replan`,`implement`,`patch`,`done`],t={init:n,plan:r,rep
108
110
  3. 生成新的拆分方案,保持「单当前计划 + 若干 preparing 计划」结构。
109
111
  4. 新增计划编号:全局 max(N)+1 递增分配;未改动计划保持原编号。
110
112
  5. 更新目录结构,确保每个新计划的 \`plan.md\` 遵循标准模板。
111
- `}function a(){return"# implement\n\n实施当前计划 `.agent-context/plan-{number}/plan.md` 中的全部步骤,通过验证循环后将状态更新为「已执行」。\n\n不接受额外描述。\n\n## 前置检查\n\n- 带描述 → 拒绝执行。\n- 当前计划不存在 → 拒绝执行,提示先创建计划。\n- 当前计划状态为 `已执行` → 拒绝执行,提示使用 patch 或归档。\n- `## 目标` 或 `## 内容` 为空 → 拒绝执行,提示补充。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 仅操作当前计划,不直接操作 `preparing/` 中的计划。\n- 遇到阻塞问题应向用户报告,不可静默跳过。\n\n## 执行步骤\n\n1. 读取当前计划 `plan.md`,理解 `## 目标` 与 `## 内容`。\n2. 依据 `## 内容` 中的步骤逐项实施。\n3. **验证循环**(全部通过前不可进入步骤 4):\n a. 逐项对照 `## 内容` 确认每个步骤已实施。\n b. 运行项目验证:类型检查 → lint → 测试。\n c. 若存在失败项 → 修复后回到 a 重新验证。\n d. 全部通过 → 进入步骤 4。\n4. 更新 `plan.md` 状态行:`> 状态: 未执行` → `> 状态: 已执行`。\n5. 更新 `## 影响范围`,记录所有变更文件。\n"}function o(){return`# patch
113
+ `}function a(){return"# implement\n\n实施当前计划 `.agent-context/plan-{number}/plan.md` 中的全部步骤,通过验证循环后将状态更新为「已执行」。\n\n不接受额外描述。\n\n## 前置检查\n\n- 运行 `agent-context validate`,不通过则中止并报告错误。\n- 带描述 → 拒绝执行。\n- 当前计划不存在 → 拒绝执行,提示先创建计划。\n- 当前计划状态为 `已执行` → 拒绝执行,提示使用 patch 修补或运行 `agent-context done` 归档。\n- `## 目标` 或 `## 内容` 为空 → 拒绝执行,提示补充。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 仅操作当前计划,不直接操作 `preparing/` 中的计划。\n- 遇到阻塞问题应向用户报告,不可静默跳过。\n\n## 执行步骤\n\n1. 读取当前计划 `plan.md`,理解 `## 目标` 与 `## 内容`。\n2. 依据 `## 内容` 中的步骤逐项实施。\n3. **验证循环**(全部通过前不可进入步骤 4):\n a. 逐项对照 `## 内容` 确认每个步骤已实施。\n b. 运行项目验证:类型检查 → lint → 测试。\n c. 若存在失败项 → 修复后回到 a 重新验证。\n d. 全部通过 → 进入步骤 4。\n4. 更新 `plan.md` 状态行:`> 状态: 未执行` → `> 状态: 已执行`。\n5. 更新 `## 影响范围`,记录所有变更文件。\n"}function o(){return`# patch
112
114
 
113
115
  基于当前已执行计划创建增量补丁,修复问题或追加变更。
114
116
 
@@ -116,6 +118,7 @@ const e=[`init`,`plan`,`replan`,`implement`,`patch`,`done`],t={init:n,plan:r,rep
116
118
 
117
119
  ## 前置检查
118
120
 
121
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
119
122
  - 描述为空 → 拒绝执行。
120
123
  - 当前计划不存在 → 拒绝执行,提示先创建计划。
121
124
  - 当前计划状态为 \`未执行\` → 拒绝执行,提示先实施。
@@ -147,26 +150,28 @@ const e=[`init`,`plan`,`replan`,`implement`,`patch`,`done`],t={init:n,plan:r,rep
147
150
  - 修改文件: \`/path/to/file\`
148
151
  - 删除文件: \`/path/to/file\`
149
152
  \`\`\`
150
- `}function s(){return`# done
153
+ `}function s(){return`# rush
151
154
 
152
- 确认当前已执行计划真正完成,归档到 \`.agent-context/done/\` 目录,并自动晋升下一个计划。
155
+ 快速通道:创建计划并立即实施,适合范围明确、无需多轮规划的任务。
153
156
 
154
- 不接受额外描述。
157
+ 必须附带任务描述。
155
158
 
156
159
  ## 前置检查
157
160
 
158
- - 带描述 拒绝执行。
159
- - 当前计划不存在拒绝执行,提示先创建计划。
160
- - 当前计划状态为 \`未执行\` 拒绝执行,提示先实施。
161
- - 存在多个当前计划拒绝执行,提示恢复单活跃状态。
162
- - 必须得到用户确认后才可归档。
161
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
162
+ - 描述为空拒绝执行。
163
+ - 存在未归档的已执行当前计划拒绝执行,提示先运行 \`agent-context done\` 归档。
164
+ - 存在未实施的当前计划拒绝执行,提示先 implement 或 replan。
163
165
 
164
166
  ## 执行步骤
165
167
 
166
- 1. **用户确认**:向用户确认当前计划已真正完成。
167
- 2. **归档**:将 \`.agent-context/plan-{number}\` 移动到 \`.agent-context/done/plan-{number}-{YYYYMMDD}\`(当日日期),包含完整 \`plan.md\` 与所有 \`patch-{number}.md\`。
168
- 3. **晋升**:若 \`.agent-context/preparing/\` 非空,将最小编号计划移至 \`.agent-context/\` 作为新当前计划。
169
- 4. **校验**:确认归档完整,晋升后仍满足单当前计划约束;失败则回滚。
170
- 5. **反馈**:报告归档路径、是否晋升及晋升编号、是否还有待执行计划。
168
+ 1. 按 plan 协议创建单计划(不拆分,不进入 preparing 队列)。
169
+ 2. 无需用户确认计划内容,直接进入 implement 流程。
170
+ 3. implement 协议执行全部步骤,包括验证循环:
171
+ a. 逐项对照 \`## 内容\` 确认每个步骤已实施。
172
+ b. 运行项目验证:类型检查 → lint → 测试。
173
+ c. 若存在失败项 → 修复后重新验证。
174
+ d. 全部通过 → 进入步骤 4。
175
+ 4. 更新 \`plan.md\` 状态行为 \`已执行\`,更新 \`## 影响范围\`。
171
176
  `}export{e as ACTION_NAMES,t as ACTION_RENDERERS};
172
177
  //# sourceMappingURL=actions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","names":[],"sources":["../../src/content/actions.ts"],"sourcesContent":["export const ACTION_NAMES = ['init', 'plan', 'replan', 'implement', 'patch', 'done'] as const\ntype ActionName = (typeof ACTION_NAMES)[number]\n\nexport const ACTION_RENDERERS: Record<ActionName, () => string> = {\n init: renderInit,\n plan: renderPlan,\n replan: renderReplan,\n implement: renderImplement,\n patch: renderPatch,\n done: renderDone\n}\n\nfunction renderInit(): string {\n return `# init\n\n初始化项目的 Agent Context 上下文。根据新旧项目类型处理 \\`AGENTS.md\\`,新项目会自动进入计划创建流程。\n\n可附带描述参数,用于补充项目背景、技术栈、特殊约束。\n\n## 执行步骤\n\n1. **判断项目类型**:检测根目录是否存在有效代码文件和目录结构。\n - 新项目:无实质代码,或用户明确说明是新项目。\n - 旧项目:已有代码、配置文件和目录结构。\n - 无法判断 → 向用户提问澄清,不可假设。\n\n2. **处理 AGENTS.md**:\n - 新项目:\n 1. 通过提问澄清以下要点(已从描述中获取的可跳过):项目目标与核心功能、技术栈与版本、代码规范与工具链(lint/formatter/测试)、目录结构偏好。\n 2. 生成高质量 \\`AGENTS.md\\`(须满足下方质量标准,不满足则重新优化直至满足)。\n 3. 继续执行 plan 创建初始计划。\n - 旧项目:\n 1. 若不存在 \\`AGENTS.md\\`:通过提问与代码阅读收集信息后生成。\n 2. 若已存在 \\`AGENTS.md\\`:按质量标准评估,不足时增补优化。\n 3. 默认不创建计划(除非用户明确要求)。\n\n3. **输出反馈**:向用户报告项目类型判定结果、AGENTS.md 处理结果、是否需要后续计划。\n\n## 高质量 AGENTS.md 标准\n\n- 常用命令与约束前置,降低代理执行歧义。\n- 明确列出目录结构(至少到第二层)。\n- 明确标注技术栈及版本。\n- 明确代码风格约束(命名规范、格式化工具、lint 配置)。\n- 内容精简,无冗余段落或模板化填充。\n- 大型单体仓库按子包拆分维护本地 \\`AGENTS.md\\`。\n`\n}\n\nfunction renderPlan(): string {\n return `# plan\n\n创建新的执行计划,写入 \\`.agent-context/plan-{number}/plan.md\\`。按复杂度可拆分为多个计划,维护「单当前计划 + preparing 队列」结构。\n\n必须附带计划描述。\n\n## 前置检查\n\n- 描述为空 → 拒绝执行。\n- 存在未归档的已执行当前计划 → 拒绝执行,提示先归档。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n\n## 执行步骤\n\n1. **需求澄清**(存在以下任一歧义时必须提问,否则跳到步骤 2):\n - 范围边界不清:无法判定影响哪些文件或模块。\n - 存在显著不同的技术路径需用户决策。\n - 验收标准不明确:无法判断何时算\"完成\"。\n2. 按复杂度决定单计划或多计划拆分。\n3. 多计划拆分时:最小编号进入 \\`.agent-context/\\` 作为当前计划,其余进入 \\`.agent-context/preparing/\\`。单计划直接创建。\n4. 每个计划创建 \\`plan.md\\`,遵循下方模板。\n5. **自检**(不通过则修改后重新检查):\n - 每个步骤可独立执行且有明确完成标准。\n - 不存在过度拆分或拆分不足。\n - 影响范围可预估。\n\n## plan.md 模板\n\n\\`\\`\\`markdown\n# {计划名称}\n\n> 状态: 未执行\n\n## 目标\n\n{明确的目标描述}\n\n## 内容\n\n{详细的实施步骤}\n\n## 影响范围\n\n## 历史补丁\n\\`\\`\\`\n\n- 状态行唯一,仅允许 \\`未执行\\` 或 \\`已执行\\`。\n- \\`## 目标\\` 与 \\`## 内容\\` 不可为空。\n- \\`## 影响范围\\` 与 \\`## 历史补丁\\` 创建时留空,后续由 implement 和 patch 写入。\n`\n}\n\nfunction renderReplan(): string {\n return `# replan\n\n重新规划已有的未实施计划,保持「单当前计划 + preparing 队列」结构不变。\n\n必须附带重规划描述。\n\n## 前置检查\n\n- 描述为空 → 拒绝执行。\n- 无未实施计划 → 拒绝执行,提示使用 plan 创建。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 目标计划编号不存在 → 拒绝执行,列出可选编号。\n- 目标计划已执行 → 拒绝执行,提示使用 patch。\n\n## 作用域\n\n- 默认作用域:\\`.agent-context/preparing/\\` 中全部未实施计划。\n- 可通过描述指定仅重规划部分计划(如\"重规划 plan-3 和 plan-5\")。\n- 当前计划为 \\`已执行\\` → 禁止重写,仅允许重规划 \\`preparing/\\` 队列。\n- 当前计划为 \\`未执行\\` 且用户明确要求 → 可纳入重规划范围。\n\n## 执行步骤\n\n1. 解析描述,确定重规划目标范围。\n2. 读取目标计划 \\`plan.md\\`,理解现有意图。\n3. 生成新的拆分方案,保持「单当前计划 + 若干 preparing 计划」结构。\n4. 新增计划编号:全局 max(N)+1 递增分配;未改动计划保持原编号。\n5. 更新目录结构,确保每个新计划的 \\`plan.md\\` 遵循标准模板。\n`\n}\n\nfunction renderImplement(): string {\n return `# implement\n\n实施当前计划 \\`.agent-context/plan-{number}/plan.md\\` 中的全部步骤,通过验证循环后将状态更新为「已执行」。\n\n不接受额外描述。\n\n## 前置检查\n\n- 带描述 → 拒绝执行。\n- 当前计划不存在 → 拒绝执行,提示先创建计划。\n- 当前计划状态为 \\`已执行\\` → 拒绝执行,提示使用 patch 或归档。\n- \\`## 目标\\` 或 \\`## 内容\\` 为空 → 拒绝执行,提示补充。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 仅操作当前计划,不直接操作 \\`preparing/\\` 中的计划。\n- 遇到阻塞问题应向用户报告,不可静默跳过。\n\n## 执行步骤\n\n1. 读取当前计划 \\`plan.md\\`,理解 \\`## 目标\\` 与 \\`## 内容\\`。\n2. 依据 \\`## 内容\\` 中的步骤逐项实施。\n3. **验证循环**(全部通过前不可进入步骤 4):\n a. 逐项对照 \\`## 内容\\` 确认每个步骤已实施。\n b. 运行项目验证:类型检查 → lint → 测试。\n c. 若存在失败项 → 修复后回到 a 重新验证。\n d. 全部通过 → 进入步骤 4。\n4. 更新 \\`plan.md\\` 状态行:\\`> 状态: 未执行\\` → \\`> 状态: 已执行\\`。\n5. 更新 \\`## 影响范围\\`,记录所有变更文件。\n`\n}\n\nfunction renderPatch(): string {\n return `# patch\n\n基于当前已执行计划创建增量补丁,修复问题或追加变更。\n\n必须附带补丁描述。\n\n## 前置检查\n\n- 描述为空 → 拒绝执行。\n- 当前计划不存在 → 拒绝执行,提示先创建计划。\n- 当前计划状态为 \\`未执行\\` → 拒绝执行,提示先实施。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 补丁不改变计划状态,完成后保持 \\`已执行\\`。\n\n## 执行步骤\n\n1. 阅读 \\`plan.md\\` 与已有 \\`patch-{number}.md\\`,了解上下文与历史,避免重复修复。\n2. 根据描述执行补丁所需的代码变更。\n3. 完成必要验证(测试、类型检查等)。\n4. 创建 \\`patch-{number}.md\\`(编号:扫描当前计划目录已有补丁取 max+1),遵循下方模板。\n5. 回写 \\`plan.md\\`:\n - \\`## 历史补丁\\`:追加 \\`- patch-{number}: {补丁名称}\\`,按编号去重。\n - \\`## 影响范围\\`:合并本次变更路径,按路径去重。\n\n## patch.md 模板\n\n\\`\\`\\`markdown\n# {补丁名称}\n\n## 补丁内容\n\n{修改了什么、为什么修改}\n\n## 影响范围\n\n- 新增文件: \\`/path/to/file\\`\n- 修改文件: \\`/path/to/file\\`\n- 删除文件: \\`/path/to/file\\`\n\\`\\`\\`\n`\n}\n\nfunction renderDone(): string {\n return `# done\n\n确认当前已执行计划真正完成,归档到 \\`.agent-context/done/\\` 目录,并自动晋升下一个计划。\n\n不接受额外描述。\n\n## 前置检查\n\n- 带描述 拒绝执行。\n- 当前计划不存在拒绝执行,提示先创建计划。\n- 当前计划状态为 \\`未执行\\` 拒绝执行,提示先实施。\n- 存在多个当前计划拒绝执行,提示恢复单活跃状态。\n- 必须得到用户确认后才可归档。\n\n## 执行步骤\n\n1. **用户确认**:向用户确认当前计划已真正完成。\n2. **归档**:将 \\`.agent-context/plan-{number}\\` 移动到 \\`.agent-context/done/plan-{number}-{YYYYMMDD}\\`(当日日期),包含完整 \\`plan.md\\` 与所有 \\`patch-{number}.md\\`。\n3. **晋升**:若 \\`.agent-context/preparing/\\` 非空,将最小编号计划移至 \\`.agent-context/\\` 作为新当前计划。\n4. **校验**:确认归档完整,晋升后仍满足单当前计划约束;失败则回滚。\n5. **反馈**:报告归档路径、是否晋升及晋升编号、是否还有待执行计划。\n`\n}\n"],"mappings":"AAAA,MAAa,EAAe,CAAC,OAAQ,OAAQ,SAAU,YAAa,QAAS,OAAO,CAGvE,EAAqD,CAChE,KAAM,EACN,KAAM,EACN,OAAQ,EACR,UAAW,EACX,MAAO,EACP,KAAM,EACP,CAED,SAAS,GAAqB,CAC5B,MAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCT,SAAS,GAAqB,CAC5B,MAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoDT,SAAS,GAAuB,CAC9B,MAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BT,SAAS,GAA0B,CACjC,MAAO,knBA8BT,SAAS,GAAsB,CAC7B,MAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0CT,SAAS,GAAqB,CAC5B,MAAO"}
1
+ {"version":3,"file":"actions.js","names":[],"sources":["../../src/content/actions.ts"],"sourcesContent":["export const ACTION_NAMES = ['init', 'plan', 'replan', 'implement', 'patch', 'rush'] as const\ntype ActionName = (typeof ACTION_NAMES)[number]\n\nexport const ACTION_RENDERERS: Record<ActionName, () => string> = {\n init: renderInit,\n plan: renderPlan,\n replan: renderReplan,\n implement: renderImplement,\n patch: renderPatch,\n rush: renderRush\n}\n\nfunction renderInit(): string {\n return `# init\n\n初始化项目的 Agent Context 上下文。根据新旧项目类型处理 \\`AGENTS.md\\`,新项目会自动进入计划创建流程。\n\n可附带描述参数,用于补充项目背景、技术栈、特殊约束。\n\n## 执行步骤\n\n1. **判断项目类型**:检测根目录是否存在有效代码文件和目录结构。\n - 新项目:无实质代码,或用户明确说明是新项目。\n - 旧项目:已有代码、配置文件和目录结构。\n - 无法判断 → 向用户提问澄清,不可假设。\n\n2. **处理 AGENTS.md**:\n - 新项目:\n 1. 通过提问澄清以下要点(已从描述中获取的可跳过):项目目标与核心功能、技术栈与版本、代码规范与工具链(lint/formatter/测试)、目录结构偏好。\n 2. 生成高质量 \\`AGENTS.md\\`(须满足下方质量标准,不满足则重新优化直至满足)。\n 3. 继续执行 plan 创建初始计划。\n - 旧项目:\n 1. 若不存在 \\`AGENTS.md\\`:通过提问与代码阅读收集信息后生成。\n 2. 若已存在 \\`AGENTS.md\\`:按质量标准评估,不足时增补优化。\n 3. 默认不创建计划(除非用户明确要求)。\n\n3. **输出反馈**:向用户报告项目类型判定结果、AGENTS.md 处理结果、是否需要后续计划。\n\n## 高质量 AGENTS.md 标准\n\n- 常用命令与约束前置,降低代理执行歧义。\n- 明确列出目录结构(至少到第二层)。\n- 明确标注技术栈及版本。\n- 明确代码风格约束(命名规范、格式化工具、lint 配置)。\n- 内容精简,无冗余段落或模板化填充。\n- 大型单体仓库按子包拆分维护本地 \\`AGENTS.md\\`。\n`\n}\n\nfunction renderPlan(): string {\n return `# plan\n\n创建新的执行计划,写入 \\`.agent-context/plan-{number}/plan.md\\`。按复杂度可拆分为多个计划,维护「单当前计划 + preparing 队列」结构。\n\n必须附带计划描述。\n\n## 前置检查\n\n- 运行 \\`agent-context validate\\`,不通过则中止并报告错误。\n- 描述为空 → 拒绝执行。\n- 存在未归档的已执行当前计划 → 拒绝执行,提示先运行 \\`agent-context done\\` 归档。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n\n## 执行步骤\n\n1. **需求澄清**(存在以下任一歧义时必须提问,否则跳到步骤 2):\n - 范围边界不清:无法判定影响哪些文件或模块。\n - 存在显著不同的技术路径需用户决策。\n - 验收标准不明确:无法判断何时算\"完成\"。\n2. 按复杂度决定单计划或多计划拆分。\n3. 多计划拆分时:最小编号进入 \\`.agent-context/\\` 作为当前计划,其余进入 \\`.agent-context/preparing/\\`。单计划直接创建。\n4. 每个计划创建 \\`plan.md\\`,遵循下方模板。\n5. **自检**(不通过则修改后重新检查):\n - 每个步骤可独立执行且有明确完成标准。\n - 不存在过度拆分或拆分不足。\n - 影响范围可预估。\n\n## plan.md 模板\n\n\\`\\`\\`markdown\n# {计划名称}\n\n> 状态: 未执行\n\n## 目标\n\n{明确的目标描述}\n\n## 内容\n\n{详细的实施步骤}\n\n## 影响范围\n\n## 历史补丁\n\\`\\`\\`\n\n- 状态行唯一,仅允许 \\`未执行\\` 或 \\`已执行\\`。\n- \\`## 目标\\` 与 \\`## 内容\\` 不可为空。\n- \\`## 影响范围\\` 与 \\`## 历史补丁\\` 创建时留空,后续由 implement 和 patch 写入。\n`\n}\n\nfunction renderReplan(): string {\n return `# replan\n\n重新规划已有的未实施计划,保持「单当前计划 + preparing 队列」结构不变。\n\n必须附带重规划描述。\n\n## 前置检查\n\n- 运行 \\`agent-context validate\\`,不通过则中止并报告错误。\n- 描述为空 → 拒绝执行。\n- 无未实施计划 → 拒绝执行,提示使用 plan 创建。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 目标计划编号不存在 → 拒绝执行,列出可选编号。\n- 目标计划已执行 → 拒绝执行,提示使用 patch。\n\n## 作用域\n\n- 默认作用域:\\`.agent-context/preparing/\\` 中全部未实施计划。\n- 可通过描述指定仅重规划部分计划(如\"重规划 plan-3 和 plan-5\")。\n- 当前计划为 \\`已执行\\` → 禁止重写,仅允许重规划 \\`preparing/\\` 队列。\n- 当前计划为 \\`未执行\\` 且用户明确要求 → 可纳入重规划范围。\n\n## 执行步骤\n\n1. 解析描述,确定重规划目标范围。\n2. 读取目标计划 \\`plan.md\\`,理解现有意图。\n3. 生成新的拆分方案,保持「单当前计划 + 若干 preparing 计划」结构。\n4. 新增计划编号:全局 max(N)+1 递增分配;未改动计划保持原编号。\n5. 更新目录结构,确保每个新计划的 \\`plan.md\\` 遵循标准模板。\n`\n}\n\nfunction renderImplement(): string {\n return `# implement\n\n实施当前计划 \\`.agent-context/plan-{number}/plan.md\\` 中的全部步骤,通过验证循环后将状态更新为「已执行」。\n\n不接受额外描述。\n\n## 前置检查\n\n- 运行 \\`agent-context validate\\`,不通过则中止并报告错误。\n- 带描述 → 拒绝执行。\n- 当前计划不存在 → 拒绝执行,提示先创建计划。\n- 当前计划状态为 \\`已执行\\` → 拒绝执行,提示使用 patch 修补或运行 \\`agent-context done\\` 归档。\n- \\`## 目标\\` 或 \\`## 内容\\` 为空 → 拒绝执行,提示补充。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 仅操作当前计划,不直接操作 \\`preparing/\\` 中的计划。\n- 遇到阻塞问题应向用户报告,不可静默跳过。\n\n## 执行步骤\n\n1. 读取当前计划 \\`plan.md\\`,理解 \\`## 目标\\` 与 \\`## 内容\\`。\n2. 依据 \\`## 内容\\` 中的步骤逐项实施。\n3. **验证循环**(全部通过前不可进入步骤 4):\n a. 逐项对照 \\`## 内容\\` 确认每个步骤已实施。\n b. 运行项目验证:类型检查 → lint → 测试。\n c. 若存在失败项 → 修复后回到 a 重新验证。\n d. 全部通过 → 进入步骤 4。\n4. 更新 \\`plan.md\\` 状态行:\\`> 状态: 未执行\\` → \\`> 状态: 已执行\\`。\n5. 更新 \\`## 影响范围\\`,记录所有变更文件。\n`\n}\n\nfunction renderPatch(): string {\n return `# patch\n\n基于当前已执行计划创建增量补丁,修复问题或追加变更。\n\n必须附带补丁描述。\n\n## 前置检查\n\n- 运行 \\`agent-context validate\\`,不通过则中止并报告错误。\n- 描述为空 → 拒绝执行。\n- 当前计划不存在 → 拒绝执行,提示先创建计划。\n- 当前计划状态为 \\`未执行\\` → 拒绝执行,提示先实施。\n- 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 补丁不改变计划状态,完成后保持 \\`已执行\\`。\n\n## 执行步骤\n\n1. 阅读 \\`plan.md\\` 与已有 \\`patch-{number}.md\\`,了解上下文与历史,避免重复修复。\n2. 根据描述执行补丁所需的代码变更。\n3. 完成必要验证(测试、类型检查等)。\n4. 创建 \\`patch-{number}.md\\`(编号:扫描当前计划目录已有补丁取 max+1),遵循下方模板。\n5. 回写 \\`plan.md\\`:\n - \\`## 历史补丁\\`:追加 \\`- patch-{number}: {补丁名称}\\`,按编号去重。\n - \\`## 影响范围\\`:合并本次变更路径,按路径去重。\n\n## patch.md 模板\n\n\\`\\`\\`markdown\n# {补丁名称}\n\n## 补丁内容\n\n{修改了什么、为什么修改}\n\n## 影响范围\n\n- 新增文件: \\`/path/to/file\\`\n- 修改文件: \\`/path/to/file\\`\n- 删除文件: \\`/path/to/file\\`\n\\`\\`\\`\n`\n}\n\nfunction renderRush(): string {\n return `# rush\n\n快速通道:创建计划并立即实施,适合范围明确、无需多轮规划的任务。\n\n必须附带任务描述。\n\n## 前置检查\n\n- 运行 \\`agent-context validate\\`,不通过则中止并报告错误。\n- 描述为空拒绝执行。\n- 存在未归档的已执行当前计划拒绝执行,提示先运行 \\`agent-context done\\` 归档。\n- 存在未实施的当前计划拒绝执行,提示先 implement 或 replan。\n\n## 执行步骤\n\n1. 按 plan 协议创建单计划(不拆分,不进入 preparing 队列)。\n2. 无需用户确认计划内容,直接进入 implement 流程。\n3. implement 协议执行全部步骤,包括验证循环:\n a. 逐项对照 \\`## 内容\\` 确认每个步骤已实施。\n b. 运行项目验证:类型检查 → lint → 测试。\n c. 若存在失败项 修复后重新验证。\n d. 全部通过 → 进入步骤 4。\n4. 更新 \\`plan.md\\` 状态行为 \\`已执行\\`,更新 \\`## 影响范围\\`。\n`\n}\n"],"mappings":"AAAA,MAAa,EAAe,CAAC,OAAQ,OAAQ,SAAU,YAAa,QAAS,OAAO,CAGvE,EAAqD,CAChE,KAAM,EACN,KAAM,EACN,OAAQ,EACR,UAAW,EACX,MAAO,EACP,KAAM,EACP,CAED,SAAS,GAAqB,CAC5B,MAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoCT,SAAS,GAAqB,CAC5B,MAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqDT,SAAS,GAAuB,CAC9B,MAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCT,SAAS,GAA0B,CACjC,MAAO,wrBA+BT,SAAS,GAAsB,CAC7B,MAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2CT,SAAS,GAAqB,CAC5B,MAAO"}
@@ -12,7 +12,8 @@ import{ACTION_NAMES as e,ACTION_RENDERERS as t}from"./actions.js";function n(n){
12
12
  | 重做计划、调整方案 | replan | \`actions/replan.md\` |
13
13
  | 按计划开始做、实现当前计划 | implement | \`actions/implement.md\` |
14
14
  | 补一个小改动、在当前结果上修 | patch | \`actions/patch.md\` |
15
- | 任务彻底完成、归档当前计划 | done | \`actions/done.md\` |
15
+ | 快速出计划并实施 | rush | \`actions/rush.md\` |
16
+ | 任务彻底完成、归档当前计划 | done | 运行 \`agent-context done\` |
16
17
 
17
18
  ## 全局约束
18
19
 
@@ -35,11 +36,11 @@ import{ACTION_NAMES as e,ACTION_RENDERERS as t}from"./actions.js";function n(n){
35
36
  \`\`\`
36
37
 
37
38
  编号规则:扫描全部 \`plan-N\` 目录取 \`max(N)+1\`。
38
- `}function i(e){let t=[`---`,`name: ac-workflow`,`description: 管理 .agent-context 计划生命周期,按 init、plan、replan、implement、patch、done 协议推进任务。`];return e.frontmatterProfile===`claude`&&t.push(`argument-hint: [request]`),e.frontmatterProfile===`copilot`&&t.push(`license: MIT`),t.push(`---`,``),`${t.join(`
39
+ `}function i(e){let t=[`---`,`name: ac-workflow`,`description: 管理 .agent-context 计划生命周期,按 init、plan、replan、implement、patch、rush、done 协议推进任务。`];return e.frontmatterProfile===`claude`&&t.push(`argument-hint: [request]`),e.frontmatterProfile===`copilot`&&t.push(`license: MIT`),t.push(`---`,``),`${t.join(`
39
40
  `)}\n`}function a(){return`interface:
40
41
  display_name: "Agent Context"
41
42
  short_description: "统一管理 .agent-context 计划生命周期"
42
- default_prompt: "Use $ac-workflow to manage the current task through init, plan, replan, implement, patch, or done."
43
+ default_prompt: "Use $ac-workflow to manage the current task through init, plan, replan, implement, patch, rush, or done."
43
44
 
44
45
  policy:
45
46
  allow_implicit_invocation: true
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/content/index.ts"],"sourcesContent":["import type { SkillArtifacts, ToolTarget } from '../types'\nimport { ACTION_NAMES, ACTION_RENDERERS } from './actions'\n\nconst SKILL_NAME = 'ac-workflow'\nconst SKILL_DESCRIPTION =\n '管理 .agent-context 计划生命周期,按 init、plan、replan、implement、patch、done 协议推进任务。'\n\nexport function renderSkillArtifacts(target: ToolTarget): SkillArtifacts {\n const files: SkillArtifacts['files'] = [\n { relativePath: 'SKILL.md', body: renderNavigator(target) },\n ...ACTION_NAMES.map((name) => ({\n relativePath: `actions/${name}.md`,\n body: ACTION_RENDERERS[name]()\n }))\n ]\n\n if (target.metadataFiles.includes('openai')) {\n files.push({ relativePath: 'agents/openai.yaml', body: renderOpenAIMetadata() })\n }\n\n return { files }\n}\n\n// ── Navigator ────────────────────────────────────────\n\nfunction renderNavigator(target: ToolTarget): string {\n return `${renderFrontmatter(target)}\n# Agent Context\n\n管理项目中的 \\`.agent-context/\\` 计划生命周期。匹配用户意图后,读取对应协议文件(相对于本文件所在目录)严格执行。\n\n## 意图匹配\n\n| 用户意图 | 动作 | 协议文件 |\n|----------|------|----------|\n| 初始化项目上下文、补全 AGENTS | init | \\`actions/init.md\\` |\n| 给需求出计划、拆分任务 | plan | \\`actions/plan.md\\` |\n| 重做计划、调整方案 | replan | \\`actions/replan.md\\` |\n| 按计划开始做、实现当前计划 | implement | \\`actions/implement.md\\` |\n| 补一个小改动、在当前结果上修 | patch | \\`actions/patch.md\\` |\n| 任务彻底完成、归档当前计划 | done | \\`actions/done.md\\` |\n\n## 全局约束\n\n- 状态机两态:\\`未执行\\`、\\`已执行\\`。\n- 任意时刻最多一个当前计划:\\`.agent-context/plan-{number}\\`。\n- 多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 计划编号全局递增,不复用。补丁编号在单计划目录内递增,不复用。\n\n## 目录结构\n\n\\`\\`\\`text\n.agent-context/\n├── plan-{N}/ # 当前计划(最多一个)\n│ ├── plan.md\n│ └── patch-{N}.md\n├── preparing/ # 待执行计划队列\n│ └── plan-{N}/\n└── done/ # 已归档计划\n └── plan-{N}-{YYYYMMDD}/\n\\`\\`\\`\n\n编号规则:扫描全部 \\`plan-N\\` 目录取 \\`max(N)+1\\`。\n`\n}\n\n// ── Frontmatter & Metadata ──────────────────────────\n\nfunction renderFrontmatter(target: ToolTarget): string {\n const lines = ['---', `name: ${SKILL_NAME}`, `description: ${SKILL_DESCRIPTION}`]\n\n if (target.frontmatterProfile === 'claude') {\n lines.push('argument-hint: [request]')\n }\n\n if (target.frontmatterProfile === 'copilot') {\n lines.push('license: MIT')\n }\n\n lines.push('---', '')\n return `${lines.join('\\n')}\\n`\n}\n\nfunction renderOpenAIMetadata(): string {\n return `interface:\n display_name: \"Agent Context\"\n short_description: \"统一管理 .agent-context 计划生命周期\"\n default_prompt: \"Use $ac-workflow to manage the current task through init, plan, replan, implement, patch, or done.\"\n\npolicy:\n allow_implicit_invocation: true\n`\n}\n"],"mappings":"kEAOA,SAAgB,EAAqB,EAAoC,CACvE,IAAM,EAAiC,CACrC,CAAE,aAAc,WAAY,KAAM,EAAgB,EAAO,CAAE,CAC3D,GAAG,EAAa,IAAK,IAAU,CAC7B,aAAc,WAAW,EAAK,KAC9B,KAAM,EAAiB,IAAO,CAC/B,EAAE,CACJ,CAMD,OAJI,EAAO,cAAc,SAAS,SAAS,EACzC,EAAM,KAAK,CAAE,aAAc,qBAAsB,KAAM,GAAsB,CAAE,CAAC,CAG3E,CAAE,QAAO,CAKlB,SAAS,EAAgB,EAA4B,CACnD,MAAO,GAAG,EAAkB,EAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0CtC,SAAS,EAAkB,EAA4B,CACrD,IAAM,EAAQ,CAAC,MAAO,oBAAuB,wFAAoC,CAWjF,OATI,EAAO,qBAAuB,UAChC,EAAM,KAAK,2BAA2B,CAGpC,EAAO,qBAAuB,WAChC,EAAM,KAAK,eAAe,CAG5B,EAAM,KAAK,MAAO,GAAG,CACd,GAAG,EAAM,KAAK;EAAK,CAAC,IAG7B,SAAS,GAA+B,CACtC,MAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/content/index.ts"],"sourcesContent":["import type { SkillArtifacts, ToolTarget } from '../types.js'\nimport { ACTION_NAMES, ACTION_RENDERERS } from './actions.js'\n\nconst SKILL_NAME = 'ac-workflow'\nconst SKILL_DESCRIPTION =\n '管理 .agent-context 计划生命周期,按 init、plan、replan、implement、patch、rush、done 协议推进任务。'\n\nexport function renderSkillArtifacts(target: ToolTarget): SkillArtifacts {\n const files: SkillArtifacts['files'] = [\n { relativePath: 'SKILL.md', body: renderNavigator(target) },\n ...ACTION_NAMES.map((name) => ({\n relativePath: `actions/${name}.md`,\n body: ACTION_RENDERERS[name]()\n }))\n ]\n\n if (target.metadataFiles.includes('openai')) {\n files.push({ relativePath: 'agents/openai.yaml', body: renderOpenAIMetadata() })\n }\n\n return { files }\n}\n\n// ── Navigator ────────────────────────────────────────\n\nfunction renderNavigator(target: ToolTarget): string {\n return `${renderFrontmatter(target)}\n# Agent Context\n\n管理项目中的 \\`.agent-context/\\` 计划生命周期。匹配用户意图后,读取对应协议文件(相对于本文件所在目录)严格执行。\n\n## 意图匹配\n\n| 用户意图 | 动作 | 协议文件 |\n|----------|------|----------|\n| 初始化项目上下文、补全 AGENTS | init | \\`actions/init.md\\` |\n| 给需求出计划、拆分任务 | plan | \\`actions/plan.md\\` |\n| 重做计划、调整方案 | replan | \\`actions/replan.md\\` |\n| 按计划开始做、实现当前计划 | implement | \\`actions/implement.md\\` |\n| 补一个小改动、在当前结果上修 | patch | \\`actions/patch.md\\` |\n| 快速出计划并实施 | rush | \\`actions/rush.md\\` |\n| 任务彻底完成、归档当前计划 | done | 运行 \\`agent-context done\\` |\n\n## 全局约束\n\n- 状态机两态:\\`未执行\\`、\\`已执行\\`。\n- 任意时刻最多一个当前计划:\\`.agent-context/plan-{number}\\`。\n- 多个当前计划 → 拒绝执行,提示恢复单活跃状态。\n- 计划编号全局递增,不复用。补丁编号在单计划目录内递增,不复用。\n\n## 目录结构\n\n\\`\\`\\`text\n.agent-context/\n├── plan-{N}/ # 当前计划(最多一个)\n│ ├── plan.md\n│ └── patch-{N}.md\n├── preparing/ # 待执行计划队列\n│ └── plan-{N}/\n└── done/ # 已归档计划\n └── plan-{N}-{YYYYMMDD}/\n\\`\\`\\`\n\n编号规则:扫描全部 \\`plan-N\\` 目录取 \\`max(N)+1\\`。\n`\n}\n\n// ── Frontmatter & Metadata ──────────────────────────\n\nfunction renderFrontmatter(target: ToolTarget): string {\n const lines = ['---', `name: ${SKILL_NAME}`, `description: ${SKILL_DESCRIPTION}`]\n\n if (target.frontmatterProfile === 'claude') {\n lines.push('argument-hint: [request]')\n }\n\n if (target.frontmatterProfile === 'copilot') {\n lines.push('license: MIT')\n }\n\n lines.push('---', '')\n return `${lines.join('\\n')}\\n`\n}\n\nfunction renderOpenAIMetadata(): string {\n return `interface:\n display_name: \"Agent Context\"\n short_description: \"统一管理 .agent-context 计划生命周期\"\n default_prompt: \"Use $ac-workflow to manage the current task through init, plan, replan, implement, patch, rush, or done.\"\n\npolicy:\n allow_implicit_invocation: true\n`\n}\n"],"mappings":"kEAOA,SAAgB,EAAqB,EAAoC,CACvE,IAAM,EAAiC,CACrC,CAAE,aAAc,WAAY,KAAM,EAAgB,EAAO,CAAE,CAC3D,GAAG,EAAa,IAAK,IAAU,CAC7B,aAAc,WAAW,EAAK,KAC9B,KAAM,EAAiB,IAAO,CAC/B,EAAE,CACJ,CAMD,OAJI,EAAO,cAAc,SAAS,SAAS,EACzC,EAAM,KAAK,CAAE,aAAc,qBAAsB,KAAM,GAAsB,CAAE,CAAC,CAG3E,CAAE,QAAO,CAKlB,SAAS,EAAgB,EAA4B,CACnD,MAAO,GAAG,EAAkB,EAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2CtC,SAAS,EAAkB,EAA4B,CACrD,IAAM,EAAQ,CAAC,MAAO,oBAAuB,6FAAoC,CAWjF,OATI,EAAO,qBAAuB,UAChC,EAAM,KAAK,2BAA2B,CAGpC,EAAO,qBAAuB,WAChC,EAAM,KAAK,eAAe,CAG5B,EAAM,KAAK,MAAO,GAAG,CACd,GAAG,EAAM,KAAK;EAAK,CAAC,IAG7B,SAAS,GAA+B,CACtC,MAAO"}
@@ -0,0 +1,2 @@
1
+ import{join as e}from"node:path";import{mkdir as t,rename as n}from"node:fs/promises";async function r(r){if(!r.currentPlan)throw Error(`无当前计划`);if(r.currentPlan.status!==`已执行`)throw Error(`当前计划尚未执行`);let a=`plan-${r.currentPlan.number}-${i()}`,o=e(r.root,`done`),s=e(o,a);await t(o,{recursive:!0}),await n(r.currentPlan.dir,s);let c=null,l=r.preparing[0];if(l){let t=e(r.root,`plan-${l.number}`);await n(l.dir,t),c=l.number}return{archivedTo:s,promoted:c,remainingPreparing:r.preparing.length-(c===null?0:1)}}function i(){let e=new Date;return`${String(e.getFullYear())}${String(e.getMonth()+1).padStart(2,`0`)}${String(e.getDate()).padStart(2,`0`)}`}export{r as archive};
2
+ //# sourceMappingURL=archiver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archiver.js","names":[],"sources":["../../src/context/archiver.ts"],"sourcesContent":["import { rename, mkdir } from 'node:fs/promises'\nimport { join } from 'node:path'\n\nimport type { ArchiveResult, ContextSnapshot } from '../types.js'\n\nexport async function archive(context: ContextSnapshot): Promise<ArchiveResult> {\n if (!context.currentPlan) {\n throw new Error('无当前计划')\n }\n\n if (context.currentPlan.status !== '已执行') {\n throw new Error('当前计划尚未执行')\n }\n\n const archiveName = `plan-${context.currentPlan.number}-${formatDate()}`\n const doneDir = join(context.root, 'done')\n const archivedTo = join(doneDir, archiveName)\n\n await mkdir(doneDir, { recursive: true })\n await rename(context.currentPlan.dir, archivedTo)\n\n let promoted: number | null = null\n const first = context.preparing[0]\n if (first) {\n const targetDir = join(context.root, `plan-${first.number}`)\n await rename(first.dir, targetDir)\n promoted = first.number\n }\n\n return {\n archivedTo,\n promoted,\n remainingPreparing: context.preparing.length - (promoted !== null ? 1 : 0)\n }\n}\n\n// ── Helpers ──────────────────────────────────────────\n\nfunction formatDate(): string {\n const d = new Date()\n const y = String(d.getFullYear())\n const m = String(d.getMonth() + 1).padStart(2, '0')\n const day = String(d.getDate()).padStart(2, '0')\n return `${y}${m}${day}`\n}\n"],"mappings":"sFAKA,eAAsB,EAAQ,EAAkD,CAC9E,GAAI,CAAC,EAAQ,YACX,MAAU,MAAM,QAAQ,CAG1B,GAAI,EAAQ,YAAY,SAAW,MACjC,MAAU,MAAM,WAAW,CAG7B,IAAM,EAAc,QAAQ,EAAQ,YAAY,OAAO,GAAG,GAAY,GAChE,EAAU,EAAK,EAAQ,KAAM,OAAO,CACpC,EAAa,EAAK,EAAS,EAAY,CAE7C,MAAM,EAAM,EAAS,CAAE,UAAW,GAAM,CAAC,CACzC,MAAM,EAAO,EAAQ,YAAY,IAAK,EAAW,CAEjD,IAAI,EAA0B,KACxB,EAAQ,EAAQ,UAAU,GAChC,GAAI,EAAO,CACT,IAAM,EAAY,EAAK,EAAQ,KAAM,QAAQ,EAAM,SAAS,CAC5D,MAAM,EAAO,EAAM,IAAK,EAAU,CAClC,EAAW,EAAM,OAGnB,MAAO,CACL,aACA,WACA,mBAAoB,EAAQ,UAAU,QAAU,IAAa,KAAW,EAAJ,GACrE,CAKH,SAAS,GAAqB,CAC5B,IAAM,EAAI,IAAI,KAId,MAAO,GAHG,OAAO,EAAE,aAAa,CAAC,GACvB,OAAO,EAAE,UAAU,CAAG,EAAE,CAAC,SAAS,EAAG,IAAI,GACvC,OAAO,EAAE,SAAS,CAAC,CAAC,SAAS,EAAG,IAAI"}
@@ -0,0 +1,2 @@
1
+ import{existsSync as e}from"node:fs";import{join as t}from"node:path";import{readFile as n,readdir as r}from"node:fs/promises";const i=/^plan-(\d+)$/,a=/^>\s*状态:\s*(未执行|已执行)\s*$/m;async function o(n){let r=t(n,`.agent-context`);if(!e(r))return{snapshot:null,currentPlanCount:0};let i=await c(r),a=await c(t(r,`preparing`)),o=await l(t(r,`done`));return{snapshot:{root:r,currentPlan:i[0]??null,preparing:a,doneCount:o},currentPlanCount:i.length}}async function s(r){let i=t(r,`plan.md`);if(!e(i))return`未执行`;let o=(await n(i,`utf-8`)).match(a);return o?o[1]:`未执行`}async function c(n){if(!e(n))return[];let a=await r(n,{withFileTypes:!0}),o=[];for(let e of a){if(!e.isDirectory())continue;let r=e.name.match(i);if(!r?.[1])continue;let a=parseInt(r[1],10),c=t(n,e.name),l=await s(c);o.push({number:a,status:l,dir:c})}return o.sort((e,t)=>e.number-t.number)}async function l(t){return e(t)?(await r(t,{withFileTypes:!0})).filter(e=>e.isDirectory()).length:0}export{o as readRawContext};
2
+ //# sourceMappingURL=reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reader.js","names":[],"sources":["../../src/context/reader.ts"],"sourcesContent":["import { readdir, readFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { ContextSnapshot, PlanInfo, PlanStatus } from '../types.js'\n\nconst PLAN_DIR_RE = /^plan-(\\d+)$/\nconst STATUS_RE = /^>\\s*状态:\\s*(未执行|已执行)\\s*$/m\n\n// ── Public API ───────────────────────────────────────\n\nexport async function readContext(cwd: string): Promise<ContextSnapshot | null> {\n const { snapshot } = await readRawContext(cwd)\n return snapshot\n}\n\nexport async function readRawContext(\n cwd: string\n): Promise<{ snapshot: ContextSnapshot | null; currentPlanCount: number }> {\n const root = join(cwd, '.agent-context')\n\n if (!existsSync(root)) {\n return { snapshot: null, currentPlanCount: 0 }\n }\n\n const currentPlans = await readPlanDirs(root)\n const preparing = await readPlanDirs(join(root, 'preparing'))\n const doneCount = await countDirs(join(root, 'done'))\n\n const snapshot: ContextSnapshot = {\n root,\n currentPlan: currentPlans[0] ?? null,\n preparing,\n doneCount\n }\n\n return { snapshot, currentPlanCount: currentPlans.length }\n}\n\nexport async function readPlanStatus(planDir: string): Promise<PlanStatus> {\n const planFile = join(planDir, 'plan.md')\n\n if (!existsSync(planFile)) {\n return '未执行'\n }\n\n const content = await readFile(planFile, 'utf-8')\n const match = content.match(STATUS_RE)\n return match ? (match[1] as PlanStatus) : '未执行'\n}\n\n// ── Helpers ──────────────────────────────────────────\n\nasync function readPlanDirs(parentDir: string): Promise<PlanInfo[]> {\n if (!existsSync(parentDir)) return []\n\n const entries = await readdir(parentDir, { withFileTypes: true })\n const plans: PlanInfo[] = []\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const match = entry.name.match(PLAN_DIR_RE)\n if (!match?.[1]) continue\n const number = parseInt(match[1], 10)\n const dir = join(parentDir, entry.name)\n const status = await readPlanStatus(dir)\n plans.push({ number, status, dir })\n }\n\n return plans.sort((a, b) => a.number - b.number)\n}\n\nasync function countDirs(dir: string): Promise<number> {\n if (!existsSync(dir)) return 0\n const entries = await readdir(dir, { withFileTypes: true })\n return entries.filter(e => e.isDirectory()).length\n}\n"],"mappings":"+HAMA,MAAM,EAAc,eACd,EAAY,4BASlB,eAAsB,EACpB,EACyE,CACzE,IAAM,EAAO,EAAK,EAAK,iBAAiB,CAExC,GAAI,CAAC,EAAW,EAAK,CACnB,MAAO,CAAE,SAAU,KAAM,iBAAkB,EAAG,CAGhD,IAAM,EAAe,MAAM,EAAa,EAAK,CACvC,EAAY,MAAM,EAAa,EAAK,EAAM,YAAY,CAAC,CACvD,EAAY,MAAM,EAAU,EAAK,EAAM,OAAO,CAAC,CASrD,MAAO,CAAE,SAPyB,CAChC,OACA,YAAa,EAAa,IAAM,KAChC,YACA,YACD,CAEkB,iBAAkB,EAAa,OAAQ,CAG5D,eAAsB,EAAe,EAAsC,CACzE,IAAM,EAAW,EAAK,EAAS,UAAU,CAEzC,GAAI,CAAC,EAAW,EAAS,CACvB,MAAO,MAIT,IAAM,GADU,MAAM,EAAS,EAAU,QAAQ,EAC3B,MAAM,EAAU,CACtC,OAAO,EAAS,EAAM,GAAoB,MAK5C,eAAe,EAAa,EAAwC,CAClE,GAAI,CAAC,EAAW,EAAU,CAAE,MAAO,EAAE,CAErC,IAAM,EAAU,MAAM,EAAQ,EAAW,CAAE,cAAe,GAAM,CAAC,CAC3D,EAAoB,EAAE,CAE5B,IAAK,IAAM,KAAS,EAAS,CAC3B,GAAI,CAAC,EAAM,aAAa,CAAE,SAC1B,IAAM,EAAQ,EAAM,KAAK,MAAM,EAAY,CAC3C,GAAI,CAAC,IAAQ,GAAI,SACjB,IAAM,EAAS,SAAS,EAAM,GAAI,GAAG,CAC/B,EAAM,EAAK,EAAW,EAAM,KAAK,CACjC,EAAS,MAAM,EAAe,EAAI,CACxC,EAAM,KAAK,CAAE,SAAQ,SAAQ,MAAK,CAAC,CAGrC,OAAO,EAAM,MAAM,EAAG,IAAM,EAAE,OAAS,EAAE,OAAO,CAGlD,eAAe,EAAU,EAA8B,CAGrD,OAFK,EAAW,EAAI,EACJ,MAAM,EAAQ,EAAK,CAAE,cAAe,GAAM,CAAC,EAC5C,OAAO,GAAK,EAAE,aAAa,CAAC,CAAC,OAFf"}
@@ -0,0 +1,2 @@
1
+ import{existsSync as e}from"node:fs";import{join as t}from"node:path";function n(n,r){if(n===null)return{valid:!0,errors:[],context:null};let i=[];r>1&&i.push(`存在 ${r} 个当前计划,应最多 1 个。`),n.currentPlan&&(e(t(n.currentPlan.dir,`plan.md`))||i.push(`当前计划 plan-${n.currentPlan.number} 缺少 plan.md。`));let a=[];n.currentPlan&&a.push(n.currentPlan.number);for(let e of n.preparing)a.push(e.number);let o=new Set,s=new Set;for(let e of a)o.has(e)&&s.add(e),o.add(e);if(s.size>0){let e=[...s].sort((e,t)=>e-t).join(`, `);i.push(`计划编号冲突: ${e}。`)}return{valid:i.length===0,errors:i,context:n}}export{n as validate};
2
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","names":[],"sources":["../../src/context/validator.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\n\nimport type { ContextSnapshot, ValidateResult } from '../types.js'\n\nexport function validate(\n snapshot: ContextSnapshot | null,\n currentPlanCount: number\n): ValidateResult {\n if (snapshot === null) {\n return { valid: true, errors: [], context: null }\n }\n\n const errors: string[] = []\n\n if (currentPlanCount > 1) {\n errors.push(`存在 ${currentPlanCount} 个当前计划,应最多 1 个。`)\n }\n\n if (snapshot.currentPlan) {\n const planMd = join(snapshot.currentPlan.dir, 'plan.md')\n if (!existsSync(planMd)) {\n errors.push(`当前计划 plan-${snapshot.currentPlan.number} 缺少 plan.md。`)\n }\n }\n\n const allNumbers: number[] = []\n if (snapshot.currentPlan) allNumbers.push(snapshot.currentPlan.number)\n for (const p of snapshot.preparing) allNumbers.push(p.number)\n\n const seen = new Set<number>()\n const duplicates = new Set<number>()\n for (const n of allNumbers) {\n if (seen.has(n)) duplicates.add(n)\n seen.add(n)\n }\n\n if (duplicates.size > 0) {\n const nums = [...duplicates].sort((a, b) => a - b).join(', ')\n errors.push(`计划编号冲突: ${nums}。`)\n }\n\n return { valid: errors.length === 0, errors, context: snapshot }\n}\n"],"mappings":"sEAKA,SAAgB,EACd,EACA,EACgB,CAChB,GAAI,IAAa,KACf,MAAO,CAAE,MAAO,GAAM,OAAQ,EAAE,CAAE,QAAS,KAAM,CAGnD,IAAM,EAAmB,EAAE,CAEvB,EAAmB,GACrB,EAAO,KAAK,MAAM,EAAiB,iBAAiB,CAGlD,EAAS,cAEN,EADU,EAAK,EAAS,YAAY,IAAK,UAAU,CACjC,EACrB,EAAO,KAAK,aAAa,EAAS,YAAY,OAAO,cAAc,EAIvE,IAAM,EAAuB,EAAE,CAC3B,EAAS,aAAa,EAAW,KAAK,EAAS,YAAY,OAAO,CACtE,IAAK,IAAM,KAAK,EAAS,UAAW,EAAW,KAAK,EAAE,OAAO,CAE7D,IAAM,EAAO,IAAI,IACX,EAAa,IAAI,IACvB,IAAK,IAAM,KAAK,EACV,EAAK,IAAI,EAAE,EAAE,EAAW,IAAI,EAAE,CAClC,EAAK,IAAI,EAAE,CAGb,GAAI,EAAW,KAAO,EAAG,CACvB,IAAM,EAAO,CAAC,GAAG,EAAW,CAAC,MAAM,EAAG,IAAM,EAAI,EAAE,CAAC,KAAK,KAAK,CAC7D,EAAO,KAAK,WAAW,EAAK,GAAG,CAGjC,MAAO,CAAE,MAAO,EAAO,SAAW,EAAG,SAAQ,QAAS,EAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","names":[],"sources":["../src/runner.ts"],"sourcesContent":["import { resolve, dirname } from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\n\nimport type { SkillPaths } from './tools'\nimport { resolveToolTargets, resolveSkillPaths } from './tools'\nimport { renderSkillArtifacts } from './content'\nimport type { ApplyMutationResult, FileMutation, RunOptions, RunResult, ToolId, ToolTarget } from './types'\n\nexport async function runInstall(options: RunOptions = {}): Promise<RunResult> {\n return run('install', options)\n}\n\nexport async function runSync(options: RunOptions = {}): Promise<RunResult> {\n return run('sync', options)\n}\n\n// ── Orchestration ───────────────────────────────────\n\nasync function run(mode: 'install' | 'sync', options: RunOptions): Promise<RunResult> {\n const cwd = options.cwd ?? process.cwd()\n const tools = dedup(options.tools)\n const targets = resolveToolTargets(tools)\n\n const mutations: FileMutation[] = targets.flatMap(target => buildMutations(target, cwd))\n\n const check = options.check ?? false\n const result = await applyMutations(mutations, check)\n\n return { ...result, mode, check }\n}\n\n// ── Mutation building ───────────────────────────────\n\nfunction buildMutations(target: ToolTarget, cwd: string): FileMutation[] {\n const artifacts = renderSkillArtifacts(target)\n const paths = resolveSkillPaths(target, cwd)\n\n return artifacts.files.map(file => ({\n path: resolveArtifactPath(paths, file.relativePath),\n body: file.body\n }))\n}\n\nfunction resolveArtifactPath(paths: SkillPaths, relativePath: string): string {\n if (relativePath === 'SKILL.md') {\n return paths.skillFile\n }\n\n return resolve(paths.skillDir, relativePath)\n}\n\n// ── Mutation application ────────────────────────────\n\nasync function applyMutations(\n mutations: FileMutation[],\n check: boolean\n): Promise<ApplyMutationResult> {\n const result: ApplyMutationResult = {\n created: [],\n updated: [],\n unchanged: [],\n changed: []\n }\n\n for (const mutation of mutations) {\n const fileExists = existsSync(mutation.path)\n const next = await resolveNextContent(mutation, fileExists)\n\n if (!next.changed) {\n result.unchanged.push(mutation.path)\n continue\n }\n\n if (!check) {\n await mkdir(dirname(mutation.path), { recursive: true })\n await writeFile(mutation.path, next.content, 'utf-8')\n }\n\n result.changed.push(mutation.path)\n\n if (fileExists) {\n result.updated.push(mutation.path)\n } else {\n result.created.push(mutation.path)\n }\n }\n\n return result\n}\n\nasync function resolveNextContent(\n mutation: FileMutation,\n fileExists: boolean\n): Promise<{ content: string; changed: boolean }> {\n const content = normalizeTrailingNewline(mutation.body)\n\n if (!fileExists) {\n return { content, changed: true }\n }\n\n const current = await readFile(mutation.path, 'utf-8')\n return { content, changed: current !== content }\n}\n\nfunction normalizeTrailingNewline(content: string): string {\n return content.endsWith('\\n') ? content : `${content}\\n`\n}\n\nfunction dedup(tools?: ToolId[]): ToolId[] | undefined {\n if (!tools || tools.length === 0) return undefined\n return [...new Set(tools)]\n}\n"],"mappings":"6RASA,eAAsB,EAAW,EAAsB,EAAE,CAAsB,CAC7E,OAAO,EAAI,UAAW,EAAQ,CAGhC,eAAsB,EAAQ,EAAsB,EAAE,CAAsB,CAC1E,OAAO,EAAI,OAAQ,EAAQ,CAK7B,eAAe,EAAI,EAA0B,EAAyC,CACpF,IAAM,EAAM,EAAQ,KAAO,QAAQ,KAAK,CAIlC,EAFU,EADF,EAAM,EAAQ,MAAM,CACO,CAEC,QAAQ,GAAU,EAAe,EAAQ,EAAI,CAAC,CAElF,EAAQ,EAAQ,OAAS,GAG/B,MAAO,CAAE,GAFM,MAAM,EAAe,EAAW,EAAM,CAEjC,OAAM,QAAO,CAKnC,SAAS,EAAe,EAAoB,EAA6B,CACvE,IAAM,EAAY,EAAqB,EAAO,CACxC,EAAQ,EAAkB,EAAQ,EAAI,CAE5C,OAAO,EAAU,MAAM,IAAI,IAAS,CAClC,KAAM,EAAoB,EAAO,EAAK,aAAa,CACnD,KAAM,EAAK,KACZ,EAAE,CAGL,SAAS,EAAoB,EAAmB,EAA8B,CAK5E,OAJI,IAAiB,WACZ,EAAM,UAGR,EAAQ,EAAM,SAAU,EAAa,CAK9C,eAAe,EACb,EACA,EAC8B,CAC9B,IAAM,EAA8B,CAClC,QAAS,EAAE,CACX,QAAS,EAAE,CACX,UAAW,EAAE,CACb,QAAS,EAAE,CACZ,CAED,IAAK,IAAM,KAAY,EAAW,CAChC,IAAM,EAAa,EAAW,EAAS,KAAK,CACtC,EAAO,MAAM,EAAmB,EAAU,EAAW,CAE3D,GAAI,CAAC,EAAK,QAAS,CACjB,EAAO,UAAU,KAAK,EAAS,KAAK,CACpC,SAGG,IACH,MAAM,EAAM,EAAQ,EAAS,KAAK,CAAE,CAAE,UAAW,GAAM,CAAC,CACxD,MAAM,EAAU,EAAS,KAAM,EAAK,QAAS,QAAQ,EAGvD,EAAO,QAAQ,KAAK,EAAS,KAAK,CAE9B,EACF,EAAO,QAAQ,KAAK,EAAS,KAAK,CAElC,EAAO,QAAQ,KAAK,EAAS,KAAK,CAItC,OAAO,EAGT,eAAe,EACb,EACA,EACgD,CAChD,IAAM,EAAU,EAAyB,EAAS,KAAK,CAOvD,OALK,EAKE,CAAE,UAAS,QADF,MAAM,EAAS,EAAS,KAAM,QAAQ,GACf,EAAS,CAJvC,CAAE,UAAS,QAAS,GAAM,CAOrC,SAAS,EAAyB,EAAyB,CACzD,OAAO,EAAQ,SAAS;EAAK,CAAG,EAAU,GAAG,EAAQ,IAGvD,SAAS,EAAM,EAAwC,CACjD,MAAC,GAAS,EAAM,SAAW,GAC/B,MAAO,CAAC,GAAG,IAAI,IAAI,EAAM,CAAC"}
1
+ {"version":3,"file":"runner.js","names":[],"sources":["../src/runner.ts"],"sourcesContent":["import { resolve, dirname } from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { mkdir, readFile, writeFile } from 'node:fs/promises'\n\nimport type { SkillPaths } from './tools.js'\nimport { resolveToolTargets, resolveSkillPaths } from './tools.js'\nimport { renderSkillArtifacts } from './content/index.js'\nimport type { ApplyMutationResult, FileMutation, RunOptions, RunResult, ToolId, ToolTarget } from './types.js'\n\nexport async function runInstall(options: RunOptions = {}): Promise<RunResult> {\n return run('install', options)\n}\n\nexport async function runSync(options: RunOptions = {}): Promise<RunResult> {\n return run('sync', options)\n}\n\n// ── Orchestration ───────────────────────────────────\n\nasync function run(mode: 'install' | 'sync', options: RunOptions): Promise<RunResult> {\n const cwd = options.cwd ?? process.cwd()\n const tools = dedup(options.tools)\n const targets = resolveToolTargets(tools)\n\n const mutations: FileMutation[] = targets.flatMap(target => buildMutations(target, cwd))\n\n const check = options.check ?? false\n const result = await applyMutations(mutations, check)\n\n return { ...result, mode, check }\n}\n\n// ── Mutation building ───────────────────────────────\n\nfunction buildMutations(target: ToolTarget, cwd: string): FileMutation[] {\n const artifacts = renderSkillArtifacts(target)\n const paths = resolveSkillPaths(target, cwd)\n\n return artifacts.files.map(file => ({\n path: resolveArtifactPath(paths, file.relativePath),\n body: file.body\n }))\n}\n\nfunction resolveArtifactPath(paths: SkillPaths, relativePath: string): string {\n if (relativePath === 'SKILL.md') {\n return paths.skillFile\n }\n\n return resolve(paths.skillDir, relativePath)\n}\n\n// ── Mutation application ────────────────────────────\n\nasync function applyMutations(\n mutations: FileMutation[],\n check: boolean\n): Promise<ApplyMutationResult> {\n const result: ApplyMutationResult = {\n created: [],\n updated: [],\n unchanged: [],\n changed: []\n }\n\n for (const mutation of mutations) {\n const fileExists = existsSync(mutation.path)\n const next = await resolveNextContent(mutation, fileExists)\n\n if (!next.changed) {\n result.unchanged.push(mutation.path)\n continue\n }\n\n if (!check) {\n await mkdir(dirname(mutation.path), { recursive: true })\n await writeFile(mutation.path, next.content, 'utf-8')\n }\n\n result.changed.push(mutation.path)\n\n if (fileExists) {\n result.updated.push(mutation.path)\n } else {\n result.created.push(mutation.path)\n }\n }\n\n return result\n}\n\nasync function resolveNextContent(\n mutation: FileMutation,\n fileExists: boolean\n): Promise<{ content: string; changed: boolean }> {\n const content = normalizeTrailingNewline(mutation.body)\n\n if (!fileExists) {\n return { content, changed: true }\n }\n\n const current = await readFile(mutation.path, 'utf-8')\n return { content, changed: current !== content }\n}\n\nfunction normalizeTrailingNewline(content: string): string {\n return content.endsWith('\\n') ? content : `${content}\\n`\n}\n\nfunction dedup(tools?: ToolId[]): ToolId[] | undefined {\n if (!tools || tools.length === 0) return undefined\n return [...new Set(tools)]\n}\n"],"mappings":"6RASA,eAAsB,EAAW,EAAsB,EAAE,CAAsB,CAC7E,OAAO,EAAI,UAAW,EAAQ,CAGhC,eAAsB,EAAQ,EAAsB,EAAE,CAAsB,CAC1E,OAAO,EAAI,OAAQ,EAAQ,CAK7B,eAAe,EAAI,EAA0B,EAAyC,CACpF,IAAM,EAAM,EAAQ,KAAO,QAAQ,KAAK,CAIlC,EAFU,EADF,EAAM,EAAQ,MAAM,CACO,CAEC,QAAQ,GAAU,EAAe,EAAQ,EAAI,CAAC,CAElF,EAAQ,EAAQ,OAAS,GAG/B,MAAO,CAAE,GAFM,MAAM,EAAe,EAAW,EAAM,CAEjC,OAAM,QAAO,CAKnC,SAAS,EAAe,EAAoB,EAA6B,CACvE,IAAM,EAAY,EAAqB,EAAO,CACxC,EAAQ,EAAkB,EAAQ,EAAI,CAE5C,OAAO,EAAU,MAAM,IAAI,IAAS,CAClC,KAAM,EAAoB,EAAO,EAAK,aAAa,CACnD,KAAM,EAAK,KACZ,EAAE,CAGL,SAAS,EAAoB,EAAmB,EAA8B,CAK5E,OAJI,IAAiB,WACZ,EAAM,UAGR,EAAQ,EAAM,SAAU,EAAa,CAK9C,eAAe,EACb,EACA,EAC8B,CAC9B,IAAM,EAA8B,CAClC,QAAS,EAAE,CACX,QAAS,EAAE,CACX,UAAW,EAAE,CACb,QAAS,EAAE,CACZ,CAED,IAAK,IAAM,KAAY,EAAW,CAChC,IAAM,EAAa,EAAW,EAAS,KAAK,CACtC,EAAO,MAAM,EAAmB,EAAU,EAAW,CAE3D,GAAI,CAAC,EAAK,QAAS,CACjB,EAAO,UAAU,KAAK,EAAS,KAAK,CACpC,SAGG,IACH,MAAM,EAAM,EAAQ,EAAS,KAAK,CAAE,CAAE,UAAW,GAAM,CAAC,CACxD,MAAM,EAAU,EAAS,KAAM,EAAK,QAAS,QAAQ,EAGvD,EAAO,QAAQ,KAAK,EAAS,KAAK,CAE9B,EACF,EAAO,QAAQ,KAAK,EAAS,KAAK,CAElC,EAAO,QAAQ,KAAK,EAAS,KAAK,CAItC,OAAO,EAGT,eAAe,EACb,EACA,EACgD,CAChD,IAAM,EAAU,EAAyB,EAAS,KAAK,CAOvD,OALK,EAKE,CAAE,UAAS,QADF,MAAM,EAAS,EAAS,KAAM,QAAQ,GACf,EAAS,CAJvC,CAAE,UAAS,QAAS,GAAM,CAOrC,SAAS,EAAyB,EAAyB,CACzD,OAAO,EAAQ,SAAS;EAAK,CAAG,EAAU,GAAG,EAAQ,IAGvD,SAAS,EAAM,EAAwC,CACjD,MAAC,GAAS,EAAM,SAAW,GAC/B,MAAO,CAAC,GAAG,IAAI,IAAI,EAAM,CAAC"}
package/dist/stats.html CHANGED
@@ -4930,7 +4930,7 @@ var drawChart = (function (exports) {
4930
4930
  </script>
4931
4931
  <script>
4932
4932
  /*<!--*/
4933
- const data = {"version":2,"tree":{"name":"root","children":[{"name":"cli.d.ts","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/cli.d.ts","uid":"ee14ac96-1"}]},{"name":"cli.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/cli.ts","uid":"ee14ac96-3"}]},{"name":"commands/install.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/install.ts","uid":"ee14ac96-5"}]},{"name":"commands/printer.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/printer.ts","uid":"ee14ac96-7"}]},{"name":"commands/sync.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/sync.ts","uid":"ee14ac96-9"}]},{"name":"content/actions.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/content/actions.ts","uid":"ee14ac96-11"}]},{"name":"content/index.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/content/index.ts","uid":"ee14ac96-13"}]},{"name":"runner.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/runner.ts","uid":"ee14ac96-15"}]},{"name":"tools.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/tools.ts","uid":"ee14ac96-17"}]}],"isRoot":true},"nodeParts":{"ee14ac96-1":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-0"},"ee14ac96-3":{"renderedLength":1182,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-2"},"ee14ac96-5":{"renderedLength":985,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-4"},"ee14ac96-7":{"renderedLength":909,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-6"},"ee14ac96-9":{"renderedLength":745,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-8"},"ee14ac96-11":{"renderedLength":8605,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-10"},"ee14ac96-13":{"renderedLength":2776,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-12"},"ee14ac96-15":{"renderedLength":2037,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-14"},"ee14ac96-17":{"renderedLength":2174,"gzipLength":0,"brotliLength":0,"metaUid":"ee14ac96-16"}},"nodeMetas":{"ee14ac96-0":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/cli.d.ts","moduleParts":{"cli.d.ts":"ee14ac96-1"},"imported":[],"importedBy":[],"isEntry":true},"ee14ac96-2":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/cli.ts","moduleParts":{"cli.js":"ee14ac96-3"},"imported":[{"uid":"ee14ac96-18"},{"uid":"ee14ac96-19"},{"uid":"ee14ac96-4"},{"uid":"ee14ac96-8"}],"importedBy":[],"isEntry":true},"ee14ac96-4":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/install.ts","moduleParts":{"commands/install.js":"ee14ac96-5"},"imported":[{"uid":"ee14ac96-20"},{"uid":"ee14ac96-14"},{"uid":"ee14ac96-16"},{"uid":"ee14ac96-6"}],"importedBy":[{"uid":"ee14ac96-2"}]},"ee14ac96-6":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/printer.ts","moduleParts":{"commands/printer.js":"ee14ac96-7"},"imported":[{"uid":"ee14ac96-21"}],"importedBy":[{"uid":"ee14ac96-4"},{"uid":"ee14ac96-8"}]},"ee14ac96-8":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/sync.ts","moduleParts":{"commands/sync.js":"ee14ac96-9"},"imported":[{"uid":"ee14ac96-16"},{"uid":"ee14ac96-14"},{"uid":"ee14ac96-6"}],"importedBy":[{"uid":"ee14ac96-2"}]},"ee14ac96-10":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/content/actions.ts","moduleParts":{"content/actions.js":"ee14ac96-11"},"imported":[],"importedBy":[{"uid":"ee14ac96-12"}]},"ee14ac96-12":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/content/index.ts","moduleParts":{"content/index.js":"ee14ac96-13"},"imported":[{"uid":"ee14ac96-10"}],"importedBy":[{"uid":"ee14ac96-14"}]},"ee14ac96-14":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/runner.ts","moduleParts":{"runner.js":"ee14ac96-15"},"imported":[{"uid":"ee14ac96-21"},{"uid":"ee14ac96-18"},{"uid":"ee14ac96-22"},{"uid":"ee14ac96-16"},{"uid":"ee14ac96-12"}],"importedBy":[{"uid":"ee14ac96-4"},{"uid":"ee14ac96-8"}]},"ee14ac96-16":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/tools.ts","moduleParts":{"tools.js":"ee14ac96-17"},"imported":[{"uid":"ee14ac96-18"},{"uid":"ee14ac96-21"}],"importedBy":[{"uid":"ee14ac96-4"},{"uid":"ee14ac96-8"},{"uid":"ee14ac96-14"}]},"ee14ac96-18":{"id":"node:fs","moduleParts":{},"imported":[],"importedBy":[{"uid":"ee14ac96-2"},{"uid":"ee14ac96-14"},{"uid":"ee14ac96-16"}]},"ee14ac96-19":{"id":"commander","moduleParts":{},"imported":[],"importedBy":[{"uid":"ee14ac96-2"}]},"ee14ac96-20":{"id":"@inquirer/prompts","moduleParts":{},"imported":[],"importedBy":[{"uid":"ee14ac96-4"}]},"ee14ac96-21":{"id":"node:path","moduleParts":{},"imported":[],"importedBy":[{"uid":"ee14ac96-14"},{"uid":"ee14ac96-16"},{"uid":"ee14ac96-6"}]},"ee14ac96-22":{"id":"node:fs/promises","moduleParts":{},"imported":[],"importedBy":[{"uid":"ee14ac96-14"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":false,"brotli":false,"sourcemap":false}};
4933
+ const data = {"version":2,"tree":{"name":"root","children":[{"name":"cli.d.ts","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/cli.d.ts","uid":"43280ddc-1"}]},{"name":"cli.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/cli.ts","uid":"43280ddc-3"}]},{"name":"commands/done.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/done.ts","uid":"43280ddc-5"}]},{"name":"commands/install.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/install.ts","uid":"43280ddc-7"}]},{"name":"commands/printer.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/printer.ts","uid":"43280ddc-9"}]},{"name":"commands/status.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/status.ts","uid":"43280ddc-11"}]},{"name":"commands/sync.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/sync.ts","uid":"43280ddc-13"}]},{"name":"commands/validate.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/commands/validate.ts","uid":"43280ddc-15"}]},{"name":"content/actions.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/content/actions.ts","uid":"43280ddc-17"}]},{"name":"content/index.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/content/index.ts","uid":"43280ddc-19"}]},{"name":"context/archiver.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/context/archiver.ts","uid":"43280ddc-21"}]},{"name":"context/reader.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/context/reader.ts","uid":"43280ddc-23"}]},{"name":"context/validator.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/context/validator.ts","uid":"43280ddc-25"}]},{"name":"runner.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/runner.ts","uid":"43280ddc-27"}]},{"name":"tools.js","children":[{"name":"home/whj/codes/cat-kit/packages/agent-context/src/tools.ts","uid":"43280ddc-29"}]}],"isRoot":true},"nodeParts":{"43280ddc-1":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-0"},"43280ddc-3":{"renderedLength":1518,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-2"},"43280ddc-5":{"renderedLength":1349,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-4"},"43280ddc-7":{"renderedLength":985,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-6"},"43280ddc-9":{"renderedLength":909,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-8"},"43280ddc-11":{"renderedLength":944,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-10"},"43280ddc-13":{"renderedLength":745,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-12"},"43280ddc-15":{"renderedLength":758,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-14"},"43280ddc-17":{"renderedLength":8890,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-16"},"43280ddc-19":{"renderedLength":2857,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-18"},"43280ddc-21":{"renderedLength":1012,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-20"},"43280ddc-23":{"renderedLength":1573,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-22"},"43280ddc-25":{"renderedLength":1039,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-24"},"43280ddc-27":{"renderedLength":2037,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-26"},"43280ddc-29":{"renderedLength":2174,"gzipLength":0,"brotliLength":0,"metaUid":"43280ddc-28"}},"nodeMetas":{"43280ddc-0":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/cli.d.ts","moduleParts":{"cli.d.ts":"43280ddc-1"},"imported":[],"importedBy":[],"isEntry":true},"43280ddc-2":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/cli.ts","moduleParts":{"cli.js":"43280ddc-3"},"imported":[{"uid":"43280ddc-30"},{"uid":"43280ddc-31"},{"uid":"43280ddc-4"},{"uid":"43280ddc-6"},{"uid":"43280ddc-10"},{"uid":"43280ddc-12"},{"uid":"43280ddc-14"}],"importedBy":[],"isEntry":true},"43280ddc-4":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/done.ts","moduleParts":{"commands/done.js":"43280ddc-5"},"imported":[{"uid":"43280ddc-32"},{"uid":"43280ddc-33"},{"uid":"43280ddc-34"}],"importedBy":[{"uid":"43280ddc-2"}]},"43280ddc-6":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/install.ts","moduleParts":{"commands/install.js":"43280ddc-7"},"imported":[{"uid":"43280ddc-33"},{"uid":"43280ddc-26"},{"uid":"43280ddc-28"},{"uid":"43280ddc-8"}],"importedBy":[{"uid":"43280ddc-2"}]},"43280ddc-8":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/printer.ts","moduleParts":{"commands/printer.js":"43280ddc-9"},"imported":[{"uid":"43280ddc-32"}],"importedBy":[{"uid":"43280ddc-6"},{"uid":"43280ddc-12"}]},"43280ddc-10":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/status.ts","moduleParts":{"commands/status.js":"43280ddc-11"},"imported":[{"uid":"43280ddc-34"}],"importedBy":[{"uid":"43280ddc-2"}]},"43280ddc-12":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/sync.ts","moduleParts":{"commands/sync.js":"43280ddc-13"},"imported":[{"uid":"43280ddc-28"},{"uid":"43280ddc-26"},{"uid":"43280ddc-8"}],"importedBy":[{"uid":"43280ddc-2"}]},"43280ddc-14":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/commands/validate.ts","moduleParts":{"commands/validate.js":"43280ddc-15"},"imported":[{"uid":"43280ddc-34"}],"importedBy":[{"uid":"43280ddc-2"}]},"43280ddc-16":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/content/actions.ts","moduleParts":{"content/actions.js":"43280ddc-17"},"imported":[],"importedBy":[{"uid":"43280ddc-18"}]},"43280ddc-18":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/content/index.ts","moduleParts":{"content/index.js":"43280ddc-19"},"imported":[{"uid":"43280ddc-16"}],"importedBy":[{"uid":"43280ddc-26"}]},"43280ddc-20":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/context/archiver.ts","moduleParts":{"context/archiver.js":"43280ddc-21"},"imported":[{"uid":"43280ddc-35"},{"uid":"43280ddc-32"}],"importedBy":[{"uid":"43280ddc-34"}]},"43280ddc-22":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/context/reader.ts","moduleParts":{"context/reader.js":"43280ddc-23"},"imported":[{"uid":"43280ddc-35"},{"uid":"43280ddc-30"},{"uid":"43280ddc-32"}],"importedBy":[{"uid":"43280ddc-34"}]},"43280ddc-24":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/context/validator.ts","moduleParts":{"context/validator.js":"43280ddc-25"},"imported":[{"uid":"43280ddc-30"},{"uid":"43280ddc-32"}],"importedBy":[{"uid":"43280ddc-34"}]},"43280ddc-26":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/runner.ts","moduleParts":{"runner.js":"43280ddc-27"},"imported":[{"uid":"43280ddc-32"},{"uid":"43280ddc-30"},{"uid":"43280ddc-35"},{"uid":"43280ddc-28"},{"uid":"43280ddc-18"}],"importedBy":[{"uid":"43280ddc-6"},{"uid":"43280ddc-12"}]},"43280ddc-28":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/tools.ts","moduleParts":{"tools.js":"43280ddc-29"},"imported":[{"uid":"43280ddc-30"},{"uid":"43280ddc-32"}],"importedBy":[{"uid":"43280ddc-6"},{"uid":"43280ddc-12"},{"uid":"43280ddc-26"}]},"43280ddc-30":{"id":"node:fs","moduleParts":{},"imported":[],"importedBy":[{"uid":"43280ddc-2"},{"uid":"43280ddc-26"},{"uid":"43280ddc-28"},{"uid":"43280ddc-22"},{"uid":"43280ddc-24"}]},"43280ddc-31":{"id":"commander","moduleParts":{},"imported":[],"importedBy":[{"uid":"43280ddc-2"}]},"43280ddc-32":{"id":"node:path","moduleParts":{},"imported":[],"importedBy":[{"uid":"43280ddc-4"},{"uid":"43280ddc-26"},{"uid":"43280ddc-28"},{"uid":"43280ddc-8"},{"uid":"43280ddc-22"},{"uid":"43280ddc-24"},{"uid":"43280ddc-20"}]},"43280ddc-33":{"id":"@inquirer/prompts","moduleParts":{},"imported":[],"importedBy":[{"uid":"43280ddc-4"},{"uid":"43280ddc-6"}]},"43280ddc-34":{"id":"/home/whj/codes/cat-kit/packages/agent-context/src/context/index.ts","moduleParts":{},"imported":[{"uid":"43280ddc-22"},{"uid":"43280ddc-24"},{"uid":"43280ddc-20"}],"importedBy":[{"uid":"43280ddc-4"},{"uid":"43280ddc-10"},{"uid":"43280ddc-14"}]},"43280ddc-35":{"id":"node:fs/promises","moduleParts":{},"imported":[],"importedBy":[{"uid":"43280ddc-26"},{"uid":"43280ddc-22"},{"uid":"43280ddc-20"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":false,"brotli":false,"sourcemap":false}};
4934
4934
 
4935
4935
  const run = () => {
4936
4936
  const width = window.innerWidth;
package/dist/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tools.js","names":[],"sources":["../src/tools.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport type { ToolId, ToolTarget } from './types'\n\nconst SKILL_FILE_NAME = 'SKILL.md'\nconst SKILL_NAME = 'ac-workflow'\n\nconst TOOL_TARGET_MAP: Record<ToolId, ToolTarget> = {\n claude: {\n id: 'claude',\n name: 'Claude Code',\n skillRootDir: '.claude/skills',\n frontmatterProfile: 'claude',\n metadataFiles: []\n },\n codex: {\n id: 'codex',\n name: 'Codex',\n skillRootDir: '.codex/skills',\n frontmatterProfile: 'standard',\n metadataFiles: ['openai']\n },\n cursor: {\n id: 'cursor',\n name: 'Cursor',\n skillRootDir: '.cursor/skills',\n frontmatterProfile: 'standard',\n metadataFiles: []\n },\n antigravity: {\n id: 'antigravity',\n name: 'Antigravity',\n skillRootDir: '.agent/skills',\n frontmatterProfile: 'standard',\n metadataFiles: []\n },\n copilot: {\n id: 'copilot',\n name: 'GitHub Copilot',\n skillRootDir: '.github/skills',\n frontmatterProfile: 'copilot',\n metadataFiles: []\n }\n}\n\nexport const DEFAULT_TOOL_ORDER: ToolId[] = ['claude', 'codex', 'cursor', 'antigravity', 'copilot']\n\nexport interface ToolChoice {\n id: ToolId\n name: string\n}\n\nexport function getToolChoices(): ToolChoice[] {\n return DEFAULT_TOOL_ORDER.map((id) => ({ id, name: TOOL_TARGET_MAP[id].name }))\n}\n\nexport function parseToolIds(toolsText: string): ToolId[] {\n const parsed = toolsText\n .split(',')\n .map((item) => item.trim().toLowerCase())\n .filter(Boolean)\n\n if (parsed.length === 0) {\n return [...DEFAULT_TOOL_ORDER]\n }\n\n const uniqueIds: ToolId[] = []\n\n for (const value of parsed) {\n if (!isToolId(value)) {\n throw new Error(`不支持的工具标识: ${value}。可选值: ${DEFAULT_TOOL_ORDER.join(', ')}`)\n }\n\n if (!uniqueIds.includes(value)) {\n uniqueIds.push(value)\n }\n }\n\n return uniqueIds\n}\n\nexport function resolveToolTargets(tools?: ToolId[]): ToolTarget[] {\n const selected = tools && tools.length > 0 ? tools : DEFAULT_TOOL_ORDER\n return selected.map((id) => ({ ...TOOL_TARGET_MAP[id] }))\n}\n\nexport function detectConfiguredToolIds(cwd: string): ToolId[] {\n return DEFAULT_TOOL_ORDER.filter((toolId) => {\n const target = TOOL_TARGET_MAP[toolId]\n return existsSync(resolveSkillPaths(target, cwd).skillFile)\n })\n}\n\n// ── Skill 路径解析 ───────────────────────────────────\n\nexport interface SkillPaths {\n skillDir: string\n skillFile: string\n openaiMetadataFile: string\n}\n\nexport function resolveSkillPaths(target: ToolTarget, cwd: string): SkillPaths {\n const skillDir = resolve(cwd, target.skillRootDir, SKILL_NAME)\n return {\n skillDir,\n skillFile: resolve(skillDir, SKILL_FILE_NAME),\n openaiMetadataFile: resolve(skillDir, 'agents/openai.yaml')\n }\n}\n\nfunction isToolId(value: string): value is ToolId {\n return Object.hasOwn(TOOL_TARGET_MAP, value)\n}\n"],"mappings":"yEAKA,MAGM,EAA8C,CAClD,OAAQ,CACN,GAAI,SACJ,KAAM,cACN,aAAc,iBACd,mBAAoB,SACpB,cAAe,EAAE,CAClB,CACD,MAAO,CACL,GAAI,QACJ,KAAM,QACN,aAAc,gBACd,mBAAoB,WACpB,cAAe,CAAC,SAAS,CAC1B,CACD,OAAQ,CACN,GAAI,SACJ,KAAM,SACN,aAAc,iBACd,mBAAoB,WACpB,cAAe,EAAE,CAClB,CACD,YAAa,CACX,GAAI,cACJ,KAAM,cACN,aAAc,gBACd,mBAAoB,WACpB,cAAe,EAAE,CAClB,CACD,QAAS,CACP,GAAI,UACJ,KAAM,iBACN,aAAc,iBACd,mBAAoB,UACpB,cAAe,EAAE,CAClB,CACF,CAEY,EAA+B,CAAC,SAAU,QAAS,SAAU,cAAe,UAAU,CAOnG,SAAgB,GAA+B,CAC7C,OAAO,EAAmB,IAAK,IAAQ,CAAE,KAAI,KAAM,EAAgB,GAAI,KAAM,EAAE,CAGjF,SAAgB,EAAa,EAA6B,CACxD,IAAM,EAAS,EACZ,MAAM,IAAI,CACV,IAAK,GAAS,EAAK,MAAM,CAAC,aAAa,CAAC,CACxC,OAAO,QAAQ,CAElB,GAAI,EAAO,SAAW,EACpB,MAAO,CAAC,GAAG,EAAmB,CAGhC,IAAM,EAAsB,EAAE,CAE9B,IAAK,IAAM,KAAS,EAAQ,CAC1B,GAAI,CAAC,EAAS,EAAM,CAClB,MAAU,MAAM,aAAa,EAAM,QAAQ,EAAmB,KAAK,KAAK,GAAG,CAGxE,EAAU,SAAS,EAAM,EAC5B,EAAU,KAAK,EAAM,CAIzB,OAAO,EAGT,SAAgB,EAAmB,EAAgC,CAEjE,OADiB,GAAS,EAAM,OAAS,EAAI,EAAQ,GACrC,IAAK,IAAQ,CAAE,GAAG,EAAgB,GAAK,EAAE,CAG3D,SAAgB,EAAwB,EAAuB,CAC7D,OAAO,EAAmB,OAAQ,GAAW,CAC3C,IAAM,EAAS,EAAgB,GAC/B,OAAO,EAAW,EAAkB,EAAQ,EAAI,CAAC,UAAU,EAC3D,CAWJ,SAAgB,EAAkB,EAAoB,EAAyB,CAC7E,IAAM,EAAW,EAAQ,EAAK,EAAO,aAAc,cAAW,CAC9D,MAAO,CACL,WACA,UAAW,EAAQ,EAAU,WAAgB,CAC7C,mBAAoB,EAAQ,EAAU,qBAAqB,CAC5D,CAGH,SAAS,EAAS,EAAgC,CAChD,OAAO,OAAO,OAAO,EAAiB,EAAM"}
1
+ {"version":3,"file":"tools.js","names":[],"sources":["../src/tools.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport type { ToolId, ToolTarget } from './types.js'\n\nconst SKILL_FILE_NAME = 'SKILL.md'\nconst SKILL_NAME = 'ac-workflow'\n\nconst TOOL_TARGET_MAP: Record<ToolId, ToolTarget> = {\n claude: {\n id: 'claude',\n name: 'Claude Code',\n skillRootDir: '.claude/skills',\n frontmatterProfile: 'claude',\n metadataFiles: []\n },\n codex: {\n id: 'codex',\n name: 'Codex',\n skillRootDir: '.codex/skills',\n frontmatterProfile: 'standard',\n metadataFiles: ['openai']\n },\n cursor: {\n id: 'cursor',\n name: 'Cursor',\n skillRootDir: '.cursor/skills',\n frontmatterProfile: 'standard',\n metadataFiles: []\n },\n antigravity: {\n id: 'antigravity',\n name: 'Antigravity',\n skillRootDir: '.agent/skills',\n frontmatterProfile: 'standard',\n metadataFiles: []\n },\n copilot: {\n id: 'copilot',\n name: 'GitHub Copilot',\n skillRootDir: '.github/skills',\n frontmatterProfile: 'copilot',\n metadataFiles: []\n }\n}\n\nexport const DEFAULT_TOOL_ORDER: ToolId[] = ['claude', 'codex', 'cursor', 'antigravity', 'copilot']\n\nexport interface ToolChoice {\n id: ToolId\n name: string\n}\n\nexport function getToolChoices(): ToolChoice[] {\n return DEFAULT_TOOL_ORDER.map((id) => ({ id, name: TOOL_TARGET_MAP[id].name }))\n}\n\nexport function parseToolIds(toolsText: string): ToolId[] {\n const parsed = toolsText\n .split(',')\n .map((item) => item.trim().toLowerCase())\n .filter(Boolean)\n\n if (parsed.length === 0) {\n return [...DEFAULT_TOOL_ORDER]\n }\n\n const uniqueIds: ToolId[] = []\n\n for (const value of parsed) {\n if (!isToolId(value)) {\n throw new Error(`不支持的工具标识: ${value}。可选值: ${DEFAULT_TOOL_ORDER.join(', ')}`)\n }\n\n if (!uniqueIds.includes(value)) {\n uniqueIds.push(value)\n }\n }\n\n return uniqueIds\n}\n\nexport function resolveToolTargets(tools?: ToolId[]): ToolTarget[] {\n const selected = tools && tools.length > 0 ? tools : DEFAULT_TOOL_ORDER\n return selected.map((id) => ({ ...TOOL_TARGET_MAP[id] }))\n}\n\nexport function detectConfiguredToolIds(cwd: string): ToolId[] {\n return DEFAULT_TOOL_ORDER.filter((toolId) => {\n const target = TOOL_TARGET_MAP[toolId]\n return existsSync(resolveSkillPaths(target, cwd).skillFile)\n })\n}\n\n// ── Skill 路径解析 ───────────────────────────────────\n\nexport interface SkillPaths {\n skillDir: string\n skillFile: string\n openaiMetadataFile: string\n}\n\nexport function resolveSkillPaths(target: ToolTarget, cwd: string): SkillPaths {\n const skillDir = resolve(cwd, target.skillRootDir, SKILL_NAME)\n return {\n skillDir,\n skillFile: resolve(skillDir, SKILL_FILE_NAME),\n openaiMetadataFile: resolve(skillDir, 'agents/openai.yaml')\n }\n}\n\nfunction isToolId(value: string): value is ToolId {\n return Object.hasOwn(TOOL_TARGET_MAP, value)\n}\n"],"mappings":"yEAKA,MAGM,EAA8C,CAClD,OAAQ,CACN,GAAI,SACJ,KAAM,cACN,aAAc,iBACd,mBAAoB,SACpB,cAAe,EAAE,CAClB,CACD,MAAO,CACL,GAAI,QACJ,KAAM,QACN,aAAc,gBACd,mBAAoB,WACpB,cAAe,CAAC,SAAS,CAC1B,CACD,OAAQ,CACN,GAAI,SACJ,KAAM,SACN,aAAc,iBACd,mBAAoB,WACpB,cAAe,EAAE,CAClB,CACD,YAAa,CACX,GAAI,cACJ,KAAM,cACN,aAAc,gBACd,mBAAoB,WACpB,cAAe,EAAE,CAClB,CACD,QAAS,CACP,GAAI,UACJ,KAAM,iBACN,aAAc,iBACd,mBAAoB,UACpB,cAAe,EAAE,CAClB,CACF,CAEY,EAA+B,CAAC,SAAU,QAAS,SAAU,cAAe,UAAU,CAOnG,SAAgB,GAA+B,CAC7C,OAAO,EAAmB,IAAK,IAAQ,CAAE,KAAI,KAAM,EAAgB,GAAI,KAAM,EAAE,CAGjF,SAAgB,EAAa,EAA6B,CACxD,IAAM,EAAS,EACZ,MAAM,IAAI,CACV,IAAK,GAAS,EAAK,MAAM,CAAC,aAAa,CAAC,CACxC,OAAO,QAAQ,CAElB,GAAI,EAAO,SAAW,EACpB,MAAO,CAAC,GAAG,EAAmB,CAGhC,IAAM,EAAsB,EAAE,CAE9B,IAAK,IAAM,KAAS,EAAQ,CAC1B,GAAI,CAAC,EAAS,EAAM,CAClB,MAAU,MAAM,aAAa,EAAM,QAAQ,EAAmB,KAAK,KAAK,GAAG,CAGxE,EAAU,SAAS,EAAM,EAC5B,EAAU,KAAK,EAAM,CAIzB,OAAO,EAGT,SAAgB,EAAmB,EAAgC,CAEjE,OADiB,GAAS,EAAM,OAAS,EAAI,EAAQ,GACrC,IAAK,IAAQ,CAAE,GAAG,EAAgB,GAAK,EAAE,CAG3D,SAAgB,EAAwB,EAAuB,CAC7D,OAAO,EAAmB,OAAQ,GAAW,CAC3C,IAAM,EAAS,EAAgB,GAC/B,OAAO,EAAW,EAAkB,EAAQ,EAAI,CAAC,UAAU,EAC3D,CAWJ,SAAgB,EAAkB,EAAoB,EAAyB,CAC7E,IAAM,EAAW,EAAQ,EAAK,EAAO,aAAc,cAAW,CAC9D,MAAO,CACL,WACA,UAAW,EAAQ,EAAU,WAAgB,CAC7C,mBAAoB,EAAQ,EAAU,qBAAqB,CAC5D,CAGH,SAAS,EAAS,EAAgC,CAChD,OAAO,OAAO,OAAO,EAAiB,EAAM"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-kit/agent-context",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "代理上下文管理工具",
5
5
  "bin": {
6
6
  "agent-context": "./dist/cli.js"
@@ -13,7 +13,7 @@
13
13
  "type": "module",
14
14
  "scripts": {
15
15
  "build": "tsc -p tsconfig.json",
16
- "clean": "rm -rf dist"
16
+ "clean": "rm -rf dist node_modules/.cache/.tsbuildinfo"
17
17
  },
18
18
  "dependencies": {
19
19
  "@inquirer/prompts": "^8.3.0",
package/src/cli.ts CHANGED
@@ -4,8 +4,11 @@ import { readFileSync } from 'node:fs'
4
4
 
5
5
  import { Command } from 'commander'
6
6
 
7
- import { installCommand } from './commands/install'
8
- import { syncCommand } from './commands/sync'
7
+ import { doneCommand } from './commands/done.js'
8
+ import { installCommand } from './commands/install.js'
9
+ import { statusCommand } from './commands/status.js'
10
+ import { syncCommand } from './commands/sync.js'
11
+ import { validateCommand } from './commands/validate.js'
9
12
 
10
13
  const packageJson = JSON.parse(
11
14
  readFileSync(new URL('../package.json', import.meta.url), 'utf8')
@@ -31,6 +34,22 @@ program
31
34
  .option('--check', '仅检查是否存在待更新内容,不写入文件')
32
35
  .action(syncCommand)
33
36
 
37
+ program
38
+ .command('validate')
39
+ .description('校验 .agent-context 目录结构')
40
+ .action(validateCommand)
41
+
42
+ program
43
+ .command('status')
44
+ .description('查看当前 agent-context 状态')
45
+ .action(statusCommand)
46
+
47
+ program
48
+ .command('done')
49
+ .description('归档当前已执行计划')
50
+ .option('--yes', '跳过确认,直接归档')
51
+ .action(doneCommand)
52
+
34
53
  program.parseAsync().catch((error: unknown) => {
35
54
  const message = error instanceof Error ? error.message : String(error)
36
55
  console.error(`\n❌ ${message}`) // eslint-disable-line no-console
@@ -0,0 +1,55 @@
1
+ import { basename } from 'node:path'
2
+
3
+ import { confirm } from '@inquirer/prompts'
4
+
5
+ import { archive, readRawContext, validate } from '../context/index.js'
6
+
7
+ export async function doneCommand(options: { yes?: boolean }): Promise<void> {
8
+ const { snapshot, currentPlanCount } = await readRawContext(process.cwd())
9
+ const result = validate(snapshot, currentPlanCount)
10
+
11
+ if (!result.valid) {
12
+ for (const error of result.errors) {
13
+ console.log(`❌ ${error}`) // eslint-disable-line no-console
14
+ }
15
+ process.exitCode = 1
16
+ return
17
+ }
18
+
19
+ if (!snapshot || !snapshot.currentPlan) {
20
+ console.log('❌ 无当前计划') // eslint-disable-line no-console
21
+ process.exitCode = 1
22
+ return
23
+ }
24
+
25
+ if (snapshot.currentPlan.status !== '已执行') {
26
+ console.log(`❌ 当前计划 plan-${snapshot.currentPlan.number} 尚未执行,无法归档。`) // eslint-disable-line no-console
27
+ process.exitCode = 1
28
+ return
29
+ }
30
+
31
+ if (!options.yes) {
32
+ const confirmed = await confirm({
33
+ message: `确认归档 plan-${snapshot.currentPlan.number}?`
34
+ })
35
+ if (!confirmed) {
36
+ console.log('已取消') // eslint-disable-line no-console
37
+ return
38
+ }
39
+ }
40
+
41
+ const archiveResult = await archive(snapshot)
42
+ const archiveName = basename(archiveResult.archivedTo)
43
+
44
+ console.log(`✅ 已归档: plan-${snapshot.currentPlan.number} → done/${archiveName}`) // eslint-disable-line no-console
45
+
46
+ if (archiveResult.promoted !== null) {
47
+ console.log(`📋 已晋升: plan-${archiveResult.promoted} 为新的当前计划`) // eslint-disable-line no-console
48
+ }
49
+
50
+ if (archiveResult.remainingPreparing > 0) {
51
+ console.log(`📋 待执行队列剩余 ${archiveResult.remainingPreparing} 个计划`) // eslint-disable-line no-console
52
+ } else if (archiveResult.promoted === null) {
53
+ console.log('ℹ 无更多待执行计划') // eslint-disable-line no-console
54
+ }
55
+ }
@@ -1,9 +1,9 @@
1
1
  import { checkbox } from '@inquirer/prompts'
2
2
 
3
- import { runInstall } from '../runner'
4
- import { DEFAULT_TOOL_ORDER, detectConfiguredToolIds, getToolChoices, parseToolIds } from '../tools'
5
- import type { ToolId } from '../types'
6
- import { printCheckResult, printRunSummary } from './printer'
3
+ import { runInstall } from '../runner.js'
4
+ import { DEFAULT_TOOL_ORDER, detectConfiguredToolIds, getToolChoices, parseToolIds } from '../tools.js'
5
+ import type { ToolId } from '../types.js'
6
+ import { printCheckResult, printRunSummary } from './printer.js'
7
7
 
8
8
  export interface InstallCommandOptions {
9
9
  tools?: string
@@ -1,6 +1,6 @@
1
1
  import { relative } from 'node:path'
2
2
 
3
- import type { RunResult } from '../types'
3
+ import type { RunResult } from '../types.js'
4
4
 
5
5
  export function printRunSummary(result: RunResult, cwd: string): void {
6
6
  console.log(`\n✅ ac-workflow ${result.mode} 完成`) // eslint-disable-line no-console
@@ -0,0 +1,35 @@
1
+ import { readRawContext, validate } from '../context/index.js'
2
+
3
+ export async function statusCommand(): Promise<void> {
4
+ const { snapshot, currentPlanCount } = await readRawContext(process.cwd())
5
+ const result = validate(snapshot, currentPlanCount)
6
+
7
+ if (!result.valid) {
8
+ for (const error of result.errors) {
9
+ console.log(`❌ ${error}`) // eslint-disable-line no-console
10
+ }
11
+ process.exitCode = 1
12
+ return
13
+ }
14
+
15
+ if (result.context === null) {
16
+ console.log('ℹ 无活跃上下文') // eslint-disable-line no-console
17
+ return
18
+ }
19
+
20
+ const ctx = result.context
21
+ const current = ctx.currentPlan
22
+ ? `plan-${ctx.currentPlan.number} (${ctx.currentPlan.status})`
23
+ : '无'
24
+ const preparing =
25
+ ctx.preparing.length > 0
26
+ ? ctx.preparing.map((p) => `plan-${p.number}`).join(', ')
27
+ : '无'
28
+
29
+ console.log('') // eslint-disable-line no-console
30
+ console.log('Agent Context Status') // eslint-disable-line no-console
31
+ console.log('────────────────────') // eslint-disable-line no-console
32
+ console.log(`当前计划: ${current}`) // eslint-disable-line no-console
33
+ console.log(`待执行队列: ${preparing}`) // eslint-disable-line no-console
34
+ console.log(`已归档: ${ctx.doneCount} 个`) // eslint-disable-line no-console
35
+ }
@@ -1,7 +1,7 @@
1
- import { detectConfiguredToolIds, parseToolIds } from '../tools'
2
- import type { ToolId } from '../types'
3
- import { runSync } from '../runner'
4
- import { printCheckResult, printRunSummary } from './printer'
1
+ import { detectConfiguredToolIds, parseToolIds } from '../tools.js'
2
+ import type { ToolId } from '../types.js'
3
+ import { runSync } from '../runner.js'
4
+ import { printCheckResult, printRunSummary } from './printer.js'
5
5
 
6
6
  export interface SyncCommandOptions {
7
7
  tools?: string
@@ -0,0 +1,28 @@
1
+ import { readRawContext, validate } from '../context/index.js'
2
+
3
+ export async function validateCommand(): Promise<void> {
4
+ const { snapshot, currentPlanCount } = await readRawContext(process.cwd())
5
+ const result = validate(snapshot, currentPlanCount)
6
+
7
+ if (result.context === null) {
8
+ console.log('ℹ 无 .agent-context 目录') // eslint-disable-line no-console
9
+ return
10
+ }
11
+
12
+ if (result.valid) {
13
+ console.log('✅ 校验通过') // eslint-disable-line no-console
14
+ const ctx = result.context
15
+ const current = ctx.currentPlan
16
+ ? `plan-${ctx.currentPlan.number} (${ctx.currentPlan.status})`
17
+ : '无'
18
+ console.log(` 当前计划: ${current}`) // eslint-disable-line no-console
19
+ console.log(` 待执行: ${ctx.preparing.length} 个`) // eslint-disable-line no-console
20
+ console.log(` 已归档: ${ctx.doneCount} 个`) // eslint-disable-line no-console
21
+ return
22
+ }
23
+
24
+ for (const error of result.errors) {
25
+ console.log(`❌ ${error}`) // eslint-disable-line no-console
26
+ }
27
+ process.exitCode = 1
28
+ }
@@ -1,4 +1,4 @@
1
- export const ACTION_NAMES = ['init', 'plan', 'replan', 'implement', 'patch', 'done'] as const
1
+ export const ACTION_NAMES = ['init', 'plan', 'replan', 'implement', 'patch', 'rush'] as const
2
2
  type ActionName = (typeof ACTION_NAMES)[number]
3
3
 
4
4
  export const ACTION_RENDERERS: Record<ActionName, () => string> = {
@@ -7,7 +7,7 @@ export const ACTION_RENDERERS: Record<ActionName, () => string> = {
7
7
  replan: renderReplan,
8
8
  implement: renderImplement,
9
9
  patch: renderPatch,
10
- done: renderDone
10
+ rush: renderRush
11
11
  }
12
12
 
13
13
  function renderInit(): string {
@@ -56,8 +56,9 @@ function renderPlan(): string {
56
56
 
57
57
  ## 前置检查
58
58
 
59
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
59
60
  - 描述为空 → 拒绝执行。
60
- - 存在未归档的已执行当前计划 → 拒绝执行,提示先归档。
61
+ - 存在未归档的已执行当前计划 → 拒绝执行,提示先运行 \`agent-context done\` 归档。
61
62
  - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
62
63
 
63
64
  ## 执行步骤
@@ -109,6 +110,7 @@ function renderReplan(): string {
109
110
 
110
111
  ## 前置检查
111
112
 
113
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
112
114
  - 描述为空 → 拒绝执行。
113
115
  - 无未实施计划 → 拒绝执行,提示使用 plan 创建。
114
116
  - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
@@ -141,9 +143,10 @@ function renderImplement(): string {
141
143
 
142
144
  ## 前置检查
143
145
 
146
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
144
147
  - 带描述 → 拒绝执行。
145
148
  - 当前计划不存在 → 拒绝执行,提示先创建计划。
146
- - 当前计划状态为 \`已执行\` → 拒绝执行,提示使用 patch 或归档。
149
+ - 当前计划状态为 \`已执行\` → 拒绝执行,提示使用 patch 修补或运行 \`agent-context done\` 归档。
147
150
  - \`## 目标\` 或 \`## 内容\` 为空 → 拒绝执行,提示补充。
148
151
  - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
149
152
  - 仅操作当前计划,不直接操作 \`preparing/\` 中的计划。
@@ -172,6 +175,7 @@ function renderPatch(): string {
172
175
 
173
176
  ## 前置检查
174
177
 
178
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
175
179
  - 描述为空 → 拒绝执行。
176
180
  - 当前计划不存在 → 拒绝执行,提示先创建计划。
177
181
  - 当前计划状态为 \`未执行\` → 拒绝执行,提示先实施。
@@ -206,27 +210,29 @@ function renderPatch(): string {
206
210
  `
207
211
  }
208
212
 
209
- function renderDone(): string {
210
- return `# done
213
+ function renderRush(): string {
214
+ return `# rush
211
215
 
212
- 确认当前已执行计划真正完成,归档到 \`.agent-context/done/\` 目录,并自动晋升下一个计划。
216
+ 快速通道:创建计划并立即实施,适合范围明确、无需多轮规划的任务。
213
217
 
214
- 不接受额外描述。
218
+ 必须附带任务描述。
215
219
 
216
220
  ## 前置检查
217
221
 
218
- - 带描述 拒绝执行。
219
- - 当前计划不存在拒绝执行,提示先创建计划。
220
- - 当前计划状态为 \`未执行\` 拒绝执行,提示先实施。
221
- - 存在多个当前计划拒绝执行,提示恢复单活跃状态。
222
- - 必须得到用户确认后才可归档。
222
+ - 运行 \`agent-context validate\`,不通过则中止并报告错误。
223
+ - 描述为空拒绝执行。
224
+ - 存在未归档的已执行当前计划拒绝执行,提示先运行 \`agent-context done\` 归档。
225
+ - 存在未实施的当前计划拒绝执行,提示先 implement 或 replan。
223
226
 
224
227
  ## 执行步骤
225
228
 
226
- 1. **用户确认**:向用户确认当前计划已真正完成。
227
- 2. **归档**:将 \`.agent-context/plan-{number}\` 移动到 \`.agent-context/done/plan-{number}-{YYYYMMDD}\`(当日日期),包含完整 \`plan.md\` 与所有 \`patch-{number}.md\`。
228
- 3. **晋升**:若 \`.agent-context/preparing/\` 非空,将最小编号计划移至 \`.agent-context/\` 作为新当前计划。
229
- 4. **校验**:确认归档完整,晋升后仍满足单当前计划约束;失败则回滚。
230
- 5. **反馈**:报告归档路径、是否晋升及晋升编号、是否还有待执行计划。
229
+ 1. 按 plan 协议创建单计划(不拆分,不进入 preparing 队列)。
230
+ 2. 无需用户确认计划内容,直接进入 implement 流程。
231
+ 3. implement 协议执行全部步骤,包括验证循环:
232
+ a. 逐项对照 \`## 内容\` 确认每个步骤已实施。
233
+ b. 运行项目验证:类型检查 → lint → 测试。
234
+ c. 若存在失败项 → 修复后重新验证。
235
+ d. 全部通过 → 进入步骤 4。
236
+ 4. 更新 \`plan.md\` 状态行为 \`已执行\`,更新 \`## 影响范围\`。
231
237
  `
232
238
  }
@@ -1,9 +1,9 @@
1
- import type { SkillArtifacts, ToolTarget } from '../types'
2
- import { ACTION_NAMES, ACTION_RENDERERS } from './actions'
1
+ import type { SkillArtifacts, ToolTarget } from '../types.js'
2
+ import { ACTION_NAMES, ACTION_RENDERERS } from './actions.js'
3
3
 
4
4
  const SKILL_NAME = 'ac-workflow'
5
5
  const SKILL_DESCRIPTION =
6
- '管理 .agent-context 计划生命周期,按 init、plan、replan、implement、patch、done 协议推进任务。'
6
+ '管理 .agent-context 计划生命周期,按 init、plan、replan、implement、patch、rush、done 协议推进任务。'
7
7
 
8
8
  export function renderSkillArtifacts(target: ToolTarget): SkillArtifacts {
9
9
  const files: SkillArtifacts['files'] = [
@@ -38,7 +38,8 @@ function renderNavigator(target: ToolTarget): string {
38
38
  | 重做计划、调整方案 | replan | \`actions/replan.md\` |
39
39
  | 按计划开始做、实现当前计划 | implement | \`actions/implement.md\` |
40
40
  | 补一个小改动、在当前结果上修 | patch | \`actions/patch.md\` |
41
- | 任务彻底完成、归档当前计划 | done | \`actions/done.md\` |
41
+ | 快速出计划并实施 | rush | \`actions/rush.md\` |
42
+ | 任务彻底完成、归档当前计划 | done | 运行 \`agent-context done\` |
42
43
 
43
44
  ## 全局约束
44
45
 
@@ -85,7 +86,7 @@ function renderOpenAIMetadata(): string {
85
86
  return `interface:
86
87
  display_name: "Agent Context"
87
88
  short_description: "统一管理 .agent-context 计划生命周期"
88
- default_prompt: "Use $ac-workflow to manage the current task through init, plan, replan, implement, patch, or done."
89
+ default_prompt: "Use $ac-workflow to manage the current task through init, plan, replan, implement, patch, rush, or done."
89
90
 
90
91
  policy:
91
92
  allow_implicit_invocation: true
@@ -0,0 +1,45 @@
1
+ import { rename, mkdir } from 'node:fs/promises'
2
+ import { join } from 'node:path'
3
+
4
+ import type { ArchiveResult, ContextSnapshot } from '../types.js'
5
+
6
+ export async function archive(context: ContextSnapshot): Promise<ArchiveResult> {
7
+ if (!context.currentPlan) {
8
+ throw new Error('无当前计划')
9
+ }
10
+
11
+ if (context.currentPlan.status !== '已执行') {
12
+ throw new Error('当前计划尚未执行')
13
+ }
14
+
15
+ const archiveName = `plan-${context.currentPlan.number}-${formatDate()}`
16
+ const doneDir = join(context.root, 'done')
17
+ const archivedTo = join(doneDir, archiveName)
18
+
19
+ await mkdir(doneDir, { recursive: true })
20
+ await rename(context.currentPlan.dir, archivedTo)
21
+
22
+ let promoted: number | null = null
23
+ const first = context.preparing[0]
24
+ if (first) {
25
+ const targetDir = join(context.root, `plan-${first.number}`)
26
+ await rename(first.dir, targetDir)
27
+ promoted = first.number
28
+ }
29
+
30
+ return {
31
+ archivedTo,
32
+ promoted,
33
+ remainingPreparing: context.preparing.length - (promoted !== null ? 1 : 0)
34
+ }
35
+ }
36
+
37
+ // ── Helpers ──────────────────────────────────────────
38
+
39
+ function formatDate(): string {
40
+ const d = new Date()
41
+ const y = String(d.getFullYear())
42
+ const m = String(d.getMonth() + 1).padStart(2, '0')
43
+ const day = String(d.getDate()).padStart(2, '0')
44
+ return `${y}${m}${day}`
45
+ }
@@ -0,0 +1,3 @@
1
+ export { readContext, readRawContext, readPlanStatus } from './reader.js'
2
+ export { validate } from './validator.js'
3
+ export { archive } from './archiver.js'
@@ -0,0 +1,77 @@
1
+ import { readdir, readFile } from 'node:fs/promises'
2
+ import { existsSync } from 'node:fs'
3
+ import { join } from 'node:path'
4
+
5
+ import type { ContextSnapshot, PlanInfo, PlanStatus } from '../types.js'
6
+
7
+ const PLAN_DIR_RE = /^plan-(\d+)$/
8
+ const STATUS_RE = /^>\s*状态:\s*(未执行|已执行)\s*$/m
9
+
10
+ // ── Public API ───────────────────────────────────────
11
+
12
+ export async function readContext(cwd: string): Promise<ContextSnapshot | null> {
13
+ const { snapshot } = await readRawContext(cwd)
14
+ return snapshot
15
+ }
16
+
17
+ export async function readRawContext(
18
+ cwd: string
19
+ ): Promise<{ snapshot: ContextSnapshot | null; currentPlanCount: number }> {
20
+ const root = join(cwd, '.agent-context')
21
+
22
+ if (!existsSync(root)) {
23
+ return { snapshot: null, currentPlanCount: 0 }
24
+ }
25
+
26
+ const currentPlans = await readPlanDirs(root)
27
+ const preparing = await readPlanDirs(join(root, 'preparing'))
28
+ const doneCount = await countDirs(join(root, 'done'))
29
+
30
+ const snapshot: ContextSnapshot = {
31
+ root,
32
+ currentPlan: currentPlans[0] ?? null,
33
+ preparing,
34
+ doneCount
35
+ }
36
+
37
+ return { snapshot, currentPlanCount: currentPlans.length }
38
+ }
39
+
40
+ export async function readPlanStatus(planDir: string): Promise<PlanStatus> {
41
+ const planFile = join(planDir, 'plan.md')
42
+
43
+ if (!existsSync(planFile)) {
44
+ return '未执行'
45
+ }
46
+
47
+ const content = await readFile(planFile, 'utf-8')
48
+ const match = content.match(STATUS_RE)
49
+ return match ? (match[1] as PlanStatus) : '未执行'
50
+ }
51
+
52
+ // ── Helpers ──────────────────────────────────────────
53
+
54
+ async function readPlanDirs(parentDir: string): Promise<PlanInfo[]> {
55
+ if (!existsSync(parentDir)) return []
56
+
57
+ const entries = await readdir(parentDir, { withFileTypes: true })
58
+ const plans: PlanInfo[] = []
59
+
60
+ for (const entry of entries) {
61
+ if (!entry.isDirectory()) continue
62
+ const match = entry.name.match(PLAN_DIR_RE)
63
+ if (!match?.[1]) continue
64
+ const number = parseInt(match[1], 10)
65
+ const dir = join(parentDir, entry.name)
66
+ const status = await readPlanStatus(dir)
67
+ plans.push({ number, status, dir })
68
+ }
69
+
70
+ return plans.sort((a, b) => a.number - b.number)
71
+ }
72
+
73
+ async function countDirs(dir: string): Promise<number> {
74
+ if (!existsSync(dir)) return 0
75
+ const entries = await readdir(dir, { withFileTypes: true })
76
+ return entries.filter(e => e.isDirectory()).length
77
+ }
@@ -0,0 +1,44 @@
1
+ import { existsSync } from 'node:fs'
2
+ import { join } from 'node:path'
3
+
4
+ import type { ContextSnapshot, ValidateResult } from '../types.js'
5
+
6
+ export function validate(
7
+ snapshot: ContextSnapshot | null,
8
+ currentPlanCount: number
9
+ ): ValidateResult {
10
+ if (snapshot === null) {
11
+ return { valid: true, errors: [], context: null }
12
+ }
13
+
14
+ const errors: string[] = []
15
+
16
+ if (currentPlanCount > 1) {
17
+ errors.push(`存在 ${currentPlanCount} 个当前计划,应最多 1 个。`)
18
+ }
19
+
20
+ if (snapshot.currentPlan) {
21
+ const planMd = join(snapshot.currentPlan.dir, 'plan.md')
22
+ if (!existsSync(planMd)) {
23
+ errors.push(`当前计划 plan-${snapshot.currentPlan.number} 缺少 plan.md。`)
24
+ }
25
+ }
26
+
27
+ const allNumbers: number[] = []
28
+ if (snapshot.currentPlan) allNumbers.push(snapshot.currentPlan.number)
29
+ for (const p of snapshot.preparing) allNumbers.push(p.number)
30
+
31
+ const seen = new Set<number>()
32
+ const duplicates = new Set<number>()
33
+ for (const n of allNumbers) {
34
+ if (seen.has(n)) duplicates.add(n)
35
+ seen.add(n)
36
+ }
37
+
38
+ if (duplicates.size > 0) {
39
+ const nums = [...duplicates].sort((a, b) => a - b).join(', ')
40
+ errors.push(`计划编号冲突: ${nums}。`)
41
+ }
42
+
43
+ return { valid: errors.length === 0, errors, context: snapshot }
44
+ }
package/src/runner.ts CHANGED
@@ -2,10 +2,10 @@ import { resolve, dirname } from 'node:path'
2
2
  import { existsSync } from 'node:fs'
3
3
  import { mkdir, readFile, writeFile } from 'node:fs/promises'
4
4
 
5
- import type { SkillPaths } from './tools'
6
- import { resolveToolTargets, resolveSkillPaths } from './tools'
7
- import { renderSkillArtifacts } from './content'
8
- import type { ApplyMutationResult, FileMutation, RunOptions, RunResult, ToolId, ToolTarget } from './types'
5
+ import type { SkillPaths } from './tools.js'
6
+ import { resolveToolTargets, resolveSkillPaths } from './tools.js'
7
+ import { renderSkillArtifacts } from './content/index.js'
8
+ import type { ApplyMutationResult, FileMutation, RunOptions, RunResult, ToolId, ToolTarget } from './types.js'
9
9
 
10
10
  export async function runInstall(options: RunOptions = {}): Promise<RunResult> {
11
11
  return run('install', options)
package/src/tools.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { existsSync } from 'node:fs'
2
2
  import { resolve } from 'node:path'
3
3
 
4
- import type { ToolId, ToolTarget } from './types'
4
+ import type { ToolId, ToolTarget } from './types.js'
5
5
 
6
6
  const SKILL_FILE_NAME = 'SKILL.md'
7
7
  const SKILL_NAME = 'ac-workflow'
package/src/types.ts CHANGED
@@ -40,3 +40,32 @@ export interface RunResult extends ApplyMutationResult {
40
40
  mode: 'install' | 'sync'
41
41
  check: boolean
42
42
  }
43
+
44
+ // ── Context types ────────────────────────────────────
45
+
46
+ export type PlanStatus = '未执行' | '已执行'
47
+
48
+ export interface PlanInfo {
49
+ number: number
50
+ status: PlanStatus
51
+ dir: string
52
+ }
53
+
54
+ export interface ContextSnapshot {
55
+ root: string
56
+ currentPlan: PlanInfo | null
57
+ preparing: PlanInfo[]
58
+ doneCount: number
59
+ }
60
+
61
+ export interface ValidateResult {
62
+ valid: boolean
63
+ errors: string[]
64
+ context: ContextSnapshot | null
65
+ }
66
+
67
+ export interface ArchiveResult {
68
+ archivedTo: string
69
+ promoted: number | null
70
+ remainingPreparing: number
71
+ }