anima-core 0.3.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. checksums.yaml +4 -4
  2. data/.reek.yml +27 -1
  3. data/CHANGELOG.md +4 -0
  4. data/README.md +219 -25
  5. data/agents/codebase-analyzer.md +88 -0
  6. data/agents/codebase-pattern-finder.md +83 -0
  7. data/agents/documentation-researcher.md +59 -0
  8. data/agents/thoughts-analyzer.md +102 -0
  9. data/agents/web-search-researcher.md +71 -0
  10. data/anima-core.gemspec +4 -1
  11. data/app/channels/session_channel.rb +76 -28
  12. data/app/jobs/agent_request_job.rb +24 -0
  13. data/app/jobs/analytical_brain_job.rb +33 -0
  14. data/app/jobs/count_event_tokens_job.rb +1 -1
  15. data/app/models/concerns/event/broadcasting.rb +20 -2
  16. data/app/models/event.rb +1 -1
  17. data/app/models/goal.rb +91 -0
  18. data/app/models/session.rb +347 -22
  19. data/config/application.rb +2 -0
  20. data/db/migrate/20260314075248_add_subagent_support_to_sessions.rb +6 -0
  21. data/db/migrate/20260314112417_add_granted_tools_to_sessions.rb +5 -0
  22. data/db/migrate/20260314140000_add_name_to_sessions.rb +7 -0
  23. data/db/migrate/20260314150000_add_viewport_event_ids_to_sessions.rb +7 -0
  24. data/db/migrate/20260315100000_add_active_skills_to_sessions.rb +7 -0
  25. data/db/migrate/20260315140843_create_goals.rb +16 -0
  26. data/db/migrate/20260315144837_add_completed_at_to_goals.rb +5 -0
  27. data/db/migrate/20260315191105_add_active_workflow_to_sessions.rb +5 -0
  28. data/lib/agent_loop.rb +65 -9
  29. data/lib/agents/definition.rb +116 -0
  30. data/lib/agents/registry.rb +106 -0
  31. data/lib/analytical_brain/runner.rb +276 -0
  32. data/lib/analytical_brain/tools/activate_skill.rb +52 -0
  33. data/lib/analytical_brain/tools/deactivate_skill.rb +43 -0
  34. data/lib/analytical_brain/tools/deactivate_workflow.rb +34 -0
  35. data/lib/analytical_brain/tools/everything_is_ready.rb +28 -0
  36. data/lib/analytical_brain/tools/finish_goal.rb +62 -0
  37. data/lib/analytical_brain/tools/read_workflow.rb +58 -0
  38. data/lib/analytical_brain/tools/rename_session.rb +63 -0
  39. data/lib/analytical_brain/tools/set_goal.rb +60 -0
  40. data/lib/analytical_brain/tools/update_goal.rb +60 -0
  41. data/lib/analytical_brain.rb +23 -0
  42. data/lib/anima/cli/mcp/secrets.rb +76 -0
  43. data/lib/anima/cli/mcp.rb +197 -0
  44. data/lib/anima/cli.rb +4 -0
  45. data/lib/anima/installer.rb +182 -6
  46. data/lib/anima/settings.rb +226 -0
  47. data/lib/anima/version.rb +1 -1
  48. data/lib/anima.rb +9 -0
  49. data/lib/credential_store.rb +103 -0
  50. data/lib/environment_probe.rb +232 -0
  51. data/lib/llm/client.rb +29 -10
  52. data/lib/mcp/client_manager.rb +86 -0
  53. data/lib/mcp/config.rb +213 -0
  54. data/lib/mcp/health_check.rb +77 -0
  55. data/lib/mcp/secrets.rb +73 -0
  56. data/lib/mcp/stdio_transport.rb +206 -0
  57. data/lib/providers/anthropic.rb +8 -7
  58. data/lib/shell_session.rb +11 -10
  59. data/lib/skills/definition.rb +97 -0
  60. data/lib/skills/registry.rb +105 -0
  61. data/lib/tools/edit.rb +3 -4
  62. data/lib/tools/mcp_tool.rb +114 -0
  63. data/lib/tools/read.rb +15 -16
  64. data/lib/tools/registry.rb +14 -12
  65. data/lib/tools/request_feature.rb +121 -0
  66. data/lib/tools/return_result.rb +81 -0
  67. data/lib/tools/spawn_specialist.rb +109 -0
  68. data/lib/tools/spawn_subagent.rb +111 -0
  69. data/lib/tools/subagent_prompts.rb +12 -0
  70. data/lib/tools/web_get.rb +8 -9
  71. data/lib/tui/app.rb +332 -43
  72. data/lib/tui/message_store.rb +20 -0
  73. data/lib/tui/screens/chat.rb +207 -20
  74. data/lib/workflows/definition.rb +97 -0
  75. data/lib/workflows/registry.rb +89 -0
  76. data/skills/activerecord/SKILL.md +255 -0
  77. data/skills/activerecord/examples/associations/association_extensions.rb +298 -0
  78. data/skills/activerecord/examples/associations/basic_associations.rb +118 -0
  79. data/skills/activerecord/examples/associations/counter_caches.rb +215 -0
  80. data/skills/activerecord/examples/associations/polymorphic_associations.rb +217 -0
  81. data/skills/activerecord/examples/associations/self_referential.rb +302 -0
  82. data/skills/activerecord/examples/associations/through_associations.rb +203 -0
  83. data/skills/activerecord/examples/basics/crud_operations.rb +209 -0
  84. data/skills/activerecord/examples/basics/dirty_tracking.rb +218 -0
  85. data/skills/activerecord/examples/basics/inheritance.rb +377 -0
  86. data/skills/activerecord/examples/basics/type_casting.rb +317 -0
  87. data/skills/activerecord/examples/callbacks/alternatives_to_callbacks.rb +447 -0
  88. data/skills/activerecord/examples/callbacks/conditional_callbacks.rb +353 -0
  89. data/skills/activerecord/examples/callbacks/lifecycle_callbacks.rb +280 -0
  90. data/skills/activerecord/examples/callbacks/transaction_callbacks.rb +340 -0
  91. data/skills/activerecord/examples/migrations/indexes_and_constraints.rb +337 -0
  92. data/skills/activerecord/examples/migrations/reversible_patterns.rb +403 -0
  93. data/skills/activerecord/examples/migrations/safe_patterns.rb +420 -0
  94. data/skills/activerecord/examples/migrations/schema_changes.rb +277 -0
  95. data/skills/activerecord/examples/querying/batch_processing.rb +226 -0
  96. data/skills/activerecord/examples/querying/eager_loading.rb +259 -0
  97. data/skills/activerecord/examples/querying/finder_methods.rb +170 -0
  98. data/skills/activerecord/examples/querying/optimization.rb +275 -0
  99. data/skills/activerecord/examples/querying/scopes.rb +260 -0
  100. data/skills/activerecord/examples/validations/built_in_validators.rb +277 -0
  101. data/skills/activerecord/examples/validations/conditional_validations.rb +288 -0
  102. data/skills/activerecord/examples/validations/custom_validators.rb +381 -0
  103. data/skills/activerecord/examples/validations/database_constraints.rb +432 -0
  104. data/skills/activerecord/examples/validations/validation_contexts.rb +367 -0
  105. data/skills/activerecord/references/associations.md +709 -0
  106. data/skills/activerecord/references/basics.md +622 -0
  107. data/skills/activerecord/references/callbacks.md +738 -0
  108. data/skills/activerecord/references/migrations.md +657 -0
  109. data/skills/activerecord/references/querying.md +655 -0
  110. data/skills/activerecord/references/validations.md +596 -0
  111. data/skills/dragonruby/SKILL.md +250 -0
  112. data/skills/dragonruby/examples/audio/audio_events.rb +55 -0
  113. data/skills/dragonruby/examples/audio/background_music.rb +29 -0
  114. data/skills/dragonruby/examples/audio/crossfade.rb +51 -0
  115. data/skills/dragonruby/examples/audio/music_controls.rb +51 -0
  116. data/skills/dragonruby/examples/audio/sound_effects.rb +30 -0
  117. data/skills/dragonruby/examples/core/coordinate_system.rb +27 -0
  118. data/skills/dragonruby/examples/core/hello_world.rb +24 -0
  119. data/skills/dragonruby/examples/core/labels.rb +22 -0
  120. data/skills/dragonruby/examples/core/sprites.rb +35 -0
  121. data/skills/dragonruby/examples/core/state_management.rb +29 -0
  122. data/skills/dragonruby/examples/distribution/background_pause.rb +42 -0
  123. data/skills/dragonruby/examples/distribution/build_workflow.sh +26 -0
  124. data/skills/dragonruby/examples/distribution/cvars_production.txt +16 -0
  125. data/skills/dragonruby/examples/distribution/game_metadata_hd.txt +23 -0
  126. data/skills/dragonruby/examples/distribution/game_metadata_minimal.txt +9 -0
  127. data/skills/dragonruby/examples/distribution/game_metadata_mobile.txt +31 -0
  128. data/skills/dragonruby/examples/distribution/platform_detection.rb +36 -0
  129. data/skills/dragonruby/examples/distribution/steam_metadata.txt +19 -0
  130. data/skills/dragonruby/examples/entities/collision_detection.rb +43 -0
  131. data/skills/dragonruby/examples/entities/entity_lifecycle.rb +68 -0
  132. data/skills/dragonruby/examples/entities/entity_storage.rb +38 -0
  133. data/skills/dragonruby/examples/entities/factory_methods.rb +45 -0
  134. data/skills/dragonruby/examples/entities/random_spawning.rb +50 -0
  135. data/skills/dragonruby/examples/game-logic/reset_patterns.rb +98 -0
  136. data/skills/dragonruby/examples/game-logic/save_load.rb +101 -0
  137. data/skills/dragonruby/examples/game-logic/scoring.rb +104 -0
  138. data/skills/dragonruby/examples/game-logic/state_transitions.rb +103 -0
  139. data/skills/dragonruby/examples/game-logic/timers.rb +87 -0
  140. data/skills/dragonruby/examples/input/action_triggers.rb +36 -0
  141. data/skills/dragonruby/examples/input/analog_movement.rb +28 -0
  142. data/skills/dragonruby/examples/input/controller_input.rb +28 -0
  143. data/skills/dragonruby/examples/input/directional_input.rb +24 -0
  144. data/skills/dragonruby/examples/input/keyboard_input.rb +28 -0
  145. data/skills/dragonruby/examples/input/mouse_click.rb +26 -0
  146. data/skills/dragonruby/examples/input/movement_with_bounds.rb +22 -0
  147. data/skills/dragonruby/examples/input/normalized_movement.rb +32 -0
  148. data/skills/dragonruby/examples/rendering/frame_animation.rb +32 -0
  149. data/skills/dragonruby/examples/rendering/labels.rb +32 -0
  150. data/skills/dragonruby/examples/rendering/layering.rb +51 -0
  151. data/skills/dragonruby/examples/rendering/solids.rb +61 -0
  152. data/skills/dragonruby/examples/rendering/sprites.rb +33 -0
  153. data/skills/dragonruby/examples/rendering/spritesheet_animation.rb +39 -0
  154. data/skills/dragonruby/examples/scenes/case_dispatch.rb +60 -0
  155. data/skills/dragonruby/examples/scenes/class_based.rb +150 -0
  156. data/skills/dragonruby/examples/scenes/pause_overlay.rb +100 -0
  157. data/skills/dragonruby/examples/scenes/safe_transitions.rb +68 -0
  158. data/skills/dragonruby/examples/scenes/scene_transitions.rb +98 -0
  159. data/skills/dragonruby/examples/scenes/send_dispatch.rb +88 -0
  160. data/skills/dragonruby/references/audio.md +396 -0
  161. data/skills/dragonruby/references/core.md +385 -0
  162. data/skills/dragonruby/references/distribution.md +434 -0
  163. data/skills/dragonruby/references/entities.md +516 -0
  164. data/skills/dragonruby/references/game-logic/persistence.md +386 -0
  165. data/skills/dragonruby/references/game-logic/state.md +389 -0
  166. data/skills/dragonruby/references/input.md +414 -0
  167. data/skills/dragonruby/references/rendering/animation.md +467 -0
  168. data/skills/dragonruby/references/rendering/primitives.md +403 -0
  169. data/skills/dragonruby/references/scenes.md +443 -0
  170. data/skills/draper-decorators/SKILL.md +344 -0
  171. data/skills/draper-decorators/examples/application_decorator.rb +61 -0
  172. data/skills/draper-decorators/examples/decorator_spec.rb +253 -0
  173. data/skills/draper-decorators/examples/model_decorator.rb +152 -0
  174. data/skills/draper-decorators/references/anti-patterns.md +640 -0
  175. data/skills/draper-decorators/references/patterns.md +507 -0
  176. data/skills/draper-decorators/references/testing.md +559 -0
  177. data/skills/gh-issue.md +182 -0
  178. data/skills/mcp-server/SKILL.md +177 -0
  179. data/skills/mcp-server/examples/dynamic_tools.rb +36 -0
  180. data/skills/mcp-server/examples/file_manager_tool.rb +85 -0
  181. data/skills/mcp-server/examples/http_client.rb +48 -0
  182. data/skills/mcp-server/examples/http_server.rb +97 -0
  183. data/skills/mcp-server/examples/rails_integration.rb +88 -0
  184. data/skills/mcp-server/examples/stdio_server.rb +108 -0
  185. data/skills/mcp-server/examples/streaming_client.rb +95 -0
  186. data/skills/mcp-server/references/gotchas.md +183 -0
  187. data/skills/mcp-server/references/prompts.md +98 -0
  188. data/skills/mcp-server/references/resources.md +53 -0
  189. data/skills/mcp-server/references/server.md +140 -0
  190. data/skills/mcp-server/references/tools.md +146 -0
  191. data/skills/mcp-server/references/transport.md +104 -0
  192. data/skills/ratatui-ruby/SKILL.md +315 -0
  193. data/skills/ratatui-ruby/references/core-concepts.md +340 -0
  194. data/skills/ratatui-ruby/references/events.md +387 -0
  195. data/skills/ratatui-ruby/references/frameworks.md +522 -0
  196. data/skills/ratatui-ruby/references/layout.md +423 -0
  197. data/skills/ratatui-ruby/references/styling.md +268 -0
  198. data/skills/ratatui-ruby/references/testing.md +433 -0
  199. data/skills/ratatui-ruby/references/widgets.md +532 -0
  200. data/skills/rspec/SKILL.md +340 -0
  201. data/skills/rspec/examples/core/basic_structure.rb +69 -0
  202. data/skills/rspec/examples/core/configuration.rb +126 -0
  203. data/skills/rspec/examples/core/hooks.rb +126 -0
  204. data/skills/rspec/examples/core/memoized_helpers.rb +139 -0
  205. data/skills/rspec/examples/core/metadata_filtering.rb +144 -0
  206. data/skills/rspec/examples/core/shared_examples.rb +145 -0
  207. data/skills/rspec/examples/factory_bot/associations.rb +314 -0
  208. data/skills/rspec/examples/factory_bot/build_strategies.rb +272 -0
  209. data/skills/rspec/examples/factory_bot/callbacks.rb +320 -0
  210. data/skills/rspec/examples/factory_bot/custom_construction.rb +328 -0
  211. data/skills/rspec/examples/factory_bot/factory_definition.rb +191 -0
  212. data/skills/rspec/examples/factory_bot/inheritance.rb +314 -0
  213. data/skills/rspec/examples/factory_bot/traits.rb +293 -0
  214. data/skills/rspec/examples/factory_bot/transients.rb +229 -0
  215. data/skills/rspec/examples/matchers/change.rb +115 -0
  216. data/skills/rspec/examples/matchers/collections.rb +154 -0
  217. data/skills/rspec/examples/matchers/comparisons.rb +79 -0
  218. data/skills/rspec/examples/matchers/composing.rb +155 -0
  219. data/skills/rspec/examples/matchers/custom_matchers.rb +197 -0
  220. data/skills/rspec/examples/matchers/equality.rb +58 -0
  221. data/skills/rspec/examples/matchers/errors.rb +136 -0
  222. data/skills/rspec/examples/matchers/output.rb +103 -0
  223. data/skills/rspec/examples/matchers/predicates.rb +87 -0
  224. data/skills/rspec/examples/matchers/truthiness.rb +101 -0
  225. data/skills/rspec/examples/matchers/types.rb +82 -0
  226. data/skills/rspec/examples/matchers/yield.rb +147 -0
  227. data/skills/rspec/examples/mocks/any_instance.rb +172 -0
  228. data/skills/rspec/examples/mocks/argument_matchers.rb +206 -0
  229. data/skills/rspec/examples/mocks/constants.rb +177 -0
  230. data/skills/rspec/examples/mocks/doubles.rb +139 -0
  231. data/skills/rspec/examples/mocks/expectations.rb +137 -0
  232. data/skills/rspec/examples/mocks/message_chains.rb +173 -0
  233. data/skills/rspec/examples/mocks/ordering.rb +144 -0
  234. data/skills/rspec/examples/mocks/receive_counts.rb +181 -0
  235. data/skills/rspec/examples/mocks/responses.rb +223 -0
  236. data/skills/rspec/examples/mocks/spies.rb +149 -0
  237. data/skills/rspec/examples/mocks/stubbing.rb +133 -0
  238. data/skills/rspec/examples/rails/channels.rb +250 -0
  239. data/skills/rspec/examples/rails/controller_specs.rb +302 -0
  240. data/skills/rspec/examples/rails/helper_specs.rb +245 -0
  241. data/skills/rspec/examples/rails/job_specs.rb +256 -0
  242. data/skills/rspec/examples/rails/mailer_specs.rb +228 -0
  243. data/skills/rspec/examples/rails/matchers.rb +374 -0
  244. data/skills/rspec/examples/rails/model_specs.rb +193 -0
  245. data/skills/rspec/examples/rails/request_specs.rb +275 -0
  246. data/skills/rspec/examples/rails/routing_specs.rb +276 -0
  247. data/skills/rspec/examples/rails/system_specs.rb +294 -0
  248. data/skills/rspec/examples/rails/transactions.rb +254 -0
  249. data/skills/rspec/examples/rails/view_specs.rb +252 -0
  250. data/skills/rspec/references/core.md +816 -0
  251. data/skills/rspec/references/factory_bot.md +641 -0
  252. data/skills/rspec/references/matchers.md +516 -0
  253. data/skills/rspec/references/mocks.md +381 -0
  254. data/skills/rspec/references/rails.md +528 -0
  255. data/templates/soul.md +40 -0
  256. data/workflows/commit.md +45 -0
  257. data/workflows/create_handoff.md +98 -0
  258. data/workflows/create_note.md +82 -0
  259. data/workflows/create_plan.md +457 -0
  260. data/workflows/decompose_ticket.md +109 -0
  261. data/workflows/feature.md +91 -0
  262. data/workflows/implement_plan.md +87 -0
  263. data/workflows/iterate_plan.md +247 -0
  264. data/workflows/research_codebase.md +210 -0
  265. data/workflows/resume_handoff.md +217 -0
  266. data/workflows/review_pr.md +320 -0
  267. data/workflows/thoughts_init.md +71 -0
  268. data/workflows/validate_plan.md +166 -0
  269. metadata +284 -2
  270. data/.mise.toml +0 -2
@@ -0,0 +1,434 @@
1
+ # Distribution
2
+
3
+ ## Overview
4
+
5
+ DragonRuby builds cross-platform with one command via `dragonruby-publish`.
6
+
7
+ | Platform | Output Format | Notes |
8
+ |----------|---------------|-------|
9
+ | Windows | `.exe` | 64-bit only |
10
+ | macOS | `.app` bundle | Intel + Apple Silicon |
11
+ | Linux | Binary | Including SteamOS |
12
+ | HTML5 | `.zip` | Requires SharedArrayBuffer |
13
+ | Android | `.apk` / `.aab` | Requires signing |
14
+ | iOS | `.ipa` | Requires signing |
15
+
16
+ ## game_metadata.txt
17
+
18
+ Located at `mygame/metadata/game_metadata.txt`. **All fields required.**
19
+
20
+ ```txt
21
+ devid=youritchusername
22
+ devtitle=Your Studio Name
23
+ gameid=my-game-slug
24
+ gametitle=My Game Title
25
+ version=0.1
26
+ icon=metadata/icon.png
27
+ ```
28
+
29
+ | Field | Purpose | Notes |
30
+ |-------|---------|-------|
31
+ | `devid` | itch.io username | Lowercase, no spaces |
32
+ | `devtitle` | Developer display name | Can have spaces |
33
+ | `gameid` | itch.io project URL slug | Must match exactly |
34
+ | `gametitle` | Game display name | Can have spaces |
35
+ | `version` | Release version | MAJOR.MINOR format |
36
+ | `icon` | Path to icon | Relative to mygame/ |
37
+
38
+ **Optional fields:**
39
+
40
+ ```txt
41
+ # Mobile package ID (required for Android/iOS)
42
+ packageid=com.yourstudio.mygame
43
+
44
+ # Exclude directories from builds
45
+ ignore_directories=saves,debug
46
+ ignore_directories_recursively=true
47
+
48
+ # High-DPI support
49
+ hd=true
50
+ highdpi=true
51
+ ```
52
+
53
+ ## Version Numbering
54
+
55
+ Simple `MAJOR.MINOR` scheme:
56
+
57
+ | Phase | Version | When to increment |
58
+ |-------|---------|-------------------|
59
+ | Development | `0.1` → `0.2` → `0.3` | Each development milestone |
60
+ | Initial Release | `1.0` | Game is complete |
61
+ | Updates | `1.1` → `1.2` | Bug fixes, content updates |
62
+ | Major Overhaul | `2.0` | Significant changes |
63
+
64
+ ## dragonruby-publish Tool
65
+
66
+ **Package only (creates builds/):**
67
+
68
+ ```sh
69
+ ./dragonruby-publish --only-package
70
+ # OR
71
+ ./dragonruby-publish --package mygame
72
+ ```
73
+
74
+ **Package and upload to itch.io:**
75
+
76
+ ```sh
77
+ ./dragonruby-publish mygame
78
+ ```
79
+
80
+ Requires `gameid` to match itch.io project slug exactly.
81
+
82
+ **Build output location:** `./builds/` directory
83
+
84
+ ## Pre-Release Checklist
85
+
86
+ Before running `dragonruby-publish`:
87
+
88
+ 1. **Delete player-specific data:**
89
+ ```sh
90
+ rm -f mygame/high-score.txt
91
+ rm -f mygame/saves/*
92
+ ```
93
+
94
+ 2. **Verify metadata:**
95
+ - All 6 required fields filled
96
+ - `gameid` matches itch.io project
97
+ - Version incremented
98
+
99
+ 3. **Test local build:**
100
+ - Run platform-appropriate binary from `builds/`
101
+ - Verify game plays correctly
102
+
103
+ ## itch.io Deployment
104
+
105
+ ### First-Time Setup
106
+
107
+ 1. Create project at https://itch.io/game/new
108
+ 2. Set **Project URL** (becomes `gameid`)
109
+ 3. Select **HTML** as project type (supports web + downloads)
110
+ 4. Run `./dragonruby-publish --only-package`
111
+ 5. Upload builds manually
112
+
113
+ ### HTML5 Configuration (Critical)
114
+
115
+ | Setting | Value | Required |
116
+ |---------|-------|----------|
117
+ | "This file will be played in browser" | Checked | Yes |
118
+ | SharedArrayBuffer support | **Enabled** | **Yes** |
119
+ | Viewport width | 1280 | Landscape |
120
+ | Viewport height | 720 | Landscape |
121
+
122
+ **For portrait games:** 540x960
123
+
124
+ **Without SharedArrayBuffer, HTML5 builds will not run.**
125
+
126
+ ### Subsequent Updates
127
+
128
+ ```sh
129
+ ./dragonruby-publish mygame
130
+ ```
131
+
132
+ Auto-uploads if `gameid` matches project slug.
133
+
134
+ ### Publishing States
135
+
136
+ | State | Visibility | Use Case |
137
+ |-------|------------|----------|
138
+ | Private | Only you | Development |
139
+ | Secret URL | Shared link only | Playtesting |
140
+ | Public | Everyone | Release |
141
+
142
+ ## Steam Deployment
143
+
144
+ Requires Steam publisher account and app configuration.
145
+
146
+ **Create `metadata/steam_metadata.txt`:**
147
+
148
+ ```txt
149
+ steam.publish=true
150
+ steam.branch=public
151
+ steam.username=YOUR_STEAM_USERNAME
152
+ steam.appid=YOUR_APP_ID
153
+ steam.linux_depotid=LINUX_DEPOT_ID
154
+ steam.windows_depotid=WINDOWS_DEPOT_ID
155
+ steam.mac_depotid=MAC_DEPOT_ID
156
+ ```
157
+
158
+ ## Mobile Deployment
159
+
160
+ **Required in game_metadata.txt:**
161
+
162
+ ```txt
163
+ packageid=com.yourstudio.mygame
164
+ ```
165
+
166
+ Uses reverse domain notation.
167
+
168
+ ### Build Outputs
169
+
170
+ | Platform | Files | Notes |
171
+ |----------|-------|-------|
172
+ | Android | `APP-android.apk`, `APP-googleplay.aab` | AAB for Play Store |
173
+ | iOS | `.ipa` | Requires Xcode signing |
174
+
175
+ **APK Signing (external tools):**
176
+
177
+ ```sh
178
+ # Generate keystore
179
+ keytool -genkey -v -keystore my-release-key.jks \
180
+ -keyalg RSA -keysize 2048 -validity 10000 \
181
+ -alias my-key-alias
182
+
183
+ # Sign APK
184
+ apksigner sign --ks my-release-key.jks \
185
+ --out signed.apk unsigned.apk
186
+ ```
187
+
188
+ ## Platform Detection
189
+
190
+ Runtime platform checks for platform-specific behavior:
191
+
192
+ ```ruby
193
+ if args.gtk.platform?(:ios)
194
+ # iOS-specific code
195
+ elsif args.gtk.platform?(:android)
196
+ # Android-specific code
197
+ elsif args.gtk.platform?(:web)
198
+ # HTML5/browser code
199
+ else
200
+ # Desktop (Windows, macOS, Linux)
201
+ end
202
+ ```
203
+
204
+ ## Background Pause (Web/Mobile)
205
+
206
+ Handle focus loss gracefully:
207
+
208
+ ```ruby
209
+ def tick(args)
210
+ if !args.inputs.keyboard.has_focus &&
211
+ args.gtk.production &&
212
+ Kernel.tick_count != 0
213
+ # Game paused
214
+ args.outputs.background_color = [0, 0, 0]
215
+ args.outputs.labels << {
216
+ x: 640, y: 360,
217
+ text: "Click to resume",
218
+ alignment_enum: 1,
219
+ r: 255, g: 255, b: 255
220
+ }
221
+ return # Skip game logic
222
+ end
223
+
224
+ # Normal game tick
225
+ tick_game(args)
226
+ end
227
+ ```
228
+
229
+ **Disable via cvars.txt:**
230
+
231
+ ```txt
232
+ renderer.background_sleep=0
233
+ ```
234
+
235
+ ## In-Game Rating Prompts
236
+
237
+ ```ruby
238
+ def open_rating_page(args)
239
+ if args.gtk.platform?(:ios)
240
+ args.gtk.openurl "itms-apps://itunes.apple.com/app/idYOURGAMEID?action=write-review"
241
+ elsif args.gtk.platform?(:android)
242
+ args.gtk.openurl "https://play.google.com/store/apps/details?id=YOURGAMEID"
243
+ elsif args.gtk.platform?(:web)
244
+ args.gtk.openurl "https://yourusername.itch.io/yourgame/purchase"
245
+ else
246
+ args.gtk.openurl "https://yourusername.itch.io/yourgame/rate?source=game"
247
+ end
248
+ end
249
+ ```
250
+
251
+ ## Icon Preparation
252
+
253
+ Default location: `mygame/metadata/icon.png`
254
+
255
+ | Platform | Requirements |
256
+ |----------|-------------|
257
+ | Desktop | Any size, PNG recommended |
258
+ | itch.io | 315x250 cover image separate |
259
+ | Mobile | Multiple sizes via asset catalogs |
260
+
261
+ ## Project Structure for Distribution
262
+
263
+ **Recommended .gitignore:**
264
+
265
+ ```gitignore
266
+ # Always ignore
267
+ /tmp/
268
+ /logs/
269
+
270
+ # For public/open-source repos
271
+ /builds/
272
+ /samples/
273
+ /docs/
274
+ /.dragonruby/
275
+ ```
276
+
277
+ **Best practice:** Commit entire engine per project. Ensures known-working version years later.
278
+
279
+ ## Console Wizard
280
+
281
+ Interactive metadata setup via console:
282
+
283
+ ```ruby
284
+ $wizards.itch.start
285
+ ```
286
+
287
+ Prompts for all required fields, then runs `dragonruby-publish --only-package`.
288
+
289
+ ## Common Antipatterns
290
+
291
+ ### Shipping with Dev Data
292
+
293
+ ```ruby
294
+ # WRONG - players see your high scores/saves
295
+ # (no code cleanup before build)
296
+
297
+ # CORRECT - delete temp files pre-build
298
+ rm -f mygame/high-score.txt
299
+ rm -rf mygame/saves/*
300
+ ```
301
+
302
+ **Why:** Development data (high scores, save files) gets bundled into the release.
303
+
304
+ ### Skipping Local Testing
305
+
306
+ ```ruby
307
+ # WRONG - publish without testing
308
+ ./dragonruby-publish mygame
309
+
310
+ # CORRECT - test each platform build
311
+ ./dragonruby-publish --only-package
312
+ # Then run: builds/mygame-windows.exe
313
+ # Then run: builds/mygame-macos.app
314
+ # Then run: builds/mygame-linux
315
+ ```
316
+
317
+ **Why:** Different platforms may have broken builds or missing assets.
318
+
319
+ ### Wrong Viewport Size
320
+
321
+ ```ruby
322
+ # WRONG - using non-standard dimensions on itch.io
323
+ Viewport: 800x600
324
+
325
+ # CORRECT - use standard dimensions
326
+ Viewport: 1280x720 (landscape)
327
+ Viewport: 540x960 (portrait)
328
+ ```
329
+
330
+ **Why:** Mismatched viewport causes layout issues in the itch.io embed.
331
+
332
+ ### Forgetting SharedArrayBuffer
333
+
334
+ ```ruby
335
+ # WRONG - HTML5 build doesn't run on itch.io
336
+ # (no SharedArrayBuffer enabled)
337
+
338
+ # CORRECT - enable in itch.io settings
339
+ # Project → Edit → SharedArrayBuffer → Enabled
340
+ ```
341
+
342
+ **Why:** DragonRuby HTML5 builds require SharedArrayBuffer to function.
343
+
344
+ ### Inconsistent Versioning
345
+
346
+ ```ruby
347
+ # WRONG - version never changes
348
+ version=1.0
349
+
350
+ # CORRECT - increment on every release
351
+ version=1.0 # Initial release
352
+ version=1.1 # Bug fixes
353
+ version=1.2 # New content
354
+ ```
355
+
356
+ **Why:** Players can't tell if they have the latest version.
357
+
358
+ ### Sharing Engine Folder
359
+
360
+ ```ruby
361
+ # WRONG - symlink or shared engine folder
362
+ dragonruby -> /shared/dragonruby
363
+
364
+ # CORRECT - copy engine per project
365
+ cp -r /path/to/dragonruby ./my-game/
366
+ ```
367
+
368
+ **Why:** Shared engines cause path issues and version conflicts between projects.
369
+
370
+ ## Decision Tree
371
+
372
+ ```
373
+ What platform are you targeting?
374
+
375
+ ├─► Desktop only (Windows/macOS/Linux)
376
+ │ └─► Use: game_metadata_minimal.txt
377
+ │ • Fill 6 required fields
378
+ │ • Run: ./dragonruby-publish --only-package
379
+ │ • Upload to itch.io or Steam
380
+
381
+ ├─► Web (HTML5) + Desktop
382
+ │ └─► Use: game_metadata_hd.txt
383
+ │ • Add hd=true, highdpi=true
384
+ │ • CRITICAL: Enable SharedArrayBuffer on itch.io
385
+ │ • Set viewport: 1280x720
386
+
387
+ ├─► Mobile (Android/iOS)
388
+ │ └─► Use: game_metadata_mobile.txt
389
+ │ • Add packageid=com.studio.game
390
+ │ • Set orientation=portrait or landscape
391
+ │ • Sign APK externally
392
+
393
+ └─► Steam Distribution
394
+ └─► Use: steam_metadata.txt
395
+ • Get Steamworks publisher account
396
+ • Configure depot IDs
397
+ • Run: ./dragonruby-publish
398
+
399
+ Publishing workflow?
400
+
401
+ ├─► First release
402
+ │ ├─► 1. Clean dev data (rm saves/*, high-score.txt)
403
+ │ ├─► 2. Configure game_metadata.txt
404
+ │ ├─► 3. ./dragonruby-publish --only-package
405
+ │ ├─► 4. Test builds locally
406
+ │ ├─► 5. Create itch.io project
407
+ │ ├─► 6. Upload builds manually
408
+ │ └─► See: build_workflow.sh
409
+
410
+ └─► Update release
411
+ ├─► 1. Increment version in game_metadata.txt
412
+ ├─► 2. Clean dev data
413
+ ├─► 3. ./dragonruby-publish mygame
414
+ └─► Auto-uploads to itch.io
415
+
416
+ Platform-specific behavior needed?
417
+
418
+ ├─► Different rating URLs → platform_detection.rb
419
+ ├─► Handle tab-away/minimize → background_pause.rb
420
+ └─► Different save paths → platform_detection.rb
421
+ ```
422
+
423
+ ## Examples
424
+
425
+ | Example | Purpose |
426
+ |---------|---------|
427
+ | `game_metadata_minimal.txt` | Required fields only |
428
+ | `game_metadata_hd.txt` | HD desktop/web game |
429
+ | `game_metadata_mobile.txt` | Mobile with portrait orientation |
430
+ | `cvars_production.txt` | Production runtime settings |
431
+ | `steam_metadata.txt` | Steam publishing config |
432
+ | `build_workflow.sh` | Complete publishing script |
433
+ | `platform_detection.rb` | Runtime platform checks |
434
+ | `background_pause.rb` | Handle focus loss |