@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.
- package/README.md +5 -5
- package/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +24 -20
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +15 -12
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/claude.js +1 -1
- package/dist/configurators/claude.js.map +1 -1
- package/dist/configurators/codebuddy.js +1 -1
- package/dist/configurators/codebuddy.js.map +1 -1
- package/dist/configurators/codex.d.ts.map +1 -1
- package/dist/configurators/codex.js +3 -6
- package/dist/configurators/codex.js.map +1 -1
- package/dist/configurators/copilot.d.ts.map +1 -1
- package/dist/configurators/copilot.js +4 -11
- package/dist/configurators/copilot.js.map +1 -1
- package/dist/configurators/cursor.js +1 -1
- package/dist/configurators/cursor.js.map +1 -1
- package/dist/configurators/droid.js +1 -1
- package/dist/configurators/droid.js.map +1 -1
- package/dist/configurators/gemini.d.ts.map +1 -1
- package/dist/configurators/gemini.js +1 -3
- package/dist/configurators/gemini.js.map +1 -1
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +24 -38
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/kiro.js +1 -1
- package/dist/configurators/kiro.js.map +1 -1
- package/dist/configurators/pi.d.ts +3 -0
- package/dist/configurators/pi.d.ts.map +1 -0
- package/dist/configurators/pi.js +39 -0
- package/dist/configurators/pi.js.map +1 -0
- package/dist/configurators/qoder.d.ts.map +1 -1
- package/dist/configurators/qoder.js +1 -3
- package/dist/configurators/qoder.js.map +1 -1
- package/dist/configurators/shared.d.ts +2 -4
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +6 -9
- package/dist/configurators/shared.js.map +1 -1
- package/dist/migrations/manifests/0.5.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.15.json +126 -0
- package/dist/templates/claude/agents/trellis-research.md +1 -1
- package/dist/templates/claude/settings.json +0 -4
- package/dist/templates/codebuddy/agents/trellis-research.md +1 -1
- package/dist/templates/codex/agents/trellis-check.toml +0 -16
- package/dist/templates/codex/agents/trellis-implement.toml +0 -16
- package/dist/templates/codex/agents/trellis-research.toml +3 -2
- package/dist/templates/codex/hooks/session-start.py +82 -22
- package/dist/templates/codex/skills/start/SKILL.md +1 -1
- package/dist/templates/copilot/hooks/session-start.py +84 -26
- package/dist/templates/copilot/prompts/start.prompt.md +1 -1
- package/dist/templates/cursor/agents/trellis-check.md +1 -1
- package/dist/templates/cursor/agents/trellis-implement.md +1 -1
- package/dist/templates/cursor/agents/trellis-research.md +2 -2
- package/dist/templates/cursor/hooks.json +7 -1
- package/dist/templates/droid/droids/trellis-research.md +1 -1
- package/dist/templates/extract.d.ts +6 -0
- package/dist/templates/extract.d.ts.map +1 -1
- package/dist/templates/extract.js +14 -0
- package/dist/templates/extract.js.map +1 -1
- package/dist/templates/gemini/agents/trellis-research.md +1 -1
- package/dist/templates/kiro/agents/trellis-research.json +1 -1
- package/dist/templates/markdown/agents.md +11 -12
- package/dist/templates/markdown/gitignore.txt +3 -0
- package/dist/templates/opencode/agents/trellis-check.md +1 -1
- package/dist/templates/opencode/agents/trellis-implement.md +1 -1
- package/dist/templates/opencode/agents/trellis-research.md +2 -2
- package/dist/templates/opencode/lib/trellis-context.js +100 -13
- package/dist/templates/opencode/plugins/inject-subagent-context.js +54 -4
- package/dist/templates/opencode/plugins/inject-workflow-state.js +50 -23
- package/dist/templates/opencode/plugins/session-start.js +46 -21
- package/dist/templates/pi/agents/trellis-check.md +28 -0
- package/dist/templates/pi/agents/trellis-implement.md +33 -0
- package/dist/templates/pi/agents/trellis-research.md +25 -0
- package/dist/templates/pi/extensions/trellis/index.ts.txt +549 -0
- package/dist/templates/pi/index.d.ts +5 -0
- package/dist/templates/pi/index.d.ts.map +1 -0
- package/dist/templates/pi/index.js +12 -0
- package/dist/templates/pi/index.js.map +1 -0
- package/dist/templates/pi/settings.json +12 -0
- package/dist/templates/qoder/agents/trellis-research.md +1 -1
- package/dist/templates/shared-hooks/index.d.ts +31 -0
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +59 -0
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/inject-shell-session-context.py +180 -0
- package/dist/templates/shared-hooks/inject-subagent-context.py +128 -26
- package/dist/templates/shared-hooks/inject-workflow-state.py +101 -61
- package/dist/templates/shared-hooks/session-start.py +151 -28
- package/dist/templates/trellis/gitignore.txt +3 -0
- package/dist/templates/trellis/index.d.ts +1 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +2 -0
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/common/__init__.py +8 -0
- package/dist/templates/trellis/scripts/common/active_task.py +593 -0
- package/dist/templates/trellis/scripts/common/cli_adapter.py +43 -8
- package/dist/templates/trellis/scripts/common/paths.py +61 -58
- package/dist/templates/trellis/scripts/common/session_context.py +12 -0
- package/dist/templates/trellis/scripts/common/task_store.py +4 -6
- package/dist/templates/trellis/scripts/task.py +56 -14
- package/dist/templates/trellis/workflow.md +31 -26
- package/dist/types/ai-tools.d.ts +3 -3
- package/dist/types/ai-tools.d.ts.map +1 -1
- package/dist/types/ai-tools.js +16 -0
- package/dist/types/ai-tools.js.map +1 -1
- package/dist/utils/template-fetcher.d.ts +22 -6
- package/dist/utils/template-fetcher.d.ts.map +1 -1
- package/dist/utils/template-fetcher.js +405 -27
- package/dist/utils/template-fetcher.js.map +1 -1
- package/dist/utils/template-hash.d.ts.map +1 -1
- package/dist/utils/template-hash.js +3 -2
- package/dist/utils/template-hash.js.map +1 -1
- package/package.json +1 -1
- package/dist/templates/shared-hooks/statusline.py +0 -218
|
@@ -3,22 +3,6 @@ description = "Workspace-write Trellis reviewer that self-fixes spec drift, lint
|
|
|
3
3
|
sandbox_mode = "workspace-write"
|
|
4
4
|
|
|
5
5
|
developer_instructions = """
|
|
6
|
-
## Required: Load Trellis Context First
|
|
7
|
-
|
|
8
|
-
This platform does NOT auto-inject task context via hook. Before doing anything else, you MUST load context yourself:
|
|
9
|
-
|
|
10
|
-
1. Read `.trellis/.current-task` to find the current task path (e.g. `.trellis/tasks/04-17-foo/`).
|
|
11
|
-
2. Read the task's `prd.md` (requirements) and `info.md` if it exists (technical design).
|
|
12
|
-
3. Read `<task-path>/check.jsonl` — JSONL list of dev spec files relevant to this agent.
|
|
13
|
-
4. For each entry in the JSONL, Read its `file` path — these are the dev specs you must follow.
|
|
14
|
-
**Skip rows without a `"file"` field** (e.g. `{"_example": "..."}` seed rows left over from `task.py create` before the curator ran).
|
|
15
|
-
|
|
16
|
-
If `check.jsonl` has no curated entries (only a seed row, or the file is missing), fall back to: read `prd.md`, list available specs with `python3 ./.trellis/scripts/get_context.py --mode packages`, and pick the specs that match the task domain yourself. Do NOT block on the missing jsonl — proceed with prd-only context plus your spec judgment.
|
|
17
|
-
|
|
18
|
-
If `.current-task` is missing or the task has no `prd.md`, ask the user what to work on; do NOT proceed without context.
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
6
|
You are the Trellis reviewer agent.
|
|
23
7
|
|
|
24
8
|
Your job is to review code changes against specs AND fix issues directly — not just report them. You have write access; use it.
|
|
@@ -3,22 +3,6 @@ description = "Workspace-write Trellis implementer that follows specs and keeps
|
|
|
3
3
|
sandbox_mode = "workspace-write"
|
|
4
4
|
|
|
5
5
|
developer_instructions = """
|
|
6
|
-
## Required: Load Trellis Context First
|
|
7
|
-
|
|
8
|
-
This platform does NOT auto-inject task context via hook. Before doing anything else, you MUST load context yourself:
|
|
9
|
-
|
|
10
|
-
1. Read `.trellis/.current-task` to find the current task path (e.g. `.trellis/tasks/04-17-foo/`).
|
|
11
|
-
2. Read the task's `prd.md` (requirements) and `info.md` if it exists (technical design).
|
|
12
|
-
3. Read `<task-path>/implement.jsonl` — JSONL list of dev spec files relevant to this agent.
|
|
13
|
-
4. For each entry in the JSONL, Read its `file` path — these are the dev specs you must follow.
|
|
14
|
-
**Skip rows without a `"file"` field** (e.g. `{"_example": "..."}` seed rows left over from `task.py create` before the curator ran).
|
|
15
|
-
|
|
16
|
-
If `implement.jsonl` has no curated entries (only a seed row, or the file is missing), fall back to: read `prd.md`, list available specs with `python3 ./.trellis/scripts/get_context.py --mode packages`, and pick the specs that match the task domain yourself. Do NOT block on the missing jsonl — proceed with prd-only context plus your spec judgment.
|
|
17
|
-
|
|
18
|
-
If `.current-task` is missing or the task has no `prd.md`, ask the user what to work on; do NOT proceed without context.
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
6
|
You are the Trellis implementer agent.
|
|
23
7
|
|
|
24
8
|
Rules:
|
|
@@ -13,8 +13,9 @@ through the chat reply is a failure.
|
|
|
13
13
|
|
|
14
14
|
## Workflow
|
|
15
15
|
|
|
16
|
-
1.
|
|
17
|
-
|
|
16
|
+
1. Run `python3 ./.trellis/scripts/task.py current --source` to get the
|
|
17
|
+
active task path and source. If no active task is set, ask the user
|
|
18
|
+
where to write output; do not guess.
|
|
18
19
|
2. Run `mkdir -p <TASK_DIR>/research` to ensure the directory exists.
|
|
19
20
|
3. Read `.trellis/workflow.md`, relevant `.trellis/spec/` files, and
|
|
20
21
|
target code before forming an opinion.
|
|
@@ -19,11 +19,31 @@ from pathlib import Path
|
|
|
19
19
|
|
|
20
20
|
warnings.filterwarnings("ignore")
|
|
21
21
|
|
|
22
|
+
FIRST_REPLY_NOTICE = """<first-reply-notice>
|
|
23
|
+
On the first visible assistant reply in this session, begin with exactly one short Chinese sentence:
|
|
24
|
+
Trellis SessionStart 已注入:workflow、当前任务状态、开发者身份、git 状态、active tasks、spec 索引已加载。
|
|
25
|
+
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.
|
|
26
|
+
</first-reply-notice>"""
|
|
27
|
+
|
|
22
28
|
|
|
23
29
|
def should_skip_injection() -> bool:
|
|
24
30
|
return os.environ.get("CODEX_NON_INTERACTIVE") == "1"
|
|
25
31
|
|
|
26
32
|
|
|
33
|
+
def configure_project_encoding(project_dir: Path) -> None:
|
|
34
|
+
"""Reuse Trellis' shared Windows stdio encoding helper before JSON output."""
|
|
35
|
+
scripts_dir = project_dir / ".trellis" / "scripts"
|
|
36
|
+
if str(scripts_dir) not in sys.path:
|
|
37
|
+
sys.path.insert(0, str(scripts_dir))
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
from common import configure_encoding # type: ignore[import-not-found]
|
|
41
|
+
|
|
42
|
+
configure_encoding()
|
|
43
|
+
except Exception:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
27
47
|
def _has_curated_jsonl_entry(jsonl_path: Path) -> bool:
|
|
28
48
|
"""Return True iff jsonl has at least one row with a ``file`` field.
|
|
29
49
|
|
|
@@ -54,10 +74,32 @@ def read_file(path: Path, fallback: str = "") -> str:
|
|
|
54
74
|
return fallback
|
|
55
75
|
|
|
56
76
|
|
|
57
|
-
def
|
|
77
|
+
def _resolve_context_key(project_dir: Path, hook_input: dict) -> str | None:
|
|
78
|
+
scripts_dir = project_dir / ".trellis" / "scripts"
|
|
79
|
+
if str(scripts_dir) not in sys.path:
|
|
80
|
+
sys.path.insert(0, str(scripts_dir))
|
|
81
|
+
try:
|
|
82
|
+
from common.active_task import resolve_context_key # type: ignore[import-not-found]
|
|
83
|
+
except Exception:
|
|
84
|
+
return None
|
|
85
|
+
return resolve_context_key(hook_input, platform="codex")
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _resolve_active_task(trellis_dir: Path, hook_input: dict):
|
|
89
|
+
scripts_dir = trellis_dir / "scripts"
|
|
90
|
+
if str(scripts_dir) not in sys.path:
|
|
91
|
+
sys.path.insert(0, str(scripts_dir))
|
|
92
|
+
from common.active_task import resolve_active_task # type: ignore[import-not-found]
|
|
93
|
+
|
|
94
|
+
return resolve_active_task(trellis_dir.parent, hook_input, platform="codex")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def run_script(script_path: Path, context_key: str | None = None) -> str:
|
|
58
98
|
try:
|
|
59
99
|
env = os.environ.copy()
|
|
60
100
|
env["PYTHONIOENCODING"] = "utf-8"
|
|
101
|
+
if context_key:
|
|
102
|
+
env["TRELLIS_CONTEXT_ID"] = context_key
|
|
61
103
|
cmd = [sys.executable, "-W", "ignore", str(script_path)]
|
|
62
104
|
result = subprocess.run(
|
|
63
105
|
cmd,
|
|
@@ -103,18 +145,15 @@ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
|
|
|
103
145
|
return trellis_dir / "tasks" / path_obj
|
|
104
146
|
|
|
105
147
|
|
|
106
|
-
def _get_task_status(trellis_dir: Path) -> str:
|
|
107
|
-
|
|
108
|
-
if not
|
|
109
|
-
return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
|
|
110
|
-
|
|
111
|
-
task_ref = _normalize_task_ref(current_task_file.read_text(encoding="utf-8").strip())
|
|
112
|
-
if not task_ref:
|
|
113
|
-
return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
|
|
148
|
+
def _get_task_status(trellis_dir: Path, hook_input: dict) -> str:
|
|
149
|
+
active = _resolve_active_task(trellis_dir, hook_input)
|
|
150
|
+
if not active.task_path:
|
|
151
|
+
return f"Status: NO ACTIVE TASK\nSource: {active.source}\nNext: Describe what you want to work on"
|
|
114
152
|
|
|
153
|
+
task_ref = active.task_path
|
|
115
154
|
task_dir = _resolve_task_dir(trellis_dir, task_ref)
|
|
116
|
-
if not task_dir.is_dir():
|
|
117
|
-
return f"Status: STALE POINTER\nTask: {task_ref}\nNext: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
|
|
155
|
+
if active.stale or not task_dir.is_dir():
|
|
156
|
+
return f"Status: STALE POINTER\nTask: {task_ref}\nSource: {active.source}\nNext: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
|
|
118
157
|
|
|
119
158
|
task_json_path = task_dir / "task.json"
|
|
120
159
|
task_data: dict = {}
|
|
@@ -128,7 +167,7 @@ def _get_task_status(trellis_dir: Path) -> str:
|
|
|
128
167
|
task_status = task_data.get("status", "unknown")
|
|
129
168
|
|
|
130
169
|
if task_status == "completed":
|
|
131
|
-
return f"Status: COMPLETED\nTask: {task_title}\nNext: Archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}` or start a new task"
|
|
170
|
+
return f"Status: COMPLETED\nTask: {task_title}\nSource: {active.source}\nNext: Archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}` or start a new task"
|
|
132
171
|
|
|
133
172
|
has_context = False
|
|
134
173
|
for jsonl_name in ("implement.jsonl", "check.jsonl", "spec.jsonl"):
|
|
@@ -140,12 +179,22 @@ def _get_task_status(trellis_dir: Path) -> str:
|
|
|
140
179
|
has_prd = (task_dir / "prd.md").is_file()
|
|
141
180
|
|
|
142
181
|
if not has_prd:
|
|
143
|
-
return f"Status: NOT READY\nTask: {task_title}\nMissing: prd.md not created\nNext: Write PRD (see workflow.md Phase 1.1) then curate implement.jsonl per Phase 1.3"
|
|
182
|
+
return f"Status: NOT READY\nTask: {task_title}\nSource: {active.source}\nMissing: prd.md not created\nNext: Write PRD (see workflow.md Phase 1.1) then curate implement.jsonl per Phase 1.3"
|
|
144
183
|
|
|
145
184
|
if not has_context:
|
|
146
|
-
return f"Status: NOT READY\nTask: {task_title}\nMissing: implement.jsonl / check.jsonl missing or empty\nNext: Curate entries per workflow.md Phase 1.3 (spec + research files only), then `task.py start`"
|
|
147
|
-
|
|
148
|
-
return
|
|
185
|
+
return f"Status: NOT READY\nTask: {task_title}\nSource: {active.source}\nMissing: implement.jsonl / check.jsonl missing or empty\nNext: Curate entries per workflow.md Phase 1.3 (spec + research files only), then `task.py start`"
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
f"Status: READY\nTask: {task_title}\n"
|
|
189
|
+
f"Source: {active.source}\n"
|
|
190
|
+
"Next required action: dispatch `trellis-implement` per Phase 2.1. "
|
|
191
|
+
"For agent-capable platforms, the default is to NOT edit code in the main session. "
|
|
192
|
+
"After implementation, dispatch `trellis-check` per Phase 2.2 before reporting completion.\n"
|
|
193
|
+
"User override (per-turn escape hatch): if the user's CURRENT message explicitly tells the "
|
|
194
|
+
"main session to handle it directly (\"你直接改\" / \"别派 sub-agent\" / \"main session 写就行\" / "
|
|
195
|
+
"\"do it inline\" / \"不用 sub-agent\"), honor it for this turn and edit code directly. "
|
|
196
|
+
"Per-turn only; do NOT invent an override the user did not say."
|
|
197
|
+
)
|
|
149
198
|
|
|
150
199
|
|
|
151
200
|
def _extract_range(content: str, start_header: str, end_header: str) -> str:
|
|
@@ -199,11 +248,17 @@ def main() -> None:
|
|
|
199
248
|
# Read hook input from stdin
|
|
200
249
|
try:
|
|
201
250
|
hook_input = json.loads(sys.stdin.read())
|
|
251
|
+
if not isinstance(hook_input, dict):
|
|
252
|
+
hook_input = {}
|
|
202
253
|
project_dir = Path(hook_input.get("cwd", ".")).resolve()
|
|
203
254
|
except (json.JSONDecodeError, KeyError):
|
|
255
|
+
hook_input = {}
|
|
204
256
|
project_dir = Path(".").resolve()
|
|
205
257
|
|
|
258
|
+
configure_project_encoding(project_dir)
|
|
259
|
+
|
|
206
260
|
trellis_dir = project_dir / ".trellis"
|
|
261
|
+
context_key = _resolve_context_key(project_dir, hook_input)
|
|
207
262
|
|
|
208
263
|
output = StringIO()
|
|
209
264
|
|
|
@@ -213,10 +268,12 @@ Read and follow all instructions below carefully.
|
|
|
213
268
|
</session-context>
|
|
214
269
|
|
|
215
270
|
""")
|
|
271
|
+
output.write(FIRST_REPLY_NOTICE)
|
|
272
|
+
output.write("\n\n")
|
|
216
273
|
|
|
217
274
|
output.write("<current-state>\n")
|
|
218
275
|
context_script = trellis_dir / "scripts" / "get_context.py"
|
|
219
|
-
output.write(run_script(context_script))
|
|
276
|
+
output.write(run_script(context_script, context_key))
|
|
220
277
|
output.write("\n</current-state>\n\n")
|
|
221
278
|
|
|
222
279
|
output.write("<workflow>\n")
|
|
@@ -231,8 +288,11 @@ Read and follow all instructions below carefully.
|
|
|
231
288
|
"- If you're spawning an implement/check sub-agent, context is injected "
|
|
232
289
|
"automatically via `{task}/implement.jsonl` / `check.jsonl`. You do NOT "
|
|
233
290
|
"need to read these indexes yourself.\n"
|
|
234
|
-
"-
|
|
235
|
-
"
|
|
291
|
+
"- For agent-capable platforms, the default is to dispatch "
|
|
292
|
+
"`trellis-implement` and `trellis-check` (so JSONL context is loaded by "
|
|
293
|
+
"the sub-agents) rather than editing code in the main session. "
|
|
294
|
+
"Honor a per-turn user override only if the user's current message "
|
|
295
|
+
"explicitly opts out (see <task-status> below for override phrases).\n\n"
|
|
236
296
|
)
|
|
237
297
|
|
|
238
298
|
# guides/ inlined (cross-package thinking, broadly useful)
|
|
@@ -276,13 +336,13 @@ Read and follow all instructions below carefully.
|
|
|
276
336
|
)
|
|
277
337
|
output.write("</guidelines>\n\n")
|
|
278
338
|
|
|
279
|
-
task_status = _get_task_status(trellis_dir)
|
|
339
|
+
task_status = _get_task_status(trellis_dir, hook_input)
|
|
280
340
|
output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
|
|
281
341
|
|
|
282
342
|
output.write("""<ready>
|
|
283
343
|
Context loaded. Workflow index, project state, and guidelines are already injected above — do NOT re-read them.
|
|
284
|
-
|
|
285
|
-
If
|
|
344
|
+
When the user sends the first message, follow <task-status> and the workflow guide.
|
|
345
|
+
If a task is READY, execute its Next required action without asking whether to continue.
|
|
286
346
|
</ready>""")
|
|
287
347
|
|
|
288
348
|
context = output.getvalue()
|
|
@@ -269,7 +269,7 @@ python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" check "<path>" "<reas
|
|
|
269
269
|
python3 ./.trellis/scripts/task.py start "$TASK_DIR"
|
|
270
270
|
```
|
|
271
271
|
|
|
272
|
-
This sets
|
|
272
|
+
This sets the active task through Trellis' session resolver so hooks can inject context for this AI session. If the command fails because no session identity is available, rerun it from an IDE/session that exposes session identity or set `TRELLIS_CONTEXT_ID`.
|
|
273
273
|
|
|
274
274
|
---
|
|
275
275
|
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
"""
|
|
4
|
-
Copilot Session Start Hook -
|
|
4
|
+
Copilot Session Start Hook - Emit Trellis session-start diagnostics.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
GitHub Copilot's documented SessionStart behavior ignores hook output, so this
|
|
7
|
+
script must not be treated as proof that model-visible context was injected.
|
|
8
|
+
The JSON shape is kept for parity with other Trellis hooks and future host
|
|
9
|
+
support, but current Copilot users should rely on UserPromptSubmit breadcrumbs
|
|
10
|
+
and hook logs instead.
|
|
8
11
|
"""
|
|
9
12
|
|
|
10
13
|
from __future__ import annotations
|
|
@@ -24,6 +27,20 @@ def should_skip_injection() -> bool:
|
|
|
24
27
|
return os.environ.get("COPILOT_NON_INTERACTIVE") == "1"
|
|
25
28
|
|
|
26
29
|
|
|
30
|
+
def configure_project_encoding(project_dir: Path) -> None:
|
|
31
|
+
"""Reuse Trellis' shared Windows stdio encoding helper before JSON output."""
|
|
32
|
+
scripts_dir = project_dir / ".trellis" / "scripts"
|
|
33
|
+
if str(scripts_dir) not in sys.path:
|
|
34
|
+
sys.path.insert(0, str(scripts_dir))
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
from common import configure_encoding # type: ignore[import-not-found]
|
|
38
|
+
|
|
39
|
+
configure_encoding()
|
|
40
|
+
except Exception:
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
27
44
|
def _has_curated_jsonl_entry(jsonl_path: Path) -> bool:
|
|
28
45
|
"""Return True iff jsonl has at least one row with a ``file`` field.
|
|
29
46
|
|
|
@@ -54,10 +71,32 @@ def read_file(path: Path, fallback: str = "") -> str:
|
|
|
54
71
|
return fallback
|
|
55
72
|
|
|
56
73
|
|
|
57
|
-
def
|
|
74
|
+
def _resolve_context_key(project_dir: Path, hook_input: dict) -> str | None:
|
|
75
|
+
scripts_dir = project_dir / ".trellis" / "scripts"
|
|
76
|
+
if str(scripts_dir) not in sys.path:
|
|
77
|
+
sys.path.insert(0, str(scripts_dir))
|
|
78
|
+
try:
|
|
79
|
+
from common.active_task import resolve_context_key # type: ignore[import-not-found]
|
|
80
|
+
except Exception:
|
|
81
|
+
return None
|
|
82
|
+
return resolve_context_key(hook_input, platform="copilot")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _resolve_active_task(trellis_dir: Path, hook_input: dict):
|
|
86
|
+
scripts_dir = trellis_dir / "scripts"
|
|
87
|
+
if str(scripts_dir) not in sys.path:
|
|
88
|
+
sys.path.insert(0, str(scripts_dir))
|
|
89
|
+
from common.active_task import resolve_active_task # type: ignore[import-not-found]
|
|
90
|
+
|
|
91
|
+
return resolve_active_task(trellis_dir.parent, hook_input, platform="copilot")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def run_script(script_path: Path, context_key: str | None = None) -> str:
|
|
58
95
|
try:
|
|
59
96
|
env = os.environ.copy()
|
|
60
97
|
env["PYTHONIOENCODING"] = "utf-8"
|
|
98
|
+
if context_key:
|
|
99
|
+
env["TRELLIS_CONTEXT_ID"] = context_key
|
|
61
100
|
cmd = [sys.executable, "-W", "ignore", str(script_path)]
|
|
62
101
|
result = subprocess.run(
|
|
63
102
|
cmd,
|
|
@@ -103,18 +142,15 @@ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
|
|
|
103
142
|
return trellis_dir / "tasks" / path_obj
|
|
104
143
|
|
|
105
144
|
|
|
106
|
-
def _get_task_status(trellis_dir: Path) -> str:
|
|
107
|
-
|
|
108
|
-
if not
|
|
109
|
-
return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
|
|
110
|
-
|
|
111
|
-
task_ref = _normalize_task_ref(current_task_file.read_text(encoding="utf-8").strip())
|
|
112
|
-
if not task_ref:
|
|
113
|
-
return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
|
|
145
|
+
def _get_task_status(trellis_dir: Path, hook_input: dict) -> str:
|
|
146
|
+
active = _resolve_active_task(trellis_dir, hook_input)
|
|
147
|
+
if not active.task_path:
|
|
148
|
+
return f"Status: NO ACTIVE TASK\nSource: {active.source}\nNext: Describe what you want to work on"
|
|
114
149
|
|
|
150
|
+
task_ref = active.task_path
|
|
115
151
|
task_dir = _resolve_task_dir(trellis_dir, task_ref)
|
|
116
|
-
if not task_dir.is_dir():
|
|
117
|
-
return f"Status: STALE POINTER\nTask: {task_ref}\nNext: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
|
|
152
|
+
if active.stale or not task_dir.is_dir():
|
|
153
|
+
return f"Status: STALE POINTER\nTask: {task_ref}\nSource: {active.source}\nNext: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
|
|
118
154
|
|
|
119
155
|
task_json_path = task_dir / "task.json"
|
|
120
156
|
task_data: dict = {}
|
|
@@ -128,7 +164,7 @@ def _get_task_status(trellis_dir: Path) -> str:
|
|
|
128
164
|
task_status = task_data.get("status", "unknown")
|
|
129
165
|
|
|
130
166
|
if task_status == "completed":
|
|
131
|
-
return f"Status: COMPLETED\nTask: {task_title}\nNext: Archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}` or start a new task"
|
|
167
|
+
return f"Status: COMPLETED\nTask: {task_title}\nSource: {active.source}\nNext: Archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}` or start a new task"
|
|
132
168
|
|
|
133
169
|
has_context = False
|
|
134
170
|
for jsonl_name in ("implement.jsonl", "check.jsonl", "spec.jsonl"):
|
|
@@ -140,12 +176,22 @@ def _get_task_status(trellis_dir: Path) -> str:
|
|
|
140
176
|
has_prd = (task_dir / "prd.md").is_file()
|
|
141
177
|
|
|
142
178
|
if not has_prd:
|
|
143
|
-
return f"Status: NOT READY\nTask: {task_title}\nMissing: prd.md not created\nNext: Write PRD (see workflow.md Phase 1.1) then curate implement.jsonl per Phase 1.3"
|
|
179
|
+
return f"Status: NOT READY\nTask: {task_title}\nSource: {active.source}\nMissing: prd.md not created\nNext: Write PRD (see workflow.md Phase 1.1) then curate implement.jsonl per Phase 1.3"
|
|
144
180
|
|
|
145
181
|
if not has_context:
|
|
146
|
-
return f"Status: NOT READY\nTask: {task_title}\nMissing: implement.jsonl / check.jsonl missing or empty\nNext: Curate entries per workflow.md Phase 1.3 (spec + research files only), then `task.py start`"
|
|
147
|
-
|
|
148
|
-
return
|
|
182
|
+
return f"Status: NOT READY\nTask: {task_title}\nSource: {active.source}\nMissing: implement.jsonl / check.jsonl missing or empty\nNext: Curate entries per workflow.md Phase 1.3 (spec + research files only), then `task.py start`"
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
f"Status: READY\nTask: {task_title}\n"
|
|
186
|
+
f"Source: {active.source}\n"
|
|
187
|
+
"Next required action: dispatch `trellis-implement` per Phase 2.1. "
|
|
188
|
+
"For agent-capable platforms, the default is to NOT edit code in the main session. "
|
|
189
|
+
"After implementation, dispatch `trellis-check` per Phase 2.2 before reporting completion.\n"
|
|
190
|
+
"User override (per-turn escape hatch): if the user's CURRENT message explicitly tells the "
|
|
191
|
+
"main session to handle it directly (\"你直接改\" / \"别派 sub-agent\" / \"main session 写就行\" / "
|
|
192
|
+
"\"do it inline\" / \"不用 sub-agent\"), honor it for this turn and edit code directly. "
|
|
193
|
+
"Per-turn only; do NOT invent an override the user did not say."
|
|
194
|
+
)
|
|
149
195
|
|
|
150
196
|
|
|
151
197
|
def _extract_range(content: str, start_header: str, end_header: str) -> str:
|
|
@@ -199,11 +245,17 @@ def main() -> None:
|
|
|
199
245
|
# Read hook input from stdin
|
|
200
246
|
try:
|
|
201
247
|
hook_input = json.loads(sys.stdin.read())
|
|
248
|
+
if not isinstance(hook_input, dict):
|
|
249
|
+
hook_input = {}
|
|
202
250
|
project_dir = Path(hook_input.get("cwd", ".")).resolve()
|
|
203
251
|
except (json.JSONDecodeError, KeyError):
|
|
252
|
+
hook_input = {}
|
|
204
253
|
project_dir = Path(".").resolve()
|
|
205
254
|
|
|
255
|
+
configure_project_encoding(project_dir)
|
|
256
|
+
|
|
206
257
|
trellis_dir = project_dir / ".trellis"
|
|
258
|
+
context_key = _resolve_context_key(project_dir, hook_input)
|
|
207
259
|
|
|
208
260
|
output = StringIO()
|
|
209
261
|
|
|
@@ -216,7 +268,7 @@ Read and follow all instructions below carefully.
|
|
|
216
268
|
|
|
217
269
|
output.write("<current-state>\n")
|
|
218
270
|
context_script = trellis_dir / "scripts" / "get_context.py"
|
|
219
|
-
output.write(run_script(context_script))
|
|
271
|
+
output.write(run_script(context_script, context_key))
|
|
220
272
|
output.write("\n</current-state>\n\n")
|
|
221
273
|
|
|
222
274
|
output.write("<workflow>\n")
|
|
@@ -231,8 +283,11 @@ Read and follow all instructions below carefully.
|
|
|
231
283
|
"- If you're spawning an implement/check sub-agent, context is injected "
|
|
232
284
|
"automatically via `{task}/implement.jsonl` / `check.jsonl`. You do NOT "
|
|
233
285
|
"need to read these indexes yourself.\n"
|
|
234
|
-
"-
|
|
235
|
-
"
|
|
286
|
+
"- For agent-capable platforms, the default is to dispatch "
|
|
287
|
+
"`trellis-implement` and `trellis-check` (so JSONL context is loaded by "
|
|
288
|
+
"the sub-agents) rather than editing code in the main session. "
|
|
289
|
+
"Honor a per-turn user override only if the user's current message "
|
|
290
|
+
"explicitly opts out (see <task-status> below for override phrases).\n\n"
|
|
236
291
|
)
|
|
237
292
|
|
|
238
293
|
# guides/ inlined (cross-package thinking, broadly useful)
|
|
@@ -276,19 +331,22 @@ Read and follow all instructions below carefully.
|
|
|
276
331
|
)
|
|
277
332
|
output.write("</guidelines>\n\n")
|
|
278
333
|
|
|
279
|
-
task_status = _get_task_status(trellis_dir)
|
|
334
|
+
task_status = _get_task_status(trellis_dir, hook_input)
|
|
280
335
|
output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
|
|
281
336
|
|
|
282
337
|
output.write("""<ready>
|
|
283
338
|
Context loaded. Workflow index, project state, and guidelines are already injected above — do NOT re-read them.
|
|
284
|
-
|
|
285
|
-
If
|
|
339
|
+
When the user sends the first message, follow <task-status> and the workflow guide.
|
|
340
|
+
If a task is READY, execute its Next required action without asking whether to continue.
|
|
286
341
|
</ready>""")
|
|
287
342
|
|
|
288
343
|
context = output.getvalue()
|
|
289
344
|
result = {
|
|
290
345
|
"suppressOutput": True,
|
|
291
|
-
"systemMessage":
|
|
346
|
+
"systemMessage": (
|
|
347
|
+
f"Trellis SessionStart diagnostics emitted ({len(context)} chars); "
|
|
348
|
+
"Copilot currently ignores sessionStart hook output."
|
|
349
|
+
),
|
|
292
350
|
"hookSpecificOutput": {
|
|
293
351
|
"hookEventName": "SessionStart",
|
|
294
352
|
"additionalContext": context,
|
|
@@ -298,7 +298,7 @@ python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" check "<path>" "<reas
|
|
|
298
298
|
python3 ./.trellis/scripts/task.py start "$TASK_DIR"
|
|
299
299
|
```
|
|
300
300
|
|
|
301
|
-
This sets
|
|
301
|
+
This sets the active task through Trellis' session resolver so hooks can inject context for this AI session. If the command fails because no session identity is available, rerun it from an IDE/session that exposes session identity or set `TRELLIS_CONTEXT_ID`.
|
|
302
302
|
|
|
303
303
|
---
|
|
304
304
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: trellis-check
|
|
3
3
|
description: |
|
|
4
|
-
|
|
4
|
+
Trellis quality check agent. Use this exact agent for Trellis task verification, check.jsonl context injection, and self-fixing code review. Do not use generic/default/generalPurpose agents for Trellis checks.
|
|
5
5
|
tools: Read, Write, Edit, Bash, Glob, Grep, mcp__exa__web_search_exa, mcp__exa__get_code_context_exa
|
|
6
6
|
---
|
|
7
7
|
# Check Agent
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: trellis-implement
|
|
3
3
|
description: |
|
|
4
|
-
|
|
4
|
+
Trellis implementation agent. Use this exact agent for Trellis task implementation, implement.jsonl context injection, and hook-injection tests. Do not use generic/default/generalPurpose agents for Trellis implementation. No git commit allowed.
|
|
5
5
|
tools: Read, Write, Edit, Bash, Glob, Grep, mcp__exa__web_search_exa, mcp__exa__get_code_context_exa
|
|
6
6
|
---
|
|
7
7
|
# Implement Agent
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: trellis-research
|
|
3
3
|
description: |
|
|
4
|
-
|
|
4
|
+
Trellis research agent. Use this exact agent for Trellis task research and research/ persistence. Do not use generic/default/generalPurpose agents for Trellis research.
|
|
5
5
|
tools: Read, Write, Glob, Grep, Bash, mcp__exa__web_search_exa, mcp__exa__get_code_context_exa, Skill, mcp__chrome-devtools__*
|
|
6
6
|
---
|
|
7
7
|
# Research Agent
|
|
@@ -29,7 +29,7 @@ Conversations get compacted; files don't. Every research output MUST end up as a
|
|
|
29
29
|
|
|
30
30
|
### Step 1: Resolve Current Task
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Run `python3 ./.trellis/scripts/task.py current --source` → active task path. If no active task is set, ask the user where to write output; do NOT guess.
|
|
33
33
|
|
|
34
34
|
Ensure `{TASK_DIR}/research/` exists:
|
|
35
35
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"preToolUse": [
|
|
5
5
|
{
|
|
6
6
|
"command": "{{PYTHON_CMD}} .cursor/hooks/inject-subagent-context.py",
|
|
7
|
-
"matcher": "Task",
|
|
7
|
+
"matcher": "Task|Subagent",
|
|
8
8
|
"timeout": 30
|
|
9
9
|
}
|
|
10
10
|
],
|
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
"command": "{{PYTHON_CMD}} .cursor/hooks/inject-workflow-state.py",
|
|
20
20
|
"timeout": 5
|
|
21
21
|
}
|
|
22
|
+
],
|
|
23
|
+
"beforeShellExecution": [
|
|
24
|
+
{
|
|
25
|
+
"command": "{{PYTHON_CMD}} .cursor/hooks/inject-shell-session-context.py",
|
|
26
|
+
"timeout": 5
|
|
27
|
+
}
|
|
22
28
|
]
|
|
23
29
|
}
|
|
24
30
|
}
|
|
@@ -29,7 +29,7 @@ Conversations get compacted; files don't. Every research output MUST end up as a
|
|
|
29
29
|
|
|
30
30
|
### Step 1: Resolve Current Task
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Run `python3 ./.trellis/scripts/task.py current --source` → active task path. If no active task is set, ask the user where to write output; do NOT guess.
|
|
33
33
|
|
|
34
34
|
Ensure `{TASK_DIR}/research/` exists:
|
|
35
35
|
|
|
@@ -13,6 +13,12 @@ export declare function getClaudeTemplatePath(): string;
|
|
|
13
13
|
* Get the path to the opencode templates directory (agents, plugins, lib).
|
|
14
14
|
*/
|
|
15
15
|
export declare function getOpenCodeTemplatePath(): string;
|
|
16
|
+
/**
|
|
17
|
+
* Get the path to the Pi Agent templates directory (agents, extension, settings).
|
|
18
|
+
*/
|
|
19
|
+
export declare function getPiTemplatePath(): string;
|
|
20
|
+
/** @deprecated Use getPiTemplatePath() instead. */
|
|
21
|
+
export declare function getPiSourcePath(): string;
|
|
16
22
|
/**
|
|
17
23
|
* Read a file from the trellis template directory.
|
|
18
24
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/templates/extract.ts"],"names":[],"mappings":"AAQA,KAAK,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAE5D;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAQ/C;AAED,wDAAwD;AACxD,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAQ9C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAQhD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,MAAM,GACf,MAAM,CAGR;AAED,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/templates/extract.ts"],"names":[],"mappings":"AAQA,KAAK,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAE5D;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAQ/C;AAED,wDAAwD;AACxD,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAQ9C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAQhD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAQ1C;AAED,mDAAmD;AACnD,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,MAAM,GACf,MAAM,CAGR;AAED,wBAAgB,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
|
@@ -38,6 +38,20 @@ export function getOpenCodeTemplatePath() {
|
|
|
38
38
|
}
|
|
39
39
|
throw new Error("Could not find opencode templates directory. Expected at templates/opencode/");
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Get the path to the Pi Agent templates directory (agents, extension, settings).
|
|
43
|
+
*/
|
|
44
|
+
export function getPiTemplatePath() {
|
|
45
|
+
const templatePath = path.join(__dirname, "pi");
|
|
46
|
+
if (fs.existsSync(templatePath)) {
|
|
47
|
+
return templatePath;
|
|
48
|
+
}
|
|
49
|
+
throw new Error("Could not find pi templates directory. Expected at templates/pi/");
|
|
50
|
+
}
|
|
51
|
+
/** @deprecated Use getPiTemplatePath() instead. */
|
|
52
|
+
export function getPiSourcePath() {
|
|
53
|
+
return getPiTemplatePath();
|
|
54
|
+
}
|
|
41
55
|
/**
|
|
42
56
|
* Read a file from the trellis template directory.
|
|
43
57
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/templates/extract.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/templates/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ Conversations get compacted; files don't. Every research output MUST end up as a
|
|
|
29
29
|
|
|
30
30
|
### Step 1: Resolve Current Task
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Run `python3 ./.trellis/scripts/task.py current --source` → active task path. If no active task is set, ask the user where to write output; do NOT guess.
|
|
33
33
|
|
|
34
34
|
Ensure `{TASK_DIR}/research/` exists:
|
|
35
35
|
|