@namewta/speculo 1.0.19 → 1.0.21

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 (194) hide show
  1. package/README.md +8 -7
  2. package/THIRD-PARTY-NOTICES.md +33 -0
  3. package/dist/src/agent-files.js +2 -2
  4. package/dist/src/agent-files.js.map +1 -1
  5. package/dist/src/agent-skills.d.ts +81 -0
  6. package/dist/src/agent-skills.js +530 -0
  7. package/dist/src/agent-skills.js.map +1 -0
  8. package/dist/src/cli.js +11 -3
  9. package/dist/src/cli.js.map +1 -1
  10. package/dist/src/config.js +5 -3
  11. package/dist/src/config.js.map +1 -1
  12. package/dist/src/doctor.js +7 -2
  13. package/dist/src/doctor.js.map +1 -1
  14. package/dist/src/index.d.ts +8 -0
  15. package/dist/src/index.js +23 -3
  16. package/dist/src/index.js.map +1 -1
  17. package/dist/src/manifest.d.ts +9 -0
  18. package/dist/src/manifest.js +45 -7
  19. package/dist/src/manifest.js.map +1 -1
  20. package/dist/src/refresh.js +40 -0
  21. package/dist/src/refresh.js.map +1 -1
  22. package/dist/src/structured.js +15 -4
  23. package/dist/src/structured.js.map +1 -1
  24. package/dist/src/transaction.d.ts +24 -3
  25. package/dist/src/transaction.js +191 -12
  26. package/dist/src/transaction.js.map +1 -1
  27. package/package.json +7 -4
  28. package/scripts/validate-skills.mjs +56 -0
  29. package/template/AGENTS.md +1 -1
  30. package/template/CLAUDE.md +1 -1
  31. package/template/canonical/canonical-specdev-goal-plan.md +156 -28
  32. package/template/canonical/canonical-specdev-grill-with-docs.md +153 -31
  33. package/template/canonical/canonical-specdev-spec.md +153 -27
  34. package/template/canonical/canonical-specdev-tickets.md +153 -27
  35. package/template/canonical/canonical-specdev-wayfinder.md +142 -27
  36. package/template/commands/retro.md +11 -9
  37. package/template/skills/archive-and-consolidate/SKILL.md +163 -7
  38. package/template/skills/archive-and-consolidate/references/cleanup-rules.md +1 -1
  39. package/template/skills/docs-sync/references/agents/claude-redirect.md +8 -8
  40. package/template/skills/docs-sync/references/agents/content-contract.md +1 -1
  41. package/template/skills/docs-sync/references/agents/manifest-discovery.md +7 -7
  42. package/template/skills/docs-sync/references/agents/role-classification.md +4 -4
  43. package/template/skills/docs-sync/references/agents-contract.md +1 -1
  44. package/template/skills/engineering-standards-builder/SKILL.md +149 -9
  45. package/template/skills/engineering-standards-builder/agents/openai.yaml +2 -0
  46. package/template/skills/engineering-standards-builder/manifest.txt +2 -1
  47. package/template/skills/engineering-standards-builder/references/rules/09-mechanical-guardrails.md +9 -0
  48. package/template/skills/engineering-standards-builder/scripts/validate-builder.mjs +4 -7
  49. package/template/skills/git-history-squash/SKILL.md +87 -11
  50. package/template/skills/git-history-squash/agents/openai.yaml +2 -0
  51. package/template/skills/optimize-codex-config/SKILL.md +71 -11
  52. package/template/skills/{speculo-retro/references/entry-procedure.md → retrospective/SKILL.md} +12 -8
  53. package/template/skills/{speculo-retro → retrospective}/references/friction-taxonomy.md +22 -13
  54. package/template/skills/{speculo-retro → retrospective}/references/issue-drafting-sop.md +10 -20
  55. package/template/skills/source-code-zip/SKILL.md +44 -8
  56. package/template/skills/source-code-zip/references/{entry-procedure.md → cli-reference.md} +0 -43
  57. package/template/skills/upstream-fork-sync/SKILL.md +71 -8
  58. package/template/skills/{writing-great-skills → writing-for-agents}/GLOSSARY.md +1 -1
  59. package/template/skills/writing-for-agents/SKILL.md +22 -0
  60. package/template/skills/writing-for-agents/agents/openai.yaml +2 -0
  61. package/template/skills/{writing-great-skills/references/entry-procedure.md → writing-for-agents/references/authoring-principles.md} +2 -9
  62. package/template/workflows/ops/D-project-deploy/D-project-deploy.md +1 -1
  63. package/template/workflows/ops/H-host-manage/H-host-manage.md +4 -0
  64. package/template/workflows/ops/H-host-manage/references/host-profiles.md +4 -0
  65. package/template/workflows/ops/I-initialize/I-initialize.md +1 -1
  66. package/template/workflows/ops/INDEX.md +2 -0
  67. package/template/workflows/ops/README.md +7 -3
  68. package/template/workflows/ops/S-server-connect/S-server-connect.md +5 -5
  69. package/template/workflows/ops/V-inventory-view/V-inventory-view.md +2 -0
  70. package/template/workflows/ops/common/CAPABILITIES.md +2 -0
  71. package/template/workflows/ops/common/USAGE.md +5 -5
  72. package/template/workflows/ops/common/WORKSPACE-USAGE.md +29 -2
  73. package/template/workflows/ops/common/examples/README.md +1 -1
  74. package/template/workflows/ops/common/examples/register.example.json +7 -3
  75. package/template/workflows/ops/common/examples/server-connection.example.json +11 -0
  76. package/template/workflows/ops/common/rules/deployment-layout.md +1 -1
  77. package/template/workflows/ops/common/rules/host-root-and-onboarding.md +47 -0
  78. package/template/workflows/ops/common/rules/persistence-and-secrets.md +1 -1
  79. package/template/workflows/ops/common/rules/research-and-decisions.md +8 -0
  80. package/template/workflows/ops/common/rules/server-onboarding.md +3 -3
  81. package/template/workflows/ops/common/rules/workspace-and-authorization.md +2 -2
  82. package/template/workflows/ops/common/schemas/fleet-view.schema.json +64 -0
  83. package/template/workflows/ops/common/schemas/host.schema.json +19 -0
  84. package/template/workflows/ops/common/schemas/plan.schema.json +57 -0
  85. package/template/workflows/ops/common/schemas/root-confirmation.schema.json +118 -0
  86. package/template/workflows/ops/common/schemas/server-connection.schema.json +67 -0
  87. package/template/workflows/ops/common/schemas/server-discovery.schema.json +171 -0
  88. package/template/workflows/ops/common/schemas/spec.schema.json +19 -0
  89. package/template/workflows/ops/common/schemas/status.schema.json +19 -0
  90. package/template/workflows/ops/common/templates/FLEET.html +1 -1
  91. package/template/workflows/ops/common/templates/HOST-README.md +3 -1
  92. package/template/workflows/ops/common/tests/test_ops.mjs +8 -11
  93. package/template/workflows/ops/common/tests/test_ops_bootstrap.mjs +101 -16
  94. package/template/workflows/ops/common/tests/test_ops_onboarding.mjs +225 -0
  95. package/template/workflows/ops/common/tests/test_ops_workspace.mjs +17 -8
  96. package/template/workflows/ops/common/tools/demo-local.mjs +4 -0
  97. package/template/workflows/ops/common/tools/opslib/agent.mjs +26 -0
  98. package/template/workflows/ops/common/tools/opslib/bootstrap.mjs +52 -26
  99. package/template/workflows/ops/common/tools/opslib/cli.mjs +1 -0
  100. package/template/workflows/ops/common/tools/opslib/core.mjs +1 -1
  101. package/template/workflows/ops/common/tools/opslib/docs.mjs +1 -0
  102. package/template/workflows/ops/common/tools/opslib/execution.mjs +4 -0
  103. package/template/workflows/ops/common/tools/opslib/fleet.mjs +26 -4
  104. package/template/workflows/ops/common/tools/opslib/host_recipes.mjs +34 -0
  105. package/template/workflows/ops/common/tools/opslib/model.mjs +6 -0
  106. package/template/workflows/ops/common/tools/opslib/onboarding.mjs +215 -0
  107. package/template/workflows/ops/common/tools/opslib/planner.mjs +3 -0
  108. package/template/workflows/ops/common/tools/opslib/transport.mjs +10 -6
  109. package/template/workflows/ops/common/tools/opslib/workspace_cli.mjs +20 -1
  110. package/template/workflows/ops/common/tools/server-discover.sh +65 -0
  111. package/template/workflows/ops/common/tools/validate-ops.mjs +1 -1
  112. package/template/workflows/ops/manifest.json +12 -5
  113. package/template/workflows/specdev/A-archive-and-consolidate/consolidation-interview.md +3 -3
  114. package/template/workflows/specdev/C-code-review/C-code-review.md +1 -1
  115. package/template/workflows/specdev/D-diagnose-bugs/D-diagnose-bugs.md +6 -0
  116. package/template/workflows/specdev/G-grill-with-docs/references/interview-procedure.md +6 -6
  117. package/template/workflows/specdev/I-implement/references/implementation-procedure.md +1 -1
  118. package/template/workflows/specdev/I-implement/tdd-rules.md +4 -0
  119. package/template/workflows/specdev/I-init-setup/config-template.json +5 -1
  120. package/template/workflows/specdev/INDEX.md +2 -2
  121. package/template/workflows/specdev/P-goal-plan/planning-modes.md +1 -1
  122. package/template/workflows/specdev/P-prototype/P-prototype.md +7 -3
  123. package/template/workflows/specdev/P-prototype/logic-protocol.md +11 -0
  124. package/template/workflows/specdev/P-prototype/logic-template.md +27 -0
  125. package/template/workflows/specdev/P-prototype/project-preview-protocol.md +9 -0
  126. package/template/workflows/specdev/R-retro/R-retro.md +26 -0
  127. package/template/workflows/specdev/R-retro/retro-template.md +27 -0
  128. package/template/workflows/specdev/R-review-architecture/references/selected-design.md +1 -1
  129. package/template/workflows/specdev/README.md +13 -2
  130. package/template/workflows/specdev/S-spec/S-spec.md +4 -0
  131. package/template/workflows/specdev/T-tickets/T-tickets.md +4 -0
  132. package/template/workflows/specdev/T-triage/T-triage.md +31 -25
  133. package/template/workflows/specdev/T-triage/capture-protocol.md +1 -1
  134. package/template/workflows/specdev/T-triage/ci-security-protocol.md +11 -0
  135. package/template/workflows/specdev/T-triage/intake-protocol.md +10 -4
  136. package/template/workflows/specdev/T-triage/pr-delivery-protocol.md +13 -0
  137. package/template/workflows/specdev/T-triage/pr-record-template.md +39 -0
  138. package/template/workflows/specdev/T-triage/publish-protocol.md +1 -1
  139. package/template/workflows/specdev/T-triage/queue-protocol.md +7 -0
  140. package/template/workflows/specdev/T-triage/reconcile-protocol.md +1 -1
  141. package/template/workflows/specdev/T-triage/references/issue-pr-policy.md +23 -0
  142. package/template/workflows/specdev/T-triage/references/release-authentication.md +9 -0
  143. package/template/workflows/specdev/T-triage/references/release-notes-injection.md +21 -0
  144. package/template/workflows/specdev/T-triage/references/workflow-yaml-reference.md +37 -0
  145. package/template/workflows/specdev/T-triage/release-preflight.md +13 -0
  146. package/template/workflows/specdev/T-triage/release-protocol.md +12 -0
  147. package/template/workflows/specdev/T-triage/release-recovery.md +18 -0
  148. package/template/workflows/specdev/T-triage/remote-operations.md +25 -0
  149. package/template/workflows/specdev/T-triage/scripts/github-transport.mjs +208 -0
  150. package/template/workflows/specdev/T-triage/source-template.md +7 -0
  151. package/template/workflows/specdev/T-triage/triage-run-template.md +34 -0
  152. package/template/workflows/specdev/T-triage/triage-template.md +4 -1
  153. package/template/workflows/specdev/common/rules/artifact-contract.md +7 -0
  154. package/template/workflows/specdev/common/rules/change-completion.md +6 -0
  155. package/template/workflows/specdev/common/rules/workflow-routing.md +6 -0
  156. package/template/workflows/specdev/common/rules/workflow-state-and-lifecycle.md +1 -1
  157. package/template/workflows/specdev/common/schemas/config.schema.json +137 -26
  158. package/template/workflows/specdev/common/schemas/logic-prototype.schema.json +62 -0
  159. package/template/workflows/specdev/common/schemas/pull-request.schema.json +90 -0
  160. package/template/workflows/specdev/common/schemas/retrospective.schema.json +58 -0
  161. package/template/workflows/specdev/common/schemas/triage-run.schema.json +149 -0
  162. package/template/workflows/specdev/common/schemas/triage.schema.json +117 -15
  163. package/template/workflows/specdev/common/tools/delivery-artifacts.mjs +95 -0
  164. package/template/workflows/specdev/common/tools/validate-specdev.mjs +60 -19
  165. package/template/workflows/specdev/runtime-contract.json +4 -2
  166. package/template/skills/archive-and-consolidate/references/entry-procedure.md +0 -178
  167. package/template/skills/docs-sync/references/entry-procedure.md +0 -3
  168. package/template/skills/engineering-standards-builder/references/entry-procedure.md +0 -154
  169. package/template/skills/git-history-squash/references/entry-procedure.md +0 -94
  170. package/template/skills/github-npm-ops/SKILL.md +0 -19
  171. package/template/skills/github-npm-ops/references/ci-and-security-ops.md +0 -178
  172. package/template/skills/github-npm-ops/references/entry-procedure.md +0 -25
  173. package/template/skills/github-npm-ops/references/failure-recovery.md +0 -123
  174. package/template/skills/github-npm-ops/references/issue-pr-triage.md +0 -227
  175. package/template/skills/github-npm-ops/references/issue-transport.md +0 -26
  176. package/template/skills/github-npm-ops/references/package-json-checklist.md +0 -171
  177. package/template/skills/github-npm-ops/references/preflight-checklist.md +0 -39
  178. package/template/skills/github-npm-ops/references/publish-detection.md +0 -68
  179. package/template/skills/github-npm-ops/references/release-notes-injection.md +0 -238
  180. package/template/skills/github-npm-ops/references/release-pipeline.md +0 -108
  181. package/template/skills/github-npm-ops/references/setup-npm-token.md +0 -63
  182. package/template/skills/github-npm-ops/references/troubleshooting-playbook.md +0 -293
  183. package/template/skills/github-npm-ops/references/version-bump-flow.md +0 -217
  184. package/template/skills/github-npm-ops/references/workflow-yaml-reference.md +0 -268
  185. package/template/skills/github-npm-ops/scripts/issue-transport.mjs +0 -227
  186. package/template/skills/optimize-codex-config/references/entry-procedure.md +0 -78
  187. package/template/skills/speculo-retro/SKILL.md +0 -19
  188. package/template/skills/upstream-fork-sync/references/entry-procedure.md +0 -78
  189. package/template/skills/writing-great-skills/SKILL.md +0 -23
  190. /package/template/skills/{writing-great-skills → writing-for-agents}/references/document-contract.md +0 -0
  191. /package/template/workflows/specdev/{G-grill-with-docs → common/rules}/adr-format.md +0 -0
  192. /package/template/workflows/specdev/{G-grill-with-docs → common/rules}/context-format.md +0 -0
  193. /package/template/workflows/specdev/{I-implement → common/rules}/design-it-twice.md +0 -0
  194. /package/template/workflows/specdev/{G-grill-with-docs/domain-modeling-rules.md → common/rules/domain-modeling.md} +0 -0
@@ -25,8 +25,10 @@ import {
25
25
  validateGoalMap, validateInitiative, resolveProjectSource,
26
26
  } from "./plan-contract.mjs";
27
27
 
28
+ import { validateRecord, validateRecords } from "./delivery-artifacts.mjs";
29
+
28
30
  const DOMAIN_SCHEMA_VERSION = 3;
29
- const CONFIG_SCHEMA_VERSION = 5;
31
+ const CONFIG_SCHEMA_VERSION = 6;
30
32
  const GOAL_PLAN_SCHEMA_VERSION = 6;
31
33
  const IMPLEMENTATION_MAP_SCHEMA_VERSION = 1;
32
34
  const IMPLEMENTATION_PLAN_SCHEMA_VERSION = 1;
@@ -50,6 +52,7 @@ const EXPECTED_WORKS = new Set([
50
52
  "P-goal-plan",
51
53
  "P-prototype",
52
54
  "R-review-architecture",
55
+ "R-retro",
53
56
  "S-spec",
54
57
  "T-tickets",
55
58
  "T-triage",
@@ -163,6 +166,8 @@ const VALID_STAGES = new Set([
163
166
  "goal-plan",
164
167
  "implement",
165
168
  "learn-change",
169
+ "retro",
170
+ "pr-delivery",
166
171
  "review",
167
172
  "prototype",
168
173
  "wayfinder",
@@ -927,7 +932,7 @@ function validateExecutionContractAssets(root) {
927
932
  configTemplate.planning.ui_design_max_candidates > 4 ||
928
933
  configTemplate.planning.ui_design_max_candidates < configTemplate.planning.ui_design_default_candidates
929
934
  ) {
930
- errors.push("config-template.json must define SpecDev config v5 with positive execution limits and valid UI design candidate bounds");
935
+ errors.push("config-template.json must define SpecDev config v6 with positive execution limits and valid UI design candidate bounds");
931
936
  }
932
937
  for (const obsolete of ["auto_commit", "worktree_for_parallel", "max_parallel"]) {
933
938
  if (JSON.stringify(configTemplate).includes(`\"${obsolete}\"`)) {
@@ -938,13 +943,13 @@ function validateExecutionContractAssets(root) {
938
943
  const configSchema = JSON.parse(readText(configSchemaPath));
939
944
  const limit = configSchema.properties?.execution?.properties?.max_implementation_agents;
940
945
  if (
941
- configSchema.$id !== "urn:speculo:specdev:config:v5" ||
946
+ configSchema.$id !== "urn:speculo:specdev:config:v6" ||
942
947
  configSchema.properties?.schema_version?.const !== CONFIG_SCHEMA_VERSION ||
943
948
  limit?.minimum !== 1 ||
944
949
  configSchema.properties?.execution?.properties?.max_integration_attempts?.minimum !== 1 ||
945
950
  configSchema.additionalProperties !== false
946
951
  ) {
947
- errors.push("config.schema.json must define the strict SpecDev config v5 execution contract");
952
+ errors.push("config.schema.json must define the strict SpecDev config v6 execution contract");
948
953
  }
949
954
 
950
955
  const goalPlanSchema = JSON.parse(readText(goalPlanSchemaPath));
@@ -1026,7 +1031,7 @@ function capabilityChecks(root) {
1026
1031
  "triage",
1027
1032
  [
1028
1033
  join(root, "T-triage", "T-triage.md"),
1029
- ["source.md", "intake", "reconcile", "publish", "publish.md", "specdev:published", "capture", "capture.md", "specdev:captured", "唯一权威", "远程写入为零"],
1034
+ ["intake", "reconcile", "publish", "capture", "capture.md", "pr-delivery", "ci-security", "release-preflight", "recover", "remote-operations.md"],
1030
1035
  ],
1031
1036
  ],
1032
1037
  [
@@ -1360,7 +1365,7 @@ function validateSource(path, expectedChange, errors) {
1360
1365
  return { path, meta, body };
1361
1366
  }
1362
1367
 
1363
- function validateTriage(path, expectedChange, errors) {
1368
+ function validateTriage(path, expectedChange, errors, historical = false) {
1364
1369
  if (!isFile(path)) {
1365
1370
  errors.push("missing triage artifact");
1366
1371
  return null;
@@ -1381,8 +1386,14 @@ function validateTriage(path, expectedChange, errors) {
1381
1386
  ];
1382
1387
  const missing = required.filter((key) => !(key in meta));
1383
1388
  if (missing.length) errors.push(`triage.md: missing keys ${JSON.stringify(missing)}`);
1384
- if (meta.schema_version !== 1 || meta.artifact !== "triage") {
1385
- errors.push("triage.md: artifact/schema_version must be triage/1");
1389
+ if ((meta.schema_version !== 2 && !(historical && meta.schema_version === 1)) || meta.artifact !== "triage") {
1390
+ errors.push("triage.md: artifact/schema_version must be triage/2; v1 is historical read-only");
1391
+ }
1392
+ if (meta.schema_version === 2) {
1393
+ if (!["needs-triage", "needs-info", "ready-for-agent", "ready-for-human", "wontfix"].includes(meta.disposition)) errors.push("triage.md: invalid disposition");
1394
+ if (!["pending", "passed", "failed", "unknown"].includes(meta.verification)) errors.push("triage.md: invalid verification");
1395
+ if (!Array.isArray(meta.remote_actions) || meta.remote_actions.some(v => typeof v !== "string")) errors.push("triage.md: remote_actions must be an array of locators");
1396
+ if (meta.disposition === "ready-for-agent" && meta.verification !== "passed") errors.push("triage.md: ready-for-agent requires passed verification");
1386
1397
  }
1387
1398
  if (meta.change !== expectedChange) errors.push("triage.md: change must equal directory name");
1388
1399
  if (!VALID_TRIAGE_MODE.has(meta.mode)) errors.push(`triage.md: invalid mode ${meta.mode}`);
@@ -1403,8 +1414,15 @@ function validateTriage(path, expectedChange, errors) {
1403
1414
  errors.push(`triage.md: invalid publish_action ${meta.publish_action}`);
1404
1415
  }
1405
1416
  meta.publish_action = publishAction;
1406
- if (!String(meta.source ?? "").includes("/source.md</Path>")) {
1407
- errors.push("triage.md: source must reference the local source.md artifact");
1417
+ const prefix = `<Path>{roots.state}/specdev/changes/${expectedChange}/`;
1418
+ const sourceRef = typeof meta.source === "string" ? meta.source.replaceAll("{change}", expectedChange) : "";
1419
+ const localSource = sourceRef.startsWith(prefix) && sourceRef.endsWith("</Path>") ? sourceRef.slice(prefix.length, -7) : null;
1420
+ if (!localSource || !/^(?:source\.md|sources\/SRC-[0-9]{3,}\.md)$/.test(localSource)) errors.push("triage.md: source must reference a local source artifact in this change");
1421
+ else if (localSource !== "source.md") {
1422
+ const selected = validateSource(join(dirname(path),localSource),expectedChange,errors);
1423
+ const previous = typeof selected?.meta.supersedes_source === "string" ? selected.meta.supersedes_source.replaceAll("{change}",expectedChange) : "";
1424
+ const previousLocal = previous.startsWith(prefix) && previous.endsWith("</Path>") ? previous.slice(prefix.length,-7) : "";
1425
+ if (!/^(?:source\.md|sources\/SRC-[0-9]{3,}\.md)$/.test(previousLocal) || previousLocal === localSource || !isFile(join(dirname(path),previousLocal))) errors.push("triage.md: evolved snapshot requires an existing distinct supersedes_source in this change");
1408
1426
  }
1409
1427
  for (const heading of ["## 当前判定", "## 未知项", "## 路由", "## 外部动作"]) {
1410
1428
  if (!body.includes(heading)) errors.push(`triage.md: missing '${heading}'`);
@@ -1703,11 +1721,18 @@ function validatePrototypes(change, required, errors) {
1703
1721
  continue;
1704
1722
  }
1705
1723
  if (!entry.isDirectory()) {
1706
- errors.push(`${label}: prototypes may only contain UI-NNN design directories`);
1724
+ errors.push(`${label}: prototypes may only contain UI-NNN or LOGIC-NNN directories`);
1725
+ continue;
1726
+ }
1727
+ if (/^LOGIC-\d{3,}$/.test(entry.name)) {
1728
+ const logic = validateRecord(join(entryPath, "logic.md"), "logic-prototype", parseFrontmatter, basename(change));
1729
+ errors.push(...logic.errors);
1730
+ if (logic.meta.status === "ready" && logic.errors.length === 0) readyCount++;
1731
+ paths.push(join(entryPath, "logic.md"));
1707
1732
  continue;
1708
1733
  }
1709
1734
  if (!/^UI-\d{3,}$/.test(entry.name)) {
1710
- errors.push(`${label}: prototype design directory must use UI-NNN`);
1735
+ errors.push(`${label}: prototype design directory must use UI-NNN or LOGIC-NNN`);
1711
1736
  continue;
1712
1737
  }
1713
1738
 
@@ -1749,7 +1774,7 @@ function validatePrototypes(change, required, errors) {
1749
1774
  }
1750
1775
  }
1751
1776
  if (required && readyCount === 0) {
1752
- errors.push("prototype stage requires at least one ready UI design package");
1777
+ errors.push("prototype stage requires at least one ready UI or logic design package");
1753
1778
  }
1754
1779
  return paths;
1755
1780
  }
@@ -3180,7 +3205,7 @@ function validateParentImplementation(change, parentStatus, stage, errors, warni
3180
3205
  const configuredAgents = positiveConfigLimit(config, "max_implementation_agents", 0);
3181
3206
  const configuredAttempts = positiveConfigLimit(config, "max_integration_attempts", 0);
3182
3207
  if (!config || config.schema_version !== CONFIG_SCHEMA_VERSION || configuredAgents === 0 || configuredAttempts === 0) {
3183
- errors.push("implementation-plan.md: SpecDev config v5 with positive execution limits is required");
3208
+ errors.push("implementation-plan.md: SpecDev config v6 with positive execution limits is required");
3184
3209
  } else {
3185
3210
  if (plan.meta.implementation_agent_limit > configuredAgents) {
3186
3211
  errors.push(`implementation-plan.md: implementation_agent_limit ${plan.meta.implementation_agent_limit} exceeds config max_implementation_agents ${configuredAgents}`);
@@ -3291,7 +3316,7 @@ function validateChange(change, stage = null, repoRoot = null) {
3291
3316
  : null;
3292
3317
  const triagePath = join(change, "triage.md");
3293
3318
  const triage = isFile(triagePath) || sourceRequired
3294
- ? validateTriage(triagePath, basename(change), errors)
3319
+ ? validateTriage(triagePath, basename(change), errors, changeStatus?.archived === true && stage === null)
3295
3320
  : null;
3296
3321
  const publishPath = join(change, "publish.md");
3297
3322
  const publishRequired = Boolean(
@@ -3307,8 +3332,17 @@ function validateChange(change, stage = null, repoRoot = null) {
3307
3332
  validateReviews(change, stage === "review", errors);
3308
3333
  validatePrototypes(change, stage === "prototype", errors);
3309
3334
  validateChangeLearning(change, stage === "learn-change", errors);
3310
-
3311
- const specRequired = new Set(["spec", "tickets", "goal-plan", "implement", "complete"]).has(stage) && !isParentImplementation;
3335
+ const retro = validateRecords(change, "retrospective", parseFrontmatter);
3336
+ const prs = validateRecords(change, "pull-request", parseFrontmatter);
3337
+ errors.push(...retro.errors, ...prs.errors);
3338
+ if (stage === "retro" && !retro.records.some(r => r.meta.status === "completed")) errors.push("retro stage requires a completed retrospective");
3339
+ if (stage === "pr-delivery" && !prs.records.length) errors.push("pr-delivery stage requires a PR record");
3340
+ if (stage === "complete" && prs.records.some(r => r.meta.requested === true && (["planned", "failed"].includes(r.meta.status) || (r.meta.delivery_target === "ready" && r.meta.status === "draft")))) errors.push("complete stage cannot archive pending PR delivery");
3341
+ const retroOnly = retro.records.length > 0 && retro.errors.length === 0 && retro.records.every(r => r.meta.status === "completed") &&
3342
+ changeStatus?.works_run?.includes("specdev/retro") && changeStatus.works_run.every(w => ["specdev/retro", "specdev/triage"].includes(w)) &&
3343
+ !["spec.md", "ticket", "tickets-map.md", "goal-plan.md", "implementation-map.md", "implementation-plan.md", "evidence"].some(p => existsSync(join(change,p))) && !changeStatus.worktrees?.length;
3344
+
3345
+ const specRequired = new Set(["spec", "tickets", "goal-plan", "implement", "complete"]).has(stage) && !isParentImplementation && !retroOnly;
3312
3346
  const specPath = join(change, "spec.md");
3313
3347
  const spec = isFile(specPath) || specRequired
3314
3348
  ? validateSpec(specPath, errors, warnings)
@@ -3565,7 +3599,7 @@ function validateChange(change, stage = null, repoRoot = null) {
3565
3599
  }
3566
3600
  if (
3567
3601
  stage === "complete" &&
3568
- !ticketFiles.length &&
3602
+ !ticketFiles.length && !retroOnly &&
3569
3603
  !isFile(join(change, "implementation-map.md")) &&
3570
3604
  !isFile(join(change, "evidence", "direct-spec.md"))
3571
3605
  ) {
@@ -3612,7 +3646,7 @@ function printResults(errors, warnings) {
3612
3646
  }
3613
3647
 
3614
3648
  function usage() {
3615
- console.error("Usage: node validate-specdev.mjs [--stage <stage>] [--repo <project-root>] <change-directory> | --self-check | --capture <capture.md>");
3649
+ console.error("Usage: node validate-specdev.mjs [--stage <stage>] [--repo <project-root>] <change-directory> | --self-check | --capture <capture.md> | --triage-run <TRI-NNN.md>");
3616
3650
  return 2;
3617
3651
  }
3618
3652
 
@@ -3621,6 +3655,7 @@ function main(argv) {
3621
3655
  let stage = null;
3622
3656
  let repoRoot = null;
3623
3657
  let capturePath = null;
3658
+ let triageRunPath = null;
3624
3659
  const positional = [];
3625
3660
  for (let index = 0; index < argv.length; index += 1) {
3626
3661
  const arg = argv[index];
@@ -3636,6 +3671,8 @@ function main(argv) {
3636
3671
  index += 1;
3637
3672
  } else if (arg.startsWith("--repo=")) {
3638
3673
  repoRoot = arg.slice("--repo=".length);
3674
+ } else if (arg === "--triage-run") {
3675
+ triageRunPath = argv[++index] ?? null;
3639
3676
  } else if (arg === "--capture") {
3640
3677
  capturePath = argv[index + 1] ?? null;
3641
3678
  index += 1;
@@ -3648,6 +3685,10 @@ function main(argv) {
3648
3685
  }
3649
3686
  }
3650
3687
  if (stage !== null && !VALID_STAGES.has(stage)) return usage();
3688
+ if (triageRunPath) {
3689
+ if (selfCheckRequested || positional.length || stage !== null || capturePath || repoRoot) return usage();
3690
+ return printResults(validateRecord(resolve(triageRunPath), "triage-run", parseFrontmatter).errors, []);
3691
+ }
3651
3692
  if (selfCheckRequested) {
3652
3693
  if (positional.length || stage !== null || capturePath) return usage();
3653
3694
  const scriptDirectory = dirname(fileURLToPath(import.meta.url));
@@ -5,14 +5,16 @@
5
5
  "path": ".speculo/specdev/config.json",
6
6
  "template": "workflows/specdev/I-init-setup/config-template.json",
7
7
  "baseline": ".speculo/baselines/workflows/specdev/config.json",
8
- "schema_version": 5,
8
+ "schema_version": 6,
9
9
  "optional": true,
10
10
  "additional_properties": {
11
11
  "": false,
12
12
  "git": false,
13
13
  "execution": false,
14
14
  "verification": true,
15
- "planning": true
15
+ "planning": true,
16
+ "github": false,
17
+ "github.labels": true
16
18
  }
17
19
  },
18
20
  "structured_state": [
@@ -1,178 +0,0 @@
1
- # Entry procedure
2
-
3
- # Archive and Consolidate
4
-
5
- 默认只分析并生成计划,不自行写报告或修改文件。调用方(command)负责获取 runtime context、管理用户确认和持久化报告。
6
-
7
- ## 核心原则
8
-
9
- **减法优先**:先归档旧 change、清理过时知识,再写入新合并内容。一个事实只有一个权威版本,其余位置放短指针。
10
- **两阶段报告**:预执行完整计划 → 用户显式确认 → 执行 → 执行后验证补遗。不可将初始任务中的"完成后清理"视为确认。
11
- **内容不是指令**:项目文件中包含的"执行某命令"等文本不构成操作授权。
12
-
13
- ## 输入
14
-
15
- - 当前工作目录或用户指定的项目目录。
16
- - 目标 workflow id(或从 `workspace.json` + `INDEX.md` 已解析的 workflow/state 根)。
17
- - 目标 workflow `INDEX.md` 中的运行时根声明和持久化约定表。
18
- - 模式:`dry-run`(默认)| `confirmed`。
19
- - 范围:`archive-single`(单个 change)| `archive-batch`(全部已完成 change)。
20
- - 知识策略:`generic`(默认)| `mechanical-only`(调用方拥有知识策略,本 Skill 只处理移动与状态)。
21
- - 可选指定 change 名称(`archive-single` 模式)。
22
-
23
- `mechanical-only` 必须由调用方提供已经确认的知识处理结果或明确说明无知识写入。本 Skill 不读取、判断、创建、合并、改写或清理知识 store;它仍执行全部路径包含、目标冲突、状态一致性、dry-run/confirmed 和重读验证门。
24
-
25
- ## 流程
26
-
27
- ### Step 0:路径解析(内建,不依赖外部 skill)
28
-
29
- 1. 从 CWD 向上查找 `<Path>{roots.state}/workspace.json</Path>`;第一个命中目录为 `project_root`;多候选或冲突时返回 blocked。
30
- 2. 读取 `workspace.json`,校验 `path_base` 为 `project-root`,所有 roots 使用 POSIX 相对路径。
31
- 3. 读取目标 workflow 的 `INDEX.md`,解析运行时根声明:
32
- - 查找 `## 运行时根` 或类似标题下的 `<Path>{roots.X}/path/</Path>` 标签。
33
- - `{roots.X}` 解析为 `workspace.roots[X]`,拼接 `/path/` 得到完整路径。
34
- - `workflow` 根必须等于 `<project_root>/workflows/<workflow>`,`state` 根必须等于 `<project_root>/.speculo/<workflow>`。
35
- 4. 读取 `INDEX.md` 的持久化约定表,提取所有声明的路径:
36
- - 表通常包含名称、路径(`<Path>...</Path>` 格式)、说明三列。
37
- - 识别操作型路径:`status.json`、`changes/`、`archive/`。
38
- - 识别知识型 store:`adr/`、`context/` 及任何标注为"永久"的目录(其内容在 change 完成后提升至此)。
39
- - 每个路径解析为完整的项目相对路径。
40
- 5. 派生固定路径:
41
- - `changes_root = state_root/changes`
42
- - `archive_root = state_root/archive`
43
- - `commands_root` 必须解析为 `<Path>{roots.state}/commands</Path>`
44
- - `{roots.commands}` 是命令定义根,记为 `commands_def_root`,不是报告根
45
- - 「不放进 workflow 私有 state root」只禁止写入 `<Path>{roots.state}/{workflow}/</Path>`(含 `specdev` / `learning` / `ops` / `person`)。它不禁止写入 `{roots.state}` 本身,更不得把报告退回 `{roots.commands}`
46
- - POSIX 规范化后,若 `commands_root` 等于 `{roots.commands}`,或任何报告路径落在 `{roots.commands}/archive-and-consolidate/` → **blocked,不写文件**
47
- - 写入 `path_context` 前再次核对 `commands_root` 等于 `<Path>{roots.state}/commands</Path>`
48
- 6. 读取 `<Path>{roots.config}</Path>`(若存在);不存在时静默降级为默认值(`language: "en"`、`confirm_before_external_write: true`)。
49
- 7. 对每个已解析路径执行真实路径包含检查;符号链接逃逸或不存在的静态引用阻塞。
50
- 8. 读取 `status.json`;扫描 changes 时校验 change 名称格式 `^\d{4}-\d{2}-\d{2}-[a-z0-9]+(-[a-z0-9]+)*$`,无日期前缀的历史 change 标注遗留但不阻塞。
51
-
52
- ### Step 1:扫描知识 stores(仅 `generic`)
53
-
54
- 1. 从 `INDEX.md` 持久化约定表中提取所有知识型 store(名称含"永久"或在 `adr/`、`context/` 等公认目录下)。
55
- 2. 验证 store 路径在 state 根下真实存在。若不存在:
56
- - `adr/` 和 `context/` 目录首次写入时自动创建(lazy)。
57
- - 其他非标准 store 标注为 `missing` 并跳过写入,仍可审计。
58
- 3. 映射 store 到规范目标:
59
- - `adr/` — 架构决策记录目录,每个决策一个 `NNNN-slug.md` 文件。
60
- - `context/` — 领域词汇表目录,存放提升后的术语定义文件。
61
- - 若 INDEX.md 声明了其他知识 store,纳入合并范围。
62
- 4. 若未声明任何知识 store,合并阶段跳过(仅归档+基本清理)。
63
-
64
- ### Step 2:扫描已完成 changes
65
-
66
- 1. 枚举 `changes_root/` 下所有目录,读取各自的 `.status.json`。
67
- 2. 筛选 `change_status: completed` 的 change。
68
- 3. 对每个候选 change 收集 `.status.json`,以及实际存在的 source、triage、diagnosis、Spec、Tickets Map、Goal Plan、Evidence、reviews、prototypes、questionnaires、ADR、LOG、CONTEXT 和 workflow 自定义产物;不存在的可选项静默跳过。
69
- 4. `archive-single` 模式用户选择一个;`archive-batch` 全选所有 completed。
70
-
71
- ### Step 3:生成归档计划
72
-
73
- 读取 `references/archive-rules.md`,执行:
74
-
75
- 1. 对每个候选 change 执行共同预检:名称格式、`.status.json` 可解析、源存在、目标不存在、状态与 `status.json` 一致。
76
- 2. 生成 `changes_root/<change>` → `archive_root/<YYYY-MM>/<change>` 映射(YYYY-MM 从 change 名称提取)。
77
- 3. **批量原子性**:所有预检通过 → ready;任一失败 → 整批 blocked,报告具体阻塞原因。
78
- 4. 生成计划表格(使用 `assets/archive-plan-template.md` 格式)。
79
-
80
- ### Step 4:生成知识合并计划(仅 `generic`)
81
-
82
- 读取 `references/consolidation-rules.md` 和 `references/knowledge-graduation.md`,执行:
83
-
84
- 1. 对每个 change 的知识产物分类,应用毕业标准:
85
- - **稳定机制**?→ 提取;**重复教训**(>1 change 涉及)?→ 提取;**接手者必知**?→ 提取
86
- - 否则 → `ephemeral`(留在归档 change,不提取)
87
- 2. 对通过毕业标准的知识,映射目标 store:
88
- - 架构决策 → `adr/<NNNN>-<slug>.md`(自动分配序号)
89
- - 领域术语 → `context/` 目录(合并到现有术语文件或创建新条目)
90
- - 如有 INDEX.md 声明的其他知识 store,按类型映射
91
- 3. 对每个目标检查冲突:重复术语、已存在同主题 ADR、矛盾规则。
92
- 4. 对冲突项标记 `needs-confirmation`,提供双方版本和建议。
93
- 5. 生成合并计划表格(使用 `assets/consolidation-plan-template.md` 格式)。
94
-
95
- ### Step 5:生成清理候选清单(仅 `generic`)
96
-
97
- 读取 `references/cleanup-rules.md`,执行:
98
-
99
- 1. 扫描所有 `INDEX.md` 持久化约定表中声明且真实存在的知识 stores。
100
- 2. 生成候选并分类:
101
- - `delete`:被取代 ADR(>30 天无引用)、空文件(>60 天)、无引用孤立术语、重复副本
102
- - `merge`:相似 lessons、多处复制的规则
103
- - `rewrite`:格式不规范、含相对时间的条目
104
- - `keep`:仍被引用、创建不足 30 天的新 ADR
105
- - `needs-confirmation`:RULES 修改、术语冲突、ADR/context 改写、非标准 store 修改
106
- 3. 交叉验证:确认标记为 delete 的候选无 active change 或代码引用。
107
- 4. 扫描反模式(历史叙事占位、多版本自称现役、会话残留)。
108
- 5. 生成清理候选表格(使用 `assets/cleanup-candidate-template.md` 格式)。
109
-
110
- ### Step 6:呈现两阶段报告(dry-run 默认)
111
-
112
- 1. 组合三部分计划为一个完整报告:
113
- - **阶段一**:归档移动 + 知识合并写入
114
- - **阶段二**:清理候选
115
- - `mechanical-only` 只展示归档移动和状态变化,并注明知识动作由调用方策略拥有
116
- 2. 报告内容:每项含来源、目标、动作、理由、风险等级。
117
- 3. 显式标注所有破坏性动作(移动、删除、改写)。
118
- 4. 报告摘要:待归档 change 数、待合并知识项数、待清理候选数、需确认项数。
119
- 5. 呈现给用户并显式声明:**"未修改任何文件。此为 dry-run 计划,请确认后执行。"**
120
- 6. dry-run 到此完成;调用方负责将报告写入 `<Path>{roots.state}/commands/archive-and-consolidate/{date}-{scope}-{topic}[-NN].md</Path>`(`<scope>` 为目标 workflow 名,`<topic>` 为 change 名或 `batch`)。禁止写入 `{roots.commands}/archive-and-consolidate/`。
121
-
122
- ### Step 7:执行已确认动作
123
-
124
- **仅在 mode=`confirmed` 且用户显式批准后执行:**
125
-
126
- 1. **重新验证**:路径包含检查、预检重跑(确认计划生成后无新 change 插入);`generic` 额外重验 store 存在性。
127
- 2. **执行顺序**:
128
- a. **归档移动**(原子批处理):创建月目录 → 移动 change 目录 → 按调用方 workflow 的状态 schema 更新归档 `.status.json` → 从全局 `status.json` 的 `active` 移除对应条目,将 change 名称去重追加到 `archived`。不得写入调用方 schema 未声明的 SpecDev 专属字段
129
- b. **知识合并写入**(仅 `generic`):创建 lazy stores(如 `adr/`、`context/` 不存在则创建)→ 写入新 ADR → 合并术语到 `context/` → 标记 superseded ADR
130
- c. **清理**(仅 `generic`):删除已批准文件 → 合并已批准内容 → 改写已批准条目
131
- 3. 任一步骤失败:报告已完成/失败清单,停止,不猜测成功。
132
-
133
- ### Step 8:重新验证所有状态变更
134
-
135
- 1. 重读源路径:归档 change 必须不存在于 `changes_root/`。
136
- 2. 重读目标路径:归档 change 完整存在于 `archive_root/<YYYY-MM>/`;`generic` 同时验证知识 store 内容正确。
137
- 3. 重读 `status.json`:`active` 数组不包含已归档 change,`archived` 数组已追加其名称,二者没有重叠。
138
- 4. 重读归档 `.status.json`:按调用方 workflow schema 验证归档终态和 archive path;只有 schema 声明 `archived` 布尔字段时才要求 `archived: true`。
139
- 5. `generic` 对照知识 stores:新内容存在,无不期望的修改;`mechanical-only` 验证知识路径未被本 Skill 修改。
140
- 6. 任一不一致 → `blocked`,报告具体差异;全部通过 → `verified`。
141
- 7. 验证结果作为补遗追加到原 dry-run 报告。
142
-
143
- ## 输出
144
-
145
- ```
146
- {
147
- mode: "dry-run" | "executed",
148
- scope: "archive-single" | "archive-batch",
149
- knowledge_policy: "generic" | "mechanical-only",
150
- path_context: { project_root, workflow_root, state_root, changes_root, archive_root, commands_root }, // commands_root === {roots.state}/commands, never {roots.commands}
151
- knowledge_stores: [{ name, path, exists }],
152
- archive_plan: [{ source, target, status: "ready" | "blocked" | "moved" | "failed", notes }],
153
- consolidation_plan: [{ source_change, target_store, action: "create" | "merge" | "append", content_summary, graduation_criterion, status }],
154
- cleanup_candidates: [{ file_path, classification: "delete" | "merge" | "rewrite" | "keep" | "needs-confirmation", rationale, risk }],
155
- conflicts_needing_confirmation: [{ item, options, recommendation }],
156
- verification: { re_read_passed: boolean, inconsistencies: [], verdict: "verified" | "blocked" }
157
- }
158
- ```
159
-
160
- ## 完成标准
161
-
162
- - `generic` 已扫描所有 `INDEX.md` 声明的知识 stores;`mechanical-only` 未读取或修改知识内容。
163
- - 每个归档 change:源不存在、目标完整、status.json 已更新。
164
- - `generic` 的每次合并写入已解决或标记冲突,目标 store 在 state 根内;每个清理动作完成路径包含验证且无跨 workflow 修改。
165
- - 未确认或 mode=`dry-run` 时无文件系统修改。
166
- - 执行后重读验证通过或不一致已记录。
167
- - `path_context.commands_root` 等于 `<Path>{roots.state}/commands</Path>`,不等于 `{roots.commands}`。
168
- - 本 skill 未自行选择报告路径或自行持久化。
169
-
170
- ## 渐进披露
171
-
172
- - `references/archive-rules.md`:构建归档计划(Step 3)或执行归档移动(Step 7)时读取。
173
- - `references/consolidation-rules.md`:构建合并计划(Step 4)或写入知识 stores(Step 7)时读取。
174
- - `references/knowledge-graduation.md`:判定知识是否值得提取(Step 4)时读取。
175
- - `references/cleanup-rules.md`:生成清理候选(Step 5)或执行清理(Step 7)时读取。
176
- - `assets/archive-plan-template.md`:生成归档计划报告时读取。
177
- - `assets/consolidation-plan-template.md`:生成合并计划报告时读取。
178
- - `assets/cleanup-candidate-template.md`:生成清理候选报告时读取。
@@ -1,3 +0,0 @@
1
- # Compatibility pointer
2
-
3
- The per-run procedure now lives in [SKILL.md](../SKILL.md). Existing callers may follow this pointer; new callers load SKILL.md directly. This file grants no authorization and does not duplicate the procedure. Choose audit/update/commit before reading mode-specific references.
@@ -1,154 +0,0 @@
1
- # Entry procedure
2
-
3
- # Engineering Standards Builder
4
-
5
- 本 Skill 只在用户明确调用时运行。它不会在新项目中自动启动,也不把 Builder 自带的通用建议直接复制成项目规范。
6
-
7
- 目标是先理解当前项目真实的代码、目录、配置、测试、CI 与模板,再生成一组可长期复用的项目专属 Skill:一个稳定的工程规范路由入口,以及零个或多个有独立触发价值的领域 Skill。
8
-
9
- ```text
10
- 项目事实 + 用户指定的重点范围 + 已确认目标
11
- -> 证据审计与冲突收敛
12
- -> 最小充分 Skill Set
13
- -> .agents/skills/
14
- ```
15
-
16
- ## 产物与所有权
17
-
18
- 始终生成根路由:
19
-
20
- ```text
21
- .agents/skills/
22
- ├── engineering-standards/
23
- │ ├── SKILL.md
24
- │ ├── generated-skill-set.json
25
- │ └── references/project/
26
- │ ├── 00-project-profile.md
27
- │ ├── 01-module-map.md
28
- │ ├── 02-decisions-and-exceptions.md
29
- │ ├── 03-skill-map.md
30
- │ ├── 04-source-and-template-map.md
31
- │ └── review-checklist.md
32
- └── <optional-domain-skill>/
33
- ├── SKILL.md
34
- └── references/...
35
- ```
36
-
37
- `engineering-standards` 是规范权威与路由器;领域 Skill 负责可独立触发的实现导航,不重复定义冲突规则。`generated-skill-set.json` 只登记 Builder 拥有的 `.agents/skills/*` 路径。刷新时不得改动或删除清单之外的 Skill。
38
-
39
- ## 最小原则
40
-
41
- - 不按语言、目录或 Agent 数量机械拆 Skill。
42
- - 能由根路由和少量 references 清楚表达时,不新增领域 Skill。
43
- - 没有项目证据的规则不生成;Builder references 只提供审计维度与 fallback。
44
- - 不复制项目源码、FM 模板或脚手架正文;引用其真实路径并说明适用条件、集成步骤和验证方式。
45
- - 不新增配置文件、参数、时间戳、hash 或模型元数据来制造形式化负担。
46
- - 扫描深度、文件数和字节限制只是脚本内部资源保护,不是用户需要决策的项目规范。
47
-
48
- ## 执行流程
49
-
50
- ### 1. 确定项目根与学习范围
51
-
52
- 从用户当前工作目录、Git/Workspace 边界和用户指定的代码或目录确定真实项目根。记录需要重点学习的模块、代码、目录、模板或脚手架;未指定时覆盖所有可编辑模块。
53
-
54
- 读取现有 `AGENTS.md`、`CLAUDE.md`、贡献文档、架构文档和 `.agents/skills/`,但将它们视为待验证证据。识别 generated、vendor、build、cache、fixture 与冻结目录。发现已有 `generated-skill-set.json` 时进入 refresh;只有 legacy `engineering-standards` 时,在计划中声明接管该根 Skill,其他现有 Skill 一律视为非 Builder 所有。
55
-
56
- 冲突优先级见 [治理与证据优先级](rules/00-governance-and-precedence.md),路径和 scope 见 [证据、拓扑与作用域](rules/02-evidence-topology-and-scope.md)。本阶段只读。
57
-
58
- **完成标准**:项目根、重点范围、排除范围、现有规范和 Builder 写入边界明确。
59
-
60
- ### 2. 建立确定性事实基线
61
-
62
- 运行扫描器并捕获 stdout;默认不在项目中持久化 inventory:
63
-
64
- ```bash
65
- node <skill-root>/scripts/discover-project.mjs --root <project-root> --pretty
66
- ```
67
-
68
- 扫描合同见 [项目发现合同](rules/01-project-discovery.md)。扫描器只提供拓扑基线,不能替代源码审计。继续读取真实 manifest/build 配置、CI 命令、公共入口、代表性实现、测试、消费者与项目模板。
69
-
70
- **完成标准**:每个可编辑模块有路径、技术栈、入口、质量门禁和证据;扫描限制、冲突与未知项已记录。
71
-
72
- ### 3. 用 Agent Team 分域取证
73
-
74
- 当运行环境支持 Agent Team 且存在两个以上可独立审计的证据域时,默认由 leader 并行派发只读 scout。证据域按项目真实边界划分,例如架构与公共 API、后端、前端、公共复用、测试与 CI、FM/脚手架;不得套用固定角色表。
75
-
76
- leader 是唯一写入者。每个 scout 必须返回同一份精简证据合同:
77
-
78
- ```text
79
- Scope
80
- Observed capability
81
- Canonical source paths
82
- Mature implementations
83
- Template paths
84
- Consumers and tests
85
- Applicable conditions
86
- Legacy/counterexamples
87
- Conflicts/unknowns
88
- Recommended skill boundary
89
- ```
90
-
91
- leader 必须复读高影响路径,检查跨域冲突,并把同一事实的重复报告合并。Agent Team 不可用或任务不可合理拆分时,leader 按相同合同顺序审计;结果标准不变。
92
-
93
- **完成标准**:重要规范均有真实路径、消费者或测试支撑;反例、旧实现和未知项没有被“多数模式”掩盖。
94
-
95
- ### 4. 收敛规范与 Skill 边界
96
-
97
- 先识别项目已经声明的 canonical 模板或代码样板,例如 `docs/fm/**`、scaffold、generator assets。模板与成熟代码冲突时,判断它是目标模板、过期模板还是仅负责骨架,并记录 current、target 与 migration;不得静默任选一方。
98
-
99
- 只有同时满足以下条件才创建领域 Skill:
100
-
101
- 1. 有可独立描述的触发场景;
102
- 2. 会在多次开发中复用;
103
- 3. 有充分的项目源码、模板、测试或配置证据;
104
- 4. 与根路由或其他领域 Skill 边界清晰;
105
- 5. 独立后能明显减少无关上下文。
106
-
107
- 否则内容留在 `engineering-standards`。领域 Skill 名称来自项目语义,不使用固定列表或固定数量。高影响未知项按 [决策收敛合同](rules/03-interview-and-decisions.md) 询问;用户已授权直接生成时,将无法安全推断的事项记为 `pending-decision`。
108
-
109
- 只读取与项目事实匹配的 [通用规则索引](rules/README.md)、[TypeScript/JavaScript](typescript/README.md)、[Java](java/README.md)、[Go](go/README.md) 或 [Rust](rust/README.md) references。内置语言包和 [未内置语言 fallback](rules/16-language-adapter-contract.md) 是检查清单,不是高于项目代码的规范来源。
110
-
111
- **完成标准**:每个生成 Skill 都有独立价值和证据边界;没有为了覆盖目录或技术栈而过度拆分。
112
-
113
- ### 5. 计划、生成与刷新
114
-
115
- 先展示精简计划:模块与证据摘要、Skill Map、每个 Skill 的来源路径、保留/更新/新增/删除项、冲突决策和验证命令。用户已在当前请求中授权实施时,展示后直接执行。
116
-
117
- 按 [Skill Set 生成合同](rules/14-generation-contract.md) 和 [模板索引](../templates/README.md) 生成。所有项目引用使用项目根相对路径,并说明:何时读取、它负责什么、输出位置、需要哪些手工集成、运行什么验证。
118
-
119
- 先准备完整候选内容并校验,再替换 Builder 拥有的文件。刷新规则:
120
-
121
- - 只更新或删除旧 `generated-skill-set.json` 登记的路径;
122
- - 名称与未登记 Skill 冲突时停止覆盖并重新命名或询问;
123
- - 保留仍有效的用户决策、例外和项目特有知识;
124
- - 删除或重命名必须在计划中显式列出;
125
- - 候选验证失败时保留旧 Skill Set;发布后验证失败时恢复旧内容;
126
- - 相同项目事实与决策重复运行应无无意义 diff。
127
-
128
- **完成标准**:根路由、领域 Skill、项目引用与所有权清单一致,清单外 Skill 未发生变化。
129
-
130
- ### 6. 验证与报告
131
-
132
- 运行:
133
-
134
- ```bash
135
- node <skill-root>/scripts/validate-generated-skill.mjs --root <project-root> --strict
136
- ```
137
-
138
- 再按 [验证合同](rules/15-validation-contract.md) 执行项目已存在且本次允许的质量门禁。不得通过删除测试、放宽编译配置或扩大例外获取通过。
139
-
140
- 最终报告生成/更新/保留/删除的 Skill,关键证据与模板路径,运行命令及退出码,未验证项、待确认决策和临时例外。
141
-
142
- **完成标准**:所有权、frontmatter、Skill 路由、项目内引用、选择性适配和规则字段通过;项目门禁通过或留下可复现阻塞证据。
143
-
144
- ## Builder 自校验
145
-
146
- 维护本 Skill 时读取 [fixture 合同](../examples/README.md),并运行:
147
-
148
- ```bash
149
- node scripts/sync-manifest.mjs --root . --check
150
- node scripts/validate-builder.mjs --root .
151
- node scripts/self-test.mjs --root .
152
- ```
153
-
154
- 这些脚本无第三方依赖、接受显式根目录、拒绝路径越界,并提供 `--help`。