@cat-kit/agent-context 1.0.6 → 1.1.0

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 (75) hide show
  1. package/README.md +58 -61
  2. package/dist/cli.js +1 -1
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/install.js +2 -0
  5. package/dist/commands/install.js.map +1 -0
  6. package/dist/commands/printer.js +4 -0
  7. package/dist/commands/printer.js.map +1 -0
  8. package/dist/commands/sync.js +2 -0
  9. package/dist/commands/sync.js.map +1 -0
  10. package/dist/content/actions.js +172 -0
  11. package/dist/content/actions.js.map +1 -0
  12. package/dist/content/index.js +47 -0
  13. package/dist/content/index.js.map +1 -0
  14. package/dist/runner.js +3 -0
  15. package/dist/runner.js.map +1 -0
  16. package/dist/stats.html +1 -1
  17. package/dist/tools.js +2 -0
  18. package/dist/tools.js.map +1 -0
  19. package/package.json +1 -1
  20. package/src/cli.ts +14 -14
  21. package/src/commands/install.ts +56 -0
  22. package/src/commands/{shared.ts → printer.ts} +2 -3
  23. package/src/commands/sync.ts +40 -0
  24. package/src/content/actions.ts +232 -0
  25. package/src/content/index.ts +93 -0
  26. package/src/runner.ts +113 -0
  27. package/src/tools.ts +114 -0
  28. package/src/types.ts +42 -0
  29. package/dist/adapters/tool-targets.js +0 -2
  30. package/dist/adapters/tool-targets.js.map +0 -1
  31. package/dist/commands/setup.js +0 -2
  32. package/dist/commands/setup.js.map +0 -1
  33. package/dist/commands/shared.js +0 -4
  34. package/dist/commands/shared.js.map +0 -1
  35. package/dist/commands/update.js +0 -2
  36. package/dist/commands/update.js.map +0 -1
  37. package/dist/domain/workflow-content.js +0 -2
  38. package/dist/domain/workflow-content.js.map +0 -1
  39. package/dist/domain/workflow-context.js +0 -2
  40. package/dist/domain/workflow-context.js.map +0 -1
  41. package/dist/domain/workflow-templates/done.js +0 -23
  42. package/dist/domain/workflow-templates/done.js.map +0 -1
  43. package/dist/domain/workflow-templates/implement.js +0 -35
  44. package/dist/domain/workflow-templates/implement.js.map +0 -1
  45. package/dist/domain/workflow-templates/init.js +0 -37
  46. package/dist/domain/workflow-templates/init.js.map +0 -1
  47. package/dist/domain/workflow-templates/patch.js +0 -41
  48. package/dist/domain/workflow-templates/patch.js.map +0 -1
  49. package/dist/domain/workflow-templates/plan.js +0 -58
  50. package/dist/domain/workflow-templates/plan.js.map +0 -1
  51. package/dist/domain/workflow-templates/replan.js +0 -31
  52. package/dist/domain/workflow-templates/replan.js.map +0 -1
  53. package/dist/generators/workflow.js +0 -2
  54. package/dist/generators/workflow.js.map +0 -1
  55. package/dist/runtime/execute.js +0 -2
  56. package/dist/runtime/execute.js.map +0 -1
  57. package/dist/shared/fs.js +0 -3
  58. package/dist/shared/fs.js.map +0 -1
  59. package/src/adapters/tool-targets.ts +0 -157
  60. package/src/commands/setup.ts +0 -64
  61. package/src/commands/update.ts +0 -46
  62. package/src/domain/types.ts +0 -50
  63. package/src/domain/workflow-content.ts +0 -25
  64. package/src/domain/workflow-context.ts +0 -48
  65. package/src/domain/workflow-templates/done.ts +0 -28
  66. package/src/domain/workflow-templates/implement.ts +0 -41
  67. package/src/domain/workflow-templates/index.ts +0 -7
  68. package/src/domain/workflow-templates/init.ts +0 -42
  69. package/src/domain/workflow-templates/patch.ts +0 -47
  70. package/src/domain/workflow-templates/plan.ts +0 -70
  71. package/src/domain/workflow-templates/replan.ts +0 -36
  72. package/src/generators/workflow.ts +0 -25
  73. package/src/runtime/execute.ts +0 -45
  74. package/src/shared/fs.ts +0 -66
  75. package/src/shared/paths.ts +0 -9
@@ -1,157 +0,0 @@
1
- import { resolve } from 'node:path'
2
- import { existsSync } from 'node:fs'
3
-
4
- import type { ToolId, ToolTarget, WorkflowCommandName } from '../domain/types'
5
-
6
- const TOOL_TARGET_MAP: Record<ToolId, ToolTarget> = {
7
- claude: {
8
- id: 'claude',
9
- name: 'Claude Code',
10
- rootDir: '.claude/commands',
11
- fileExtension: '.md',
12
- supportsFrontmatter: true,
13
- commandSeparator: ':',
14
- commandPrefix: '/'
15
- },
16
- codex: {
17
- id: 'codex',
18
- name: 'Codex',
19
- rootDir: '.codex/commands',
20
- fileExtension: '.md',
21
- supportsFrontmatter: true,
22
- commandSeparator: '-',
23
- commandPrefix: '/'
24
- },
25
- cursor: {
26
- id: 'cursor',
27
- name: 'Cursor',
28
- rootDir: '.cursor/commands',
29
- fileExtension: '.md',
30
- supportsFrontmatter: false,
31
- commandSeparator: '-',
32
- commandPrefix: '/'
33
- },
34
- antigravity: {
35
- id: 'antigravity',
36
- name: 'Antigravity',
37
- rootDir: '.agents',
38
- fileExtension: '.md',
39
- supportsFrontmatter: true,
40
- commandSeparator: '-',
41
- commandPrefix: '/'
42
- },
43
- copilot: {
44
- id: 'copilot',
45
- name: 'GitHub Copilot',
46
- rootDir: '.github/prompts',
47
- fileExtension: '.prompt.md',
48
- supportsFrontmatter: true,
49
- commandSeparator: '-',
50
- commandPrefix: '#'
51
- }
52
- }
53
-
54
- export const DEFAULT_TOOL_ORDER: ToolId[] = [
55
- 'claude',
56
- 'codex',
57
- 'cursor',
58
- 'antigravity',
59
- 'copilot'
60
- ]
61
-
62
- const WORKFLOW_COMMAND_ORDER: WorkflowCommandName[] = [
63
- 'init',
64
- 'plan',
65
- 'replan',
66
- 'implement',
67
- 'patch',
68
- 'done'
69
- ]
70
-
71
- export interface ToolChoice {
72
- id: ToolId
73
- name: string
74
- }
75
-
76
- export function getToolChoices(): ToolChoice[] {
77
- return DEFAULT_TOOL_ORDER.map(id => ({
78
- id,
79
- name: TOOL_TARGET_MAP[id].name
80
- }))
81
- }
82
-
83
- export function parseToolIds(toolsText: string): ToolId[] {
84
- const parsed = toolsText
85
- .split(',')
86
- .map(item => item.trim().toLowerCase())
87
- .filter(Boolean)
88
-
89
- if (parsed.length === 0) {
90
- return [...DEFAULT_TOOL_ORDER]
91
- }
92
-
93
- const uniqueIds: ToolId[] = []
94
-
95
- for (const value of parsed) {
96
- if (!isToolId(value)) {
97
- throw new Error(
98
- `不支持的工具标识: ${value}。可选值: ${DEFAULT_TOOL_ORDER.join(', ')}`
99
- )
100
- }
101
-
102
- if (!uniqueIds.includes(value)) {
103
- uniqueIds.push(value)
104
- }
105
- }
106
-
107
- return uniqueIds
108
- }
109
-
110
- export function resolveToolTargets(tools?: ToolId[]): ToolTarget[] {
111
- const selected = tools && tools.length > 0 ? tools : DEFAULT_TOOL_ORDER
112
- return selected.map(id => ({ ...TOOL_TARGET_MAP[id] }))
113
- }
114
-
115
- export function detectConfiguredToolIds(cwd: string): ToolId[] {
116
- return DEFAULT_TOOL_ORDER.filter((toolId) => {
117
- const target = TOOL_TARGET_MAP[toolId]
118
- const workflowPaths = resolveWorkflowPaths(target, cwd)
119
-
120
- return WORKFLOW_COMMAND_ORDER.some(command =>
121
- existsSync(workflowPaths.commandFile(command))
122
- )
123
- })
124
- }
125
-
126
- // ── 工作流路径解析 ────────────────────────────────────
127
-
128
- export interface WorkflowPaths {
129
- commandFile(name: WorkflowCommandName): string
130
- }
131
-
132
- /**
133
- * 根据工具约束计算工作流文件输出路径
134
- *
135
- * - separator=':' (Claude) → 嵌套: .claude/commands/ac/init.md → /ac:init
136
- * - separator='-' (其他) → 扁平: .cursor/commands/ac-init.md → /ac-init
137
- */
138
- export function resolveWorkflowPaths(target: ToolTarget, cwd: string): WorkflowPaths {
139
- const root = resolve(cwd, target.rootDir)
140
- const ext = target.fileExtension
141
- const nested = target.commandSeparator === ':'
142
-
143
- if (nested) {
144
- const nsDir = resolve(root, 'ac')
145
- return {
146
- commandFile: name => resolve(nsDir, `${name}${ext}`)
147
- }
148
- }
149
-
150
- return {
151
- commandFile: name => resolve(root, `ac-${name}${ext}`)
152
- }
153
- }
154
-
155
- function isToolId(value: string): value is ToolId {
156
- return Object.hasOwn(TOOL_TARGET_MAP, value)
157
- }
@@ -1,64 +0,0 @@
1
- import { checkbox } from '@inquirer/prompts'
2
-
3
- import {
4
- DEFAULT_TOOL_ORDER,
5
- detectConfiguredToolIds,
6
- getToolChoices,
7
- parseToolIds
8
- } from '../adapters/tool-targets'
9
- import type { ToolId } from '../domain/types'
10
- import { runSetup } from '../runtime/execute'
11
- import { printCheckResult, printRunSummary } from './shared'
12
-
13
- export interface SetupCommandOptions {
14
- tools?: string
15
- check?: boolean
16
- yes?: boolean
17
- }
18
-
19
- export async function setupCommand(options: SetupCommandOptions = {}): Promise<void> {
20
- const cwd = process.cwd()
21
- const tools = await resolveTools(cwd, options)
22
- const check = options.check ?? false
23
-
24
- const result = await runSetup({ cwd, tools, check })
25
-
26
- if (check) {
27
- printCheckResult(result, cwd)
28
- if (result.changed.length > 0) {
29
- process.exitCode = 1
30
- }
31
- return
32
- }
33
-
34
- printRunSummary(result, cwd)
35
- }
36
-
37
- async function resolveTools(cwd: string, options: SetupCommandOptions): Promise<ToolId[] | undefined> {
38
- const raw = options.tools
39
-
40
- if (!raw || raw.trim().length === 0) {
41
- const configuredTools = detectConfiguredToolIds(cwd)
42
-
43
- if (options.yes) {
44
- if (configuredTools.length > 0) {
45
- return configuredTools
46
- }
47
- return [...DEFAULT_TOOL_ORDER]
48
- }
49
-
50
- const selectedTools = await checkbox<ToolId>({
51
- message: '请选择要生成工作流命令的工具(可多选):',
52
- choices: getToolChoices().map((tool) => ({
53
- name: tool.name,
54
- value: tool.id,
55
- checked: configuredTools.includes(tool.id)
56
- })),
57
- required: true
58
- })
59
-
60
- return selectedTools
61
- }
62
-
63
- return parseToolIds(raw)
64
- }
@@ -1,46 +0,0 @@
1
- import { detectConfiguredToolIds, parseToolIds } from '../adapters/tool-targets'
2
- import type { ToolId } from '../domain/types'
3
- import { runUpdate } from '../runtime/execute'
4
- import { printCheckResult, printRunSummary } from './shared'
5
-
6
- export interface UpdateCommandOptions {
7
- tools?: string
8
- check?: boolean
9
- yes?: boolean
10
- }
11
-
12
- export async function updateCommand(options: UpdateCommandOptions = {}): Promise<void> {
13
- const cwd = process.cwd()
14
- const tools = resolveTools(cwd, options.tools)
15
- const check = options.check ?? false
16
-
17
- const result = await runUpdate({
18
- cwd,
19
- tools,
20
- check
21
- })
22
-
23
- if (check) {
24
- printCheckResult(result, cwd)
25
- if (result.changed.length > 0) {
26
- process.exitCode = 1
27
- }
28
- return
29
- }
30
-
31
- printRunSummary(result, cwd)
32
- }
33
-
34
- function resolveTools(cwd: string, raw?: string): ToolId[] | undefined {
35
- if (!raw || raw.trim().length === 0) {
36
- const configuredTools = detectConfiguredToolIds(cwd)
37
-
38
- if (configuredTools.length === 0) {
39
- throw new Error('未检测到已 setup 的工具,请先执行 setup 或通过 --tools 显式指定工具')
40
- }
41
-
42
- return configuredTools
43
- }
44
-
45
- return parseToolIds(raw)
46
- }
@@ -1,50 +0,0 @@
1
- export type ToolId = 'claude' | 'codex' | 'cursor' | 'antigravity' | 'copilot'
2
-
3
- export interface ToolTarget {
4
- id: ToolId
5
- name: string
6
- rootDir: string
7
- /** 工作流文件扩展名:'.md' | '.prompt.md'(Copilot) */
8
- fileExtension: string
9
- /** 是否支持 YAML frontmatter(Cursor 不支持) */
10
- supportsFrontmatter: boolean
11
- /** 命令分隔符:':'(Claude 嵌套目录 ac/init.md → /ac:init)或 '-'(扁平 ac-init.md) */
12
- commandSeparator: string
13
- /** 命令调用前缀:'/'(Claude/Cursor)或 '#'(Copilot) */
14
- commandPrefix: string
15
- }
16
-
17
- export type WorkflowCommandName =
18
- | 'init'
19
- | 'plan'
20
- | 'replan'
21
- | 'implement'
22
- | 'patch'
23
- | 'done'
24
-
25
- export interface WorkflowArtifacts {
26
- commandFiles: Record<WorkflowCommandName, string>
27
- }
28
-
29
- export interface FileMutation {
30
- path: string
31
- body: string
32
- }
33
-
34
- export interface ApplyMutationResult {
35
- created: string[]
36
- updated: string[]
37
- unchanged: string[]
38
- changed: string[]
39
- }
40
-
41
- export interface RunOptions {
42
- cwd?: string
43
- tools?: ToolId[]
44
- check?: boolean
45
- }
46
-
47
- export interface RunResult extends ApplyMutationResult {
48
- mode: 'setup' | 'update'
49
- check: boolean
50
- }
@@ -1,25 +0,0 @@
1
- import type { ToolTarget, WorkflowArtifacts } from './types'
2
- import {
3
- createWorkflowContext,
4
- renderDone,
5
- renderImplement,
6
- renderInit,
7
- renderPatch,
8
- renderPlan,
9
- renderReplan
10
- } from './workflow-templates/index.js'
11
-
12
- export function renderWorkflowArtifacts(target: ToolTarget): WorkflowArtifacts {
13
- const ctx = createWorkflowContext(target)
14
-
15
- return {
16
- commandFiles: {
17
- init: renderInit(ctx),
18
- plan: renderPlan(ctx),
19
- replan: renderReplan(ctx),
20
- implement: renderImplement(ctx),
21
- patch: renderPatch(ctx),
22
- done: renderDone(ctx)
23
- }
24
- }
25
- }
@@ -1,48 +0,0 @@
1
- import type { ToolTarget } from './types'
2
-
3
- export interface WorkflowContext {
4
- /** 命令引用: 'ac:init' | 'ac-init' */
5
- cmd(name: string): string
6
- /** 命令调用: '/ac:init' | '#ac-init' */
7
- invoke(name: string): string
8
- /** 命令前缀模式: 'ac:' | 'ac-' */
9
- cmdPrefix(): string
10
- /** 生成 YAML frontmatter 或空字符串 */
11
- frontmatter(description: string): string
12
- }
13
-
14
- export function createWorkflowContext(target: ToolTarget): WorkflowContext {
15
- const sep = target.commandSeparator
16
- const pre = target.commandPrefix
17
- return {
18
- cmd: (name) => `ac${sep}${name}`,
19
- invoke: (name) => `${pre}ac${sep}${name}`,
20
- cmdPrefix: () => `ac${sep}`,
21
- frontmatter: (desc) => (target.supportsFrontmatter ? `---\ndescription: ${desc}\n---\n\n` : '')
22
- }
23
- }
24
-
25
- export const fence = '```'
26
- export const code = (t: string) => `\`${t}\``
27
-
28
- export interface NextStep {
29
- command: string
30
- description: string
31
- }
32
-
33
- export function renderNextSteps(c: WorkflowContext, steps: NextStep[]): string {
34
- const items = steps.map((s) => `${code(c.invoke(s.command))}(${s.description})`).join(' | ')
35
-
36
- return `> **下一步:** ${items}`
37
- }
38
-
39
- const LIFECYCLE_COMMANDS = ['init', 'plan', 'replan', 'implement', 'patch', 'done'] as const
40
-
41
- export function renderPreamble(c: WorkflowContext, current: string, description: string): string {
42
- const lifecycle = LIFECYCLE_COMMANDS.map((cmd) => {
43
- const ref = code(c.cmd(cmd))
44
- return cmd === current ? `**${ref}**` : ref
45
- }).join(' → ')
46
-
47
- return `${description}\n\n生命周期: ${lifecycle}。`
48
- }
@@ -1,28 +0,0 @@
1
- import { code, renderNextSteps, renderPreamble, type WorkflowContext } from '../workflow-context'
2
-
3
- export function renderDone(c: WorkflowContext): string {
4
- return `${c.frontmatter('将当前已执行计划标记为真正完成并归档,必要时晋升 preparing 队列')}\
5
- # ${c.invoke('done')}
6
-
7
- ${renderPreamble(c, 'done', `确认当前已执行计划真正完成,归档到 ${code('.agent-context/done/')} 目录,并自动晋升 ${code('preparing/')} 队列中的下一个计划。`)}
8
-
9
- ## 前置规则
10
-
11
- - 带描述 → 拒绝执行。
12
- - 当前计划不存在 → 拒绝执行,提示先运行 ${code(c.cmd('plan'))}。
13
- - 当前计划状态为 ${code('未执行')} → 拒绝执行,提示先运行 ${code(c.cmd('implement'))}。
14
- - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
15
- - 必须得到用户确认后才可归档;用户未确认 → 中止。
16
-
17
- ## 执行步骤
18
-
19
- 1. **用户确认**:向用户确认当前计划已真正完成,可以归档。
20
- 2. **归档当前计划**:将 ${code('.agent-context/plan-{number}')} 移动到 ${code('.agent-context/done/plan-{number}-{YYYYMMDD}')}(当日日期),包含完整 ${code('plan.md')} 与所有 ${code('patch-{number}.md')}。编号不可被新计划复用。
21
- 3. **晋升 preparing 队列**:若 ${code('.agent-context/preparing/')} 非空,将最小编号计划移至 ${code('.agent-context/')} 作为新当前计划。
22
- 4. **校验**:确认归档完整,晋升后仍满足单当前计划约束;失败则回滚。
23
- 5. **输出反馈**:报告归档路径、是否晋升及晋升编号、是否还有待执行计划。
24
-
25
- ${renderNextSteps(c, [
26
- { command: 'plan', description: '创建新计划' }
27
- ])}`
28
- }
@@ -1,41 +0,0 @@
1
- import { code, fence, renderNextSteps, renderPreamble, type WorkflowContext } from '../workflow-context'
2
-
3
- export function renderImplement(c: WorkflowContext): string {
4
- return `${c.frontmatter('实施当前计划并将状态从未执行更新为已执行')}\
5
- # ${c.invoke('implement')}
6
-
7
- ${renderPreamble(c, 'implement', `实施当前计划 ${code('.agent-context/plan-{number}/plan.md')} 中的全部步骤,通过验证循环后将状态从「未执行」更新为「已执行」。`)}
8
-
9
- ## 前置规则
10
-
11
- - 带描述 → 拒绝执行。
12
- - 当前计划不存在 → 拒绝执行,提示先运行 ${code(c.cmd('plan'))}。
13
- - 当前计划状态为 ${code('已执行')} → 拒绝执行,提示使用 ${code(c.cmd('patch'))} 或 ${code(c.cmd('done'))}。
14
- - ${code('## 目标')} 或 ${code('## 内容')} 为空 → 拒绝执行,提示补充内容。
15
- - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
16
- - 仅操作当前计划,不直接操作 ${code('preparing/')} 中的计划。
17
- - 遇到阻塞问题应向用户报告,不可静默跳过。
18
-
19
- ## 执行步骤
20
-
21
- 1. 读取当前计划 ${code('plan.md')},理解 ${code('## 目标')} 与 ${code('## 内容')}。
22
- 2. 依据 ${code('## 内容')} 中的步骤逐项实施。
23
- 3. **验证循环**(全部通过前不可进入步骤 4):
24
- a. 逐项对照 ${code('## 内容')} 确认每个步骤已实施。
25
- b. 运行项目验证:类型检查 → lint → 测试。
26
- c. 若存在失败项 → 修复后回到 a 重新验证。
27
- d. 全部通过 → 进入步骤 4。
28
- 4. 更新 ${code('plan.md')} 状态行:${code('> 状态: 未执行')} → ${code('> 状态: 已执行')}。状态行须唯一,仅在验证通过后更新。
29
- 5. 更新 ${code('## 影响范围')},记录所有变更文件:
30
-
31
- ${fence}markdown
32
- - 新增文件: ${code('/path/to/new-file')}
33
- - 修改文件: ${code('/path/to/modified-file')}
34
- - 删除文件: ${code('/path/to/deleted-file')}
35
- ${fence}
36
-
37
- ${renderNextSteps(c, [
38
- { command: 'done', description: '归档当前计划' },
39
- { command: 'patch', description: '补丁修复' }
40
- ])}`
41
- }
@@ -1,7 +0,0 @@
1
- export { createWorkflowContext, type WorkflowContext } from '../workflow-context'
2
- export { renderInit } from './init'
3
- export { renderPlan } from './plan'
4
- export { renderReplan } from './replan'
5
- export { renderImplement } from './implement'
6
- export { renderPatch } from './patch'
7
- export { renderDone } from './done'
@@ -1,42 +0,0 @@
1
- import { code, renderNextSteps, renderPreamble, type WorkflowContext } from '../workflow-context'
2
-
3
- export function renderInit(c: WorkflowContext): string {
4
- return `${c.frontmatter('初始化项目上下文,按新旧项目规则处理 AGENTS.md 与计划入口')}\
5
- # ${c.invoke('init')} {描述?}
6
-
7
- ${renderPreamble(c, 'init', `初始化项目的 Agent Context 工作流上下文。根据新旧项目类型处理 ${code('AGENTS.md')},新项目会自动进入 ${code(c.cmd('plan'))} 计划创建流程。`)}
8
-
9
- 描述为可选参数,用于补充项目背景、技术栈、特殊约束。
10
-
11
- ## 执行步骤
12
-
13
- 1. **判断项目类型**:检测根目录是否存在有效代码文件和目录结构。
14
- - 新项目:无实质代码,或用户明确说明是新项目。
15
- - 旧项目:已有代码、配置文件和目录结构。
16
- - 无法判断 → 向用户提问澄清,不可假设。
17
-
18
- 2. **处理 AGENTS.md**:
19
- - 新项目:
20
- 1. 通过提问澄清以下要点(已从描述中获取的可跳过):项目目标与核心功能、技术栈与版本、代码规范与工具链(lint/formatter/测试)、目录结构偏好。
21
- 2. 生成高质量 ${code('AGENTS.md')}(须满足下方质量标准,不满足则重新优化直至满足)。
22
- 3. 继续执行 ${code(c.cmd('plan'))} 创建初始计划。
23
- - 旧项目:
24
- 1. 若不存在 ${code('AGENTS.md')}:通过提问与代码阅读收集信息后生成。
25
- 2. 若已存在 ${code('AGENTS.md')}:按质量标准评估,不足时增补优化。
26
- 3. 默认不创建计划(除非用户明确要求)。
27
-
28
- 3. **输出反馈**:向用户报告项目类型判定结果、AGENTS.md 处理结果、是否需要后续 ${code(c.cmd('plan'))}。
29
-
30
- ## 高质量 AGENTS.md 标准
31
-
32
- - [ ] 常用命令与约束前置,降低代理执行歧义。
33
- - [ ] 明确列出目录结构(至少到第二层)。
34
- - [ ] 明确标注技术栈及版本。
35
- - [ ] 明确代码风格约束(命名规范、格式化工具、lint 配置)。
36
- - [ ] 内容精简,无冗余段落或模板化填充。
37
- - [ ] 大型单体仓库按子包拆分维护本地 ${code('AGENTS.md')}。
38
-
39
- ${renderNextSteps(c, [
40
- { command: 'plan', description: '创建新计划' }
41
- ])}`
42
- }
@@ -1,47 +0,0 @@
1
- import { code, fence, renderNextSteps, renderPreamble, type WorkflowContext } from '../workflow-context'
2
-
3
- export function renderPatch(c: WorkflowContext): string {
4
- return `${c.frontmatter('基于当前已执行计划创建补丁并回写历史记录')}\
5
- # ${c.invoke('patch')} {描述}
6
-
7
- ${renderPreamble(c, 'patch', `基于当前已执行计划创建增量补丁,修复问题或追加变更,生成 ${code('patch-{number}.md')} 并回写计划的影响范围与历史记录。`)}
8
-
9
- ## 前置规则
10
-
11
- - 描述为空 → 拒绝执行。
12
- - 当前计划不存在 → 拒绝执行,提示先运行 ${code(c.cmd('plan'))}。
13
- - 当前计划状态为 ${code('未执行')} → 拒绝执行,提示先运行 ${code(c.cmd('implement'))}。
14
- - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
15
- - 补丁不改变计划状态,完成后保持 ${code('已执行')}。
16
-
17
- ## 执行步骤
18
-
19
- 1. 阅读 ${code('plan.md')} 与已有 ${code('patch-{number}.md')},了解上下文与历史补丁,避免重复修复。
20
- 2. 根据描述执行补丁所需的代码变更。
21
- 3. 完成必要验证(测试、类型检查等)。
22
- 4. 创建 ${code('patch-{number}.md')}(编号:扫描当前计划目录已有补丁,取 max+1),遵循下方模板。
23
- 5. 回写 ${code('plan.md')}:
24
- - ${code('## 历史补丁')}:追加 ${code('- patch-{number}: {补丁名称}')},按编号去重。
25
- - ${code('## 影响范围')}:合并本次变更路径,按路径去重。
26
-
27
- ## patch.md 标准模板
28
-
29
- ${fence}markdown
30
- # {补丁名称}
31
-
32
- ## 补丁内容
33
-
34
- {修改了什么、为什么修改}
35
-
36
- ## 影响范围
37
-
38
- - 新增文件: ${code('/path/to/file')}
39
- - 修改文件: ${code('/path/to/file')}
40
- - 删除文件: ${code('/path/to/file')}
41
- ${fence}
42
-
43
- ${renderNextSteps(c, [
44
- { command: 'done', description: '归档当前计划' },
45
- { command: 'patch', description: '继续补丁' }
46
- ])}`
47
- }
@@ -1,70 +0,0 @@
1
- import {
2
- code,
3
- fence,
4
- renderNextSteps,
5
- renderPreamble,
6
- type WorkflowContext
7
- } from '../workflow-context'
8
-
9
- export function renderPlan(c: WorkflowContext): string {
10
- return `${c.frontmatter('创建新计划并维护单当前计划 + preparing 队列结构')}\
11
- # ${c.invoke('plan')} {描述}
12
-
13
- ${renderPreamble(c, 'plan', `创建新的执行计划,写入 ${code('.agent-context/plan-{number}/plan.md')}。按复杂度可拆分为多个计划,维护「单当前计划 + preparing 队列」结构。`)}
14
-
15
- ## 前置规则
16
-
17
- - 描述为空 → 拒绝执行,提示必须附带描述。
18
- - 存在未归档的已执行当前计划 → 拒绝执行,提示先运行 ${code(c.cmd('done'))}。
19
- - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
20
- - 编号:扫描 ${code('.agent-context/{,preparing/,done/}')} 全部 ${code('plan-N')},取 max(N)+1,不复用。
21
-
22
- ## 执行步骤
23
-
24
- 1. **需求澄清**(存在以下任一歧义时必须向用户提问,否则直接跳到步骤 2):
25
- - 范围边界不清:无法判定影响哪些文件或模块。
26
- - 存在显著不同的技术路径需用户决策。
27
- - 验收标准不明确:无法判断何时算"完成"。
28
- 2. 按复杂度决定单计划或多计划拆分。
29
- 3. 多计划拆分时:最小编号进入 ${code('.agent-context/')} 作为当前计划,其余进入 ${code('.agent-context/preparing/')}。单计划直接创建到 ${code('.agent-context/plan-{number}')}。
30
- 4. 每个计划创建 ${code('plan.md')},遵循下方标准模板。
31
- 5. **计划自检**(不通过则修改后重新检查):
32
- - 每个步骤可独立执行且有明确完成标准。
33
- - 不存在过度拆分(过于琐碎)或拆分不足(单步骤过于复杂)。
34
- - 影响范围可预估。
35
-
36
- ## plan.md 标准模板
37
-
38
- ${fence}markdown
39
- # {计划名称}
40
-
41
- > 状态: 未执行
42
-
43
- ## 目标
44
-
45
- {明确的目标描述}
46
-
47
- ## 内容
48
-
49
- {详细的实施步骤和内容}
50
-
51
- ## 影响范围
52
-
53
- - 新增文件: \`/path/to/file\`
54
- - 修改文件: \`/path/to/file\`
55
- - 删除文件: \`/path/to/file\`
56
-
57
- ## 历史补丁
58
-
59
- - patch-1: {补丁名称}
60
- ${fence}
61
-
62
- - 状态行唯一,仅允许 ${code('未执行')} 或 ${code('已执行')}。
63
- - ${code('## 目标')} 与 ${code('## 内容')} 不可为空。
64
- - ${code('## 影响范围')} 与 ${code('## 历史补丁')} 创建时留空,分别由 ${code(c.cmd('implement'))} 和 ${code(c.cmd('patch'))} 写入。
65
-
66
- ${renderNextSteps(c, [
67
- { command: 'implement', description: '实施当前计划' },
68
- { command: 'replan', description: '调整计划' }
69
- ])}`
70
- }
@@ -1,36 +0,0 @@
1
- import { code, renderNextSteps, renderPreamble, type WorkflowContext } from '../workflow-context'
2
-
3
- export function renderReplan(c: WorkflowContext): string {
4
- return `${c.frontmatter('重规划未实施计划,保持单当前计划结构不变')}\
5
- # ${c.invoke('replan')} {描述}
6
-
7
- ${renderPreamble(c, 'replan', `重新规划已有的未实施计划(${code('preparing/')} 队列或未执行的当前计划),保持单当前计划结构不变。`)}
8
-
9
- ## 前置规则
10
-
11
- - 描述为空 → 拒绝执行。
12
- - 无未实施计划 → 拒绝执行,提示使用 ${code(c.cmd('plan'))} 创建。
13
- - 存在多个当前计划 → 拒绝执行,提示恢复单活跃状态。
14
- - 目标计划编号不存在 → 拒绝执行,列出可选编号。
15
- - 目标计划已执行 → 拒绝执行,提示使用 ${code(c.cmd('patch'))} 修补。
16
- - 重规划后违反单当前计划约束 → 回滚并报错。
17
-
18
- ## 作用域规则
19
-
20
- - 默认作用域:${code('.agent-context/preparing/')} 中全部未实施计划。
21
- - 可通过描述指定仅重规划部分计划(如"重规划 plan-3 和 plan-5")。
22
- - 当前计划为 ${code('已执行')} → 禁止重写,仅允许重规划 ${code('preparing/')} 队列。
23
- - 当前计划为 ${code('未执行')} 且用户明确要求 → 可纳入重规划范围。
24
-
25
- ## 执行步骤
26
-
27
- 1. 解析描述,确定重规划目标范围。
28
- 2. 读取目标计划 ${code('plan.md')},理解现有意图。
29
- 3. 生成新的拆分方案,保持"单当前计划 + 若干 preparing 计划"结构。
30
- 4. 新增计划编号:全局 max(N)+1 递增分配;未改动计划保持原编号。
31
- 5. 更新目录结构,确保每个新计划的 ${code('plan.md')} 遵循标准模板。
32
-
33
- ${renderNextSteps(c, [
34
- { command: 'implement', description: '实施当前计划' }
35
- ])}`
36
- }