@devtrack-solution/codesdd 1.2.2 → 1.2.4-rc3

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 (413) hide show
  1. package/.sdd/skills/curated/api-clean-flask-langgraph/SKILL.md +17 -17
  2. package/.sdd/skills/curated/devtrack-api/SKILL.md +170 -31
  3. package/.sdd/skills/curated/devtrack-api/agents/claude-code.yaml +8 -0
  4. package/.sdd/skills/curated/devtrack-api/agents/codex.yaml +8 -0
  5. package/.sdd/skills/curated/devtrack-api/agents/cursor.yaml +8 -0
  6. package/.sdd/skills/curated/devtrack-api/agents/gemini.yaml +8 -0
  7. package/.sdd/skills/curated/devtrack-api/agents/kimi.yaml +8 -0
  8. package/.sdd/skills/curated/devtrack-api/agents/openai.yaml +4 -2
  9. package/.sdd/skills/curated/devtrack-api/agents/opencode.yaml +10 -0
  10. package/.sdd/skills/curated/devtrack-api/references/application-presentation.md +2 -2
  11. package/.sdd/skills/curated/devtrack-api/references/architecture-governance.md +8 -7
  12. package/.sdd/skills/curated/devtrack-api/references/consumer-sync-policy.md +93 -0
  13. package/.sdd/skills/curated/devtrack-api/references/contract-pack.yaml +372 -0
  14. package/.sdd/skills/curated/devtrack-api/references/domain-modeling.md +13 -13
  15. package/.sdd/skills/curated/devtrack-api/references/field-validation-protocol.md +95 -0
  16. package/.sdd/skills/curated/devtrack-api/references/foundation-layout.md +294 -0
  17. package/.sdd/skills/curated/devtrack-api/references/implementation-checklist.md +5 -5
  18. package/.sdd/skills/curated/devtrack-api/references/imports-lint.md +4 -0
  19. package/.sdd/skills/curated/devtrack-api/references/portable-agent-contract.md +41 -0
  20. package/.sdd/skills/curated/devtrack-api/references/testing-validation.md +2 -2
  21. package/.sdd/skills/curated/devtrack-api/references/typeorm-infrastructure.md +7 -9
  22. package/LICENSE +1 -1
  23. package/README.md +399 -53
  24. package/bin/codesdd.js +3 -2
  25. package/dist/applications/sdd/index.d.ts +16 -0
  26. package/dist/applications/sdd/index.js +16 -0
  27. package/dist/cli/index.d.ts +2 -2
  28. package/dist/cli/index.js +11 -558
  29. package/dist/cli/program.d.ts +14 -0
  30. package/dist/cli/program.js +645 -0
  31. package/dist/commands/change.js +5 -5
  32. package/dist/commands/completion.d.ts +1 -1
  33. package/dist/commands/completion.js +9 -2
  34. package/dist/commands/config.js +320 -20
  35. package/dist/commands/feedback.js +1 -1
  36. package/dist/commands/schema.d.ts +63 -0
  37. package/dist/commands/schema.js +12 -12
  38. package/dist/commands/sdd/backlog.d.ts +3 -0
  39. package/dist/commands/sdd/backlog.js +54 -0
  40. package/dist/commands/sdd/execution.js +489 -28
  41. package/dist/commands/sdd/plugin.d.ts +3 -0
  42. package/dist/commands/sdd/plugin.js +158 -0
  43. package/dist/commands/sdd/shared.d.ts +1 -0
  44. package/dist/commands/sdd/shared.js +11 -22
  45. package/dist/commands/sdd/skills.js +7 -0
  46. package/dist/commands/sdd.js +107 -15
  47. package/dist/commands/spec.js +9 -9
  48. package/dist/commands/validate.js +6 -6
  49. package/dist/commands/workflow/instructions.js +6 -6
  50. package/dist/commands/workflow/new-change.js +3 -3
  51. package/dist/commands/workflow/shared.d.ts +1 -1
  52. package/dist/commands/workflow/shared.js +4 -4
  53. package/dist/core/archive.js +15 -5
  54. package/dist/core/artifact-graph/instruction-loader.d.ts +1 -1
  55. package/dist/core/artifact-graph/instruction-loader.js +3 -3
  56. package/dist/core/artifact-graph/resolver.d.ts +4 -4
  57. package/dist/core/artifact-graph/resolver.js +6 -6
  58. package/dist/core/branding.js +3 -3
  59. package/dist/core/cli/command-matrix.js +19 -1
  60. package/dist/core/cli-command-quality.d.ts +27 -0
  61. package/dist/core/cli-command-quality.js +180 -0
  62. package/dist/core/command-generation/adapters/costrict.d.ts +1 -1
  63. package/dist/core/command-generation/adapters/costrict.js +2 -2
  64. package/dist/core/command-generation/types.d.ts +1 -1
  65. package/dist/core/completions/command-registry.d.ts +1 -1
  66. package/dist/core/completions/command-registry.js +200 -12
  67. package/dist/core/completions/completion-provider.d.ts +14 -1
  68. package/dist/core/completions/completion-provider.js +29 -1
  69. package/dist/core/completions/generators/bash-generator.d.ts +1 -1
  70. package/dist/core/completions/generators/bash-generator.js +20 -12
  71. package/dist/core/completions/generators/fish-generator.d.ts +9 -1
  72. package/dist/core/completions/generators/fish-generator.js +39 -25
  73. package/dist/core/completions/generators/powershell-generator.d.ts +1 -1
  74. package/dist/core/completions/generators/powershell-generator.js +21 -11
  75. package/dist/core/completions/generators/zsh-generator.d.ts +3 -6
  76. package/dist/core/completions/generators/zsh-generator.js +21 -42
  77. package/dist/core/completions/installers/bash-installer.js +6 -6
  78. package/dist/core/completions/installers/fish-installer.js +1 -1
  79. package/dist/core/completions/installers/powershell-installer.js +14 -14
  80. package/dist/core/completions/installers/zsh-installer.d.ts +7 -1
  81. package/dist/core/completions/installers/zsh-installer.js +36 -8
  82. package/dist/core/completions/templates/bash-templates.d.ts +1 -1
  83. package/dist/core/completions/templates/bash-templates.js +12 -6
  84. package/dist/core/completions/templates/fish-templates.d.ts +2 -2
  85. package/dist/core/completions/templates/fish-templates.js +20 -9
  86. package/dist/core/completions/templates/powershell-templates.d.ts +1 -1
  87. package/dist/core/completions/templates/powershell-templates.js +13 -4
  88. package/dist/core/completions/templates/zsh-templates.d.ts +1 -1
  89. package/dist/core/completions/templates/zsh-templates.js +18 -9
  90. package/dist/core/config-schema.d.ts +20 -1
  91. package/dist/core/config-schema.js +70 -2
  92. package/dist/core/config.d.ts +3 -3
  93. package/dist/core/config.js +4 -4
  94. package/dist/core/global-config.d.ts +57 -12
  95. package/dist/core/global-config.js +344 -27
  96. package/dist/core/index.d.ts +1 -1
  97. package/dist/core/index.js +2 -2
  98. package/dist/core/init.d.ts +6 -1
  99. package/dist/core/init.js +99 -77
  100. package/dist/core/legacy-cleanup.d.ts +17 -17
  101. package/dist/core/legacy-cleanup.js +96 -79
  102. package/dist/core/list.js +18 -4
  103. package/dist/core/migration.d.ts +3 -1
  104. package/dist/core/migration.js +7 -8
  105. package/dist/core/parsers/change-parser.js +1 -1
  106. package/dist/core/parsers/markdown-parser.js +2 -2
  107. package/dist/core/profile-sync-drift.d.ts +1 -1
  108. package/dist/core/profile-sync-drift.js +13 -13
  109. package/dist/core/project-config.d.ts +4 -4
  110. package/dist/core/project-config.js +11 -11
  111. package/dist/core/schemas/change.schema.d.ts +1 -1
  112. package/dist/core/schemas/change.schema.js +1 -1
  113. package/dist/core/schemas/spec.schema.d.ts +1 -1
  114. package/dist/core/schemas/spec.schema.js +1 -1
  115. package/dist/core/sdd/adr.js +23 -1
  116. package/dist/core/sdd/agent-binding.d.ts +346 -0
  117. package/dist/core/sdd/agent-binding.js +343 -0
  118. package/dist/core/sdd/agent-runtime-contract.d.ts +204 -0
  119. package/dist/core/sdd/agent-runtime-contract.js +200 -0
  120. package/dist/core/sdd/backlog-cli.d.ts +16 -0
  121. package/dist/core/sdd/backlog-cli.js +146 -0
  122. package/dist/core/sdd/backlog-conflict-policy.d.ts +58 -0
  123. package/dist/core/sdd/backlog-conflict-policy.js +230 -0
  124. package/dist/core/sdd/backlog-projection.d.ts +8 -0
  125. package/dist/core/sdd/backlog-projection.js +89 -0
  126. package/dist/core/sdd/backlog-provider-contract.d.ts +252 -0
  127. package/dist/core/sdd/backlog-provider-contract.js +158 -0
  128. package/dist/core/sdd/bootstrap.js +2 -2
  129. package/dist/core/sdd/check.d.ts +44 -0
  130. package/dist/core/sdd/check.js +62 -24
  131. package/dist/core/sdd/contract.d.ts +13 -0
  132. package/dist/core/sdd/contract.js +36 -0
  133. package/dist/core/sdd/coordination/coordination-adapters.d.ts +53 -8
  134. package/dist/core/sdd/coordination/coordination-adapters.js +182 -16
  135. package/dist/core/sdd/coordination/index.d.ts +1 -0
  136. package/dist/core/sdd/coordination/index.js +1 -0
  137. package/dist/core/sdd/coordination/redis-runtime.d.ts +131 -0
  138. package/dist/core/sdd/coordination/redis-runtime.js +698 -0
  139. package/dist/core/sdd/deepagent-contracts.d.ts +370 -0
  140. package/dist/core/sdd/deepagent-contracts.js +235 -0
  141. package/dist/core/sdd/deepagents/adr-governor.d.ts +2 -0
  142. package/dist/core/sdd/deepagents/adr-governor.js +30 -0
  143. package/dist/core/sdd/deepagents/backend.d.ts +63 -0
  144. package/dist/core/sdd/deepagents/backend.js +174 -0
  145. package/dist/core/sdd/deepagents/codesdd-tools.d.ts +39 -0
  146. package/dist/core/sdd/deepagents/codesdd-tools.js +83 -0
  147. package/dist/core/sdd/deepagents/evidence-mapper.d.ts +86 -0
  148. package/dist/core/sdd/deepagents/evidence-mapper.js +178 -0
  149. package/dist/core/sdd/deepagents/model-provider.d.ts +53 -0
  150. package/dist/core/sdd/deepagents/model-provider.js +379 -0
  151. package/dist/core/sdd/deepagents/policy-enforcement.d.ts +30 -0
  152. package/dist/core/sdd/deepagents/policy-enforcement.js +90 -0
  153. package/dist/core/sdd/deepagents/policy.d.ts +75 -0
  154. package/dist/core/sdd/deepagents/policy.js +358 -0
  155. package/dist/core/sdd/deepagents/quality-witness.d.ts +3 -0
  156. package/dist/core/sdd/deepagents/quality-witness.js +77 -0
  157. package/dist/core/sdd/deepagents/reversa-subagents.d.ts +75 -0
  158. package/dist/core/sdd/deepagents/reversa-subagents.js +182 -0
  159. package/dist/core/sdd/deepagents/runtime-factory.d.ts +90 -0
  160. package/dist/core/sdd/deepagents/runtime-factory.js +231 -0
  161. package/dist/core/sdd/deepagents/runtime-loader.d.ts +16 -0
  162. package/dist/core/sdd/deepagents/runtime-loader.js +65 -0
  163. package/dist/core/sdd/default-bootstrap-files.d.ts +3 -3
  164. package/dist/core/sdd/default-bootstrap-files.js +50 -10
  165. package/dist/core/sdd/default-skills.d.ts +30 -0
  166. package/dist/core/sdd/default-skills.js +288 -8
  167. package/dist/core/sdd/devtrack-api-appliance.d.ts +91 -0
  168. package/dist/core/sdd/devtrack-api-appliance.js +280 -0
  169. package/dist/core/sdd/devtrack-api-architecture.d.ts +31 -0
  170. package/dist/core/sdd/devtrack-api-architecture.js +608 -0
  171. package/dist/core/sdd/devtrack-api-import-boundary.d.ts +19 -0
  172. package/dist/core/sdd/devtrack-api-import-boundary.js +32 -0
  173. package/dist/core/sdd/diagnose.d.ts +59 -0
  174. package/dist/core/sdd/diagnose.js +37 -37
  175. package/dist/core/sdd/docs-sync.js +54 -20
  176. package/dist/core/sdd/domain/capability-diff.d.ts +63 -0
  177. package/dist/core/sdd/domain/capability-diff.js +200 -0
  178. package/dist/core/sdd/domain/change-safety-guardrails.d.ts +74 -0
  179. package/dist/core/sdd/domain/change-safety-guardrails.js +333 -0
  180. package/dist/core/sdd/domain/post-active-validation.d.ts +7 -0
  181. package/dist/core/sdd/domain/post-active-validation.js +61 -0
  182. package/dist/core/sdd/domain/semantic-intent-classifier.d.ts +29 -0
  183. package/dist/core/sdd/domain/semantic-intent-classifier.js +117 -0
  184. package/dist/core/sdd/domain/transition-engine.js +1 -0
  185. package/dist/core/sdd/entity-reference.d.ts +5 -0
  186. package/dist/core/sdd/entity-reference.js +22 -0
  187. package/dist/core/sdd/foundation-artifact-map-validator.d.ts +16 -0
  188. package/dist/core/sdd/foundation-artifact-map-validator.js +71 -0
  189. package/dist/core/sdd/foundation-layer-manifest.d.ts +24 -0
  190. package/dist/core/sdd/foundation-layer-manifest.js +117 -0
  191. package/dist/core/sdd/governance-backfill.d.ts +31 -0
  192. package/dist/core/sdd/governance-backfill.js +359 -0
  193. package/dist/core/sdd/governance-parser.d.ts +21 -0
  194. package/dist/core/sdd/governance-parser.js +91 -0
  195. package/dist/core/sdd/governance-schemas.d.ts +245 -0
  196. package/dist/core/sdd/governance-schemas.js +143 -0
  197. package/dist/core/sdd/{import-openspec.d.ts → import-legacy-spec.d.ts} +7 -7
  198. package/dist/core/sdd/{import-openspec.js → import-legacy-spec.js} +21 -29
  199. package/dist/core/sdd/init.d.ts +3 -0
  200. package/dist/core/sdd/init.js +6 -3
  201. package/dist/core/sdd/intent-guard.d.ts +22 -0
  202. package/dist/core/sdd/intent-guard.js +67 -0
  203. package/dist/core/sdd/json-schema.js +108 -6
  204. package/dist/core/sdd/knowledge-graph.d.ts +45 -0
  205. package/dist/core/sdd/knowledge-graph.js +288 -0
  206. package/dist/core/sdd/legacy-operations.js +507 -44
  207. package/dist/core/sdd/lenses.d.ts +1 -0
  208. package/dist/core/sdd/lenses.js +29 -1
  209. package/dist/core/sdd/migrate-workspace.js +95 -2
  210. package/dist/core/sdd/migrate.d.ts +1 -1
  211. package/dist/core/sdd/migrate.js +36 -2
  212. package/dist/core/sdd/package-security-gates.d.ts +21 -0
  213. package/dist/core/sdd/package-security-gates.js +119 -0
  214. package/dist/core/sdd/package-structure-gate.d.ts +83 -0
  215. package/dist/core/sdd/package-structure-gate.js +357 -0
  216. package/dist/core/sdd/parallel-feat-automation.d.ts +330 -0
  217. package/dist/core/sdd/parallel-feat-automation.js +424 -0
  218. package/dist/core/sdd/plugin-broker.d.ts +777 -0
  219. package/dist/core/sdd/plugin-broker.js +492 -0
  220. package/dist/core/sdd/plugin-certification.d.ts +79 -0
  221. package/dist/core/sdd/plugin-certification.js +453 -0
  222. package/dist/core/sdd/plugin-cli.d.ts +139 -0
  223. package/dist/core/sdd/plugin-cli.js +265 -0
  224. package/dist/core/sdd/plugin-evidence.d.ts +348 -0
  225. package/dist/core/sdd/plugin-evidence.js +307 -0
  226. package/dist/core/sdd/plugin-manifest.d.ts +232 -0
  227. package/dist/core/sdd/plugin-manifest.js +225 -0
  228. package/dist/core/sdd/plugin-policy-pack.d.ts +88 -0
  229. package/dist/core/sdd/plugin-policy-pack.js +236 -0
  230. package/dist/core/sdd/plugin-policy.d.ts +68 -0
  231. package/dist/core/sdd/plugin-policy.js +212 -0
  232. package/dist/core/sdd/plugin-registry.d.ts +447 -0
  233. package/dist/core/sdd/plugin-registry.js +138 -0
  234. package/dist/core/sdd/plugin-sdk-contract.d.ts +363 -0
  235. package/dist/core/sdd/plugin-sdk-contract.js +268 -0
  236. package/dist/core/sdd/plugin-skill-binding.d.ts +151 -0
  237. package/dist/core/sdd/plugin-skill-binding.js +339 -0
  238. package/dist/core/sdd/quality-artifact-manifest-validator.d.ts +28 -0
  239. package/dist/core/sdd/quality-artifact-manifest-validator.js +167 -0
  240. package/dist/core/sdd/quality-evidence-renderer.d.ts +65 -0
  241. package/dist/core/sdd/quality-evidence-renderer.js +218 -0
  242. package/dist/core/sdd/quality-scenario-runner.d.ts +42 -0
  243. package/dist/core/sdd/quality-scenario-runner.js +613 -0
  244. package/dist/core/sdd/quality-validation.d.ts +620 -0
  245. package/dist/core/sdd/quality-validation.js +239 -0
  246. package/dist/core/sdd/release-readiness.d.ts +19 -0
  247. package/dist/core/sdd/release-readiness.js +472 -0
  248. package/dist/core/sdd/resolve-project-root.d.ts +2 -2
  249. package/dist/core/sdd/resolve-project-root.js +11 -5
  250. package/dist/core/sdd/runtime-boundary-contract.d.ts +45 -0
  251. package/dist/core/sdd/runtime-boundary-contract.js +90 -0
  252. package/dist/core/sdd/sanitize.d.ts +30 -1
  253. package/dist/core/sdd/sanitize.js +23 -23
  254. package/dist/core/sdd/sdk-agent-plugin-quality-gates.d.ts +150 -0
  255. package/dist/core/sdd/sdk-agent-plugin-quality-gates.js +258 -0
  256. package/dist/core/sdd/services/agent-run.service.d.ts +97 -0
  257. package/dist/core/sdd/services/agent-run.service.js +261 -0
  258. package/dist/core/sdd/services/breakdown.service.js +2 -1
  259. package/dist/core/sdd/services/capability-diff.service.d.ts +18 -0
  260. package/dist/core/sdd/services/capability-diff.service.js +26 -0
  261. package/dist/core/sdd/services/change-safety-preflight.service.d.ts +17 -0
  262. package/dist/core/sdd/services/change-safety-preflight.service.js +17 -0
  263. package/dist/core/sdd/services/context.service.d.ts +43 -340
  264. package/dist/core/sdd/services/context.service.js +341 -25
  265. package/dist/core/sdd/services/debate.service.js +15 -2
  266. package/dist/core/sdd/services/feature-lint.service.d.ts +22 -0
  267. package/dist/core/sdd/services/feature-lint.service.js +105 -5
  268. package/dist/core/sdd/services/finalize.service.d.ts +105 -0
  269. package/dist/core/sdd/services/finalize.service.js +499 -38
  270. package/dist/core/sdd/services/frontend-gap.service.js +22 -7
  271. package/dist/core/sdd/services/frontend-impact.service.d.ts +1 -1
  272. package/dist/core/sdd/services/governance-control-plane-runtime-adapters.d.ts +17 -0
  273. package/dist/core/sdd/services/governance-control-plane-runtime-adapters.js +38 -0
  274. package/dist/core/sdd/services/governance-control-plane.service.d.ts +66 -0
  275. package/dist/core/sdd/services/governance-control-plane.service.js +134 -0
  276. package/dist/core/sdd/services/ingest-deposito.service.js +1 -1
  277. package/dist/core/sdd/services/legacy-capability.service.d.ts +10 -7
  278. package/dist/core/sdd/services/legacy-capability.service.js +38 -21
  279. package/dist/core/sdd/services/mcp-runtime.service.d.ts +123 -8
  280. package/dist/core/sdd/services/mcp-runtime.service.js +1085 -33
  281. package/dist/core/sdd/services/onboard.service.js +2 -1
  282. package/dist/core/sdd/services/rebuild.service.js +6 -1
  283. package/dist/core/sdd/services/semantic-intent-classifier.service.d.ts +6 -0
  284. package/dist/core/sdd/services/semantic-intent-classifier.service.js +7 -0
  285. package/dist/core/sdd/services/skills-sync.service.d.ts +17 -5
  286. package/dist/core/sdd/services/skills-sync.service.js +55 -2
  287. package/dist/core/sdd/services/start.service.js +6 -4
  288. package/dist/core/sdd/skill-bundles-curation-schema.d.ts +66 -0
  289. package/dist/core/sdd/skill-bundles-curation-schema.js +52 -0
  290. package/dist/core/sdd/skill-evidence.d.ts +19 -0
  291. package/dist/core/sdd/skill-evidence.js +38 -0
  292. package/dist/core/sdd/skill-policy-pool.d.ts +46 -0
  293. package/dist/core/sdd/skill-policy-pool.js +185 -0
  294. package/dist/core/sdd/state.d.ts +23 -0
  295. package/dist/core/sdd/state.js +313 -66
  296. package/dist/core/sdd/store/sdd-stores.js +2 -2
  297. package/dist/core/sdd/structural-health.d.ts +55 -55
  298. package/dist/core/sdd/types.d.ts +60 -19
  299. package/dist/core/sdd/types.js +21 -0
  300. package/dist/core/sdd/upgrade-to-codesdd.d.ts +45 -0
  301. package/dist/core/sdd/upgrade-to-codesdd.js +179 -0
  302. package/dist/core/sdd/views.js +17 -0
  303. package/dist/core/sdd/workspace-schemas.d.ts +670 -19
  304. package/dist/core/sdd/workspace-schemas.js +285 -5
  305. package/dist/core/sdd/write-manifest.js +22 -4
  306. package/dist/core/shared/skill-generation.d.ts +1 -1
  307. package/dist/core/shared/skill-generation.js +15 -15
  308. package/dist/core/shared/tool-detection.d.ts +3 -3
  309. package/dist/core/shared/tool-detection.js +14 -14
  310. package/dist/core/specs-apply.js +6 -6
  311. package/dist/core/templates/index.d.ts +1 -1
  312. package/dist/core/templates/index.js +1 -1
  313. package/dist/core/templates/workflows/apply-change.js +14 -14
  314. package/dist/core/templates/workflows/archive-change.js +32 -32
  315. package/dist/core/templates/workflows/bulk-archive-change.js +25 -25
  316. package/dist/core/templates/workflows/continue-change.js +12 -12
  317. package/dist/core/templates/workflows/explore.js +29 -29
  318. package/dist/core/templates/workflows/feedback.js +6 -6
  319. package/dist/core/templates/workflows/ff-change.js +24 -24
  320. package/dist/core/templates/workflows/new-change.js +20 -20
  321. package/dist/core/templates/workflows/onboard.js +33 -33
  322. package/dist/core/templates/workflows/propose.js +23 -23
  323. package/dist/core/templates/workflows/sdd.js +8 -8
  324. package/dist/core/templates/workflows/sync-specs.js +19 -19
  325. package/dist/core/templates/workflows/verify-change.js +17 -17
  326. package/dist/core/update.d.ts +2 -2
  327. package/dist/core/update.js +16 -15
  328. package/dist/core/validation/constants.d.ts +1 -1
  329. package/dist/core/validation/constants.js +1 -1
  330. package/dist/core/view.js +11 -11
  331. package/dist/domains/sdd/index.d.ts +6 -0
  332. package/dist/domains/sdd/index.js +6 -0
  333. package/dist/infrastructures/sdd/index.d.ts +7 -0
  334. package/dist/infrastructures/sdd/index.js +6 -0
  335. package/dist/presentations/cli/sdd/index.d.ts +3 -0
  336. package/dist/presentations/cli/sdd/index.js +3 -0
  337. package/dist/shared/sdd/index.d.ts +3 -0
  338. package/dist/shared/sdd/index.js +2 -0
  339. package/dist/telemetry/config.d.ts +2 -1
  340. package/dist/telemetry/config.js +17 -8
  341. package/dist/telemetry/index.d.ts +10 -2
  342. package/dist/telemetry/index.js +40 -7
  343. package/dist/ui/ascii-patterns.d.ts +2 -2
  344. package/dist/ui/ascii-patterns.js +2 -2
  345. package/dist/ui/welcome-screen.js +2 -2
  346. package/dist/utils/change-metadata.d.ts +4 -4
  347. package/dist/utils/change-metadata.js +6 -6
  348. package/dist/utils/change-utils.d.ts +3 -3
  349. package/dist/utils/change-utils.js +5 -5
  350. package/dist/utils/file-system.js +1 -1
  351. package/dist/utils/interactive.js +1 -1
  352. package/dist/utils/item-discovery.js +4 -4
  353. package/dist/utils/legacy-spec-compat.d.ts +2 -0
  354. package/dist/utils/legacy-spec-compat.js +2 -0
  355. package/dist/utils/shell-detection.d.ts +1 -0
  356. package/dist/utils/shell-detection.js +16 -0
  357. package/package.json +34 -21
  358. package/schemas/sdd/1-spec.schema.json +1 -1
  359. package/schemas/sdd/2-plan.schema.json +280 -3
  360. package/schemas/sdd/3-tasks.schema.json +73 -1
  361. package/schemas/sdd/4-changelog.schema.json +1 -1
  362. package/schemas/sdd/5-quality.schema.json +701 -5
  363. package/schemas/sdd/adr.schema.json +148 -0
  364. package/schemas/sdd/agent-binding-adapter.schema.json +210 -0
  365. package/schemas/sdd/agent-binding-resolution.schema.json +338 -0
  366. package/schemas/sdd/agent-runtime-command-plan.schema.json +212 -0
  367. package/schemas/sdd/agent-runtime-opencode-run-evidence.schema.json +270 -0
  368. package/schemas/sdd/backlog-projection-plan.schema.json +180 -0
  369. package/schemas/sdd/backlog-provider-contract.schema.json +260 -0
  370. package/schemas/sdd/codesdd-plugin.schema.json +645 -0
  371. package/schemas/sdd/debate.schema.json +244 -0
  372. package/schemas/sdd/deepagent-decision-evidence.schema.json +58 -0
  373. package/schemas/sdd/deepagent-env-contract.schema.json +143 -0
  374. package/schemas/sdd/deepagent-quality-evidence.schema.json +108 -0
  375. package/schemas/sdd/deepagent-run-evidence.schema.json +192 -0
  376. package/schemas/sdd/deepagent-run-plan.schema.json +197 -0
  377. package/schemas/sdd/deepagent-run-request.schema.json +637 -0
  378. package/schemas/sdd/deepagent-subagent-evidence.schema.json +110 -0
  379. package/schemas/sdd/deepagent-tool-call-evidence.schema.json +78 -0
  380. package/schemas/sdd/discarded.schema.json +127 -0
  381. package/schemas/sdd/epic.schema.json +147 -0
  382. package/schemas/sdd/insight.schema.json +136 -0
  383. package/schemas/sdd/parallel-feat-automation-plan.schema.json +304 -0
  384. package/schemas/sdd/parallel-feat-automation-request.schema.json +109 -0
  385. package/schemas/sdd/parallel-feat-scheduler-request.schema.json +116 -0
  386. package/schemas/sdd/parallel-feat-scheduler-result.schema.json +404 -0
  387. package/schemas/sdd/plugin-artifact-manifest.schema.json +259 -0
  388. package/schemas/sdd/plugin-artifact-map.schema.json +223 -0
  389. package/schemas/sdd/plugin-compliance-index.schema.json +136 -0
  390. package/schemas/sdd/plugin-dry-run-plan.schema.json +260 -0
  391. package/schemas/sdd/plugin-evidence-manifest.schema.json +678 -0
  392. package/schemas/sdd/plugin-language-runtime.schema.json +103 -0
  393. package/schemas/sdd/plugin-package-governance.schema.json +74 -0
  394. package/schemas/sdd/plugin-policy-evaluation.schema.json +92 -0
  395. package/schemas/sdd/plugin-policy-pack-evaluation.schema.json +94 -0
  396. package/schemas/sdd/plugin-policy-pack.schema.json +196 -0
  397. package/schemas/sdd/plugin-registry.schema.json +729 -0
  398. package/schemas/sdd/plugin-rollback-manifest.schema.json +87 -0
  399. package/schemas/sdd/plugin-runtime-invocation-plan.schema.json +954 -0
  400. package/schemas/sdd/plugin-skill-binding-resolution.schema.json +305 -0
  401. package/schemas/sdd/plugin-skill-binding.schema.json +88 -0
  402. package/schemas/sdd/plugin-validation-manifest.schema.json +123 -0
  403. package/schemas/sdd/quality-architecture-schema.schema.json +216 -0
  404. package/schemas/sdd/quality-evidence-bundle.schema.json +1337 -0
  405. package/schemas/sdd/quality-run.schema.json +197 -0
  406. package/schemas/sdd/quality-scenario.schema.json +252 -0
  407. package/schemas/sdd/sdk-agent-plugin-quality-gate-input.schema.json +168 -0
  408. package/schemas/sdd/sdk-agent-plugin-quality-gate-report.schema.json +160 -0
  409. package/schemas/sdd/workspace-catalog.schema.json +13232 -35
  410. package/schemas/spec-driven/schema.yaml +4 -4
  411. package/schemas/spec-driven/templates/proposal.md +1 -1
  412. package/dist/utils/openspec-compat.d.ts +0 -2
  413. package/dist/utils/openspec-compat.js +0 -2
@@ -0,0 +1,339 @@
1
+ import { z } from 'zod';
2
+ import { pluginRegistryStateSchema, } from './plugin-registry.js';
3
+ const FEATURE_REF_PATTERN = /^FEAT-\d{4}$/;
4
+ const PLUGIN_ID_PATTERN = /^codesdd-plugin-[a-z0-9][a-z0-9-]*$/;
5
+ const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
6
+ const CAPABILITY_NAME_PATTERN = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+$/;
7
+ const SKILL_ID_PATTERN = /^[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)*$/;
8
+ const TRUST_RANK = {
9
+ 'enterprise-approved': 3,
10
+ 'local-dev': 2,
11
+ experimental: 1,
12
+ blocked: 0,
13
+ };
14
+ const RISK_RANK = {
15
+ low: 4,
16
+ medium: 3,
17
+ high: 2,
18
+ critical: 1,
19
+ };
20
+ const bindingStatusSchema = z.enum(['active', 'disabled', 'deprecated']);
21
+ const pluginTrustTierSchema = z.enum(['local-dev', 'experimental', 'enterprise-approved', 'blocked']);
22
+ const pluginRegistryStatusSchema = z.enum(['active', 'disabled', 'blocked', 'deprecated']);
23
+ const capabilityNameSchema = z.string().regex(CAPABILITY_NAME_PATTERN);
24
+ const skillIdSchema = z.string().regex(SKILL_ID_PATTERN);
25
+ const pluginIdSchema = z.string().regex(PLUGIN_ID_PATTERN);
26
+ export const pluginSkillBindingSchema = z
27
+ .object({
28
+ schema_version: z.literal(1).default(1),
29
+ skill_id: skillIdSchema,
30
+ plugin_id: pluginIdSchema,
31
+ plugin_version: z.string().regex(SEMVER_PATTERN).optional(),
32
+ capabilities: z.array(capabilityNameSchema).min(1),
33
+ operations: z.record(z.string().min(1), capabilityNameSchema).default({}),
34
+ priority: z.number().int().min(0).max(100).default(50),
35
+ status: bindingStatusSchema.default('active'),
36
+ rationale: z.string().min(1).optional(),
37
+ technology: z
38
+ .object({
39
+ language: z.string().min(1).optional(),
40
+ framework: z.string().min(1).optional(),
41
+ })
42
+ .optional(),
43
+ })
44
+ .superRefine((binding, context) => {
45
+ const seen = new Set();
46
+ for (const [index, capability] of binding.capabilities.entries()) {
47
+ if (seen.has(capability)) {
48
+ context.addIssue({
49
+ code: 'custom',
50
+ path: ['capabilities', index],
51
+ message: `Duplicate bound capability: ${capability}.`,
52
+ });
53
+ }
54
+ seen.add(capability);
55
+ }
56
+ for (const [operation, capability] of Object.entries(binding.operations)) {
57
+ if (!binding.capabilities.includes(capability)) {
58
+ context.addIssue({
59
+ code: 'custom',
60
+ path: ['operations', operation],
61
+ message: `Operation ${operation} targets ${capability}, which is not listed in capabilities.`,
62
+ });
63
+ }
64
+ }
65
+ });
66
+ export const pluginSkillBindingResolutionRequestSchema = z.object({
67
+ schema_version: z.literal(1).default(1),
68
+ feature_ref: z.string().regex(FEATURE_REF_PATTERN),
69
+ recommended_skills: z.array(skillIdSchema).default([]),
70
+ requested_operation: z.string().min(1).optional(),
71
+ requested_capability: capabilityNameSchema.optional(),
72
+ explicit_plugin_id: pluginIdSchema.optional(),
73
+ technology: z
74
+ .object({
75
+ language: z.string().min(1).optional(),
76
+ framework: z.string().min(1).optional(),
77
+ })
78
+ .optional(),
79
+ trust_tiers: z
80
+ .array(pluginTrustTierSchema)
81
+ .default(['enterprise-approved', 'local-dev', 'experimental']),
82
+ statuses: z.array(pluginRegistryStatusSchema).default(['active']),
83
+ require_apply: z.boolean().default(false),
84
+ require_dry_run: z.boolean().default(true),
85
+ created_at: z.string().datetime().optional(),
86
+ });
87
+ export const pluginSkillBindingCandidateSchema = z.object({
88
+ source: z.enum(['explicit-plugin', 'skill-binding', 'capability-match']),
89
+ skill_id: skillIdSchema.optional(),
90
+ plugin_ref: z.object({
91
+ id: pluginIdSchema,
92
+ version: z.string().regex(SEMVER_PATTERN),
93
+ }),
94
+ capability: capabilityNameSchema,
95
+ operation: z.string().min(1).optional(),
96
+ binding_priority: z.number().int().min(0).max(100).optional(),
97
+ rank: z.number().int().nonnegative(),
98
+ reasons: z.array(z.string()).default([]),
99
+ });
100
+ export const pluginSkillBindingResolutionSchema = z.object({
101
+ schema_version: z.literal(1),
102
+ created_at: z.string().datetime(),
103
+ status: z.enum(['resolved', 'fallback']),
104
+ request: pluginSkillBindingResolutionRequestSchema,
105
+ selected: pluginSkillBindingCandidateSchema.optional(),
106
+ candidates: z.array(pluginSkillBindingCandidateSchema).default([]),
107
+ reasons: z.array(z.string()).default([]),
108
+ fallback: z
109
+ .object({
110
+ strategy: z.enum(['manual-selection', 'llm-guidance', 'no-compatible-plugin']),
111
+ message: z.string().min(1),
112
+ })
113
+ .optional(),
114
+ });
115
+ export function resolvePluginSkillBinding(registryState, bindings, request) {
116
+ const registry = pluginRegistryStateSchema.parse(registryState);
117
+ const parsedBindings = bindings.map((binding) => pluginSkillBindingSchema.parse(binding));
118
+ const parsedRequest = pluginSkillBindingResolutionRequestSchema.parse(request);
119
+ const createdAt = parsedRequest.created_at ?? new Date().toISOString();
120
+ const reasons = [];
121
+ const candidates = [];
122
+ candidates.push(...collectExplicitPluginCandidates(registry.entries, parsedBindings, parsedRequest, reasons));
123
+ candidates.push(...collectSkillBindingCandidates(registry.entries, parsedBindings, parsedRequest, reasons));
124
+ candidates.push(...collectCapabilityFallbackCandidates(registry.entries, parsedRequest, reasons));
125
+ const sortedCandidates = dedupeCandidates(candidates).sort(compareCandidates);
126
+ const [selected] = sortedCandidates;
127
+ if (!selected) {
128
+ return pluginSkillBindingResolutionSchema.parse({
129
+ schema_version: 1,
130
+ created_at: createdAt,
131
+ status: 'fallback',
132
+ request: {
133
+ ...parsedRequest,
134
+ created_at: createdAt,
135
+ },
136
+ candidates: [],
137
+ reasons: reasons.length > 0 ? reasons : ['No compatible plugin binding or capability was found.'],
138
+ fallback: {
139
+ strategy: 'no-compatible-plugin',
140
+ message: 'Continue with skill guidance or manual plugin selection; no deterministic plugin invocation is available.',
141
+ },
142
+ });
143
+ }
144
+ return pluginSkillBindingResolutionSchema.parse({
145
+ schema_version: 1,
146
+ created_at: createdAt,
147
+ status: 'resolved',
148
+ request: {
149
+ ...parsedRequest,
150
+ created_at: createdAt,
151
+ },
152
+ selected,
153
+ candidates: sortedCandidates,
154
+ reasons: [
155
+ `Resolved ${selected.skill_id ?? '<no-skill>'} to ${selected.plugin_ref.id}@${selected.plugin_ref.version}/${selected.capability}.`,
156
+ ...selected.reasons,
157
+ ],
158
+ });
159
+ }
160
+ function collectExplicitPluginCandidates(entries, bindings, request, reasons) {
161
+ if (!request.explicit_plugin_id) {
162
+ return [];
163
+ }
164
+ const matchedEntries = entries.filter((entry) => entry.manifest.id === request.explicit_plugin_id);
165
+ if (matchedEntries.length === 0) {
166
+ reasons.push(`Explicit plugin ${request.explicit_plugin_id} is not registered.`);
167
+ return [];
168
+ }
169
+ return matchedEntries.flatMap((entry) => {
170
+ const bindingTargets = bindings
171
+ .filter((binding) => binding.plugin_id === request.explicit_plugin_id && binding.status === 'active')
172
+ .flatMap((binding) => targetCapabilitiesForBinding(binding, request));
173
+ const targets = bindingTargets.length > 0 ? bindingTargets : targetCapabilitiesForEntry(entry, request);
174
+ return targets.flatMap((capability) => buildCandidate(entry, request, reasons, {
175
+ source: 'explicit-plugin',
176
+ binding: bindings.find((binding) => binding.plugin_id === request.explicit_plugin_id && binding.capabilities.includes(capability)),
177
+ skillOrder: 0,
178
+ capability,
179
+ }));
180
+ });
181
+ }
182
+ function collectSkillBindingCandidates(entries, bindings, request, reasons) {
183
+ const recommendedOrder = new Map(request.recommended_skills.map((skillId, index) => [skillId, index]));
184
+ const candidates = [];
185
+ for (const binding of bindings) {
186
+ const skillOrder = recommendedOrder.get(binding.skill_id);
187
+ if (skillOrder === undefined) {
188
+ continue;
189
+ }
190
+ if (binding.status !== 'active') {
191
+ reasons.push(`Skill binding ${binding.skill_id} -> ${binding.plugin_id} is ${binding.status}.`);
192
+ continue;
193
+ }
194
+ const targets = targetCapabilitiesForBinding(binding, request);
195
+ if (targets.length === 0) {
196
+ reasons.push(`Skill binding ${binding.skill_id} has no capability for the requested operation.`);
197
+ continue;
198
+ }
199
+ for (const entry of entries.filter((candidate) => candidate.manifest.id === binding.plugin_id)) {
200
+ for (const capability of targets) {
201
+ candidates.push(...buildCandidate(entry, request, reasons, {
202
+ source: 'skill-binding',
203
+ binding,
204
+ skillOrder,
205
+ capability,
206
+ }));
207
+ }
208
+ }
209
+ }
210
+ return candidates;
211
+ }
212
+ function collectCapabilityFallbackCandidates(entries, request, reasons) {
213
+ if (!request.requested_capability) {
214
+ return [];
215
+ }
216
+ return entries.flatMap((entry) => buildCandidate(entry, request, reasons, {
217
+ source: 'capability-match',
218
+ skillOrder: request.recommended_skills.length,
219
+ capability: request.requested_capability,
220
+ }));
221
+ }
222
+ function buildCandidate(entry, request, reasons, context) {
223
+ const rejectionReasons = collectRejectionReasons(entry, request, context);
224
+ const pluginRef = `${entry.manifest.id}@${entry.manifest.version}`;
225
+ if (rejectionReasons.length > 0) {
226
+ reasons.push(...rejectionReasons.map((reason) => `${pluginRef}/${context.capability}: ${reason}`));
227
+ return [];
228
+ }
229
+ const capability = entry.manifest.capabilities.find((candidate) => candidate.name === context.capability);
230
+ return [
231
+ pluginSkillBindingCandidateSchema.parse({
232
+ source: context.source,
233
+ skill_id: context.binding?.skill_id,
234
+ plugin_ref: {
235
+ id: entry.manifest.id,
236
+ version: entry.manifest.version,
237
+ },
238
+ capability: capability.name,
239
+ operation: request.requested_operation,
240
+ binding_priority: context.binding?.priority,
241
+ rank: rankCandidate(entry, capability, context),
242
+ reasons: candidateReasons(context, capability),
243
+ }),
244
+ ];
245
+ }
246
+ function collectRejectionReasons(entry, request, context) {
247
+ const reasons = [];
248
+ if (!request.statuses.includes(entry.status)) {
249
+ reasons.push(`status ${entry.status} is not eligible.`);
250
+ }
251
+ if (!request.trust_tiers.includes(entry.manifest.governance.trust_tier)) {
252
+ reasons.push(`trust tier ${entry.manifest.governance.trust_tier} is not eligible.`);
253
+ }
254
+ if (context.binding?.plugin_version && context.binding.plugin_version !== entry.manifest.version) {
255
+ reasons.push(`version ${entry.manifest.version} does not match binding version ${context.binding.plugin_version}.`);
256
+ }
257
+ if (request.technology?.language && request.technology.language !== entry.manifest.technology.language) {
258
+ reasons.push(`language ${entry.manifest.technology.language} does not match ${request.technology.language}.`);
259
+ }
260
+ if (request.technology?.framework && request.technology.framework !== entry.manifest.technology.framework) {
261
+ reasons.push(`framework ${entry.manifest.technology.framework ?? '<none>'} does not match ${request.technology.framework}.`);
262
+ }
263
+ if (context.binding?.technology?.language && context.binding.technology.language !== entry.manifest.technology.language) {
264
+ reasons.push(`binding language ${context.binding.technology.language} does not match ${entry.manifest.technology.language}.`);
265
+ }
266
+ if (context.binding?.technology?.framework && context.binding.technology.framework !== entry.manifest.technology.framework) {
267
+ reasons.push(`binding framework ${context.binding.technology.framework} does not match ${entry.manifest.technology.framework ?? '<none>'}.`);
268
+ }
269
+ const capability = entry.manifest.capabilities.find((candidate) => candidate.name === context.capability);
270
+ if (!capability) {
271
+ reasons.push(`capability ${context.capability} is not advertised.`);
272
+ return reasons;
273
+ }
274
+ if (request.require_apply && !capability.supports_apply) {
275
+ reasons.push('apply mode is required but not supported.');
276
+ }
277
+ if (request.require_dry_run && !capability.supports_dry_run) {
278
+ reasons.push('dry-run mode is required but not supported.');
279
+ }
280
+ return reasons;
281
+ }
282
+ function targetCapabilitiesForBinding(binding, request) {
283
+ if (request.requested_operation) {
284
+ const capability = binding.operations[request.requested_operation];
285
+ if (!capability || (request.requested_capability && capability !== request.requested_capability)) {
286
+ return [];
287
+ }
288
+ return [capability];
289
+ }
290
+ if (request.requested_capability) {
291
+ return binding.capabilities.includes(request.requested_capability) ? [request.requested_capability] : [];
292
+ }
293
+ return binding.capabilities;
294
+ }
295
+ function targetCapabilitiesForEntry(entry, request) {
296
+ if (request.requested_capability) {
297
+ return [request.requested_capability];
298
+ }
299
+ return entry.manifest.capabilities.map((capability) => capability.name);
300
+ }
301
+ function candidateReasons(context, capability) {
302
+ if (context.source === 'explicit-plugin') {
303
+ return [`Explicit plugin request selected ${capability.name}.`];
304
+ }
305
+ if (context.source === 'skill-binding') {
306
+ return [`Skill binding ${context.binding?.skill_id} declares ${capability.name}.`];
307
+ }
308
+ return [`Registry capability fallback found ${capability.name}.`];
309
+ }
310
+ function rankCandidate(entry, capability, context) {
311
+ const sourceRank = context.source === 'explicit-plugin' ? 300_000 : context.source === 'skill-binding' ? 200_000 : 100_000;
312
+ const skillRank = Math.max(0, 100 - context.skillOrder) * 1_000;
313
+ const bindingRank = (context.binding?.priority ?? 0) * 10;
314
+ const trustRank = TRUST_RANK[entry.manifest.governance.trust_tier] * 100;
315
+ const riskRank = RISK_RANK[capability.risk_tier] * 10;
316
+ return sourceRank + skillRank + bindingRank + trustRank + riskRank;
317
+ }
318
+ function dedupeCandidates(candidates) {
319
+ const seen = new Set();
320
+ const deduped = [];
321
+ for (const candidate of candidates) {
322
+ const key = `${candidate.source}:${candidate.skill_id ?? ''}:${candidate.plugin_ref.id}@${candidate.plugin_ref.version}:${candidate.capability}`;
323
+ if (seen.has(key)) {
324
+ continue;
325
+ }
326
+ seen.add(key);
327
+ deduped.push(candidate);
328
+ }
329
+ return deduped;
330
+ }
331
+ function compareCandidates(left, right) {
332
+ if (right.rank !== left.rank) {
333
+ return right.rank - left.rank;
334
+ }
335
+ const leftRef = `${left.plugin_ref.id}@${left.plugin_ref.version}/${left.capability}`;
336
+ const rightRef = `${right.plugin_ref.id}@${right.plugin_ref.version}/${right.capability}`;
337
+ return leftRef.localeCompare(rightRef);
338
+ }
339
+ //# sourceMappingURL=plugin-skill-binding.js.map
@@ -0,0 +1,28 @@
1
+ import { type PluginArtifactManifest } from './plugin-broker.js';
2
+ import { type QualityFilesystemSnapshot } from './quality-validation.js';
3
+ export type QualityArtifactManifestIssueCode = 'ARTIFACT_FILE_MISSING' | 'ARTIFACT_CHECKSUM_MISMATCH' | 'ARTIFACT_DELETED_FILE_PRESENT' | 'ARTIFACT_PATH_UNSAFE' | 'ARTIFACT_DUPLICATE_PATH' | 'ARTIFACT_EXPECTED_PATTERN_MISSING' | 'ARTIFACT_REALPATH_ESCAPE';
4
+ export interface QualityArtifactManifestFinding {
5
+ code: QualityArtifactManifestIssueCode;
6
+ severity: 'warn' | 'error' | 'blocker';
7
+ path?: string;
8
+ message: string;
9
+ remediation: string;
10
+ }
11
+ export interface BuildFilesystemSnapshotOptions {
12
+ paths?: string[];
13
+ computeSha256?: boolean;
14
+ }
15
+ export interface ValidateArtifactManifestAgainstFilesystemInput {
16
+ projectRoot: string;
17
+ manifest: PluginArtifactManifest;
18
+ snapshot?: QualityFilesystemSnapshot;
19
+ expectedPathPatterns?: string[];
20
+ }
21
+ export interface QualityArtifactManifestValidationResult {
22
+ status: 'passed' | 'warning' | 'failed' | 'blocked';
23
+ findings: QualityArtifactManifestFinding[];
24
+ filesystem_snapshot: QualityFilesystemSnapshot;
25
+ }
26
+ export declare function buildFilesystemSnapshot(projectRoot: string, options?: BuildFilesystemSnapshotOptions): Promise<QualityFilesystemSnapshot>;
27
+ export declare function validateArtifactManifestAgainstFilesystem(input: ValidateArtifactManifestAgainstFilesystemInput): Promise<QualityArtifactManifestValidationResult>;
28
+ //# sourceMappingURL=quality-artifact-manifest-validator.d.ts.map
@@ -0,0 +1,167 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { promises as fs } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { pluginArtifactManifestSchema, } from './plugin-broker.js';
5
+ import { qualityFilesystemSnapshotSchema, } from './quality-validation.js';
6
+ const WINDOWS_ABSOLUTE_PATH_PATTERN = /^[A-Za-z]:[\\/]/;
7
+ const FILE_REQUIRED_OPERATIONS = new Set(['created', 'modified', 'unchanged', 'validated']);
8
+ export async function buildFilesystemSnapshot(projectRoot, options = {}) {
9
+ const files = [];
10
+ for (const rawPath of options.paths ?? []) {
11
+ const safePath = normalizeRelativePath(rawPath);
12
+ if (!isSafeRelativePath(safePath))
13
+ continue;
14
+ const absolutePath = path.resolve(projectRoot, safePath);
15
+ const stat = await fs.stat(absolutePath).catch(() => null);
16
+ if (!stat?.isFile())
17
+ continue;
18
+ files.push({
19
+ path: safePath,
20
+ size_bytes: stat.size,
21
+ sha256: options.computeSha256 ? await sha256File(absolutePath) : undefined,
22
+ });
23
+ }
24
+ return qualityFilesystemSnapshotSchema.parse({
25
+ root: '.',
26
+ files,
27
+ });
28
+ }
29
+ export async function validateArtifactManifestAgainstFilesystem(input) {
30
+ const manifest = pluginArtifactManifestSchema.parse(input.manifest);
31
+ const artifactPaths = manifest.artifacts.map((artifact) => artifact.path);
32
+ const snapshot = input.snapshot ??
33
+ await buildFilesystemSnapshot(input.projectRoot, {
34
+ paths: artifactPaths,
35
+ computeSha256: manifest.artifacts.some((artifact) => Boolean(artifact.checksum_after)),
36
+ });
37
+ const snapshotByPath = new Map(snapshot.files.map((file) => [normalizeRelativePath(file.path), file]));
38
+ const findings = [];
39
+ const seenPaths = new Set();
40
+ for (const artifact of manifest.artifacts) {
41
+ const artifactPath = normalizeRelativePath(artifact.path);
42
+ if (!isSafeRelativePath(artifactPath)) {
43
+ findings.push(finding('ARTIFACT_PATH_UNSAFE', 'blocker', artifact.path, `Artifact path "${artifact.path}" is unsafe or escapes the project root.`, 'Use a project-relative artifact path without absolute roots or traversal segments.'));
44
+ continue;
45
+ }
46
+ if (seenPaths.has(artifactPath)) {
47
+ findings.push(finding('ARTIFACT_DUPLICATE_PATH', 'error', artifactPath, `Artifact path "${artifactPath}" appears more than once in the manifest.`, 'Keep one manifest entry per artifact path and merge operation evidence there.'));
48
+ }
49
+ seenPaths.add(artifactPath);
50
+ const absolutePath = path.resolve(input.projectRoot, artifactPath);
51
+ const containment = await verifyRealpathContainment(input.projectRoot, absolutePath);
52
+ if (!containment.ok) {
53
+ findings.push(finding('ARTIFACT_REALPATH_ESCAPE', 'blocker', artifactPath, `Artifact path "${artifactPath}" resolves outside the project root.`, 'Remove the symlink or move the artifact inside the project root before accepting the evidence.'));
54
+ continue;
55
+ }
56
+ const exists = await pathExists(absolutePath);
57
+ if (artifact.operation === 'deleted') {
58
+ if (exists) {
59
+ findings.push(finding('ARTIFACT_DELETED_FILE_PRESENT', 'error', artifactPath, `Artifact "${artifactPath}" is marked deleted but still exists.`, 'Delete the file or correct the artifact operation in the manifest.'));
60
+ }
61
+ continue;
62
+ }
63
+ if (FILE_REQUIRED_OPERATIONS.has(artifact.operation) && !exists) {
64
+ findings.push(finding('ARTIFACT_FILE_MISSING', 'error', artifactPath, `Artifact "${artifactPath}" is marked ${artifact.operation} but does not exist.`, 'Create the artifact, update the manifest path, or change the operation to planned if this is a dry-run.'));
65
+ continue;
66
+ }
67
+ if (artifact.checksum_after && exists) {
68
+ const actualChecksum = snapshotByPath.get(artifactPath)?.sha256 ?? await sha256File(absolutePath);
69
+ if (actualChecksum !== artifact.checksum_after) {
70
+ findings.push(finding('ARTIFACT_CHECKSUM_MISMATCH', 'error', artifactPath, `Artifact "${artifactPath}" checksum does not match the manifest.`, 'Regenerate the checksum after producing the artifact or investigate unexpected file drift.'));
71
+ }
72
+ }
73
+ }
74
+ for (const pattern of input.expectedPathPatterns ?? []) {
75
+ const matcher = globToRegExp(pattern);
76
+ const matched = [...seenPaths, ...snapshot.files.map((file) => normalizeRelativePath(file.path))]
77
+ .some((candidate) => matcher.test(candidate));
78
+ if (!matched) {
79
+ findings.push(finding('ARTIFACT_EXPECTED_PATTERN_MISSING', 'error', pattern, `No manifest or filesystem artifact matched expected pattern "${pattern}".`, 'Create the expected artifact or adjust the scenario expectation.'));
80
+ }
81
+ }
82
+ return {
83
+ status: statusFromFindings(findings),
84
+ findings,
85
+ filesystem_snapshot: snapshot,
86
+ };
87
+ }
88
+ function finding(code, severity, artifactPath, message, remediation) {
89
+ return {
90
+ code,
91
+ severity,
92
+ path: artifactPath,
93
+ message,
94
+ remediation,
95
+ };
96
+ }
97
+ function statusFromFindings(findings) {
98
+ if (findings.some((item) => item.severity === 'blocker'))
99
+ return 'blocked';
100
+ if (findings.some((item) => item.severity === 'error'))
101
+ return 'failed';
102
+ if (findings.length > 0)
103
+ return 'warning';
104
+ return 'passed';
105
+ }
106
+ function normalizeRelativePath(value) {
107
+ return value.replace(/\\/gu, '/').replace(/^\.\//u, '');
108
+ }
109
+ function isSafeRelativePath(value) {
110
+ if (!value || value.startsWith('/') || WINDOWS_ABSOLUTE_PATH_PATTERN.test(value)) {
111
+ return false;
112
+ }
113
+ return !value.split('/').some((segment) => segment === '..');
114
+ }
115
+ async function verifyRealpathContainment(projectRoot, absolutePath) {
116
+ const resolvedRoot = path.resolve(projectRoot);
117
+ const relativeLogical = path.relative(resolvedRoot, absolutePath);
118
+ if (relativeLogical !== '' && (relativeLogical.startsWith('..') || path.isAbsolute(relativeLogical))) {
119
+ return { ok: false };
120
+ }
121
+ const realRoot = await fs.realpath(resolvedRoot).catch(() => resolvedRoot);
122
+ const realTarget = await fs.realpath(absolutePath).catch(() => null);
123
+ if (!realTarget)
124
+ return { ok: true };
125
+ const relativePhysical = path.relative(realRoot, realTarget);
126
+ if (relativePhysical !== '' && (relativePhysical.startsWith('..') || path.isAbsolute(relativePhysical))) {
127
+ return { ok: false };
128
+ }
129
+ return { ok: true };
130
+ }
131
+ async function pathExists(filePath) {
132
+ try {
133
+ await fs.access(filePath);
134
+ return true;
135
+ }
136
+ catch {
137
+ return false;
138
+ }
139
+ }
140
+ async function sha256File(filePath) {
141
+ const hash = createHash('sha256');
142
+ hash.update(await fs.readFile(filePath));
143
+ return hash.digest('hex');
144
+ }
145
+ function globToRegExp(pattern) {
146
+ const normalized = normalizeRelativePath(pattern);
147
+ let source = '';
148
+ for (let index = 0; index < normalized.length; index += 1) {
149
+ const char = normalized[index];
150
+ const next = normalized[index + 1];
151
+ if (char === '*' && next === '*') {
152
+ source += '.*';
153
+ index += 1;
154
+ continue;
155
+ }
156
+ if (char === '*') {
157
+ source += '[^/]*';
158
+ continue;
159
+ }
160
+ source += escapeRegExp(char);
161
+ }
162
+ return new RegExp(`^${source}$`, 'u');
163
+ }
164
+ function escapeRegExp(value) {
165
+ return value.replace(/[|\\{}()[\]^$+?.]/gu, '\\$&');
166
+ }
167
+ //# sourceMappingURL=quality-artifact-manifest-validator.js.map
@@ -0,0 +1,65 @@
1
+ import { type QualityEvidenceBundle } from './quality-validation.js';
2
+ export type QualityEvidenceRendererStatus = 'passed' | 'warning';
3
+ export interface QualityEvidenceRenderInput {
4
+ projectRoot: string;
5
+ memoryRoot?: string;
6
+ bundle: unknown;
7
+ generatedAt?: string | Date;
8
+ }
9
+ export interface QualityEvidenceValidationIssue {
10
+ path: string;
11
+ message: string;
12
+ }
13
+ export interface QualityEvidenceFindingSummary {
14
+ code: string;
15
+ severity: string;
16
+ message: string;
17
+ remediation: string;
18
+ path?: string;
19
+ gate_id?: string;
20
+ }
21
+ export interface QualityEvidenceRenderSummary {
22
+ schema_version: 1;
23
+ run_id: string;
24
+ scenario_ref: string;
25
+ feature_ref: string;
26
+ mode: string;
27
+ generated_at: string;
28
+ warning_only: true;
29
+ blocking: false;
30
+ status: QualityEvidenceRendererStatus;
31
+ run_status: string;
32
+ validation: {
33
+ valid: boolean;
34
+ issue_count: number;
35
+ issues: QualityEvidenceValidationIssue[];
36
+ };
37
+ counts: {
38
+ findings: number;
39
+ warning_findings: number;
40
+ error_findings: number;
41
+ blocker_findings: number;
42
+ artifacts: number;
43
+ filesystem_files: number;
44
+ import_nodes: number;
45
+ import_edges: number;
46
+ checksums: number;
47
+ exceptions: number;
48
+ };
49
+ findings: QualityEvidenceFindingSummary[];
50
+ outputs: {
51
+ report_path: string;
52
+ summary_path: string;
53
+ };
54
+ }
55
+ export interface QualityEvidenceRenderResult {
56
+ summary: QualityEvidenceRenderSummary;
57
+ reportMarkdown: string;
58
+ paths: {
59
+ report: string;
60
+ summary: string;
61
+ };
62
+ bundle?: QualityEvidenceBundle;
63
+ }
64
+ export declare function renderQualityEvidenceBundle(input: QualityEvidenceRenderInput): Promise<QualityEvidenceRenderResult>;
65
+ //# sourceMappingURL=quality-evidence-renderer.d.ts.map