ai-project-manage-cli 6.0.87 → 6.0.89

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 CHANGED
@@ -2281,7 +2281,8 @@ function validateDeployPush(o) {
2281
2281
  type: "deploy",
2282
2282
  deploymentRunId: o.deploymentRunId.trim(),
2283
2283
  workdir: o.workdir.trim(),
2284
- environment
2284
+ environment,
2285
+ ...o.packOnly === true ? { packOnly: true } : {}
2285
2286
  }
2286
2287
  };
2287
2288
  }
@@ -2561,8 +2562,8 @@ async function uploadDeployArtifactZip(options) {
2561
2562
 
2562
2563
  // src/commands/connect/deploy-run.ts
2563
2564
  var DEPLOY_LOG_SYNC_INTERVAL_MS = 3e4;
2564
- function resolveDeployCommand(environment) {
2565
- return `apm deploy ${environment}`;
2565
+ function resolveDeployCommand(environment, packOnly) {
2566
+ return packOnly ? `apm deploy ${environment} --pack-only` : `apm deploy ${environment}`;
2566
2567
  }
2567
2568
  function buildDeployLog(stdout, stderr) {
2568
2569
  return [stdout, stderr].filter(Boolean).join("\n");
@@ -2658,7 +2659,7 @@ async function handleInboundDeploy(cfg, msg, signal) {
2658
2659
  status: "DEPLOYING"
2659
2660
  });
2660
2661
  const workdir = requireRemoteWorkdir(msg.workdir);
2661
- const command = resolveDeployCommand(msg.environment);
2662
+ const command = resolveDeployCommand(msg.environment, msg.packOnly);
2662
2663
  console.log(
2663
2664
  `[apm] deploy start id=${deploymentRunId} env=${msg.environment} cwd=${workdir}`
2664
2665
  );
@@ -4675,6 +4676,12 @@ function formatDeployNotConfiguredLines(env, deployCommands) {
4675
4676
  "[apm] \u90E8\u5206\u9879\u76EE\u4E0D\u652F\u6301\u6216\u672A\u542F\u7528\u81EA\u52A8\u5316\u90E8\u7F72\uFF0C\u5C5E\u6B63\u5E38\u60C5\u51B5\uFF0C\u53EF\u8DF3\u8FC7\u90E8\u7F72"
4676
4677
  ];
4677
4678
  }
4679
+ function formatWisdomFrontendBuildNotConfiguredLines(env, packageJsonPath) {
4680
+ return [
4681
+ `[apm] \u65E0\u6CD5\u6267\u884C\u4EC5\u6253\u5305\uFF1A${packageJsonPath} \u4E2D\u672A\u627E\u5230 build:${env} \u811A\u672C`,
4682
+ "[apm] \u8BF7\u914D\u7F6E npm run build:test / build:online \u540E\u518D\u8BD5"
4683
+ ];
4684
+ }
4678
4685
  function formatWisdomFrontendDeployNotConfiguredLines(env, packageJsonPath) {
4679
4686
  return [
4680
4687
  `[apm] \u65E0\u6CD5\u6267\u884C\u90E8\u7F72\uFF1A${packageJsonPath} \u4E2D\u672A\u627E\u5230 deploy:${env} \u811A\u672C`,
@@ -4857,7 +4864,7 @@ async function runWisdomSftpDeploy(params) {
4857
4864
  zipPath: resolvedZipPath,
4858
4865
  projectName: params.projectName,
4859
4866
  kind: "frontend",
4860
- uploadWithoutRunId: packOnly
4867
+ uploadWithoutRunId: packOnly && !resolveDeploymentRunIdFromEnv()
4861
4868
  });
4862
4869
  artifactUploaded = artifact !== null;
4863
4870
  if (packOnly && artifactUploaded) {
@@ -5424,6 +5431,7 @@ async function runWisdomBackendDeploy(options) {
5424
5431
  sourceDetail: config.mavenLocalRepoSourceDetail
5425
5432
  });
5426
5433
  if (packOnly) {
5434
+ const uploadWithoutRunId = !resolveDeploymentRunIdFromEnv();
5427
5435
  if (config.mode === "full") {
5428
5436
  const mainJar = locateMainJar(projectRoot);
5429
5437
  const archiveZipPath = await createUpdatePackage(
@@ -5440,7 +5448,7 @@ async function runWisdomBackendDeploy(options) {
5440
5448
  zipPath: archiveZipPath,
5441
5449
  projectName: config.projectName,
5442
5450
  kind: "backend",
5443
- uploadWithoutRunId: true
5451
+ uploadWithoutRunId
5444
5452
  });
5445
5453
  } else {
5446
5454
  const libDir = locateLibDir(projectRoot);
@@ -5453,7 +5461,7 @@ async function runWisdomBackendDeploy(options) {
5453
5461
  zipPath,
5454
5462
  projectName: config.projectName,
5455
5463
  kind: "backend",
5456
- uploadWithoutRunId: true
5464
+ uploadWithoutRunId
5457
5465
  });
5458
5466
  }
5459
5467
  log("\u4EC5\u6253\u5305\u5B8C\u6210\uFF08\u672A\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF09");
@@ -5580,6 +5588,14 @@ function resolveFrontendDeployCommand(env, cwd) {
5580
5588
  }
5581
5589
  return null;
5582
5590
  }
5591
+ function resolveFrontendBuildCommand(env, cwd) {
5592
+ const scripts = readPackageScripts(cwd);
5593
+ const buildKey = `build:${env}`;
5594
+ if (scripts[buildKey]?.trim()) {
5595
+ return `npm run build:${env}`;
5596
+ }
5597
+ return null;
5598
+ }
5583
5599
  function runShellCommand2(command, cwd, captureOutput) {
5584
5600
  const result = spawnSync4(command, {
5585
5601
  cwd,
@@ -5629,6 +5645,16 @@ async function runWisdomAutoDeploy(options) {
5629
5645
  );
5630
5646
  if (projectType === "frontend") {
5631
5647
  if (packOnly) {
5648
+ const buildCmd = resolveFrontendBuildCommand(options.env, cwd);
5649
+ if (!buildCmd) {
5650
+ const lines = formatWisdomFrontendBuildNotConfiguredLines(
5651
+ options.env,
5652
+ path4.join(cwd, "package.json")
5653
+ );
5654
+ throw new DeployExecutionError(lines.join("\n"), 1, lines.join("\n"));
5655
+ }
5656
+ console.error(`[apm] \u524D\u7AEF\u4EC5\u6253\u5305\u6A21\u5F0F\uFF1A\u6267\u884C ${buildCmd}`);
5657
+ runShellCommand2(buildCmd, cwd, captureOutput);
5632
5658
  const projectName = (cfg.name ?? "").trim();
5633
5659
  if (!projectName) {
5634
5660
  throw new DeployExecutionError(
@@ -6033,7 +6059,7 @@ function registerDeployMainCommand(program) {
6033
6059
  "\u6C9F\u901A\u7FA4 ID\uFF1B\u4F20\u5165\u65F6\u5728\u5E73\u53F0\u521B\u5EFA\u90E8\u7F72\u8BB0\u5F55\u5E76\u540C\u6B65\u65E5\u5FD7"
6034
6060
  ).option(
6035
6061
  "--pack-only",
6036
- "\u4EC5\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF08\u533B\u52A1\u5B58\u91CF SFTP / Java \u90E8\u7F72\uFF09"
6062
+ "\u4EC5\u6784\u5EFA/\u6253\u5305\u5E76\u4E0A\u4F20 MinIO \u5F52\u6863\uFF0C\u4E0D\u4E0A\u4F20\u8FDC\u7A0B\u670D\u52A1\u5668\uFF08\u524D\u7AEF build:<env>\uFF0C\u540E\u7AEF Maven \u6784\u5EFA\uFF09"
6037
6063
  ).action(
6038
6064
  async (env, opts) => {
6039
6065
  const cwd = process.cwd();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-project-manage-cli",
3
- "version": "6.0.87",
3
+ "version": "6.0.89",
4
4
  "description": "命令行工具:后续用于调用平台后端 API 完成运维与自动化操作",
5
5
  "type": "module",
6
6
  "private": false,
@@ -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 评审与项目经理重验。
@@ -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
- - 「假设」仍有未确认项:**Read** `.apm/sessions/<会话ID>/messages.xml`,查找项目经理是否已回复确认;
11
- - 项目经理已回复:先按 `.apm/skills/apm-write-plan/SKILL.md` 步骤 5 把确认结果**回填进计划文档并同步**(确认的假设移入「依据」,否定的修订实现步骤与白名单),然后再开发;
12
- - 项目经理未回复:`@项目经理` 列出待确认假设,**停止本次开发**。
13
- 严禁带着未回填的澄清直接开发——项目经理在聊天里给过的口径若没落进计划,开发与 diff 评审都不会认。
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. **发布测试环境**:**Read** `.apm/skills/apm-deploy/SKILL.md` 并按其流程执行 `apm deploy`(以命令结果判断是否跳过);**后端**涉及 SQL 变更时,须在回复中引用 `docs/SQL.md`,并写明待执行的 SQL 文件名或执行顺序。
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` 回复:改动概述 + 白名单对账 + 构建结果 + 测试环境地址,并 `@` 评审角色进行 diff 评审。
97
+ 完成后用 `append_message` 回复:改动概述 + 白名单对账 + 构建结果,并 `@` 评审角色进行 diff 评审。
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 适用范围
4
4
 
5
- 开发完成、发布测试环境之后,由评审角色(可以是另一端工程师或专职评审智能体)检查 git 改动是否「只做了该做的事」。这是防止 AI 乱改代码的机器门禁:**通过才交人验收,不通过打回开发**。
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
 
@@ -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>`