@use-the-fork/spindle 0.0.0-stage → 0.0.1

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 (245) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -2
  3. package/build/Assets/Blueprints/Catalog.js +110 -0
  4. package/build/Assets/Blueprints/agents/general.agent.md +67 -0
  5. package/build/Assets/Blueprints/agents/sdd-code-reviewer.agent.md +62 -0
  6. package/build/Assets/Blueprints/agents/sdd-code-slop-reviewer.agent.md +59 -0
  7. package/build/Assets/Blueprints/agents/sdd-implementer.agent.md +77 -0
  8. package/build/Assets/Blueprints/agents/sdd-orchestrator.agent.md +42 -0
  9. package/build/Assets/Blueprints/agents/sdd-re-review.agent.md +57 -0
  10. package/build/Assets/Blueprints/agents/sdd-reviewer.agent.md +89 -0
  11. package/build/Assets/Blueprints/agents/sdd-task-reviewer.agent.md +54 -0
  12. package/build/Assets/Blueprints/agents/shared-codebase-analyzer.agent.md +151 -0
  13. package/build/Assets/Blueprints/agents/shared-codebase-locator.agent.md +130 -0
  14. package/build/Assets/Blueprints/agents/shared-codebase-pattern-finder.agent.md +247 -0
  15. package/build/Assets/Blueprints/agents/shared-explore.agent.md +53 -0
  16. package/build/Assets/Blueprints/agents/shared-r.agent.md +17 -0
  17. package/build/Assets/Blueprints/agents/shared-rw.agent.md +17 -0
  18. package/build/Assets/Blueprints/agents/shared-rwx.agent.md +17 -0
  19. package/build/Assets/Blueprints/agents/shared-web-search-researcher.agent.md +122 -0
  20. package/build/Assets/Blueprints/instructions/code-commenting.instructions.md +39 -0
  21. package/build/Assets/Blueprints/instructions/source-architecture.instructions.md +15 -0
  22. package/build/Assets/Blueprints/skills/asd-ste100/CREDITS.MD +1 -0
  23. package/build/Assets/Blueprints/skills/asd-ste100/SKILL.md +83 -0
  24. package/build/Assets/Blueprints/skills/asd-ste100/examples/before-after.md +107 -0
  25. package/build/Assets/Blueprints/skills/asd-ste100/references/writing-rules.md +65 -0
  26. package/build/Assets/Blueprints/skills/author-agent/SKILL.md +26 -0
  27. package/build/Assets/Blueprints/skills/author-design/SKILL.md +38 -0
  28. package/build/Assets/Blueprints/skills/author-instruction/SKILL.md +28 -0
  29. package/build/Assets/Blueprints/skills/author-skill/SKILL.md +26 -0
  30. package/build/Assets/Blueprints/skills/grill/SKILL.md +33 -0
  31. package/build/Assets/Blueprints/skills/grill-design/SKILL.md +41 -0
  32. package/build/Assets/Blueprints/skills/grill-with-docs/SKILL.md +14 -0
  33. package/build/Assets/Blueprints/skills/implement/SKILL.md +79 -0
  34. package/build/Assets/Blueprints/skills/implement-spec/SKILL.md +34 -0
  35. package/build/Assets/Blueprints/skills/improve-codebase-architecture/HTML-REPORT.md +129 -0
  36. package/build/Assets/Blueprints/skills/improve-codebase-architecture/SKILL.md +74 -0
  37. package/build/Assets/Blueprints/skills/int-code-review/SKILL.md +76 -0
  38. package/build/Assets/Blueprints/skills/int-code-slop-review/SKILL.md +238 -0
  39. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/_sections.md +36 -0
  40. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/_template.md +42 -0
  41. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/comments-closing-brace-labels.md +112 -0
  42. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/comments-empty-docblocks.md +132 -0
  43. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/comments-narration.md +118 -0
  44. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/comments-placeholder.md +130 -0
  45. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/defensive-generic-catch.md +153 -0
  46. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/defensive-impossible-null.md +157 -0
  47. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/defensive-missing-real.md +157 -0
  48. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/naming-generic-placeholders.md +120 -0
  49. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/naming-over-descriptive.md +108 -0
  50. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/naming-suffix-abuse.md +167 -0
  51. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/naming-type-in-name.md +100 -0
  52. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/over-eng-dependency-creep.md +114 -0
  53. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/over-eng-premature-interface.md +136 -0
  54. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/over-eng-single-method-class.md +161 -0
  55. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/over-eng-useless-wrapper.md +140 -0
  56. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/style-as-any-escape.md +127 -0
  57. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/style-debug-artifacts.md +144 -0
  58. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/style-hyper-consistent.md +84 -0
  59. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/style-no-hack-scars.md +113 -0
  60. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/style-trivial-boilerplate.md +191 -0
  61. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/test-doesnt-throw.md +132 -0
  62. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/test-mirror-implementation.md +125 -0
  63. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/test-mock-everything.md +148 -0
  64. package/build/Assets/Blueprints/skills/int-code-slop-review/rules/test-snapshot-abuse.md +131 -0
  65. package/build/Assets/Blueprints/skills/int-codebase-design/SKILL.md +116 -0
  66. package/build/Assets/Blueprints/skills/int-codebase-design/references/DEEPENING.md +37 -0
  67. package/build/Assets/Blueprints/skills/int-codebase-design/references/DESIGN-IT-TWICE.md +44 -0
  68. package/build/Assets/Blueprints/skills/int-domain-modeling/SKILL.md +78 -0
  69. package/build/Assets/Blueprints/skills/int-domain-modeling/references/ADR-FORMAT.md +47 -0
  70. package/build/Assets/Blueprints/skills/int-domain-modeling/references/GLOSSARY-FORMAT.md +60 -0
  71. package/build/Assets/Blueprints/skills/int-prototype/LOGIC.md +67 -0
  72. package/build/Assets/Blueprints/skills/int-prototype/SKILL.md +30 -0
  73. package/build/Assets/Blueprints/skills/int-prototype/UI.md +112 -0
  74. package/build/Assets/Blueprints/skills/int-retrospective/SKILL.md +88 -0
  75. package/build/Assets/Blueprints/skills/int-retrospective/assets/retrospective-prompt.md +38 -0
  76. package/build/Assets/Blueprints/skills/int-retrospective/references/assessment.md +56 -0
  77. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/SKILL.md +64 -0
  78. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/assets/implementer-prompt.md +40 -0
  79. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/assets/reviewer-prompt.md +43 -0
  80. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/aggregate-review.md +7 -0
  81. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/corrective-rounds.md +72 -0
  82. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/example-workflow.md +25 -0
  83. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/full-spec.md +72 -0
  84. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/implementer-corrections.md +9 -0
  85. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/review-inputs.md +26 -0
  86. package/build/Assets/Blueprints/skills/int-subagent-driven-dev/references/verification-evidence.md +7 -0
  87. package/build/Assets/Blueprints/skills/int-test-driven-development/SKILL.md +51 -0
  88. package/build/Assets/Blueprints/skills/int-test-driven-development/references/mocking.md +31 -0
  89. package/build/Assets/Blueprints/skills/int-test-driven-development/references/tests.md +68 -0
  90. package/build/Assets/Blueprints/skills/int-testing-agent-guidance/SKILL.md +53 -0
  91. package/build/Assets/Blueprints/skills/int-verification-before-completion/SKILL.md +25 -0
  92. package/build/Assets/Blueprints/skills/int-writing-agents/SKILL.md +66 -0
  93. package/build/Assets/Blueprints/skills/int-writing-for-agents/SKILL.md +86 -0
  94. package/build/Assets/Blueprints/skills/int-writing-instruction/SKILL.md +57 -0
  95. package/build/Assets/Blueprints/skills/int-writing-skills/SKILL.md +129 -0
  96. package/build/Assets/Blueprints/skills/int-writing-skills/assets/interactive.md +83 -0
  97. package/build/Assets/Blueprints/skills/int-writing-skills/assets/reference.md +32 -0
  98. package/build/Assets/Blueprints/skills/int-writing-skills/references/arguments.md +50 -0
  99. package/build/Assets/Blueprints/skills/int-writing-skills/references/interactive-skills.md +53 -0
  100. package/build/Assets/Blueprints/skills/int-writing-skills/references/persuasion-principles.md +220 -0
  101. package/build/Assets/Blueprints/skills/int-writing-skills/references/reference-skills.md +20 -0
  102. package/build/Assets/Blueprints/skills/int-writing-skills/references/testing-skills.md +48 -0
  103. package/build/Assets/Blueprints/skills/retrospective/SKILL.md +16 -0
  104. package/build/Assets/Blueprints/skills/setup-project/SKILL.md +66 -0
  105. package/build/Assets/Blueprints/skills/to-spec/SKILL.md +53 -0
  106. package/build/Assets/Blueprints/skills/to-tickets/SKILL.md +49 -0
  107. package/build/Assets/Blueprints/skills/update-tooling/SKILL.md +86 -0
  108. package/build/Assets/Templates/Catalog.js +12 -0
  109. package/build/Assets/Templates/Catalog.ts +17 -0
  110. package/build/Assets/Templates/project/copilot-instructions.md +17 -0
  111. package/build/Assets/Templates/project/domain.md +51 -0
  112. package/build/Assets/Templates/project/ticket-tracker.md +33 -0
  113. package/build/Assets/Templates/sdd/design.md +25 -0
  114. package/build/Assets/Templates/sdd/spec.md +29 -0
  115. package/build/Assets/Templates/sdd/ticket.md +15 -0
  116. package/build/BlueprintManagement/BlueprintManagementServiceProvider.js +15 -0
  117. package/build/BlueprintManagement/Catalog/BlueprintCatalog.js +238 -0
  118. package/build/BlueprintManagement/Commands/BlueprintCommandOptions.js +9 -0
  119. package/build/BlueprintManagement/Commands/ConflictPolicy.js +6 -0
  120. package/build/BlueprintManagement/Commands/InitCommand.js +117 -0
  121. package/build/BlueprintManagement/Commands/Prompts.js +66 -0
  122. package/build/BlueprintManagement/Commands/UpdateCommand.js +86 -0
  123. package/build/BlueprintManagement/Handlers/Agents/AgentHandler.js +21 -0
  124. package/build/BlueprintManagement/Handlers/BlueprintHandlers.js +4 -0
  125. package/build/BlueprintManagement/Handlers/Instructions/InstructionHandler.js +21 -0
  126. package/build/BlueprintManagement/Handlers/Skills/SkillHandler.js +10 -0
  127. package/build/BlueprintManagement/Reconciliation/BlueprintCatalogPlanner.js +87 -0
  128. package/build/BlueprintManagement/Reconciliation/BlueprintRemovalCoordinator.js +78 -0
  129. package/build/BlueprintManagement/Services/BlueprintReconciliationService.js +391 -0
  130. package/build/BlueprintManagement/Services/InstallationService.js +54 -0
  131. package/build/BlueprintManagement/Support/BlueprintFiles.js +113 -0
  132. package/build/BlueprintManagement/Types/Blueprint.js +1 -0
  133. package/build/BlueprintManagement/Types/Installation.js +1 -0
  134. package/build/BlueprintManagement/Types/Reconciliation.js +1 -0
  135. package/build/BlueprintManagement/Versioning/BlueprintVersion.js +70 -0
  136. package/build/BlueprintManagement/Versioning/BlueprintVersioning.js +55 -0
  137. package/build/Commands/Command.js +3 -0
  138. package/build/Commands/CommandOptions.js +12 -0
  139. package/build/Config/Config.js +3 -0
  140. package/build/Foundation/Application.js +112 -0
  141. package/build/Foundation/ApplicationBuilder.js +23 -0
  142. package/build/Foundation/Bootstrap/Bootstrapper.js +2 -0
  143. package/build/Foundation/Bootstrap/DiscoverGitRoot.js +8 -0
  144. package/build/Foundation/Bootstrap/LoadConsoleArgs.js +47 -0
  145. package/build/Foundation/Bootstrap/LoadProjectConfiguration.js +144 -0
  146. package/build/Foundation/Bootstrap/RegisterProviders.js +12 -0
  147. package/build/Foundation/Bootstrap/RequireProjectConfiguration.js +14 -0
  148. package/build/Foundation/ConsoleInvocation.js +1 -0
  149. package/build/Foundation/Container.js +185 -0
  150. package/build/Foundation/FoundationServiceProvider.js +5 -0
  151. package/build/Foundation/Kernel.js +30 -0
  152. package/build/Foundation/Service.js +23 -0
  153. package/build/Foundation/ServiceProvider.js +12 -0
  154. package/build/Git/GitServiceProvider.js +8 -0
  155. package/build/Git/Services/GitService.js +26 -0
  156. package/build/Project/ProjectServiceProvider.js +8 -0
  157. package/build/Project/Services/ProjectService.js +124 -0
  158. package/build/SubagentDrivenDevelopment/Commands/ChecksRecordCommand.js +35 -0
  159. package/build/SubagentDrivenDevelopment/Commands/ChecksRequireCommand.js +33 -0
  160. package/build/SubagentDrivenDevelopment/Commands/ClaimCommand.js +23 -0
  161. package/build/SubagentDrivenDevelopment/Commands/CorrectCommand.js +37 -0
  162. package/build/SubagentDrivenDevelopment/Commands/CreateCommand.js +26 -0
  163. package/build/SubagentDrivenDevelopment/Commands/FindingCreateCommand.js +39 -0
  164. package/build/SubagentDrivenDevelopment/Commands/FindingUpdateCommand.js +36 -0
  165. package/build/SubagentDrivenDevelopment/Commands/FinishCommand.js +23 -0
  166. package/build/SubagentDrivenDevelopment/Commands/ImplementCommand.js +23 -0
  167. package/build/SubagentDrivenDevelopment/Commands/NextCommand.js +21 -0
  168. package/build/SubagentDrivenDevelopment/Commands/ReadyCommand.js +21 -0
  169. package/build/SubagentDrivenDevelopment/Commands/RequirementsDecideCommand.js +33 -0
  170. package/build/SubagentDrivenDevelopment/Commands/ResumeCommand.js +31 -0
  171. package/build/SubagentDrivenDevelopment/Commands/ReviewCommand.js +55 -0
  172. package/build/SubagentDrivenDevelopment/Commands/ReviewRequireCommand.js +12 -0
  173. package/build/SubagentDrivenDevelopment/Commands/StatusCommand.js +21 -0
  174. package/build/SubagentDrivenDevelopment/Commands/SubmitCommand.js +59 -0
  175. package/build/SubagentDrivenDevelopment/Commands/TicketCommentCommand.js +24 -0
  176. package/build/SubagentDrivenDevelopment/Commands/TicketCreateCommand.js +25 -0
  177. package/build/SubagentDrivenDevelopment/Commands/TicketUpdateCommand.js +31 -0
  178. package/build/SubagentDrivenDevelopment/Commands/groups.js +36 -0
  179. package/build/SubagentDrivenDevelopment/Evidence/GitEvidence.js +449 -0
  180. package/build/SubagentDrivenDevelopment/Evidence/ReportEvidence.js +80 -0
  181. package/build/SubagentDrivenDevelopment/Models/Assignments.js +1 -0
  182. package/build/SubagentDrivenDevelopment/Models/Evidence.js +1 -0
  183. package/build/SubagentDrivenDevelopment/Models/Findings.js +1 -0
  184. package/build/SubagentDrivenDevelopment/Models/Options.js +1 -0
  185. package/build/SubagentDrivenDevelopment/Models/Workflow.js +16 -0
  186. package/build/SubagentDrivenDevelopment/Persistence/AssignmentSchema.js +155 -0
  187. package/build/SubagentDrivenDevelopment/Persistence/CheckSchema.js +71 -0
  188. package/build/SubagentDrivenDevelopment/Persistence/FeatureWorkspace.js +76 -0
  189. package/build/SubagentDrivenDevelopment/Persistence/FileSystem.js +28 -0
  190. package/build/SubagentDrivenDevelopment/Persistence/FindingSchema.js +81 -0
  191. package/build/SubagentDrivenDevelopment/Persistence/LedgerRepository.js +322 -0
  192. package/build/SubagentDrivenDevelopment/Persistence/PathSafety.js +62 -0
  193. package/build/SubagentDrivenDevelopment/Persistence/ProgressSchema.js +95 -0
  194. package/build/SubagentDrivenDevelopment/Persistence/ReadinessReader.js +40 -0
  195. package/build/SubagentDrivenDevelopment/Persistence/ReviewSchema.js +68 -0
  196. package/build/SubagentDrivenDevelopment/Persistence/TicketRepository.js +147 -0
  197. package/build/SubagentDrivenDevelopment/Persistence/WorkspaceTransaction.js +282 -0
  198. package/build/SubagentDrivenDevelopment/Policies/AcceptancePolicy.js +100 -0
  199. package/build/SubagentDrivenDevelopment/Policies/AssignmentPolicy.js +36 -0
  200. package/build/SubagentDrivenDevelopment/Policies/CheckPolicy.js +93 -0
  201. package/build/SubagentDrivenDevelopment/Policies/FindingPolicy.js +53 -0
  202. package/build/SubagentDrivenDevelopment/Policies/InputValidation.js +36 -0
  203. package/build/SubagentDrivenDevelopment/Policies/ReadinessPolicy.js +26 -0
  204. package/build/SubagentDrivenDevelopment/Policies/RequiredReviewers.js +12 -0
  205. package/build/SubagentDrivenDevelopment/Policies/ReviewPolicy.js +87 -0
  206. package/build/SubagentDrivenDevelopment/Policies/WorkflowPolicy.js +85 -0
  207. package/build/SubagentDrivenDevelopment/Services/AssignmentService.js +269 -0
  208. package/build/SubagentDrivenDevelopment/Services/ChecksService.js +319 -0
  209. package/build/SubagentDrivenDevelopment/Services/CorrectionService.js +273 -0
  210. package/build/SubagentDrivenDevelopment/Services/DeliveryCorrectionService.js +253 -0
  211. package/build/SubagentDrivenDevelopment/Services/DeliveryFindingService.js +302 -0
  212. package/build/SubagentDrivenDevelopment/Services/DeliveryService.js +160 -0
  213. package/build/SubagentDrivenDevelopment/Services/DeliverySubmissionService.js +273 -0
  214. package/build/SubagentDrivenDevelopment/Services/FeatureCreationService.js +138 -0
  215. package/build/SubagentDrivenDevelopment/Services/FeatureInspectionService.js +399 -0
  216. package/build/SubagentDrivenDevelopment/Services/FindingService.js +392 -0
  217. package/build/SubagentDrivenDevelopment/Services/IntegrationService.js +258 -0
  218. package/build/SubagentDrivenDevelopment/Services/ReadinessService.js +21 -0
  219. package/build/SubagentDrivenDevelopment/Services/RequirementsService.js +216 -0
  220. package/build/SubagentDrivenDevelopment/Services/ReviewService.js +471 -0
  221. package/build/SubagentDrivenDevelopment/Services/SubmissionService.js +299 -0
  222. package/build/SubagentDrivenDevelopment/Services/TicketService.js +186 -0
  223. package/build/SubagentDrivenDevelopment/SubagentDrivenDevelopmentServiceProvider.js +113 -0
  224. package/build/Support/Records.js +5 -0
  225. package/build/Support/Repository.js +139 -0
  226. package/build/Support/Stacks.js +10 -0
  227. package/build/TemplateRendering/Computed/ComputedContextService.js +13 -0
  228. package/build/TemplateRendering/Computed/ComputedVariableProvider.js +6 -0
  229. package/build/TemplateRendering/Computed/ComputedVariableProviders.js +6 -0
  230. package/build/TemplateRendering/Computed/Providers/InternalSkillDescriptionProvider.js +6 -0
  231. package/build/TemplateRendering/Computed/Providers/SpindlePackageManagerProvider.js +11 -0
  232. package/build/TemplateRendering/Computed/ResolveRenderContext.js +18 -0
  233. package/build/TemplateRendering/Rendering/RenderText.js +43 -0
  234. package/build/TemplateRendering/TemplateRenderingServiceProvider.js +8 -0
  235. package/build/Tooling/Commands/ToolingAddCommand.js +29 -0
  236. package/build/Tooling/Commands/ToolingListCommand.js +19 -0
  237. package/build/Tooling/Commands/ToolingRemoveCommand.js +19 -0
  238. package/build/Tooling/Commands/ToolingUpdateCommand.js +30 -0
  239. package/build/Tooling/Commands/groups.js +4 -0
  240. package/build/Tooling/Models/ToolingEntry.js +1 -0
  241. package/build/Tooling/Services/ToolingService.js +278 -0
  242. package/build/Tooling/ToolingServiceProvider.js +15 -0
  243. package/build/cli.js +36 -0
  244. package/build/index.js +31 -0
  245. package/package.json +54 -3
@@ -0,0 +1,86 @@
1
+ import chalk from "chalk";
2
+ import { BlueprintCommandOptions } from "./BlueprintCommandOptions.js";
3
+ import { parseConflictPolicy } from "./ConflictPolicy.js";
4
+ import { promptNewBlueprints, promptOutdated } from "./Prompts.js";
5
+ import { blueprintHandlers } from "../Handlers/BlueprintHandlers.js";
6
+ import { BlueprintReconciliationService } from "../Services/BlueprintReconciliationService.js";
7
+ import { Command } from "../../Commands/Command.js";
8
+ import { LoadProjectConfiguration } from "../../Foundation/Bootstrap/LoadProjectConfiguration.js";
9
+ import { Stacks } from "../../Support/Stacks.js";
10
+ export class UpdateCommand extends Command {
11
+ handlers = [];
12
+ reconciliationService;
13
+ static register(program, createApp) {
14
+ program
15
+ .command("update")
16
+ .description(`Re-render installed Blueprints (Skills, Agents, and Instructions) whose shipped version is newer.
17
+ Reads stacks and the Spindle package-manager command from .github/spindle.json and leaves it unchanged.
18
+ New shipped Blueprints are offered interactively; use
19
+ --include-new to install all of them without a prompt.`)
20
+ .addOption(BlueprintCommandOptions.conflictPolicyOption("Policy for outdated Blueprints"))
21
+ .addOption(BlueprintCommandOptions.noInteractiveOption("Never prompt; outdated Blueprints without --on-conflict are an error"))
22
+ .option("--include-new", "Install every newly shipped Blueprint without prompting")
23
+ .addHelpText("after", `
24
+ Requires .github/spindle.json; run \`spindle init\` first.
25
+ Installed Blueprints with a missing or non-semver version are skipped with a warning.
26
+ `)
27
+ .allowExcessArguments(false)
28
+ .action(async (options) => {
29
+ const interactive = options.interactive && Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
30
+ const policy = parseConflictPolicy(options.onConflict);
31
+ await (await (await createApp()).make(UpdateCommand)).run(interactive, policy, options.includeNew);
32
+ });
33
+ }
34
+ constructor(app) {
35
+ super(app);
36
+ }
37
+ async boot() {
38
+ this.handlers = blueprintHandlers;
39
+ this.reconciliationService = await this.app.make(BlueprintReconciliationService);
40
+ }
41
+ async run(interactive, policy, includeNew = false) {
42
+ this.assertApplicationBooted();
43
+ const config = LoadProjectConfiguration.require(await LoadProjectConfiguration.refresh(this.app));
44
+ if (config.stacks.length === 0) {
45
+ throw new Error(`No Blueprint stacks are configured. Run \`spindle init --stack <${Stacks.supported.join("|")}>\` first.`);
46
+ }
47
+ const spindlePackageManager = config.config.spindle_package_manager;
48
+ if (spindlePackageManager === undefined) {
49
+ throw new Error('Missing "spindle_package_manager" in .github/spindle.json; add the preferred Spindle package-manager command before running `spindle update`.');
50
+ }
51
+ const outcomes = await this.reconciliationService.reconcile(this.handlers, {
52
+ mode: "update",
53
+ config: config.config,
54
+ includeNew,
55
+ chooseNew: interactive && !includeNew ? promptNewBlueprints : undefined,
56
+ conflictPolicy: policy,
57
+ chooseConflict: interactive && policy === undefined
58
+ ? async (kind, name, installed, available) => promptOutdated(kind, name, installed, available)
59
+ : undefined,
60
+ resolveContext: async () => ({
61
+ stacks: config.stacks,
62
+ variables: {},
63
+ }),
64
+ });
65
+ await LoadProjectConfiguration.refresh(this.app);
66
+ for (const outcome of outcomes) {
67
+ if (outcome.warning) {
68
+ console.error(chalk.yellow(outcome.warning));
69
+ }
70
+ }
71
+ for (const outcome of outcomes.filter((item) => item.status === "removed")) {
72
+ console.log(`${chalk.green("✔")} Removed ${outcome.kind.toLowerCase()} '${outcome.name}'`);
73
+ }
74
+ if (outcomes.length === 0) {
75
+ console.log(`${chalk.green("✔")} No Blueprints apply to the selected stacks`);
76
+ }
77
+ for (const kind of new Set(outcomes.map((outcome) => outcome.kind))) {
78
+ const ofKind = outcomes.filter((outcome) => outcome.kind === kind);
79
+ const added = ofKind.filter((outcome) => outcome.status === "installed").length;
80
+ const updated = ofKind.filter((outcome) => outcome.status === "updated").length;
81
+ const skipped = ofKind.filter((outcome) => outcome.status === "skipped").length;
82
+ const upToDate = ofKind.filter((outcome) => outcome.status === "up-to-date").length;
83
+ console.log(`${chalk.green("✔")} Added ${added}, updated ${updated}, skipped ${skipped}, up to date ${upToDate} ${kind.toLowerCase()}(s)`);
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,21 @@
1
+ import { join } from "node:path";
2
+ import { planVersionedUpdate, validateVersionedMetadata, } from "../../Versioning/BlueprintVersioning.js";
3
+ export const agentHandler = {
4
+ kind: "Agent",
5
+ catalogKind: "agents",
6
+ sourceDirectory: (blueprintSourceRoot) => join(blueprintSourceRoot, "agents"),
7
+ destinationDirectory: (githubDirectory) => join(githubDirectory, "agents"),
8
+ fileTarget: true,
9
+ targetPath: (destinationDirectory, name) => join(destinationDirectory, name),
10
+ validateMetadata: (relativePath, renderedText) => {
11
+ if (relativePath.toLowerCase().endsWith(".md")) {
12
+ validateVersionedMetadata("Agent", relativePath, relativePath, renderedText);
13
+ }
14
+ },
15
+ planUpdate: (input) => {
16
+ const entry = input.sourceFiles[0].outputPath;
17
+ return entry.toLowerCase().endsWith(".md")
18
+ ? planVersionedUpdate(input, "Agent", entry, (target) => target, "warning")
19
+ : Promise.resolve({ status: input.installed ? "conflict" : "new" });
20
+ },
21
+ };
@@ -0,0 +1,4 @@
1
+ import { agentHandler } from "./Agents/AgentHandler.js";
2
+ import { instructionHandler } from "./Instructions/InstructionHandler.js";
3
+ import { skillHandler } from "./Skills/SkillHandler.js";
4
+ export const blueprintHandlers = [skillHandler, agentHandler, instructionHandler];
@@ -0,0 +1,21 @@
1
+ import { join } from "node:path";
2
+ import { planVersionedUpdate, validateVersionedMetadata, } from "../../Versioning/BlueprintVersioning.js";
3
+ export const instructionHandler = {
4
+ kind: "Instruction",
5
+ catalogKind: "instructions",
6
+ sourceDirectory: (blueprintSourceRoot) => join(blueprintSourceRoot, "instructions"),
7
+ destinationDirectory: (githubDirectory) => join(githubDirectory, "instructions"),
8
+ fileTarget: true,
9
+ targetPath: (destinationDirectory, name) => join(destinationDirectory, name),
10
+ validateMetadata: (relativePath, renderedText) => {
11
+ if (relativePath.toLowerCase().endsWith(".md")) {
12
+ validateVersionedMetadata("Instruction", relativePath, relativePath, renderedText);
13
+ }
14
+ },
15
+ planUpdate: (input) => {
16
+ const entry = input.sourceFiles[0].outputPath;
17
+ return entry.toLowerCase().endsWith(".md")
18
+ ? planVersionedUpdate(input, "Instruction", entry, (target) => target, "warning")
19
+ : Promise.resolve({ status: input.installed ? "conflict" : "new" });
20
+ },
21
+ };
@@ -0,0 +1,10 @@
1
+ import { join } from "node:path";
2
+ import { planVersionedUpdate, validateVersionedMetadata, } from "../../Versioning/BlueprintVersioning.js";
3
+ export const skillHandler = {
4
+ kind: "Skill",
5
+ catalogKind: "skills",
6
+ sourceDirectory: (blueprintSourceRoot) => join(blueprintSourceRoot, "skills"),
7
+ destinationDirectory: (githubDirectory) => join(githubDirectory, "skills"),
8
+ validateMetadata: (relativePath, renderedText) => validateVersionedMetadata("Skill", "SKILL.md", relativePath, renderedText),
9
+ planUpdate: (input) => planVersionedUpdate(input, "Skill", "SKILL.md", (target) => join(target, "SKILL.md"), "error"),
10
+ };
@@ -0,0 +1,87 @@
1
+ import { lstat, readdir } from "node:fs/promises";
2
+ import { join, relative, sep } from "node:path";
3
+ import { planBlueprintCatalog, blueprintCatalog, validateBlueprintCatalog, } from "../Catalog/BlueprintCatalog.js";
4
+ import { assertSafeInstallPaths } from "../Support/BlueprintFiles.js";
5
+ async function collectDestinationFiles(directory, result = []) {
6
+ let directoryStat;
7
+ try {
8
+ directoryStat = await lstat(directory);
9
+ }
10
+ catch (error) {
11
+ if (error.code === "ENOENT")
12
+ return result;
13
+ throw error;
14
+ }
15
+ if (directoryStat.isSymbolicLink()) {
16
+ throw new Error(`Refusing to reconcile selected directory '${directory}': symbolic-link traversal is unsafe.`);
17
+ }
18
+ if (!directoryStat.isDirectory()) {
19
+ throw new Error(`Refusing to reconcile selected directory '${directory}': expected a directory.`);
20
+ }
21
+ for (const entry of (await readdir(directory)).sort()) {
22
+ const path = join(directory, entry);
23
+ const stat = await lstat(path);
24
+ if (stat.isSymbolicLink()) {
25
+ throw new Error(`Refusing to reconcile selected directory '${directory}': symbolic link '${path}' is unsafe.`);
26
+ }
27
+ if (stat.isDirectory()) {
28
+ await collectDestinationFiles(path, result);
29
+ }
30
+ else if (stat.isFile()) {
31
+ result.push(path);
32
+ }
33
+ else {
34
+ throw new Error(`Refusing to reconcile selected directory '${directory}': '${path}' is not a regular file or directory.`);
35
+ }
36
+ }
37
+ return result;
38
+ }
39
+ export async function planBlueprintCatalogReconciliation(handlers, githubDirectory, blueprintSourceRoot, selectedStacks) {
40
+ const catalog = validateBlueprintCatalog(blueprintCatalog);
41
+ const handlerPlans = [];
42
+ for (const handler of handlers) {
43
+ const expansion = await planBlueprintCatalog(catalog, handler.catalogKind, handler.sourceDirectory(blueprintSourceRoot), selectedStacks);
44
+ const destinationDirectory = handler.destinationDirectory(githubDirectory);
45
+ const deletions = expansion.deletions.map((deletion) => ({
46
+ kind: handler.kind,
47
+ catalogKind: handler.catalogKind,
48
+ key: deletion.entry.key,
49
+ path: deletion.path,
50
+ target: handler.targetPath?.(destinationDirectory, deletion.path) ??
51
+ join(destinationDirectory, deletion.path),
52
+ directory: deletion.entry.directory,
53
+ reason: deletion.reason,
54
+ }));
55
+ const membershipCleanup = [];
56
+ for (const directory of expansion.directories) {
57
+ const directoryTarget = handler.targetPath?.(destinationDirectory, directory.path) ??
58
+ join(destinationDirectory, directory.path);
59
+ await assertSafeInstallPaths(githubDirectory, [directory.path], destinationDirectory, (name) => handler.targetPath?.(destinationDirectory, name) ?? join(destinationDirectory, name));
60
+ const sourceFiles = new Set(directory.sourceFiles);
61
+ const installedFiles = await collectDestinationFiles(directoryTarget);
62
+ for (const installedFile of installedFiles) {
63
+ const relativePath = relative(directoryTarget, installedFile).split(sep).join("/");
64
+ if (sourceFiles.has(relativePath))
65
+ continue;
66
+ const path = `${directory.path}/${relativePath}`;
67
+ membershipCleanup.push({
68
+ kind: handler.kind,
69
+ catalogKind: handler.catalogKind,
70
+ key: directory.entry.key,
71
+ path,
72
+ target: handler.targetPath?.(destinationDirectory, path) ?? join(destinationDirectory, path),
73
+ directory: false,
74
+ reason: "directory-membership",
75
+ });
76
+ }
77
+ }
78
+ handlerPlans.push({
79
+ handler,
80
+ selections: expansion.selections,
81
+ catalogDeletions: expansion.deletions,
82
+ deletions,
83
+ membershipCleanup,
84
+ });
85
+ }
86
+ return handlerPlans;
87
+ }
@@ -0,0 +1,78 @@
1
+ import { lstat, rm } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { assertSafeInstallPaths } from "../Support/BlueprintFiles.js";
4
+ export async function validateRemovalTarget(githubDirectory, operation) {
5
+ const { handler, plan, expectedTarget } = operation;
6
+ const destinationDirectory = handler.destinationDirectory(githubDirectory);
7
+ const targetPath = (name) => handler.targetPath?.(destinationDirectory, name) ?? join(destinationDirectory, name);
8
+ await assertSafeInstallPaths(githubDirectory, [plan.path], destinationDirectory, targetPath);
9
+ try {
10
+ const stat = await lstat(plan.target);
11
+ if (stat.isSymbolicLink()) {
12
+ throw new Error(`Refusing to remove '${plan.target}': symbolic-link targets are unsafe.`);
13
+ }
14
+ if (expectedTarget === "directory" ? !stat.isDirectory() : !stat.isFile()) {
15
+ const expected = expectedTarget === "directory" ? "a directory" : "a regular file";
16
+ throw new Error(`Refusing to remove '${plan.target}': expected ${expected}.`);
17
+ }
18
+ return true;
19
+ }
20
+ catch (error) {
21
+ if (error.code === "ENOENT")
22
+ return false;
23
+ throw error;
24
+ }
25
+ }
26
+ export function catalogRemovalOperation(operation) {
27
+ const { handler, deletion, plan } = operation;
28
+ const name = `${handler.kind} '${deletion.path}'`;
29
+ return {
30
+ handler,
31
+ plan,
32
+ expectedTarget: deletion.entry.directory ? "directory" : "file",
33
+ recursive: deletion.entry.directory,
34
+ validationDescription: `removal of ${name}`,
35
+ removalDescription: name,
36
+ completedName: name,
37
+ };
38
+ }
39
+ export function membershipRemovalOperation(operation) {
40
+ const { handler, plan } = operation;
41
+ const name = `${handler.kind} '${plan.path}'`;
42
+ return {
43
+ handler,
44
+ plan,
45
+ expectedTarget: "file",
46
+ recursive: false,
47
+ validationDescription: `directory-membership cleanup of ${name}`,
48
+ removalDescription: `destination-only ${handler.kind} file '${plan.path}'`,
49
+ completedName: name,
50
+ };
51
+ }
52
+ export async function applyRemovalOperations(githubDirectory, operations, recordAppliedChange) {
53
+ const outcomes = [];
54
+ for (const operation of operations) {
55
+ let targetExists;
56
+ try {
57
+ targetExists = await validateRemovalTarget(githubDirectory, operation);
58
+ }
59
+ catch (error) {
60
+ throw new Error(`Failed to validate ${operation.validationDescription} at '${operation.plan.target}': ${error instanceof Error ? error.message : String(error)}`, { cause: error });
61
+ }
62
+ if (!targetExists)
63
+ continue;
64
+ try {
65
+ await rm(operation.plan.target, { recursive: operation.recursive });
66
+ }
67
+ catch (error) {
68
+ throw new Error(`Failed to remove ${operation.removalDescription} at '${operation.plan.target}': ${error instanceof Error ? error.message : String(error)}`, { cause: error });
69
+ }
70
+ recordAppliedChange(`removed ${operation.completedName}`);
71
+ outcomes.push({
72
+ kind: operation.handler.kind,
73
+ name: operation.plan.path,
74
+ status: "removed",
75
+ });
76
+ }
77
+ return outcomes;
78
+ }