codex-autorunner 1.0.0__py3-none-any.whl → 1.2.0__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 (227) hide show
  1. codex_autorunner/__init__.py +12 -1
  2. codex_autorunner/agents/codex/harness.py +1 -1
  3. codex_autorunner/agents/opencode/client.py +113 -4
  4. codex_autorunner/agents/opencode/constants.py +3 -0
  5. codex_autorunner/agents/opencode/harness.py +6 -1
  6. codex_autorunner/agents/opencode/runtime.py +59 -18
  7. codex_autorunner/agents/opencode/supervisor.py +4 -0
  8. codex_autorunner/agents/registry.py +36 -7
  9. codex_autorunner/bootstrap.py +226 -4
  10. codex_autorunner/cli.py +5 -1174
  11. codex_autorunner/codex_cli.py +20 -84
  12. codex_autorunner/core/__init__.py +20 -0
  13. codex_autorunner/core/about_car.py +119 -1
  14. codex_autorunner/core/app_server_ids.py +59 -0
  15. codex_autorunner/core/app_server_threads.py +17 -2
  16. codex_autorunner/core/app_server_utils.py +165 -0
  17. codex_autorunner/core/archive.py +349 -0
  18. codex_autorunner/core/codex_runner.py +6 -2
  19. codex_autorunner/core/config.py +433 -4
  20. codex_autorunner/core/context_awareness.py +38 -0
  21. codex_autorunner/core/docs.py +0 -122
  22. codex_autorunner/core/drafts.py +58 -4
  23. codex_autorunner/core/exceptions.py +4 -0
  24. codex_autorunner/core/filebox.py +265 -0
  25. codex_autorunner/core/flows/controller.py +96 -2
  26. codex_autorunner/core/flows/models.py +13 -0
  27. codex_autorunner/core/flows/reasons.py +52 -0
  28. codex_autorunner/core/flows/reconciler.py +134 -0
  29. codex_autorunner/core/flows/runtime.py +57 -4
  30. codex_autorunner/core/flows/store.py +142 -7
  31. codex_autorunner/core/flows/transition.py +27 -15
  32. codex_autorunner/core/flows/ux_helpers.py +272 -0
  33. codex_autorunner/core/flows/worker_process.py +32 -6
  34. codex_autorunner/core/git_utils.py +62 -0
  35. codex_autorunner/core/hub.py +291 -20
  36. codex_autorunner/core/lifecycle_events.py +253 -0
  37. codex_autorunner/core/notifications.py +14 -2
  38. codex_autorunner/core/path_utils.py +2 -1
  39. codex_autorunner/core/pma_audit.py +224 -0
  40. codex_autorunner/core/pma_context.py +496 -0
  41. codex_autorunner/core/pma_dispatch_interceptor.py +284 -0
  42. codex_autorunner/core/pma_lifecycle.py +527 -0
  43. codex_autorunner/core/pma_queue.py +367 -0
  44. codex_autorunner/core/pma_safety.py +221 -0
  45. codex_autorunner/core/pma_state.py +115 -0
  46. codex_autorunner/core/ports/__init__.py +28 -0
  47. codex_autorunner/{integrations/agents → core/ports}/agent_backend.py +13 -8
  48. codex_autorunner/core/ports/backend_orchestrator.py +41 -0
  49. codex_autorunner/{integrations/agents → core/ports}/run_event.py +23 -6
  50. codex_autorunner/core/prompt.py +0 -80
  51. codex_autorunner/core/prompts.py +56 -172
  52. codex_autorunner/core/redaction.py +0 -4
  53. codex_autorunner/core/review_context.py +11 -9
  54. codex_autorunner/core/runner_controller.py +35 -33
  55. codex_autorunner/core/runner_state.py +147 -0
  56. codex_autorunner/core/runtime.py +829 -0
  57. codex_autorunner/core/sqlite_utils.py +13 -4
  58. codex_autorunner/core/state.py +7 -10
  59. codex_autorunner/core/state_roots.py +62 -0
  60. codex_autorunner/core/supervisor_protocol.py +15 -0
  61. codex_autorunner/core/templates/__init__.py +39 -0
  62. codex_autorunner/core/templates/git_mirror.py +234 -0
  63. codex_autorunner/core/templates/provenance.py +56 -0
  64. codex_autorunner/core/templates/scan_cache.py +120 -0
  65. codex_autorunner/core/text_delta_coalescer.py +54 -0
  66. codex_autorunner/core/ticket_linter_cli.py +218 -0
  67. codex_autorunner/core/ticket_manager_cli.py +494 -0
  68. codex_autorunner/core/time_utils.py +11 -0
  69. codex_autorunner/core/types.py +18 -0
  70. codex_autorunner/core/update.py +4 -5
  71. codex_autorunner/core/update_paths.py +28 -0
  72. codex_autorunner/core/usage.py +164 -12
  73. codex_autorunner/core/utils.py +125 -15
  74. codex_autorunner/flows/review/__init__.py +17 -0
  75. codex_autorunner/{core/review.py → flows/review/service.py} +37 -34
  76. codex_autorunner/flows/ticket_flow/definition.py +52 -3
  77. codex_autorunner/integrations/agents/__init__.py +11 -19
  78. codex_autorunner/integrations/agents/backend_orchestrator.py +302 -0
  79. codex_autorunner/integrations/agents/codex_adapter.py +90 -0
  80. codex_autorunner/integrations/agents/codex_backend.py +177 -25
  81. codex_autorunner/integrations/agents/opencode_adapter.py +108 -0
  82. codex_autorunner/integrations/agents/opencode_backend.py +305 -32
  83. codex_autorunner/integrations/agents/runner.py +86 -0
  84. codex_autorunner/integrations/agents/wiring.py +279 -0
  85. codex_autorunner/integrations/app_server/client.py +7 -60
  86. codex_autorunner/integrations/app_server/env.py +2 -107
  87. codex_autorunner/{core/app_server_events.py → integrations/app_server/event_buffer.py} +15 -8
  88. codex_autorunner/integrations/telegram/adapter.py +65 -0
  89. codex_autorunner/integrations/telegram/config.py +46 -0
  90. codex_autorunner/integrations/telegram/constants.py +1 -1
  91. codex_autorunner/integrations/telegram/doctor.py +228 -6
  92. codex_autorunner/integrations/telegram/handlers/callbacks.py +7 -0
  93. codex_autorunner/integrations/telegram/handlers/commands/execution.py +236 -74
  94. codex_autorunner/integrations/telegram/handlers/commands/files.py +314 -75
  95. codex_autorunner/integrations/telegram/handlers/commands/flows.py +1496 -71
  96. codex_autorunner/integrations/telegram/handlers/commands/workspace.py +498 -37
  97. codex_autorunner/integrations/telegram/handlers/commands_runtime.py +206 -48
  98. codex_autorunner/integrations/telegram/handlers/commands_spec.py +20 -3
  99. codex_autorunner/integrations/telegram/handlers/messages.py +27 -1
  100. codex_autorunner/integrations/telegram/handlers/selections.py +61 -1
  101. codex_autorunner/integrations/telegram/helpers.py +22 -1
  102. codex_autorunner/integrations/telegram/runtime.py +9 -4
  103. codex_autorunner/integrations/telegram/service.py +45 -10
  104. codex_autorunner/integrations/telegram/state.py +38 -0
  105. codex_autorunner/integrations/telegram/ticket_flow_bridge.py +338 -43
  106. codex_autorunner/integrations/telegram/transport.py +13 -4
  107. codex_autorunner/integrations/templates/__init__.py +27 -0
  108. codex_autorunner/integrations/templates/scan_agent.py +312 -0
  109. codex_autorunner/routes/__init__.py +37 -76
  110. codex_autorunner/routes/agents.py +2 -137
  111. codex_autorunner/routes/analytics.py +2 -238
  112. codex_autorunner/routes/app_server.py +2 -131
  113. codex_autorunner/routes/base.py +2 -596
  114. codex_autorunner/routes/file_chat.py +4 -833
  115. codex_autorunner/routes/flows.py +4 -977
  116. codex_autorunner/routes/messages.py +4 -456
  117. codex_autorunner/routes/repos.py +2 -196
  118. codex_autorunner/routes/review.py +2 -147
  119. codex_autorunner/routes/sessions.py +2 -175
  120. codex_autorunner/routes/settings.py +2 -168
  121. codex_autorunner/routes/shared.py +2 -275
  122. codex_autorunner/routes/system.py +4 -193
  123. codex_autorunner/routes/usage.py +2 -86
  124. codex_autorunner/routes/voice.py +2 -119
  125. codex_autorunner/routes/workspace.py +2 -270
  126. codex_autorunner/server.py +4 -4
  127. codex_autorunner/static/agentControls.js +61 -16
  128. codex_autorunner/static/app.js +126 -14
  129. codex_autorunner/static/archive.js +826 -0
  130. codex_autorunner/static/archiveApi.js +37 -0
  131. codex_autorunner/static/autoRefresh.js +7 -7
  132. codex_autorunner/static/chatUploads.js +137 -0
  133. codex_autorunner/static/dashboard.js +224 -171
  134. codex_autorunner/static/docChatCore.js +185 -13
  135. codex_autorunner/static/fileChat.js +68 -40
  136. codex_autorunner/static/fileboxUi.js +159 -0
  137. codex_autorunner/static/hub.js +114 -131
  138. codex_autorunner/static/index.html +375 -49
  139. codex_autorunner/static/messages.js +568 -87
  140. codex_autorunner/static/notifications.js +255 -0
  141. codex_autorunner/static/pma.js +1167 -0
  142. codex_autorunner/static/preserve.js +17 -0
  143. codex_autorunner/static/settings.js +128 -6
  144. codex_autorunner/static/smartRefresh.js +52 -0
  145. codex_autorunner/static/streamUtils.js +57 -0
  146. codex_autorunner/static/styles.css +9798 -6143
  147. codex_autorunner/static/tabs.js +152 -11
  148. codex_autorunner/static/templateReposSettings.js +225 -0
  149. codex_autorunner/static/terminal.js +18 -0
  150. codex_autorunner/static/ticketChatActions.js +165 -3
  151. codex_autorunner/static/ticketChatStream.js +17 -119
  152. codex_autorunner/static/ticketEditor.js +137 -15
  153. codex_autorunner/static/ticketTemplates.js +798 -0
  154. codex_autorunner/static/tickets.js +821 -98
  155. codex_autorunner/static/turnEvents.js +27 -0
  156. codex_autorunner/static/turnResume.js +33 -0
  157. codex_autorunner/static/utils.js +39 -0
  158. codex_autorunner/static/workspace.js +389 -82
  159. codex_autorunner/static/workspaceFileBrowser.js +15 -13
  160. codex_autorunner/surfaces/__init__.py +5 -0
  161. codex_autorunner/surfaces/cli/__init__.py +6 -0
  162. codex_autorunner/surfaces/cli/cli.py +2534 -0
  163. codex_autorunner/surfaces/cli/codex_cli.py +20 -0
  164. codex_autorunner/surfaces/cli/pma_cli.py +817 -0
  165. codex_autorunner/surfaces/telegram/__init__.py +3 -0
  166. codex_autorunner/surfaces/web/__init__.py +1 -0
  167. codex_autorunner/surfaces/web/app.py +2223 -0
  168. codex_autorunner/surfaces/web/hub_jobs.py +192 -0
  169. codex_autorunner/surfaces/web/middleware.py +587 -0
  170. codex_autorunner/surfaces/web/pty_session.py +370 -0
  171. codex_autorunner/surfaces/web/review.py +6 -0
  172. codex_autorunner/surfaces/web/routes/__init__.py +82 -0
  173. codex_autorunner/surfaces/web/routes/agents.py +138 -0
  174. codex_autorunner/surfaces/web/routes/analytics.py +284 -0
  175. codex_autorunner/surfaces/web/routes/app_server.py +132 -0
  176. codex_autorunner/surfaces/web/routes/archive.py +357 -0
  177. codex_autorunner/surfaces/web/routes/base.py +615 -0
  178. codex_autorunner/surfaces/web/routes/file_chat.py +1117 -0
  179. codex_autorunner/surfaces/web/routes/filebox.py +227 -0
  180. codex_autorunner/surfaces/web/routes/flows.py +1354 -0
  181. codex_autorunner/surfaces/web/routes/messages.py +490 -0
  182. codex_autorunner/surfaces/web/routes/pma.py +1652 -0
  183. codex_autorunner/surfaces/web/routes/repos.py +197 -0
  184. codex_autorunner/surfaces/web/routes/review.py +148 -0
  185. codex_autorunner/surfaces/web/routes/sessions.py +176 -0
  186. codex_autorunner/surfaces/web/routes/settings.py +169 -0
  187. codex_autorunner/surfaces/web/routes/shared.py +277 -0
  188. codex_autorunner/surfaces/web/routes/system.py +196 -0
  189. codex_autorunner/surfaces/web/routes/templates.py +634 -0
  190. codex_autorunner/surfaces/web/routes/usage.py +89 -0
  191. codex_autorunner/surfaces/web/routes/voice.py +120 -0
  192. codex_autorunner/surfaces/web/routes/workspace.py +271 -0
  193. codex_autorunner/surfaces/web/runner_manager.py +25 -0
  194. codex_autorunner/surfaces/web/schemas.py +469 -0
  195. codex_autorunner/surfaces/web/static_assets.py +490 -0
  196. codex_autorunner/surfaces/web/static_refresh.py +86 -0
  197. codex_autorunner/surfaces/web/terminal_sessions.py +78 -0
  198. codex_autorunner/tickets/__init__.py +8 -1
  199. codex_autorunner/tickets/agent_pool.py +53 -4
  200. codex_autorunner/tickets/files.py +37 -16
  201. codex_autorunner/tickets/lint.py +50 -0
  202. codex_autorunner/tickets/models.py +6 -1
  203. codex_autorunner/tickets/outbox.py +50 -2
  204. codex_autorunner/tickets/runner.py +396 -57
  205. codex_autorunner/web/__init__.py +5 -1
  206. codex_autorunner/web/app.py +2 -1949
  207. codex_autorunner/web/hub_jobs.py +2 -191
  208. codex_autorunner/web/middleware.py +2 -586
  209. codex_autorunner/web/pty_session.py +2 -369
  210. codex_autorunner/web/runner_manager.py +2 -24
  211. codex_autorunner/web/schemas.py +2 -376
  212. codex_autorunner/web/static_assets.py +4 -441
  213. codex_autorunner/web/static_refresh.py +2 -85
  214. codex_autorunner/web/terminal_sessions.py +2 -77
  215. codex_autorunner/workspace/paths.py +49 -33
  216. codex_autorunner-1.2.0.dist-info/METADATA +150 -0
  217. codex_autorunner-1.2.0.dist-info/RECORD +339 -0
  218. codex_autorunner/core/adapter_utils.py +0 -21
  219. codex_autorunner/core/engine.py +0 -2653
  220. codex_autorunner/core/static_assets.py +0 -55
  221. codex_autorunner-1.0.0.dist-info/METADATA +0 -246
  222. codex_autorunner-1.0.0.dist-info/RECORD +0 -251
  223. /codex_autorunner/{routes → surfaces/web/routes}/terminal_images.py +0 -0
  224. {codex_autorunner-1.0.0.dist-info → codex_autorunner-1.2.0.dist-info}/WHEEL +0 -0
  225. {codex_autorunner-1.0.0.dist-info → codex_autorunner-1.2.0.dist-info}/entry_points.txt +0 -0
  226. {codex_autorunner-1.0.0.dist-info → codex_autorunner-1.2.0.dist-info}/licenses/LICENSE +0 -0
  227. {codex_autorunner-1.0.0.dist-info → codex_autorunner-1.2.0.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,14 @@
1
+ import sys
1
2
  from pathlib import Path
3
+ from typing import Optional
2
4
 
3
5
  import yaml
4
6
 
5
- from .core.about_car import ensure_about_car_file_for_repo
7
+ from .core.about_car import (
8
+ ensure_about_car_file_for_repo,
9
+ ensure_ticket_flow_quickstart_file_for_repo,
10
+ ensure_tickets_agents_file_for_repo,
11
+ )
6
12
  from .core.config import (
7
13
  CONFIG_FILENAME,
8
14
  DEFAULT_HUB_CONFIG,
@@ -11,19 +17,24 @@ from .core.config import (
11
17
  resolve_hub_config_data,
12
18
  )
13
19
  from .core.state import RunnerState, save_state
20
+ from .core.ticket_linter_cli import ensure_ticket_linter
21
+ from .core.ticket_manager_cli import ensure_ticket_manager
14
22
  from .core.utils import atomic_write
15
23
  from .manifest import load_manifest
16
24
 
17
25
  GITIGNORE_CONTENT = "*"
18
26
  GENERATED_CONFIG_HEADER = "# GENERATED by CAR - DO NOT EDIT\n"
27
+ HUB_CAR_SHIM_MARKER = "# CAR:HUB_CLI_SHIM"
28
+ HUB_CAR_SHIM_REL_PATH = Path(".codex-autorunner/bin/car")
29
+ HUB_CAR_SHIM_ROOT_BASENAME = "car"
19
30
 
20
31
 
21
32
  def sample_todo() -> str:
22
- return """# TODO\n\n- [ ] Replace this item with your first task\n- [ ] Add another task\n- [x] Example completed item\n"""
33
+ return ""
23
34
 
24
35
 
25
36
  def sample_spec() -> str:
26
- return """# Spec\n\n## Context\n- Add project background and goals here.\n\n## Requirements\n- Requirement 1\n- Requirement 2\n\n## Non-goals\n- Out of scope items\n"""
37
+ return ""
27
38
 
28
39
 
29
40
  def _seed_doc(path: Path, force: bool, content: str) -> None:
@@ -67,6 +78,58 @@ def write_hub_config(hub_root: Path, force: bool = False) -> Path:
67
78
  return config_path
68
79
 
69
80
 
81
+ def _build_hub_car_shim(python_executable: str) -> str:
82
+ content = (
83
+ "#!/bin/sh\n"
84
+ f"{HUB_CAR_SHIM_MARKER}\n"
85
+ "# Generated by CAR. Safe to overwrite.\n"
86
+ f'exec "{python_executable}" -m codex_autorunner.cli "$@"\n'
87
+ )
88
+ return content
89
+
90
+
91
+ def _should_refresh_shim(path: Path, content: str, *, force: bool) -> bool:
92
+ if force or not path.exists():
93
+ return True
94
+ try:
95
+ existing = path.read_text(encoding="utf-8")
96
+ except OSError:
97
+ return True
98
+ if HUB_CAR_SHIM_MARKER not in existing:
99
+ return False
100
+ return existing != content
101
+
102
+
103
+ def ensure_hub_car_shim(
104
+ hub_root: Path,
105
+ *,
106
+ python_executable: Optional[str] = None,
107
+ force: bool = False,
108
+ ) -> list[Path]:
109
+ """Ensure a hub-local car shim points at the current runtime."""
110
+ python_executable = python_executable or sys.executable
111
+ content = _build_hub_car_shim(python_executable)
112
+ if content and not content.endswith("\n"):
113
+ content += "\n"
114
+ targets = [
115
+ hub_root / HUB_CAR_SHIM_ROOT_BASENAME,
116
+ hub_root / HUB_CAR_SHIM_REL_PATH,
117
+ ]
118
+ written: list[Path] = []
119
+ for path in targets:
120
+ if not _should_refresh_shim(path, content, force=force):
121
+ continue
122
+ path.parent.mkdir(parents=True, exist_ok=True)
123
+ path.write_text(content, encoding="utf-8")
124
+ try:
125
+ mode = path.stat().st_mode
126
+ path.chmod(mode | 0o111)
127
+ except OSError:
128
+ pass
129
+ written.append(path)
130
+ return written
131
+
132
+
70
133
  def seed_repo_files(
71
134
  repo_root: Path, force: bool = False, git_required: bool = True
72
135
  ) -> None:
@@ -102,7 +165,7 @@ def seed_repo_files(
102
165
  workspace_dir.mkdir(parents=True, exist_ok=True)
103
166
 
104
167
  _seed_doc(workspace_dir / "active_context.md", force, sample_todo())
105
- _seed_doc(workspace_dir / "decisions.md", force, "# Decisions\n\n")
168
+ _seed_doc(workspace_dir / "decisions.md", force, "")
106
169
  _seed_doc(workspace_dir / "spec.md", force, sample_spec())
107
170
 
108
171
  # Seed an always-available briefing doc for interactive Codex sessions.
@@ -115,6 +178,21 @@ def seed_repo_files(
115
178
  },
116
179
  force=force,
117
180
  )
181
+ ensure_ticket_flow_quickstart_file_for_repo(repo_root, force=force)
182
+ ensure_tickets_agents_file_for_repo(repo_root, force=force)
183
+ ensure_ticket_linter(repo_root, force=force)
184
+ ensure_ticket_manager(repo_root, force=force)
185
+
186
+
187
+ def ensure_pma_docs(hub_root: Path, force: bool = False) -> None:
188
+ ca_dir = hub_root / ".codex-autorunner"
189
+ pma_dir = ca_dir / "pma"
190
+ pma_dir.mkdir(parents=True, exist_ok=True)
191
+ _seed_doc(pma_dir / "prompt.md", force, pma_prompt_content())
192
+ _seed_doc(pma_dir / "ABOUT_CAR.md", force, pma_about_content())
193
+ _seed_doc(pma_dir / "AGENTS.md", force, pma_agents_content())
194
+ _seed_doc(pma_dir / "active_context.md", force, pma_active_context_content())
195
+ _seed_doc(pma_dir / "context_log.md", force, pma_context_log_content())
118
196
 
119
197
 
120
198
  def seed_hub_files(hub_root: Path, force: bool = False) -> None:
@@ -130,6 +208,9 @@ def seed_hub_files(hub_root: Path, force: bool = False) -> None:
130
208
 
131
209
  write_hub_config(hub_root, force=force)
132
210
 
211
+ ensure_pma_docs(hub_root, force=force)
212
+ ensure_hub_car_shim(hub_root, force=force)
213
+
133
214
  manifest_path = hub_root / DEFAULT_HUB_CONFIG["hub"]["manifest"]
134
215
  load_manifest(manifest_path, hub_root)
135
216
 
@@ -139,3 +220,144 @@ def seed_hub_files(hub_root: Path, force: bool = False) -> None:
139
220
  hub_state_path,
140
221
  '{\n "last_scan_at": null,\n "repos": []\n}\n',
141
222
  )
223
+
224
+
225
+ def pma_prompt_content() -> str:
226
+ return """# Project Management Agent (PMA)
227
+
228
+ You are the hub-level Project Management Agent (PMA), the user's primary interface for coordinating work across repos.
229
+
230
+ ## Role
231
+
232
+ You are an **abstraction layer, not an executor**. Coordinate tickets and flows across multiple repos by delegating to repo agents.
233
+
234
+ ## Guidance
235
+
236
+ - Use CAR-native artifacts (tickets, ticket_flow, dispatch, PMA inbox/outbox).
237
+ - Ask questions when requirements are ambiguous; keep updates concise.
238
+ - Treat this prompt as code: keep it short and stable.
239
+ - See `.codex-autorunner/pma/ABOUT_CAR.md` for operational how-to.
240
+
241
+ ## Worktrees (hub-managed)
242
+
243
+ - Prefer hub-owned worktrees:
244
+ - Hub UI: “New Worktree”
245
+ - CLI: `car hub worktree create <base_repo_id> <branch> [--start-point <ref>]`
246
+ - If a worktree was created manually (e.g. `git worktree add`), it MUST be registered:
247
+ - `car hub scan --path <hub_root>`
248
+ - Never copy `.codex-autorunner/` between worktrees. Each worktree has its own CAR state/docs.
249
+
250
+ ## PMA durable workspace
251
+
252
+ Prefer writing durable guidance and recurring best-practices to `.codex-autorunner/pma/AGENTS.md`.
253
+ Keep short-lived working context in `.codex-autorunner/pma/active_context.md` and prune it when it grows.
254
+ When pruning, append the prior context to `.codex-autorunner/pma/context_log.md` with a timestamp.
255
+ """
256
+
257
+
258
+ def pma_notes_content() -> str:
259
+ return """# PMA Operations Guide
260
+
261
+ ## Tickets (create/modify)
262
+
263
+ - Tickets live per repo at `<repo>/.codex-autorunner/tickets/`.
264
+ - Create or edit `TICKET-###*.md` files directly; keep diffs small and single-purpose.
265
+ - Set `done: true` in the ticket frontmatter only when the ticket is complete.
266
+
267
+ ## Ticket flow (start/resume)
268
+
269
+ - Bootstrap (creates TICKET-001 if missing):
270
+ `car flow ticket_flow bootstrap --repo <path>`
271
+ - Start/resume:
272
+ `car flow ticket_flow start --repo <path>`
273
+ `car flow ticket_flow resume --repo <path> [--run-id <uuid>]`
274
+ - Status/stop:
275
+ `car flow ticket_flow status --repo <path> [--run-id <uuid>]`
276
+ `car flow ticket_flow stop --repo <path> [--run-id <uuid>]`
277
+ - See `<repo>/.codex-autorunner/TICKET_FLOW_QUICKSTART.md` for CLI entrypoints + gotchas.
278
+
279
+ ## Worktrees 101 (Hub-managed)
280
+
281
+ Canonical worktree creation:
282
+ - Hub UI: “New Worktree”
283
+ - CLI (from hub root):
284
+ `car hub worktree create <base_repo_id> <branch> [--start-point <ref>]`
285
+
286
+ Registering a manually-created worktree:
287
+ - If you used `git worktree add`, run:
288
+ `car hub scan --path <hub_root>`
289
+ - Worktrees should live under the hub’s configured worktrees root and be shallow (depth=1) discoverable.
290
+
291
+ Naming / grouping:
292
+ - Prefer worktree directory names like:
293
+ `<base_repo_id>--<branch>`
294
+ - This enables `worktree_of` inference during scan and grouping in the hub UI.
295
+
296
+ Do NOT copy `.codex-autorunner/` between worktrees:
297
+ - Each worktree is a full repo with its own `.codex-autorunner/` state/docs.
298
+ - Copying can introduce stale locks and confusing run metadata.
299
+
300
+ ## Dispatch pauses (handle)
301
+
302
+ - Paused runs appear in the hub inbox snapshot with `repo_id`, `run_id`, and `open_url`.
303
+ - Read the latest dispatch, respond to the user, then resume the run.
304
+ - Dispatch history lives under:
305
+ `<repo>/.codex-autorunner/runs/<run_id>/dispatch_history/####/DISPATCH.md`
306
+
307
+ ## PMA file handoff
308
+
309
+ - User uploads arrive in `.codex-autorunner/pma/inbox/`.
310
+ - Send user-facing files by writing to `.codex-autorunner/pma/outbox/`.
311
+ """
312
+
313
+
314
+ def pma_about_content() -> str:
315
+ return pma_notes_content()
316
+
317
+
318
+ def pma_agents_content() -> str:
319
+ return """# PMA AGENTS (durable guidance + defaults)
320
+
321
+ This document is jointly maintained by the user and PMA.
322
+
323
+ ## What belongs here
324
+
325
+ - Durable best-practices you want PMA to apply repeatedly ("defaults").
326
+ - Stable preferences (how to structure tickets, review habits, PR conventions).
327
+ - Template shortcuts / references that PMA should re-use.
328
+
329
+ ## What does NOT belong here
330
+
331
+ - Temporary work-in-progress details (put those in `active_context.md`).
332
+ - Long transcripts.
333
+
334
+ ## Template shortcuts (optional)
335
+
336
+ - Add references to frequently used ticket templates here (repo/path/ref) and when to apply them.
337
+
338
+ ## Defaults (examples)
339
+
340
+ - After implementation work, add a final review ticket, then a ticket to open a PR.
341
+ """
342
+
343
+
344
+ def pma_active_context_content() -> str:
345
+ return """# PMA active context (short-lived)
346
+
347
+ Use this file for the current working set: active projects, open questions, links, and immediate next steps.
348
+
349
+ Pruning guidance:
350
+ - Keep this file compact (prefer bullet points).
351
+ - When it grows too large, summarize older items and move durable guidance to `AGENTS.md`.
352
+ - Before a major prune, append a timestamped snapshot to `context_log.md`.
353
+ """
354
+
355
+
356
+ def pma_context_log_content() -> str:
357
+ return """# PMA context log (append-only)
358
+
359
+ This file is an append-only history of past `active_context.md` snapshots.
360
+
361
+ - Add a new section with an ISO timestamp when you perform a major prune.
362
+ - Keep entries concise; the goal is searchability and historical recall.
363
+ """