kanibako-cli 1.6.0.dev26__tar.gz → 1.6.0.dev30__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 (177) hide show
  1. {kanibako_cli-1.6.0.dev26/src/kanibako_cli.egg-info → kanibako_cli-1.6.0.dev30}/PKG-INFO +1 -1
  2. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/pyproject.toml +1 -1
  3. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/__init__.py +1 -1
  4. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/templates.py +34 -13
  5. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30/src/kanibako_cli.egg-info}/PKG-INFO +1 -1
  6. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_templates.py +64 -0
  7. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/LICENSE.md +0 -0
  8. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/README.md +0 -0
  9. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/setup.cfg +0 -0
  10. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/__main__.py +0 -0
  11. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/_atomic.py +0 -0
  12. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/agent_config.py +0 -0
  13. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/auth_browser.py +0 -0
  14. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/auth_parser.py +0 -0
  15. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/baseline.py +0 -0
  16. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/box_identity.py +0 -0
  17. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/browser_sidecar.py +0 -0
  18. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/browser_state.py +0 -0
  19. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/bun_sea.py +0 -0
  20. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/channels.py +0 -0
  21. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/cli.py +0 -0
  22. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/__init__.py +0 -0
  23. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/agent_cmd.py +0 -0
  24. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/archive.py +0 -0
  25. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/baseline_cmd.py +0 -0
  26. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/box/__init__.py +0 -0
  27. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/box/_duplicate.py +0 -0
  28. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/box/_lifecycle.py +0 -0
  29. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/box/_parser.py +0 -0
  30. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/clean.py +0 -0
  31. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/diagnose.py +0 -0
  32. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/flags.py +0 -0
  33. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/fork_cmd.py +0 -0
  34. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/helper_cmd.py +0 -0
  35. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/image.py +0 -0
  36. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/install.py +0 -0
  37. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/restore.py +0 -0
  38. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/setup_cmd.py +0 -0
  39. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/start.py +0 -0
  40. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/stop.py +0 -0
  41. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/system_cmd.py +0 -0
  42. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/upgrade.py +0 -0
  43. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/vault_cmd.py +0 -0
  44. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/commands/workset_cmd.py +0 -0
  45. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/config.py +0 -0
  46. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/config_interface.py +0 -0
  47. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/config_io.py +0 -0
  48. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/container.py +0 -0
  49. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/containerfiles.py +0 -0
  50. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/containers/Containerfile.template-android +0 -0
  51. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/containers/Containerfile.template-dotnet +0 -0
  52. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/containers/Containerfile.template-js +0 -0
  53. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/containers/Containerfile.template-jvm +0 -0
  54. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/containers/Containerfile.template-systems +0 -0
  55. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/containers/__init__.py +0 -0
  56. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/containers/tmux.conf +0 -0
  57. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/data/__init__.py +0 -0
  58. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/data/image-baseline.yaml +0 -0
  59. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/data/templates/base/INSTRUCTIONS.md +0 -0
  60. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/deprecation.py +0 -0
  61. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/errors.py +0 -0
  62. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/freshness.py +0 -0
  63. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/git.py +0 -0
  64. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/helper_client.py +0 -0
  65. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/helper_listener.py +0 -0
  66. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/helpers.py +0 -0
  67. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/hygiene.py +0 -0
  68. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/image_sharing.py +0 -0
  69. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/import_reconcile.py +0 -0
  70. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/install_method.py +0 -0
  71. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/log.py +0 -0
  72. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/names.py +0 -0
  73. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/paths.py +0 -0
  74. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/plugins/__init__.py +0 -0
  75. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/py.typed +0 -0
  76. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/registry.py +0 -0
  77. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/registry_store.py +0 -0
  78. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/rig_bundle.py +0 -0
  79. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/rig_meta.py +0 -0
  80. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/rig_registry.py +0 -0
  81. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/rig_resolve.py +0 -0
  82. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/rig_source.py +0 -0
  83. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/scripts/__init__.py +0 -0
  84. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/scripts/helper-init.sh +0 -0
  85. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/scripts/kanibako-entry +0 -0
  86. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/settings_categories.py +0 -0
  87. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/settings_resolve.py +0 -0
  88. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/settings_seeds.py +0 -0
  89. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/settings_shares.py +0 -0
  90. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/shellenv.py +0 -0
  91. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/shells.py +0 -0
  92. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/snapshots.py +0 -0
  93. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/targets/__init__.py +0 -0
  94. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/targets/assembly.py +0 -0
  95. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/targets/base.py +0 -0
  96. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/targets/credsync.py +0 -0
  97. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/targets/no_agent.py +0 -0
  98. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/templates_image.py +0 -0
  99. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/tweakcc.py +0 -0
  100. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/tweakcc_cache.py +0 -0
  101. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/utils.py +0 -0
  102. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako/workset.py +0 -0
  103. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako_cli.egg-info/SOURCES.txt +0 -0
  104. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako_cli.egg-info/dependency_links.txt +0 -0
  105. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako_cli.egg-info/entry_points.txt +0 -0
  106. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako_cli.egg-info/requires.txt +0 -0
  107. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/src/kanibako_cli.egg-info/top_level.txt +0 -0
  108. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_agent_config.py +0 -0
  109. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_agent_resolution.py +0 -0
  110. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_archive_restore_integration.py +0 -0
  111. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_atomic.py +0 -0
  112. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_auth_browser.py +0 -0
  113. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_auth_parser.py +0 -0
  114. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_baseline.py +0 -0
  115. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_box_identity.py +0 -0
  116. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_browser_sidecar.py +0 -0
  117. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_browser_state.py +0 -0
  118. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_bun_sea.py +0 -0
  119. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_channels.py +0 -0
  120. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_cli.py +0 -0
  121. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_cli_exitcodes.py +0 -0
  122. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_comms.py +0 -0
  123. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_config.py +0 -0
  124. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_config_interface.py +0 -0
  125. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_container.py +0 -0
  126. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_container_extended.py +0 -0
  127. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_container_integration.py +0 -0
  128. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_containerfiles.py +0 -0
  129. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_credentials.py +0 -0
  130. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_deprecations.py +0 -0
  131. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_env_cmd.py +0 -0
  132. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_error_messages.py +0 -0
  133. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_fork.py +0 -0
  134. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_freshness.py +0 -0
  135. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_git.py +0 -0
  136. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_helper_client.py +0 -0
  137. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_helper_cmd.py +0 -0
  138. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_helper_listener.py +0 -0
  139. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_helpers.py +0 -0
  140. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_hygiene.py +0 -0
  141. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_image_sharing.py +0 -0
  142. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_import.py +0 -0
  143. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_init_cmd.py +0 -0
  144. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_install_integration.py +0 -0
  145. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_lifecycle_integration.py +0 -0
  146. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_log.py +0 -0
  147. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_names.py +0 -0
  148. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_paths.py +0 -0
  149. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_paths_extended.py +0 -0
  150. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_registry.py +0 -0
  151. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_registry_store.py +0 -0
  152. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_resolve_box_target.py +0 -0
  153. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_resource_scoping.py +0 -0
  154. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_rig_bundle.py +0 -0
  155. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_rig_meta.py +0 -0
  156. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_rig_registry.py +0 -0
  157. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_rig_resolve.py +0 -0
  158. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_rig_source.py +0 -0
  159. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_safety_invariants.py +0 -0
  160. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_settings_categories.py +0 -0
  161. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_settings_loader.py +0 -0
  162. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_settings_resolve.py +0 -0
  163. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_settings_seeds.py +0 -0
  164. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_settings_shares.py +0 -0
  165. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_setup_cmd.py +0 -0
  166. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_shellenv.py +0 -0
  167. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_shells.py +0 -0
  168. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_snapshots.py +0 -0
  169. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_standalone_paths.py +0 -0
  170. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_start_integration.py +0 -0
  171. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_status.py +0 -0
  172. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_system_paths.py +0 -0
  173. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_templates_image.py +0 -0
  174. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_tweakcc.py +0 -0
  175. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_utils.py +0 -0
  176. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_workset.py +0 -0
  177. {kanibako_cli-1.6.0.dev26 → kanibako_cli-1.6.0.dev30}/tests/test_workset_paths.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kanibako-cli
3
- Version: 1.6.0.dev26
3
+ Version: 1.6.0.dev30
4
4
  Summary: Run AI coding agents in rootless containers with per-project isolation
5
5
  Requires-Python: >=3.11
6
6
  License-File: LICENSE.md
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kanibako-cli"
7
- version = "1.6.0.dev26"
7
+ version = "1.6.0.dev30"
8
8
  description = "Run AI coding agents in rootless containers with per-project isolation"
9
9
  requires-python = ">=3.11"
10
10
  dependencies = ["argcomplete>=3.0", "PyYAML>=6.0", "packaging>=20.0"]
@@ -1,6 +1,6 @@
1
1
  """kanibako: Run AI coding agents in rootless containers with per-project isolation."""
2
2
 
3
- __version__ = "1.6.0.dev26"
3
+ __version__ = "1.6.0.dev30"
4
4
 
5
5
  # The oldest build version whose ``setup`` run is still considered current. The
6
6
  # setup-completion gate (W1) re-nudges the user to re-run ``kanibako setup`` when
@@ -107,26 +107,47 @@ def apply_template_layers(
107
107
  """Seed *home* once by copying the ordered template *layers* in order.
108
108
 
109
109
  The 1.6.0 home-seed model layers ordered template sources into the box home
110
- at creation (base -> agent -> workset; later overlays earlier). Each layer
111
- in *layers* is copied into *home* in sequence with ``dirs_exist_ok=True`` so
112
- a later layer's file overwrites an earlier layer's file at the same relative
113
- path (per-file LAST-WINS). Layers that do not exist on disk are skipped (a
114
- ``<None>`` / absent layer contributes nothing e.g. STANDALONE boxes have
115
- no workset layer).
116
-
117
- This is SEED-ONCE: callers invoke it only on box creation
118
- (``proj.is_new``). It does NOT special-case or merge any file every file
110
+ at creation (base -> agent -> workset; later overlays earlier). The copy is
111
+ NON-DESTRUCTIVE toward files that ALREADY EXIST in *home* before this seed
112
+ pass begins: such a pre-existing file (a user-edited home file on a
113
+ marker-less migrated box) is NEVER clobbered. This is the guard against
114
+ re-seed DATA LOSS a box whose home is already populated but lacks the
115
+ ``.seeded`` marker would otherwise have its files overwritten.
116
+
117
+ Within a SINGLE seed pass, cross-layer LAST-WINS is still honoured: a file
118
+ written by an earlier layer during this pass IS overwritten by a later
119
+ layer's file at the same relative path. A per-pass ``written`` set of
120
+ relative paths distinguishes "created earlier this pass" (override OK) from
121
+ "pre-existed before the pass" (preserve). Layers that do not exist on disk
122
+ are skipped (a ``<None>`` / absent layer contributes nothing — e.g.
123
+ STANDALONE boxes have no workset layer).
124
+
125
+ This is SEED-ONCE: callers invoke it only when the box still
126
+ :func:`needs_seed`. It does NOT special-case or merge any file — every file
119
127
  is a plain ordered copy (the CLAUDE.md merge special-case is gone, D-B5).
120
- The caller is responsible for never re-running it on a subsequent launch so
121
- user edits made inside the box survive (D-B6).
128
+ The caller is responsible for never re-running it once the box is marked
129
+ seeded so user edits made inside the box survive (D-B6); the non-destructive
130
+ copy here is an additional safety net for the marker-less re-seed case.
122
131
  """
132
+ written: set[Path] = set()
123
133
  for layer in layers:
124
134
  if layer is None:
125
135
  continue
126
136
  if not layer.is_dir():
127
137
  continue
128
- home.mkdir(parents=True, exist_ok=True)
129
- shutil.copytree(str(layer), str(home), dirs_exist_ok=True)
138
+ for entry in sorted(layer.rglob("*")):
139
+ if not entry.is_file():
140
+ continue
141
+ rel = entry.relative_to(layer)
142
+ target = home / rel
143
+ # Write when an earlier layer in THIS pass created the file
144
+ # (last-wins override) OR the target does not yet exist. Skip a
145
+ # target that pre-existed the pass (a user/pre-existing file).
146
+ if rel not in written and target.exists():
147
+ continue
148
+ target.parent.mkdir(parents=True, exist_ok=True)
149
+ shutil.copy2(str(entry), str(target))
150
+ written.add(rel)
130
151
 
131
152
 
132
153
  # ---------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kanibako-cli
3
- Version: 1.6.0.dev26
3
+ Version: 1.6.0.dev30
4
4
  Summary: Run AI coding agents in rootless containers with per-project isolation
5
5
  Requires-Python: >=3.11
6
6
  License-File: LICENSE.md
@@ -76,6 +76,70 @@ class TestApplyTemplateLayers:
76
76
  assert (home / "user-edited.txt").read_text() == "user changes"
77
77
  assert (home / "base-only.txt").read_text() == "base"
78
78
 
79
+ def test_existing_home_file_not_clobbered_by_same_path_layer(self, tmp_path):
80
+ """A pre-existing home file is preserved even when a layer ships the same path.
81
+
82
+ This is the re-seed DATA-LOSS guard: a marker-less migrated box has a
83
+ home full of user-edited files; a layer with a file at the same relative
84
+ path must NOT overwrite the user's content.
85
+ """
86
+ home = tmp_path / "home"
87
+ home.mkdir()
88
+ (home / "shared.txt").write_text("user changes")
89
+ base = self._layer(tmp_path, "base", {
90
+ "shared.txt": "base version",
91
+ "base-only.txt": "base",
92
+ })
93
+
94
+ apply_template_layers(home, [base])
95
+
96
+ # Pre-existing file preserved (NOT clobbered by the layer's same-path file).
97
+ assert (home / "shared.txt").read_text() == "user changes"
98
+ # New file from the layer still lands.
99
+ assert (home / "base-only.txt").read_text() == "base"
100
+
101
+ def test_cross_layer_last_wins_when_home_absent(self, tmp_path):
102
+ """Two layers both shipping foo.txt -> later layer wins (home didn't have it)."""
103
+ home = tmp_path / "home"
104
+ home.mkdir()
105
+ base = self._layer(tmp_path, "base", {"foo.txt": "base version"})
106
+ agent = self._layer(tmp_path, "agent", {"foo.txt": "agent version"})
107
+
108
+ apply_template_layers(home, [base, agent])
109
+
110
+ # Later layer overrides the earlier layer's file written THIS pass.
111
+ assert (home / "foo.txt").read_text() == "agent version"
112
+
113
+ def test_new_layer_files_land_in_nonempty_home(self, tmp_path):
114
+ """Files unique to a layer are copied into an existing non-empty home."""
115
+ home = tmp_path / "home"
116
+ home.mkdir()
117
+ (home / "user-edited.txt").write_text("user changes")
118
+ base = self._layer(tmp_path, "base", {
119
+ "base-only.txt": "base",
120
+ "nested/deep.txt": "deep",
121
+ })
122
+
123
+ apply_template_layers(home, [base])
124
+
125
+ # Pre-existing user file untouched.
126
+ assert (home / "user-edited.txt").read_text() == "user changes"
127
+ # New unique files (including nested) land.
128
+ assert (home / "base-only.txt").read_text() == "base"
129
+ assert (home / "nested" / "deep.txt").read_text() == "deep"
130
+
131
+ def test_existing_nested_file_not_clobbered(self, tmp_path):
132
+ """A pre-existing file in a nested home subdir is preserved against a layer."""
133
+ home = tmp_path / "home"
134
+ nested = home / ".claude"
135
+ nested.mkdir(parents=True)
136
+ (nested / "settings.json").write_text("user settings")
137
+ agent = self._layer(tmp_path, "agent", {".claude/settings.json": "shipped"})
138
+
139
+ apply_template_layers(home, [agent])
140
+
141
+ assert (home / ".claude" / "settings.json").read_text() == "user settings"
142
+
79
143
  def test_none_and_missing_layers_skipped(self, tmp_path):
80
144
  """A None layer or a layer dir that doesn't exist contributes nothing."""
81
145
  home = tmp_path / "home"