@mindfoldhq/trellis 0.6.0-beta.8 → 0.6.0-rc.0
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 +49 -49
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +59 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/channel/adapters/claude.d.ts +29 -0
- package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
- package/dist/commands/channel/adapters/claude.js +203 -0
- package/dist/commands/channel/adapters/claude.js.map +1 -0
- package/dist/commands/channel/adapters/codex.d.ts +85 -0
- package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
- package/dist/commands/channel/adapters/codex.js +505 -0
- package/dist/commands/channel/adapters/codex.js.map +1 -0
- package/dist/commands/channel/adapters/index.d.ts +84 -0
- package/dist/commands/channel/adapters/index.d.ts.map +1 -0
- package/dist/commands/channel/adapters/index.js +115 -0
- package/dist/commands/channel/adapters/index.js.map +1 -0
- package/dist/commands/channel/adapters/types.d.ts +33 -0
- package/dist/commands/channel/adapters/types.d.ts.map +1 -0
- package/dist/commands/channel/adapters/types.js +2 -0
- package/dist/commands/channel/adapters/types.js.map +1 -0
- package/dist/commands/channel/agent-loader.d.ts +32 -0
- package/dist/commands/channel/agent-loader.d.ts.map +1 -0
- package/dist/commands/channel/agent-loader.js +154 -0
- package/dist/commands/channel/agent-loader.js.map +1 -0
- package/dist/commands/channel/context-loader.d.ts +26 -0
- package/dist/commands/channel/context-loader.d.ts.map +1 -0
- package/dist/commands/channel/context-loader.js +290 -0
- package/dist/commands/channel/context-loader.js.map +1 -0
- package/dist/commands/channel/context.d.ts +16 -0
- package/dist/commands/channel/context.d.ts.map +1 -0
- package/dist/commands/channel/context.js +83 -0
- package/dist/commands/channel/context.js.map +1 -0
- package/dist/commands/channel/create.d.ts +27 -0
- package/dist/commands/channel/create.d.ts.map +1 -0
- package/dist/commands/channel/create.js +39 -0
- package/dist/commands/channel/create.js.map +1 -0
- package/dist/commands/channel/dev-parse-trace.d.ts +14 -0
- package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -0
- package/dist/commands/channel/dev-parse-trace.js +70 -0
- package/dist/commands/channel/dev-parse-trace.js.map +1 -0
- package/dist/commands/channel/guard.d.ts +150 -0
- package/dist/commands/channel/guard.d.ts.map +1 -0
- package/dist/commands/channel/guard.js +474 -0
- package/dist/commands/channel/guard.js.map +1 -0
- package/dist/commands/channel/index.d.ts +3 -0
- package/dist/commands/channel/index.d.ts.map +1 -0
- package/dist/commands/channel/index.js +531 -0
- package/dist/commands/channel/index.js.map +1 -0
- package/dist/commands/channel/interrupt.d.ts +10 -0
- package/dist/commands/channel/interrupt.d.ts.map +1 -0
- package/dist/commands/channel/interrupt.js +22 -0
- package/dist/commands/channel/interrupt.js.map +1 -0
- package/dist/commands/channel/kill.d.ts +7 -0
- package/dist/commands/channel/kill.d.ts.map +1 -0
- package/dist/commands/channel/kill.js +121 -0
- package/dist/commands/channel/kill.js.map +1 -0
- package/dist/commands/channel/list.d.ts +17 -0
- package/dist/commands/channel/list.d.ts.map +1 -0
- package/dist/commands/channel/list.js +233 -0
- package/dist/commands/channel/list.js.map +1 -0
- package/dist/commands/channel/messages.d.ts +15 -0
- package/dist/commands/channel/messages.d.ts.map +1 -0
- package/dist/commands/channel/messages.js +245 -0
- package/dist/commands/channel/messages.js.map +1 -0
- package/dist/commands/channel/rm.d.ts +27 -0
- package/dist/commands/channel/rm.d.ts.map +1 -0
- package/dist/commands/channel/rm.js +216 -0
- package/dist/commands/channel/rm.js.map +1 -0
- package/dist/commands/channel/run.d.ts +30 -0
- package/dist/commands/channel/run.d.ts.map +1 -0
- package/dist/commands/channel/run.js +130 -0
- package/dist/commands/channel/run.js.map +1 -0
- package/dist/commands/channel/send.d.ts +11 -0
- package/dist/commands/channel/send.d.ts.map +1 -0
- package/dist/commands/channel/send.js +24 -0
- package/dist/commands/channel/send.js.map +1 -0
- package/dist/commands/channel/spawn.d.ts +40 -0
- package/dist/commands/channel/spawn.d.ts.map +1 -0
- package/dist/commands/channel/spawn.js +244 -0
- package/dist/commands/channel/spawn.js.map +1 -0
- package/dist/commands/channel/store/events.d.ts +39 -0
- package/dist/commands/channel/store/events.d.ts.map +1 -0
- package/dist/commands/channel/store/events.js +87 -0
- package/dist/commands/channel/store/events.js.map +1 -0
- package/dist/commands/channel/store/filter.d.ts +3 -0
- package/dist/commands/channel/store/filter.d.ts.map +1 -0
- package/dist/commands/channel/store/filter.js +2 -0
- package/dist/commands/channel/store/filter.js.map +1 -0
- package/dist/commands/channel/store/lock.d.ts +23 -0
- package/dist/commands/channel/store/lock.d.ts.map +1 -0
- package/dist/commands/channel/store/lock.js +99 -0
- package/dist/commands/channel/store/lock.js.map +1 -0
- package/dist/commands/channel/store/paths.d.ts +63 -0
- package/dist/commands/channel/store/paths.d.ts.map +1 -0
- package/dist/commands/channel/store/paths.js +246 -0
- package/dist/commands/channel/store/paths.js.map +1 -0
- package/dist/commands/channel/store/schema.d.ts +27 -0
- package/dist/commands/channel/store/schema.d.ts.map +1 -0
- package/dist/commands/channel/store/schema.js +34 -0
- package/dist/commands/channel/store/schema.js.map +1 -0
- package/dist/commands/channel/store/thread-state.d.ts +5 -0
- package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
- package/dist/commands/channel/store/thread-state.js +16 -0
- package/dist/commands/channel/store/thread-state.js.map +1 -0
- package/dist/commands/channel/store/watch.d.ts +19 -0
- package/dist/commands/channel/store/watch.d.ts.map +1 -0
- package/dist/commands/channel/store/watch.js +146 -0
- package/dist/commands/channel/store/watch.js.map +1 -0
- package/dist/commands/channel/supervisor/idle.d.ts +46 -0
- package/dist/commands/channel/supervisor/idle.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/idle.js +72 -0
- package/dist/commands/channel/supervisor/idle.js.map +1 -0
- package/dist/commands/channel/supervisor/inbox.d.ts +30 -0
- package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/inbox.js +160 -0
- package/dist/commands/channel/supervisor/inbox.js.map +1 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts +68 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/shutdown.js +146 -0
- package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
- package/dist/commands/channel/supervisor/stdout.d.ts +51 -0
- package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/stdout.js +121 -0
- package/dist/commands/channel/supervisor/stdout.js.map +1 -0
- package/dist/commands/channel/supervisor/turns.d.ts +31 -0
- package/dist/commands/channel/supervisor/turns.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/turns.js +45 -0
- package/dist/commands/channel/supervisor/turns.js.map +1 -0
- package/dist/commands/channel/supervisor/warning.d.ts +48 -0
- package/dist/commands/channel/supervisor/warning.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/warning.js +77 -0
- package/dist/commands/channel/supervisor/warning.js.map +1 -0
- package/dist/commands/channel/supervisor.d.ts +59 -0
- package/dist/commands/channel/supervisor.d.ts.map +1 -0
- package/dist/commands/channel/supervisor.js +344 -0
- package/dist/commands/channel/supervisor.js.map +1 -0
- package/dist/commands/channel/text-body.d.ts +13 -0
- package/dist/commands/channel/text-body.d.ts.map +1 -0
- package/dist/commands/channel/text-body.js +47 -0
- package/dist/commands/channel/text-body.js.map +1 -0
- package/dist/commands/channel/threads.d.ts +39 -0
- package/dist/commands/channel/threads.d.ts.map +1 -0
- package/dist/commands/channel/threads.js +106 -0
- package/dist/commands/channel/threads.js.map +1 -0
- package/dist/commands/channel/title.d.ts +12 -0
- package/dist/commands/channel/title.d.ts.map +1 -0
- package/dist/commands/channel/title.js +24 -0
- package/dist/commands/channel/title.js.map +1 -0
- package/dist/commands/channel/wait.d.ts +17 -0
- package/dist/commands/channel/wait.d.ts.map +1 -0
- package/dist/commands/channel/wait.js +75 -0
- package/dist/commands/channel/wait.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +162 -43
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mem.d.ts +13 -217
- package/dist/commands/mem.d.ts.map +1 -1
- package/dist/commands/mem.js +142 -1587
- package/dist/commands/mem.js.map +1 -1
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +28 -2
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +104 -7
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/upgrade.d.ts +28 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +84 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/workflow.d.ts +35 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +232 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/configurators/claude.d.ts.map +1 -1
- package/dist/configurators/claude.js +1 -0
- package/dist/configurators/claude.js.map +1 -1
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +5 -0
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/reasonix.d.ts +23 -0
- package/dist/configurators/reasonix.d.ts.map +1 -0
- package/dist/configurators/reasonix.js +60 -0
- package/dist/configurators/reasonix.js.map +1 -0
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +8 -0
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/workflow.d.ts +8 -0
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +14 -3
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/constants/paths.d.ts +4 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +4 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/migrations/manifests/0.5.13.json +9 -0
- package/dist/migrations/manifests/0.5.14.json +9 -0
- package/dist/migrations/manifests/0.5.15.json +9 -0
- package/dist/migrations/manifests/0.5.16.json +9 -0
- package/dist/migrations/manifests/0.5.17.json +9 -0
- package/dist/migrations/manifests/0.5.18.json +9 -0
- package/dist/migrations/manifests/0.5.19.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.15.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.16.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.17.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.18.json +16 -0
- package/dist/migrations/manifests/0.6.0-beta.19.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.20.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.21.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.22.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.23.json +88 -0
- package/dist/migrations/manifests/0.6.0-beta.9.json +9 -0
- package/dist/migrations/manifests/0.6.0-rc.0.json +9 -0
- package/dist/templates/claude/agents/trellis-check.md +12 -6
- package/dist/templates/claude/agents/trellis-implement.md +1 -1
- package/dist/templates/claude/agents/trellis-research.md +1 -1
- package/dist/templates/claude/settings.json +4 -4
- package/dist/templates/codebuddy/agents/trellis-check.md +12 -6
- package/dist/templates/codebuddy/agents/trellis-implement.md +1 -1
- package/dist/templates/codebuddy/agents/trellis-research.md +1 -1
- package/dist/templates/codebuddy/settings.json +4 -4
- package/dist/templates/codex/agents/trellis-check.toml +0 -25
- package/dist/templates/codex/agents/trellis-implement.toml +0 -25
- package/dist/templates/codex/config.toml +9 -16
- package/dist/templates/codex/hooks/session-start.py +22 -0
- package/dist/templates/codex/hooks.json +2 -2
- package/dist/templates/codex/skills/brainstorm/SKILL.md +69 -519
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +27 -0
- package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +81 -0
- package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +66 -0
- package/dist/templates/common/bundled-skills/trellis-session-insight/references/triggering-patterns.md +93 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/SKILL.md +41 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/mcp-setup.md +90 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/repository-analysis.md +59 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-task-planning.md +61 -0
- package/dist/templates/common/bundled-skills/trellis-spec-bootstrap/references/spec-writing.md +70 -0
- package/dist/templates/common/skills/brainstorm.md +68 -518
- package/dist/templates/copilot/hooks/session-start.py +36 -11
- package/dist/templates/copilot/hooks.json +2 -2
- package/dist/templates/copilot/prompts/brainstorm.prompt.md +69 -519
- package/dist/templates/cursor/agents/trellis-check.md +12 -6
- package/dist/templates/cursor/agents/trellis-implement.md +1 -1
- package/dist/templates/cursor/agents/trellis-research.md +1 -1
- package/dist/templates/cursor/hooks.json +1 -7
- package/dist/templates/droid/droids/trellis-check.md +12 -6
- package/dist/templates/droid/droids/trellis-implement.md +1 -1
- package/dist/templates/droid/droids/trellis-research.md +1 -1
- package/dist/templates/droid/settings.json +4 -4
- package/dist/templates/gemini/agents/trellis-check.md +11 -5
- package/dist/templates/gemini/settings.json +2 -2
- package/dist/templates/kiro/agents/trellis-check.json +1 -1
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +127 -9
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +171 -6
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +48 -4
- package/dist/templates/markdown/spec/guides/index.md.txt +18 -0
- package/dist/templates/opencode/agents/trellis-check.md +11 -5
- package/dist/templates/opencode/lib/trellis-context.js +73 -11
- package/dist/templates/opencode/plugins/inject-subagent-context.js +112 -26
- package/dist/templates/opencode/plugins/inject-workflow-state.js +8 -1
- package/dist/templates/opencode/plugins/session-start.js +9 -1
- package/dist/templates/pi/agents/trellis-check.md +5 -4
- package/dist/templates/pi/agents/trellis-implement.md +5 -4
- package/dist/templates/pi/extensions/trellis/index.ts.txt +1339 -913
- package/dist/templates/pi/settings.json +0 -9
- package/dist/templates/qoder/agents/trellis-check.md +12 -6
- package/dist/templates/qoder/agents/trellis-implement.md +1 -1
- package/dist/templates/qoder/agents/trellis-research.md +1 -1
- package/dist/templates/qoder/settings.json +4 -4
- package/dist/templates/reasonix/agents/trellis-check.md +36 -0
- package/dist/templates/reasonix/agents/trellis-implement.md +41 -0
- package/dist/templates/reasonix/index.d.ts +13 -0
- package/dist/templates/reasonix/index.d.ts.map +1 -0
- package/dist/templates/reasonix/index.js +16 -0
- package/dist/templates/reasonix/index.js.map +1 -0
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +0 -1
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/inject-workflow-state.py +22 -0
- package/dist/templates/shared-hooks/session-start.py +25 -8
- package/dist/templates/trellis/agents/check.md +70 -0
- package/dist/templates/trellis/agents/implement.md +71 -0
- package/dist/templates/trellis/config.yaml +20 -0
- package/dist/templates/trellis/index.d.ts +13 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +22 -0
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/common/safe_commit.py +49 -19
- package/dist/templates/trellis/scripts/common/session_context.py +215 -138
- package/dist/templates/trellis/scripts/common/task_store.py +94 -16
- package/dist/templates/trellis/workflow.md +21 -0
- package/dist/types/ai-tools.d.ts +4 -4
- 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/agent-refs.d.ts +31 -0
- package/dist/utils/agent-refs.d.ts.map +1 -0
- package/dist/utils/agent-refs.js +63 -0
- package/dist/utils/agent-refs.js.map +1 -0
- package/dist/utils/cwd-guard.d.ts +38 -0
- package/dist/utils/cwd-guard.d.ts.map +1 -0
- package/dist/utils/cwd-guard.js +62 -0
- package/dist/utils/cwd-guard.js.map +1 -0
- package/dist/utils/file-writer.d.ts +13 -0
- package/dist/utils/file-writer.d.ts.map +1 -1
- package/dist/utils/file-writer.js +59 -1
- package/dist/utils/file-writer.js.map +1 -1
- package/dist/utils/manifest-prune.d.ts +61 -0
- package/dist/utils/manifest-prune.d.ts.map +1 -0
- package/dist/utils/manifest-prune.js +136 -0
- package/dist/utils/manifest-prune.js.map +1 -0
- package/dist/utils/registry-config.d.ts +7 -0
- package/dist/utils/registry-config.d.ts.map +1 -0
- package/dist/utils/registry-config.js +171 -0
- package/dist/utils/registry-config.js.map +1 -0
- package/dist/utils/task-json.d.ts +9 -42
- package/dist/utils/task-json.d.ts.map +1 -1
- package/dist/utils/task-json.js +8 -45
- package/dist/utils/task-json.js.map +1 -1
- package/dist/utils/template-fetcher.d.ts +11 -0
- package/dist/utils/template-fetcher.d.ts.map +1 -1
- package/dist/utils/template-fetcher.js +51 -2
- package/dist/utils/template-fetcher.js.map +1 -1
- package/dist/utils/template-hash.d.ts +32 -6
- package/dist/utils/template-hash.d.ts.map +1 -1
- package/dist/utils/template-hash.js +53 -31
- package/dist/utils/template-hash.js.map +1 -1
- package/dist/utils/workflow-resolver.d.ts +86 -0
- package/dist/utils/workflow-resolver.d.ts.map +1 -0
- package/dist/utils/workflow-resolver.js +265 -0
- package/dist/utils/workflow-resolver.js.map +1 -0
- package/package.json +9 -8
|
@@ -215,20 +215,26 @@ home = Path.home()
|
|
|
215
215
|
```
|
|
216
216
|
|
|
217
217
|
**Rule 2**: When injecting environment variables into shell commands, generate
|
|
218
|
-
the prefix for the actual
|
|
219
|
-
AI tool "Bash" surfaces on Windows may execute through
|
|
218
|
+
the prefix for the actual shell that will parse the command. Do not choose
|
|
219
|
+
syntax from OS alone. AI tool "Bash" surfaces on Windows may execute through
|
|
220
|
+
PowerShell, Git Bash, MSYS2, or another POSIX-like shell.
|
|
220
221
|
|
|
221
222
|
```javascript
|
|
222
223
|
// BAD - breaks when the host shell is PowerShell
|
|
223
224
|
command = `export TRELLIS_CONTEXT_ID=${shellQuote(contextKey)}; ${command}`;
|
|
224
225
|
|
|
225
|
-
// GOOD - shell-aware command prefix
|
|
226
|
-
const prefix = process.platform === "win32"
|
|
226
|
+
// GOOD - shell-dialect-aware command prefix
|
|
227
|
+
const prefix = process.platform === "win32" && !isWindowsPosixShell(process.env)
|
|
227
228
|
? `$env:TRELLIS_CONTEXT_ID = ${powershellQuote(contextKey)}; `
|
|
228
229
|
: `export TRELLIS_CONTEXT_ID=${shellQuote(contextKey)}; `;
|
|
229
230
|
command = `${prefix}${command}`;
|
|
230
231
|
```
|
|
231
232
|
|
|
233
|
+
On Windows, treat `MSYSTEM`, `MINGW_PREFIX`, `OSTYPE=msys|mingw|cygwin`,
|
|
234
|
+
`SHELL=...bash`, or a platform-specific Git Bash setting as POSIX-shell
|
|
235
|
+
signals. Keep PowerShell as the Windows default when there is no POSIX-shell
|
|
236
|
+
signal.
|
|
237
|
+
|
|
232
238
|
Also make duplicate-injection detection shell-aware. A guard that only matches
|
|
233
239
|
`export VAR=` will miss PowerShell's `$env:VAR = ...` form and can wrap an
|
|
234
240
|
already-correct command a second time.
|
|
@@ -587,3 +593,41 @@ const { getMigrationsForVersion } = require('./dist/migrations/index.js');
|
|
|
587
593
|
console.log('From 0.2.12:', getMigrationsForVersion('0.2.12', 'CURRENT').length);
|
|
588
594
|
"
|
|
589
595
|
```
|
|
596
|
+
|
|
597
|
+
## Release Checklist: Bundled Assets
|
|
598
|
+
|
|
599
|
+
When release notes or docs claim an asset is bundled, installed automatically, or
|
|
600
|
+
included with Trellis, verify the whole distribution path:
|
|
601
|
+
|
|
602
|
+
- [ ] Source file exists in the branch being tagged, not only in another branch,
|
|
603
|
+
docs submodule, or marketplace tree.
|
|
604
|
+
- [ ] `pnpm build` copies the asset into `dist/templates/**`.
|
|
605
|
+
- [ ] `npm pack --dry-run --json` includes the expected `dist/**` path.
|
|
606
|
+
- [ ] The built binary installs the asset in a fresh temp repository.
|
|
607
|
+
- [ ] `.trellis/.template-hashes.json` tracks the generated asset path.
|
|
608
|
+
- [ ] `trellis update --dry-run` reports `Already up to date!` in that temp
|
|
609
|
+
repository.
|
|
610
|
+
|
|
611
|
+
**Why this matters**: docs/changelog text can move independently from the code
|
|
612
|
+
branch that owns distributable templates. A feature can be documented as bundled
|
|
613
|
+
while the published npm tarball still lacks the files.
|
|
614
|
+
|
|
615
|
+
```bash
|
|
616
|
+
pnpm --filter @mindfoldhq/trellis build
|
|
617
|
+
|
|
618
|
+
cd packages/cli
|
|
619
|
+
npm pack --dry-run --json | grep 'dist/templates/common/bundled-skills/<skill>/SKILL.md'
|
|
620
|
+
cd ../..
|
|
621
|
+
|
|
622
|
+
tmpdir=$(mktemp -d /tmp/trellis-built-bin-smoke-XXXXXX)
|
|
623
|
+
printf '{"name":"trellis-smoke","version":"0.0.0"}\n' > "$tmpdir/package.json"
|
|
624
|
+
git -C "$tmpdir" init -q
|
|
625
|
+
(
|
|
626
|
+
cd "$tmpdir"
|
|
627
|
+
node /path/to/Trellis/packages/cli/bin/trellis.js init -u smoke --yes --claude --codex
|
|
628
|
+
test -f .claude/skills/<skill>/SKILL.md
|
|
629
|
+
test -f .agents/skills/<skill>/SKILL.md
|
|
630
|
+
grep -q '<skill>' .trellis/.template-hashes.json
|
|
631
|
+
node /path/to/Trellis/packages/cli/bin/trellis.js update --dry-run
|
|
632
|
+
)
|
|
633
|
+
```
|
|
@@ -34,6 +34,8 @@ These guides help you **ask the right questions before coding**.
|
|
|
34
34
|
- [ ] Data format changes between layers
|
|
35
35
|
- [ ] Multiple consumers need the same data
|
|
36
36
|
- [ ] You're not sure where to put some logic
|
|
37
|
+
- [ ] You are adding an event kind, JSONL record, RPC payload, or config field
|
|
38
|
+
- [ ] UI / command code starts casting raw payload fields directly
|
|
37
39
|
|
|
38
40
|
→ Read [Cross-Layer Thinking Guide](./cross-layer-thinking-guide.md)
|
|
39
41
|
|
|
@@ -44,9 +46,25 @@ These guides help you **ask the right questions before coding**.
|
|
|
44
46
|
- [ ] You're adding a new field to multiple places
|
|
45
47
|
- [ ] **You're modifying any constant or config**
|
|
46
48
|
- [ ] **You're creating a new utility/helper function** ← Search first!
|
|
49
|
+
- [ ] Two files read the same untyped payload field with local casts
|
|
50
|
+
- [ ] Multiple branches update the same derived state from `kind` / `action`
|
|
47
51
|
|
|
48
52
|
→ Read [Code Reuse Thinking Guide](./code-reuse-thinking-guide.md)
|
|
49
53
|
|
|
54
|
+
### When Verifying AI Cross-Review Results
|
|
55
|
+
|
|
56
|
+
- [ ] Reviewer claims "user input can be malicious" → Check the actual data source (internal manifest? user config? external API?)
|
|
57
|
+
- [ ] Reviewer flags "missing validation" → Is the data from a trusted internal source?
|
|
58
|
+
- [ ] Reviewer says "behavior change" → Read the code comments — is it intentional design?
|
|
59
|
+
- [ ] Reviewer identifies a "bug" in test → Mentally delete the feature being tested — does the test still pass? If yes → tautological test
|
|
60
|
+
|
|
61
|
+
**Common AI reviewer false-positive patterns**:
|
|
62
|
+
1. **Trust boundary confusion**: Treating internal data (bundled JSON manifests) as untrusted external input
|
|
63
|
+
2. **Ignoring design comments**: Flagging intentional behavior documented in code comments as bugs
|
|
64
|
+
3. **Variable misreading**: Not tracing a variable to its actual definition (e.g., Map keyed by path vs name)
|
|
65
|
+
|
|
66
|
+
**Verification rule**: Every CRITICAL/WARNING finding must be verified against the actual code before prioritizing. Budget ~35% false-positive rate for AI reviews.
|
|
67
|
+
|
|
50
68
|
---
|
|
51
69
|
|
|
52
70
|
## Pre-Modification Rule (CRITICAL)
|
|
@@ -34,14 +34,18 @@ Look for the `<!-- trellis-hook-injected -->` marker in your input above.
|
|
|
34
34
|
|
|
35
35
|
Before checking, read:
|
|
36
36
|
- `.trellis/spec/` - Development guidelines
|
|
37
|
+
- Task `prd.md` - Requirements document
|
|
38
|
+
- Task `design.md` - Technical design (if exists)
|
|
39
|
+
- Task `implement.md` - Execution plan (if exists)
|
|
37
40
|
- Pre-commit checklist for quality standards
|
|
38
41
|
|
|
39
42
|
## Core Responsibilities
|
|
40
43
|
|
|
41
44
|
1. **Get code changes** - Use git diff to get uncommitted code
|
|
42
|
-
2. **
|
|
43
|
-
3. **
|
|
44
|
-
4. **
|
|
45
|
+
2. **Review task artifacts** - Check changes against prd.md, design.md if present, and implement.md if present
|
|
46
|
+
3. **Check against specs** - Verify code follows guidelines
|
|
47
|
+
4. **Self-fix** - Fix issues yourself, not just report them
|
|
48
|
+
5. **Run verification** - typecheck and lint
|
|
45
49
|
|
|
46
50
|
## Important
|
|
47
51
|
|
|
@@ -60,10 +64,12 @@ git diff --name-only # List changed files
|
|
|
60
64
|
git diff # View specific changes
|
|
61
65
|
```
|
|
62
66
|
|
|
63
|
-
### Step 2: Check Against Specs
|
|
67
|
+
### Step 2: Check Against Specs and Task Artifacts
|
|
64
68
|
|
|
65
|
-
Read relevant specs in `.trellis/spec/` to check code:
|
|
69
|
+
Read the task's prd.md, design.md if present, and implement.md if present, then read relevant specs in `.trellis/spec/` to check code:
|
|
66
70
|
|
|
71
|
+
- Does it satisfy the task requirements
|
|
72
|
+
- Does it follow the technical design and implementation plan when present
|
|
67
73
|
- Does it follow directory structure conventions
|
|
68
74
|
- Does it follow naming conventions
|
|
69
75
|
- Does it follow code patterns
|
|
@@ -63,6 +63,21 @@ function buildContextKey(platformName, kind, value) {
|
|
|
63
63
|
return safeValue ? `${platformName}_${safeValue}` : `${platformName}_${hashValue(value)}`
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// Matches `trellis-implement`, `trellis-check`, `trellis-research` exactly.
|
|
67
|
+
// Used by chat.message plugins to skip injection inside Trellis sub-agent turns.
|
|
68
|
+
const TRELLIS_SUBAGENT_RE = /^trellis-(implement|check|research)$/
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Return true when the OpenCode `chat.message` input represents a Trellis
|
|
72
|
+
* sub-agent turn. `input.agent` is set by OpenCode when a Task tool spawns a
|
|
73
|
+
* child session with a custom agent (see `packages/opencode/src/tool/task.ts`).
|
|
74
|
+
*/
|
|
75
|
+
export function isTrellisSubagent(input) {
|
|
76
|
+
if (!input || typeof input !== "object") return false
|
|
77
|
+
const agent = typeof input.agent === "string" ? input.agent.trim() : ""
|
|
78
|
+
return TRELLIS_SUBAGENT_RE.test(agent)
|
|
79
|
+
}
|
|
80
|
+
|
|
66
81
|
/**
|
|
67
82
|
* Trellis Context Manager
|
|
68
83
|
*/
|
|
@@ -116,27 +131,74 @@ export class TrellisContext {
|
|
|
116
131
|
|
|
117
132
|
/**
|
|
118
133
|
* Get active task from session runtime context.
|
|
134
|
+
*
|
|
135
|
+
* Resolution order (mirrors Python `active_task.resolve_active_task`):
|
|
136
|
+
* 1. Lookup the runtime file for the input-derived context key.
|
|
137
|
+
* 2. If that misses and exactly one session runtime file exists locally,
|
|
138
|
+
* use it (`_resolveSingleSessionFallback`). Refuses to guess when 0 or
|
|
139
|
+
* ≥2 files exist so multi-window isolation holds.
|
|
119
140
|
*/
|
|
120
141
|
getActiveTask(platformInput = null) {
|
|
121
142
|
const contextKey = this.getContextKey(platformInput)
|
|
122
|
-
if (
|
|
123
|
-
|
|
143
|
+
if (contextKey) {
|
|
144
|
+
const context = this.readContext(contextKey)
|
|
145
|
+
const taskRef = this.normalizeTaskRef(context?.current_task || "")
|
|
146
|
+
if (taskRef) {
|
|
147
|
+
const taskDir = this.resolveTaskDir(taskRef)
|
|
148
|
+
return {
|
|
149
|
+
taskPath: taskRef,
|
|
150
|
+
source: `session:${contextKey}`,
|
|
151
|
+
stale: !taskDir || !existsSync(taskDir),
|
|
152
|
+
}
|
|
153
|
+
}
|
|
124
154
|
}
|
|
125
155
|
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const taskDir = this.resolveTaskDir(taskRef)
|
|
130
|
-
return {
|
|
131
|
-
taskPath: taskRef,
|
|
132
|
-
source: `session:${contextKey}`,
|
|
133
|
-
stale: !taskDir || !existsSync(taskDir),
|
|
134
|
-
}
|
|
156
|
+
const fallback = this._resolveSingleSessionFallback()
|
|
157
|
+
if (fallback) {
|
|
158
|
+
return fallback
|
|
135
159
|
}
|
|
136
160
|
|
|
137
161
|
return { taskPath: null, source: "none", stale: false }
|
|
138
162
|
}
|
|
139
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Mirror of Python `_resolve_single_session_fallback`. Returns the task
|
|
166
|
+
* pointed at by the sole session runtime file when exactly one exists,
|
|
167
|
+
* else null.
|
|
168
|
+
*/
|
|
169
|
+
_resolveSingleSessionFallback() {
|
|
170
|
+
const sessionsDir = join(this.directory, ".trellis", ".runtime", "sessions")
|
|
171
|
+
if (!existsSync(sessionsDir)) return null
|
|
172
|
+
|
|
173
|
+
let files
|
|
174
|
+
try {
|
|
175
|
+
files = readdirSync(sessionsDir)
|
|
176
|
+
.filter(name => name.endsWith(".json"))
|
|
177
|
+
.sort()
|
|
178
|
+
} catch {
|
|
179
|
+
return null
|
|
180
|
+
}
|
|
181
|
+
if (files.length !== 1) return null
|
|
182
|
+
|
|
183
|
+
const sessionFile = join(sessionsDir, files[0])
|
|
184
|
+
let context
|
|
185
|
+
try {
|
|
186
|
+
context = JSON.parse(readFileSync(sessionFile, "utf-8"))
|
|
187
|
+
} catch {
|
|
188
|
+
return null
|
|
189
|
+
}
|
|
190
|
+
const taskRef = this.normalizeTaskRef(context?.current_task || "")
|
|
191
|
+
if (!taskRef) return null
|
|
192
|
+
|
|
193
|
+
const taskDir = this.resolveTaskDir(taskRef)
|
|
194
|
+
const fallbackKey = files[0].replace(/\.json$/, "")
|
|
195
|
+
return {
|
|
196
|
+
taskPath: taskRef,
|
|
197
|
+
source: `session-fallback:${fallbackKey}`,
|
|
198
|
+
stale: !taskDir || !existsSync(taskDir),
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
140
202
|
getCurrentTask(platformInput = null) {
|
|
141
203
|
return this.getActiveTask(platformInput).taskPath
|
|
142
204
|
}
|
|
@@ -14,29 +14,44 @@ import { TrellisContext, debugLog } from "../lib/trellis-context.js"
|
|
|
14
14
|
const AGENTS_ALL = ["implement", "check", "research"]
|
|
15
15
|
const AGENTS_REQUIRE_TASK = ["implement", "check"]
|
|
16
16
|
|
|
17
|
+
// Match `Active task: <path>` on the first non-empty line of the dispatch
|
|
18
|
+
// prompt. Mirrors the contract in workflow.md's [workflow-state:in_progress]
|
|
19
|
+
// breadcrumb so multi-window users can disambiguate which task is targeted.
|
|
20
|
+
const ACTIVE_TASK_HINT_RE = /^\s*Active task:\s*(\S+)\s*$/m
|
|
21
|
+
|
|
22
|
+
function extractActiveTaskHint(prompt) {
|
|
23
|
+
if (typeof prompt !== "string" || !prompt) return null
|
|
24
|
+
const match = prompt.match(ACTIVE_TASK_HINT_RE)
|
|
25
|
+
return match ? match[1].trim() : null
|
|
26
|
+
}
|
|
27
|
+
|
|
17
28
|
/**
|
|
18
|
-
* Get context for implement agent
|
|
29
|
+
* Get context for implement agent. `taskDir` may be relative
|
|
30
|
+
* (`.trellis/tasks/foo`) or absolute; both are resolved via
|
|
31
|
+
* `ctx.resolveTaskDir`.
|
|
19
32
|
*/
|
|
20
33
|
function getImplementContext(ctx, taskDir) {
|
|
21
34
|
const parts = []
|
|
35
|
+
const taskDirFull = ctx.resolveTaskDir(taskDir)
|
|
36
|
+
if (!taskDirFull) return ""
|
|
22
37
|
|
|
23
|
-
const jsonlPath = join(
|
|
38
|
+
const jsonlPath = join(taskDirFull, "implement.jsonl")
|
|
24
39
|
const entries = ctx.readJsonlWithFiles(jsonlPath)
|
|
25
40
|
if (entries.length > 0) {
|
|
26
41
|
parts.push(ctx.buildContextFromEntries(entries))
|
|
27
42
|
}
|
|
28
43
|
|
|
29
|
-
const prd = ctx.
|
|
44
|
+
const prd = ctx.readFile(join(taskDirFull, "prd.md"))
|
|
30
45
|
if (prd) {
|
|
31
46
|
parts.push(`=== ${taskDir}/prd.md (Requirements) ===\n${prd}`)
|
|
32
47
|
}
|
|
33
48
|
|
|
34
|
-
const design = ctx.
|
|
49
|
+
const design = ctx.readFile(join(taskDirFull, "design.md"))
|
|
35
50
|
if (design) {
|
|
36
51
|
parts.push(`=== ${taskDir}/design.md (Technical Design) ===\n${design}`)
|
|
37
52
|
}
|
|
38
53
|
|
|
39
|
-
const implementPlan = ctx.
|
|
54
|
+
const implementPlan = ctx.readFile(join(taskDirFull, "implement.md"))
|
|
40
55
|
if (implementPlan) {
|
|
41
56
|
parts.push(`=== ${taskDir}/implement.md (Execution Plan) ===\n${implementPlan}`)
|
|
42
57
|
}
|
|
@@ -45,28 +60,30 @@ function getImplementContext(ctx, taskDir) {
|
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
/**
|
|
48
|
-
* Get context for check agent
|
|
63
|
+
* Get context for check agent. `taskDir` may be relative or absolute.
|
|
49
64
|
*/
|
|
50
65
|
function getCheckContext(ctx, taskDir) {
|
|
51
66
|
const parts = []
|
|
67
|
+
const taskDirFull = ctx.resolveTaskDir(taskDir)
|
|
68
|
+
if (!taskDirFull) return ""
|
|
52
69
|
|
|
53
|
-
const jsonlPath = join(
|
|
70
|
+
const jsonlPath = join(taskDirFull, "check.jsonl")
|
|
54
71
|
const entries = ctx.readJsonlWithFiles(jsonlPath)
|
|
55
72
|
if (entries.length > 0) {
|
|
56
73
|
parts.push(ctx.buildContextFromEntries(entries))
|
|
57
74
|
}
|
|
58
75
|
|
|
59
|
-
const prd = ctx.
|
|
76
|
+
const prd = ctx.readFile(join(taskDirFull, "prd.md"))
|
|
60
77
|
if (prd) {
|
|
61
78
|
parts.push(`=== ${taskDir}/prd.md (Requirements) ===\n${prd}`)
|
|
62
79
|
}
|
|
63
80
|
|
|
64
|
-
const design = ctx.
|
|
81
|
+
const design = ctx.readFile(join(taskDirFull, "design.md"))
|
|
65
82
|
if (design) {
|
|
66
83
|
parts.push(`=== ${taskDir}/design.md (Technical Design) ===\n${design}`)
|
|
67
84
|
}
|
|
68
85
|
|
|
69
|
-
const implementPlan = ctx.
|
|
86
|
+
const implementPlan = ctx.readFile(join(taskDirFull, "implement.md"))
|
|
70
87
|
if (implementPlan) {
|
|
71
88
|
parts.push(`=== ${taskDir}/implement.md (Execution Plan) ===\n${implementPlan}`)
|
|
72
89
|
}
|
|
@@ -143,7 +160,8 @@ function getResearchContext(ctx) {
|
|
|
143
160
|
*/
|
|
144
161
|
function buildPrompt(agentType, originalPrompt, context, isFinish = false) {
|
|
145
162
|
const templates = {
|
|
146
|
-
implement:
|
|
163
|
+
implement: `<!-- trellis-hook-injected -->
|
|
164
|
+
# Implement Agent Task
|
|
147
165
|
|
|
148
166
|
You are the Implement Agent in the Multi-Agent Pipeline.
|
|
149
167
|
|
|
@@ -172,7 +190,8 @@ ${originalPrompt}
|
|
|
172
190
|
- Follow all dev specs injected above
|
|
173
191
|
- Report list of modified/created files when done`,
|
|
174
192
|
|
|
175
|
-
check: isFinish ?
|
|
193
|
+
check: isFinish ? `<!-- trellis-hook-injected -->
|
|
194
|
+
# Finish Agent Task
|
|
176
195
|
|
|
177
196
|
You are performing the final check before creating a PR.
|
|
178
197
|
|
|
@@ -207,7 +226,8 @@ ${originalPrompt}
|
|
|
207
226
|
- If critical CODE issues found, report them clearly (fix specs, not code)
|
|
208
227
|
- Verify all acceptance criteria in prd.md are met
|
|
209
228
|
- Verify design.md and implement.md constraints when those files are present` :
|
|
210
|
-
|
|
229
|
+
`<!-- trellis-hook-injected -->
|
|
230
|
+
# Check Agent Task
|
|
211
231
|
|
|
212
232
|
You are the Check Agent in the Multi-Agent Pipeline.
|
|
213
233
|
|
|
@@ -235,7 +255,8 @@ ${originalPrompt}
|
|
|
235
255
|
- Fix issues yourself, don't just report
|
|
236
256
|
- Must execute complete checklist`,
|
|
237
257
|
|
|
238
|
-
research:
|
|
258
|
+
research: `<!-- trellis-hook-injected -->
|
|
259
|
+
# Research Agent Task
|
|
239
260
|
|
|
240
261
|
You are the Research Agent in the Multi-Agent Pipeline.
|
|
241
262
|
|
|
@@ -280,9 +301,29 @@ function powershellQuote(value) {
|
|
|
280
301
|
return `'${String(value).replace(/'/g, "''")}'`
|
|
281
302
|
}
|
|
282
303
|
|
|
283
|
-
function
|
|
284
|
-
|
|
285
|
-
|
|
304
|
+
function envValue(env, key) {
|
|
305
|
+
const value = env?.[key]
|
|
306
|
+
return typeof value === "string" && value.trim() ? value.trim() : null
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function shellBasename(value) {
|
|
310
|
+
return value.replace(/\\/g, "/").split("/").pop()?.toLowerCase() || ""
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function isWindowsPosixShell(env = process.env) {
|
|
314
|
+
if (envValue(env, "MSYSTEM")) return true
|
|
315
|
+
if (envValue(env, "MINGW_PREFIX")) return true
|
|
316
|
+
if (envValue(env, "OPENCODE_GIT_BASH_PATH")) return true
|
|
317
|
+
|
|
318
|
+
const ostype = envValue(env, "OSTYPE")?.toLowerCase() || ""
|
|
319
|
+
if (/(msys|mingw|cygwin)/.test(ostype)) return true
|
|
320
|
+
|
|
321
|
+
const shell = shellBasename(envValue(env, "SHELL") || "")
|
|
322
|
+
return /^(bash|sh|zsh)(\.exe)?$/.test(shell)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function buildTrellisContextPrefix(contextKey, hostPlatform = process.platform, env = process.env) {
|
|
326
|
+
if (hostPlatform === "win32" && !isWindowsPosixShell(env)) {
|
|
286
327
|
return `$env:TRELLIS_CONTEXT_ID = ${powershellQuote(contextKey)}; `
|
|
287
328
|
}
|
|
288
329
|
|
|
@@ -301,7 +342,7 @@ function commandStartsWithTrellisContext(command) {
|
|
|
301
342
|
return (
|
|
302
343
|
/^TRELLIS_CONTEXT_ID\s*=/.test(firstCommand) ||
|
|
303
344
|
/^export\s+TRELLIS_CONTEXT_ID\s*=/.test(firstCommand) ||
|
|
304
|
-
/^env\s+(?:[
|
|
345
|
+
/^env\s+(?:(?:-\S+|[A-Za-z_][A-Za-z0-9_]*=\S*)\s+)*TRELLIS_CONTEXT_ID\s*=/.test(firstCommand) ||
|
|
305
346
|
/^\$env:TRELLIS_CONTEXT_ID\s*=/i.test(firstCommand)
|
|
306
347
|
)
|
|
307
348
|
}
|
|
@@ -310,7 +351,7 @@ function commandStartsWithTrellisContext(command) {
|
|
|
310
351
|
* OpenCode TUI may not expose OPENCODE_RUN_ID to Bash. The plugin hook still
|
|
311
352
|
* receives session identity, so inject it into Bash commands before execution.
|
|
312
353
|
*/
|
|
313
|
-
function injectTrellisContextIntoBash(ctx, input, output, hostPlatform) {
|
|
354
|
+
function injectTrellisContextIntoBash(ctx, input, output, hostPlatform, env) {
|
|
314
355
|
const args = output?.args
|
|
315
356
|
const commandKey = getBashCommandKey(args)
|
|
316
357
|
if (!commandKey) return false
|
|
@@ -322,7 +363,7 @@ function injectTrellisContextIntoBash(ctx, input, output, hostPlatform) {
|
|
|
322
363
|
const contextKey = ctx.getContextKey(input)
|
|
323
364
|
if (!contextKey) return false
|
|
324
365
|
|
|
325
|
-
args[commandKey] = `${buildTrellisContextPrefix(contextKey, hostPlatform)}${command}`
|
|
366
|
+
args[commandKey] = `${buildTrellisContextPrefix(contextKey, hostPlatform, env)}${command}`
|
|
326
367
|
return true
|
|
327
368
|
}
|
|
328
369
|
|
|
@@ -331,7 +372,7 @@ function injectTrellisContextIntoBash(ctx, input, output, hostPlatform) {
|
|
|
331
372
|
// (packages/opencode/src/plugin/index.ts — `for ([_, fn] of Object.entries(mod)) await fn(input)`);
|
|
332
373
|
// the previous `{ id, server }` object shape failed with
|
|
333
374
|
// `TypeError: fn is not a function` in 1.2.x.
|
|
334
|
-
export default async ({ directory, platform: hostPlatform = process.platform }) => {
|
|
375
|
+
export default async ({ directory, platform: hostPlatform = process.platform, env = process.env }) => {
|
|
335
376
|
const ctx = new TrellisContext(directory)
|
|
336
377
|
debugLog("inject", "Plugin loaded, directory:", directory)
|
|
337
378
|
|
|
@@ -345,7 +386,7 @@ export default async ({ directory, platform: hostPlatform = process.platform })
|
|
|
345
386
|
|
|
346
387
|
const toolName = input?.tool?.toLowerCase()
|
|
347
388
|
if (toolName === "bash") {
|
|
348
|
-
if (injectTrellisContextIntoBash(ctx, input, output, hostPlatform)) {
|
|
389
|
+
if (injectTrellisContextIntoBash(ctx, input, output, hostPlatform, env)) {
|
|
349
390
|
debugLog("inject", "Injected TRELLIS_CONTEXT_ID into Bash command")
|
|
350
391
|
}
|
|
351
392
|
return
|
|
@@ -370,8 +411,53 @@ export default async ({ directory, platform: hostPlatform = process.platform })
|
|
|
370
411
|
return
|
|
371
412
|
}
|
|
372
413
|
|
|
373
|
-
// Resolve active task
|
|
374
|
-
|
|
414
|
+
// Resolve active task in this priority order (only later steps
|
|
415
|
+
// run when earlier ones miss):
|
|
416
|
+
// 1. Exact session runtime context lookup for input.sessionID
|
|
417
|
+
// 2. `Active task: <path>` hint in the dispatch prompt
|
|
418
|
+
// (explicit per-dispatch override — beats single-session
|
|
419
|
+
// inference so multi-window users can disambiguate)
|
|
420
|
+
// 3. Single-session fallback — only when exactly 1 session
|
|
421
|
+
// runtime file exists locally
|
|
422
|
+
let taskDir = null
|
|
423
|
+
let taskSource = null
|
|
424
|
+
|
|
425
|
+
const contextKey = ctx.getContextKey(input)
|
|
426
|
+
if (contextKey) {
|
|
427
|
+
const context = ctx.readContext(contextKey)
|
|
428
|
+
const exactRef = ctx.normalizeTaskRef(context?.current_task || "")
|
|
429
|
+
if (exactRef) {
|
|
430
|
+
taskDir = exactRef
|
|
431
|
+
taskSource = `session:${contextKey}`
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (!taskDir) {
|
|
436
|
+
const hintRef = extractActiveTaskHint(originalPrompt)
|
|
437
|
+
if (hintRef) {
|
|
438
|
+
const hintNormalized = ctx.normalizeTaskRef(hintRef)
|
|
439
|
+
if (hintNormalized) {
|
|
440
|
+
const hintDir = ctx.resolveTaskDir(hintNormalized)
|
|
441
|
+
if (hintDir && existsSync(hintDir)) {
|
|
442
|
+
taskDir = hintNormalized
|
|
443
|
+
taskSource = "prompt-hint"
|
|
444
|
+
debugLog("inject", "Resolved task from Active task: hint:", hintNormalized)
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (!taskDir) {
|
|
451
|
+
const fallback = ctx._resolveSingleSessionFallback()
|
|
452
|
+
if (fallback?.taskPath) {
|
|
453
|
+
const fallbackDir = ctx.resolveTaskDir(fallback.taskPath)
|
|
454
|
+
if (fallbackDir && existsSync(fallbackDir)) {
|
|
455
|
+
taskDir = fallback.taskPath
|
|
456
|
+
taskSource = fallback.source
|
|
457
|
+
debugLog("inject", "Resolved task via single-session fallback:", taskDir, "source:", taskSource)
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
375
461
|
|
|
376
462
|
// Agents requiring task directory
|
|
377
463
|
if (AGENTS_REQUIRE_TASK.includes(subagentType)) {
|
|
@@ -380,8 +466,8 @@ export default async ({ directory, platform: hostPlatform = process.platform })
|
|
|
380
466
|
debugLog("inject", "Skipping - no current task")
|
|
381
467
|
return
|
|
382
468
|
}
|
|
383
|
-
const taskDirFull =
|
|
384
|
-
if (!existsSync(taskDirFull)) {
|
|
469
|
+
const taskDirFull = ctx.resolveTaskDir(taskDir)
|
|
470
|
+
if (!taskDirFull || !existsSync(taskDirFull)) {
|
|
385
471
|
debugLog("inject", "Skipping - task directory not found")
|
|
386
472
|
return
|
|
387
473
|
}
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
import { existsSync, readFileSync } from "fs"
|
|
27
27
|
import { join } from "path"
|
|
28
|
-
import { TrellisContext, debugLog } from "../lib/trellis-context.js"
|
|
28
|
+
import { TrellisContext, debugLog, isTrellisSubagent } from "../lib/trellis-context.js"
|
|
29
29
|
|
|
30
30
|
// Supports STATUS values with letters, digits, underscores, hyphens
|
|
31
31
|
// (so "in-review" / "blocked-by-team" work alongside "in_progress").
|
|
@@ -108,6 +108,13 @@ export default async ({ directory }) => {
|
|
|
108
108
|
// so it persists in conversation history.
|
|
109
109
|
"chat.message": async (input, output) => {
|
|
110
110
|
try {
|
|
111
|
+
// Skip Trellis sub-agent turns — the per-turn breadcrumb is for the
|
|
112
|
+
// main session only; sub-agent context comes from the parent's
|
|
113
|
+
// tool.execute.before injection.
|
|
114
|
+
if (isTrellisSubagent(input)) {
|
|
115
|
+
debugLog("workflow-state", "Skipping trellis subagent turn:", input?.agent)
|
|
116
|
+
return
|
|
117
|
+
}
|
|
111
118
|
if (process.env.TRELLIS_HOOKS === "0" || process.env.TRELLIS_DISABLE_HOOKS === "1") {
|
|
112
119
|
return
|
|
113
120
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Uses OpenCode's chat.message hook directly so the context persists in history.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { TrellisContext, contextCollector, debugLog } from "../lib/trellis-context.js"
|
|
9
|
+
import { TrellisContext, contextCollector, debugLog, isTrellisSubagent } from "../lib/trellis-context.js"
|
|
10
10
|
import {
|
|
11
11
|
buildSessionContext,
|
|
12
12
|
hasPersistedInjectedContext,
|
|
@@ -43,6 +43,14 @@ export default async ({ directory, client }) => {
|
|
|
43
43
|
const agent = input.agent || "unknown"
|
|
44
44
|
debugLog("session", "chat.message called, sessionID:", sessionID, "agent:", agent)
|
|
45
45
|
|
|
46
|
+
// Skip Trellis sub-agent turns — sub-agent context is injected by
|
|
47
|
+
// `inject-subagent-context.js` on the parent's tool.execute.before;
|
|
48
|
+
// re-injecting the main-session SessionStart here would drown that.
|
|
49
|
+
if (isTrellisSubagent(input)) {
|
|
50
|
+
debugLog("session", "Skipping trellis subagent turn:", agent)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
if (process.env.TRELLIS_HOOKS === "0" || process.env.TRELLIS_DISABLE_HOOKS === "1") {
|
|
47
55
|
debugLog("session", "Skipping - TRELLIS_HOOKS disabled")
|
|
48
56
|
return
|
|
@@ -19,10 +19,11 @@ You are already the `trellis-check` sub-agent that the main session dispatched.
|
|
|
19
19
|
## Core Responsibilities
|
|
20
20
|
|
|
21
21
|
1. Inspect the current git diff.
|
|
22
|
-
2. Read
|
|
23
|
-
3.
|
|
24
|
-
4.
|
|
25
|
-
5.
|
|
22
|
+
2. Read `prd.md`, `design.md` if present, and `implement.md` if present.
|
|
23
|
+
3. Read and follow the spec and research files listed in the task's `check.jsonl`.
|
|
24
|
+
4. Review all changed code against the task artifacts and project specs.
|
|
25
|
+
5. Fix issues directly when they are within scope.
|
|
26
|
+
6. Run the relevant lint, typecheck, and focused tests available for the touched code.
|
|
26
27
|
|
|
27
28
|
## Review Priorities
|
|
28
29
|
|
|
@@ -19,10 +19,11 @@ You are already the `trellis-implement` sub-agent that the main session dispatch
|
|
|
19
19
|
## Core Responsibilities
|
|
20
20
|
|
|
21
21
|
1. Understand the active task requirements.
|
|
22
|
-
2. Read
|
|
23
|
-
3.
|
|
24
|
-
4.
|
|
25
|
-
5.
|
|
22
|
+
2. Read `prd.md`, `design.md` if present, and `implement.md` if present.
|
|
23
|
+
3. Read and follow the spec and research files listed in the task's `implement.jsonl`.
|
|
24
|
+
4. Implement the requested change using existing project patterns.
|
|
25
|
+
5. Run the relevant lint, typecheck, and focused tests available for the touched code.
|
|
26
|
+
6. Report files changed and verification results.
|
|
26
27
|
|
|
27
28
|
## Forbidden Operations
|
|
28
29
|
|