@blxzer/cursor-trellis 0.1.0 → 0.1.2

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 (285) hide show
  1. package/README.md +124 -5
  2. package/README.zh-CN.md +170 -0
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +1 -33
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/commands/init.d.ts +0 -13
  7. package/dist/commands/init.d.ts.map +1 -1
  8. package/dist/commands/init.js +7 -14
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/uninstall.d.ts.map +1 -1
  11. package/dist/commands/uninstall.js +3 -32
  12. package/dist/commands/uninstall.js.map +1 -1
  13. package/dist/commands/update.d.ts.map +1 -1
  14. package/dist/commands/update.js +7 -84
  15. package/dist/commands/update.js.map +1 -1
  16. package/dist/configurators/index.d.ts +7 -8
  17. package/dist/configurators/index.d.ts.map +1 -1
  18. package/dist/configurators/index.js +11 -236
  19. package/dist/configurators/index.js.map +1 -1
  20. package/dist/configurators/workflow.d.ts.map +1 -1
  21. package/dist/configurators/workflow.js +5 -1
  22. package/dist/configurators/workflow.js.map +1 -1
  23. package/dist/migrations/manifests/0.1.1.json +9 -0
  24. package/dist/migrations/manifests/0.1.2.json +9 -0
  25. package/dist/templates/common/bundled-skills/smart-search-cli/SKILL.md +3 -3
  26. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +4 -2
  27. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +8 -15
  28. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +7 -7
  29. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +18 -21
  30. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +2 -2
  31. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +10 -7
  32. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +4 -4
  33. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +20 -31
  34. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +20 -31
  35. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +24 -40
  36. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +28 -59
  37. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +12 -28
  38. package/dist/templates/common/bundled-skills/trellis-skill-creator/references/trellis-skill-locations.md +2 -2
  39. package/dist/templates/cursor/hooks.json +6 -0
  40. package/dist/templates/cursor/rules/retrieval-routing.mdc +57 -0
  41. package/dist/templates/extract.d.ts +0 -14
  42. package/dist/templates/extract.d.ts.map +1 -1
  43. package/dist/templates/extract.js +0 -34
  44. package/dist/templates/extract.js.map +1 -1
  45. package/dist/templates/markdown/agents.md +2 -6
  46. package/dist/templates/markdown/index.d.ts +1 -0
  47. package/dist/templates/markdown/index.d.ts.map +1 -1
  48. package/dist/templates/markdown/index.js +1 -0
  49. package/dist/templates/markdown/index.js.map +1 -1
  50. package/dist/templates/markdown/prompts/run-semantic-slice-12.md.txt +41 -0
  51. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +14 -14
  52. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +8 -20
  53. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +15 -14
  54. package/dist/templates/markdown/spec/guides/cursor-context-injection-guide.md.txt +4 -2
  55. package/dist/templates/markdown/spec/guides/cursor-semantic-compliance.md.txt +49 -0
  56. package/dist/templates/markdown/spec/guides/cursor-subagent-policy.md.txt +18 -5
  57. package/dist/templates/markdown/spec/guides/retrieval-daily-guide.md.txt +68 -20
  58. package/dist/templates/shared-hooks/index.d.ts +1 -1
  59. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  60. package/dist/templates/shared-hooks/index.js +1 -0
  61. package/dist/templates/shared-hooks/index.js.map +1 -1
  62. package/dist/templates/shared-hooks/inject-retrieval-plan.py +163 -0
  63. package/dist/templates/shared-hooks/inject-subagent-context.py +31 -567
  64. package/dist/templates/shared-hooks/research-end-retrieval-pack.py +2 -11
  65. package/dist/templates/trellis/index.d.ts +12 -0
  66. package/dist/templates/trellis/index.d.ts.map +1 -1
  67. package/dist/templates/trellis/index.js +24 -0
  68. package/dist/templates/trellis/index.js.map +1 -1
  69. package/dist/templates/trellis/scripts/aggregate_retrieval_telemetry.py +342 -0
  70. package/dist/templates/trellis/scripts/batch_plan_envelope.py +105 -0
  71. package/dist/templates/trellis/scripts/codegraph_session_smoke.py +76 -0
  72. package/dist/templates/trellis/scripts/common/active_task.py +116 -147
  73. package/dist/templates/trellis/scripts/common/cli_adapter.py +34 -710
  74. package/dist/templates/trellis/scripts/common/codebase_retrieval_router.py +49 -106
  75. package/dist/templates/trellis/scripts/common/git_context.py +17 -2
  76. package/dist/templates/trellis/scripts/common/project_file_stats.py +91 -0
  77. package/dist/templates/trellis/scripts/common/retrieval_adapter_metadata.py +9 -11
  78. package/dist/templates/trellis/scripts/common/retrieval_agent_instructions.py +313 -0
  79. package/dist/templates/trellis/scripts/common/retrieval_pack.py +0 -6
  80. package/dist/templates/trellis/scripts/common/retrieval_pack_context.py +0 -4
  81. package/dist/templates/trellis/scripts/common/retrieval_plan_gate.py +76 -0
  82. package/dist/templates/trellis/scripts/common/retrieval_result_ranking.py +253 -0
  83. package/dist/templates/trellis/scripts/common/retrieval_tool_classification.py +157 -0
  84. package/dist/templates/trellis/scripts/common/semantic_plan_gate.py +52 -0
  85. package/dist/templates/trellis/scripts/common/subagent_dispatch.py +527 -0
  86. package/dist/templates/trellis/scripts/common/task_store.py +32 -0
  87. package/dist/templates/trellis/scripts/common/workflow_phase.py +3 -24
  88. package/dist/templates/trellis/scripts/rank_retrieval_candidates.py +80 -0
  89. package/dist/templates/trellis/scripts/route_codebase_retrieval.py +38 -11
  90. package/dist/templates/trellis/scripts/score_evidence.py +112 -0
  91. package/dist/templates/trellis/scripts/task.py +26 -0
  92. package/dist/templates/trellis/workflow.md +844 -960
  93. package/dist/types/ai-tools.d.ts +13 -16
  94. package/dist/types/ai-tools.d.ts.map +1 -1
  95. package/dist/types/ai-tools.js +5 -238
  96. package/dist/types/ai-tools.js.map +1 -1
  97. package/dist/utils/codebase-retrieval-router.d.ts +1 -8
  98. package/dist/utils/codebase-retrieval-router.d.ts.map +1 -1
  99. package/dist/utils/codebase-retrieval-router.js +39 -180
  100. package/dist/utils/codebase-retrieval-router.js.map +1 -1
  101. package/dist/utils/project-capabilities.d.ts.map +1 -1
  102. package/dist/utils/project-capabilities.js +10 -24
  103. package/dist/utils/project-capabilities.js.map +1 -1
  104. package/dist/utils/retrieval-agent-instructions.d.ts +14 -0
  105. package/dist/utils/retrieval-agent-instructions.d.ts.map +1 -0
  106. package/dist/utils/retrieval-agent-instructions.js +221 -0
  107. package/dist/utils/retrieval-agent-instructions.js.map +1 -0
  108. package/dist/utils/retrieval-execution-telemetry.d.ts +43 -85
  109. package/dist/utils/retrieval-execution-telemetry.d.ts.map +1 -1
  110. package/dist/utils/retrieval-execution-telemetry.js +289 -22
  111. package/dist/utils/retrieval-execution-telemetry.js.map +1 -1
  112. package/dist/utils/retrieval-result-ranking.js +1 -1
  113. package/dist/utils/retrieval-result-ranking.js.map +1 -1
  114. package/dist/utils/retrieval-tool-classification.d.ts +32 -0
  115. package/dist/utils/retrieval-tool-classification.d.ts.map +1 -0
  116. package/dist/utils/retrieval-tool-classification.js +113 -0
  117. package/dist/utils/retrieval-tool-classification.js.map +1 -0
  118. package/dist/utils/uninstall-scrubbers.d.ts +0 -36
  119. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  120. package/dist/utils/uninstall-scrubbers.js +0 -184
  121. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  122. package/package.json +4 -2
  123. package/dist/commands/mem.d.ts +0 -30
  124. package/dist/commands/mem.d.ts.map +0 -1
  125. package/dist/commands/mem.js +0 -424
  126. package/dist/commands/mem.js.map +0 -1
  127. package/dist/configurators/antigravity.d.ts +0 -7
  128. package/dist/configurators/antigravity.d.ts.map +0 -1
  129. package/dist/configurators/antigravity.js +0 -19
  130. package/dist/configurators/antigravity.js.map +0 -1
  131. package/dist/configurators/claude.d.ts +0 -9
  132. package/dist/configurators/claude.d.ts.map +0 -1
  133. package/dist/configurators/claude.js +0 -72
  134. package/dist/configurators/claude.js.map +0 -1
  135. package/dist/configurators/codebuddy.d.ts +0 -10
  136. package/dist/configurators/codebuddy.d.ts.map +0 -1
  137. package/dist/configurators/codebuddy.js +0 -30
  138. package/dist/configurators/codebuddy.js.map +0 -1
  139. package/dist/configurators/codex.d.ts +0 -8
  140. package/dist/configurators/codex.d.ts.map +0 -1
  141. package/dist/configurators/codex.js +0 -87
  142. package/dist/configurators/codex.js.map +0 -1
  143. package/dist/configurators/copilot.d.ts +0 -10
  144. package/dist/configurators/copilot.d.ts.map +0 -1
  145. package/dist/configurators/copilot.js +0 -51
  146. package/dist/configurators/copilot.js.map +0 -1
  147. package/dist/configurators/droid.d.ts +0 -10
  148. package/dist/configurators/droid.d.ts.map +0 -1
  149. package/dist/configurators/droid.js +0 -30
  150. package/dist/configurators/droid.js.map +0 -1
  151. package/dist/configurators/gemini.d.ts +0 -16
  152. package/dist/configurators/gemini.d.ts.map +0 -1
  153. package/dist/configurators/gemini.js +0 -38
  154. package/dist/configurators/gemini.js.map +0 -1
  155. package/dist/configurators/kilo.d.ts +0 -7
  156. package/dist/configurators/kilo.d.ts.map +0 -1
  157. package/dist/configurators/kilo.js +0 -19
  158. package/dist/configurators/kilo.js.map +0 -1
  159. package/dist/configurators/kiro.d.ts +0 -8
  160. package/dist/configurators/kiro.d.ts.map +0 -1
  161. package/dist/configurators/kiro.js +0 -24
  162. package/dist/configurators/kiro.js.map +0 -1
  163. package/dist/configurators/opencode.d.ts +0 -14
  164. package/dist/configurators/opencode.d.ts.map +0 -1
  165. package/dist/configurators/opencode.js +0 -96
  166. package/dist/configurators/opencode.js.map +0 -1
  167. package/dist/configurators/pi.d.ts +0 -3
  168. package/dist/configurators/pi.d.ts.map +0 -1
  169. package/dist/configurators/pi.js +0 -45
  170. package/dist/configurators/pi.js.map +0 -1
  171. package/dist/configurators/qoder.d.ts +0 -11
  172. package/dist/configurators/qoder.d.ts.map +0 -1
  173. package/dist/configurators/qoder.js +0 -31
  174. package/dist/configurators/qoder.js.map +0 -1
  175. package/dist/configurators/windsurf.d.ts +0 -7
  176. package/dist/configurators/windsurf.d.ts.map +0 -1
  177. package/dist/configurators/windsurf.js +0 -19
  178. package/dist/configurators/windsurf.js.map +0 -1
  179. package/dist/templates/claude/agents/trellis-check.md +0 -124
  180. package/dist/templates/claude/agents/trellis-implement.md +0 -110
  181. package/dist/templates/claude/agents/trellis-research.md +0 -137
  182. package/dist/templates/claude/index.d.ts +0 -22
  183. package/dist/templates/claude/index.d.ts.map +0 -1
  184. package/dist/templates/claude/index.js +0 -46
  185. package/dist/templates/claude/index.js.map +0 -1
  186. package/dist/templates/claude/settings.json +0 -84
  187. package/dist/templates/codebuddy/agents/trellis-check.md +0 -115
  188. package/dist/templates/codebuddy/agents/trellis-implement.md +0 -110
  189. package/dist/templates/codebuddy/agents/trellis-research.md +0 -137
  190. package/dist/templates/codebuddy/index.d.ts +0 -15
  191. package/dist/templates/codebuddy/index.d.ts.map +0 -1
  192. package/dist/templates/codebuddy/index.js +0 -15
  193. package/dist/templates/codebuddy/index.js.map +0 -1
  194. package/dist/templates/codebuddy/settings.json +0 -70
  195. package/dist/templates/codex/agents/trellis-check.toml +0 -67
  196. package/dist/templates/codex/agents/trellis-implement.toml +0 -40
  197. package/dist/templates/codex/agents/trellis-research.toml +0 -73
  198. package/dist/templates/codex/config.toml +0 -28
  199. package/dist/templates/codex/hooks/session-start.py +0 -575
  200. package/dist/templates/codex/hooks.json +0 -15
  201. package/dist/templates/codex/index.d.ts +0 -39
  202. package/dist/templates/codex/index.d.ts.map +0 -1
  203. package/dist/templates/codex/index.js +0 -85
  204. package/dist/templates/codex/index.js.map +0 -1
  205. package/dist/templates/codex/skills/before-dev/SKILL.md +0 -40
  206. package/dist/templates/codex/skills/brainstorm/SKILL.md +0 -112
  207. package/dist/templates/codex/skills/break-loop/SKILL.md +0 -130
  208. package/dist/templates/codex/skills/check/SKILL.md +0 -98
  209. package/dist/templates/codex/skills/check-cross-layer/SKILL.md +0 -158
  210. package/dist/templates/codex/skills/create-command/SKILL.md +0 -101
  211. package/dist/templates/codex/skills/finish-work/SKILL.md +0 -90
  212. package/dist/templates/codex/skills/improve-ut/SKILL.md +0 -69
  213. package/dist/templates/codex/skills/integrate-skill/SKILL.md +0 -221
  214. package/dist/templates/codex/skills/onboard/SKILL.md +0 -363
  215. package/dist/templates/codex/skills/record-session/SKILL.md +0 -67
  216. package/dist/templates/codex/skills/start/SKILL.md +0 -66
  217. package/dist/templates/codex/skills/update-spec/SKILL.md +0 -335
  218. package/dist/templates/copilot/hooks/session-start.py +0 -557
  219. package/dist/templates/copilot/hooks.json +0 -19
  220. package/dist/templates/copilot/index.d.ts +0 -23
  221. package/dist/templates/copilot/index.d.ts.map +0 -1
  222. package/dist/templates/copilot/index.js +0 -54
  223. package/dist/templates/copilot/index.js.map +0 -1
  224. package/dist/templates/copilot/prompts/before-dev.prompt.md +0 -39
  225. package/dist/templates/copilot/prompts/brainstorm.prompt.md +0 -111
  226. package/dist/templates/copilot/prompts/break-loop.prompt.md +0 -129
  227. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +0 -157
  228. package/dist/templates/copilot/prompts/check.prompt.md +0 -97
  229. package/dist/templates/copilot/prompts/create-command.prompt.md +0 -116
  230. package/dist/templates/copilot/prompts/finish-work.prompt.md +0 -99
  231. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +0 -223
  232. package/dist/templates/copilot/prompts/onboard.prompt.md +0 -362
  233. package/dist/templates/copilot/prompts/parallel.prompt.md +0 -204
  234. package/dist/templates/copilot/prompts/record-session.prompt.md +0 -66
  235. package/dist/templates/copilot/prompts/start.prompt.md +0 -63
  236. package/dist/templates/copilot/prompts/update-spec.prompt.md +0 -358
  237. package/dist/templates/droid/droids/trellis-check.md +0 -107
  238. package/dist/templates/droid/droids/trellis-implement.md +0 -102
  239. package/dist/templates/droid/droids/trellis-research.md +0 -137
  240. package/dist/templates/droid/index.d.ts +0 -15
  241. package/dist/templates/droid/index.d.ts.map +0 -1
  242. package/dist/templates/droid/index.js +0 -15
  243. package/dist/templates/droid/index.js.map +0 -1
  244. package/dist/templates/droid/settings.json +0 -70
  245. package/dist/templates/gemini/agents/trellis-check.md +0 -107
  246. package/dist/templates/gemini/agents/trellis-implement.md +0 -102
  247. package/dist/templates/gemini/agents/trellis-research.md +0 -136
  248. package/dist/templates/gemini/index.d.ts +0 -13
  249. package/dist/templates/gemini/index.d.ts.map +0 -1
  250. package/dist/templates/gemini/index.js +0 -13
  251. package/dist/templates/gemini/index.js.map +0 -1
  252. package/dist/templates/gemini/settings.json +0 -28
  253. package/dist/templates/kiro/agents/trellis-check.json +0 -26
  254. package/dist/templates/kiro/agents/trellis-implement.json +0 -26
  255. package/dist/templates/kiro/agents/trellis-research.json +0 -30
  256. package/dist/templates/kiro/index.d.ts +0 -18
  257. package/dist/templates/kiro/index.d.ts.map +0 -1
  258. package/dist/templates/kiro/index.js +0 -18
  259. package/dist/templates/kiro/index.js.map +0 -1
  260. package/dist/templates/opencode/agents/trellis-check.md +0 -122
  261. package/dist/templates/opencode/agents/trellis-implement.md +0 -118
  262. package/dist/templates/opencode/agents/trellis-research.md +0 -145
  263. package/dist/templates/opencode/lib/session-utils.js +0 -667
  264. package/dist/templates/opencode/lib/trellis-context.js +0 -336
  265. package/dist/templates/opencode/package.json +0 -5
  266. package/dist/templates/opencode/plugins/inject-subagent-context.js +0 -495
  267. package/dist/templates/opencode/plugins/inject-workflow-state.js +0 -159
  268. package/dist/templates/opencode/plugins/session-start.js +0 -101
  269. package/dist/templates/pi/agents/trellis-check.md +0 -37
  270. package/dist/templates/pi/agents/trellis-implement.md +0 -42
  271. package/dist/templates/pi/agents/trellis-research.md +0 -25
  272. package/dist/templates/pi/extensions/trellis/index.ts.txt +0 -1600
  273. package/dist/templates/pi/index.d.ts +0 -5
  274. package/dist/templates/pi/index.d.ts.map +0 -1
  275. package/dist/templates/pi/index.js +0 -12
  276. package/dist/templates/pi/index.js.map +0 -1
  277. package/dist/templates/pi/settings.json +0 -12
  278. package/dist/templates/qoder/agents/trellis-check.md +0 -108
  279. package/dist/templates/qoder/agents/trellis-implement.md +0 -103
  280. package/dist/templates/qoder/agents/trellis-research.md +0 -137
  281. package/dist/templates/qoder/index.d.ts +0 -15
  282. package/dist/templates/qoder/index.d.ts.map +0 -1
  283. package/dist/templates/qoder/index.js +0 -15
  284. package/dist/templates/qoder/index.js.map +0 -1
  285. package/dist/templates/qoder/settings.json +0 -47
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env python3
2
+ """Pre-run checks for codegraph index presence (does not start MCP)."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import sys
9
+ from datetime import datetime, timezone
10
+ from pathlib import Path
11
+
12
+ from common.paths import get_repo_root
13
+
14
+
15
+ def _find_codegraph_dirs(root: Path) -> list[Path]:
16
+ found: list[Path] = []
17
+ direct = root / ".codegraph"
18
+ if direct.is_dir():
19
+ found.append(direct.resolve())
20
+ for child in sorted(root.iterdir()):
21
+ if not child.is_dir():
22
+ continue
23
+ nested = child / ".codegraph"
24
+ if nested.is_dir() and nested.resolve() not in found:
25
+ found.append(nested.resolve())
26
+ return found
27
+
28
+
29
+ def main() -> int:
30
+ parser = argparse.ArgumentParser(description="Codegraph session smoke (index on disk)")
31
+ parser.add_argument(
32
+ "--root",
33
+ type=Path,
34
+ default=None,
35
+ help="Workspace root (default: Trellis repo root)",
36
+ )
37
+ parser.add_argument("--json", action="store_true", help="Machine-readable report")
38
+ args = parser.parse_args()
39
+
40
+ root = (args.root or get_repo_root()).resolve()
41
+ indexes = _find_codegraph_dirs(root)
42
+ ok = len(indexes) > 0
43
+ payload = {
44
+ "ok": ok,
45
+ "workspace_root": str(root),
46
+ "codegraph_index_paths": [str(p) for p in indexes],
47
+ "checked_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
48
+ "mcp_note": (
49
+ "Cursor: enable codegraph MCP in project settings; this script only checks "
50
+ "on-disk .codegraph/ directories."
51
+ ),
52
+ "run_header_fields": {
53
+ "codegraph_mcp": "configured|unknown|off",
54
+ "codegraph_index_path": str(indexes[0]) if indexes else "",
55
+ "codegraph_smoke_at": "<iso8601>",
56
+ "codegraph_smoke_ok": ok,
57
+ },
58
+ }
59
+
60
+ if args.json:
61
+ print(json.dumps(payload, indent=2))
62
+ else:
63
+ if ok:
64
+ print("Codegraph smoke: PASS")
65
+ for p in indexes:
66
+ print(f" index: {p}")
67
+ else:
68
+ print("Codegraph smoke: FAIL — no .codegraph/ under workspace root", file=sys.stderr)
69
+ print(f" root: {root}", file=sys.stderr)
70
+ print(payload["mcp_note"])
71
+
72
+ return 0 if ok else 1
73
+
74
+
75
+ if __name__ == "__main__":
76
+ raise SystemExit(main())
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env python3
2
- """Session-scoped selected task resolution.
3
-
4
- The user-facing concept is a live-session "selected task". Trellis stores that
5
- pointer per AI session/window under `.trellis/.runtime/sessions/`; without a
6
- stable session key there is no selected task.
7
- """
2
+ """Session-scoped selected task resolution.
3
+
4
+ The user-facing concept is a live-session "selected task". Trellis stores that
5
+ pointer per AI session/window under `.trellis/.runtime/sessions/`; without a
6
+ stable session key there is no selected task.
7
+ """
8
8
 
9
9
  from __future__ import annotations
10
10
 
@@ -25,74 +25,43 @@ DIR_RUNTIME = ".runtime"
25
25
  DIR_SESSIONS = "sessions"
26
26
  DIR_CURSOR_SHELL = "cursor-shell"
27
27
  CURSOR_SHELL_TICKET_TTL_SECONDS = 30
28
- TASK_SESSION_COMMANDS = {"select", "selected", "exit"}
28
+ TASK_SESSION_COMMANDS = {"select", "selected", "exit"}
29
29
 
30
30
  _SESSION_KEYS = ("session_id", "sessionId", "sessionID")
31
31
  _CONVERSATION_KEYS = ("conversation_id", "conversationId", "conversationID")
32
32
  _TRANSCRIPT_KEYS = ("transcript_path", "transcriptPath", "transcript")
33
33
  _NESTED_KEYS = ("input", "properties", "event", "hook_input", "hookInput")
34
34
  _KNOWN_PLATFORMS = {
35
- "claude",
36
- "codex",
37
35
  "cursor",
38
- "opencode",
39
- "gemini",
40
- "droid",
41
- "qoder",
42
- "codebuddy",
43
- "kiro",
44
- "copilot",
45
- "pi",
46
36
  }
47
37
 
48
38
  _ENV_SESSION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
49
- ("claude", ("CLAUDE_SESSION_ID", "CLAUDE_CODE_SESSION_ID")),
50
- ("codex", ("CODEX_SESSION_ID", "CODEX_THREAD_ID")),
51
39
  ("cursor", ("CURSOR_SESSION_ID",)),
52
- ("opencode", ("OPENCODE_SESSION_ID", "OPENCODE_SESSIONID", "OPENCODE_RUN_ID")),
53
- ("gemini", ("GEMINI_SESSION_ID",)),
54
- ("droid", ("FACTORY_SESSION_ID", "DROID_SESSION_ID")),
55
- ("qoder", ("QODER_SESSION_ID",)),
56
- ("codebuddy", ("CODEBUDDY_SESSION_ID",)),
57
- ("kiro", ("KIRO_SESSION_ID",)),
58
- ("copilot", ("COPILOT_SESSION_ID", "COPILOT_SESSIONID")),
59
- ("pi", ("PI_SESSION_ID", "PI_SESSIONID")),
60
40
  )
61
41
  _ENV_CONVERSATION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
62
42
  ("cursor", ("CURSOR_CONVERSATION_ID", "CURSOR_CONVERSATIONID")),
63
43
  )
64
44
  _ENV_TRANSCRIPT_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
65
- ("claude", ("CLAUDE_TRANSCRIPT_PATH",)),
66
- ("codex", ("CODEX_TRANSCRIPT_PATH",)),
67
45
  ("cursor", ("CURSOR_TRANSCRIPT_PATH",)),
68
- ("gemini", ("GEMINI_TRANSCRIPT_PATH",)),
69
- ("droid", ("FACTORY_TRANSCRIPT_PATH", "DROID_TRANSCRIPT_PATH")),
70
- ("qoder", ("QODER_TRANSCRIPT_PATH",)),
71
- ("codebuddy", ("CODEBUDDY_TRANSCRIPT_PATH",)),
72
46
  )
73
- _ENV_PLATFORM_ALIASES = {
74
- "claude-code": "claude",
75
- "factory": "droid",
76
- "factory-ai": "droid",
77
- "github-copilot": "copilot",
78
- }
47
+ _ENV_PLATFORM_ALIASES: dict[str, str] = {}
79
48
 
80
49
 
81
50
  @dataclass(frozen=True)
82
- class SelectedTask:
83
- """Resolved selected task state."""
51
+ class SelectedTask:
52
+ """Resolved selected task state."""
84
53
 
85
54
  task_path: str | None
86
55
  source_type: str
87
56
  context_key: str | None = None
88
57
  stale: bool = False
89
58
 
90
- @property
91
- def source(self) -> str:
92
- """Human-readable source label."""
93
- if self.source_type == "session" and self.context_key:
94
- return f"session:{self.context_key}"
95
- return self.source_type
59
+ @property
60
+ def source(self) -> str:
61
+ """Human-readable source label."""
62
+ if self.source_type == "session" and self.context_key:
63
+ return f"session:{self.context_key}"
64
+ return self.source_type
96
65
 
97
66
 
98
67
  def normalize_task_ref(task_ref: str) -> str:
@@ -217,7 +186,7 @@ def _lookup_env_context_key(platform_name: str | None) -> str | None:
217
186
  Hooks pass `TRELLIS_CONTEXT_ID` to subprocesses they launch, but an AI-run
218
187
  shell command can only see session identity if the host platform exports it
219
188
  in the command environment. These names are best-effort adapters; if none
220
- are present, there is no session-scoped selected task.
189
+ are present, there is no session-scoped selected task.
221
190
  """
222
191
  env_platform_name = _env_platform_name(platform_name)
223
192
 
@@ -274,7 +243,7 @@ def _task_refs_match(left: str | None, right: str | None, repo_root: Path) -> bo
274
243
  return normalize_task_ref(left) == normalize_task_ref(right)
275
244
 
276
245
 
277
- def _pending_ticket_matches_args(ticket: dict[str, Any], repo_root: Path) -> bool:
246
+ def _pending_ticket_matches_args(ticket: dict[str, Any], repo_root: Path) -> bool:
278
247
  if Path(sys.argv[0]).name != "task.py":
279
248
  return False
280
249
  args = tuple(sys.argv[1:])
@@ -294,11 +263,11 @@ def _pending_ticket_matches_args(ticket: dict[str, Any], repo_root: Path) -> boo
294
263
  continue
295
264
  if _string_value(subcommand.get("name")) != command_name:
296
265
  continue
297
- if command_name != "select":
298
- return True
299
- task_ref = args[1] if len(args) > 1 else None
300
- if _task_refs_match(_string_value(subcommand.get("task_ref")), task_ref, repo_root):
301
- return True
266
+ if command_name != "select":
267
+ return True
268
+ task_ref = args[1] if len(args) > 1 else None
269
+ if _task_refs_match(_string_value(subcommand.get("task_ref")), task_ref, repo_root):
270
+ return True
302
271
 
303
272
  return False
304
273
 
@@ -446,44 +415,44 @@ def _canonical_task_ref(task_path: str, repo_root: Path) -> str | None:
446
415
  return str(full_path)
447
416
 
448
417
 
449
- def _selected_from_ref(
450
- task_ref: str | None,
451
- repo_root: Path,
452
- source_type: str,
453
- context_key: str | None = None,
454
- ) -> SelectedTask | None:
455
- if not task_ref:
456
- return None
457
- resolved = resolve_task_ref(task_ref, repo_root)
458
- stale = resolved is None or not resolved.is_dir()
459
- return SelectedTask(task_ref, source_type, context_key, stale)
418
+ def _selected_from_ref(
419
+ task_ref: str | None,
420
+ repo_root: Path,
421
+ source_type: str,
422
+ context_key: str | None = None,
423
+ ) -> SelectedTask | None:
424
+ if not task_ref:
425
+ return None
426
+ resolved = resolve_task_ref(task_ref, repo_root)
427
+ stale = resolved is None or not resolved.is_dir()
428
+ return SelectedTask(task_ref, source_type, context_key, stale)
460
429
 
461
430
 
462
431
  def _context_path(repo_root: Path, context_key: str) -> Path:
463
432
  return _runtime_sessions_dir(repo_root) / f"{context_key}.json"
464
433
 
465
434
 
466
- def resolve_selected_task(
467
- repo_root: Path,
468
- platform_input: dict[str, Any] | None = None,
469
- platform: str | None = None,
470
- ) -> SelectedTask:
471
- """Resolve the selected task from explicit session runtime state only.
472
-
473
- A stale session task is returned as stale. Missing context identity or a
474
- missing/empty session context returns no selected task. Trellis deliberately
475
- does not infer selection from the existence of a single runtime session file;
476
- every live session starts with no selected task until the user selects one.
477
- """
478
- context_key = resolve_context_key(platform_input, platform)
479
- if context_key:
480
- context = _read_json(_context_path(repo_root, context_key)) or {}
481
- task_ref = _string_value(context.get("selected_task"))
482
- selected = _selected_from_ref(task_ref, repo_root, "session", context_key)
483
- if selected:
484
- return selected
485
-
486
- return SelectedTask(None, "none", context_key)
435
+ def resolve_selected_task(
436
+ repo_root: Path,
437
+ platform_input: dict[str, Any] | None = None,
438
+ platform: str | None = None,
439
+ ) -> SelectedTask:
440
+ """Resolve the selected task from explicit session runtime state only.
441
+
442
+ A stale session task is returned as stale. Missing context identity or a
443
+ missing/empty session context returns no selected task. Trellis deliberately
444
+ does not infer selection from the existence of a single runtime session file;
445
+ every live session starts with no selected task until the user selects one.
446
+ """
447
+ context_key = resolve_context_key(platform_input, platform)
448
+ if context_key:
449
+ context = _read_json(_context_path(repo_root, context_key)) or {}
450
+ task_ref = _string_value(context.get("selected_task"))
451
+ selected = _selected_from_ref(task_ref, repo_root, "session", context_key)
452
+ if selected:
453
+ return selected
454
+
455
+ return SelectedTask(None, "none", context_key)
487
456
 
488
457
 
489
458
  def _utc_now() -> str:
@@ -512,17 +481,17 @@ def _context_metadata(
512
481
  return metadata
513
482
 
514
483
 
515
- def set_selected_task(
516
- task_path: str,
517
- repo_root: Path,
518
- platform_input: dict[str, Any] | None = None,
519
- platform: str | None = None,
520
- ) -> SelectedTask | None:
521
- """Set the selected task in session scope.
522
-
523
- Returns None when no context key is available; callers should surface a
524
- user-facing error that explains how to provide session identity.
525
- """
484
+ def set_selected_task(
485
+ task_path: str,
486
+ repo_root: Path,
487
+ platform_input: dict[str, Any] | None = None,
488
+ platform: str | None = None,
489
+ ) -> SelectedTask | None:
490
+ """Set the selected task in session scope.
491
+
492
+ Returns None when no context key is available; callers should surface a
493
+ user-facing error that explains how to provide session identity.
494
+ """
526
495
  canonical = _canonical_task_ref(task_path, repo_root)
527
496
  if canonical is None:
528
497
  return None
@@ -531,32 +500,32 @@ def set_selected_task(
531
500
  if not context_key:
532
501
  return None
533
502
 
534
- context_path = _context_path(repo_root, context_key)
535
- context = _read_json(context_path) or {}
536
- context.update(_context_metadata(platform_input, platform, context_key))
537
- context["selected_task"] = canonical
538
- context.pop("current_task", None)
539
- context.setdefault("current_run", None)
540
- if not _write_json(context_path, context):
541
- return None
542
- return SelectedTask(canonical, "session", context_key)
543
-
544
-
545
- def clear_selected_task(
546
- repo_root: Path,
547
- platform_input: dict[str, Any] | None = None,
548
- platform: str | None = None,
549
- ) -> SelectedTask:
550
- """Clear the selected task by deleting the current session context file."""
551
- context_key = resolve_context_key(platform_input, platform)
552
- if not context_key:
553
- return SelectedTask(None, "none")
554
-
555
- previous = resolve_selected_task(repo_root, platform_input, platform)
556
- context_path = _context_path(repo_root, context_key)
557
- if context_path.is_file():
558
- _remove_file(context_path)
559
- return previous
503
+ context_path = _context_path(repo_root, context_key)
504
+ context = _read_json(context_path) or {}
505
+ context.update(_context_metadata(platform_input, platform, context_key))
506
+ context["selected_task"] = canonical
507
+ context.pop("current_task", None)
508
+ context.setdefault("current_run", None)
509
+ if not _write_json(context_path, context):
510
+ return None
511
+ return SelectedTask(canonical, "session", context_key)
512
+
513
+
514
+ def clear_selected_task(
515
+ repo_root: Path,
516
+ platform_input: dict[str, Any] | None = None,
517
+ platform: str | None = None,
518
+ ) -> SelectedTask:
519
+ """Clear the selected task by deleting the current session context file."""
520
+ context_key = resolve_context_key(platform_input, platform)
521
+ if not context_key:
522
+ return SelectedTask(None, "none")
523
+
524
+ previous = resolve_selected_task(repo_root, platform_input, platform)
525
+ context_path = _context_path(repo_root, context_key)
526
+ if context_path.is_file():
527
+ _remove_file(context_path)
528
+ return previous
560
529
 
561
530
 
562
531
  def clear_task_from_sessions(task_path: str, repo_root: Path) -> int:
@@ -572,12 +541,12 @@ def clear_task_from_sessions(task_path: str, repo_root: Path) -> int:
572
541
 
573
542
  for session_path in sessions_dir.glob("*.json"):
574
543
  context = _read_json(session_path) or {}
575
- current = (
576
- _string_value(context.get("selected_task"))
577
- or _string_value(context.get("current_task"))
578
- )
579
- if not current:
580
- continue
544
+ current = (
545
+ _string_value(context.get("selected_task"))
546
+ or _string_value(context.get("current_task"))
547
+ )
548
+ if not current:
549
+ continue
581
550
  current_ref = _canonical_task_ref(current, repo_root) or normalize_task_ref(current)
582
551
  if current_ref != target:
583
552
  continue
@@ -587,21 +556,21 @@ def clear_task_from_sessions(task_path: str, repo_root: Path) -> int:
587
556
  return cleared
588
557
 
589
558
 
590
- def get_selected_task_source(
591
- repo_root: Path,
592
- platform_input: dict[str, Any] | None = None,
593
- platform: str | None = None,
594
- ) -> tuple[str, str | None, str | None]:
595
- """Return (`source_type`, `context_key`, `task_path`) for selected task."""
596
- active = resolve_selected_task(repo_root, platform_input, platform)
597
- return active.source_type, active.context_key, active.task_path
598
-
599
-
600
- # Internal compatibility aliases. User-facing commands and generated guidance
601
- # use selected-task wording, but keeping these names avoids a broad one-shot
602
- # rewrite of imports that are not part of the public command surface.
603
- ActiveTask = SelectedTask
604
- resolve_active_task = resolve_selected_task
605
- set_active_task = set_selected_task
606
- clear_active_task = clear_selected_task
607
- get_current_task_source = get_selected_task_source
559
+ def get_selected_task_source(
560
+ repo_root: Path,
561
+ platform_input: dict[str, Any] | None = None,
562
+ platform: str | None = None,
563
+ ) -> tuple[str, str | None, str | None]:
564
+ """Return (`source_type`, `context_key`, `task_path`) for selected task."""
565
+ active = resolve_selected_task(repo_root, platform_input, platform)
566
+ return active.source_type, active.context_key, active.task_path
567
+
568
+
569
+ # Internal compatibility aliases. User-facing commands and generated guidance
570
+ # use selected-task wording, but keeping these names avoids a broad one-shot
571
+ # rewrite of imports that are not part of the public command surface.
572
+ ActiveTask = SelectedTask
573
+ resolve_active_task = resolve_selected_task
574
+ set_active_task = set_selected_task
575
+ clear_active_task = clear_selected_task
576
+ get_current_task_source = get_selected_task_source