cc-session-tools 3.12.1__tar.gz → 3.12.2__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 (304) hide show
  1. {cc_session_tools-3.12.1/src/cc_session_tools.egg-info → cc_session_tools-3.12.2}/PKG-INFO +1 -1
  2. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/pyproject.toml +1 -1
  3. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/readiness.py +16 -0
  4. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-pdata-do-audit-and-prepare-to-migrate/SKILL.md +2 -2
  5. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2/src/cc_session_tools.egg-info}/PKG-INFO +1 -1
  6. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools.egg-info/SOURCES.txt +1 -0
  7. cc_session_tools-3.12.2/tests/test_date_format_conformance.py +140 -0
  8. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/LICENSE +0 -0
  9. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/README.md +0 -0
  10. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/setup.cfg +0 -0
  11. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/__init__.py +0 -0
  12. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/__init__.py +0 -0
  13. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/ccd.py +0 -0
  14. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/ccmsg.py +0 -0
  15. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/ccr.py +0 -0
  16. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/ccs.py +0 -0
  17. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/ccsched.py +0 -0
  18. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/ccst.py +0 -0
  19. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/migrate_ccmsg.py +0 -0
  20. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/migrate_ccsched.py +0 -0
  21. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/migrate_sessions_db.py +0 -0
  22. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/cli/migrate_telemetry.py +0 -0
  23. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/config/api-keys.example +0 -0
  24. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/config/hooks-bundle.json +0 -0
  25. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/config/session-tag-hook.json +0 -0
  26. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/hooks_install.py +0 -0
  27. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/__init__.py +0 -0
  28. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/api_keys.py +0 -0
  29. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/bun_tools.py +0 -0
  30. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/claude_flags.py +0 -0
  31. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/claude_md_install.py +0 -0
  32. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/context_overrides.py +0 -0
  33. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/db.py +0 -0
  34. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/debug.py +0 -0
  35. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/doctor.py +0 -0
  36. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/doctor_mutes.py +0 -0
  37. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/hook_registry.py +0 -0
  38. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/install_sync.py +0 -0
  39. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/levenshtein.py +0 -0
  40. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/machine_identity.py +0 -0
  41. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/__init__.py +0 -0
  42. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/addressing.py +0 -0
  43. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/cursor.py +0 -0
  44. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/lock.py +0 -0
  45. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/message.py +0 -0
  46. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/move_safety.py +0 -0
  47. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/repository.py +0 -0
  48. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/retention.py +0 -0
  49. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/service.py +0 -0
  50. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/messaging/store.py +0 -0
  51. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/occupancy.py +0 -0
  52. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/paths.py +0 -0
  53. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/__init__.py +0 -0
  54. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/backup.py +0 -0
  55. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/classify.py +0 -0
  56. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/cutover.py +0 -0
  57. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/dump.py +0 -0
  58. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/formatting.py +0 -0
  59. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/importers.py +0 -0
  60. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/init_paths.py +0 -0
  61. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/init_service.py +0 -0
  62. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/manifest.py +0 -0
  63. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/naming.py +0 -0
  64. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/rehydrate.py +0 -0
  65. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/rename_group.py +0 -0
  66. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/reorganize.py +0 -0
  67. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/repository.py +0 -0
  68. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/resolve.py +0 -0
  69. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/service.py +0 -0
  70. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/session_output.py +0 -0
  71. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/store.py +0 -0
  72. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/sync_check.py +0 -0
  73. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/sync_lock.py +0 -0
  74. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/sync_notify.py +0 -0
  75. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/vector_clock.py +0 -0
  76. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/vector_clock_store.py +0 -0
  77. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/verify.py +0 -0
  78. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/pdata/write_log.py +0 -0
  79. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/picker.py +0 -0
  80. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/proc_lock.py +0 -0
  81. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/prompts.py +0 -0
  82. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/roots.py +0 -0
  83. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/rules.py +0 -0
  84. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/__init__.py +0 -0
  85. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/bundled_jobs.py +0 -0
  86. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/cadence.py +0 -0
  87. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/cursor.py +0 -0
  88. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/digest.py +0 -0
  89. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/due.py +0 -0
  90. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/duration.py +0 -0
  91. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/jobspec.py +0 -0
  92. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/ledger.py +0 -0
  93. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/lock.py +0 -0
  94. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/notify.py +0 -0
  95. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/reconcile.py +0 -0
  96. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/registry.py +0 -0
  97. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/runner.py +0 -0
  98. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/state.py +0 -0
  99. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/store.py +0 -0
  100. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/surface.py +0 -0
  101. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/throttle.py +0 -0
  102. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/scheduler/worker.py +0 -0
  103. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/session_gc.py +0 -0
  104. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/sessions.py +0 -0
  105. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/sessions_db.py +0 -0
  106. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/sessions_repair.py +0 -0
  107. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/shell_install.py +0 -0
  108. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/tasklist.py +0 -0
  109. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/telemetry_store.py +0 -0
  110. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/text_wrap.py +0 -0
  111. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/lib/timefmt.py +0 -0
  112. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/analyse-cc-usage/SKILL.md +0 -0
  113. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/clean-hook-sessions/SKILL.md +0 -0
  114. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/clean-hook-sessions/scripts/clean-hook-sessions.py +0 -0
  115. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/compact-smart/SKILL.md +0 -0
  116. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/context-override/SKILL.md +0 -0
  117. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/delete-sessions/SKILL.md +0 -0
  118. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/delete-sessions/scripts/delete_sessions.py +0 -0
  119. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/do-executor-critic-assessor-loop/SKILL.md +0 -0
  120. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/extract-pptx/SKILL.md +0 -0
  121. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/extract-pptx/scripts/extract_pptx.py +0 -0
  122. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/extract-to-text/SKILL.md +0 -0
  123. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/extract-to-text/scripts/extract_to_text.py +0 -0
  124. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/find-claude-code-session/SKILL.md +0 -0
  125. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/generate-8digit-code/SKILL.md +0 -0
  126. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/generate-8digit-code/scripts/generate_8digit_code.py +0 -0
  127. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/list-empty-sessions/SKILL.md +0 -0
  128. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/list-empty-sessions/scripts/list_empty_sessions.py +0 -0
  129. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/manage-recurring-cc-jobs-using-ccsched/SKILL.md +0 -0
  130. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/move-session/SKILL.md +0 -0
  131. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/move-session/hooks/sessionstart-pending-rename.sh +0 -0
  132. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/move-session/scripts/cc_session_rules.py +0 -0
  133. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/move-session/scripts/move_session.py +0 -0
  134. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-pdata-design-schema/SKILL.md +0 -0
  135. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-pdata-do-init/SKILL.md +0 -0
  136. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-pdata-do-manual-migration/SKILL.md +0 -0
  137. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-pdata-do-update-consuming-skills/SKILL.md +0 -0
  138. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-pdata-do-update-project-docs/SKILL.md +0 -0
  139. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-pdata-resolve-conflicts/SKILL.md +0 -0
  140. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-project-layout-reference/SKILL.md +0 -0
  141. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/pm-update-central-files/SKILL.md +0 -0
  142. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/reduce-persistent-context/CALIBRATION.md +0 -0
  143. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/reduce-persistent-context/SKILL.md +0 -0
  144. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/analyze_context.py +0 -0
  145. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/duplicates.py +0 -0
  146. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/measure.py +0 -0
  147. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/report.py +0 -0
  148. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/tokens.py +0 -0
  149. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/usage.py +0 -0
  150. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/select-agent-model/SKILL.md +0 -0
  151. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/send-session-message/SKILL.md +0 -0
  152. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/update-command-cache/SKILL.md +0 -0
  153. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools/skills/update-command-cache/scripts/update_command_cache.py +0 -0
  154. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools.egg-info/dependency_links.txt +0 -0
  155. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools.egg-info/entry_points.txt +0 -0
  156. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools.egg-info/requires.txt +0 -0
  157. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/cc_session_tools.egg-info/top_level.txt +0 -0
  158. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/__init__.py +0 -0
  159. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/attribution.py +0 -0
  160. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/cache.py +0 -0
  161. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/ccusage_wrapper.py +0 -0
  162. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/cli.py +0 -0
  163. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/data/pricing.json +0 -0
  164. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/parent_inference.py +0 -0
  165. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/parser.py +0 -0
  166. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/pricing.py +0 -0
  167. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/query.py +0 -0
  168. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/report.py +0 -0
  169. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/schema.py +0 -0
  170. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/claude_code_usage/session_names.py +0 -0
  171. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/__init__.py +0 -0
  172. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/after_response.py +0 -0
  173. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/bash_hard_deny.py +0 -0
  174. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/bash_security_review.py +0 -0
  175. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/cache.py +0 -0
  176. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/catchup.py +0 -0
  177. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/confirm_8digit.py +0 -0
  178. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/context_window_warning.py +0 -0
  179. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/last_screenshot.py +0 -0
  180. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/marker_allow.py +0 -0
  181. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/markers.py +0 -0
  182. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/messaging_deliver.py +0 -0
  183. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/model_info.py +0 -0
  184. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/normalise.py +0 -0
  185. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/pdata_sync.py +0 -0
  186. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/pending_migration.py +0 -0
  187. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/pending_rename.py +0 -0
  188. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/script_allowlist.py +0 -0
  189. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/session_tag.py +0 -0
  190. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/stats.py +0 -0
  191. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/telemetry.py +0 -0
  192. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/telemetry_query.py +0 -0
  193. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/telemetry_trim.py +0 -0
  194. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/transcript.py +0 -0
  195. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/src/hooks/worklog_guard.py +0 -0
  196. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_after_response.py +0 -0
  197. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_api_keys.py +0 -0
  198. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_attribution.py +0 -0
  199. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_bash_hard_deny.py +0 -0
  200. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_bash_security_review.py +0 -0
  201. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_bash_security_review_allowlist.py +0 -0
  202. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_bun_tools.py +0 -0
  203. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cache.py +0 -0
  204. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cache_sqlite.py +0 -0
  205. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccr_orphans.py +0 -0
  206. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccs_emptiness.py +0 -0
  207. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccs_eta.py +0 -0
  208. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccs_list_mode.py +0 -0
  209. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccs_scope_flags.py +0 -0
  210. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccs_sentinel_sort.py +0 -0
  211. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccs_session_counts.py +0 -0
  212. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_bundle_discovery.py +0 -0
  213. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_ccsched_jobs_cli.py +0 -0
  214. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_cli.py +0 -0
  215. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_context_override_cli.py +0 -0
  216. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_doctor.py +0 -0
  217. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_gc_prune.py +0 -0
  218. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_gc_report.py +0 -0
  219. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_hook_dispatcher.py +0 -0
  220. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_hooks_allowlist.py +0 -0
  221. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_hooks_install_prune.py +0 -0
  222. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_hooks_install_zero_arg.py +0 -0
  223. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_hooks_uninstall.py +0 -0
  224. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_install_everything.py +0 -0
  225. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_machine_identity_cli.py +0 -0
  226. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_main_gate.py +0 -0
  227. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_pdata_cli.py +0 -0
  228. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_pdata_init_cli.py +0 -0
  229. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_pdata_readiness_cli.py +0 -0
  230. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_pdata_reconcile_cli.py +0 -0
  231. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_pdata_rename_group_cli.py +0 -0
  232. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_pdata_reorganize_cli.py +0 -0
  233. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_pdata_sync_cli.py +0 -0
  234. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_pdata_verify_cli.py +0 -0
  235. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_repair_sessions_cli.py +0 -0
  236. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_sessions_cli.py +0 -0
  237. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_shell_install.py +0 -0
  238. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_skills_install.py +0 -0
  239. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_skills_uninstall.py +0 -0
  240. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_telemetry_query.py +0 -0
  241. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccst_telemetry_trim.py +0 -0
  242. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_ccusage_wrapper.py +0 -0
  243. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_claude_flags.py +0 -0
  244. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_claude_md_install.py +0 -0
  245. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_clean_hook_sessions_format.py +0 -0
  246. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cli.py +0 -0
  247. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cli_api_launchers.py +0 -0
  248. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cli_ccd.py +0 -0
  249. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cli_ccd_dry_run.py +0 -0
  250. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cli_ccr.py +0 -0
  251. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cli_ccs.py +0 -0
  252. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_cli_version.py +0 -0
  253. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_confirm_8digit.py +0 -0
  254. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_context_overrides.py +0 -0
  255. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_context_window_warning.py +0 -0
  256. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_db.py +0 -0
  257. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_debug.py +0 -0
  258. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_doctor_mutes.py +0 -0
  259. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_empty_session.py +0 -0
  260. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_hook_cache.py +0 -0
  261. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_hooks_install.py +0 -0
  262. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_hooks_install_records.py +0 -0
  263. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_install_sync.py +0 -0
  264. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_last_screenshot.py +0 -0
  265. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_levenshtein.py +0 -0
  266. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_machine_identity.py +0 -0
  267. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_marker_allow.py +0 -0
  268. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_migrate_ccmsg.py +0 -0
  269. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_migrate_ccsched.py +0 -0
  270. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_migrate_sessions_db.py +0 -0
  271. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_migrate_telemetry.py +0 -0
  272. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_model_info.py +0 -0
  273. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_normalise.py +0 -0
  274. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_occupancy.py +0 -0
  275. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_parent_inference.py +0 -0
  276. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_parser.py +0 -0
  277. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_paths.py +0 -0
  278. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_pdata_audit_skill.py +0 -0
  279. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_pdata_post_migration_skills.py +0 -0
  280. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_pending_migration_hook.py +0 -0
  281. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_picker.py +0 -0
  282. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_pricing.py +0 -0
  283. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_proc_lock.py +0 -0
  284. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_prompts.py +0 -0
  285. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_query.py +0 -0
  286. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_report.py +0 -0
  287. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_roots.py +0 -0
  288. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_rules.py +0 -0
  289. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_scheduler_bundled_jobs.py +0 -0
  290. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_schema.py +0 -0
  291. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_script_allowlist.py +0 -0
  292. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_session_names.py +0 -0
  293. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_session_tag.py +0 -0
  294. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_sessions.py +0 -0
  295. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_sessions_db.py +0 -0
  296. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_sessions_db_migration_chain.py +0 -0
  297. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_sessions_repair.py +0 -0
  298. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_tasklist.py +0 -0
  299. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_telemetry.py +0 -0
  300. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_telemetry_store.py +0 -0
  301. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_text_wrap.py +0 -0
  302. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_timefmt.py +0 -0
  303. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_transcript.py +0 -0
  304. {cc_session_tools-3.12.1 → cc_session_tools-3.12.2}/tests/test_worklog_guard.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-session-tools
3
- Version: 3.12.1
3
+ Version: 3.12.2
4
4
  Summary: Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (hooks package)
5
5
  Author: raffishquartan
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cc-session-tools"
7
- version = "3.12.1"
7
+ version = "3.12.2"
8
8
  description = "Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (hooks package)"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -89,10 +89,26 @@ def _is_real_yyyymmdd(value: str) -> bool:
89
89
  return 1900 <= parsed.year <= 2100
90
90
 
91
91
 
92
+ _COMPACT_DATETIME = re.compile(r"(\d{8})T(\d{2})(\d{2})(\d{2})?Z?")
93
+
94
+
95
+ def _is_compact_datetime(value: str) -> bool:
96
+ match = _COMPACT_DATETIME.fullmatch(value)
97
+ if match is None:
98
+ return False
99
+ date_part, hour, minute, second = match.groups()
100
+ return (
101
+ _is_real_yyyymmdd(date_part)
102
+ and int(hour) <= 23 and int(minute) <= 59 and int(second or 0) <= 59
103
+ )
104
+
105
+
92
106
  def _date_format(value: str) -> str | None:
93
107
  for name, pattern in _DATE_FORMATS:
94
108
  if pattern.match(value):
95
109
  return name
110
+ if _is_compact_datetime(value):
111
+ return "compact-datetime"
96
112
  return "yyyymmdd" if _is_real_yyyymmdd(value) else None
97
113
 
98
114
 
@@ -57,8 +57,8 @@ ccst pdata readiness-scan --project <name> --path <domain-dir>/ --findings-only
57
57
  ```
58
58
 
59
59
  It is read-only and deterministic. It reports, per CSV, `ragged-rows`, `bad-header`,
60
- `mixed-date-formats`, `non-iso-dates` (any dotted `yyyy.MM.dd`, compact `yyyyMMdd`, slash or
61
- long-form value, even when the whole column uses it; advisory, since an 8-digit identifier that
60
+ `mixed-date-formats`, `non-iso-dates` (any dotted `yyyy.MM.dd`, compact `yyyyMMdd` or `yyyyMMddTHHmm`, slash
61
+ or long-form value, even when the whole column uses it; advisory, since an 8-digit identifier that
62
62
  is a real date is flagged too), `mixed-separators` (`|` with `;` only), `machine-paths`, `null-strings`,
63
63
  `duplicate-rows`, `comment-rows`, `repeated-header`, `no-unique-column`, `bom`, `crlf` and
64
64
  `unreadable`, plus row counts and unique columns. Treat findings as leads to verify, not facts to
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-session-tools
3
- Version: 3.12.1
3
+ Version: 3.12.2
4
4
  Summary: Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (hooks package)
5
5
  Author: raffishquartan
6
6
  License: MIT License
@@ -250,6 +250,7 @@ tests/test_cli_version.py
250
250
  tests/test_confirm_8digit.py
251
251
  tests/test_context_overrides.py
252
252
  tests/test_context_window_warning.py
253
+ tests/test_date_format_conformance.py
253
254
  tests/test_db.py
254
255
  tests/test_debug.py
255
256
  tests/test_doctor_mutes.py
@@ -0,0 +1,140 @@
1
+ """Every date format string under src/ is a convention form or a listed exemption.
2
+
3
+ The convention: filenames and folder names use `yyyy.MM.dd`; everything else is ISO `yyyy-MM-dd`
4
+ (`yyyy-MM-dd HH:mm` for a time of day, ISO 8601 with `T` and `Z` for machine timestamps).
5
+ A new format string must be added to ALLOWED below with one of the REASONS, or the test fails; an
6
+ entry that no longer matches a format string in src/ must be deleted.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import ast
11
+ import re
12
+ from pathlib import Path
13
+
14
+ SRC = Path(__file__).parent.parent / "src"
15
+
16
+ REASONS = {
17
+ "machine-iso": "stored, compared or exchanged timestamp: ISO 8601 with T and Z",
18
+ "identifier": "session tag or other identifier that contains a date",
19
+ "backup-stamp": "backup, snapshot or migration stamp in a file name",
20
+ "human-iso": "printed for a human in the ISO text form",
21
+ "folder-name": "year or month folder name",
22
+ "time-only": "time of day with no date",
23
+ "input-parse": "accepts a user-supplied value, writes nothing",
24
+ "detection-parse": "recognises a value in data, writes nothing",
25
+ }
26
+
27
+ _MACHINE = "%Y-%m-%dT%H:%M:%SZ"
28
+ _HUMAN = "%Y-%m-%d %H:%M"
29
+ _BACKUP_UTC = "%Y%m%dT%H%M%SZ"
30
+
31
+ ALLOWED: dict[tuple[str, str], str] = {
32
+ ("cc_session_tools/cli/ccd.py", "%Y%m%d"): "identifier",
33
+ ("cc_session_tools/cli/ccr.py", _HUMAN): "human-iso",
34
+ ("cc_session_tools/cli/ccs.py", "%Y%m%d"): "identifier",
35
+ ("cc_session_tools/cli/ccs.py", "%Y-%m-%d"): "input-parse",
36
+ ("cc_session_tools/cli/ccs.py", _HUMAN): "human-iso",
37
+ ("cc_session_tools/cli/ccs.py", "%Y-%m-%dT%H:%M"): "input-parse",
38
+ ("cc_session_tools/cli/ccs.py", "%Y-%m-%dT%H:%M:%S"): "input-parse",
39
+ ("cc_session_tools/cli/ccsched.py", _MACHINE): "machine-iso",
40
+ ("cc_session_tools/cli/ccst.py", "%Y%m%d%H%M%S"): "backup-stamp",
41
+ ("cc_session_tools/cli/ccst.py", _BACKUP_UTC): "backup-stamp",
42
+ ("cc_session_tools/cli/ccst.py", _HUMAN): "human-iso",
43
+ ("cc_session_tools/cli/migrate_ccmsg.py", _BACKUP_UTC): "backup-stamp",
44
+ ("cc_session_tools/cli/migrate_ccsched.py", _BACKUP_UTC): "backup-stamp",
45
+ ("cc_session_tools/cli/migrate_ccsched.py", _MACHINE): "machine-iso",
46
+ ("cc_session_tools/cli/migrate_sessions_db.py", _BACKUP_UTC): "backup-stamp",
47
+ ("cc_session_tools/cli/migrate_telemetry.py", _BACKUP_UTC): "backup-stamp",
48
+ ("cc_session_tools/lib/install_sync.py", _MACHINE): "machine-iso",
49
+ ("cc_session_tools/lib/messaging/repository.py", _MACHINE): "machine-iso",
50
+ ("cc_session_tools/lib/messaging/retention.py", _MACHINE): "machine-iso",
51
+ ("cc_session_tools/lib/messaging/service.py", _MACHINE): "machine-iso",
52
+ ("cc_session_tools/lib/messaging/store.py", _BACKUP_UTC): "backup-stamp",
53
+ ("cc_session_tools/lib/pdata/backup.py", "%Y%m%d-%H%M%S"): "backup-stamp",
54
+ ("cc_session_tools/lib/pdata/dump.py", _HUMAN): "human-iso",
55
+ ("cc_session_tools/lib/pdata/init_service.py", _MACHINE): "machine-iso",
56
+ ("cc_session_tools/lib/pdata/readiness.py", "%Y%m%d"): "detection-parse",
57
+ ("cc_session_tools/lib/pdata/reorganize.py", "%Y"): "folder-name",
58
+ ("cc_session_tools/lib/pdata/reorganize.py", "%m"): "folder-name",
59
+ ("cc_session_tools/lib/proc_lock.py", _MACHINE): "machine-iso",
60
+ ("cc_session_tools/lib/scheduler/cursor.py", _MACHINE): "machine-iso",
61
+ ("cc_session_tools/lib/scheduler/registry.py", _MACHINE): "machine-iso",
62
+ ("cc_session_tools/lib/scheduler/state.py", _MACHINE): "machine-iso",
63
+ ("cc_session_tools/lib/scheduler/surface.py", _MACHINE): "machine-iso",
64
+ ("cc_session_tools/lib/sessions_db.py", _MACHINE): "machine-iso",
65
+ ("cc_session_tools/lib/telemetry_store.py", _MACHINE): "machine-iso",
66
+ ("cc_session_tools/lib/timefmt.py", "%Y-%m-%d %H:%M UTC"): "human-iso",
67
+ ("cc_session_tools/skills/clean-hook-sessions/scripts/clean-hook-sessions.py",
68
+ "%Y%m%d-%H%M%S"): "backup-stamp",
69
+ ("cc_session_tools/skills/clean-hook-sessions/scripts/clean-hook-sessions.py",
70
+ _HUMAN): "human-iso",
71
+ ("cc_session_tools/skills/move-session/scripts/move_session.py",
72
+ "%Y%m%d-%H%M%S"): "backup-stamp",
73
+ ("cc_session_tools/skills/move-session/scripts/move_session.py",
74
+ "%Y-%m-%dT%H:%M:%S.%f"): "machine-iso",
75
+ ("claude_code_usage/query.py", "%Y"): "human-iso",
76
+ ("claude_code_usage/query.py", "%Y-%m"): "human-iso",
77
+ ("claude_code_usage/query.py", "%Y-%m-%d"): "human-iso",
78
+ ("hooks/bash_security_review.py", "%Y%m%d-%H%M"): "identifier",
79
+ ("hooks/cache.py", _MACHINE): "machine-iso",
80
+ ("hooks/cache.py", f"strftime('{_MACHINE}', datetime('now', ?))"): "machine-iso",
81
+ ("hooks/context_window_warning.py", "%H:%M"): "time-only",
82
+ ("hooks/session_tag.py", "%Y%m%d"): "identifier",
83
+ ("hooks/telemetry_query.py", _MACHINE): "machine-iso",
84
+ ("hooks/telemetry_trim.py", _MACHINE): "machine-iso",
85
+ }
86
+
87
+ # A year, month, hour, minute, second or fraction directive. Bare %d/%s are logging placeholders.
88
+ _DIRECTIVE = re.compile(r"%[YymHMSfBb]")
89
+ _MAX_FORMAT_LENGTH = 80
90
+
91
+
92
+ def _docstring_ids(tree: ast.AST) -> set[int]:
93
+ ids: set[int] = set()
94
+ for node in ast.walk(tree):
95
+ if isinstance(node, (ast.Module, ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
96
+ first = node.body[0] if node.body else None
97
+ if (
98
+ isinstance(first, ast.Expr)
99
+ and isinstance(first.value, ast.Constant)
100
+ and isinstance(first.value.value, str)
101
+ ):
102
+ ids.add(id(first.value))
103
+ return ids
104
+
105
+
106
+ def _format_strings() -> set[tuple[str, str]]:
107
+ found: set[tuple[str, str]] = set()
108
+ for path in sorted(SRC.rglob("*.py")):
109
+ if "tests" in path.relative_to(SRC).parts:
110
+ continue
111
+ tree = ast.parse(path.read_text(encoding="utf-8"))
112
+ docstrings = _docstring_ids(tree)
113
+ for node in ast.walk(tree):
114
+ if (
115
+ isinstance(node, ast.Constant)
116
+ and isinstance(node.value, str)
117
+ and id(node) not in docstrings
118
+ and len(node.value) < _MAX_FORMAT_LENGTH
119
+ and _DIRECTIVE.search(node.value)
120
+ ):
121
+ found.add((path.relative_to(SRC).as_posix(), node.value))
122
+ return found
123
+
124
+
125
+ def test_every_allowlist_entry_has_a_known_reason() -> None:
126
+ assert set(ALLOWED.values()) <= set(REASONS)
127
+
128
+
129
+ def test_no_date_format_string_outside_the_allowlist() -> None:
130
+ unlisted = sorted(_format_strings() - set(ALLOWED))
131
+ assert not unlisted, (
132
+ "date format string(s) not in the convention: use yyyy-MM-dd / yyyy-MM-dd HH:mm for "
133
+ "output and ISO 8601 with T and Z for stored timestamps, or add an ALLOWED entry with a "
134
+ f"reason from REASONS if it is exempt: {unlisted}"
135
+ )
136
+
137
+
138
+ def test_no_stale_allowlist_entry() -> None:
139
+ stale = sorted(set(ALLOWED) - _format_strings())
140
+ assert not stale, f"ALLOWED entries that match no format string in src/: {stale}"