agent-sdd 1.0.3

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 (304) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1028 -0
  3. package/README.ru.md +1046 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.js +867 -0
  6. package/dist/features/approve/adapters/inbound/CliApproveHandler.d.ts +17 -0
  7. package/dist/features/approve/adapters/inbound/CliApproveHandler.js +108 -0
  8. package/dist/features/approve/adapters/outbound/NodeApproveFileSystem.d.ts +8 -0
  9. package/dist/features/approve/adapters/outbound/NodeApproveFileSystem.js +147 -0
  10. package/dist/features/approve/adapters/outbound/NodePlanFileWriter.d.ts +6 -0
  11. package/dist/features/approve/adapters/outbound/NodePlanFileWriter.js +92 -0
  12. package/dist/features/approve/adapters/outbound/SystemApproveClock.d.ts +4 -0
  13. package/dist/features/approve/adapters/outbound/SystemApproveClock.js +5 -0
  14. package/dist/features/approve/application/ApplyApproval.d.ts +19 -0
  15. package/dist/features/approve/application/ApplyApproval.js +30 -0
  16. package/dist/features/approve/application/WriteAttestation.d.ts +19 -0
  17. package/dist/features/approve/application/WriteAttestation.js +23 -0
  18. package/dist/features/approve/domain/ApproveRequest.d.ts +24 -0
  19. package/dist/features/approve/domain/ApproveRequest.js +24 -0
  20. package/dist/features/approve/domain/Rewrite.d.ts +1 -0
  21. package/dist/features/approve/domain/Rewrite.js +6 -0
  22. package/dist/features/approve/ports/inbound/ApproveCommand.d.ts +10 -0
  23. package/dist/features/approve/ports/inbound/ApproveCommand.js +1 -0
  24. package/dist/features/approve/ports/outbound/ApproveClock.d.ts +3 -0
  25. package/dist/features/approve/ports/outbound/ApproveClock.js +1 -0
  26. package/dist/features/approve/ports/outbound/ApproveConfigPort.d.ts +4 -0
  27. package/dist/features/approve/ports/outbound/ApproveConfigPort.js +1 -0
  28. package/dist/features/approve/ports/outbound/ApproveFileSystem.d.ts +8 -0
  29. package/dist/features/approve/ports/outbound/ApproveFileSystem.js +1 -0
  30. package/dist/features/approve/ports/outbound/PlanFileWriter.d.ts +13 -0
  31. package/dist/features/approve/ports/outbound/PlanFileWriter.js +1 -0
  32. package/dist/features/check/adapters/inbound/CliCheckHandler.d.ts +8 -0
  33. package/dist/features/check/adapters/inbound/CliCheckHandler.js +62 -0
  34. package/dist/features/check/adapters/outbound/ChildProcessCheckGit.d.ts +8 -0
  35. package/dist/features/check/adapters/outbound/ChildProcessCheckGit.js +112 -0
  36. package/dist/features/check/adapters/outbound/NodeCheckFileReader.d.ts +7 -0
  37. package/dist/features/check/adapters/outbound/NodeCheckFileReader.js +44 -0
  38. package/dist/features/check/application/CheckBaseline.d.ts +28 -0
  39. package/dist/features/check/application/CheckBaseline.js +54 -0
  40. package/dist/features/check/domain/BaselineComparison.d.ts +1 -0
  41. package/dist/features/check/domain/BaselineComparison.js +2 -0
  42. package/dist/features/check/ports/inbound/CheckCommand.d.ts +4 -0
  43. package/dist/features/check/ports/inbound/CheckCommand.js +1 -0
  44. package/dist/features/check/ports/outbound/CheckConfigPort.d.ts +4 -0
  45. package/dist/features/check/ports/outbound/CheckConfigPort.js +1 -0
  46. package/dist/features/check/ports/outbound/CheckGitPort.d.ts +7 -0
  47. package/dist/features/check/ports/outbound/CheckGitPort.js +1 -0
  48. package/dist/features/check/ports/outbound/CheckSpecPort.d.ts +9 -0
  49. package/dist/features/check/ports/outbound/CheckSpecPort.js +1 -0
  50. package/dist/features/doctor/adapters/inbound/CliDoctorHandler.d.ts +8 -0
  51. package/dist/features/doctor/adapters/inbound/CliDoctorHandler.js +77 -0
  52. package/dist/features/doctor/adapters/outbound/NodeRegistryReader.d.ts +5 -0
  53. package/dist/features/doctor/adapters/outbound/NodeRegistryReader.js +40 -0
  54. package/dist/features/doctor/application/RunDoctor.d.ts +30 -0
  55. package/dist/features/doctor/application/RunDoctor.js +78 -0
  56. package/dist/features/doctor/domain/RegistryRow.d.ts +23 -0
  57. package/dist/features/doctor/domain/RegistryRow.js +114 -0
  58. package/dist/features/doctor/domain/SemverRange.d.ts +7 -0
  59. package/dist/features/doctor/domain/SemverRange.js +82 -0
  60. package/dist/features/doctor/ports/inbound/DoctorCommand.d.ts +8 -0
  61. package/dist/features/doctor/ports/inbound/DoctorCommand.js +1 -0
  62. package/dist/features/doctor/ports/outbound/RegistryReader.d.ts +12 -0
  63. package/dist/features/doctor/ports/outbound/RegistryReader.js +1 -0
  64. package/dist/features/finalize/adapters/inbound/CliFinalizeHandler.d.ts +8 -0
  65. package/dist/features/finalize/adapters/inbound/CliFinalizeHandler.js +80 -0
  66. package/dist/features/finalize/adapters/outbound/NodeFinalizeFileSystem.d.ts +11 -0
  67. package/dist/features/finalize/adapters/outbound/NodeFinalizeFileSystem.js +167 -0
  68. package/dist/features/finalize/adapters/outbound/NodePlanRepo.d.ts +7 -0
  69. package/dist/features/finalize/adapters/outbound/NodePlanRepo.js +82 -0
  70. package/dist/features/finalize/adapters/outbound/SystemFinalizeClock.d.ts +4 -0
  71. package/dist/features/finalize/adapters/outbound/SystemFinalizeClock.js +5 -0
  72. package/dist/features/finalize/application/RunFinalize.d.ts +34 -0
  73. package/dist/features/finalize/application/RunFinalize.js +98 -0
  74. package/dist/features/finalize/domain/ValidateFinalizeGraph.d.ts +9 -0
  75. package/dist/features/finalize/domain/ValidateFinalizeGraph.js +86 -0
  76. package/dist/features/finalize/ports/inbound/FinalizeCommand.d.ts +7 -0
  77. package/dist/features/finalize/ports/inbound/FinalizeCommand.js +1 -0
  78. package/dist/features/finalize/ports/outbound/FinalizeClock.d.ts +3 -0
  79. package/dist/features/finalize/ports/outbound/FinalizeClock.js +1 -0
  80. package/dist/features/finalize/ports/outbound/FinalizeConfigPort.d.ts +4 -0
  81. package/dist/features/finalize/ports/outbound/FinalizeConfigPort.js +1 -0
  82. package/dist/features/finalize/ports/outbound/FinalizeFileSystem.d.ts +14 -0
  83. package/dist/features/finalize/ports/outbound/FinalizeFileSystem.js +1 -0
  84. package/dist/features/finalize/ports/outbound/PlanRepo.d.ts +21 -0
  85. package/dist/features/finalize/ports/outbound/PlanRepo.js +1 -0
  86. package/dist/features/install/adapters/inbound/CliInstallHandler.d.ts +8 -0
  87. package/dist/features/install/adapters/inbound/CliInstallHandler.js +54 -0
  88. package/dist/features/install/adapters/outbound/NodeInstallSource.d.ts +7 -0
  89. package/dist/features/install/adapters/outbound/NodeInstallSource.js +24 -0
  90. package/dist/features/install/adapters/outbound/NodeInstallTargetFs.d.ts +7 -0
  91. package/dist/features/install/adapters/outbound/NodeInstallTargetFs.js +30 -0
  92. package/dist/features/install/application/InstallRules.d.ts +10 -0
  93. package/dist/features/install/application/InstallRules.js +73 -0
  94. package/dist/features/install/domain/InstallPlan.d.ts +27 -0
  95. package/dist/features/install/domain/InstallPlan.js +168 -0
  96. package/dist/features/install/domain/InstallResult.d.ts +23 -0
  97. package/dist/features/install/domain/InstallResult.js +1 -0
  98. package/dist/features/install/domain/InstallTarget.d.ts +6 -0
  99. package/dist/features/install/domain/InstallTarget.js +7 -0
  100. package/dist/features/install/domain/ManagedBlock.d.ts +3 -0
  101. package/dist/features/install/domain/ManagedBlock.js +20 -0
  102. package/dist/features/install/domain/RuleManifest.d.ts +17 -0
  103. package/dist/features/install/domain/RuleManifest.js +69 -0
  104. package/dist/features/install/domain/SettingsMerge.d.ts +5 -0
  105. package/dist/features/install/domain/SettingsMerge.js +43 -0
  106. package/dist/features/install/ports/inbound/InstallCommand.d.ts +10 -0
  107. package/dist/features/install/ports/inbound/InstallCommand.js +1 -0
  108. package/dist/features/install/ports/outbound/InstallSource.d.ts +4 -0
  109. package/dist/features/install/ports/outbound/InstallSource.js +1 -0
  110. package/dist/features/install/ports/outbound/InstallTargetFs.d.ts +6 -0
  111. package/dist/features/install/ports/outbound/InstallTargetFs.js +1 -0
  112. package/dist/features/lint/adapters/inbound/CliLintHandler.d.ts +8 -0
  113. package/dist/features/lint/adapters/inbound/CliLintHandler.js +61 -0
  114. package/dist/features/lint/adapters/outbound/NodeLintFileReader.d.ts +7 -0
  115. package/dist/features/lint/adapters/outbound/NodeLintFileReader.js +165 -0
  116. package/dist/features/lint/application/RunLint.d.ts +10 -0
  117. package/dist/features/lint/application/RunLint.js +100 -0
  118. package/dist/features/lint/domain/Diagnostic.d.ts +1 -0
  119. package/dist/features/lint/domain/Diagnostic.js +2 -0
  120. package/dist/features/lint/domain/Record.d.ts +1 -0
  121. package/dist/features/lint/domain/Record.js +5 -0
  122. package/dist/features/lint/domain/Rules.d.ts +1 -0
  123. package/dist/features/lint/domain/Rules.js +2 -0
  124. package/dist/features/lint/domain/SpecParser.d.ts +1 -0
  125. package/dist/features/lint/domain/SpecParser.js +2 -0
  126. package/dist/features/lint/ports/inbound/LintCommand.d.ts +4 -0
  127. package/dist/features/lint/ports/inbound/LintCommand.js +1 -0
  128. package/dist/features/lint/ports/outbound/LintConfigPort.d.ts +4 -0
  129. package/dist/features/lint/ports/outbound/LintConfigPort.js +1 -0
  130. package/dist/features/lint/ports/outbound/LintFileReader.d.ts +10 -0
  131. package/dist/features/lint/ports/outbound/LintFileReader.js +1 -0
  132. package/dist/features/plan/adapters/inbound/CliPlanShowHandler.d.ts +8 -0
  133. package/dist/features/plan/adapters/inbound/CliPlanShowHandler.js +73 -0
  134. package/dist/features/plan/adapters/outbound/NodePlanReader.d.ts +7 -0
  135. package/dist/features/plan/adapters/outbound/NodePlanReader.js +68 -0
  136. package/dist/features/plan/application/ShowPlan.d.ts +7 -0
  137. package/dist/features/plan/application/ShowPlan.js +4 -0
  138. package/dist/features/plan/ports/inbound/PlanShowCommand.d.ts +7 -0
  139. package/dist/features/plan/ports/inbound/PlanShowCommand.js +1 -0
  140. package/dist/features/plan/ports/outbound/PlanConfigPort.d.ts +4 -0
  141. package/dist/features/plan/ports/outbound/PlanConfigPort.js +1 -0
  142. package/dist/features/plan/ports/outbound/PlanReader.d.ts +19 -0
  143. package/dist/features/plan/ports/outbound/PlanReader.js +1 -0
  144. package/dist/features/ready/adapters/inbound/CliReadyHandler.d.ts +8 -0
  145. package/dist/features/ready/adapters/inbound/CliReadyHandler.js +79 -0
  146. package/dist/features/ready/adapters/outbound/ChildProcessReadyGit.d.ts +9 -0
  147. package/dist/features/ready/adapters/outbound/ChildProcessReadyGit.js +113 -0
  148. package/dist/features/ready/adapters/outbound/NodeReadyFileSystem.d.ts +8 -0
  149. package/dist/features/ready/adapters/outbound/NodeReadyFileSystem.js +159 -0
  150. package/dist/features/ready/application/RunReady.d.ts +16 -0
  151. package/dist/features/ready/application/RunReady.js +572 -0
  152. package/dist/features/ready/domain/AggregatedRules.d.ts +16 -0
  153. package/dist/features/ready/domain/AggregatedRules.js +42 -0
  154. package/dist/features/ready/domain/MarkerParser.d.ts +17 -0
  155. package/dist/features/ready/domain/MarkerParser.js +108 -0
  156. package/dist/features/ready/domain/PartitionResolver.d.ts +1 -0
  157. package/dist/features/ready/domain/PartitionResolver.js +5 -0
  158. package/dist/features/ready/domain/ReadyInput.d.ts +6 -0
  159. package/dist/features/ready/domain/ReadyInput.js +1 -0
  160. package/dist/features/ready/domain/ReadyViolation.d.ts +38 -0
  161. package/dist/features/ready/domain/ReadyViolation.js +19 -0
  162. package/dist/features/ready/domain/Rules.d.ts +22 -0
  163. package/dist/features/ready/domain/Rules.js +243 -0
  164. package/dist/features/ready/domain/SpecDiff.d.ts +33 -0
  165. package/dist/features/ready/domain/SpecDiff.js +321 -0
  166. package/dist/features/ready/ports/inbound/ReadyCommand.d.ts +4 -0
  167. package/dist/features/ready/ports/inbound/ReadyCommand.js +1 -0
  168. package/dist/features/ready/ports/outbound/ReadyConfigPort.d.ts +4 -0
  169. package/dist/features/ready/ports/outbound/ReadyConfigPort.js +1 -0
  170. package/dist/features/ready/ports/outbound/ReadyFileReader.d.ts +12 -0
  171. package/dist/features/ready/ports/outbound/ReadyFileReader.js +1 -0
  172. package/dist/features/ready/ports/outbound/ReadyGitPort.d.ts +10 -0
  173. package/dist/features/ready/ports/outbound/ReadyGitPort.js +5 -0
  174. package/dist/features/record/adapters/inbound/CliRecordHandler.d.ts +10 -0
  175. package/dist/features/record/adapters/inbound/CliRecordHandler.js +111 -0
  176. package/dist/features/record/adapters/outbound/NodeRecordFileSystem.d.ts +9 -0
  177. package/dist/features/record/adapters/outbound/NodeRecordFileSystem.js +152 -0
  178. package/dist/features/record/application/AddRecord.d.ts +11 -0
  179. package/dist/features/record/application/AddRecord.js +84 -0
  180. package/dist/features/record/application/GetRecord.d.ts +8 -0
  181. package/dist/features/record/application/GetRecord.js +22 -0
  182. package/dist/features/record/application/ListRecords.d.ts +9 -0
  183. package/dist/features/record/application/ListRecords.js +24 -0
  184. package/dist/features/record/application/SetRecord.d.ts +11 -0
  185. package/dist/features/record/application/SetRecord.js +68 -0
  186. package/dist/features/record/domain/RecordBody.d.ts +12 -0
  187. package/dist/features/record/domain/RecordBody.js +66 -0
  188. package/dist/features/record/domain/RecordPartition.d.ts +1 -0
  189. package/dist/features/record/domain/RecordPartition.js +7 -0
  190. package/dist/features/record/domain/RecordSlice.d.ts +7 -0
  191. package/dist/features/record/domain/RecordSlice.js +1 -0
  192. package/dist/features/record/domain/RecordSummary.d.ts +11 -0
  193. package/dist/features/record/domain/RecordSummary.js +13 -0
  194. package/dist/features/record/domain/RecordWrite.d.ts +14 -0
  195. package/dist/features/record/domain/RecordWrite.js +8 -0
  196. package/dist/features/record/ports/inbound/RecordCommand.d.ts +19 -0
  197. package/dist/features/record/ports/inbound/RecordCommand.js +1 -0
  198. package/dist/features/record/ports/outbound/RecordConfigPort.d.ts +4 -0
  199. package/dist/features/record/ports/outbound/RecordConfigPort.js +1 -0
  200. package/dist/features/record/ports/outbound/RecordFileReader.d.ts +10 -0
  201. package/dist/features/record/ports/outbound/RecordFileReader.js +1 -0
  202. package/dist/features/record/ports/outbound/RecordFileWriter.d.ts +6 -0
  203. package/dist/features/record/ports/outbound/RecordFileWriter.js +1 -0
  204. package/dist/features/refresh/adapters/inbound/CliRefreshHandler.d.ts +8 -0
  205. package/dist/features/refresh/adapters/inbound/CliRefreshHandler.js +24 -0
  206. package/dist/features/refresh/adapters/outbound/ChildProcessRefreshGit.d.ts +8 -0
  207. package/dist/features/refresh/adapters/outbound/ChildProcessRefreshGit.js +118 -0
  208. package/dist/features/refresh/adapters/outbound/NodeRefreshFileReader.d.ts +7 -0
  209. package/dist/features/refresh/adapters/outbound/NodeRefreshFileReader.js +44 -0
  210. package/dist/features/refresh/adapters/outbound/SystemRefreshClock.d.ts +4 -0
  211. package/dist/features/refresh/adapters/outbound/SystemRefreshClock.js +5 -0
  212. package/dist/features/refresh/application/BuildRefreshStubs.d.ts +25 -0
  213. package/dist/features/refresh/application/BuildRefreshStubs.js +43 -0
  214. package/dist/features/refresh/domain/DiffStubs.d.ts +24 -0
  215. package/dist/features/refresh/domain/DiffStubs.js +81 -0
  216. package/dist/features/refresh/domain/Footprint.d.ts +14 -0
  217. package/dist/features/refresh/domain/Footprint.js +45 -0
  218. package/dist/features/refresh/ports/inbound/RefreshCommand.d.ts +4 -0
  219. package/dist/features/refresh/ports/inbound/RefreshCommand.js +1 -0
  220. package/dist/features/refresh/ports/outbound/RefreshClockPort.d.ts +3 -0
  221. package/dist/features/refresh/ports/outbound/RefreshClockPort.js +1 -0
  222. package/dist/features/refresh/ports/outbound/RefreshConfigPort.d.ts +4 -0
  223. package/dist/features/refresh/ports/outbound/RefreshConfigPort.js +1 -0
  224. package/dist/features/refresh/ports/outbound/RefreshGitPort.d.ts +7 -0
  225. package/dist/features/refresh/ports/outbound/RefreshGitPort.js +1 -0
  226. package/dist/features/refresh/ports/outbound/RefreshSpecPort.d.ts +9 -0
  227. package/dist/features/refresh/ports/outbound/RefreshSpecPort.js +1 -0
  228. package/dist/features/report/adapters/inbound/CliReportHandler.d.ts +8 -0
  229. package/dist/features/report/adapters/inbound/CliReportHandler.js +35 -0
  230. package/dist/features/report/adapters/outbound/NodeReportFileSystem.d.ts +7 -0
  231. package/dist/features/report/adapters/outbound/NodeReportFileSystem.js +128 -0
  232. package/dist/features/report/application/RunReport.d.ts +19 -0
  233. package/dist/features/report/application/RunReport.js +161 -0
  234. package/dist/features/report/ports/inbound/ReportCommand.d.ts +8 -0
  235. package/dist/features/report/ports/inbound/ReportCommand.js +1 -0
  236. package/dist/features/report/ports/outbound/ReportConfigPort.d.ts +4 -0
  237. package/dist/features/report/ports/outbound/ReportConfigPort.js +1 -0
  238. package/dist/features/report/ports/outbound/ReportFileReader.d.ts +7 -0
  239. package/dist/features/report/ports/outbound/ReportFileReader.js +1 -0
  240. package/dist/features/token/adapters/inbound/CliTokenHandler.d.ts +8 -0
  241. package/dist/features/token/adapters/inbound/CliTokenHandler.js +53 -0
  242. package/dist/features/token/adapters/outbound/ChildProcessTokenGit.d.ts +8 -0
  243. package/dist/features/token/adapters/outbound/ChildProcessTokenGit.js +112 -0
  244. package/dist/features/token/adapters/outbound/NodeTokenConfigReader.d.ts +5 -0
  245. package/dist/features/token/adapters/outbound/NodeTokenConfigReader.js +41 -0
  246. package/dist/features/token/application/ComputeToken.d.ts +18 -0
  247. package/dist/features/token/application/ComputeToken.js +27 -0
  248. package/dist/features/token/ports/inbound/TokenCommand.d.ts +4 -0
  249. package/dist/features/token/ports/inbound/TokenCommand.js +1 -0
  250. package/dist/features/token/ports/outbound/TokenConfigPort.d.ts +4 -0
  251. package/dist/features/token/ports/outbound/TokenConfigPort.js +1 -0
  252. package/dist/features/token/ports/outbound/TokenGitPort.d.ts +7 -0
  253. package/dist/features/token/ports/outbound/TokenGitPort.js +1 -0
  254. package/dist/shared/domain/AgentBlocklist.d.ts +5 -0
  255. package/dist/shared/domain/AgentBlocklist.js +28 -0
  256. package/dist/shared/domain/BoundaryReachability.d.ts +5 -0
  257. package/dist/shared/domain/BoundaryReachability.js +71 -0
  258. package/dist/shared/domain/CheckOutcome.d.ts +10 -0
  259. package/dist/shared/domain/CheckOutcome.js +7 -0
  260. package/dist/shared/domain/CliOutput.d.ts +10 -0
  261. package/dist/shared/domain/CliOutput.js +29 -0
  262. package/dist/shared/domain/Config.d.ts +29 -0
  263. package/dist/shared/domain/Config.js +201 -0
  264. package/dist/shared/domain/DiagnosticRegistry.d.ts +8 -0
  265. package/dist/shared/domain/DiagnosticRegistry.js +71 -0
  266. package/dist/shared/domain/Errors.d.ts +12 -0
  267. package/dist/shared/domain/Errors.js +23 -0
  268. package/dist/shared/domain/GlobMatch.d.ts +2 -0
  269. package/dist/shared/domain/GlobMatch.js +58 -0
  270. package/dist/shared/domain/LintReport.d.ts +16 -0
  271. package/dist/shared/domain/LintReport.js +11 -0
  272. package/dist/shared/domain/LintRules.d.ts +67 -0
  273. package/dist/shared/domain/LintRules.js +956 -0
  274. package/dist/shared/domain/PartitionGrammar.d.ts +4 -0
  275. package/dist/shared/domain/PartitionGrammar.js +16 -0
  276. package/dist/shared/domain/PlanFile.d.ts +28 -0
  277. package/dist/shared/domain/PlanFile.js +112 -0
  278. package/dist/shared/domain/Scope.d.ts +1 -0
  279. package/dist/shared/domain/Scope.js +3 -0
  280. package/dist/shared/domain/SpecApprovalRewrite.d.ts +23 -0
  281. package/dist/shared/domain/SpecApprovalRewrite.js +254 -0
  282. package/dist/shared/domain/SpecBlocks.d.ts +12 -0
  283. package/dist/shared/domain/SpecBlocks.js +96 -0
  284. package/dist/shared/domain/SpecRecord.d.ts +17 -0
  285. package/dist/shared/domain/SpecRecord.js +208 -0
  286. package/dist/shared/domain/TemplateFieldMetadata.d.ts +2 -0
  287. package/dist/shared/domain/TemplateFieldMetadata.js +177 -0
  288. package/dist/shared/domain/Token.d.ts +2 -0
  289. package/dist/shared/domain/Token.js +5 -0
  290. package/dist/shared/domain/WeaselWords.d.ts +3 -0
  291. package/dist/shared/domain/WeaselWords.js +32 -0
  292. package/package.json +71 -0
  293. package/rules/enforcement_registry.md +126 -0
  294. package/rules/hooks/sdd-lint-reminder.sh +33 -0
  295. package/rules/hooks/sdd-spec-read-guard.sh +73 -0
  296. package/rules/manifest.json +15 -0
  297. package/rules/review-sdd.md +9 -0
  298. package/rules/sdd-cli-usage.md +91 -0
  299. package/rules/skills/spec-driven-development/SKILL.md +554 -0
  300. package/rules/skills/spec-driven-development/data/weasel-words.json +22 -0
  301. package/rules/spec-driven-development.md +69 -0
  302. package/rules/tdd-sdd.md +127 -0
  303. package/rules/workflow-sdd.md +56 -0
  304. package/schema/sdd.config.schema.json +104 -0
@@ -0,0 +1,98 @@
1
+ import { rewriteApproval, } from "../../../shared/domain/SpecApprovalRewrite.js";
2
+ import { lintRecordsFromMarkdown } from "../../../shared/domain/SpecRecord.js";
3
+ import { validateFinalizeGraph, } from "../domain/ValidateFinalizeGraph.js";
4
+ export async function runFinalize(cwd, planId, ports) {
5
+ const config = await ports.config.config(cwd);
6
+ const load = await ports.plans.load(cwd, config.plansDir, planId);
7
+ if (load.kind === "no-active-plan") {
8
+ return { kind: "no-active-plan" };
9
+ }
10
+ if (load.kind === "invalid-plan-file") {
11
+ return {
12
+ kind: "invalid-plan",
13
+ planId: load.planId,
14
+ sourcePath: load.sourcePath,
15
+ reason: load.reason,
16
+ };
17
+ }
18
+ const plan = load.plan;
19
+ const entries = await ports.files.resolveSpecFiles(cwd, config.lint.specFiles);
20
+ const records = entries.flatMap((e) => lintRecordsFromMarkdown(e.path, e.content));
21
+ const violations = validateFinalizeGraph(records, plan.pendingAttestations);
22
+ if (violations.length > 0) {
23
+ return { kind: "graph-violation", planId: plan.planId, violations };
24
+ }
25
+ /*
26
+ * INV-012: apply each attestation as a rewriteApproval against the matching
27
+ * record; abort before writing if any attestation fails to match.
28
+ */
29
+ const applied = applyAttestations(entries, plan.pendingAttestations, ports.clock.now());
30
+ if (applied.missingIds.length > 0) {
31
+ return {
32
+ kind: "no-id-match",
33
+ planId: plan.planId,
34
+ missingIds: applied.missingIds,
35
+ };
36
+ }
37
+ const { fileContent, finalizedIds } = applied;
38
+ const filesChanged = [];
39
+ const batch = [];
40
+ for (const e of entries) {
41
+ const next = fileContent.get(e.path);
42
+ if (next !== undefined && next !== e.content) {
43
+ batch.push({ path: e.path, content: next });
44
+ filesChanged.push(e.path);
45
+ }
46
+ }
47
+ await ports.files.writeBatch(cwd, batch);
48
+ const archive = await ports.plans.archive(cwd, config.plansDir, plan.planId);
49
+ return {
50
+ kind: "finalized",
51
+ planId: plan.planId,
52
+ finalizedIds,
53
+ filesChanged,
54
+ archivedPath: archive.archivedPath,
55
+ };
56
+ }
57
+ function applyAttestations(entries, attestations, when) {
58
+ const fileContent = new Map();
59
+ for (const e of entries) {
60
+ fileContent.set(e.path, e.content);
61
+ }
62
+ const finalizedIds = [];
63
+ const missingIds = [];
64
+ for (const a of attestations) {
65
+ const req = {
66
+ id: a.id,
67
+ approver: a.approverIdentity,
68
+ ownerRole: a.ownerRole,
69
+ changeRequest: a.changeRequest,
70
+ scope: a.scope,
71
+ targetStatus: a.targetStatus,
72
+ reviewedTestOracle: a.reviewedTestOracle ?? null,
73
+ };
74
+ const reqWhen = new Date(a.timestamp);
75
+ const reqClock = isNaN(reqWhen.valueOf()) ? when : reqWhen;
76
+ let matched = false;
77
+ for (const e of entries) {
78
+ const current = fileContent.get(e.path);
79
+ if (current === undefined) {
80
+ continue;
81
+ }
82
+ const result = rewriteApproval(current, req, reqClock);
83
+ if (result.matched.length === 0) {
84
+ continue;
85
+ }
86
+ fileContent.set(e.path, result.newContent);
87
+ matched = true;
88
+ for (const m of result.matched) {
89
+ finalizedIds.push(m.id);
90
+ }
91
+ break;
92
+ }
93
+ if (!matched) {
94
+ missingIds.push(a.id);
95
+ }
96
+ }
97
+ return { fileContent, finalizedIds, missingIds };
98
+ }
@@ -0,0 +1,9 @@
1
+ import type { LintRecord } from "../../../shared/domain/SpecRecord.js";
2
+ import type { PendingAttestation } from "../../../shared/domain/PlanFile.js";
3
+ export interface GraphViolation {
4
+ flippedId: string;
5
+ referencesId: string;
6
+ referencesStatus: string;
7
+ via: "members" | "policy_refs" | "target_ids" | "surface_ref";
8
+ }
9
+ export declare function validateFinalizeGraph(records: ReadonlyArray<LintRecord>, plan: ReadonlyArray<PendingAttestation>): GraphViolation[];
@@ -0,0 +1,86 @@
1
+ /*
2
+ * BEH-024 / BEH-025 / INV-012: prospective graph validator for `sdd finalize`
3
+ * — refuse if any flipped record would still reference a <approved ID after
4
+ * applying every pending attestation. See spec record for rationale.
5
+ */
6
+ const TERMINAL_STATUSES = new Set(["approved", "deprecated", "removed"]);
7
+ export function validateFinalizeGraph(records, plan) {
8
+ const byId = new Map();
9
+ for (const r of records) {
10
+ byId.set(r.id, r);
11
+ }
12
+ const planTargets = new Map();
13
+ for (const a of plan) {
14
+ planTargets.set(a.id, a.targetStatus);
15
+ }
16
+ const out = [];
17
+ for (const a of plan) {
18
+ if (a.targetStatus !== "approved") {
19
+ continue;
20
+ }
21
+ const rec = byId.get(a.id);
22
+ if (rec === undefined) {
23
+ continue;
24
+ } /* missing record is caught elsewhere */
25
+ for (const ref of refsOf(rec)) {
26
+ const refRec = byId.get(ref.id);
27
+ const refStatus = effectiveStatus(refRec, planTargets.get(ref.id));
28
+ if (refStatus === null) {
29
+ continue;
30
+ } /* missing referenced record — not a graph violation */
31
+ if (TERMINAL_STATUSES.has(refStatus)) {
32
+ continue;
33
+ }
34
+ out.push({
35
+ flippedId: a.id,
36
+ referencesId: ref.id,
37
+ referencesStatus: refStatus,
38
+ via: ref.via,
39
+ });
40
+ }
41
+ }
42
+ return out;
43
+ }
44
+ function effectiveStatus(rec, planTarget) {
45
+ if (rec === undefined) {
46
+ return null;
47
+ }
48
+ return planTarget ?? rec.lifecycleStatus ?? "draft";
49
+ }
50
+ function refsOf(rec) {
51
+ const out = [];
52
+ const v = rec.parsed;
53
+ /* Surface.members[] */
54
+ const members = v.members;
55
+ if (Array.isArray(members)) {
56
+ for (const m of members) {
57
+ if (typeof m === "string") {
58
+ out.push({ id: m, via: "members" });
59
+ }
60
+ }
61
+ }
62
+ /* surface_ref */
63
+ const surfaceRef = v.surface_ref;
64
+ if (typeof surfaceRef === "string") {
65
+ out.push({ id: surfaceRef, via: "surface_ref" });
66
+ }
67
+ /* policy_refs[] */
68
+ const policyRefs = v.policy_refs;
69
+ if (Array.isArray(policyRefs)) {
70
+ for (const p of policyRefs) {
71
+ if (typeof p === "string") {
72
+ out.push({ id: p, via: "policy_refs" });
73
+ }
74
+ }
75
+ }
76
+ /* target_ids[] (Migration / Delta) */
77
+ const targetIds = v.target_ids;
78
+ if (Array.isArray(targetIds)) {
79
+ for (const t of targetIds) {
80
+ if (typeof t === "string") {
81
+ out.push({ id: t, via: "target_ids" });
82
+ }
83
+ }
84
+ }
85
+ return out;
86
+ }
@@ -0,0 +1,7 @@
1
+ import type { CommandResult, OutputFormat } from "../../../../shared/domain/CliOutput.js";
2
+ export interface FinalizeRequest {
3
+ planId?: string;
4
+ }
5
+ export interface FinalizeCommand {
6
+ execute(cwd: string, req: FinalizeRequest, format: Exclude<OutputFormat, "yaml">): Promise<CommandResult>;
7
+ }
@@ -0,0 +1,3 @@
1
+ export interface FinalizeClock {
2
+ now(): Date;
3
+ }
@@ -0,0 +1,4 @@
1
+ import type { SddConfig } from "../../../../shared/domain/Config.js";
2
+ export interface FinalizeConfigPort {
3
+ config(repoRoot: string): Promise<SddConfig>;
4
+ }
@@ -0,0 +1,14 @@
1
+ export interface SpecFileEntry {
2
+ path: string;
3
+ content: string;
4
+ }
5
+ export interface FinalizeFileSystem {
6
+ resolveSpecFiles(repoRoot: string, patterns: readonly string[]): Promise<SpecFileEntry[]>;
7
+ /** Atomic batch write: either every (path, content) pair lands or none.
8
+ * Implementations write to .tmp files and then rename in a deterministic
9
+ * order so a mid-flight failure leaves the working tree byte-stable. */
10
+ writeBatch(repoRoot: string, entries: ReadonlyArray<{
11
+ path: string;
12
+ content: string;
13
+ }>): Promise<void>;
14
+ }
@@ -0,0 +1,21 @@
1
+ import type { PlanFileShape } from "../../../../shared/domain/PlanFile.js";
2
+ export type PlanLoad = {
3
+ kind: "found";
4
+ plan: PlanFileShape;
5
+ sourcePath: string;
6
+ } | {
7
+ kind: "no-active-plan";
8
+ } | {
9
+ kind: "invalid-plan-file";
10
+ planId: string;
11
+ sourcePath: string;
12
+ reason: string;
13
+ };
14
+ export interface PlanRepo {
15
+ load(repoRoot: string, plansDir: string, planId: string | undefined): Promise<PlanLoad>;
16
+ /** Atomically move the plan file to <plansDir>/finalized/<plan_id>.yaml.
17
+ * Also clears <plansDir>/.active if it pointed at this plan_id. */
18
+ archive(repoRoot: string, plansDir: string, planId: string): Promise<{
19
+ archivedPath: string;
20
+ }>;
21
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { type CommandResult } from "../../../../shared/domain/CliOutput.js";
2
+ import { type InstallPorts } from "../../application/InstallRules.js";
3
+ import type { InstallCommand, InstallOptions, InstallTarget } from "../../ports/inbound/InstallCommand.js";
4
+ export declare class CliInstallHandler implements InstallCommand {
5
+ private readonly ports;
6
+ constructor(ports: InstallPorts);
7
+ execute(target: InstallTarget, options: InstallOptions, format: "json" | "human"): Promise<CommandResult>;
8
+ }
@@ -0,0 +1,54 @@
1
+ import { ok } from "../../../../shared/domain/CliOutput.js";
2
+ import { installRules, } from "../../application/InstallRules.js";
3
+ export class CliInstallHandler {
4
+ ports;
5
+ constructor(ports) {
6
+ this.ports = ports;
7
+ }
8
+ async execute(target, options, format) {
9
+ const outcome = await installRules(target, options.dryRun, this.ports, options.scope);
10
+ return format === "json" ? toJson(outcome) : toHuman(outcome);
11
+ }
12
+ }
13
+ function toJson(outcome) {
14
+ if (!outcome.ok) {
15
+ const body = JSON.stringify({
16
+ format_version: 1,
17
+ ok: false,
18
+ reason: outcome.reason,
19
+ detail: outcome.message,
20
+ });
21
+ return { exitCode: outcome.exitCode, stdout: `${body}\n`, stderr: "" };
22
+ }
23
+ return ok(JSON.stringify({
24
+ format_version: 1,
25
+ ok: true,
26
+ dry_run: outcome.dryRun,
27
+ scope: outcome.scope,
28
+ targets: outcome.targets,
29
+ actions: outcome.actions.map((a) => ({
30
+ target: a.target,
31
+ kind: a.kind,
32
+ op: a.op,
33
+ path: a.path,
34
+ note: a.note,
35
+ })),
36
+ }));
37
+ }
38
+ function toHuman(outcome) {
39
+ if (!outcome.ok) {
40
+ return {
41
+ exitCode: outcome.exitCode,
42
+ stdout: "",
43
+ stderr: `${outcome.reason}: ${outcome.message}\n`,
44
+ };
45
+ }
46
+ const header = outcome.dryRun
47
+ ? `sdd install (dry run) — ${outcome.targets.join(", ")}: ${outcome.actions.length} action(s) planned`
48
+ : `sdd install — ${outcome.targets.join(", ")}: ${outcome.actions.length} action(s) applied`;
49
+ const lines = outcome.actions.map((a) => {
50
+ const note = a.note ? ` (${a.note})` : "";
51
+ return ` ${a.op.padEnd(11)} ${a.target.padEnd(6)} ${a.path}${note}`;
52
+ });
53
+ return ok([header, ...lines].join("\n"));
54
+ }
@@ -0,0 +1,7 @@
1
+ import type { InstallSource } from "../../ports/outbound/InstallSource.js";
2
+ export declare class NodeInstallSource implements InstallSource {
3
+ private readonly rulesRoot;
4
+ constructor(rulesRoot?: string);
5
+ manifestText(): Promise<string | null>;
6
+ readArtifact(source: string): Promise<string | null>;
7
+ }
@@ -0,0 +1,24 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const DEFAULT_RULES_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "..", "..", "rules");
5
+ export class NodeInstallSource {
6
+ rulesRoot;
7
+ constructor(rulesRoot = DEFAULT_RULES_ROOT) {
8
+ this.rulesRoot = rulesRoot;
9
+ }
10
+ manifestText() {
11
+ return readTextOrNull(resolve(this.rulesRoot, "manifest.json"));
12
+ }
13
+ readArtifact(source) {
14
+ return readTextOrNull(resolve(this.rulesRoot, source));
15
+ }
16
+ }
17
+ async function readTextOrNull(absPath) {
18
+ try {
19
+ return await readFile(absPath, "utf8");
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
@@ -0,0 +1,7 @@
1
+ import type { InstallTargetFs } from "../../ports/outbound/InstallTargetFs.js";
2
+ export declare class NodeInstallTargetFs implements InstallTargetFs {
3
+ homeRoot(): string;
4
+ projectRoot(): string;
5
+ readText(absPath: string): Promise<string | null>;
6
+ writeText(absPath: string, content: string, executable: boolean): Promise<void>;
7
+ }
@@ -0,0 +1,30 @@
1
+ import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { dirname } from "node:path";
4
+ import process from "node:process";
5
+ export class NodeInstallTargetFs {
6
+ homeRoot() {
7
+ const override = process.env.SDD_INSTALL_HOME;
8
+ return override !== undefined && override.length > 0 ? override : homedir();
9
+ }
10
+ projectRoot() {
11
+ return process.cwd();
12
+ }
13
+ async readText(absPath) {
14
+ try {
15
+ return await readFile(absPath, "utf8");
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ async writeText(absPath, content, executable) {
22
+ await mkdir(dirname(absPath), { recursive: true });
23
+ const tmp = `${absPath}.tmp.${process.pid}.${Date.now()}`;
24
+ await writeFile(tmp, content, "utf8");
25
+ if (executable) {
26
+ await chmod(tmp, 0o755);
27
+ }
28
+ await rename(tmp, absPath);
29
+ }
30
+ }
@@ -0,0 +1,10 @@
1
+ import type { InstallAction, InstallOutcome } from "../domain/InstallResult.js";
2
+ import { type InstallScope, type InstallTarget } from "../domain/InstallTarget.js";
3
+ import type { InstallSource } from "../ports/outbound/InstallSource.js";
4
+ import type { InstallTargetFs } from "../ports/outbound/InstallTargetFs.js";
5
+ export type { InstallAction, InstallOutcome };
6
+ export interface InstallPorts {
7
+ source: InstallSource;
8
+ fs: InstallTargetFs;
9
+ }
10
+ export declare function installRules(target: InstallTarget, dryRun: boolean, ports: InstallPorts, scope?: InstallScope): Promise<InstallOutcome>;
@@ -0,0 +1,73 @@
1
+ import { buildPlan, homePath, installLayout, } from "../domain/InstallPlan.js";
2
+ import { agentsFor, } from "../domain/InstallTarget.js";
3
+ import { ManifestError, parseManifest } from "../domain/RuleManifest.js";
4
+ export async function installRules(target, dryRun, ports, scope = "user") {
5
+ const manifestText = await ports.source.manifestText();
6
+ if (manifestText === null) {
7
+ return {
8
+ ok: false,
9
+ exitCode: 1,
10
+ reason: "manifest-missing",
11
+ message: "packaged rules/manifest.json was not found",
12
+ };
13
+ }
14
+ let manifest;
15
+ try {
16
+ manifest = parseManifest(manifestText);
17
+ }
18
+ catch (error) {
19
+ if (error instanceof ManifestError) {
20
+ return {
21
+ ok: false,
22
+ exitCode: 1,
23
+ reason: "manifest-invalid",
24
+ message: error.message,
25
+ };
26
+ }
27
+ throw error;
28
+ }
29
+ const agents = agentsFor(target);
30
+ const sources = new Map();
31
+ for (const artifact of manifest.artifacts) {
32
+ if (!artifact.targets.some((t) => agents.includes(t)) ||
33
+ sources.has(artifact.source)) {
34
+ continue;
35
+ }
36
+ const content = await ports.source.readArtifact(artifact.source);
37
+ if (content === null) {
38
+ return {
39
+ ok: false,
40
+ exitCode: 1,
41
+ reason: "artifact-missing",
42
+ message: `packaged rule file was not found: ${artifact.source}`,
43
+ };
44
+ }
45
+ sources.set(artifact.source, content);
46
+ }
47
+ const layout = installLayout(scope);
48
+ const home = scope === "project" ? ports.fs.projectRoot() : ports.fs.homeRoot();
49
+ const writes = [];
50
+ const actions = [];
51
+ for (const agent of agents) {
52
+ const existing = {
53
+ claudeMd: agent === "claude"
54
+ ? await ports.fs.readText(homePath(home, layout.claudeMemoryRel))
55
+ : null,
56
+ settingsJson: agent === "claude"
57
+ ? await ports.fs.readText(homePath(home, ".claude/settings.json"))
58
+ : null,
59
+ agentsMd: agent === "codex"
60
+ ? await ports.fs.readText(homePath(home, layout.codexMemoryRel))
61
+ : null,
62
+ };
63
+ const plan = buildPlan(manifest, agent, sources, existing, home, scope);
64
+ writes.push(...plan.writes);
65
+ actions.push(...plan.actions);
66
+ }
67
+ if (!dryRun) {
68
+ for (const write of writes) {
69
+ await ports.fs.writeText(write.absPath, write.content, write.executable);
70
+ }
71
+ }
72
+ return { ok: true, dryRun, scope, targets: [...agents], actions };
73
+ }
@@ -0,0 +1,27 @@
1
+ import type { AgentTarget, InstallScope } from "./InstallTarget.js";
2
+ import type { InstallAction } from "./InstallResult.js";
3
+ import type { RuleManifest } from "./RuleManifest.js";
4
+ export interface PlannedWrite {
5
+ absPath: string;
6
+ content: string;
7
+ executable: boolean;
8
+ }
9
+ export interface ExistingTargetFiles {
10
+ claudeMd: string | null;
11
+ settingsJson: string | null;
12
+ agentsMd: string | null;
13
+ }
14
+ export interface InstallPlanResult {
15
+ writes: PlannedWrite[];
16
+ actions: InstallAction[];
17
+ }
18
+ export interface InstallLayout {
19
+ claudeMemoryRel: string;
20
+ codexMemoryRel: string;
21
+ claudeImportPrefix: string;
22
+ codexRulePrefix: string;
23
+ hookCommand(home: string, source: string): string;
24
+ }
25
+ export declare function installLayout(scope: InstallScope): InstallLayout;
26
+ export declare function buildPlan(manifest: RuleManifest, agent: AgentTarget, sources: ReadonlyMap<string, string>, existing: ExistingTargetFiles, home: string, scope?: InstallScope): InstallPlanResult;
27
+ export declare function homePath(home: string, relPath: string): string;