@devtrack-solution/codesdd 1.2.2

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 (433) hide show
  1. package/.sdd/skills/curated/api-clean-flask-langgraph/SKILL.md +2751 -0
  2. package/.sdd/skills/curated/devtrack-api/SKILL.md +137 -0
  3. package/.sdd/skills/curated/devtrack-api/agents/openai.yaml +4 -0
  4. package/.sdd/skills/curated/devtrack-api/references/application-presentation.md +381 -0
  5. package/.sdd/skills/curated/devtrack-api/references/architecture-governance.md +219 -0
  6. package/.sdd/skills/curated/devtrack-api/references/domain-modeling.md +359 -0
  7. package/.sdd/skills/curated/devtrack-api/references/implementation-checklist.md +127 -0
  8. package/.sdd/skills/curated/devtrack-api/references/imports-lint.md +207 -0
  9. package/.sdd/skills/curated/devtrack-api/references/testing-validation.md +167 -0
  10. package/.sdd/skills/curated/devtrack-api/references/typeorm-infrastructure.md +334 -0
  11. package/LICENSE +21 -0
  12. package/README.md +842 -0
  13. package/bin/codesdd.js +10 -0
  14. package/dist/cli/index.d.ts +3 -0
  15. package/dist/cli/index.js +560 -0
  16. package/dist/commands/change.d.ts +35 -0
  17. package/dist/commands/change.js +296 -0
  18. package/dist/commands/completion.d.ts +72 -0
  19. package/dist/commands/completion.js +258 -0
  20. package/dist/commands/config.d.ts +36 -0
  21. package/dist/commands/config.js +552 -0
  22. package/dist/commands/feedback.d.ts +9 -0
  23. package/dist/commands/feedback.js +184 -0
  24. package/dist/commands/schema.d.ts +6 -0
  25. package/dist/commands/schema.js +870 -0
  26. package/dist/commands/sdd/execution.d.ts +3 -0
  27. package/dist/commands/sdd/execution.js +409 -0
  28. package/dist/commands/sdd/shared.d.ts +9 -0
  29. package/dist/commands/sdd/shared.js +84 -0
  30. package/dist/commands/sdd/skills.d.ts +3 -0
  31. package/dist/commands/sdd/skills.js +154 -0
  32. package/dist/commands/sdd.d.ts +3 -0
  33. package/dist/commands/sdd.js +769 -0
  34. package/dist/commands/show.d.ts +14 -0
  35. package/dist/commands/show.js +133 -0
  36. package/dist/commands/spec.d.ts +15 -0
  37. package/dist/commands/spec.js +228 -0
  38. package/dist/commands/validate.d.ts +24 -0
  39. package/dist/commands/validate.js +295 -0
  40. package/dist/commands/workflow/index.d.ts +17 -0
  41. package/dist/commands/workflow/index.js +12 -0
  42. package/dist/commands/workflow/instructions.d.ts +29 -0
  43. package/dist/commands/workflow/instructions.js +383 -0
  44. package/dist/commands/workflow/new-change.d.ts +11 -0
  45. package/dist/commands/workflow/new-change.js +45 -0
  46. package/dist/commands/workflow/schemas.d.ts +10 -0
  47. package/dist/commands/workflow/schemas.js +34 -0
  48. package/dist/commands/workflow/shared.d.ts +57 -0
  49. package/dist/commands/workflow/shared.js +117 -0
  50. package/dist/commands/workflow/status.d.ts +14 -0
  51. package/dist/commands/workflow/status.js +76 -0
  52. package/dist/commands/workflow/templates.d.ts +16 -0
  53. package/dist/commands/workflow/templates.js +68 -0
  54. package/dist/core/archive.d.ts +16 -0
  55. package/dist/core/archive.js +487 -0
  56. package/dist/core/artifact-graph/graph.d.ts +56 -0
  57. package/dist/core/artifact-graph/graph.js +141 -0
  58. package/dist/core/artifact-graph/index.d.ts +7 -0
  59. package/dist/core/artifact-graph/index.js +13 -0
  60. package/dist/core/artifact-graph/instruction-loader.d.ts +143 -0
  61. package/dist/core/artifact-graph/instruction-loader.js +215 -0
  62. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  63. package/dist/core/artifact-graph/resolver.js +258 -0
  64. package/dist/core/artifact-graph/schema.d.ts +13 -0
  65. package/dist/core/artifact-graph/schema.js +108 -0
  66. package/dist/core/artifact-graph/state.d.ts +12 -0
  67. package/dist/core/artifact-graph/state.js +54 -0
  68. package/dist/core/artifact-graph/types.d.ts +45 -0
  69. package/dist/core/artifact-graph/types.js +43 -0
  70. package/dist/core/available-tools.d.ts +16 -0
  71. package/dist/core/available-tools.js +30 -0
  72. package/dist/core/branding.d.ts +8 -0
  73. package/dist/core/branding.js +12 -0
  74. package/dist/core/cli/command-matrix.d.ts +23 -0
  75. package/dist/core/cli/command-matrix.js +123 -0
  76. package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
  77. package/dist/core/command-generation/adapters/amazon-q.js +26 -0
  78. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  79. package/dist/core/command-generation/adapters/antigravity.js +26 -0
  80. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  81. package/dist/core/command-generation/adapters/auggie.js +27 -0
  82. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  83. package/dist/core/command-generation/adapters/claude.js +50 -0
  84. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  85. package/dist/core/command-generation/adapters/cline.js +27 -0
  86. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/codebuddy.js +28 -0
  88. package/dist/core/command-generation/adapters/codex.d.ts +16 -0
  89. package/dist/core/command-generation/adapters/codex.js +39 -0
  90. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  91. package/dist/core/command-generation/adapters/continue.js +28 -0
  92. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  93. package/dist/core/command-generation/adapters/costrict.js +27 -0
  94. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  95. package/dist/core/command-generation/adapters/crush.js +30 -0
  96. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  97. package/dist/core/command-generation/adapters/cursor.js +44 -0
  98. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  99. package/dist/core/command-generation/adapters/factory.js +27 -0
  100. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  101. package/dist/core/command-generation/adapters/gemini.js +26 -0
  102. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  103. package/dist/core/command-generation/adapters/github-copilot.js +26 -0
  104. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  105. package/dist/core/command-generation/adapters/iflow.js +29 -0
  106. package/dist/core/command-generation/adapters/index.d.ts +29 -0
  107. package/dist/core/command-generation/adapters/index.js +29 -0
  108. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  109. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  110. package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
  111. package/dist/core/command-generation/adapters/kiro.js +26 -0
  112. package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
  113. package/dist/core/command-generation/adapters/opencode.js +29 -0
  114. package/dist/core/command-generation/adapters/pi.d.ts +14 -0
  115. package/dist/core/command-generation/adapters/pi.js +41 -0
  116. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  117. package/dist/core/command-generation/adapters/qoder.js +30 -0
  118. package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
  119. package/dist/core/command-generation/adapters/qwen.js +26 -0
  120. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  121. package/dist/core/command-generation/adapters/roocode.js +27 -0
  122. package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
  123. package/dist/core/command-generation/adapters/windsurf.js +51 -0
  124. package/dist/core/command-generation/generator.d.ts +21 -0
  125. package/dist/core/command-generation/generator.js +27 -0
  126. package/dist/core/command-generation/index.d.ts +22 -0
  127. package/dist/core/command-generation/index.js +24 -0
  128. package/dist/core/command-generation/registry.d.ts +36 -0
  129. package/dist/core/command-generation/registry.js +92 -0
  130. package/dist/core/command-generation/types.d.ts +56 -0
  131. package/dist/core/command-generation/types.js +8 -0
  132. package/dist/core/completions/command-registry.d.ts +7 -0
  133. package/dist/core/completions/command-registry.js +461 -0
  134. package/dist/core/completions/completion-provider.d.ts +60 -0
  135. package/dist/core/completions/completion-provider.js +102 -0
  136. package/dist/core/completions/factory.d.ts +64 -0
  137. package/dist/core/completions/factory.js +75 -0
  138. package/dist/core/completions/generators/bash-generator.d.ts +32 -0
  139. package/dist/core/completions/generators/bash-generator.js +174 -0
  140. package/dist/core/completions/generators/fish-generator.d.ts +32 -0
  141. package/dist/core/completions/generators/fish-generator.js +157 -0
  142. package/dist/core/completions/generators/powershell-generator.d.ts +33 -0
  143. package/dist/core/completions/generators/powershell-generator.js +207 -0
  144. package/dist/core/completions/generators/zsh-generator.d.ts +44 -0
  145. package/dist/core/completions/generators/zsh-generator.js +250 -0
  146. package/dist/core/completions/installers/bash-installer.d.ts +87 -0
  147. package/dist/core/completions/installers/bash-installer.js +318 -0
  148. package/dist/core/completions/installers/fish-installer.d.ts +43 -0
  149. package/dist/core/completions/installers/fish-installer.js +143 -0
  150. package/dist/core/completions/installers/powershell-installer.d.ts +88 -0
  151. package/dist/core/completions/installers/powershell-installer.js +327 -0
  152. package/dist/core/completions/installers/zsh-installer.d.ts +125 -0
  153. package/dist/core/completions/installers/zsh-installer.js +452 -0
  154. package/dist/core/completions/templates/bash-templates.d.ts +6 -0
  155. package/dist/core/completions/templates/bash-templates.js +24 -0
  156. package/dist/core/completions/templates/fish-templates.d.ts +7 -0
  157. package/dist/core/completions/templates/fish-templates.js +39 -0
  158. package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
  159. package/dist/core/completions/templates/powershell-templates.js +25 -0
  160. package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
  161. package/dist/core/completions/templates/zsh-templates.js +36 -0
  162. package/dist/core/completions/types.d.ts +79 -0
  163. package/dist/core/completions/types.js +2 -0
  164. package/dist/core/config-prompts.d.ts +9 -0
  165. package/dist/core/config-prompts.js +34 -0
  166. package/dist/core/config-schema.d.ts +86 -0
  167. package/dist/core/config-schema.js +213 -0
  168. package/dist/core/config.d.ts +17 -0
  169. package/dist/core/config.js +33 -0
  170. package/dist/core/converters/json-converter.d.ts +6 -0
  171. package/dist/core/converters/json-converter.js +51 -0
  172. package/dist/core/global-config.d.ts +44 -0
  173. package/dist/core/global-config.js +125 -0
  174. package/dist/core/index.d.ts +2 -0
  175. package/dist/core/index.js +3 -0
  176. package/dist/core/init.d.ts +36 -0
  177. package/dist/core/init.js +576 -0
  178. package/dist/core/legacy-cleanup.d.ts +162 -0
  179. package/dist/core/legacy-cleanup.js +512 -0
  180. package/dist/core/list.d.ts +9 -0
  181. package/dist/core/list.js +173 -0
  182. package/dist/core/migration.d.ts +23 -0
  183. package/dist/core/migration.js +108 -0
  184. package/dist/core/parsers/change-parser.d.ts +13 -0
  185. package/dist/core/parsers/change-parser.js +193 -0
  186. package/dist/core/parsers/markdown-parser.d.ts +22 -0
  187. package/dist/core/parsers/markdown-parser.js +187 -0
  188. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  189. package/dist/core/parsers/requirement-blocks.js +201 -0
  190. package/dist/core/profile-sync-drift.d.ts +38 -0
  191. package/dist/core/profile-sync-drift.js +201 -0
  192. package/dist/core/profiles.d.ts +26 -0
  193. package/dist/core/profiles.js +41 -0
  194. package/dist/core/project-config.d.ts +64 -0
  195. package/dist/core/project-config.js +223 -0
  196. package/dist/core/schemas/base.schema.d.ts +13 -0
  197. package/dist/core/schemas/base.schema.js +13 -0
  198. package/dist/core/schemas/change.schema.d.ts +73 -0
  199. package/dist/core/schemas/change.schema.js +31 -0
  200. package/dist/core/schemas/index.d.ts +4 -0
  201. package/dist/core/schemas/index.js +4 -0
  202. package/dist/core/schemas/spec.schema.d.ts +18 -0
  203. package/dist/core/schemas/spec.schema.js +15 -0
  204. package/dist/core/sdd/adr-policy.d.ts +7 -0
  205. package/dist/core/sdd/adr-policy.js +47 -0
  206. package/dist/core/sdd/adr.d.ts +4 -0
  207. package/dist/core/sdd/adr.js +27 -0
  208. package/dist/core/sdd/bootstrap.d.ts +28 -0
  209. package/dist/core/sdd/bootstrap.js +353 -0
  210. package/dist/core/sdd/check.d.ts +51 -0
  211. package/dist/core/sdd/check.js +831 -0
  212. package/dist/core/sdd/coordination/coordination-adapters.d.ts +73 -0
  213. package/dist/core/sdd/coordination/coordination-adapters.js +87 -0
  214. package/dist/core/sdd/coordination/index.d.ts +2 -0
  215. package/dist/core/sdd/coordination/index.js +2 -0
  216. package/dist/core/sdd/dedup.d.ts +23 -0
  217. package/dist/core/sdd/dedup.js +62 -0
  218. package/dist/core/sdd/default-bootstrap-files.d.ts +23 -0
  219. package/dist/core/sdd/default-bootstrap-files.js +385 -0
  220. package/dist/core/sdd/default-skills.d.ts +16 -0
  221. package/dist/core/sdd/default-skills.js +427 -0
  222. package/dist/core/sdd/diagnose.d.ts +25 -0
  223. package/dist/core/sdd/diagnose.js +1312 -0
  224. package/dist/core/sdd/docs-sync.d.ts +21 -0
  225. package/dist/core/sdd/docs-sync.js +231 -0
  226. package/dist/core/sdd/domain/helpers.d.ts +6 -0
  227. package/dist/core/sdd/domain/helpers.js +37 -0
  228. package/dist/core/sdd/domain/lifecycle-guardrails.d.ts +22 -0
  229. package/dist/core/sdd/domain/lifecycle-guardrails.js +31 -0
  230. package/dist/core/sdd/domain/lifecycle-hooks.d.ts +16 -0
  231. package/dist/core/sdd/domain/lifecycle-hooks.js +27 -0
  232. package/dist/core/sdd/domain/post-active-validation.d.ts +15 -0
  233. package/dist/core/sdd/domain/post-active-validation.js +71 -0
  234. package/dist/core/sdd/domain/traceability.d.ts +8 -0
  235. package/dist/core/sdd/domain/traceability.js +83 -0
  236. package/dist/core/sdd/domain/transition-engine.d.ts +49 -0
  237. package/dist/core/sdd/domain/transition-engine.js +120 -0
  238. package/dist/core/sdd/fingerprint.d.ts +23 -0
  239. package/dist/core/sdd/fingerprint.js +146 -0
  240. package/dist/core/sdd/import-openspec.d.ts +31 -0
  241. package/dist/core/sdd/import-openspec.js +232 -0
  242. package/dist/core/sdd/init.d.ts +36 -0
  243. package/dist/core/sdd/init.js +65 -0
  244. package/dist/core/sdd/json-schema.d.ts +6 -0
  245. package/dist/core/sdd/json-schema.js +59 -0
  246. package/dist/core/sdd/legacy-operations.d.ts +286 -0
  247. package/dist/core/sdd/legacy-operations.js +2175 -0
  248. package/dist/core/sdd/lenses.d.ts +14 -0
  249. package/dist/core/sdd/lenses.js +97 -0
  250. package/dist/core/sdd/merge-catalog.d.ts +9 -0
  251. package/dist/core/sdd/merge-catalog.js +70 -0
  252. package/dist/core/sdd/migrate-workspace.d.ts +36 -0
  253. package/dist/core/sdd/migrate-workspace.js +344 -0
  254. package/dist/core/sdd/migrate.d.ts +24 -0
  255. package/dist/core/sdd/migrate.js +385 -0
  256. package/dist/core/sdd/resolve-project-root.d.ts +15 -0
  257. package/dist/core/sdd/resolve-project-root.js +46 -0
  258. package/dist/core/sdd/root-resolver.d.ts +16 -0
  259. package/dist/core/sdd/root-resolver.js +62 -0
  260. package/dist/core/sdd/sanitize.d.ts +35 -0
  261. package/dist/core/sdd/sanitize.js +750 -0
  262. package/dist/core/sdd/services/approve.service.d.ts +20 -0
  263. package/dist/core/sdd/services/approve.service.js +82 -0
  264. package/dist/core/sdd/services/audit.service.d.ts +53 -0
  265. package/dist/core/sdd/services/audit.service.js +136 -0
  266. package/dist/core/sdd/services/breakdown.service.d.ts +35 -0
  267. package/dist/core/sdd/services/breakdown.service.js +185 -0
  268. package/dist/core/sdd/services/context.service.d.ts +346 -0
  269. package/dist/core/sdd/services/context.service.js +278 -0
  270. package/dist/core/sdd/services/debate.service.d.ts +16 -0
  271. package/dist/core/sdd/services/debate.service.js +73 -0
  272. package/dist/core/sdd/services/decide.service.d.ts +23 -0
  273. package/dist/core/sdd/services/decide.service.js +81 -0
  274. package/dist/core/sdd/services/dedup-apply.service.d.ts +39 -0
  275. package/dist/core/sdd/services/dedup-apply.service.js +259 -0
  276. package/dist/core/sdd/services/feature-lint.service.d.ts +29 -0
  277. package/dist/core/sdd/services/feature-lint.service.js +146 -0
  278. package/dist/core/sdd/services/finalize.service.d.ts +33 -0
  279. package/dist/core/sdd/services/finalize.service.js +707 -0
  280. package/dist/core/sdd/services/frontend-gap.service.d.ts +23 -0
  281. package/dist/core/sdd/services/frontend-gap.service.js +117 -0
  282. package/dist/core/sdd/services/frontend-impact.service.d.ts +19 -0
  283. package/dist/core/sdd/services/frontend-impact.service.js +46 -0
  284. package/dist/core/sdd/services/ingest-deposito.service.d.ts +32 -0
  285. package/dist/core/sdd/services/ingest-deposito.service.js +231 -0
  286. package/dist/core/sdd/services/insight.service.d.ts +21 -0
  287. package/dist/core/sdd/services/insight.service.js +81 -0
  288. package/dist/core/sdd/services/legacy-capability.service.d.ts +24 -0
  289. package/dist/core/sdd/services/legacy-capability.service.js +59 -0
  290. package/dist/core/sdd/services/mcp-runtime.service.d.ts +42 -0
  291. package/dist/core/sdd/services/mcp-runtime.service.js +144 -0
  292. package/dist/core/sdd/services/metrics.service.d.ts +49 -0
  293. package/dist/core/sdd/services/metrics.service.js +181 -0
  294. package/dist/core/sdd/services/next.service.d.ts +35 -0
  295. package/dist/core/sdd/services/next.service.js +54 -0
  296. package/dist/core/sdd/services/onboard.service.d.ts +9 -0
  297. package/dist/core/sdd/services/onboard.service.js +165 -0
  298. package/dist/core/sdd/services/rebuild.service.d.ts +31 -0
  299. package/dist/core/sdd/services/rebuild.service.js +482 -0
  300. package/dist/core/sdd/services/scan-naming.service.d.ts +43 -0
  301. package/dist/core/sdd/services/scan-naming.service.js +246 -0
  302. package/dist/core/sdd/services/skills-invoke.service.d.ts +24 -0
  303. package/dist/core/sdd/services/skills-invoke.service.js +63 -0
  304. package/dist/core/sdd/services/skills-sync.service.d.ts +15 -0
  305. package/dist/core/sdd/services/skills-sync.service.js +117 -0
  306. package/dist/core/sdd/services/start.service.d.ts +26 -0
  307. package/dist/core/sdd/services/start.service.js +237 -0
  308. package/dist/core/sdd/skills.d.ts +15 -0
  309. package/dist/core/sdd/skills.js +46 -0
  310. package/dist/core/sdd/state-lock.d.ts +19 -0
  311. package/dist/core/sdd/state-lock.js +144 -0
  312. package/dist/core/sdd/state.d.ts +155 -0
  313. package/dist/core/sdd/state.js +1000 -0
  314. package/dist/core/sdd/store/in-memory-adapter.d.ts +12 -0
  315. package/dist/core/sdd/store/in-memory-adapter.js +27 -0
  316. package/dist/core/sdd/store/index.d.ts +5 -0
  317. package/dist/core/sdd/store/index.js +5 -0
  318. package/dist/core/sdd/store/sdd-stores.d.ts +25 -0
  319. package/dist/core/sdd/store/sdd-stores.js +59 -0
  320. package/dist/core/sdd/store/state-store.d.ts +32 -0
  321. package/dist/core/sdd/store/state-store.js +2 -0
  322. package/dist/core/sdd/store/yaml-file-adapter.d.ts +12 -0
  323. package/dist/core/sdd/store/yaml-file-adapter.js +43 -0
  324. package/dist/core/sdd/structural-health.d.ts +557 -0
  325. package/dist/core/sdd/structural-health.js +187 -0
  326. package/dist/core/sdd/transaction.d.ts +14 -0
  327. package/dist/core/sdd/transaction.js +100 -0
  328. package/dist/core/sdd/types.d.ts +1570 -0
  329. package/dist/core/sdd/types.js +617 -0
  330. package/dist/core/sdd/views.d.ts +3 -0
  331. package/dist/core/sdd/views.js +560 -0
  332. package/dist/core/sdd/workspace-schemas.d.ts +620 -0
  333. package/dist/core/sdd/workspace-schemas.js +254 -0
  334. package/dist/core/sdd/write-manifest.d.ts +25 -0
  335. package/dist/core/sdd/write-manifest.js +353 -0
  336. package/dist/core/shared/index.d.ts +8 -0
  337. package/dist/core/shared/index.js +8 -0
  338. package/dist/core/shared/skill-generation.d.ts +49 -0
  339. package/dist/core/shared/skill-generation.js +106 -0
  340. package/dist/core/shared/tool-detection.d.ts +71 -0
  341. package/dist/core/shared/tool-detection.js +158 -0
  342. package/dist/core/specs-apply.d.ts +73 -0
  343. package/dist/core/specs-apply.js +385 -0
  344. package/dist/core/styles/palette.d.ts +7 -0
  345. package/dist/core/styles/palette.js +8 -0
  346. package/dist/core/templates/index.d.ts +8 -0
  347. package/dist/core/templates/index.js +9 -0
  348. package/dist/core/templates/skill-templates.d.ts +20 -0
  349. package/dist/core/templates/skill-templates.js +19 -0
  350. package/dist/core/templates/types.d.ts +19 -0
  351. package/dist/core/templates/types.js +5 -0
  352. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  353. package/dist/core/templates/workflows/apply-change.js +308 -0
  354. package/dist/core/templates/workflows/archive-change.d.ts +10 -0
  355. package/dist/core/templates/workflows/archive-change.js +277 -0
  356. package/dist/core/templates/workflows/bulk-archive-change.d.ts +10 -0
  357. package/dist/core/templates/workflows/bulk-archive-change.js +502 -0
  358. package/dist/core/templates/workflows/continue-change.d.ts +10 -0
  359. package/dist/core/templates/workflows/continue-change.js +232 -0
  360. package/dist/core/templates/workflows/explore.d.ts +10 -0
  361. package/dist/core/templates/workflows/explore.js +475 -0
  362. package/dist/core/templates/workflows/feedback.d.ts +9 -0
  363. package/dist/core/templates/workflows/feedback.js +108 -0
  364. package/dist/core/templates/workflows/ff-change.d.ts +10 -0
  365. package/dist/core/templates/workflows/ff-change.js +206 -0
  366. package/dist/core/templates/workflows/new-change.d.ts +10 -0
  367. package/dist/core/templates/workflows/new-change.js +151 -0
  368. package/dist/core/templates/workflows/onboard.d.ts +10 -0
  369. package/dist/core/templates/workflows/onboard.js +573 -0
  370. package/dist/core/templates/workflows/propose.d.ts +10 -0
  371. package/dist/core/templates/workflows/propose.js +224 -0
  372. package/dist/core/templates/workflows/sdd.d.ts +10 -0
  373. package/dist/core/templates/workflows/sdd.js +107 -0
  374. package/dist/core/templates/workflows/sync-specs.d.ts +10 -0
  375. package/dist/core/templates/workflows/sync-specs.js +286 -0
  376. package/dist/core/templates/workflows/verify-change.d.ts +10 -0
  377. package/dist/core/templates/workflows/verify-change.js +346 -0
  378. package/dist/core/update.d.ts +77 -0
  379. package/dist/core/update.js +538 -0
  380. package/dist/core/validation/constants.d.ts +34 -0
  381. package/dist/core/validation/constants.js +40 -0
  382. package/dist/core/validation/types.d.ts +18 -0
  383. package/dist/core/validation/types.js +2 -0
  384. package/dist/core/validation/validator.d.ts +33 -0
  385. package/dist/core/validation/validator.js +409 -0
  386. package/dist/core/view.d.ts +8 -0
  387. package/dist/core/view.js +170 -0
  388. package/dist/index.d.ts +3 -0
  389. package/dist/index.js +3 -0
  390. package/dist/prompts/searchable-multi-select.d.ts +28 -0
  391. package/dist/prompts/searchable-multi-select.js +159 -0
  392. package/dist/telemetry/config.d.ts +32 -0
  393. package/dist/telemetry/config.js +68 -0
  394. package/dist/telemetry/index.d.ts +44 -0
  395. package/dist/telemetry/index.js +207 -0
  396. package/dist/ui/ascii-patterns.d.ts +16 -0
  397. package/dist/ui/ascii-patterns.js +133 -0
  398. package/dist/ui/welcome-screen.d.ts +10 -0
  399. package/dist/ui/welcome-screen.js +146 -0
  400. package/dist/utils/change-metadata.d.ts +51 -0
  401. package/dist/utils/change-metadata.js +147 -0
  402. package/dist/utils/change-utils.d.ts +62 -0
  403. package/dist/utils/change-utils.js +121 -0
  404. package/dist/utils/command-references.d.ts +18 -0
  405. package/dist/utils/command-references.js +20 -0
  406. package/dist/utils/file-system.d.ts +36 -0
  407. package/dist/utils/file-system.js +281 -0
  408. package/dist/utils/index.d.ts +6 -0
  409. package/dist/utils/index.js +9 -0
  410. package/dist/utils/interactive.d.ts +18 -0
  411. package/dist/utils/interactive.js +21 -0
  412. package/dist/utils/item-discovery.d.ts +4 -0
  413. package/dist/utils/item-discovery.js +73 -0
  414. package/dist/utils/match.d.ts +3 -0
  415. package/dist/utils/match.js +22 -0
  416. package/dist/utils/openspec-compat.d.ts +2 -0
  417. package/dist/utils/openspec-compat.js +2 -0
  418. package/dist/utils/shell-detection.d.ts +20 -0
  419. package/dist/utils/shell-detection.js +41 -0
  420. package/dist/utils/task-progress.d.ts +8 -0
  421. package/dist/utils/task-progress.js +36 -0
  422. package/package.json +111 -0
  423. package/schemas/sdd/1-spec.schema.json +221 -0
  424. package/schemas/sdd/2-plan.schema.json +199 -0
  425. package/schemas/sdd/3-tasks.schema.json +102 -0
  426. package/schemas/sdd/4-changelog.schema.json +55 -0
  427. package/schemas/sdd/5-quality.schema.json +427 -0
  428. package/schemas/sdd/workspace-catalog.schema.json +1012 -0
  429. package/schemas/spec-driven/schema.yaml +153 -0
  430. package/schemas/spec-driven/templates/design.md +19 -0
  431. package/schemas/spec-driven/templates/proposal.md +23 -0
  432. package/schemas/spec-driven/templates/spec.md +8 -0
  433. package/schemas/spec-driven/templates/tasks.md +9 -0
@@ -0,0 +1,707 @@
1
+ import path from "node:path";
2
+ import { existsSync, promises as fs } from "node:fs";
3
+ import { LENSES, validateDocumentAgainstLens } from "../lenses.js";
4
+ import { adrFileName } from "../adr.js";
5
+ import { evaluateFeatureFinalizeGuardrails } from "../domain/lifecycle-guardrails.js";
6
+ import { runLifecycleHooks } from "../domain/lifecycle-hooks.js";
7
+ import { evaluateWorkspaceTraceability } from "../domain/traceability.js";
8
+ import { validatePostActiveFeaturePlacement, validatePreFinalizeArchiveCanonicalization, } from "../domain/post-active-validation.js";
9
+ import { loadStateSnapshot, nowIso, saveStateTransaction } from "../state.js";
10
+ import { syncSddGuideDocs } from "../docs-sync.js";
11
+ import { mergeArchitectureNode, mergeFrontendDecisionRecord, mergeRepoMapRecord, mergeServiceRecord, mergeTechStackRecord, stableUniqueStrings, upsertByKey } from "../merge-catalog.js";
12
+ import { getRuntime, persistAndRender, relProjectPath, coreDocRef, activeDocNamesForLayout, activeDocCandidateNames, unresolvedDependencies, updateDependencyMetadata, gitChangedFiles, detectFrontendImpactEvidence, maybeCreateAutomaticFrontendGap, buildFinalizeQueue, evaluateFeatureQuality, buildAdrMarkdown, applyLoggedTransition, gateSatisfied, pathExists, RADAR_TO_DISCOVERY_STATUS } from "../legacy-operations.js";
13
+ import { SddWriteTransaction } from "../write-manifest.js";
14
+ import { withStateLock } from "../state-lock.js";
15
+ import { activeWorkspaceDeclaresMandatoryAdrImpact } from "../adr-policy.js";
16
+ import { parseWorkspaceYamlDocument, } from "../workspace-schemas.js";
17
+ export class FinalizeService {
18
+ stores;
19
+ constructor(stores) {
20
+ this.stores = stores;
21
+ }
22
+ async execute(projectRoot, options) {
23
+ const { config, paths } = await getRuntime(projectRoot);
24
+ return withStateLock(paths.stateDir, async () => {
25
+ const snapshot = await loadStateSnapshot(paths, config);
26
+ snapshot.finalizeQueue.items = await buildFinalizeQueue(paths, snapshot.backlog.items, snapshot.finalizeQueue.items);
27
+ const pending = snapshot.finalizeQueue.items.filter((item) => item.status === 'PENDING');
28
+ const inferredRef = options?.allReady
29
+ ? undefined
30
+ : await inferFinalizeTarget(paths, pending, options?.ref, options?.cwd || process.cwd());
31
+ const targets = options?.allReady
32
+ ? pending.map((item) => item.feature_id)
33
+ : inferredRef
34
+ ? [inferredRef]
35
+ : pending.slice(0, 1).map((item) => item.feature_id);
36
+ if (targets.length === 0) {
37
+ await saveStateTransaction(paths, {
38
+ finalizeQueue: snapshot.finalizeQueue,
39
+ backlog: snapshot.backlog,
40
+ unblockEvents: snapshot.unblockEvents,
41
+ transitionLog: snapshot.transitionLog,
42
+ });
43
+ await persistAndRender(paths, config, options?.render);
44
+ return {
45
+ finalized: [],
46
+ unblocked: [],
47
+ pending: pending.length,
48
+ updated_core_docs: [],
49
+ updated_readme: false,
50
+ updated_agent_guide: false,
51
+ doc_warnings: [],
52
+ auto_frontend_gaps: [],
53
+ frontend_guardrails: [],
54
+ };
55
+ }
56
+ const finalized = [];
57
+ const unblocked = new Set();
58
+ const updatedCoreDocs = new Set();
59
+ const docWarnings = [];
60
+ const autoFrontendGaps = [];
61
+ const frontendGuardrails = [];
62
+ const now = nowIso();
63
+ const existingEvents = new Set(snapshot.unblockEvents.events.map((event) => `${event.feature_id}:${event.unblocked_by}`));
64
+ for (const featureId of targets) {
65
+ const feature = snapshot.backlog.items.find((item) => item.id === featureId);
66
+ if (!feature)
67
+ continue;
68
+ const plannedDirPath = path.join(paths.plannedDir, feature.id);
69
+ const activeDirPath = path.join(paths.activeDir, feature.id);
70
+ const archivedDirPath = path.join(paths.archivedDir, feature.id);
71
+ const plannedWorkspaceExists = await pathExists(plannedDirPath);
72
+ const activeWorkspaceExists = await pathExists(activeDirPath);
73
+ const archivedWorkspaceExists = await pathExists(archivedDirPath);
74
+ if (archivedWorkspaceExists) {
75
+ throw new Error(`${feature.id} ja foi finalizada`);
76
+ }
77
+ if (plannedWorkspaceExists && !activeWorkspaceExists) {
78
+ throw new Error(`${feature.id} nao foi iniciada, use sdd start primeiro`);
79
+ }
80
+ if (!activeWorkspaceExists) {
81
+ throw new Error(`Workspace ativo de ${feature.id} nao encontrado para finalize.`);
82
+ }
83
+ const archiveCanonicalization = await validatePreFinalizeArchiveCanonicalization(paths, feature.id);
84
+ if (!archiveCanonicalization.ok) {
85
+ throw new Error(`${feature.id} post-active lifecycle validation failed: ${archiveCanonicalization.reasons.join(' | ')}`);
86
+ }
87
+ const finalizeGuardrails = evaluateFeatureFinalizeGuardrails(feature, snapshot.backlog.items, !!options?.forceTransition);
88
+ if (!finalizeGuardrails.dependency_check.ok) {
89
+ docWarnings.push(`${feature.id} finalize dependency guardrail blocked: ${finalizeGuardrails.reasons.join(' | ')}`);
90
+ if (!options?.forceTransition) {
91
+ continue;
92
+ }
93
+ docWarnings.push(`${feature.id} finalized with --force-transition despite unresolved blocked_by dependencies.`);
94
+ }
95
+ await runLifecycleHooks('before-finalize', {
96
+ projectRoot,
97
+ featureId: feature.id,
98
+ entityId: feature.id,
99
+ options: options,
100
+ metadata: {
101
+ finalize_guardrails: finalizeGuardrails,
102
+ current_status: feature.status,
103
+ },
104
+ });
105
+ if (feature.flow_mode === 'rigoroso' &&
106
+ (!gateSatisfied(feature.gates.proposta.status) ||
107
+ !gateSatisfied(feature.gates.planejamento.status) ||
108
+ !gateSatisfied(feature.gates.tarefas.status))) {
109
+ docWarnings.push(`${feature.id} em modo rigoroso sem gates aprovados (proposta=${feature.gates.proposta.status}, planejamento=${feature.gates.planejamento.status}, tarefas=${feature.gates.tarefas.status})`);
110
+ continue;
111
+ }
112
+ if (config.frontend.enabled) {
113
+ const changed = await gitChangedFiles(projectRoot, feature.start_commit_sha || '');
114
+ const evidence = detectFrontendImpactEvidence(feature, changed.files);
115
+ const declaredStatus = feature.frontend_impact_status || 'unknown';
116
+ const reasons = [];
117
+ let autoGapId = '';
118
+ if (declaredStatus === 'unknown') {
119
+ reasons.push('frontend_impact_status=unknown');
120
+ }
121
+ if (declaredStatus === 'none') {
122
+ const reason = (feature.frontend_impact_reason || '').trim();
123
+ if (reason.length < 20) {
124
+ reasons.push('frontend_impact_status=none sem justificativa minima (20 chars)');
125
+ }
126
+ if (evidence.has_frontend_evidence) {
127
+ reasons.push('frontend_impact_status=none contradiz evidencias (metadata/diff)');
128
+ }
129
+ }
130
+ if (declaredStatus === 'required' && feature.frontend_gap_refs.length === 0) {
131
+ autoGapId = await maybeCreateAutomaticFrontendGap(paths, snapshot, feature, {
132
+ force: true,
133
+ routeTargets: evidence.metadata_routes,
134
+ detectionSources: evidence.evidence_sources.length > 0
135
+ ? [...evidence.evidence_sources]
136
+ : ['metadata'],
137
+ });
138
+ if (autoGapId) {
139
+ autoFrontendGaps.push(autoGapId);
140
+ docWarnings.push(`${feature.id} gerou ${autoGapId} automaticamente (cobertura frontend pendente).`);
141
+ }
142
+ reasons.push(`frontend_impact_status=required exige FGAP vinculado antes do finalize (${autoGapId || 'nao criado'})`);
143
+ }
144
+ if (changed.warning) {
145
+ docWarnings.push(`${feature.id}: deteccao diff com baixa confianca (${changed.warning}).`);
146
+ }
147
+ const blockedByGuardrail = reasons.length > 0;
148
+ const forcedByGuardrail = blockedByGuardrail && !!options?.forceFrontend;
149
+ frontendGuardrails.push({
150
+ feature_id: feature.id,
151
+ declared_status: declaredStatus,
152
+ evidence_sources: evidence.evidence_sources,
153
+ auto_gap_created: autoGapId,
154
+ blocked: blockedByGuardrail,
155
+ forced: forcedByGuardrail,
156
+ reasons,
157
+ });
158
+ if (blockedByGuardrail && !options?.forceFrontend) {
159
+ docWarnings.push(`${feature.id} bloqueada pelos guardrails de frontend: ${reasons.join(' | ')}`);
160
+ continue;
161
+ }
162
+ if (forcedByGuardrail) {
163
+ docWarnings.push(`${feature.id} finalizada com --force-frontend apesar de guardrails: ${reasons.join(' | ')}`);
164
+ }
165
+ }
166
+ const qualityGuardrail = await evaluateFeatureQuality(paths, config, feature);
167
+ if (!qualityGuardrail.ok) {
168
+ docWarnings.push(`${feature.id} quality contract warnings: ${qualityGuardrail.reasons.join(' | ')}`);
169
+ if (qualityGuardrail.blocking && !options?.forceTransition) {
170
+ continue;
171
+ }
172
+ if (qualityGuardrail.blocking && options?.forceTransition) {
173
+ docWarnings.push(`${feature.id} finalized with --force-transition despite quality contract warnings.`);
174
+ }
175
+ }
176
+ const qualityFeedbackGuardrail = await evaluateWorkspaceQualityFeedback(paths, config, feature);
177
+ if (!qualityFeedbackGuardrail.ok) {
178
+ docWarnings.push(`${feature.id} quality feedback loop blocked finalize: ${qualityFeedbackGuardrail.reasons.join(' | ')}`);
179
+ if (!options?.forceTransition) {
180
+ continue;
181
+ }
182
+ docWarnings.push(`${feature.id} finalized with --force-transition despite quality feedback loop warnings.`);
183
+ }
184
+ const traceabilityGuardrail = await evaluateWorkspaceTraceabilityFeedback(paths, config, feature);
185
+ if (!traceabilityGuardrail.ok) {
186
+ docWarnings.push(`${feature.id} traceability guardrail blocked finalize: ${traceabilityGuardrail.reasons.join(' | ')}`);
187
+ if (!options?.forceTransition) {
188
+ continue;
189
+ }
190
+ docWarnings.push(`${feature.id} finalized with --force-transition despite traceability guardrail warnings.`);
191
+ }
192
+ const privacyFinalizeGuardrail = await evaluatePrivacyFinalizeGuardrail(paths, config, feature);
193
+ if (!privacyFinalizeGuardrail.ok) {
194
+ docWarnings.push(`${feature.id} privacy compliance guardrail blocked finalize: ${privacyFinalizeGuardrail.reasons.join(' | ')}`);
195
+ if (!options?.forceTransition) {
196
+ continue;
197
+ }
198
+ docWarnings.push(`${feature.id} finalized with --force-transition despite privacy compliance guardrail warnings.`);
199
+ }
200
+ if (!feature.requires_adr && (await activeWorkspaceDeclaresMandatoryAdrImpact(paths, feature))) {
201
+ feature.requires_adr = true;
202
+ }
203
+ if (feature.requires_adr) {
204
+ const requiredAdrPath = path.join(paths.coreDir, 'adrs', adrFileName(feature.id));
205
+ const adrContent = await fs.readFile(requiredAdrPath, 'utf-8').catch(() => '');
206
+ if (!adrContent.trim()) {
207
+ docWarnings.push(`${feature.id} exige ADR obrigatório ausente: ${relProjectPath(paths, requiredAdrPath)}`);
208
+ if (!options?.forceTransition) {
209
+ continue;
210
+ }
211
+ docWarnings.push(`${feature.id} finalizada com --force-transition sem ADR obrigatório preenchido.`);
212
+ }
213
+ else {
214
+ const adrViolations = validateDocumentAgainstLens(adrContent, LENSES.adr);
215
+ if (adrViolations.length > 0) {
216
+ docWarnings.push(`${feature.id} ADR obrigatório inválido: ${adrViolations.join(' | ')}`);
217
+ if (!options?.forceTransition) {
218
+ continue;
219
+ }
220
+ docWarnings.push(`${feature.id} finalizada com --force-transition apesar de violações no ADR obrigatório.`);
221
+ }
222
+ }
223
+ }
224
+ // Validate active workspace docs with the canonical YAML/Zod contract.
225
+ const activePath = path.join(paths.activeDir, feature.id);
226
+ const docNames = activeDocNamesForLayout(config);
227
+ const specPath = path.join(activePath, docNames.spec);
228
+ const planPath = path.join(activePath, docNames.plan);
229
+ let lensViolations = [];
230
+ const specContent = await fs.readFile(specPath, 'utf8').catch(() => '');
231
+ if (specContent) {
232
+ try {
233
+ parseWorkspaceYamlDocument('1-spec.yaml', specContent);
234
+ }
235
+ catch (error) {
236
+ lensViolations.push(`Spec: ${error.message}`);
237
+ }
238
+ }
239
+ else {
240
+ lensViolations.push(`Arquivo de especificação YAML não encontrado ou vazio: ${docNames.spec}.`);
241
+ }
242
+ const planContent = await fs.readFile(planPath, 'utf8').catch(() => '');
243
+ if (planContent) {
244
+ try {
245
+ parseWorkspaceYamlDocument('2-plan.yaml', planContent);
246
+ }
247
+ catch (error) {
248
+ lensViolations.push(`Plan: ${error.message}`);
249
+ }
250
+ }
251
+ else {
252
+ lensViolations.push(`Arquivo de plano YAML não encontrado ou vazio: ${docNames.plan}.`);
253
+ }
254
+ try {
255
+ applyLoggedTransition(snapshot.transitionLog.events, 'FEAT', feature, 'DONE', {
256
+ sourceCommand: 'sdd finalize',
257
+ forceTransition: options?.forceTransition,
258
+ lensViolations,
259
+ reason: `Finalize consolidado para ${feature.id}`,
260
+ timestamp: now,
261
+ afterTransition: (currentFeature) => {
262
+ currentFeature.current_stage = 'consolidacao';
263
+ currentFeature.done_at = now;
264
+ currentFeature.last_sync_at = now;
265
+ },
266
+ });
267
+ }
268
+ catch (err) {
269
+ docWarnings.push(`${feature.id} ${err.message}`);
270
+ continue;
271
+ }
272
+ const queue = snapshot.finalizeQueue.items.find((item) => item.feature_id === featureId);
273
+ if (queue) {
274
+ queue.status = 'DONE';
275
+ queue.completed_at = now;
276
+ }
277
+ else {
278
+ snapshot.finalizeQueue.items.push({
279
+ feature_id: featureId,
280
+ status: 'DONE',
281
+ summary: `Finalizado manualmente: ${featureId}`,
282
+ created_at: now,
283
+ completed_at: now,
284
+ });
285
+ }
286
+ if ((feature.origin_type === 'radar' || feature.origin_type === 'epic') && feature.origin_ref) {
287
+ const siblings = snapshot.backlog.items.filter((item) => (item.origin_type === 'radar' || item.origin_type === 'epic') && item.origin_ref === feature.origin_ref);
288
+ if (siblings.every((item) => item.status === 'DONE' || item.status === 'ARCHIVED')) {
289
+ const radar = snapshot.discoveryIndex.records.find((r) => r.id === feature.origin_ref);
290
+ if (radar && (radar.type === 'RAD' || radar.type === 'EPIC')) {
291
+ const targetStatus = RADAR_TO_DISCOVERY_STATUS.DONE;
292
+ if (radar.status !== targetStatus) {
293
+ applyLoggedTransition(snapshot.transitionLog.events, radar.type, radar, targetStatus, {
294
+ sourceCommand: 'sdd finalize',
295
+ reason: `Todas as features derivadas de ${radar.id} foram concluídas`,
296
+ timestamp: now,
297
+ afterTransition: (currentRadar) => {
298
+ currentRadar.updated_at = now;
299
+ },
300
+ });
301
+ }
302
+ }
303
+ }
304
+ }
305
+ // Consolida memória macro canônica com dados objetivos da feature finalizada.
306
+ upsertByKey(snapshot.architecture.nodes, {
307
+ id: feature.id,
308
+ name: feature.title,
309
+ kind: feature.execution_kind,
310
+ description: feature.summary || '',
311
+ repo_paths: feature.worktree_path ? [feature.worktree_path] : [],
312
+ depends_on: feature.blocked_by,
313
+ }, (node) => node.id, mergeArchitectureNode);
314
+ updatedCoreDocs.add(coreDocRef(paths, 'arquitetura.md'));
315
+ const serviceId = feature.touches[0] || feature.execution_kind;
316
+ upsertByKey(snapshot.serviceCatalog.services, {
317
+ id: serviceId,
318
+ name: serviceId,
319
+ responsibility: feature.summary || '',
320
+ owner_refs: [feature.id],
321
+ repo_paths: feature.worktree_path ? [feature.worktree_path] : [],
322
+ contracts: feature.consumes,
323
+ external_dependencies: [],
324
+ }, (service) => service.id, mergeServiceRecord);
325
+ updatedCoreDocs.add(coreDocRef(paths, 'servicos.md'));
326
+ for (const tech of feature.touches) {
327
+ upsertByKey(snapshot.techStack.items, {
328
+ layer: tech,
329
+ technology: tech,
330
+ version: '',
331
+ purpose: `Area impactada por ${feature.id}`,
332
+ constraints: feature.lock_domains,
333
+ }, (entry) => `${entry.layer}::${entry.technology}`, mergeTechStackRecord);
334
+ }
335
+ updatedCoreDocs.add(coreDocRef(paths, 'spec-tecnologica.md'));
336
+ const contractTokens = Array.from(new Set([...feature.consumes, ...feature.produces]));
337
+ snapshot.integrationContracts.contracts = stableUniqueStrings([
338
+ ...snapshot.integrationContracts.contracts,
339
+ ...contractTokens.map((token) => `${token}::${feature.id}`),
340
+ ]);
341
+ upsertByKey(snapshot.repoMap.items, {
342
+ path: `.sdd/archived/${feature.id}`,
343
+ kind: 'sdd-feature-archive',
344
+ service_ref: serviceId,
345
+ notes: feature.summary || `Finalize ${feature.id}`,
346
+ }, (item) => item.path, mergeRepoMapRecord);
347
+ updatedCoreDocs.add(coreDocRef(paths, 'repo-map.md'));
348
+ if (config.frontend.enabled && snapshot.frontendDecisions && feature.execution_kind === 'frontend_coverage') {
349
+ upsertByKey(snapshot.frontendDecisions.items, {
350
+ id: `FD-${feature.id}`,
351
+ title: `Decisao de frontend para ${feature.id}`,
352
+ status: 'APPROVED',
353
+ decision: `Cobrir frontend da feature ${feature.id}`,
354
+ rationale: feature.summary || '',
355
+ related_refs: [feature.id, feature.origin_ref || ''].filter(Boolean),
356
+ route_refs: [],
357
+ adr_refs: [`ADR-${feature.id}`],
358
+ }, (entry) => entry.id, mergeFrontendDecisionRecord);
359
+ updatedCoreDocs.add(coreDocRef(paths, 'frontend-decisions.md'));
360
+ }
361
+ const unlockedByFeature = [];
362
+ for (const dependant of snapshot.backlog.items) {
363
+ if (dependant.id === feature.id)
364
+ continue;
365
+ if (!dependant.blocked_by.includes(feature.id))
366
+ continue;
367
+ if (dependant.status === 'DONE' || dependant.status === 'ARCHIVED')
368
+ continue;
369
+ const unresolved = unresolvedDependencies(dependant, snapshot.backlog.items);
370
+ if (unresolved.length > 0)
371
+ continue;
372
+ if (dependant.status === 'BLOCKED') {
373
+ dependant.status = 'READY';
374
+ }
375
+ dependant.unblocked_at = now;
376
+ dependant.last_sync_at = now;
377
+ unblocked.add(dependant.id);
378
+ unlockedByFeature.push(dependant.id);
379
+ const eventKey = `${dependant.id}:${feature.id}`;
380
+ if (!existingEvents.has(eventKey)) {
381
+ snapshot.unblockEvents.events.push({
382
+ feature_id: dependant.id,
383
+ unblocked_by: feature.id,
384
+ created_at: now,
385
+ status: 'NEW',
386
+ });
387
+ existingEvents.add(eventKey);
388
+ }
389
+ }
390
+ if (!options?.noAdr && !feature.requires_adr) {
391
+ const adrPath = path.join(paths.coreDir, 'adrs', `ADR-${feature.id}.md`);
392
+ const tx = new SddWriteTransaction();
393
+ tx.writeFile(adrPath, buildAdrMarkdown(feature, unlockedByFeature, now));
394
+ await tx.commit(paths.projectRoot, paths.memoryRoot, 'finalize.service (ADR)');
395
+ }
396
+ await fs.mkdir(paths.archivedDir, { recursive: true });
397
+ await fs.rename(activeDirPath, archivedDirPath);
398
+ const postActiveValidation = await validatePostActiveFeaturePlacement(paths, feature.id);
399
+ if (!postActiveValidation.ok) {
400
+ if (!(await pathExists(activeDirPath)) && (await pathExists(archivedDirPath))) {
401
+ await fs.rename(archivedDirPath, activeDirPath).catch(() => undefined);
402
+ }
403
+ throw new Error(`${feature.id} post-active lifecycle validation failed: ${postActiveValidation.reasons.join(' | ')}`);
404
+ }
405
+ finalized.push(featureId);
406
+ await runLifecycleHooks('after-finalize', {
407
+ projectRoot,
408
+ featureId: feature.id,
409
+ entityId: feature.id,
410
+ options: options,
411
+ metadata: {
412
+ finalized: true,
413
+ unblocked: Array.from(unblocked).sort(),
414
+ },
415
+ });
416
+ }
417
+ updateDependencyMetadata(snapshot.backlog.items);
418
+ const stateUpdates = {
419
+ discoveryIndex: snapshot.discoveryIndex,
420
+ backlog: snapshot.backlog,
421
+ finalizeQueue: snapshot.finalizeQueue,
422
+ unblockEvents: snapshot.unblockEvents,
423
+ transitionLog: snapshot.transitionLog,
424
+ architecture: snapshot.architecture,
425
+ serviceCatalog: snapshot.serviceCatalog,
426
+ techStack: snapshot.techStack,
427
+ integrationContracts: snapshot.integrationContracts,
428
+ repoMap: snapshot.repoMap,
429
+ };
430
+ if (config.frontend.enabled && snapshot.frontendDecisions) {
431
+ await saveStateTransaction(paths, {
432
+ ...stateUpdates,
433
+ frontendDecisions: snapshot.frontendDecisions,
434
+ frontendGaps: snapshot.frontendGaps,
435
+ frontendMap: snapshot.frontendMap,
436
+ });
437
+ }
438
+ else {
439
+ if (config.frontend.enabled) {
440
+ docWarnings.push('frontend.enabled=true sem frontend-decisions carregado');
441
+ }
442
+ await saveStateTransaction(paths, stateUpdates);
443
+ }
444
+ await persistAndRender(paths, config, options?.render);
445
+ const syncResult = await syncSddGuideDocs(projectRoot, paths, config);
446
+ const remaining = snapshot.finalizeQueue.items.filter((item) => item.status === 'PENDING').length;
447
+ return {
448
+ finalized,
449
+ unblocked: Array.from(unblocked).sort(),
450
+ pending: remaining,
451
+ updated_core_docs: Array.from(updatedCoreDocs).sort(),
452
+ updated_readme: syncResult.updatedReadme,
453
+ updated_agent_guide: syncResult.updatedAgentGuide || syncResult.updatedRootAgents,
454
+ doc_warnings: docWarnings,
455
+ auto_frontend_gaps: autoFrontendGaps,
456
+ frontend_guardrails: frontendGuardrails,
457
+ };
458
+ });
459
+ }
460
+ }
461
+ async function inferFinalizeTarget(paths, pending, explicitRef, cwd) {
462
+ if (explicitRef)
463
+ return explicitRef;
464
+ const activeEntries = await fs.readdir(paths.activeDir, { withFileTypes: true }).catch(() => []);
465
+ const activeFeatures = activeEntries
466
+ .filter((entry) => entry.isDirectory() && /^FEAT-\d{4}$/.test(entry.name))
467
+ .map((entry) => entry.name);
468
+ if (cwd) {
469
+ const normalizedCwd = path.resolve(cwd);
470
+ const cwdMatch = activeFeatures.find((featureId) => {
471
+ const featureRoot = path.join(paths.activeDir, featureId);
472
+ return normalizedCwd === featureRoot || normalizedCwd.startsWith(`${featureRoot}${path.sep}`);
473
+ });
474
+ if (cwdMatch) {
475
+ return cwdMatch;
476
+ }
477
+ }
478
+ if (pending.length === 1) {
479
+ return pending[0].feature_id;
480
+ }
481
+ if (activeFeatures.length === 1) {
482
+ return activeFeatures[0];
483
+ }
484
+ return undefined;
485
+ }
486
+ function isPrivacyComplianceFeature(feature) {
487
+ if (feature.origin_ref === 'EPIC-0020' || feature.origin_ref === 'EPIC-0021')
488
+ return true;
489
+ const refs = new Set(feature.acceptance_refs || []);
490
+ return refs.has('EPIC-0020') || refs.has('EPIC-0021') || refs.has('DEB-0021') || refs.has('INS-0021');
491
+ }
492
+ async function evaluatePrivacyFinalizeGuardrail(paths, config, feature) {
493
+ if (!isPrivacyComplianceFeature(feature)) {
494
+ return { ok: true, reasons: [] };
495
+ }
496
+ const activePath = path.join(paths.activeDir, feature.id);
497
+ const names = activeDocNamesForLayout(config);
498
+ const specPath = path.join(activePath, names.spec);
499
+ const planPath = path.join(activePath, names.plan);
500
+ const qualityPath = path.join(activePath, names.quality);
501
+ const reasons = [];
502
+ const [specContent, planContent, qualityContent] = await Promise.all([
503
+ fs.readFile(specPath, 'utf-8').catch(() => ''),
504
+ fs.readFile(planPath, 'utf-8').catch(() => ''),
505
+ fs.readFile(qualityPath, 'utf-8').catch(() => ''),
506
+ ]);
507
+ if (!specContent.trim())
508
+ reasons.push(`missing spec YAML: ${relProjectPath(paths, specPath)}`);
509
+ if (!planContent.trim())
510
+ reasons.push(`missing plan YAML: ${relProjectPath(paths, planPath)}`);
511
+ if (!qualityContent.trim())
512
+ reasons.push(`missing quality YAML: ${relProjectPath(paths, qualityPath)}`);
513
+ if (reasons.length > 0)
514
+ return { ok: false, reasons };
515
+ let spec;
516
+ let plan;
517
+ let quality;
518
+ try {
519
+ spec = parseWorkspaceYamlDocument('1-spec.yaml', specContent);
520
+ plan = parseWorkspaceYamlDocument('2-plan.yaml', planContent);
521
+ quality = parseWorkspaceYamlDocument('5-quality.yaml', qualityContent);
522
+ }
523
+ catch (error) {
524
+ return { ok: false, reasons: [`privacy guardrail parse failure: ${error.message}`] };
525
+ }
526
+ const complianceContext = spec.compliance_context;
527
+ const privacyControls = plan.privacy_controls;
528
+ const securityIntegrity = quality.security_integrity;
529
+ if (!complianceContext || complianceContext.source_refs.length === 0) {
530
+ reasons.push('spec.compliance_context.source_refs must include at least one canonical source reference');
531
+ }
532
+ if (!complianceContext || complianceContext.jurisdictions.length === 0) {
533
+ reasons.push('spec.compliance_context.jurisdictions must list at least one jurisdiction profile');
534
+ }
535
+ if (!privacyControls || privacyControls.source_registry_refs.length === 0) {
536
+ reasons.push('plan.privacy_controls.source_registry_refs must include at least one source registry link');
537
+ }
538
+ if (!privacyControls || privacyControls.jurisdiction_profiles.length === 0) {
539
+ reasons.push('plan.privacy_controls.jurisdiction_profiles must include at least one profile');
540
+ }
541
+ if (!privacyControls || privacyControls.control_ids.length === 0) {
542
+ reasons.push('plan.privacy_controls.control_ids must include at least one control');
543
+ }
544
+ const skillConformance = plan.skill_conformance;
545
+ if (!skillConformance || skillConformance.selected_skills.length === 0) {
546
+ reasons.push('plan.skill_conformance.selected_skills must list at least one selected skill');
547
+ }
548
+ if (feature.execution_kind !== 'documentation' &&
549
+ (!skillConformance || !(skillConformance.architecture_tree_ascii || '').trim())) {
550
+ reasons.push('plan.skill_conformance.architecture_tree_ascii is required for code-impacting features');
551
+ }
552
+ if (skillConformance &&
553
+ skillConformance.detected_conflicts.length > 0 &&
554
+ !(skillConformance.resolution_adr_ref || '').trim()) {
555
+ reasons.push('plan.skill_conformance.detected_conflicts requires resolution_adr_ref');
556
+ }
557
+ if (!securityIntegrity) {
558
+ reasons.push('quality.security_integrity block is required for privacy-compliance finalize');
559
+ return { ok: false, reasons };
560
+ }
561
+ const reviewStates = [
562
+ ['endpoint_auth_review', securityIntegrity.endpoint_auth_review],
563
+ ['sensitive_data_exposure_review', securityIntegrity.sensitive_data_exposure_review],
564
+ ['incident_response_review', securityIntegrity.incident_response_review],
565
+ ];
566
+ for (const [name, value] of reviewStates) {
567
+ if (value === 'pending') {
568
+ reasons.push(`quality.security_integrity.${name} cannot stay pending at finalize`);
569
+ }
570
+ if (value === 'failed') {
571
+ reasons.push(`quality.security_integrity.${name} is failed and requires remediation or formal exception`);
572
+ }
573
+ }
574
+ if (privacyControls?.legal_review_gate === 'required' && !complianceContext?.legal_review_required) {
575
+ reasons.push('plan.privacy_controls.legal_review_gate=required requires spec.compliance_context.legal_review_required=true');
576
+ }
577
+ return { ok: reasons.length === 0, reasons };
578
+ }
579
+ async function evaluateWorkspaceQualityFeedback(paths, config, feature) {
580
+ const activePath = path.join(paths.activeDir, feature.id);
581
+ const names = activeDocNamesForLayout(config);
582
+ const artifactName = [names.quality, ...activeDocCandidateNames(config)].find((name) => name === '5-quality.yaml' && existsSync(path.join(activePath, name))) || '';
583
+ if (!artifactName) {
584
+ return { ok: true, reasons: [], artifact: '' };
585
+ }
586
+ const artifactPath = path.join(activePath, artifactName);
587
+ const artifact = relProjectPath(paths, artifactPath);
588
+ const content = await fs.readFile(artifactPath, 'utf-8').catch(() => '');
589
+ if (!content.trim()) {
590
+ return { ok: false, reasons: [`quality artifact empty: ${artifact}`], artifact };
591
+ }
592
+ let document;
593
+ try {
594
+ document = parseWorkspaceYamlDocument('5-quality.yaml', content);
595
+ }
596
+ catch (err) {
597
+ return { ok: false, reasons: [`quality artifact YAML invalid: ${err.message}`], artifact };
598
+ }
599
+ const missingTargets = missingCoverageTargets(document);
600
+ const missingSkills = missingSkillEvidence(document);
601
+ const reasons = [];
602
+ const maxRounds = document.remediation_policy.max_rounds;
603
+ const rounds = countQualityEvidenceRounds(document);
604
+ if (rounds > maxRounds && document.exceptions.length === 0) {
605
+ reasons.push(`quality remediation max_rounds exceeded (${rounds}/${maxRounds}); formal exception required in ${artifact}`);
606
+ }
607
+ if (missingTargets.length > 0) {
608
+ const targetSummary = missingTargets
609
+ .map((target) => `${target.kind} >= ${target.target}`)
610
+ .join(', ');
611
+ if (document.remediation_policy.on_coverage_miss === 're_task') {
612
+ reasons.push(`coverage targets not met for ${targetSummary}; create a new task round before finalize`);
613
+ }
614
+ else if (document.remediation_policy.on_coverage_miss === 'block') {
615
+ reasons.push(`coverage targets not met for ${targetSummary}`);
616
+ }
617
+ else if (document.exceptions.length === 0) {
618
+ reasons.push(`coverage targets not met for ${targetSummary}; remediation_policy=exception requires exceptions[]`);
619
+ }
620
+ }
621
+ if (missingSkills.length > 0) {
622
+ reasons.push(`required skill evidence missing for ${missingSkills.join(', ')}`);
623
+ }
624
+ return { ok: reasons.length === 0, reasons, artifact };
625
+ }
626
+ async function evaluateWorkspaceTraceabilityFeedback(paths, config, feature) {
627
+ const activePath = path.join(paths.activeDir, feature.id);
628
+ const names = activeDocNamesForLayout(config);
629
+ const specPath = path.join(activePath, names.spec);
630
+ const changelogPath = path.join(activePath, names.changelog);
631
+ const qualityPath = path.join(activePath, names.quality);
632
+ const artifact = relProjectPath(paths, qualityPath);
633
+ const [specContent, changelogContent, qualityContent] = await Promise.all([
634
+ fs.readFile(specPath, 'utf-8').catch(() => ''),
635
+ fs.readFile(changelogPath, 'utf-8').catch(() => ''),
636
+ fs.readFile(qualityPath, 'utf-8').catch(() => ''),
637
+ ]);
638
+ if (!specContent.trim() || !changelogContent.trim() || !qualityContent.trim()) {
639
+ return {
640
+ ok: false,
641
+ artifact,
642
+ reasons: [
643
+ `traceability requires 1-spec.yaml, 4-changelog.yaml, and 5-quality.yaml in ${relProjectPath(paths, activePath)}`,
644
+ ],
645
+ };
646
+ }
647
+ let spec;
648
+ let changelog;
649
+ let quality;
650
+ try {
651
+ spec = parseWorkspaceYamlDocument('1-spec.yaml', specContent);
652
+ changelog = parseWorkspaceYamlDocument('4-changelog.yaml', changelogContent);
653
+ quality = parseWorkspaceYamlDocument('5-quality.yaml', qualityContent);
654
+ }
655
+ catch (error) {
656
+ return {
657
+ ok: false,
658
+ artifact,
659
+ reasons: [`traceability workspace YAML invalid: ${error.message}`],
660
+ };
661
+ }
662
+ const result = evaluateWorkspaceTraceability(paths.projectRoot, spec, changelog, quality);
663
+ return {
664
+ ok: result.ok,
665
+ reasons: result.reasons,
666
+ artifact,
667
+ };
668
+ }
669
+ function missingCoverageTargets(document) {
670
+ const targets = [
671
+ { kind: 'unit', target: document.coverage_targets.unit },
672
+ { kind: 'integration', target: document.coverage_targets.integration },
673
+ ];
674
+ return targets.filter((target) => !coverageTargetMet(document, target.kind, target.target));
675
+ }
676
+ function coverageTargetMet(document, kind, target) {
677
+ return document.evidence_log.some((entry) => {
678
+ const evidenceKind = entry.kind.toLowerCase();
679
+ const result = entry.result.toLowerCase();
680
+ const relevant = evidenceKind.includes(kind) ||
681
+ evidenceKind.includes('coverage') ||
682
+ (kind === 'integration' && evidenceKind.includes('e2e'));
683
+ if (!relevant) {
684
+ return false;
685
+ }
686
+ const percentages = result.match(/\d+(?:\.\d+)?/g)?.map(Number) ?? [];
687
+ return percentages.some((value) => value >= target);
688
+ });
689
+ }
690
+ function countQualityEvidenceRounds(document) {
691
+ const roundKinds = ['round', 'unit', 'integration', 'e2e', 'coverage', 'validation', 'test', 'build'];
692
+ return document.evidence_log.filter((entry) => {
693
+ const kind = entry.kind.toLowerCase();
694
+ return roundKinds.some((token) => kind.includes(token));
695
+ }).length;
696
+ }
697
+ function missingSkillEvidence(document) {
698
+ const required = Array.from(new Set((document.skill_evidence?.required_skill_ids ?? []).map((value) => value.trim()).filter(Boolean)));
699
+ if (required.length === 0) {
700
+ return [];
701
+ }
702
+ const provided = new Set((document.skill_evidence?.evidence ?? [])
703
+ .map((entry) => entry.skill_id.trim().toLowerCase())
704
+ .filter(Boolean));
705
+ return required.filter((skillId) => !provided.has(skillId.toLowerCase()));
706
+ }
707
+ //# sourceMappingURL=finalize.service.js.map