@mindfoldhq/trellis 0.5.0-beta.13 → 0.5.0-beta.15

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 (119) hide show
  1. package/README.md +5 -5
  2. package/dist/cli/index.js +1 -0
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/init.d.ts +1 -0
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +24 -20
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/update.d.ts.map +1 -1
  9. package/dist/commands/update.js +15 -12
  10. package/dist/commands/update.js.map +1 -1
  11. package/dist/configurators/claude.js +1 -1
  12. package/dist/configurators/claude.js.map +1 -1
  13. package/dist/configurators/codebuddy.js +1 -1
  14. package/dist/configurators/codebuddy.js.map +1 -1
  15. package/dist/configurators/codex.d.ts.map +1 -1
  16. package/dist/configurators/codex.js +3 -6
  17. package/dist/configurators/codex.js.map +1 -1
  18. package/dist/configurators/copilot.d.ts.map +1 -1
  19. package/dist/configurators/copilot.js +4 -11
  20. package/dist/configurators/copilot.js.map +1 -1
  21. package/dist/configurators/cursor.js +1 -1
  22. package/dist/configurators/cursor.js.map +1 -1
  23. package/dist/configurators/droid.js +1 -1
  24. package/dist/configurators/droid.js.map +1 -1
  25. package/dist/configurators/gemini.d.ts.map +1 -1
  26. package/dist/configurators/gemini.js +1 -3
  27. package/dist/configurators/gemini.js.map +1 -1
  28. package/dist/configurators/index.d.ts.map +1 -1
  29. package/dist/configurators/index.js +24 -38
  30. package/dist/configurators/index.js.map +1 -1
  31. package/dist/configurators/kiro.js +1 -1
  32. package/dist/configurators/kiro.js.map +1 -1
  33. package/dist/configurators/pi.d.ts +3 -0
  34. package/dist/configurators/pi.d.ts.map +1 -0
  35. package/dist/configurators/pi.js +39 -0
  36. package/dist/configurators/pi.js.map +1 -0
  37. package/dist/configurators/qoder.d.ts.map +1 -1
  38. package/dist/configurators/qoder.js +1 -3
  39. package/dist/configurators/qoder.js.map +1 -1
  40. package/dist/configurators/shared.d.ts +2 -4
  41. package/dist/configurators/shared.d.ts.map +1 -1
  42. package/dist/configurators/shared.js +6 -9
  43. package/dist/configurators/shared.js.map +1 -1
  44. package/dist/migrations/manifests/0.5.0-beta.14.json +9 -0
  45. package/dist/migrations/manifests/0.5.0-beta.15.json +126 -0
  46. package/dist/templates/claude/agents/trellis-research.md +1 -1
  47. package/dist/templates/claude/settings.json +0 -4
  48. package/dist/templates/codebuddy/agents/trellis-research.md +1 -1
  49. package/dist/templates/codex/agents/trellis-check.toml +0 -16
  50. package/dist/templates/codex/agents/trellis-implement.toml +0 -16
  51. package/dist/templates/codex/agents/trellis-research.toml +3 -2
  52. package/dist/templates/codex/hooks/session-start.py +82 -22
  53. package/dist/templates/codex/skills/start/SKILL.md +1 -1
  54. package/dist/templates/copilot/hooks/session-start.py +84 -26
  55. package/dist/templates/copilot/prompts/start.prompt.md +1 -1
  56. package/dist/templates/cursor/agents/trellis-check.md +1 -1
  57. package/dist/templates/cursor/agents/trellis-implement.md +1 -1
  58. package/dist/templates/cursor/agents/trellis-research.md +2 -2
  59. package/dist/templates/cursor/hooks.json +7 -1
  60. package/dist/templates/droid/droids/trellis-research.md +1 -1
  61. package/dist/templates/extract.d.ts +6 -0
  62. package/dist/templates/extract.d.ts.map +1 -1
  63. package/dist/templates/extract.js +14 -0
  64. package/dist/templates/extract.js.map +1 -1
  65. package/dist/templates/gemini/agents/trellis-research.md +1 -1
  66. package/dist/templates/kiro/agents/trellis-research.json +1 -1
  67. package/dist/templates/markdown/agents.md +11 -12
  68. package/dist/templates/markdown/gitignore.txt +3 -0
  69. package/dist/templates/opencode/agents/trellis-check.md +1 -1
  70. package/dist/templates/opencode/agents/trellis-implement.md +1 -1
  71. package/dist/templates/opencode/agents/trellis-research.md +2 -2
  72. package/dist/templates/opencode/lib/trellis-context.js +100 -13
  73. package/dist/templates/opencode/plugins/inject-subagent-context.js +54 -4
  74. package/dist/templates/opencode/plugins/inject-workflow-state.js +50 -23
  75. package/dist/templates/opencode/plugins/session-start.js +46 -21
  76. package/dist/templates/pi/agents/trellis-check.md +28 -0
  77. package/dist/templates/pi/agents/trellis-implement.md +33 -0
  78. package/dist/templates/pi/agents/trellis-research.md +25 -0
  79. package/dist/templates/pi/extensions/trellis/index.ts.txt +549 -0
  80. package/dist/templates/pi/index.d.ts +5 -0
  81. package/dist/templates/pi/index.d.ts.map +1 -0
  82. package/dist/templates/pi/index.js +12 -0
  83. package/dist/templates/pi/index.js.map +1 -0
  84. package/dist/templates/pi/settings.json +12 -0
  85. package/dist/templates/qoder/agents/trellis-research.md +1 -1
  86. package/dist/templates/shared-hooks/index.d.ts +31 -0
  87. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  88. package/dist/templates/shared-hooks/index.js +59 -0
  89. package/dist/templates/shared-hooks/index.js.map +1 -1
  90. package/dist/templates/shared-hooks/inject-shell-session-context.py +180 -0
  91. package/dist/templates/shared-hooks/inject-subagent-context.py +128 -26
  92. package/dist/templates/shared-hooks/inject-workflow-state.py +101 -61
  93. package/dist/templates/shared-hooks/session-start.py +151 -28
  94. package/dist/templates/trellis/gitignore.txt +3 -0
  95. package/dist/templates/trellis/index.d.ts +1 -0
  96. package/dist/templates/trellis/index.d.ts.map +1 -1
  97. package/dist/templates/trellis/index.js +2 -0
  98. package/dist/templates/trellis/index.js.map +1 -1
  99. package/dist/templates/trellis/scripts/common/__init__.py +8 -0
  100. package/dist/templates/trellis/scripts/common/active_task.py +593 -0
  101. package/dist/templates/trellis/scripts/common/cli_adapter.py +43 -8
  102. package/dist/templates/trellis/scripts/common/paths.py +61 -58
  103. package/dist/templates/trellis/scripts/common/session_context.py +12 -0
  104. package/dist/templates/trellis/scripts/common/task_store.py +4 -6
  105. package/dist/templates/trellis/scripts/task.py +56 -14
  106. package/dist/templates/trellis/workflow.md +31 -26
  107. package/dist/types/ai-tools.d.ts +3 -3
  108. package/dist/types/ai-tools.d.ts.map +1 -1
  109. package/dist/types/ai-tools.js +16 -0
  110. package/dist/types/ai-tools.js.map +1 -1
  111. package/dist/utils/template-fetcher.d.ts +22 -6
  112. package/dist/utils/template-fetcher.d.ts.map +1 -1
  113. package/dist/utils/template-fetcher.js +405 -27
  114. package/dist/utils/template-fetcher.js.map +1 -1
  115. package/dist/utils/template-hash.d.ts.map +1 -1
  116. package/dist/utils/template-hash.js +3 -2
  117. package/dist/utils/template-hash.js.map +1 -1
  118. package/package.json +1 -1
  119. package/dist/templates/shared-hooks/statusline.py +0 -218
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env python3
2
2
  """Trellis UserPromptSubmit hook: inject per-turn workflow breadcrumb.
3
3
 
4
- Runs on every user prompt. Reads the active task (.trellis/.current-task)
5
- and emits a short <workflow-state> block reminding the main AI what task
6
- is active and its expected flow. Breadcrumb text is pulled from
4
+ Runs on every user prompt. Resolves the active task through Trellis'
5
+ session-aware active task resolver and emits a short <workflow-state> block
6
+ reminding the main AI what task is active and its expected flow. Breadcrumb text is pulled from
7
7
  workflow.md [workflow-state:STATUS] tag blocks (single source of truth
8
8
  for users who fork the Trellis workflow), with hardcoded fallbacks so
9
9
  the hook never breaks when workflow.md is missing or malformed.
@@ -15,7 +15,6 @@ writeSharedHooks() at init time.
15
15
 
16
16
  Silent exit 0 cases (no output):
17
17
  - No .trellis/ directory found (not a Trellis project)
18
- - No .current-task file, or it's empty
19
18
  - task.json malformed or missing status
20
19
 
21
20
  Unknown status (no tag + no hardcoded fallback) emits a generic
@@ -29,7 +28,7 @@ import os
29
28
  import re
30
29
  import sys
31
30
  from pathlib import Path
32
- from typing import Optional, Tuple
31
+ from typing import Optional
33
32
 
34
33
 
35
34
  # ---------------------------------------------------------------------------
@@ -54,48 +53,63 @@ def find_trellis_root(start: Path) -> Optional[Path]:
54
53
  # Active task discovery
55
54
  # ---------------------------------------------------------------------------
56
55
 
57
- def _normalize_task_ref(task_ref: str) -> str:
58
- """Normalize .current-task path ref.
56
+ def _detect_platform(input_data: dict) -> str | None:
57
+ if isinstance(input_data.get("cursor_version"), str):
58
+ return "cursor"
59
+ env_map = {
60
+ "CLAUDE_PROJECT_DIR": "claude",
61
+ "CURSOR_PROJECT_DIR": "cursor",
62
+ "CODEBUDDY_PROJECT_DIR": "codebuddy",
63
+ "FACTORY_PROJECT_DIR": "droid",
64
+ "GEMINI_PROJECT_DIR": "gemini",
65
+ "QODER_PROJECT_DIR": "qoder",
66
+ "KIRO_PROJECT_DIR": "kiro",
67
+ "COPILOT_PROJECT_DIR": "copilot",
68
+ }
69
+ for env_name, platform in env_map.items():
70
+ if os.environ.get(env_name):
71
+ return platform
72
+ script_parts = set(Path(sys.argv[0]).parts)
73
+ if ".claude" in script_parts:
74
+ return "claude"
75
+ if ".cursor" in script_parts:
76
+ return "cursor"
77
+ if ".codex" in script_parts:
78
+ return "codex"
79
+ if ".gemini" in script_parts:
80
+ return "gemini"
81
+ if ".qoder" in script_parts:
82
+ return "qoder"
83
+ if ".codebuddy" in script_parts:
84
+ return "codebuddy"
85
+ if ".factory" in script_parts:
86
+ return "droid"
87
+ if ".kiro" in script_parts:
88
+ return "kiro"
89
+ return None
59
90
 
60
- Accepts:
61
- - Absolute paths (left as-is)
62
- - Windows-style backslashes (converted to forward slash)
63
- - Legacy relative refs like "tasks/foo" (prefixed with .trellis/)
64
- """
65
- normalized = task_ref.strip()
66
- if not normalized:
67
- return ""
68
- path_obj = Path(normalized)
69
- if path_obj.is_absolute():
70
- return str(path_obj)
71
- normalized = normalized.replace("\\", "/")
72
- while normalized.startswith("./"):
73
- normalized = normalized[2:]
74
- if normalized.startswith("tasks/"):
75
- normalized = f".trellis/{normalized}"
76
- return normalized
77
-
78
-
79
- def get_active_task(root: Path) -> Optional[Tuple[str, str]]:
80
- """Return (task_id, status) from the current active task, else None.
81
-
82
- Reads .trellis/.current-task (a path relative to root, e.g.
83
- ".trellis/tasks/04-17-foo") then that task's task.json.
84
- Normalizes backslashes so Windows paths work on Unix and vice versa.
85
- """
86
- ref_file = root / ".trellis" / ".current-task"
87
- if not ref_file.is_file():
88
- return None
89
- try:
90
- raw = ref_file.read_text(encoding="utf-8").strip()
91
- except OSError:
92
- return None
93
- task_ref = _normalize_task_ref(raw)
94
- if not task_ref:
91
+
92
+ def _resolve_active_task(root: Path, input_data: dict):
93
+ scripts_dir = root / ".trellis" / "scripts"
94
+ if str(scripts_dir) not in sys.path:
95
+ sys.path.insert(0, str(scripts_dir))
96
+ from common.active_task import resolve_active_task # type: ignore[import-not-found]
97
+
98
+ return resolve_active_task(root, input_data, platform=_detect_platform(input_data))
99
+
100
+
101
+ def get_active_task(root: Path, input_data: dict) -> Optional[tuple[str, str, str]]:
102
+ """Return (task_id, status, source) from the current active task."""
103
+ active = _resolve_active_task(root, input_data)
104
+ if not active.task_path:
95
105
  return None
96
106
 
97
- path_obj = Path(task_ref)
98
- task_dir = path_obj if path_obj.is_absolute() else root / path_obj
107
+ task_dir = Path(active.task_path)
108
+ if not task_dir.is_absolute():
109
+ task_dir = root / task_dir
110
+ if active.stale:
111
+ return task_dir.name, f"stale_{active.source_type}", active.source
112
+
99
113
  task_json = task_dir / "task.json"
100
114
  if not task_json.is_file():
101
115
  return None
@@ -108,7 +122,7 @@ def get_active_task(root: Path) -> Optional[Tuple[str, str]]:
108
122
  status = data.get("status", "")
109
123
  if not isinstance(status, str) or not status:
110
124
  return None
111
- return task_id, status
125
+ return task_id, status, active.source
112
126
 
113
127
 
114
128
  # ---------------------------------------------------------------------------
@@ -125,25 +139,32 @@ _TAG_RE = re.compile(
125
139
  # Hardcoded defaults for built-in Trellis statuses. Used when workflow.md is
126
140
  # missing, malformed, or lacks the tag for this status.
127
141
  #
128
- # `no_task` is a pseudo-status emitted when .current-task is missing — it keeps
142
+ # `no_task` is a pseudo-status emitted when no session active task exists — it keeps
129
143
  # the Next-Action reminder flowing per-turn even without an active task.
130
144
  _FALLBACK_BREADCRUMBS = {
131
145
  "no_task": (
132
146
  "No active task.\n"
133
- "Trigger words in the user message that REQUIRE creating a task "
134
- "(non-negotiable, do NOT self-exempt): 重构 / 抽成 / 独立 / 分发 / "
135
- "拆出来 / 搞一个 / 做成 / 接入 / 集成 / refactor / rewrite / extract / "
136
- "productize / publish / build X / design Y.\n"
137
- "Task is NOT required ONLY if ALL three hold: (a) zero file writes "
138
- "this turn, (b) answer fits in one reply with no multi-round plan, "
139
- "(c) no research beyond reading 1-2 repo files.\n"
140
- "When in doubt: create task. Over-tasking is cheap; under-tasking "
141
- "leaks plans and research into main context.\n"
147
+ "Trigger words in the user message that suggest creating a task: "
148
+ "重构 / 抽成 / 独立 / 分发 / 拆出来 / 搞一个 / 做成 / 接入 / 集成 / "
149
+ "refactor / rewrite / extract / productize / publish / build X / design Y.\n"
150
+ "Task is NOT required if ALL three hold: (a) zero file writes this turn, "
151
+ "(b) answer fits in one reply with no multi-round plan, (c) no research "
152
+ "beyond reading 1-2 repo files.\n"
153
+ "When in doubt and no override below applies: prefer creating a task — "
154
+ "over-tasking is cheap; under-tasking leaks plans and research into "
155
+ "main context.\n"
142
156
  "Flow: load `trellis-brainstorm` skill → it creates the task via "
143
157
  "`python3 ./.trellis/scripts/task.py create` and drives requirements Q&A. "
144
158
  "For research-heavy work (tool comparison, docs, cross-platform survey), "
145
159
  "spawn `trellis-research` sub-agents via Task tool — NEVER do 3+ inline "
146
- "WebFetch/WebSearch/`gh api` calls in the main conversation."
160
+ "WebFetch/WebSearch/`gh api` calls in the main conversation.\n"
161
+ "User override (per-turn escape hatch): if the user's CURRENT message "
162
+ "contains an explicit opt-out phrase (\"跳过 trellis\" / \"别走流程\" / "
163
+ "\"小修一下\" / \"直接改\" / \"先别建任务\" / \"skip trellis\" / "
164
+ "\"no task\" / \"just do it\" / \"don't create a task\"), honor it for "
165
+ "this turn — briefly acknowledge (\"好,本轮跳过 trellis 流程\") and "
166
+ "proceed without creating a task. Per-turn only; does not carry forward; "
167
+ "do NOT invent an override the user did not say."
147
168
  ),
148
169
  "planning": (
149
170
  "Complete prd.md via trellis-brainstorm skill; then run task.py start.\n"
@@ -153,8 +174,21 @@ _FALLBACK_BREADCRUMBS = {
153
174
  ),
154
175
  "in_progress": (
155
176
  "Flow: trellis-implement → trellis-check → trellis-update-spec → finish\n"
156
- "Check conversation history + git status to determine current step; "
157
- "do NOT skip trellis-check."
177
+ "Next required action: inspect conversation history + git status, then "
178
+ "execute the next uncompleted step in that sequence.\n"
179
+ "For agent-capable platforms, the default is to dispatch "
180
+ "`trellis-implement` for implementation and `trellis-check` before "
181
+ "reporting completion — do not edit code in the main session by default.\n"
182
+ "Use the exact Trellis agent type names when spawning sub-agents: "
183
+ "`trellis-implement`, `trellis-check`, or `trellis-research`. "
184
+ "Generic/default/generalPurpose sub-agents do not receive "
185
+ "`implement.jsonl` / `check.jsonl` injection.\n"
186
+ "User override (per-turn escape hatch): if the user's CURRENT message "
187
+ "explicitly tells the main session to handle it directly (\"你直接改\" / "
188
+ "\"别派 sub-agent\" / \"main session 写就行\" / \"do it inline\" / "
189
+ "\"不用 sub-agent\"), honor it for this turn and edit code directly. "
190
+ "Per-turn only; does not carry forward; do NOT invent an override the "
191
+ "user did not say."
158
192
  ),
159
193
  "completed": (
160
194
  "User commits changes; then run task.py archive."
@@ -189,7 +223,10 @@ def load_breadcrumbs(root: Path) -> dict[str, str]:
189
223
 
190
224
 
191
225
  def build_breadcrumb(
192
- task_id: Optional[str], status: str, templates: dict[str, str]
226
+ task_id: Optional[str],
227
+ status: str,
228
+ templates: dict[str, str],
229
+ source: str | None = None,
193
230
  ) -> str:
194
231
  """Build the <workflow-state>...</workflow-state> block.
195
232
 
@@ -201,6 +238,8 @@ def build_breadcrumb(
201
238
  if body is None:
202
239
  body = "Refer to workflow.md for current step."
203
240
  header = f"Status: {status}" if task_id is None else f"Task: {task_id} ({status})"
241
+ if source:
242
+ header = f"{header}\nSource: {source}"
204
243
  return f"<workflow-state>\n{header}\n{body}\n</workflow-state>"
205
244
 
206
245
 
@@ -222,13 +261,14 @@ def main() -> int:
222
261
  return 0 # not a Trellis project
223
262
 
224
263
  templates = load_breadcrumbs(root)
225
- task = get_active_task(root)
264
+ task = get_active_task(root, data)
226
265
  if task is None:
227
266
  # No active task — still emit a breadcrumb nudging AI toward
228
267
  # trellis-brainstorm + task.py create when user describes real work.
229
268
  breadcrumb = build_breadcrumb(None, "no_task", templates)
230
269
  else:
231
- breadcrumb = build_breadcrumb(*task, templates=templates)
270
+ task_id, status, source = task
271
+ breadcrumb = build_breadcrumb(task_id, status, templates, source)
232
272
 
233
273
  output = {
234
274
  "hookSpecificOutput": {
@@ -11,11 +11,18 @@ warnings.filterwarnings("ignore")
11
11
 
12
12
  import json
13
13
  import os
14
+ import shlex
14
15
  import subprocess
15
16
  import sys
16
17
  from io import StringIO
17
18
  from pathlib import Path
18
19
 
20
+ FIRST_REPLY_NOTICE = """<first-reply-notice>
21
+ On the first visible assistant reply in this session, begin with exactly one short Chinese sentence:
22
+ Trellis SessionStart 已注入:workflow、当前任务状态、开发者身份、git 状态、active tasks、spec 索引已加载。
23
+ Then continue directly with the user's request. This notice is one-shot: do not repeat it after the first assistant reply in the same session.
24
+ </first-reply-notice>"""
25
+
19
26
  # IMPORTANT: Force stdout to use UTF-8 on Windows
20
27
  # This fixes UnicodeEncodeError when outputting non-ASCII characters
21
28
  if sys.platform.startswith("win"):
@@ -32,7 +39,8 @@ def _has_curated_jsonl_entry(jsonl_path: Path) -> bool:
32
39
 
33
40
  A freshly seeded jsonl only contains a ``{"_example": ...}`` row (no
34
41
  ``file`` key) — that is NOT "ready". Readiness requires at least one
35
- curated entry. Matches the contract used by ``inject-subagent-context.py``.
42
+ curated entry. Matches the contract used by hook-inject and pull-based
43
+ sub-agent context loaders.
36
44
  """
37
45
  try:
38
46
  for line in jsonl_path.read_text(encoding="utf-8").splitlines():
@@ -72,15 +80,97 @@ def read_file(path: Path, fallback: str = "") -> str:
72
80
  return fallback
73
81
 
74
82
 
75
- def run_script(script_path: Path) -> str:
83
+ def _detect_platform(input_data: dict) -> str | None:
84
+ if isinstance(input_data.get("cursor_version"), str):
85
+ return "cursor"
86
+ env_map = {
87
+ "CLAUDE_PROJECT_DIR": "claude",
88
+ "CURSOR_PROJECT_DIR": "cursor",
89
+ "CODEBUDDY_PROJECT_DIR": "codebuddy",
90
+ "FACTORY_PROJECT_DIR": "droid",
91
+ "GEMINI_PROJECT_DIR": "gemini",
92
+ "QODER_PROJECT_DIR": "qoder",
93
+ "KIRO_PROJECT_DIR": "kiro",
94
+ "COPILOT_PROJECT_DIR": "copilot",
95
+ }
96
+ for env_name, platform in env_map.items():
97
+ if os.environ.get(env_name):
98
+ return platform
99
+ script_parts = set(Path(sys.argv[0]).parts)
100
+ if ".claude" in script_parts:
101
+ return "claude"
102
+ if ".cursor" in script_parts:
103
+ return "cursor"
104
+ if ".codex" in script_parts:
105
+ return "codex"
106
+ if ".gemini" in script_parts:
107
+ return "gemini"
108
+ if ".qoder" in script_parts:
109
+ return "qoder"
110
+ if ".codebuddy" in script_parts:
111
+ return "codebuddy"
112
+ if ".factory" in script_parts:
113
+ return "droid"
114
+ if ".kiro" in script_parts:
115
+ return "kiro"
116
+ return None
117
+
118
+
119
+ def _resolve_context_key(trellis_dir: Path, input_data: dict) -> str | None:
120
+ scripts_dir = trellis_dir / "scripts"
121
+ if str(scripts_dir) not in sys.path:
122
+ sys.path.insert(0, str(scripts_dir))
123
+ from common.active_task import resolve_context_key # type: ignore[import-not-found]
124
+
125
+ return resolve_context_key(input_data, platform=_detect_platform(input_data))
126
+
127
+
128
+ def _persist_context_key_for_bash(context_key: str | None) -> None:
129
+ """Expose Trellis session identity to later Claude Code Bash commands.
130
+
131
+ Claude Code SessionStart hooks can append exports to CLAUDE_ENV_FILE; those
132
+ variables are then available to Bash tools in the same conversation. Without
133
+ this bridge, `task.py start` has hook stdin during SessionStart but no
134
+ session identity when the AI later runs it as a normal shell command.
135
+ """
136
+ if not context_key:
137
+ return
138
+ env_file = os.environ.get("CLAUDE_ENV_FILE")
139
+ if not env_file:
140
+ return
141
+ try:
142
+ with open(env_file, "a", encoding="utf-8") as handle:
143
+ handle.write(f"export TRELLIS_CONTEXT_ID={shlex.quote(context_key)}\n")
144
+ except OSError:
145
+ pass
146
+
147
+
148
+ def _resolve_active_task(trellis_dir: Path, input_data: dict):
149
+ scripts_dir = trellis_dir / "scripts"
150
+ if str(scripts_dir) not in sys.path:
151
+ sys.path.insert(0, str(scripts_dir))
152
+ from common.active_task import resolve_active_task # type: ignore[import-not-found]
153
+
154
+ return resolve_active_task(
155
+ trellis_dir.parent,
156
+ input_data,
157
+ platform=_detect_platform(input_data),
158
+ )
159
+
160
+
161
+ def run_script(script_path: Path, context_key: str | None = None) -> str:
76
162
  try:
77
163
  if script_path.suffix == ".py":
78
164
  # Add PYTHONIOENCODING to force UTF-8 in subprocess
79
165
  env = os.environ.copy()
80
166
  env["PYTHONIOENCODING"] = "utf-8"
167
+ if context_key:
168
+ env["TRELLIS_CONTEXT_ID"] = context_key
81
169
  cmd = [sys.executable, "-W", "ignore", str(script_path)]
82
170
  else:
83
- env = os.environ
171
+ env = os.environ.copy()
172
+ if context_key:
173
+ env["TRELLIS_CONTEXT_ID"] = context_key
84
174
  cmd = [str(script_path)]
85
175
 
86
176
  result = subprocess.run(
@@ -127,7 +217,7 @@ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
127
217
  return trellis_dir / "tasks" / path_obj
128
218
 
129
219
 
130
- def _get_task_status(trellis_dir: Path) -> str:
220
+ def _get_task_status(trellis_dir: Path, input_data: dict) -> str:
131
221
  """Check current task status and return structured status string with explicit next action.
132
222
 
133
223
  Returns a block with three fields:
@@ -135,27 +225,32 @@ def _get_task_status(trellis_dir: Path) -> str:
135
225
  - Task: task identifier (when applicable)
136
226
  - Next-Action: explicit skill/command/tool call the AI should invoke
137
227
  """
138
- current_task_file = trellis_dir / ".current-task"
228
+ active = _resolve_active_task(trellis_dir, input_data)
139
229
 
140
230
  # Case 1: No active task — waiting for user to describe intent
141
- if not current_task_file.is_file() or not current_task_file.read_text(encoding="utf-8").strip():
231
+ if not active.task_path:
142
232
  return (
143
233
  "Status: NO ACTIVE TASK\n"
234
+ f"Source: {active.source}\n"
144
235
  "Next-Action: After the user describes their intent, load skill `trellis-brainstorm` "
145
236
  "to clarify requirements and create a task via `python3 ./.trellis/scripts/task.py create`.\n"
146
237
  "Research reminder: for research-heavy tasks (comparing tools, reading external docs, "
147
238
  "cross-platform surveys), spawn `trellis-research` sub-agents via the Task tool — "
148
239
  "they persist findings to `{TASK_DIR}/research/*.md` and keep main context clean. "
149
- "Do NOT do 10+ inline WebFetch/WebSearch in the main conversation."
240
+ "Do NOT do 10+ inline WebFetch/WebSearch in the main conversation.\n"
241
+ "User override (per-turn escape hatch): if the user's first message explicitly opts "
242
+ "out of the workflow (\"跳过 trellis\" / \"别走流程\" / \"小修一下\" / \"直接改\" / "
243
+ "\"skip trellis\" / \"no task\" / \"just do it\"), honor it for this turn — "
244
+ "acknowledge briefly and proceed without creating a task. Per-turn only."
150
245
  )
151
246
 
152
- task_ref = _normalize_task_ref(current_task_file.read_text(encoding="utf-8").strip())
153
-
154
247
  # Case 2: Stale pointer — task dir was deleted
248
+ task_ref = active.task_path
155
249
  task_dir = _resolve_task_dir(trellis_dir, task_ref)
156
- if not task_dir.is_dir():
250
+ if active.stale or not task_dir.is_dir():
157
251
  return (
158
252
  f"Status: STALE POINTER\nTask: {task_ref}\n"
253
+ f"Source: {active.source}\n"
159
254
  f"Next-Action: Run `python3 ./.trellis/scripts/task.py finish` to clear the stale pointer, "
160
255
  "then ask the user what to work on next."
161
256
  )
@@ -176,6 +271,7 @@ def _get_task_status(trellis_dir: Path) -> str:
176
271
  if task_status == "completed":
177
272
  return (
178
273
  f"Status: COMPLETED\nTask: {task_title}\n"
274
+ f"Source: {active.source}\n"
179
275
  f"Next-Action: Load skill `trellis-update-spec` to capture learnings, "
180
276
  f"then archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}`."
181
277
  )
@@ -186,6 +282,7 @@ def _get_task_status(trellis_dir: Path) -> str:
186
282
  if not has_prd:
187
283
  return (
188
284
  f"Status: PLANNING\nTask: {task_title}\n"
285
+ f"Source: {active.source}\n"
189
286
  "Next-Action: Load skill `trellis-brainstorm` to clarify requirements with the user "
190
287
  "and produce prd.md in the task directory.\n"
191
288
  "Research reminder: when the task needs external research (tool comparison, docs, "
@@ -198,6 +295,7 @@ def _get_task_status(trellis_dir: Path) -> str:
198
295
  if implement_jsonl.is_file() and not _has_curated_jsonl_entry(implement_jsonl):
199
296
  return (
200
297
  f"Status: PLANNING (Phase 1.3)\nTask: {task_title}\n"
298
+ f"Source: {active.source}\n"
201
299
  "Next-Action: Curate `implement.jsonl` and `check.jsonl` with the spec + research files "
202
300
  "the Phase 2 sub-agents will need. Only spec paths (`.trellis/spec/**/*.md`) and research "
203
301
  "files (`{TASK_DIR}/research/*.md`) — no code paths. Run "
@@ -209,17 +307,21 @@ def _get_task_status(trellis_dir: Path) -> str:
209
307
  # Case 5: PRD + curated jsonl (or agent-less platform with no jsonl) — enter Execute phase
210
308
  return (
211
309
  f"Status: READY\nTask: {task_title}\n"
212
- "Next-Action: Follow Phase 2.1 for your platform. For agent-capable platforms, "
213
- "spawn `trellis-implement` via the Task tool; if you stay in the main session, "
214
- "load `trellis-before-dev` before writing code. "
215
- "After implementation, spawn `trellis-check` sub-agent for quality verification.\n"
310
+ f"Source: {active.source}\n"
311
+ "Next required action: dispatch `trellis-implement` per Phase 2.1. "
312
+ "For agent-capable platforms, the default is to NOT edit code in the main session. "
313
+ "After implementation, dispatch `trellis-check` per Phase 2.2 before reporting completion.\n"
216
314
  "Sub-agent roster: `trellis-implement` (writes code), `trellis-check` (verifies + self-fixes), "
217
315
  "`trellis-research` (persists findings to `research/*.md` — use when you'd otherwise do "
218
- "multiple WebFetch/WebSearch inline)."
316
+ "multiple WebFetch/WebSearch inline).\n"
317
+ "User override (per-turn escape hatch): if the user's CURRENT message explicitly tells the "
318
+ "main session to handle it directly (\"你直接改\" / \"别派 sub-agent\" / \"main session 写就行\" / "
319
+ "\"do it inline\" / \"不用 sub-agent\"), honor it for this turn and edit code directly. "
320
+ "Per-turn only; do NOT invent an override the user did not say."
219
321
  )
220
322
 
221
323
 
222
- def _load_trellis_config(trellis_dir: Path) -> tuple:
324
+ def _load_trellis_config(trellis_dir: Path, input_data: dict) -> tuple:
223
325
  """Load Trellis config for session-start decisions.
224
326
 
225
327
  Returns:
@@ -240,7 +342,11 @@ def _load_trellis_config(trellis_dir: Path) -> tuple:
240
342
 
241
343
  # Get active task's package
242
344
  task_pkg = None
243
- current = get_current_task(repo_root)
345
+ current = get_current_task(
346
+ repo_root,
347
+ input_data,
348
+ platform=_detect_platform(input_data),
349
+ )
244
350
  if current:
245
351
  task_json = repo_root / current / "task.json"
246
352
  if task_json.is_file():
@@ -435,7 +541,14 @@ def main():
435
541
  if should_skip_injection():
436
542
  sys.exit(0)
437
543
 
438
- # Try platform-specific env vars, fallback to cwd
544
+ try:
545
+ hook_input = json.loads(sys.stdin.read())
546
+ if not isinstance(hook_input, dict):
547
+ hook_input = {}
548
+ except (json.JSONDecodeError, ValueError):
549
+ hook_input = {}
550
+
551
+ # Try platform-specific env vars, hook cwd, fallback to cwd
439
552
  project_dir_env_vars = [
440
553
  "CLAUDE_PROJECT_DIR",
441
554
  "QODER_PROJECT_DIR",
@@ -453,12 +566,17 @@ def main():
453
566
  project_dir = Path(val).resolve()
454
567
  break
455
568
  if project_dir is None:
456
- project_dir = Path(".").resolve()
569
+ project_dir = Path(hook_input.get("cwd", ".")).resolve()
457
570
 
458
571
  trellis_dir = project_dir / ".trellis"
572
+ context_key = _resolve_context_key(trellis_dir, hook_input)
573
+ _persist_context_key_for_bash(context_key)
459
574
 
460
575
  # Load config for scope filtering and legacy detection
461
- is_mono, packages, scope_config, task_pkg, default_pkg = _load_trellis_config(trellis_dir)
576
+ is_mono, packages, scope_config, task_pkg, default_pkg = _load_trellis_config(
577
+ trellis_dir,
578
+ hook_input,
579
+ )
462
580
  allowed_pkgs = _resolve_spec_scope(is_mono, packages, scope_config, task_pkg, default_pkg)
463
581
 
464
582
  output = StringIO()
@@ -469,6 +587,8 @@ Read and follow all instructions below carefully.
469
587
  </session-context>
470
588
 
471
589
  """)
590
+ output.write(FIRST_REPLY_NOTICE)
591
+ output.write("\n\n")
472
592
 
473
593
  # Legacy migration warning
474
594
  legacy_warning = _check_legacy_spec(trellis_dir, is_mono, packages)
@@ -477,7 +597,7 @@ Read and follow all instructions below carefully.
477
597
 
478
598
  output.write("<current-state>\n")
479
599
  context_script = trellis_dir / "scripts" / "get_context.py"
480
- output.write(run_script(context_script))
600
+ output.write(run_script(context_script, context_key))
481
601
  output.write("\n</current-state>\n\n")
482
602
 
483
603
  output.write("<workflow>\n")
@@ -490,10 +610,13 @@ Read and follow all instructions below carefully.
490
610
  "**Pre-Development Checklist** listing the specific guideline files to "
491
611
  "read before coding.\n\n"
492
612
  "- If you're spawning an implement/check sub-agent, context is injected "
493
- "automatically via `{task}/implement.jsonl` / `check.jsonl`. You do NOT "
494
- "need to read these indexes yourself.\n"
495
- "- If you're editing code directly in the main session, Read the relevant "
496
- "index(es) on-demand and follow their Pre-Dev Checklist.\n\n"
613
+ "or loaded by the sub-agent via `{task}/implement.jsonl` / `check.jsonl`. "
614
+ "You do NOT need to read these indexes yourself.\n"
615
+ "- For agent-capable platforms, the default is to dispatch "
616
+ "`trellis-implement` and `trellis-check` (so JSONL context is loaded by "
617
+ "the sub-agents) rather than editing code in the main session. "
618
+ "Honor a per-turn user override only if the user's current message "
619
+ "explicitly opts out (see <task-status> below for override phrases).\n\n"
497
620
  )
498
621
 
499
622
  # guides/ is cross-package thinking — always include inline (small, broadly useful)
@@ -545,13 +668,13 @@ Read and follow all instructions below carefully.
545
668
  output.write("</guidelines>\n\n")
546
669
 
547
670
  # Check task status and inject structured tag
548
- task_status = _get_task_status(trellis_dir)
671
+ task_status = _get_task_status(trellis_dir, hook_input)
549
672
  output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
550
673
 
551
674
  output.write("""<ready>
552
675
  Context loaded. Workflow index, project state, and guidelines are already injected above — do NOT re-read them.
553
- Wait for the user's first message, then handle it following the workflow guide.
554
- If there is an active task, ask whether to continue it.
676
+ When the user sends the first message, follow <task-status> and the workflow guide.
677
+ If a task is READY, execute its Next required action without asking whether to continue.
555
678
  </ready>""")
556
679
 
557
680
  result = {
@@ -4,6 +4,9 @@
4
4
  # Current task pointer (each dev works on different task)
5
5
  .current-task
6
6
 
7
+ # Session/window scoped runtime state
8
+ .runtime/
9
+
7
10
  # Ralph Loop state file
8
11
  .ralph-state.json
9
12
 
@@ -22,6 +22,7 @@ export declare const commonDeveloper: string;
22
22
  export declare const commonGitContext: string;
23
23
  export declare const commonTaskQueue: string;
24
24
  export declare const commonTaskUtils: string;
25
+ export declare const commonActiveTask: string;
25
26
  export declare const commonCliAdapter: string;
26
27
  export declare const commonConfig: string;
27
28
  export declare const commonIo: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,eAAO,MAAM,WAAW,QAAsC,CAAC;AAG/D,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,YAAY,QAA2C,CAAC;AACrE,eAAO,MAAM,QAAQ,QAAuC,CAAC;AAC7D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAChF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,qBAAqB,QAEjC,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AAGF,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,UAAU,QAAkC,CAAC;AAC1D,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AAGvE,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAE/D;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAkCnD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,eAAO,MAAM,WAAW,QAAsC,CAAC;AAG/D,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,YAAY,QAA2C,CAAC;AACrE,eAAO,MAAM,QAAQ,QAAuC,CAAC;AAC7D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAChF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,qBAAqB,QAEjC,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AAGF,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,UAAU,QAAkC,CAAC;AAC1D,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AAGvE,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAE/D;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAmCnD"}
@@ -32,6 +32,7 @@ export const commonDeveloper = readTemplate("scripts/common/developer.py");
32
32
  export const commonGitContext = readTemplate("scripts/common/git_context.py");
33
33
  export const commonTaskQueue = readTemplate("scripts/common/task_queue.py");
34
34
  export const commonTaskUtils = readTemplate("scripts/common/task_utils.py");
35
+ export const commonActiveTask = readTemplate("scripts/common/active_task.py");
35
36
  export const commonCliAdapter = readTemplate("scripts/common/cli_adapter.py");
36
37
  export const commonConfig = readTemplate("scripts/common/config.py");
37
38
  export const commonIo = readTemplate("scripts/common/io.py");
@@ -68,6 +69,7 @@ export function getAllScripts() {
68
69
  scripts.set("common/git_context.py", commonGitContext);
69
70
  scripts.set("common/task_queue.py", commonTaskQueue);
70
71
  scripts.set("common/task_utils.py", commonTaskUtils);
72
+ scripts.set("common/active_task.py", commonActiveTask);
71
73
  scripts.set("common/cli_adapter.py", commonCliAdapter);
72
74
  scripts.set("common/config.py", commonConfig);
73
75
  scripts.set("common/io.py", commonIo);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"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"}
@@ -82,3 +82,11 @@ from .paths import (
82
82
  has_current_task,
83
83
  generate_task_date_prefix,
84
84
  )
85
+
86
+ from .active_task import (
87
+ ActiveTask,
88
+ clear_active_task,
89
+ resolve_active_task,
90
+ resolve_context_key,
91
+ set_active_task,
92
+ )