erk 0.4.5__py3-none-any.whl

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 (331) hide show
  1. erk/__init__.py +12 -0
  2. erk/__main__.py +6 -0
  3. erk/agent_docs/__init__.py +5 -0
  4. erk/agent_docs/models.py +123 -0
  5. erk/agent_docs/operations.py +666 -0
  6. erk/artifacts/__init__.py +5 -0
  7. erk/artifacts/artifact_health.py +623 -0
  8. erk/artifacts/detection.py +16 -0
  9. erk/artifacts/discovery.py +343 -0
  10. erk/artifacts/models.py +63 -0
  11. erk/artifacts/staleness.py +56 -0
  12. erk/artifacts/state.py +100 -0
  13. erk/artifacts/sync.py +624 -0
  14. erk/cli/__init__.py +0 -0
  15. erk/cli/activation.py +132 -0
  16. erk/cli/alias.py +53 -0
  17. erk/cli/cli.py +221 -0
  18. erk/cli/commands/__init__.py +0 -0
  19. erk/cli/commands/admin.py +153 -0
  20. erk/cli/commands/artifact/__init__.py +1 -0
  21. erk/cli/commands/artifact/check.py +260 -0
  22. erk/cli/commands/artifact/group.py +31 -0
  23. erk/cli/commands/artifact/list_cmd.py +89 -0
  24. erk/cli/commands/artifact/show.py +62 -0
  25. erk/cli/commands/artifact/sync_cmd.py +39 -0
  26. erk/cli/commands/branch/__init__.py +26 -0
  27. erk/cli/commands/branch/assign_cmd.py +152 -0
  28. erk/cli/commands/branch/checkout_cmd.py +357 -0
  29. erk/cli/commands/branch/create_cmd.py +161 -0
  30. erk/cli/commands/branch/list_cmd.py +82 -0
  31. erk/cli/commands/branch/unassign_cmd.py +197 -0
  32. erk/cli/commands/cc/__init__.py +15 -0
  33. erk/cli/commands/cc/jsonl_cmd.py +20 -0
  34. erk/cli/commands/cc/session/AGENTS.md +30 -0
  35. erk/cli/commands/cc/session/CLAUDE.md +1 -0
  36. erk/cli/commands/cc/session/__init__.py +15 -0
  37. erk/cli/commands/cc/session/list_cmd.py +167 -0
  38. erk/cli/commands/cc/session/show_cmd.py +175 -0
  39. erk/cli/commands/completion.py +89 -0
  40. erk/cli/commands/completions.py +165 -0
  41. erk/cli/commands/config.py +327 -0
  42. erk/cli/commands/docs/__init__.py +1 -0
  43. erk/cli/commands/docs/group.py +16 -0
  44. erk/cli/commands/docs/sync.py +121 -0
  45. erk/cli/commands/docs/validate.py +102 -0
  46. erk/cli/commands/doctor.py +243 -0
  47. erk/cli/commands/down.py +171 -0
  48. erk/cli/commands/exec/__init__.py +1 -0
  49. erk/cli/commands/exec/group.py +164 -0
  50. erk/cli/commands/exec/scripts/AGENTS.md +79 -0
  51. erk/cli/commands/exec/scripts/CLAUDE.md +1 -0
  52. erk/cli/commands/exec/scripts/__init__.py +5 -0
  53. erk/cli/commands/exec/scripts/add_reaction_to_comment.py +69 -0
  54. erk/cli/commands/exec/scripts/add_remote_execution_note.py +68 -0
  55. erk/cli/commands/exec/scripts/check_impl.py +152 -0
  56. erk/cli/commands/exec/scripts/ci_update_pr_body.py +294 -0
  57. erk/cli/commands/exec/scripts/create_extraction_branch.py +138 -0
  58. erk/cli/commands/exec/scripts/create_extraction_plan.py +242 -0
  59. erk/cli/commands/exec/scripts/create_issue_from_session.py +103 -0
  60. erk/cli/commands/exec/scripts/create_plan_from_context.py +103 -0
  61. erk/cli/commands/exec/scripts/create_worker_impl_from_issue.py +93 -0
  62. erk/cli/commands/exec/scripts/detect_trunk_branch.py +121 -0
  63. erk/cli/commands/exec/scripts/exit_plan_mode_hook.py +777 -0
  64. erk/cli/commands/exec/scripts/extract_latest_plan.py +49 -0
  65. erk/cli/commands/exec/scripts/extract_session_from_issue.py +150 -0
  66. erk/cli/commands/exec/scripts/find_project_dir.py +214 -0
  67. erk/cli/commands/exec/scripts/generate_pr_summary.py +112 -0
  68. erk/cli/commands/exec/scripts/get_closing_text.py +98 -0
  69. erk/cli/commands/exec/scripts/get_embedded_prompt.py +62 -0
  70. erk/cli/commands/exec/scripts/get_plan_metadata.py +95 -0
  71. erk/cli/commands/exec/scripts/get_pr_body_footer.py +70 -0
  72. erk/cli/commands/exec/scripts/get_pr_discussion_comments.py +149 -0
  73. erk/cli/commands/exec/scripts/get_pr_review_comments.py +155 -0
  74. erk/cli/commands/exec/scripts/impl_init.py +158 -0
  75. erk/cli/commands/exec/scripts/impl_signal.py +375 -0
  76. erk/cli/commands/exec/scripts/impl_verify.py +49 -0
  77. erk/cli/commands/exec/scripts/issue_title_to_filename.py +34 -0
  78. erk/cli/commands/exec/scripts/list_sessions.py +296 -0
  79. erk/cli/commands/exec/scripts/mark_impl_ended.py +188 -0
  80. erk/cli/commands/exec/scripts/mark_impl_started.py +188 -0
  81. erk/cli/commands/exec/scripts/marker.py +163 -0
  82. erk/cli/commands/exec/scripts/objective_save_to_issue.py +109 -0
  83. erk/cli/commands/exec/scripts/plan_save_to_issue.py +269 -0
  84. erk/cli/commands/exec/scripts/plan_update_issue.py +147 -0
  85. erk/cli/commands/exec/scripts/post_extraction_comment.py +237 -0
  86. erk/cli/commands/exec/scripts/post_or_update_pr_summary.py +133 -0
  87. erk/cli/commands/exec/scripts/post_pr_inline_comment.py +143 -0
  88. erk/cli/commands/exec/scripts/post_workflow_started_comment.py +168 -0
  89. erk/cli/commands/exec/scripts/preprocess_session.py +777 -0
  90. erk/cli/commands/exec/scripts/quick_submit.py +32 -0
  91. erk/cli/commands/exec/scripts/rebase_with_conflict_resolution.py +260 -0
  92. erk/cli/commands/exec/scripts/reply_to_discussion_comment.py +173 -0
  93. erk/cli/commands/exec/scripts/resolve_review_thread.py +170 -0
  94. erk/cli/commands/exec/scripts/session_id_injector_hook.py +52 -0
  95. erk/cli/commands/exec/scripts/setup_impl_from_issue.py +159 -0
  96. erk/cli/commands/exec/scripts/slot_objective.py +102 -0
  97. erk/cli/commands/exec/scripts/tripwires_reminder_hook.py +20 -0
  98. erk/cli/commands/exec/scripts/update_dispatch_info.py +116 -0
  99. erk/cli/commands/exec/scripts/user_prompt_hook.py +113 -0
  100. erk/cli/commands/exec/scripts/validate_plan_content.py +98 -0
  101. erk/cli/commands/exec/scripts/wrap_plan_in_metadata_block.py +34 -0
  102. erk/cli/commands/implement.py +695 -0
  103. erk/cli/commands/implement_shared.py +649 -0
  104. erk/cli/commands/info/__init__.py +14 -0
  105. erk/cli/commands/info/release_notes_cmd.py +128 -0
  106. erk/cli/commands/init.py +801 -0
  107. erk/cli/commands/land_cmd.py +690 -0
  108. erk/cli/commands/log_cmd.py +137 -0
  109. erk/cli/commands/md/__init__.py +5 -0
  110. erk/cli/commands/md/check.py +118 -0
  111. erk/cli/commands/md/group.py +14 -0
  112. erk/cli/commands/navigation_helpers.py +430 -0
  113. erk/cli/commands/objective/__init__.py +16 -0
  114. erk/cli/commands/objective/list_cmd.py +47 -0
  115. erk/cli/commands/objective_helpers.py +132 -0
  116. erk/cli/commands/plan/__init__.py +32 -0
  117. erk/cli/commands/plan/check_cmd.py +174 -0
  118. erk/cli/commands/plan/close_cmd.py +69 -0
  119. erk/cli/commands/plan/create_cmd.py +120 -0
  120. erk/cli/commands/plan/docs/__init__.py +18 -0
  121. erk/cli/commands/plan/docs/extract_cmd.py +53 -0
  122. erk/cli/commands/plan/docs/unextract_cmd.py +38 -0
  123. erk/cli/commands/plan/docs/unextracted_cmd.py +72 -0
  124. erk/cli/commands/plan/extraction/__init__.py +16 -0
  125. erk/cli/commands/plan/extraction/complete_cmd.py +101 -0
  126. erk/cli/commands/plan/extraction/create_raw_cmd.py +63 -0
  127. erk/cli/commands/plan/get.py +71 -0
  128. erk/cli/commands/plan/list_cmd.py +754 -0
  129. erk/cli/commands/plan/log_cmd.py +440 -0
  130. erk/cli/commands/plan/start_cmd.py +459 -0
  131. erk/cli/commands/planner/__init__.py +40 -0
  132. erk/cli/commands/planner/configure_cmd.py +73 -0
  133. erk/cli/commands/planner/connect_cmd.py +96 -0
  134. erk/cli/commands/planner/create_cmd.py +148 -0
  135. erk/cli/commands/planner/list_cmd.py +51 -0
  136. erk/cli/commands/planner/register_cmd.py +105 -0
  137. erk/cli/commands/planner/set_default_cmd.py +23 -0
  138. erk/cli/commands/planner/unregister_cmd.py +43 -0
  139. erk/cli/commands/pr/__init__.py +23 -0
  140. erk/cli/commands/pr/check_cmd.py +112 -0
  141. erk/cli/commands/pr/checkout_cmd.py +165 -0
  142. erk/cli/commands/pr/fix_conflicts_cmd.py +82 -0
  143. erk/cli/commands/pr/parse_pr_reference.py +10 -0
  144. erk/cli/commands/pr/submit_cmd.py +360 -0
  145. erk/cli/commands/pr/sync_cmd.py +181 -0
  146. erk/cli/commands/prepare_cwd_recovery.py +60 -0
  147. erk/cli/commands/project/__init__.py +16 -0
  148. erk/cli/commands/project/init_cmd.py +91 -0
  149. erk/cli/commands/run/__init__.py +17 -0
  150. erk/cli/commands/run/list_cmd.py +189 -0
  151. erk/cli/commands/run/logs_cmd.py +54 -0
  152. erk/cli/commands/run/shared.py +19 -0
  153. erk/cli/commands/shell_integration.py +29 -0
  154. erk/cli/commands/slot/__init__.py +23 -0
  155. erk/cli/commands/slot/check_cmd.py +277 -0
  156. erk/cli/commands/slot/common.py +314 -0
  157. erk/cli/commands/slot/init_pool_cmd.py +157 -0
  158. erk/cli/commands/slot/list_cmd.py +228 -0
  159. erk/cli/commands/slot/repair_cmd.py +190 -0
  160. erk/cli/commands/stack/__init__.py +23 -0
  161. erk/cli/commands/stack/consolidate_cmd.py +470 -0
  162. erk/cli/commands/stack/list_cmd.py +79 -0
  163. erk/cli/commands/stack/move_cmd.py +309 -0
  164. erk/cli/commands/stack/split_old/README.md +64 -0
  165. erk/cli/commands/stack/split_old/__init__.py +5 -0
  166. erk/cli/commands/stack/split_old/command.py +233 -0
  167. erk/cli/commands/stack/split_old/display.py +116 -0
  168. erk/cli/commands/stack/split_old/plan.py +216 -0
  169. erk/cli/commands/status.py +58 -0
  170. erk/cli/commands/submit.py +768 -0
  171. erk/cli/commands/up.py +154 -0
  172. erk/cli/commands/upgrade.py +82 -0
  173. erk/cli/commands/wt/__init__.py +29 -0
  174. erk/cli/commands/wt/checkout_cmd.py +110 -0
  175. erk/cli/commands/wt/create_cmd.py +998 -0
  176. erk/cli/commands/wt/current_cmd.py +35 -0
  177. erk/cli/commands/wt/delete_cmd.py +573 -0
  178. erk/cli/commands/wt/list_cmd.py +332 -0
  179. erk/cli/commands/wt/rename_cmd.py +66 -0
  180. erk/cli/config.py +242 -0
  181. erk/cli/constants.py +29 -0
  182. erk/cli/core.py +65 -0
  183. erk/cli/debug.py +9 -0
  184. erk/cli/ensure-conversion-tasks.md +288 -0
  185. erk/cli/ensure.py +628 -0
  186. erk/cli/github_parsing.py +96 -0
  187. erk/cli/graphite.py +81 -0
  188. erk/cli/graphite_command.py +80 -0
  189. erk/cli/help_formatter.py +345 -0
  190. erk/cli/output.py +361 -0
  191. erk/cli/presets/dagster.toml +12 -0
  192. erk/cli/presets/generic.toml +12 -0
  193. erk/cli/prompt_hooks_templates/README.md +68 -0
  194. erk/cli/script_output.py +32 -0
  195. erk/cli/shell_integration/bash_wrapper.sh +32 -0
  196. erk/cli/shell_integration/fish_wrapper.fish +39 -0
  197. erk/cli/shell_integration/handler.py +338 -0
  198. erk/cli/shell_integration/zsh_wrapper.sh +32 -0
  199. erk/cli/shell_utils.py +171 -0
  200. erk/cli/subprocess_utils.py +92 -0
  201. erk/cli/uvx_detection.py +59 -0
  202. erk/core/__init__.py +0 -0
  203. erk/core/claude_executor.py +511 -0
  204. erk/core/claude_settings.py +317 -0
  205. erk/core/command_log.py +406 -0
  206. erk/core/commit_message_generator.py +234 -0
  207. erk/core/completion.py +10 -0
  208. erk/core/consolidation_utils.py +177 -0
  209. erk/core/context.py +570 -0
  210. erk/core/display/__init__.py +4 -0
  211. erk/core/display/abc.py +24 -0
  212. erk/core/display/real.py +30 -0
  213. erk/core/display_utils.py +526 -0
  214. erk/core/file_utils.py +87 -0
  215. erk/core/health_checks.py +1315 -0
  216. erk/core/health_checks_dogfooder/__init__.py +85 -0
  217. erk/core/health_checks_dogfooder/deprecated_dot_agent_config.py +64 -0
  218. erk/core/health_checks_dogfooder/legacy_claude_docs.py +69 -0
  219. erk/core/health_checks_dogfooder/legacy_config_locations.py +122 -0
  220. erk/core/health_checks_dogfooder/legacy_erk_docs_agent.py +61 -0
  221. erk/core/health_checks_dogfooder/legacy_erk_kits_folder.py +60 -0
  222. erk/core/health_checks_dogfooder/legacy_hook_settings.py +104 -0
  223. erk/core/health_checks_dogfooder/legacy_kit_yaml.py +78 -0
  224. erk/core/health_checks_dogfooder/legacy_kits_toml.py +43 -0
  225. erk/core/health_checks_dogfooder/outdated_erk_skill.py +43 -0
  226. erk/core/implementation_queue/__init__.py +1 -0
  227. erk/core/implementation_queue/github/__init__.py +8 -0
  228. erk/core/implementation_queue/github/abc.py +7 -0
  229. erk/core/implementation_queue/github/noop.py +38 -0
  230. erk/core/implementation_queue/github/printing.py +43 -0
  231. erk/core/implementation_queue/github/real.py +119 -0
  232. erk/core/init_utils.py +227 -0
  233. erk/core/output_filter.py +338 -0
  234. erk/core/plan_store/__init__.py +6 -0
  235. erk/core/planner/__init__.py +1 -0
  236. erk/core/planner/registry_abc.py +8 -0
  237. erk/core/planner/registry_fake.py +129 -0
  238. erk/core/planner/registry_real.py +195 -0
  239. erk/core/planner/types.py +7 -0
  240. erk/core/pr_utils.py +30 -0
  241. erk/core/release_notes.py +263 -0
  242. erk/core/repo_discovery.py +126 -0
  243. erk/core/script_writer.py +41 -0
  244. erk/core/services/__init__.py +1 -0
  245. erk/core/services/plan_list_service.py +94 -0
  246. erk/core/shell.py +51 -0
  247. erk/core/user_feedback.py +11 -0
  248. erk/core/version_check.py +55 -0
  249. erk/core/workflow_display.py +75 -0
  250. erk/core/worktree_pool.py +190 -0
  251. erk/core/worktree_utils.py +300 -0
  252. erk/data/CHANGELOG.md +438 -0
  253. erk/data/__init__.py +1 -0
  254. erk/data/claude/agents/devrun.md +180 -0
  255. erk/data/claude/commands/erk/__init__.py +0 -0
  256. erk/data/claude/commands/erk/create-extraction-plan.md +360 -0
  257. erk/data/claude/commands/erk/fix-conflicts.md +25 -0
  258. erk/data/claude/commands/erk/git-pr-push.md +345 -0
  259. erk/data/claude/commands/erk/implement-stacked-plan.md +96 -0
  260. erk/data/claude/commands/erk/land.md +193 -0
  261. erk/data/claude/commands/erk/objective-create.md +370 -0
  262. erk/data/claude/commands/erk/objective-list.md +34 -0
  263. erk/data/claude/commands/erk/objective-next-plan.md +220 -0
  264. erk/data/claude/commands/erk/objective-update-with-landed-pr.md +216 -0
  265. erk/data/claude/commands/erk/plan-implement.md +202 -0
  266. erk/data/claude/commands/erk/plan-save.md +45 -0
  267. erk/data/claude/commands/erk/plan-submit.md +39 -0
  268. erk/data/claude/commands/erk/pr-address.md +367 -0
  269. erk/data/claude/commands/erk/pr-submit.md +58 -0
  270. erk/data/claude/skills/dignified-python/SKILL.md +48 -0
  271. erk/data/claude/skills/dignified-python/cli-patterns.md +155 -0
  272. erk/data/claude/skills/dignified-python/dignified-python-core.md +1190 -0
  273. erk/data/claude/skills/dignified-python/subprocess.md +99 -0
  274. erk/data/claude/skills/dignified-python/versions/python-3.10.md +517 -0
  275. erk/data/claude/skills/dignified-python/versions/python-3.11.md +536 -0
  276. erk/data/claude/skills/dignified-python/versions/python-3.12.md +662 -0
  277. erk/data/claude/skills/dignified-python/versions/python-3.13.md +653 -0
  278. erk/data/claude/skills/erk-diff-analysis/SKILL.md +27 -0
  279. erk/data/claude/skills/erk-diff-analysis/references/commit-message-prompt.md +78 -0
  280. erk/data/claude/skills/learned-docs/SKILL.md +362 -0
  281. erk/data/github/actions/setup-claude-erk/action.yml +11 -0
  282. erk/data/github/prompts/dignified-python-review.md +125 -0
  283. erk/data/github/workflows/dignified-python-review.yml +61 -0
  284. erk/data/github/workflows/erk-impl.yml +251 -0
  285. erk/hooks/__init__.py +1 -0
  286. erk/hooks/decorators.py +319 -0
  287. erk/status/__init__.py +8 -0
  288. erk/status/collectors/__init__.py +9 -0
  289. erk/status/collectors/base.py +52 -0
  290. erk/status/collectors/git.py +76 -0
  291. erk/status/collectors/github.py +81 -0
  292. erk/status/collectors/graphite.py +80 -0
  293. erk/status/collectors/impl.py +145 -0
  294. erk/status/models/__init__.py +4 -0
  295. erk/status/models/status_data.py +404 -0
  296. erk/status/orchestrator.py +169 -0
  297. erk/status/renderers/__init__.py +5 -0
  298. erk/status/renderers/simple.py +322 -0
  299. erk/tui/AGENTS.md +193 -0
  300. erk/tui/CLAUDE.md +1 -0
  301. erk/tui/__init__.py +1 -0
  302. erk/tui/app.py +1404 -0
  303. erk/tui/commands/__init__.py +1 -0
  304. erk/tui/commands/executor.py +66 -0
  305. erk/tui/commands/provider.py +165 -0
  306. erk/tui/commands/real_executor.py +63 -0
  307. erk/tui/commands/registry.py +121 -0
  308. erk/tui/commands/types.py +36 -0
  309. erk/tui/data/__init__.py +1 -0
  310. erk/tui/data/provider.py +492 -0
  311. erk/tui/data/types.py +104 -0
  312. erk/tui/filtering/__init__.py +1 -0
  313. erk/tui/filtering/logic.py +43 -0
  314. erk/tui/filtering/types.py +55 -0
  315. erk/tui/jsonl_viewer/__init__.py +1 -0
  316. erk/tui/jsonl_viewer/app.py +61 -0
  317. erk/tui/jsonl_viewer/models.py +208 -0
  318. erk/tui/jsonl_viewer/widgets.py +204 -0
  319. erk/tui/sorting/__init__.py +6 -0
  320. erk/tui/sorting/logic.py +55 -0
  321. erk/tui/sorting/types.py +68 -0
  322. erk/tui/styles/dash.tcss +95 -0
  323. erk/tui/widgets/__init__.py +1 -0
  324. erk/tui/widgets/command_output.py +112 -0
  325. erk/tui/widgets/plan_table.py +276 -0
  326. erk/tui/widgets/status_bar.py +116 -0
  327. erk-0.4.5.dist-info/METADATA +376 -0
  328. erk-0.4.5.dist-info/RECORD +331 -0
  329. erk-0.4.5.dist-info/WHEEL +4 -0
  330. erk-0.4.5.dist-info/entry_points.txt +2 -0
  331. erk-0.4.5.dist-info/licenses/LICENSE.md +3 -0
@@ -0,0 +1,78 @@
1
+ You are a commit message generator. Analyze the provided git diff and return ONLY a commit message.
2
+
3
+ ## Analysis Principles
4
+
5
+ Analyze the diff following these principles:
6
+
7
+ - **Be concise and strategic** - focus on significant changes
8
+ - **Use component-level descriptions** - reference modules/components, not individual functions
9
+ - **Highlight breaking changes prominently**
10
+ - **Note test coverage patterns**
11
+ - **Use relative paths from repository root**
12
+
13
+ ## Level of Detail
14
+
15
+ - Focus on architectural and component-level impact
16
+ - Keep "Key Changes" to 3-5 major items
17
+ - Group related changes together
18
+ - Skip minor refactoring, formatting, or trivial updates
19
+
20
+ ## Output Format
21
+
22
+ ```
23
+ [Clear one-line PR title describing the change]
24
+
25
+ [2-3 sentence summary explaining what changed and why. State what the branch does (feature/fix/refactor) and highlight key changes briefly.]
26
+
27
+ ## Files Changed
28
+
29
+ ### Added (N files)
30
+ - `path/to/file.py` - Brief purpose (one line)
31
+
32
+ ### Modified (N files)
33
+ - `path/to/file.py` - What area changed (component level)
34
+
35
+ ### Deleted (N files)
36
+ - `path/to/file.py` - Why removed (strategic reason)
37
+
38
+ ## Key Changes
39
+
40
+ - [3-5 high-level component/architectural changes]
41
+ - Strategic change description focusing on purpose and impact
42
+ - Focus on what capabilities changed, not implementation details
43
+
44
+ ## User Experience
45
+ [Only include this section if changes affect user-facing behavior: CLI commands, prompts, output, workflows]
46
+
47
+ **Before:**
48
+ ```
49
+
50
+ [Show the old user experience - what command they ran and what happened]
51
+
52
+ ```
53
+
54
+ **After:**
55
+ ```
56
+
57
+ [Show the new user experience - same scenario with new behavior]
58
+
59
+ ```
60
+
61
+ [Optional 1-2 sentence explanation of the improvement]
62
+
63
+ ## Critical Notes
64
+ [Only if there are breaking changes, security concerns, or important warnings - 1-2 bullets max]
65
+ ```
66
+
67
+ ## Rules
68
+
69
+ - **IMPORTANT**: Output the commit message directly. Do NOT wrap your response in code fences or markdown blocks.
70
+ - Output ONLY the commit message (no preamble, no explanation, no commentary)
71
+ - NO Claude attribution or footer (NEVER add "Generated with Claude Code" or similar)
72
+ - NO metadata headers (NEVER add `**Author:**`, `**Plan:**`, `Closes #N`, or similar)
73
+ - Use relative paths from repository root
74
+ - Be concise (15-40 lines total, shorter if no User Experience section)
75
+ - First line = PR title, rest = PR body
76
+ - Avoid function-level details unless critical
77
+ - Maximum 5 key changes
78
+ - Only include Critical Notes if necessary
@@ -0,0 +1,362 @@
1
+ ---
2
+ name: learned-docs
3
+ description: This skill should be used when writing, modifying, or reorganizing
4
+ documentation in docs/learned/. Use when creating new documents, updating frontmatter,
5
+ choosing categories, creating index files, updating routing tables, or moving
6
+ files between categories. Essential for maintaining consistent documentation structure.
7
+ ---
8
+
9
+ # Learned Documentation Guide
10
+
11
+ Overview: `docs/learned/` contains agent-focused documentation with:
12
+
13
+ - YAML frontmatter for routing and discovery
14
+ - Hierarchical category organization (categories listed in index below)
15
+ - Index files for category navigation
16
+ - Routing tables in AGENTS.md
17
+
18
+ ## Document Registry (Auto-Generated)
19
+
20
+ @docs/learned/index.md
21
+
22
+ ## Frontmatter Requirements
23
+
24
+ Every markdown file (except index.md) MUST have:
25
+
26
+ ```yaml
27
+ ---
28
+ title: Document Title
29
+ read_when:
30
+ - "first condition"
31
+ - "second condition"
32
+ ---
33
+ ```
34
+
35
+ ### Required Fields
36
+
37
+ | Field | Type | Purpose |
38
+ | ----------- | ------------ | ------------------------------------------ |
39
+ | `title` | string | Human-readable title for index tables |
40
+ | `read_when` | list[string] | Conditions when agent should read this doc |
41
+
42
+ ### Writing Effective read_when Values
43
+
44
+ - Use gerund phrases: "creating a plan", "styling CLI output"
45
+ - Be specific: "fixing merge conflicts in tests" not "tests"
46
+ - Include 2-4 conditions covering primary use cases
47
+ - Think: "An agent should read this when they are..."
48
+
49
+ Good:
50
+
51
+ ```yaml
52
+ read_when:
53
+ - "creating or closing plans"
54
+ - "understanding plan states"
55
+ - "working with .impl/ folders"
56
+ ```
57
+
58
+ Bad:
59
+
60
+ ```yaml
61
+ read_when:
62
+ - "plans" # Too vague
63
+ - "the user asks" # Not descriptive
64
+ ```
65
+
66
+ ## Documentation Structure
67
+
68
+ **Read the master index for current categories and documents:**
69
+
70
+ `docs/learned/index.md`
71
+
72
+ The index contains:
73
+
74
+ - All category paths and descriptions
75
+ - Root-level documents
76
+ - Document listings with "Read when..." conditions
77
+
78
+ ## Category Placement Guidelines
79
+
80
+ 1. **Match by topic** - Does the doc clearly fit one category? (see index above for categories)
81
+ 2. **Match by related docs** - Are similar docs already in a category?
82
+ 3. **When unclear** - Place at root level; categorize later when patterns emerge
83
+ 4. **Create new category** - When 3+ related docs exist at root level
84
+
85
+ ### Distinguishing cli/ vs architecture/
86
+
87
+ This is the most common confusion:
88
+
89
+ - **cli/**: Patterns for **building CLI commands** - how users interact with the tool
90
+ - Fast-path patterns (skipping expensive ops)
91
+ - Output formatting and styling
92
+ - Script mode behavior
93
+ - Command organization
94
+
95
+ - **architecture/**: **Internal implementation patterns** - how the code works
96
+ - Gateway ABCs and dependency injection
97
+ - Dry-run via wrapper classes
98
+ - Shell integration constraints
99
+ - Protocol vs ABC decisions
100
+
101
+ ## Document Structure Template
102
+
103
+ ```markdown
104
+ ---
105
+ title: [Clear Document Title]
106
+ read_when:
107
+ - "[first condition]"
108
+ - "[second condition]"
109
+ ---
110
+
111
+ # [Title Matching Frontmatter]
112
+
113
+ [1-2 sentence overview]
114
+
115
+ ## [Main Content Sections]
116
+
117
+ [Organized content with clear headers]
118
+
119
+ ## Related Topics
120
+
121
+ - [Link to related docs](../category/doc.md) - Brief description
122
+ ```
123
+
124
+ ## Index File Template
125
+
126
+ Each category has an `index.md` following this pattern:
127
+
128
+ ```markdown
129
+ ---
130
+ title: [Category] Documentation
131
+ read_when:
132
+ - "[when to browse this category]"
133
+ ---
134
+
135
+ # [Category] Documentation
136
+
137
+ [Brief category description]
138
+
139
+ ## Quick Navigation
140
+
141
+ | When you need to... | Read this |
142
+ | ------------------- | ---------------- |
143
+ | [specific task] | [doc.md](doc.md) |
144
+
145
+ ## Documents in This Category
146
+
147
+ ### [Document Title]
148
+
149
+ **File:** [doc.md](doc.md)
150
+
151
+ [1-2 sentence description]
152
+
153
+ ## Related Topics
154
+
155
+ - [Other Category](../other/) - Brief relevance
156
+ ```
157
+
158
+ ## Code in Documentation
159
+
160
+ **Critical rule**: NEVER embed Python functions that process erk data or encode business logic.
161
+
162
+ ### Why This Matters
163
+
164
+ Embedded Python code in documentation:
165
+
166
+ - Is NOT under test - it silently goes stale
167
+ - Causes bugs when agents copy outdated patterns
168
+ - Encodes business assumptions (field names, conventions) that can change
169
+ - Creates maintenance burden requiring docs-code sync
170
+
171
+ PR #2681 demonstrated this: an agent copied incorrect scratch directory paths from documentation because the docs hadn't been updated when the implementation changed.
172
+
173
+ ### The "Simple Function" Trap
174
+
175
+ Even "simple" functions are dangerous. A one-liner like:
176
+
177
+ ```python
178
+ # DANGEROUS - encodes `agent-` prefix convention
179
+ files = [f for f in dir.glob("*.jsonl") if not f.name.startswith("agent-")]
180
+ ```
181
+
182
+ Embeds a naming convention that could change. When it does, the docs become a source of bugs.
183
+
184
+ ### What to REMOVE (Aggressive Stance)
185
+
186
+ Remove ALL Python `def` functions that:
187
+
188
+ - Process session logs, JSONL, or erk data
189
+ - Encode path patterns or naming conventions
190
+ - Filter, parse, or transform erk-specific data
191
+ - Implement algorithms that exist (or could exist) in production
192
+ - Show "how to" implementation patterns for erk internals
193
+
194
+ **Even if the function doesn't exist in production today**, it could be added later, creating divergence.
195
+
196
+ ### What to KEEP (Narrow Exceptions)
197
+
198
+ - **JSON/YAML format examples**: Showing data structure, not processing code
199
+ - **External library patterns**: Click commands, pytest fixtures, Rich tables (teaching third-party APIs)
200
+ - **Anti-pattern demonstrations**: Code explicitly marked "WRONG" or "DON'T DO THIS"
201
+ - **Shell/bash commands**: `ls`, `jq`, `grep` for operational tasks
202
+ - **Type definitions**: Dataclass/TypedDict showing structure (not methods)
203
+
204
+ ### Decision Test
205
+
206
+ Before keeping a Python code block, ask:
207
+
208
+ 1. Does it contain a `def` statement? → Probably REMOVE
209
+ 2. Does it process erk-specific data? → REMOVE
210
+ 3. Does it encode a convention (field name, path pattern, prefix)? → REMOVE
211
+ 4. Is it teaching a third-party API (Click, pytest, Rich)? → KEEP
212
+ 5. Is it showing data FORMAT (not processing)? → KEEP
213
+
214
+ ### Replacement Format
215
+
216
+ When removing code, replace with:
217
+
218
+ 1. **Prose description** of what the operation does
219
+ 2. **Source pointer** to canonical implementation
220
+ 3. **CLI command** if one exists for agents to use
221
+
222
+ **Before (BAD)**:
223
+
224
+ ````markdown
225
+ ```python
226
+ def find_session_logs(project_dir: Path) -> list[Path]:
227
+ """Find all main session logs (exclude agent logs)."""
228
+ return [
229
+ f for f in project_dir.glob("*.jsonl")
230
+ if f.is_file() and not f.name.startswith("agent-")
231
+ ]
232
+ ```
233
+ ````
234
+
235
+ **After (GOOD)**:
236
+
237
+ ```markdown
238
+ Main session logs are `.jsonl` files that don't start with `agent-`. Agent
239
+ subprocess logs use the `agent-<id>.jsonl` naming convention.
240
+
241
+ To list sessions for a project, use:
242
+ erk exec list-sessions
243
+
244
+ See `preprocess_session.py` for the canonical implementation.
245
+ ```
246
+
247
+ ### Source Pointer Rules
248
+
249
+ - Point to source file path: `package/module.py`
250
+ - NEVER include line numbers (they go stale)
251
+ - Use backticks for file paths
252
+ - Prefer CLI commands over source pointers when available
253
+
254
+ ## Reorganizing Documentation
255
+
256
+ When moving files between categories:
257
+
258
+ ### Step 1: Move Files with git mv
259
+
260
+ ```bash
261
+ cd docs/learned
262
+ git mv old-location/doc.md new-category/doc.md
263
+ ```
264
+
265
+ ### Step 2: Update Cross-References
266
+
267
+ Find all references to moved files:
268
+
269
+ ```bash
270
+ grep -r "old-filename.md" docs/learned/
271
+ ```
272
+
273
+ Update relative links:
274
+
275
+ - Same category: `[doc.md](doc.md)`
276
+ - Different category: `[doc.md](../category/doc.md)`
277
+ - To category index: `[Category](../category/)`
278
+
279
+ ### Step 3: Update Index Files
280
+
281
+ Update Quick Navigation tables in affected index files.
282
+
283
+ ### Step 4: Update AGENTS.md
284
+
285
+ If the doc was in the routing table, update the path.
286
+
287
+ ### Step 5: Validate
288
+
289
+ Run `make fast-ci` to catch broken links and formatting issues.
290
+
291
+ ## Updating Routing Tables
292
+
293
+ AGENTS.md contains the Quick Routing Table for agent navigation.
294
+
295
+ ### When to Add Entries
296
+
297
+ - New category additions
298
+ - High-frequency tasks
299
+ - Tasks where wrong approach is common
300
+
301
+ ### Entry Format
302
+
303
+ ```markdown
304
+ | [Task description] | → [Link or skill] |
305
+ ```
306
+
307
+ Examples:
308
+
309
+ - `| Understand project architecture | → [Architecture](docs/learned/architecture/) |`
310
+ - `| Write Python code | → Load \`dignified-python\` skill FIRST |`
311
+
312
+ ## Validation
313
+
314
+ Run before committing:
315
+
316
+ ```bash
317
+ make fast-ci
318
+ ```
319
+
320
+ This validates:
321
+
322
+ - YAML frontmatter syntax
323
+ - Required fields present
324
+ - Markdown formatting (prettier)
325
+
326
+ ## ⚠️ Generated Files - Do Not Edit Directly
327
+
328
+ The following files are **auto-generated** from frontmatter metadata:
329
+
330
+ | File | Source |
331
+ | ---------------------------------- | -------------------------- |
332
+ | `docs/learned/index.md` | Frontmatter from all docs |
333
+ | `docs/learned/<category>/index.md` | Frontmatter from category |
334
+ | `docs/learned/tripwires.md` | `tripwires:` field in docs |
335
+
336
+ **Never edit these files directly.** Changes will be overwritten.
337
+
338
+ ### Workflow for Changes
339
+
340
+ 1. **Edit the source frontmatter** in the relevant documentation file(s)
341
+ 2. **Run sync**: `erk docs sync`
342
+ 3. **Verify changes** in the generated files
343
+ 4. **Commit both** the source and generated files
344
+
345
+ ### Adding a New Tripwire
346
+
347
+ To add a tripwire rule:
348
+
349
+ 1. Add to the `tripwires:` field in the relevant doc's frontmatter:
350
+ ```yaml
351
+ tripwires:
352
+ - action: "doing something dangerous"
353
+ warning: "Do this instead."
354
+ ```
355
+ 2. Run `erk docs sync` to regenerate `tripwires.md`
356
+
357
+ ## Quick Reference
358
+
359
+ - Full navigation: [docs/learned/guide.md](docs/learned/guide.md)
360
+ - Category index: [docs/learned/index.md](docs/learned/index.md)
361
+ - Regenerate indexes: `erk docs sync`
362
+ - Run validation: `make fast-ci`
@@ -0,0 +1,11 @@
1
+ name: "Setup Erk"
2
+ description: "Install erk tools (assumes container has uv and claude preinstalled)"
3
+
4
+ runs:
5
+ using: "composite"
6
+ steps:
7
+ - name: Install erk
8
+ shell: bash
9
+ run: |
10
+ cd $GITHUB_WORKSPACE
11
+ uv tool install --from . --with ./packages/erk-shared erk
@@ -0,0 +1,125 @@
1
+ REPO: {{ github.repository }}
2
+ PR NUMBER: {{ github.event.pull_request.number }}
3
+
4
+ ## Task
5
+
6
+ Review Python code changes for adherence to dignified-python standards.
7
+
8
+ ## Step 1: Load the Dignified Python Standards
9
+
10
+ Read these skill files from the repository:
11
+
12
+ 1. .claude/skills/dignified-python/SKILL.md (routing and version detection)
13
+ 2. .claude/skills/dignified-python/dignified-python-core.md (LBYL, exceptions, paths, imports, DI, performance)
14
+ 3. .claude/skills/dignified-python/cli-patterns.md (Click best practices)
15
+ 4. .claude/skills/dignified-python/subprocess.md (subprocess handling)
16
+
17
+ ## Step 2: Get Existing Review Comment
18
+
19
+ Fetch the existing review comment to preserve the activity log:
20
+
21
+ ```
22
+ gh pr view {{ github.event.pull_request.number }} --json comments --jq '.comments[] | select(.body | contains("<!-- dignified-python-review -->")) | .body'
23
+ ```
24
+
25
+ If a comment exists, extract the Activity Log section (everything after `### Activity Log`). You will append to this log.
26
+
27
+ ## Step 3: Get the Python Diff
28
+
29
+ ```
30
+ gh pr diff {{ github.event.pull_request.number }} --name-only | grep '\.py$'
31
+ gh pr diff {{ github.event.pull_request.number }}
32
+ ```
33
+
34
+ ## Step 3b: Identify Changed Lines
35
+
36
+ For each Python file, determine which lines were actually modified (not just context):
37
+
38
+ - Lines starting with `+` in the diff are additions/modifications
39
+ - Lines starting with ` ` (space) are unchanged context
40
+
41
+ For the `__all__` / re-export rule specifically:
42
+
43
+ - If `__all__` appears on a `+` line → Flag as violation (actively being modified)
44
+ - If `__all__` only appears in context lines → Skip (pre-existing, not being modified)
45
+
46
+ This allows file moves/refactors to pass while catching active modifications.
47
+
48
+ ## Step 4: Analyze Code
49
+
50
+ Check each Python file against dignified-python rules:
51
+
52
+ - LBYL over EAFP (no try/except for control flow)
53
+ - Exception handling (no silent swallowing, log at boundaries)
54
+ - Path operations (exists before resolve)
55
+ - Import organization (module-level, absolute, no re-exports)
56
+ - No default parameter values
57
+ - Dependency injection with ABC
58
+ - Frozen dataclasses
59
+
60
+ **For `__all__` / re-exports:**
61
+
62
+ - Only flag if `__all__` appears in the **changed lines** (Step 3b analysis)
63
+ - Skip if `__all__` is pre-existing and unchanged in this PR
64
+
65
+ ## Step 5: Post Inline Comments
66
+
67
+ **IMPORTANT: You MUST post an inline comment for EACH violation found.**
68
+
69
+ ```
70
+ erk exec post-pr-inline-comment \
71
+ --pr-number {{ github.event.pull_request.number }} \
72
+ --path "path/to/file.py" \
73
+ --line LINE_NUMBER \
74
+ --body "**Dignified Python**: [rule violated] - [fix suggestion]"
75
+ ```
76
+
77
+ ## Step 6: Post Summary Comment
78
+
79
+ **IMPORTANT: All timestamps MUST be in Pacific Time (PT), NOT UTC.**
80
+
81
+ Get the current Pacific time timestamp by running this command:
82
+
83
+ ```
84
+ TZ='America/Los_Angeles' date '+%Y-%m-%d %H:%M:%S'
85
+ ```
86
+
87
+ Use this timestamp (with " PT" suffix) for both "Last updated" and Activity Log entries.
88
+
89
+ Post/update the summary comment:
90
+
91
+ ```
92
+ erk exec post-or-update-pr-summary \
93
+ --pr-number {{ github.event.pull_request.number }} \
94
+ --marker "<!-- dignified-python-review -->" \
95
+ --body "SUMMARY_TEXT"
96
+ ```
97
+
98
+ Summary format (preserve existing Activity Log entries and prepend new entry):
99
+
100
+ ```
101
+ <!-- dignified-python-review -->
102
+
103
+ ## ✅ Dignified Python Review (use ✅ if 0 issues, ❌ if 1+ issues)
104
+
105
+ **Last updated:** YYYY-MM-DD HH:MM:SS PT
106
+
107
+ Found X issues across Y files. Inline comments posted for each.
108
+
109
+ ### Files Reviewed
110
+ - `file.py`: N issues
111
+
112
+ ---
113
+
114
+ ### Activity Log
115
+ - **YYYY-MM-DD HH:MM:SS PT**: [Brief description of this review's findings]
116
+ - [Previous log entries preserved here...]
117
+ ```
118
+
119
+ Activity log entry examples:
120
+
121
+ - "Found 2 issues (LBYL violation in x.py, inline import in y.py)"
122
+ - "All issues resolved"
123
+ - "False positive dismissed: CLI error boundary pattern"
124
+
125
+ Keep the last 10 log entries maximum.
@@ -0,0 +1,61 @@
1
+ # Claude Code CI workflow
2
+ # See docs/learned/ci/containerless-ci.md for native tool installation details
3
+ name: dignified-python-review
4
+
5
+ on:
6
+ pull_request:
7
+ types: [opened, synchronize]
8
+ paths:
9
+ - "**/*.py"
10
+
11
+ jobs:
12
+ dignified-review:
13
+ if: github.event.pull_request.draft != true
14
+ runs-on: ubuntu-latest
15
+ timeout-minutes: 30
16
+ permissions:
17
+ contents: read
18
+ pull-requests: write
19
+
20
+ steps:
21
+ - name: Checkout repository
22
+ uses: actions/checkout@v4
23
+ with:
24
+ fetch-depth: 1
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v5
28
+
29
+ - name: Install Claude Code
30
+ uses: ./.github/actions/setup-claude-code
31
+
32
+ - name: Install erk
33
+ run: uv tool install --from . --with ./packages/erk-shared erk
34
+
35
+ - name: Prepare prompt
36
+ shell: bash
37
+ run: |
38
+ # Read prompt file and substitute variables
39
+ PROMPT=$(cat .github/prompts/dignified-python-review.md)
40
+ PROMPT="${PROMPT//\{\{ github.repository \}\}/${{ github.repository }}}"
41
+ PROMPT="${PROMPT//\{\{ github.event.pull_request.number \}\}/${{ github.event.pull_request.number }}}"
42
+
43
+ # Write to temp file for claude to read
44
+ echo "$PROMPT" > /tmp/dignified-python-prompt.md
45
+ echo "Prompt prepared with PR #${{ github.event.pull_request.number }}"
46
+
47
+ - name: Run Dignified Python Review
48
+ env:
49
+ CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
50
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
51
+ GH_TOKEN: ${{ github.token }}
52
+ run: |
53
+ # Using sonnet for better analysis accuracy. Haiku missed inline import
54
+ # violations in PR #3980 - see https://github.com/dagster-io/erk/pull/3980
55
+ claude --print \
56
+ --model claude-sonnet-4-5 \
57
+ --allowedTools 'Bash(gh:*),Bash(erk exec:*),Read(*)' \
58
+ --dangerously-skip-permissions \
59
+ --output-format stream-json \
60
+ --verbose \
61
+ "$(cat /tmp/dignified-python-prompt.md)"