@mycodemap/mycodemap 0.5.2-beta.1 → 1.9.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 (96) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +84 -10
  3. package/dist/cli/commands/init.d.ts +7 -2
  4. package/dist/cli/commands/init.d.ts.map +1 -1
  5. package/dist/cli/commands/init.js +22 -34
  6. package/dist/cli/commands/init.js.map +1 -1
  7. package/dist/cli/commands/publish-status.d.ts +31 -0
  8. package/dist/cli/commands/publish-status.d.ts.map +1 -0
  9. package/dist/cli/commands/publish-status.js +101 -0
  10. package/dist/cli/commands/publish-status.js.map +1 -0
  11. package/dist/cli/commands/readiness-gate.d.ts +25 -0
  12. package/dist/cli/commands/readiness-gate.d.ts.map +1 -0
  13. package/dist/cli/commands/readiness-gate.js +197 -0
  14. package/dist/cli/commands/readiness-gate.js.map +1 -0
  15. package/dist/cli/commands/ship/checker.d.ts +4 -9
  16. package/dist/cli/commands/ship/checker.d.ts.map +1 -1
  17. package/dist/cli/commands/ship/checker.js +60 -22
  18. package/dist/cli/commands/ship/checker.js.map +1 -1
  19. package/dist/cli/commands/ship/monitor.d.ts +6 -1
  20. package/dist/cli/commands/ship/monitor.d.ts.map +1 -1
  21. package/dist/cli/commands/ship/monitor.js +223 -46
  22. package/dist/cli/commands/ship/monitor.js.map +1 -1
  23. package/dist/cli/commands/ship/pipeline.d.ts.map +1 -1
  24. package/dist/cli/commands/ship/pipeline.js +14 -5
  25. package/dist/cli/commands/ship/pipeline.js.map +1 -1
  26. package/dist/cli/commands/ship/rules/quality-rules.d.ts +12 -8
  27. package/dist/cli/commands/ship/rules/quality-rules.d.ts.map +1 -1
  28. package/dist/cli/commands/ship/rules/quality-rules.js +49 -34
  29. package/dist/cli/commands/ship/rules/quality-rules.js.map +1 -1
  30. package/dist/cli/config-loader.js +1 -1
  31. package/dist/cli/config-loader.js.map +1 -1
  32. package/dist/cli/first-run-guide.d.ts.map +1 -1
  33. package/dist/cli/first-run-guide.js +10 -12
  34. package/dist/cli/first-run-guide.js.map +1 -1
  35. package/dist/cli/index.js +8 -1
  36. package/dist/cli/index.js.map +1 -1
  37. package/dist/cli/init/hooks.d.ts +17 -0
  38. package/dist/cli/init/hooks.d.ts.map +1 -0
  39. package/dist/cli/init/hooks.js +220 -0
  40. package/dist/cli/init/hooks.js.map +1 -0
  41. package/dist/cli/init/receipt.d.ts +4 -0
  42. package/dist/cli/init/receipt.d.ts.map +1 -0
  43. package/dist/cli/init/receipt.js +117 -0
  44. package/dist/cli/init/receipt.js.map +1 -0
  45. package/dist/cli/init/reconciler.d.ts +44 -0
  46. package/dist/cli/init/reconciler.d.ts.map +1 -0
  47. package/dist/cli/init/reconciler.js +377 -0
  48. package/dist/cli/init/reconciler.js.map +1 -0
  49. package/dist/cli/init/rule-templates.d.ts +9 -0
  50. package/dist/cli/init/rule-templates.d.ts.map +1 -0
  51. package/dist/cli/init/rule-templates.js +105 -0
  52. package/dist/cli/init/rule-templates.js.map +1 -0
  53. package/dist/cli/init/rules.d.ts +13 -0
  54. package/dist/cli/init/rules.d.ts.map +1 -0
  55. package/dist/cli/init/rules.js +113 -0
  56. package/dist/cli/init/rules.js.map +1 -0
  57. package/dist/cli/paths.d.ts +4 -2
  58. package/dist/cli/paths.d.ts.map +1 -1
  59. package/dist/cli/paths.js +13 -5
  60. package/dist/cli/paths.js.map +1 -1
  61. package/dist/orchestrator/test-linker.d.ts.map +1 -1
  62. package/dist/orchestrator/test-linker.js +5 -36
  63. package/dist/orchestrator/test-linker.js.map +1 -1
  64. package/docs/AI_ASSISTANT_SETUP.md +4 -2
  65. package/docs/SETUP_GUIDE.md +12 -12
  66. package/docs/agents/domain.md +36 -0
  67. package/docs/agents/issue-tracker.md +22 -0
  68. package/docs/agents/triage-labels.md +15 -0
  69. package/docs/ai-guide/COMMANDS.md +57 -3
  70. package/docs/ai-guide/INTEGRATION.md +1 -1
  71. package/docs/ai-guide/PATTERNS.md +3 -3
  72. package/docs/ai-guide/QUICKSTART.md +13 -4
  73. package/docs/ai-guide/README.md +7 -7
  74. package/docs/archive/ideation/2026-04-22-harness-rules-entry-docs-optimization-ideation.md +102 -0
  75. package/docs/archive/ideation/2026-04-22-rules-claude-agents-optimization-ideation.md +107 -0
  76. package/docs/brainstorms/2026-04-22-rules-entry-docs-phase1-structure-consolidation-requirements.md +110 -0
  77. package/docs/brainstorms/999.1-mycodemap-init-enhancements-requirements.md +166 -0
  78. package/docs/exec-plans/README.md +3 -0
  79. package/docs/ideation/2026-04-20-mycodemap-init-enhancements-ideation.md +96 -0
  80. package/docs/ideation/2026-04-22-rules-entry-docs-optimization-consolidated-ideation.md +119 -0
  81. package/docs/lesson-learn/2026-04-19-prerelease-trusted-publishing-fix.md +119 -0
  82. package/docs/lesson-learn/image.png +0 -0
  83. package/docs/rules/README.md +4 -1
  84. package/docs/rules/deployment.md +7 -0
  85. package/docs/rules/engineering-with-codex-openai.md +47 -8
  86. package/docs/rules/pre-release-checklist.md +44 -33
  87. package/docs/rules/release.md +303 -0
  88. package/docs/rules/testing.md +19 -0
  89. package/docs/rules/validation.md +16 -7
  90. package/mycodemap.config.schema.json +1 -1
  91. package/package.json +3 -3
  92. package/scripts/hooks/templates/commit-msg +38 -0
  93. package/scripts/hooks/templates/pre-commit +224 -0
  94. package/scripts/pre-release-check.js +4 -4
  95. package/scripts/release.sh +1 -1
  96. package/scripts/validate-docs.js +283 -14
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.9.0] - 2026-04-29 - Release Governance Unification
6
+
7
+ ### 🏛️ Governance
8
+
9
+ - **release**: `/release v{X.Y}` 统一发布治理入口,绑定 milestone closeout 与 npm release 1:1
10
+ - **release**: 引入双确认门(Confirmation Gate #1 / #2),发布操作升级为 L3 受控等级
11
+ - **release**: `docs/rules/release.md` 成为单一权威发布流程文档
12
+ - **release**: `.claude/skills/release/SKILL.md` 作为 thin orchestrator,委托 `scripts/release.sh` 与 `.github/workflows/publish.yml`
13
+
14
+ ### 📝 Documentation
15
+
16
+ - **release**: 同步 `llms.txt`、`AI_GUIDE.md`、`AI_DISCOVERY.md`、`ai-document-index.yaml` 到 `v1.9.0`
17
+ - **changelog**: 新增 v1.9.0 发布条目,记录 release governance unification milestone
18
+
5
19
  ## [0.5.2-beta.1] - 2026-04-19 - Trusted Publishing Verification
6
20
 
7
21
  ### 🛠️ Infrastructure
package/README.md CHANGED
@@ -110,7 +110,7 @@ mycodemap design verify mycodemap.design.md --json
110
110
  | **[💬 docs/ai-guide/PROMPTS.md](docs/ai-guide/PROMPTS.md)** | 即用型提示词模板 |
111
111
  | **[🔧 docs/ai-guide/INTEGRATION.md](docs/ai-guide/INTEGRATION.md)** | 集成指南、错误处理 |
112
112
  | **[🛡️ AGENTS.md](AGENTS.md)** | 仓库级强约束、任务分级、代码红线 |
113
- | **[⚡ CLAUDE.md](CLAUDE.md)** | AI 执行手册、验收清单 |
113
+ | **[⚡ CLAUDE.md](CLAUDE.md)** | AI 入口路由、下一步阅读导航 |
114
114
  | **[🤖 docs/AI_ASSISTANT_SETUP.md](docs/AI_ASSISTANT_SETUP.md)** | AI 助手配置指引 |
115
115
  | **[🛠️ docs/rules/engineering-with-codex-openai.md](docs/rules/engineering-with-codex-openai.md)** | 面向 agent 的工程约束 |
116
116
 
@@ -122,11 +122,12 @@ mycodemap design verify mycodemap.design.md --json
122
122
 
123
123
  ### `mycodemap init`
124
124
 
125
- 初始化项目的 CodeMap 配置文件。
125
+ 初始化并收敛项目的 CodeMap workspace / config / hooks / rules 状态。
126
126
 
127
127
  ```bash
128
- mycodemap init # 创建默认配置文件
129
- mycodemap init -y # 使用默认配置直接创建
128
+ mycodemap init # 显示 reconciliation preview(默认不写入)
129
+ mycodemap init --interactive # 显式显示 preview(等同默认行为)
130
+ mycodemap init -y # 使用默认选择直接写入
130
131
 
131
132
  # 别名:codemap init 也可以使用
132
133
  ```
@@ -134,8 +135,13 @@ mycodemap init -y # 使用默认配置直接创建
134
135
  | 选项 | 说明 |
135
136
  |------|------|
136
137
  | `-y, --yes` | 使用默认配置 |
138
+ | `--interactive` | 仅显示 reconciliation preview,不写入文件 |
137
139
 
138
- 执行后会在项目根目录生成 `mycodemap.config.json` 配置文件。
140
+ 默认显示 reconciliation preview;使用 `mycodemap init -y` 或 `mycodemap init --yes` 才会真正写入。
141
+
142
+ 执行后会收敛 `.mycodemap/config.json`,并把 machine-readable receipt 写入 `.mycodemap/status/init-last.json`。
143
+
144
+ `init` 还会同步 `.mycodemap/hooks/` 与 `.mycodemap/rules/`;但不会自动改写团队自有的 `CLAUDE.md` / `AGENTS.md`,只会在 receipt 中输出可复制片段。
139
145
 
140
146
  ### `mycodemap generate`
141
147
 
@@ -450,9 +456,16 @@ mycodemap ci check-output-contract
450
456
 
451
457
  > `ci assess-risk` 现在输出 `status/confidence/freshness/source` 与统一 risk level;若 Git history 不可用,会显式打印 `unavailable` / warning,并说明阈值未被应用。
452
458
 
459
+ ## Validation quick truth
460
+
461
+ - 文档/入口变更先跑 `npm run docs:check`。
462
+ - 统一 docs/AI guardrail 入口:`node dist/cli/index.js ci check-docs-sync`(产品命令等价于 `mycodemap ci check-docs-sync`)。
463
+ - repo-local rules 预检:`python3 scripts/validate-rules.py code --report-only` 只报告,不阻断。
464
+ - CI / PR 超窗、fallback 或 false-positive 漂移时,`warn-only / fallback` 不是 hard gate success。
465
+
453
466
  ## 配置说明
454
467
 
455
- 通过 `mycodemap init` 生成的 `mycodemap.config.json` 配置文件支持以下选项:
468
+ 通过 `mycodemap init` 收敛的 canonical 配置文件是 `.mycodemap/config.json`(根目录 `mycodemap.config.json` / `codemap.config.json` 只作为 legacy migration source)。
456
469
 
457
470
  ```jsonc
458
471
  {
@@ -487,7 +500,7 @@ mycodemap ci check-output-contract
487
500
  // 图存储后端配置
488
501
  "storage": {
489
502
  "type": "filesystem",
490
- "outputPath": ".codemap/storage"
503
+ "outputPath": ".mycodemap/storage"
491
504
  },
492
505
 
493
506
  // 插件加载配置
@@ -507,8 +520,8 @@ mycodemap ci check-output-contract
507
520
  | `output` | `string` | 输出目录路径 | `".mycodemap"` |
508
521
  | `watch` | `boolean` | 监听模式预留配置 | `false` |
509
522
  | `storage.type` | `"filesystem" \| "sqlite" \| "memory" \| "auto"` | 图存储后端类型 | `"filesystem"` |
510
- | `storage.outputPath` | `string` | 文件系统存储目录 | `".codemap/storage"` |
511
- | `storage.databasePath` | `string` | SQLite 数据目录(相对项目根目录) | `".codemap/governance.sqlite"` |
523
+ | `storage.outputPath` | `string` | 文件系统存储目录 | `".mycodemap/storage"` |
524
+ | `storage.databasePath` | `string` | SQLite 数据目录(相对项目根目录,建议放在 `.mycodemap/` 下) | `".mycodemap/governance.sqlite"` |
512
525
  | `storage.autoThresholds` | `object` | `auto` 后端选择阈值 | - |
513
526
  | `plugins.builtInPlugins` | `boolean` | 是否启用内置插件 | `true` |
514
527
  | `plugins.pluginDir` | `string` | 额外插件目录 | - |
@@ -521,7 +534,7 @@ mycodemap ci check-output-contract
521
534
  {
522
535
  "storage": {
523
536
  "type": "sqlite",
524
- "databasePath": ".codemap/governance.sqlite"
537
+ "databasePath": ".mycodemap/governance.sqlite"
525
538
  }
526
539
  }
527
540
  ```
@@ -701,6 +714,67 @@ cp examples/codex/codemap-agent.md .agents/skills/codemap/SKILL.md
701
714
 
702
715
  详细配置请参考 [AI_ASSISTANT_SETUP.md](docs/AI_ASSISTANT_SETUP.md),设计与规则入口请先看 [docs/README.md](docs/README.md)。
703
716
 
717
+ ### CodeMap Skill 使用指南
718
+
719
+ CodeMap Skill 是一个预置的 AI 技能文件,让 Claude Code 等支持 Skill 机制的 AI 助手自动获得 CodeMap 的全部分析能力。当用户提到"分析代码结构"、"查找依赖"、"影响范围"、"代码地图"等意图时,AI 会自动加载该技能并调用 CodeMap CLI。
720
+
721
+ #### 工作原理
722
+
723
+ ```
724
+ 用户提问 → AI 识别意图 → 加载 CodeMap Skill → 调用 CLI 命令 → 返回结构化结果
725
+ ```
726
+
727
+ Skill 文件由两部分组成:
728
+
729
+ | 文件 | 作用 |
730
+ |------|------|
731
+ | `.claude/skills/codemap/SKILL.md` | 主技能文件:触发条件、场景-命令映射、任务示例、错误处理 |
732
+ | `.claude/skills/codemap/references/commands.md` | 完整命令参考:所有命令的选项、参数和用法 |
733
+
734
+ #### 安装
735
+
736
+ Skill 文件已内置在本仓库中,无需额外安装。对于其他项目,复制即可:
737
+
738
+ ```bash
739
+ # 复制到目标项目的 .claude/skills/ 目录
740
+ cp -r .claude/skills/codemap /path/to/target-project/.claude/skills/
741
+ ```
742
+
743
+ #### 典型使用场景
744
+
745
+ 在 Claude Code 对话中直接用自然语言触发,无需手动输入命令:
746
+
747
+ | 用户意图 | AI 自动执行的命令 |
748
+ |----------|-------------------|
749
+ | "这个项目有哪些模块?" | `mycodemap query -m "src/..."` 或查看 `AI_MAP.md` |
750
+ | "IntentRouter 在哪里定义的?" | `mycodemap query -s "IntentRouter"` |
751
+ | "修改这个文件会影响什么?" | `mycodemap impact -f <path> --transitive` |
752
+ | "项目有循环依赖吗?" | `mycodemap cycles` |
753
+ | "这个模块的复杂度如何?" | `mycodemap complexity -f <path> --detail` |
754
+ | "帮我检查提交格式" | `mycodemap ci check-commits` |
755
+ | "验证设计契约" | `mycodemap design validate` |
756
+
757
+ #### CLI 调用方式
758
+
759
+ 标准用户通过全局安装的 `mycodemap` 调用;CodeMap 本体仓库的开发者使用 `node dist/cli/index.js`:
760
+
761
+ ```bash
762
+ # 用户模式(全局安装后)
763
+ mycodemap query -s "SymbolName"
764
+ mycodemap impact -f src/file.ts
765
+
766
+ # 开发者模式(CodeMap 本体仓库内,需先 npm run build)
767
+ node dist/cli/index.js query -s "SymbolName"
768
+ ```
769
+
770
+ #### 自定义与扩展
771
+
772
+ - **修改触发条件**:编辑 `SKILL.md` 头部的 `description` 字段,调整 AI 何时自动加载此技能
773
+ - **添加新命令**:在 `references/commands.md` 中补充新命令文档
774
+ - **添加新场景**:在 `SKILL.md` 的 "任务场景" 部分追加新的使用模式
775
+
776
+ 详细配置请参考 [AI_ASSISTANT_SETUP.md](docs/AI_ASSISTANT_SETUP.md),设计与规则入口请先看 [docs/README.md](docs/README.md)。
777
+
704
778
  ## 新增 CLI 命令
705
779
 
706
780
  ### `mycodemap design`
@@ -1,4 +1,9 @@
1
- export declare function initCommand(_options: {
1
+ import { type InitReceipt } from '../init/reconciler.js';
2
+ export interface InitCommandOptions {
2
3
  yes?: boolean;
3
- }): Promise<void>;
4
+ interactive?: boolean;
5
+ cwd?: string;
6
+ }
7
+ export declare function executeInitCommand(options: InitCommandOptions): Promise<InitReceipt>;
8
+ export declare function initCommand(options: InitCommandOptions): Promise<void>;
4
9
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAWA,wBAAsB,WAAW,CAAC,QAAQ,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAmC5D"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG1G,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAUD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAgB1F;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5E"}
@@ -1,41 +1,29 @@
1
1
  // [META] since:2026-03 | owner:cli-team | stable:true
2
2
  // [WHY] Initialize CodeMap configuration for new projects
3
3
  import chalk from 'chalk';
4
- import fs from 'fs/promises';
5
- import path from 'path';
6
- import { createDefaultCodemapConfigFile } from '../config-loader.js';
7
- const NEW_CONFIG_NAME = 'mycodemap.config.json';
8
- const LEGACY_CONFIG_NAME = 'codemap.config.json';
9
- export async function initCommand(_options) {
10
- console.log(chalk.blue('🚀 初始化 CodeMap...'));
11
- const newConfigPath = path.join(process.cwd(), NEW_CONFIG_NAME);
12
- const legacyConfigPath = path.join(process.cwd(), LEGACY_CONFIG_NAME);
13
- // 优先检查新配置
14
- try {
15
- await fs.access(newConfigPath);
16
- console.log(chalk.yellow(`⚠️ 配置文件已存在 (${NEW_CONFIG_NAME})`));
17
- return;
18
- }
19
- catch {
20
- // 新配置不存在,继续
21
- }
22
- // 兼容旧配置:如果存在旧配置,迁移到新配置
23
- try {
24
- await fs.access(legacyConfigPath);
25
- console.log(chalk.yellow(`⚠️ 发现旧配置文件 ${LEGACY_CONFIG_NAME},已迁移到 ${NEW_CONFIG_NAME}`));
26
- const legacyContent = await fs.readFile(legacyConfigPath, 'utf-8');
27
- await fs.writeFile(newConfigPath, legacyContent);
28
- console.log(chalk.green(`✅ 迁移完成!配置文件: ${NEW_CONFIG_NAME}`));
29
- return;
4
+ import { applyInitPlan, createInitPlan, writeInitReceipt } from '../init/reconciler.js';
5
+ import { renderInitPreview, renderInitReceipt } from '../init/receipt.js';
6
+ function resolveInitMode(options) {
7
+ if (options.yes) {
8
+ return 'apply';
30
9
  }
31
- catch {
32
- // 旧配置也不存在,创建新配置
10
+ return 'preview';
11
+ }
12
+ export async function executeInitCommand(options) {
13
+ const rootDir = options.cwd ?? process.cwd();
14
+ const mode = resolveInitMode(options);
15
+ const plan = createInitPlan(rootDir, mode);
16
+ console.log(chalk.blue('🚀 初始化 CodeMap...'));
17
+ if (mode === 'preview') {
18
+ renderInitPreview(plan.receipt);
19
+ return plan.receipt;
33
20
  }
34
- // 创建默认配置
35
- const defaultConfig = createDefaultCodemapConfigFile();
36
- await fs.writeFile(newConfigPath, JSON.stringify(defaultConfig, null, 2));
37
- console.log(chalk.green('✅ 初始化完成!'));
38
- console.log(chalk.gray(`配置文件已创建: ${NEW_CONFIG_NAME}`));
39
- console.log(chalk.gray('运行 "mycodemap generate" "codemap generate" 生成代码地图'));
21
+ const receipt = await applyInitPlan(plan);
22
+ await writeInitReceipt(receipt);
23
+ renderInitReceipt(receipt);
24
+ return receipt;
25
+ }
26
+ export async function initCommand(options) {
27
+ await executeInitCommand(options);
40
28
  }
41
29
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,0DAA0D;AAE1D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAChD,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAA2B;IAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAE7C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;IAChE,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAEtE,UAAU;IACV,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,eAAe,GAAG,CAAC,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IAED,uBAAuB;IACvB,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,kBAAkB,SAAS,eAAe,EAAE,CAAC,CAAC,CAAC;QACvF,MAAM,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;QACnE,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,eAAe,EAAE,CAAC,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;IAED,SAAS;IACT,MAAM,aAAa,GAAG,8BAA8B,EAAE,CAAC;IAEvD,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAE1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,eAAe,EAAE,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC,CAAC;AACjF,CAAC"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,0DAA0D;AAE1D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAC1G,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAQ1E,SAAS,eAAe,CAAC,OAA2B;IAClD,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAA2B;IAClE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC7C,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAE3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAE7C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAChC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA2B;IAC3D,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * [META] since:2026-04-23 | owner:cli-team | stable:false
3
+ * [WHY] Expose read-only publish workflow snapshot truth as a standalone follow-up command for humans and agents
4
+ */
5
+ import { Command } from 'commander';
6
+ import { type MonitorStatus } from './ship/monitor.js';
7
+ export interface PublishStatusCommandOptions {
8
+ tag: string;
9
+ sha: string;
10
+ workflowFile?: string;
11
+ json?: boolean;
12
+ structured?: boolean;
13
+ }
14
+ export interface PublishStatusCommandResult {
15
+ success: boolean;
16
+ status: Exclude<MonitorStatus, 'timeout'>;
17
+ workflowUrl?: string;
18
+ releaseUrl?: string;
19
+ runId?: number;
20
+ failedJobs: string[];
21
+ reason?: string;
22
+ details?: string;
23
+ matchedRunCount?: number;
24
+ content?: string;
25
+ }
26
+ export declare function renderPublishStatusResult(result: PublishStatusCommandResult): string;
27
+ export declare function executePublishStatusCommand(options: PublishStatusCommandOptions): Promise<PublishStatusCommandResult>;
28
+ export declare function handlePublishStatusCommand(options: PublishStatusCommandOptions): Promise<void>;
29
+ export declare function createPublishStatusCommand(): Command;
30
+ export declare const publishStatusCommand: Command;
31
+ //# sourceMappingURL=publish-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/publish-status.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA0CD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,0BAA0B,GAAG,MAAM,CAkCpF;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,0BAA0B,CAAC,CAQrC;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CASpD;AAED,eAAO,MAAM,oBAAoB,SAA+B,CAAC"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * [META] since:2026-04-23 | owner:cli-team | stable:false
3
+ * [WHY] Expose read-only publish workflow snapshot truth as a standalone follow-up command for humans and agents
4
+ */
5
+ import chalk from 'chalk';
6
+ import { Command } from 'commander';
7
+ import { snapshotPublishStatus, } from './ship/monitor.js';
8
+ function toCommandResult(result, structured) {
9
+ const base = {
10
+ success: result.success,
11
+ status: result.status === 'timeout' ? 'unavailable' : result.status,
12
+ workflowUrl: result.workflowUrl,
13
+ releaseUrl: result.releaseUrl,
14
+ runId: result.runId,
15
+ failedJobs: result.failedJobs ?? [],
16
+ reason: result.reason,
17
+ details: result.details ?? result.error,
18
+ matchedRunCount: result.matchedRunCount,
19
+ };
20
+ if (structured) {
21
+ return base;
22
+ }
23
+ return {
24
+ ...base,
25
+ content: renderPublishStatusResult(base),
26
+ };
27
+ }
28
+ function formatStatusLabel(status) {
29
+ switch (status) {
30
+ case 'success':
31
+ return chalk.green('success');
32
+ case 'failure':
33
+ return chalk.red('failure');
34
+ case 'pending':
35
+ return chalk.yellow('pending');
36
+ case 'ambiguous':
37
+ return chalk.yellow('ambiguous');
38
+ case 'unavailable':
39
+ return chalk.yellow('unavailable');
40
+ default:
41
+ return chalk.yellow(status);
42
+ }
43
+ }
44
+ export function renderPublishStatusResult(result) {
45
+ const lines = [
46
+ `Publish 状态: ${formatStatusLabel(result.status)}`,
47
+ ];
48
+ if (result.runId) {
49
+ lines.push(`Run ID: ${result.runId}`);
50
+ }
51
+ if (result.reason) {
52
+ lines.push(`Reason: ${result.reason}`);
53
+ }
54
+ if (result.details) {
55
+ lines.push(`Details: ${result.details}`);
56
+ }
57
+ if (result.failedJobs.length > 0) {
58
+ lines.push(`Failed Jobs: ${result.failedJobs.join(', ')}`);
59
+ }
60
+ if (result.matchedRunCount && result.matchedRunCount > 1) {
61
+ lines.push(`Matched Runs: ${result.matchedRunCount}`);
62
+ }
63
+ if (result.workflowUrl) {
64
+ lines.push(`Workflow: ${result.workflowUrl}`);
65
+ }
66
+ if (result.releaseUrl) {
67
+ lines.push(`Release: ${result.releaseUrl}`);
68
+ }
69
+ return lines.join('\n');
70
+ }
71
+ export async function executePublishStatusCommand(options) {
72
+ const snapshot = await snapshotPublishStatus({
73
+ tagName: options.tag,
74
+ headSha: options.sha,
75
+ workflowFile: options.workflowFile,
76
+ });
77
+ return toCommandResult(snapshot, options.structured === true);
78
+ }
79
+ export async function handlePublishStatusCommand(options) {
80
+ if (options.structured && !options.json) {
81
+ throw new Error('--structured 需要配合 --json 使用');
82
+ }
83
+ const result = await executePublishStatusCommand(options);
84
+ if (!options.json) {
85
+ console.log(renderPublishStatusResult(result));
86
+ return;
87
+ }
88
+ console.log(JSON.stringify(result, null, 2));
89
+ }
90
+ export function createPublishStatusCommand() {
91
+ return new Command('publish-status')
92
+ .description('查询 publish workflow 的只读 snapshot 状态(默认人类可读输出)')
93
+ .requiredOption('--tag <tag>', '发布 tag(精确匹配)')
94
+ .requiredOption('--sha <sha>', '发布 commit SHA(精确匹配)')
95
+ .option('--workflow-file <file>', 'GitHub Actions workflow 文件名', 'publish.yml')
96
+ .option('--json', 'JSON 格式输出')
97
+ .option('--structured', '输出完全结构化的 JSON(不包含自然语言字符串,需要配合 --json 使用)')
98
+ .action(handlePublishStatusCommand);
99
+ }
100
+ export const publishStatusCommand = createPublishStatusCommand();
101
+ //# sourceMappingURL=publish-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-status.js","sourceRoot":"","sources":["../../../src/cli/commands/publish-status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * [META] since:2026-04-29 | owner:cli-team | stable:false
3
+ * [WHY] standalone readiness gate command that runs all release quality checks with three-layer gate semantics
4
+ */
5
+ import { Command } from 'commander';
6
+ import { type CheckOutput } from './ship/checker.js';
7
+ export interface ReadinessGateOptions {
8
+ dryRun?: boolean;
9
+ verbose?: boolean;
10
+ json?: boolean;
11
+ structured?: boolean;
12
+ }
13
+ export interface ReadinessGateResult {
14
+ success: boolean;
15
+ blocked: boolean;
16
+ blockReason?: string;
17
+ checkOutput: CheckOutput;
18
+ version?: string;
19
+ versionType?: string;
20
+ }
21
+ export declare function runReadinessGate(options?: ReadinessGateOptions): Promise<ReadinessGateResult>;
22
+ export declare function handleReadinessGateCommand(options: ReadinessGateOptions): Promise<void>;
23
+ export declare function createReadinessGateCommand(): Command;
24
+ export declare const readinessGateCommand: Command;
25
+ //# sourceMappingURL=readiness-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readiness-gate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/readiness-gate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EAA2D,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE9G,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAuFD,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA6EvG;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB7F;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CAQpD;AAED,eAAO,MAAM,oBAAoB,SAA+B,CAAC"}
@@ -0,0 +1,197 @@
1
+ /**
2
+ * [META] since:2026-04-29 | owner:cli-team | stable:false
3
+ * [WHY] standalone readiness gate command that runs all release quality checks with three-layer gate semantics
4
+ */
5
+ import chalk from 'chalk';
6
+ import { Command } from 'commander';
7
+ import { analyzeCommits } from './ship/analyzer.js';
8
+ import { calculateVersion } from './ship/versioner.js';
9
+ import { runQualityChecks, shouldBlockRelease } from './ship/checker.js';
10
+ function renderGateResult(result) {
11
+ const lines = [];
12
+ const { checkOutput, version, versionType } = result;
13
+ lines.push(chalk.bold('Readiness Gate 结果'));
14
+ lines.push('');
15
+ if (version) {
16
+ lines.push(`目标版本: v${version} (${versionType})`);
17
+ lines.push('');
18
+ }
19
+ // Hard gates
20
+ lines.push(chalk.bold('Hard Gates:'));
21
+ for (const [name, item] of checkOutput.results) {
22
+ if (item.gateMode !== 'hard')
23
+ continue;
24
+ const icon = item.result.status === 'passed' ? chalk.green('✓') : item.result.status === 'failed' ? chalk.red('✗') : chalk.yellow('⏸');
25
+ const label = name.replace(/([A-Z])/g, ' $1').toLowerCase();
26
+ lines.push(` ${icon} ${label}`);
27
+ if (item.result.message) {
28
+ lines.push(` ${chalk.gray(item.result.message)}`);
29
+ }
30
+ }
31
+ lines.push('');
32
+ // Warn-only gates
33
+ lines.push(chalk.bold('Warn-only Gates:'));
34
+ for (const [name, item] of checkOutput.results) {
35
+ if (item.gateMode === 'hard')
36
+ continue;
37
+ const icon = item.result.status === 'passed' ? chalk.green('✓') : item.result.status === 'failed' ? chalk.yellow('!') : chalk.yellow('⏸');
38
+ const label = name.replace(/([A-Z])/g, ' $1').toLowerCase();
39
+ lines.push(` ${icon} ${label}`);
40
+ if (item.result.message) {
41
+ lines.push(` ${chalk.gray(item.result.message)}`);
42
+ }
43
+ }
44
+ lines.push('');
45
+ // Summary
46
+ const hardPassed = Array.from(checkOutput.results.values())
47
+ .filter(item => item.gateMode === 'hard')
48
+ .every(item => item.result.status === 'passed');
49
+ const hasFallback = checkOutput.hasFallback;
50
+ if (hasFallback) {
51
+ lines.push(chalk.yellow('⏸️ 判定: FALLBACK — 部分检查信号不可用,需要人工判断'));
52
+ }
53
+ else if (!hardPassed) {
54
+ lines.push(chalk.red('❌ 判定: BLOCKED — hard gate 未通过'));
55
+ }
56
+ else if (checkOutput.confidence.decision === 'block') {
57
+ lines.push(chalk.red('❌ 判定: BLOCKED — 置信度过低'));
58
+ }
59
+ else if (checkOutput.confidence.decision === 'confirm') {
60
+ lines.push(chalk.yellow('⚠️ 判定: CONFIRM — 置信度中等,建议人工确认'));
61
+ }
62
+ else {
63
+ lines.push(chalk.green('✅ 判定: PASSED — 所有 gate 通过'));
64
+ }
65
+ lines.push(`置信度: ${checkOutput.confidence.score}/100`);
66
+ return lines.join('\n');
67
+ }
68
+ function toStructuredResult(result) {
69
+ const { checkOutput, version, versionType } = result;
70
+ const gates = {};
71
+ for (const [name, item] of checkOutput.results) {
72
+ gates[name] = {
73
+ gateMode: item.gateMode,
74
+ status: item.result.status,
75
+ message: item.result.message,
76
+ details: item.result.details,
77
+ };
78
+ }
79
+ return {
80
+ success: result.success,
81
+ blocked: result.blocked,
82
+ blockReason: result.blockReason,
83
+ version,
84
+ versionType,
85
+ confidence: checkOutput.confidence,
86
+ gates,
87
+ };
88
+ }
89
+ export async function runReadinessGate(options = {}) {
90
+ // Step 1: Analyze
91
+ let analyzeResult;
92
+ try {
93
+ analyzeResult = await analyzeCommits();
94
+ }
95
+ catch {
96
+ return {
97
+ success: false,
98
+ blocked: true,
99
+ blockReason: '变更分析失败',
100
+ checkOutput: {
101
+ results: new Map(),
102
+ allHardPassed: false,
103
+ hasFallback: true,
104
+ confidence: { score: 0, decision: 'block', reasons: ['无法分析 commits'], breakdown: { base: 0, bonuses: [], penalties: [] } }
105
+ }
106
+ };
107
+ }
108
+ // Step 2: Version
109
+ let versionResult;
110
+ try {
111
+ versionResult = await calculateVersion(analyzeResult);
112
+ }
113
+ catch {
114
+ return {
115
+ success: false,
116
+ blocked: true,
117
+ blockReason: '版本计算失败',
118
+ checkOutput: {
119
+ results: new Map(),
120
+ allHardPassed: false,
121
+ hasFallback: true,
122
+ confidence: { score: 0, decision: 'block', reasons: ['无法计算版本'], breakdown: { base: 0, bonuses: [], penalties: [] } }
123
+ }
124
+ };
125
+ }
126
+ if (!versionResult.shouldRelease || versionResult.versionType === 'none') {
127
+ return {
128
+ success: true,
129
+ blocked: false,
130
+ checkOutput: {
131
+ results: new Map(),
132
+ allHardPassed: true,
133
+ hasFallback: false,
134
+ confidence: { score: 100, decision: 'auto', reasons: ['无可发布变更'], breakdown: { base: 100, bonuses: [], penalties: [] } }
135
+ },
136
+ version: versionResult.suggestedVersion,
137
+ versionType: versionResult.versionType,
138
+ };
139
+ }
140
+ // Step 3: Gate checks
141
+ const checkOutput = await runQualityChecks(analyzeResult, versionResult);
142
+ const blocked = shouldBlockRelease(checkOutput);
143
+ let blockReason;
144
+ if (blocked) {
145
+ if (checkOutput.hasFallback) {
146
+ blockReason = '存在 fallback 状态,需要人工判断';
147
+ }
148
+ else if (!checkOutput.allHardPassed) {
149
+ blockReason = 'hard gate 未通过';
150
+ }
151
+ else if (checkOutput.confidence.decision === 'block') {
152
+ blockReason = '置信度过低';
153
+ }
154
+ else {
155
+ blockReason = '发布检查未通过';
156
+ }
157
+ }
158
+ return {
159
+ success: !blocked,
160
+ blocked,
161
+ blockReason,
162
+ checkOutput,
163
+ version: versionResult.suggestedVersion,
164
+ versionType: versionResult.versionType,
165
+ };
166
+ }
167
+ export async function handleReadinessGateCommand(options) {
168
+ if (options.structured && !options.json) {
169
+ throw new Error('--structured 需要配合 --json 使用');
170
+ }
171
+ const result = await runReadinessGate(options);
172
+ if (options.json) {
173
+ const output = options.structured
174
+ ? toStructuredResult(result)
175
+ : {
176
+ ...result,
177
+ checkOutput: {
178
+ ...result.checkOutput,
179
+ results: Object.fromEntries(result.checkOutput.results),
180
+ },
181
+ };
182
+ console.log(JSON.stringify(output, null, 2));
183
+ return;
184
+ }
185
+ console.log(renderGateResult(result));
186
+ }
187
+ export function createReadinessGateCommand() {
188
+ return new Command('readiness-gate')
189
+ .description('运行发布 readiness gate 检查(hard / warn-only / fallback 三层语义)')
190
+ .option('--dry-run', '仅分析,不发布')
191
+ .option('--verbose', '显示详细输出')
192
+ .option('--json', 'JSON 格式输出')
193
+ .option('--structured', '输出完全结构化的 JSON(不包含自然语言字符串,需要配合 --json 使用)')
194
+ .action(handleReadinessGateCommand);
195
+ }
196
+ export const readinessGateCommand = createReadinessGateCommand();
197
+ //# sourceMappingURL=readiness-gate.js.map