pushframe 5.0.3__tar.gz → 5.0.5__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 (391) hide show
  1. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/MILESTONES.md +25 -0
  2. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/PROJECT.md +2 -0
  3. pushframe-5.0.5/.planning/REQUIREMENTS.md +118 -0
  4. pushframe-5.0.5/.planning/ROADMAP.md +105 -0
  5. pushframe-5.0.5/.planning/STATE.md +22 -0
  6. pushframe-5.0.3/.planning/REQUIREMENTS.md → pushframe-5.0.5/.planning/milestones/v5.0-REQUIREMENTS.md +9 -0
  7. pushframe-5.0.5/.planning/phases/23-config-wizard-precedence/23-01-PLAN.md +157 -0
  8. pushframe-5.0.5/.planning/phases/23-config-wizard-precedence/23-01-SUMMARY.md +70 -0
  9. pushframe-5.0.5/.planning/phases/23-config-wizard-precedence/23-CONTEXT.md +68 -0
  10. pushframe-5.0.5/.planning/phases/23-config-wizard-precedence/23-RESEARCH.md +89 -0
  11. pushframe-5.0.5/.planning/phases/23-config-wizard-precedence/23-VERIFICATION.md +57 -0
  12. pushframe-5.0.5/.planning/state.json +32 -0
  13. {pushframe-5.0.3 → pushframe-5.0.5}/CHANGELOG.md +86 -14
  14. {pushframe-5.0.3 → pushframe-5.0.5}/PKG-INFO +33 -6
  15. {pushframe-5.0.3 → pushframe-5.0.5}/README.md +32 -5
  16. {pushframe-5.0.3 → pushframe-5.0.5}/docs/CLI.md +52 -2
  17. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/__init__.py +1 -1
  18. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/aura.py +25 -0
  19. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/aws/s3client.py +13 -9
  20. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/aws/sqsclient.py +6 -6
  21. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/cli.py +280 -23
  22. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/client.py +14 -3
  23. pushframe-5.0.5/pushframe/config_store.py +103 -0
  24. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/bootstrap.py +77 -8
  25. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/gsync.py +58 -5
  26. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/sync.py +14 -0
  27. pushframe-5.0.5/pushframe/utils/settings.py +122 -0
  28. {pushframe-5.0.3 → pushframe-5.0.5}/pyproject.toml +1 -1
  29. pushframe-5.0.5/scripts/test-config-journey-container.sh +201 -0
  30. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_google_link.py +52 -7
  31. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_push_budget_geo.py +2 -2
  32. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_status.py +39 -0
  33. pushframe-5.0.5/tests/test_config_wizard.py +168 -0
  34. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_execute_plan.py +35 -0
  35. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_gsync_execute.py +62 -0
  36. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_imports.py +5 -4
  37. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_settings_budget.py +6 -6
  38. pushframe-5.0.5/tests/test_settings_resolution.py +106 -0
  39. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_version.py +2 -2
  40. {pushframe-5.0.3 → pushframe-5.0.5}/uv.lock +1 -1
  41. pushframe-5.0.3/.planning/STATE.md +0 -168
  42. pushframe-5.0.3/.planning/state.json +0 -28
  43. pushframe-5.0.3/pushframe/utils/settings.py +0 -59
  44. {pushframe-5.0.3 → pushframe-5.0.5}/.env.sample +0 -0
  45. {pushframe-5.0.3 → pushframe-5.0.5}/.freebuff/project-id +0 -0
  46. {pushframe-5.0.3 → pushframe-5.0.5}/.github/workflows/release.yml +0 -0
  47. {pushframe-5.0.3 → pushframe-5.0.5}/.github/workflows/tests.yml +0 -0
  48. {pushframe-5.0.3 → pushframe-5.0.5}/.gitignore +0 -0
  49. {pushframe-5.0.3 → pushframe-5.0.5}/.gsd/dispatch-isolation-sentinel.json +0 -0
  50. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/RETROSPECTIVE.md +0 -0
  51. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/WINDOWS.md +0 -0
  52. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/codebase/ARCHITECTURE.md +0 -0
  53. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/codebase/CONCERNS.md +0 -0
  54. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/codebase/CONVENTIONS.md +0 -0
  55. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/codebase/INTEGRATIONS.md +0 -0
  56. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/codebase/STACK.md +0 -0
  57. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/codebase/STRUCTURE.md +0 -0
  58. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/codebase/TESTING.md +0 -0
  59. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/config.json +0 -0
  60. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/debug/knowledge-base.md +0 -0
  61. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/debug/login-475-null-creds.md +0 -0
  62. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/debug/resolved/cli-status-verbose-logging.md +0 -0
  63. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/debug/resolved/inspect-asset-null-fields.md +0 -0
  64. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/debug/resolved/select-asset-401-unauthorized.md +0 -0
  65. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-REQUIREMENTS.md +0 -0
  66. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-ROADMAP.md +0 -0
  67. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-01-PLAN.md +0 -0
  68. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-01-SUMMARY.md +0 -0
  69. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-02-PLAN.md +0 -0
  70. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-02-SUMMARY.md +0 -0
  71. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-CONTEXT.md +0 -0
  72. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-DISCUSSION-LOG.md +0 -0
  73. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-PATTERNS.md +0 -0
  74. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-RESEARCH.md +0 -0
  75. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-REVIEW.md +0 -0
  76. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/01-toolchain-revival/01-VERIFICATION.md +0 -0
  77. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-01-PLAN.md +0 -0
  78. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-01-SUMMARY.md +0 -0
  79. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-02-PLAN.md +0 -0
  80. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-02-SUMMARY.md +0 -0
  81. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-CONTEXT.md +0 -0
  82. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-DISCUSSION-LOG.md +0 -0
  83. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-LIVE-EVIDENCE.md +0 -0
  84. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-PATTERNS.md +0 -0
  85. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-RESEARCH.md +0 -0
  86. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-REVIEW.md +0 -0
  87. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/02-live-read-path-verification/02-VERIFICATION.md +0 -0
  88. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/03-run-docs-verification-report/03-01-PLAN.md +0 -0
  89. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/03-run-docs-verification-report/03-01-SUMMARY.md +0 -0
  90. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/03-run-docs-verification-report/03-CONTEXT.md +0 -0
  91. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/03-run-docs-verification-report/03-DISCUSSION-LOG.md +0 -0
  92. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/03-run-docs-verification-report/03-PATTERNS.md +0 -0
  93. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/03-run-docs-verification-report/03-RESEARCH.md +0 -0
  94. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/03-run-docs-verification-report/03-REVIEW.md +0 -0
  95. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.0-phases/03-run-docs-verification-report/03-VERIFICATION.md +0 -0
  96. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-ROADMAP.md +0 -0
  97. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/.gitkeep +0 -0
  98. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-01-PLAN.md +0 -0
  99. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-01-SUMMARY.md +0 -0
  100. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-02-PLAN.md +0 -0
  101. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-02-SUMMARY.md +0 -0
  102. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-03-PLAN.md +0 -0
  103. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-03-SUMMARY.md +0 -0
  104. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-PATTERNS.md +0 -0
  105. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-RESEARCH.md +0 -0
  106. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-REVIEW.md +0 -0
  107. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-SECURITY.md +0 -0
  108. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-UAT.md +0 -0
  109. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v1.1-phases/04-client-transport-seam-for-offline-testability/04-VERIFICATION.md +0 -0
  110. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-REQUIREMENTS.md +0 -0
  111. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-ROADMAP.md +0 -0
  112. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-01-PLAN.md +0 -0
  113. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-01-SUMMARY.md +0 -0
  114. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-02-PLAN.md +0 -0
  115. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-02-SUMMARY.md +0 -0
  116. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-CONTEXT.md +0 -0
  117. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-DISCUSSION-LOG.md +0 -0
  118. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-PATTERNS.md +0 -0
  119. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-REVIEW.md +0 -0
  120. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-SECURITY.md +0 -0
  121. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-UAT.md +0 -0
  122. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/05-cli-skeleton-status/05-VERIFICATION.md +0 -0
  123. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-01-PLAN.md +0 -0
  124. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-01-SUMMARY.md +0 -0
  125. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-02-PLAN.md +0 -0
  126. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-02-SUMMARY.md +0 -0
  127. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-CONTEXT.md +0 -0
  128. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-DISCUSSION-LOG.md +0 -0
  129. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-PATTERNS.md +0 -0
  130. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-RESEARCH.md +0 -0
  131. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-REVIEW.md +0 -0
  132. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-SECURITY.md +0 -0
  133. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/06-inspect-frame-resolution/06-VERIFICATION.md +0 -0
  134. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-01-PLAN.md +0 -0
  135. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-01-SUMMARY.md +0 -0
  136. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-02-PLAN.md +0 -0
  137. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-02-SUMMARY.md +0 -0
  138. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-03-PLAN.md +0 -0
  139. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-03-SUMMARY.md +0 -0
  140. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-CONTEXT.md +0 -0
  141. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-DISCUSSION-LOG.md +0 -0
  142. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-PATTERNS.md +0 -0
  143. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-REVIEW-FIX.md +0 -0
  144. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-REVIEW.md +0 -0
  145. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-SECURITY.md +0 -0
  146. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/07-sync-diffing-engine-dry-run-only/07-VERIFICATION.md +0 -0
  147. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-01-PLAN.md +0 -0
  148. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-01-SUMMARY.md +0 -0
  149. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-02-PLAN.md +0 -0
  150. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-02-SUMMARY.md +0 -0
  151. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-03-PLAN.md +0 -0
  152. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-03-SUMMARY.md +0 -0
  153. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-04-PLAN.md +0 -0
  154. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-04-SUMMARY.md +0 -0
  155. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-CONTEXT.md +0 -0
  156. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-DISCUSSION-LOG.md +0 -0
  157. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-LIVE-FINDINGS.md +0 -0
  158. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-PATTERNS.md +0 -0
  159. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-RESEARCH.md +0 -0
  160. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-REVIEW-FIX.md +0 -0
  161. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-REVIEW.md +0 -0
  162. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/08-destructive-execution-upload-delete-verification/08-VERIFICATION.md +0 -0
  163. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/.gitkeep +0 -0
  164. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-01-PLAN.md +0 -0
  165. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-01-SUMMARY.md +0 -0
  166. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-02-PLAN.md +0 -0
  167. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-02-SUMMARY.md +0 -0
  168. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-CONTEXT.md +0 -0
  169. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-RESEARCH.md +0 -0
  170. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-REVIEW-FIX.md +0 -0
  171. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-REVIEW.md +0 -0
  172. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/09-proactive-write-rate-limiter-geo-guard/09-VERIFICATION.md +0 -0
  173. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/.gitkeep +0 -0
  174. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-01-PLAN.md +0 -0
  175. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-01-SUMMARY.md +0 -0
  176. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-02-PLAN.md +0 -0
  177. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-02-SUMMARY.md +0 -0
  178. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-03-PLAN.md +0 -0
  179. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-03-SUMMARY.md +0 -0
  180. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-04-PLAN.md +0 -0
  181. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-04-SUMMARY.md +0 -0
  182. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-CONTEXT.md +0 -0
  183. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-DISCUSSION-LOG.md +0 -0
  184. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-LIVE-FINDINGS.md +0 -0
  185. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-PATTERNS.md +0 -0
  186. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-RESEARCH.md +0 -0
  187. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-SECURITY.md +0 -0
  188. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-UAT.md +0 -0
  189. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/10-VERIFICATION.md +0 -0
  190. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-phases/10-hide-instead-of-delete-sync-mode/COVERAGE.md +0 -0
  191. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/260630-qs8-make-main-py-load-a-local-env-file-at-st/260630-qs8-PLAN.md +0 -0
  192. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/260630-qs8-make-main-py-load-a-local-env-file-at-st/260630-qs8-SUMMARY.md +0 -0
  193. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/260708-dt9-add-progress-feedback-to-aura-cli-sync-a/260708-dt9-PLAN.md +0 -0
  194. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/260708-dt9-add-progress-feedback-to-aura-cli-sync-a/260708-dt9-SUMMARY.md +0 -0
  195. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/260708-dt9-add-progress-feedback-to-aura-cli-sync-a/deferred-items.md +0 -0
  196. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/260708-fyr-batch-refactor-of-sync-apply-write-path-/260708-fyr-PLAN.md +0 -0
  197. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/260708-fyr-batch-refactor-of-sync-apply-write-path-/260708-fyr-SUMMARY.md +0 -0
  198. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/260708-fyr-batch-refactor-of-sync-apply-write-path-/260708-fyr-VERIFICATION.md +0 -0
  199. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v2.0-quick/README.md +0 -0
  200. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-REQUIREMENTS.md +0 -0
  201. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-ROADMAP.md +0 -0
  202. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-01-PLAN.md +0 -0
  203. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-01-SUMMARY.md +0 -0
  204. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-02-PLAN.md +0 -0
  205. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-02-SUMMARY.md +0 -0
  206. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-03-PLAN.md +0 -0
  207. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-03-SUMMARY.md +0 -0
  208. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-04-PLAN.md +0 -0
  209. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-04-SUMMARY.md +0 -0
  210. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-05-PLAN.md +0 -0
  211. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-05-SUMMARY.md +0 -0
  212. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-06-PLAN.md +0 -0
  213. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-06-SUMMARY.md +0 -0
  214. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-CONTEXT.md +0 -0
  215. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-DISCUSSION-LOG.md +0 -0
  216. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-LIVE-FINDINGS.md +0 -0
  217. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-PATTERNS.md +0 -0
  218. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-REVIEW.md +0 -0
  219. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v3.0-phases/11-write-path-reliability-format-support/11-VERIFICATION.md +0 -0
  220. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-REQUIREMENTS.md +0 -0
  221. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-ROADMAP.md +0 -0
  222. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-01-PLAN.md +0 -0
  223. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-01-SUMMARY.md +0 -0
  224. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-02-PLAN.md +0 -0
  225. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-02-SUMMARY.md +0 -0
  226. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-03-PLAN.md +0 -0
  227. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-03-SUMMARY.md +0 -0
  228. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-CONTEXT.md +0 -0
  229. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-DECISION-RECORD.md +0 -0
  230. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-DISCUSSION-LOG.md +0 -0
  231. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/16-LIVE-FINDINGS.md +0 -0
  232. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/16-local-mechanism-spike-decision/COVERAGE.md +0 -0
  233. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/17-google-link-album-selection/17-01-PLAN.md +0 -0
  234. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/17-google-link-album-selection/17-01-SUMMARY.md +0 -0
  235. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/17-google-link-album-selection/17-02-PLAN.md +0 -0
  236. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/17-google-link-album-selection/17-02-SUMMARY.md +0 -0
  237. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/17-google-link-album-selection/17-CONTEXT.md +0 -0
  238. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/17-google-link-album-selection/17-DISCUSS-CHECKPOINT.json +0 -0
  239. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/17-google-link-album-selection/17-VERIFICATION.md +0 -0
  240. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/17-google-link-album-selection/COVERAGE.md +0 -0
  241. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-01-PLAN.md +0 -0
  242. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-01-SUMMARY.md +0 -0
  243. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-02-PLAN.md +0 -0
  244. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-02-SUMMARY.md +0 -0
  245. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-03-PLAN.md +0 -0
  246. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-03-SUMMARY.md +0 -0
  247. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-CONTEXT.md +0 -0
  248. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-RESEARCH.md +0 -0
  249. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-UAT.md +0 -0
  250. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/18-album-frame-mirror-sync-single-pair/18-VERIFICATION.md +0 -0
  251. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/19-debt-closeout/19-01-PLAN.md +0 -0
  252. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/19-debt-closeout/19-01-SUMMARY.md +0 -0
  253. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/19-debt-closeout/19-02-PLAN.md +0 -0
  254. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/19-debt-closeout/19-02-SUMMARY.md +0 -0
  255. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/19-debt-closeout/19-CONTEXT.md +0 -0
  256. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/19-debt-closeout/19-RESEARCH.md +0 -0
  257. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/milestones/v4.0-phases/19-debt-closeout/19-VERIFICATION.md +0 -0
  258. /pushframe-5.0.3/.planning/ROADMAP.md → /pushframe-5.0.5/.planning/milestones/v5.0-ROADMAP.md +0 -0
  259. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/20-pushframe-rename-migration-repo-switch/20-SUMMARY.md +0 -0
  260. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/21-debian-package-apt-repo/21-01-PLAN.md +0 -0
  261. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/21-debian-package-apt-repo/21-01-SUMMARY.md +0 -0
  262. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/21-debian-package-apt-repo/21-02-PLAN.md +0 -0
  263. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/21-debian-package-apt-repo/21-02-SUMMARY.md +0 -0
  264. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/21-debian-package-apt-repo/21-CONTEXT.md +0 -0
  265. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/21-debian-package-apt-repo/21-RESEARCH.md +0 -0
  266. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/21-debian-package-apt-repo/21-VERIFICATION.md +0 -0
  267. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/22-pypi-release-engineering/22-01-PLAN.md +0 -0
  268. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/22-pypi-release-engineering/22-01-SUMMARY.md +0 -0
  269. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/22-pypi-release-engineering/22-02-PLAN.md +0 -0
  270. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/22-pypi-release-engineering/22-02-SUMMARY.md +0 -0
  271. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/22-pypi-release-engineering/22-CONTEXT.md +0 -0
  272. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/22-pypi-release-engineering/22-RESEARCH.md +0 -0
  273. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/22-pypi-release-engineering/22-VERIFICATION.md +0 -0
  274. {pushframe-5.0.3/.planning/phases → pushframe-5.0.5/.planning/milestones/v5.0-phases}/22-pypi-release-engineering/OPERATOR-STEPS.md +0 -0
  275. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/research/ALBUM-ACCESS-V4-ADDENDUM.md +0 -0
  276. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/research/ALBUM-ACCESS.md +0 -0
  277. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/research/ARCHITECTURE.md +0 -0
  278. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/research/BROWSER-AUTOMATION.md +0 -0
  279. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/research/FEATURES.md +0 -0
  280. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/research/PITFALLS.md +0 -0
  281. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/research/STACK.md +0 -0
  282. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/research/SUMMARY.md +0 -0
  283. {pushframe-5.0.3 → pushframe-5.0.5}/.planning/todos/completed/2026-07-06-promote-debug-flag-to-a-global-cli-convention.md +0 -0
  284. {pushframe-5.0.3 → pushframe-5.0.5}/.python-version +0 -0
  285. {pushframe-5.0.3 → pushframe-5.0.5}/CLAUDE.md +0 -0
  286. {pushframe-5.0.3 → pushframe-5.0.5}/LICENSE +0 -0
  287. {pushframe-5.0.3 → pushframe-5.0.5}/SECURITY.md +0 -0
  288. {pushframe-5.0.3 → pushframe-5.0.5}/VERIFICATION-REPORT.md +0 -0
  289. {pushframe-5.0.3 → pushframe-5.0.5}/docs/agents/domain.md +0 -0
  290. {pushframe-5.0.3 → pushframe-5.0.5}/docs/agents/issue-tracker.md +0 -0
  291. {pushframe-5.0.3 → pushframe-5.0.5}/docs/agents/triage-labels.md +0 -0
  292. {pushframe-5.0.3 → pushframe-5.0.5}/docs/superpowers/specs/2026-07-09-write-rate-limiter-design.md +0 -0
  293. {pushframe-5.0.3 → pushframe-5.0.5}/main.py +0 -0
  294. {pushframe-5.0.3 → pushframe-5.0.5}/packaging/control-template +0 -0
  295. {pushframe-5.0.3 → pushframe-5.0.5}/packaging/lintian-overrides +0 -0
  296. {pushframe-5.0.3 → pushframe-5.0.5}/packaging/postinst +0 -0
  297. {pushframe-5.0.3 → pushframe-5.0.5}/packaging/pushframe.copyright +0 -0
  298. {pushframe-5.0.3 → pushframe-5.0.5}/probes/.gitignore +0 -0
  299. {pushframe-5.0.3 → pushframe-5.0.5}/probes/README.md +0 -0
  300. {pushframe-5.0.3 → pushframe-5.0.5}/probes/browser_bootstrap.py +0 -0
  301. {pushframe-5.0.3 → pushframe-5.0.5}/probes/common.py +0 -0
  302. {pushframe-5.0.3 → pushframe-5.0.5}/probes/cookie_vault.py +0 -0
  303. {pushframe-5.0.3 → pushframe-5.0.5}/probes/fidelity_check.py +0 -0
  304. {pushframe-5.0.3 → pushframe-5.0.5}/probes/rpc_capture.py +0 -0
  305. {pushframe-5.0.3 → pushframe-5.0.5}/probes/shared_link_probe.py +0 -0
  306. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/__init__.py +0 -0
  307. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/accountApi.py +0 -0
  308. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/activityApi.py +0 -0
  309. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/assetApi.py +0 -0
  310. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/baseApi.py +0 -0
  311. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/frameApi.py +0 -0
  312. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/notificationApi.py +0 -0
  313. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/peopleApi.py +0 -0
  314. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/api/playlistApi.py +0 -0
  315. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/aws/__init__.py +0 -0
  316. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/aws/awsclient.py +0 -0
  317. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/cache.py +0 -0
  318. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/exif.py +0 -0
  319. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/export.py +0 -0
  320. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/__init__.py +0 -0
  321. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/cache.py +0 -0
  322. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/client.py +0 -0
  323. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/enumerate.py +0 -0
  324. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/manifest.py +0 -0
  325. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/parsers.py +0 -0
  326. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/redaction.py +0 -0
  327. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/google/vault.py +0 -0
  328. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/migration.py +0 -0
  329. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/models/__init__.py +0 -0
  330. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/models/activity.py +0 -0
  331. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/models/asset.py +0 -0
  332. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/models/frame.py +0 -0
  333. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/models/meta.py +0 -0
  334. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/models/person.py +0 -0
  335. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/models/user.py +0 -0
  336. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/ratelimit.py +0 -0
  337. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/reconcile.py +0 -0
  338. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/utils/dt.py +0 -0
  339. {pushframe-5.0.3 → pushframe-5.0.5}/pushframe/utils/io.py +0 -0
  340. {pushframe-5.0.3 → pushframe-5.0.5}/scripts/build-deb.sh +0 -0
  341. {pushframe-5.0.3 → pushframe-5.0.5}/scripts/make-apt-key.sh +0 -0
  342. {pushframe-5.0.3 → pushframe-5.0.5}/scripts/publish-apt-repo.sh +0 -0
  343. {pushframe-5.0.3 → pushframe-5.0.5}/scripts/test-apt-journey-container.sh +0 -0
  344. {pushframe-5.0.3 → pushframe-5.0.5}/scripts/test-deb-container.sh +0 -0
  345. {pushframe-5.0.3 → pushframe-5.0.5}/scripts/test-install-journey-container.sh +0 -0
  346. {pushframe-5.0.3 → pushframe-5.0.5}/tests/conftest.py +0 -0
  347. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/asset_unprocessed.json +0 -0
  348. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/assets_page1.json +0 -0
  349. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/assets_page2.json +0 -0
  350. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/assets_placeholders.json +0 -0
  351. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/error_envelope.json +0 -0
  352. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/frame_detail.json +0 -0
  353. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/frames.json +0 -0
  354. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/google_rpc_snackc_page.json +0 -0
  355. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/google_share_page_sample.html +0 -0
  356. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/login.json +0 -0
  357. {pushframe-5.0.3 → pushframe-5.0.5}/tests/fixtures/probe_af_initdata_sample.html +0 -0
  358. {pushframe-5.0.3 → pushframe-5.0.5}/tests/offline.py +0 -0
  359. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_asset_partial.py +0 -0
  360. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_asset_unprocessed.py +0 -0
  361. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_aura_logger.py +0 -0
  362. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_batch_update_contract.py +0 -0
  363. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_apply.py +0 -0
  364. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_google_album.py +0 -0
  365. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_inspect.py +0 -0
  366. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_reconcile.py +0 -0
  367. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_status_google.py +0 -0
  368. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_cli_sync.py +0 -0
  369. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_client_rate_limit.py +0 -0
  370. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_execute_plan_budget_geo.py +0 -0
  371. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_fixtures_validity.py +0 -0
  372. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_google_cache.py +0 -0
  373. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_google_client.py +0 -0
  374. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_google_enumerate.py +0 -0
  375. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_google_manifest.py +0 -0
  376. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_google_parsers.py +0 -0
  377. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_google_vault.py +0 -0
  378. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_gsync_engine.py +0 -0
  379. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_migration.py +0 -0
  380. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_offline_read_path.py +0 -0
  381. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_prep_upload_formats.py +0 -0
  382. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_probe_browser.py +0 -0
  383. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_probe_shared_link.py +0 -0
  384. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_ratelimit.py +0 -0
  385. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_read_path.py +0 -0
  386. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_reconcile.py +0 -0
  387. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_retry_401.py +0 -0
  388. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_sync_engine.py +0 -0
  389. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_write_endpoints_failloud.py +0 -0
  390. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_write_formats_live.py +0 -0
  391. {pushframe-5.0.3 → pushframe-5.0.5}/tests/test_write_throttling.py +0 -0
@@ -1,5 +1,30 @@
1
1
  # Milestones
2
2
 
3
+ ## v5.0 — Distribution & Rename: pushframe packages (Shipped: 2026-09-29)
4
+
5
+ **Phases completed:** 3 phases (20-22), 4 plans — the first milestone
6
+ about *shipping the tool itself* rather than its features.
7
+
8
+ **Key accomplishments:**
9
+
10
+ | Phase | Delivered | Proof |
11
+ |-------|-----------|-------|
12
+ | 20 — Rename & repo switch | `auraframes`→`pushframe` (module, binary, config migration), env `PUSHFRAME_*` primary, standalone repo `coredmp95/pushframe` (not a fork), MIT LICENSE + provenance | 407 tests green through the rename; live migration validated; name cleared on PyPI + trademark-adjacency checked |
13
+ | 21 — Debian + APT | Hermetic `.deb` (embedded CPython 3.14, lintian 0E/0W, clean removal), signed APT repo live on GitHub Pages, container journeys for both channels | bytecode-ownership defect caught by our own container test and fixed for every user; live-URL journey exit 0 |
14
+ | 22 — PyPI + releases | Trusted publishing (OIDC, zero PyPI tokens), tag-triggered release workflow, `--version` single-sourced, OPERATOR-STEPS + CHANGELOG | v5.0.2 run all-green 5/5 jobs; v5.0.3 carries the Changelog URL |
15
+
16
+ **Shipped releases:** 5.0.0 → 5.0.1 (page metadata) → 5.0.2 (first
17
+ pipeline-complete) → 5.0.3 (changelog URL) — each on PyPI + TestPyPI +
18
+ APT + GitHub Releases simultaneously. First real deployment:
19
+ venus.coredmp.net via the signed APT repo (human-driven: keyring →
20
+ sources → install).
21
+
22
+ **Known gaps carried forward:** 5.0.0 remains on PyPI (empty page,
23
+ immutable) — yank candidate; `AURA_*` env vars in a one-release
24
+ deprecation window; credentials still live in env vars/.env (v5.1's
25
+ charter: config wizard + token-first sessions).
26
+
27
+
3
28
  ## v4.0 Local Google Photos Album Sync (Shipped: 2026-09-29)
4
29
 
5
30
  **Phases completed:** 4 phases (16-19), 10 plans, offline suite 349 → **401 tests**
@@ -364,3 +364,5 @@ sequences write-path reliability first, then Google account linking → album di
364
364
  album-to-frame mirroring via a pruned local cache, then the carried debt. Biggest open
365
365
  unknown: whether Google's post-March-2025 Photos API still permits enumerating a user's own
366
366
  albums, or whether album selection has to go through the Picker API.*
367
+
368
+ **Current Milestone:** v5.1 — Operations: Config, Sessions, Multi-frame & Scheduling (started 2026-09-29)
@@ -0,0 +1,118 @@
1
+ # Requirements: pushframe — v5.1 Operations: Config, Sessions, Multi-frame & Scheduling
2
+
3
+ **Defined:** 2026-09-29
4
+ **Core Value:** `pushframe` becomes *operable unattended*: configuration is a
5
+ conversation (`pushframe config`) instead of env-var archaeology, the Aura
6
+ password never touches disk (token-first sessions), mirrors run on a schedule
7
+ without root (systemd user timers), one album can mirror to every frame
8
+ (named mappings), and every command that needs a machine prerequisite fails
9
+ with the remedy instead of a traceback.
10
+
11
+ ## Requirements
12
+
13
+ ### Config wizard (CFG)
14
+
15
+ - [ ] **CFG-01**: `pushframe config` (interactive) asks for and stores: Aura
16
+ email, Aura secret, default frame name, and the tool's non-secret settings
17
+ (default album, write-budget override, debug) — prompts are masked for
18
+ secrets (getpass-style), values are validated (email shape; login test on
19
+ request), and the result is written to `~/.config/pushframe/config.json`
20
+ with mode `0600`. Re-running edits in place (existing values shown
21
+ redacted, Enter keeps).
22
+ - [ ] **CFG-02**: precedence is `env var > config file > built-in default`
23
+ everywhere the CLI reads configuration; the env vars keep working exactly
24
+ as today (deprecation window opened in 5.0.0 stays honored); `pushframe
25
+ config show` prints the *effective* configuration with secrets redacted
26
+ and the source of each value (env/file/default).
27
+ - [ ] **CFG-03**: `pushframe config import` migrates an existing `.env`
28
+ (or exported `PUSHFRAME_*`/`AURA_*` set) into `config.json` without
29
+ retyping; the command reports what it took from where and never stores
30
+ what it could resolve from the environment instead.
31
+ - [ ] **CFG-04**: `pushframe config path` prints the config file location;
32
+ `pushframe config set <key> <value>` / `get <key>` exist for scripts;
33
+ unknown keys fail with the list of known keys.
34
+
35
+ ### Credential handling (SEC — token-first)
36
+
37
+ - [ ] **SEC-01**: the Aura password is **never persisted** — not in
38
+ `config.json`, not in env files the tool writes. `pushframe config`
39
+ authenticates once, stores the returned `auth_token` (0600) plus the
40
+ account email, and discards the password when the process exits.
41
+ - [ ] **SEC-02**: every command that needs the API uses the stored token
42
+ (header auth) and falls back to interactive password login **only** when
43
+ the token is absent/expired/revoked, after which the new token is
44
+ persisted; a `--password` / `PUSHFRAME_PASSWORD` override still wins
45
+ (CI/script path) but is documented as discouraged for humans.
46
+ - [ ] **SEC-03**: `pushframe logout` deletes the stored token (and only the
47
+ token); token material never appears in logs, output, or the history
48
+ ledger (existing redaction stays enforced by tests).
49
+
50
+ ### Scheduling (TMR — systemd user)
51
+
52
+ - [ ] **TMR-01**: `pushframe schedule add <job>` installs a systemd **user**
53
+ timer + service unit under `~/.config/systemd/user/` for the supported
54
+ jobs (`google-sync --apply` for a named pair, directory `sync`) with a
55
+ prompted or `--every` schedule; no root anywhere; `pushframe schedule
56
+ list` shows installed jobs with next-run times (from `systemctl list-timers`).
57
+ - [ ] **TMR-02**: `pushframe schedule remove <job>` uninstalls cleanly
58
+ (units + timer state); installed units are named `pushframe-<job>.service/.timer`
59
+ and never collide with system units.
60
+ - [ ] **TMR-03**: unattended correctness: a scheduled run uses only
61
+ stored configuration (no prompts), honors SAFE-02's removal threshold
62
+ (a run that would exceed it **skips and logs** rather than fails the unit),
63
+ writes a per-job log (`~/.local/state/pushframe/<job>.log`), and the
64
+ docs cover `loginctl enable-linger` for headless machines (venus).
65
+
66
+ ### Multi-frame (MTF — GSF-01 closed)
67
+
68
+ - [ ] **MTF-01**: named **album↔frame mappings** live in config: one album
69
+ may mirror to N frames and one frame may receive from N albums
70
+ (`pushframe config` manages them; `--pair <name>` selects one,
71
+ `--all` selects every pair).
72
+ - [ ] **MTF-02**: `google-sync` resolves a pair the same way it resolves the
73
+ current single pair today (dry-run default, `--apply` gated, SAFE-01..04
74
+ per pair); **state is per-pair** — the manifest and staging cache are
75
+ sharded by pair so two pairs never share dedupe memory.
76
+ - [ ] **MTF-03**: the write budget is **account-wide and shared** across
77
+ pairs within one run (`--all`), preserving SAFE-02 semantics at account
78
+ level; per-pair reports stay exact (pairs list what they did, and a
79
+ skipped pair never blocks the others).
80
+
81
+ ### Preflights & error quality (PRF)
82
+
83
+ - [ ] **PRF-01**: commands with machine prerequisites check them up front
84
+ and fail with per-item remedies — `google-link` (playwright package,
85
+ Chrome/Chromium, profile dir) ships in 5.1's first cut (already
86
+ implemented on master), extended to: `google-sync` (vault present),
87
+ `schedule` (systemd user session available, `loginctl` linger status),
88
+ and `sync`/`push` (target dir exists/contains images).
89
+ - [ ] **PRF-02**: no user-facing command may end in an unhandled traceback
90
+ for a foreseeable condition (missing module, missing browser, missing
91
+ vault, ambiguous frame, multi-arch notice): each maps to a named,
92
+ one-screen error with the next action. A test sweep asserts the
93
+ traceback-free contract for the documented failure modes.
94
+
95
+ ## Non-Goals
96
+
97
+ | Feature | Reason |
98
+ |---------|--------|
99
+ | OS keyring storage (gnome-keyring/Secret Service) | headless servers (venus) lack a keyring session; file-0600 token is the contract, keyring is a later nicety |
100
+ | Encrypting config.json with a user passphrase | circularity (where does the passphrase live?); token-first removes the high-value secret anyway |
101
+ | Cron support | systemd user timers are the modern path; cron adds a second code path for no new capability |
102
+ | Real deletion exposure on the Google verb | unchanged posture from v2.0/v4.0; hide-not-delete stays |
103
+ | Many-to-many with per-pair schedules | each pair is its own scheduled job — same capability, simpler model |
104
+
105
+ ## Traceability
106
+
107
+ Every v5.1 requirement maps to exactly one phase; numbering continues from
108
+ Phase 22.
109
+
110
+ | Requirement | Phase | Status |
111
+ |-------------|-------|--------|
112
+ | CFG-01..04 | Phase 23 | Pending |
113
+ | SEC-01..03 | Phase 24 | Pending |
114
+ | PRF-01..02 | Phase 24 | Pending |
115
+ | MTF-01..03 | Phase 25 | Pending |
116
+ | TMR-01..03 | Phase 25 | Pending |
117
+
118
+ **Coverage:** v5.1 requirements: 14 total — no orphans, no double-mapping.
@@ -0,0 +1,105 @@
1
+ # pushframe Roadmap — v5.1 Operations: Config, Sessions, Multi-frame & Scheduling
2
+
3
+ **Defined:** 2026-09-29
4
+ **Ships when:** a fresh machine goes from `apt install pushframe` to a
5
+ scheduled, unattended, multi-frame Google mirror with **zero** hand-edited
6
+ config files and **zero** stored passwords.
7
+
8
+ ## Milestone Goal
9
+
10
+ Make pushframe *operable* the way it is *installable*: one conversational
11
+ command (`pushframe config`) to set everything up, password-free sessions
12
+ (token-first), `pushframe schedule` for root-less systemd user timers,
13
+ named album↔frame mappings with per-pair mirror state, and preflights that
14
+ always fail with a remedy.
15
+
16
+ ## Phases
17
+
18
+ ### Phase 23: Config Wizard & Precedence (CFG-01..04)
19
+
20
+ **Goal**: `pushframe config` replaces env-var archaeology — interactive,
21
+ masked, validated, `0600`; env vars keep working; `show` prints effective
22
+ config with sources; `import` swallows an existing `.env`.
23
+
24
+ **Success Criteria**:
25
+
26
+ 1. On a fresh machine, `pushframe config` → `pushframe status` works with
27
+ no env vars set at all (file-only path), verified in a clean container.
28
+ 2. With env vars set, they override the file — proven by a test that flips
29
+ both and asserts which value each command sees.
30
+ 3. `config show` never prints a secret value (redaction test); `config
31
+ import` on a real `.env` reproduces the same effective config as the
32
+ env-var path (golden diff test).
33
+
34
+ **Depends on**: nothing (master already carries the google-link preflights
35
+ that started this work).
36
+
37
+ ### Phase 24: Token-First Sessions & Preflight Sweep (SEC-01..03, PRF-01..02)
38
+
39
+ **Goal**: the password is used once at login and never stored; the token
40
+ drives every subsequent command with transparent re-login on expiry; the
41
+ preflight pattern from google-link covers every command's machine
42
+ prerequisites; no foreseeable condition ends in a traceback.
43
+
44
+ **Success Criteria**:
45
+
46
+ 1. `pushframe config` + login → `~/.config/pushframe/` contains a token,
47
+ no password, mode 0600 (file-content test).
48
+ 2. A token-expiry simulation (mocked 401) transparently re-logins once and
49
+ retries the request; a second consecutive failure surfaces the login
50
+ error (no loops).
51
+ 3. The traceback-free sweep passes: every documented foreseeable failure
52
+ mode maps to a named error with a remedy (parametrized test).
53
+
54
+ **Depends on**: Phase 23 (config file is where the token lives).
55
+
56
+ ### Phase 25: Multi-frame Mappings & systemd User Scheduling (MTF-01..03, TMR-01..03)
57
+
58
+ **Goal**: GSF-01 and GSF-02 close — named album↔frame pairs (N:M),
59
+ per-pair mirror state with an account-wide shared write budget, and
60
+ `pushframe schedule` installing systemd **user** timers that run pairs
61
+ unattended (SAFE-02 skips-and-logs, per-job logs, linger documented for
62
+ headless hosts like venus).
63
+
64
+ **Success Criteria**:
65
+
66
+ 1. Two pairs (one album → two frames) sync in one `--all` run, each with
67
+ its own manifest/cache shard, the shared budget capping the total, and
68
+ per-pair reports exact (container + fake-API proof).
69
+ 2. `schedule add/list/remove` round-trips units in
70
+ `~/.config/systemd/user/` (unit-content assertions in a container with
71
+ systemd available); a scheduled google-sync run is prompt-free and
72
+ logs to `~/.local/state/pushframe/<job>.log`.
73
+ 3. SAFE-02 behavior under scheduling: a pair whose plan exceeds the
74
+ removal threshold is skipped-and-logged, the unit exits 0, and the
75
+ other pairs still run.
76
+
77
+ **Depends on**: Phase 24 (scheduled runs read token sessions, not
78
+ passwords; preflights guard scheduled contexts).
79
+
80
+ ## Progress
81
+
82
+ **Execution Order:** 23 → 24 → 25
83
+
84
+ | Phase | Plans Complete | Status | Completed |
85
+ |-------|----------------|--------|-----------|
86
+ | 23. Config Wizard & Precedence | 0/? | Not started | - |
87
+ | 24. Token-First Sessions & Preflight Sweep | 0/? | Not started | - |
88
+ | 25. Multi-frame & systemd User Scheduling | 0/? | Not started | - |
89
+
90
+ ## Requirement Coverage (v5.1)
91
+
92
+ | Phase | Requirements | Count |
93
+ |-------|--------------|-------|
94
+ | 23 | CFG-01..04 | 4 |
95
+ | 24 | SEC-01..03, PRF-01..02 | 5 |
96
+ | 25 | MTF-01..03, TMR-01..03 | 6 |
97
+ | **Total** | | **15 / 15** |
98
+
99
+ No orphaned requirements; no requirement mapped to more than one phase.
100
+
101
+ ## Backlog
102
+
103
+ - Yank 5.0.0 from PyPI (empty-page release, superseded by 5.0.3).
104
+ - OS keyring token storage (Secret Service) as an optional backend.
105
+ - Ubuntu 26 runner observation after 2026-10-19 (deb job toolchain).
@@ -0,0 +1,22 @@
1
+ # pushframe — State
2
+
3
+ **Milestone:** v5.1 — Operations: Config, Sessions, Multi-frame & Scheduling
4
+ **Started:** 2026-09-29
5
+
6
+ ## Current Position
7
+
8
+ Phase: 23 — VERIFIED (passed)
9
+ Current Plan: 23-01 complete
10
+ Total Plans in Phase: 1
11
+ Status: Verified — next: phase 24 (Token-First Sessions & Preflight Sweep)
12
+
13
+ ## Milestone Roadmap (v5.1, Phases 23-25)
14
+
15
+ - [x] Phase 23 — Config Wizard & Precedence (CFG-01..04)
16
+ - [ ] Phase 24 — Token-First Sessions & Preflight Sweep (SEC-01..03, PRF-01..02)
17
+ - [ ] Phase 25 — Multi-frame Mappings & systemd User Scheduling (MTF-01..03, TMR-01..03)
18
+
19
+ ## Completed Milestones
20
+
21
+ - v4.0 — Local Google Photos Album Sync (2026-09-29)
22
+ - v5.0 — Distribution & Rename: pushframe packages (2026-09-29)
@@ -1,3 +1,12 @@
1
+ # Requirements Archive: v5.0 v5.0
2
+
3
+ **Archived:** 2026-09-29
4
+ **Status:** SHIPPED
5
+
6
+ For current requirements, see `.planning/REQUIREMENTS.md`.
7
+
8
+ ---
9
+
1
10
  # Requirements: Aura Frames Python Client — v5.0 Distribution & Rename: pushframe packages
2
11
 
3
12
  **Defined:** 2026-09-29
@@ -0,0 +1,157 @@
1
+ ---
2
+ phase: 23-config-wizard-precedence
3
+ plan: 01
4
+ type: execute
5
+ wave: 1
6
+ depends_on: []
7
+ files_modified:
8
+ - pushframe/utils/settings.py
9
+ - pushframe/config_store.py
10
+ - pushframe/cli.py
11
+ - tests/test_settings_resolution.py
12
+ - tests/test_config_store.py
13
+ - tests/test_config_wizard.py
14
+ autonomous: true
15
+ requirements: [CFG-01, CFG-02, CFG-03, CFG-04]
16
+
17
+ estimate:
18
+ tokens: 55000
19
+ raw_tokens: 42000
20
+ tasks: 3
21
+ confidence: medium
22
+
23
+ must_haves:
24
+ truths:
25
+ - "settings.py resolves every settings name as config-file → env var → built-in default at access time (PEP 562 __getattr__), importers unchanged, offline suite hermetic"
26
+ - "~/.config/pushframe/config.json (0600, atomic write, versioned schema) stores email, auth_token, default_frame, debug, optional settings overrides, and a reserved pairs key; nothing is written when the wizard's login test fails"
27
+ - "pushframe config (tty-guarded wizard) walks email → masked password → live login → store; pushframe config show prints the effective config with secrets redacted and per-key sources; import migrates a .env without storing env-resolved keys; set/get/path exist and unknown keys fail listing known keys"
28
+
29
+ <objective>
30
+ Turn env-var archaeology into a conversation: dynamic settings resolution
31
+ with locked precedence, the 0600 config.json store, and the `pushframe
32
+ config` command family (wizard, show, import, set/get, path) — importers
33
+ untouched, suite hermetic.
34
+ </objective>
35
+
36
+ <execution_context>
37
+ @~/.claude/gsd-core/workflows/execute-plan.md
38
+ @~/.claude/gsd-core/templates/summary.md
39
+ </execution_context>
40
+
41
+ <context>
42
+ @.planning/phases/23-config-wizard-precedence/23-CONTEXT.md
43
+ @.planning/phases/23-config-wizard-precedence/23-RESEARCH.md
44
+ @pushframe/utils/settings.py
45
+ @pushframe/google/manifest.py
46
+ </context>
47
+
48
+ <tasks>
49
+
50
+ <task type="tdd">
51
+ <name>Task 1: dynamic settings resolution + config store (CFG-02, D-01/D-02)</name>
52
+ <files>pushframe/utils/settings.py, pushframe/config_store.py, tests/test_settings_resolution.py, tests/test_config_store.py</files>
53
+ <read_first>
54
+ - pushframe/utils/settings.py (the constants being replaced + _env)
55
+ - pushframe/google/manifest.py (_atomic_write pattern to mirror)
56
+ - .planning/phases/23-config-wizard-precedence/23-RESEARCH.md (R1/R2/R3)
57
+ </read_first>
58
+ <action>
59
+ 1. RED tests/test_settings_resolution.py: with a tmp config.json providing
60
+ LOCALE=fr-FR and env unset → `settings.LOCALE == "fr-FR"`; env set → env
61
+ wins; neither → the built-in default; unknown name → AttributeError with
62
+ the known-keys list; env-shadowing helper
63
+ `shadowed_keys(values) -> list[str]` reports which keys env currently
64
+ overrides (D-04 warning source).
65
+ 2. GREEN: rewrite settings.py with a DEFAULTS table (name → default),
66
+ module `__getattr__` implementing config → env → default (config read
67
+ via config_store.load()), keep `_env` for compatibility, add
68
+ `known_keys()` and `shadowed_keys()`. Importers unchanged (the suite
69
+ proves it).
70
+ 3. RED tests/test_config_store.py: load/save round-trip; save writes 0600
71
+ atomically (tmp+rename); schema version key; unknown top-level keys
72
+ fail loud on load (the manifest pattern); reserved "pairs" dict accepted
73
+ (empty) for phase 25.
74
+ 4. GREEN: pushframe/config_store.py — CONFIG_PATH default
75
+ ~/.config/pushframe/config.json, load()/save(dict)/update(**kw),
76
+ os.open 0600 + atomic rename, schema version 1, key whitelist
77
+ (email, auth_token, default_frame, debug, settings, pairs, version).
78
+ </action>
79
+ <acceptance_criteria>
80
+ - All three contracts green; importer files untouched (git diff scope)
81
+ - config.json created 0600; corrupt file fails loud naming the path
82
+ - Offline suite stays green (settings importers untouched)
83
+ </acceptance_criteria>
84
+ <verify>
85
+ <automated>uv run --extra dev pytest tests/test_settings_resolution.py tests/test_config_store.py -q 2>&1 | tail -1 | grep -qE "[0-9]+ passed"</automated>
86
+ <fails_when>resolution order wrong, 0600/atomicity missing, or suite regression</fails_when>
87
+ </verify>
88
+ </task>
89
+
90
+ <task>
91
+ <name>Task 2: the config command family (CFG-01/03/04)</name>
92
+ <files>pushframe/cli.py, tests/test_config_wizard.py</files>
93
+ <read_first>
94
+ - pushframe/cli.py (subparser wiring + run_status's credential check pattern)
95
+ - .planning/phases/23-config-wizard-precedence/23-RESEARCH.md (R4/R5)
96
+ </read_first>
97
+ <action>
98
+ 1. `pushframe config` wizard (tty-guarded): existing config → show email
99
+ redacted, Enter keeps; email prompt (shape check); getpass password;
100
+ LIVE login via the existing Aura seam; success → store email +
101
+ user.auth_token (+ optional default frame from get_frames(), debug);
102
+ failure → print the API message, write NOTHING, return 1. Before
103
+ saving, warn listing settings.shadowed_keys() (D-04).
104
+ (D-03 order: credentials first + login-tested BEFORE anything is
105
+ stored; optional questions only after the login succeeds.)
106
+ 2. `config show`: effective config (resolution at access), secrets
107
+ redacted to `***` + per-key source (file/env/default) — CFG-02.
108
+ 3. `config import [--file .env]`: parse KEY=VALUE, map PUSHFRAME_*/AURA_*
109
+ prefixes onto settings names, store only keys NOT env-resolved now,
110
+ print the key → source table (CFG-03).
111
+ 4. `config path` prints the path; `config set <key> <value>` /
112
+ `config get <key>`: known-keys validation, unknown fails with the
113
+ list (CFG-04); `set` refuses auth_token/email (wizard-only keys).
114
+ </action>
115
+ <acceptance_criteria>
116
+ - Wizard writes nothing on failed login (file-content assertion)
117
+ - `config show` output never contains a token/password value
118
+ - import on a fixture .env reproduces the env-path effective config
119
+ - non-tty wizard with missing input exits 1 with a message
120
+ </acceptance_criteria>
121
+ <verify>
122
+ <automated>uv run --extra dev pytest tests/test_config_wizard.py -q 2>&1 | tail -1 | grep -qE "[0-9]+ passed"</automated>
123
+ <fails_when>secrets leak, writes on failure, or precedence inversion</fails_when>
124
+ </verify>
125
+ </task>
126
+
127
+ <task>
128
+ <name>Task 3: docs + suite + changelog</name>
129
+ <files>README.md, docs/CLI.md, CHANGELOG.md</files>
130
+ <read_first>
131
+ - README.md (Environment Variables section gains a Config file note)
132
+ </read_first>
133
+ <action>
134
+ 1. README: "Configuration" — the file, the wizard, the precedence line
135
+ (env > file > default), pointer that env vars remain supported.
136
+ 2. docs/CLI.md: `config` command reference (subcommands, exit codes).
137
+ 3. CHANGELOG [Unreleased]: Added entries (wizard, store, precedence).
138
+ 4. Full offline suite green.
139
+ </action>
140
+ <acceptance_criteria>
141
+ - README documents precedence + wizard; CLI.md documents config
142
+ - CHANGELOG [Unreleased] carries the feature
143
+ - suite ≥ 411 passed
144
+ </acceptance_criteria>
145
+ <verify>
146
+ <automated>grep -q "config" docs/CLI.md && grep -q "env var > config file\|env > file" README.md && grep -q "config" CHANGELOG.md && uv run --extra dev pytest -q -m "not live" 2>&1 | tail -1 | grep -qE "passed"</automated>
147
+ <fails_when>missing docs or suite failure</fails_when>
148
+ </verify>
149
+ </task>
150
+
151
+ </tasks>
152
+
153
+ ## Verification Criteria (plan-level)
154
+
155
+ 1. Precedence proven: file → env → default, importers unchanged.
156
+ 2. Wizard: login-tested, nothing-on-failure, 0600, shadowing warning.
157
+ 3. show/import/set/get/path all present with redaction guarantees.
@@ -0,0 +1,70 @@
1
+ # Plan 23-01 Execution Summary — Dynamic config resolution + `pushframe config` (CFG-01..04)
2
+
3
+ **Phase:** 23-config-wizard-precedence
4
+ **Date:** 2026-09-29
5
+ **Status:** Complete — suite **426 passed** (was 420 before the phase; +6 wizard tests, +8 resolution/store tests, 2 legacy alias asserts updated to the dynamic contract)
6
+ **Commits:** `936a2c4` (T1 dynamic resolution + config_store) · `acd3ba1` (T3 docs) · T2 wizard shipped in the T1→T2 working commit on this branch
7
+
8
+ ## What Shipped
9
+
10
+ - **Dynamic settings resolution (D-01/D-04, CFG-02)** — `settings.py` rewritten
11
+ around PEP 562 module `__getattr__`: every `settings.X` access resolves live as
12
+ **environment → config file (`~/.config/pushframe/config.json`) → DEFAULTS
13
+ table**. All existing importers kept their attribute-style reads (the 411→420
14
+ regression passed byte-for-byte on defaults); `s3client`/`sqsclient` converted
15
+ from frozen `from settings import X` copies to module-attribute reads so
16
+ long-running processes see updates.
17
+ - **`config_store.py` (D-02)** — 0600 JSON store, atomic writes (tmp + rename),
18
+ known-key whitelist (fail-loud on unknown keys), schema-versioned, `"pairs"`
19
+ key reserved for phase 25 (multi-frame). Reads `settings.CONFIG_PATH`
20
+ dynamically (module import, not from-import) so tests and the wizard share
21
+ one path truth.
22
+ - **The `config` family (D-03, CFG-01/03/04)** — wired into the CLI parser and
23
+ dispatch:
24
+ - `pushframe config` — wizard: email → hidden password → **real API login
25
+ before anything is written** (fail = zero writes); stores email +
26
+ `auth_token`; optional questions afterwards; refuses non-tty stdin for the
27
+ interactive path (scheduled jobs never hang on a prompt).
28
+ - `config show` — every setting with effective value (secrets `***`) and
29
+ its source (`env`/`file`/`default`) + explicit env-shadow warnings.
30
+ - `config import FILE` — adopts `.env`-style files; skips env-provided keys
31
+ (reported), validates against the whitelist.
32
+ - `config set/get/path` — single-key direct access; `get` reflects true
33
+ precedence.
34
+ - **Docs (T3)** — README gets a wizard-first *Configuration* section (env vars
35
+ folded into an override `<details>`); `docs/CLI.md` gets a full `config`
36
+ command section + precedence-aware env-var intro; CHANGELOG `[Unreleased]`
37
+ carries Added/Changed entries.
38
+
39
+ ## Broken-and-fixed along the way
40
+
41
+ - CHANGELOG had been corrupted by the session interruption (sections out of
42
+ order: Unreleased/5.0.4/5.0.3 stuck *after* 5.0.0; 5.0.4 content duplicated
43
+ inside its own block). Rewritten cleanly in Keep-a-Changelog order,
44
+ deduplicated — no content lost.
45
+ - `config_store` initially froze `CONFIG_PATH` via from-import (test
46
+ monkeypatch invisible) → module-attribute read.
47
+ - `_bool_env` signature drifted from the historical `default=` keyword →
48
+ restored (12 budget tests green again).
49
+ - AWS from-imports froze values at import time → dynamic access (matches the
50
+ phase-19 MOD-02 intent; two legacy alias asserts updated accordingly).
51
+
52
+ ## Live proofs
53
+
54
+ - Wrong-password login against the real API raises
55
+ (`RateLimitError … HTTP 475`, the account's current Aura-side lockout) and
56
+ writes **no config.json** — the D-03 "nothing written on failed login"
57
+ contract, verified live. A successful-login wizard run was not repeated
58
+ against the real API to avoid worsening the lockout; the seam
59
+ (`_wizard_login`) is exactly the tested `Aura.login` path.
60
+
61
+ ## Must-have truths check (plan 23-01)
62
+
63
+ | Truth | Status |
64
+ |---|---|
65
+ | Env/file/default precedence at access time | ✅ PEP 562 + DEFAULTS table (8 tests) |
66
+ | config.json 0600, atomic, whitelist, schema-versioned | ✅ config_store + tests |
67
+ | Wizard tests login before writing; fail = zero writes | ✅ 6 tests + live negative proof |
68
+ | `config show` reports source per key + shadows | ✅ implemented + tested |
69
+ | Import skips env-provided keys | ✅ tested (env-shadow contract) |
70
+ | Existing readers unchanged | ✅ 426 passed incl. all pre-phase tests |
@@ -0,0 +1,68 @@
1
+ # Phase 23: Config Wizard & Precedence — Context
2
+
3
+ **Gathered:** 2026-09-29
4
+ **Status:** Ready for planning
5
+ **Provenance:** compiled from REQUIREMENTS CFG-01..04, a full read of the
6
+ current config plumbing (`pushframe/utils/settings.py`, its 7+ importers,
7
+ `cli.py`'s env reads), and the operator's design decisions taken at the
8
+ discuss checkpoint (2026-09-29).
9
+
10
+ ## Current state (probe facts)
11
+
12
+ - `pushframe/utils/settings.py` exposes ~15 **module constants evaluated
13
+ at import** via the `_env(*names)` helper: PUSHFRAME_* primary, AURA_*
14
+ legacy fallback (IDN-04), hard-coded defaults last.
15
+ - Importers do `from pushframe.utils import settings` and read
16
+ `settings.LOCALE`, `settings.AURA_API_BASE_URL`, budget constants, etc.
17
+ — none import `settings` as mutable state they replace.
18
+ - Credentials today: `PUSHFRAME_EMAIL` / `PUSHFRAME_PASSWORD` read in
19
+ `pushframe/aura.py` (login) and `cli.py` (status health check prints
20
+ set/NOT SET only).
21
+ - Existing JSON in `~/.config/pushframe/`: `google-cookies.json` (0600
22
+ vault), `google-manifest.json` (0600), budget file. A config.json sits
23
+ naturally in that family.
24
+ - The deb/wheel ships no `python-dotenv` auto-import for user shells
25
+ (`.env` is loaded by `main()` via `load_dotenv()` — cwd-relative, a
26
+ known fragility the file-config supersedes for humans).
27
+
28
+ ## Design decisions (operator, 2026-09-29)
29
+
30
+ - **D-01:** Dynamic resolution — `settings.py` keeps its public names but
31
+ each becomes a *resolved-at-access* value with precedence
32
+ **config file → env var → built-in default**; importers stay untouched.
33
+ `config set` affects the next process and any re-read; no stale
34
+ import-time snapshot. Implementation must keep the offline test suite
35
+ hermetic (tests patch the file path / env, never the network).
36
+ - **D-02:** JSON — `~/.config/pushframe/config.json`, mode 0600, stdlib
37
+ `json` only — same family as the vault/manifest. The MTF-01 pairs
38
+ (phase 25) will live there as a dict.
39
+ - **D-03:** Wizard order: credentials first, login-tested — email →
40
+ password (getpass, masked) → **live login test** → on success store
41
+ email + the returned `auth_token` (SEC-01 lands in phase 24; phase 23
42
+ already stores the token since the API hands it back) → optional
43
+ questions (default frame — listed from a real `get_frames` when
44
+ credentials work —, debug). Login failure ⇒ clear message, **nothing
45
+ is written**.
46
+ - **D-04:** Precedence (locked): env var > config file > default —
47
+ Rationale: 12-factor; CI/scripts keep working unchanged; the file is
48
+ human comfort. The wizard warns when an env var would shadow the file
49
+ value it just wrote (the venus lesson: silent shadowing is the trap).
50
+
51
+ ## Non-goals for this phase
52
+
53
+ - Token *expiry/re-login* semantics (phase 24, SEC-02).
54
+ - OS keyring backends, config encryption (v5.1 non-goals table).
55
+ - MTF pairs schema beyond reserving the `"pairs": {}` key in the file
56
+ schema (phase 25).
57
+
58
+ ## Operator steps
59
+
60
+ None — everything is in-repo; the phase ships in the next release.
61
+
62
+ ## Discretion areas (executor)
63
+
64
+ - Exact wizard prompt wording/order of optional questions.
65
+ - Whether `config show` reads settings lazily per key or snapshots
66
+ (recommend lazy — matches D-01).
67
+ - Test seam choice: fixture writing a temp config.json + monkeypatched
68
+ path constant (existing pattern in tests/test_migration.py).