@mindfoldhq/trellis 0.6.0-beta.7 → 0.6.0-beta.8
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/dist/configurators/codex.d.ts.map +1 -1
- package/dist/configurators/codex.js +5 -3
- package/dist/configurators/codex.js.map +1 -1
- package/dist/configurators/shared.js +4 -4
- package/dist/configurators/shared.js.map +1 -1
- package/dist/migrations/manifests/0.6.0-beta.8.json +9 -0
- package/dist/templates/claude/agents/trellis-check.md +2 -2
- package/dist/templates/claude/agents/trellis-implement.md +8 -7
- package/dist/templates/codebuddy/agents/trellis-check.md +2 -2
- package/dist/templates/codebuddy/agents/trellis-implement.md +8 -7
- package/dist/templates/codex/agents/trellis-check.toml +4 -4
- package/dist/templates/codex/agents/trellis-implement.toml +4 -4
- package/dist/templates/codex/hooks/session-start.py +183 -119
- package/dist/templates/codex/skills/before-dev/SKILL.md +12 -6
- package/dist/templates/codex/skills/brainstorm/SKILL.md +113 -51
- package/dist/templates/codex/skills/check/SKILL.md +86 -18
- package/dist/templates/codex/skills/start/SKILL.md +33 -323
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +7 -4
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +3 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +5 -5
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +8 -6
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +5 -4
- package/dist/templates/common/commands/continue.md +6 -5
- package/dist/templates/common/commands/start.md +7 -6
- package/dist/templates/common/skills/before-dev.md +12 -6
- package/dist/templates/common/skills/brainstorm.md +56 -42
- package/dist/templates/common/skills/check.md +7 -1
- package/dist/templates/copilot/hooks/session-start.py +183 -90
- package/dist/templates/copilot/prompts/before-dev.prompt.md +12 -6
- package/dist/templates/copilot/prompts/brainstorm.prompt.md +146 -84
- package/dist/templates/copilot/prompts/check.prompt.md +86 -18
- package/dist/templates/copilot/prompts/parallel.prompt.md +16 -8
- package/dist/templates/copilot/prompts/start.prompt.md +33 -367
- package/dist/templates/cursor/agents/trellis-check.md +2 -2
- package/dist/templates/cursor/agents/trellis-implement.md +8 -7
- package/dist/templates/droid/droids/trellis-check.md +2 -2
- package/dist/templates/droid/droids/trellis-implement.md +8 -7
- package/dist/templates/gemini/agents/trellis-implement.md +7 -6
- package/dist/templates/kiro/agents/trellis-check.json +1 -1
- package/dist/templates/kiro/agents/trellis-implement.json +1 -1
- package/dist/templates/opencode/agents/trellis-check.md +2 -2
- package/dist/templates/opencode/agents/trellis-implement.md +9 -8
- package/dist/templates/opencode/lib/session-utils.js +212 -123
- package/dist/templates/opencode/plugins/inject-subagent-context.js +23 -7
- package/dist/templates/opencode/plugins/inject-workflow-state.js +1 -4
- package/dist/templates/pi/extensions/trellis/index.ts.txt +7 -5
- package/dist/templates/qoder/agents/trellis-implement.md +7 -6
- package/dist/templates/shared-hooks/inject-subagent-context.py +36 -14
- package/dist/templates/shared-hooks/inject-workflow-state.py +18 -42
- package/dist/templates/shared-hooks/session-start.py +197 -163
- package/dist/templates/trellis/scripts/common/task_context.py +3 -3
- package/dist/templates/trellis/scripts/common/task_store.py +39 -7
- package/dist/templates/trellis/scripts/common/workflow_phase.py +7 -10
- package/dist/templates/trellis/scripts/task.py +3 -3
- package/dist/templates/trellis/workflow.md +98 -98
- package/package.json +1 -1
|
@@ -2,28 +2,34 @@ Read the relevant development guidelines before starting your task.
|
|
|
2
2
|
|
|
3
3
|
Execute these steps:
|
|
4
4
|
|
|
5
|
-
1. **
|
|
5
|
+
1. **Read current task artifacts**:
|
|
6
|
+
- `prd.md` for requirements and acceptance criteria
|
|
7
|
+
- `design.md` if present for technical design
|
|
8
|
+
- `implement.md` if present for execution order and validation plan
|
|
9
|
+
|
|
10
|
+
2. **Discover packages and their spec layers**:
|
|
6
11
|
```bash
|
|
7
12
|
python3 ./.trellis/scripts/get_context.py --mode packages
|
|
8
13
|
```
|
|
9
14
|
|
|
10
|
-
|
|
15
|
+
3. **Identify which specs apply** to your task based on:
|
|
11
16
|
- Which package you're modifying (e.g., `cli/`, `docs-site/`)
|
|
12
17
|
- What type of work (backend, frontend, unit-test, docs, etc.)
|
|
18
|
+
- Any spec/research paths referenced by the task artifacts
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
4. **Read the spec index** for each relevant module:
|
|
15
21
|
```bash
|
|
16
22
|
cat .trellis/spec/<package>/<layer>/index.md
|
|
17
23
|
```
|
|
18
24
|
Follow the **"Pre-Development Checklist"** section in the index.
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
5. **Read the specific guideline files** listed in the Pre-Development Checklist that are relevant to your task. The index is NOT the goal — it points you to the actual guideline files (e.g., `error-handling.md`, `conventions.md`, `mock-strategies.md`). Read those files to understand the coding standards and patterns.
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
6. **Always read shared guides**:
|
|
23
29
|
```bash
|
|
24
30
|
cat .trellis/spec/guides/index.md
|
|
25
31
|
```
|
|
26
32
|
|
|
27
|
-
|
|
33
|
+
7. Understand the coding standards and patterns you need to follow, then proceed with your development plan.
|
|
28
34
|
|
|
29
35
|
This step is **mandatory** before writing any code.
|
|
@@ -68,7 +68,7 @@ TASK_DIR=$(python3 ./.trellis/scripts/task.py create "brainstorm: <short goal>"
|
|
|
68
68
|
Use a slug without a date prefix. `task.py create` adds the `MM-DD-`
|
|
69
69
|
directory prefix automatically.
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
`task.py create` already created a default `prd.md`. Immediately update it with what you know:
|
|
72
72
|
|
|
73
73
|
```markdown
|
|
74
74
|
# brainstorm: <short goal>
|
|
@@ -77,7 +77,7 @@ Create/seed `prd.md` immediately with what you know:
|
|
|
77
77
|
|
|
78
78
|
<one paragraph: what + why>
|
|
79
79
|
|
|
80
|
-
##
|
|
80
|
+
## Background / Known Context
|
|
81
81
|
|
|
82
82
|
* <facts from user message>
|
|
83
83
|
* <facts discovered from repo/docs>
|
|
@@ -90,11 +90,11 @@ Create/seed `prd.md` immediately with what you know:
|
|
|
90
90
|
|
|
91
91
|
* <ONLY Blocking / Preference questions; keep list short>
|
|
92
92
|
|
|
93
|
-
## Requirements
|
|
93
|
+
## Requirements
|
|
94
94
|
|
|
95
95
|
* <start with what is known>
|
|
96
96
|
|
|
97
|
-
## Acceptance Criteria
|
|
97
|
+
## Acceptance Criteria
|
|
98
98
|
|
|
99
99
|
* [ ] <testable criterion>
|
|
100
100
|
|
|
@@ -109,10 +109,39 @@ Create/seed `prd.md` immediately with what you know:
|
|
|
109
109
|
|
|
110
110
|
* <what we will not do in this task>
|
|
111
111
|
|
|
112
|
-
##
|
|
112
|
+
## Research References
|
|
113
|
+
|
|
114
|
+
* <links to research/*.md or external references>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
For complex tasks, also create/update:
|
|
118
|
+
|
|
119
|
+
```markdown
|
|
120
|
+
# design.md
|
|
121
|
+
|
|
122
|
+
## Technical Design
|
|
123
|
+
|
|
124
|
+
<boundaries, contracts, data flow, compatibility, tradeoffs>
|
|
125
|
+
|
|
126
|
+
## Rollout / Rollback
|
|
127
|
+
|
|
128
|
+
<operational notes if relevant>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
```markdown
|
|
132
|
+
# implement.md
|
|
133
|
+
|
|
134
|
+
## Implementation Checklist
|
|
135
|
+
|
|
136
|
+
- [ ] <ordered implementation step>
|
|
137
|
+
|
|
138
|
+
## Validation
|
|
139
|
+
|
|
140
|
+
- <lint/typecheck/test command>
|
|
113
141
|
|
|
114
|
-
|
|
115
|
-
|
|
142
|
+
## Review Gates
|
|
143
|
+
|
|
144
|
+
- <human or technical checkpoint before start/finish>
|
|
116
145
|
```
|
|
117
146
|
|
|
118
147
|
---
|
|
@@ -135,8 +164,8 @@ Before asking questions like "what does the code look like?", gather context you
|
|
|
135
164
|
|
|
136
165
|
Write findings into PRD:
|
|
137
166
|
|
|
138
|
-
* Add to `
|
|
139
|
-
*
|
|
167
|
+
* Add user-visible facts to `Background / Known Context`
|
|
168
|
+
* Write technical findings to `research/*.md`, `design.md`, or `implement.md` as appropriate
|
|
140
169
|
|
|
141
170
|
---
|
|
142
171
|
|
|
@@ -402,7 +431,7 @@ Record the outcome in PRD as an ADR-lite section:
|
|
|
402
431
|
|
|
403
432
|
---
|
|
404
433
|
|
|
405
|
-
## Step 8: Final Confirmation +
|
|
434
|
+
## Step 8: Final Confirmation + Planning Artifacts
|
|
406
435
|
|
|
407
436
|
When open questions are resolved, confirm complete requirements with a structured summary:
|
|
408
437
|
|
|
@@ -431,16 +460,13 @@ Here's my understanding of the complete requirements:
|
|
|
431
460
|
|
|
432
461
|
* ...
|
|
433
462
|
|
|
434
|
-
**
|
|
435
|
-
<brief summary + key decisions>
|
|
436
|
-
|
|
437
|
-
**Implementation Plan (small PRs)**:
|
|
463
|
+
**Artifact status**:
|
|
438
464
|
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
465
|
+
* prd.md: <ready / needs update>
|
|
466
|
+
* design.md: <not needed for lightweight / ready / missing>
|
|
467
|
+
* implement.md: <not needed for lightweight / ready / missing>
|
|
442
468
|
|
|
443
|
-
Does this look correct? If yes,
|
|
469
|
+
Does this look correct? If yes, the next step is planning review before `task.py start`.
|
|
444
470
|
```
|
|
445
471
|
|
|
446
472
|
### Subtask Decomposition (Complex Tasks)
|
|
@@ -477,25 +503,13 @@ python3 ./.trellis/scripts/task.py add-subtask "$TASK_DIR" "$CHILD_DIR"
|
|
|
477
503
|
|
|
478
504
|
* [ ] ...
|
|
479
505
|
|
|
480
|
-
## Definition of Done
|
|
481
|
-
|
|
482
|
-
* ...
|
|
483
|
-
|
|
484
|
-
## Technical Approach
|
|
485
|
-
|
|
486
|
-
<key design + decisions>
|
|
487
|
-
|
|
488
|
-
## Decision (ADR-lite)
|
|
489
|
-
|
|
490
|
-
Context / Decision / Consequences
|
|
491
|
-
|
|
492
506
|
## Out of Scope
|
|
493
507
|
|
|
494
508
|
* ...
|
|
495
509
|
|
|
496
|
-
##
|
|
510
|
+
## Research References
|
|
497
511
|
|
|
498
|
-
<
|
|
512
|
+
* <links to research/*.md or external references>
|
|
499
513
|
```
|
|
500
514
|
|
|
501
515
|
---
|
|
@@ -512,25 +526,25 @@ Context / Decision / Consequences
|
|
|
512
526
|
|
|
513
527
|
## Integration with Start Workflow
|
|
514
528
|
|
|
515
|
-
After brainstorm completes (Step 8 confirmation approved), the flow continues to the Task Workflow
|
|
529
|
+
After brainstorm completes (Step 8 confirmation approved), the flow continues to the Task Workflow planning review gate:
|
|
516
530
|
|
|
517
531
|
```text
|
|
518
532
|
Brainstorm
|
|
519
|
-
Step 0: Create task directory +
|
|
533
|
+
Step 0: Create task directory + update PRD
|
|
520
534
|
Step 1–7: Discover requirements, research, converge
|
|
521
|
-
Step 8: Final confirmation → user approves
|
|
535
|
+
Step 8: Final confirmation → user approves planning artifacts
|
|
522
536
|
↓
|
|
523
|
-
Task Workflow Phase
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
→
|
|
527
|
-
→
|
|
537
|
+
Task Workflow Phase 1 (Plan)
|
|
538
|
+
Lightweight task → PRD-only may be enough
|
|
539
|
+
Complex task → design.md + implement.md required
|
|
540
|
+
Sub-agent platforms → curate implement.jsonl / check.jsonl manifests
|
|
541
|
+
→ Review gate → task.py start
|
|
528
542
|
↓
|
|
529
|
-
Task Workflow Phase
|
|
543
|
+
Task Workflow Phase 2 (Execute)
|
|
530
544
|
Implement → Check → Complete
|
|
531
545
|
```
|
|
532
546
|
|
|
533
|
-
The task directory and PRD already exist from brainstorm,
|
|
547
|
+
The task directory and PRD already exist from brainstorm, but Phase 1 is not skipped; it owns artifact review and the `task.py start` gate.
|
|
534
548
|
|
|
535
549
|
---
|
|
536
550
|
|
|
@@ -11,7 +11,13 @@ git diff --name-only HEAD
|
|
|
11
11
|
git status
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
## Step 2: Read Applicable Specs
|
|
14
|
+
## Step 2: Read Task Artifacts and Applicable Specs
|
|
15
|
+
|
|
16
|
+
Read the current task artifacts in order:
|
|
17
|
+
|
|
18
|
+
- `prd.md`
|
|
19
|
+
- `design.md` if present
|
|
20
|
+
- `implement.md` if present
|
|
15
21
|
|
|
16
22
|
```bash
|
|
17
23
|
python3 ./.trellis/scripts/get_context.py --mode packages
|
|
@@ -199,12 +199,19 @@ def _resolve_task_dir(trellis_dir: Path, task_ref: str) -> Path:
|
|
|
199
199
|
def _get_task_status(trellis_dir: Path, hook_input: dict) -> str:
|
|
200
200
|
active = _resolve_active_task(trellis_dir, hook_input)
|
|
201
201
|
if not active.task_path:
|
|
202
|
-
return
|
|
202
|
+
return (
|
|
203
|
+
"Status: NO ACTIVE TASK\n"
|
|
204
|
+
"Next: Classify the current turn and ask for task-creation consent "
|
|
205
|
+
"before creating any Trellis task."
|
|
206
|
+
)
|
|
203
207
|
|
|
204
208
|
task_ref = active.task_path
|
|
205
209
|
task_dir = _resolve_task_dir(trellis_dir, task_ref)
|
|
206
210
|
if active.stale or not task_dir.is_dir():
|
|
207
|
-
return
|
|
211
|
+
return (
|
|
212
|
+
f"Status: STALE POINTER\nTask: {task_ref}\n"
|
|
213
|
+
"Next: Task directory not found. Run: python3 ./.trellis/scripts/task.py finish"
|
|
214
|
+
)
|
|
208
215
|
|
|
209
216
|
task_json_path = task_dir / "task.json"
|
|
210
217
|
task_data: dict = {}
|
|
@@ -218,36 +225,170 @@ def _get_task_status(trellis_dir: Path, hook_input: dict) -> str:
|
|
|
218
225
|
task_status = task_data.get("status", "unknown")
|
|
219
226
|
|
|
220
227
|
if task_status == "completed":
|
|
221
|
-
return
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if jsonl_path.is_file() and _has_curated_jsonl_entry(jsonl_path):
|
|
227
|
-
has_context = True
|
|
228
|
-
break
|
|
228
|
+
return (
|
|
229
|
+
f"Status: COMPLETED\nTask: {task_title}\n"
|
|
230
|
+
f"Next: Archive with `python3 ./.trellis/scripts/task.py archive {task_dir.name}` "
|
|
231
|
+
"or start a new task."
|
|
232
|
+
)
|
|
229
233
|
|
|
230
234
|
has_prd = (task_dir / "prd.md").is_file()
|
|
235
|
+
has_design = (task_dir / "design.md").is_file()
|
|
236
|
+
has_implement = (task_dir / "implement.md").is_file()
|
|
237
|
+
present = [
|
|
238
|
+
name
|
|
239
|
+
for name in ("prd.md", "design.md", "implement.md", "implement.jsonl", "check.jsonl")
|
|
240
|
+
if (task_dir / name).is_file()
|
|
241
|
+
]
|
|
242
|
+
present_line = ", ".join(present) if present else "none"
|
|
231
243
|
|
|
232
244
|
if not has_prd:
|
|
233
|
-
return
|
|
245
|
+
return (
|
|
246
|
+
f"Status: PLANNING\nTask: {task_title}\nPresent: {present_line}\n"
|
|
247
|
+
"Next: Load trellis-brainstorm and write prd.md. Stay in planning."
|
|
248
|
+
)
|
|
234
249
|
|
|
235
|
-
if
|
|
236
|
-
|
|
250
|
+
if task_status == "planning":
|
|
251
|
+
if has_design and has_implement:
|
|
252
|
+
next_action = "Review planning artifacts with the user before `task.py start`."
|
|
253
|
+
else:
|
|
254
|
+
next_action = (
|
|
255
|
+
"Lightweight task can ask for start review with PRD-only; "
|
|
256
|
+
"complex task must add design.md and implement.md before `task.py start`."
|
|
257
|
+
)
|
|
258
|
+
return (
|
|
259
|
+
f"Status: PLANNING\nTask: {task_title}\nPresent: {present_line}\n"
|
|
260
|
+
f"Next: {next_action}"
|
|
261
|
+
)
|
|
237
262
|
|
|
238
263
|
return (
|
|
239
|
-
f"Status:
|
|
240
|
-
|
|
241
|
-
"
|
|
242
|
-
"For agent-capable platforms, the default is to NOT edit code in the main session. "
|
|
243
|
-
"After implementation, dispatch `trellis-check` per Phase 2.2 before reporting completion.\n"
|
|
244
|
-
"User override (per-turn escape hatch): if the user's CURRENT message explicitly tells the "
|
|
245
|
-
"main session to handle it directly (\"你直接改\" / \"别派 sub-agent\" / \"main session 写就行\" / "
|
|
246
|
-
"\"do it inline\" / \"不用 sub-agent\"), honor it for this turn and edit code directly. "
|
|
247
|
-
"Per-turn only; do NOT invent an override the user did not say."
|
|
264
|
+
f"Status: {task_status.upper()}\nTask: {task_title}\nPresent: {present_line}\n"
|
|
265
|
+
"Next: Follow the matching per-turn workflow-state. Context order is jsonl entries, "
|
|
266
|
+
"prd.md, design.md if present, implement.md if present."
|
|
248
267
|
)
|
|
249
268
|
|
|
250
269
|
|
|
270
|
+
def _run_git(repo_root: Path, args: list[str]) -> str:
|
|
271
|
+
try:
|
|
272
|
+
result = subprocess.run(
|
|
273
|
+
["git", *args],
|
|
274
|
+
capture_output=True,
|
|
275
|
+
text=True,
|
|
276
|
+
encoding="utf-8",
|
|
277
|
+
errors="replace",
|
|
278
|
+
timeout=3,
|
|
279
|
+
cwd=str(repo_root),
|
|
280
|
+
)
|
|
281
|
+
except (subprocess.TimeoutExpired, FileNotFoundError, PermissionError):
|
|
282
|
+
return ""
|
|
283
|
+
if result.returncode != 0:
|
|
284
|
+
return ""
|
|
285
|
+
return result.stdout.strip()
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def _format_git_state(repo_root: Path) -> str:
|
|
289
|
+
branch = _run_git(repo_root, ["branch", "--show-current"]) or "(detached)"
|
|
290
|
+
dirty_lines = [
|
|
291
|
+
line for line in _run_git(repo_root, ["status", "--porcelain"]).splitlines()
|
|
292
|
+
if line.strip()
|
|
293
|
+
]
|
|
294
|
+
dirty_text = "clean" if not dirty_lines else f"dirty {len(dirty_lines)} paths"
|
|
295
|
+
return f"Git: branch {branch}; {dirty_text}."
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _repo_relative(repo_root: Path, path: Path) -> str:
|
|
299
|
+
try:
|
|
300
|
+
return path.relative_to(repo_root).as_posix()
|
|
301
|
+
except ValueError:
|
|
302
|
+
return str(path)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def _collect_spec_index_paths(trellis_dir: Path) -> list[str]:
|
|
306
|
+
paths: list[str] = []
|
|
307
|
+
guides_index = trellis_dir / "spec" / "guides" / "index.md"
|
|
308
|
+
if guides_index.is_file():
|
|
309
|
+
paths.append(".trellis/spec/guides/index.md")
|
|
310
|
+
|
|
311
|
+
spec_dir = trellis_dir / "spec"
|
|
312
|
+
if not spec_dir.is_dir():
|
|
313
|
+
return paths
|
|
314
|
+
|
|
315
|
+
for sub in sorted(spec_dir.iterdir()):
|
|
316
|
+
if not sub.is_dir() or sub.name.startswith(".") or sub.name == "guides":
|
|
317
|
+
continue
|
|
318
|
+
index_file = sub / "index.md"
|
|
319
|
+
if index_file.is_file():
|
|
320
|
+
paths.append(f".trellis/spec/{sub.name}/index.md")
|
|
321
|
+
continue
|
|
322
|
+
for nested in sorted(sub.iterdir()):
|
|
323
|
+
if not nested.is_dir():
|
|
324
|
+
continue
|
|
325
|
+
nested_index = nested / "index.md"
|
|
326
|
+
if nested_index.is_file():
|
|
327
|
+
paths.append(f".trellis/spec/{sub.name}/{nested.name}/index.md")
|
|
328
|
+
|
|
329
|
+
return paths
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def _build_compact_current_state(
|
|
333
|
+
trellis_dir: Path,
|
|
334
|
+
hook_input: dict,
|
|
335
|
+
spec_index_paths: list[str],
|
|
336
|
+
) -> str:
|
|
337
|
+
repo_root = trellis_dir.parent
|
|
338
|
+
lines: list[str] = []
|
|
339
|
+
|
|
340
|
+
try:
|
|
341
|
+
from common.paths import get_active_journal_file, get_developer, get_tasks_dir, count_lines # type: ignore[import-not-found]
|
|
342
|
+
from common.tasks import iter_active_tasks # type: ignore[import-not-found]
|
|
343
|
+
except Exception:
|
|
344
|
+
get_active_journal_file = None # type: ignore[assignment]
|
|
345
|
+
get_developer = None # type: ignore[assignment]
|
|
346
|
+
get_tasks_dir = None # type: ignore[assignment]
|
|
347
|
+
count_lines = None # type: ignore[assignment]
|
|
348
|
+
iter_active_tasks = None # type: ignore[assignment]
|
|
349
|
+
|
|
350
|
+
developer = get_developer(repo_root) if get_developer else None
|
|
351
|
+
lines.append(f"Developer: {developer or '(not initialized)'}")
|
|
352
|
+
lines.append(_format_git_state(repo_root))
|
|
353
|
+
|
|
354
|
+
active = _resolve_active_task(trellis_dir, hook_input)
|
|
355
|
+
if active.task_path:
|
|
356
|
+
task_dir = _resolve_task_dir(trellis_dir, active.task_path)
|
|
357
|
+
status = "unknown"
|
|
358
|
+
task_json = task_dir / "task.json"
|
|
359
|
+
if task_json.is_file():
|
|
360
|
+
try:
|
|
361
|
+
data = json.loads(task_json.read_text(encoding="utf-8"))
|
|
362
|
+
if isinstance(data, dict):
|
|
363
|
+
status = str(data.get("status") or "unknown")
|
|
364
|
+
except (json.JSONDecodeError, OSError):
|
|
365
|
+
pass
|
|
366
|
+
lines.append(f"Current task: {_repo_relative(repo_root, task_dir)}; status={status}.")
|
|
367
|
+
else:
|
|
368
|
+
lines.append("Current task: none.")
|
|
369
|
+
|
|
370
|
+
if get_tasks_dir and iter_active_tasks:
|
|
371
|
+
try:
|
|
372
|
+
task_count = sum(1 for _ in iter_active_tasks(get_tasks_dir(repo_root)))
|
|
373
|
+
lines.append(
|
|
374
|
+
f"Active tasks: {task_count} total. Use `python3 ./.trellis/scripts/task.py list --mine` only if needed."
|
|
375
|
+
)
|
|
376
|
+
except Exception:
|
|
377
|
+
pass
|
|
378
|
+
|
|
379
|
+
if get_active_journal_file and count_lines:
|
|
380
|
+
journal = get_active_journal_file(repo_root)
|
|
381
|
+
if journal:
|
|
382
|
+
lines.append(
|
|
383
|
+
f"Journal: {_repo_relative(repo_root, journal)}, {count_lines(journal)} / 2000 lines."
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
if spec_index_paths:
|
|
387
|
+
lines.append(f"Spec indexes: {len(spec_index_paths)} available.")
|
|
388
|
+
|
|
389
|
+
return "\n".join(lines)
|
|
390
|
+
|
|
391
|
+
|
|
251
392
|
def _extract_range(content: str, start_header: str, end_header: str) -> str:
|
|
252
393
|
"""Extract lines starting at `## start_header` up to (but excluding) `## end_header`."""
|
|
253
394
|
lines = content.splitlines()
|
|
@@ -275,32 +416,25 @@ _BREADCRUMB_TAG_RE = re.compile(
|
|
|
275
416
|
|
|
276
417
|
|
|
277
418
|
def _strip_breadcrumb_tag_blocks(content: str) -> str:
|
|
278
|
-
|
|
419
|
+
stripped = _BREADCRUMB_TAG_RE.sub("", content)
|
|
420
|
+
stripped = re.sub(r"<!--.*?-->", "", stripped, flags=re.DOTALL)
|
|
421
|
+
stripped = re.sub(r"^\[(?!/?workflow-state:)/?[^\]\n]+\]\s*\n?", "", stripped, flags=re.MULTILINE)
|
|
422
|
+
return re.sub(r"\n{3,}", "\n\n", stripped).strip()
|
|
279
423
|
|
|
280
424
|
|
|
281
425
|
def _build_workflow_toc(workflow_path: Path) -> str:
|
|
282
|
-
"""Inject
|
|
283
|
-
|
|
284
|
-
Since v0.5.0-rc.0 the [workflow-state:STATUS] breadcrumb tag blocks
|
|
285
|
-
live inside ## Phase Index. They're consumed by inject-workflow-state.py
|
|
286
|
-
on each UserPromptSubmit, so strip them from the session-start payload.
|
|
287
|
-
"""
|
|
426
|
+
"""Inject only the compact Phase Index summary for SessionStart."""
|
|
288
427
|
content = read_file(workflow_path)
|
|
289
428
|
if not content:
|
|
290
429
|
return "No workflow.md found"
|
|
291
430
|
|
|
292
431
|
out_lines = [
|
|
293
|
-
"# Development Workflow
|
|
294
|
-
"Full guide: .trellis/workflow.md
|
|
432
|
+
"# Development Workflow - Session Summary",
|
|
433
|
+
"Full guide: .trellis/workflow.md. Step detail: `python3 ./.trellis/scripts/get_context.py --mode phase --step <X.Y>`.",
|
|
295
434
|
"",
|
|
296
|
-
"## Table of Contents",
|
|
297
435
|
]
|
|
298
|
-
for line in content.splitlines():
|
|
299
|
-
if line.startswith("## "):
|
|
300
|
-
out_lines.append(line)
|
|
301
|
-
out_lines += ["", "---", ""]
|
|
302
436
|
|
|
303
|
-
phases = _extract_range(content, "Phase Index", "
|
|
437
|
+
phases = _extract_range(content, "Phase Index", "Phase 1: Plan")
|
|
304
438
|
if phases:
|
|
305
439
|
out_lines.append(_strip_breadcrumb_tag_blocks(phases).rstrip())
|
|
306
440
|
|
|
@@ -324,73 +458,34 @@ def main() -> None:
|
|
|
324
458
|
configure_project_encoding(project_dir)
|
|
325
459
|
|
|
326
460
|
trellis_dir = project_dir / ".trellis"
|
|
327
|
-
|
|
461
|
+
spec_index_paths = _collect_spec_index_paths(trellis_dir)
|
|
328
462
|
|
|
329
463
|
output = StringIO()
|
|
330
464
|
|
|
331
465
|
output.write("""<session-context>
|
|
332
|
-
|
|
333
|
-
Read and follow all instructions below carefully.
|
|
466
|
+
Trellis compact SessionStart context. Use it to orient the session; load details on demand.
|
|
334
467
|
</session-context>
|
|
335
468
|
|
|
336
469
|
""")
|
|
337
470
|
|
|
338
471
|
output.write("<current-state>\n")
|
|
339
|
-
|
|
340
|
-
output.write(run_script(context_script, context_key))
|
|
472
|
+
output.write(_build_compact_current_state(trellis_dir, hook_input, spec_index_paths))
|
|
341
473
|
output.write("\n</current-state>\n\n")
|
|
342
474
|
|
|
343
|
-
output.write("<workflow>\n")
|
|
475
|
+
output.write("<trellis-workflow>\n")
|
|
344
476
|
output.write(_build_workflow_toc(trellis_dir / "workflow.md"))
|
|
345
|
-
output.write("\n</workflow>\n\n")
|
|
477
|
+
output.write("\n</trellis-workflow>\n\n")
|
|
346
478
|
|
|
347
479
|
output.write("<guidelines>\n")
|
|
348
480
|
output.write(
|
|
349
|
-
"
|
|
350
|
-
"
|
|
351
|
-
"
|
|
352
|
-
"- If you're spawning an implement/check sub-agent, context is injected "
|
|
353
|
-
"automatically via `{task}/implement.jsonl` / `check.jsonl`. You do NOT "
|
|
354
|
-
"need to read these indexes yourself.\n"
|
|
355
|
-
"- For agent-capable platforms, the default is to dispatch "
|
|
356
|
-
"`trellis-implement` and `trellis-check` (so JSONL context is loaded by "
|
|
357
|
-
"the sub-agents) rather than editing code in the main session. "
|
|
358
|
-
"Honor a per-turn user override only if the user's current message "
|
|
359
|
-
"explicitly opts out (see <task-status> below for override phrases).\n\n"
|
|
481
|
+
"Task context order for implementation/check: jsonl entries -> `prd.md` -> "
|
|
482
|
+
"`design.md if present` -> `implement.md if present`. Missing optional artifacts "
|
|
483
|
+
"are skipped for lightweight tasks.\n\n"
|
|
360
484
|
)
|
|
361
485
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
output.write("## guides (inlined — cross-package thinking guides)\n")
|
|
366
|
-
output.write(read_file(guides_index))
|
|
367
|
-
output.write("\n\n")
|
|
368
|
-
|
|
369
|
-
# Other indexes — paths only
|
|
370
|
-
paths: list[str] = []
|
|
371
|
-
spec_dir = trellis_dir / "spec"
|
|
372
|
-
if spec_dir.is_dir():
|
|
373
|
-
for sub in sorted(spec_dir.iterdir()):
|
|
374
|
-
if not sub.is_dir() or sub.name.startswith("."):
|
|
375
|
-
continue
|
|
376
|
-
if sub.name == "guides":
|
|
377
|
-
continue
|
|
378
|
-
index_file = sub / "index.md"
|
|
379
|
-
if index_file.is_file():
|
|
380
|
-
paths.append(f".trellis/spec/{sub.name}/index.md")
|
|
381
|
-
else:
|
|
382
|
-
for nested in sorted(sub.iterdir()):
|
|
383
|
-
if not nested.is_dir():
|
|
384
|
-
continue
|
|
385
|
-
nested_index = nested / "index.md"
|
|
386
|
-
if nested_index.is_file():
|
|
387
|
-
paths.append(
|
|
388
|
-
f".trellis/spec/{sub.name}/{nested.name}/index.md"
|
|
389
|
-
)
|
|
390
|
-
|
|
391
|
-
if paths:
|
|
392
|
-
output.write("## Available spec indexes (read on demand)\n")
|
|
393
|
-
for p in paths:
|
|
486
|
+
if spec_index_paths:
|
|
487
|
+
output.write("## Available indexes (read on demand)\n")
|
|
488
|
+
for p in spec_index_paths:
|
|
394
489
|
output.write(f"- {p}\n")
|
|
395
490
|
output.write("\n")
|
|
396
491
|
|
|
@@ -404,9 +499,7 @@ Read and follow all instructions below carefully.
|
|
|
404
499
|
output.write(f"<task-status>\n{task_status}\n</task-status>\n\n")
|
|
405
500
|
|
|
406
501
|
output.write("""<ready>
|
|
407
|
-
Context loaded.
|
|
408
|
-
When the user sends the first message, follow <task-status> and the workflow guide.
|
|
409
|
-
If a task is READY, execute its Next required action without asking whether to continue.
|
|
502
|
+
Context loaded. Follow <task-status>. Load workflow/spec/task details only when needed.
|
|
410
503
|
</ready>""")
|
|
411
504
|
|
|
412
505
|
context = output.getvalue()
|
|
@@ -6,28 +6,34 @@ Read the relevant development guidelines before starting your task.
|
|
|
6
6
|
|
|
7
7
|
Execute these steps:
|
|
8
8
|
|
|
9
|
-
1. **
|
|
9
|
+
1. **Read current task artifacts**:
|
|
10
|
+
- `prd.md` for requirements and acceptance criteria
|
|
11
|
+
- `design.md` if present for technical design
|
|
12
|
+
- `implement.md` if present for execution order and validation plan
|
|
13
|
+
|
|
14
|
+
2. **Discover packages and their spec layers**:
|
|
10
15
|
```bash
|
|
11
16
|
python3 ./.trellis/scripts/get_context.py --mode packages
|
|
12
17
|
```
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
3. **Identify which specs apply** to your task based on:
|
|
15
20
|
- Which package you're modifying (e.g., `cli/`, `docs-site/`)
|
|
16
21
|
- What type of work (backend, frontend, unit-test, docs, etc.)
|
|
22
|
+
- Any spec/research paths referenced by the task artifacts
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
4. **Read the spec index** for each relevant module:
|
|
19
25
|
```bash
|
|
20
26
|
cat .trellis/spec/<package>/<layer>/index.md
|
|
21
27
|
```
|
|
22
28
|
Follow the **"Pre-Development Checklist"** section in the index.
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
5. **Read the specific guideline files** listed in the Pre-Development Checklist that are relevant to your task. The index is NOT the goal — it points you to the actual guideline files (e.g., `error-handling.md`, `conventions.md`, `mock-strategies.md`). Read those files to understand the coding standards and patterns.
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
6. **Always read shared guides**:
|
|
27
33
|
```bash
|
|
28
34
|
cat .trellis/spec/guides/index.md
|
|
29
35
|
```
|
|
30
36
|
|
|
31
|
-
|
|
37
|
+
7. Understand the coding standards and patterns you need to follow, then proceed with your development plan.
|
|
32
38
|
|
|
33
39
|
This step is **mandatory** before writing any code.
|