@dv.nghiem/flowdeck 0.1.0

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 (331) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +136 -0
  3. package/bin/flowdeck.js +108 -0
  4. package/dist/agents/architect.d.ts +3 -0
  5. package/dist/agents/architect.d.ts.map +1 -0
  6. package/dist/agents/code-explorer.d.ts +3 -0
  7. package/dist/agents/code-explorer.d.ts.map +1 -0
  8. package/dist/agents/coder.d.ts +3 -0
  9. package/dist/agents/coder.d.ts.map +1 -0
  10. package/dist/agents/debug.d.ts +4 -0
  11. package/dist/agents/debug.d.ts.map +1 -0
  12. package/dist/agents/doc-updater.d.ts +3 -0
  13. package/dist/agents/doc-updater.d.ts.map +1 -0
  14. package/dist/agents/flowdeck.d.ts +5 -0
  15. package/dist/agents/flowdeck.d.ts.map +1 -0
  16. package/dist/agents/index.d.ts +38 -0
  17. package/dist/agents/index.d.ts.map +1 -0
  18. package/dist/agents/mapper.d.ts +3 -0
  19. package/dist/agents/mapper.d.ts.map +1 -0
  20. package/dist/agents/orchestrator.d.ts +10 -0
  21. package/dist/agents/orchestrator.d.ts.map +1 -0
  22. package/dist/agents/performance.d.ts +4 -0
  23. package/dist/agents/performance.d.ts.map +1 -0
  24. package/dist/agents/planner.d.ts +3 -0
  25. package/dist/agents/planner.d.ts.map +1 -0
  26. package/dist/agents/policy-enforcer.d.ts +3 -0
  27. package/dist/agents/policy-enforcer.d.ts.map +1 -0
  28. package/dist/agents/researcher.d.ts +3 -0
  29. package/dist/agents/researcher.d.ts.map +1 -0
  30. package/dist/agents/reviewer.d.ts +3 -0
  31. package/dist/agents/reviewer.d.ts.map +1 -0
  32. package/dist/agents/risk-analyst.d.ts +3 -0
  33. package/dist/agents/risk-analyst.d.ts.map +1 -0
  34. package/dist/agents/security-auditor.d.ts +3 -0
  35. package/dist/agents/security-auditor.d.ts.map +1 -0
  36. package/dist/agents/specialist.d.ts +5 -0
  37. package/dist/agents/specialist.d.ts.map +1 -0
  38. package/dist/agents/tester.d.ts +3 -0
  39. package/dist/agents/tester.d.ts.map +1 -0
  40. package/dist/agents/types.d.ts +20 -0
  41. package/dist/agents/types.d.ts.map +1 -0
  42. package/dist/agents/writer.d.ts +3 -0
  43. package/dist/agents/writer.d.ts.map +1 -0
  44. package/dist/commands/analysis/analysis.test.d.ts +2 -0
  45. package/dist/commands/analysis/analysis.test.d.ts.map +1 -0
  46. package/dist/commands/analysis/analyze-change.d.ts +148 -0
  47. package/dist/commands/analysis/analyze-change.d.ts.map +1 -0
  48. package/dist/commands/analysis/evaluate-risk.d.ts +77 -0
  49. package/dist/commands/analysis/evaluate-risk.d.ts.map +1 -0
  50. package/dist/commands/analysis/guarded-edit.d.ts +72 -0
  51. package/dist/commands/analysis/guarded-edit.d.ts.map +1 -0
  52. package/dist/commands/execution/deploy-check.d.ts +91 -0
  53. package/dist/commands/execution/deploy-check.d.ts.map +1 -0
  54. package/dist/commands/execution/fix-bug.d.ts +187 -0
  55. package/dist/commands/execution/fix-bug.d.ts.map +1 -0
  56. package/dist/commands/execution/new-feature.d.ts +171 -0
  57. package/dist/commands/execution/new-feature.d.ts.map +1 -0
  58. package/dist/commands/execution/review-code.d.ts +130 -0
  59. package/dist/commands/execution/review-code.d.ts.map +1 -0
  60. package/dist/commands/execution/write-docs.d.ts +94 -0
  61. package/dist/commands/execution/write-docs.d.ts.map +1 -0
  62. package/dist/commands/governance/approve.d.ts +80 -0
  63. package/dist/commands/governance/approve.d.ts.map +1 -0
  64. package/dist/commands/intelligence/blast-radius.d.ts +67 -0
  65. package/dist/commands/intelligence/blast-radius.d.ts.map +1 -0
  66. package/dist/commands/intelligence/impact-radar.d.ts +71 -0
  67. package/dist/commands/intelligence/impact-radar.d.ts.map +1 -0
  68. package/dist/commands/intelligence/intelligence.test.d.ts +2 -0
  69. package/dist/commands/intelligence/intelligence.test.d.ts.map +1 -0
  70. package/dist/commands/intelligence/regression-predict.d.ts +75 -0
  71. package/dist/commands/intelligence/regression-predict.d.ts.map +1 -0
  72. package/dist/commands/intelligence/review-route.d.ts +65 -0
  73. package/dist/commands/intelligence/review-route.d.ts.map +1 -0
  74. package/dist/commands/intelligence/test-gap.d.ts +73 -0
  75. package/dist/commands/intelligence/test-gap.d.ts.map +1 -0
  76. package/dist/commands/intelligence/translate-intent.d.ts +87 -0
  77. package/dist/commands/intelligence/translate-intent.d.ts.map +1 -0
  78. package/dist/commands/intelligence/volatility-map-cmd.d.ts +68 -0
  79. package/dist/commands/intelligence/volatility-map-cmd.d.ts.map +1 -0
  80. package/dist/commands/planning/ask.d.ts +62 -0
  81. package/dist/commands/planning/ask.d.ts.map +1 -0
  82. package/dist/commands/planning/ask.test.d.ts +2 -0
  83. package/dist/commands/planning/ask.test.d.ts.map +1 -0
  84. package/dist/commands/planning/dashboard.d.ts +30 -0
  85. package/dist/commands/planning/dashboard.d.ts.map +1 -0
  86. package/dist/commands/planning/discuss.d.ts +39 -0
  87. package/dist/commands/planning/discuss.d.ts.map +1 -0
  88. package/dist/commands/planning/plan.d.ts +67 -0
  89. package/dist/commands/planning/plan.d.ts.map +1 -0
  90. package/dist/commands/planning/roadmap.d.ts +105 -0
  91. package/dist/commands/planning/roadmap.d.ts.map +1 -0
  92. package/dist/commands/setup/doctor.d.ts +10 -0
  93. package/dist/commands/setup/doctor.d.ts.map +1 -0
  94. package/dist/commands/setup/map-codebase.d.ts +62 -0
  95. package/dist/commands/setup/map-codebase.d.ts.map +1 -0
  96. package/dist/commands/setup/new-project.d.ts +19 -0
  97. package/dist/commands/setup/new-project.d.ts.map +1 -0
  98. package/dist/commands/setup/settings.d.ts +57 -0
  99. package/dist/commands/setup/settings.d.ts.map +1 -0
  100. package/dist/commands/state/checkpoint.d.ts +27 -0
  101. package/dist/commands/state/checkpoint.d.ts.map +1 -0
  102. package/dist/commands/state/multi-repo.d.ts +63 -0
  103. package/dist/commands/state/multi-repo.d.ts.map +1 -0
  104. package/dist/commands/state/progress.d.ts +57 -0
  105. package/dist/commands/state/progress.d.ts.map +1 -0
  106. package/dist/commands/state/resume.d.ts +11 -0
  107. package/dist/commands/state/resume.d.ts.map +1 -0
  108. package/dist/commands/state/workspace-commands.d.ts +207 -0
  109. package/dist/commands/state/workspace-commands.d.ts.map +1 -0
  110. package/dist/dashboard/lib/port-finder.d.ts +10 -0
  111. package/dist/dashboard/lib/port-finder.d.ts.map +1 -0
  112. package/dist/dashboard/lib/port-finder.test.d.ts +2 -0
  113. package/dist/dashboard/lib/port-finder.test.d.ts.map +1 -0
  114. package/dist/dashboard/lib/state-reader.d.ts +3 -0
  115. package/dist/dashboard/lib/state-reader.d.ts.map +1 -0
  116. package/dist/dashboard/server.d.ts +2 -0
  117. package/dist/dashboard/server.d.ts.map +1 -0
  118. package/dist/dashboard/server.mjs +13649 -0
  119. package/dist/dashboard/types.d.ts +72 -0
  120. package/dist/dashboard/types.d.ts.map +1 -0
  121. package/dist/dashboard/views/index.ejs +391 -0
  122. package/dist/dashboard/views/partials/blockers.ejs +10 -0
  123. package/dist/dashboard/views/partials/header.ejs +20 -0
  124. package/dist/dashboard/views/partials/phase-timeline.ejs +40 -0
  125. package/dist/dashboard/views/partials/progress.ejs +12 -0
  126. package/dist/hooks/approval-hook.d.ts +13 -0
  127. package/dist/hooks/approval-hook.d.ts.map +1 -0
  128. package/dist/hooks/compaction-hook.d.ts +23 -0
  129. package/dist/hooks/compaction-hook.d.ts.map +1 -0
  130. package/dist/hooks/context-window-monitor.d.ts +21 -0
  131. package/dist/hooks/context-window-monitor.d.ts.map +1 -0
  132. package/dist/hooks/decision-trace-hook.d.ts +13 -0
  133. package/dist/hooks/decision-trace-hook.d.ts.map +1 -0
  134. package/dist/hooks/file-tracker.d.ts +29 -0
  135. package/dist/hooks/file-tracker.d.ts.map +1 -0
  136. package/dist/hooks/guard-rails.d.ts +33 -0
  137. package/dist/hooks/guard-rails.d.ts.map +1 -0
  138. package/dist/hooks/index.d.ts +5 -0
  139. package/dist/hooks/index.d.ts.map +1 -0
  140. package/dist/hooks/notifications.d.ts +21 -0
  141. package/dist/hooks/notifications.d.ts.map +1 -0
  142. package/dist/hooks/patch-trust.d.ts +27 -0
  143. package/dist/hooks/patch-trust.d.ts.map +1 -0
  144. package/dist/hooks/patch-trust.test.d.ts +2 -0
  145. package/dist/hooks/patch-trust.test.d.ts.map +1 -0
  146. package/dist/hooks/session-events.d.ts +8 -0
  147. package/dist/hooks/session-events.d.ts.map +1 -0
  148. package/dist/hooks/session-idle-hook.d.ts +21 -0
  149. package/dist/hooks/session-idle-hook.d.ts.map +1 -0
  150. package/dist/hooks/session-start.d.ts +10 -0
  151. package/dist/hooks/session-start.d.ts.map +1 -0
  152. package/dist/hooks/shell-env-hook.d.ts +21 -0
  153. package/dist/hooks/shell-env-hook.d.ts.map +1 -0
  154. package/dist/hooks/telemetry-hook.d.ts +25 -0
  155. package/dist/hooks/telemetry-hook.d.ts.map +1 -0
  156. package/dist/hooks/todo-hook.d.ts +25 -0
  157. package/dist/hooks/todo-hook.d.ts.map +1 -0
  158. package/dist/hooks/tool-guard.d.ts +41 -0
  159. package/dist/hooks/tool-guard.d.ts.map +1 -0
  160. package/dist/hooks/tool-guard.test.d.ts +2 -0
  161. package/dist/hooks/tool-guard.test.d.ts.map +1 -0
  162. package/dist/index.d.ts +4 -0
  163. package/dist/index.d.ts.map +1 -0
  164. package/dist/index.js +6639 -0
  165. package/dist/lib/confirmation.d.ts +20 -0
  166. package/dist/lib/confirmation.d.ts.map +1 -0
  167. package/dist/lib/impact-radar.d.ts +35 -0
  168. package/dist/lib/impact-radar.d.ts.map +1 -0
  169. package/dist/lib/signatures.d.ts +12 -0
  170. package/dist/lib/signatures.d.ts.map +1 -0
  171. package/dist/lib/timestamps.d.ts +23 -0
  172. package/dist/lib/timestamps.d.ts.map +1 -0
  173. package/dist/mcp/index.d.ts +20 -0
  174. package/dist/mcp/index.d.ts.map +1 -0
  175. package/dist/services/agent-performance.d.ts +29 -0
  176. package/dist/services/agent-performance.d.ts.map +1 -0
  177. package/dist/services/approval-manager.d.ts +30 -0
  178. package/dist/services/approval-manager.d.ts.map +1 -0
  179. package/dist/services/index.d.ts +7 -0
  180. package/dist/services/index.d.ts.map +1 -0
  181. package/dist/services/model-router.d.ts +35 -0
  182. package/dist/services/model-router.d.ts.map +1 -0
  183. package/dist/services/policy-compiler.d.ts +27 -0
  184. package/dist/services/policy-compiler.d.ts.map +1 -0
  185. package/dist/services/run-trace.d.ts +34 -0
  186. package/dist/services/run-trace.d.ts.map +1 -0
  187. package/dist/services/services.test.d.ts +2 -0
  188. package/dist/services/services.test.d.ts.map +1 -0
  189. package/dist/services/telemetry.d.ts +34 -0
  190. package/dist/services/telemetry.d.ts.map +1 -0
  191. package/dist/tools/agent-dispatch.test.d.ts +2 -0
  192. package/dist/tools/agent-dispatch.test.d.ts.map +1 -0
  193. package/dist/tools/codebase-state.d.ts +4 -0
  194. package/dist/tools/codebase-state.d.ts.map +1 -0
  195. package/dist/tools/context-generator.d.ts +3 -0
  196. package/dist/tools/context-generator.d.ts.map +1 -0
  197. package/dist/tools/council.d.ts +4 -0
  198. package/dist/tools/council.d.ts.map +1 -0
  199. package/dist/tools/decision-trace.d.ts +16 -0
  200. package/dist/tools/decision-trace.d.ts.map +1 -0
  201. package/dist/tools/delegate.d.ts +4 -0
  202. package/dist/tools/delegate.d.ts.map +1 -0
  203. package/dist/tools/failure-replay.d.ts +19 -0
  204. package/dist/tools/failure-replay.d.ts.map +1 -0
  205. package/dist/tools/failure-replay.test.d.ts +2 -0
  206. package/dist/tools/failure-replay.test.d.ts.map +1 -0
  207. package/dist/tools/hash-edit.d.ts +3 -0
  208. package/dist/tools/hash-edit.d.ts.map +1 -0
  209. package/dist/tools/planning-state-lib.d.ts +65 -0
  210. package/dist/tools/planning-state-lib.d.ts.map +1 -0
  211. package/dist/tools/planning-state.d.ts +3 -0
  212. package/dist/tools/planning-state.d.ts.map +1 -0
  213. package/dist/tools/policy-engine.d.ts +19 -0
  214. package/dist/tools/policy-engine.d.ts.map +1 -0
  215. package/dist/tools/repo-memory.d.ts +20 -0
  216. package/dist/tools/repo-memory.d.ts.map +1 -0
  217. package/dist/tools/repo-memory.test.d.ts +2 -0
  218. package/dist/tools/repo-memory.test.d.ts.map +1 -0
  219. package/dist/tools/run-parallel.d.ts +4 -0
  220. package/dist/tools/run-parallel.d.ts.map +1 -0
  221. package/dist/tools/run-pipeline.d.ts +4 -0
  222. package/dist/tools/run-pipeline.d.ts.map +1 -0
  223. package/dist/tools/volatility-map.d.ts +18 -0
  224. package/dist/tools/volatility-map.d.ts.map +1 -0
  225. package/dist/tools/volatility-map.test.d.ts +2 -0
  226. package/dist/tools/volatility-map.test.d.ts.map +1 -0
  227. package/dist/tools/workspace-state.d.ts +3 -0
  228. package/dist/tools/workspace-state.d.ts.map +1 -0
  229. package/docs/USER_GUIDE.md +20 -0
  230. package/docs/agents.md +562 -0
  231. package/docs/best-practices.md +47 -0
  232. package/docs/command-migration.md +175 -0
  233. package/docs/commands/fd-analyze-change.md +107 -0
  234. package/docs/commands/fd-ask.md +51 -0
  235. package/docs/commands/fd-checkpoint.md +10 -0
  236. package/docs/commands/fd-dashboard.md +11 -0
  237. package/docs/commands/fd-deploy-check.md +11 -0
  238. package/docs/commands/fd-discuss.md +28 -0
  239. package/docs/commands/fd-evaluate-risk.md +134 -0
  240. package/docs/commands/fd-fix-bug.md +24 -0
  241. package/docs/commands/fd-guarded-edit.md +105 -0
  242. package/docs/commands/fd-map-codebase.md +27 -0
  243. package/docs/commands/fd-multi-repo.md +63 -0
  244. package/docs/commands/fd-new-feature.md +25 -0
  245. package/docs/commands/fd-new-project.md +24 -0
  246. package/docs/commands/fd-plan.md +33 -0
  247. package/docs/commands/fd-progress.md +11 -0
  248. package/docs/commands/fd-resume.md +10 -0
  249. package/docs/commands/fd-review-code.md +29 -0
  250. package/docs/commands/fd-roadmap.md +10 -0
  251. package/docs/commands/fd-settings.md +10 -0
  252. package/docs/commands/fd-write-docs.md +10 -0
  253. package/docs/commands.md +476 -0
  254. package/docs/configuration.md +211 -0
  255. package/docs/feature-integration-architecture.md +255 -0
  256. package/docs/index.md +75 -0
  257. package/docs/installation.md +134 -0
  258. package/docs/intelligence.md +294 -0
  259. package/docs/multi-repo.md +201 -0
  260. package/docs/notifications.md +170 -0
  261. package/docs/parallel-execution.md +227 -0
  262. package/docs/quick-start.md +174 -0
  263. package/docs/rules.md +459 -0
  264. package/docs/skills.md +408 -0
  265. package/docs/workflows.md +376 -0
  266. package/package.json +58 -0
  267. package/postinstall.mjs +102 -0
  268. package/src/rules/README.md +37 -0
  269. package/src/rules/common/agent-orchestration.md +86 -0
  270. package/src/rules/common/coding-style.md +120 -0
  271. package/src/rules/common/git-workflow.md +77 -0
  272. package/src/rules/common/security.md +94 -0
  273. package/src/rules/common/testing.md +105 -0
  274. package/src/rules/golang/patterns.md +187 -0
  275. package/src/rules/java/patterns.md +204 -0
  276. package/src/rules/python/patterns.md +141 -0
  277. package/src/rules/rust/patterns.md +210 -0
  278. package/src/rules/typescript/patterns.md +168 -0
  279. package/src/skills/api-design/SKILL.md +143 -0
  280. package/src/skills/arch-constraint-guard/SKILL.md +61 -0
  281. package/src/skills/blast-radius-preview/SKILL.md +65 -0
  282. package/src/skills/change-impact-radar/SKILL.md +63 -0
  283. package/src/skills/code-review/SKILL.md +108 -0
  284. package/src/skills/code-tour/SKILL.md +101 -0
  285. package/src/skills/codebase-mapping/SKILL.md +87 -0
  286. package/src/skills/codebase-onboarding/SKILL.md +133 -0
  287. package/src/skills/confidence-aware-planning/SKILL.md +67 -0
  288. package/src/skills/context-load/SKILL.md +63 -0
  289. package/src/skills/debug-flow/SKILL.md +75 -0
  290. package/src/skills/decision-trace/SKILL.md +72 -0
  291. package/src/skills/dependency-audit/SKILL.md +126 -0
  292. package/src/skills/deploy-check/SKILL.md +87 -0
  293. package/src/skills/documentation-writer/SKILL.md +154 -0
  294. package/src/skills/failure-replay-engine/SKILL.md +59 -0
  295. package/src/skills/git-release/SKILL.md +94 -0
  296. package/src/skills/git-workflow/SKILL.md +177 -0
  297. package/src/skills/golang-patterns/SKILL.md +511 -0
  298. package/src/skills/human-review-routing/SKILL.md +65 -0
  299. package/src/skills/intent-translator/SKILL.md +57 -0
  300. package/src/skills/java-patterns/SKILL.md +479 -0
  301. package/src/skills/multi-repo/SKILL.md +187 -0
  302. package/src/skills/parallel-execute/SKILL.md +92 -0
  303. package/src/skills/patch-trust-score/SKILL.md +44 -0
  304. package/src/skills/performance-profiling/SKILL.md +153 -0
  305. package/src/skills/plan-task/SKILL.md +101 -0
  306. package/src/skills/python-patterns/SKILL.md +529 -0
  307. package/src/skills/refactor-guide/SKILL.md +117 -0
  308. package/src/skills/regression-prediction/SKILL.md +57 -0
  309. package/src/skills/repo-memory-graph/SKILL.md +49 -0
  310. package/src/skills/rust-patterns/SKILL.md +492 -0
  311. package/src/skills/security-scan/SKILL.md +91 -0
  312. package/src/skills/self-healing-policies/SKILL.md +76 -0
  313. package/src/skills/tdd-workflow/SKILL.md +126 -0
  314. package/src/skills/test-coverage/SKILL.md +94 -0
  315. package/src/skills/test-gap-detector/SKILL.md +58 -0
  316. package/src/skills/volatility-map/SKILL.md +52 -0
  317. package/src/workflows/debug-flow.md +119 -0
  318. package/src/workflows/deploy-check-flow.md +98 -0
  319. package/src/workflows/discuss-flow.md +97 -0
  320. package/src/workflows/execute-flow.md +233 -0
  321. package/src/workflows/execute-phase.md +142 -0
  322. package/src/workflows/fix-bug-flow.md +210 -0
  323. package/src/workflows/map-codebase-flow.md +92 -0
  324. package/src/workflows/multi-repo-flow.md +226 -0
  325. package/src/workflows/parallel-execution-flow.md +236 -0
  326. package/src/workflows/plan-flow.md +126 -0
  327. package/src/workflows/plan-phase.md +101 -0
  328. package/src/workflows/refactor-flow.md +122 -0
  329. package/src/workflows/review-code-flow.md +105 -0
  330. package/src/workflows/spec-driven-flow.md +43 -0
  331. package/src/workflows/write-docs-flow.md +95 -0
@@ -0,0 +1,479 @@
1
+ ---
2
+ name: java-patterns
3
+ description: Modern Java (17+) patterns covering records, sealed classes, Stream API, CompletableFuture, Spring Boot, JPA, and testing. Activate when writing or reviewing Java code.
4
+ origin: FlowDeck
5
+ ---
6
+
7
+ # Java Patterns Skill
8
+
9
+ Modern Java for production applications. Focuses on Java 17+ features and Spring Boot conventions.
10
+
11
+ ## When to Activate
12
+
13
+ Activate when:
14
+ - Writing new Java services or libraries
15
+ - Reviewing Java code for correctness and modern idiom
16
+ - Designing API layers, service classes, or data access
17
+ - Troubleshooting Spring Boot configuration or JPA queries
18
+ - Setting up testing infrastructure
19
+
20
+ ## Modern Java Features (17+)
21
+
22
+ ### Records — Immutable Data Carriers
23
+
24
+ Records eliminate boilerplate for data classes. Use them for DTOs, value objects, and command/query objects.
25
+
26
+ ```java
27
+ // Compiler generates constructor, getters, equals, hashCode, toString
28
+ public record Point(double x, double y) {}
29
+
30
+ // Custom constructor for validation
31
+ public record EmailAddress(String value) {
32
+ public EmailAddress {
33
+ Objects.requireNonNull(value);
34
+ if (!value.contains("@")) {
35
+ throw new IllegalArgumentException("invalid email: " + value);
36
+ }
37
+ value = value.toLowerCase();
38
+ }
39
+ }
40
+
41
+ // Records can implement interfaces
42
+ public record PageRequest(int page, int size) implements Serializable {
43
+ public PageRequest {
44
+ if (page < 0) throw new IllegalArgumentException("page must be >= 0");
45
+ if (size < 1 || size > 100) throw new IllegalArgumentException("size must be 1-100");
46
+ }
47
+
48
+ public int offset() { return page * size; }
49
+ }
50
+ ```
51
+
52
+ ### Sealed Classes — Closed Hierarchies
53
+
54
+ Use sealed classes to model a fixed set of variants. The compiler enforces exhaustive pattern matching.
55
+
56
+ ```java
57
+ public sealed interface PaymentResult
58
+ permits PaymentResult.Success, PaymentResult.Declined, PaymentResult.Error {
59
+
60
+ record Success(String transactionId, BigDecimal amount) implements PaymentResult {}
61
+ record Declined(String reason) implements PaymentResult {}
62
+ record Error(Throwable cause) implements PaymentResult {}
63
+ }
64
+
65
+ // Pattern matching ensures all cases are handled
66
+ String message = switch (result) {
67
+ case PaymentResult.Success s -> "Charged " + s.amount();
68
+ case PaymentResult.Declined d -> "Declined: " + d.reason();
69
+ case PaymentResult.Error e -> "Error: " + e.cause().getMessage();
70
+ };
71
+ ```
72
+
73
+ ### Pattern Matching instanceof
74
+
75
+ ```java
76
+ // ❌ Old style — verbose cast
77
+ if (obj instanceof String) {
78
+ String s = (String) obj;
79
+ System.out.println(s.length());
80
+ }
81
+
82
+ // ✅ Pattern variable — binding in same expression
83
+ if (obj instanceof String s) {
84
+ System.out.println(s.length());
85
+ }
86
+
87
+ // Combining with guards
88
+ if (obj instanceof String s && s.length() > 5) {
89
+ System.out.println("long string: " + s);
90
+ }
91
+ ```
92
+
93
+ ### Text Blocks
94
+
95
+ ```java
96
+ // ✅ Multiline strings without escaping
97
+ String json = """
98
+ {
99
+ "name": "Alice",
100
+ "age": 30
101
+ }
102
+ """;
103
+
104
+ String query = """
105
+ SELECT u.id, u.email
106
+ FROM users u
107
+ WHERE u.active = true
108
+ AND u.created_at > :since
109
+ """;
110
+ ```
111
+
112
+ ## Optional — Use at API Boundaries
113
+
114
+ Optional communicates "might be absent" in a return type. Never use it as a field type or parameter.
115
+
116
+ ```java
117
+ // ✅ Return type — caller must handle absence
118
+ public Optional<User> findByEmail(String email) {
119
+ return userRepository.findByEmail(email);
120
+ }
121
+
122
+ // ✅ Chained operations
123
+ String displayName = findByEmail(email)
124
+ .map(User::displayName)
125
+ .orElse("Anonymous");
126
+
127
+ // ✅ Throw if absent with meaningful message
128
+ User user = findByEmail(email)
129
+ .orElseThrow(() -> new UserNotFoundException(email));
130
+
131
+ // ✅ Execute only if present
132
+ findByEmail(email).ifPresent(user -> auditLog.record(user.id()));
133
+
134
+ // ❌ Never null-check Optional itself
135
+ Optional<User> opt = findByEmail(email);
136
+ if (opt != null && opt.isPresent()) { ... } // wrong
137
+
138
+ // ❌ Never use as a field type
139
+ class Service {
140
+ private Optional<Cache> cache; // wrong — use @Nullable or just null
141
+ }
142
+ ```
143
+
144
+ ## Stream API
145
+
146
+ ### Core Operations
147
+
148
+ ```java
149
+ List<String> activeEmails = users.stream()
150
+ .filter(User::isActive)
151
+ .sorted(Comparator.comparing(User::lastName))
152
+ .map(User::email)
153
+ .toList(); // Java 16+ unmodifiable list
154
+
155
+ // Collectors
156
+ Map<Department, List<Employee>> byDept = employees.stream()
157
+ .collect(Collectors.groupingBy(Employee::department));
158
+
159
+ Map<Boolean, List<User>> partitioned = users.stream()
160
+ .collect(Collectors.partitioningBy(User::isAdmin));
161
+
162
+ // Reduce
163
+ BigDecimal total = cart.items().stream()
164
+ .map(Item::price)
165
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
166
+ ```
167
+
168
+ ### flatMap — Flattening Nested Collections
169
+
170
+ ```java
171
+ // One user has many orders, each order has many items
172
+ List<Item> allItems = users.stream()
173
+ .flatMap(u -> u.orders().stream())
174
+ .flatMap(o -> o.items().stream())
175
+ .toList();
176
+ ```
177
+
178
+ ### Parallel Streams — When NOT to Use
179
+
180
+ ```java
181
+ // ✅ Parallel for CPU-bound work on large, independent datasets
182
+ long count = IntStream.range(0, 10_000_000)
183
+ .parallel()
184
+ .filter(n -> isPrime(n))
185
+ .count();
186
+
187
+ // ❌ Parallel with shared mutable state — data race
188
+ List<Integer> result = new ArrayList<>();
189
+ IntStream.range(0, 1000).parallel()
190
+ .forEach(result::add); // non-thread-safe!
191
+
192
+ // ❌ Parallel for I/O-bound work — blocks common ForkJoinPool
193
+ Stream.of(urls).parallel()
194
+ .map(this::fetch) // ties up ForkJoin threads on I/O
195
+ .toList();
196
+
197
+ // Rule: parallel only when dataset is large, work is CPU-bound,
198
+ // and no shared mutable state exists. Benchmark first.
199
+ ```
200
+
201
+ ## CompletableFuture — Async Composition
202
+
203
+ ```java
204
+ // Chain transformations
205
+ CompletableFuture<String> result = CompletableFuture
206
+ .supplyAsync(() -> fetchUser(userId)) // background thread
207
+ .thenApply(User::email) // same thread
208
+ .thenApplyAsync(this::sendWelcome, executor); // different thread
209
+
210
+ // Compose dependent futures (flatMap equivalent)
211
+ CompletableFuture<Order> order = CompletableFuture
212
+ .supplyAsync(() -> findUser(id))
213
+ .thenCompose(user -> placeOrder(user, items)); // avoids nested futures
214
+
215
+ // Recover from failure
216
+ CompletableFuture<User> withFallback = fetchUser(id)
217
+ .exceptionally(ex -> {
218
+ log.warn("fetch failed, using guest", ex);
219
+ return User.guest();
220
+ });
221
+
222
+ // Wait for multiple independent futures
223
+ CompletableFuture<Void> all = CompletableFuture.allOf(
224
+ sendEmail(user), updateCache(user), auditLog(user)
225
+ );
226
+ all.join(); // blocks — use only at the top of the call stack
227
+
228
+ // Timeout
229
+ CompletableFuture<User> withTimeout = fetchUser(id)
230
+ .orTimeout(2, TimeUnit.SECONDS)
231
+ .exceptionally(ex -> User.guest());
232
+ ```
233
+
234
+ ## Spring Boot Patterns
235
+
236
+ ### Dependency Injection — Constructor Injection Only
237
+
238
+ ```java
239
+ // ✅ Constructor injection — dependencies are explicit and final
240
+ @Service
241
+ public class OrderService {
242
+ private final OrderRepository orders;
243
+ private final PaymentGateway payments;
244
+ private final EventPublisher events;
245
+
246
+ public OrderService(
247
+ OrderRepository orders,
248
+ PaymentGateway payments,
249
+ EventPublisher events
250
+ ) {
251
+ this.orders = orders;
252
+ this.payments = payments;
253
+ this.events = events;
254
+ }
255
+ }
256
+
257
+ // ❌ Field injection — hides dependencies, breaks tests
258
+ @Service
259
+ public class OrderService {
260
+ @Autowired private OrderRepository orders; // bad
261
+ }
262
+ ```
263
+
264
+ ### @ConfigurationProperties — Typed Config
265
+
266
+ ```java
267
+ @ConfigurationProperties(prefix = "payment")
268
+ public record PaymentConfig(
269
+ String apiKey,
270
+ URI baseUrl,
271
+ Duration timeout,
272
+ int maxRetries
273
+ ) {}
274
+
275
+ // application.yml
276
+ // payment:
277
+ // api-key: sk_live_...
278
+ // base-url: https://api.stripe.com
279
+ // timeout: 5s
280
+ // max-retries: 3
281
+ ```
282
+
283
+ ### Layered Stereotypes
284
+
285
+ ```java
286
+ @Repository // data access — wraps DataAccessException
287
+ @Service // business logic
288
+ @Component // general-purpose bean
289
+ @RestController // HTTP endpoints (combines @Controller + @ResponseBody)
290
+ ```
291
+
292
+ ## JPA and Hibernate
293
+
294
+ ### N+1 Problem
295
+
296
+ ```java
297
+ // ❌ N+1: one query for orders, then one query per order for items
298
+ List<Order> orders = orderRepo.findAll();
299
+ orders.forEach(o -> System.out.println(o.getItems().size()));
300
+
301
+ // ✅ Fetch join: single query
302
+ @Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.userId = :userId")
303
+ List<Order> findWithItems(@Param("userId") Long userId);
304
+
305
+ // ✅ Or use @EntityGraph for reuse
306
+ @EntityGraph(attributePaths = {"items", "items.product"})
307
+ List<Order> findByUserId(Long userId);
308
+ ```
309
+
310
+ ### Fetch Strategy
311
+
312
+ ```java
313
+ // Default for @OneToMany is LAZY — keep it that way
314
+ @OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
315
+ private List<OrderItem> items;
316
+
317
+ // EAGER causes joins on every query, even when items aren't needed
318
+ // Only use EAGER for @ManyToOne / @OneToOne where the association is always needed
319
+ ```
320
+
321
+ ### Transaction Boundaries
322
+
323
+ ```java
324
+ // @Transactional on service methods, not repository methods
325
+ @Service
326
+ public class TransferService {
327
+ @Transactional
328
+ public void transfer(Long fromId, Long toId, BigDecimal amount) {
329
+ Account from = accounts.findById(fromId).orElseThrow();
330
+ Account to = accounts.findById(toId).orElseThrow();
331
+ from.debit(amount);
332
+ to.credit(amount);
333
+ // both saves happen in the same transaction
334
+ }
335
+ }
336
+ ```
337
+
338
+ ## Testing
339
+
340
+ ### JUnit 5 with Mockito
341
+
342
+ ```java
343
+ @ExtendWith(MockitoExtension.class)
344
+ class OrderServiceTest {
345
+
346
+ @Mock OrderRepository orders;
347
+ @Mock PaymentGateway payments;
348
+ @InjectMocks OrderService service;
349
+
350
+ @Test
351
+ void placeOrder_chargesPaymentAndSavesOrder() {
352
+ var user = aUser().build();
353
+ var items = List.of(anItem().withPrice(BigDecimal.TEN).build());
354
+ when(payments.charge(any(), any())).thenReturn(chargeSuccess());
355
+
356
+ var result = service.placeOrder(user, items);
357
+
358
+ assertThat(result.status()).isEqualTo(OrderStatus.CONFIRMED);
359
+ verify(orders).save(argThat(o -> o.total().equals(BigDecimal.TEN)));
360
+ }
361
+ }
362
+ ```
363
+
364
+ ### Spring Boot Test Slices
365
+
366
+ ```java
367
+ // Unit test — no Spring context
368
+ @ExtendWith(MockitoExtension.class)
369
+ class UserServiceTest { ... }
370
+
371
+ // Web layer only — no full context
372
+ @WebMvcTest(UserController.class)
373
+ class UserControllerTest {
374
+ @Autowired MockMvc mvc;
375
+ @MockBean UserService service;
376
+
377
+ @Test
378
+ void getUser_returns200() throws Exception {
379
+ when(service.findById(1L)).thenReturn(Optional.of(aUser().build()));
380
+ mvc.perform(get("/users/1"))
381
+ .andExpect(status().isOk())
382
+ .andExpect(jsonPath("$.email").value("alice@example.com"));
383
+ }
384
+ }
385
+
386
+ // Full integration test
387
+ @SpringBootTest(webEnvironment = RANDOM_PORT)
388
+ @Transactional // rolls back each test
389
+ class OrderIntegrationTest { ... }
390
+ ```
391
+
392
+ ## Build Configuration
393
+
394
+ ### Maven
395
+
396
+ ```xml
397
+ <properties>
398
+ <java.version>21</java.version>
399
+ <spring-boot.version>3.3.0</spring-boot.version>
400
+ </properties>
401
+
402
+ <plugin>
403
+ <groupId>org.apache.maven.plugins</groupId>
404
+ <artifactId>maven-compiler-plugin</artifactId>
405
+ <configuration>
406
+ <release>${java.version}</release>
407
+ <compilerArgs><arg>-parameters</arg></compilerArgs>
408
+ </configuration>
409
+ </plugin>
410
+ ```
411
+
412
+ ### Gradle (Kotlin DSL)
413
+
414
+ ```kotlin
415
+ java {
416
+ toolchain { languageVersion = JavaLanguageVersion.of(21) }
417
+ }
418
+
419
+ tasks.withType<JavaCompile> {
420
+ options.compilerArgs.add("-parameters")
421
+ }
422
+ ```
423
+
424
+ ## Common Pitfalls
425
+
426
+ ### Checked Exceptions in New Code
427
+
428
+ ```java
429
+ // ❌ Checked exceptions force callers to handle or declare them
430
+ public List<User> loadUsers() throws IOException, ParseException { ... }
431
+
432
+ // ✅ Wrap in unchecked and carry the cause
433
+ public List<User> loadUsers() {
434
+ try {
435
+ return parser.parse(Files.readString(path));
436
+ } catch (IOException | ParseException e) {
437
+ throw new UserLoadException("failed to load users from " + path, e);
438
+ }
439
+ }
440
+ ```
441
+
442
+ ### String Concatenation in Loops
443
+
444
+ ```java
445
+ // ❌ Creates a new String object every iteration — O(n²) allocations
446
+ String result = "";
447
+ for (String s : list) {
448
+ result += s + ", ";
449
+ }
450
+
451
+ // ✅ StringBuilder is O(n)
452
+ var sb = new StringBuilder();
453
+ for (String s : list) {
454
+ sb.append(s).append(", ");
455
+ }
456
+ String result = sb.toString();
457
+
458
+ // ✅ Or use String.join / Collectors.joining
459
+ String result = String.join(", ", list);
460
+ ```
461
+
462
+ ### Autoboxing Overhead
463
+
464
+ ```java
465
+ // ❌ Unnecessary boxing in tight loops
466
+ Long sum = 0L;
467
+ for (long i = 0; i < 1_000_000; i++) {
468
+ sum += i; // unboxes sum, adds, boxes result each iteration
469
+ }
470
+
471
+ // ✅ Use primitives
472
+ long sum = 0L;
473
+ for (long i = 0; i < 1_000_000; i++) {
474
+ sum += i;
475
+ }
476
+
477
+ // ✅ LongStream avoids boxing entirely
478
+ long sum = LongStream.range(0, 1_000_000).sum();
479
+ ```
@@ -0,0 +1,187 @@
1
+ ---
2
+ name: multi-repo
3
+ description: Coordinate changes across multiple repositories in a microservice architecture. Manages cross-repo dependencies, API contract evolution, and ordered rollouts.
4
+ origin: FlowDeck
5
+ ---
6
+
7
+ # Multi-Repo Skill
8
+
9
+ Provides the patterns and vocabulary for planning, sequencing, and executing changes that span more than one repository in a microservice system.
10
+
11
+ ## When to Activate
12
+
13
+ Activate when:
14
+ - A feature or fix requires changes in two or more repositories
15
+ - An API contract in one service must change and consumers exist in other repos
16
+ - A shared library version bump ripples downstream
17
+ - You need to verify no two services are making incompatible concurrent changes
18
+
19
+ Do not activate for single-repo changes, even if the repo is part of a larger microservice system.
20
+
21
+ ## Architecture Patterns
22
+
23
+ ### Service Mesh
24
+
25
+ Services communicate through well-defined contracts (REST, gRPC, event schemas). No direct database sharing between services. Each service owns its data store.
26
+
27
+ Key implication: contract changes are the primary coordination surface. A service can change its internals freely; it cannot change its contract without coordinating consumers.
28
+
29
+ ### API Contracts
30
+
31
+ Every `upstream-api` service maintains a contract — the stable interface it promises to consumers. Contracts define:
32
+ - Endpoint paths and HTTP methods (or gRPC service definitions)
33
+ - Request and response schemas (fields, types, nullability)
34
+ - Error response shapes
35
+ - Authentication requirements
36
+ - Rate limits and SLAs (where relevant)
37
+
38
+ Contracts are the input to `@architect` when designing cross-repo changes.
39
+
40
+ ### Event-Driven Changes
41
+
42
+ For services that communicate via message queues or event streams:
43
+ - The event schema plays the same role as an API contract
44
+ - Producers must publish the new schema before consumers update their handlers
45
+ - Both old and new schema versions must be supported during the transition window
46
+ - Treat schema changes with the same breaking/non-breaking classification used for REST APIs
47
+
48
+ ## Microservice Role Vocabulary
49
+
50
+ | Role | Meaning |
51
+ |------|---------|
52
+ | `upstream-api` | Provides an API consumed by other services |
53
+ | `downstream-consumer` | Calls one or more upstream APIs |
54
+ | `shared-lib` | Imported as a package dependency by other services |
55
+ | `gateway` | Routes external traffic to internal services |
56
+ | `worker` | Processes background jobs; no inbound HTTP API |
57
+
58
+ ## Config Schema
59
+
60
+ The multi-repo registry lives at `.planning/config.json` in the root repository.
61
+
62
+ ```json
63
+ {
64
+ "sub_repos": [
65
+ {
66
+ "name": "user-service",
67
+ "path": "../user-service",
68
+ "role": "upstream-api",
69
+ "tech_stack": "node+typescript",
70
+ "owner_team": "platform"
71
+ },
72
+ {
73
+ "name": "order-service",
74
+ "path": "../order-service",
75
+ "role": "downstream-consumer",
76
+ "tech_stack": "node+typescript",
77
+ "owner_team": "commerce"
78
+ },
79
+ {
80
+ "name": "shared-types",
81
+ "path": "../shared-types",
82
+ "role": "shared-lib",
83
+ "tech_stack": "node+typescript",
84
+ "owner_team": "platform"
85
+ },
86
+ {
87
+ "name": "api-gateway",
88
+ "path": "../api-gateway",
89
+ "role": "gateway",
90
+ "tech_stack": "nginx+lua",
91
+ "owner_team": "infra"
92
+ }
93
+ ]
94
+ }
95
+ ```
96
+
97
+ **Field definitions:**
98
+ - `name` — unique identifier used in dependency graph and change plans
99
+ - `path` — relative path from the root repo's parent directory (the directory containing `.planning/`)
100
+ - `role` — service role from the vocabulary above; determines dependency ordering
101
+ - `tech_stack` — technology used; informs which tools and commands to run
102
+ - `owner_team` — team responsible; flagged in conflict reports and escalations
103
+
104
+ ## Cross-Repo Workflow
105
+
106
+ ### When to Use Feature Branches vs Trunk Per Repo
107
+
108
+ **Feature branches per repo:**
109
+ - Use when the change spans multiple repos and involves breaking API changes
110
+ - Each repo gets its own branch (e.g., `feature/refresh-token-support`)
111
+ - Branch per repo enables coordinated review before any deploy
112
+ - Merge in dependency order: upstream merged and released before downstream merges
113
+
114
+ **Trunk-based per repo:**
115
+ - Use when the change is non-breaking (additive field, new optional endpoint)
116
+ - Changes can be merged independently to each repo's main branch
117
+ - Downstream consumers update on their own schedule
118
+ - Safe because the old contract remains valid during transition
119
+
120
+ Decision rule: if any change in the set is breaking for any consumer, use feature branches. If all changes are non-breaking, trunk-based is fine.
121
+
122
+ ## Contract-First Development Pattern
123
+
124
+ For any cross-repo change involving an API:
125
+
126
+ 1. **Write the new contract first** — `@architect` produces the updated interface definition before any code is written
127
+ 2. **Review the contract in isolation** — confirm all affected teams agree before implementation starts
128
+ 3. **Implement upstream against the new contract** — `@coder` in the upstream repo
129
+ 4. **Implement downstream against the new contract** — `@coder` in each consumer repo, independently
130
+ 5. **Integration test** — verify upstream and downstream work together against the contract
131
+
132
+ This pattern allows Wave 3 parallelism (upstream and downstream `@coder` agents can work simultaneously from the same contract) even across repos.
133
+
134
+ ## Breaking vs Non-Breaking API Changes
135
+
136
+ ### Non-Breaking (safe to deploy independently):
137
+ - Adding a new optional field to a response object
138
+ - Adding a new endpoint (existing endpoints unchanged)
139
+ - Adding an optional request parameter
140
+ - Relaxing a validation rule (e.g., allowing a longer string)
141
+ - Adding a new event type to a message stream
142
+
143
+ ### Breaking (requires coordinated rollout):
144
+ - Removing a field from a response object
145
+ - Renaming an existing field
146
+ - Changing a field's type (e.g., string → number)
147
+ - Making an optional field required
148
+ - Removing or renaming an endpoint
149
+ - Changing the authentication scheme
150
+ - Modifying an existing event schema in an incompatible way
151
+
152
+ When a breaking change is unavoidable, use versioned paths (`/v2/endpoint`) to maintain the old contract alongside the new one during the transition window. Retire the old version only after all consumers have migrated.
153
+
154
+ ## Rollout Sequencing
155
+
156
+ Changes deploy in dependency order. The general sequence:
157
+
158
+ ```
159
+ 1. shared-lib → publish new version (semver bump)
160
+ 2. upstream-api → canary → stage → prod
161
+ 3. downstream-consumers → canary → stage → prod (after upstream is in prod)
162
+ 4. gateway → route config update after all services are live in prod
163
+ ```
164
+
165
+ **Canary phase:** 5% of traffic, monitor error rate and latency for 15 minutes before proceeding.
166
+ **Stage phase:** full deploy to staging environment, run integration tests.
167
+ **Prod phase:** full production deploy after stage passes.
168
+
169
+ For breaking changes, complete the full canary → stage → prod cycle for the upstream before starting the canary phase for any downstream consumer. Mixed versions in prod during a breaking change window will cause errors.
170
+
171
+ ## Conflict Detection Rules
172
+
173
+ Two concurrent changes conflict when:
174
+ - Both change the same endpoint's response shape in incompatible ways
175
+ - Both require incompatible versions of the same shared-lib
176
+ - Both claim the same gateway route prefix
177
+ - Both migrate the same database table in incompatible directions
178
+
179
+ Conflicts must be resolved before any CHANGE PLAN is executed. The `@multi-repo-coordinator` surfaces conflicts with resolution options; the relevant `owner_team` decides.
180
+
181
+ ## Independence Check Before Executing
182
+
183
+ Before running `/multi-repo`:
184
+ - [ ] `.planning/config.json` has a `sub_repos` array with at least two entries
185
+ - [ ] All `path` values resolve to actual directories on disk
186
+ - [ ] Each repo has its own `.git` directory (they are separate repos, not subtrees)
187
+ - [ ] You have read access to all repos in the registry