@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,204 @@
1
+ # Java Patterns
2
+
3
+ Java conventions for FlowDeck projects. Targets Java 17+.
4
+
5
+ ## Constructor Injection Only
6
+
7
+ Use constructor injection for all Spring-managed beans. Never use field injection.
8
+
9
+ ```java
10
+ // ❌ Field injection — hides dependencies, cannot be tested without Spring
11
+ @Service
12
+ public class ReportService {
13
+ @Autowired private UserRepository users;
14
+ @Autowired private EmailService email;
15
+ }
16
+
17
+ // ✅ Constructor injection — explicit, testable, fields can be final
18
+ @Service
19
+ public class ReportService {
20
+ private final UserRepository users;
21
+ private final EmailService email;
22
+
23
+ public ReportService(UserRepository users, EmailService email) {
24
+ this.users = users;
25
+ this.email = email;
26
+ }
27
+ }
28
+ ```
29
+
30
+ ## Never Return null from Public Methods
31
+
32
+ Public methods must not return `null`. Use `Optional<T>` for absence, throw for impossible states.
33
+
34
+ ```java
35
+ // ❌ null return — callers can't tell if null is expected or a bug
36
+ public User findUser(long id) {
37
+ return repository.findById(id); // returns null when not found
38
+ }
39
+
40
+ // ✅ Optional signals intentional absence
41
+ public Optional<User> findUser(long id) {
42
+ return repository.findById(id);
43
+ }
44
+
45
+ // ✅ Throw when absence is a contract violation
46
+ public User getUser(long id) {
47
+ return repository.findById(id)
48
+ .orElseThrow(() -> new UserNotFoundException(id));
49
+ }
50
+ ```
51
+
52
+ ## All DTOs Should Be Records
53
+
54
+ Use Java records (Java 16+) for data transfer objects, API request/response bodies, and value objects.
55
+
56
+ ```java
57
+ // ❌ Mutable class with boilerplate
58
+ public class CreateUserRequest {
59
+ private String email;
60
+ private String name;
61
+ // getters, setters, equals, hashCode, toString...
62
+ }
63
+
64
+ // ✅ Record — immutable, compact, compiler-generated methods
65
+ public record CreateUserRequest(String email, String name) {}
66
+
67
+ // Records can include validation
68
+ public record PageRequest(int page, int size) {
69
+ public PageRequest {
70
+ if (page < 0) throw new IllegalArgumentException("page must be >= 0");
71
+ if (size < 1 || size > 100) throw new IllegalArgumentException("size must be 1–100");
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## Use var for Obvious Local Variable Types
77
+
78
+ Use `var` when the right-hand side makes the type immediately apparent. Do not use `var` when it obscures the type.
79
+
80
+ ```java
81
+ // ✅ Type is obvious from the right-hand side
82
+ var users = new ArrayList<User>();
83
+ var config = PaymentConfig.load();
84
+ var client = new HttpClient();
85
+
86
+ // ❌ Type is not obvious — write it out
87
+ var result = process(data); // what type is result?
88
+ var x = getValue(); // unclear
89
+ ```
90
+
91
+ ## Avoid Checked Exceptions in New Code
92
+
93
+ New code must not declare checked exceptions. Wrap checked exceptions from third-party libraries in unchecked exceptions and preserve the cause.
94
+
95
+ ```java
96
+ // ❌ Checked exception propagates through every caller
97
+ public List<User> loadUsers() throws IOException { ... }
98
+
99
+ // ✅ Unchecked exception at the boundary
100
+ public List<User> loadUsers() {
101
+ try {
102
+ return parser.parse(Files.readString(configPath));
103
+ } catch (IOException e) {
104
+ throw new UserLoadException("failed to read users from " + configPath, e);
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## All Database Queries Must Have Explicit Transaction Boundaries
110
+
111
+ Annotate the service method with `@Transactional`, not the repository method. The service defines the unit of work.
112
+
113
+ ```java
114
+ // ❌ Transaction on repository — too granular, two separate transactions
115
+ public void transfer(long fromId, long toId, BigDecimal amount) {
116
+ accountRepo.debit(fromId, amount); // tx 1
117
+ accountRepo.credit(toId, amount); // tx 2 — debit committed even if credit fails
118
+ }
119
+
120
+ // ✅ Transaction on service method — single atomic unit
121
+ @Transactional
122
+ public void transfer(long fromId, long toId, BigDecimal amount) {
123
+ accountRepo.debit(fromId, amount);
124
+ accountRepo.credit(toId, amount); // rolls back both on failure
125
+ }
126
+ ```
127
+
128
+ ## Never Use String.format() in Hot Paths
129
+
130
+ Avoid `String.format()` in loops or frequently-called methods. Use `StringBuilder` or text blocks.
131
+
132
+ ```java
133
+ // ❌ String.format in a loop — allocates a new formatter each iteration
134
+ for (var item : items) {
135
+ log.debug(String.format("Processing item id=%d name=%s", item.id(), item.name()));
136
+ }
137
+
138
+ // ✅ SLF4J lazy substitution — string only built if DEBUG is enabled
139
+ for (var item : items) {
140
+ log.debug("Processing item id={} name={}", item.id(), item.name());
141
+ }
142
+
143
+ // ✅ StringBuilder for building large strings
144
+ var sb = new StringBuilder();
145
+ for (var item : items) {
146
+ sb.append(item.name()).append(", ");
147
+ }
148
+ ```
149
+
150
+ ## Testing Strategy
151
+
152
+ - **Unit tests**: pure JUnit 5 + Mockito, annotated with `@ExtendWith(MockitoExtension.class)`. No Spring context.
153
+ - **Web slice tests**: `@WebMvcTest` for controller layer only.
154
+ - **Integration tests**: `@SpringBootTest` for end-to-end paths. Use `@Transactional` to roll back data after each test.
155
+ - Do not use `@SpringBootTest` for pure service or repository unit tests — it loads the full context unnecessarily.
156
+
157
+ ```java
158
+ // Unit test — no Spring
159
+ @ExtendWith(MockitoExtension.class)
160
+ class OrderServiceTest {
161
+ @Mock OrderRepository orders;
162
+ @InjectMocks OrderService service;
163
+ ...
164
+ }
165
+
166
+ // Integration test
167
+ @SpringBootTest
168
+ @Transactional
169
+ class OrderFlowIntegrationTest { ... }
170
+ ```
171
+
172
+ ## Lombok Usage
173
+
174
+ Lombok is permitted only for the following annotations:
175
+
176
+ - `@Builder` — for complex object construction
177
+ - `@Value` — for immutable classes (prefer records for new code)
178
+ - `@Slf4j` — for logger injection
179
+
180
+ Do **not** use `@Data` on JPA entities. It generates `equals`/`hashCode` based on all fields, which causes problems with proxies and lazy loading. Implement them manually using only the primary key.
181
+
182
+ ```java
183
+ // ❌ @Data on entity
184
+ @Data
185
+ @Entity
186
+ public class Order { ... }
187
+
188
+ // ✅ @Slf4j and manual equals/hashCode on entity
189
+ @Slf4j
190
+ @Entity
191
+ public class Order {
192
+ @Id private Long id;
193
+
194
+ @Override
195
+ public boolean equals(Object o) {
196
+ if (this == o) return true;
197
+ if (!(o instanceof Order other)) return false;
198
+ return id != null && id.equals(other.id);
199
+ }
200
+
201
+ @Override
202
+ public int hashCode() { return getClass().hashCode(); }
203
+ }
204
+ ```
@@ -0,0 +1,141 @@
1
+ # Python Patterns
2
+
3
+ Python conventions for FlowDeck projects.
4
+
5
+ ## Module Organization
6
+
7
+ - Single `.py` file for small, cohesive utilities.
8
+ - Convert to a package (`dir/__init__.py`) when the file grows past ~300 lines or needs sub-modules.
9
+ - Keep `__init__.py` thin — expose only the public API; don't execute side effects.
10
+ - Declare `__all__` in every module that has a meaningful public surface.
11
+
12
+ ```python
13
+ # mypackage/__init__.py
14
+ from .core import Engine
15
+ from .config import Config
16
+
17
+ __all__ = ["Engine", "Config"]
18
+ ```
19
+
20
+ ## Naming Conventions
21
+
22
+ | Construct | Style | Example |
23
+ |---|---|---|
24
+ | Variable / function / method | `snake_case` | `get_user`, `is_active` |
25
+ | Class | `PascalCase` | `UserService`, `HttpClient` |
26
+ | Module / package | `snake_case` | `user_service.py` |
27
+ | Constant (module-level) | `SCREAMING_SNAKE_CASE` | `MAX_RETRIES = 3` |
28
+ | "Private" member | `_leading_underscore` | `_internal_cache` |
29
+ | Name-mangled member | `__double_leading` | `__secret` (avoid in most cases) |
30
+
31
+ ## Never Use Mutable Default Arguments
32
+
33
+ ```python
34
+ # ❌ The list is shared across all calls
35
+ def add_item(item, lst=[]):
36
+ lst.append(item)
37
+ return lst
38
+
39
+ # ✅ Use None and guard inside the function
40
+ def add_item(item, lst=None):
41
+ if lst is None:
42
+ lst = []
43
+ lst.append(item)
44
+ return lst
45
+ ```
46
+
47
+ ## Always Use f-strings
48
+
49
+ ```python
50
+ # ❌ %-formatting — old, hard to read
51
+ msg = "Hello, %s! You have %d messages." % (name, count)
52
+
53
+ # ❌ .format() — verbose
54
+ msg = "Hello, {}! You have {} messages.".format(name, count)
55
+
56
+ # ✅ f-string — concise, readable, evaluated at runtime
57
+ msg = f"Hello, {name}! You have {count} messages."
58
+
59
+ # f-strings support expressions and format specs
60
+ price = f"${amount:.2f}"
61
+ debug = f"{obj!r}"
62
+ ```
63
+
64
+ ## Use pathlib.Path, Not os.path
65
+
66
+ ```python
67
+ # ❌ os.path — verbose and easy to misuse
68
+ import os
69
+ full_path = os.path.join(base_dir, "data", "users.csv")
70
+ if os.path.exists(full_path):
71
+ with open(full_path) as f: ...
72
+
73
+ # ✅ pathlib.Path — object-oriented, composable
74
+ from pathlib import Path
75
+ full_path = Path(base_dir) / "data" / "users.csv"
76
+ if full_path.exists():
77
+ content = full_path.read_text()
78
+ ```
79
+
80
+ ## Prefer Explicit Over Implicit
81
+
82
+ ```python
83
+ # ❌ Wildcard import — pollutes namespace, hides dependencies
84
+ from mymodule import *
85
+
86
+ # ✅ Explicit import — clear origin of each name
87
+ from mymodule import SpecificClass, helper_function
88
+ ```
89
+
90
+ ## Type Annotations on All Public Functions
91
+
92
+ Every public function and method must have type annotations on all parameters and the return type.
93
+
94
+ ```python
95
+ # ❌ No annotations
96
+ def find_users(active, limit):
97
+ ...
98
+
99
+ # ✅ Fully annotated
100
+ def find_users(active: bool, limit: int = 100) -> list[User]:
101
+ ...
102
+ ```
103
+
104
+ Private/internal functions (prefixed with `_`) should be annotated where the types are non-obvious.
105
+
106
+ ## Testing with pytest
107
+
108
+ - All tests use `pytest`. Do not use `unittest` for new code (legacy code may remain).
109
+ - Test files: `tests/test_<module>.py` or co-located `<module>_test.py`.
110
+ - Use fixtures for setup/teardown — not `setUp`/`tearDown` class methods.
111
+ - Use `@pytest.mark.parametrize` for functions that need more than two input cases.
112
+ - Tests must be deterministic — no time-dependent, order-dependent, or network-dependent tests without explicit mocking.
113
+
114
+ ```python
115
+ # ✅ parametrize instead of copy-pasted test functions
116
+ @pytest.mark.parametrize("value,expected", [
117
+ (0, False),
118
+ (1, True),
119
+ (-1, False),
120
+ ])
121
+ def test_is_positive(value: int, expected: bool) -> None:
122
+ assert is_positive(value) == expected
123
+ ```
124
+
125
+ ## Virtual Environments — Never Global pip Install
126
+
127
+ ```bash
128
+ # ✅ Create a venv and install there
129
+ python -m venv .venv
130
+ source .venv/bin/activate
131
+ pip install -e ".[dev]"
132
+
133
+ # ✅ uv (preferred — much faster)
134
+ uv venv && source .venv/bin/activate
135
+ uv pip install -e ".[dev]"
136
+
137
+ # ❌ Never install packages globally for a project
138
+ pip install requests # installs into system Python
139
+ ```
140
+
141
+ All project dependencies must live in `pyproject.toml`. Development tools (pytest, mypy, ruff) go in `[project.optional-dependencies]` under `dev`.
@@ -0,0 +1,210 @@
1
+ # Rust Patterns
2
+
3
+ Rust conventions for FlowDeck projects.
4
+
5
+ ## Prefer Result<T, E> Over Panicking in Library Code
6
+
7
+ Library code must not panic on expected failure conditions. Return `Result` and let the caller decide how to handle the error.
8
+
9
+ ```rust
10
+ // ❌ Panics on invalid input — caller has no recovery path
11
+ pub fn parse_port(s: &str) -> u16 {
12
+ s.parse().unwrap()
13
+ }
14
+
15
+ // ✅ Return Result — caller decides what to do
16
+ pub fn parse_port(s: &str) -> Result<u16, std::num::ParseIntError> {
17
+ s.parse()
18
+ }
19
+ ```
20
+
21
+ Application code (binaries, CLI entrypoints) may use `?` propagation up to `main`, which prints the error and exits.
22
+
23
+ ## Use thiserror for Library Errors, anyhow for Application Errors
24
+
25
+ ```rust
26
+ // Library crate: thiserror — structured, matchable error variants
27
+ use thiserror::Error;
28
+
29
+ #[derive(Debug, Error)]
30
+ pub enum CacheError {
31
+ #[error("key {0:?} not found")]
32
+ NotFound(String),
33
+ #[error("serialization failed: {0}")]
34
+ Serialize(#[from] serde_json::Error),
35
+ }
36
+
37
+ // Application binary: anyhow — ergonomic propagation with context
38
+ use anyhow::{Context, Result};
39
+
40
+ fn run() -> Result<()> {
41
+ let config = load_config("app.toml")
42
+ .context("loading application config")?;
43
+ serve(config).await
44
+ }
45
+ ```
46
+
47
+ ## Never Use unwrap() in Production Code
48
+
49
+ `unwrap()` panics on `None` or `Err`. Use `expect()` with a message that explains the invariant being asserted, or propagate with `?`.
50
+
51
+ ```rust
52
+ // ❌ Panics with an unhelpful message
53
+ let port: u16 = env::var("PORT").unwrap().parse().unwrap();
54
+
55
+ // ✅ expect() with a reason
56
+ let port_str = env::var("PORT")
57
+ .expect("PORT environment variable must be set");
58
+ let port: u16 = port_str
59
+ .parse()
60
+ .expect("PORT must be a valid u16");
61
+
62
+ // ✅ Propagate with ? when inside a Result-returning function
63
+ let port: u16 = env::var("PORT")?.parse()?;
64
+ ```
65
+
66
+ ## All Public Items Must Have rustdoc Comments
67
+
68
+ Every public function, struct, enum, trait, and module requires a doc comment (`///`).
69
+
70
+ ```rust
71
+ // ❌ No documentation
72
+ pub fn compress(data: &[u8]) -> Vec<u8> { ... }
73
+
74
+ // ✅ Describe what it does, mention important contracts
75
+ /// Compresses `data` using LZ4 and returns the compressed bytes.
76
+ ///
77
+ /// Returns an empty `Vec` if `data` is empty.
78
+ /// Panics if the internal compressor is exhausted (should never happen in practice).
79
+ pub fn compress(data: &[u8]) -> Vec<u8> { ... }
80
+ ```
81
+
82
+ ## Use the Newtype Pattern for Semantically Distinct Primitives
83
+
84
+ Wrapping primitives prevents accidentally mixing values of different meaning.
85
+
86
+ ```rust
87
+ // ❌ Easy to confuse which u64 is which
88
+ fn transfer(from: u64, to: u64, amount: u64) { ... }
89
+
90
+ // ✅ Distinct types — compiler catches transpositions
91
+ pub struct AccountId(u64);
92
+ pub struct CentAmount(u64);
93
+
94
+ fn transfer(from: AccountId, to: AccountId, amount: CentAmount) { ... }
95
+ ```
96
+
97
+ Newtype wrappers have zero runtime overhead.
98
+
99
+ ## Prefer iter() Chains Over Explicit Loops When Semantics Are Clear
100
+
101
+ ```rust
102
+ // ❌ Explicit loop for a pure transformation
103
+ let mut result = Vec::new();
104
+ for item in &items {
105
+ if item.is_active() {
106
+ result.push(item.name.clone());
107
+ }
108
+ }
109
+
110
+ // ✅ Iterator chain — intent is immediately clear
111
+ let result: Vec<String> = items.iter()
112
+ .filter(|item| item.is_active())
113
+ .map(|item| item.name.clone())
114
+ .collect();
115
+
116
+ // Use explicit loops when there are side effects or early returns that
117
+ // would obscure the logic if written as a chain
118
+ ```
119
+
120
+ ## Derive Debug, Clone, PartialEq by Default on Data Structs
121
+
122
+ ```rust
123
+ // ✅ Standard derives on data-holding structs
124
+ #[derive(Debug, Clone, PartialEq)]
125
+ pub struct Config {
126
+ pub host: String,
127
+ pub port: u16,
128
+ pub max_connections: usize,
129
+ }
130
+
131
+ // Add Eq when PartialEq implies total equality (no floats)
132
+ // Add Hash when the type will be used as a map key
133
+ // Add Serialize/Deserialize when crossing I/O boundaries
134
+ #[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
135
+ pub struct UserId(u64);
136
+ ```
137
+
138
+ ## Test Organization
139
+
140
+ - **Unit tests**: inside the module in a `#[cfg(test)]` block, next to the code they test.
141
+ - **Integration tests**: in a top-level `tests/` directory. These test the public API of the crate.
142
+ - **Doctests**: write examples in doc comments — they are compiled and run by `cargo test`.
143
+
144
+ ```rust
145
+ // src/parser.rs
146
+ pub fn parse(input: &str) -> Result<Ast, ParseError> { ... }
147
+
148
+ #[cfg(test)]
149
+ mod tests {
150
+ use super::*;
151
+
152
+ #[test]
153
+ fn empty_input_returns_error() {
154
+ assert!(parse("").is_err());
155
+ }
156
+
157
+ #[test]
158
+ fn valid_expression_parses_correctly() {
159
+ let ast = parse("1 + 2").unwrap();
160
+ assert_eq!(ast.eval(), 3);
161
+ }
162
+ }
163
+ ```
164
+
165
+ ```rust
166
+ // tests/integration_test.rs — tests/ is a separate crate
167
+ use mylib::parse;
168
+
169
+ #[test]
170
+ fn parses_complex_expression() {
171
+ let result = parse("(a + b) * c");
172
+ assert!(result.is_ok());
173
+ }
174
+ ```
175
+
176
+ ## clippy Must Pass with No Warnings
177
+
178
+ All code must pass `cargo clippy -- -D warnings` with no warnings. Enforce this in CI.
179
+
180
+ If a lint must be suppressed, add `#[allow(...)]` on the smallest scope possible with a comment explaining why.
181
+
182
+ ```rust
183
+ // ❌ Global allow — hides all issues of that category
184
+ #![allow(clippy::unwrap_used)]
185
+
186
+ // ✅ Local suppression with explanation
187
+ #[allow(clippy::unwrap_used)]
188
+ // Safety: regex pattern is a compile-time constant and always valid
189
+ let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
190
+ ```
191
+
192
+ ## Never Use unsafe Without a Safety Comment
193
+
194
+ Every `unsafe` block must have a comment that documents the invariants being upheld and why the operation is sound.
195
+
196
+ ```rust
197
+ // ❌ unsafe with no explanation
198
+ unsafe {
199
+ std::ptr::write(ptr, value);
200
+ }
201
+
202
+ // ✅ Safety comment explains the contract
203
+ // SAFETY: `ptr` is non-null, properly aligned, and uniquely owned here.
204
+ // The caller guaranteed these conditions in the function contract.
205
+ unsafe {
206
+ std::ptr::write(ptr, value);
207
+ }
208
+ ```
209
+
210
+ If you cannot write a clear safety comment, reconsider whether `unsafe` is necessary.