cc-session-tools 3.2.1__tar.gz → 3.3.1__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.
- {cc_session_tools-3.2.1/src/cc_session_tools.egg-info → cc_session_tools-3.3.1}/PKG-INFO +1 -1
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/pyproject.toml +1 -1
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/ccst.py +20 -5
- cc_session_tools-3.3.1/src/cc_session_tools/lib/pdata/cutover.py +90 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/init_service.py +70 -6
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/manifest.py +9 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/resolve.py +3 -3
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/service.py +1 -1
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/prompts/pdata-migration-claude-md-update.md +9 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/prompts/pdata-migration-skills-update.md +9 -0
- {cc_session_tools-3.2.1/src/cc_session_tools/skills/pm-pdata-schema-design → cc_session_tools-3.3.1/src/cc_session_tools/skills/pm-pdata-design-schema}/SKILL.md +1 -1
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/pm-pdata-do-audit-and-prepare-to-migrate/SKILL.md +17 -8
- {cc_session_tools-3.2.1/src/cc_session_tools/skills/pm-pdata-do-migrate → cc_session_tools-3.3.1/src/cc_session_tools/skills/pm-pdata-do-manual-migration}/SKILL.md +22 -6
- {cc_session_tools-3.2.1/src/cc_session_tools/skills/pm-pdata-conflict-resolution → cc_session_tools-3.3.1/src/cc_session_tools/skills/pm-pdata-resolve-conflicts}/SKILL.md +1 -1
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/pm-project-init/SKILL.md +84 -1
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/pm-project-layout-reference/SKILL.md +1 -1
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1/src/cc_session_tools.egg-info}/PKG-INFO +1 -1
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools.egg-info/SOURCES.txt +3 -3
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_bundle_discovery.py +9 -8
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_pdata_init_cli.py +29 -0
- cc_session_tools-3.2.1/src/cc_session_tools/lib/pdata/cutover.py +0 -34
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/LICENSE +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/README.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/setup.cfg +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/__init__.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/__init__.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/ccd.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/ccmsg.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/ccr.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/ccs.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/ccsched.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/migrate_ccmsg.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/migrate_ccsched.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/migrate_sessions_db.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/cli/migrate_telemetry.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/config/hooks-bundle.json +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/config/session-tag-hook.json +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/hooks_install.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/__init__.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/claude_flags.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/claude_md_install.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/context_overrides.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/db.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/debug.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/doctor.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/doctor_mutes.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/hook_registry.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/install_sync.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/levenshtein.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/machine_identity.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/__init__.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/addressing.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/cursor.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/lock.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/message.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/move_safety.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/repository.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/retention.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/service.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/messaging/store.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/occupancy.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/paths.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/__init__.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/backup.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/classify.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/dump.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/formatting.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/importers.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/init_paths.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/naming.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/rehydrate.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/rename_group.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/reorganize.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/repository.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/session_output.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/store.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/sync_check.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/sync_lock.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/sync_notify.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/vector_clock.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/vector_clock_store.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/verify.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/write_log.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/picker.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/proc_lock.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/prompts.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/roots.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/rules.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/__init__.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/bundled_jobs.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/cadence.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/cursor.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/digest.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/due.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/duration.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/jobspec.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/ledger.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/lock.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/notify.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/reconcile.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/registry.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/runner.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/state.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/store.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/surface.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/throttle.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/scheduler/worker.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/session_gc.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/sessions.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/sessions_db.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/sessions_repair.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/shell_install.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/tasklist.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/telemetry_store.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/analyse-cc-usage/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/clean-hook-sessions/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/clean-hook-sessions/scripts/clean-hook-sessions.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/compact-smart/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/context-override/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/delete-sessions/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/delete-sessions/scripts/delete_sessions.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/do-executor-critic-assessor-loop/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/find-claude-code-session/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/generate-8digit-code/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/generate-8digit-code/scripts/generate_8digit_code.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/list-empty-sessions/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/list-empty-sessions/scripts/list_empty_sessions.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/manage-recurring-cc-jobs-using-ccsched/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/move-session/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/move-session/hooks/sessionstart-pending-rename.sh +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/move-session/scripts/cc_session_rules.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/move-session/scripts/move_session.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/pm-update-central-files/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/reduce-persistent-context/CALIBRATION.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/reduce-persistent-context/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/reduce-persistent-context/scripts/analyze_context.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/reduce-persistent-context/scripts/duplicates.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/reduce-persistent-context/scripts/measure.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/reduce-persistent-context/scripts/report.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/reduce-persistent-context/scripts/tokens.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/reduce-persistent-context/scripts/usage.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/select-agent-model/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/send-session-message/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/update-command-cache/SKILL.md +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/skills/update-command-cache/scripts/update_command_cache.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools.egg-info/dependency_links.txt +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools.egg-info/entry_points.txt +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools.egg-info/requires.txt +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools.egg-info/top_level.txt +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/__init__.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/attribution.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/cache.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/ccusage_wrapper.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/data/pricing.json +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/parent_inference.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/parser.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/pricing.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/query.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/report.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/schema.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/claude_code_usage/session_names.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/__init__.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/after_response.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/bash_hard_deny.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/bash_security_review.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/cache.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/catchup.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/confirm_8digit.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/context_window_warning.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/last_screenshot.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/marker_allow.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/markers.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/messaging_deliver.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/model_info.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/normalise.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/pdata_sync.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/pending_migration.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/pending_rename.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/session_tag.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/stats.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/telemetry.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/telemetry_query.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/telemetry_trim.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/transcript.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/hooks/worklog_guard.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_after_response.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_attribution.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_bash_hard_deny.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_bash_security_review.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_cache.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_cache_sqlite.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccr_orphans.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccs_emptiness.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccs_eta.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccs_list_mode.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccs_scope_flags.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccs_sentinel_sort.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccs_session_counts.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_ccsched_jobs_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_context_override_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_doctor.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_gc_prune.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_gc_report.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_hook_dispatcher.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_hooks_install_prune.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_hooks_install_zero_arg.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_hooks_uninstall.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_install_everything.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_machine_identity_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_main_gate.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_pdata_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_pdata_reconcile_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_pdata_rename_group_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_pdata_reorganize_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_pdata_sync_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_pdata_verify_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_repair_sessions_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_sessions_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_shell_install.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_skills_install.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_skills_uninstall.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_telemetry_query.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccst_telemetry_trim.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_ccusage_wrapper.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_claude_flags.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_claude_md_install.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_cli.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_cli_ccd.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_cli_ccd_dry_run.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_cli_ccr.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_cli_ccs.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_cli_version.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_confirm_8digit.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_context_overrides.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_context_window_warning.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_db.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_debug.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_doctor_mutes.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_empty_session.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_hook_cache.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_hooks_install.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_install_sync.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_last_screenshot.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_levenshtein.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_machine_identity.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_marker_allow.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_migrate_ccmsg.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_migrate_ccsched.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_migrate_sessions_db.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_migrate_telemetry.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_model_info.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_normalise.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_occupancy.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_parent_inference.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_parser.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_paths.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_pending_migration_hook.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_picker.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_pricing.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_proc_lock.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_prompts.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_query.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_report.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_roots.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_rules.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_scheduler_bundled_jobs.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_schema.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_session_names.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_session_tag.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_sessions.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_sessions_db.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_sessions_repair.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_tasklist.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_telemetry.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_telemetry_store.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_transcript.py +0 -0
- {cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/tests/test_worklog_guard.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cc-session-tools"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.3.1"
|
|
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" }
|
|
@@ -173,14 +173,19 @@ def _print_migration_prompt_reminders(
|
|
|
173
173
|
project_root: Path, *labeled_filenames: tuple[str, str]
|
|
174
174
|
) -> None:
|
|
175
175
|
"""Print one "<label>: <path>" reminder line per (label, filename) pair, for the bundled
|
|
176
|
-
prompts/ directory, followed by a line telling the user to run it in a fresh
|
|
177
|
-
session started in project_root.
|
|
176
|
+
prompts/ directory, followed by a line telling the user to run it in a fresh context (a new
|
|
177
|
+
Claude Code session, or a dispatched Agent subagent) started in project_root.
|
|
178
178
|
|
|
179
179
|
Each prompt's own "Run it via" section already spells out the `cd <project> && claude -p
|
|
180
180
|
...` invocation (see e.g. pdata-migration-skills-update.md) - that only works if the
|
|
181
181
|
session's cwd is the project root, since every prompt's Step 1 checks for it and aborts
|
|
182
|
-
otherwise.
|
|
183
|
-
|
|
182
|
+
otherwise. What the fresh-context requirement is actually protecting against is an
|
|
183
|
+
orchestrating session rationalizing away a stale reference it half-remembers writing
|
|
184
|
+
earlier in the same conversation - a dispatched Agent subagent (same cwd) gets that same
|
|
185
|
+
benefit without shelling out to a literal second process, so both are offered here rather
|
|
186
|
+
than only the `claude -p` invocation. Printing the reminder without saying so reads as "open
|
|
187
|
+
this file", which invites running it inline in whatever session called `ccst pdata init` -
|
|
188
|
+
the wrong cwd entirely.
|
|
184
189
|
|
|
185
190
|
Best-effort, deliberately swallowing a missing prompts/ directory: these reminders are a
|
|
186
191
|
nicety layered on top of an otherwise-already-completed classification or migration, not
|
|
@@ -197,7 +202,8 @@ def _print_migration_prompt_reminders(
|
|
|
197
202
|
print(f"{label}: {prompts_dir / filename}")
|
|
198
203
|
print(
|
|
199
204
|
f" Run in a new Claude Code session started in {project_root} (its own "
|
|
200
|
-
f"\"Run it via\" section has the exact command)
|
|
205
|
+
f"\"Run it via\" section has the exact command), or dispatch it as an Agent "
|
|
206
|
+
f"subagent with the same cwd - not inline in this session."
|
|
201
207
|
)
|
|
202
208
|
|
|
203
209
|
|
|
@@ -1178,6 +1184,7 @@ def _cmd_pdata_init(args: argparse.Namespace) -> int:
|
|
|
1178
1184
|
try:
|
|
1179
1185
|
write_result = init_service.write(
|
|
1180
1186
|
project=args.project, rehearse=rehearse, on_progress=print,
|
|
1187
|
+
leave_no_pointer_files=args.leave_no_pointer_files,
|
|
1181
1188
|
)
|
|
1182
1189
|
except (FileNotFoundError, ValueError) as exc:
|
|
1183
1190
|
print(f"ccst pdata: {exc}", file=sys.stderr)
|
|
@@ -3035,6 +3042,14 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
3035
3042
|
"<project>/ccst-pdata-init-write.log"
|
|
3036
3043
|
),
|
|
3037
3044
|
)
|
|
3045
|
+
pdata_init_parser.add_argument(
|
|
3046
|
+
"--leave-no-pointer-files", action="store_true",
|
|
3047
|
+
help=(
|
|
3048
|
+
"By default, --write leaves a Markdown pointer file at each migrated entry's "
|
|
3049
|
+
"original path (record_group, schema, an example query command). Pass this "
|
|
3050
|
+
"flag to suppress that and leave nothing behind at the original path."
|
|
3051
|
+
),
|
|
3052
|
+
)
|
|
3038
3053
|
|
|
3039
3054
|
pdata_reorganize_parser = pdata_sub.add_parser(
|
|
3040
3055
|
"reorganize", help="Split a flat folder into a nested (by-year or by-year-month) structure"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Cutover: archive migrated-source originals, never delete them (spec §7.1 steps 6-7)."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import time
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from cc_session_tools.lib.pdata.init_paths import (
|
|
8
|
+
MIGRATED_ARCHIVE_DIRNAME,
|
|
9
|
+
MIGRATED_MANIFEST_FILENAME,
|
|
10
|
+
)
|
|
11
|
+
from cc_session_tools.lib.pdata.manifest import ManifestEntry
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _pointer_file_content(*, project: str, entry: ManifestEntry) -> str:
|
|
15
|
+
"""Generic pointer content (spec pdata/init-pointer-files): the record_group now
|
|
16
|
+
holding this file's data, its field/schema table, and an example query — plus,
|
|
17
|
+
when the entry carries preface_text (set by hand per pm-project-init's
|
|
18
|
+
garbled-CSV-header fix recipe), that text verbatim under its own heading."""
|
|
19
|
+
lines = [
|
|
20
|
+
f"# {Path(entry.path).name} — migrated to pdata",
|
|
21
|
+
"",
|
|
22
|
+
f"This file's data now lives in pdata record group `{entry.db_group()}` for "
|
|
23
|
+
f"project `{project}`. The original was moved to "
|
|
24
|
+
f"`{MIGRATED_ARCHIVE_DIRNAME}/{entry.path}` and is no longer read from here.",
|
|
25
|
+
"",
|
|
26
|
+
"## Schema",
|
|
27
|
+
"",
|
|
28
|
+
"| field | sql_type | description |",
|
|
29
|
+
"| --- | --- | --- |",
|
|
30
|
+
]
|
|
31
|
+
for spec in entry.fields:
|
|
32
|
+
lines.append(f"| {spec.name} | {spec.sql_type} | {spec.description or ''} |")
|
|
33
|
+
lines += [
|
|
34
|
+
"",
|
|
35
|
+
"## Example query",
|
|
36
|
+
"",
|
|
37
|
+
"```sh",
|
|
38
|
+
f"ccst pdata list --project {project} --group {entry.db_group()}",
|
|
39
|
+
"```",
|
|
40
|
+
]
|
|
41
|
+
if entry.preface_text:
|
|
42
|
+
lines += [
|
|
43
|
+
"",
|
|
44
|
+
"## Preserved preface text (removed from the original file before migration)",
|
|
45
|
+
"",
|
|
46
|
+
entry.preface_text,
|
|
47
|
+
]
|
|
48
|
+
return "\n".join(lines) + "\n"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _write_pointer_file(*, project_root: Path, project: str, entry: ManifestEntry) -> None:
|
|
52
|
+
pointer_path = project_root / Path(entry.path).with_suffix(".md")
|
|
53
|
+
pointer_path.parent.mkdir(parents=True, exist_ok=True)
|
|
54
|
+
pointer_path.write_text(
|
|
55
|
+
_pointer_file_content(project=project, entry=entry), encoding="utf-8",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def archive_entries(
|
|
60
|
+
*, project_root: Path, entries: list[ManifestEntry], project: str,
|
|
61
|
+
write_pointer_files: bool = True,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""Move every db-owned entry's source file into project_root/.pdata-migrated/,
|
|
64
|
+
preserving its relative path, and append one line per entry to MANIFEST.md.
|
|
65
|
+
Never deletes — cutover only relocates within project_root (spec §7.1 step 6);
|
|
66
|
+
deleting the archive is a manual, human-directed action (step 7).
|
|
67
|
+
|
|
68
|
+
By default (write_pointer_files=True, spec pdata/init-pointer-files), also writes a
|
|
69
|
+
Markdown pointer file back at each entry's original path so anything else in the
|
|
70
|
+
project that cites the old path by name finds a live signpost instead of a silent
|
|
71
|
+
404. Pass write_pointer_files=False (--leave-no-pointer-files at the CLI) to
|
|
72
|
+
suppress this."""
|
|
73
|
+
if not entries:
|
|
74
|
+
return
|
|
75
|
+
archive_root = project_root / MIGRATED_ARCHIVE_DIRNAME
|
|
76
|
+
archive_root.mkdir(parents=True, exist_ok=True)
|
|
77
|
+
manifest_path = archive_root / MIGRATED_MANIFEST_FILENAME
|
|
78
|
+
now = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
|
79
|
+
with manifest_path.open("a", encoding="utf-8") as log:
|
|
80
|
+
for entry in entries:
|
|
81
|
+
source = project_root / entry.path
|
|
82
|
+
destination = archive_root / entry.path
|
|
83
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
84
|
+
source.rename(destination)
|
|
85
|
+
log.write(
|
|
86
|
+
f"- {now} — {entry.path} — migrated source, superseded by ccst pdata "
|
|
87
|
+
f"(record_group={entry.db_group()})\n"
|
|
88
|
+
)
|
|
89
|
+
if write_pointer_files:
|
|
90
|
+
_write_pointer_file(project_root=project_root, project=project, entry=entry)
|
{cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/init_service.py
RENAMED
|
@@ -8,7 +8,7 @@ import csv
|
|
|
8
8
|
import sqlite3
|
|
9
9
|
from collections.abc import Callable
|
|
10
10
|
from dataclasses import dataclass
|
|
11
|
-
from datetime import datetime
|
|
11
|
+
from datetime import UTC, datetime
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
|
|
14
14
|
from cc_session_tools.lib import db
|
|
@@ -96,6 +96,29 @@ def dry_run(*, project: str, rehearse: Path | None = None) -> DryRunResult:
|
|
|
96
96
|
return DryRunResult(manifest=m, report=_render_report(m), proposal_path=proposal_path)
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
# A field name proposed by _classify_csv is derived from a real CSV header cell (see
|
|
100
|
+
# classify._slugify_field_name) — an ordinary column name slugifies to something short.
|
|
101
|
+
# A garbled header (prose/provenance text on the "header" row, spec pdata/
|
|
102
|
+
# init-classification-report) instead produces long, many-word sentence-fragment names
|
|
103
|
+
# like `pending_chris_s_manual_review`. Neither threshold alone is exact, but a name
|
|
104
|
+
# tripping either is worth a reviewer's second look.
|
|
105
|
+
_SUSPICIOUS_FIELD_NAME_CHAR_THRESHOLD = 40
|
|
106
|
+
_SUSPICIOUS_FIELD_NAME_WORD_THRESHOLD = 5
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _looks_like_garbled_header(field_names: list[str]) -> bool:
|
|
110
|
+
"""True when multiple proposed field names read as sentence fragments rather than
|
|
111
|
+
short domain nouns — see spec pdata/init-classification-report. A single long name
|
|
112
|
+
isn't enough on its own (a legitimately verbose but real column header shouldn't be
|
|
113
|
+
flagged); this looks for the pattern repeating across an entry's fields."""
|
|
114
|
+
suspicious = sum(
|
|
115
|
+
1 for name in field_names
|
|
116
|
+
if len(name) > _SUSPICIOUS_FIELD_NAME_CHAR_THRESHOLD
|
|
117
|
+
or name.count("_") + 1 >= _SUSPICIOUS_FIELD_NAME_WORD_THRESHOLD
|
|
118
|
+
)
|
|
119
|
+
return suspicious >= 2
|
|
120
|
+
|
|
121
|
+
|
|
99
122
|
def _render_report(m: Manifest) -> str:
|
|
100
123
|
if not m.entries:
|
|
101
124
|
return f"ccst pdata init — {m.project}: no files found, empty base schema created."
|
|
@@ -109,6 +132,12 @@ def _render_report(m: Manifest) -> str:
|
|
|
109
132
|
f" [db-owned] {e.path} -> group={e.record_group} "
|
|
110
133
|
f"strategy={e.strategy} fields={field_names}"
|
|
111
134
|
)
|
|
135
|
+
if _looks_like_garbled_header(field_names):
|
|
136
|
+
lines.append(
|
|
137
|
+
" ⚠ worth double-checking — these field names read as sentence "
|
|
138
|
+
"fragments, not column names; this file's header may not be what it "
|
|
139
|
+
"looks like (see pm-project-init's garbled-CSV-header caveat)"
|
|
140
|
+
)
|
|
112
141
|
lines.append(
|
|
113
142
|
"Review/override entries in the proposal file listed below before running --write."
|
|
114
143
|
)
|
|
@@ -352,6 +381,7 @@ def _adopt_from_dump(
|
|
|
352
381
|
def write(
|
|
353
382
|
*, project: str, rehearse: Path | None = None,
|
|
354
383
|
on_progress: Callable[[str], None] | None = None,
|
|
384
|
+
leave_no_pointer_files: bool = False,
|
|
355
385
|
) -> WriteResult:
|
|
356
386
|
project_root = init_paths.resolve_project_root(project, rehearse=rehearse)
|
|
357
387
|
|
|
@@ -396,11 +426,33 @@ def write(
|
|
|
396
426
|
_check_db_not_locked(project)
|
|
397
427
|
|
|
398
428
|
db_owned = [e for e in m.entries if e.classification == "db-owned"]
|
|
399
|
-
|
|
400
|
-
for
|
|
401
|
-
|
|
402
|
-
|
|
429
|
+
already_migrated = [e for e in db_owned if e.migrated_at is not None]
|
|
430
|
+
to_import = [e for e in db_owned if e.migrated_at is None]
|
|
431
|
+
_emit(on_progress, f"Importing {len(to_import)} file(s)...")
|
|
432
|
+
if already_migrated:
|
|
433
|
+
_emit(
|
|
434
|
+
on_progress,
|
|
435
|
+
f" skipping {len(already_migrated)} already-migrated file(s): "
|
|
436
|
+
f"{', '.join(e.path for e in already_migrated)}",
|
|
437
|
+
)
|
|
438
|
+
for entry in to_import:
|
|
403
439
|
try:
|
|
440
|
+
source_path = project_root / entry.path
|
|
441
|
+
if not source_path.exists():
|
|
442
|
+
# entry.migrated_at is None here (to_import excludes already-migrated
|
|
443
|
+
# entries above), so this is not the ordinary "already cut over by an
|
|
444
|
+
# earlier --write" case — the source is genuinely missing for an entry
|
|
445
|
+
# this run believes still needs importing. Fail with a specific,
|
|
446
|
+
# actionable message (still caught by this loop's own except clause
|
|
447
|
+
# below, so it contributes to `reasons`/rollback exactly like any other
|
|
448
|
+
# per-entry import failure) instead of a bare FileNotFoundError only
|
|
449
|
+
# discoverable via the rollback reasons list.
|
|
450
|
+
raise ValueError(
|
|
451
|
+
f"{entry.path}: marked db-owned with no migrated_at, but its source "
|
|
452
|
+
f"file does not exist at {source_path} — if this entry was already "
|
|
453
|
+
f"migrated by another means, set its classification to folder-owned "
|
|
454
|
+
f"(or otherwise correct the manifest) before running --write again"
|
|
455
|
+
)
|
|
404
456
|
_emit(on_progress, f" importing {entry.path} -> group={entry.db_group()}...")
|
|
405
457
|
for spec in entry.fields:
|
|
406
458
|
service.schema_add_field(
|
|
@@ -456,7 +508,19 @@ def write(
|
|
|
456
508
|
)
|
|
457
509
|
|
|
458
510
|
_emit(on_progress, f"Cutting over {len(written_entries)} file(s)...")
|
|
459
|
-
cutover.archive_entries(
|
|
511
|
+
cutover.archive_entries(
|
|
512
|
+
project_root=project_root, entries=written_entries, project=project,
|
|
513
|
+
write_pointer_files=not leave_no_pointer_files,
|
|
514
|
+
)
|
|
515
|
+
# Mark every entry this run actually cut over as migrated, and persist that back to
|
|
516
|
+
# the manifest — write() only ever `manifest.load`s otherwise, so without this a later
|
|
517
|
+
# --write would re-attempt (and, pre-fix, roll back) these same now-archived entries.
|
|
518
|
+
# written_entries holds the same ManifestEntry objects m.entries does (see the
|
|
519
|
+
# `to_import`/`written_entries.append(entry)` loop above), so mutating here mutates m.
|
|
520
|
+
migrated_at = datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
521
|
+
for entry in written_entries:
|
|
522
|
+
entry.migrated_at = migrated_at
|
|
523
|
+
manifest.save(m, proposal_path)
|
|
460
524
|
return WriteResult(
|
|
461
525
|
created_record_ids=created_ids,
|
|
462
526
|
entries_written=[e.path for e in written_entries],
|
{cc_session_tools-3.2.1 → cc_session_tools-3.3.1}/src/cc_session_tools/lib/pdata/manifest.py
RENAMED
|
@@ -40,6 +40,15 @@ class ManifestEntry:
|
|
|
40
40
|
content_column: str | None = None
|
|
41
41
|
file_path_column: str | None = None
|
|
42
42
|
fields: list[FieldSpec] = field(default_factory=list)
|
|
43
|
+
# Set by init_service.write() on successful cutover (ISO-8601 UTC) — a later
|
|
44
|
+
# --write skips any entry that already carries one instead of re-importing it
|
|
45
|
+
# (spec pdata/init-write-idempotency). None for an entry never yet migrated.
|
|
46
|
+
migrated_at: str | None = None
|
|
47
|
+
# Hand-set during review (pm-project-init's garbled-CSV-header fix recipe):
|
|
48
|
+
# header/provenance text stripped from the source file before migration,
|
|
49
|
+
# preserved verbatim here so cutover.archive_entries can carry it into the
|
|
50
|
+
# entry's pointer file (spec pdata/init-pointer-files). None when not applicable.
|
|
51
|
+
preface_text: str | None = None
|
|
43
52
|
|
|
44
53
|
def __post_init__(self) -> None:
|
|
45
54
|
if self.classification not in _VALID_CLASSIFICATIONS:
|
|
@@ -8,7 +8,7 @@ overwrite (that is rehydrate.py's job for the clean fast-forward case; this modu
|
|
|
8
8
|
|
|
9
9
|
Never auto-merges, never silently keeps one side and discards the other — every record surfaced
|
|
10
10
|
here needs an explicit choice from the caller (ultimately Chris, via the CLI/skill), matching the
|
|
11
|
-
existing `pm-pdata-
|
|
11
|
+
existing `pm-pdata-resolve-conflicts` skill's single-file-conflict framing exactly. Every
|
|
12
12
|
record: `apply_resolution` is all-or-nothing over the whole diff, for the reasons in its own
|
|
13
13
|
docstring.
|
|
14
14
|
|
|
@@ -342,7 +342,7 @@ def _apply_resolution(
|
|
|
342
342
|
f"record_id(s) {collisions}: id collision (the same id was independently assigned to "
|
|
343
343
|
f"two unrelated records) — not resolvable as a local/dump choice, since either pick "
|
|
344
344
|
f"would discard one side's real record; needs a manual, out-of-band fix (see the "
|
|
345
|
-
f"pm-pdata-
|
|
345
|
+
f"pm-pdata-resolve-conflicts skill, point 4)"
|
|
346
346
|
)
|
|
347
347
|
|
|
348
348
|
group_mismatches = sorted(rid for rid, rd in by_id.items() if rd.group_mismatch)
|
|
@@ -351,7 +351,7 @@ def _apply_resolution(
|
|
|
351
351
|
f"record_id(s) {group_mismatches}: group mismatch (same id and created_at, but the "
|
|
352
352
|
f"two sides disagree on record_group) — not resolvable as a local/dump choice. "
|
|
353
353
|
f"Compare each side's content/file_path before assuming a rename is safe (see the "
|
|
354
|
-
f"pm-pdata-
|
|
354
|
+
f"pm-pdata-resolve-conflicts skill, point 5, for why it may instead be a "
|
|
355
355
|
f"same-second id collision), then retry"
|
|
356
356
|
)
|
|
357
357
|
|
|
@@ -310,7 +310,7 @@ def update_record(
|
|
|
310
310
|
content and fields are independent — updating fields never re-serializes content, and vice
|
|
311
311
|
versa. This is deliberate (it's what lets a --field-only update skip resending content), not
|
|
312
312
|
a gap: a record group whose content is designed to mirror its fields is the caller's own
|
|
313
|
-
duplication to keep in sync, on every write, by passing both. See pm-pdata-schema
|
|
313
|
+
duplication to keep in sync, on every write, by passing both. See pm-pdata-design-schema
|
|
314
314
|
SKILL.md's "content and extension fields are never auto-synced" section."""
|
|
315
315
|
if content is None and file_path is None and not fields:
|
|
316
316
|
raise ValueError(
|
|
@@ -12,6 +12,15 @@ cd ~/cc/<project> && \
|
|
|
12
12
|
claude -p "Check that you are executing with a ~/cc/<project> directory as your cwd, containing a CLAUDE.md. If you are not then exit. If you are then use this file as your prompt: <path-to-cc-session-tools>/src/cc_session_tools/prompts/pdata-migration-claude-md-update.md"
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
**What matters is a fresh context, not literally a new process.** The reason this prompt asks
|
|
16
|
+
for a new session is a genuinely fresh, unbiased read that won't rationalize away a stale
|
|
17
|
+
reference it half-remembers writing earlier in the same conversation. An orchestrating session
|
|
18
|
+
that just ran `ccst pdata init --write` can dispatch this prompt as an `Agent` subagent (with its
|
|
19
|
+
cwd set to the project root) instead of shelling out to a literal `claude -p` process — a
|
|
20
|
+
dispatched subagent gets the same fresh-context benefit without leaving the orchestrating
|
|
21
|
+
session's control flow. Either is acceptable; what is not acceptable is running this prompt
|
|
22
|
+
inline in the same context that just did the migration.
|
|
23
|
+
|
|
15
24
|
---
|
|
16
25
|
|
|
17
26
|
## Step 1 — Verify project context
|
|
@@ -12,6 +12,15 @@ cd ~/cc/<project> && \
|
|
|
12
12
|
claude -p "Check that you are executing with a ~/cc/<project> directory as your cwd. If you are not then exit. If you are then use this file as your prompt: <path-to-cc-session-tools>/src/cc_session_tools/prompts/pdata-migration-skills-update.md"
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
**What matters is a fresh context, not literally a new process.** The reason this prompt asks
|
|
16
|
+
for a new session is a genuinely fresh, unbiased read that won't rationalize away a stale
|
|
17
|
+
reference it half-remembers writing earlier in the same conversation. An orchestrating session
|
|
18
|
+
that just ran `ccst pdata init --write` can dispatch this prompt as an `Agent` subagent (with its
|
|
19
|
+
cwd set to the project root) instead of shelling out to a literal `claude -p` process — a
|
|
20
|
+
dispatched subagent gets the same fresh-context benefit without leaving the orchestrating
|
|
21
|
+
session's control flow. Either is acceptable; what is not acceptable is running this prompt
|
|
22
|
+
inline in the same context that just did the migration.
|
|
23
|
+
|
|
15
24
|
---
|
|
16
25
|
|
|
17
26
|
## Step 1 — Verify project context
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: pm-pdata-schema
|
|
2
|
+
name: pm-pdata-design-schema
|
|
3
3
|
description: Use before writing a genuinely new kind of structured data into any project's ccst pdata store - deciding whether it fits an existing record_group, needs a brand-new group, and whether that group needs an extension table or free-text content suffices. Triggers on "I need to track a new kind of record", "what record_group should this be", "does this need an extension table", "add a new field to ccst pdata", or any session about to call `ccst pdata add`/`schema add-field` for a record shape it hasn't used before. Prevents lazy catch-all groups (`notes`/`misc`) that silently recreate the EAV undifferentiated-bucket problem the schema deliberately rejected.
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pm-pdata-do-audit-and-prepare-to-migrate
|
|
3
|
-
description: Full consistency/completeness audit of a project's central and recordkeeping files - OneDrive sync-conflict cleanup, cross-checking every index/register/log against what it claims to describe, and a pdata-migration readiness pass. Ends by writing a readiness manifest file that
|
|
3
|
+
description: Full consistency/completeness audit of a project's central and recordkeeping files - OneDrive sync-conflict cleanup, cross-checking every index/register/log against what it claims to describe, and a pdata-migration readiness pass. Ends by writing a readiness manifest file that feeds `ccst pdata init` (via `pm-project-init`) - the tool-native migration mechanism - and, only for the narrow record shapes it can't express, the deprecated `pm-pdata-do-manual-migration` fallback. Triggers on "review all my central files", "audit the project files", "check everything is up to date and consistent", "get this project ready for pdata", "/pm-pdata-do-audit-and-prepare-to-migrate", or any request for a thorough review/health-check of a project's index/log/register files (as opposed to a single-session wrap-up, which is pm-update-central-files). Especially relevant when a project is scheduled to migrate to pdata - this audit is the recommended prerequisite pass, since a schema design should not be built against files that still have unresolved sync-conflict duplicates or known dangling rows.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Audit central files
|
|
7
7
|
|
|
8
|
+
> **This audit feeds `ccst pdata init`, not a manual migration.** The readiness manifest this
|
|
9
|
+
> skill produces (Phase 5) is a pre-flight pass for `ccst pdata init` (driven by the
|
|
10
|
+
> `pm-project-init` skill) - the tool-native, default migration mechanism. `pm-pdata-do-manual-migration`
|
|
11
|
+
> is a deprecated fallback for record shapes `ccst pdata init` genuinely can't express; it is not
|
|
12
|
+
> the default next step after this audit.
|
|
13
|
+
|
|
8
14
|
## When to use this vs. `pm-update-central-files`
|
|
9
15
|
|
|
10
16
|
`pm-update-central-files` is a lightweight, single-session wrap-up: rewrite WORKLOG, apply
|
|
@@ -115,7 +121,7 @@ Give the user a single reviewable delete script for every confirmed-safe deletio
|
|
|
115
121
|
## Phase 4: pdata-readiness pass
|
|
116
122
|
|
|
117
123
|
Compile a dedicated `pdata-readiness-notes.md` (or equivalent) listing, file by file, every
|
|
118
|
-
blocker a future `pm-pdata-schema
|
|
124
|
+
blocker a future `pm-pdata-design-schema` session would hit if it tried to design a schema
|
|
119
125
|
against the file as it currently stands:
|
|
120
126
|
|
|
121
127
|
- Inconsistent separator/delimiter use within one logical column.
|
|
@@ -131,10 +137,10 @@ against the file as it currently stands:
|
|
|
131
137
|
means something different from a genuinely blank one).
|
|
132
138
|
|
|
133
139
|
This file is deliberately NOT a migration plan - it's a findings list for whoever runs the actual
|
|
134
|
-
`pm-pdata-schema
|
|
140
|
+
`pm-pdata-design-schema` session next, so that work isn't designed against a still-messy
|
|
135
141
|
substrate.
|
|
136
142
|
|
|
137
|
-
## Phase 5: write the readiness manifest (for `pm-
|
|
143
|
+
## Phase 5: write the readiness manifest (for `ccst pdata init`/`pm-project-init` to consume)
|
|
138
144
|
|
|
139
145
|
Once the audit reaches a settled state (per your own stopping rule - typically two consecutive
|
|
140
146
|
clean verification rounds, or a documented pragmatic stop), write one machine-and-human-readable
|
|
@@ -145,7 +151,9 @@ otherwise the project's own top-level docs location. Its existence and location
|
|
|
145
151
|
recorded in the project's own instructions file (`CLAUDE.md`/`AGENTS.md`/equivalent) so a future
|
|
146
152
|
session doesn't have to search for it.
|
|
147
153
|
|
|
148
|
-
The manifest must have, in this order, so `pm-
|
|
154
|
+
The manifest must have, in this order, so a `pm-project-init` session running `ccst pdata init`
|
|
155
|
+
(or, for the narrow record shapes it can't express, the deprecated `pm-pdata-do-manual-migration`
|
|
156
|
+
fallback) can parse it deterministically:
|
|
149
157
|
|
|
150
158
|
1. **Header**: audit date, session/agent identifier, and an explicit "STALE IF" note - state the
|
|
151
159
|
condition that would invalidate this manifest (e.g. "stale if any of the files below have
|
|
@@ -153,8 +161,8 @@ The manifest must have, in this order, so `pm-pdata-do-migrate` can parse it det
|
|
|
153
161
|
2. **File inventory**: every central/index/recordkeeping file the audit covered, with: full path,
|
|
154
162
|
row/entry count, last-verified-clean date, and its role (`index`, `register`, `log`,
|
|
155
163
|
`narrative`, `derived-artefact`).
|
|
156
|
-
3. **Per-file migration blockers**, in the exact shape `pm-pdata-schema
|
|
157
|
-
`pm-
|
|
164
|
+
3. **Per-file migration blockers**, in the exact shape `pm-pdata-design-schema` and
|
|
165
|
+
`pm-project-init` expect to consume - this is the same content this skill's own Phase 4
|
|
158
166
|
already produces, just formalised into the manifest rather than a standalone prose report:
|
|
159
167
|
inconsistent separators, unstable/non-existent natural keys, mixed date formats, multi-schema
|
|
160
168
|
single files, machine-specific paths, null-value conventions that aren't real nulls.
|
|
@@ -165,7 +173,8 @@ The manifest must have, in this order, so `pm-pdata-do-migrate` can parse it det
|
|
|
165
173
|
a migration pass doesn't waste time re-flagging it or, worse, silently drops one copy.
|
|
166
174
|
6. **Open decisions** - anything the audit found but explicitly did NOT resolve because it needed
|
|
167
175
|
the project owner's judgement (scope calls, curation completeness, which of two forks is
|
|
168
|
-
canonical). List these plainly;
|
|
176
|
+
canonical). List these plainly; a later migration session must not treat an unresolved item as
|
|
177
|
+
settled.
|
|
169
178
|
|
|
170
179
|
## Common mistakes
|
|
171
180
|
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: pm-pdata-do-
|
|
3
|
-
description: Execute a project's actual migration from flat central/index files to a ccst pdata record store - build a migration plan, adversarially verify the plan itself, present it for the user's confirmation, then execute it and write a results file. Consumes the readiness manifest pm-pdata-do-audit-and-prepare-to-migrate produces if one exists, but always explores the project independently too, so it works even without that manifest. Triggers on "migrate this project to pdata", "run the pdata migration", "/pm-pdata-do-
|
|
2
|
+
name: pm-pdata-do-manual-migration
|
|
3
|
+
description: Execute a project's actual migration from flat central/index files to a ccst pdata record store - build a migration plan, adversarially verify the plan itself, present it for the user's confirmation, then execute it and write a results file. Consumes the readiness manifest pm-pdata-do-audit-and-prepare-to-migrate produces if one exists, but always explores the project independently too, so it works even without that manifest. Triggers on "migrate this project to pdata", "run the pdata migration", "/pm-pdata-do-manual-migration", or any request to actually move a project's CSV/index/log files into pdata (as opposed to just auditing readiness, which is pm-pdata-do-audit-and-prepare-to-migrate, or designing the target schema in the abstract, which is pm-pdata-design-schema).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# Manually migrate a project to pdata (deprecated fallback)
|
|
7
|
+
|
|
8
|
+
> **Deprecated fallback — `ccst pdata init` is the standard mechanism.** `ccst pdata init`
|
|
9
|
+
> (driven by the `pm-project-init` skill) is the tool-native migration mechanism: classification,
|
|
10
|
+
> a human-reviewable manifest, backup, verify, atomic cutover, and shipped post-write doc/skill-
|
|
11
|
+
> update prompts. It is the default choice wherever it is available, and this skill is superseded
|
|
12
|
+
> by it for any file `ccst pdata init`'s classifier can already handle (a normal CSV/JSON file
|
|
13
|
+
> with a real header row). This skill remains only as a deprecated manual fallback for the narrow
|
|
14
|
+
> case where the programmatic approach genuinely doesn't fit - e.g. a record shape none of `ccst
|
|
15
|
+
> pdata init`'s five import strategies (`whole-file`, `delimited-sections`, `csv-rows`,
|
|
16
|
+
> `json-array-rows`, `json-singleton`) can express.
|
|
17
|
+
>
|
|
18
|
+
> **Before doing anything else, stop and get the user's explicit confirmation** that: (a) they
|
|
19
|
+
> understand `ccst pdata init` is the standard, tool-native mechanism and this skill is a
|
|
20
|
+
> deprecated fallback; and (b) they have a specific reason the programmatic approach doesn't fit
|
|
21
|
+
> this case. Do not proceed to Step 1, or any later step, without that confirmation - if the user
|
|
22
|
+
> hasn't already stated a reason, ask them for one before continuing.
|
|
7
23
|
|
|
8
24
|
## When to use this vs. the other pm-pdata-* skills
|
|
9
25
|
|
|
10
26
|
- `pm-pdata-do-audit-and-prepare-to-migrate` - readiness audit. Finds and fixes problems in the CURRENT flat files.
|
|
11
27
|
Produces a readiness manifest. Does not touch pdata at all.
|
|
12
|
-
- `pm-pdata-schema
|
|
28
|
+
- `pm-pdata-design-schema` - designs the TARGET record-group schema in the abstract (field names,
|
|
13
29
|
types, groupings) before any data moves.
|
|
14
|
-
- `pm-pdata-do-
|
|
30
|
+
- `pm-pdata-do-manual-migration` (this skill) - takes whatever schema exists (designed via the skill above,
|
|
15
31
|
or designed inline as part of this skill's own plan if no separate design session happened) and
|
|
16
32
|
actually moves the data: `ccst pdata add`/`batch` calls, verification, and a results record.
|
|
17
33
|
|
|
@@ -43,7 +59,7 @@ audit pass would.
|
|
|
43
59
|
|
|
44
60
|
## Step 2: design or confirm the target schema
|
|
45
61
|
|
|
46
|
-
For each central file being migrated, decide (or confirm, if `pm-pdata-schema
|
|
62
|
+
For each central file being migrated, decide (or confirm, if `pm-pdata-design-schema` already
|
|
47
63
|
ran):
|
|
48
64
|
|
|
49
65
|
- **Record group name** - typically the file's own conceptual name (`correspondence-log`,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: pm-pdata-
|
|
2
|
+
name: pm-pdata-resolve-conflicts
|
|
3
3
|
description: Use immediately when `ccst pdata update` or `ccst pdata delete` exits 3 (a version conflict) - takes the CLI's current-vs-attempted diff and presents it to Chris for reconciliation, per spec §6.2's "the session asks Chris how to reconcile" contract. Also use when `ccst pdata resolve` reports a cross-machine fork (a `.pdata-db-dump` conflict between two laptops), or phrasing like "pdata update conflict", "version conflict on a record", "someone else already updated this row", "sync conflict", "pdata fork between machines". Never auto-retries, never silently picks a side, never discards either version.
|
|
4
4
|
---
|
|
5
5
|
|