cc-session-tools 3.9.0__tar.gz → 3.10.0__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 (298) hide show
  1. {cc_session_tools-3.9.0/src/cc_session_tools.egg-info → cc_session_tools-3.10.0}/PKG-INFO +3 -3
  2. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/README.md +2 -2
  3. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/pyproject.toml +3 -3
  4. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/ccst.py +61 -55
  5. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/migrate_sessions_db.py +81 -8
  6. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/doctor.py +56 -7
  7. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/init_paths.py +32 -4
  8. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/init_service.py +5 -1
  9. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/sessions_db.py +47 -0
  10. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/pm-pdata-do-init/SKILL.md +16 -0
  11. cc_session_tools-3.10.0/src/cc_session_tools/skills/pm-pdata-do-update-consuming-skills/SKILL.md +114 -0
  12. cc_session_tools-3.10.0/src/cc_session_tools/skills/pm-pdata-do-update-project-docs/SKILL.md +103 -0
  13. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0/src/cc_session_tools.egg-info}/PKG-INFO +3 -3
  14. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools.egg-info/SOURCES.txt +4 -2
  15. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_bundle_discovery.py +35 -62
  16. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_pdata_init_cli.py +70 -9
  17. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_migrate_sessions_db.py +3 -3
  18. cc_session_tools-3.10.0/tests/test_pdata_post_migration_skills.py +123 -0
  19. cc_session_tools-3.10.0/tests/test_sessions_db_migration_chain.py +464 -0
  20. cc_session_tools-3.9.0/src/cc_session_tools/prompts/pdata-migration-claude-md-update.md +0 -134
  21. cc_session_tools-3.9.0/src/cc_session_tools/prompts/pdata-migration-skills-update.md +0 -137
  22. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/LICENSE +0 -0
  23. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/setup.cfg +0 -0
  24. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/__init__.py +0 -0
  25. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/__init__.py +0 -0
  26. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/ccd.py +0 -0
  27. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/ccmsg.py +0 -0
  28. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/ccr.py +0 -0
  29. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/ccs.py +0 -0
  30. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/ccsched.py +0 -0
  31. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/migrate_ccmsg.py +0 -0
  32. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/migrate_ccsched.py +0 -0
  33. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/cli/migrate_telemetry.py +0 -0
  34. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/config/hooks-bundle.json +0 -0
  35. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/config/session-tag-hook.json +0 -0
  36. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/hooks_install.py +0 -0
  37. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/__init__.py +0 -0
  38. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/bun_tools.py +0 -0
  39. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/claude_flags.py +0 -0
  40. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/claude_md_install.py +0 -0
  41. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/context_overrides.py +0 -0
  42. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/db.py +0 -0
  43. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/debug.py +0 -0
  44. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/doctor_mutes.py +0 -0
  45. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/hook_registry.py +0 -0
  46. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/install_sync.py +0 -0
  47. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/levenshtein.py +0 -0
  48. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/machine_identity.py +0 -0
  49. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/__init__.py +0 -0
  50. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/addressing.py +0 -0
  51. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/cursor.py +0 -0
  52. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/lock.py +0 -0
  53. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/message.py +0 -0
  54. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/move_safety.py +0 -0
  55. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/repository.py +0 -0
  56. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/retention.py +0 -0
  57. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/service.py +0 -0
  58. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/messaging/store.py +0 -0
  59. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/occupancy.py +0 -0
  60. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/paths.py +0 -0
  61. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/__init__.py +0 -0
  62. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/backup.py +0 -0
  63. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/classify.py +0 -0
  64. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/cutover.py +0 -0
  65. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/dump.py +0 -0
  66. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/formatting.py +0 -0
  67. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/importers.py +0 -0
  68. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/manifest.py +0 -0
  69. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/naming.py +0 -0
  70. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/readiness.py +0 -0
  71. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/rehydrate.py +0 -0
  72. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/rename_group.py +0 -0
  73. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/reorganize.py +0 -0
  74. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/repository.py +0 -0
  75. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/resolve.py +0 -0
  76. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/service.py +0 -0
  77. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/session_output.py +0 -0
  78. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/store.py +0 -0
  79. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/sync_check.py +0 -0
  80. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/sync_lock.py +0 -0
  81. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/sync_notify.py +0 -0
  82. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/vector_clock.py +0 -0
  83. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/vector_clock_store.py +0 -0
  84. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/verify.py +0 -0
  85. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/pdata/write_log.py +0 -0
  86. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/picker.py +0 -0
  87. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/proc_lock.py +0 -0
  88. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/prompts.py +0 -0
  89. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/roots.py +0 -0
  90. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/rules.py +0 -0
  91. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/__init__.py +0 -0
  92. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/bundled_jobs.py +0 -0
  93. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/cadence.py +0 -0
  94. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/cursor.py +0 -0
  95. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/digest.py +0 -0
  96. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/due.py +0 -0
  97. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/duration.py +0 -0
  98. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/jobspec.py +0 -0
  99. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/ledger.py +0 -0
  100. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/lock.py +0 -0
  101. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/notify.py +0 -0
  102. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/reconcile.py +0 -0
  103. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/registry.py +0 -0
  104. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/runner.py +0 -0
  105. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/state.py +0 -0
  106. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/store.py +0 -0
  107. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/surface.py +0 -0
  108. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/throttle.py +0 -0
  109. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/scheduler/worker.py +0 -0
  110. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/session_gc.py +0 -0
  111. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/sessions.py +0 -0
  112. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/sessions_repair.py +0 -0
  113. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/shell_install.py +0 -0
  114. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/tasklist.py +0 -0
  115. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/telemetry_store.py +0 -0
  116. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/lib/text_wrap.py +0 -0
  117. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/analyse-cc-usage/SKILL.md +0 -0
  118. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/clean-hook-sessions/SKILL.md +0 -0
  119. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/clean-hook-sessions/scripts/clean-hook-sessions.py +0 -0
  120. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/compact-smart/SKILL.md +0 -0
  121. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/context-override/SKILL.md +0 -0
  122. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/delete-sessions/SKILL.md +0 -0
  123. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/delete-sessions/scripts/delete_sessions.py +0 -0
  124. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/do-executor-critic-assessor-loop/SKILL.md +0 -0
  125. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/extract-pptx/SKILL.md +0 -0
  126. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/extract-pptx/scripts/extract_pptx.py +0 -0
  127. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/extract-to-text/SKILL.md +0 -0
  128. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/extract-to-text/scripts/extract_to_text.py +0 -0
  129. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/find-claude-code-session/SKILL.md +0 -0
  130. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/generate-8digit-code/SKILL.md +0 -0
  131. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/generate-8digit-code/scripts/generate_8digit_code.py +0 -0
  132. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/list-empty-sessions/SKILL.md +0 -0
  133. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/list-empty-sessions/scripts/list_empty_sessions.py +0 -0
  134. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/manage-recurring-cc-jobs-using-ccsched/SKILL.md +0 -0
  135. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/move-session/SKILL.md +0 -0
  136. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/move-session/hooks/sessionstart-pending-rename.sh +0 -0
  137. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/move-session/scripts/cc_session_rules.py +0 -0
  138. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/move-session/scripts/move_session.py +0 -0
  139. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/pm-pdata-design-schema/SKILL.md +0 -0
  140. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/pm-pdata-do-audit-and-prepare-to-migrate/SKILL.md +0 -0
  141. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/pm-pdata-do-manual-migration/SKILL.md +0 -0
  142. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/pm-pdata-resolve-conflicts/SKILL.md +0 -0
  143. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/pm-project-layout-reference/SKILL.md +0 -0
  144. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/pm-update-central-files/SKILL.md +0 -0
  145. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/reduce-persistent-context/CALIBRATION.md +0 -0
  146. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/reduce-persistent-context/SKILL.md +0 -0
  147. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/analyze_context.py +0 -0
  148. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/duplicates.py +0 -0
  149. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/measure.py +0 -0
  150. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/report.py +0 -0
  151. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/tokens.py +0 -0
  152. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/usage.py +0 -0
  153. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/select-agent-model/SKILL.md +0 -0
  154. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/send-session-message/SKILL.md +0 -0
  155. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/update-command-cache/SKILL.md +0 -0
  156. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools/skills/update-command-cache/scripts/update_command_cache.py +0 -0
  157. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools.egg-info/dependency_links.txt +0 -0
  158. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools.egg-info/entry_points.txt +0 -0
  159. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools.egg-info/requires.txt +0 -0
  160. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/cc_session_tools.egg-info/top_level.txt +0 -0
  161. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/__init__.py +0 -0
  162. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/attribution.py +0 -0
  163. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/cache.py +0 -0
  164. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/ccusage_wrapper.py +0 -0
  165. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/cli.py +0 -0
  166. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/data/pricing.json +0 -0
  167. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/parent_inference.py +0 -0
  168. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/parser.py +0 -0
  169. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/pricing.py +0 -0
  170. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/query.py +0 -0
  171. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/report.py +0 -0
  172. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/schema.py +0 -0
  173. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/claude_code_usage/session_names.py +0 -0
  174. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/__init__.py +0 -0
  175. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/after_response.py +0 -0
  176. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/bash_hard_deny.py +0 -0
  177. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/bash_security_review.py +0 -0
  178. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/cache.py +0 -0
  179. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/catchup.py +0 -0
  180. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/confirm_8digit.py +0 -0
  181. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/context_window_warning.py +0 -0
  182. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/last_screenshot.py +0 -0
  183. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/marker_allow.py +0 -0
  184. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/markers.py +0 -0
  185. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/messaging_deliver.py +0 -0
  186. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/model_info.py +0 -0
  187. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/normalise.py +0 -0
  188. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/pdata_sync.py +0 -0
  189. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/pending_migration.py +0 -0
  190. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/pending_rename.py +0 -0
  191. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/script_allowlist.py +0 -0
  192. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/session_tag.py +0 -0
  193. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/stats.py +0 -0
  194. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/telemetry.py +0 -0
  195. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/telemetry_query.py +0 -0
  196. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/telemetry_trim.py +0 -0
  197. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/transcript.py +0 -0
  198. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/src/hooks/worklog_guard.py +0 -0
  199. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_after_response.py +0 -0
  200. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_attribution.py +0 -0
  201. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_bash_hard_deny.py +0 -0
  202. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_bash_security_review.py +0 -0
  203. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_bash_security_review_allowlist.py +0 -0
  204. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_bun_tools.py +0 -0
  205. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_cache.py +0 -0
  206. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_cache_sqlite.py +0 -0
  207. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccr_orphans.py +0 -0
  208. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccs_emptiness.py +0 -0
  209. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccs_eta.py +0 -0
  210. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccs_list_mode.py +0 -0
  211. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccs_scope_flags.py +0 -0
  212. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccs_sentinel_sort.py +0 -0
  213. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccs_session_counts.py +0 -0
  214. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_ccsched_jobs_cli.py +0 -0
  215. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_cli.py +0 -0
  216. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_context_override_cli.py +0 -0
  217. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_doctor.py +0 -0
  218. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_gc_prune.py +0 -0
  219. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_gc_report.py +0 -0
  220. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_hook_dispatcher.py +0 -0
  221. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_hooks_allowlist.py +0 -0
  222. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_hooks_install_prune.py +0 -0
  223. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_hooks_install_zero_arg.py +0 -0
  224. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_hooks_uninstall.py +0 -0
  225. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_install_everything.py +0 -0
  226. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_machine_identity_cli.py +0 -0
  227. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_main_gate.py +0 -0
  228. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_pdata_cli.py +0 -0
  229. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_pdata_readiness_cli.py +0 -0
  230. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_pdata_reconcile_cli.py +0 -0
  231. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_pdata_rename_group_cli.py +0 -0
  232. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_pdata_reorganize_cli.py +0 -0
  233. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_pdata_sync_cli.py +0 -0
  234. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_pdata_verify_cli.py +0 -0
  235. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_repair_sessions_cli.py +0 -0
  236. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_sessions_cli.py +0 -0
  237. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_shell_install.py +0 -0
  238. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_skills_install.py +0 -0
  239. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_skills_uninstall.py +0 -0
  240. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_telemetry_query.py +0 -0
  241. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccst_telemetry_trim.py +0 -0
  242. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_ccusage_wrapper.py +0 -0
  243. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_claude_flags.py +0 -0
  244. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_claude_md_install.py +0 -0
  245. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_cli.py +0 -0
  246. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_cli_ccd.py +0 -0
  247. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_cli_ccd_dry_run.py +0 -0
  248. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_cli_ccr.py +0 -0
  249. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_cli_ccs.py +0 -0
  250. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_cli_version.py +0 -0
  251. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_confirm_8digit.py +0 -0
  252. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_context_overrides.py +0 -0
  253. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_context_window_warning.py +0 -0
  254. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_db.py +0 -0
  255. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_debug.py +0 -0
  256. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_doctor_mutes.py +0 -0
  257. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_empty_session.py +0 -0
  258. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_hook_cache.py +0 -0
  259. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_hooks_install.py +0 -0
  260. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_hooks_install_records.py +0 -0
  261. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_install_sync.py +0 -0
  262. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_last_screenshot.py +0 -0
  263. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_levenshtein.py +0 -0
  264. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_machine_identity.py +0 -0
  265. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_marker_allow.py +0 -0
  266. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_migrate_ccmsg.py +0 -0
  267. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_migrate_ccsched.py +0 -0
  268. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_migrate_telemetry.py +0 -0
  269. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_model_info.py +0 -0
  270. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_normalise.py +0 -0
  271. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_occupancy.py +0 -0
  272. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_parent_inference.py +0 -0
  273. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_parser.py +0 -0
  274. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_paths.py +0 -0
  275. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_pdata_audit_skill.py +0 -0
  276. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_pending_migration_hook.py +0 -0
  277. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_picker.py +0 -0
  278. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_pricing.py +0 -0
  279. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_proc_lock.py +0 -0
  280. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_prompts.py +0 -0
  281. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_query.py +0 -0
  282. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_report.py +0 -0
  283. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_roots.py +0 -0
  284. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_rules.py +0 -0
  285. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_scheduler_bundled_jobs.py +0 -0
  286. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_schema.py +0 -0
  287. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_script_allowlist.py +0 -0
  288. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_session_names.py +0 -0
  289. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_session_tag.py +0 -0
  290. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_sessions.py +0 -0
  291. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_sessions_db.py +0 -0
  292. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_sessions_repair.py +0 -0
  293. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_tasklist.py +0 -0
  294. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_telemetry.py +0 -0
  295. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_telemetry_store.py +0 -0
  296. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_text_wrap.py +0 -0
  297. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/tests/test_transcript.py +0 -0
  298. {cc_session_tools-3.9.0 → cc_session_tools-3.10.0}/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.9.0
3
+ Version: 3.10.0
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
@@ -192,8 +192,8 @@ Messages can also be addressed to a specific session (`--to-session`) or to a fr
192
192
  description for whichever session picks it up first (`--to-description`) - project-
193
193
  addressed is by far the most common pattern in practice.
194
194
 
195
- The easiest way to use sessions is just to tell your session to send a message to
196
- another session (e.g. by name tag and/or location).
195
+ The easiest way to use messages when you need them is just to tell your session to send
196
+ a message to another session (e.g. by name tag and/or location).
197
197
 
198
198
  ## Scheduled housekeeping: `ccsched`
199
199
 
@@ -135,8 +135,8 @@ Messages can also be addressed to a specific session (`--to-session`) or to a fr
135
135
  description for whichever session picks it up first (`--to-description`) - project-
136
136
  addressed is by far the most common pattern in practice.
137
137
 
138
- The easiest way to use sessions is just to tell your session to send a message to
139
- another session (e.g. by name tag and/or location).
138
+ The easiest way to use messages when you need them is just to tell your session to send
139
+ a message to another session (e.g. by name tag and/or location).
140
140
 
141
141
  ## Scheduled housekeeping: `ccsched`
142
142
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cc-session-tools"
7
- version = "3.9.0"
7
+ version = "3.10.0"
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" }
@@ -62,11 +62,11 @@ where = ["src"]
62
62
  # only filters within the file's *own* discovered package, and a wrongly
63
63
  # auto-discovered "cc_session_tools.skills.<name>.tests" package was never
64
64
  # covered by an exclude-package-data entry keyed just "cc_session_tools").
65
- exclude = ["cc_session_tools.skills", "cc_session_tools.skills.*", "cc_session_tools.config", "cc_session_tools.config.*", "cc_session_tools.prompts", "cc_session_tools.prompts.*"]
65
+ exclude = ["cc_session_tools.skills", "cc_session_tools.skills.*", "cc_session_tools.config", "cc_session_tools.config.*"]
66
66
 
67
67
  [tool.setuptools.package-data]
68
68
  claude_code_usage = ["data/*.json"]
69
- cc_session_tools = ["skills/**/*", "config/*", "prompts/**/*"]
69
+ cc_session_tools = ["skills/**/*", "config/*"]
70
70
 
71
71
  [tool.setuptools.exclude-package-data]
72
72
  cc_session_tools = ["**/tests/*", "**/__pycache__/*"]
@@ -160,56 +160,25 @@ def _discover_bundle() -> Path:
160
160
  )
161
161
 
162
162
 
163
- def _discover_prompts_dir() -> Path:
164
- """Return the bundled prompts/ directory (pdata-migration follow-up prompts).
165
-
166
- prompts/ is packaged inside cc_session_tools the same way skills/ and config/ are (see
167
- _discover_source_dir) - src/cc_session_tools/cli/ccst.py -> ../prompts. No install-location
168
- fallback, same reasoning as the other two: a fallback here would just mask a broken install.
169
- """
170
- candidate = Path(__file__).resolve().parent.parent / "prompts"
171
- if candidate.is_dir():
172
- return candidate
173
- raise FileNotFoundError(
174
- "Cannot locate bundled prompts/ directory. Run from the source tree or reinstall ccst."
175
- )
176
-
177
-
178
- def _print_migration_prompt_reminders(
179
- project_root: Path, *labeled_filenames: tuple[str, str]
163
+ def _print_post_migration_skill_reminders(
164
+ project_root: Path, *labeled_skills: tuple[str, str]
180
165
  ) -> None:
181
- """Print one "<label>: <path>" reminder line per (label, filename) pair, for the bundled
182
- prompts/ directory, followed by a line telling the user to run it in a fresh context (a new
183
- Claude Code session, or a dispatched Agent subagent) started in project_root.
184
-
185
- Each prompt's own "Run it via" section already spells out the `cd <project> && claude -p
186
- ...` invocation (see e.g. pdata-migration-skills-update.md) - that only works if the
187
- session's cwd is the project root, since every prompt's Step 1 checks for it and aborts
188
- otherwise. What the fresh-context requirement is actually protecting against is an
189
- orchestrating session rationalizing away a stale reference it half-remembers writing
190
- earlier in the same conversation - a dispatched Agent subagent (same cwd) gets that same
191
- benefit without shelling out to a literal second process, so both are offered here rather
192
- than only the `claude -p` invocation. Printing the reminder without saying so reads as "open
193
- this file", which invites running it inline in whatever session called `ccst pdata init` -
194
- the wrong cwd entirely.
195
-
196
- Best-effort, deliberately swallowing a missing prompts/ directory: these reminders are a
197
- nicety layered on top of an otherwise-already-completed classification or migration, not
198
- the operation itself — a broken/partial install must never turn a successful --write (rows
199
- already written, files already cut over) or dry-run (proposal already written) into a
200
- reported failure just because this follow-up reminder couldn't be printed.
166
+ """Print one "<label>: <skill-name>" reminder per (label, skill) pair, each followed by a
167
+ line telling the user to run it in a fresh context rooted at project_root.
168
+
169
+ Each skill's Step 1 checks that cwd is the project root and aborts otherwise, so a bare skill
170
+ name invites running it inline in whatever session called `ccst pdata init` - the wrong cwd,
171
+ and the wrong context: the fresh-context requirement protects against an orchestrating
172
+ session rationalizing away a stale reference it half-remembers writing earlier in the same
173
+ conversation. A dispatched Agent subagent whose prompt starts with a `cd` into project_root
174
+ gets that same benefit as a new Claude Code session, so both are offered.
201
175
  """
202
- try:
203
- prompts_dir = _discover_prompts_dir()
204
- except FileNotFoundError as exc:
205
- print(f"({exc})", file=sys.stderr)
206
- return
207
- for label, filename in labeled_filenames:
208
- print(f"{label}: {prompts_dir / filename}")
176
+ for label, skill in labeled_skills:
177
+ print(f"{label}: {skill}")
209
178
  print(
210
- f" Run in a new Claude Code session started in {project_root} (its own "
211
- f"\"Run it via\" section has the exact command), or dispatch it as an Agent "
212
- f"subagent with the same cwd - not inline in this session."
179
+ f" Run it in a fresh context rooted at {project_root}: dispatch an Agent subagent "
180
+ f"whose prompt starts with `cd {project_root}`, or start a new Claude Code session "
181
+ f"there - not inline in this session."
213
182
  )
214
183
 
215
184
 
@@ -1236,9 +1205,9 @@ def _cmd_pdata_init(args: argparse.Namespace) -> int:
1236
1205
  # apply here.
1237
1206
  return 0
1238
1207
  print(f"\nProposal: {result.proposal_path}")
1239
- _print_migration_prompt_reminders(
1208
+ _print_post_migration_skill_reminders(
1240
1209
  result.proposal_path.parent,
1241
- ("After a successful --write, update project docs", "pdata-migration-claude-md-update.md"),
1210
+ ("After a successful --write, update project docs", "pm-pdata-do-update-project-docs"),
1242
1211
  )
1243
1212
  return 0
1244
1213
 
@@ -1286,10 +1255,10 @@ def _cmd_pdata_init(args: argparse.Namespace) -> int:
1286
1255
  print()
1287
1256
  print(write_result.report) # spec §7.1 step 4's diff report, for review
1288
1257
  print(f"\nVerify: ccst pdata verify --project {args.project} --full")
1289
- _print_migration_prompt_reminders(
1258
+ _print_post_migration_skill_reminders(
1290
1259
  project_root,
1291
- ("Update project docs", "pdata-migration-claude-md-update.md"),
1292
- ("Update consuming skills", "pdata-migration-skills-update.md"),
1260
+ ("Update project docs", "pm-pdata-do-update-project-docs"),
1261
+ ("Update consuming skills", "pm-pdata-do-update-consuming-skills"),
1293
1262
  )
1294
1263
  print("SUCCESS")
1295
1264
  return 0
@@ -2340,12 +2309,44 @@ _MIGRATE_ALL_BANNER = (
2340
2309
  )
2341
2310
 
2342
2311
 
2312
+ def _migrate_all_sessions_step(args: argparse.Namespace) -> int:
2313
+ """The sessions step of `migrate all`: the legacy import writes uuid-keyed rows, so a
2314
+ pre-uuid `sessions.db` is rebuilt first (`sessions migrate-uuid`, with its own backup and
2315
+ concurrent-writer guard). A failed or refused rebuild skips the import."""
2316
+ import sqlite3
2317
+
2318
+ from cc_session_tools.cli.migrate_sessions_db import migrate_uuid
2319
+ from cc_session_tools.lib import sessions_db
2320
+
2321
+ db_path = sessions_db.default_db_path()
2322
+ try:
2323
+ pre_uuid = sessions_db.pre_uuid_sessions_table(db_path)
2324
+ except sqlite3.DatabaseError as exc:
2325
+ print(f"cannot read {db_path}: {exc} - not a valid sessions.db; nothing was changed",
2326
+ file=sys.stderr)
2327
+ return 1
2328
+ if pre_uuid:
2329
+ print(f"{db_path} is on the pre-3.0.0 schema - rebuilding it first "
2330
+ "(`ccst sessions migrate-uuid`) so the legacy import can write to it.")
2331
+ try:
2332
+ rc = migrate_uuid(db_path=db_path, dry_run=args.dry_run)
2333
+ except ValueError as exc:
2334
+ print(str(exc), file=sys.stderr)
2335
+ return 1
2336
+ if rc != 0:
2337
+ return rc
2338
+ if args.dry_run:
2339
+ print("The legacy import's own dry-run is skipped until the rebuild has run.")
2340
+ return 0
2341
+ return _cmd_sessions_migrate(argparse.Namespace(
2342
+ dry_run=args.dry_run, sessions_db=None, tags_dir=None, mutes_file=None))
2343
+
2344
+
2343
2345
  def _cmd_migrate_all(args: argparse.Namespace) -> int:
2344
2346
  print(_MIGRATE_ALL_BANNER)
2345
2347
 
2346
2348
  steps: list[tuple[str, object]] = [
2347
- ("sessions", lambda: _cmd_sessions_migrate(argparse.Namespace(
2348
- dry_run=args.dry_run, sessions_db=None, tags_dir=None, mutes_file=None))),
2349
+ ("sessions", lambda: _migrate_all_sessions_step(args)),
2349
2350
  ("ccmsg", lambda: _cmd_migrate_ccmsg(argparse.Namespace(
2350
2351
  old_root=None, backup_dir=None, dry_run=args.dry_run))),
2351
2352
  ("ccsched", lambda: _cmd_migrate_ccsched(argparse.Namespace(
@@ -2355,14 +2356,19 @@ def _cmd_migrate_all(args: argparse.Namespace) -> int:
2355
2356
  ]
2356
2357
 
2357
2358
  overall_rc = 0
2359
+ failed: list[str] = []
2358
2360
  for name, step in steps:
2359
2361
  print(f"\n=== {name} ===")
2360
2362
  rc = step() # type: ignore[operator]
2361
2363
  if rc != 0:
2362
2364
  overall_rc = rc
2365
+ failed.append(name)
2363
2366
 
2364
2367
  print()
2365
- if args.dry_run:
2368
+ if failed:
2369
+ print(f"Steps that failed: {', '.join(failed)}. Review the ERROR/ABORT/refusal lines "
2370
+ "above; a failed step leaves its own old files untouched and is safe to re-run.")
2371
+ elif args.dry_run:
2366
2372
  print("Dry run complete — re-run without --dry-run once you're satisfied.")
2367
2373
  else:
2368
2374
  print("All migrations attempted. Review any ERROR/ABORT lines above; a "
@@ -114,10 +114,15 @@ def _read_legacy_sessions_rows(conn: sqlite3.Connection) -> list[sqlite3.Row]:
114
114
  """Every row from the pre-3.0.0 (project_dir, basename) `sessions` table, via raw SQL -
115
115
  not sessions_db.list_sessions()/_row_to_session, which require the `uuid` column this
116
116
  migration is the one adding. Safe to call against either schema shape: only the columns
117
- that exist pre-3.0.0 are selected."""
117
+ that exist pre-3.0.0 are selected; `updated_at` (absent from v1.0.0 through v2.12.x) is read
118
+ as NULL when the table has no such column."""
119
+ updated_at = (
120
+ "updated_at" if "updated_at" in sessions_db.sessions_column_names(conn)
121
+ else "NULL AS updated_at"
122
+ )
118
123
  return conn.execute(
119
124
  "SELECT project_dir, basename, start_date, last_opened, last_active, "
120
- "discovered_at, updated_at FROM sessions"
125
+ f"discovered_at, {updated_at} FROM sessions"
121
126
  ).fetchall()
122
127
 
123
128
 
@@ -162,6 +167,26 @@ def print_uuid_migration_dry_run(plan: UuidMigrationPlan, *, db_path: Path) -> N
162
167
  print("backing up: this rebuilds the sessions table and is a one-way schema change.")
163
168
 
164
169
 
170
+ def _record_uuid_marker_only(db_path: Path, *, dry_run: bool) -> int:
171
+ """`sessions` is already uuid-keyed, or there is no `sessions` table to rebuild: there is
172
+ nothing to rebuild, only the completion marker to record (creating the current schema first
173
+ if the table is missing)."""
174
+ if dry_run:
175
+ print(f"{db_path} needs no rebuild - only its 3.0.0 completion marker would be "
176
+ "recorded. Re-run with --write to record it.")
177
+ return 0
178
+ conn = sessions_db.connect(path=db_path)
179
+ try:
180
+ db.record_migration(
181
+ conn, sessions_db.SESSIONS_UUID_MIGRATION, applied_at=sessions_db._now_iso()
182
+ )
183
+ conn.commit()
184
+ finally:
185
+ conn.close()
186
+ print(f"{db_path} needed no rebuild - recorded its 3.0.0 completion marker.")
187
+ return 0
188
+
189
+
165
190
  def migrate_uuid(*, db_path: Path, dry_run: bool, backup_dir: Path | None = None) -> int:
166
191
  """The 3.0.0 schema migration: rebuild `sessions` from the pre-3.0.0
167
192
  (project_dir, basename) primary key to (project_dir, basename, uuid), backfilling each
@@ -185,15 +210,35 @@ def migrate_uuid(*, db_path: Path, dry_run: bool, backup_dir: Path | None = None
185
210
  # be held by a live hook write, defeating the point of checking before touching anything.
186
211
  conn = db.connect(db_path)
187
212
  try:
188
- if sessions_db.sessions_schema_is_uuid_keyed(conn) and db.migration_applied(
189
- conn, sessions_db.SESSIONS_UUID_MIGRATION
190
- ):
191
- print(f"{db_path} is already migrated to the uuid-aware schema - nothing to do.")
192
- return 0
193
- legacy_rows = _read_legacy_sessions_rows(conn)
213
+ if not sessions_db.sessions_table_exists(conn):
214
+ marker_only = True
215
+ legacy_rows: list[sqlite3.Row] = []
216
+ else:
217
+ keyed = sessions_db.sessions_schema_is_uuid_keyed(conn)
218
+ recorded = sessions_db.migration_marker_recorded(
219
+ conn, sessions_db.SESSIONS_UUID_MIGRATION
220
+ )
221
+ if keyed and recorded:
222
+ print(f"{db_path} is already migrated to the uuid-aware schema - nothing to do.")
223
+ return 0
224
+ marker_only = keyed
225
+ if not keyed:
226
+ missing = sessions_db.missing_rebuild_columns(conn)
227
+ if missing:
228
+ print(
229
+ f"cannot migrate {db_path}: its `sessions` table is missing "
230
+ f"column(s) the rebuild copies: {', '.join(missing)}. Nothing was "
231
+ "changed; restore the file from a backup or repair it by hand.",
232
+ file=sys.stderr,
233
+ )
234
+ return 1
235
+ legacy_rows = [] if keyed else _read_legacy_sessions_rows(conn)
194
236
  finally:
195
237
  conn.close()
196
238
 
239
+ if marker_only:
240
+ return _record_uuid_marker_only(db_path, dry_run=dry_run)
241
+
197
242
  plan = plan_uuid_migration(legacy_rows)
198
243
 
199
244
  if dry_run:
@@ -418,6 +463,30 @@ def _tar_backup(sources: list[Path], *, backup_dir: Path) -> Path | None:
418
463
  return dest
419
464
 
420
465
 
466
+ def refuse_if_sessions_db_pre_uuid(db_path: Path) -> int | None:
467
+ """Pre-flight for the legacy import: it writes uuid-keyed rows, which a `sessions.db` still
468
+ on the pre-3.0.0 schema cannot accept. Returns a non-zero exit code (after printing the
469
+ fix) when the import must not run, else None. Read-only; must run before anything that could
470
+ connect-with-DDL, write, or back up."""
471
+ try:
472
+ pre_uuid = sessions_db.pre_uuid_sessions_table(db_path)
473
+ except sqlite3.DatabaseError as exc:
474
+ print(f"cannot read {db_path}: {exc} - not a valid sessions.db; nothing was changed",
475
+ file=sys.stderr)
476
+ return 1
477
+ if not pre_uuid:
478
+ return None
479
+ print(
480
+ f"cannot run the legacy flat-file import: {db_path} is still on the pre-3.0.0 schema "
481
+ "(no uuid column), which the import cannot write to. Nothing was changed. First run "
482
+ "`ccst sessions migrate-uuid --write` from a plain terminal with no other `claude` "
483
+ "session running (it takes a backup first), then re-run this - or run `ccst migrate "
484
+ "all`, which does both in order.",
485
+ file=sys.stderr,
486
+ )
487
+ return 1
488
+
489
+
421
490
  def run_migration(
422
491
  *,
423
492
  dry_run: bool,
@@ -427,6 +496,10 @@ def run_migration(
427
496
  roots: list[Path],
428
497
  backup_dir: Path,
429
498
  ) -> int:
499
+ refusal = refuse_if_sessions_db_pre_uuid(db_path)
500
+ if refusal is not None:
501
+ return refusal
502
+
430
503
  print(f"Sessions DB : {db_path}")
431
504
  print(f"Tags source : {tags_dir}")
432
505
  print(f"Mutes source : {mutes_file}")
@@ -675,7 +675,26 @@ def _migration_recorded(db_path: Path, marker_name: str) -> bool:
675
675
  conn.close()
676
676
 
677
677
 
678
- def check_pending_data_store_migration(paths: LegacyMigrationPaths) -> list[CheckResult]:
678
+ def _sessions_marker() -> str:
679
+ from cc_session_tools.lib.sessions_db import LEGACY_FLAT_FILE_MIGRATION
680
+
681
+ return LEGACY_FLAT_FILE_MIGRATION
682
+
683
+
684
+ def _sessions_db_is_pre_uuid(db_path: Path) -> bool:
685
+ """`sessions_db.pre_uuid_sessions_table`, with an unreadable file counting as not pre-uuid
686
+ (other checks already report a database that fails to open)."""
687
+ from cc_session_tools.lib import sessions_db
688
+
689
+ try:
690
+ return sessions_db.pre_uuid_sessions_table(db_path)
691
+ except sqlite3.DatabaseError:
692
+ return False
693
+
694
+
695
+ def check_pending_data_store_migration(
696
+ paths: LegacyMigrationPaths, *, sessions_db_path: Path | None = None,
697
+ ) -> list[CheckResult]:
679
698
  """Detect legacy flat-file data left over from a pre-1.0.0 install.
680
699
 
681
700
  :func:`check_data_stores` can't distinguish a fresh install (nothing to
@@ -696,6 +715,10 @@ def check_pending_data_store_migration(paths: LegacyMigrationPaths) -> list[Chec
696
715
  fills from the first hook fire after install, so counting rows reported "already
697
716
  migrated" for anyone who opened a session before migrating, and the FAIL that should
698
717
  have prompted them never fired.
718
+
719
+ `sessions_db_path` is the sessions.db the `sessions` finding reads; pass the same path the
720
+ 3.0.0 uuid check uses so the two findings can never describe different files (defaults to
721
+ `paths.data_home / "sessions.db"`).
699
722
  """
700
723
  from cc_session_tools.lib.messaging.repository import (
701
724
  LEGACY_FLAT_FILE_MIGRATION as _CCMSG_MIGRATION,
@@ -724,7 +747,7 @@ def check_pending_data_store_migration(paths: LegacyMigrationPaths) -> list[Chec
724
747
  "sessions": (
725
748
  (paths.tags_dir, paths.mutes_file),
726
749
  _count_legacy_sessions(paths.tags_dir, paths.mutes_file),
727
- paths.data_home / "sessions.db",
750
+ sessions_db_path if sessions_db_path is not None else paths.data_home / "sessions.db",
728
751
  _SESSIONS_MIGRATION,
729
752
  ),
730
753
  "telemetry": (
@@ -748,6 +771,13 @@ def check_pending_data_store_migration(paths: LegacyMigrationPaths) -> list[Chec
748
771
  already_migrated = _migration_recorded(new_db_path, marker_name)
749
772
  evidence = f"the import is recorded in {new_db_path.name}"
750
773
  if not already_migrated:
774
+ rebuild_note = ""
775
+ if store_name == "sessions" and _sessions_db_is_pre_uuid(new_db_path):
776
+ rebuild_note = (
777
+ f" It will first rebuild {new_db_path.name} to the 3.0.0 uuid schema "
778
+ "(taking a backup; close any running `claude` sessions first) - the "
779
+ "import cannot write to the old schema."
780
+ )
751
781
  results.append(
752
782
  CheckResult(
753
783
  name=name,
@@ -756,7 +786,7 @@ def check_pending_data_store_migration(paths: LegacyMigrationPaths) -> list[Chec
756
786
  f"{legacy_count} unmigrated item(s) at {existing}; run "
757
787
  "`ccst migrate all` from a plain terminal (NOT inside a Claude Code "
758
788
  "session — the delete step is blocked by bash-hard-deny) to migrate "
759
- f"into {new_db_path}"
789
+ f"into {new_db_path}.{rebuild_note}"
760
790
  ),
761
791
  )
762
792
  )
@@ -942,7 +972,9 @@ def check_sessions_project_dir_absolute(sessions_db_path: Path) -> list[CheckRes
942
972
  )]
943
973
 
944
974
 
945
- def check_sessions_uuid_migration(sessions_db_path: Path) -> list[CheckResult]:
975
+ def check_sessions_uuid_migration(
976
+ sessions_db_path: Path, *, legacy_sessions_pending: bool = False,
977
+ ) -> list[CheckResult]:
946
978
  """FAIL if sessions.db still has the pre-3.0.0 (project_dir, basename) primary key -
947
979
  forked sessions (Ctrl-L) silently clobber each other's activity rows until
948
980
  `ccst sessions migrate-uuid --write` runs. Distinguishes "never migrated" from
@@ -956,7 +988,10 @@ def check_sessions_uuid_migration(sessions_db_path: Path) -> list[CheckResult]:
956
988
  A sessions.db that doesn't exist yet reads OK: connect() records the migration
957
989
  marker at creation time for any brand-new file (sessions_db.py), so a genuinely
958
990
  fresh install is never in a pending state - there is simply nothing to check here
959
- yet, and this check must not create the file itself just to inspect it."""
991
+ yet, and this check must not create the file itself just to inspect it.
992
+
993
+ `legacy_sessions_pending` says the 1.0.0 flat-file import is also still pending; the two FAIL
994
+ branches then note that `ccst migrate all` performs both, in the order that works."""
960
995
  import sqlite3
961
996
 
962
997
  from cc_session_tools.lib import db as db_lib
@@ -1000,6 +1035,11 @@ def check_sessions_uuid_migration(sessions_db_path: Path) -> list[CheckResult]:
1000
1035
  "run `ccst sessions migrate-uuid --write` from a plain terminal with no other "
1001
1036
  "`claude` session running (it takes a backup first; see --help)"
1002
1037
  )
1038
+ if legacy_sessions_pending:
1039
+ remediation += (
1040
+ "; the legacy import is also pending, and `ccst migrate all` performs both in "
1041
+ "the order that works"
1042
+ )
1003
1043
  if not pk_is_uuid_keyed and not marker_present:
1004
1044
  return [CheckResult(
1005
1045
  name=name, status=Status.FAIL,
@@ -1158,7 +1198,8 @@ def run_all_checks(
1158
1198
 
1159
1199
  # Pending legacy-data migration
1160
1200
  if legacy_migration_paths is not None:
1161
- results.extend(check_pending_data_store_migration(legacy_migration_paths))
1201
+ results.extend(check_pending_data_store_migration(
1202
+ legacy_migration_paths, sessions_db_path=sessions_db_path))
1162
1203
 
1163
1204
  # Pending ccst pdata init cutover (spec §7.1 step 7)
1164
1205
  if projects_root is not None:
@@ -1172,7 +1213,15 @@ def run_all_checks(
1172
1213
  # since project-dir-absolute's own check degrades to a WARN pointing back at it when
1173
1214
  # the uuid migration hasn't run yet (a pre-migration schema can't be queried the same way).
1174
1215
  if sessions_db_path is not None:
1175
- results.extend(check_sessions_uuid_migration(sessions_db_path))
1216
+ legacy_sessions_pending = (
1217
+ legacy_migration_paths is not None
1218
+ and _count_legacy_sessions(
1219
+ legacy_migration_paths.tags_dir, legacy_migration_paths.mutes_file
1220
+ ) > 0
1221
+ and not _migration_recorded(sessions_db_path, _sessions_marker())
1222
+ )
1223
+ results.extend(check_sessions_uuid_migration(
1224
+ sessions_db_path, legacy_sessions_pending=legacy_sessions_pending))
1176
1225
  results.extend(check_sessions_project_dir_absolute(sessions_db_path))
1177
1226
 
1178
1227
  # Optional dependencies for claude-code-usage's reconcile / ccusage blocks
@@ -112,13 +112,41 @@ def project_db_dir_override(rehearse: Path | None) -> Iterator[None]:
112
112
  override_dir = rehearse / REHEARSAL_DB_DIRNAME
113
113
  previous = os.environ.get(store.PROJECT_DB_DIR_ENV)
114
114
  os.environ[store.PROJECT_DB_DIR_ENV] = str(override_dir)
115
+ _live_db_dir_env_stack.append(previous)
115
116
  try:
116
117
  yield
117
118
  finally:
118
- if previous is None:
119
- os.environ.pop(store.PROJECT_DB_DIR_ENV, None)
120
- else:
121
- os.environ[store.PROJECT_DB_DIR_ENV] = previous
119
+ _live_db_dir_env_stack.pop()
120
+ _restore_db_dir_env(previous)
121
+
122
+
123
+ # The CCST_PROJECT_DB_DIR value in effect before each active project_db_dir_override (None =
124
+ # unset), outermost first - what live_project_db_dir() restores.
125
+ _live_db_dir_env_stack: list[str | None] = []
126
+
127
+
128
+ def _restore_db_dir_env(value: str | None) -> None:
129
+ if value is None:
130
+ os.environ.pop(store.PROJECT_DB_DIR_ENV, None)
131
+ else:
132
+ os.environ[store.PROJECT_DB_DIR_ENV] = value
133
+
134
+
135
+ @contextmanager
136
+ def live_project_db_dir() -> Iterator[None]:
137
+ """Inside a project_db_dir_override block, temporarily point store.db_path() back at the
138
+ real per-project .db dir. For questions about the machine rather than the rehearsal copy
139
+ (e.g. "is this project already migrated here?"): a `cp -r` rehearsal copy never contains the
140
+ real .db, so the sandbox always answers "no". No-op outside an override."""
141
+ if not _live_db_dir_env_stack:
142
+ yield
143
+ return
144
+ inside = os.environ.get(store.PROJECT_DB_DIR_ENV)
145
+ _restore_db_dir_env(_live_db_dir_env_stack[0])
146
+ try:
147
+ yield
148
+ finally:
149
+ _restore_db_dir_env(inside)
122
150
 
123
151
 
124
152
  @contextmanager
@@ -324,7 +324,11 @@ def _pending_adoption(*, project: str, project_root: Path) -> dump.DumpInfo | No
324
324
  "project. Publish a fresh dump from a known-good machine (ccst pdata dump --force) "
325
325
  "or reconcile manually (ccst pdata resolve) once those commands exist."
326
326
  )
327
- if _already_locally_migrated(project):
327
+ # The live .db, not a --rehearse sandbox's: a rehearsal copy never contains the real .db, so
328
+ # the sandbox would always look unmigrated and rehearsal would never reach classification.
329
+ with init_paths.live_project_db_dir():
330
+ already_migrated = _already_locally_migrated(project)
331
+ if already_migrated:
328
332
  return None
329
333
  return info
330
334
 
@@ -153,6 +153,53 @@ def sessions_schema_is_uuid_keyed(conn: sqlite3.Connection) -> bool:
153
153
  )
154
154
 
155
155
 
156
+ # Columns of the pre-3.0.0 `sessions` table that the uuid rebuild copies into the new table.
157
+ # `updated_at` is deliberately absent: databases from v1.0.0 through v2.12.x never had it.
158
+ REBUILD_REQUIRED_COLUMNS = (
159
+ "project_dir", "basename", "start_date", "last_opened", "last_active", "discovered_at",
160
+ )
161
+
162
+
163
+ def sessions_table_exists(conn: sqlite3.Connection) -> bool:
164
+ return conn.execute(
165
+ "SELECT 1 FROM sqlite_master WHERE type='table' AND name='sessions'"
166
+ ).fetchone() is not None
167
+
168
+
169
+ def sessions_column_names(conn: sqlite3.Connection) -> set[str]:
170
+ return {row["name"] for row in conn.execute("PRAGMA table_info(sessions)")}
171
+
172
+
173
+ def missing_rebuild_columns(conn: sqlite3.Connection) -> list[str]:
174
+ """Columns the 3.0.0 rebuild must copy that the existing `sessions` table lacks."""
175
+ present = sessions_column_names(conn)
176
+ return [c for c in REBUILD_REQUIRED_COLUMNS if c not in present]
177
+
178
+
179
+ def migration_marker_recorded(conn: sqlite3.Connection, name: str) -> bool:
180
+ """`db.migration_applied`, but False (not an error) on a database that predates the
181
+ `migrations` table (v1.0.0 through roughly v2.8)."""
182
+ try:
183
+ return db.migration_applied(conn, name)
184
+ except sqlite3.OperationalError:
185
+ return False
186
+
187
+
188
+ def pre_uuid_sessions_table(path: Path) -> bool:
189
+ """True iff `path` exists, has a `sessions` table, and that table is not uuid-keyed - the
190
+ one state in which the 1.0.0 legacy import cannot write. A missing file or a missing
191
+ `sessions` table is False: `connect()` creates the current schema for both. Read-only, so it
192
+ never creates or alters anything; raises sqlite3.DatabaseError for a file that is not a
193
+ valid database."""
194
+ if not path.exists():
195
+ return False
196
+ conn = db.connect(path, readonly=True)
197
+ try:
198
+ return sessions_table_exists(conn) and not sessions_schema_is_uuid_keyed(conn)
199
+ finally:
200
+ conn.close()
201
+
202
+
156
203
  def connect(*, path: Path | None = None, readonly: bool = False) -> sqlite3.Connection:
157
204
  """Open sessions.db (or an explicit override path — used by tests and by
158
205
  ccst doctor --mutes-file). readonly=True skips schema creation; callers
@@ -210,6 +210,22 @@ Step 3's garbled-header recipe) - so anything else in the project citing the old
210
210
  a live signpost instead of a silent 404. Pass `--leave-no-pointer-files` if this run shouldn't
211
211
  leave one (e.g. a rehearsal, or a project convention against extra files at migrated paths).
212
212
 
213
+ ### Then run both post-migration skills
214
+
215
+ After a successful `--write` (not after a dry-run or a rehearsal), update everything that still
216
+ describes or uses the old flat-file layout. Run these in order, each in its own fresh-context
217
+ `Agent` subagent whose prompt begins with `cd ~/cc/<project>` - not inline in this session, which
218
+ has just written the migration and would rationalize away stale references it remembers:
219
+
220
+ 1. `pm-pdata-do-update-project-docs` - rewrites the project's `CLAUDE.md` and other top-level docs
221
+ to name the pdata record_groups and `ccst pdata` commands, and reports folder-layout drift.
222
+ 2. `pm-pdata-do-update-consuming-skills` - finds skills that literally reference the old paths and
223
+ rewrites direct reads/writes to `ccst pdata` commands, flagging anything it cannot rewrite
224
+ mechanically.
225
+
226
+ Relay each subagent's report to the user, including anything flagged for a human decision. If a
227
+ later `--write` round adds more record groups, run both again; they are safe to re-run.
228
+
213
229
  ## 8. Rollback, if something's found wrong post-cutover
214
230
 
215
231
  There is no `--rollback` flag. Recover by hand: