@devcxl/opencode-cabbage 1.1.0 → 1.3.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 (142) hide show
  1. package/.codex-plugin/plugin.json +36 -0
  2. package/README.md +53 -25
  3. package/README.zh.md +23 -23
  4. package/assets/agents/dev-lifecycle.md +208 -68
  5. package/assets/agents/team/architect.md +22 -7
  6. package/assets/agents/team/developer.md +13 -6
  7. package/assets/agents/team/goal-verify.md +4 -1
  8. package/assets/agents/team/researcher.md +59 -0
  9. package/assets/agents/team/reviewer.md +34 -18
  10. package/assets/commands/setup.md +1 -1
  11. package/assets/prompts/bootstrap.md +10 -9
  12. package/assets/prompts/stage-contract.md +25 -25
  13. package/assets/skills/flow-code/SKILL.md +23 -25
  14. package/assets/skills/flow-design/SKILL.md +94 -26
  15. package/assets/skills/flow-release/SKILL.md +41 -17
  16. package/assets/skills/flow-requirements/SKILL.md +19 -13
  17. package/assets/skills/flow-research/SKILL.md +77 -0
  18. package/assets/skills/flow-review/SKILL.md +55 -25
  19. package/assets/skills/flow-setup/SKILL.md +27 -24
  20. package/assets/skills/flow-tasks/SKILL.md +178 -35
  21. package/assets/skills/flow-tdd/SKILL.md +68 -40
  22. package/codex-skills/agent-architect/SKILL.md +79 -0
  23. package/codex-skills/agent-dev-lifecycle/SKILL.md +309 -0
  24. package/codex-skills/agent-developer/SKILL.md +51 -0
  25. package/codex-skills/agent-goal-verify/SKILL.md +45 -0
  26. package/codex-skills/agent-researcher/SKILL.md +32 -0
  27. package/codex-skills/agent-reviewer/SKILL.md +109 -0
  28. package/codex-skills/flow-code/SKILL.md +71 -0
  29. package/codex-skills/flow-design/SKILL.md +146 -0
  30. package/codex-skills/flow-release/SKILL.md +90 -0
  31. package/codex-skills/flow-requirements/SKILL.md +90 -0
  32. package/codex-skills/flow-research/SKILL.md +77 -0
  33. package/codex-skills/flow-review/SKILL.md +110 -0
  34. package/codex-skills/flow-setup/SKILL.md +75 -0
  35. package/codex-skills/flow-tasks/SKILL.md +220 -0
  36. package/codex-skills/flow-tdd/SKILL.md +235 -0
  37. package/dist/hooks/session-start.d.ts +1 -0
  38. package/dist/hooks/session-start.js +72 -0
  39. package/dist/hooks/session-start.js.map +1 -0
  40. package/dist/kernel/session-index.d.ts +8 -25
  41. package/dist/kernel/session-index.js +5 -55
  42. package/dist/kernel/session-index.js.map +1 -1
  43. package/dist/plugin/bootstrap.d.ts +0 -1
  44. package/dist/plugin/bootstrap.js +0 -3
  45. package/dist/plugin/bootstrap.js.map +1 -1
  46. package/dist/plugin/goal-store.d.ts +71 -0
  47. package/dist/plugin/goal-store.js +54 -0
  48. package/dist/plugin/goal-store.js.map +1 -0
  49. package/dist/plugin/goal.d.ts +47 -13
  50. package/dist/plugin/goal.js +228 -128
  51. package/dist/plugin/goal.js.map +1 -1
  52. package/dist/plugin/prompt-lint.js +3 -11
  53. package/dist/plugin/prompt-lint.js.map +1 -1
  54. package/dist/plugin/prompts.d.ts +0 -1
  55. package/dist/plugin/prompts.js +0 -4
  56. package/dist/plugin/prompts.js.map +1 -1
  57. package/dist/plugin/server.d.ts +3 -5
  58. package/dist/plugin/server.js +247 -155
  59. package/dist/plugin/server.js.map +1 -1
  60. package/dist/plugin/skills.d.ts +7 -1
  61. package/dist/plugin/skills.js +75 -12
  62. package/dist/plugin/skills.js.map +1 -1
  63. package/dist/plugin.d.ts +0 -1
  64. package/dist/plugin.js +1 -4
  65. package/dist/plugin.js.map +1 -1
  66. package/dist/util/gh.d.ts +0 -11
  67. package/dist/util/gh.js +0 -14
  68. package/dist/util/gh.js.map +1 -1
  69. package/dist/util/paths.d.ts +0 -14
  70. package/dist/util/paths.js +0 -69
  71. package/dist/util/paths.js.map +1 -1
  72. package/hooks/hooks.json +17 -0
  73. package/package.json +12 -4
  74. package/assets/prompts/ADR-FORMAT.md +0 -45
  75. package/assets/prompts/PRD-FORMAT.md +0 -17
  76. package/assets/templates/gitignore +0 -5
  77. package/dist/kernel/caller.d.ts +0 -48
  78. package/dist/kernel/caller.js +0 -88
  79. package/dist/kernel/caller.js.map +0 -1
  80. package/dist/kernel/flow.d.ts +0 -175
  81. package/dist/kernel/flow.js +0 -467
  82. package/dist/kernel/flow.js.map +0 -1
  83. package/dist/kernel/legacy.d.ts +0 -19
  84. package/dist/kernel/legacy.js +0 -34
  85. package/dist/kernel/legacy.js.map +0 -1
  86. package/dist/kernel/records.d.ts +0 -103
  87. package/dist/kernel/records.js +0 -240
  88. package/dist/kernel/records.js.map +0 -1
  89. package/dist/kernel/release.d.ts +0 -106
  90. package/dist/kernel/release.js +0 -241
  91. package/dist/kernel/release.js.map +0 -1
  92. package/dist/kernel/review.d.ts +0 -34
  93. package/dist/kernel/review.js +0 -82
  94. package/dist/kernel/review.js.map +0 -1
  95. package/dist/kernel/setup.d.ts +0 -95
  96. package/dist/kernel/setup.js +0 -401
  97. package/dist/kernel/setup.js.map +0 -1
  98. package/dist/kernel/slug.d.ts +0 -23
  99. package/dist/kernel/slug.js +0 -67
  100. package/dist/kernel/slug.js.map +0 -1
  101. package/dist/kernel/task.d.ts +0 -213
  102. package/dist/kernel/task.js +0 -873
  103. package/dist/kernel/task.js.map +0 -1
  104. package/dist/kernel/tdd/adapter.d.ts +0 -49
  105. package/dist/kernel/tdd/adapter.js +0 -294
  106. package/dist/kernel/tdd/adapter.js.map +0 -1
  107. package/dist/kernel/tdd/digest.d.ts +0 -18
  108. package/dist/kernel/tdd/digest.js +0 -303
  109. package/dist/kernel/tdd/digest.js.map +0 -1
  110. package/dist/kernel/tdd/evaluator.d.ts +0 -38
  111. package/dist/kernel/tdd/evaluator.js +0 -185
  112. package/dist/kernel/tdd/evaluator.js.map +0 -1
  113. package/dist/kernel/tdd/evidence.d.ts +0 -42
  114. package/dist/kernel/tdd/evidence.js +0 -48
  115. package/dist/kernel/tdd/evidence.js.map +0 -1
  116. package/dist/kernel/tdd/state.d.ts +0 -79
  117. package/dist/kernel/tdd/state.js +0 -363
  118. package/dist/kernel/tdd/state.js.map +0 -1
  119. package/dist/kernel/types.d.ts +0 -180
  120. package/dist/kernel/types.js +0 -2
  121. package/dist/kernel/types.js.map +0 -1
  122. package/dist/kernel/worktree.d.ts +0 -45
  123. package/dist/kernel/worktree.js +0 -156
  124. package/dist/kernel/worktree.js.map +0 -1
  125. package/dist/plugin/flow-control.d.ts +0 -91
  126. package/dist/plugin/flow-control.js +0 -287
  127. package/dist/plugin/flow-control.js.map +0 -1
  128. package/dist/plugin/release-control.d.ts +0 -39
  129. package/dist/plugin/release-control.js +0 -343
  130. package/dist/plugin/release-control.js.map +0 -1
  131. package/dist/plugin/setup-control.d.ts +0 -59
  132. package/dist/plugin/setup-control.js +0 -111
  133. package/dist/plugin/setup-control.js.map +0 -1
  134. package/dist/plugin/task-control.d.ts +0 -90
  135. package/dist/plugin/task-control.js +0 -208
  136. package/dist/plugin/task-control.js.map +0 -1
  137. package/dist/plugin/tdd-checkpoint.d.ts +0 -128
  138. package/dist/plugin/tdd-checkpoint.js +0 -664
  139. package/dist/plugin/tdd-checkpoint.js.map +0 -1
  140. package/dist/util/shell.d.ts +0 -1
  141. package/dist/util/shell.js +0 -4
  142. package/dist/util/shell.js.map +0 -1
@@ -1,401 +0,0 @@
1
- import { exec } from "node:child_process";
2
- import { promisify } from "node:util";
3
- import { readdir, access, constants, readFile, writeFile, mkdir } from "node:fs/promises";
4
- import { join, basename } from "node:path";
5
- import { readProjectProfile, upsertProjectProfile } from "./profile.js";
6
- import { KeyedMutex } from "./mutex.js";
7
- import { escapeShellArg } from "../util/shell.js";
8
- import { parsePrUrlNumber } from "../util/gh.js";
9
- const execAsync = promisify(exec);
10
- let setupGitExecutor = null;
11
- let setupGhExecutor = null;
12
- export function setSetupGitExecutor(fn) {
13
- setupGitExecutor = fn;
14
- }
15
- export function setSetupGhExecutor(fn) {
16
- setupGhExecutor = fn;
17
- }
18
- async function runGit(args, cwd) {
19
- if (setupGitExecutor)
20
- return setupGitExecutor(args, cwd);
21
- return execAsync(`git ${args}`, { cwd });
22
- }
23
- async function runGh(args) {
24
- if (setupGhExecutor)
25
- return setupGhExecutor(args);
26
- return execAsync(`gh ${args}`, {});
27
- }
28
- /**
29
- * 探测项目 setup 就绪度(PRD R10)。
30
- * development-ready:git/gh + Profile 确认 + TDD 命令可执行 + CI workflow + 分支保护;
31
- * release-ready:额外版本规则 + release workflow。
32
- */
33
- export async function probe(projectDir) {
34
- const gitAvailable = await tryRun(() => runGit("--version", projectDir));
35
- const ghAuthenticated = await tryRun(() => runGh("auth status"));
36
- let remoteUrl = null;
37
- try {
38
- const { stdout } = await runGit("remote get-url origin", projectDir);
39
- remoteUrl = stdout.trim() || null;
40
- }
41
- catch {
42
- remoteUrl = null;
43
- }
44
- const hasRemote = remoteUrl !== null;
45
- let defaultBranch = null;
46
- try {
47
- const { stdout } = await runGit("symbolic-ref --short refs/remotes/origin/HEAD", projectDir);
48
- defaultBranch = stdout.trim() || null;
49
- }
50
- catch {
51
- defaultBranch = null;
52
- }
53
- const profile = await readProjectProfile(projectDir);
54
- const profileConfirmed = profile.testCommand !== null;
55
- const versionRuleConfirmed = profile.versionBumpRule !== null && profile.versionFile !== null && profile.tagFormat !== null;
56
- const tddCommandExecutable = await isCommandExecutable(profile.testCommand);
57
- const { ci, release } = await scanWorkflows(projectDir, profile.releaseWorkflowPath);
58
- const contextMdPresent = await fileExists(join(projectDir, "CONTEXT.md"));
59
- let branchProtection = false;
60
- const ownerRepo = remoteUrl ? parseGithubRemote(remoteUrl) : null;
61
- if (ownerRepo && defaultBranch) {
62
- branchProtection = await tryRun(() => runGh(`api repos/${ownerRepo.owner}/${ownerRepo.repo}/branches/${defaultBranch}/protection`));
63
- }
64
- const developmentReady = gitAvailable && ghAuthenticated && profileConfirmed && tddCommandExecutable && ci !== null && branchProtection;
65
- const releaseReady = developmentReady && versionRuleConfirmed && release !== null;
66
- return {
67
- gitAvailable,
68
- ghAuthenticated,
69
- hasRemote,
70
- defaultBranch,
71
- profileConfirmed,
72
- tddCommandExecutable,
73
- ciWorkflow: ci,
74
- releaseWorkflow: release,
75
- contextMdPresent,
76
- branchProtection,
77
- versionRuleConfirmed,
78
- developmentReady,
79
- releaseReady,
80
- };
81
- }
82
- /** 从 git remote URL 解析 GitHub owner/repo;非 GitHub 仓库返回 null */
83
- export function parseGithubRemote(url) {
84
- const patterns = [
85
- /^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/,
86
- /^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/,
87
- /^ssh:\/\/git@github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/,
88
- ];
89
- for (const pattern of patterns) {
90
- const match = pattern.exec(url);
91
- if (match)
92
- return { owner: match[1], repo: match[2] };
93
- }
94
- return null;
95
- }
96
- /**
97
- * 初始化 git 仓库(空目录场景):git init → 首次提交 → 可选 gh repo create + push。
98
- * 已初始化的仓库跳过对应步骤(幂等)。
99
- */
100
- export async function initRepo(projectDir, input) {
101
- const result = { ok: false, initialized: false, committed: false, remoteCreated: false };
102
- try {
103
- const isRepo = await tryRun(() => runGit("rev-parse --is-inside-work-tree", projectDir));
104
- if (!isRepo) {
105
- await runGit("init -b main", projectDir);
106
- result.initialized = true;
107
- }
108
- const hasCommits = await tryRun(() => runGit("rev-parse HEAD", projectDir));
109
- if (!hasCommits) {
110
- await runGit("add -A", projectDir);
111
- await runGit("commit -m 'chore: initial commit'", projectDir);
112
- result.committed = true;
113
- }
114
- if (input.createRemote) {
115
- const hasRemote = await tryRun(() => runGit("remote get-url origin", projectDir));
116
- if (!hasRemote) {
117
- const repoName = input.remoteName ?? basename(projectDir);
118
- await runGh(`repo create '${repoName}' ${input.private ? "--private" : "--public"} --source . --remote origin --push`);
119
- result.remoteCreated = true;
120
- }
121
- else {
122
- await runGit("push -u origin HEAD", projectDir);
123
- }
124
- }
125
- result.ok = true;
126
- return result;
127
- }
128
- catch (err) {
129
- result.error = String(err);
130
- return result;
131
- }
132
- }
133
- /** 扫描 .github/workflows/:文件名含 ci → CI workflow;含 release 或 Profile 指定路径 → release workflow */
134
- async function scanWorkflows(projectDir, profileReleasePath) {
135
- const workflowsDir = join(projectDir, ".github", "workflows");
136
- let files = [];
137
- try {
138
- files = (await readdir(workflowsDir)).filter(f => f.endsWith(".yml") || f.endsWith(".yaml"));
139
- }
140
- catch {
141
- files = [];
142
- }
143
- let ci = null;
144
- let release = null;
145
- for (const file of files) {
146
- const lower = file.toLowerCase();
147
- if (ci === null && lower.includes("ci"))
148
- ci = `.github/workflows/${file}`;
149
- if (release === null && lower.includes("release"))
150
- release = `.github/workflows/${file}`;
151
- }
152
- if (profileReleasePath && (await fileExists(join(projectDir, profileReleasePath)))) {
153
- release = profileReleasePath;
154
- }
155
- return { ci, release };
156
- }
157
- /** TDD 命令可执行:首个 token 存在于 PATH(相对路径则直接检查可执行) */
158
- async function isCommandExecutable(testCommand) {
159
- if (!testCommand)
160
- return false;
161
- const firstToken = testCommand.trim().split(/\s+/)[0];
162
- if (!firstToken)
163
- return false;
164
- const candidates = firstToken.includes("/")
165
- ? [firstToken]
166
- : (process.env.PATH ?? "").split(":").filter(Boolean).map(dir => join(dir, firstToken));
167
- for (const candidate of candidates) {
168
- if (await isExecutable(candidate))
169
- return true;
170
- }
171
- return false;
172
- }
173
- async function isExecutable(path) {
174
- try {
175
- await access(path, constants.X_OK);
176
- return true;
177
- }
178
- catch {
179
- return false;
180
- }
181
- }
182
- async function fileExists(path) {
183
- try {
184
- await access(path);
185
- return true;
186
- }
187
- catch {
188
- return false;
189
- }
190
- }
191
- async function tryRun(fn) {
192
- try {
193
- await fn();
194
- return true;
195
- }
196
- catch {
197
- return false;
198
- }
199
- }
200
- // ─── generate-workflows:缺失时生成 CI/release 草案 + Setup PR ───
201
- const SETUP_WORKFLOWS_BRANCH = "chore/setup-workflows";
202
- /** ci.yml 中的测试命令占位符(Profile 未确认时生成) */
203
- const TEST_COMMAND_PLACEHOLDER = "<test-command>";
204
- /**
205
- * 缺失时生成 CI/release workflow 草案(技术栈无关,不硬编码包管理器),
206
- * 创建 chore/setup-workflows 分支 + commit + push + Setup PR(人工合入)。
207
- * 幂等增强:
208
- * - 已存在的 workflow 含占位符(Profile 未确认时生成)→ 更新注入 test command(updated)
209
- * - 分支已存在(上次 PR 创建失败残留的 orphan 分支)→ 复用分支,不重复 checkout -b
210
- * - 分支已有 open PR → 复用 PR 编号,不重复创建(补建场景)
211
- */
212
- export async function generateWorkflows(projectDir, input) {
213
- const profile = await readProjectProfile(projectDir);
214
- const testCommand = input.testCommand ?? profile.testCommand;
215
- const tagFormat = input.tagFormat ?? profile.tagFormat;
216
- const releaseWorkflowPath = input.releaseWorkflowPath ?? profile.releaseWorkflowPath;
217
- let defaultBranch = input.defaultBranch ?? null;
218
- if (!defaultBranch) {
219
- try {
220
- const { stdout } = await runGit("symbolic-ref --short refs/remotes/origin/HEAD", projectDir);
221
- defaultBranch = stdout.trim() || null;
222
- }
223
- catch {
224
- defaultBranch = null;
225
- }
226
- }
227
- const workflowsDir = join(projectDir, ".github", "workflows");
228
- await mkdir(workflowsDir, { recursive: true });
229
- const { ci, release } = await scanWorkflows(projectDir, releaseWorkflowPath);
230
- const created = [];
231
- const updated = [];
232
- const existing = [];
233
- // ci.yml:缺失 → 创建;存在但含占位符(Profile 未确认时生成)→ 更新注入 test command
234
- if (ci === null) {
235
- await writeFile(join(workflowsDir, "ci.yml"), buildCiWorkflow(testCommand, defaultBranch));
236
- created.push(".github/workflows/ci.yml");
237
- }
238
- else {
239
- const ciPath = join(projectDir, ci);
240
- const ciContent = await readFile(ciPath, "utf8").catch(() => "");
241
- if (ciContent.includes(TEST_COMMAND_PLACEHOLDER)) {
242
- await writeFile(ciPath, buildCiWorkflow(testCommand, defaultBranch));
243
- updated.push(ci);
244
- }
245
- else {
246
- existing.push(ci);
247
- }
248
- }
249
- if (release === null) {
250
- const fileName = releaseWorkflowPath ? basename(releaseWorkflowPath) : "release.yml";
251
- await writeFile(join(workflowsDir, fileName), buildReleaseWorkflow(tagFormat));
252
- created.push(`.github/workflows/${fileName}`);
253
- }
254
- else {
255
- existing.push(release);
256
- }
257
- if (created.length === 0 && updated.length === 0) {
258
- return { ok: true, created, updated, existing, branch: null, prNumber: null };
259
- }
260
- try {
261
- const prTitle = input.prTitle || "chore: add CI/release workflow drafts";
262
- const prBody = `Setup generated workflow drafts for manual review:\n\n${[
263
- ...created.map(f => `- ${f}`),
264
- ...updated.map(f => `- ${f} (updated: test command injected)`),
265
- ].join("\n")}`;
266
- // 幂等:分支已存在(上次失败残留的 orphan 分支)→ 复用;否则新建
267
- const branchExists = await tryRun(() => runGit(`rev-parse --verify refs/heads/${SETUP_WORKFLOWS_BRANCH}`, projectDir));
268
- if (branchExists) {
269
- await runGit(`checkout ${SETUP_WORKFLOWS_BRANCH}`, projectDir);
270
- }
271
- else {
272
- await runGit(`checkout -b ${SETUP_WORKFLOWS_BRANCH}`, projectDir);
273
- }
274
- await runGit("add .github/workflows", projectDir);
275
- await runGit(`commit -m ${shellQuote(prTitle)}`, projectDir).catch(() => {
276
- // 无新变更(内容一致)时 commit 失败可忽略
277
- });
278
- await runGit(`push -u origin ${SETUP_WORKFLOWS_BRANCH}`, projectDir);
279
- // 幂等:分支已有 open PR → 复用,不重复创建
280
- const { stdout: prList } = await runGh(`pr list --head ${SETUP_WORKFLOWS_BRANCH} --state open --json number --jq '.[0].number'`);
281
- const existingPr = Number(prList.trim());
282
- if (Number.isInteger(existingPr) && existingPr > 0) {
283
- return { ok: true, created, updated, existing, branch: SETUP_WORKFLOWS_BRANCH, prNumber: existingPr };
284
- }
285
- const { stdout } = await runGh(`pr create --title ${shellQuote(prTitle)} --body ${shellQuote(prBody)} --base ${defaultBranch ?? "main"} --head ${SETUP_WORKFLOWS_BRANCH}`);
286
- return {
287
- ok: true,
288
- created,
289
- updated,
290
- existing,
291
- branch: SETUP_WORKFLOWS_BRANCH,
292
- // gh pr create 不支持 --json:解析 stdout 中的 PR URL
293
- prNumber: parsePrUrlNumber(stdout),
294
- };
295
- }
296
- catch (err) {
297
- return { ok: false, created, updated, existing, branch: null, prNumber: null, error: String(err) };
298
- }
299
- }
300
- /** CI workflow 草案:PR check 触发,运行 Profile 的测试命令(无则占位);纯文档 PR 不触发(paths-ignore,技术栈无关) */
301
- export function buildCiWorkflow(testCommand, defaultBranch) {
302
- const command = testCommand ?? "<test-command>";
303
- const branch = defaultBranch ?? "**";
304
- return [
305
- "name: CI",
306
- "",
307
- "on:",
308
- " pull_request:",
309
- " branches:",
310
- ` - '${branch}'`,
311
- " paths-ignore:",
312
- " - 'docs/**'",
313
- " - '**/*.md'",
314
- "",
315
- "jobs:",
316
- " check:",
317
- " runs-on: ubuntu-latest",
318
- " steps:",
319
- " - uses: actions/checkout@v4",
320
- ` - run: ${command}`,
321
- "",
322
- ].join("\n");
323
- }
324
- /** release workflow 草案:tag 触发,技术栈无关占位步骤 */
325
- export function buildReleaseWorkflow(tagFormat) {
326
- const tag = tagFormat ?? "v*";
327
- return [
328
- "name: Release",
329
- "",
330
- "on:",
331
- " push:",
332
- " tags:",
333
- ` - '${tag}'`,
334
- "",
335
- "jobs:",
336
- " release:",
337
- " runs-on: ubuntu-latest",
338
- " steps:",
339
- " - uses: actions/checkout@v4",
340
- " - run: echo \"Define project-specific release steps here (version bump + artifact publish)\"",
341
- "",
342
- ].join("\n");
343
- }
344
- function shellQuote(value) {
345
- return `'${escapeShellArg(value)}'`;
346
- }
347
- const profileMutex = new KeyedMutex();
348
- /** overrides JSON 键 → Profile 区块行键(§9.1 顺序) */
349
- const PROFILE_KEY_ORDER = [
350
- { jsonKey: "testCommand", sectionKey: "test command" },
351
- { jsonKey: "regressionCommand", sectionKey: "regression command" },
352
- { jsonKey: "testFilePatterns", sectionKey: "test file patterns" },
353
- { jsonKey: "implementationFilePatterns", sectionKey: "implementation file patterns" },
354
- { jsonKey: "tddDefaultMode", sectionKey: "tdd default mode" },
355
- { jsonKey: "versionBumpRule", sectionKey: "version bump rule" },
356
- { jsonKey: "versionFile", sectionKey: "version file" },
357
- { jsonKey: "tagFormat", sectionKey: "tag format" },
358
- { jsonKey: "releaseWorkflowPath", sectionKey: "release workflow" },
359
- { jsonKey: "riskPatterns", sectionKey: "risk patterns" },
360
- ];
361
- /** 由用户确认的 overrides 生成完整 `## Project Profile` 区块(未提供的键省略) */
362
- export function buildProfileBlock(overrides) {
363
- const lines = ["## Project Profile", ""];
364
- for (const { jsonKey, sectionKey } of PROFILE_KEY_ORDER) {
365
- const value = overrides[jsonKey];
366
- if (value === undefined || value === null)
367
- continue;
368
- const formatted = Array.isArray(value) ? value.join(", ") : String(value);
369
- if (formatted === "")
370
- continue;
371
- lines.push(`- ${sectionKey}: \`${formatted}\``);
372
- }
373
- return lines.join("\n");
374
- }
375
- /**
376
- * 用户确认后把 Profile 区块写回根 AGENTS.md(§9.3)。
377
- * 先读后写,按 key 串行(mutex);testCommand 为必需键。
378
- */
379
- export async function confirmProjectProfile(projectDir, overridesJson) {
380
- let overrides;
381
- try {
382
- overrides = JSON.parse(overridesJson);
383
- }
384
- catch {
385
- return { ok: false, code: "POLICY_INVALID", message: "profile_overrides is not valid JSON" };
386
- }
387
- if (typeof overrides !== "object" || overrides === null || Array.isArray(overrides)) {
388
- return { ok: false, code: "POLICY_INVALID", message: "profile_overrides must be a JSON object" };
389
- }
390
- if (typeof overrides.testCommand !== "string" || overrides.testCommand.trim() === "") {
391
- return { ok: false, code: "POLICY_INVALID", message: "testCommand is required to confirm the profile" };
392
- }
393
- const block = buildProfileBlock(overrides);
394
- const agentsPath = join(projectDir, "AGENTS.md");
395
- await profileMutex.runExclusive("agents-md", async () => {
396
- const markdown = await readFile(agentsPath, "utf8").catch(() => "");
397
- await writeFile(agentsPath, upsertProjectProfile(markdown, block));
398
- });
399
- return { ok: true, block };
400
- }
401
- //# sourceMappingURL=setup.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/kernel/setup.ts"],"names":[],"mappings":"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"}
@@ -1,23 +0,0 @@
1
- export declare const MAX_SLUG_LENGTH = 60;
2
- export type BranchType = "feat" | "fix" | "chore" | "docs";
3
- export type SlugValidationResult = {
4
- ok: true;
5
- slug: string;
6
- } | {
7
- ok: false;
8
- code: "EMPTY_TITLE" | "INVALID_FORMAT" | "SLUG_TOO_LONG" | "GENERIC_TITLE";
9
- message: string;
10
- };
11
- /**
12
- * 严格 slug 派生:沿用 util/paths.ts slugify 的归一化规则,
13
- * 但不做 "doc" 兜底——无意义输入返回空串,由调用方判定。
14
- */
15
- export declare function deriveSlug(value: string): string;
16
- /**
17
- * 校验功能标题(须已是 kebab-case slug):
18
- * - 空标题、非法字符(大写/下划线/空格/连续连字符/首尾连字符)、过长(>60)→ 格式拒绝
19
- * - 纯序号或全部由泛化词组成(task-001、implement-task、fix-bug)→ GENERIC_TITLE
20
- */
21
- export declare function validateTitle(title: string): SlugValidationResult;
22
- export declare function branchFor(slug: string, type: BranchType): string;
23
- export declare function worktreeFor(slug: string): string;
@@ -1,67 +0,0 @@
1
- export const MAX_SLUG_LENGTH = 60;
2
- /** 合法 slug:小写字母/数字分段,段间单个连字符 */
3
- const SLUG_FORMAT = /^[a-z0-9]+(-[a-z0-9]+)*$/;
4
- /** 泛化/占位词:与数字或其他泛化词组合时无法表达具体功能 */
5
- const GENERIC_WORDS = new Set([
6
- "add", "bug", "bugs", "chore", "create", "delete", "docs", "feature",
7
- "features", "fix", "fixes", "implement", "issue", "issues", "refactor",
8
- "remove", "support", "task", "tasks", "test", "tests", "update", "wip",
9
- ]);
10
- /**
11
- * 严格 slug 派生:沿用 util/paths.ts slugify 的归一化规则,
12
- * 但不做 "doc" 兜底——无意义输入返回空串,由调用方判定。
13
- */
14
- export function deriveSlug(value) {
15
- let slug = value
16
- .trim()
17
- .toLowerCase()
18
- .replace(/[^a-z0-9]+/g, "-")
19
- .replace(/^-+|-+$/g, "")
20
- .replace(/--+/g, "-");
21
- if (slug.length > MAX_SLUG_LENGTH) {
22
- const sliced = slug.slice(0, MAX_SLUG_LENGTH);
23
- const lastDash = sliced.lastIndexOf("-");
24
- slug = lastDash > MAX_SLUG_LENGTH / 2 ? sliced.slice(0, lastDash) : sliced;
25
- }
26
- return slug;
27
- }
28
- /**
29
- * 校验功能标题(须已是 kebab-case slug):
30
- * - 空标题、非法字符(大写/下划线/空格/连续连字符/首尾连字符)、过长(>60)→ 格式拒绝
31
- * - 纯序号或全部由泛化词组成(task-001、implement-task、fix-bug)→ GENERIC_TITLE
32
- */
33
- export function validateTitle(title) {
34
- if (title.trim() === "") {
35
- return { ok: false, code: "EMPTY_TITLE", message: "Title must not be empty" };
36
- }
37
- if (title.length > MAX_SLUG_LENGTH) {
38
- return { ok: false, code: "SLUG_TOO_LONG", message: `Title must be at most ${MAX_SLUG_LENGTH} characters` };
39
- }
40
- if (!SLUG_FORMAT.test(title)) {
41
- return {
42
- ok: false,
43
- code: "INVALID_FORMAT",
44
- message: "Title must be a kebab-case slug: lowercase letters, digits, and single hyphens between segments",
45
- };
46
- }
47
- if (isGenericSlug(title)) {
48
- return {
49
- ok: false,
50
- code: "GENERIC_TITLE",
51
- message: "Title is too generic: use a functional slug that describes the concrete behavior",
52
- };
53
- }
54
- return { ok: true, slug: title };
55
- }
56
- /** 纯序号,或所有分段均为泛化词/数字 → 无法描述具体功能 */
57
- function isGenericSlug(slug) {
58
- const segments = slug.split("-");
59
- return segments.every(seg => /^\d+$/.test(seg) || GENERIC_WORDS.has(seg));
60
- }
61
- export function branchFor(slug, type) {
62
- return `${type}/${slug}`;
63
- }
64
- export function worktreeFor(slug) {
65
- return `.worktree/${slug}`;
66
- }
67
- //# sourceMappingURL=slug.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"slug.js","sourceRoot":"","sources":["../../src/kernel/slug.ts"],"names":[],"mappings":"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"}