@pennixrv/trellis 0.7.0-beta.5 → 0.7.0-beta.50

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 (219) hide show
  1. package/dist/cli/index.d.ts.map +1 -1
  2. package/dist/cli/index.js +47 -3
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/backup.d.ts +25 -0
  5. package/dist/commands/backup.d.ts.map +1 -0
  6. package/dist/commands/backup.js +152 -0
  7. package/dist/commands/backup.js.map +1 -0
  8. package/dist/commands/channel/adapters/claude.d.ts.map +1 -1
  9. package/dist/commands/channel/adapters/claude.js +2 -0
  10. package/dist/commands/channel/adapters/claude.js.map +1 -1
  11. package/dist/commands/channel/adapters/codex.d.ts +5 -1
  12. package/dist/commands/channel/adapters/codex.d.ts.map +1 -1
  13. package/dist/commands/channel/adapters/codex.js +19 -9
  14. package/dist/commands/channel/adapters/codex.js.map +1 -1
  15. package/dist/commands/channel/adapters/index.d.ts +3 -0
  16. package/dist/commands/channel/adapters/index.d.ts.map +1 -1
  17. package/dist/commands/channel/adapters/index.js +3 -3
  18. package/dist/commands/channel/adapters/index.js.map +1 -1
  19. package/dist/commands/channel/adapters/types.d.ts +2 -0
  20. package/dist/commands/channel/adapters/types.d.ts.map +1 -1
  21. package/dist/commands/channel/guard.d.ts.map +1 -1
  22. package/dist/commands/channel/guard.js +38 -29
  23. package/dist/commands/channel/guard.js.map +1 -1
  24. package/dist/commands/channel/index.d.ts.map +1 -1
  25. package/dist/commands/channel/index.js +52 -16
  26. package/dist/commands/channel/index.js.map +1 -1
  27. package/dist/commands/channel/kill.d.ts.map +1 -1
  28. package/dist/commands/channel/kill.js +37 -15
  29. package/dist/commands/channel/kill.js.map +1 -1
  30. package/dist/commands/channel/messages.d.ts.map +1 -1
  31. package/dist/commands/channel/messages.js +3 -2
  32. package/dist/commands/channel/messages.js.map +1 -1
  33. package/dist/commands/channel/process-identity.d.ts +3 -0
  34. package/dist/commands/channel/process-identity.d.ts.map +1 -0
  35. package/dist/commands/channel/process-identity.js +24 -0
  36. package/dist/commands/channel/process-identity.js.map +1 -0
  37. package/dist/commands/channel/profiles.d.ts +26 -0
  38. package/dist/commands/channel/profiles.d.ts.map +1 -0
  39. package/dist/commands/channel/profiles.js +186 -0
  40. package/dist/commands/channel/profiles.js.map +1 -0
  41. package/dist/commands/channel/rm.d.ts +0 -1
  42. package/dist/commands/channel/rm.d.ts.map +1 -1
  43. package/dist/commands/channel/rm.js +203 -96
  44. package/dist/commands/channel/rm.js.map +1 -1
  45. package/dist/commands/channel/spawn.d.ts +3 -0
  46. package/dist/commands/channel/spawn.d.ts.map +1 -1
  47. package/dist/commands/channel/spawn.js +43 -15
  48. package/dist/commands/channel/spawn.js.map +1 -1
  49. package/dist/commands/channel/supervisor/idle.d.ts +2 -0
  50. package/dist/commands/channel/supervisor/idle.d.ts.map +1 -1
  51. package/dist/commands/channel/supervisor/idle.js +15 -7
  52. package/dist/commands/channel/supervisor/idle.js.map +1 -1
  53. package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -1
  54. package/dist/commands/channel/supervisor/inbox.js +48 -33
  55. package/dist/commands/channel/supervisor/inbox.js.map +1 -1
  56. package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -1
  57. package/dist/commands/channel/supervisor/stdout.js +6 -3
  58. package/dist/commands/channel/supervisor/stdout.js.map +1 -1
  59. package/dist/commands/channel/supervisor/warning.d.ts.map +1 -1
  60. package/dist/commands/channel/supervisor/warning.js +2 -3
  61. package/dist/commands/channel/supervisor/warning.js.map +1 -1
  62. package/dist/commands/channel/supervisor.d.ts +12 -0
  63. package/dist/commands/channel/supervisor.d.ts.map +1 -1
  64. package/dist/commands/channel/supervisor.js +88 -16
  65. package/dist/commands/channel/supervisor.js.map +1 -1
  66. package/dist/commands/channel/wait.d.ts +3 -1
  67. package/dist/commands/channel/wait.d.ts.map +1 -1
  68. package/dist/commands/channel/wait.js +59 -14
  69. package/dist/commands/channel/wait.js.map +1 -1
  70. package/dist/commands/init.d.ts.map +1 -1
  71. package/dist/commands/init.js +23 -10
  72. package/dist/commands/init.js.map +1 -1
  73. package/dist/commands/update.d.ts.map +1 -1
  74. package/dist/commands/update.js +446 -333
  75. package/dist/commands/update.js.map +1 -1
  76. package/dist/commands/workflow.d.ts +1 -0
  77. package/dist/commands/workflow.d.ts.map +1 -1
  78. package/dist/commands/workflow.js +56 -1
  79. package/dist/commands/workflow.js.map +1 -1
  80. package/dist/configurators/codex.d.ts +6 -0
  81. package/dist/configurators/codex.d.ts.map +1 -1
  82. package/dist/configurators/codex.js +93 -0
  83. package/dist/configurators/codex.js.map +1 -1
  84. package/dist/configurators/shared.js +2 -2
  85. package/dist/configurators/shared.js.map +1 -1
  86. package/dist/constants/paths.d.ts +2 -0
  87. package/dist/constants/paths.d.ts.map +1 -1
  88. package/dist/constants/paths.js +2 -0
  89. package/dist/constants/paths.js.map +1 -1
  90. package/dist/migrations/manifests/0.7.0-beta.10.json +9 -0
  91. package/dist/migrations/manifests/0.7.0-beta.11.json +9 -0
  92. package/dist/migrations/manifests/0.7.0-beta.12.json +9 -0
  93. package/dist/migrations/manifests/0.7.0-beta.13.json +9 -0
  94. package/dist/migrations/manifests/0.7.0-beta.14.json +9 -0
  95. package/dist/migrations/manifests/0.7.0-beta.15.json +9 -0
  96. package/dist/migrations/manifests/0.7.0-beta.16.json +9 -0
  97. package/dist/migrations/manifests/0.7.0-beta.17.json +9 -0
  98. package/dist/migrations/manifests/0.7.0-beta.18.json +9 -0
  99. package/dist/migrations/manifests/0.7.0-beta.19.json +9 -0
  100. package/dist/migrations/manifests/0.7.0-beta.20.json +9 -0
  101. package/dist/migrations/manifests/0.7.0-beta.21.json +17 -0
  102. package/dist/migrations/manifests/0.7.0-beta.22.json +9 -0
  103. package/dist/migrations/manifests/0.7.0-beta.23.json +9 -0
  104. package/dist/migrations/manifests/0.7.0-beta.24.json +9 -0
  105. package/dist/migrations/manifests/0.7.0-beta.25.json +9 -0
  106. package/dist/migrations/manifests/0.7.0-beta.26.json +9 -0
  107. package/dist/migrations/manifests/0.7.0-beta.27.json +9 -0
  108. package/dist/migrations/manifests/0.7.0-beta.28.json +9 -0
  109. package/dist/migrations/manifests/0.7.0-beta.29.json +9 -0
  110. package/dist/migrations/manifests/0.7.0-beta.30.json +9 -0
  111. package/dist/migrations/manifests/0.7.0-beta.31.json +9 -0
  112. package/dist/migrations/manifests/0.7.0-beta.32.json +9 -0
  113. package/dist/migrations/manifests/0.7.0-beta.33.json +9 -0
  114. package/dist/migrations/manifests/0.7.0-beta.34.json +9 -0
  115. package/dist/migrations/manifests/0.7.0-beta.35.json +9 -0
  116. package/dist/migrations/manifests/0.7.0-beta.36.json +9 -0
  117. package/dist/migrations/manifests/0.7.0-beta.37.json +9 -0
  118. package/dist/migrations/manifests/0.7.0-beta.38.json +9 -0
  119. package/dist/migrations/manifests/0.7.0-beta.39.json +9 -0
  120. package/dist/migrations/manifests/0.7.0-beta.40.json +9 -0
  121. package/dist/migrations/manifests/0.7.0-beta.41.json +9 -0
  122. package/dist/migrations/manifests/0.7.0-beta.42.json +9 -0
  123. package/dist/migrations/manifests/0.7.0-beta.43.json +9 -0
  124. package/dist/migrations/manifests/0.7.0-beta.44.json +9 -0
  125. package/dist/migrations/manifests/0.7.0-beta.45.json +9 -0
  126. package/dist/migrations/manifests/0.7.0-beta.46.json +9 -0
  127. package/dist/migrations/manifests/0.7.0-beta.47.json +9 -0
  128. package/dist/migrations/manifests/0.7.0-beta.48.json +9 -0
  129. package/dist/migrations/manifests/0.7.0-beta.49.json +13 -0
  130. package/dist/migrations/manifests/0.7.0-beta.50.json +12 -0
  131. package/dist/migrations/manifests/0.7.0-beta.6.json +9 -0
  132. package/dist/migrations/manifests/0.7.0-beta.7.json +9 -0
  133. package/dist/migrations/manifests/0.7.0-beta.8.json +9 -0
  134. package/dist/migrations/manifests/0.7.0-beta.9.json +9 -0
  135. package/dist/templates/codex/hooks/session-start.py +21 -17
  136. package/dist/templates/common/bundled-skills/trellis-channel/SKILL.md +3 -1
  137. package/dist/templates/common/bundled-skills/trellis-channel/references/command-reference.md +24 -16
  138. package/dist/templates/common/bundled-skills/trellis-channel/references/forum.md +4 -12
  139. package/dist/templates/common/bundled-skills/trellis-channel/references/multi-target-dispatch.md +139 -0
  140. package/dist/templates/common/bundled-skills/trellis-channel/references/progress-debugging.md +9 -5
  141. package/dist/templates/common/bundled-skills/trellis-channel/references/subnode-work.md +84 -14
  142. package/dist/templates/common/bundled-skills/trellis-channel/references/workers.md +9 -11
  143. package/dist/templates/common/bundled-skills/trellis-channel/references/workflows.md +25 -14
  144. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +13 -11
  145. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +7 -2
  146. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +6 -1
  147. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workflow.md +6 -4
  148. package/dist/templates/common/bundled-skills/trellis-session-insight/SKILL.md +42 -3
  149. package/dist/templates/common/bundled-skills/trellis-session-insight/references/cli-quick-reference.md +1 -1
  150. package/dist/templates/common/bundled-skills/trellis-session-insight/references/triggering-patterns.md +10 -2
  151. package/dist/templates/common/commands/continue.md +36 -8
  152. package/dist/templates/common/commands/finish-work.md +17 -2
  153. package/dist/templates/common/commands/start.md +8 -1
  154. package/dist/templates/common/skills/brainstorm.md +49 -22
  155. package/dist/templates/common/skills/break-loop.md +6 -10
  156. package/dist/templates/common/skills/check.md +34 -5
  157. package/dist/templates/copilot/hooks/session-start.py +19 -15
  158. package/dist/templates/copilot/prompts/brainstorm.prompt.md +27 -21
  159. package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +22 -22
  160. package/dist/templates/markdown/spec/backend/directory-structure.md.txt +20 -20
  161. package/dist/templates/markdown/spec/backend/error-handling.md.txt +22 -22
  162. package/dist/templates/markdown/spec/backend/index.md.txt +19 -19
  163. package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +22 -22
  164. package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +22 -22
  165. package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +25 -25
  166. package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +20 -20
  167. package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +22 -22
  168. package/dist/templates/markdown/spec/frontend/index.md.txt +20 -20
  169. package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +22 -22
  170. package/dist/templates/markdown/spec/frontend/state-management.md.txt +22 -22
  171. package/dist/templates/markdown/spec/frontend/type-safety.md.txt +22 -22
  172. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +80 -85
  173. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +164 -209
  174. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +161 -185
  175. package/dist/templates/markdown/spec/guides/index.md.txt +51 -51
  176. package/dist/templates/markdown/workspace-index.md +44 -44
  177. package/dist/templates/opencode/lib/session-utils.js +2 -2
  178. package/dist/templates/shared-hooks/inject-shell-session-context.py +3 -6
  179. package/dist/templates/shared-hooks/inject-workflow-state.py +3 -2
  180. package/dist/templates/shared-hooks/session-start.py +23 -18
  181. package/dist/templates/trellis/agents/subnode-profiles.json +13 -0
  182. package/dist/templates/trellis/agents/subnode.md +11 -5
  183. package/dist/templates/trellis/config.yaml +2 -0
  184. package/dist/templates/trellis/index.d.ts +2 -1
  185. package/dist/templates/trellis/index.d.ts.map +1 -1
  186. package/dist/templates/trellis/index.js +4 -2
  187. package/dist/templates/trellis/index.js.map +1 -1
  188. package/dist/templates/trellis/scripts/add_session.py +35 -32
  189. package/dist/templates/trellis/scripts/common/active_task.py +8 -8
  190. package/dist/templates/trellis/scripts/common/developer.py +18 -18
  191. package/dist/templates/trellis/scripts/common/ownership_record.py +13 -8
  192. package/dist/templates/trellis/scripts/common/safe_commit.py +38 -9
  193. package/dist/templates/trellis/scripts/common/task_planning.py +137 -0
  194. package/dist/templates/trellis/scripts/common/task_store.py +46 -14
  195. package/dist/templates/trellis/scripts/common/workflow_phase.py +4 -3
  196. package/dist/templates/trellis/scripts/subnode_artifact.py +470 -21
  197. package/dist/templates/trellis/scripts/task.py +175 -2
  198. package/dist/templates/trellis/workflow.md +407 -388
  199. package/dist/utils/managed-paths.d.ts +2 -0
  200. package/dist/utils/managed-paths.d.ts.map +1 -1
  201. package/dist/utils/managed-paths.js +24 -2
  202. package/dist/utils/managed-paths.js.map +1 -1
  203. package/dist/utils/template-fetcher.d.ts +1 -0
  204. package/dist/utils/template-fetcher.d.ts.map +1 -1
  205. package/dist/utils/template-fetcher.js +2 -1
  206. package/dist/utils/template-fetcher.js.map +1 -1
  207. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  208. package/dist/utils/uninstall-scrubbers.js +5 -0
  209. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  210. package/dist/utils/workflow-provenance.d.ts +24 -0
  211. package/dist/utils/workflow-provenance.d.ts.map +1 -0
  212. package/dist/utils/workflow-provenance.js +71 -0
  213. package/dist/utils/workflow-provenance.js.map +1 -0
  214. package/dist/utils/workflow-resolver.d.ts +9 -2
  215. package/dist/utils/workflow-resolver.d.ts.map +1 -1
  216. package/dist/utils/workflow-resolver.js +33 -7
  217. package/dist/utils/workflow-resolver.js.map +1 -1
  218. package/package.json +2 -2
  219. package/dist/templates/trellis/agents/subnode.env +0 -4
@@ -1,6 +1,8 @@
1
1
  # Triggering Patterns
2
2
 
3
- Verbatim user phrasings that should make an AI reach for `trellis mem`. Calibrate instinct against these — if a user message hits one of these patterns and you do not reach for `mem`, you probably missed an obvious recall.
3
+ Verbatim user phrasings that suggest local conversation recall. Check the intent
4
+ and available current evidence before calling `trellis mem`; these examples do
5
+ not require an unconditional history search.
4
6
 
5
7
  Patterns are grouped by the *intent* behind the phrasing, not the surface words. The same intent shows up in different languages and registers.
6
8
 
@@ -32,7 +34,8 @@ Reach: `trellis mem search "<decision keyword>"` to find the session, then `extr
32
34
 
33
35
  ## Cross-session continuation
34
36
 
35
- The user resumed work after a gap and the context is implicit.
37
+ The user resumed work after a gap and the context is implicit. Read the active
38
+ task and current files first; use raw history only for missing discussion.
36
39
 
37
40
  - "Where were we?"
38
41
  - "Continue from last time."
@@ -84,6 +87,11 @@ Reach: identify the current task's session id (from `.trellis/.runtime/sessions/
84
87
 
85
88
  ## Anti-patterns: do NOT reach for `mem` here
86
89
 
90
+ - "Find our maintained deployment notes" → the configured native knowledge tool.
91
+ - "Save this reusable result to my notebook" → explicit knowledge write through its owner.
92
+ - "Promote this method into a Skill" → verify the evidence, then the source Skill owner.
93
+ - Current task artifacts already answer the question → use those artifacts.
94
+
87
95
  - "What does this function do?" → read the file.
88
96
  - "Why is this test failing?" → read the test output and the file.
89
97
  - "What's the right pattern for X in our codebase?" → grep / read spec files.
@@ -4,31 +4,59 @@ Resume work on the current task — pick up at the right phase/step in `.trellis
4
4
 
5
5
  ---
6
6
 
7
- ## Step 1: Load Current Context
7
+ ## Step 1: Reuse the Checkpoint; Fill Only Missing Context
8
+
9
+ If the current conversation or compaction summary already supplies project root,
10
+ task, phase, authorization and pending action, resume that action directly. Keep
11
+ running tool handles and completed work; skip the queries below and Steps 2–4
12
+ unless a specific fact or instruction is missing/conflicting. A plain continue
13
+ does not require startup, Git/status/history or formal handoff validation.
14
+
15
+ After compaction, never repeat or re-answer the last consumed user input from
16
+ before compaction. Continue from the actual checkpoint. Handle genuinely new
17
+ post-compaction input normally.
18
+
19
+ For a fresh session, changed target, missing/conflicting facts or explicit
20
+ inspection, use the minimum query that resolves the gap:
8
21
 
9
22
  ```bash
10
- {{PYTHON_CMD}} ./.trellis/scripts/get_context.py
23
+ {{PYTHON_CMD}} ./.trellis/scripts/task.py current --json
11
24
  ```
12
25
 
13
- Confirms: current task, git state, recent commits.
26
+ Use full `get_context.py` only when its identity/project/Git overview is needed.
27
+ Protected native writes still enforce identity, binding and ownership through
28
+ their owner; this shortcut never bypasses those checks.
29
+
30
+ Before routing by status, distinguish identity from task binding. A non-null
31
+ `session_source` confirms available identity; only `source=session:...` confirms
32
+ a direct task binding. For `unbound` / `unbound_ambiguous`, review existing task
33
+ artifacts and select by the user's explicit intent. Exit code 1 for ambiguity
34
+ does not mean identity is absent. Do not guess, duplicate tasks, invent identity,
35
+ or edit runtime pointers. Return a planning candidate to the planning gates below;
36
+ use native `task.py select <task>` to bind planning context after any required
37
+ Channel drain; use `task.py start` only when its activation contract permits it.
38
+ An eligible `analysis_only` candidate remains in planning without start.
39
+ If `session_source` is null, report unavailable identity separately.
14
40
 
15
- ## Step 2: Load the Phase Index
41
+ ## Step 2: Load the Phase Index Only When Needed
16
42
 
17
43
  ```bash
18
44
  {{PYTHON_CMD}} ./.trellis/scripts/get_context.py --mode phase
19
45
  ```
20
46
 
21
- Shows the Phase Index (Plan / Execute / Finish) with routing + skill mapping.
47
+ Run only when the phase or routing rule is missing; otherwise reuse it.
22
48
 
23
49
  ## Step 3: Decide Where You Are
24
50
 
25
51
  `get_context.py` shows the active task's `status` field. Route by `status` + artifact presence. This command replaces the user needing to remember the Trellis flow; it does not itself approve implementation.
26
52
 
27
- - `status=planning` + `task.json.meta.delivery_mode = "analysis_only"` → complete the PRD's bounded evidence work, verify its acceptance criteria and no-change boundary, then commit task artifacts and archive directly. Do not run `task.py start`; a protected-target change requires a separate change-bearing task.
53
+ - `status=planning` + `task.json.meta.delivery_mode = "analysis_only"` → verify the PRD's bounded evidence deliverable and protected-target no-change boundary, then complete the evidence and archive directly regardless of complexity or cross-owner scope. Do not run `task.py start`; a protected-target change requires a separate change-bearing task.
28
54
  - `status=planning` + no `prd.md` → **1.1** (load `trellis-brainstorm`)
55
+ - `status=planning` + a recorded `decision-needed` or unsealed decision chain → return to `pennix-decision-grill` only for a change-bearing decision or a user-owned choice that materially defines the requested research scope or method; research recommendations and open product choices alone do not trigger the gate.
56
+ - `status=in_progress` + a material unresolved decision → record the reason and run `task.py replan <task> "<reason>"`; do not ask a native question during implementation.
29
57
  - `status=planning` + `prd.md` only → decide whether the task is lightweight or complex. Lightweight can move to **1.4** review; complex returns to **1.1** to add `design.md` + `implement.md`.
30
58
  - `status=planning` + complex artifacts complete + sub-agent jsonl not curated (empty, or only a legacy `_example` placeholder row) → **1.3**
31
- - `status=planning` + required artifacts complete + required jsonl curated or inline mode → **1.4** (ask for start review; only run `task.py start` after user confirms)
59
+ - `status=planning` + required artifacts complete + required jsonl curated or inline mode → for change-bearing work, run the Planning Seal closure pass, then **1.4**; require later explicit implementation approval for the current sealed revision and use native plan seal/approve/start. `analysis_only` work completes its evidence and archives without this path. A replan invalidates change-bearing approval; minor progress edits do not.
32
60
  - `status=in_progress` + implementation not started → **2.1**
33
61
  - `status=in_progress` + implementation done, not yet checked → **2.2**
34
62
  - `status=in_progress` + check passed → **3.3** (spec update) → **3.4** (commit)
@@ -42,7 +70,7 @@ Phase rules (full detail in `.trellis/workflow.md`):
42
70
 
43
71
  ## Step 4: Load the Specific Step
44
72
 
45
- Once you know which step to resume at:
73
+ Only if the identified step's instructions are missing:
46
74
 
47
75
  ```bash
48
76
  {{PYTHON_CMD}} ./.trellis/scripts/get_context.py --mode phase --step <X.X> --platform {{CLI_FLAG}}
@@ -16,7 +16,7 @@ This prints:
16
16
  - **Git status** — quick visual on what's dirty.
17
17
  - **Recent commits** — you'll need their hashes in Step 4 for `--commit`.
18
18
 
19
- If `--mode record` surfaces other completed tasks not tied to the current session, surface them to the user with a one-shot confirmation: "These N tasks look done — archive them too in this round? [y/N]". Default is no; the current active task is always archived in Step 3 regardless.
19
+ If `--mode record` surfaces other completed tasks not tied to the current session, surface them to the user with a one-shot confirmation: "These N tasks look done — archive them too in this round? [y/N]". Default is no; archive the current task only after the acceptance check below.
20
20
 
21
21
  ## Step 2: Sanity check — classify dirty paths
22
22
 
@@ -44,13 +44,28 @@ Then route:
44
44
  > "FYI, dirty files outside this task's scope — leaving them for the other window: `<list>`."
45
45
  - **Genuinely unsure** — ask the user once: "Are `<list>` this task's work I forgot to commit, or another window's? (commit / ignore)" — then route per their answer.
46
46
 
47
+ ### Acceptance check before archive
48
+
49
+ Compare the task's PRD-defined endpoint and required acceptance criteria with
50
+ actual evidence in its records and verification results. Reuse valid results;
51
+ state which checks ran, did not run, were blocked, or had limited coverage.
52
+ Installation, publishing, project updates or live execution require their own
53
+ evidence when they are part of the authorized endpoint; static readiness or
54
+ isolated tests cannot stand in for them. Clean bootstrap/cleanup is conditional
55
+ on the task goal and authorization, not an automatic finishing step.
56
+
57
+ If a required criterion is unmet or lacks sufficient evidence, return to the
58
+ corresponding work and leave the task unarchived. Reporting a limitation does
59
+ not satisfy a required criterion. Keep this conclusion in the existing task
60
+ record; do not add a separate acceptance receipt.
61
+
47
62
  ## Step 3: Archive task(s)
48
63
 
49
64
  ```bash
50
65
  {{PYTHON_CMD}} ./.trellis/scripts/task.py archive <task-name>
51
66
  ```
52
67
 
53
- At minimum: the current active task (if any). Plus any extra tasks the user confirmed in Step 1. Each archive produces a `chore(task): archive ...` commit via the script's auto-commit.
68
+ Archive the current active task and any extra tasks confirmed in Step 1 only when their required acceptance has been verified. Each archive produces a `chore(task): archive ...` commit via the script's auto-commit.
54
69
 
55
70
  If there is no active task and the user did not confirm any cleanup archives, skip this step.
56
71
 
@@ -2,6 +2,12 @@
2
2
 
3
3
  Initialize a Trellis-managed development session. This platform has no session-start hook, so manually load the equivalent compact context by following these steps.
4
4
 
5
+ Run this initialization once when project context is genuinely missing or the
6
+ target project changes. Existing session context and a sufficient compaction
7
+ summary count as loaded context. An ordinary continue or new task in the same
8
+ known project resumes the pending action without repeating these steps. For
9
+ partial missing/conflicting facts, query only the needed owner evidence.
10
+
5
11
  ---
6
12
 
7
13
  ## Step 1: Current state
@@ -39,11 +45,12 @@ From Step 1 you know the current task and status. Check the task directory:
39
45
  - **Active task with `task.json.meta.delivery_mode = "analysis_only"`** → keep `planning`, complete the PRD's bounded evidence work, then verify the no-change boundary, commit task artifacts, and archive directly. Do not run `task.py start`; any protected-target change needs a separate change-bearing task.
40
46
  - **Active task status `planning` + no `prd.md`** → Phase 1.1. Load the `trellis-brainstorm` skill.
41
47
  - **Active task status `planning` + `prd.md` exists** → stay in Phase 1. Lightweight tasks can be PRD-only; complex tasks need `design.md` + `implement.md`. Load the relevant Phase 1 step detail before `task.py start`.
48
+ - **Existing task selected by explicit intent but not bound** → use native `task.py select` for context only. Drain already dispatched Channel units before a real task switch. Planned/change-bearing start requires native plan seal and matching later approval for this task's current material revision; selecting or recovering context does not approve implementation.
42
49
  - **Active task status `in_progress`** → Phase 2 step 2.1. Load the step detail:
43
50
  ```bash
44
51
  {{PYTHON_CMD}} ./.trellis/scripts/get_context.py --mode phase --step 2.1 --platform {{CLI_FLAG}}
45
52
  ```
46
- - **No active task** → classify first. For simple conversation / small task, ask only whether this turn should create a Trellis task. For complex work, ask whether you may create a Trellis task and enter planning. If the user says no, skip Trellis for this session.
53
+ - **No active task** → classify first. Simple conversation needs no task. Bounded direct work uses the workflow's direct path without a mandatory task-creation question. Complex work creates a task and enters planning when authorized; ask only if the necessary authorization is missing.
47
54
 
48
55
  ---
49
56
 
@@ -6,12 +6,26 @@ A request to build, implement, fix, refactor, or "go ahead" is not approval to l
6
6
 
7
7
  For every non-trivial task, the user must respond at least once after the initial request before implementation begins. If no clarification is needed, that response must approve the final planning summary described below.
8
8
 
9
- While any user-owned product, scope, UX, compatibility, risk, or acceptance decision remains unresolved, end the turn with exactly one highest-value question. Do not edit product code, dispatch implementation, or run `task.py start`.
9
+ Keep the task in planning while a user-owned choice needed to define the requested work remains unresolved. For `analysis_only`, findings, recommendations, and open product options do not block evidence work or require a sealed decision chain. For other work, screen consequential user-owned choices with `pennix-decision-grill`, including a single choice; it owns progressive decision method, not task lifecycle. Do not implement or run `task.py start` until change decisions are sealed and approved.
10
+
11
+ ## Idea-to-Plan Route
12
+
13
+ When the input is an idea, suspected gap, review finding, or loosely stated improvement, route it through the smallest complete chain:
14
+
15
+ 1. State the user outcome and the concrete problem or gap in one sentence.
16
+ 2. Separate repository-answerable facts from user-owned choices; inspect the repository, task history, and applicable specs before asking about facts.
17
+ 3. Record the current evidence and its recovery point in the natural task artifact: research matrix for research, PRD/design for planning, and the diff or Git history for code.
18
+ 4. Screen only the choices that change scope, owner, risk, public behavior, release, or acceptance through `$pennix-decision-grill`.
19
+ 5. Define observable acceptance, boundaries, rollback, and the next dependency-ready action; then use the normal seal and approval gate.
20
+
21
+ An issue discovered while doing this work is not automatically part of the task. Compare its owner, target, risk, and acceptance with the sealed scope. Record every consequential finding and ask whether it should be included; a same-owner, reversible, low-risk correction may use the existing in-progress addition rule. Otherwise use `task.py replan` and reseal before dependent implementation.
10
22
 
11
23
  ## Analysis-Only Exception
12
24
 
13
25
  When `task.json.meta.delivery_mode = "analysis_only"` exactly and the PRD names a bounded evidence deliverable plus a no-change boundary for product source, runtime configuration, deployment, credentials, and external systems, task-creation consent authorizes that evidence work. Do not require a second planning approval or run `task.py start`: perform the declared research, audit, or design work while status remains `planning`, record the evidence, verify acceptance criteria and the boundary, commit task artifacts, and archive directly. If the evidence recommends a protected-target change, record it and create a separate change-bearing task before doing it.
14
26
 
27
+ This route remains eligible for bounded evidence work regardless of complexity, cross-owner scope, multiple evidence units, or whether conclusions include recommendations or unresolved product choices. Record findings and recommendations in task artifacts; do not change protected targets, deploy, release, alter credentials, or mutate external systems. The initial request authorizes the requested main-session research, so do not require a second implementation approval, Planning Seal, or `task.py start` to complete it. If the user requests independent subnode evidence, freeze its dispatch plan in the task first and obtain explicit approval of that plan before any spawn/send; this approval authorizes only the listed evidence dispatch. If implementation is later requested, create or replan a change-bearing task and use its normal Planning Seal and implementation approval gates.
28
+
15
29
  All other tasks follow the planning and implementation approval gates below.
16
30
 
17
31
  ## Non-Negotiable Evidence Rule
@@ -24,6 +38,19 @@ Do not ask the user to confirm facts that the repository can answer. Ask only fo
24
38
 
25
39
  Repository evidence establishes current behavior and technical constraints. The user's intended behavior, feature scope boundaries, and UX preferences are never answerable by repository evidence alone, even when an existing pattern exists; existing patterns are options and recommendation evidence, not decisions.
26
40
 
41
+ ## Evidence Units For Read-Heavy Work
42
+
43
+ When research, audit, review, or investigation is too large to leave one independently useful conclusion in the current bounded session, split it into evidence units. Each unit must have one question or scope, a minimal evidence range, a destination artifact, and a stop condition; write its facts, conclusion or blocker, unknowns, and recovery point before starting another unit. Size units so one normal context window can finish and persist one useful result; do not promise an exact token or time limit. Routine navigation and transient tool output do not need an artifact. Create a child task only when the unit has an independent owner, lifecycle, and acceptance contract.
44
+
45
+ Persist the unit-to-point mapping in this task's existing plan/matrix before
46
+ dispatch. Include workload rationale, dependencies, minimal evidence, shared
47
+ context, and per-point delivery. Combine points only when each is quick/simple
48
+ and they are obviously related; explain the grouping and bounded total workload.
49
+ Complex or lengthy points need separate units or further splitting. Slots and
50
+ owner domains do not determine unit count. Explicit independent subnodes use
51
+ `trellis-channel`'s unit-plan and multi-target procedure; planning itself does
52
+ not authorize dispatch.
53
+
27
54
  ---
28
55
 
29
56
  Use this skill during Phase 1 planning to turn the user's request into clear requirements and planning artifacts.
@@ -54,18 +81,21 @@ Use a concise title from the user's request. Both the title and `--description`
54
81
  - product intent still needed from the user
55
82
  - scope or risk decisions still needed from the user
56
83
  - likely out-of-scope items
57
- 4. If a user-owned decision remains, ask the single highest-value question, include your recommendation and trade-off, then stop. Do not perform implementation work in the same turn.
58
- 5. After each user answer, update `prd.md`, recompute the decision inventory, and repeat from step 2.
59
- 6. When no user-owned decision remains, create or update `design.md` and `implement.md` for complex tasks.
60
- 7. Run the requirement convergence gate, then the PRD convergence pass.
61
- 8. Present the final planning summary and stop. Do not run `task.py start` or edit product code in the same turn.
62
- 9. Only a subsequent user message that explicitly approves the latest planning summary authorizes `task.py start` and implementation. If the artifacts change materially after approval, repeat the final review.
84
+ 4. Screen genuine user-owned decisions; resolve repository facts and settled local details directly. Use `pennix-decision-grill` progressively: dependency readiness first, then impact/priority; ask only the coherent current frontier and reassess after answers. For bounded research, ask only when its requested scope or method depends on the choice; findings and recommendations need no implementation decision.
85
+ 5. If the user requests independent subnode evidence, first freeze the dispatch plan in the task: question, evidence-unit mapping and grouping rationale, brief scope/stop conditions/destinations, concurrency and FIFO refill/acceptance method. Obtain the user's explicit approval of that frozen plan before any spawn/send. This approval covers only the listed evidence dispatch; material changes to units, scope, method, owner, risk, or acceptance require reapproval. Main-session evidence work may continue while dispatch approval is pending.
86
+ 6. When a needed answer returns, persist it and the affected dependencies, recheck evidence, and continue the same task. Before substantial evidence work, save the current decision, known answers, missing facts, return point and stop condition. Use bounded local/web evidence or explicitly approved independent subnodes; they establish facts, not user decisions. An empty ready frontier can mean missing evidence, not planning closure. Do not create a second lifecycle for the same decision chain.
87
+ 7. For `analysis_only`, record and verify the declared evidence and no-change boundary in planning; do not require `design.md`, `implement.md`, a Planning Seal, implementation approval, or `task.py start` merely because the research is complex.
88
+ 8. For change-bearing work, resolve material decisions, create/update complex-task artifacts, run the requirement convergence and PRD passes, then close and present the Planning Seal. Stop before implementation. Only a later explicit approval for this task's current sealed revision authorizes native plan approval and `task.py start`. Initial requests, parent-task approvals, and design answers do not qualify. Material changes require `task.py replan` and approval of its newly sealed revision; progress and wording edits do not.
89
+
90
+ When changing the active task only for planning, use native `task.py select`,
91
+ not start. `create --no-start` intentionally preserves the old pointer. Follow
92
+ the Channel drain procedure before switching with live evidence workers.
63
93
 
64
94
  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.
65
95
 
66
96
  ## Question Rules
67
97
 
68
- Ask only one question per message.
98
+ Ask one to three independent, coherent, ready decisions per round, ordered by impact. One high-priority decision is sufficient even when other choices exist; never fill a batch just to reach a count. Dependent questions wait for the preceding answer, and later rounds may discover new branches. Use the host's blocking native question tool; never choose by elapsed time or an unanswered required decision.
69
99
 
70
100
  Each question must include:
71
101
 
@@ -78,9 +108,7 @@ Do not ask process questions such as whether to search, inspect files, or contin
78
108
 
79
109
  Recommendations are not default selections. Never choose a recommended product decision on the user's behalf merely because the user asked for implementation.
80
110
 
81
- Do not manufacture clarification questions when the request and repository evidence already resolve every decision. In that case, proceed directly to the final planning summary, which still requires a subsequent explicit approval.
82
-
83
- The final review is a required phase-transition gate, not a prohibited process question. Task-creation consent, the initial implementation request, and approval given before the latest final summary do not satisfy this gate.
111
+ Do not manufacture clarification questions when the request and repository evidence already resolve the scope and method. For `analysis_only`, proceed with the requested evidence work; no final implementation review or approval is required. The final review and subsequent approval are phase-transition gates for change-bearing implementation only.
84
112
 
85
113
  ## Thinking Framework: First Principles Analysis
86
114
 
@@ -136,10 +164,12 @@ Before final review, verify all of the following:
136
164
  - blocking open questions are empty
137
165
  - technical unknowns are researched or explicitly deferred without changing MVP behavior
138
166
 
139
- Lightweight tasks may omit `design.md` and `implement.md`; they may not skip evidence inspection, requirement convergence, final review, or fresh implementation approval.
167
+ For `analysis_only`, keep the task PRD bounded to evidence and the protected-target no-change boundary; it may omit `design.md` and `implement.md` and does not need an implementation review or approval. Change-bearing tasks retain their applicable evidence, convergence, final review, and fresh implementation approval gates.
140
168
 
141
169
  The final planning summary must show Goal, In Scope, Out of Scope, Acceptance Criteria, Key Decisions, relevant Risks or Deferred Items, and artifact status.
142
170
 
171
+ For change-bearing work, the Planning Seal closure pass reconciles task artifacts, targets, branches, dependencies, release, validation, rollback, dynamic facts, and material decisions before implementation; unresolved implementation ambiguity invalidates the seal. This closure pass is not an eligibility or completion gate for `analysis_only` evidence work.
172
+
143
173
  ## Artifact Rules
144
174
 
145
175
  `prd.md` records requirements and acceptance:
@@ -187,15 +217,12 @@ After the pass, read `prd.md` top to bottom and verify that no fact is repeated
187
217
 
188
218
  ## Quality Bar
189
219
 
190
- Before declaring planning ready:
220
+ Before declaring change-bearing planning ready:
191
221
 
192
- - `prd.md` contains testable acceptance criteria.
193
- - `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.
194
- - Repository-answerable questions have already been answered through inspection.
195
- - Blocking open questions are empty.
196
- - Complex tasks have `design.md` and `implement.md`.
197
- - Sub-agent-dispatch tasks have real curated entries in both `implement.jsonl` and `check.jsonl`; seed-only manifests are not ready.
198
- - The latest final planning summary has been presented to the user.
199
- - In a subsequent message, the user explicitly approved that summary for implementation.
222
+ - `prd.md` contains testable acceptance criteria and has passed the PRD convergence pass.
223
+ - Repository-answerable questions have been answered; blocking implementation questions are resolved.
224
+ - Complex change-bearing tasks have `design.md` and `implement.md`; sub-agent-dispatch implementation tasks have curated manifests.
225
+ - The Planning Seal and final summary cover the implementation target, validation, and rollback.
226
+ - The user subsequently approved this task's current sealed plan.
200
227
 
201
- Do not start implementation merely because the user originally asked for implementation.
228
+ For `analysis_only`, verify the declared evidence deliverable and protected-target no-change boundary, then proceed to complete the research in planning without an implementation summary approval. Do not start change-bearing implementation merely because the user originally requested it.
@@ -8,6 +8,8 @@ When debug is complete, use this for deep analysis to break the "fix bug -> forg
8
8
 
9
9
  Analyze the bug you just fixed from these 5 dimensions:
10
10
 
11
+ Start with a short causal loop before filling the five dimensions: expected behavior → observed failure → discriminating evidence → root cause → prevention check. If the failure is not reproduced, label the uncertainty and do not promote a plausible explanation to a confirmed cause.
12
+
11
13
  ### 1. Root Cause Category
12
14
 
13
15
  Which category does this bug belong to?
@@ -169,16 +171,10 @@ Never express binary certainty when evidence is incomplete. Use "most likely", "
169
171
 
170
172
  ## After Analysis: Immediate Actions
171
173
 
172
- **IMPORTANT**: After completing the analysis above, you MUST immediately:
173
-
174
- 1. **Update spec/guides** - Don't just list TODOs, actually update the relevant files:
175
- - If it's a cross-platform issue → update `cross-platform-thinking-guide.md`
176
- - If it's a cross-layer issue → update `cross-layer-thinking-guide.md`
177
- - If it's a code reuse issue → update `code-reuse-thinking-guide.md`
178
- - If it's domain-specific → update `backend/*.md` or `frontend/*.md`
174
+ Record verified findings in the active task. Update a spec only when the finding establishes a reusable, executable contract owned by that project and the current task authorizes the change. Routine progress and one-off observations stay in task records.
179
175
 
180
- 2. **Sync templates** - After updating `.trellis/spec/`, sync to `src/templates/markdown/spec/`
176
+ Consumer projects do not sync specs into Trellis templates. When working on the Trellis source itself, update a corresponding template under `packages/cli/src/templates/markdown/` only if it exists and the change is intended for generated consumers. Keep root coordination contracts in their owner; do not copy them into component specs.
181
177
 
182
- 3. **Commit the spec updates** - This is the primary output, not just the analysis text
178
+ Follow the task's existing commit and release process. This skill does not independently authorize source changes, commits, publication, or new tickets.
183
179
 
184
- > **The analysis is worthless if it stays in chat. The value is in the updated specs.**
180
+ When the analysis reveals a neighboring defect, compare its owner, target, risk, and acceptance with the current task. Record the finding and ask for inclusion when it changes material scope; only a same-owner, reversible, low-risk correction may continue under the existing in-progress addition rule. This keeps root-cause learning broad while keeping implementation scope explicit.
@@ -1,6 +1,6 @@
1
1
  # Code Quality Check
2
2
 
3
- Comprehensive quality verification for recently written code. Combines spec compliance, cross-layer safety, and pre-commit checks.
3
+ Verify the task's affected behavior against the current implementation, applicable specs, and acceptance criteria.
4
4
 
5
5
  ---
6
6
 
@@ -11,6 +11,11 @@ git diff --name-only HEAD
11
11
  git status
12
12
  ```
13
13
 
14
+ Use the diff as the entry point. Follow the affected behavior through existing
15
+ implementation, necessary callers, configuration, tests, documentation and
16
+ generated consumers. Expand when evidence of an existing problem could affect
17
+ the task result; do not default to a whole-module or whole-repository audit.
18
+
14
19
  ## Step 2: Read Task Artifacts and Applicable Specs
15
20
 
16
21
  Read the current task artifacts in order:
@@ -35,6 +40,12 @@ Read the specific guideline files referenced — the index is a pointer, not the
35
40
 
36
41
  Run the project's lint, type-check, and test commands. Fix any failures before proceeding.
37
42
 
43
+ Choose checks by changed behavior and risk. When the task includes installation,
44
+ release or a live workflow, verify its normal entry and required endpoint;
45
+ isolated tests do not prove those endpoints. A clean bootstrap or destructive
46
+ cleanup applies only when required by the task and authorized. Reuse valid
47
+ results and distinguish checks run, not run, blocked, or limited.
48
+
38
49
  ## Step 4: Review Against Checklist
39
50
 
40
51
  ### Code Quality
@@ -47,9 +58,9 @@ Run the project's lint, type-check, and test commands. Fix any failures before p
47
58
 
48
59
  ### Test Coverage
49
60
 
50
- - [ ] New function → unit test added?
51
- - [ ] Bug fix → regression test added?
52
- - [ ] Changed behavior → existing tests updated?
61
+ - [ ] Non-trivial behavior and material risks covered by meaningful checks?
62
+ - [ ] Bug fix has a regression that reaches the failing path?
63
+ - [ ] Existing tests updated when their behavior changed, without duplicating trivial implementation?
53
64
 
54
65
  ### Spec Sync
55
66
 
@@ -62,7 +73,7 @@ Run the project's lint, type-check, and test commands. Fix any failures before p
62
73
  - [ ] Any tidying of code the task did not require?
63
74
  - [ ] Any abstraction, config or extension point added for a case that does not exist yet?
64
75
  - [ ] Any speculative fallback for a state that cannot occur?
65
- - [ ] Any file changed that the acceptance criteria do not mention?
76
+ - [ ] Each changed file serves the task or a necessary consumer, even if the AC do not name it individually?
66
77
  - [ ] Any workaround added at the caller instead of a fix where the behavior actually lives?
67
78
 
68
79
  ## Step 5: Cross-Layer Dimensions (if applicable)
@@ -100,7 +111,25 @@ Skip this step if your change is confined to a single layer.
100
111
 
101
112
  Report every violation you find. Then:
102
113
 
114
+ Verify important findings against current requirements, actual sources, callers
115
+ and relevant counterevidence before prioritizing. Separate observed facts from
116
+ inferences; a rule's presence, a zero call count or an intentional behavior is
117
+ not by itself proof of a defect. Record task-relevant findings and their effect
118
+ on acceptance; new consequential scope choices follow the task's decision gate.
119
+
103
120
  - Mechanical and local (lint nit, missing type, wrong import, dead branch, failing assertion) → fix in place, then re-run project checks.
104
121
  - Design or judgment (naming a shared concept, moving a module boundary, changing a public interface, reassigning where behavior lives) → record the evidence and your recommendation, and stop. Do not rewrite it silently.
105
122
 
106
123
  If a fix would touch files outside the current task's scope, say so and stop instead of widening the change.
124
+
125
+ ## Step 7: Close the Review Loop
126
+
127
+ For each material finding, preserve the chain from evidence to action:
128
+
129
+ 1. State the observed behavior, source or test evidence, and confidence.
130
+ 2. Identify the affected acceptance criterion, owner, target, and risk.
131
+ 3. Classify the finding as an in-scope correction, a separately owned issue, or a consequential scope change.
132
+ 4. Fix only in-scope mechanical corrections. Record separately owned or consequential findings and use the task's decision/replan gate before dependent work.
133
+ 5. Re-run the smallest check that exercises the finding, then re-read the affected acceptance criteria and final diff.
134
+
135
+ Do not silently absorb newly discovered work because it is nearby. A user-requested addition can remain in the current task only when the existing same-owner, reversible, low-risk rule applies; otherwise ask through the normal decision route and update the sealed plan before implementation.
@@ -244,12 +244,10 @@ def _get_task_status(trellis_dir: Path, hook_input: dict) -> str:
244
244
  )
245
245
 
246
246
  task_json_path = task_dir / "task.json"
247
- task_data: dict = {}
248
- if task_json_path.is_file():
249
- try:
250
- task_data = json.loads(task_json_path.read_text(encoding="utf-8"))
251
- except (json.JSONDecodeError, PermissionError):
252
- pass # Optional task metadata; fall back to generic status.
247
+ from common.io import read_json_checked
248
+ task_data, _reason = read_json_checked(task_json_path)
249
+ if task_data is None or not isinstance(task_data.get("status"), str) or not task_data["status"].strip():
250
+ return f"Status: TASK_ERROR\nTask: {task_ref}\nNext: Repair the existing task record through its owner before continuing; do not create a replacement task."
253
251
 
254
252
  task_title = task_data.get("title", task_ref)
255
253
  task_status = task_data.get("status", "unknown")
@@ -384,13 +382,15 @@ def _build_compact_current_state(
384
382
  active = _resolve_active_task(trellis_dir, hook_input)
385
383
  if active.task_path:
386
384
  task_dir = _resolve_task_dir(trellis_dir, active.task_path)
387
- status = "unknown"
385
+ status = "task_error"
388
386
  task_json = task_dir / "task.json"
389
387
  if task_json.is_file():
390
388
  try:
391
389
  data = json.loads(task_json.read_text(encoding="utf-8"))
392
390
  if isinstance(data, dict):
393
- status = str(data.get("status") or "unknown")
391
+ value = data.get("status")
392
+ if isinstance(value, str) and value.strip():
393
+ status = value
394
394
  except (json.JSONDecodeError, OSError):
395
395
  pass # Optional task metadata; fall back to generic status.
396
396
  lines.append(f"Current task: {_repo_relative(repo_root, task_dir)}; status={status}.")
@@ -419,19 +419,19 @@ def _build_compact_current_state(
419
419
  return "\n".join(lines)
420
420
 
421
421
 
422
- def _extract_range(content: str, start_header: str, end_header: str) -> str:
422
+ def _extract_range(content: str, start_header: tuple[str, ...], end_header: tuple[str, ...]) -> str:
423
423
  """Extract lines starting at `## start_header` up to (but excluding) `## end_header`."""
424
424
  lines = content.splitlines()
425
425
  start: "int | None" = None
426
426
  end: int = len(lines)
427
- start_match = f"## {start_header}"
428
- end_match = f"## {end_header}"
427
+ start_matches = {f"## {header}" for header in start_header}
428
+ end_matches = {f"## {header}" for header in end_header}
429
429
  for i, line in enumerate(lines):
430
430
  stripped = line.strip()
431
- if start is None and stripped == start_match:
431
+ if start is None and stripped in start_matches:
432
432
  start = i
433
433
  continue
434
- if start is not None and stripped == end_match:
434
+ if start is not None and stripped in end_matches:
435
435
  end = i
436
436
  break
437
437
  if start is None:
@@ -483,7 +483,7 @@ def _build_workflow_toc(workflow_path: Path) -> str:
483
483
  "",
484
484
  ]
485
485
 
486
- phases = _extract_range(content, "Phase Index", "Phase 1: Plan")
486
+ phases = _extract_range(content, ("阶段索引(Phase Index)", "Phase Index"), ("阶段一:规划(Phase 1: Plan)", "Phase 1: Plan"))
487
487
  if phases:
488
488
  out_lines.append(_strip_breadcrumb_tag_blocks(phases).rstrip())
489
489
 
@@ -499,11 +499,15 @@ def main() -> None:
499
499
  hook_input = json.loads(sys.stdin.read())
500
500
  if not isinstance(hook_input, dict):
501
501
  hook_input = {}
502
- project_dir = Path(_normalize_windows_shell_path(hook_input.get("cwd", "."))).resolve()
502
+ raw_cwd = hook_input.get("cwd")
503
+ project_dir = Path(_normalize_windows_shell_path(raw_cwd if isinstance(raw_cwd, str) and raw_cwd else ".")).resolve()
503
504
  except (json.JSONDecodeError, KeyError):
504
505
  hook_input = {}
505
506
  project_dir = Path(".").resolve()
506
507
 
508
+ project_dir = next((candidate for candidate in (project_dir, *project_dir.parents) if (candidate / ".trellis").is_dir()), None)
509
+ if project_dir is None or not (project_dir / ".trellis" / "scripts" / "common" / "active_task.py").is_file():
510
+ return
507
511
  configure_project_encoding(project_dir)
508
512
 
509
513
  trellis_dir = project_dir / ".trellis"