speccore 8.3.313 → 8.3.332

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 (122) hide show
  1. package/dist/cli.js +3 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/analyze.js +2 -2
  4. package/dist/commands/analyze.js.map +1 -1
  5. package/dist/commands/doc2spec.d.ts +12 -0
  6. package/dist/commands/doc2spec.d.ts.map +1 -1
  7. package/dist/commands/doc2spec.js +64 -17
  8. package/dist/commands/doc2spec.js.map +1 -1
  9. package/dist/commands/done.js +4 -1
  10. package/dist/commands/done.js.map +1 -1
  11. package/dist/commands/execute.js +22 -19
  12. package/dist/commands/execute.js.map +1 -1
  13. package/dist/commands/help.js +1 -0
  14. package/dist/commands/help.js.map +1 -1
  15. package/dist/commands/init.d.ts.map +1 -1
  16. package/dist/commands/init.js +299 -113
  17. package/dist/commands/init.js.map +1 -1
  18. package/dist/commands/iteration/create.js +9 -6
  19. package/dist/commands/iteration/create.js.map +1 -1
  20. package/dist/commands/iteration/taskify.d.ts +8 -0
  21. package/dist/commands/iteration/taskify.d.ts.map +1 -1
  22. package/dist/commands/iteration/taskify.js +55 -38
  23. package/dist/commands/iteration/taskify.js.map +1 -1
  24. package/dist/commands/review.js +2 -7
  25. package/dist/commands/review.js.map +1 -1
  26. package/dist/commands/run.js +11 -2
  27. package/dist/commands/run.js.map +1 -1
  28. package/dist/commands/spec2doc.d.ts +7 -0
  29. package/dist/commands/spec2doc.d.ts.map +1 -1
  30. package/dist/commands/spec2doc.js +32 -18
  31. package/dist/commands/spec2doc.js.map +1 -1
  32. package/dist/commands/unitize.d.ts +2 -0
  33. package/dist/commands/unitize.d.ts.map +1 -1
  34. package/dist/commands/unitize.js +79 -0
  35. package/dist/commands/unitize.js.map +1 -1
  36. package/dist/commands/update.d.ts.map +1 -1
  37. package/dist/commands/update.js +6 -0
  38. package/dist/commands/update.js.map +1 -1
  39. package/dist/core/agents/engine/agent-loader.d.ts +2 -0
  40. package/dist/core/agents/engine/agent-loader.d.ts.map +1 -1
  41. package/dist/core/agents/engine/agent-loader.js +8 -2
  42. package/dist/core/agents/engine/agent-loader.js.map +1 -1
  43. package/dist/core/analyze-engine.d.ts +11 -0
  44. package/dist/core/analyze-engine.d.ts.map +1 -1
  45. package/dist/core/analyze-engine.js +136 -112
  46. package/dist/core/analyze-engine.js.map +1 -1
  47. package/dist/core/ask-engine.d.ts.map +1 -1
  48. package/dist/core/ask-engine.js +22 -2
  49. package/dist/core/ask-engine.js.map +1 -1
  50. package/dist/core/asset-stamp.d.ts +40 -0
  51. package/dist/core/asset-stamp.d.ts.map +1 -0
  52. package/dist/core/asset-stamp.js +77 -0
  53. package/dist/core/asset-stamp.js.map +1 -0
  54. package/dist/core/change-detection.d.ts +1 -1
  55. package/dist/core/change-detection.d.ts.map +1 -1
  56. package/dist/core/change-detection.js +28 -1
  57. package/dist/core/change-detection.js.map +1 -1
  58. package/dist/core/code-graph/incremental-build.d.ts.map +1 -1
  59. package/dist/core/code-graph/incremental-build.js +2 -2
  60. package/dist/core/code-graph/incremental-build.js.map +1 -1
  61. package/dist/core/code-graph/index.d.ts.map +1 -1
  62. package/dist/core/code-graph/index.js +3 -2
  63. package/dist/core/code-graph/index.js.map +1 -1
  64. package/dist/core/code-graph/requirement-linker.js +2 -2
  65. package/dist/core/code-graph/requirement-linker.js.map +1 -1
  66. package/dist/core/code-scanner.d.ts +11 -0
  67. package/dist/core/code-scanner.d.ts.map +1 -1
  68. package/dist/core/code-scanner.js +103 -1
  69. package/dist/core/code-scanner.js.map +1 -1
  70. package/dist/core/constitution-builder.d.ts +24 -0
  71. package/dist/core/constitution-builder.d.ts.map +1 -1
  72. package/dist/core/constitution-builder.js +110 -88
  73. package/dist/core/constitution-builder.js.map +1 -1
  74. package/dist/core/doc-validator.d.ts.map +1 -1
  75. package/dist/core/doc-validator.js +14 -4
  76. package/dist/core/doc-validator.js.map +1 -1
  77. package/dist/core/git-integration.d.ts +13 -8
  78. package/dist/core/git-integration.d.ts.map +1 -1
  79. package/dist/core/git-integration.js +191 -89
  80. package/dist/core/git-integration.js.map +1 -1
  81. package/dist/core/global-knowledge.js +1 -1
  82. package/dist/core/global-knowledge.js.map +1 -1
  83. package/dist/core/intent-recognition.d.ts.map +1 -1
  84. package/dist/core/intent-recognition.js +40 -0
  85. package/dist/core/intent-recognition.js.map +1 -1
  86. package/dist/core/platform-registry.d.ts +2 -2
  87. package/dist/core/platform-registry.d.ts.map +1 -1
  88. package/dist/core/platform-registry.js +25 -2
  89. package/dist/core/platform-registry.js.map +1 -1
  90. package/dist/core/prompt-builder.js +1 -1
  91. package/dist/core/prompt-builder.js.map +1 -1
  92. package/dist/core/rag-engine.d.ts +25 -0
  93. package/dist/core/rag-engine.d.ts.map +1 -1
  94. package/dist/core/rag-engine.js +88 -3
  95. package/dist/core/rag-engine.js.map +1 -1
  96. package/dist/core/refresh-scheduler.js +39 -17
  97. package/dist/core/refresh-scheduler.js.map +1 -1
  98. package/dist/core/requirement-clarifier.js +1 -1
  99. package/dist/core/requirement-clarifier.js.map +1 -1
  100. package/dist/core/task-paths.d.ts.map +1 -1
  101. package/dist/core/task-paths.js +4 -1
  102. package/dist/core/task-paths.js.map +1 -1
  103. package/dist/core/unified-config.d.ts +8 -0
  104. package/dist/core/unified-config.d.ts.map +1 -1
  105. package/dist/core/unified-config.js +3 -0
  106. package/dist/core/unified-config.js.map +1 -1
  107. package/dist/core/unit-context-assembler.d.ts.map +1 -1
  108. package/dist/core/unit-context-assembler.js +21 -45
  109. package/dist/core/unit-context-assembler.js.map +1 -1
  110. package/dist/core/unit-staffing.d.ts +28 -1
  111. package/dist/core/unit-staffing.d.ts.map +1 -1
  112. package/dist/core/unit-staffing.js +115 -20
  113. package/dist/core/unit-staffing.js.map +1 -1
  114. package/dist/utils/markdown-image.d.ts +12 -0
  115. package/dist/utils/markdown-image.d.ts.map +1 -0
  116. package/dist/utils/markdown-image.js +34 -0
  117. package/dist/utils/markdown-image.js.map +1 -0
  118. package/package.json +2 -1
  119. package/templates/html/speccore-ask-guide.html +1 -1
  120. package/templates/html/speccore-ask-pipeline.html +1 -1
  121. package/templates/html/speccore-ask-result.html +1 -1
  122. package/templates/html/speccore-help.html +2 -2
@@ -63,6 +63,8 @@ const ask_1 = require("./ask");
63
63
  const agents_1 = require("../core/agents");
64
64
  // v6.85.0+: RULES 规范库
65
65
  const rule_loader_1 = require("../core/rule-loader");
66
+ const task_utils_1 = require("../utils/task-utils");
67
+ const asset_stamp_1 = require("../core/asset-stamp");
66
68
  // v6.87.0+: COMMANDS 命令模板
67
69
  const command_loader_1 = require("../core/command-loader");
68
70
  // v6.88.0+: SKILLS + HOOKS
@@ -367,6 +369,8 @@ async function createDefaultFiles(projectRoot, speccoreDir) {
367
369
  ## 字段对照总表
368
370
 
369
371
  > **AI 必读**:以下表格明确 CONSTITUTION.md 各字段与 PROJECT.yaml 的对应关系,以及每个字段的准确语义。请勿混淆。
372
+ >
373
+ > **事实源(v8.3.322+)**:CLI 命令的机器执行只认 PROJECT.yaml;CONSTITUTION.md 是 AI 阅读契约,仅在 PROJECT.yaml 未声明对应字段时作兼容回退。两处内容需保持语义一致。
370
374
 
371
375
  ### 项目信息表字段
372
376
 
@@ -424,6 +428,8 @@ async function createDefaultFiles(projectRoot, speccoreDir) {
424
428
 
425
429
  ## 项目信息
426
430
 
431
+ > ⚠️ **机器事实源是 \`.speccore/PROJECT.yaml\` 的 \`platforms\`**(v8.3.323+):源码路径→端的映射(变更检测等)以 platforms[].code_path 为准;本表为 AI 契约与兼容回退,两处需保持一致。
432
+
427
433
  | 工程标识 | 工程类型 | 工程名 | 项目名称 | 项目描述 | 工程源码路径 | 涉及需求端 | 备注 |
428
434
  | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
429
435
  | ${projectName} | 待填写 | 待填写 | 待填写 | 待填写 | ./ | 待填写 | 待填写 |
@@ -532,32 +538,44 @@ async function createDefaultFiles(projectRoot, speccoreDir) {
532
538
 
533
539
  ## 技术栈
534
540
 
535
- ### 后端
536
- - 语言:Java / TypeScript / Go / Python
537
- - 框架:Spring Boot / NestJS / Gin / FastAPI
538
- - 数据库:MySQL / PostgreSQL / MongoDB
539
- - 缓存:Redis
541
+ > 填写规则:**每端一行,只写「已选定」的技术与版本**(决策式声明,不是选项菜单)。
542
+ > AI 生成代码时以本表为准;未填写的端回退到端级 TECH.md(analyze 产物)。
543
+ > 可选技术域见本节末尾,仅作约束参考——未出现在上表中的均视为未选用。
544
+
545
+ | 端 | 语言 | 框架 | 数据存储 | 依据(依赖清单文件) |
546
+ | :--- | :--- | :--- | :--- | :--- |
547
+ | backend-api | Java 17 | Spring Boot 3.x | MySQL 8 | pom.xml |
548
+ | admin-web | TypeScript | Vue 3 | — | package.json |
540
549
 
541
- ### 前端
542
- - 框架:Vue / React / Angular
543
- - 状态管理:Pinia / Redux / NgRx
544
- - UI 组件:Element Plus / Ant Design
550
+ > 可选技术域(约束参考,非已选):
551
+ > - 后端语言:Java / TypeScript / Go / Python;框架:Spring Boot / NestJS / Gin / FastAPI
552
+ > - 前端框架:Vue / React / Angular;状态管理:Pinia / Redux / NgRx;UI 组件:Element Plus / Ant Design
553
+ > - 数据存储:MySQL / PostgreSQL / MongoDB;缓存:Redis
545
554
 
546
555
  ## 命名规范
547
556
  - 接口:/api/v1/{模块}/{操作}
548
- - 错误码:4 位数字,按模块划分
549
- - 数据库:snake_case
550
- - 代码:camelCase / PascalCase
557
+ - 错误码:4 位数字,按「异常码体系」分段划分
558
+ - 数据库:snake_case;代码:camelCase;类/组件:PascalCase
559
+ - 目录:全小写短横线(user-service);文件名与默认导出组件同名
560
+ - Git 提交:type(scope): subject(feat/fix/docs/refactor/test)
551
561
 
552
562
  ## 异常码体系
553
- | 错误码 | 含义 | 场景 |
563
+
564
+ > 错误码为 4 位数字,按段划分——**分段规则给 AI 的是「生成能力」,不是几个示例**:
565
+
566
+ | 段 | 范围 | 归属 |
554
567
  | :--- | :--- | :--- |
555
- | 1001 | 用户不存在 | 登录时手机号未注册 |
556
- | 1002 | 密码错误 | 登录密码不匹配 |
557
- | ... | ... | ... |
568
+ | 1xxx | 1000-1999 | 用户模块 |
569
+ | 2xxx | 2000-2999 | 订单模块 |
570
+
571
+ - 首位 = 模块段,后三位 = 段内序号;错误码全项目唯一,跨端共用同一套编号
572
+ - 示例(演示用,按真实模块替换上表):1001 用户不存在 / 2001 订单不存在
558
573
 
559
574
  ## Git 分支策略
560
575
 
576
+ > ⚠️ **机器事实源是 \`.speccore/PROJECT.yaml\` 的 \`git\` 段**(v8.3.322+):CLI 命令(分支创建、PR、保护分支拦截)只认 PROJECT.yaml;
577
+ > 本节是 AI 阅读契约,仅在 PROJECT.yaml 未声明对应字段时作为兼容回退。修改策略请改 PROJECT.yaml,并保持本节语义一致。
578
+
561
579
  > 公共默认策略。各工程可在「Git 配置」表中覆盖。
562
580
 
563
581
  - 默认分支: main(可选: master / develop / trunk)
@@ -568,6 +586,15 @@ async function createDefaultFiles(projectRoot, speccoreDir) {
568
586
  - 保护分支上禁止直接 commit 和 push,只能通过 PR 合并
569
587
  - 支持精确匹配和通配符(如 release/*)
570
588
  `);
589
+ // v8.3.325: 自动检测技术栈并预填决策式技术栈表(模板刚生成,示例行可整体替换)
590
+ try {
591
+ const { enhanceConstitutionTechStack } = require('../core/constitution-builder');
592
+ await enhanceConstitutionTechStack(projectRoot, {
593
+ platformName: projectName,
594
+ freshTemplate: true,
595
+ });
596
+ }
597
+ catch { /* 检测失败不影响 init 主流程 */ }
571
598
  } // if CONSTITUTION.md 不存在
572
599
  // PROJECT files
573
600
  await (0, fs_extra_1.writeFile)((0, path_1.join)(speccoreDir, 'PROJECT', 'INDEX.md'), `# 项目索引
@@ -586,9 +613,18 @@ async function createDefaultFiles(projectRoot, speccoreDir) {
586
613
  `);
587
614
  await (0, fs_extra_1.writeFile)((0, path_1.join)(speccoreDir, 'PROJECT', 'TEAM.md'), `# 团队与 Git 映射
588
615
 
589
- | 成员 | Git 用户名 | 角色 | 技术栈 | 负责模块 |
590
- | :--- | :--- | :--- | :--- | :--- |
591
- | | | | | |
616
+ > **全员名册(全局基座,v8.3.319+)**: 成员在此登记后,所有迭代的 STAFFING.md 自动继承。
617
+ > 各迭代 STAFFING.md 只写差异(同名成员整体覆盖其方向/比例);本表是团队人员的唯一事实源。
618
+
619
+ | 成员 | Git 用户名 | 角色 | 技术栈 | 负责模块 | 平台方向 | 投入比例 | 状态 |
620
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
621
+ | | | | | | | | |
622
+
623
+ > 说明:
624
+ > - **平台方向**: 后台 / 小程序 / Web / APP,多个用逗号分隔(也可直接写标准端名)
625
+ > - **投入比例**: 0-100%(缺省按 100),用于 taskify 时自动分配和负荷均衡
626
+ > - **状态**: 在职(缺省)/ 出项目——出项目成员不参与自动填充(analyze 候选推导、taskify 负荷均衡自动跳过)
627
+ > - 旧版本表(无「平台方向」列)兼容读取:缺此列时全局基座不参与合并,各迭代 STAFFING.md 独立生效
592
628
  `);
593
629
  // ITERATIONS/README.md
594
630
  await (0, fs_extra_1.writeFile)((0, path_1.join)(speccoreDir, 'ITERATIONS', 'README.md'), `# 迭代索引
@@ -656,77 +692,11 @@ async function createDefaultFiles(projectRoot, speccoreDir) {
656
692
  },
657
693
  },
658
694
  }, null, 2));
659
- // CODE_REVIEW.md
660
- await (0, fs_extra_1.writeFile)((0, path_1.join)(speccoreDir, 'RULES', 'CODE_REVIEW.md'), `# 代码审查规则
661
-
662
- ## 审查维度
663
- 1. 规范遵循
664
- 2. 代码质量
665
- 3. 测试覆盖
666
- 4. 性能指标
667
- 5. 安全性
668
-
669
- ## 评分标准
670
- | 等级 | 分数 | 说明 |
671
- | :--- | :--- | :--- |
672
- | A | 90-100 | 优秀 |
673
- | B | 75-89 | 良好 |
674
- | C | 60-74 | 合格 |
675
- | D | <60 | 不合格 |
676
- `);
677
- // POST_COMPLETION.md (Feature 完成后的维护流程)
678
- await (0, fs_extra_1.writeFile)((0, path_1.join)(speccoreDir, 'RULES', 'POST_COMPLETION.md'), `# Feature 完成后的维护流程
679
-
680
- > 当 Feature 已签署 ✅ 已完成 后,本文件定义其线上运行与维护期的标准流程。
681
-
682
- ## 1. Feature 状态扩展
683
-
684
- | 状态 | 图标 | 含义 | 触发条件 |
685
- | :--- | :--- | :--- | :--- |
686
- | 已完成 | ✅ | Spec 与代码完全对齐,已上线 | 开发完成 + 验收通过 |
687
- | 待反向同步 | ⚠️ | 代码已改但 Spec 未同步 | 紧急补丁后 |
688
- | 维护中 | 🔄 | 正在回归或功能增强 | 分配维护任务后 |
689
- | 已废弃 | 🚫 | 功能下线,不再维护 | 业务下线 + 代码移除 |
690
-
691
- ## 2. 补丁反向同步流程(⚠️ → ✅)
692
-
693
- 1. AI 读取当前代码,对比 Spec 文件,生成差异报告
694
- 2. 逐项更新:REQ.md、API_CONTRACT.yaml、TASK.md
695
- 3. 更新变更履历
696
- 4. 更新 PROJECT_GRAPH.md 状态
697
-
698
- ## 3. Bug 修复流程(✅ → 🔄 → ✅)
699
-
700
- 1. 标记状态为 🔄 维护中
701
- 2. 根因分析 → 追加到 TASK.md「线上问题记录」
702
- 3. 沉淀到 PATTERNS/ 模式库
703
- 4. 回归验证 → 恢复状态到 ✅
704
-
705
- ## 4. 功能增强流程(✅ → 🔄 → ✅)
706
-
707
- 1. 标记状态为 🔄 维护中
708
- 2. 在 REQ.md 追加新需求
709
- 3. 更新 API_CONTRACT.yaml
710
- 4. 更新 TASK.md 和 E2E-TEST-SPEC.md
711
- 5. 完成后改回 ✅
712
-
713
- ## 5. 功能下线流程(✅ → 🚫)
714
-
715
- 1. 状态改为 🚫 已废弃
716
- 2. PATTERNS/ 标记相关模式为「仅作历史参考」
717
- 3. 代码保留至少一个迭代周期
718
- 4. 最后一个周期后删除代码和 Spec
719
-
720
- ## 6. 维护检查清单
721
-
722
- - [ ] 是否已更新所有受影响的 Spec 文件?
723
- - [ ] 是否已在变更履历中追加记录?
724
- - [ ] 是否已更新 PROJECT_GRAPH.md 状态?
725
- - [ ] 是否已沉淀到 PATTERNS/ 模式库?
726
- - [ ] 是否已回归 E2E-TEST-SPEC.md 测试场景?
727
-
728
- 若有任何一项为"否",不得将状态改回 ✅ 已完成。
729
- `);
695
+ // CODE_REVIEW.md / POST_COMPLETION.md(内容由 EXTRA_BUILTIN_RULES 常量统一维护,
696
+ // 首次 init 无条件写入;update 路径由 initRulesDir 缺失补写)
697
+ for (const rule of EXTRA_BUILTIN_RULES) {
698
+ await (0, fs_extra_1.writeFile)((0, path_1.join)(speccoreDir, 'RULES', rule.name), rule.content);
699
+ }
730
700
  // v8.3.41+: 用户自定义分析文档模板说明
731
701
  const templatesReadmePath = (0, path_1.join)(speccoreDir, 'templates', 'README.md');
732
702
  if (!(await (0, fs_extra_1.pathExists)(templatesReadmePath))) {
@@ -1474,6 +1444,22 @@ async function initAgentsDir(projectRoot) {
1474
1444
  if (!(await (0, fs_extra_1.pathExists)(destPath))) {
1475
1445
  await (0, fs_extra_1.writeFile)(destPath, agent.content);
1476
1446
  }
1447
+ else {
1448
+ // v8.3.315+: 版本戳驱动同步 — 内置内容带当前版本戳:
1449
+ // 有旧戳 → 旧版 CLI 生成 → 备份刷新
1450
+ // 无戳且命中旧版特征(「# 角色:」标题、缺 systemPrompt frontmatter)→ 老项目首升级 → 备份刷新
1451
+ // 无戳且无旧版特征 → 用户自定义 → 保留
1452
+ const existing = await (0, fs_extra_1.readFile)(destPath, 'utf-8');
1453
+ // 旧版特征 = 缺 systemPrompt frontmatter 且带「# 角色:」标题(新版无此标题)
1454
+ const decision = (0, asset_stamp_1.decideStampedSync)(existing, agent.content, c => !/^---\s*[\s\S]*?systemPrompt:/m.test(c) && /#\s*角色[::]\s*\(?/m.test(c));
1455
+ if (decision === 'refresh') {
1456
+ await safeWriteWithBackup(destPath, agent.content);
1457
+ logger_1.logger.info(` 🔄 刷新旧版角色定义: ${agent.name}.md(原文件已备份)`);
1458
+ }
1459
+ else if (decision === 'restamp') {
1460
+ await (0, fs_extra_1.writeFile)(destPath, agent.content);
1461
+ }
1462
+ }
1477
1463
  }
1478
1464
  // 复制注册表(不覆盖用户已自定义的)
1479
1465
  const registryContent = await (0, agents_1.getBuiltinRegistryContent)();
@@ -1482,6 +1468,19 @@ async function initAgentsDir(projectRoot) {
1482
1468
  if (!(await (0, fs_extra_1.pathExists)(registryPath))) {
1483
1469
  await (0, fs_extra_1.writeFile)(registryPath, registryContent);
1484
1470
  }
1471
+ else {
1472
+ // v8.3.315+: 版本戳驱动 + 缺失型旧特征兜底(老项目无戳且缺「叠加 RULES/」列)
1473
+ // 已注册的自定义角色如有丢失可从备份文件恢复。
1474
+ const existing = await (0, fs_extra_1.readFile)(registryPath, 'utf-8');
1475
+ const decision = (0, asset_stamp_1.decideStampedSync)(existing, registryContent, c => !/叠加\s+RULES\//.test(c));
1476
+ if (decision === 'refresh') {
1477
+ await safeWriteWithBackup(registryPath, registryContent);
1478
+ logger_1.logger.info(' 🔄 刷新旧版 AGENTS 注册表: _INDEX.md(原文件已备份,自定义角色请从备份合并)');
1479
+ }
1480
+ else if (decision === 'restamp') {
1481
+ await (0, fs_extra_1.writeFile)(registryPath, registryContent);
1482
+ }
1483
+ }
1485
1484
  }
1486
1485
  // 复制模板(不覆盖用户已自定义的)
1487
1486
  const templateContent = await (0, agents_1.getBuiltinTemplateContent)();
@@ -1503,17 +1502,110 @@ const OBSOLETE_MARKERS = [
1503
1502
  { pattern: /speccore\s+split|split\s+-I/, desc: 'split 死命令(v8.3.231+ 应为 taskify)' },
1504
1503
  { pattern: /taskify\s+-I/, desc: 'taskify -I(应为 -i)' },
1505
1504
  { pattern: /CONSTITUTION\.md\s+指定的源码路径(?!\s*\/\s*PROJECT\.yaml)/, desc: '缺少 PROJECT.yaml 引用' },
1506
- { pattern: /禁止在迭代目录下创建\s+10-backend/, desc: '旧表述:迭代目录(应为 任务目录)' },
1505
+ { pattern: /禁止在迭代目录下创建\s+10-backend/, desc: '旧表述:迭代目录(应为任务目录)' },
1506
+ { pattern: /dev\s+后生成/, desc: '旧流水线表述(dev 已更名 run,v8.3.280+)' },
1507
+ { pattern: /必须开始新对话/, desc: 'SPECCORE_CONTINUE 旧文案(应为优先在同一会话继续)' },
1507
1508
  ];
1508
- function detectObsoleteContent(content) {
1509
+ /**
1510
+ * v8.3.46+: 智能过时检测(命中型)
1511
+ * v8.3.314+: 支持 requiredPatterns 缺失型检测 — 新版模板独有的关键内容块,旧版文件缺失即视为过时
1512
+ */
1513
+ function detectObsoleteContent(content, requiredPatterns = []) {
1509
1514
  const markers = [];
1510
1515
  for (const marker of OBSOLETE_MARKERS) {
1511
1516
  if (marker.pattern.test(content)) {
1512
1517
  markers.push(marker.desc);
1513
1518
  }
1514
1519
  }
1520
+ for (const pattern of requiredPatterns) {
1521
+ if (!pattern.test(content)) {
1522
+ markers.push('缺少新版关键内容');
1523
+ }
1524
+ }
1515
1525
  return { hasObsolete: markers.length > 0, markers };
1516
1526
  }
1527
+ /**
1528
+ * v8.3.314+: 不在 getBuiltinRuleContents 列表内的内置规则。
1529
+ * 首次 init(createDefaultFiles)与 update(initRulesDir)都必须确保其存在,
1530
+ * 否则 AGENTS.md 的引用会出现断链(update 路径此前只补列表内文件)。
1531
+ */
1532
+ const EXTRA_BUILTIN_RULES = [
1533
+ {
1534
+ name: 'CODE_REVIEW.md',
1535
+ content: `# 代码审查规则
1536
+
1537
+ ## 审查维度
1538
+ 1. 规范遵循
1539
+ 2. 代码质量
1540
+ 3. 测试覆盖
1541
+ 4. 性能指标
1542
+ 5. 安全性
1543
+
1544
+ ## 评分标准
1545
+ | 等级 | 分数 | 说明 |
1546
+ | :--- | :--- | :--- |
1547
+ | A | 90-100 | 优秀 |
1548
+ | B | 75-89 | 良好 |
1549
+ | C | 60-74 | 合格 |
1550
+ | D | <60 | 不合格 |
1551
+ `,
1552
+ },
1553
+ {
1554
+ name: 'POST_COMPLETION.md',
1555
+ content: `# Feature 完成后的维护流程
1556
+
1557
+ > 当 Feature 已签署 ✅ 已完成 后,本文件定义其线上运行与维护期的标准流程。
1558
+
1559
+ ## 1. Feature 状态扩展
1560
+
1561
+ | 状态 | 图标 | 含义 | 触发条件 |
1562
+ | :--- | :--- | :--- | :--- |
1563
+ | 已完成 | ✅ | Spec 与代码完全对齐,已上线 | 开发完成 + 验收通过 |
1564
+ | 待反向同步 | ⚠️ | 代码已改但 Spec 未同步 | 紧急补丁后 |
1565
+ | 维护中 | 🔄 | 正在回归或功能增强 | 分配维护任务后 |
1566
+ | 已废弃 | 🚫 | 功能下线,不再维护 | 业务下线 + 代码移除 |
1567
+
1568
+ ## 2. 补丁反向同步流程(⚠️ → ✅)
1569
+
1570
+ 1. AI 读取当前代码,对比 Spec 文件,生成差异报告
1571
+ 2. 逐项更新:REQ.md、API_CONTRACT.yaml、TASK.md
1572
+ 3. 更新变更履历
1573
+ 4. 更新 PROJECT_GRAPH.md 状态
1574
+
1575
+ ## 3. Bug 修复流程(✅ → 🔄 → ✅)
1576
+
1577
+ 1. 标记状态为 🔄 维护中
1578
+ 2. 根因分析 → 追加到 TASK.md「线上问题记录」
1579
+ 3. 沉淀到 PATTERNS/ 模式库
1580
+ 4. 回归验证 → 恢复状态到 ✅
1581
+
1582
+ ## 4. 功能增强流程(✅ → 🔄 → ✅)
1583
+
1584
+ 1. 标记状态为 🔄 维护中
1585
+ 2. 在 REQ.md 追加新需求
1586
+ 3. 更新 API_CONTRACT.yaml
1587
+ 4. 更新 TASK.md 和 E2E-TEST-SPEC.md
1588
+ 5. 完成后改回 ✅
1589
+
1590
+ ## 5. 功能下线流程(✅ → 🚫)
1591
+
1592
+ 1. 状态改为 🚫 已废弃
1593
+ 2. PATTERNS/ 标记相关模式为「仅作历史参考」
1594
+ 3. 代码保留至少一个迭代周期
1595
+ 4. 最后一个周期后删除代码和 Spec
1596
+
1597
+ ## 6. 维护检查清单
1598
+
1599
+ - [ ] 是否已更新所有受影响的 Spec 文件?
1600
+ - [ ] 是否已在变更履历中追加记录?
1601
+ - [ ] 是否已更新 PROJECT_GRAPH.md 状态?
1602
+ - [ ] 是否已沉淀到 PATTERNS/ 模式库?
1603
+ - [ ] 是否已回归 E2E-TEST-SPEC.md 测试场景?
1604
+
1605
+ 若有任何一项为"否",不得将状态改回 ✅ 已完成。
1606
+ `,
1607
+ },
1608
+ ];
1517
1609
  /**
1518
1610
  * v6.85.0+: 初始化 RULES 规范库
1519
1611
  * 将内置默认编码规范复制到 .speccore/RULES/ 目录
@@ -1532,9 +1624,11 @@ async function initRulesDir(projectRoot) {
1532
1624
  }
1533
1625
  // v6.98.0+: 创建 AGENTS.md 投影用的 .inline.md 文件
1534
1626
  // v8.3.46+: 智能过时检测 — 发现已知过时标记时自动覆盖
1627
+ // v8.3.314+: required 缺失型检测 — 新版模板独有内容块缺失时同样覆盖
1535
1628
  const inlineTemplates = [
1536
1629
  {
1537
1630
  name: '01-PROJECT_STRUCTURE.inline.md',
1631
+ required: [/SOURCE\.md/],
1538
1632
  content: `## 项目结构
1539
1633
 
1540
1634
  \`\`\`
@@ -1543,6 +1637,7 @@ Iteration-NNN-name/ ← 迭代目录
1543
1637
  ├── 010-requirements/ ← 需求层
1544
1638
  │ ├── sources/ converted/ ← [只读] 原始 PRD / doc2spec 转换
1545
1639
  │ ├── features/{功能单元}/ ← unitize 切分产出(功能单元目录 = analyze 对齐锚点)
1640
+ │ │ └── SOURCE.md ← 需求原文切片(旧版为 README.md)
1546
1641
  │ ├── bugs/ refactors/ research/ ← 三类需求文档(与任务类型对应)
1547
1642
  │ └── CLARIFY_REPORT.md ← 澄清报告
1548
1643
  ├── 020-specs/ ← 需求分析(analyze 输出)
@@ -1612,6 +1707,7 @@ Iteration-NNN-name/ ← 迭代目录
1612
1707
  | \`[SPECCORE_STEP_FAIL: <cmd>]\` | Pipeline 步骤失败 | 提示用户选择重试/跳过/停止 |
1613
1708
  | \`[SPECCORE_AMBIGUOUS: <cmd1> \\| <cmd2>]\` | 意图模糊 | 展示匹配选项让用户选择 |
1614
1709
  | \`[SPECCORE_CONTINUE: <path>]\` | 批次执行完成,需续批 | **优先在同一会话继续**(按标记中的命令执行下一批);上下文紧张时开新对话,先读取 \`<path>\` 恢复上下文再续批 |`,
1710
+ required: [/SPECCORE_NEEDS_INFO/],
1615
1711
  },
1616
1712
  {
1617
1713
  name: '03-COMMAND_CHEATSHEET.inline.md',
@@ -1638,22 +1734,39 @@ speccore run --demand deploy # 逃生舱:显式声明是需求(
1638
1734
  speccore analyze -g # 快捷糖:等价 speccore global analyze
1639
1735
  speccore unitize prd.md # 文件位置参数;doc2spec prd.docx 同理
1640
1736
  speccore verify deploy # 测试阶段位置参数(dev/pr/deploy/release)
1641
- \`\`\``
1737
+ \`\`\``,
1738
+ required: [/speccore\s+run\s+#/],
1642
1739
  },
1643
1740
  ];
1741
+ // v8.3.314+: 补写 getBuiltinRuleContents 列表之外的内置规则(CODE_REVIEW/POST_COMPLETION)。
1742
+ // update 路径此前只补列表内文件,旧项目缺失这两份时 AGENTS.md 引用断链。
1743
+ for (const rule of EXTRA_BUILTIN_RULES) {
1744
+ const destPath = (0, path_1.join)(rulesDir, rule.name);
1745
+ if (!(await (0, fs_extra_1.pathExists)(destPath))) {
1746
+ await (0, fs_extra_1.writeFile)(destPath, rule.content);
1747
+ }
1748
+ }
1644
1749
  for (const tpl of inlineTemplates) {
1645
1750
  const destPath = (0, path_1.join)(rulesDir, tpl.name);
1751
+ const stampedContent = (0, asset_stamp_1.stampContent)(tpl.content);
1646
1752
  const exists = await (0, fs_extra_1.pathExists)(destPath);
1647
1753
  if (!exists) {
1648
- await (0, fs_extra_1.writeFile)(destPath, tpl.content);
1754
+ await (0, fs_extra_1.writeFile)(destPath, stampedContent);
1649
1755
  }
1650
- else if (tpl.name.endsWith('.inline.md')) {
1651
- // v8.3.46+: 智能过时检测 — 发现已知过时标记时自动覆盖
1756
+ else {
1757
+ // v8.3.315+: 版本戳驱动同步(统一决策表 decideStampedSync)
1758
+ // 有旧戳 → 旧版 CLI 生成 → 备份刷新(不再枚举旧特征,改模板即自动迁移)
1759
+ // 无戳 → 旧特征兜底:过时标记命中 / 缺新版关键内容(required)→ 备份刷新
1760
+ // 同版本戳或用户自定义 → 保留
1761
+ // 覆盖一律 safeWriteWithBackup:旧版特征检测存在误判可能,备份保底可回滚
1652
1762
  const existingContent = await (0, fs_extra_1.readFile)(destPath, 'utf-8');
1653
- const { hasObsolete, markers } = detectObsoleteContent(existingContent);
1654
- if (hasObsolete) {
1655
- logger_1.logger.info(` 🔄 检测到过时内容 [${tpl.name}]: ${markers.join('、')},已自动更新`);
1656
- await (0, fs_extra_1.writeFile)(destPath, tpl.content);
1763
+ const decision = (0, asset_stamp_1.decideStampedSync)(existingContent, stampedContent, c => detectObsoleteContent(c, tpl.required).hasObsolete);
1764
+ if (decision === 'refresh') {
1765
+ logger_1.logger.info(` 🔄 检测到旧版内容 [${tpl.name}],已备份并更新`);
1766
+ await safeWriteWithBackup(destPath, stampedContent);
1767
+ }
1768
+ else if (decision === 'restamp') {
1769
+ await (0, fs_extra_1.writeFile)(destPath, stampedContent);
1657
1770
  }
1658
1771
  }
1659
1772
  }
@@ -1743,12 +1856,12 @@ async function syncAgentsMd(projectRoot, force = false) {
1743
1856
  const agentRows = [];
1744
1857
  if (await (0, fs_extra_1.pathExists)(agentsDir)) {
1745
1858
  const files = (await (0, fs_extra_1.readdir)(agentsDir))
1746
- .filter(f => f.endsWith('.md') && !f.startsWith('_') && !f.startsWith('.'))
1859
+ .filter(f => f.endsWith('.md') && !f.startsWith('_') && !f.startsWith('.') && !(0, task_utils_1.isTimestampBackup)(f))
1747
1860
  .sort();
1748
1861
  for (const f of files) {
1749
1862
  if (f.endsWith('.inline.md')) {
1750
1863
  const content = await (0, fs_extra_1.readFile)((0, path_1.join)(agentsDir, f), 'utf-8');
1751
- agentInlines.push(content.trim());
1864
+ agentInlines.push((0, asset_stamp_1.stripAssetStamp)(content).trim());
1752
1865
  }
1753
1866
  else {
1754
1867
  const content = await (0, fs_extra_1.readFile)((0, path_1.join)(agentsDir, f), 'utf-8');
@@ -1788,12 +1901,13 @@ async function syncAgentsMd(projectRoot, force = false) {
1788
1901
  const ruleLinks = [];
1789
1902
  if (await (0, fs_extra_1.pathExists)(rulesDir)) {
1790
1903
  const files = (await (0, fs_extra_1.readdir)(rulesDir))
1791
- .filter(f => f.endsWith('.md') && !f.startsWith('_') && !f.startsWith('.'))
1904
+ .filter(f => f.endsWith('.md') && !f.startsWith('_') && !f.startsWith('.') && !(0, task_utils_1.isTimestampBackup)(f))
1792
1905
  .sort();
1793
1906
  for (const f of files) {
1794
1907
  if (f.endsWith('.inline.md')) {
1795
1908
  const content = await (0, fs_extra_1.readFile)((0, path_1.join)(rulesDir, f), 'utf-8');
1796
- ruleInlines.push(content.trim());
1909
+ // v8.3.315+: 剥掉资产版本戳(投影内容不携带 CLI 内部戳)
1910
+ ruleInlines.push((0, asset_stamp_1.stripAssetStamp)(content).trim());
1797
1911
  }
1798
1912
  else {
1799
1913
  const name = f.replace(/\.md$/, '').replace(/[-_]/g, ' ');
@@ -1836,10 +1950,12 @@ async function createSampleIteration(projectRoot) {
1836
1950
  await (0, fs_extra_1.writeFile)((0, path_1.join)(iterDir, 'STAFFING.md'), [
1837
1951
  '# 示例 人员排期配置',
1838
1952
  '',
1839
- '| 成员 | 平台方向 | 投入比例 |',
1840
- '| :--- | :--- | :--- |',
1841
- '| 张三 | APP, H5 | 80% |',
1842
- '| 李四 | admin, 小程序 | 70% |',
1953
+ '> 全员基座见 .speccore/PROJECT/TEAM.md(全局名册,自动继承);本文件只写本迭代差异/覆盖',
1954
+ '',
1955
+ '| 成员 | 平台方向 | 投入比例 | 状态 |',
1956
+ '| :--- | :--- | :--- | :--- |',
1957
+ '| 张三 | APP, H5 | 80% | |',
1958
+ '| 李四 | admin, 小程序 | 70% | |',
1843
1959
  '',
1844
1960
  '> 编辑此文件后重新运行 taskify 即可更新默认分配',
1845
1961
  ].join('\n'));
@@ -2095,7 +2211,7 @@ function generateAIRulesContent() {
2095
2211
  '1. **/spec:ask 是智能路由入口** — 用户说"新建迭代"、"分析需求" → 调用 `speccore ask`,不要自己写 mkdir/analyze',
2096
2212
  '2. **不要跨命令猜测** — 每个斜杠命令只做它描述的事,不要自动级联后续步骤',
2097
2213
  '3. **参数从命令描述获取** — /spec:execute 的描述中有完整的参数说明',
2098
- '4. **上下文不足时读取文件** — 查看 .speccore/CONSTITUTION.md、STAFFING.md 等',
2214
+ '4. **上下文不足时读取文件** — 查看 .speccore/CONSTITUTION.md、STAFFING.md、.speccore/PROJECT/TEAM.md(全员名册)等',
2099
2215
  '',
2100
2216
  '## 核心流水线',
2101
2217
  '',
@@ -2272,6 +2388,8 @@ examples/
2272
2388
  ├── README.md ← 本文件
2273
2389
  ├── config/ ← 配置文件示例
2274
2390
  │ ├── CONSTITUTION-EXAMPLE.md ← CONSTITUTION.md 完整示例(多工程)
2391
+ │ ├── TEAM-EXAMPLE.md ← TEAM.md 全员名册示例(7 列,含状态)
2392
+ │ ├── STAFFING-EXAMPLE.md ← STAFFING.md 迭代排期示例(差异覆盖,含状态)
2275
2393
  │ ├── PROJECT-EXAMPLE.yaml ← PROJECT.yaml 完整示例(多工程)
2276
2394
  │ ├── SPECCORE-YML-EXAMPLE.yml ← .speccore.yml 主配置完整示例(v8.3.296+)
2277
2395
  │ ├── GIT-CONFIG-EXAMPLE.txt ← 子任务 .meta/git-config 格式示例
@@ -2298,8 +2416,9 @@ examples/
2298
2416
  8. 查看 \`config/DEPLOY-EXAMPLE.yaml\`,了解部署配置格式(用于 \`speccore deploy\`)
2299
2417
  9. 查看 \`config/VERIFY-EXAMPLE.yaml\`,了解测试验证配置格式(用于 \`speccore verify --config\`)
2300
2418
  10. 查看 \`config/SPECCORE-YML-EXAMPLE.yml\`,了解主配置 .speccore.yml 全部字段(质量门禁/冒烟三时机/流水线/AI provider)
2301
- 11. 查看 \`ci/github-actions.yml\`,复制到 \`.github/workflows/\` 启用 CI 校验
2302
- 12. 修改后运行 \`speccore update\` 自动同步到 PROJECT.yaml
2419
+ 11. 查看 \`config/TEAM-EXAMPLE.md\` 与 \`config/STAFFING-EXAMPLE.md\`,了解人员配置两级继承(TEAM 全员基座 + STAFFING 迭代差异),「状态」列支持出项目成员免分配
2420
+ 12. 查看 \`ci/github-actions.yml\`,复制到 \`.github/workflows/\` 启用 CI 校验
2421
+ 13. 修改后运行 \`speccore update\` 更新配置结构(Git 策略以 \`.speccore/PROJECT.yaml\` 的 \`git\` 段为机器事实源)
2303
2422
 
2304
2423
  ## 注意事项
2305
2424
 
@@ -2311,7 +2430,7 @@ examples/
2311
2430
  const constitutionExample = `## 字段对照总表
2312
2431
 
2313
2432
  > **AI 必读**:以下表格明确 CONSTITUTION.md 各字段与 PROJECT.yaml 的对应关系。
2314
- > 人类只需填写 CONSTITUTION.md,PROJECT.yaml 由 CLI 自动生成/同步。
2433
+ > 机器执行以 PROJECT.yaml 为事实源(CLI 只读 PROJECT.yaml);CONSTITUTION.md 是 AI 阅读契约,仅在 PROJECT.yaml 未声明对应字段时作兼容回退。两处内容需保持语义一致。
2315
2434
 
2316
2435
  ### 项目信息表字段
2317
2436
 
@@ -2363,6 +2482,8 @@ examples/
2363
2482
 
2364
2483
  ## 项目信息
2365
2484
 
2485
+ > ⚠️ **机器事实源是 \`.speccore/PROJECT.yaml\` 的 \`platforms\`**(v8.3.323+):源码路径→端的映射(变更检测等)以 platforms[].code_path 为准;本表为 AI 契约与兼容回退,两处需保持一致。
2486
+
2366
2487
  | 工程标识 | 工程类型 | 工程名 | 项目名称 | 项目描述 | 工程源码路径 | 涉及需求端 | 备注 |
2367
2488
  | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
2368
2489
  | admin-web | Web管理后台 | 后台管理 | 运营后台 | 运营人员使用的后台管理系统 | ./packages/admin | 后台管理端需求文档 | 核心系统 |
@@ -2382,6 +2503,35 @@ examples/
2382
2503
 
2383
2504
  ---
2384
2505
 
2506
+ ## 技术栈
2507
+
2508
+ > 填写规则:**每端一行,只写「已选定」的技术与版本**(决策式声明,不是选项菜单)。
2509
+ > AI 生成代码时以本表为准;未填写的端回退到端级 TECH.md(analyze 产物)。
2510
+
2511
+ | 端 | 语言 | 框架 | 数据存储 | 依据(依赖清单文件) |
2512
+ | :--- | :--- | :--- | :--- | :--- |
2513
+ | backend-api | Java 17 | Spring Boot 3.x | MySQL 8 | pom.xml |
2514
+ | admin-web | TypeScript | Vue 3 | — | package.json |
2515
+ | h5-mobile | TypeScript | Vue 3 | — | package.json |
2516
+ | miniapp | JavaScript | 原生小程序 | — | package.json |
2517
+
2518
+ > 可选技术域(约束参考,非已选):后端语言 Java/TypeScript/Go/Python;框架 Spring Boot/NestJS/Gin/FastAPI;前端框架 Vue/React/Angular;数据存储 MySQL/PostgreSQL/MongoDB;缓存 Redis。
2519
+
2520
+ ## 异常码体系
2521
+
2522
+ > 错误码为 4 位数字,按段划分——**分段规则给 AI 的是「生成能力」,不是几个示例**:
2523
+
2524
+ | 段 | 范围 | 归属 |
2525
+ | :--- | :--- | :--- |
2526
+ | 1xxx | 1000-1999 | 用户模块 |
2527
+ | 2xxx | 2000-2999 | 订单模块 |
2528
+ | 3xxx | 3000-3999 | 支付模块 |
2529
+
2530
+ - 首位 = 模块段,后三位 = 段内序号;错误码全项目唯一,跨端共用同一套编号
2531
+ - 示例(演示用,按真实模块替换上表):1001 用户不存在 / 2001 订单不存在 / 3001 支付超时
2532
+
2533
+ ---
2534
+
2385
2535
  ## Git 公共配置
2386
2536
 
2387
2537
  > 公共默认值。各工程在「Git 配置」表中只写与公共配置不同的字段,未填写的字段自动使用此处默认值。
@@ -2471,10 +2621,46 @@ examples/
2471
2621
 
2472
2622
  > 📌 **使用说明**:
2473
2623
  > 1. 复制本示例内容到 \`CONSTITUTION.md\`,根据实际项目修改
2474
- > 2. 修改后运行 \`speccore update\` 自动同步到 PROJECT.yaml
2624
+ > 2. 修改后运行 \`speccore update\` 更新配置结构(Git 策略以 \`.speccore/PROJECT.yaml\` 的 \`git\` 段为机器事实源)
2475
2625
  > 3. 子任务目录下的 \`.meta/git-config\` 可覆盖全局配置(见目录结构说明)
2476
2626
  `;
2477
2627
  await (0, fs_extra_1.writeFile)((0, path_1.join)(configDir, 'CONSTITUTION-EXAMPLE.md'), constitutionExample);
2628
+ // v8.3.324: 人员配置示例(两级继承:TEAM 全员基座 + STAFFING 迭代差异,含「状态」列)
2629
+ const teamExample = `# TEAM.md — 团队与 Git 映射(全员名册,示例)
2630
+
2631
+ > **全员名册(全局基座,v8.3.319+)**: 成员在此登记后,所有迭代的 STAFFING.md 自动继承。
2632
+ > 各迭代 STAFFING.md 只写差异(同名成员整体覆盖其方向/比例/状态);本表是团队人员的唯一事实源。
2633
+
2634
+ | 成员 | Git 用户名 | 角色 | 技术栈 | 负责模块 | 平台方向 | 投入比例 | 状态 |
2635
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
2636
+ | 张三 | zhangsan | 后端 | Java/Spring Boot | 订单模块 | backend-api | 100% | 在职 |
2637
+ | 李四 | lisi | 前端 | Vue 3 | 商城页面 | admin-web, h5-mobile | 80% | 在职 |
2638
+ | 王五 | wangwu | 前端 | 原生小程序 | 小程序 | miniapp | 60% | 在职 |
2639
+ | 赵六 | zhaoliu | 后端 | Go | 消息推送 | backend-api | 0% | 出项目 |
2640
+
2641
+ > 说明:
2642
+ > - **平台方向**: 后台 / 小程序 / Web / APP,多个用逗号分隔(也可直接写标准端名)
2643
+ > - **投入比例**: 0-100%(缺省按 100),用于 taskify 时自动分配和负荷均衡
2644
+ > - **状态**: 在职(缺省)/ 出项目——出项目成员不参与自动填充(analyze 候选推导、taskify 负荷均衡自动跳过);迭代层写「在职」可临时复活(如赵六回归某期)
2645
+ `;
2646
+ await (0, fs_extra_1.writeFile)((0, path_1.join)(configDir, 'TEAM-EXAMPLE.md'), teamExample);
2647
+ const staffingExample = `# STAFFING.md — 迭代人员排期(差异覆盖层,示例)
2648
+
2649
+ > **本文件只写差异**: 与基座 TEAM.md 同名的成员整体覆盖其方向/比例/状态;基座成员未列出的默认参与本迭代。
2650
+ > 全员名册见 .speccore/PROJECT/TEAM.md(全局基座,自动继承)。
2651
+
2652
+ | 成员 | 平台方向 | 投入比例 | 状态 |
2653
+ | :--- | :--- | :--- | :--- |
2654
+ | 李四 | admin-web | 100% | 在职 |
2655
+ | 赵六 | backend-api | 50% | 在职 |
2656
+
2657
+ > 说明:
2658
+ > - **平台方向**: 后台 / 小程序 / Web / APP,多个用逗号分隔(也可直接写标准端名)
2659
+ > - **投入比例**: 0-100%,用于 taskify 时自动分配和负荷均衡;写 0% 表示本迭代不参与
2660
+ > - **状态**: 在职(缺省)/ 出项目——出项目成员不参与自动填充;留空则继承基座状态。示例中赵六基座「出项目」,本迭代写「在职 50%」= 临时回归
2661
+ > - 编辑此文件后重新运行 taskify 即可更新默认分配
2662
+ `;
2663
+ await (0, fs_extra_1.writeFile)((0, path_1.join)(configDir, 'STAFFING-EXAMPLE.md'), staffingExample);
2478
2664
  // PROJECT.yaml 完整示例(多工程)
2479
2665
  const projectExample = `# PROJECT.yaml — 项目配置(由 CLI 自动生成,不建议手动编辑)
2480
2666
  # 如需修改,请编辑 CONSTITUTION.md 后运行 speccore update