gOdoo-cli 1.0.2__tar.gz → 1.0.4__tar.gz

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 (184) hide show
  1. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.agents/skills/godoo-editor-validation/SKILL.md +3 -4
  2. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.agents/skills/godoo-runtime-validation/SKILL.md +3 -3
  3. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.env.sample +4 -0
  4. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.vscode/settings.json +1 -1
  5. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/AGENTS.md +18 -0
  6. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/PKG-INFO +9 -7
  7. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/README.md +7 -6
  8. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docker/Dockerfile +2 -2
  9. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docker/docker-compose.base.yml +7 -3
  10. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docker/docker-compose.dev.yml +2 -1
  11. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docs/downstream.md +23 -14
  12. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docs/hooks.md +19 -5
  13. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docs/lifecycle.md +92 -22
  14. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docs/workspace.md +8 -3
  15. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/pyproject.toml +2 -0
  16. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/__about__.py +1 -1
  17. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/configuration.py +2 -0
  18. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/db/archive.py +23 -12
  19. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/rpc/importer.py +2 -0
  20. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/run.py +2 -0
  21. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/runtime/__init__.py +2 -0
  22. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/runtime/init.py +158 -66
  23. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/runtime/launch.py +32 -4
  24. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/runtime/shell.py +6 -0
  25. godoo_cli-1.0.4/src/godoo_cli/commands/runtime/start.py +56 -0
  26. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/test/load_data.py +2 -0
  27. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/test/run.py +2 -0
  28. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/archive.py +76 -27
  29. godoo_cli-1.0.4/src/godoo_cli/runtime/backup.py +80 -0
  30. godoo_cli-1.0.4/src/godoo_cli/runtime/checksums.py +220 -0
  31. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/hooks.py +27 -1
  32. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/lifecycle.py +8 -4
  33. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/promotion.py +2 -0
  34. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/reset.py +14 -0
  35. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/restore.py +2 -0
  36. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/editor.py +25 -5
  37. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/git.py +2 -0
  38. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_runtime_cli.py +1 -1
  39. godoo_cli-1.0.4/tests/commands/test_runtime_start.py +82 -0
  40. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/conftest.py +1 -0
  41. godoo_cli-1.0.4/tests/database/test_db_backup.py +342 -0
  42. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/database/test_db_reset.py +12 -5
  43. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/integration/test_container_contract.py +7 -5
  44. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/integration/test_odoo_integration.py +204 -4
  45. godoo_cli-1.0.4/tests/runtime/test_checksums.py +184 -0
  46. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_hooks.py +119 -0
  47. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_init_hooks.py +38 -11
  48. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_lifecycle.py +8 -3
  49. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/workspace/test_workspace.py +58 -0
  50. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/workspace/test_workspace_layout.py +1 -2
  51. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/uv.lock +11 -0
  52. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.agents/skills/godoo-changeset-review/SKILL.md +0 -0
  53. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.agents/skills/godoo-source-workspaces/SKILL.md +0 -0
  54. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.codecovrc +0 -0
  55. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.dockerignore +0 -0
  56. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.github/FUNDING.yml +0 -0
  57. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.github/workflows/README.md +0 -0
  58. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.github/workflows/quality.yml +0 -0
  59. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.github/workflows/version-bump.yml +0 -0
  60. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.github/workflows/version-publish.yml +0 -0
  61. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.gitignore +0 -0
  62. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.pre-commit-config.yaml +0 -0
  63. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.prettierrc.yml +0 -0
  64. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.vscode/extensions.json +0 -0
  65. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/.vscode/tasks.json +0 -0
  66. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/LICENSE +0 -0
  67. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/addons/.gitkeep +0 -0
  68. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/addons/godoo_test_succ_mod/__init__.py +0 -0
  69. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/addons/godoo_test_succ_mod/__manifest__.py +0 -0
  70. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/addons/godoo_test_succ_mod/models/__init__.py +0 -0
  71. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/addons/godoo_test_succ_mod/tests/__init__.py +0 -0
  72. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/addons/godoo_test_succ_mod/tests/data.py +0 -0
  73. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/addons/godoo_test_succ_mod/tests/test_succ.py +0 -0
  74. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/assets/odoo_logo.png +0 -0
  75. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/config/nginx.conf.template +0 -0
  76. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/config/postgresql.conf +0 -0
  77. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docker/docker-compose.traefik.yml +0 -0
  78. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docker/postgres-init/10-vector.sql +0 -0
  79. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/docs/architecture.md +0 -0
  80. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/makefile +0 -0
  81. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/odoo_manifest.yml +0 -0
  82. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/package-lock.json +0 -0
  83. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/package.json +0 -0
  84. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/scripts/check_docstring_style.py +0 -0
  85. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/scripts/migrations/development/shrink_database.py +0 -0
  86. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/__init__.py +0 -0
  87. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/__main__.py +0 -0
  88. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/__init__.py +0 -0
  89. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/common.py +0 -0
  90. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/db/__init__.py +0 -0
  91. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/db/cli.py +0 -0
  92. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/db/passwords.py +0 -0
  93. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/db/query.py +0 -0
  94. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/db/reset.py +0 -0
  95. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/odoo_bin/__init__.py +0 -0
  96. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/root.py +0 -0
  97. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/rpc/__init__.py +0 -0
  98. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/rpc/cli.py +0 -0
  99. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/rpc/config_parameters.py +0 -0
  100. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/rpc/modules.py +0 -0
  101. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/rpc/translations.py +0 -0
  102. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/runtime/dependencies.py +0 -0
  103. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/runtime/shell_scripts/odoo_banner.py +0 -0
  104. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/runtime/shell_scripts/render_report.py +0 -0
  105. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/runtime/status.py +0 -0
  106. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/test/__init__.py +0 -0
  107. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/test/cli.py +0 -0
  108. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/upgrade.py +0 -0
  109. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/workspace/__init__.py +0 -0
  110. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/workspace/common.py +0 -0
  111. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/workspace/configure.py +0 -0
  112. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/workspace/image.py +0 -0
  113. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/workspace/storage.py +0 -0
  114. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/commands/workspace/sync.py +0 -0
  115. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/database/__init__.py +0 -0
  116. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/database/connection.py +0 -0
  117. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/database/postgres.py +0 -0
  118. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/database/settings.py +0 -0
  119. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/database/state.py +0 -0
  120. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/git/__init__.py +0 -0
  121. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/git/git_url.py +0 -0
  122. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/git/repository.py +0 -0
  123. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/helpers/__init__.py +0 -0
  124. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/helpers/hashing.py +0 -0
  125. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/helpers/modules_git.py +0 -0
  126. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/helpers/progress.py +0 -0
  127. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/helpers/system.py +0 -0
  128. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/models/__init__.py +0 -0
  129. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/models/godoo_git_repo.py +0 -0
  130. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/models/godoo_manifest.py +0 -0
  131. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/models/godoo_models.py +0 -0
  132. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/models/godoo_modules.py +0 -0
  133. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/__init__.py +0 -0
  134. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/baseline.py +0 -0
  135. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/dataset.py +0 -0
  136. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/filestore.py +0 -0
  137. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/locks.py +0 -0
  138. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/nginx.py +0 -0
  139. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/odoo.py +0 -0
  140. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/runtime/status.py +0 -0
  141. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/__init__.py +0 -0
  142. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/image.py +0 -0
  143. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/manifest.py +0 -0
  144. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/operations.py +0 -0
  145. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/specifications.py +0 -0
  146. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/storage.py +0 -0
  147. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/src/godoo_cli/workspace/types.py +0 -0
  148. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/__init__.py +0 -0
  149. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_db_archive_cli.py +0 -0
  150. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_db_query_cli.py +0 -0
  151. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_odoo_bin_commands.py +0 -0
  152. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_rpc_commands.py +0 -0
  153. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_runtime_dependencies.py +0 -0
  154. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_runtime_shell_scripts.py +0 -0
  155. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_test_run.py +0 -0
  156. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/commands/test_upgrade.py +0 -0
  157. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/database/test_db_query.py +0 -0
  158. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/database/test_db_restore.py +0 -0
  159. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/git/test_git_url_uri.py +0 -0
  160. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_archive_crc.py +0 -0
  161. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_baseline_recovery.py +0 -0
  162. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_database_copy.py +0 -0
  163. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_dataset.py +0 -0
  164. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_filestore.py +0 -0
  165. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_filestore_copy.py +0 -0
  166. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_init_policy.py +0 -0
  167. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_lifecycle_service.py +0 -0
  168. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_nginx.py +0 -0
  169. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_nginx_cli.py +0 -0
  170. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_odoo_config_generation.py +0 -0
  171. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_odoo_preflight.py +0 -0
  172. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_odoo_version_compatibility.py +0 -0
  173. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_report_url.py +0 -0
  174. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_reset_baseline.py +0 -0
  175. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_runtime_models.py +0 -0
  176. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_runtime_operations.py +0 -0
  177. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/runtime/test_runtime_source_environment.py +0 -0
  178. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/test_logging.py +0 -0
  179. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/workspace/test_godoo_manifest.py +0 -0
  180. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/workspace/test_workspace_git.py +0 -0
  181. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/workspace/test_workspace_image.py +0 -0
  182. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/workspace/test_workspace_runtime_env.py +0 -0
  183. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/tests/workspace/test_workspace_storage.py +0 -0
  184. {godoo_cli-1.0.2 → godoo_cli-1.0.4}/thirdparty/.gitkeep +0 -0
@@ -8,10 +8,9 @@ description:
8
8
 
9
9
  Read `docs/workspace.md`, then open the generated `<project>.code-workspace`.
10
10
 
11
- gOdoo sets `python.languageServer` to `None` so the installed Odoo IDE extension provides Python and Odoo analysis
12
- without a competing Pylance server. Keep the Python extension for interpreter selection and debugging. The generated
13
- `python.analysis.extraPaths` covers the resolved project, Odoo, third-party, and archive addon roots. The supported
14
- source mapping is the generated multi-root workspace plus its generated extra paths.
11
+ Keep the Python extension for interpreter selection and debugging. The generated `python.analysis.extraPaths` covers the
12
+ resolved project, Odoo, third-party, and archive addon roots. The supported source mapping is the generated multi-root
13
+ workspace plus its generated extra paths.
15
14
 
16
15
  Reload the window after generation, save representative project, Odoo, and addon files, then inspect VS Code Problems.
17
16
  Confirm each diagnostic refers to the intended selected host worktree. Problems validate editor analysis, not execution.
@@ -28,9 +28,9 @@ environment options, source paths, lifecycle hooks, or generated proxy configura
28
28
  upstream; downstream owns images, Compose, mounts, runtime users, service ordering, and project hooks. Check whether the
29
29
  downstream pin includes the required fix before proposing another implementation.
30
30
 
31
- `runtime init` owns restore, bootstrap, and reconciliation as a one-shot job. `runtime launch` only starts prepared
32
- state. Keep `init` ahead of `app` with `service_completed_successfully`. gOdoo provides no downstream service
33
- orchestration.
31
+ `runtime start` initializes and reconciles explicitly before launching the same target on every app process start. Keep
32
+ maintenance `runtime init` out of ordinary startup; the app depends on a healthy database. `runtime launch` starts
33
+ prepared state only. gOdoo provides no downstream service orchestration.
34
34
 
35
35
  Use the downstream Make/Compose path for authorized runtime validation. Reuse host-resolved workspace paths rather than
36
36
  assembling a substitute container with guessed addon mounts. A pin change needs a rebuilt artifact and, when live
@@ -32,3 +32,7 @@ ODOO_DB_PORT=5432
32
32
  # ODOO_RPC_USER=admin
33
33
  # ODOO_RPC_PASSWORD=admin
34
34
  # ODOO_RPC_DB_NAME=odoo
35
+
36
+ # runtime start reconciles before every server process start, including Docker restart.
37
+ # The first source-baseline run deliberately updates installed source-backed modules.
38
+ GODOO_UPDATE_CHANGED=true
@@ -2,7 +2,7 @@
2
2
  "python.testing.unittestEnabled": false,
3
3
  "python.testing.pytestEnabled": false,
4
4
  "xml.symbols.enabled": false,
5
- "python.languageServer": "Pylance",
5
+ "python.languageServer": "None",
6
6
  "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
7
7
  "ruff.path": ["${workspaceFolder}/.venv/bin/ruff"],
8
8
  "ruff.configurationPreference": "filesystemFirst",
@@ -14,6 +14,24 @@ coherent change.
14
14
  whole-changeset reviews.
15
15
  - Keep shared Docker validation sequential.
16
16
 
17
+ ## Branches and releases
18
+
19
+ - Start each independent change on a short-lived `codex/<topic>` branch from freshly fetched `origin/main`. Do not reuse
20
+ a merged branch for new work. Keep implementation, tests, and documentation for one behavior together.
21
+ - Before switching or creating a branch, inspect staged, unstaged, and untracked work. Preserve existing changes and
22
+ verify the resulting diff against `origin/main`; use a separate Git worktree for concurrent independent work.
23
+ - Open topic PRs into `main` and check Quality results before merging. Topic-branch pushes alone do not trigger Quality.
24
+ Follow the existing merge strategy and commit conventions. Push and merge only within explicit authorization.
25
+ - After merge, return to an updated `main` or start the next topic branch from current `origin/main`. Prune stale remote
26
+ references and remove merged branches only after checking ancestry and worktree ownership; preserve unfinished work.
27
+ - Leave package version changes to `.github/workflows/version-bump.yml`, dispatched against `main` with the chosen bump
28
+ type. It creates `release/<version>` and the release PR; keep that PR limited to preparing the release.
29
+ - Review the release PR description and available Quality results before merging: its description becomes the release
30
+ notes. The release-labeled PR must target `main` and match the title, branch, and version identities documented in
31
+ `.github/workflows/README.md`. Publication uses the release merge commit for PyPI, the tag, and the GitHub Release.
32
+ - Keep release PRs short-lived and coordinate other merges to preserve the intended release scope. Do not use a
33
+ long-lived `release` or `develop` branch for this workflow, or move an existing release tag to repair publication.
34
+
17
35
  ## Code and CLI
18
36
 
19
37
  - Every shell script under `scripts/` has a purpose comment immediately below its shebang.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: gOdoo-cli
3
- Version: 1.0.2
3
+ Version: 1.0.4
4
4
  Summary: Odoo lifecycle, Python dependency preflight, and shared Git workspaces.
5
5
  Project-URL: repository, https://github.com/OpenJKSoftware/gOdoo
6
6
  Author-email: Joshua Kreuder <Joshua_Kreuder@outlook.com>
@@ -10,6 +10,7 @@ Keywords: docker,godoo,odoo,worktree
10
10
  Requires-Python: >=3.11
11
11
  Requires-Dist: gitpython>=3.1.27
12
12
  Requires-Dist: godoo-rpc>=0.1.4
13
+ Requires-Dist: json-with-comments>=1.3.0
13
14
  Requires-Dist: packaging>=21.0
14
15
  Requires-Dist: passlib>=1.7.3
15
16
  Requires-Dist: psycopg2-binary>=2.7.7; sys_platform != 'linux'
@@ -144,19 +145,20 @@ in the Python environment that contains Odoo; gOdoo uses `VIRTUAL_ENV`, otherwis
144
145
  Commands read the project `.env`. **Explicit CLI values → exported environment → project `.env`** is the configuration
145
146
  precedence. Use `godoo --help` or `godoo <command> --help` for the full reference.
146
147
 
147
- ### Prepare once, then launch
148
+ ### Prepare on every server start
148
149
 
149
150
  Initialization prepares the database and matching filestore, checks dependencies, and runs selected module updates and
150
- hooks. Launch starts the prepared runtime. In Compose, the app should depend on the init service completing
151
- successfully.
151
+ hooks. `runtime start` performs this work before launching Odoo on the same target. Use it as the app entrypoint so
152
+ Docker restarts also prepare the runtime; the app depends on a healthy database.
152
153
 
153
154
  ```bash
154
155
  # Run in a configured runtime environment with other Odoo writers stopped.
155
- godoo runtime init && godoo runtime launch
156
+ godoo runtime start --update-changed
156
157
  ```
157
158
 
158
- Use `godoo runtime init --if-needed` for startup that skips reconciliation when the runtime is already ready. For
159
- deployments applying module updates or hooks, use explicit initialization. Inspect state without changing it:
159
+ `--update-changed` selects native upgrades from source hashes; unchanged starts skip upgrades. Explicit maintenance
160
+ `runtime init` and prepared-only `runtime launch` remain available. `runtime init --if-needed` skips all hooks and
161
+ reconciliation on a ready runtime; `runtime start` always initializes explicitly. Inspect state without changing it:
160
162
 
161
163
  ```bash
162
164
  godoo runtime status --json
@@ -109,19 +109,20 @@ in the Python environment that contains Odoo; gOdoo uses `VIRTUAL_ENV`, otherwis
109
109
  Commands read the project `.env`. **Explicit CLI values → exported environment → project `.env`** is the configuration
110
110
  precedence. Use `godoo --help` or `godoo <command> --help` for the full reference.
111
111
 
112
- ### Prepare once, then launch
112
+ ### Prepare on every server start
113
113
 
114
114
  Initialization prepares the database and matching filestore, checks dependencies, and runs selected module updates and
115
- hooks. Launch starts the prepared runtime. In Compose, the app should depend on the init service completing
116
- successfully.
115
+ hooks. `runtime start` performs this work before launching Odoo on the same target. Use it as the app entrypoint so
116
+ Docker restarts also prepare the runtime; the app depends on a healthy database.
117
117
 
118
118
  ```bash
119
119
  # Run in a configured runtime environment with other Odoo writers stopped.
120
- godoo runtime init && godoo runtime launch
120
+ godoo runtime start --update-changed
121
121
  ```
122
122
 
123
- Use `godoo runtime init --if-needed` for startup that skips reconciliation when the runtime is already ready. For
124
- deployments applying module updates or hooks, use explicit initialization. Inspect state without changing it:
123
+ `--update-changed` selects native upgrades from source hashes; unchanged starts skip upgrades. Explicit maintenance
124
+ `runtime init` and prepared-only `runtime launch` remain available. `runtime init --if-needed` skips all hooks and
125
+ reconciliation on a ready runtime; `runtime start` always initializes explicitly. Inspect state without changing it:
125
126
 
126
127
  ```bash
127
128
  godoo runtime status --json
@@ -48,7 +48,7 @@ RUN --mount=type=cache,target=/root/.cache/uv,sharing=locked \
48
48
  && chown -R odoo:odoo "$VIRTUAL_ENV"
49
49
  WORKDIR /odoo/godoo_workspace
50
50
  USER odoo
51
- CMD ["python", "-m", "godoo_cli", "runtime", "launch"]
51
+ CMD ["python", "-m", "godoo_cli", "runtime", "start"]
52
52
 
53
53
  # Materialize selected sources from read-only mounts without Git commands or worktree scans.
54
54
  FROM dependencies AS materialized
@@ -86,4 +86,4 @@ RUN --mount=type=cache,target=/root/.cache/uv,sharing=locked \
86
86
  COPY --from=materialized --chown=odoo:odoo /image/odoo/ /odoo/
87
87
  WORKDIR /odoo/godoo_workspace
88
88
  USER odoo
89
- CMD ["godoo", "runtime", "launch"]
89
+ CMD ["godoo", "runtime", "start"]
@@ -23,6 +23,9 @@ x-runtime: &runtime
23
23
  ODOO_WORKSPACE_ADDON_LOCATION: ${ODOO_WORKSPACE_ADDON_LOCATION:-/odoo/godoo_workspace/addons}
24
24
  ODOO_CONF_PATH: ${ODOO_CONF_PATH:-/odoo/config/odoo.conf}
25
25
  GODOO_RUNTIME_SEED: "${GODOO_RUNTIME_SEED:-}"
26
+ GODOO_UPDATE_CHANGED: ${GODOO_UPDATE_CHANGED:-true}
27
+ GODOO_RECONCILE_UPDATE: "${GODOO_RECONCILE_UPDATE:-}"
28
+ GODOO_RECONCILE_INSTALL: "${GODOO_RECONCILE_INSTALL:-}"
26
29
  GODOO_X_SENDFILE: ${GODOO_X_SENDFILE:-true}
27
30
  GODOO_HOOK_DIRS: "${GODOO_HOOK_DIRS:-}"
28
31
  GODOO_ENVIRONMENT: "${GODOO_ENVIRONMENT:-}"
@@ -37,16 +40,17 @@ x-runtime: &runtime
37
40
  services:
38
41
  init:
39
42
  <<: *runtime
43
+ profiles: [maintenance]
40
44
  command: [godoo, runtime, init]
41
45
  depends_on:
42
46
  db:
43
47
  condition: service_healthy
44
48
  app:
45
49
  <<: *runtime
46
- command: [godoo, runtime, launch, "--extra-args=${ODOO_BIN_ARGS:+${ODOO_BIN_ARGS} }--proxy-mode"]
50
+ command: [godoo, runtime, start, "--extra-args=${ODOO_BIN_ARGS:+${ODOO_BIN_ARGS} }--proxy-mode"]
47
51
  depends_on:
48
- init:
49
- condition: service_completed_successfully
52
+ db:
53
+ condition: service_healthy
50
54
  nginx:
51
55
  build:
52
56
  context: ..
@@ -28,7 +28,7 @@ services:
28
28
  -m,
29
29
  godoo_cli,
30
30
  runtime,
31
- launch,
31
+ start,
32
32
  "--extra-args=${ODOO_BIN_ARGS:+${ODOO_BIN_ARGS} }--workers=0 --proxy-mode",
33
33
  ]
34
34
  volumes:
@@ -39,6 +39,7 @@ services:
39
39
  GODOO_RUNTIME_ODOO_PATH: ${GODOO_RUNTIME_ODOO_PATH}
40
40
  GODOO_RUNTIME_ADDON_PATHS: ${GODOO_RUNTIME_ADDON_PATHS}
41
41
  GODOO_DEV_MODE: "1"
42
+ GODOO_KEEP_RESET_BASELINE: ${GODOO_KEEP_RESET_BASELINE:-true}
42
43
  ODOO_MANIFEST: /odoo/godoo_workspace/odoo_manifest.yml
43
44
  PYTHONPATH: /odoo/godoo_workspace/src
44
45
 
@@ -8,16 +8,15 @@ database topology is a same-host PostgreSQL sidecar on an isolated Compose netwo
8
8
 
9
9
  ## Service and ownership boundaries
10
10
 
11
- This diagram shows **Compose startup dependencies**, not HTTP traffic. A failed database healthcheck or init job
12
- prevents the dependent app from starting. “App service started” is a Compose state, not proof of HTTP readiness. The
13
- [HTTP and file delivery](#http-and-file-delivery) section describes request routing.
11
+ This diagram shows **Compose startup dependencies**, not HTTP traffic. A failed database healthcheck prevents app
12
+ startup; failed preparation makes the app exit before it serves. “App service started” is a Compose state, not proof of
13
+ HTTP readiness. The [HTTP and file delivery](#http-and-file-delivery) section describes request routing.
14
14
 
15
15
  ```mermaid
16
16
  flowchart TD
17
17
  Compose["Operator runs downstream Docker Compose"]
18
18
  Compose --> DB["Compose starts db<br/>and waits for PostgreSQL's healthcheck"]
19
- DB -->|database healthy| Init["Compose runs init<br/>godoo runtime init prepares the database and filestore"]
20
- Init -->|init exits with code 0| App["Compose starts app<br/>godoo runtime launch starts Odoo"]
19
+ DB -->|database healthy| App["Compose starts app<br/>godoo runtime start prepares, then serves"]
21
20
  App -->|app service started| Nginx["Compose starts nginx<br/>HTTP ingress becomes available"]
22
21
  ```
23
22
 
@@ -61,22 +60,32 @@ healthcheck from [the base Compose file](../docker/docker-compose.base.yml).
61
60
 
62
61
  ```yaml
63
62
  services:
64
- init:
65
- command: [godoo, runtime, init] # One-shot preparation, not a daemon.
63
+ app:
64
+ command: [godoo, runtime, start]
65
+ environment:
66
+ GODOO_UPDATE_CHANGED: "true"
66
67
  depends_on:
67
68
  db:
68
69
  condition: service_healthy
69
70
 
70
- app:
71
- command: [godoo, runtime, launch] # Launch only prepared state.
71
+ init:
72
+ profiles: [maintenance]
73
+ command: [godoo, runtime, init] # Explicit maintenance, excluded from ordinary startup.
72
74
  depends_on:
73
- init:
74
- condition: service_completed_successfully
75
+ db:
76
+ condition: service_healthy
75
77
  ```
76
78
 
77
- Use `GODOO_INIT_IF_EMPTY=true` for startup that skips a ready runtime. Keep it false, or pass `--no-if-needed`, for
78
- deployment jobs that reconcile modules and hooks. Demo mode ignores configured restore inputs and rejects an explicit
79
- seed. All processes managing the pair must share the same data directory.
79
+ The app owns initialization on every process start, including Docker restarts. Give it all restore dataset mounts and
80
+ settings previously provided to init; seed datasets should be read-only. Stop existing Odoo writers before deployment or
81
+ maintenance initialization. The supported scope is one app service, not concurrent replicas writing the same runtime.
82
+ Use routed HTTP readiness after app startup; a running or restarting container does not prove initialization succeeded.
83
+
84
+ `runtime start` always reconciles and ignores `GODOO_INIT_IF_EMPTY`. That variable still controls standalone
85
+ `runtime init`. Demo mode ignores configured datasets and rejects an explicit seed. All pair operations share the same
86
+ data directory. For maintenance, `docker compose run --rm init` explicitly selects the profiled service. Do not also
87
+ start it through an ordinary deployment service list. Use `runtime launch` only when preparation is deliberately owned
88
+ by a separate caller.
80
89
 
81
90
  ## PostgreSQL
82
91
 
@@ -18,7 +18,7 @@ Ordinary restores and major upgrades share the same initialization flow.
18
18
 
19
19
  Native migration versions must be above the installed version and at or below the manifest version. Fresh installs need
20
20
  their own install behavior. There is no transition directory, version-pair selector, implicit module list, or hook
21
- completion ledger.
21
+ implicit migration scheduler. Ordinary database hooks can opt into transactional one-shot completion with `once=True`.
22
22
 
23
23
  ## Discover and select hooks
24
24
 
@@ -49,6 +49,7 @@ actual boolean. A missing predicate runs whenever eligible; an exception fails i
49
49
  | `phase` | `prepare`, `after_bootstrap`, `after_restore`, or `after_reconcile`. |
50
50
  | `on` | Tuple of `ready`, `bootstrapped`, and/or `restored`; defaults to all. Custom outcome filters are invalid for preparation. |
51
51
  | `environments` | Optional tuple of exact `GODOO_ENVIRONMENT` values. Omitted means unrestricted; an allowlist never matches an unset environment. |
52
+ | `once` | Optional boolean, default false. Record successful database-hook completion; preparation hooks cannot use it. |
52
53
 
53
54
  Environment is a deployment input, never inferred from database contents.
54
55
 
@@ -101,8 +102,9 @@ Database contexts expose `ctx.env`, `ctx.environment`, and the original `ctx.out
101
102
  lifecycle markers as an API, rebuild the registry, or perform immediate module installs/updates. Module loading belongs
102
103
  in native reconciliation.
103
104
 
104
- An eligible `after_restore` database hook conflicts with native pre-upgrade scripts because it would open the registry
105
- first. The combination is rejected before mutation. Put post-upgrade environment setup in `after_reconcile`.
105
+ An eligible `after_restore` database hook conflicts with selected native pre-upgrade scripts because it would open the
106
+ registry first. `--update-changed` requires database hooks to use `after_reconcile`; it rejects eligible `after_restore`
107
+ and `after_bootstrap` declarations rather than changing their order. Put post-upgrade setup in `after_reconcile`.
106
108
 
107
109
  ## Execution and transaction boundaries
108
110
 
@@ -147,8 +149,20 @@ already satisfied, running, completed, or failed. Do not log passwords or comple
147
149
 
148
150
  ## Idempotence and recovery
149
151
 
150
- Hooks run **at least once**. There is no `once=True`, file-hash cache, or generic success ledger. `on=("restored",)`
151
- means eligible during restore initialization and its retries, rather than exactly one execution.
152
+ Ordinary hooks run whenever eligible, subject to `needs_run`. `on=("restored",)` selects restore initialization and its
153
+ retries; it is not a completion record.
154
+
155
+ Use `Hook(id="project.repair.2026_10", phase="after_reconcile", once=True)` for a transactional one-shot repair. IDs are
156
+ immutable: use a new ID for a new repair. The runner stores completion in `ir_config_parameter` under
157
+ `godoo.hooks.once.<identity-hash>`, in the same transaction as the action. Unrestricted hooks complete globally in that
158
+ database; environment-restricted hooks complete separately for each selected environment. Restores and baseline resets
159
+ carry or rewind the records with the database. Declaration filters still apply, and duplicate IDs remain invalid.
160
+
161
+ Completed hooks skip `needs_run`. A false predicate means the desired state is already satisfied and records completion
162
+ atomically without running the action. An exception rolls back the action and its completion record. A later hook's
163
+ failure preserves earlier committed repairs. Hooks that commit internally or change external systems still need their
164
+ own idempotency: the runner cannot promise exactly-once external effects. Keep recurring environment policy repeatable,
165
+ with state predicates, so ordinary drift is repaired after every controlled start.
152
166
 
153
167
  | Attempt | Outcome visible to hooks |
154
168
  | ---------------------------------------------- | ----------------------------------------------------------------------------------- |
@@ -8,6 +8,39 @@ hooks, then launch Odoo. Runtime commands require Odoo 16 or newer.
8
8
  Stop ordinary Odoo writers before initialization, restore, clone, or replacement. gOdoo locks coordinate gOdoo
9
9
  operations; they do not stop ordinary Odoo writes.
10
10
 
11
+ ## Back up a live runtime
12
+
13
+ ```bash
14
+ # Default: one combined ZIP, including attachments.
15
+ godoo db backup /backups/runtime.zip --db-name odoo
16
+
17
+ # PostgreSQL custom format plus a separate filestore, copied with rsync.
18
+ godoo db backup /backups/current --db-name odoo --format dump
19
+ ```
20
+
21
+ `--format` accepts `zip` (default) or `dump`; `GODOO_BACKUP_FORMAT` supplies the environment default. Both formats
22
+ capture the database first, then the filestore. The `dump` destination contains `odoo.dump` and
23
+ `odoo_filestore/filestore/<database>/`, directly usable by `godoo runtime init --dump-path` or
24
+ `godoo db restore <directory> --force`. It requires `pg_dump` and `rsync` in the execution environment. The destination
25
+ must be outside Odoo's data directory. Borg or another backup system owns history; each successful run replaces the
26
+ selected destination.
27
+
28
+ During capture, gOdoo holds a row lock on `base.autovacuum_job`. Odoo's scheduler skips that internal cleanup job;
29
+ users, attachment writes, integrations, and other background jobs continue. No app restart or attachment-table write
30
+ lock is needed. The lock is released on completion or connection closure. If cleanup is already running, backup fails
31
+ immediately so it can be retried afterward. The backup fails if the guard connection is lost before publication.
32
+
33
+ This protects standard Odoo filestore storage and scheduled cleanup on Odoo 16 and newer, including Odoo 19's manual
34
+ scheduled-action trigger. Do not run private cleanup methods, custom file deletion, attachment storage migration, or
35
+ Odoo 16–18 manual autovacuum during backup. External attachment backends need their own backup procedure. Files added
36
+ after the database snapshot may also be copied; they are harmless extra files, not additional database records.
37
+
38
+ Backups are staged before replacing the previous result. Directory destinations must be dedicated child directories
39
+ inside a mounted backup volume, not the mount root itself. Replacing a directory briefly renames the previous pair to
40
+ `.<destination-name>.previous`; failed promotion restores it. After an abrupt termination, inspect that directory and
41
+ the destination before retrying. gOdoo refuses to overwrite a retained previous pair. Start Borg only after this command
42
+ succeeds, and keep other backup readers out of the brief directory promotion window.
43
+
11
44
  ## Initialize and launch
12
45
 
13
46
  Run in the configured downstream runtime environment. CLI values override exported environment values, then the project
@@ -16,44 +49,79 @@ Run in the configured downstream runtime environment. CLI values override export
16
49
  ```bash
17
50
  # Prepare and reconcile explicitly, including on an already ready database.
18
51
  # Other Odoo writers must be stopped.
19
- godoo runtime init && godoo runtime launch
52
+ godoo runtime start --update-changed
20
53
 
21
- # For ordinary startup, skip initialization when the runtime is already ready.
54
+ # Optional maintenance policy: skip all hooks and reconciliation on a ready runtime.
22
55
  godoo runtime init --if-needed && godoo runtime launch
23
56
 
24
57
  # Inspect state without changing the runtime.
25
58
  godoo runtime status --json
26
59
  ```
27
60
 
28
- These are alternative startup policies. Set `GODOO_INIT_IF_EMPTY=true` for conditional startup; use `--no-if-needed` to
29
- override it for deployment jobs that must apply updates or hooks. Conditional init prints the same JSON payload as
61
+ `runtime start` uses the existing init and launch options, resolves one target, and always initializes explicitly before
62
+ serving. It ignores `GODOO_INIT_IF_EMPTY` and has no `--if-needed` option. Bootstrap arguments apply only to
63
+ initialization; server/debugger arguments apply only to launch. Failed initialization returns nonzero without launching,
64
+ and lifecycle locks are released before the server lifetime.
65
+
66
+ For separate maintenance commands, set `GODOO_INIT_IF_EMPTY=true` for conditional init; use `--no-if-needed` to override
67
+ it for deployment jobs that must apply updates or hooks. Conditional init prints the same JSON payload as
30
68
  `runtime status --json` and checks readiness before loading datasets, hooks, or Odoo.
31
69
 
32
70
  The diagram below starts when initialization is required or explicitly requested. A ready runtime skipped by
33
71
  `--if-needed` exits before this work. Each arrow means the preceding step succeeded; failures stop initialization.
34
- Launching the server is a separate caller action. The bootstrap/restore branches show first initialization; recovery
35
- retries rerun hooks for the original outcome, as described under
72
+ `runtime start` launches after this work succeeds; `runtime init` exits without serving. The bootstrap/restore branches
73
+ show first initialization; recovery retries rerun hooks for the original outcome, as described under
36
74
  [incomplete initialization](#incomplete-initialization).
37
75
 
38
76
  ```mermaid
39
77
  flowchart TD
40
- Prepare["gOdoo: run prepare hooks<br/>and check known dependencies"] --> State{"State of the target<br/>database and filestore?"}
41
- State -->|ready| Reconcile["Odoo: install or update selected modules<br/>and run eligible native migrations"]
42
- State -->|missing or empty| Seed{"Backup or dataset<br/>selected for restore?"}
43
- State -->|inconsistent| Stop["Stop initialization<br/>Operator must recover a matching database and filestore"]
44
- Seed -->|yes| Restore["gOdoo: restore the selected backup<br/>and its matching attachments"]
45
- Seed -->|no| Bootstrap["Odoo: create a new database"]
46
- Restore --> Restored["gOdoo: run eligible after_restore hooks"]
47
- Bootstrap --> Bootstrapped["gOdoo: run eligible after_bootstrap hooks"]
48
- Restored --> Reconcile
49
- Bootstrapped --> Reconcile
50
- Reconcile --> Finalize["gOdoo: run eligible after_reconcile hooks"]
51
- Finalize --> Ready["gOdoo: mark initialization complete<br/>and exit successfully"]
52
- Ready -->|caller runs a separate command| Launch["godoo runtime launch<br/>Start the prepared Odoo server"]
78
+ Prepare["Prepare hooks and dependency preflight"] --> State{"Database and filestore state"}
79
+ State -->|ready| Plan["Registry-free source selection when enabled"]
80
+ State -->|missing or empty| Seed{"Seed selected?"}
81
+ State -->|inconsistent| Stop["Stop; recover a matching pair"]
82
+ Seed -->|yes| Restore["Restore backup and matching attachments"]
83
+ Seed -->|no| Bootstrap["Native Odoo bootstrap"]
84
+ Restore --> Plan
85
+ Bootstrap --> Plan
86
+ Plan --> OutcomeHooks["Eligible after_restore / after_bootstrap hooks<br/>Legacy ordering; excluded with update-changed"]
87
+ OutcomeHooks --> Reconcile["Native module reconciliation"]
88
+ Reconcile --> Baseline["Verify and save the planned source baseline when enabled"]
89
+ Baseline --> Finalize["Eligible after_reconcile hooks"]
90
+ Finalize --> Ready["Clear pending lifecycle state"]
91
+ Ready --> Launch["runtime start launches Odoo<br/>runtime init exits"]
53
92
  ```
54
93
 
55
- Init is a one-shot job. In Compose, launch depends on init's `service_completed_successfully`; gOdoo does not start
56
- downstream services itself.
94
+ Use `runtime start` as the app entrypoint so Docker restarts also prepare the runtime. Keep `runtime init` as explicit
95
+ maintenance tooling; do not also run a second init service during ordinary startup. gOdoo does not start downstream
96
+ services itself.
97
+
98
+ ### Source-driven native reconciliation
99
+
100
+ `--update-changed` or `GODOO_UPDATE_CHANGED=true` selects source changes without loading an Odoo registry. Under the
101
+ runtime lock, after restore/bootstrap and before database hooks, gOdoo reads installed and pending module state and
102
+ compares source snapshots. A missing baseline deliberately upgrades installed source-backed modules once. Later
103
+ unchanged starts request no native updates. Explicit `--update` selections remain explicit; desired installs already
104
+ installed or queued for upgrade are filtered out. Native Odoo expands upgrade dependents and installs new dependencies.
105
+ Pending install/upgrade states are included; pending removals need a selected native action or initialization fails.
106
+
107
+ The independent `godoo.runtime.source_checksums.v1` parameter stores JSON `{"format": 1, "modules": {name: sha256}}`.
108
+ Hashes include deterministic relative filenames and content, all translations regardless of active languages, and core
109
+ Python package sources as part of `base`. Tests, static assets, Git metadata, Python bytecode, and editor swap files are
110
+ excluded. Installed, pending, and requested addons plus their source dependencies are snapshotted before native work. If
111
+ that set can introduce installs, potential auto-install addons and their dependencies are captured too. Unrelated
112
+ ordinary addons are not hashed unless the caller explicitly selects `all`. Imported addons and pathless Studio
113
+ customization are not source modules. Corrupt baseline data fails visibly.
114
+
115
+ Missing installed sources may be deferred only when a selected native update will run configured pre-upgrade cleanup.
116
+ They must be removed or repaired before a strict post-native rescan. Other missing sources fail initialization. Valid
117
+ native upgrade paths can remain configured without forcing an update; pre-upgrade scripts run only with native update
118
+ selections. These settings are dormant on unchanged starts.
119
+
120
+ Only a successful native process with no unfinished module states can advance the baseline. gOdoo verifies final
121
+ installed sources against the snapshot taken before native work and saves that snapshot before post-hooks. Source drift
122
+ or failed native work leaves the old baseline; failed post-hooks retain the successful baseline and earlier completed
123
+ one-shot hooks. The pending lifecycle marker remains until all phases succeed. Native Odoo can commit partial work; this
124
+ is not an atomic module-upgrade guarantee. See the native migration recovery limits in [Hooks](hooks.md).
57
125
 
58
126
  Backups use native Odoo commands on Odoo 19 or newer and PostgreSQL tools on Odoo 16–18.
59
127
 
@@ -267,7 +335,9 @@ make dev
267
335
 
268
336
  `godoo db reset` performs the pair operation; callers must stop writers first. `--db-template` selects another database
269
337
  with its matching filestore; `--empty` retains drop-only behavior. Reset copies the database and uses rsync to delete
270
- filestore files absent from the baseline. PostgreSQL's faster copy method is used when available.
338
+ filestore files absent from the baseline. PostgreSQL's faster copy method is used when available. At default verbosity,
339
+ reset logs lock waiting, baseline checks, database and filestore operations, lifecycle updates, and successful
340
+ completion. `--empty` logs database removal and filestore cleanup too.
271
341
 
272
342
  An interrupted reset can leave an incomplete active filestore: its marker blocks init, so rerun reset. A missing or
273
343
  incomplete baseline needs a fresh restore. The next init reruns restore hooks, native reconciliation, and final hooks.
@@ -90,18 +90,23 @@ make typecheck
90
90
  ```
91
91
 
92
92
  Open `godoo.code-workspace` for this repository, or the generated `<project>.code-workspace` downstream. Opening the
93
- same files in another project's window does not load their workspace settings.
93
+ same files in another project's window does not load their workspace settings. The generated workspace copies settings
94
+ from the project's `.vscode/settings.json`, including JSON comments and trailing commas. Set fixed editor preferences
95
+ there, including the interpreter, language server, and test discovery. gOdoo generates `python.analysis.extraPaths` from
96
+ the selected sources and takes precedence for that setting in the generated workspace. Run `workspace configure` after
97
+ changing project settings; `workspace check` reports the workspace as stale until it is regenerated. Projects without
98
+ those fixed settings inherit their VS Code defaults or other configured values.
94
99
 
95
100
  | Generated setting | Contract |
96
101
  | -------------------- | ---------------------------------------------------------------------------------------------------------- |
97
102
  | Workspace folder | Fixed name `gOdoo`; project-relative paths use `${workspaceFolder:gOdoo}`. |
98
103
  | Selected sources | Odoo, addon, and archive paths remain absolute host paths. |
99
- | Python analysis | The Python extension's language server is disabled so Odoo IDE can provide Python and Odoo analysis. |
100
- | Python extension | Keep it installed for interpreter selection and debugging. |
101
104
  | Extra paths | `python.analysis.extraPaths` includes the selected sources. |
102
105
  | `gOdoo: attach` | Maps the project to `/odoo/godoo_workspace` and the selected sources to their development-container paths. |
103
106
  | `pyrightconfig.json` | Ignored project-root file covering `src/`, `addons/`, `scripts/`, project addons, and resolved sources. |
104
107
 
108
+ Keep the Python extension for interpreter selection and debugging.
109
+
105
110
  Python uses Ruff for formatting and safe fixes on save, with lint rules from `pyproject.toml`, including C901. Supported
106
111
  text formats use Prettier and `.prettierrc.yml`.
107
112
 
@@ -27,6 +27,7 @@ dependencies = [
27
27
  "packaging>=21.0",
28
28
  "typer-common-functions>=0.1.0",
29
29
  "typer>=0.9.0",
30
+ "json-with-comments>=1.3.0",
30
31
  ]
31
32
 
32
33
  [project.optional-dependencies]
@@ -168,6 +169,7 @@ disable = [
168
169
  "wrong-import-order", # Handled by isort
169
170
  ]
170
171
  enable = [
172
+ "too-many-arguments", # R0913; annotate justified public signatures locally.
171
173
  "eval-used",
172
174
  "license-allowed",
173
175
  "manifest-required-author",
@@ -1,3 +1,3 @@
1
1
  """Version information."""
2
2
 
3
- __version__ = "1.0.2"
3
+ __version__ = "1.0.4"
@@ -15,6 +15,8 @@ from ..workspace.types import ResolvedSource
15
15
  LOGGER = logging.getLogger(__name__)
16
16
 
17
17
 
18
+ # Resolve distinct CLI, config, and argv inputs before constructing GodooConfig; override precedence stays explicit.
19
+ # pylint: disable-next=too-many-arguments
18
20
  def resolve_command_config(
19
21
  *,
20
22
  odoo_main_path: Path,
@@ -15,6 +15,7 @@ from ...runtime.archive import (
15
15
  load_runtime_archive,
16
16
  prepare_archive_with_original_filestore,
17
17
  )
18
+ from ...runtime.backup import BackupFormat
18
19
  from ...runtime.odoo import SUPPORTED_ODOO_VERSION_SPECIFIER
19
20
  from ..common import CommonCLI
20
21
  from ..configuration import require_cli_odoo_version, resolve_development_odoo_main_path
@@ -29,27 +30,37 @@ def dump_database(
29
30
  odoo_main_path: Annotated[Path, CLI.odoo_paths.bin_path],
30
31
  odoo_conf_path: Annotated[Path | None, CLI.odoo_paths.conf_path] = None,
31
32
  data_dir: Annotated[Path, CLI.odoo_paths.data_dir] = Path("/var/lib/odoo"),
33
+ backup_format: Annotated[
34
+ BackupFormat,
35
+ typer.Option(
36
+ "--format",
37
+ envvar="GODOO_BACKUP_FORMAT",
38
+ help="zip: combined archive; dump: custom PostgreSQL dump and rsync filestore directory.",
39
+ ),
40
+ ] = BackupFormat.ZIP,
32
41
  ) -> int:
33
- """Create an Odoo runtime archive."""
42
+ """Back up a live Odoo database and its filestore in the selected format."""
34
43
  try:
35
44
  odoo_main_path = resolve_development_odoo_main_path(odoo_main_path)
36
45
  version = require_cli_odoo_version(odoo_main_path, SUPPORTED_ODOO_VERSION_SPECIFIER)
37
- return CLI.returner(
38
- dump_runtime_archive(
39
- db_name=db_name,
40
- archive_path=archive_path,
41
- odoo_bin_path=odoo_main_path / "odoo-bin",
42
- odoo_conf_path=odoo_conf_path,
43
- data_dir=data_dir,
44
- odoo_version=version.major,
45
- connection=DBConnection.from_odoo_config(db_name, odoo_conf_path),
46
- )
46
+ result = dump_runtime_archive(
47
+ db_name=db_name,
48
+ backup_format=backup_format,
49
+ archive_path=archive_path,
50
+ odoo_bin_path=odoo_main_path / "odoo-bin",
51
+ odoo_conf_path=odoo_conf_path,
52
+ data_dir=data_dir,
53
+ odoo_version=version.major,
54
+ connection=DBConnection.from_odoo_config(db_name, odoo_conf_path),
47
55
  )
48
- except OSError:
56
+ except (OSError, RuntimeError, ValueError, psycopg2.Error):
49
57
  LOGGER.exception("Archive creation failed")
50
58
  return CLI.returner(1)
59
+ return CLI.returner(result)
51
60
 
52
61
 
62
+ # Typer declares each archive-restore option in this public callback signature.
63
+ # pylint: disable-next=too-many-arguments
53
64
  def load_database(
54
65
  db_name: Annotated[str, CLI.database.db_name],
55
66
  archive_path: Annotated[Path, typer.Argument()],
@@ -14,6 +14,8 @@ CLI = CommonCLI()
14
14
  LOGGER = logging.getLogger(__name__)
15
15
 
16
16
 
17
+ # Typer declares each RPC import option in this public callback signature.
18
+ # pylint: disable-next=too-many-arguments
17
19
  def import_to_odoo(
18
20
  read_paths: Annotated[
19
21
  list[Path],