cctx-cli 1.5.0__tar.gz → 1.5.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.
Files changed (174) hide show
  1. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/CHANGELOG.md +15 -0
  2. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/PKG-INFO +1 -1
  3. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/PRODUCT.md +23 -12
  4. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/__init__.py +1 -1
  5. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/recommender/claude_md.py +21 -3
  6. cctx_cli-1.5.1/docs/product-reviews/2026-06-09-product-review.md +186 -0
  7. cctx_cli-1.5.1/docs/superpowers/specs/2026-06-09-cross-agent-emit-design.md +198 -0
  8. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/pyproject.toml +1 -1
  9. cctx_cli-1.5.1/tests/test_recommender.py +125 -0
  10. cctx_cli-1.5.0/tests/test_recommender.py +0 -56
  11. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/.github/workflows/ci.yml +0 -0
  12. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/.github/workflows/publish.yml +0 -0
  13. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/.github/workflows/release.yml +0 -0
  14. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/.gitignore +0 -0
  15. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/CLAUDE.md +0 -0
  16. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/DESIGN.md +0 -0
  17. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/README.md +0 -0
  18. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/action.yml +0 -0
  19. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/agents.py +0 -0
  20. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/cli.py +0 -0
  21. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/__init__.py +0 -0
  22. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/aggregate.py +0 -0
  23. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/inflection.py +0 -0
  24. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/patterns/__init__.py +0 -0
  25. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/patterns/dead_end.py +0 -0
  26. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/patterns/project_specific.py +0 -0
  27. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/patterns/retry_loop.py +0 -0
  28. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/patterns/scope_creep.py +0 -0
  29. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/patterns/stale_context.py +0 -0
  30. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/diagnostician/patterns/tool_thrash.py +0 -0
  31. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/discovery.py +0 -0
  32. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/exporters/__init__.py +0 -0
  33. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/exporters/csv.py +0 -0
  34. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/exporters/json.py +0 -0
  35. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/exporters/jsonl.py +0 -0
  36. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/harvest.py +0 -0
  37. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/models.py +0 -0
  38. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/parsers/__init__.py +0 -0
  39. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/parsers/claude_code.py +0 -0
  40. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/pricing.py +0 -0
  41. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/recommender/__init__.py +0 -0
  42. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/recommender/evidence.py +0 -0
  43. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/renderers/__init__.py +0 -0
  44. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/renderers/github.py +0 -0
  45. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/renderers/report.py +0 -0
  46. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/renderers/templates/autopsy.html.j2 +0 -0
  47. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/renderers/terminal.py +0 -0
  48. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/renderers/trace_tui.py +0 -0
  49. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/tokenizer.py +0 -0
  50. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx/watcher.py +0 -0
  51. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/cctx-project-brief.md +0 -0
  52. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/demo.gif +0 -0
  53. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/demo.tape +0 -0
  54. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/health-reviews/2026-05-15-deep-review-summary.md +0 -0
  55. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/health-reviews/2026-05-15-health-review.md +0 -0
  56. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/product-reviews/2026-05-15-product-review.md +0 -0
  57. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/plans/2026-05-12-claude-code-parser.md +0 -0
  58. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/plans/2026-05-14-autopsy-v0.md +0 -0
  59. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/plans/2026-05-16-readme-pypi-release.md +0 -0
  60. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/plans/2026-05-17-harvest-check-depth.md +0 -0
  61. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/plans/2026-05-17-project-pattern-detection.md +0 -0
  62. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/plans/2026-05-19-claude-agents-live-integration.md +0 -0
  63. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/specs/2026-05-12-claude-code-parser-design.md +0 -0
  64. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/specs/2026-05-14-autopsy-design.md +0 -0
  65. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/specs/2026-05-14-harvest-design.md +0 -0
  66. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/specs/2026-05-14-trace-tui-design.md +0 -0
  67. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/specs/2026-05-16-readme-pypi-release-design.md +0 -0
  68. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/specs/2026-05-17-harvest-check-depth-design.md +0 -0
  69. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/specs/2026-05-17-project-pattern-detection-design.md +0 -0
  70. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/docs/superpowers/specs/2026-05-19-claude-agents-live-integration-design.md +0 -0
  71. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/__init__.py +0 -0
  72. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/conftest.py +0 -0
  73. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/__init__.py +0 -0
  74. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/conftest.py +0 -0
  75. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/test_dead_end.py +0 -0
  76. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/test_inflection.py +0 -0
  77. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/test_orchestrator.py +0 -0
  78. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/test_project_specific.py +0 -0
  79. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/test_retry_loop.py +0 -0
  80. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/test_scope_creep.py +0 -0
  81. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/test_stale_context.py +0 -0
  82. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/diagnostician/test_tool_thrash.py +0 -0
  83. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/exporters/__init__.py +0 -0
  84. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/exporters/test_csv.py +0 -0
  85. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/exporters/test_jsonl.py +0 -0
  86. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/README.md +0 -0
  87. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/short-clean/short-clean.jsonl +0 -0
  88. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a0b4c2cf1dde0ca56.meta.json +0 -0
  89. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a116ae34b1b09c332.meta.json +0 -0
  90. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a1c4c417b35658c9e.meta.json +0 -0
  91. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a1e41a901de38f1b5.meta.json +0 -0
  92. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a338f8d0c74612a24.meta.json +0 -0
  93. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a34f6f3c0e7094186.meta.json +0 -0
  94. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a5a5a0cff4d13308b.meta.json +0 -0
  95. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a6b0a3da6a0484db5.meta.json +0 -0
  96. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a7f73f1790b02cde5.meta.json +0 -0
  97. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a7f7c17c38a9d8788.meta.json +0 -0
  98. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a853259e2cd7bbe8a.meta.json +0 -0
  99. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-a8d9aedb0d0c6e12d.meta.json +0 -0
  100. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-aa778bc1d59e4a441.meta.json +0 -0
  101. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-aba869dedee4a12ba.meta.json +0 -0
  102. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-ada2746d9774b94db.meta.json +0 -0
  103. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-aea0132068c64d2dd.meta.json +0 -0
  104. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-aea215eff50874d5f.meta.json +0 -0
  105. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments/subagents/agent-afee21f2b3852a4a0.meta.json +0 -0
  106. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-attachments/with-attachments.jsonl +0 -0
  107. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a051d9c9a6b2f5cc3.jsonl +0 -0
  108. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a051d9c9a6b2f5cc3.meta.json +0 -0
  109. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a171f16f4e65cfe75.jsonl +0 -0
  110. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a171f16f4e65cfe75.meta.json +0 -0
  111. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a1b77fea2c0a2269b.jsonl +0 -0
  112. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a1b77fea2c0a2269b.meta.json +0 -0
  113. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a20da4c01a54acca8.jsonl +0 -0
  114. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a20da4c01a54acca8.meta.json +0 -0
  115. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a3c82739b1383fb14.jsonl +0 -0
  116. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a3c82739b1383fb14.meta.json +0 -0
  117. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a49e8539611c5fe12.jsonl +0 -0
  118. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a49e8539611c5fe12.meta.json +0 -0
  119. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a7bb58f3fff2b3e8d.jsonl +0 -0
  120. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a7bb58f3fff2b3e8d.meta.json +0 -0
  121. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a92b48c0331195aac.jsonl +0 -0
  122. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-a92b48c0331195aac.meta.json +0 -0
  123. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-ab96c4264099694a9.jsonl +0 -0
  124. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-ab96c4264099694a9.meta.json +0 -0
  125. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-acb2895c5e34ffec0.jsonl +0 -0
  126. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-acb2895c5e34ffec0.meta.json +0 -0
  127. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-adb2302769938fb3f.jsonl +0 -0
  128. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-adb2302769938fb3f.meta.json +0 -0
  129. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-ae585eca15cb93b9c.jsonl +0 -0
  130. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-ae585eca15cb93b9c.meta.json +0 -0
  131. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-aec9c917feb903d67.jsonl +0 -0
  132. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction/subagents/agent-aec9c917feb903d67.meta.json +0 -0
  133. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-compaction/with-compaction.jsonl +0 -0
  134. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents/subagents/agent-a1a3a21aeb76bb0a9.jsonl +0 -0
  135. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents/subagents/agent-a1a3a21aeb76bb0a9.meta.json +0 -0
  136. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents/subagents/agent-aaa1d6ecc05a78442.jsonl +0 -0
  137. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents/subagents/agent-aaa1d6ecc05a78442.meta.json +0 -0
  138. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents/subagents/agent-af3c545ccd30036d2.jsonl +0 -0
  139. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents/subagents/agent-af3c545ccd30036d2.meta.json +0 -0
  140. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents/tool-results/btwp2bzro.txt +0 -0
  141. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents/tool-results/byqjbgy4b.txt +0 -0
  142. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-subagents/with-subagents.jsonl +0 -0
  143. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-tool-results/with-tool-results/tool-results/bosbkda0h.txt +0 -0
  144. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/claude_code/with-tool-results/with-tool-results.jsonl +0 -0
  145. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/scrub.py +0 -0
  146. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/synthetic/bookkeeping_only.jsonl +0 -0
  147. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/synthetic/malformed_middle.jsonl +0 -0
  148. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/synthetic/truncated_final_line.jsonl +0 -0
  149. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/synthetic/unknown_attachment_shape.jsonl +0 -0
  150. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/fixtures/synthetic/unknown_type.jsonl +0 -0
  151. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/parsers/__init__.py +0 -0
  152. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/parsers/test_claude_code.py +0 -0
  153. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/parsers/test_claude_code_integration.py +0 -0
  154. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/recommender/__init__.py +0 -0
  155. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/recommender/test_claude_md.py +0 -0
  156. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/recommender/test_evidence.py +0 -0
  157. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/renderers/__init__.py +0 -0
  158. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/renderers/test_report.py +0 -0
  159. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/renderers/test_terminal_renderer_full.py +0 -0
  160. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_agents.py +0 -0
  161. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_aggregate.py +0 -0
  162. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_cli.py +0 -0
  163. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_cli_export.py +0 -0
  164. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_discovery.py +0 -0
  165. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_github_summary.py +0 -0
  166. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_harvest.py +0 -0
  167. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_harvest_check.py +0 -0
  168. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_models.py +0 -0
  169. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_models_project_pattern.py +0 -0
  170. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_smoke.py +0 -0
  171. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_terminal_renderer.py +0 -0
  172. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_tokenizer.py +0 -0
  173. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_trace_tui.py +0 -0
  174. {cctx_cli-1.5.0 → cctx_cli-1.5.1}/tests/test_watcher.py +0 -0
@@ -2,6 +2,21 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v1.5.1 (2026-06-10)
6
+
7
+ ### Bug Fixes
8
+
9
+ - Recommender — add TOOL_THRASH/DEAD_END patch templates
10
+ ([#107](https://github.com/jacquardlabs/cctx/pull/107),
11
+ [`3c79d58`](https://github.com/jacquardlabs/cctx/commit/3c79d58a55af106d3fd81542e70b8f892569185c))
12
+
13
+ ### Documentation
14
+
15
+ - Product review 2026-06-09 + M15 cross-agent emit spec
16
+ ([#107](https://github.com/jacquardlabs/cctx/pull/107),
17
+ [`3c79d58`](https://github.com/jacquardlabs/cctx/commit/3c79d58a55af106d3fd81542e70b8f892569185c))
18
+
19
+
5
20
  ## v1.5.0 (2026-05-20)
6
21
 
7
22
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cctx-cli
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: Diagnose Claude Code sessions — find what went wrong, what it cost, and what to add to CLAUDE.md
5
5
  Author: Jacquard Labs
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@
4
4
 
5
5
  cctx is a local Python CLI that reads Claude Code session logs and tells you what went wrong, why it cost what it did, and what to add to your CLAUDE.md so it doesn't happen again.
6
6
 
7
- It is a forensic tool, not a monitoring tool. You reach for it after a session — when something felt off, when the bill was higher than expected, or on a weekly review pass.
7
+ It is forensic-first. You reach for it after a session — when something felt off, when the bill was higher than expected, or on a weekly review pass. `cctx watch` extends the same waste detection into a live, opt-in companion for an active session; it is a foreground command you run deliberately, not background infrastructure.
8
8
 
9
9
  ## Primary persona
10
10
 
@@ -20,7 +20,7 @@ This persona is already the target; everything shipped to date serves them direc
20
20
  ## What cctx is NOT for
21
21
 
22
22
  - Teams or organizations (no shared reports, no access control, no multi-user state)
23
- - Real-time monitoring (completed sessions only in v0 and v1)
23
+ - Ambient monitoring (no daemons, no persistent watcher state, no alerting — `cctx watch` is a foreground command you start and stop)
24
24
  - General cost dashboards (CodeBurn covers that; cctx is forensic)
25
25
  - Multi-provider support (Claude Code only in v0/v1)
26
26
  - Users who do not read session transcripts or maintain CLAUDE.md
@@ -28,7 +28,7 @@ This persona is already the target; everything shipped to date serves them direc
28
28
  ## Product principles
29
29
 
30
30
  **1. Forensic, not ambient.**
31
- cctx is used after something goes wrong, not as background infrastructure. Every feature should be justified by this use case: "I just ran a session, something went sideways, I want to know what."
31
+ cctx is forensic-first: the core use case is "I just ran a session, something went sideways, I want to know what." Live mode (`watch`) is justified only as the same detection running earlier it surfaces the identical findings, never becomes a daemon, and never holds state between runs.
32
32
 
33
33
  **2. Output must be actionable.**
34
34
  Every report should produce at least one thing the user can do immediately. Findings without patches are incomplete. Patches must be copy-pasteable or auto-applicable.
@@ -37,15 +37,15 @@ Every report should produce at least one thing the user can do immediately. Find
37
37
  Costs are approximated (85–95% of actual). Pattern classifiers fire only on high-confidence signals. Low-confidence signals are shown with explicit confidence labels. "System internals" token budget is never hidden or misattributed.
38
38
 
39
39
  **4. Local and stateless.**
40
- No network calls in the core analysis path (tokenizer may call the API for token counting; that is opt-in). No persistent database. No telemetry. No account. Users own their data.
40
+ No network calls in the core analysis path (tokenizer may call the API for token counting; that is opt-in). Live-session detection may shell out to the local `claude` CLI and degrades gracefully without it. No persistent database. No telemetry. No account. Users own their data.
41
41
 
42
42
  **5. Deterministic.**
43
43
  Pattern classifiers are heuristics, not LLM calls. The same session file produces the same output every time. Testable on fixtures. Predictable cost to run.
44
44
 
45
45
  **6. Small surface, deep on each command.**
46
- Four commands. No command is shallow. Users should be able to learn the product in an afternoon and trust what it tells them.
46
+ Six commands (`ls`, `autopsy`, `harvest`, `watch`, `trace`, `export`). No command is shallow. Users should be able to learn the product in an afternoon and trust what it tells them.
47
47
 
48
- ## Feature map (v0.2.0)
48
+ ## Feature map (v1.4.0)
49
49
 
50
50
  ### Shipped
51
51
 
@@ -68,8 +68,16 @@ Four commands. No command is shallow. Users should be able to learn the product
68
68
  | Cross-session harvest | `cctx harvest <project> --since N` | M5 |
69
69
  | Session discovery | `cctx ls` / `cctx autopsy --latest` | M6+ |
70
70
  | Live waste signals | `cctx watch <project>` | M6+ |
71
+ | Verdict headline + `--top N` + `--turn N` | `autopsy` | v1.1.0 (M9) |
72
+ | `--until DATE` on cross-session mode | `autopsy --since ... --until` | v1.2.0 (M12) |
73
+ | Machine-readable diagnosis | `cctx autopsy <session> --json` | v1.2.0 (M12) |
74
+ | JSON export | `cctx export <session> --format json` | v1.2.0 (M12) |
75
+ | Project-specific pattern detection | `autopsy`/`harvest` `--since` | v1.3.0 (M14) |
76
+ | Memory-hygiene depth | `harvest --check` + `--check-severity` | v1.4.0 (M13) |
77
+ | Live session badges | `cctx ls` | unreleased |
78
+ | Live session detection, early idle exit | `cctx watch` | unreleased |
71
79
 
72
- ### Pattern classifiers (v0.2.0)
80
+ ### Pattern classifiers (v1.4.0)
73
81
 
74
82
  | Pattern | Status |
75
83
  |---|---|
@@ -78,6 +86,7 @@ Four commands. No command is shallow. Users should be able to learn the product
78
86
  | Stale context | Shipped |
79
87
  | Dead-end exploration | Shipped (v0.2.0) |
80
88
  | Tool thrashing | Shipped (v0.2.0) |
89
+ | Project-specific patterns (cross-session) | Shipped (v1.3.0) |
81
90
 
82
91
  ## What we are NOT building
83
92
 
@@ -87,12 +96,14 @@ Four commands. No command is shallow. Users should be able to learn the product
87
96
  - A fork-and-replay debugger
88
97
  - A general eval or testing framework
89
98
 
90
- ## Known problems (as of 2026-05-16)
99
+ ## Known problems (as of 2026-06-09)
91
100
 
92
- **Active gaps (non-blocking for v0.2.0 but worth tracking):**
101
+ **Active gaps:**
93
102
 
94
- 1. **`cctx watch` polling is simple.** Polls every 1s and re-runs classifiers on any file growth. Does not debounce or use `fsevents`/`inotify`. Fine for v0 but will chatter on active sessions.
103
+ 1. **`cctx watch` polling is simple.** Early idle exit via `claude agents --json` has landed, but the watcher still polls at 1s without `fsevents`/`inotify` debouncing.
95
104
 
96
- 2. **`--format json` on `export` not shipped.** `--html` moved to `autopsy --html`; `json` format on the `export` subcommand is still deferred.
105
+ 2. **Subagent traces are parsed but never diagnosed.** The parser models subagent sessions recursively and the tokenizer counts their tokens, but no classifier or cost attribution reads `trace.subagents`. Autopsy is blind to spend inside agent fan-outs. (M16)
97
106
 
98
- 3. **Cross-agent layer not started.** Emitting findings as `.cursorrules`, `AGENTS.md`, `.windsurfrules`, or GitHub Copilot instructions is a roadmap item with no milestone yet.
107
+ 3. **Cross-agent layer not started.** Tracked as M15 / #82 the final step of the original growth staircase.
108
+
109
+ 4. **Harvest has no feedback loop.** Nothing measures whether an applied patch reduced the recurrence of the pattern it targeted, even though patches carry fingerprints and sessions carry dates. (M17)
@@ -1,3 +1,3 @@
1
1
  """cctx: profile, debug, and optimize Claude Code and Agent SDK sessions."""
2
2
 
3
- __version__ = "1.5.0"
3
+ __version__ = "1.5.1"
@@ -41,11 +41,29 @@ _STALE_CONTEXT_DIFF = """\
41
41
  +without re-referencing it. Prefer re-running the tool over dragging stale context
42
42
  +forward — the compaction system handles removal."""
43
43
 
44
+ _TOOL_THRASH_DIFF = """\
45
+ +## Tool-call discipline
46
+ +
47
+ +Before reaching for a tool, decide what specific information the call must return
48
+ +and how it changes the next step. Don't fan out near-identical searches or re-read
49
+ +the same file from different angles hoping something turns up. If two or three calls
50
+ +haven't moved you forward, stop and form a hypothesis before the next one."""
51
+
52
+ _DEAD_END_DIFF = """\
53
+ +## Exploration discipline
54
+ +
55
+ +When an approach stops making progress, name the dead end explicitly and back out
56
+ +rather than pushing deeper on a path that isn't working. Re-read the goal, list the
57
+ +approaches already ruled out, and pick a meaningfully different one. Sunk effort on a
58
+ +failing approach is not a reason to continue it."""
59
+
44
60
  _TEMPLATES: dict[FindingKind, tuple[str, str, str]] = {
45
61
  # kind → (description, diff_body, target_file)
46
- FindingKind.RETRY_LOOP: ("Add retry discipline rule", _RETRY_LOOP_DIFF, "CLAUDE.md"),
47
- FindingKind.SCOPE_CREEP: ("Add scope discipline rule", _SCOPE_CREEP_DIFF, "CLAUDE.md"),
48
- FindingKind.STALE_CONTEXT: ("Add context hygiene rule", _STALE_CONTEXT_DIFF, "CLAUDE.md"),
62
+ FindingKind.RETRY_LOOP: ("Add retry discipline rule", _RETRY_LOOP_DIFF, "CLAUDE.md"),
63
+ FindingKind.SCOPE_CREEP: ("Add scope discipline rule", _SCOPE_CREEP_DIFF, "CLAUDE.md"),
64
+ FindingKind.STALE_CONTEXT: ("Add context hygiene rule", _STALE_CONTEXT_DIFF, "CLAUDE.md"),
65
+ FindingKind.TOOL_THRASH: ("Add tool-call discipline rule", _TOOL_THRASH_DIFF, "CLAUDE.md"),
66
+ FindingKind.DEAD_END: ("Add exploration discipline rule", _DEAD_END_DIFF, "CLAUDE.md"),
49
67
  }
50
68
 
51
69
 
@@ -0,0 +1,186 @@
1
+ # cctx Product Health Review — 2026-06-09
2
+
3
+ Second review. Prior review: `2026-05-15-product-review.md`. Source of product truth: `PRODUCT.md` (created from the prior review's draft), with `cctx-project-brief.md` as the original pitch and growth staircase.
4
+
5
+ **Headline: the growth staircase is one step from complete.** Every milestone from the original brief — autopsy, cross-session, harvest, memory hygiene, live mode — has shipped. The issue board holds three open issues, one of which (#80) actually shipped in v1.4.0. The only substantive roadmap item left is the cross-agent layer (#82, M15). The product needs two things now: PRODUCT.md brought up to date (it describes v0.2.0; reality is v1.4.0+), and a deliberate decision about what comes after the staircase.
6
+
7
+ ---
8
+
9
+ ## Part 1 — Is PRODUCT.md still true?
10
+
11
+ ### 1. Persona check
12
+
13
+ Everything shipped since the last review — M9 polish (verdict headline, `--top`, `--turn`), M11 GitHub Action, M12 output completeness (`--until`, `autopsy --json`, `export --format json`), M13 harvest `--check` depth, M14 project-specific patterns, and the unreleased live-session integration — serves the same single developer reviewing their own sessions. No team features, no dashboards, no hypothetical users.
14
+
15
+ **Verdict: no persona drift.** The discipline noted in the prior review has held through eight releases.
16
+
17
+ ### 2. Principles check
18
+
19
+ **P1 — Forensic, not ambient.** *Bent, deliberately.* `cctx watch` (M10) and the in-flight `claude agents --json` live integration (live badges in `cctx ls`, early idle exit in the watcher) are real-time features. The staircase sanctioned this as v2 ("Live mode — optional"), so it is roadmap-aligned, not drift — but PRODUCT.md's principle text and its "NOT for: real-time monitoring" line now contradict the shipped product. The doc must evolve: forensic-first, with live mode as an explicitly opt-in companion.
20
+
21
+ **P2 — Output must be actionable.** Honored. M14 project-specific patterns emit CLAUDE.md patches via `generate_from_patterns()`; harvest `--check` depth findings carry severity and location.
22
+
23
+ **P3 — Honest about uncertainty.** Honored. The prior review's gap (cost confidence not surfaced) was fixed in #69 — terminal and HTML output annotate costs as ~85–95% estimates.
24
+
25
+ **P4 — Local and stateless.** Honored, with one footnote: the live path now shells out to the `claude` CLI (`claude agents --json`). Still local, no network, gracefully degrades when the binary is absent — but it is the first external-binary dependency in any code path and should be named in the principle.
26
+
27
+ **P5 — Deterministic.** Fully honored. All four new analysis surfaces since the last review (tool-thrash, dead-end, project-specific patterns, check-depth detectors) are heuristic — Jaccard similarity, keyword matching, n-gram overlap. No LLM calls anywhere outside the opt-in tokenizer.
28
+
29
+ **P6 — Small surface, deep on each command.** The text says "Four commands." There are six: `ls`, `autopsy`, `export`, `trace`, `harvest`, `watch`. The spirit holds — each verb is deep and the surface is learnable in an afternoon — but the letter is false.
30
+
31
+ ### 3. Feature map accuracy
32
+
33
+ PRODUCT.md is headed "Feature map (v0.2.0)". The released version is **v1.4.0** (2026-05-20), with live-session integration unreleased on main. Missing from the map:
34
+
35
+ | Shipped feature | Where | Version |
36
+ |---|---|---|
37
+ | Verdict headline | `autopsy` terminal output | v1.1.0 (M9) |
38
+ | `--top N` on cross-session autopsy | `autopsy --since` | v1.1.0 (M9) |
39
+ | `--turn N` drill-down | `autopsy` | v1.1.0 (M9) |
40
+ | `--until DATE` | `autopsy --since` | v1.2.0 (M12) |
41
+ | Machine-readable diagnosis | `autopsy --json` | v1.2.0 (M12) |
42
+ | JSON export | `export --format json` | v1.2.0 (M12) |
43
+ | Project-specific pattern detection | `autopsy --since` / `harvest --since` | v1.3.0 (M14) |
44
+ | Contradiction / redundancy / staleness detectors | `harvest --check`, `--check-severity` | v1.4.0 (M13) |
45
+ | Live session badges | `cctx ls` | unreleased |
46
+ | Live session detection + early idle exit | `cctx watch` | unreleased |
47
+
48
+ The classifier table is also incomplete: project-specific patterns (M14) is a sixth detection surface alongside the five listed.
49
+
50
+ ### 4. "Not building" check
51
+
52
+ - "Real-time monitoring (completed sessions only in v0 and v1)" — **crossed**, per the staircase's own v2 plan. Remove from the NOT-for list; replace with what genuinely stays out (background daemons, persistent monitoring state, alerting).
53
+ - No SaaS, no agent behavior, no multi-provider, no fork-and-replay, no eval framework — all still clean. `claude agents --json` is reading local state from a local binary, not provider expansion.
54
+
55
+ ### 5. Known problems freshness
56
+
57
+ 1. **"watch polling is simple"** — partially fixed. Early idle exit via `claude agents --json` landed (unreleased); 1s polling without fsevents/inotify remains. Update, don't remove.
58
+ 2. **"`--format json` on export not shipped"** — **fixed in v1.2.0**. Remove.
59
+ 3. **"Cross-agent layer not started… no milestone yet"** — stale. It now has milestone M15 and issue #82. Update.
60
+
61
+ **New problems to add:**
62
+ 4. **Subagent traces are parsed but never diagnosed.** The parser recursively parses subagent sessions (`models.py:151`, `parsers/claude_code.py:165`), the tokenizer counts their tokens, but no classifier or cost attribution ever reads `trace.subagents`. As agent fan-out becomes the dominant Claude Code workflow, autopsy is blind to where an increasing share of the spend goes.
63
+ 5. **Issue board hygiene.** #80 shipped in v1.4.0 (PR #87) but is still open. #85 has no milestone.
64
+ 6. **Roadmap exhaustion.** After M15 there is no defined direction. Not a bug — but the next planning conversation is overdue.
65
+
66
+ ---
67
+
68
+ ## Part 2 — Product coherence
69
+
70
+ ### One product?
71
+
72
+ Yes — more so than at the last review. The loop now has a clean narrative arc that matches a real day: `cctx ls` (what sessions exist, which are live) → `cctx watch` (catch waste during) → `cctx autopsy` (diagnose after) → `cctx harvest` (persist the lesson) → `harvest --check` (keep the memory honest). `trace` and `export` are the inspection/escape hatches. Every command operates on the same `SessionTrace → Diagnosis → Patch` chain.
73
+
74
+ ### Feature interaction
75
+
76
+ - `ls` ↔ `watch` via live badges: good new connection (unreleased).
77
+ - `autopsy → harvest`: still the spine, now strengthened by M14 (cross-session patterns produce evidence-backed patches).
78
+ - **Gap: `watch` findings are ephemeral.** A waste signal surfaced live evaporates when the session ends; the user must re-run autopsy to act on it. A natural connection — watch ending with "run `cctx autopsy --latest` to harvest these findings" or writing a findings stub — is unbuilt.
79
+ - **Gap: harvest never learns whether its patches worked.** Patches carry fingerprints and sessions carry dates; nothing compares pattern recurrence before/after a patch was applied. This is the strongest unbuilt connection in the product (see proposals).
80
+
81
+ ### Complexity audit
82
+
83
+ Nothing is deadweight. `trace` (Textual TUI) remains the highest-maintenance surface relative to use; acceptable while it stays stable. The two JSON outputs (`autopsy --json` vs `export --format json`) are different shapes for different purposes (diagnosis vs raw turns) — fine, but the README should say which to use when.
84
+
85
+ ### Onboarding
86
+
87
+ Dramatically improved since the last review: `pip install cctx` → `cctx ls` → `cctx autopsy --latest` is a genuine under-60-second path, and the README exists. Remaining friction: a clean session yields "no findings," which still reads anticlimactic on a first run — consider always showing the cost/token decomposition so a clean session still demonstrates value.
88
+
89
+ ---
90
+
91
+ ## Part 3 — Proposed PRODUCT.md updates
92
+
93
+ Presented as a diff; not applied.
94
+
95
+ ```diff
96
+ --- PRODUCT.md
97
+ +++ PRODUCT.md
98
+ @@ -5,7 +5,8 @@
99
+ cctx is a local Python CLI that reads Claude Code session logs and tells you what went wrong, why it cost what it did, and what to add to your CLAUDE.md so it doesn't happen again.
100
+
101
+ -It is a forensic tool, not a monitoring tool. You reach for it after a session — when something felt off, when the bill was higher than expected, or on a weekly review pass.
102
+ +It is forensic-first. You reach for it after a session — when something felt off, when the bill was higher than expected, or on a weekly review pass. `cctx watch` extends the same waste detection into a live, opt-in companion for an active session; it is a foreground command you run deliberately, not background infrastructure.
103
+
104
+ @@ -20,9 +21,9 @@
105
+ ## What cctx is NOT for
106
+
107
+ - Teams or organizations (no shared reports, no access control, no multi-user state)
108
+ -- Real-time monitoring (completed sessions only in v0 and v1)
109
+ +- Ambient monitoring (no daemons, no persistent watcher state, no alerting — `cctx watch` is a foreground command you start and stop)
110
+ - General cost dashboards (CodeBurn covers that; cctx is forensic)
111
+ - Multi-provider support (Claude Code only in v0/v1)
112
+ - Users who do not read session transcripts or maintain CLAUDE.md
113
+
114
+ @@ -30,8 +31,8 @@
115
+ **1. Forensic, not ambient.**
116
+ -cctx is used after something goes wrong, not as background infrastructure. Every feature should be justified by this use case: "I just ran a session, something went sideways, I want to know what."
117
+ +cctx is forensic-first: the core use case is "I just ran a session, something went sideways, I want to know what." Live mode (`watch`) is justified only as the same detection running earlier — it surfaces the identical findings, never becomes a daemon, and never holds state between runs.
118
+
119
+ @@ -39,7 +40,7 @@
120
+ **4. Local and stateless.**
121
+ -No network calls in the core analysis path (tokenizer may call the API for token counting; that is opt-in). No persistent database. No telemetry. No account. Users own their data.
122
+ +No network calls in the core analysis path (tokenizer may call the API for token counting; that is opt-in). Live-session detection may shell out to the local `claude` CLI and degrades gracefully without it. No persistent database. No telemetry. No account. Users own their data.
123
+
124
+ @@ -45,7 +46,7 @@
125
+ **6. Small surface, deep on each command.**
126
+ -Four commands. No command is shallow. Users should be able to learn the product in an afternoon and trust what it tells them.
127
+ +Six commands (`ls`, `autopsy`, `harvest`, `watch`, `trace`, `export`). No command is shallow. Users should be able to learn the product in an afternoon and trust what it tells them.
128
+
129
+ @@ -48,2 +49,2 @@
130
+ -## Feature map (v0.2.0)
131
+ +## Feature map (v1.4.0)
132
+
133
+ @@ (append to Shipped table)
134
+ +| Verdict headline + `--top N` + `--turn N` | `autopsy` | v1.1.0 (M9) |
135
+ +| `--until DATE` on cross-session mode | `autopsy --since ... --until` | v1.2.0 (M12) |
136
+ +| Machine-readable diagnosis | `cctx autopsy <session> --json` | v1.2.0 (M12) |
137
+ +| JSON export | `cctx export <session> --format json` | v1.2.0 (M12) |
138
+ +| Project-specific pattern detection | `autopsy`/`harvest` `--since` | v1.3.0 (M14) |
139
+ +| Memory-hygiene depth | `harvest --check` + `--check-severity` | v1.4.0 (M13) |
140
+ +| Live session badges | `cctx ls` | unreleased |
141
+ +| Live session detection, early idle exit | `cctx watch` | unreleased |
142
+
143
+ @@ (classifier table)
144
+ +| Project-specific patterns (cross-session) | Shipped (v1.3.0) |
145
+
146
+ @@ -90,12 +99,14 @@
147
+ -## Known problems (as of 2026-05-16)
148
+ +## Known problems (as of 2026-06-09)
149
+
150
+ -1. **`cctx watch` polling is simple.** Polls every 1s and re-runs classifiers on any file growth. Does not debounce or use `fsevents`/`inotify`. Fine for v0 but will chatter on active sessions.
151
+ +1. **`cctx watch` polling is simple.** Early idle exit via `claude agents --json` has landed, but the watcher still polls at 1s without `fsevents`/`inotify` debouncing.
152
+
153
+ -2. **`--format json` on `export` not shipped.** `--html` moved to `autopsy --html`; `json` format on the `export` subcommand is still deferred.
154
+ +2. **Subagent traces are parsed but never diagnosed.** The parser models subagent sessions recursively and the tokenizer counts their tokens, but no classifier or cost attribution reads `trace.subagents`. Autopsy is blind to spend inside agent fan-outs.
155
+
156
+ -3. **Cross-agent layer not started.** Emitting findings as `.cursorrules`, `AGENTS.md`, `.windsurfrules`, or GitHub Copilot instructions is a roadmap item with no milestone yet.
157
+ +3. **Cross-agent layer not started.** Tracked as M15 / #82 — the final step of the original growth staircase.
158
+ +
159
+ +4. **Harvest has no feedback loop.** Nothing measures whether an applied patch reduced the recurrence of the pattern it targeted, even though patches carry fingerprints and sessions carry dates.
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Issue board actions
165
+
166
+ 1. **Close #80** — shipped in v1.4.0 via PR #87 (`check_contradictions`/`check_redundancy`/`check_staleness` + `--check-severity` are on main). Close with a comment linking the PR.
167
+ 2. **#85 (fuzzy/semantic normalization, M14 Option B)** — assign a milestone or label it explicitly as icebox. As written it risks drifting toward embedding/LLM territory; if pursued, constrain to deterministic techniques (stemming, edit distance) per P5.
168
+ 3. **#82 (M15 cross-agent layer)** — the committed next milestone. Note: emitting `AGENTS.md`/`.cursorrules` partially relaxes "multi-provider support" in the NOT-for list; the distinction worth preserving is *we write other agents' config formats; we do not parse other agents' logs*.
169
+
170
+ ## Post-staircase feature proposals
171
+
172
+ Ranked by leverage. All are deterministic, local, and persona-aligned.
173
+
174
+ **1. Subagent-aware diagnosis (highest leverage).** The data model is already built — parser recurses into subagent sessions, tokenizer counts them — only the analysis is missing. Ship: (a) per-subagent cost attribution in the autopsy decomposition ("$1.84 of $3.10 went to 7 subagents"), (b) a fan-out waste classifier (overlapping subagent work, failed-and-retried agents, subagent results never referenced by the parent). Claude Code's evolution (Task tool, workflows, parallel agents) makes this the fastest-growing blind spot in the product.
175
+
176
+ **2. Patch efficacy tracking.** `harvest` patches carry fingerprints; sessions carry dates. Compare pattern recurrence before/after a patch's application date: "retry-loop fired in 5 sessions the week before the 2026-05-20 patch; 0 since." This converts cctx from *suggesting* improvements to *proving* them — no other tool in the space closes this loop, and it requires no new data collection.
177
+
178
+ **3. Loaded-but-never-used context waste (MCP servers / skills).** Extend the brief's binary waste decision to context overhead: MCP tool definitions and skills that are loaded into every request but never invoked across N sessions. Finding: "MCP server X adds ~8K tokens/request and was never called in 30 sessions — disable it for this project." Binary signal, high confidence, directly actionable patch (settings change).
179
+
180
+ **4. `cctx init` — SessionEnd hook installer.** The biggest adoption friction is remembering to run cctx. A command that installs an opt-in Claude Code SessionEnd/Stop hook running `cctx autopsy --latest --quiet` and printing a one-line verdict *only when findings exist*. Preserves forensic-first (output appears only when something went sideways) while removing the memory burden.
181
+
182
+ **5. Compaction findings.** Compaction events are already detected (classifiers reset on them) but never reported. Promote to a finding: compaction count, content re-fetched after compaction (re-reading a file that was compacted away is concrete, attributable waste), and a "compact earlier" recommendation when stale context preceded a forced compaction.
183
+
184
+ **6. Cross-project digest.** `cctx autopsy --all --since 7d` — the persona's stated "weekly review pass" currently requires running per-project. Aggregate the aggregates; lowest effort of the six.
185
+
186
+ Suggested sequencing: board hygiene now → M15 (#82) finishes the staircase → M16 subagent-aware diagnosis → M17 patch efficacy. Items 3–6 slot in as polish-scale milestones between or after.
@@ -0,0 +1,198 @@
1
+ # cctx harvest --emit — Cross-agent layer (M15)
2
+
3
+ **Issue:** #82
4
+ **Date:** 2026-06-09
5
+ **Status:** Ready for implementation
6
+
7
+ ---
8
+
9
+ ## Goal
10
+
11
+ Write harvested findings to `AGENTS.md` so developers who use multiple AI coding
12
+ tools get the same captured knowledge without manual copy-pasting. CLAUDE.md
13
+ remains the source of truth; AGENTS.md is a downstream mirror of the sections
14
+ cctx itself manages.
15
+
16
+ Scope: `AGENTS.md` only in this milestone. Cursor (`.cursor/rules/*.mdc`),
17
+ Windsurf (`.windsurf/rules/`), and Copilot (`.github/copilot-instructions.md`)
18
+ are follow-on issues to file when user demand exists, since those formats require
19
+ either frontmatter metadata or different directory layouts.
20
+
21
+ ---
22
+
23
+ ## Two modes
24
+
25
+ ### 1. Fan-out (`--emit agents`)
26
+
27
+ `cctx harvest <target> --emit agents` fans the patches from this run out to
28
+ `AGENTS.md` alongside the normal CLAUDE.md apply.
29
+
30
+ Patches targeting `.claude/rules/` or `.claude/skills/` are excluded — those
31
+ surfaces are Claude Code-specific and do not translate to other agents.
32
+
33
+ ### 2. Backfill (`--emit agents --sync`)
34
+
35
+ `--sync` (valid only when `--emit` is also present) mirrors every
36
+ cctx-managed section already in CLAUDE.md into the emit target, not just the
37
+ patches from this run. Use when AGENTS.md doesn't exist yet and you want to
38
+ seed it from everything cctx has accumulated in CLAUDE.md over time.
39
+
40
+ ---
41
+
42
+ ## Managed-heading registry
43
+
44
+ New constants in `cctx/models.py`:
45
+
46
+ ```python
47
+ # Maps FindingKind to the exact ## heading emitted by its patch template.
48
+ # Single source of truth for "which CLAUDE.md sections does cctx own."
49
+ MANAGED_HEADINGS: dict[FindingKind, str] = {
50
+ FindingKind.RETRY_LOOP: "## Retry discipline",
51
+ FindingKind.SCOPE_CREEP: "## Scope discipline",
52
+ FindingKind.STALE_CONTEXT: "## Context hygiene",
53
+ FindingKind.TOOL_THRASH: "## Tool-call discipline",
54
+ FindingKind.DEAD_END: "## Exploration discipline",
55
+ }
56
+
57
+ # Prefix for project-specific patterns (heading includes tool+key, so match by prefix).
58
+ MANAGED_HEADING_PREFIX: str = "## Project-specific: "
59
+ ```
60
+
61
+ A test in `tests/test_harvest_emit.py` asserts that each template's first
62
+ `+##` line equals its `MANAGED_HEADINGS` entry, so the registry and the
63
+ recommender templates cannot drift silently.
64
+
65
+ **`harvest.py` imports the registry from `models.py`** — the existing rule
66
+ "harvest does not import from recommender" remains intact.
67
+
68
+ ---
69
+
70
+ ## New functions in `cctx/harvest.py`
71
+
72
+ ### `EMIT_TARGETS`
73
+
74
+ ```python
75
+ EMIT_TARGETS: dict[str, str] = {
76
+ "agents": "AGENTS.md",
77
+ }
78
+ ```
79
+
80
+ Single place to add future targets. CLI `Choice` is derived from its keys.
81
+
82
+ ### `retarget_patches(patches, emit_target) -> list[Patch]`
83
+
84
+ Clones patches suitable for emission:
85
+
86
+ - Includes only patches with `target_file == "CLAUDE.md"`.
87
+ - Excludes patches targeting `.claude/rules/` or `.claude/skills/` (none
88
+ reach here given the above filter, but stated explicitly for clarity).
89
+ - Returns clones via `dataclasses.replace(patch, target_file=EMIT_TARGETS[emit_target])`.
90
+
91
+ ### `sync_managed_sections(target_dir, emit_target) -> list[ApplyResult]`
92
+
93
+ 1. Reads `CLAUDE.md` from `target_dir`. Returns empty list if absent.
94
+ 2. Calls `_parse_sections(content)` (already in `harvest.py`).
95
+ 3. Keeps sections whose heading is exactly in `MANAGED_HEADINGS.values()` OR
96
+ starts with `MANAGED_HEADING_PREFIX`.
97
+ 4. For each kept section, constructs a synthetic `Patch` with:
98
+ - `target_file = EMIT_TARGETS[emit_target]`
99
+ - `unified_diff = "\n".join(f"+{line}" for line in [heading] + body.splitlines())`
100
+ so the heading itself is the first line (drives `_fingerprint` dedup)
101
+ - `finding_kind`: reverse-lookup from `MANAGED_HEADINGS` for fixed headings;
102
+ `FindingKind.PROJECT_PATTERN` for `## Project-specific: …` prefixed headings
103
+ - `description = heading`
104
+ - `evidence_summary = "synced from CLAUDE.md"`
105
+ 5. Applies each synthetic patch via `apply_patch`, which handles idempotency
106
+ via `_already_present` (the `## Heading` line is the fingerprint).
107
+
108
+ ---
109
+
110
+ ## CLI changes (`cctx/cli.py`)
111
+
112
+ ```
113
+ harvest <target>
114
+ --emit [agents] Fan out this run's patches to the named target.
115
+ Multiple targets accepted (future-proofing).
116
+ --sync With --emit: also mirror already-harvested managed
117
+ sections from CLAUDE.md to the emit target.
118
+ Error if used without --emit.
119
+ ```
120
+
121
+ `--emit` is `click.option(..., multiple=True, type=click.Choice(list(EMIT_TARGETS)))`.
122
+
123
+ `--sync` without `--emit` prints an error and exits non-zero.
124
+
125
+ Both flags compose with the existing `--dry-run`/`--apply` flow:
126
+ - `--dry-run` previews all targets (CLAUDE.md rows + AGENTS.md rows).
127
+ - Without `--dry-run`, the normal interactive confirmation fires first, showing
128
+ the full diff including emit targets.
129
+
130
+ `--since` mode: `retarget_patches` runs on the aggregate patches exactly as it
131
+ does on single-session patches.
132
+
133
+ ---
134
+
135
+ ## Rendering
136
+
137
+ The existing results table in `cli.py` groups by `target_path`. No renderer
138
+ changes needed — AGENTS.md rows appear as a second group in the same table
139
+ under their full path.
140
+
141
+ ---
142
+
143
+ ## Error contract
144
+
145
+ - Never raises. All failures return `ApplyResult(status=ERROR, message=...)`.
146
+ - `--sync` with no CLAUDE.md: returns `[]` (not an error), logged as a
147
+ single `SKIPPED` line: "CLAUDE.md not found — nothing to sync."
148
+ - Emit target directory is created by `apply_patch`'s existing `parent.mkdir`.
149
+
150
+ ---
151
+
152
+ ## Out of scope
153
+
154
+ - Cursor (`.cursor/rules/*.mdc` with frontmatter), Windsurf, Copilot — future issues.
155
+ - Format translation / agent-specific adaptation of rule text.
156
+ - Drift detection between CLAUDE.md and AGENTS.md after independent edits.
157
+ - The `TOOL_THRASH`/`DEAD_END` `KeyError` in `recommender.generate()` when
158
+ findings of those kinds have no `_TEMPLATES` entry — filed separately as a
159
+ bug before M15 implementation begins, since M15 adds those kinds to
160
+ `MANAGED_HEADINGS` and the fix belongs in the recommender, not the emitter.
161
+
162
+ ---
163
+
164
+ ## Testing (`tests/test_harvest_emit.py`)
165
+
166
+ | Test | Asserts |
167
+ |---|---|
168
+ | `test_emit_applies_both_targets` | Patch lands in both CLAUDE.md and AGENTS.md |
169
+ | `test_emit_excludes_rules_patches` | `.claude/rules/` patch not emitted |
170
+ | `test_emit_idempotent` | Second `--emit` run: AGENTS.md unchanged |
171
+ | `test_sync_copies_managed_only` | Managed section copied; hand-written section absent from AGENTS.md |
172
+ | `test_sync_no_claude_md` | Returns `[]`; AGENTS.md not created |
173
+ | `test_sync_idempotent` | Second `--sync` run: no duplicate sections |
174
+ | `test_dry_run_no_writes` | Neither CLAUDE.md nor AGENTS.md written |
175
+ | `test_sync_without_emit_errors` | `--sync` alone exits non-zero |
176
+ | `test_registry_matches_templates` | Each `MANAGED_HEADINGS[k]` equals first `+##` line of `_TEMPLATES[k]`'s diff body |
177
+
178
+ ---
179
+
180
+ ## Layering
181
+
182
+ No layering rules are broken:
183
+ - `harvest.py` imports `MANAGED_HEADINGS` and `MANAGED_HEADING_PREFIX` from
184
+ `models.py`, not from `recommender/`.
185
+ - `recommender/` is unchanged.
186
+ - `harvest.py` does not import `click` or `anthropic`.
187
+
188
+ ---
189
+
190
+ ## Files touched
191
+
192
+ | File | Change |
193
+ |---|---|
194
+ | `cctx/models.py` | Add `MANAGED_HEADINGS`, `MANAGED_HEADING_PREFIX` |
195
+ | `cctx/harvest.py` | Add `EMIT_TARGETS`, `retarget_patches`, `sync_managed_sections` |
196
+ | `cctx/cli.py` | Add `--emit` + `--sync` to `harvest` command |
197
+ | `tests/test_harvest_emit.py` | New test file |
198
+ | `PRODUCT.md` | Add cross-agent emit row to feature map (on release) |
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cctx-cli"
7
- version = "1.5.0"
7
+ version = "1.5.1"
8
8
  description = "Diagnose Claude Code sessions — find what went wrong, what it cost, and what to add to CLAUDE.md"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"