oh-my-agent-commandcode 0.0.0-stage → 20.38.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/README.md +35 -2
  2. package/filter-test-output.sh +52 -0
  3. package/mods/oma.ts +347 -0
  4. package/package.json +30 -4
  5. package/skills/_shared/conditional/experiment-ledger.md +28 -0
  6. package/skills/_shared/conditional/exploration-loop.md +22 -0
  7. package/skills/_shared/conditional/quality-score.md +33 -0
  8. package/skills/_shared/core/anti-ai-prose.md +191 -0
  9. package/skills/_shared/core/api-contracts/README.md +28 -0
  10. package/skills/_shared/core/api-contracts/template.md +90 -0
  11. package/skills/_shared/core/clarification-protocol.md +23 -0
  12. package/skills/_shared/core/code-intelligence.md +46 -0
  13. package/skills/_shared/core/collaboration-policy.md +28 -0
  14. package/skills/_shared/core/common-checklist.md +28 -0
  15. package/skills/_shared/core/context-budget.md +22 -0
  16. package/skills/_shared/core/context-loading.md +34 -0
  17. package/skills/_shared/core/difficulty-guide.md +26 -0
  18. package/skills/_shared/core/execution-policy.md +31 -0
  19. package/skills/_shared/core/lessons-learned.md +33 -0
  20. package/skills/_shared/core/prompt-structure.md +18 -0
  21. package/skills/_shared/core/quality-principles.md +11 -0
  22. package/skills/_shared/core/session-metrics.md +35 -0
  23. package/skills/_shared/core/skill-routing.md +39 -0
  24. package/skills/_shared/core/test-approach.md +54 -0
  25. package/skills/_shared/core/vendor-detection.md +52 -0
  26. package/skills/_shared/runtime/memory-protocol.md +118 -0
  27. package/skills/_shared/runtime/result-contract.md +64 -0
  28. package/skills/_shared/ui-interaction-quality.md +133 -0
  29. package/skills/oma-academic-writing/SKILL.md +181 -0
  30. package/skills/oma-academic-writing/resources/abstract-guide.md +51 -0
  31. package/skills/oma-academic-writing/resources/academic-verb-tiers.md +42 -0
  32. package/skills/oma-academic-writing/resources/anti-ai-checklist.md +52 -0
  33. package/skills/oma-academic-writing/resources/hedging-guide.md +132 -0
  34. package/skills/oma-academic-writing/resources/sentence-structure-reference.md +151 -0
  35. package/skills/oma-architecture/SKILL.md +203 -0
  36. package/skills/oma-architecture/resources/api-evolution.md +41 -0
  37. package/skills/oma-architecture/resources/checklist.md +42 -0
  38. package/skills/oma-architecture/resources/execution-protocol.md +115 -0
  39. package/skills/oma-architecture/resources/methodology-selection.md +92 -0
  40. package/skills/oma-architecture/resources/migration-patterns.md +28 -0
  41. package/skills/oma-architecture/resources/output-templates.md +111 -0
  42. package/skills/oma-architecture/resources/stakeholder-synthesis.md +80 -0
  43. package/skills/oma-backend/SKILL.md +202 -0
  44. package/skills/oma-backend/resources/checklist.md +45 -0
  45. package/skills/oma-backend/resources/error-playbook.md +97 -0
  46. package/skills/oma-backend/resources/execution-protocol.md +39 -0
  47. package/skills/oma-backend/resources/orm-reference.md +61 -0
  48. package/skills/oma-backend/variants/node/api-template.ts +315 -0
  49. package/skills/oma-backend/variants/node/snippets.md +475 -0
  50. package/skills/oma-backend/variants/node/stack.yaml +21 -0
  51. package/skills/oma-backend/variants/node/tech-stack.md +33 -0
  52. package/skills/oma-backend/variants/python/api-template.py +378 -0
  53. package/skills/oma-backend/variants/python/snippets.md +199 -0
  54. package/skills/oma-backend/variants/python/stack.yaml +18 -0
  55. package/skills/oma-backend/variants/python/tech-stack.md +45 -0
  56. package/skills/oma-backend/variants/rust/api-template.rs +635 -0
  57. package/skills/oma-backend/variants/rust/snippets.md +471 -0
  58. package/skills/oma-backend/variants/rust/stack.yaml +20 -0
  59. package/skills/oma-backend/variants/rust/tech-stack.md +36 -0
  60. package/skills/oma-backend/variants/stack.schema.json +73 -0
  61. package/skills/oma-brainstorm/SKILL.md +166 -0
  62. package/skills/oma-brainstorm/resources/triz-lite.md +117 -0
  63. package/skills/oma-coordination/SKILL.md +171 -0
  64. package/skills/oma-db/SKILL.md +201 -0
  65. package/skills/oma-db/resources/anti-patterns.md +177 -0
  66. package/skills/oma-db/resources/checklist.md +67 -0
  67. package/skills/oma-db/resources/document-templates.md +107 -0
  68. package/skills/oma-db/resources/error-playbook.md +50 -0
  69. package/skills/oma-db/resources/examples.md +170 -0
  70. package/skills/oma-db/resources/execution-protocol.md +127 -0
  71. package/skills/oma-db/resources/iso-controls.md +98 -0
  72. package/skills/oma-db/resources/migration-playbook.md +93 -0
  73. package/skills/oma-db/resources/query-tuning.md +57 -0
  74. package/skills/oma-db/resources/vector-db.md +159 -0
  75. package/skills/oma-debug/SKILL.md +146 -0
  76. package/skills/oma-debug/resources/bug-report-template.md +327 -0
  77. package/skills/oma-debug/resources/checklist.md +31 -0
  78. package/skills/oma-debug/resources/common-patterns.md +734 -0
  79. package/skills/oma-debug/resources/debugging-checklist.md +364 -0
  80. package/skills/oma-debug/resources/error-playbook.md +94 -0
  81. package/skills/oma-debug/resources/execution-protocol.md +40 -0
  82. package/skills/oma-design/SKILL.md +135 -0
  83. package/skills/oma-design/resources/asset-strategy.md +34 -0
  84. package/skills/oma-design/resources/checklist.md +63 -0
  85. package/skills/oma-design/resources/data-grid.md +48 -0
  86. package/skills/oma-design/resources/design-md-spec.md +107 -0
  87. package/skills/oma-design/resources/design-tokens.md +53 -0
  88. package/skills/oma-design/resources/error-playbook.md +18 -0
  89. package/skills/oma-design/resources/execution-protocol.md +95 -0
  90. package/skills/oma-design/resources/external-design-skills.md +130 -0
  91. package/skills/oma-design/resources/getdesign-fetcher.md +104 -0
  92. package/skills/oma-design/resources/product-interface-review.md +59 -0
  93. package/skills/oma-design/resources/redesign-protocol.md +52 -0
  94. package/skills/oma-design/resources/stitch-integration.md +244 -0
  95. package/skills/oma-dev-workflow/SKILL.md +375 -0
  96. package/skills/oma-dev-workflow/resources/affected-checks.py +58 -0
  97. package/skills/oma-dev-workflow/resources/api-workflows.md +58 -0
  98. package/skills/oma-dev-workflow/resources/database-patterns.md +107 -0
  99. package/skills/oma-dev-workflow/resources/i18n-patterns.md +63 -0
  100. package/skills/oma-dev-workflow/resources/release-coordination.md +240 -0
  101. package/skills/oma-dev-workflow/resources/tooling-profiles.md +217 -0
  102. package/skills/oma-dev-workflow/resources/troubleshooting.md +78 -0
  103. package/skills/oma-dev-workflow/resources/validation-pipeline.md +246 -0
  104. package/skills/oma-docs/SKILL.md +77 -0
  105. package/skills/oma-docs/resources/commands.md +76 -0
  106. package/skills/oma-explanation/SKILL.md +212 -0
  107. package/skills/oma-explanation/resources/document-structure.md +115 -0
  108. package/skills/oma-explanation/resources/draft-format.md +199 -0
  109. package/skills/oma-explanation/resources/html-contract.md +102 -0
  110. package/skills/oma-frontend/SKILL.md +227 -0
  111. package/skills/oma-frontend/resources/angular-rules.md +110 -0
  112. package/skills/oma-frontend/resources/checklist.md +76 -0
  113. package/skills/oma-frontend/resources/error-playbook.md +125 -0
  114. package/skills/oma-frontend/resources/execution-protocol.md +46 -0
  115. package/skills/oma-frontend/resources/snippets.md +354 -0
  116. package/skills/oma-frontend/resources/specialized-visual-implementation.md +193 -0
  117. package/skills/oma-frontend/resources/tailwind-rules.md +83 -0
  118. package/skills/oma-frontend/resources/tech-stack.md +156 -0
  119. package/skills/oma-hwp/SKILL.md +166 -0
  120. package/skills/oma-hwp/config/hwp-config.yaml +35 -0
  121. package/skills/oma-hwp/resources/balanced-tables.ts +39 -0
  122. package/skills/oma-hwp/resources/execution-protocol.md +145 -0
  123. package/skills/oma-hwp/resources/flatten-tables.ts +101 -0
  124. package/skills/oma-hwp/resources/package.json +13 -0
  125. package/skills/oma-hwp/resources/troubleshooting.md +70 -0
  126. package/skills/oma-hwp/resources/tsconfig.json +10 -0
  127. package/skills/oma-hwp/resources/turndown-plugin-gfm.d.ts +9 -0
  128. package/skills/oma-image/SKILL.md +142 -0
  129. package/skills/oma-image/config/image-config.yaml +70 -0
  130. package/skills/oma-image/resources/checklist.md +18 -0
  131. package/skills/oma-image/resources/execution-protocol.md +117 -0
  132. package/skills/oma-image/resources/invocation.md +105 -0
  133. package/skills/oma-image/resources/prompt-tips.md +71 -0
  134. package/skills/oma-image/resources/vendor-matrix.md +90 -0
  135. package/skills/oma-market/SKILL.md +142 -0
  136. package/skills/oma-market/resources/checklist.md +12 -0
  137. package/skills/oma-market/resources/error-playbook.md +12 -0
  138. package/skills/oma-market/resources/execution-protocol.md +60 -0
  139. package/skills/oma-market/resources/frameworks/pestel.md +101 -0
  140. package/skills/oma-market/resources/frameworks/porters-5f.md +90 -0
  141. package/skills/oma-market/resources/frameworks/swot.md +61 -0
  142. package/skills/oma-market/resources/intent-rules.md +35 -0
  143. package/skills/oma-market/resources/output-laws.md +53 -0
  144. package/skills/oma-mobile/SKILL.md +168 -0
  145. package/skills/oma-mobile/resources/checklist.md +77 -0
  146. package/skills/oma-mobile/resources/error-playbook.md +198 -0
  147. package/skills/oma-mobile/resources/execution-protocol.md +47 -0
  148. package/skills/oma-mobile/resources/screen-template.dart +331 -0
  149. package/skills/oma-mobile/resources/screen-template.swift +239 -0
  150. package/skills/oma-mobile/resources/screen-template.tsx +179 -0
  151. package/skills/oma-mobile/resources/tech-stack.md +69 -0
  152. package/skills/oma-mobile/variants/README.md +45 -0
  153. package/skills/oma-mobile/variants/flutter/api-template.dart +461 -0
  154. package/skills/oma-mobile/variants/flutter/snippets.md +1353 -0
  155. package/skills/oma-mobile/variants/flutter/stack.yaml +21 -0
  156. package/skills/oma-mobile/variants/flutter/tech-stack.md +201 -0
  157. package/skills/oma-mobile/variants/kotlin-android/api-template.kt +182 -0
  158. package/skills/oma-mobile/variants/kotlin-android/snippets.md +871 -0
  159. package/skills/oma-mobile/variants/kotlin-android/stack.yaml +32 -0
  160. package/skills/oma-mobile/variants/kotlin-android/tech-stack.md +159 -0
  161. package/skills/oma-mobile/variants/react-native/api-template.ts +531 -0
  162. package/skills/oma-mobile/variants/react-native/snippets.md +1014 -0
  163. package/skills/oma-mobile/variants/react-native/stack.yaml +22 -0
  164. package/skills/oma-mobile/variants/react-native/tech-stack.md +192 -0
  165. package/skills/oma-mobile/variants/stack.schema.json +68 -0
  166. package/skills/oma-mobile/variants/swift-ios/api-template.swift +165 -0
  167. package/skills/oma-mobile/variants/swift-ios/snippets.md +1028 -0
  168. package/skills/oma-mobile/variants/swift-ios/stack.yaml +25 -0
  169. package/skills/oma-mobile/variants/swift-ios/tech-stack.md +174 -0
  170. package/skills/oma-observability/SKILL.md +225 -0
  171. package/skills/oma-observability/resources/anti-patterns.md +555 -0
  172. package/skills/oma-observability/resources/boundaries/cross-application.md +348 -0
  173. package/skills/oma-observability/resources/boundaries/multi-tenant.md +290 -0
  174. package/skills/oma-observability/resources/boundaries/release.md +372 -0
  175. package/skills/oma-observability/resources/boundaries/slo.md +225 -0
  176. package/skills/oma-observability/resources/checklist.md +123 -0
  177. package/skills/oma-observability/resources/examples.md +448 -0
  178. package/skills/oma-observability/resources/execution-protocol.md +166 -0
  179. package/skills/oma-observability/resources/incident-forensics.md +348 -0
  180. package/skills/oma-observability/resources/intent-rules.md +307 -0
  181. package/skills/oma-observability/resources/layers/L3-network.md +281 -0
  182. package/skills/oma-observability/resources/layers/L4-transport.md +299 -0
  183. package/skills/oma-observability/resources/layers/L7-application/crash-analytics.md +359 -0
  184. package/skills/oma-observability/resources/layers/L7-application/mobile-rum.md +278 -0
  185. package/skills/oma-observability/resources/layers/L7-application/waf.md +246 -0
  186. package/skills/oma-observability/resources/layers/L7-application/web-rum.md +350 -0
  187. package/skills/oma-observability/resources/layers/mesh.md +368 -0
  188. package/skills/oma-observability/resources/matrix.md +177 -0
  189. package/skills/oma-observability/resources/meta-observability.md +605 -0
  190. package/skills/oma-observability/resources/observability-as-code.md +666 -0
  191. package/skills/oma-observability/resources/signals/audit.md +310 -0
  192. package/skills/oma-observability/resources/signals/cost.md +303 -0
  193. package/skills/oma-observability/resources/signals/logs.md +263 -0
  194. package/skills/oma-observability/resources/signals/metrics.md +478 -0
  195. package/skills/oma-observability/resources/signals/privacy.md +351 -0
  196. package/skills/oma-observability/resources/signals/profiles.md +245 -0
  197. package/skills/oma-observability/resources/signals/traces.md +360 -0
  198. package/skills/oma-observability/resources/standards.md +214 -0
  199. package/skills/oma-observability/resources/transport/collector-topology.md +308 -0
  200. package/skills/oma-observability/resources/transport/otlp-grpc-vs-http.md +256 -0
  201. package/skills/oma-observability/resources/transport/sampling-recipes.md +297 -0
  202. package/skills/oma-observability/resources/transport/udp-statsd-mtu.md +167 -0
  203. package/skills/oma-observability/resources/vendor-categories.md +352 -0
  204. package/skills/oma-orchestration/SKILL.md +302 -0
  205. package/skills/oma-orchestration/config/cli-config.yaml +92 -0
  206. package/skills/oma-orchestration/resources/memory-schema.md +232 -0
  207. package/skills/oma-orchestration/resources/subagent-prompt-template.md +30 -0
  208. package/skills/oma-orchestration/scripts/parallel-run.sh +6 -0
  209. package/skills/oma-orchestration/scripts/spawn-agent.sh +5 -0
  210. package/skills/oma-orchestration/scripts/verify.sh +20 -0
  211. package/skills/oma-orchestration/templates/backend-task.md +19 -0
  212. package/skills/oma-orchestration/templates/debug-task.md +16 -0
  213. package/skills/oma-orchestration/templates/frontend-task.md +18 -0
  214. package/skills/oma-orchestration/templates/mobile-task.md +18 -0
  215. package/skills/oma-orchestration/templates/qa-task.md +16 -0
  216. package/skills/oma-orchestration/templates/tasks-example.yaml +15 -0
  217. package/skills/oma-pdf/SKILL.md +162 -0
  218. package/skills/oma-pdf/config/pdf-config.yaml +27 -0
  219. package/skills/oma-pdf/resources/execution-protocol.md +127 -0
  220. package/skills/oma-pm/SKILL.md +157 -0
  221. package/skills/oma-pm/resources/error-playbook.md +75 -0
  222. package/skills/oma-pm/resources/examples.md +439 -0
  223. package/skills/oma-pm/resources/execution-protocol.md +62 -0
  224. package/skills/oma-pm/resources/iso-planning.md +110 -0
  225. package/skills/oma-pm/resources/plan-phase-protocol.md +66 -0
  226. package/skills/oma-pm/resources/task-template.json +86 -0
  227. package/skills/oma-qa/SKILL.md +141 -0
  228. package/skills/oma-qa/resources/checklist.md +339 -0
  229. package/skills/oma-qa/resources/error-playbook.md +98 -0
  230. package/skills/oma-qa/resources/execution-protocol.md +169 -0
  231. package/skills/oma-qa/resources/iso-quality.md +82 -0
  232. package/skills/oma-qa/resources/verify-ship-protocol.md +116 -0
  233. package/skills/oma-recap/SKILL.md +245 -0
  234. package/skills/oma-recap/resources/output-formats.md +83 -0
  235. package/skills/oma-refactor/SKILL.md +184 -0
  236. package/skills/oma-refactor/resources/definition.md +108 -0
  237. package/skills/oma-refactor/resources/governance.md +33 -0
  238. package/skills/oma-refactor/resources/hotspots.py +44 -0
  239. package/skills/oma-refactor/resources/measurement.md +93 -0
  240. package/skills/oma-scholar/SKILL.md +276 -0
  241. package/skills/oma-scholar/config/scholar-config.yaml +79 -0
  242. package/skills/oma-scholar/resources/api-endpoints.md +174 -0
  243. package/skills/oma-scholar/resources/checklist.md +92 -0
  244. package/skills/oma-scholar/resources/execution-protocol.md +224 -0
  245. package/skills/oma-scholar/resources/fallback-providers.md +143 -0
  246. package/skills/oma-scholar/resources/setup-openalex.md +85 -0
  247. package/skills/oma-scholar/resources/sidecar-spec.md +341 -0
  248. package/skills/oma-scholar/resources/upstream-spec-cache.md +972 -0
  249. package/skills/oma-scm/SKILL.md +103 -0
  250. package/skills/oma-scm/resources/cm-operations.md +56 -0
  251. package/skills/oma-scm/resources/codeowners-playbook.md +45 -0
  252. package/skills/oma-scm/resources/conventional-commits.md +108 -0
  253. package/skills/oma-scm/resources/merge-risk.md +76 -0
  254. package/skills/oma-scm/resources/onboarding-risk-signals.md +71 -0
  255. package/skills/oma-search/SKILL.md +125 -0
  256. package/skills/oma-search/resources/checklist.md +36 -0
  257. package/skills/oma-search/resources/error-playbook.md +66 -0
  258. package/skills/oma-search/resources/examples.md +80 -0
  259. package/skills/oma-search/resources/execution-protocol.md +86 -0
  260. package/skills/oma-search/resources/intent-rules.md +47 -0
  261. package/skills/oma-search/resources/trust-registry.md +53 -0
  262. package/skills/oma-security/SKILL.md +172 -0
  263. package/skills/oma-security/resources/artex.md +108 -0
  264. package/skills/oma-security/resources/ci.md +134 -0
  265. package/skills/oma-security/resources/cisco-source.md +108 -0
  266. package/skills/oma-security/resources/deepsec-config.md +45 -0
  267. package/skills/oma-security/resources/deepsec-matchers.md +35 -0
  268. package/skills/oma-security/resources/deepsec-scanning.md +45 -0
  269. package/skills/oma-security/resources/deepsec-setup.md +41 -0
  270. package/skills/oma-security/resources/findings-contract.md +408 -0
  271. package/skills/oma-security/resources/mcp-scanning.md +122 -0
  272. package/skills/oma-security/resources/skill-scanning.md +106 -0
  273. package/skills/oma-security/resources/validation.md +71 -0
  274. package/skills/oma-skill-creation/SKILL.md +84 -0
  275. package/skills/oma-skill-creation/resources/prompt-evaluation.md +36 -0
  276. package/skills/oma-skill-creation/resources/ssl-lite-template.md +108 -0
  277. package/skills/oma-skill-creation/resources/validation-checklist.md +101 -0
  278. package/skills/oma-slide/SKILL.md +277 -0
  279. package/skills/oma-slide/resources/animation-patterns.md +245 -0
  280. package/skills/oma-slide/resources/assets/deck-stage.js +514 -0
  281. package/skills/oma-slide/resources/assets/viewport-base.css +257 -0
  282. package/skills/oma-slide/resources/canva-integration.md +203 -0
  283. package/skills/oma-slide/resources/checklist.md +46 -0
  284. package/skills/oma-slide/resources/design-doctrine.md +260 -0
  285. package/skills/oma-slide/resources/fixed-stage.md +232 -0
  286. package/skills/oma-slide/resources/generation-protocol.md +393 -0
  287. package/skills/oma-slide/resources/native-pptx.md +84 -0
  288. package/skills/oma-slide/resources/selection-index.json +461 -0
  289. package/skills/oma-slide/resources/style-presets.LICENSE +10 -0
  290. package/skills/oma-slide/resources/style-presets.md +520 -0
  291. package/skills/oma-tf-infra/SKILL.md +201 -0
  292. package/skills/oma-tf-infra/resources/checklist.md +53 -0
  293. package/skills/oma-tf-infra/resources/cost-optimization.md +574 -0
  294. package/skills/oma-tf-infra/resources/error-playbook.md +68 -0
  295. package/skills/oma-tf-infra/resources/examples.md +38 -0
  296. package/skills/oma-tf-infra/resources/execution-protocol.md +129 -0
  297. package/skills/oma-tf-infra/resources/iso-42001-infra.md +229 -0
  298. package/skills/oma-tf-infra/resources/multi-cloud-examples.md +241 -0
  299. package/skills/oma-tf-infra/resources/policy-testing-examples.md +332 -0
  300. package/skills/oma-translation/SKILL.md +229 -0
  301. package/skills/oma-translation/resources/anti-ai-patterns.md +104 -0
  302. package/skills/oma-translation/resources/lang/_template.md +73 -0
  303. package/skills/oma-translation/resources/lang/en.md +123 -0
  304. package/skills/oma-translation/resources/lang/ja.md +274 -0
  305. package/skills/oma-translation/resources/lang/ko.md +228 -0
  306. package/skills/oma-translation/resources/lang/zh.md +285 -0
  307. package/skills/oma-translation/resources/style-skills.md +104 -0
  308. package/skills/oma-translation/resources/translation-rubric.md +126 -0
  309. package/skills/oma-video/SKILL.md +229 -0
  310. package/skills/oma-video/config/video-config.yaml +60 -0
  311. package/skills/oma-video/resources/checklist.md +26 -0
  312. package/skills/oma-video/resources/execution-protocol.md +122 -0
  313. package/skills/oma-video/resources/existing-media.md +185 -0
  314. package/skills/oma-video/resources/hyperframes-authoring/README.md +44 -0
  315. package/skills/oma-video/resources/hyperframes-authoring/demo.md +31 -0
  316. package/skills/oma-video/resources/hyperframes-authoring/explainer.md +10 -0
  317. package/skills/oma-video/resources/hyperframes-authoring/shorts.md +10 -0
  318. package/skills/oma-video/resources/motion-principles.md +81 -0
  319. package/skills/oma-video/resources/mpt/driver.py +301 -0
  320. package/skills/oma-video/resources/prompt-tips.md +75 -0
  321. package/skills/oma-video/resources/script-schema.md +81 -0
  322. package/skills/oma-video/resources/sound-design.md +127 -0
  323. package/skills/oma-video/resources/strudel/package.json +11 -0
  324. package/skills/oma-video/resources/strudel/page.html +87 -0
  325. package/skills/oma-video/resources/strudel/render.mjs +295 -0
  326. package/skills/oma-video/resources/vendor-matrix.md +124 -0
  327. package/skills/oma-voice/SKILL.md +249 -0
  328. package/skills/oma-voice/config/voice-config.yaml +30 -0
  329. package/skills/oma-voice/resources/audio-processing.md +119 -0
  330. package/skills/oma-voice/resources/checklist.md +47 -0
  331. package/skills/oma-voice/resources/execution-protocol.md +215 -0
  332. package/skills/oma-voice/resources/prompt-tips.md +43 -0
  333. package/skills/oma-voice/resources/voice-matrix.md +51 -0
  334. package/skills/oma-voice/resources/voicestudio.md +87 -0
@@ -0,0 +1,461 @@
1
+ /// API Repository Template for Mobile Agent (Flutter)
2
+ ///
3
+ /// This file is the Flutter analogue of `variants/swift-ios/api-template.swift`.
4
+ /// It provides a complete, commented [TodoRepository] showing:
5
+ /// - The abstract repository interface (domain layer)
6
+ /// - The offline-first implementation (data layer) with stale-while-revalidate caching
7
+ /// - The Drift-backed local cache (real @DriftDatabase + @DriftAccessor DAO)
8
+ /// - The Dio-backed remote data source
9
+ /// - Cache invalidation on every write (create / toggle / delete)
10
+ ///
11
+ /// This is a reference showing every layer in one place. It is NOT a
12
+ /// single-file standalone compile: the `part` directives below pull in
13
+ /// build_runner output (freezed, drift, json_serializable). In production,
14
+ /// split it into the files listed under "File layout" and run
15
+ /// `dart run build_runner build --delete-conflicting-outputs`.
16
+ ///
17
+ /// Caching contract (mandatory — mirrors the swift-ios ResponseCache rules):
18
+ /// - Cache DECODED domain entities ([Todo]) at the Repository layer,
19
+ /// NOT raw HTTP bytes or JSON strings at the Dio transport layer.
20
+ /// - [TodoRepositoryImpl.watchAll] emits the locally-cached Drift rows first
21
+ /// (instant render), then revalidates from the network and re-emits via the
22
+ /// Drift stream (stale-while-revalidate). The UI renders immediately then updates.
23
+ /// - Every write ([create] / [toggle] / [delete]) upserts or removes the
24
+ /// affected Drift row after a successful network response so the stream
25
+ /// re-emits the change without a separate read round-trip.
26
+ /// - Cache key = logical operation name + params (never URLs or raw path strings).
27
+ /// - TTL is explicit ([_kCacheTtl]). No implicit or infinite cache.
28
+ /// - Secrets → flutter_secure_storage. User-authored durable data → a separate
29
+ /// Drift table. This cache is for transient server-owned data only.
30
+ ///
31
+ /// File layout (split into real files in production):
32
+ /// lib/core/database/
33
+ /// app_database.dart <- [AppDatabase] @DriftDatabase definition
34
+ /// lib/features/todos/
35
+ /// domain/
36
+ /// todo.dart <- [Todo] domain entity (§ Domain Entity)
37
+ /// todo_repository.dart <- [TodoRepository] abstract interface
38
+ /// data/
39
+ /// dtos/
40
+ /// todo_dto.dart <- [TodoDto] JSON transfer object
41
+ /// local/
42
+ /// todos_dao.dart <- [TodosDao] Drift @DriftAccessor DAO
43
+ /// remote/
44
+ /// todos_remote_data_source.dart <- [TodosRemoteDataSource] Dio calls
45
+ /// todo_repository_impl.dart <- [TodoRepositoryImpl] offline-first impl
46
+ ///
47
+ /// See snippets.md for the Riverpod [StreamNotifier] that consumes this repository
48
+ /// and the flutter_test + mocktail tests that stub the interface seam.
49
+
50
+ import 'package:drift/drift.dart';
51
+ import 'package:dio/dio.dart';
52
+ import 'package:freezed_annotation/freezed_annotation.dart';
53
+ import 'package:json_annotation/json_annotation.dart';
54
+
55
+ // ---------------------------------------------------------------------------
56
+ // DOMAIN ENTITY
57
+ // ---------------------------------------------------------------------------
58
+ // lib/features/todos/domain/todo.dart
59
+
60
+ part 'api-template.freezed.dart';
61
+ part 'api-template.g.dart';
62
+
63
+ /// Pure domain entity — no Drift columns, no JSON annotations, no Dio types.
64
+ /// Equality, copyWith, and toString are generated by freezed.
65
+ /// Freezed 3 requires the class to be `abstract` (or `sealed`).
66
+ @freezed
67
+ abstract class Todo with _$Todo {
68
+ const factory Todo({
69
+ required int id,
70
+ required String title,
71
+ required bool completed,
72
+ /// Timestamp set by the Repository when the entity is written to the cache.
73
+ /// Used to evaluate staleness against [_kCacheTtl].
74
+ required DateTime cachedAt,
75
+ }) = _Todo;
76
+ }
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // REPOSITORY INTERFACE (domain layer)
80
+ // ---------------------------------------------------------------------------
81
+ // lib/features/todos/domain/todo_repository.dart
82
+
83
+ /// Abstract contract that the presentation layer (Riverpod providers) depends on.
84
+ ///
85
+ /// Concrete implementations ([TodoRepositoryImpl], stubs, mocks) swap behind
86
+ /// this interface seam. View models and providers NEVER import [TodoRepositoryImpl],
87
+ /// [TodosRemoteDataSource], or [TodosDao] directly.
88
+ abstract interface class TodoRepository {
89
+ /// Returns a live [Stream] of all todos.
90
+ ///
91
+ /// Emits the locally-cached list immediately (may be empty on first launch),
92
+ /// then silently revalidates from the network when the cache is stale or empty.
93
+ /// Drift re-emits the stream automatically after each upsert, so the UI
94
+ /// updates without any explicit refresh call.
95
+ Stream<List<Todo>> watchAll();
96
+ /// Bypass TTL; complete only after the network result has been stored.
97
+ Future<void> refresh();
98
+
99
+ /// Fetches a single todo by [id].
100
+ ///
101
+ /// Returns the cached entity immediately when present, revalidating from the
102
+ /// network in the background only when it is stale (older than the TTL). A
103
+ /// `Future` cannot re-emit — watchers of [watchAll] observe the refreshed row
104
+ /// via the Drift stream. Returns null when the id is absent both locally and
105
+ /// remotely (HTTP 404).
106
+ Future<Todo?> findById(int id);
107
+
108
+ /// Creates a new todo with the given [title].
109
+ ///
110
+ /// Hits the network first, then upserts the returned entity into the local
111
+ /// Drift cache so [watchAll()] emits the new item immediately.
112
+ Future<Todo> create(String title);
113
+
114
+ /// Toggles the [completed] flag on the todo with the given [id].
115
+ ///
116
+ /// Hits the network first, then upserts the updated entity into the local cache.
117
+ Future<Todo> toggle(int id);
118
+
119
+ /// Permanently deletes the todo with the given [id].
120
+ ///
121
+ /// Hits the network first, then removes the row from the local cache so
122
+ /// [watchAll()] emits the deletion immediately.
123
+ Future<void> delete(int id);
124
+ }
125
+
126
+ // ---------------------------------------------------------------------------
127
+ // JSON TRANSFER OBJECT (data layer)
128
+ // ---------------------------------------------------------------------------
129
+ // lib/features/todos/data/dtos/todo_dto.dart
130
+
131
+ /// JSON ↔ Dart mapping object. Isolated from the domain entity so that
132
+ /// API shape changes don't propagate into the domain.
133
+ @JsonSerializable()
134
+ class TodoDto {
135
+ const TodoDto({
136
+ required this.id,
137
+ required this.title,
138
+ required this.completed,
139
+ });
140
+
141
+ final int id;
142
+ final String title;
143
+ final bool completed;
144
+
145
+ factory TodoDto.fromJson(Map<String, dynamic> json) =>
146
+ _$TodoDtoFromJson(json);
147
+
148
+ Map<String, dynamic> toJson() => _$TodoDtoToJson(this);
149
+
150
+ /// Converts this DTO to a domain [Todo].
151
+ ///
152
+ /// [cachedAt] is provided by the Repository (not the network) so that
153
+ /// TTL comparisons use the local clock, not the server's.
154
+ Todo toDomain({required DateTime cachedAt}) => Todo(
155
+ id: id,
156
+ title: title,
157
+ completed: completed,
158
+ cachedAt: cachedAt,
159
+ );
160
+ }
161
+
162
+ // ---------------------------------------------------------------------------
163
+ // DRIFT TABLE (data layer — local cache)
164
+ // ---------------------------------------------------------------------------
165
+ // lib/core/database/app_database.dart (declared alongside the AppDatabase below)
166
+
167
+ /// One Drift row per server-owned Todo.
168
+ ///
169
+ /// [cachedAt] is written by the Repository at insert/upsert time.
170
+ /// It is compared against [_kCacheTtl] to decide whether to revalidate.
171
+ class TodosTable extends Table {
172
+ IntColumn get id => integer()();
173
+ TextColumn get title => text()();
174
+ BoolColumn get completed =>
175
+ boolean().withDefault(const Constant(false))();
176
+ DateTimeColumn get cachedAt => dateTime()();
177
+
178
+ @override
179
+ Set<Column> get primaryKey => {id};
180
+ }
181
+
182
+ // ---------------------------------------------------------------------------
183
+ // DRIFT DATABASE + DAO (data layer — typed queries)
184
+ // ---------------------------------------------------------------------------
185
+ // lib/core/database/app_database.dart + lib/features/todos/data/local/todos_dao.dart
186
+ //
187
+ // build_runner (drift_dev) generates the row data class [TodosTableData], the
188
+ // insert/update companion [TodosTableCompanion], the [_$AppDatabase] base, and
189
+ // the [_$TodosDaoMixin] into api-template.g.dart. See snippets.md §3c for the
190
+ // same declarations with the LazyDatabase connection/open-file wiring.
191
+
192
+ @DriftDatabase(tables: [TodosTable], daos: [TodosDao])
193
+ class AppDatabase extends _$AppDatabase {
194
+ AppDatabase(super.executor);
195
+
196
+ @override
197
+ int get schemaVersion => 1;
198
+ }
199
+
200
+ /// Type-safe Data Access Object for the todos cache table.
201
+ ///
202
+ /// Exposes [Stream]-returning methods so [TodoRepositoryImpl] can forward
203
+ /// live Drift updates directly to Riverpod without any manual polling.
204
+ @DriftAccessor(tables: [TodosTable])
205
+ class TodosDao extends DatabaseAccessor<AppDatabase> with _$TodosDaoMixin {
206
+ TodosDao(super.db);
207
+
208
+ /// Live stream — Drift re-emits on every INSERT / UPDATE / DELETE on the table.
209
+ Stream<List<TodosTableData>> watchAll() => select(todosTable).watch();
210
+
211
+ /// Returns the most recently cached row for [id], or null if not present.
212
+ Future<TodosTableData?> findById(int id) =>
213
+ (select(todosTable)..where((t) => t.id.equals(id))).getSingleOrNull();
214
+
215
+ /// Upserts a batch of rows (INSERT OR REPLACE). Additive only — use
216
+ /// [replaceAll] to mirror a full server list.
217
+ Future<void> upsertAll(List<TodosTableCompanion> rows) =>
218
+ batch((b) => b.insertAllOnConflictUpdate(todosTable, rows));
219
+
220
+ /// Replace the whole cached list with the fresh server set in ONE
221
+ /// transaction: delete rows the server no longer returns, then upsert the
222
+ /// rest, so server-side deletions do not linger as ghost rows.
223
+ Future<void> replaceAll(List<TodosTableCompanion> rows) {
224
+ return transaction(() async {
225
+ final freshIds = rows.map((r) => r.id.value).toList();
226
+ await (delete(todosTable)..where((t) => t.id.isNotIn(freshIds))).go();
227
+ await batch((b) => b.insertAllOnConflictUpdate(todosTable, rows));
228
+ });
229
+ }
230
+
231
+ /// Upserts a single row. Used after create / toggle.
232
+ Future<void> upsertOne(TodosTableCompanion row) =>
233
+ into(todosTable).insertOnConflictUpdate(row);
234
+
235
+ /// Removes the row for [id]. Used after delete.
236
+ Future<void> deleteById(int id) =>
237
+ (delete(todosTable)..where((t) => t.id.equals(id))).go();
238
+ }
239
+
240
+ // ---------------------------------------------------------------------------
241
+ // REMOTE DATA SOURCE (data layer — Dio calls)
242
+ // ---------------------------------------------------------------------------
243
+ // lib/features/todos/data/remote/todos_remote_data_source.dart
244
+
245
+ /// All Dio HTTP calls for the /todos resource.
246
+ ///
247
+ /// This class is transport-only — no caching, no domain types.
248
+ /// It maps HTTP responses to [TodoDto] and surfaces [DioException] on failure.
249
+ /// Interceptors (auth, retry, logging) are registered on the [Dio] instance
250
+ /// in `core/network/dio_client.dart`, not here.
251
+ class TodosRemoteDataSource {
252
+ TodosRemoteDataSource(this._dio);
253
+
254
+ final Dio _dio;
255
+
256
+ /// GET /todos — returns the full list.
257
+ Future<List<TodoDto>> fetchAll() async {
258
+ final response = await _dio.get<List<dynamic>>('/todos');
259
+ return (response.data ?? [])
260
+ .map((json) => TodoDto.fromJson(json as Map<String, dynamic>))
261
+ .toList();
262
+ }
263
+
264
+ /// GET /todos/:id — returns a single item.
265
+ Future<TodoDto> fetchById(int id) async {
266
+ final response =
267
+ await _dio.get<Map<String, dynamic>>('/todos/$id');
268
+ return TodoDto.fromJson(response.data!);
269
+ }
270
+
271
+ /// POST /todos — creates a new item with the given [title].
272
+ Future<TodoDto> create(String title) async {
273
+ final response = await _dio.post<Map<String, dynamic>>(
274
+ '/todos',
275
+ data: {'title': title},
276
+ );
277
+ return TodoDto.fromJson(response.data!);
278
+ }
279
+
280
+ /// PATCH /todos/:id/toggle — flips the completed flag.
281
+ Future<TodoDto> toggle(int id) async {
282
+ final response = await _dio
283
+ .patch<Map<String, dynamic>>('/todos/$id/toggle');
284
+ return TodoDto.fromJson(response.data!);
285
+ }
286
+
287
+ /// DELETE /todos/:id — permanently removes the item.
288
+ Future<void> delete(int id) => _dio.delete<void>('/todos/$id');
289
+ }
290
+
291
+ // ---------------------------------------------------------------------------
292
+ // OFFLINE-FIRST REPOSITORY IMPLEMENTATION (data layer)
293
+ // ---------------------------------------------------------------------------
294
+ // lib/features/todos/data/todo_repository_impl.dart
295
+
296
+ /// How long a cached list is considered fresh before a background revalidation
297
+ /// is triggered. Adjust per resource; NEVER use Duration.zero or "infinite".
298
+ const Duration _kCacheTtl = Duration(minutes: 5);
299
+
300
+ /// Offline-first implementation of [TodoRepository].
301
+ ///
302
+ /// # Caching contract
303
+ ///
304
+ /// ## Reads (stale-while-revalidate)
305
+ /// [watchAll] and [findById] emit the locally-cached Drift data first.
306
+ /// Cold cache loads await the network and propagate failures. Warm revalidation runs when
307
+ /// older than [_kCacheTtl]. After the network response is upserted into
308
+ /// Drift, the DAO stream re-emits automatically — the UI updates without
309
+ /// any explicit refresh call.
310
+ ///
311
+ /// ## Writes (invalidate-on-write)
312
+ /// [create] and [toggle] hit the network first, then upsert the returned
313
+ /// entity into Drift so the stream emits the change instantly.
314
+ /// [delete] hits the network first, then removes the Drift row so the
315
+ /// stream emits the deletion instantly.
316
+ ///
317
+ /// ## Key strategy
318
+ /// Cache key = the DAO method name + the primary-key param (where applicable).
319
+ /// Examples: "watchAll" → the full [TodosTable]; "findById:42" → a single row.
320
+ /// Never key on URLs or path strings.
321
+ ///
322
+ /// ## Boundaries
323
+ /// This class caches transient server-owned data only. Secrets belong in
324
+ /// [FlutterSecureStorage]. Durable user-authored data belongs in a separate
325
+ /// Drift table with an independent retention policy.
326
+ class TodoRepositoryImpl implements TodoRepository {
327
+ TodoRepositoryImpl({
328
+ required TodosDao dao,
329
+ required TodosRemoteDataSource remote,
330
+ }) : _dao = dao,
331
+ _remote = remote;
332
+
333
+ final TodosDao _dao;
334
+ final TodosRemoteDataSource _remote;
335
+
336
+ // ---------------------------------------------------------------------------
337
+ // READ — stale-while-revalidate
338
+ // ---------------------------------------------------------------------------
339
+
340
+ @override
341
+ Stream<List<Todo>> watchAll() async* {
342
+ final snapshot = await _dao.watchAll().first;
343
+ final now = DateTime.now();
344
+ if (snapshot.isEmpty) {
345
+ // Cold-cache failures must reach Riverpod's error state.
346
+ await refresh();
347
+ } else if (snapshot.any((row) => now.difference(row.cachedAt) > _kCacheTtl)) {
348
+ // Only warm-cache revalidation may degrade to the stale value.
349
+ refresh().ignore();
350
+ }
351
+ yield* _dao.watchAll().map((rows) => rows.map(_rowToEntity).toList());
352
+ }
353
+
354
+ @override
355
+ Future<void> refresh() => _revalidateAll(DateTime.now());
356
+
357
+ @override
358
+ Future<Todo?> findById(int id) async {
359
+ final cached = await _dao.findById(id);
360
+ final now = DateTime.now();
361
+
362
+ if (cached != null) {
363
+ // Serve the cached row immediately. Revalidate in the background only
364
+ // when it is stale; watchers of watchAll() observe the refreshed row via
365
+ // the Drift stream. This Future returns the cached snapshot as-is.
366
+ if (now.difference(cached.cachedAt) > _kCacheTtl) {
367
+ _revalidateById(id, now).ignore();
368
+ }
369
+ return _rowToEntity(cached);
370
+ }
371
+
372
+ // Cache miss — fetch from network and persist.
373
+ try {
374
+ final dto = await _remote.fetchById(id);
375
+ await _dao.upsertOne(_dtoToCompanion(dto, cachedAt: now));
376
+ return dto.toDomain(cachedAt: now);
377
+ } on DioException catch (e) {
378
+ if (e.response?.statusCode == 404) return null;
379
+ rethrow;
380
+ }
381
+ }
382
+
383
+ // ---------------------------------------------------------------------------
384
+ // WRITE — upsert / delete after success
385
+ // ---------------------------------------------------------------------------
386
+
387
+ @override
388
+ Future<Todo> create(String title) async {
389
+ // Network first; cache on success.
390
+ final dto = await _remote.create(title);
391
+ final now = DateTime.now();
392
+ await _dao.upsertOne(_dtoToCompanion(dto, cachedAt: now));
393
+ // watchAll() stream auto-emits the new row via Drift.
394
+ return dto.toDomain(cachedAt: now);
395
+ }
396
+
397
+ @override
398
+ Future<Todo> toggle(int id) async {
399
+ // Network first; upsert updated entity on success.
400
+ final dto = await _remote.toggle(id);
401
+ final now = DateTime.now();
402
+ await _dao.upsertOne(_dtoToCompanion(dto, cachedAt: now));
403
+ // watchAll() stream auto-emits the updated row via Drift.
404
+ return dto.toDomain(cachedAt: now);
405
+ }
406
+
407
+ @override
408
+ Future<void> delete(int id) async {
409
+ // Network first; remove local row on success.
410
+ await _remote.delete(id);
411
+ await _dao.deleteById(id);
412
+ // watchAll() stream auto-emits the deletion via Drift.
413
+ }
414
+
415
+ // ---------------------------------------------------------------------------
416
+ // Private helpers
417
+ // ---------------------------------------------------------------------------
418
+
419
+ bool _isStaleOrEmpty(List<TodosTableData> rows, DateTime now) {
420
+ if (rows.isEmpty) return true;
421
+ // Revalidate the whole list if any row is older than the TTL.
422
+ return rows.any((row) => now.difference(row.cachedAt) > _kCacheTtl);
423
+ }
424
+
425
+ Future<void> _revalidateAll(DateTime now) async {
426
+ final dtos = await _remote.fetchAll();
427
+ await _dao.replaceAll(
428
+ dtos.map((dto) => _dtoToCompanion(dto, cachedAt: now)).toList(),
429
+ );
430
+ }
431
+
432
+ Future<void> _revalidateById(int id, DateTime now) async {
433
+ try {
434
+ final dto = await _remote.fetchById(id);
435
+ await _dao.upsertOne(_dtoToCompanion(dto, cachedAt: now));
436
+ } catch (_) {
437
+ // Non-fatal — caller already received the cached value.
438
+ }
439
+ }
440
+
441
+ /// Maps a Drift row to a domain [Todo].
442
+ Todo _rowToEntity(TodosTableData row) => Todo(
443
+ id: row.id,
444
+ title: row.title,
445
+ completed: row.completed,
446
+ cachedAt: row.cachedAt,
447
+ );
448
+
449
+ /// Maps a [TodoDto] to a Drift [TodosTableCompanion] for upsert.
450
+ /// `cachedAt` is stamped from the local clock by the Repository, not the DTO.
451
+ TodosTableCompanion _dtoToCompanion(
452
+ TodoDto dto, {
453
+ required DateTime cachedAt,
454
+ }) =>
455
+ TodosTableCompanion(
456
+ id: Value(dto.id),
457
+ title: Value(dto.title),
458
+ completed: Value(dto.completed),
459
+ cachedAt: Value(cachedAt),
460
+ );
461
+ }