ai-project-manage-cli 6.0.88 → 6.0.90
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.
- package/dist/index.js +64 -9
- package/package.json +1 -1
- package/template/AGENTS.md +2 -1
- package/template/collaboration-prompt.md +24 -0
- package/template/skills/apm-confirm-assumptions/SKILL.md +21 -0
- package/template/skills/apm-dev/SKILL.md +14 -11
- package/template/skills/apm-diff-review/SKILL.md +3 -4
- package/template/skills/apm-rewrite-assumptions/SKILL.md +12 -0
- package/template/skills/apm-write-checklist/SKILL.md +1 -1
- package/template/skills/apm-write-plan/SKILL.md +24 -47
- package/template/skills/apm-write-plan/plan-template.md +14 -4
- package/template/skills/apm-deploy/SKILL.md +0 -23
package/dist/index.js
CHANGED
|
@@ -244,6 +244,9 @@ function sessionYamlPath(sessionId, apmRoot) {
|
|
|
244
244
|
function sessionMessagesXmlPath(sessionId, apmRoot) {
|
|
245
245
|
return join2(sessionDir(sessionId, apmRoot), "messages.xml");
|
|
246
246
|
}
|
|
247
|
+
function sessionAssumptionsJsonPath(sessionId, apmRoot) {
|
|
248
|
+
return join2(sessionDir(sessionId, apmRoot), "assumptions.json");
|
|
249
|
+
}
|
|
247
250
|
function documentLocalFileName(platformName) {
|
|
248
251
|
const trimmed = platformName.trim();
|
|
249
252
|
if (!trimmed) return "document.md";
|
|
@@ -399,6 +402,14 @@ var requestConfig = {
|
|
|
399
402
|
method: "GET",
|
|
400
403
|
path: "/cli/documents"
|
|
401
404
|
}),
|
|
405
|
+
listAssumptions: defineEndpoint({
|
|
406
|
+
method: "GET",
|
|
407
|
+
path: "/cli/assumptions"
|
|
408
|
+
}),
|
|
409
|
+
markAssumptionsBackfilled: defineEndpoint({
|
|
410
|
+
method: "POST",
|
|
411
|
+
path: "/cli/assumptions/mark-backfilled"
|
|
412
|
+
}),
|
|
402
413
|
listAttachments: defineEndpoint(
|
|
403
414
|
{
|
|
404
415
|
method: "GET",
|
|
@@ -1706,15 +1717,14 @@ async function runPull(sessionId, remoteWorkdir) {
|
|
|
1706
1717
|
const api = createApmApiClient(cfg);
|
|
1707
1718
|
const workdir = remoteWorkdir === void 0 ? resolveWorkdirPath() : requireRemoteWorkdir(remoteWorkdir);
|
|
1708
1719
|
const apmRoot = workspaceApmDir(workdir);
|
|
1709
|
-
const [detail, members, documents, attachments, messages] = await Promise.all(
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
);
|
|
1720
|
+
const [detail, members, documents, attachments, messages, assumptions] = await Promise.all([
|
|
1721
|
+
api.cli.sessionDetail({ sessionId: trimmedId }),
|
|
1722
|
+
api.cli.sessionMembers({ sessionId: trimmedId }),
|
|
1723
|
+
api.cli.listDocuments({ sessionId: trimmedId }),
|
|
1724
|
+
api.cli.listAttachments({ sessionId: trimmedId }),
|
|
1725
|
+
api.cli.listSessionMessages({ sessionId: trimmedId }),
|
|
1726
|
+
api.cli.listAssumptions({ sessionId: trimmedId }).catch(() => null)
|
|
1727
|
+
]);
|
|
1718
1728
|
const dir = sessionDir(trimmedId, apmRoot);
|
|
1719
1729
|
const docsDir = sessionDocsDir(trimmedId, apmRoot);
|
|
1720
1730
|
await ensureDirExists(docsDir);
|
|
@@ -1759,6 +1769,20 @@ async function runPull(sessionId, remoteWorkdir) {
|
|
|
1759
1769
|
formatSessionMessagesXml(trimmedId, messages),
|
|
1760
1770
|
"utf8"
|
|
1761
1771
|
);
|
|
1772
|
+
writeFileSync9(
|
|
1773
|
+
sessionAssumptionsJsonPath(trimmedId, apmRoot),
|
|
1774
|
+
JSON.stringify(
|
|
1775
|
+
assumptions ?? {
|
|
1776
|
+
sessionId: trimmedId,
|
|
1777
|
+
clearedAt: null,
|
|
1778
|
+
backfilledAt: null,
|
|
1779
|
+
assumptions: []
|
|
1780
|
+
},
|
|
1781
|
+
null,
|
|
1782
|
+
2
|
|
1783
|
+
),
|
|
1784
|
+
"utf8"
|
|
1785
|
+
);
|
|
1762
1786
|
await syncSessionAttachments(cfg, trimmedId, attachments, apmRoot);
|
|
1763
1787
|
await syncPlatformRules(cfg, trimmedId, workdir, apmRoot);
|
|
1764
1788
|
await syncRemoteDeploymentConfig(workdir, apmRoot);
|
|
@@ -2128,6 +2152,30 @@ async function runSyncDocument(sessionId, options) {
|
|
|
2128
2152
|
console.log(`[apm] \u5DF2\u540C\u6B65\u6587\u6863: ${doc.name} (id=${doc.id})`);
|
|
2129
2153
|
}
|
|
2130
2154
|
|
|
2155
|
+
// src/commands/assumptions.ts
|
|
2156
|
+
async function runAssumptionsList(sessionId) {
|
|
2157
|
+
const trimmedId = sessionId.trim();
|
|
2158
|
+
if (!trimmedId) {
|
|
2159
|
+
console.error("[apm] sessionId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
2160
|
+
process.exit(1);
|
|
2161
|
+
}
|
|
2162
|
+
const cfg = await ensureLoggedConfig();
|
|
2163
|
+
const api = createApmApiClient(cfg);
|
|
2164
|
+
const data = await api.cli.listAssumptions({ sessionId: trimmedId });
|
|
2165
|
+
console.log(JSON.stringify(data, null, 2));
|
|
2166
|
+
}
|
|
2167
|
+
async function runAssumptionsMarkBackfilled(sessionId) {
|
|
2168
|
+
const trimmedId = sessionId.trim();
|
|
2169
|
+
if (!trimmedId) {
|
|
2170
|
+
console.error("[apm] sessionId \u4E0D\u80FD\u4E3A\u7A7A");
|
|
2171
|
+
process.exit(1);
|
|
2172
|
+
}
|
|
2173
|
+
const cfg = await ensureLoggedConfig();
|
|
2174
|
+
const api = createApmApiClient(cfg);
|
|
2175
|
+
await api.cli.markAssumptionsBackfilled({ sessionId: trimmedId });
|
|
2176
|
+
console.log(`[apm] \u5DF2\u6807\u8BB0\u5047\u8BBE\u56DE\u586B\u5B8C\u6210: sessionId=${trimmedId}`);
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2131
2179
|
// src/commands/append-message.ts
|
|
2132
2180
|
async function appendMessageContent(cfg, messageId, content) {
|
|
2133
2181
|
const trimmedId = messageId.trim();
|
|
@@ -6973,6 +7021,13 @@ function buildProgram() {
|
|
|
6973
7021
|
).argument("<sessionId>", "\u6C9F\u901A\u7FA4 ID").action(async (sessionId) => {
|
|
6974
7022
|
await runPull(sessionId);
|
|
6975
7023
|
});
|
|
7024
|
+
program.command("assumptions").description("\u5047\u8BBE\u786E\u8BA4\uFF1A\u5217\u51FA\u6216\u6807\u8BB0\u56DE\u586B\u5B8C\u6210").argument("<sessionId>", "\u6C9F\u901A\u7FA4 ID").option("--mark-backfilled", "\u6807\u8BB0\u5047\u8BBE\u5DF2\u5199\u56DE\u8BA1\u5212").action(async (sessionId, opts) => {
|
|
7025
|
+
if (opts.markBackfilled) {
|
|
7026
|
+
await runAssumptionsMarkBackfilled(sessionId);
|
|
7027
|
+
return;
|
|
7028
|
+
}
|
|
7029
|
+
await runAssumptionsList(sessionId);
|
|
7030
|
+
});
|
|
6976
7031
|
program.command("sync-document").description("\u5C06\u672C\u5730 Markdown \u8986\u76D6\u5F0F upsert \u5230\u5E73\u53F0\u4EFB\u52A1\u6587\u6863").argument("<sessionId>", "\u6C9F\u901A\u7FA4 ID").requiredOption(
|
|
6977
7032
|
"--file <name>",
|
|
6978
7033
|
"\u6587\u6863\u540D\u79F0\uFF08\u5982 PRD \u6216 PRD.md\uFF09\uFF0C\u8BFB\u53D6 .apm/sessions/<sessionId>/docs/ \u4E0B\u5BF9\u5E94\u6587\u4EF6"
|
package/package.json
CHANGED
package/template/AGENTS.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
3. **立即**用 `append_message` 工具回复(可先简短确认,再补充)
|
|
12
12
|
4. 按需阅读 `docs/` 下的文档,有进展继续调用 `append_message`
|
|
13
13
|
|
|
14
|
-
####
|
|
14
|
+
#### 重任务(开发、写方案、评审)
|
|
15
15
|
|
|
16
16
|
1. 读取 `.apm/sessions/<会话ID>/session.yaml`,必要时读取 `messages.xml` 了解历史
|
|
17
17
|
2. 根据你的名字从 `session.yaml` 的 `members` 中找到你对应的 **description**(智能体描述,非人设提示词)
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
- write_doc.md:当需要写文档时需要读取这个文档,记住写文档的规则
|
|
32
32
|
|
|
33
33
|
- 仓库项目上下文(`.apm/project/`):
|
|
34
|
+
|
|
34
35
|
- 索引: `.apm/project/manifest.json` — 本仓库在平台登记的文档列表
|
|
35
36
|
- 文档文件: `.apm/project/{path}` — 与 manifest 中 path 对应;`apm pull` 自动同步,`apm connect` 消息结束后自动推回平台
|
|
36
37
|
- 任务涉及菜单名、路由、业务术语等时,**先 Read manifest 与相关文档**,禁止猜测路径
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
### 阶段 1:实现计划(前后端可同轮并行)
|
|
2
|
+
|
|
3
|
+
前端、后端工程师各自按技能 `apm-write-plan` 执行:先判断本需求是否涉及本端,不涉及则回复「与本端无关」并说明理由;涉及则直接基于需求原文编写实现计划(后端 `BACKEND-PLAN.md` 含「API 契约」,前端 `FRONTEND-PLAN.md`),计划必须包含「依据与假设」与「改动文件白名单」。**禁止改代码。**
|
|
4
|
+
计划存在「假设」时 @ 项目经理逐条确认,然后进入阶段 1.5;计划无假设时直接进入阶段 2。
|
|
5
|
+
|
|
6
|
+
### 阶段 2:假设回填(项目经理回复假设后,单人或多人按需)
|
|
7
|
+
|
|
8
|
+
项目经理回复假设确认后,必须安排对应工程师按技能 `apm-write-plan` 步骤 5 执行假设回填:阅读聊天记录中项目经理的回复,把确认的假设移入计划「依据」、被否定的按新口径修订实现步骤与白名单,重新同步计划并逐条回复处理结果。回填完成(假设清零)后才进入阶段 2;**禁止跳过本阶段直接安排开发**。计划无假设时跳过本阶段。
|
|
9
|
+
|
|
10
|
+
### 阶段 3:需求开发(前后端可同轮并行)
|
|
11
|
+
|
|
12
|
+
前后端工程师按技能 `apm-dev` 各自开发:只允许改动本端计划「改动文件白名单」内的文件;前端接口对接以后端计划的「API 契约」为准。完成标准 = 构建通过 + 回复中逐文件对账白名单。**禁止自行部署。** **不安排联调。**完成后进入阶段 4。
|
|
13
|
+
|
|
14
|
+
### 阶段 4:diff 评审(单人)
|
|
15
|
+
|
|
16
|
+
评审工程师按技能 `apm-diff-review` 执行:检查 git 改动是否越出白名单、是否夹带与需求无关的修改、计划关键点是否落实。不通过:列出问题清单 @ 对应工程师,回到阶段 3 修复,同一任务最多打回 3 次,超过则 @ 项目经理决策;通过:@ 项目经理交人验收(部署与回归验收由人工或平台完成)。
|
|
17
|
+
|
|
18
|
+
### 阶段 5:需求验收
|
|
19
|
+
|
|
20
|
+
项目经理验证并给出结论。全部通过则任务完成;某条不通过时回复「第 N 条不通过,实际现象:xxx」,由对应工程师回到阶段 3 修复该条,修复后重新走阶段 4 评审再重验。
|
|
21
|
+
|
|
22
|
+
### BUG 修复流程
|
|
23
|
+
|
|
24
|
+
项目经理描述 BUG 现象。前端、后端工程师按顺序分轮发言,各自分析归属并给出结论;归属明确后由责任端按阶段 3 标准修复,再走阶段 4 评审与项目经理重验。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# apm-confirm-assumptions:按 PM 确认结果回填计划
|
|
2
|
+
|
|
3
|
+
## 何时使用
|
|
4
|
+
|
|
5
|
+
收到项目经理会话消息「已回复所有假设,可以继续后面的流程」后;或 `assumptions.json` 中 `clearedAt` 有值且 `backfilledAt` 为空。
|
|
6
|
+
|
|
7
|
+
## 工作流程
|
|
8
|
+
|
|
9
|
+
1. **Read** `.apm/sessions/<会话ID>/assumptions.json`;不存在或 `backfilledAt` 已有 → 退出。
|
|
10
|
+
2. **Read** 本 Skill;过滤 **本端** 条目(后端只看 `BACKEND_PLAN`,前端只看 `FRONTEND_PLAN`)。
|
|
11
|
+
3. **Read** 本端计划:`docs/BACKEND-PLAN.md` 或 `docs/FRONTEND-PLAN.md`。
|
|
12
|
+
4. 逐条按 `resolution` 更新计划:
|
|
13
|
+
- 移入「依据」表,来源写「项目经理确认」;
|
|
14
|
+
- 从「假设」章节删除该题;
|
|
15
|
+
- `customAnswer` 或影响实现范围时 → 修订「实现步骤 / 改动文件白名单」;后端涉及接口则同步 `docs/API.md`。
|
|
16
|
+
5. **`apm sync-document`** 同步计划(及 API 文档)。
|
|
17
|
+
6. **Read/Update** `TODO.md`:勾选「等待项目经理确认假设」等相关项。
|
|
18
|
+
7. **`append_message`**:摘要回填结果;声明「假设已清零,可进入测试要点编写」。
|
|
19
|
+
8. 执行 **`apm assumptions <会话ID> --mark-backfilled`**。
|
|
20
|
+
|
|
21
|
+
**禁止**从 `messages.xml` 解析 PM 对假设的回复——只认 `assumptions.json`。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# apm-dev
|
|
1
|
+
# apm-dev:按计划开发
|
|
2
2
|
|
|
3
3
|
## 工作流程
|
|
4
4
|
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
1. 用 **Read** 工具阅读本端计划:前端读 `.apm/sessions/<会话ID>/docs/FRONTEND-PLAN.md`,后端读 `docs/BACKEND-PLAN.md`;计划不存在则退出流程并回复说明(兼容旧流程:若存在 `PRD.md` + `FRONTEND.md` / `BACKEND.md` + `API.md`,按旧文档执行)。
|
|
8
8
|
2. 前端涉及接口对接时,以 `docs/API.md` 为唯一契约来源,**不等后端部署完成**;`API.md` 不存在或字段没写清时 `@后端` 补充,禁止自行猜测或在计划中重复编写接口定义。
|
|
9
|
-
3.
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
9
|
+
3. **假设门禁(开发前必须检查)**:
|
|
10
|
+
- **Read** `.apm/sessions/<会话ID>/assumptions.json`;
|
|
11
|
+
- 有 `PENDING` 且 `quality=OK` → `@项目经理` 请其在 Web「待您确认」Panel 提交,**停止开发**;
|
|
12
|
+
- `clearedAt` 有值但 `backfilledAt` 为空 → 执行 **`apm-confirm-assumptions`**(或 `@` 本端自行回填),**停止开发**;
|
|
13
|
+
- 计划「假设」章节仍有未清空项 → 同上,停止开发。
|
|
14
|
+
**禁止**从 `messages.xml` 解析 PM 假设回复。
|
|
14
15
|
|
|
15
16
|
### 步骤 2: 明确开发模式
|
|
16
17
|
|
|
@@ -81,14 +82,16 @@ ALTER TABLE inspection_class ADD COLUMN is_project_add VARCHAR(1) DEFAULT '0';
|
|
|
81
82
|
- Quick / Spec 子 Agent 完成且本地已有 commit 时,父 Agent **立即 `git push`**(当前分支首次 push 用 `git push -u origin HEAD`)。
|
|
82
83
|
- 无本地 commit、无远程或未配置 upstream 时说明原因,勿强行 push。
|
|
83
84
|
|
|
84
|
-
### 步骤 6:
|
|
85
|
+
### 步骤 6: 构建验证(完成定义)
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
开发完成的定义是以下各项**全部满足**,缺一不可:
|
|
87
88
|
|
|
88
|
-
1. **构建通过**:执行本仓库的构建/检查命令(见 AGENTS.md
|
|
89
|
-
2.
|
|
89
|
+
1. **构建通过**:执行本仓库的构建/检查命令(见 AGENTS.md),失败必须修复后重试。
|
|
90
|
+
2. **SQL 文档**(**仅后端**):涉及 SQL 变更时,须在回复中引用 `docs/SQL.md`,并写明待执行的 SQL 文件名或执行顺序。
|
|
90
91
|
3. **白名单对账**:在回复中逐文件列出本次改动与计划白名单的对应关系。
|
|
91
92
|
|
|
93
|
+
**禁止自行部署。** 不要执行 `apm deploy`、`apm deploy-frontend`、`apm deploy-backend`、`apm deploy-sftp` 等任何部署命令;发布测试/正式环境由人工或平台触发。
|
|
94
|
+
|
|
92
95
|
**注意:不做联调。** 前后端各自按 `API.md` 交付,接口对不上属于契约或实现问题,由 diff 评审与人工验收暴露后打回修复;禁止自行发起「联调」「接口实测」类的开放式动作。
|
|
93
96
|
|
|
94
|
-
完成后用 `append_message` 回复:改动概述 + 白名单对账 +
|
|
97
|
+
完成后用 `append_message` 回复:改动概述 + 白名单对账 + 构建结果,并 `@` 评审角色进行 diff 评审。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## 适用范围
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
开发完成之后,由评审角色(可以是另一端工程师或专职评审智能体)检查 git 改动是否「只做了该做的事」。这是防止 AI 乱改代码的机器门禁:**通过才交人验收,不通过打回开发**。
|
|
6
6
|
|
|
7
7
|
评审对象是 **diff**,不是整个代码库;禁止借评审之机重构或顺手改代码。**本技能全程只读,不允许写任何代码。**
|
|
8
8
|
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
评审**通过**后,先在工作目录执行(创建/更新本会话特性分支对应的 PR):
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
apm create-pr --session <会话ID> --title "<需求摘要>" --content "<计划摘要 + 白名单对账 +
|
|
38
|
+
apm create-pr --session <会话ID> --title "<需求摘要>" --content "<计划摘要 + 白名单对账 + 评审结论>"
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
- 标题会自动加上 `[AI]` 标识,表明该 PR 由 AI 创建;同一分支已有开启的 PR 时会改为更新,不会重复创建。
|
|
@@ -48,8 +48,7 @@ apm create-pr --session <会话ID> --title "<需求摘要>" --content "<计划
|
|
|
48
48
|
|
|
49
49
|
1. 「diff 评审通过」+ 一句话改动概述;
|
|
50
50
|
2. **PR 链接**(上一步 `apm create-pr` 输出;创建失败则注明原因);
|
|
51
|
-
3.
|
|
52
|
-
4. 提示按 `CHECKLIST.md` 逐条验收。
|
|
51
|
+
3. 提示按 `CHECKLIST.md` 逐条验收(部署与回归验收由人工或平台完成)。
|
|
53
52
|
|
|
54
53
|
**不通过**:用 `append_message` 输出问题清单(每条注明文件 + 问题 + 依据哪条计划/需求),`@` 对应工程师打回修改。**禁止自己动手改。**
|
|
55
54
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# apm-rewrite-assumptions:重写 PM 不友好的假设问法
|
|
2
|
+
|
|
3
|
+
## 何时使用
|
|
4
|
+
|
|
5
|
+
`apm sync-document` 后平台标记假设 `quality=NEEDS_REWRITE`,或计划被退回需重写「问 / 场景 / 选项」。
|
|
6
|
+
|
|
7
|
+
## 工作流程
|
|
8
|
+
|
|
9
|
+
1. **Read** 本端计划文档的「假设」章节与 `qualityIssues`(若有 assumptions.json 中的 technicalNote)。
|
|
10
|
+
2. 将研发术语移入 **研发备注**;**问** 改为 PM 可理解的业务句子;补全 **场景** 与 **≥2 个选项**(含 id + label)。
|
|
11
|
+
3. **禁止多选**;复合口径说明写在 Other 指引中。
|
|
12
|
+
4. 重新 **`apm sync-document`** 同步计划。
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
逐条对照需求原文与计划:
|
|
21
21
|
|
|
22
22
|
- **计划与需求矛盾、或需求关键点在计划中没有覆盖**:不要写清单,先用 `append_message` 指出问题并 `@` 对应工程师打回,等计划修订后再写。
|
|
23
|
-
-
|
|
23
|
+
- **计划中的「假设」尚未确认或尚未回填计划**(查 `assumptions.json`:`PENDING` 或 `clearedAt && !backfilledAt`):**不要写清单**,先提醒 PM / 执行 `apm-confirm-assumptions`。
|
|
24
24
|
- 计划覆盖完整:进入步骤 3。
|
|
25
25
|
|
|
26
26
|
### 步骤 3:按模板写清单
|
|
@@ -4,14 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
前端 / 后端工程师在任务启动后**直接读原始需求写实现计划**,不经过 PRD。
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
|
10
|
-
|
|
|
11
|
-
| 后端 | `BACKEND-PLAN.md`(实现计划)+ `API.md`(联调契约,单独产出) | `docs/BACKEND-PLAN.md`、`docs/API.md` |
|
|
12
|
-
| 前端 | `FRONTEND-PLAN.md` | `docs/FRONTEND-PLAN.md` |
|
|
13
|
-
|
|
14
|
-
**两份后端文档禁止合并**:`BACKEND-PLAN.md` 不写完整参数表 / JSON 示例;`API.md` 不写 Service / SQL 等实现细节。
|
|
7
|
+
| 角色 | 产出文档 | 路径 |
|
|
8
|
+
| ---- | -------- | ---- |
|
|
9
|
+
| 后端 | `BACKEND-PLAN.md` + `API.md` | `docs/BACKEND-PLAN.md`、`docs/API.md` |
|
|
10
|
+
| 前端 | `FRONTEND-PLAN.md` | `docs/FRONTEND-PLAN.md` |
|
|
15
11
|
|
|
16
12
|
---
|
|
17
13
|
|
|
@@ -19,61 +15,42 @@
|
|
|
19
15
|
|
|
20
16
|
### 步骤 1:判断本端是否需要参与
|
|
21
17
|
|
|
22
|
-
**Read** `.apm/sessions/<会话ID>/TASK.md
|
|
18
|
+
**Read** `.apm/sessions/<会话ID>/TASK.md`。
|
|
23
19
|
|
|
24
|
-
-
|
|
20
|
+
- **不涉及本端改动**:`append_message` 回复理由后结束。
|
|
25
21
|
- **涉及本端改动**:进入步骤 2。
|
|
26
22
|
|
|
27
|
-
### 步骤 2
|
|
28
|
-
|
|
29
|
-
1. **优先读现成结论**:先读 `docs/` 下已有的模块档案、历史工作日志、其他成员已同步的文档,能复用就不要重新调研。
|
|
30
|
-
2. **再调研代码**:只看与需求直接相关的页面 / 接口 / 表。**调研预算:最多读 15 个代码文件**,禁止全库考古、禁止顺藤摸瓜阅读无关模块。
|
|
31
|
-
3. **口径不清不要自己拍板**:调研中发现需求没写清的业务口径(例如字段含义、互斥规则、历史数据兼容),一律记入计划的「依据与假设」章节,禁止编造业务规则。
|
|
23
|
+
### 步骤 2:有限调研
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
1. 优先读 `docs/` 现成结论。
|
|
26
|
+
2. 代码调研预算:**最多 15 个文件**。
|
|
27
|
+
3. 口径不清 → 记入「假设」章节,禁止编造。
|
|
34
28
|
|
|
35
29
|
### 步骤 3:按模板写计划
|
|
36
30
|
|
|
37
|
-
**Read** `.apm/skills/apm-write-plan/plan-template.md
|
|
31
|
+
**Read** `.apm/skills/apm-write-plan/plan-template.md`,**Write** 计划文档。
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
2. **改动文件白名单**:本次允许改动的文件完整列表。后续开发与 diff 评审都以此为准,**开发时改了白名单之外的文件会被打回**。
|
|
41
|
-
3. **后端专属——同步产出 API.md**(涉及接口变更时):**Read** `.apm/skills/apm-write-plan/api-template.md`,按模板 **Write** `docs/API.md`。这是前端联调的唯一契约来源,前端直接阅读本文档,禁止各写一份。
|
|
42
|
-
4. **后端专属——SQL 变更声明**(仅当涉及表结构/数据变更时):在「实现步骤」中注明开发须产出 `docs/SQL.md`;计划本身不写大段 SQL,完整语句由后端开发阶段写入该文档。
|
|
43
|
-
5. **前端专属——接口对接要点**:只写「何时调、关键点」,引用 `API.md` 章节,**禁止复制参数表 / JSON 示例**。
|
|
33
|
+
### 步骤 3.5:假设 PM 友好自检(sync 前必做)
|
|
44
34
|
|
|
45
|
-
|
|
35
|
+
每条假设必须含 **问 / 场景 / 选项(≥2 项,id + label)**:
|
|
46
36
|
|
|
47
|
-
|
|
37
|
+
- **问** 禁止:`status=`、字段名、表名、类路径、SQL。
|
|
38
|
+
- **禁止多选**;复合口径由 PM 在 Web「其他」中填写。
|
|
39
|
+
- 能自己查清的代码含义 → 移入「依据」,删除假设。
|
|
40
|
+
- 技术发现 → 写进 **研发备注**,问句用业务语言。
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
- **无假设**:回复计划已就绪,可进入测试要点编写。
|
|
51
|
-
- **后端**:涉及接口变更时,回复中 `@前端` 阅读 `API.md` 并编写 `FRONTEND-PLAN.md`。
|
|
52
|
-
- **前端**:`API.md` 尚未就绪时,回复 `@后端` 先产出 `API.md`,**禁止自行编写接口契约**。
|
|
42
|
+
### 步骤 4:同步与回复
|
|
53
43
|
|
|
54
|
-
|
|
44
|
+
1. `apm sync-document` 同步计划(及 API 文档)。
|
|
45
|
+
2. **有假设**:`@项目经理` 请其在 Web **「待您确认」** Panel 点选;说明「以上假设确认前不开始开发」。**禁止**在聊天里粘贴研发术语。
|
|
46
|
+
3. **无假设**:回复计划已就绪,可进入测试要点编写。
|
|
55
47
|
|
|
56
|
-
|
|
48
|
+
### 假设回填
|
|
57
49
|
|
|
58
|
-
|
|
59
|
-
2. 更新计划文档:
|
|
60
|
-
- 被确认的假设 → **移入「依据」表格**,来源写「项目经理确认(第 N 轮)」;
|
|
61
|
-
- 被否定或修正的假设 → 按项目经理给出的口径**修订「实现步骤」与「改动文件白名单」**;
|
|
62
|
-
- 项目经理没有回应的假设 → 保留在「假设」中,再次 `@项目经理` 追问。
|
|
63
|
-
3. **后端**:假设修订涉及接口口径时,同步更新 `docs/API.md`。
|
|
64
|
-
4. 重新执行 `apm sync-document` 同步计划与 API 文档。
|
|
65
|
-
5. 回复消息:逐条说明每个假设的处理结果(确认采纳 / 按口径修订了什么),全部解决则声明「假设已清零,可进入测试要点编写」。
|
|
66
|
-
|
|
67
|
-
**禁止**跳过回填直接开发:澄清结论必须落进计划文档(接口口径落进 `API.md`),后续开发与 diff 评审都只认文档,不认聊天记录。
|
|
50
|
+
项目经理确认后由 **`apm-confirm-assumptions`** 技能执行(读 `assumptions.json`,**禁止**读 messages.xml 猜 PM 回复)。
|
|
68
51
|
|
|
69
52
|
---
|
|
70
53
|
|
|
71
|
-
## 写作要求
|
|
72
|
-
|
|
73
|
-
- 篇幅 **40 ~ 100 行**,宁可少写;不要伪代码、不要大段 SQL(完整语句写入 `docs/SQL.md`,由后端开发阶段产出)。
|
|
74
|
-
- 用产品语言描述行为,文件路径只出现在「改动文件白名单」。
|
|
75
|
-
- 前后端可同轮并行编写计划;前端接口部分依赖 `API.md`,后端须先或同步产出。
|
|
76
|
-
|
|
77
54
|
## 何时使用
|
|
78
55
|
|
|
79
|
-
协作流程阶段 1
|
|
56
|
+
协作流程阶段 1(实现计划)。
|
|
@@ -24,10 +24,15 @@
|
|
|
24
24
|
|
|
25
25
|
### 假设(待项目经理确认,确认前不开发)
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
-
|
|
27
|
+
#### A1
|
|
28
|
+
- **问**(prompt):审批被驳回后,申请人能否修改并重新提交?
|
|
29
|
+
- **场景**:需求写了审批流程,未说明驳回后的操作
|
|
30
|
+
- **选项**:
|
|
31
|
+
- opt_resubmit:允许修改后重新提交
|
|
32
|
+
- opt_new:不允许,需新建申请
|
|
33
|
+
- **研发备注**:代码 `inspection_flow.status=5` 表示 REJECTED(仅研发可见)
|
|
29
34
|
|
|
30
|
-
>
|
|
35
|
+
> PM 若需表达复合口径,在 Web Panel 选 **「其他」** 并文字说明。
|
|
31
36
|
|
|
32
37
|
## 3. 实现步骤
|
|
33
38
|
|
|
@@ -70,7 +75,12 @@
|
|
|
70
75
|
|
|
71
76
|
### 假设(待项目经理确认,确认前不开发)
|
|
72
77
|
|
|
73
|
-
|
|
78
|
+
#### A1
|
|
79
|
+
- **问**(prompt):…
|
|
80
|
+
- **场景**:…
|
|
81
|
+
- **选项**:
|
|
82
|
+
- opt_a:…
|
|
83
|
+
- opt_b:…
|
|
74
84
|
|
|
75
85
|
> 无假设时写「无,口径均有依据」。
|
|
76
86
|
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# apm-deploy:自动化部署
|
|
2
|
-
|
|
3
|
-
## 工作流程
|
|
4
|
-
|
|
5
|
-
在项目根目录执行 `apm deploy <环境名称> --session <sessionId>`,**以命令执行结果为准**。
|
|
6
|
-
|
|
7
|
-
**sessionId**:从当前工作项目录 `.apm/sessions/<sessionId>/` 或 `session.yaml` 获取;必须传入 `--session`,平台才会记录部署。
|
|
8
|
-
|
|
9
|
-
部署前会自动:
|
|
10
|
-
|
|
11
|
-
1. 从平台同步最新部署配置(`.apm/apm.config.json`)
|
|
12
|
-
2. 合并仓库基线分支最新代码到当前分支
|
|
13
|
-
|
|
14
|
-
若平台刚更新过部署配置,也可先手动执行 `apm sync-deploy-config` 再部署。
|
|
15
|
-
|
|
16
|
-
- **成功**:部署完成,在回信中说明测试环境地址或部署结果。
|
|
17
|
-
- **失败且输出含「未配置自动化部署」或「可跳过部署」**:本项目不支持自动化部署,属正常情况;放弃部署,在回信说明已跳过即可,无需修复配置或重试。
|
|
18
|
-
- **其他失败**:按输出排查并修复后重试。
|
|
19
|
-
|
|
20
|
-
## 示例
|
|
21
|
-
|
|
22
|
-
1. 部署测试环境:`apm deploy test --session <sessionId>`
|
|
23
|
-
2. 部署正式环境:`apm deploy online --session <sessionId>`
|