@mindfoldhq/trellis 0.5.12 → 0.5.14

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 CHANGED
@@ -7,8 +7,8 @@
7
7
  </p>
8
8
 
9
9
  <p align="center">
10
- <strong>Make AI coding reliable at team scale.</strong><br/>
11
- <sub>A team AI coding harness for progressive specs, custom workflows, task context, and memory across Claude Code, Cursor, Codex, OpenCode, Pi Agent, and more.</sub>
10
+ <strong>The harness that makes coding agents production-ready</strong><br/>
11
+ <sub>Start a feature in Gemini, continue in Claude Code, ship it with Codex — or hand it off to a teammate at any step. Context, specs, and standards are shared across every agent and every teammate, so anyone's best spec lifts the whole team.</sub>
12
12
  </p>
13
13
 
14
14
  <p align="center">
@@ -26,7 +26,6 @@
26
26
  <a href="https://github.com/mindfold-ai/Trellis/stargazers"><img src="https://img.shields.io/github/stars/mindfold-ai/Trellis?style=flat-square&color=eab308" alt="stars" /></a>
27
27
  <a href="https://docs.trytrellis.app/"><img src="https://img.shields.io/badge/docs-trytrellis.app-0f766e?style=flat-square" alt="docs" /></a>
28
28
  <a href="https://discord.com/invite/tWcCZ3aRHc"><img src="https://img.shields.io/badge/Discord-Join-5865F2?style=flat-square&logo=discord&logoColor=white" alt="Discord" /></a>
29
- <a href="https://linux.do"><img src="https://img.shields.io/badge/LINUX-DO-FFB003.svg?logo=data:image/svg%2bxml;base64,DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiPjxwYXRoIGQ9Ik00Ni44Mi0uMDU1aDYuMjVxMjMuOTY5IDIuMDYyIDM4IDIxLjQyNmM1LjI1OCA3LjY3NiA4LjIxNSAxNi4xNTYgOC44NzUgMjUuNDV2Ni4yNXEtMi4wNjQgMjMuOTY4LTIxLjQzIDM4LTExLjUxMiA3Ljg4NS0yNS40NDUgOC44NzRoLTYuMjVxLTIzLjk3LTIuMDY0LTM4LjAwNC0yMS40M1EuOTcxIDY3LjA1Ni0uMDU0IDUzLjE4di02LjQ3M0MxLjM2MiAzMC43ODEgOC41MDMgMTguMTQ4IDIxLjM3IDguODE3IDI5LjA0NyAzLjU2MiAzNy41MjcuNjA0IDQ2LjgyMS0uMDU2IiBzdHlsZT0ic3Ryb2tlOm5vbmU7ZmlsbC1ydWxlOmV2ZW5vZGQ7ZmlsbDojZWNlY2VjO2ZpbGwtb3BhY2l0eToxIi8+PHBhdGggZD0iTTQ3LjI2NiAyLjk1N3EyMi41My0uNjUgMzcuNzc3IDE1LjczOGE0OS43IDQ5LjcgMCAwIDEgNi44NjcgMTAuMTU3cS00MS45NjQuMjIyLTgzLjkzIDAgOS43NS0xOC42MTYgMzAuMDI0LTI0LjM4N2E2MSA2MSAwIDAgMSA5LjI2Mi0xLjUwOCIgc3R5bGU9InN0cm9rZTpub25lO2ZpbGwtcnVsZTpldmVub2RkO2ZpbGw6IzE5MTkxOTtmaWxsLW9wYWNpdHk6MSIvPjxwYXRoIGQ9Ik03Ljk4IDcwLjkyNmMyNy45NzctLjAzNSA1NS45NTQgMCA4My45My4xMTNRODMuNDI2IDg3LjQ3MyA2Ni4xMyA5NC4wODZxLTE4LjgxIDYuNTQ0LTM2LjgzMi0xLjg5OC0xNC4yMDMtNy4wOS0yMS4zMTctMjEuMjYyIiBzdHlsZT0ic3Ryb2tlOm5vbmU7ZmlsbC1ydWxlOmV2ZW5vZGQ7ZmlsbDojZjlhZjAwO2ZpbGwtb3BhY2l0eToxIi8+PC9zdmc+&style=flat-square" alt="LINUX DO" /></a>
30
29
  <a href="https://github.com/mindfold-ai/Trellis/issues"><img src="https://img.shields.io/github/issues/mindfold-ai/Trellis?style=flat-square&color=e67e22" alt="open issues" /></a>
31
30
  <a href="https://github.com/mindfold-ai/Trellis/pulls"><img src="https://img.shields.io/github/issues-pr/mindfold-ai/Trellis?style=flat-square&color=9b59b6" alt="open PRs" /></a>
32
31
  <a href="https://deepwiki.com/mindfold-ai/Trellis"><img src="https://img.shields.io/badge/Ask-DeepWiki-blue?style=flat-square" alt="Ask DeepWiki" /></a>
@@ -37,68 +36,55 @@
37
36
  <img src="assets/trellis-demo.gif" alt="Trellis workflow demo" width="100%">
38
37
  </p>
39
38
 
40
- ## What is Trellis?
39
+ ## Why Trellis?
41
40
 
42
- Trellis is a built-in AI coding harness for teams. It turns the huge system prompt you would normally put in `CLAUDE.md`, `AGENTS.md`, or `.cursorrules` into a progressive wiki of specs, tasks, workflows, and journals that agents load only when needed.
41
+ | Capability | What it changes |
42
+ | --- | --- |
43
+ | **Auto-injected specs** | Write conventions once in `.trellis/spec/`, then let Trellis inject the relevant context into each session instead of repeating yourself. |
44
+ | **Task-centered workflow** | Keep PRDs, implementation context, review context, and task status in `.trellis/tasks/` so AI work stays structured. |
45
+ | **Project memory** | Journals in `.trellis/workspace/` preserve what happened last time, so each new session starts with real context. |
46
+ | **Team-shared standards** | Specs live in the repo, so one person's hard-won workflow or rule can benefit the whole team. |
47
+ | **Multi-platform setup** | Bring the same Trellis structure to 14 AI coding platforms instead of rebuilding your workflow per tool. |
43
48
 
44
- It gives Claude Code, Cursor, Codex, OpenCode, Pi Agent, and other agents the same project source of truth: team standards, task decisions, runbooks, and session memory, without stuffing the whole codebase into every prompt. Trellis is used by individual builders, open-source maintainers, teams inside tech giants, top university labs, and public-company engineering departments working on production monorepos with hundreds of thousands of lines of code.
45
-
46
- ## How it works
47
-
48
- Trellis installs a `.trellis/` directory into your repository and generates the right entry points for each AI coding platform you use.
49
-
50
- | Layer | Purpose |
51
- | ---------------------- | -------------------------------------------------------------------------------------- |
52
- | `.trellis/spec/` | Team standards and coding guidelines that agents can load automatically. |
53
- | `.trellis/tasks/` | PRDs, task context, status, review notes, and acceptance criteria. |
54
- | `.trellis/workspace/` | Developer-level journals, decisions, and handoff notes for session continuity. |
55
- | `.trellis/workflow.md` | The shared lifecycle for planning, building, checking, finishing, and learning. |
56
- | Platform adapters | Generated commands, hooks, skills, prompts, workflows, and agent files for your tools. |
57
-
58
- The core loop is short:
59
-
60
- 1. Capture the task as a PRD.
61
- 2. Inject the relevant project specs.
62
- 3. Let the agent implement inside a clear boundary.
63
- 4. Run checks before handoff.
64
- 5. Promote reusable lessons back into specs.
65
- 6. Record the session so the next agent starts with the decisions and context it needs.
66
-
67
- For the deeper product model, see the [docs](https://docs.trytrellis.app/) and [real-world scenarios](https://docs.trytrellis.app/start/real-world-scenarios).
68
-
69
- ## Install
70
-
71
- Prerequisites:
49
+ ## Prerequisites:
72
50
 
73
51
  - **Node.js** >= 18
74
- - **Python** >= 3.9 for hooks and automation scripts
52
+ - **Python** >= 3.9
75
53
 
76
- Install Trellis:
54
+ ## Quick Start
77
55
 
78
56
  ```bash
79
- npm install -g @mindfoldhq/trellis@beta
80
- ```
81
-
82
- Initialize a repository:
57
+ # 1. Install Trellis
58
+ npm install -g @mindfoldhq/trellis@latest
83
59
 
84
- ```bash
85
- # Start Trellis and create a developer workspace
60
+ # 2. Initialize in your repo
86
61
  trellis init -u your-name
62
+
63
+ # 3. Or initialize with the platforms you actually use
64
+ trellis init --cursor --opencode --codex -u your-name
87
65
  ```
88
66
 
89
67
  See the [Quick Start](https://docs.trytrellis.app/start/install-and-first-task) and [Supported Platforms](https://docs.trytrellis.app/advanced/multi-platform) guides for setup details.
90
68
 
91
- ## First task
69
+ ## How to Use
92
70
 
93
- Trellis 0.5 is skill-first. On hook-capable or extension-capable platforms, session context loads automatically. On platforms that need a manual entry point, start with:
71
+ The workflow is simple:
94
72
 
95
- ```text
96
- /start or /trellis:start # Load project context
97
- ```
73
+ 1. **Describe what you want** in natural language.
74
+ 2. **Brainstorm** with the AI one question at a time until the PRD is clear, then implementation begins.
75
+ 3. **Let it run** — the AI calls Trellis Implement and auto-checks the result against specs, lint, type-check, and tests.
76
+ 4. **Type `/trellis:finish-work`** when the work is done or the session context fills up. Trellis archives the task and updates journals.
98
77
 
99
- Then describe the task in natural language. Trellis routes the work through skills for brainstorming, spec loading, implementation checks, and knowledge capture. Use `continue` to advance the current task and `finish-work` after human testing and commit.
78
+ ## How It Works
100
79
 
101
- ## Learn more
80
+ Trellis runs a 4-phase loop with auto-invoked skills and sub-agents:
81
+
82
+ 1. **Plan** — `trellis-brainstorm` walks through requirements one question at a time and writes `prd.md`. Research-heavy items go to a `trellis-research` sub-agent. The result is curated specs + research files referenced from `implement.jsonl` / `check.jsonl`.
83
+ 2. **Implement** — a `trellis-implement` sub-agent writes code from the PRD with the curated context auto-injected, no git commit.
84
+ 3. **Verify** — a `trellis-check` sub-agent reviews the diff against specs and runs lint, type-check, and tests, self-fixing where it can.
85
+ 4. **Finish** — a final check runs, then `trellis-update-spec` promotes new learnings back into `.trellis/spec/` so the next session starts smarter.
86
+
87
+ ## Resources
102
88
 
103
89
  | Need | Link |
104
90
  | ------------------------------- | ------------------------------------------------------------------------------ |
@@ -106,7 +92,7 @@ Then describe the task in natural language. Trellis routes the work through skil
106
92
  | Understand platform differences | [Supported Platforms](https://docs.trytrellis.app/advanced/multi-platform) |
107
93
  | See the workflow in practice | [Real-World Scenarios](https://docs.trytrellis.app/start/real-world-scenarios) |
108
94
  | Start from spec templates | [Spec Templates](https://docs.trytrellis.app/templates/specs-index) |
109
- | Track releases | [Changelog](https://docs.trytrellis.app/changelog/v0.5.0-beta.16) |
95
+ | Track releases | [Changelog](https://docs.trytrellis.app/changelog) |
110
96
 
111
97
  ## FAQ
112
98
 
@@ -131,6 +117,20 @@ Both. Solo developers use it for memory and repeatable workflow. Teams get the l
131
117
 
132
118
  </details>
133
119
 
120
+ <details>
121
+ <summary><strong>Do I have to write every spec file manually?</strong></summary>
122
+
123
+ No. Many teams start by letting AI draft specs from existing code and then tighten the important parts by hand. Trellis works best when you keep the high-signal rules explicit and versioned.
124
+
125
+ </details>
126
+
127
+ <details>
128
+ <summary><strong>Can teams use this without constant conflicts?</strong></summary>
129
+
130
+ Yes. Personal workspace journals stay separate per developer, while shared specs and tasks stay in the repo where they can be reviewed and improved like any other project artifact.
131
+
132
+ </details>
133
+
134
134
  ## Star History
135
135
 
136
136
  [![Star History Chart](https://api.star-history.com/svg?repos=mindfold-ai/Trellis&type=Date)](https://star-history.com/#mindfold-ai/Trellis&Date)
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.5.13",
3
+ "description": "Patch: OpenCode context injection, non-Git session context, hook timeouts, and Copilot SessionStart wording.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Bug Fixes:**\n- fix(opencode): detect Windows POSIX shell dialects before injecting `TRELLIS_CONTEXT_ID`, so Git Bash / MSYS / Cygwin sessions receive `export ...` while PowerShell keeps `$env:...`.\n- fix(context): session context now handles non-Git Trellis roots without reporting fake clean Git state, and falls back to bounded child-repo discovery for unconfigured polyrepo layouts.\n- fix(opencode): Trellis sub-agent dispatch now skips duplicate SessionStart / workflow-state injection, resolves active tasks from session context, `Active task:` hints, or single-session fallback, and marks successfully injected prompts.\n- fix(hooks): default hook timeouts now use 30s for SessionStart and 15s for per-prompt workflow injection across hook-based platforms, avoiding Windows Python cold-start drops.\n- fix(copilot): SessionStart output no longer emits the stale `Copilot currently ignores sessionStart hook output` system message; it keeps `hookSpecificOutput.additionalContext` as the documented payload.\n\n**Internal:**\n- docs(spec): platform and cross-platform spec templates document shell-dialect-aware `TRELLIS_CONTEXT_ID` prefix rules for OpenCode.",
7
+ "migrations": [],
8
+ "notes": "Run `trellis update` to refresh hash-tracked hook, OpenCode, session-context, and spec templates. No migration required."
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.5.14",
3
+ "description": "Patch: `task.py archive` auto-commit no longer leaks dirty changes from other task dirs into the archive commit, and source-side deletes now stage correctly (no more phantom-delete fixups).",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Bug Fixes:**\n- fix(scripts): `task.py archive` auto-commit is now scoped to just the archived task's source + destination paths (plus any child task dirs whose `task.json` was edited as part of the parent→children relationship update). Dirty changes in OTHER active task dirs no longer get bundled into the archive commit.\n- fix(scripts): after `shutil.move` of a tracked task dir, the source-side deletions are now explicitly staged via `git rm -r --cached --ignore-unmatch`, so the working tree stays clean against HEAD without needing a follow-up fixup commit.\n\n**Internal:**\n- `safe_archive_paths_to_add()` accepts optional `task_name` + `modified_children` parameters; backward-compatible when called with no args (legacy wide scope preserved).\n- New integration test `test/scripts/task-archive.integration.test.ts` covers scope-creep + phantom-delete regressions against the real Python script.",
7
+ "migrations": [],
8
+ "notes": "Run `trellis update` to pull in the fixed `.trellis/scripts/common/task_store.py` + `safe_commit.py`. No migration required — script signatures changed but file paths did not."
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.6.0-beta.10",
3
+ "description": "Beta release for the trellis channel multi-agent collaboration runtime.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Enhancements:**\n- feat(channel): add `trellis channel` multi-agent collaboration runtime with `create`, `send`, `wait`, `spawn`, `run`, `list`, `messages`, `kill`, `rm`, and `prune` subcommands.\n- feat(channel): add Claude stream-json and Codex app-server adapters that translate provider output into channel `message`, `progress`, `done`, and `error` events.\n- feat(channel): store project-scoped channel logs under `~/.trellis/channels/<project>/<channel>/events.jsonl` with locked sequence assignment and lazy legacy-channel relocation.\n\n**Internal:**\n- refactor(channel): isolate adapter parsing, event storage, supervisor shutdown, inbox polling, and stdout pumping under `packages/cli/src/commands/channel/`.",
7
+ "migrations": [],
8
+ "notes": "Beta release on top of 0.6.0-beta.9. Run `trellis update` after installing `@mindfoldhq/trellis@beta`. No project-file migration required."
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.6.0-beta.7",
3
+ "description": "Beta patch: brings the v0.5.12 workflow update fix into the 0.6 beta line.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Bug Fixes:**\n- fix(update): update `.trellis/workflow.md` as a whole hash-tracked template so runtime phase routing markers, including Codex `codex-inline` / `codex-sub-agent` blocks, refresh during `trellis update`.",
7
+ "migrations": [],
8
+ "notes": "Beta patch on top of 0.6.0-beta.6. Run `trellis update` to refresh hash-tracked workflow templates. No migration required."
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.6.0-beta.8",
3
+ "description": "Beta patch: adds task-creation consent gates and planning artifacts across workflow, hooks, skills, and platform templates.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Enhancements:**\n- feat(workflow): no-task turns now classify simple conversation, inline small work, and full Trellis tasks before task creation; complex work asks before creating a task and entering planning.\n- feat(task): `task.py create` now creates a default `prd.md`, while complex tasks require `design.md` and `implement.md` before `task.py start`.\n- feat(context): implement/check context loading now uses the same artifact order across hook-push, pull-prelude, Pi, OpenCode, and inline modes: jsonl entries -> `prd.md` -> optional `design.md` -> optional `implement.md`.\n- feat(codex): Codex no-task breadcrumbs include `<trellis-bootstrap>` plus explicit `<codex-mode>` text, and inline mode keeps implementation/check work in the main session.",
7
+ "migrations": [],
8
+ "notes": "Beta patch on top of 0.6.0-beta.7. Run `trellis update` to refresh workflow, hook, skill, agent, and platform templates. No migration required."
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.6.0-beta.9",
3
+ "description": "Beta patch for trellis upgrade, OpenCode and Copilot context fixes, hook timeout defaults, and manifest continuity.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Enhancements:**\n- feat(upgrade): add `trellis upgrade` with channel-aware defaults (`latest`, `beta`, `rc`), `--tag`, and `--dry-run`; update CLI/session hints to point at the command.\n- docs(brainstorm): simplify bundled brainstorm skill/prompt templates after beta.8 planning artifact routing.\n\n**Bug Fixes:**\n- fix(upgrade): harden upgrade execution with tag validation, no shell on POSIX, Windows `cmd.exe` invocation, and troubleshooting output for npm/PATH failures.\n- fix(opencode): inject `TRELLIS_CONTEXT_ID` using the shell dialect that parses the command and recognize `env ... TRELLIS_CONTEXT_ID=...` prefixes.\n- fix(context): handle non-Git Trellis roots without fake clean Git status and discover child Git repos for unconfigured polyrepos.\n- fix(opencode): isolate Trellis sub-agent context, resolve active tasks from session context / `Active task:` hints / single-session fallback, and preserve beta.8 task artifact order.\n- fix(hooks): raise hook timeout defaults to 30s for SessionStart and 15s for per-prompt workflow injection across hook-based platforms.\n- fix(copilot): remove stale SessionStart `systemMessage` while keeping `hookSpecificOutput.additionalContext`.\n\n**Internal:**\n- chore(manifests): restore `0.5.13.json` on the beta line for stable-to-beta manifest continuity.",
7
+ "migrations": [],
8
+ "notes": "Beta patch on top of 0.6.0-beta.8. Run `trellis update` to refresh workflow, hook, OpenCode, Copilot, session-context, and skill templates. No migration required."
9
+ }
@@ -10,7 +10,7 @@
10
10
  {
11
11
  "type": "command",
12
12
  "command": "{{PYTHON_CMD}} .claude/hooks/session-start.py",
13
- "timeout": 10
13
+ "timeout": 30
14
14
  }
15
15
  ]
16
16
  },
@@ -20,7 +20,7 @@
20
20
  {
21
21
  "type": "command",
22
22
  "command": "{{PYTHON_CMD}} .claude/hooks/session-start.py",
23
- "timeout": 10
23
+ "timeout": 30
24
24
  }
25
25
  ]
26
26
  },
@@ -30,7 +30,7 @@
30
30
  {
31
31
  "type": "command",
32
32
  "command": "{{PYTHON_CMD}} .claude/hooks/session-start.py",
33
- "timeout": 10
33
+ "timeout": 30
34
34
  }
35
35
  ]
36
36
  }
@@ -63,7 +63,7 @@
63
63
  {
64
64
  "type": "command",
65
65
  "command": "{{PYTHON_CMD}} .claude/hooks/inject-workflow-state.py",
66
- "timeout": 5
66
+ "timeout": 15
67
67
  }
68
68
  ]
69
69
  }
@@ -7,7 +7,7 @@
7
7
  {
8
8
  "type": "command",
9
9
  "command": "{{PYTHON_CMD}} .codebuddy/hooks/session-start.py",
10
- "timeout": 10
10
+ "timeout": 30
11
11
  }
12
12
  ]
13
13
  },
@@ -17,7 +17,7 @@
17
17
  {
18
18
  "type": "command",
19
19
  "command": "{{PYTHON_CMD}} .codebuddy/hooks/session-start.py",
20
- "timeout": 10
20
+ "timeout": 30
21
21
  }
22
22
  ]
23
23
  },
@@ -27,7 +27,7 @@
27
27
  {
28
28
  "type": "command",
29
29
  "command": "{{PYTHON_CMD}} .codebuddy/hooks/session-start.py",
30
- "timeout": 10
30
+ "timeout": 30
31
31
  }
32
32
  ]
33
33
  }
@@ -50,7 +50,7 @@
50
50
  {
51
51
  "type": "command",
52
52
  "command": "{{PYTHON_CMD}} .codebuddy/hooks/inject-workflow-state.py",
53
- "timeout": 5
53
+ "timeout": 15
54
54
  }
55
55
  ]
56
56
  }
@@ -6,7 +6,7 @@
6
6
  {
7
7
  "type": "command",
8
8
  "command": "{{PYTHON_CMD}} .codex/hooks/inject-workflow-state.py",
9
- "timeout": 5
9
+ "timeout": 15
10
10
  }
11
11
  ]
12
12
  }
@@ -1,13 +1,18 @@
1
1
  #!/usr/bin/env python3
2
2
  # -*- coding: utf-8 -*-
3
3
  """
4
- Copilot Session Start Hook - Emit Trellis session-start diagnostics.
5
-
6
- GitHub Copilot's documented SessionStart behavior ignores hook output, so this
7
- script must not be treated as proof that model-visible context was injected.
8
- The JSON shape is kept for parity with other Trellis hooks and future host
9
- support, but current Copilot users should rely on UserPromptSubmit breadcrumbs
10
- and hook logs instead.
4
+ Copilot Session Start Hook - Emit Trellis session-start context.
5
+
6
+ Microsoft VS Code Agent hooks are in preview and have been documented since
7
+ VS Code 1.110 (February 2026). The official documentation
8
+ (https://code.visualstudio.com/docs/copilot/customization/hooks) defines
9
+ `SessionStart.hookSpecificOutput.additionalContext` as the field used to inject
10
+ additional context into the agent's conversation.
11
+
12
+ This script emits the spec-compliant SessionStart payload. Whether Copilot
13
+ actually consumes `additionalContext` depends on the user's installed VS Code
14
+ and Copilot versions, which is outside Trellis's control. UserPromptSubmit
15
+ breadcrumbs remain available as a per-turn complement.
11
16
  """
12
17
 
13
18
  from __future__ import annotations
@@ -412,10 +417,6 @@ If a task is READY, execute its Next required action without asking whether to c
412
417
  context = output.getvalue()
413
418
  result = {
414
419
  "suppressOutput": True,
415
- "systemMessage": (
416
- f"Trellis SessionStart diagnostics emitted ({len(context)} chars); "
417
- "Copilot currently ignores sessionStart hook output."
418
- ),
419
420
  "hookSpecificOutput": {
420
421
  "hookEventName": "SessionStart",
421
422
  "additionalContext": context,
@@ -4,7 +4,7 @@
4
4
  {
5
5
  "type": "command",
6
6
  "command": "{{PYTHON_CMD}} .github/copilot/hooks/session-start.py",
7
- "timeout": 10
7
+ "timeout": 30
8
8
  }
9
9
  ],
10
10
  "userPromptSubmitted": [
@@ -12,7 +12,7 @@
12
12
  "type": "command",
13
13
  "bash": "{{PYTHON_CMD}} .github/copilot/hooks/inject-workflow-state.py",
14
14
  "powershell": "{{PYTHON_CMD}} .github/copilot/hooks/inject-workflow-state.py",
15
- "timeoutSec": 5
15
+ "timeoutSec": 15
16
16
  }
17
17
  ]
18
18
  }
@@ -11,13 +11,13 @@
11
11
  "sessionStart": [
12
12
  {
13
13
  "command": "{{PYTHON_CMD}} .cursor/hooks/session-start.py",
14
- "timeout": 10
14
+ "timeout": 30
15
15
  }
16
16
  ],
17
17
  "beforeSubmitPrompt": [
18
18
  {
19
19
  "command": "{{PYTHON_CMD}} .cursor/hooks/inject-workflow-state.py",
20
- "timeout": 5
20
+ "timeout": 15
21
21
  }
22
22
  ],
23
23
  "beforeShellExecution": [
@@ -7,7 +7,7 @@
7
7
  {
8
8
  "type": "command",
9
9
  "command": "{{PYTHON_CMD}} .factory/hooks/session-start.py",
10
- "timeout": 10
10
+ "timeout": 30
11
11
  }
12
12
  ]
13
13
  },
@@ -17,7 +17,7 @@
17
17
  {
18
18
  "type": "command",
19
19
  "command": "{{PYTHON_CMD}} .factory/hooks/session-start.py",
20
- "timeout": 10
20
+ "timeout": 30
21
21
  }
22
22
  ]
23
23
  },
@@ -27,7 +27,7 @@
27
27
  {
28
28
  "type": "command",
29
29
  "command": "{{PYTHON_CMD}} .factory/hooks/session-start.py",
30
- "timeout": 10
30
+ "timeout": 30
31
31
  }
32
32
  ]
33
33
  }
@@ -50,7 +50,7 @@
50
50
  {
51
51
  "type": "command",
52
52
  "command": "{{PYTHON_CMD}} .factory/hooks/inject-workflow-state.py",
53
- "timeout": 5
53
+ "timeout": 15
54
54
  }
55
55
  ]
56
56
  }
@@ -7,7 +7,7 @@
7
7
  {
8
8
  "type": "command",
9
9
  "command": "{{PYTHON_CMD}} .gemini/hooks/session-start.py",
10
- "timeout": 10000
10
+ "timeout": 30000
11
11
  }
12
12
  ]
13
13
  }
@@ -19,7 +19,7 @@
19
19
  {
20
20
  "type": "command",
21
21
  "command": "{{PYTHON_CMD}} .gemini/hooks/inject-workflow-state.py",
22
- "timeout": 5000
22
+ "timeout": 15000
23
23
  }
24
24
  ]
25
25
  }
@@ -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 host shell. Do not assume `export` works everywhere.
219
- AI tool "Bash" surfaces on Windows may execute through PowerShell.
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.
@@ -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 (!contextKey) {
123
- return { taskPath: null, source: "none", stale: false }
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 context = this.readContext(contextKey)
127
- const taskRef = this.normalizeTaskRef(context?.current_task || "")
128
- if (taskRef) {
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
  }