cc-session-tools 2.8.1__tar.gz → 2.8.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 (255) hide show
  1. {cc_session_tools-2.8.1/src/cc_session_tools.egg-info → cc_session_tools-2.8.2}/PKG-INFO +1 -1
  2. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/pyproject.toml +1 -1
  3. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/ccst.py +35 -8
  4. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/service.py +9 -3
  5. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/pm-pdata-schema-design/SKILL.md +20 -0
  6. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2/src/cc_session_tools.egg-info}/PKG-INFO +1 -1
  7. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_bundle_discovery.py +17 -1
  8. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_pdata_cli.py +22 -0
  9. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_pdata_init_cli.py +7 -0
  10. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/LICENSE +0 -0
  11. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/README.md +0 -0
  12. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/setup.cfg +0 -0
  13. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/__init__.py +0 -0
  14. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/__init__.py +0 -0
  15. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/ccd.py +0 -0
  16. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/ccmsg.py +0 -0
  17. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/ccr.py +0 -0
  18. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/ccs.py +0 -0
  19. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/ccsched.py +0 -0
  20. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/migrate_ccmsg.py +0 -0
  21. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/migrate_ccsched.py +0 -0
  22. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/migrate_sessions_db.py +0 -0
  23. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/cli/migrate_telemetry.py +0 -0
  24. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/config/hooks-bundle.json +0 -0
  25. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/config/session-tag-hook.json +0 -0
  26. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/hooks_install.py +0 -0
  27. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/__init__.py +0 -0
  28. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/claude_flags.py +0 -0
  29. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/claude_md_install.py +0 -0
  30. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/context_overrides.py +0 -0
  31. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/db.py +0 -0
  32. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/debug.py +0 -0
  33. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/doctor.py +0 -0
  34. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/doctor_mutes.py +0 -0
  35. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/hook_registry.py +0 -0
  36. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/install_sync.py +0 -0
  37. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/levenshtein.py +0 -0
  38. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/__init__.py +0 -0
  39. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/addressing.py +0 -0
  40. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/cursor.py +0 -0
  41. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/lock.py +0 -0
  42. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/message.py +0 -0
  43. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/move_safety.py +0 -0
  44. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/repository.py +0 -0
  45. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/retention.py +0 -0
  46. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/service.py +0 -0
  47. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/messaging/store.py +0 -0
  48. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/paths.py +0 -0
  49. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/__init__.py +0 -0
  50. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/backup.py +0 -0
  51. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/classify.py +0 -0
  52. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/cutover.py +0 -0
  53. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/formatting.py +0 -0
  54. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/importers.py +0 -0
  55. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/init_paths.py +0 -0
  56. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/init_service.py +0 -0
  57. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/manifest.py +0 -0
  58. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/naming.py +0 -0
  59. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/reorganize.py +0 -0
  60. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/repository.py +0 -0
  61. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/session_output.py +0 -0
  62. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/store.py +0 -0
  63. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/verify.py +0 -0
  64. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/pdata/write_log.py +0 -0
  65. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/picker.py +0 -0
  66. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/proc_lock.py +0 -0
  67. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/prompts.py +0 -0
  68. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/roots.py +0 -0
  69. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/rules.py +0 -0
  70. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/__init__.py +0 -0
  71. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/bundled_jobs.py +0 -0
  72. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/cadence.py +0 -0
  73. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/cursor.py +0 -0
  74. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/digest.py +0 -0
  75. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/due.py +0 -0
  76. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/duration.py +0 -0
  77. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/jobspec.py +0 -0
  78. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/ledger.py +0 -0
  79. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/lock.py +0 -0
  80. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/notify.py +0 -0
  81. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/reconcile.py +0 -0
  82. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/registry.py +0 -0
  83. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/runner.py +0 -0
  84. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/state.py +0 -0
  85. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/store.py +0 -0
  86. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/surface.py +0 -0
  87. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/throttle.py +0 -0
  88. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/scheduler/worker.py +0 -0
  89. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/session_gc.py +0 -0
  90. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/sessions.py +0 -0
  91. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/sessions_db.py +0 -0
  92. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/sessions_repair.py +0 -0
  93. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/shell_install.py +0 -0
  94. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/tasklist.py +0 -0
  95. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/lib/telemetry_store.py +0 -0
  96. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/prompts/pdata-migration-claude-md-update.md +0 -0
  97. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/prompts/pdata-migration-skills-update.md +0 -0
  98. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/analyse-cc-usage/SKILL.md +0 -0
  99. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/context-override/SKILL.md +0 -0
  100. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/delete-sessions/SKILL.md +0 -0
  101. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/delete-sessions/scripts/delete_sessions.py +0 -0
  102. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/do-executor-critic-assessor-loop/SKILL.md +0 -0
  103. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/find-claude-code-session/SKILL.md +0 -0
  104. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/generate-8digit-code/SKILL.md +0 -0
  105. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/generate-8digit-code/scripts/generate_8digit_code.py +0 -0
  106. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/list-empty-sessions/SKILL.md +0 -0
  107. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/list-empty-sessions/scripts/list_empty_sessions.py +0 -0
  108. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/manage-recurring-cc-jobs-using-ccsched/SKILL.md +0 -0
  109. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/move-session/SKILL.md +0 -0
  110. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/move-session/hooks/sessionstart-pending-rename.sh +0 -0
  111. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/move-session/scripts/cc_session_rules.py +0 -0
  112. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/move-session/scripts/move_session.py +0 -0
  113. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/pm-pdata-conflict-resolution/SKILL.md +0 -0
  114. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/pm-project-init/SKILL.md +0 -0
  115. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/pm-project-layout-reference/SKILL.md +0 -0
  116. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/pm-update-central-files/SKILL.md +0 -0
  117. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/reduce-persistent-context/CALIBRATION.md +0 -0
  118. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/reduce-persistent-context/SKILL.md +0 -0
  119. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/analyze_context.py +0 -0
  120. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/duplicates.py +0 -0
  121. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/measure.py +0 -0
  122. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/report.py +0 -0
  123. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/tokens.py +0 -0
  124. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/reduce-persistent-context/scripts/usage.py +0 -0
  125. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/select-agent-model/SKILL.md +0 -0
  126. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/send-session-message/SKILL.md +0 -0
  127. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/update-command-cache/SKILL.md +0 -0
  128. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools/skills/update-command-cache/scripts/update_command_cache.py +0 -0
  129. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools.egg-info/SOURCES.txt +0 -0
  130. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools.egg-info/dependency_links.txt +0 -0
  131. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools.egg-info/entry_points.txt +0 -0
  132. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools.egg-info/requires.txt +0 -0
  133. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cc_session_tools.egg-info/top_level.txt +0 -0
  134. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/__init__.py +0 -0
  135. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/after_response.py +0 -0
  136. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/bash_hard_deny.py +0 -0
  137. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/bash_security_review.py +0 -0
  138. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/cache.py +0 -0
  139. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/catchup.py +0 -0
  140. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/confirm_8digit.py +0 -0
  141. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/context_window_warning.py +0 -0
  142. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/last_screenshot.py +0 -0
  143. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/marker_allow.py +0 -0
  144. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/markers.py +0 -0
  145. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/messaging_deliver.py +0 -0
  146. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/model_info.py +0 -0
  147. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/normalise.py +0 -0
  148. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/pending_migration.py +0 -0
  149. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/pending_rename.py +0 -0
  150. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/session_tag.py +0 -0
  151. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/stats.py +0 -0
  152. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/telemetry.py +0 -0
  153. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/telemetry_query.py +0 -0
  154. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/telemetry_trim.py +0 -0
  155. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/transcript.py +0 -0
  156. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/cccs_hooks/worklog_guard.py +0 -0
  157. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/__init__.py +0 -0
  158. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/attribution.py +0 -0
  159. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/cache.py +0 -0
  160. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/ccusage_wrapper.py +0 -0
  161. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/cli.py +0 -0
  162. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/data/pricing.json +0 -0
  163. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/parent_inference.py +0 -0
  164. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/parser.py +0 -0
  165. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/pricing.py +0 -0
  166. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/query.py +0 -0
  167. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/report.py +0 -0
  168. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/schema.py +0 -0
  169. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/src/claude_code_usage/session_names.py +0 -0
  170. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_after_response.py +0 -0
  171. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_attribution.py +0 -0
  172. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_bash_hard_deny.py +0 -0
  173. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_bash_security_review.py +0 -0
  174. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_cache.py +0 -0
  175. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_cache_sqlite.py +0 -0
  176. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccr_orphans.py +0 -0
  177. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccs_emptiness.py +0 -0
  178. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccs_eta.py +0 -0
  179. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccs_list_mode.py +0 -0
  180. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccs_scope_flags.py +0 -0
  181. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccs_sentinel_sort.py +0 -0
  182. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccs_session_counts.py +0 -0
  183. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_ccsched_jobs_cli.py +0 -0
  184. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_cli.py +0 -0
  185. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_context_override_cli.py +0 -0
  186. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_doctor.py +0 -0
  187. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_gc_report.py +0 -0
  188. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_hook_dispatcher.py +0 -0
  189. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_hooks_install_prune.py +0 -0
  190. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_hooks_install_zero_arg.py +0 -0
  191. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_hooks_uninstall.py +0 -0
  192. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_install_everything.py +0 -0
  193. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_main_gate.py +0 -0
  194. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_pdata_reconcile_cli.py +0 -0
  195. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_pdata_reorganize_cli.py +0 -0
  196. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_pdata_verify_cli.py +0 -0
  197. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_repair_sessions_cli.py +0 -0
  198. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_sessions_cli.py +0 -0
  199. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_shell_install.py +0 -0
  200. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_skills_install.py +0 -0
  201. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_skills_uninstall.py +0 -0
  202. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_telemetry_query.py +0 -0
  203. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccst_telemetry_trim.py +0 -0
  204. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_ccusage_wrapper.py +0 -0
  205. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_claude_flags.py +0 -0
  206. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_claude_md_install.py +0 -0
  207. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_cli.py +0 -0
  208. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_cli_ccd.py +0 -0
  209. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_cli_ccd_dry_run.py +0 -0
  210. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_cli_ccr.py +0 -0
  211. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_cli_ccs.py +0 -0
  212. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_cli_version.py +0 -0
  213. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_confirm_8digit.py +0 -0
  214. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_context_overrides.py +0 -0
  215. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_context_window_warning.py +0 -0
  216. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_db.py +0 -0
  217. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_debug.py +0 -0
  218. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_doctor_mutes.py +0 -0
  219. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_empty_session.py +0 -0
  220. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_hook_cache.py +0 -0
  221. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_hooks_install.py +0 -0
  222. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_install_sync.py +0 -0
  223. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_last_screenshot.py +0 -0
  224. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_levenshtein.py +0 -0
  225. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_marker_allow.py +0 -0
  226. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_migrate_ccmsg.py +0 -0
  227. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_migrate_ccsched.py +0 -0
  228. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_migrate_sessions_db.py +0 -0
  229. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_migrate_telemetry.py +0 -0
  230. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_model_info.py +0 -0
  231. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_normalise.py +0 -0
  232. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_parent_inference.py +0 -0
  233. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_parser.py +0 -0
  234. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_paths.py +0 -0
  235. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_pending_migration_hook.py +0 -0
  236. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_picker.py +0 -0
  237. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_pricing.py +0 -0
  238. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_proc_lock.py +0 -0
  239. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_prompts.py +0 -0
  240. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_query.py +0 -0
  241. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_report.py +0 -0
  242. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_roots.py +0 -0
  243. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_rules.py +0 -0
  244. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_scheduler_bundled_jobs.py +0 -0
  245. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_schema.py +0 -0
  246. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_session_names.py +0 -0
  247. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_session_tag.py +0 -0
  248. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_sessions.py +0 -0
  249. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_sessions_db.py +0 -0
  250. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_sessions_repair.py +0 -0
  251. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_tasklist.py +0 -0
  252. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_telemetry.py +0 -0
  253. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_telemetry_store.py +0 -0
  254. {cc_session_tools-2.8.1 → cc_session_tools-2.8.2}/tests/test_transcript.py +0 -0
  255. {cc_session_tools-2.8.1 → cc_session_tools-2.8.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: 2.8.1
3
+ Version: 2.8.2
4
4
  Summary: Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (cccs_hooks)
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 = "2.8.1"
7
+ version = "2.8.2"
8
8
  description = "Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (cccs_hooks)"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -137,9 +137,18 @@ def _discover_prompts_dir() -> Path:
137
137
  )
138
138
 
139
139
 
140
- def _print_migration_prompt_reminders(*labeled_filenames: tuple[str, str]) -> None:
140
+ def _print_migration_prompt_reminders(
141
+ project_root: Path, *labeled_filenames: tuple[str, str]
142
+ ) -> None:
141
143
  """Print one "<label>: <path>" reminder line per (label, filename) pair, for the bundled
142
- prompts/ directory.
144
+ prompts/ directory, followed by a line telling the user to run it in a fresh Claude Code
145
+ session started in project_root.
146
+
147
+ Each prompt's own "Run it via" section already spells out the `cd <project> && claude -p
148
+ ...` invocation (see e.g. pdata-migration-skills-update.md) - that only works if the
149
+ session's cwd is the project root, since every prompt's Step 1 checks for it and aborts
150
+ otherwise. Printing the reminder without saying so reads as "open this file", which invites
151
+ running it inline in whatever session called `ccst pdata init` - the wrong cwd entirely.
143
152
 
144
153
  Best-effort, deliberately swallowing a missing prompts/ directory: these reminders are a
145
154
  nicety layered on top of an otherwise-already-completed classification or migration, not
@@ -154,6 +163,10 @@ def _print_migration_prompt_reminders(*labeled_filenames: tuple[str, str]) -> No
154
163
  return
155
164
  for label, filename in labeled_filenames:
156
165
  print(f"{label}: {prompts_dir / filename}")
166
+ print(
167
+ f" Run in a new Claude Code session started in {project_root} (its own "
168
+ f"\"Run it via\" section has the exact command) - not in this session."
169
+ )
157
170
 
158
171
 
159
172
  # ---------- skills install ----------
@@ -875,14 +888,19 @@ def _cmd_gc_report(args: argparse.Namespace) -> int:
875
888
  # ---------- pdata ----------
876
889
 
877
890
 
878
- def _parse_field_assignment(raw: str) -> tuple[str, str]:
879
- """Parse "k=v" into (k, v). Raises ValueError on malformed input."""
891
+ def _parse_field_assignment(raw: str) -> tuple[str, str | None]:
892
+ """Parse "k=v" into (k, v). The literal token `null` (unquoted, lowercase) is interpreted
893
+ as SQL NULL rather than the four-character string "null" - this is the documented way to
894
+ clear/unset a field via --field (see check-tesco-shop-due's SKILL.md for a real caller that
895
+ relies on it). A field genuinely needing to store the text "null" cannot be written via
896
+ --field; there's no escape hatch for that case since --field has no quoting syntax at all.
897
+ Raises ValueError on malformed input."""
880
898
  if "=" not in raw:
881
899
  raise ValueError(f"malformed --field assignment (want name=value): {raw!r}")
882
900
  name, value = raw.split("=", 1)
883
901
  if not name:
884
902
  raise ValueError(f"malformed --field assignment (want name=value): {raw!r}")
885
- return name, value
903
+ return name, (None if value == "null" else value)
886
904
 
887
905
 
888
906
  def _cmd_pdata_add(args: argparse.Namespace) -> int:
@@ -1091,6 +1109,7 @@ def _cmd_pdata_init(args: argparse.Namespace) -> int:
1091
1109
  print(result.report)
1092
1110
  print(f"\nProposal: {result.proposal_path}")
1093
1111
  _print_migration_prompt_reminders(
1112
+ result.proposal_path.parent,
1094
1113
  ("After a successful --write, update project docs", "pdata-migration-claude-md-update.md"),
1095
1114
  )
1096
1115
  return 0
@@ -1129,6 +1148,7 @@ def _cmd_pdata_init(args: argparse.Namespace) -> int:
1129
1148
  print(write_result.report) # spec §7.1 step 4's diff report, for review
1130
1149
  print(f"\nVerify: ccst pdata verify --project {args.project} --full")
1131
1150
  _print_migration_prompt_reminders(
1151
+ project_root,
1132
1152
  ("Update project docs", "pdata-migration-claude-md-update.md"),
1133
1153
  ("Update consuming skills", "pdata-migration-skills-update.md"),
1134
1154
  )
@@ -2099,7 +2119,8 @@ def _build_parser() -> argparse.ArgumentParser:
2099
2119
  pdata_add_parser.add_argument(
2100
2120
  "--field", action="append", default=[], metavar="NAME=VALUE",
2101
2121
  help="Extension field assignment; may repeat. Field must already be registered via "
2102
- "'ccst pdata schema add-field'.",
2122
+ "'ccst pdata schema add-field'. VALUE of the literal token 'null' sets SQL NULL "
2123
+ "rather than the string \"null\".",
2103
2124
  )
2104
2125
 
2105
2126
  pdata_schema_parser = pdata_sub.add_parser("schema", help="Schema discovery and evolution")
@@ -2168,13 +2189,19 @@ def _build_parser() -> argparse.ArgumentParser:
2168
2189
  pdata_update_parser.add_argument(
2169
2190
  "--content", default=None,
2170
2191
  help="New content. Omit to leave content unchanged (at least one of --content, "
2171
- "--file, --field is required)",
2192
+ "--file, --field is required). Never re-derived from --field - if a record's "
2193
+ "content is meant to mirror its fields, pass a matching --content on every "
2194
+ "--field update yourself.",
2172
2195
  )
2173
2196
  pdata_update_parser.add_argument(
2174
2197
  "--file", default=None, metavar="PATH",
2175
2198
  help="New relative file path. Omit to leave the existing file_path unchanged.",
2176
2199
  )
2177
- pdata_update_parser.add_argument("--field", action="append", default=[], metavar="NAME=VALUE")
2200
+ pdata_update_parser.add_argument(
2201
+ "--field", action="append", default=[], metavar="NAME=VALUE",
2202
+ help="Extension field assignment; may repeat. Never updates content (see --content). "
2203
+ "VALUE of the literal token 'null' sets SQL NULL rather than the string \"null\".",
2204
+ )
2178
2205
  pdata_update_parser.add_argument(
2179
2206
  "--format", choices=("table", "json"), default="table",
2180
2207
  help="Format used only for the conflict diff on a version mismatch",
@@ -87,7 +87,7 @@ def add_record(
87
87
  record_group: str,
88
88
  content: str,
89
89
  file_path: str | None,
90
- fields: Mapping[str, str],
90
+ fields: Mapping[str, str | None],
91
91
  created_at: int | None = None,
92
92
  ) -> Record:
93
93
  naming.validate_record_group(record_group)
@@ -294,14 +294,20 @@ def update_record(
294
294
  expected_version: int,
295
295
  content: str | None,
296
296
  file_path: str | None,
297
- fields: Mapping[str, str],
297
+ fields: Mapping[str, str | None],
298
298
  updated_at: int | None = None,
299
299
  ) -> Record:
300
300
  """content and file_path are each optional (spec §5's `[--content "..."] [--file <path>]`)
301
301
  — omitting one (passing None) leaves that column unchanged; it does not clear it. At least
302
302
  one of content, file_path, or fields must be given, or this is a no-op update request that
303
303
  only bumps version/updated_at for nothing (this repo's coding standard: reject inputs that
304
- ask the system to do nothing)."""
304
+ ask the system to do nothing).
305
+
306
+ content and fields are independent — updating fields never re-serializes content, and vice
307
+ versa. This is deliberate (it's what lets a --field-only update skip resending content), not
308
+ a gap: a record group whose content is designed to mirror its fields is the caller's own
309
+ duplication to keep in sync, on every write, by passing both. See pm-pdata-schema-design
310
+ SKILL.md's "content and extension fields are never auto-synced" section."""
305
311
  if content is None and file_path is None and not fields:
306
312
  raise ValueError(
307
313
  "ccst pdata update requires at least one of --content, --file, or --field"
@@ -72,6 +72,26 @@ for that information (spec §4.4: `record_group_fields` stores no type informati
72
72
  a field with a blank description is genuinely undocumented for the next session that runs `schema
73
73
  show`).
74
74
 
75
+ ## `content` and extension fields are never auto-synced
76
+
77
+ `ccst pdata update` treats `--content` and `--field` as independent, both-optional writes -
78
+ updating one never re-derives the other, for any record group. If a group's design has `content`
79
+ hold the same values as one or more extension fields (e.g. a JSON snapshot that duplicates fields
80
+ also exposed for querying), every caller that updates those fields via `--field` alone leaves
81
+ `content` silently stale from that point on. There is no code-level fix for this - it is the
82
+ tool's actual contract, not a bug in it (`ccst pdata update`'s optional `--content`/`--file`/
83
+ `--field` shape exists precisely so a `--field`-only update doesn't have to resend `content`).
84
+
85
+ Two ways to avoid the trap, not one - pick per record group:
86
+ - Don't duplicate the data in the first place: either the fields are the record (no matching keys
87
+ in `content`), or `content` is the record and nothing needs the duplicated fields to be queryable.
88
+ - If both really are needed, the caller updating fields is responsible for also passing a
89
+ matching `--content` on every write that changes a mirrored field - `ccst pdata update` will not
90
+ do this for you.
91
+
92
+ A `--field` value of the literal token `null` (unquoted) sets that column to real SQL `NULL` - it
93
+ is not possible to write the four-character string `"null"` into a field via `--field`.
94
+
75
95
  ## Quick reference
76
96
 
77
97
  | Question | Where the answer comes from |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-session-tools
3
- Version: 2.8.1
3
+ Version: 2.8.2
4
4
  Summary: Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (cccs_hooks)
5
5
  Author: raffishquartan
6
6
  License: MIT License
@@ -84,13 +84,29 @@ def test_print_migration_prompt_reminders_degrades_gracefully_when_prompts_dir_m
84
84
 
85
85
  monkeypatch.setattr(ccst, "_discover_prompts_dir", _raise)
86
86
 
87
- ccst._print_migration_prompt_reminders(("Update project docs", "some-prompt.md"))
87
+ ccst._print_migration_prompt_reminders(
88
+ Path("/some/project"), ("Update project docs", "some-prompt.md")
89
+ )
88
90
 
89
91
  captured = capsys.readouterr()
90
92
  assert captured.out == "" # nothing bogus printed to stdout (would land in --write's log)
91
93
  assert "Cannot locate bundled prompts" in captured.err
92
94
 
93
95
 
96
+ def test_print_migration_prompt_reminders_tells_user_to_run_in_project_dir(capsys):
97
+ """Each reminder must say to run the prompt in a fresh CC session started in the project
98
+ directory — the prompt's own Step 1 aborts if cwd isn't the project root, so a bare path
99
+ with no such instruction invites running it inline in the current (wrong-cwd) session."""
100
+ ccst._print_migration_prompt_reminders(
101
+ Path("/home/chris/cc/demo"), ("Update project docs", "pdata-migration-claude-md-update.md")
102
+ )
103
+
104
+ captured = capsys.readouterr()
105
+ assert "pdata-migration-claude-md-update.md" in captured.out
106
+ assert "new Claude Code session" in captured.out
107
+ assert "/home/chris/cc/demo" in captured.out
108
+
109
+
94
110
  def test_bundled_prompts_are_no_longer_placeholders():
95
111
  prompts_dir = ccst._discover_prompts_dir()
96
112
  for filename in ("pdata-migration-claude-md-update.md", "pdata-migration-skills-update.md"):
@@ -206,6 +206,28 @@ def test_pdata_update_without_file_preserves_existing_file_path(base_env):
206
206
  assert "filings/keep.md" in r_get.stdout
207
207
 
208
208
 
209
+ def test_pdata_update_field_null_literal_sets_true_null(base_env):
210
+ """Regression test: --field name=null (the literal token null, unquoted) must set the
211
+ column to real SQL NULL, not the four-character string "null" - check-tesco-shop-due's
212
+ SKILL.md already documents --field next_upcoming_delivery=null as the way to clear that
213
+ field, so the CLI must actually honour it."""
214
+ _run(base_env, "pdata", "schema", "add-field", "--project", "testproj",
215
+ "--group", "key-events", "--field", "sender:TEXT")
216
+ r_add = _run(base_env, "pdata", "add", "--project", "testproj", "--group", "key-events",
217
+ "--content", "an event", "--field", "sender=alice")
218
+ record_id = r_add.stdout.strip()
219
+
220
+ r_update = _run(base_env, "pdata", "update", "--project", "testproj", "--id", record_id,
221
+ "--version", "1", "--field", "sender=null")
222
+ assert r_update.returncode == 0, r_update.stderr
223
+
224
+ r_list = _run(base_env, "pdata", "list", "--project", "testproj", "--group", "key-events",
225
+ "--format", "json")
226
+ import json
227
+ parsed = json.loads(r_list.stdout)
228
+ assert parsed[0]["sender"] is None
229
+
230
+
209
231
  def test_pdata_update_rejects_empty_update(base_env):
210
232
  r_add = _run(base_env, "pdata", "add", "--project", "testproj", "--group", "notes",
211
233
  "--content", "x")
@@ -55,6 +55,11 @@ def test_pdata_init_dry_run_prints_doc_update_prompt_path(base_env, tmp_path):
55
55
  r = _run(base_env, "pdata", "init", "--project", "demo")
56
56
  assert r.returncode == 0, r.stderr
57
57
  assert "pdata-migration-claude-md-update.md" in r.stdout
58
+ # Must tell the user to run it in a fresh session started in the project dir - the
59
+ # prompt's own Step 1 aborts otherwise, so a bare path alone invites running it inline
60
+ # in whatever session called `ccst pdata init`.
61
+ assert "new Claude Code session" in r.stdout
62
+ assert str(project_dir) in r.stdout
58
63
 
59
64
 
60
65
  def test_pdata_init_rejects_bad_project_name(base_env):
@@ -187,6 +192,8 @@ def test_pdata_init_write_success_ends_with_success_sentinel_and_verify_command(
187
192
  assert "ccst pdata verify --project demo --full" in r_write.stdout
188
193
  assert "pdata-migration-claude-md-update.md" in r_write.stdout
189
194
  assert "pdata-migration-skills-update.md" in r_write.stdout
195
+ assert r_write.stdout.count("new Claude Code session") == 2 # one per prompt reminder
196
+ assert str(project_dir) in r_write.stdout
190
197
  assert r_write.stdout.rstrip().splitlines()[-1] == "SUCCESS"
191
198
 
192
199
  log_content = (project_dir / "ccst-pdata-init-write.log").read_text()