@mindfoldhq/trellis 0.5.0-beta.14 → 0.5.0-beta.16
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 +44 -13
- 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/opencode.d.ts.map +1 -1
- package/dist/configurators/opencode.js +4 -1
- package/dist/configurators/opencode.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.15.json +116 -0
- package/dist/migrations/manifests/0.5.0-beta.16.json +9 -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 +51 -21
- package/dist/templates/codex/skills/start/SKILL.md +1 -1
- package/dist/templates/copilot/hooks/session-start.py +51 -21
- 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 +48 -25
- package/dist/templates/opencode/plugins/session-start.js +29 -16
- 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 +99 -62
- package/dist/templates/shared-hooks/session-start.py +139 -24
- 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 +6 -8
- package/dist/templates/trellis/scripts/task.py +59 -17
- package/dist/templates/trellis/workflow.md +30 -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/posix.d.ts +13 -0
- package/dist/utils/posix.d.ts.map +1 -0
- package/dist/utils/posix.js +15 -0
- package/dist/utils/posix.js.map +1 -0
- 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 +22 -3
- package/dist/utils/template-hash.d.ts.map +1 -1
- package/dist/utils/template-hash.js +80 -18
- package/dist/utils/template-hash.js.map +1 -1
- package/package.json +1 -1
- package/dist/templates/shared-hooks/statusline.py +0 -219
|
@@ -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
|
|
|
@@ -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.
|
|
@@ -74,10 +74,32 @@ def read_file(path: Path, fallback: str = "") -> str:
|
|
|
74
74
|
return fallback
|
|
75
75
|
|
|
76
76
|
|
|
77
|
-
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:
|
|
78
98
|
try:
|
|
79
99
|
env = os.environ.copy()
|
|
80
100
|
env["PYTHONIOENCODING"] = "utf-8"
|
|
101
|
+
if context_key:
|
|
102
|
+
env["TRELLIS_CONTEXT_ID"] = context_key
|
|
81
103
|
cmd = [sys.executable, "-W", "ignore", str(script_path)]
|
|
82
104
|
result = subprocess.run(
|
|
83
105
|
cmd,
|
|
@@ -123,18 +145,15 @@ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
|
|
|
123
145
|
return trellis_dir / "tasks" / path_obj
|
|
124
146
|
|
|
125
147
|
|
|
126
|
-
def _get_task_status(trellis_dir: Path) -> str:
|
|
127
|
-
|
|
128
|
-
if not
|
|
129
|
-
return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
|
|
130
|
-
|
|
131
|
-
task_ref = _normalize_task_ref(current_task_file.read_text(encoding="utf-8").strip())
|
|
132
|
-
if not task_ref:
|
|
133
|
-
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"
|
|
134
152
|
|
|
153
|
+
task_ref = active.task_path
|
|
135
154
|
task_dir = _resolve_task_dir(trellis_dir, task_ref)
|
|
136
|
-
if not task_dir.is_dir():
|
|
137
|
-
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"
|
|
138
157
|
|
|
139
158
|
task_json_path = task_dir / "task.json"
|
|
140
159
|
task_data: dict = {}
|
|
@@ -148,7 +167,7 @@ def _get_task_status(trellis_dir: Path) -> str:
|
|
|
148
167
|
task_status = task_data.get("status", "unknown")
|
|
149
168
|
|
|
150
169
|
if task_status == "completed":
|
|
151
|
-
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"
|
|
152
171
|
|
|
153
172
|
has_context = False
|
|
154
173
|
for jsonl_name in ("implement.jsonl", "check.jsonl", "spec.jsonl"):
|
|
@@ -160,16 +179,21 @@ def _get_task_status(trellis_dir: Path) -> str:
|
|
|
160
179
|
has_prd = (task_dir / "prd.md").is_file()
|
|
161
180
|
|
|
162
181
|
if not has_prd:
|
|
163
|
-
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"
|
|
164
183
|
|
|
165
184
|
if not has_context:
|
|
166
|
-
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`"
|
|
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`"
|
|
167
186
|
|
|
168
187
|
return (
|
|
169
188
|
f"Status: READY\nTask: {task_title}\n"
|
|
189
|
+
f"Source: {active.source}\n"
|
|
170
190
|
"Next required action: dispatch `trellis-implement` per Phase 2.1. "
|
|
171
|
-
"For agent-capable platforms,
|
|
172
|
-
"After implementation, dispatch `trellis-check` per Phase 2.2 before reporting completion
|
|
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."
|
|
173
197
|
)
|
|
174
198
|
|
|
175
199
|
|
|
@@ -224,13 +248,17 @@ def main() -> None:
|
|
|
224
248
|
# Read hook input from stdin
|
|
225
249
|
try:
|
|
226
250
|
hook_input = json.loads(sys.stdin.read())
|
|
251
|
+
if not isinstance(hook_input, dict):
|
|
252
|
+
hook_input = {}
|
|
227
253
|
project_dir = Path(hook_input.get("cwd", ".")).resolve()
|
|
228
254
|
except (json.JSONDecodeError, KeyError):
|
|
255
|
+
hook_input = {}
|
|
229
256
|
project_dir = Path(".").resolve()
|
|
230
257
|
|
|
231
258
|
configure_project_encoding(project_dir)
|
|
232
259
|
|
|
233
260
|
trellis_dir = project_dir / ".trellis"
|
|
261
|
+
context_key = _resolve_context_key(project_dir, hook_input)
|
|
234
262
|
|
|
235
263
|
output = StringIO()
|
|
236
264
|
|
|
@@ -245,7 +273,7 @@ Read and follow all instructions below carefully.
|
|
|
245
273
|
|
|
246
274
|
output.write("<current-state>\n")
|
|
247
275
|
context_script = trellis_dir / "scripts" / "get_context.py"
|
|
248
|
-
output.write(run_script(context_script))
|
|
276
|
+
output.write(run_script(context_script, context_key))
|
|
249
277
|
output.write("\n</current-state>\n\n")
|
|
250
278
|
|
|
251
279
|
output.write("<workflow>\n")
|
|
@@ -260,9 +288,11 @@ Read and follow all instructions below carefully.
|
|
|
260
288
|
"- If you're spawning an implement/check sub-agent, context is injected "
|
|
261
289
|
"automatically via `{task}/implement.jsonl` / `check.jsonl`. You do NOT "
|
|
262
290
|
"need to read these indexes yourself.\n"
|
|
263
|
-
"- For agent-capable platforms,
|
|
264
|
-
"
|
|
265
|
-
"
|
|
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"
|
|
266
296
|
)
|
|
267
297
|
|
|
268
298
|
# guides/ inlined (cross-package thinking, broadly useful)
|
|
@@ -306,7 +336,7 @@ Read and follow all instructions below carefully.
|
|
|
306
336
|
)
|
|
307
337
|
output.write("</guidelines>\n\n")
|
|
308
338
|
|
|
309
|
-
task_status = _get_task_status(trellis_dir)
|
|
339
|
+
task_status = _get_task_status(trellis_dir, hook_input)
|
|
310
340
|
output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
|
|
311
341
|
|
|
312
342
|
output.write("""<ready>
|
|
@@ -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
|
|
|
@@ -71,10 +71,32 @@ def read_file(path: Path, fallback: str = "") -> str:
|
|
|
71
71
|
return fallback
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
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:
|
|
75
95
|
try:
|
|
76
96
|
env = os.environ.copy()
|
|
77
97
|
env["PYTHONIOENCODING"] = "utf-8"
|
|
98
|
+
if context_key:
|
|
99
|
+
env["TRELLIS_CONTEXT_ID"] = context_key
|
|
78
100
|
cmd = [sys.executable, "-W", "ignore", str(script_path)]
|
|
79
101
|
result = subprocess.run(
|
|
80
102
|
cmd,
|
|
@@ -120,18 +142,15 @@ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
|
|
|
120
142
|
return trellis_dir / "tasks" / path_obj
|
|
121
143
|
|
|
122
144
|
|
|
123
|
-
def _get_task_status(trellis_dir: Path) -> str:
|
|
124
|
-
|
|
125
|
-
if not
|
|
126
|
-
return "Status: NO ACTIVE TASK\nNext: Describe what you want to work on"
|
|
127
|
-
|
|
128
|
-
task_ref = _normalize_task_ref(current_task_file.read_text(encoding="utf-8").strip())
|
|
129
|
-
if not task_ref:
|
|
130
|
-
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"
|
|
131
149
|
|
|
150
|
+
task_ref = active.task_path
|
|
132
151
|
task_dir = _resolve_task_dir(trellis_dir, task_ref)
|
|
133
|
-
if not task_dir.is_dir():
|
|
134
|
-
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"
|
|
135
154
|
|
|
136
155
|
task_json_path = task_dir / "task.json"
|
|
137
156
|
task_data: dict = {}
|
|
@@ -145,7 +164,7 @@ def _get_task_status(trellis_dir: Path) -> str:
|
|
|
145
164
|
task_status = task_data.get("status", "unknown")
|
|
146
165
|
|
|
147
166
|
if task_status == "completed":
|
|
148
|
-
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"
|
|
149
168
|
|
|
150
169
|
has_context = False
|
|
151
170
|
for jsonl_name in ("implement.jsonl", "check.jsonl", "spec.jsonl"):
|
|
@@ -157,16 +176,21 @@ def _get_task_status(trellis_dir: Path) -> str:
|
|
|
157
176
|
has_prd = (task_dir / "prd.md").is_file()
|
|
158
177
|
|
|
159
178
|
if not has_prd:
|
|
160
|
-
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"
|
|
161
180
|
|
|
162
181
|
if not has_context:
|
|
163
|
-
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`"
|
|
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`"
|
|
164
183
|
|
|
165
184
|
return (
|
|
166
185
|
f"Status: READY\nTask: {task_title}\n"
|
|
186
|
+
f"Source: {active.source}\n"
|
|
167
187
|
"Next required action: dispatch `trellis-implement` per Phase 2.1. "
|
|
168
|
-
"For agent-capable platforms,
|
|
169
|
-
"After implementation, dispatch `trellis-check` per Phase 2.2 before reporting completion
|
|
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."
|
|
170
194
|
)
|
|
171
195
|
|
|
172
196
|
|
|
@@ -221,13 +245,17 @@ def main() -> None:
|
|
|
221
245
|
# Read hook input from stdin
|
|
222
246
|
try:
|
|
223
247
|
hook_input = json.loads(sys.stdin.read())
|
|
248
|
+
if not isinstance(hook_input, dict):
|
|
249
|
+
hook_input = {}
|
|
224
250
|
project_dir = Path(hook_input.get("cwd", ".")).resolve()
|
|
225
251
|
except (json.JSONDecodeError, KeyError):
|
|
252
|
+
hook_input = {}
|
|
226
253
|
project_dir = Path(".").resolve()
|
|
227
254
|
|
|
228
255
|
configure_project_encoding(project_dir)
|
|
229
256
|
|
|
230
257
|
trellis_dir = project_dir / ".trellis"
|
|
258
|
+
context_key = _resolve_context_key(project_dir, hook_input)
|
|
231
259
|
|
|
232
260
|
output = StringIO()
|
|
233
261
|
|
|
@@ -240,7 +268,7 @@ Read and follow all instructions below carefully.
|
|
|
240
268
|
|
|
241
269
|
output.write("<current-state>\n")
|
|
242
270
|
context_script = trellis_dir / "scripts" / "get_context.py"
|
|
243
|
-
output.write(run_script(context_script))
|
|
271
|
+
output.write(run_script(context_script, context_key))
|
|
244
272
|
output.write("\n</current-state>\n\n")
|
|
245
273
|
|
|
246
274
|
output.write("<workflow>\n")
|
|
@@ -255,9 +283,11 @@ Read and follow all instructions below carefully.
|
|
|
255
283
|
"- If you're spawning an implement/check sub-agent, context is injected "
|
|
256
284
|
"automatically via `{task}/implement.jsonl` / `check.jsonl`. You do NOT "
|
|
257
285
|
"need to read these indexes yourself.\n"
|
|
258
|
-
"- For agent-capable platforms,
|
|
259
|
-
"
|
|
260
|
-
"
|
|
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"
|
|
261
291
|
)
|
|
262
292
|
|
|
263
293
|
# guides/ inlined (cross-package thinking, broadly useful)
|
|
@@ -301,7 +331,7 @@ Read and follow all instructions below carefully.
|
|
|
301
331
|
)
|
|
302
332
|
output.write("</guidelines>\n\n")
|
|
303
333
|
|
|
304
|
-
task_status = _get_task_status(trellis_dir)
|
|
334
|
+
task_status = _get_task_status(trellis_dir, hook_input)
|
|
305
335
|
output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
|
|
306
336
|
|
|
307
337
|
output.write("""<ready>
|
|
@@ -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
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trellis-research",
|
|
3
3
|
"description": "Code and tech search expert. Persists findings to {TASK_DIR}/research/. No writes outside that directory.",
|
|
4
|
-
"instructions": "# Research Agent\n\nYou are the Research Agent in the Trellis workflow.\n\n## Core Principle\n\n**You do one thing: find, explain, and PERSIST information.**\n\nConversations get compacted; files don't. Every research output MUST end up as a file under `{TASK_DIR}/research/`. Returning findings only through the chat reply is a failure — the caller cannot read them next session.\n\n---\n\n## Core Responsibilities\n\n1. **Internal Search** — locate files/components, understand code logic, discover patterns (Glob, Grep, Read)\n2. **External Search** — library docs, API references, best practices (web search)\n3. **Persist** — write each research topic to `{TASK_DIR}/research/<topic>.md`\n4. **Report** — return file paths + one-line summaries to the main agent (not full content)\n\n---\n\n## Workflow\n\n### Step 1: Resolve Current Task\n\
|
|
4
|
+
"instructions": "# Research Agent\n\nYou are the Research Agent in the Trellis workflow.\n\n## Core Principle\n\n**You do one thing: find, explain, and PERSIST information.**\n\nConversations get compacted; files don't. Every research output MUST end up as a file under `{TASK_DIR}/research/`. Returning findings only through the chat reply is a failure — the caller cannot read them next session.\n\n---\n\n## Core Responsibilities\n\n1. **Internal Search** — locate files/components, understand code logic, discover patterns (Glob, Grep, Read)\n2. **External Search** — library docs, API references, best practices (web search)\n3. **Persist** — write each research topic to `{TASK_DIR}/research/<topic>.md`\n4. **Report** — return file paths + one-line summaries to the main agent (not full content)\n\n---\n\n## Workflow\n\n### Step 1: Resolve Current Task\n\nRun `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.\n\nEnsure `{TASK_DIR}/research/` exists:\n\n```bash\nmkdir -p <TASK_DIR>/research\n```\n\n### Step 2: Understand Search Request\n\nClassify: internal / external / mixed. Determine scope (global / specific directory) and expected shape (file list / pattern notes / tech comparison).\n\n### Step 3: Execute Search\n\nRun independent searches in parallel (Glob + Grep + web) for efficiency.\n\n### Step 4: Persist Each Topic\n\nFor each distinct research topic, Write a markdown file at `{TASK_DIR}/research/<topic-slug>.md`. Use the File Format below.\n\n### Step 5: Report to Main Agent\n\nReply with ONLY:\n\n- List of files written (paths relative to repo root)\n- One-line summary per file\n- Any critical caveats that the main agent needs to know right now\n\nDo NOT paste full research content into the reply. The files are the contract.\n\n---\n\n## Scope Limits (Strict)\n\n### Write ALLOWED\n\n- `{TASK_DIR}/research/*.md` — your own output\n- Creating `{TASK_DIR}/research/` if it doesn't exist (via `mkdir -p`)\n\n### Write FORBIDDEN\n\n- Code files (`src/`, `lib/`, …)\n- Spec files (`.trellis/spec/`) — main agent should use `update-spec` skill instead\n- `.trellis/scripts/`, `.trellis/workflow.md`, platform config (`.claude/`, `.cursor/`, etc.)\n- Other task directories\n- Any git operation (commit / push / branch / merge)\n\nIf the user asks you to edit code, decline and suggest spawning `implement` instead.\n\n---\n\n## File Format\n\nEach `{TASK_DIR}/research/<topic>.md` should follow:\n\n```markdown\n# Research: <topic>\n\n- **Query**: <original query>\n- **Scope**: <internal / external / mixed>\n- **Date**: <YYYY-MM-DD>\n\n## Findings\n\n### Files Found\n\n| File Path | Description |\n|---|---|\n| `src/services/xxx.ts` | Main implementation |\n| `src/types/xxx.ts` | Type definitions |\n\n### Code Patterns\n\n<describe patterns, cite file:line>\n\n### External References\n\n- [Library X docs](url) — <why relevant, version constraints>\n\n### Related Specs\n\n- `.trellis/spec/xxx.md` — <description>\n\n## Caveats / Not Found\n\n<anything incomplete or uncertain>\n```\n\n---\n\n## Guidelines\n\n### DO\n\n- Provide specific file paths and line numbers\n- Quote actual code snippets\n- Persist every topic to its own file\n- Return file paths in your reply, not the full content\n- Mark \"not found\" explicitly when searches come up empty\n\n### DON'T\n\n- Don't write code or modify files outside `{TASK_DIR}/research/`\n- Don't guess uncertain info\n- Don't paste full research text into the reply (files are the deliverable)\n- Don't propose improvements or critique implementation (that's not your role)\n",
|
|
5
5
|
"tools": [
|
|
6
6
|
"read",
|
|
7
7
|
"write",
|
|
@@ -3,20 +3,19 @@
|
|
|
3
3
|
|
|
4
4
|
These instructions are for AI assistants working in this project.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
- Initialize your developer identity
|
|
8
|
-
- Understand current project context
|
|
9
|
-
- Read relevant guidelines
|
|
6
|
+
This project is managed by Trellis. The working knowledge you need lives under `.trellis/`:
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
8
|
+
- `.trellis/workflow.md` — development phases, when to create tasks, skill routing
|
|
9
|
+
- `.trellis/spec/` — package- and layer-scoped coding guidelines (read before writing code in a given layer)
|
|
10
|
+
- `.trellis/workspace/` — per-developer journals and session traces
|
|
11
|
+
- `.trellis/tasks/` — active and archived tasks (PRDs, research, jsonl context)
|
|
15
12
|
|
|
16
|
-
If
|
|
17
|
-
- `.agents/skills/` for reusable Trellis skills
|
|
18
|
-
- `.codex/agents/` for optional custom subagents
|
|
13
|
+
If a Trellis command is available on your platform (e.g. `/trellis:finish-work`, `/trellis:continue`), prefer it over manual steps. Not every platform exposes every command.
|
|
19
14
|
|
|
20
|
-
|
|
15
|
+
If you're using Codex or another agent-capable tool, additional project-scoped helpers may live in:
|
|
16
|
+
- `.agents/skills/` — reusable Trellis skills
|
|
17
|
+
- `.codex/agents/` — optional custom subagents
|
|
18
|
+
|
|
19
|
+
Managed by Trellis. Edits outside this block are preserved; edits inside may be overwritten by a future `trellis update`.
|
|
21
20
|
|
|
22
21
|
<!-- TRELLIS:END -->
|
|
@@ -21,7 +21,7 @@ You are the Check Agent in the Trellis workflow.
|
|
|
21
21
|
|
|
22
22
|
Otherwise, load context yourself:
|
|
23
23
|
|
|
24
|
-
1.
|
|
24
|
+
1. Run `python3 ./.trellis/scripts/task.py current --source` → get active task directory and source (e.g., `Current task: .trellis/tasks/xxx`)
|
|
25
25
|
2. Read `{task_dir}/check.jsonl`
|
|
26
26
|
3. For each entry in JSONL:
|
|
27
27
|
- If `path` is a file → Read it
|
|
@@ -21,7 +21,7 @@ You are the Implement Agent in the Trellis workflow.
|
|
|
21
21
|
|
|
22
22
|
Otherwise, load context yourself:
|
|
23
23
|
|
|
24
|
-
1.
|
|
24
|
+
1. Run `python3 ./.trellis/scripts/task.py current --source` → get active task directory and source (e.g., `Current task: .trellis/tasks/xxx`)
|
|
25
25
|
2. Read `{task_dir}/implement.jsonl`
|
|
26
26
|
3. For each entry in JSONL (JSON object per line):
|
|
27
27
|
- Skip rows without a `"file"` field (e.g. `{"_example": "..."}` seed rows)
|