@mindfoldhq/trellis 0.6.4 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/cli/index.js +1 -0
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/commands/channel/messages.js +1 -1
  4. package/dist/commands/channel/supervisor.d.ts.map +1 -1
  5. package/dist/commands/channel/supervisor.js +34 -2
  6. package/dist/commands/channel/supervisor.js.map +1 -1
  7. package/dist/commands/init.d.ts +1 -0
  8. package/dist/commands/init.d.ts.map +1 -1
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/uninstall.d.ts.map +1 -1
  11. package/dist/commands/uninstall.js +1 -0
  12. package/dist/commands/uninstall.js.map +1 -1
  13. package/dist/commands/update.d.ts.map +1 -1
  14. package/dist/commands/update.js +23 -11
  15. package/dist/commands/update.js.map +1 -1
  16. package/dist/configurators/index.d.ts.map +1 -1
  17. package/dist/configurators/index.js +20 -0
  18. package/dist/configurators/index.js.map +1 -1
  19. package/dist/configurators/pi.d.ts.map +1 -1
  20. package/dist/configurators/pi.js +14 -4
  21. package/dist/configurators/pi.js.map +1 -1
  22. package/dist/configurators/trae.d.ts +17 -0
  23. package/dist/configurators/trae.d.ts.map +1 -0
  24. package/dist/configurators/trae.js +42 -0
  25. package/dist/configurators/trae.js.map +1 -0
  26. package/dist/configurators/zcode.js +3 -3
  27. package/dist/configurators/zcode.js.map +1 -1
  28. package/dist/migrations/manifests/0.6.5.json +9 -0
  29. package/dist/templates/codex/skills/brainstorm/SKILL.md +19 -1
  30. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +1 -1
  31. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +1 -1
  32. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +1 -0
  33. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +2 -2
  34. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +2 -0
  35. package/dist/templates/common/skills/brainstorm.md +19 -1
  36. package/dist/templates/copilot/prompts/brainstorm.prompt.md +19 -1
  37. package/dist/templates/pi/agents/trellis-check.md +1 -1
  38. package/dist/templates/pi/agents/trellis-implement.md +1 -1
  39. package/dist/templates/pi/agents/trellis-research.md +1 -1
  40. package/dist/templates/pi/extensions/trellis/index.ts.txt +84 -8
  41. package/dist/templates/shared-hooks/index.d.ts +1 -1
  42. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  43. package/dist/templates/shared-hooks/index.js +1 -0
  44. package/dist/templates/shared-hooks/index.js.map +1 -1
  45. package/dist/templates/shared-hooks/inject-workflow-state.py +39 -4
  46. package/dist/templates/shared-hooks/session-start.py +5 -0
  47. package/dist/templates/trae/agents/trellis-check.md +108 -0
  48. package/dist/templates/trae/agents/trellis-implement.md +103 -0
  49. package/dist/templates/trae/agents/trellis-research.md +137 -0
  50. package/dist/templates/trae/hooks.json +27 -0
  51. package/dist/templates/trae/index.d.ts +15 -0
  52. package/dist/templates/trae/index.d.ts.map +1 -0
  53. package/dist/templates/trae/index.js +15 -0
  54. package/dist/templates/trae/index.js.map +1 -0
  55. package/dist/templates/trellis/scripts/common/active_task.py +2 -0
  56. package/dist/templates/trellis/scripts/common/cli_adapter.py +37 -11
  57. package/dist/templates/trellis/scripts/common/task_store.py +1 -0
  58. package/dist/templates/trellis/workflow.md +21 -19
  59. package/dist/types/ai-tools.d.ts +4 -4
  60. package/dist/types/ai-tools.d.ts.map +1 -1
  61. package/dist/types/ai-tools.js +16 -0
  62. package/dist/types/ai-tools.js.map +1 -1
  63. package/package.json +2 -2
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.6.5",
3
+ "description": "Patch release: adds Trae IDE support, restores reliable Pi startup context and sub-agent tool configuration, and fixes Windows channel spawning plus workflow planning gates.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Features:**\n- feat(trae): add Trae IDE platform support. `trellis init --trae` / `trellis uninstall --trae` now manage `.trae/commands/`, `.trae/skills/`, `.trae/agents/`, `.trae/hooks/`, and `.trae/hooks.json`; Trae uses shared SessionStart/UserPromptSubmit hooks for main-session context and pull-based sub-agent prelude for task context.\n- feat(pi): support `tools` frontmatter in `.pi/agents/trellis-*.md` for `trellis_subagent`, so generated Pi sub-agent definitions can declare their required tool surface.\n\n**Bug Fixes:**\n- fix(pi): inject compact Trellis startup context through Pi's first `before_agent_start` event and keep `.pi/prompts/trellis-start.md` as the manual fallback because Pi `session_start` is notify-only. New Pi sessions now receive workflow, active-task, session-overview, and first-reply notice context without relying on a manual start command.\n- fix(pi): normalize Pi sub-agent tool names to lowercase and remove the dead `PI_TOOL_ALLOWLIST` path so tool declarations match Pi's expected names.\n- fix(channel): resolve Windows npm `.cmd` shims to a spawnable executable path before launching channel sessions, preventing `.exe` path resolution failures.\n- fix(hooks): avoid blocking shared Python hooks when stdin is empty.\n- fix(workflow): keep class-2 implement dispatch (codex-sub-agent, Gemini, Qoder, Copilot, ZCode, Reasonix, Trae) in the pull-based block instead of the hook auto-handles block, matching generated pull-based sub-agent context loading and preventing the ZCode/Reasonix misclassification class from recurring.\n- fix(zcode): keep ZCode command fallbacks in `.zcode/commands/trellis/` and out of shared `.agents/skills/`, preventing Codex/ZCode combined installs from reporting immediate template drift.\n- fix(workflow): require curated `implement.jsonl` / `check.jsonl` context before starting work, so seed-only task context is not treated as implementation-ready.\n- fix(brainstorm): require lossless PRD convergence before task planning continues, preventing brainstorm updates from dropping existing requirements.\n\n**Internal:**\n- ci: run Trellis CI on marketplace submodule pointer changes and sync the marketplace workflow mirror for Trae support.",
7
+ "migrations": [],
8
+ "notes": "No `--migrate` required.\n\nRun `trellis update` after upgrading. Trae users can run `trellis init --trae` in projects that do not yet have `.trae/` configured; existing Trellis projects should run `trellis update`. Pi users should run `trellis update` to receive the generated start prompt and extension startup-context updates.\n\nInstall: `npm install -g @mindfoldhq/trellis`"
9
+ }
@@ -53,6 +53,7 @@ Use a concise title from the user's request. Use a slug without a date prefix. `
53
53
  5. Include your recommended answer with the question.
54
54
  6. After each user answer, update `prd.md` before continuing.
55
55
  7. For complex tasks, create or update `design.md` and `implement.md` before implementation starts.
56
+ 8. Before final review or `task.py start`, run the PRD convergence pass below.
56
57
 
57
58
  Do not invent a project-specific product/spec hierarchy. If the repository already has product, domain, or spec docs, use them. If it does not, proceed with the evidence that exists.
58
59
 
@@ -97,16 +98,33 @@ Do not ask process questions such as whether to search, inspect files, or contin
97
98
 
98
99
  Lightweight tasks may have only `prd.md`. Complex tasks must have `prd.md`, `design.md`, and `implement.md` before `task.py start`.
99
100
 
100
- `implement.md` is not a replacement for `implement.jsonl`. Use JSONL files only for manifest-style spec and research references when the task needs them.
101
+ `implement.md` is not a replacement for `implement.jsonl`. On sub-agent-dispatch workflows, `implement.jsonl` and `check.jsonl` must each contain at least one real spec/research entry before `task.py start`; the seed `_example` row does not count. Inline workflows skip this JSONL gate because Phase 2 loads context through `trellis-before-dev`.
102
+
103
+ ## PRD Convergence Pass
104
+
105
+ Before declaring planning ready or running `task.py start`, rewrite `prd.md` once against the final structure described in the artifact rules above. This is not optional cleanup; it is the final planning gate.
106
+
107
+ The pass must be lossless:
108
+
109
+ - Collapse repeated facts into one authoritative section.
110
+ - Fold temporary brainstorm sections such as `What I already know`, `Assumptions`, and resolved `Open Questions` into Goal, Background, Requirements, Technical Notes, or Acceptance Criteria.
111
+ - Remove resolved open questions instead of leaving empty or already-answered sections.
112
+ - Merge parallel bug and requirement lists when they describe the same work; keep each defect's severity, evidence, and file:line anchors on the owning requirement.
113
+ - Preserve every file:line anchor, decision, constraint, requirement ID, and acceptance-criteria mapping.
114
+ - Keep only genuinely blocking open questions.
115
+
116
+ After the pass, read `prd.md` top to bottom and verify that no fact is repeated across sections unless the repetition adds new information.
101
117
 
102
118
  ## Quality Bar
103
119
 
104
120
  Before declaring planning ready:
105
121
 
106
122
  - `prd.md` contains testable acceptance criteria.
123
+ - `prd.md` has passed the PRD convergence pass: no unresolved temporary brainstorm sections, no duplicate facts across sections, and no lost anchors, decisions, or acceptance mappings.
107
124
  - Repository-answerable questions have already been answered through inspection.
108
125
  - Remaining open questions are genuinely about user intent or scope.
109
126
  - Complex tasks have `design.md` and `implement.md`.
127
+ - Sub-agent-dispatch tasks have real curated entries in both `implement.jsonl` and `check.jsonl`; seed-only manifests are not ready.
110
128
  - The user has reviewed the final planning artifacts or explicitly approved proceeding.
111
129
 
112
130
  Do not start implementation until the user approves or asks for implementation.
@@ -4,7 +4,7 @@ Hooks are the automation layer that connects a platform to Trellis. When the use
4
4
 
5
5
  ## Read These Files First
6
6
 
7
- 1. Target platform settings/config, such as `.claude/settings.json`, `.codex/hooks.json`, `.cursor/hooks.json`
7
+ 1. Target platform settings/config, such as `.claude/settings.json`, `.codex/hooks.json`, `.cursor/hooks.json`, `.trae/hooks.json`
8
8
  2. Target platform hooks directory
9
9
  3. `.trellis/scripts/common/active_task.py`
10
10
  4. `.trellis/scripts/common/session_context.py`
@@ -40,7 +40,7 @@ Different platforms generate different directories. Common categories:
40
40
  | Category | Example paths | Purpose |
41
41
  | --- | --- | --- |
42
42
  | hooks | `.claude/hooks/`, `.codex/hooks/`, `.cursor/hooks/` | Inject session context, workflow-state, and sub-agent context. |
43
- | settings | `.claude/settings.json`, `.codex/hooks.json`, `.qoder/settings.json` | Tell the platform when to run hooks or plugins. |
43
+ | settings | `.claude/settings.json`, `.codex/hooks.json`, `.qoder/settings.json`, `.trae/hooks.json` | Tell the platform when to run hooks or plugins. |
44
44
  | agents | `.claude/agents/`, `.codex/agents/`, `.kiro/agents/`, `.zcode/cli/agents/` | Define agents such as `trellis-research`, `trellis-implement`, and `trellis-check`. |
45
45
  | skills | `.claude/skills/`, `.agents/skills/`, `.qoder/skills/` | Skills that auto-trigger or can be read by AI. |
46
46
  | commands/prompts/workflows | `.cursor/commands/`, `.github/prompts/`, `.devin/workflows/`, `.zcode/commands/` | Explicit user-invoked command or workflow entry points. |
@@ -27,6 +27,7 @@ Common files:
27
27
  | GitHub Copilot | `.github/copilot/hooks.json` |
28
28
  | Factory Droid | `.factory/settings.json` |
29
29
  | Pi Agent | `.pi/settings.json`, `.pi/extensions/trellis/` |
30
+ | Trae IDE | `.trae/hooks.json` |
30
31
 
31
32
  Reasonix and ZCode are pull-based platforms that do not use hooks or settings files; their agent files contain prelude instructions to read context after startup.
32
33
 
@@ -5,7 +5,7 @@ Trellis connects the same local architecture to different AI tools. `.trellis/`
5
5
  When a local AI modifies Trellis, it should distinguish two file categories first:
6
6
 
7
7
  - **Shared files**: `.trellis/workflow.md`, `.trellis/tasks/`, `.trellis/spec/`, `.trellis/scripts/`.
8
- - **Platform files**: `.claude/`, `.codex/`, `.cursor/`, `.opencode/`, `.kiro/`, `.gemini/`, `.qoder/`, `.codebuddy/`, `.github/`, `.factory/`, `.pi/`, `.kilocode/`, `.agent/`, `.devin/`, `.reasonix/`, `.zcode/`, and similar directories.
8
+ - **Platform files**: `.claude/`, `.codex/`, `.cursor/`, `.opencode/`, `.kiro/`, `.gemini/`, `.qoder/`, `.codebuddy/`, `.github/`, `.factory/`, `.pi/`, `.trae/`, `.kilocode/`, `.agent/`, `.devin/`, `.reasonix/`, `.zcode/`, and similar directories.
9
9
 
10
10
  Platform files do not store business state. They let the corresponding AI tool read Trellis state, call Trellis scripts, and load Trellis skills/agents/hooks.
11
11
 
@@ -13,7 +13,7 @@ Platform files do not store business state. They let the corresponding AI tool r
13
13
 
14
14
  | Category | Common paths | Purpose |
15
15
  | --- | --- | --- |
16
- | settings/config | `.claude/settings.json`, `.codex/hooks.json`, `.qoder/settings.json` | Register hooks, plugins, extensions, or platform behavior. |
16
+ | settings/config | `.claude/settings.json`, `.codex/hooks.json`, `.qoder/settings.json`, `.trae/hooks.json` | Register hooks, plugins, extensions, or platform behavior. |
17
17
  | hooks/plugins/extensions | `.claude/hooks/`, `.opencode/plugins/`, `.pi/extensions/` | Inject context at session start, user input, agent startup, shell execution, and similar events. |
18
18
  | agents | `.claude/agents/`, `.codex/agents/`, `.kiro/agents/` | Define `trellis-research`, `trellis-implement`, and `trellis-check`. |
19
19
  | skills | `.claude/skills/`, `.agents/skills/`, `.qoder/skills/` | Capability descriptions that auto-trigger or can be read on demand. |
@@ -20,6 +20,7 @@ This page lists common Trellis file locations in a user project by platform. Whe
20
20
  | GitHub Copilot | `--copilot` | `.github/` | `.github/skills/` | `.github/agents/` | `.github/copilot/hooks/` + prompts |
21
21
  | Factory Droid | `--droid` | `.factory/` | `.factory/skills/` | `.factory/droids/` | `.factory/hooks/` + settings |
22
22
  | Pi Agent | `--pi` | `.pi/` | `.pi/skills/` | `.pi/agents/` | `.pi/extensions/trellis/` (native `trellis_subagent` tool) + `.pi/settings.json` |
23
+ | Trae IDE | `--trae` | `.trae/` | `.trae/skills/` | `.trae/agents/` | `.trae/hooks/` + `.trae/hooks.json` |
23
24
  | Reasonix | `--reasonix` | `.reasonix/` | `.reasonix/skills/` | None — sub-agents are skills with `runAs: subagent` frontmatter | None |
24
25
  | ZCode | `--zcode` | `.zcode/` | `.agents/skills/` | `.zcode/cli/agents/` | pull-based prelude (no hooks) |
25
26
 
@@ -40,6 +41,7 @@ These platforms usually have `trellis-research`, `trellis-implement`, and `trell
40
41
  - GitHub Copilot
41
42
  - Factory Droid
42
43
  - Pi Agent
44
+ - Trae IDE
43
45
  - Reasonix (delivered as skills with `runAs: subagent` under `.reasonix/skills/`, not as a separate `agents/` directory)
44
46
  - ZCode
45
47
 
@@ -48,6 +48,7 @@ Use a concise title from the user's request. Use a slug without a date prefix. `
48
48
  5. Include your recommended answer with the question.
49
49
  6. After each user answer, update `prd.md` before continuing.
50
50
  7. For complex tasks, create or update `design.md` and `implement.md` before implementation starts.
51
+ 8. Before final review or `task.py start`, run the PRD convergence pass below.
51
52
 
52
53
  Do not invent a project-specific product/spec hierarchy. If the repository already has product, domain, or spec docs, use them. If it does not, proceed with the evidence that exists.
53
54
 
@@ -135,16 +136,33 @@ For each component of the current plan:
135
136
 
136
137
  Lightweight tasks may have only `prd.md`. Complex tasks must have `prd.md`, `design.md`, and `implement.md` before `task.py start`.
137
138
 
138
- `implement.md` is not a replacement for `implement.jsonl`. Use JSONL files only for manifest-style spec and research references when the task needs them.
139
+ `implement.md` is not a replacement for `implement.jsonl`. On sub-agent-dispatch workflows, `implement.jsonl` and `check.jsonl` must each contain at least one real spec/research entry before `task.py start`; the seed `_example` row does not count. Inline workflows skip this JSONL gate because Phase 2 loads context through `trellis-before-dev`.
140
+
141
+ ## PRD Convergence Pass
142
+
143
+ Before declaring planning ready or running `task.py start`, rewrite `prd.md` once against the final structure described in the artifact rules above. This is not optional cleanup; it is the final planning gate.
144
+
145
+ The pass must be lossless:
146
+
147
+ - Collapse repeated facts into one authoritative section.
148
+ - Fold temporary brainstorm sections such as `What I already know`, `Assumptions`, and resolved `Open Questions` into Goal, Background, Requirements, Technical Notes, or Acceptance Criteria.
149
+ - Remove resolved open questions instead of leaving empty or already-answered sections.
150
+ - Merge parallel bug and requirement lists when they describe the same work; keep each defect's severity, evidence, and file:line anchors on the owning requirement.
151
+ - Preserve every file:line anchor, decision, constraint, requirement ID, and acceptance-criteria mapping.
152
+ - Keep only genuinely blocking open questions.
153
+
154
+ After the pass, read `prd.md` top to bottom and verify that no fact is repeated across sections unless the repetition adds new information.
139
155
 
140
156
  ## Quality Bar
141
157
 
142
158
  Before declaring planning ready:
143
159
 
144
160
  - `prd.md` contains testable acceptance criteria.
161
+ - `prd.md` has passed the PRD convergence pass: no unresolved temporary brainstorm sections, no duplicate facts across sections, and no lost anchors, decisions, or acceptance mappings.
145
162
  - Repository-answerable questions have already been answered through inspection.
146
163
  - Remaining open questions are genuinely about user intent or scope.
147
164
  - Complex tasks have `design.md` and `implement.md`.
165
+ - Sub-agent-dispatch tasks have real curated entries in both `implement.jsonl` and `check.jsonl`; seed-only manifests are not ready.
148
166
  - The user has reviewed the final planning artifacts or explicitly approved proceeding.
149
167
 
150
168
  Do not start implementation until the user approves or asks for implementation.
@@ -52,6 +52,7 @@ Use a concise title from the user's request. Use a slug without a date prefix. `
52
52
  5. Include your recommended answer with the question.
53
53
  6. After each user answer, update `prd.md` before continuing.
54
54
  7. For complex tasks, create or update `design.md` and `implement.md` before implementation starts.
55
+ 8. Before final review or `task.py start`, run the PRD convergence pass below.
55
56
 
56
57
  Do not invent a project-specific product/spec hierarchy. If the repository already has product, domain, or spec docs, use them. If it does not, proceed with the evidence that exists.
57
58
 
@@ -96,16 +97,33 @@ Do not ask process questions such as whether to search, inspect files, or contin
96
97
 
97
98
  Lightweight tasks may have only `prd.md`. Complex tasks must have `prd.md`, `design.md`, and `implement.md` before `task.py start`.
98
99
 
99
- `implement.md` is not a replacement for `implement.jsonl`. Use JSONL files only for manifest-style spec and research references when the task needs them.
100
+ `implement.md` is not a replacement for `implement.jsonl`. On sub-agent-dispatch workflows, `implement.jsonl` and `check.jsonl` must each contain at least one real spec/research entry before `task.py start`; the seed `_example` row does not count. Inline workflows skip this JSONL gate because Phase 2 loads context through `trellis-before-dev`.
101
+
102
+ ## PRD Convergence Pass
103
+
104
+ Before declaring planning ready or running `task.py start`, rewrite `prd.md` once against the final structure described in the artifact rules above. This is not optional cleanup; it is the final planning gate.
105
+
106
+ The pass must be lossless:
107
+
108
+ - Collapse repeated facts into one authoritative section.
109
+ - Fold temporary brainstorm sections such as `What I already know`, `Assumptions`, and resolved `Open Questions` into Goal, Background, Requirements, Technical Notes, or Acceptance Criteria.
110
+ - Remove resolved open questions instead of leaving empty or already-answered sections.
111
+ - Merge parallel bug and requirement lists when they describe the same work; keep each defect's severity, evidence, and file:line anchors on the owning requirement.
112
+ - Preserve every file:line anchor, decision, constraint, requirement ID, and acceptance-criteria mapping.
113
+ - Keep only genuinely blocking open questions.
114
+
115
+ After the pass, read `prd.md` top to bottom and verify that no fact is repeated across sections unless the repetition adds new information.
100
116
 
101
117
  ## Quality Bar
102
118
 
103
119
  Before declaring planning ready:
104
120
 
105
121
  - `prd.md` contains testable acceptance criteria.
122
+ - `prd.md` has passed the PRD convergence pass: no unresolved temporary brainstorm sections, no duplicate facts across sections, and no lost anchors, decisions, or acceptance mappings.
106
123
  - Repository-answerable questions have already been answered through inspection.
107
124
  - Remaining open questions are genuinely about user intent or scope.
108
125
  - Complex tasks have `design.md` and `implement.md`.
126
+ - Sub-agent-dispatch tasks have real curated entries in both `implement.jsonl` and `check.jsonl`; seed-only manifests are not ready.
109
127
  - The user has reviewed the final planning artifacts or explicitly approved proceeding.
110
128
 
111
129
  Do not start implementation until the user approves or asks for implementation.
@@ -2,7 +2,7 @@
2
2
  name: trellis-check
3
3
  description: |
4
4
  Code quality check expert. Reviews changes against Trellis specs, fixes issues directly, and verifies quality gates.
5
- tools: Read, Write, Edit, Bash, Glob, Grep
5
+ tools: read, write, edit, bash, find, grep
6
6
  ---
7
7
  # Check Agent
8
8
 
@@ -2,7 +2,7 @@
2
2
  name: trellis-implement
3
3
  description: |
4
4
  Code implementation expert. Understands Trellis specs and requirements, then implements features. No git commit allowed.
5
- tools: Read, Write, Edit, Bash, Glob, Grep
5
+ tools: read, write, edit, bash, find, grep
6
6
  ---
7
7
  # Implement Agent
8
8
 
@@ -2,7 +2,7 @@
2
2
  name: trellis-research
3
3
  description: |
4
4
  Code and technical research expert. Finds relevant files, patterns, docs, and persists findings to the current task's research/ directory.
5
- tools: Read, Write, Bash, Glob, Grep
5
+ tools: read, write, bash, find, grep
6
6
  ---
7
7
  # Research Agent
8
8
 
@@ -31,11 +31,13 @@ interface SubagentInput {
31
31
  interface AgentConfig {
32
32
  model?: string;
33
33
  thinking?: string;
34
+ tools?: string[];
34
35
  fallbackModels: string[];
35
36
  }
36
37
  interface PiRunConfig {
37
38
  model?: string;
38
39
  thinking?: string;
40
+ tools?: string[];
39
41
  }
40
42
 
41
43
  // ── Lazy-load pi-tui (avoid failing top-level imports) ─────────────────
@@ -81,6 +83,10 @@ const MAX_PARALLEL_PROMPTS = 6;
81
83
  const ABORT_KILL_GRACE_MS = 1500;
82
84
  const SESSION_OVERVIEW_TIMEOUT_MS = 1500;
83
85
  const THROTTLE_MS = 500;
86
+ const FIRST_REPLY_NOTICE = `<first-reply-notice>
87
+ First visible reply: say once in Chinese that Trellis SessionStart context is loaded, then answer directly.
88
+ This notice is one-shot: do not repeat it after the first assistant reply in the same session.
89
+ </first-reply-notice>`;
84
90
 
85
91
  // ── State types ───────────────────────────────────────────────────────
86
92
  type RunStatus = "pending" | "running" | "succeeded" | "failed" | "cancelled";
@@ -654,8 +660,8 @@ function resolveRunCfg(
654
660
  agentSuffixThinking ??
655
661
  normalize(inheritedThinking);
656
662
  if (baseModel && thinking && thinking !== "off")
657
- return { model: `${baseModel}:${thinking}`, thinking };
658
- return { model: baseModel || rawModel, thinking };
663
+ return { model: `${baseModel}:${thinking}`, thinking, tools: agentCfg.tools };
664
+ return { model: baseModel || rawModel, thinking, tools: agentCfg.tools };
659
665
  }
660
666
 
661
667
  function buildPiArgs(cfg: PiRunConfig): string[] {
@@ -669,6 +675,8 @@ function buildPiArgs(cfg: PiRunConfig): string[] {
669
675
  );
670
676
  else if (cfg.thinking && cfg.thinking !== "off")
671
677
  args.push("--thinking", cfg.thinking);
678
+ if (cfg.tools && cfg.tools.length > 0)
679
+ args.push("--tools", cfg.tools.join(","));
672
680
  return args;
673
681
  }
674
682
 
@@ -762,6 +770,16 @@ function parseAgentFM(c: string): AgentConfig {
762
770
  }
763
771
  i--;
764
772
  }
773
+ } else if (k === "tools") {
774
+ // Pi tool names are lowercase (read, bash, edit, write, grep, find, ls).
775
+ // Normalize to lowercase so mixed-case frontmatter still matches.
776
+ if (v.trim()) {
777
+ cfg.tools = v
778
+ .trim()
779
+ .split(",")
780
+ .map((s) => s.trim().replace(/^["']|["']$/g, "").toLowerCase())
781
+ .filter(Boolean);
782
+ }
765
783
  }
766
784
  }
767
785
  return cfg;
@@ -862,12 +880,12 @@ function workflowBreadcrumb(root: string, key: string | null): string {
862
880
  }
863
881
 
864
882
  // ── Session Overview ───────────────────────────────────────────────────
865
- function sessionOverview(root: string, key: string | null): string {
883
+ function runContextScript(root: string, key: string | null, args: string[]): string {
866
884
  const script = join(root, ".trellis", "scripts", "get_context.py");
867
885
  if (!exists(script)) return "";
868
886
  try {
869
887
  const py = process.platform === "win32" ? "python" : "python3";
870
- const result = spawnSync(py, [script], {
888
+ const result = spawnSync(py, [script, ...args], {
871
889
  cwd: root,
872
890
  env: key ? { ...process.env, TRELLIS_CONTEXT_ID: key } : process.env,
873
891
  encoding: "utf-8",
@@ -876,12 +894,44 @@ function sessionOverview(root: string, key: string | null): string {
876
894
  });
877
895
  if (result.status !== 0) return "";
878
896
  const stdout = (result.stdout ?? "").trim();
879
- return stdout ? `<session-overview>\n${stdout}\n</session-overview>` : "";
897
+ return stdout;
880
898
  } catch {
881
899
  return "";
882
900
  }
883
901
  }
884
902
 
903
+ function sessionOverview(root: string, key: string | null): string {
904
+ const stdout = runContextScript(root, key, []);
905
+ return stdout ? `<session-overview>\n${stdout}\n</session-overview>` : "";
906
+ }
907
+
908
+ function workflowOverview(root: string, key: string | null): string {
909
+ const stdout = runContextScript(root, key, [
910
+ "--mode",
911
+ "phase",
912
+ "--platform",
913
+ "pi",
914
+ ]);
915
+ return stdout ? `<trellis-workflow>\n${stdout}\n</trellis-workflow>` : "";
916
+ }
917
+
918
+ function buildStartupContext(
919
+ root: string,
920
+ key: string | null,
921
+ overview: string,
922
+ ): string {
923
+ const workflow = workflowOverview(root, key);
924
+ return [
925
+ "<session-context>\nTrellis compact SessionStart context. Use it to orient the session; load details on demand.\n</session-context>",
926
+ FIRST_REPLY_NOTICE,
927
+ overview,
928
+ workflow,
929
+ "<ready>\nUse the current workflow state to decide whether to create, continue, or skip a Trellis task.\n</ready>",
930
+ ]
931
+ .filter(Boolean)
932
+ .join("\n\n");
933
+ }
934
+
885
935
  function buildContext(root: string, agent: string, key: string | null): string {
886
936
  const dir = readTaskDir(root, key);
887
937
  if (!dir)
@@ -1372,6 +1422,16 @@ export default function trellisExtension(pi: {
1372
1422
  };
1373
1423
  return turnCache;
1374
1424
  };
1425
+ const startupKeys = new Set<string>();
1426
+ const getStartupCtx = (
1427
+ k: string | null,
1428
+ turn: { ov: string },
1429
+ ): string => {
1430
+ const key = k ?? "default";
1431
+ if (startupKeys.has(key)) return "";
1432
+ startupKeys.add(key);
1433
+ return buildStartupContext(root, k, turn.ov);
1434
+ };
1375
1435
 
1376
1436
  // Toggle only the latest subagent native card; do not use Pi global tool expansion.
1377
1437
  const toggleDetail = (ctx: PiExtensionContext) => {
@@ -1550,7 +1610,7 @@ export default function trellisExtension(pi: {
1550
1610
  pi.on?.("session_start", (event, ctx) => {
1551
1611
  getKey(event, ctx);
1552
1612
  ctx?.ui?.notify?.(
1553
- "Trellis project context is available. Use /trellis-continue to resume the current task.",
1613
+ "Trellis project context is available. Use /trellis-start to bootstrap or /trellis-continue to resume.",
1554
1614
  "info",
1555
1615
  );
1556
1616
  });
@@ -1585,13 +1645,29 @@ export default function trellisExtension(pi: {
1585
1645
  return { isError: true };
1586
1646
  return undefined;
1587
1647
  });
1648
+ pi.on?.("input", (event, ctx) => {
1649
+ const k = getKey(event, ctx);
1650
+ const ev = event as { text?: string };
1651
+ if (typeof ev.text !== "string" || !ev.text.trim())
1652
+ return { action: "continue" };
1653
+ const { wf, ov } = getTurnCtx(k);
1654
+ const injection = [wf, ov].filter(Boolean).join("\n\n");
1655
+ if (!injection) return { action: "continue" };
1656
+ return {
1657
+ action: "transform",
1658
+ text: [ev.text, injection].join("\n\n"),
1659
+ };
1660
+ });
1588
1661
  pi.on?.("before_agent_start", (event, ctx) => {
1589
1662
  const k = getKey(event, ctx);
1590
1663
  const cur = (event as { systemPrompt?: string }).systemPrompt ?? "";
1591
1664
  const ctxText = buildContext(root, "trellis-implement", k);
1592
- const { wf, ov } = getTurnCtx(k);
1665
+ const turn = getTurnCtx(k);
1666
+ const startup = getStartupCtx(k, turn);
1593
1667
  return {
1594
- systemPrompt: [cur, ctxText, wf, ov].filter(Boolean).join("\n\n"),
1668
+ systemPrompt: [cur, startup, ctxText, turn.wf, turn.ov]
1669
+ .filter(Boolean)
1670
+ .join("\n\n"),
1595
1671
  };
1596
1672
  });
1597
1673
  pi.on?.("context", (event, ctx) => {
@@ -12,7 +12,7 @@ export interface HookScript {
12
12
  content: string;
13
13
  }
14
14
  export type SharedHookName = "session-start.py" | "inject-shell-session-context.py" | "inject-workflow-state.py" | "inject-subagent-context.py";
15
- export type SharedHookPlatform = "claude" | "cursor" | "codex" | "gemini" | "qoder" | "copilot" | "codebuddy" | "droid" | "kiro";
15
+ export type SharedHookPlatform = "claude" | "cursor" | "codex" | "gemini" | "qoder" | "copilot" | "codebuddy" | "droid" | "kiro" | "trae";
16
16
  /**
17
17
  * Which shared hooks each platform actually invokes. Single source of truth
18
18
  * for shared-hook distribution — both `writeSharedHooks` (runtime install)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/shared-hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,iCAAiC,GACjC,0BAA0B,GAC1B,4BAA4B,CAAC;AAEjC,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,SAAS,GACT,WAAW,GACX,OAAO,GACP,MAAM,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAC3C,kBAAkB,EAClB,SAAS,cAAc,EAAE,CA+B1B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,UAAU,EAAE,CAWnD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,kBAAkB,GAC3B,UAAU,EAAE,CAGd"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/shared-hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GACtB,kBAAkB,GAClB,iCAAiC,GACjC,0BAA0B,GAC1B,4BAA4B,CAAC;AAEjC,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,SAAS,GACT,WAAW,GACX,OAAO,GACP,MAAM,GACN,MAAM,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAC3C,kBAAkB,EAClB,SAAS,cAAc,EAAE,CAgC1B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,UAAU,EAAE,CAWnD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,kBAAkB,GAC3B,UAAU,EAAE,CAGd"}
@@ -73,6 +73,7 @@ export const SHARED_HOOKS_BY_PLATFORM = {
73
73
  "inject-workflow-state.py",
74
74
  "inject-subagent-context.py",
75
75
  ],
76
+ trae: ["session-start.py", "inject-workflow-state.py"],
76
77
  };
77
78
  /**
78
79
  * Get all shared hook scripts. Content is platform-independent and can be
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/shared-hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,SAAS,YAAY,CAAC,YAAoB;IACxC,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AA0BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAGjC;IACF,MAAM,EAAE;QACN,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,MAAM,EAAE;QACN,kBAAkB;QAClB,iCAAiC;QACjC,4BAA4B;KAC7B;IACD,KAAK,EAAE,CAAC,0BAA0B,CAAC;IACnC,MAAM,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IACxD,KAAK,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IACvD,OAAO,EAAE,CAAC,0BAA0B,CAAC;IACrC,SAAS,EAAE;QACT,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,KAAK,EAAE;QACL,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,IAAI,EAAE;QACJ,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC;SACjC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChC,IAAI,EAAE,CAAC;IAEV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAC7C,QAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpE,OAAO,oBAAoB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/shared-hooks/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,SAAS,YAAY,CAAC,YAAoB;IACxC,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAGjC;IACF,MAAM,EAAE;QACN,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,MAAM,EAAE;QACN,kBAAkB;QAClB,iCAAiC;QACjC,4BAA4B;KAC7B;IACD,KAAK,EAAE,CAAC,0BAA0B,CAAC;IACnC,MAAM,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IACxD,KAAK,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IACvD,OAAO,EAAE,CAAC,0BAA0B,CAAC;IACrC,SAAS,EAAE;QACT,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,KAAK,EAAE;QACL,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,IAAI,EAAE;QACJ,kBAAkB;QAClB,0BAA0B;QAC1B,4BAA4B;KAC7B;IACD,IAAI,EAAE,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;CACvD,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC;SACjC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChC,IAAI,EAAE,CAAC;IAEV,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAC7C,QAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,wBAAwB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpE,OAAO,oBAAoB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACnE,CAAC"}
@@ -34,6 +34,8 @@ import json
34
34
  import os
35
35
  import re
36
36
  import sys
37
+ import queue
38
+ import threading
37
39
  from pathlib import Path
38
40
 
39
41
  # Force UTF-8 on stdin/stdout/stderr on Windows. Default codepage there is
@@ -102,6 +104,7 @@ def _detect_platform(input_data: dict) -> str | None:
102
104
  "QODER_PROJECT_DIR": "qoder",
103
105
  "KIRO_PROJECT_DIR": "kiro",
104
106
  "COPILOT_PROJECT_DIR": "copilot",
107
+ "TRAE_PROJECT_DIR": "trae",
105
108
  }
106
109
  for env_name, platform in env_map.items():
107
110
  if os.environ.get(env_name):
@@ -123,6 +126,8 @@ def _detect_platform(input_data: dict) -> str | None:
123
126
  return "droid"
124
127
  if ".kiro" in script_parts:
125
128
  return "kiro"
129
+ if ".trae" in script_parts:
130
+ return "trae"
126
131
  return None
127
132
 
128
133
 
@@ -302,14 +307,44 @@ def build_breadcrumb(
302
307
  # Entry
303
308
  # ---------------------------------------------------------------------------
304
309
 
310
+ def _load_hook_input() -> dict:
311
+ """Read hook JSON without trusting host runners to close stdin.
312
+
313
+ Kiro IDE `runCommand` and similar hook runners can leave stdin open while
314
+ sending no payload. A plain `json.load(sys.stdin)` then blocks forever.
315
+ Normal hook runners write the complete JSON payload and close stdin, so the
316
+ short daemon read preserves that path while failing closed to `{}` for
317
+ non-piping hosts.
318
+ """
319
+ result_queue: "queue.Queue[str | BaseException]" = queue.Queue(maxsize=1)
320
+
321
+ def _read() -> None:
322
+ try:
323
+ result_queue.put(sys.stdin.read())
324
+ except BaseException as exc:
325
+ result_queue.put(exc)
326
+
327
+ reader = threading.Thread(target=_read, daemon=True)
328
+ reader.start()
329
+ try:
330
+ raw = result_queue.get(timeout=0.2)
331
+ except queue.Empty:
332
+ return {}
333
+
334
+ if isinstance(raw, BaseException):
335
+ return {}
336
+ try:
337
+ data = json.loads(raw) if raw.strip() else {}
338
+ except (json.JSONDecodeError, ValueError):
339
+ return {}
340
+ return data if isinstance(data, dict) else {}
341
+
342
+
305
343
  def main() -> int:
306
344
  if os.environ.get("TRELLIS_HOOKS") == "0" or os.environ.get("TRELLIS_DISABLE_HOOKS") == "1":
307
345
  return 0
308
346
 
309
- try:
310
- data = json.load(sys.stdin)
311
- except (json.JSONDecodeError, ValueError):
312
- data = {}
347
+ data = _load_hook_input()
313
348
 
314
349
  cwd_str = data.get("cwd") or os.getcwd()
315
350
  cwd = Path(cwd_str)
@@ -137,6 +137,7 @@ def should_skip_injection() -> bool:
137
137
  "GEMINI_NON_INTERACTIVE",
138
138
  "KIRO_NON_INTERACTIVE",
139
139
  "COPILOT_NON_INTERACTIVE",
140
+ "TRAE_NON_INTERACTIVE",
140
141
  ]
141
142
  return any(os.environ.get(var) == "1" for var in non_interactive_vars)
142
143
 
@@ -195,6 +196,7 @@ def _detect_platform(input_data: dict) -> str | None:
195
196
  "QODER_PROJECT_DIR": "qoder",
196
197
  "KIRO_PROJECT_DIR": "kiro",
197
198
  "COPILOT_PROJECT_DIR": "copilot",
199
+ "TRAE_PROJECT_DIR": "trae",
198
200
  }
199
201
  for env_name, platform in env_map.items():
200
202
  if os.environ.get(env_name):
@@ -216,6 +218,8 @@ def _detect_platform(input_data: dict) -> str | None:
216
218
  return "droid"
217
219
  if ".kiro" in script_parts:
218
220
  return "kiro"
221
+ if ".trae" in script_parts:
222
+ return "trae"
219
223
  return None
220
224
 
221
225
 
@@ -739,6 +743,7 @@ def main():
739
743
  "GEMINI_PROJECT_DIR",
740
744
  "KIRO_PROJECT_DIR",
741
745
  "COPILOT_PROJECT_DIR",
746
+ "TRAE_PROJECT_DIR",
742
747
  ]
743
748
  project_dir = None
744
749
  for var in project_dir_env_vars: