@mindfoldhq/trellis 0.6.8 → 0.6.9

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 (90) hide show
  1. package/dist/cli/index.js +1 -0
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/commands/channel/agent-loader.d.ts +2 -2
  4. package/dist/commands/channel/agent-loader.d.ts.map +1 -1
  5. package/dist/commands/channel/agent-loader.js +9 -5
  6. package/dist/commands/channel/agent-loader.js.map +1 -1
  7. package/dist/commands/channel/context-loader.d.ts +1 -1
  8. package/dist/commands/channel/context-loader.d.ts.map +1 -1
  9. package/dist/commands/channel/context-loader.js +36 -15
  10. package/dist/commands/channel/context-loader.js.map +1 -1
  11. package/dist/commands/channel/context-trust.d.ts +31 -0
  12. package/dist/commands/channel/context-trust.d.ts.map +1 -0
  13. package/dist/commands/channel/context-trust.js +139 -0
  14. package/dist/commands/channel/context-trust.js.map +1 -0
  15. package/dist/commands/channel/spawn.d.ts.map +1 -1
  16. package/dist/commands/channel/spawn.js +4 -2
  17. package/dist/commands/channel/spawn.js.map +1 -1
  18. package/dist/commands/init.d.ts +1 -0
  19. package/dist/commands/init.d.ts.map +1 -1
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/update.d.ts.map +1 -1
  22. package/dist/commands/update.js +17 -0
  23. package/dist/commands/update.js.map +1 -1
  24. package/dist/configurators/codex.d.ts +36 -0
  25. package/dist/configurators/codex.d.ts.map +1 -1
  26. package/dist/configurators/codex.js +100 -1
  27. package/dist/configurators/codex.js.map +1 -1
  28. package/dist/configurators/index.d.ts.map +1 -1
  29. package/dist/configurators/index.js +5 -0
  30. package/dist/configurators/index.js.map +1 -1
  31. package/dist/configurators/shared.d.ts.map +1 -1
  32. package/dist/configurators/shared.js +1 -0
  33. package/dist/configurators/shared.js.map +1 -1
  34. package/dist/configurators/snow.d.ts +31 -0
  35. package/dist/configurators/snow.d.ts.map +1 -0
  36. package/dist/configurators/snow.js +95 -0
  37. package/dist/configurators/snow.js.map +1 -0
  38. package/dist/configurators/workflow.d.ts +14 -0
  39. package/dist/configurators/workflow.d.ts.map +1 -1
  40. package/dist/configurators/workflow.js +37 -1
  41. package/dist/configurators/workflow.js.map +1 -1
  42. package/dist/migrations/manifests/0.6.9.json +9 -0
  43. package/dist/templates/codex/agents/trellis-check.toml +2 -0
  44. package/dist/templates/codex/agents/trellis-implement.toml +2 -0
  45. package/dist/templates/codex/agents/trellis-research.toml +2 -0
  46. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +1 -1
  47. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +1 -1
  48. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +4 -2
  49. package/dist/templates/kimi/agents/trellis-research.md +7 -3
  50. package/dist/templates/omp/extensions/trellis/index.ts.txt +114 -4
  51. package/dist/templates/opencode/lib/trellis-context.js +263 -43
  52. package/dist/templates/opencode/plugins/inject-subagent-context.js +89 -35
  53. package/dist/templates/opencode/plugins/inject-workflow-state.js +90 -5
  54. package/dist/templates/pi/extensions/trellis/index.ts.txt +270 -22
  55. package/dist/templates/shared-hooks/inject-subagent-context.py +311 -83
  56. package/dist/templates/shared-hooks/inject-workflow-state.py +36 -1
  57. package/dist/templates/snow/SNOW.md +86 -0
  58. package/dist/templates/snow/agents/trellis-check.md +135 -0
  59. package/dist/templates/snow/agents/trellis-implement.md +153 -0
  60. package/dist/templates/snow/agents/trellis-research.md +114 -0
  61. package/dist/templates/snow/hooks/beforeSubAgentStart.json +15 -0
  62. package/dist/templates/snow/hooks/onSessionStart.json +15 -0
  63. package/dist/templates/snow/hooks/onUserMessage.json +15 -0
  64. package/dist/templates/snow/hooks/write-trellis-context.py +644 -0
  65. package/dist/templates/snow/index.d.ts +26 -0
  66. package/dist/templates/snow/index.d.ts.map +1 -0
  67. package/dist/templates/snow/index.js +36 -0
  68. package/dist/templates/snow/index.js.map +1 -0
  69. package/dist/templates/template-utils.d.ts.map +1 -1
  70. package/dist/templates/template-utils.js +5 -1
  71. package/dist/templates/template-utils.js.map +1 -1
  72. package/dist/templates/trellis/config.yaml +46 -0
  73. package/dist/templates/trellis/gitattributes.txt +9 -0
  74. package/dist/templates/trellis/index.d.ts +3 -1
  75. package/dist/templates/trellis/index.d.ts.map +1 -1
  76. package/dist/templates/trellis/index.js +3 -1
  77. package/dist/templates/trellis/index.js.map +1 -1
  78. package/dist/templates/trellis/scripts/add_session.py +94 -28
  79. package/dist/templates/trellis/scripts/common/active_task.py +4 -0
  80. package/dist/templates/trellis/scripts/common/config.py +89 -2
  81. package/dist/templates/trellis/scripts/common/task_context.py +82 -6
  82. package/dist/templates/trellis/scripts/common/task_store.py +63 -1
  83. package/dist/templates/trellis/scripts/common/trellis_config.py +2 -1
  84. package/dist/templates/trellis/scripts/task.py +21 -2
  85. package/dist/templates/trellis/workflow.md +14 -14
  86. package/dist/types/ai-tools.d.ts +3 -3
  87. package/dist/types/ai-tools.d.ts.map +1 -1
  88. package/dist/types/ai-tools.js +38 -0
  89. package/dist/types/ai-tools.js.map +1 -1
  90. package/package.json +2 -2
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Snow CLI template module.
3
+ *
4
+ * Snow CLI is a class-1 platform:
5
+ * - Skills under `.snow/skills/<name>/SKILL.md`
6
+ * - Slash commands under `.snow/commands/trellis-*.json` (prompt type)
7
+ * - Project agents under `.snow/agents/<name>.md` (auto-discovered)
8
+ * - Inject hooks under `.snow/hooks/` (additionalContext + log breadcrumb)
9
+ * - Operator guide `.snow/SNOW.md`
10
+ *
11
+ * hasHooks=true: SessionStart/UserMessage/beforeSubAgentStart inject workflow
12
+ * context, so trellis-start is filtered out of skills/commands (optional
13
+ * recovery still documented in SNOW.md).
14
+ *
15
+ * Class-1: do NOT inject the class-2 "does NOT auto-inject" pull-based prelude.
16
+ * Hook inject (session/user/beforeSubAgentStart) is the primary context path.
17
+ * trellis-research remains standalone (no implement/check-specific prelude).
18
+ */
19
+ import { createTemplateReader, } from "../template-utils.js";
20
+ const { listMdAgents, readTemplate, listFiles } = createTemplateReader(import.meta.url);
21
+ /** Sub-agent definitions (trellis-implement, trellis-check, trellis-research). */
22
+ export function getAllAgents() {
23
+ return listMdAgents();
24
+ }
25
+ /** Inject + breadcrumb hooks (onSessionStart / onUserMessage / beforeSubAgentStart). */
26
+ export function getAllHooks() {
27
+ return listFiles("hooks").map((name) => ({
28
+ targetPath: name,
29
+ content: readTemplate(`hooks/${name}`),
30
+ }));
31
+ }
32
+ /** Operator guide copied to `.snow/SNOW.md`. */
33
+ export function getSnowGuide() {
34
+ return readTemplate("SNOW.md");
35
+ }
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/snow/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,oBAAoB,GAGrB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,oBAAoB,CACpE,MAAM,CAAC,IAAI,CAAC,GAAG,CAChB,CAAC;AAEF,kFAAkF;AAClF,MAAM,UAAU,YAAY;IAC1B,OAAO,YAAY,EAAE,CAAC;AACxB,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,WAAW;IACzB,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvC,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,YAAY,CAAC,SAAS,IAAI,EAAE,CAAC;KACvC,CAAC,CAAC,CAAC;AACN,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,YAAY;IAC1B,OAAO,YAAY,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"template-utils.d.ts","sourceRoot":"","sources":["../../src/templates/template-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACrC,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,aAAa,EAAE,CAAC;IAChD,cAAc,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,aAAa,EAAE,CAAC;IAClD,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC;IACjD,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,CAqD1E"}
1
+ {"version":3,"file":"template-utils.d.ts","sourceRoot":"","sources":["../../src/templates/template-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;IACrC,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,aAAa,EAAE,CAAC;IAChD,cAAc,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,KAAK,aAAa,EAAE,CAAC;IAClD,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC;IACjD,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,CAyD1E"}
@@ -16,7 +16,11 @@ export function createTemplateReader(importMetaUrl) {
16
16
  }
17
17
  function listFiles(dir) {
18
18
  try {
19
- return readdirSync(join(__dirname, dir)).sort();
19
+ // Only regular files — skip dirs like __pycache__ that break readTemplate.
20
+ return readdirSync(join(__dirname, dir), { withFileTypes: true })
21
+ .filter((e) => e.isFile())
22
+ .map((e) => e.name)
23
+ .sort();
20
24
  }
21
25
  catch {
22
26
  return [];
@@ -1 +1 @@
1
- {"version":3,"file":"template-utils.js","sourceRoot":"","sources":["../../src/templates/template-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAqBzC;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,aAAqB;IACxD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;IAExD,SAAS,YAAY,CAAC,YAAoB;QACxC,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,SAAS,SAAS,CAAC,GAAW;QAC5B,IAAI,CAAC;YACH,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,SAAS,YAAY,CAAC,GAAG,GAAG,QAAQ;QAClC,OAAO,SAAS,CAAC,GAAG,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YAC1B,OAAO,EAAE,YAAY,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;SACrC,CAAC,CAAC,CAAC;IACR,CAAC;IAED,4DAA4D;IAC5D,SAAS,cAAc,CAAC,GAAG,GAAG,QAAQ;QACpC,OAAO,SAAS,CAAC,GAAG,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5B,OAAO,EAAE,YAAY,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;SACrC,CAAC,CAAC,CAAC;IACR,CAAC;IAED,oDAAoD;IACpD,SAAS,WAAW,CAAC,QAAQ,GAAG,eAAe;QAC7C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;IACnE,CAAC;IAED,+CAA+C;IAC/C,SAAS,SAAS,CAAC,QAAgB;QACjC,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,OAAO;QACL,YAAY;QACZ,SAAS;QACT,YAAY;QACZ,cAAc;QACd,WAAW;QACX,SAAS;KACV,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"template-utils.js","sourceRoot":"","sources":["../../src/templates/template-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAqBzC;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,aAAqB;IACxD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;IAExD,SAAS,YAAY,CAAC,YAAoB;QACxC,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,SAAS,SAAS,CAAC,GAAW;QAC5B,IAAI,CAAC;YACH,2EAA2E;YAC3E,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;iBAC9D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;iBACzB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBAClB,IAAI,EAAE,CAAC;QACZ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,SAAS,YAAY,CAAC,GAAG,GAAG,QAAQ;QAClC,OAAO,SAAS,CAAC,GAAG,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YAC1B,OAAO,EAAE,YAAY,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;SACrC,CAAC,CAAC,CAAC;IACR,CAAC;IAED,4DAA4D;IAC5D,SAAS,cAAc,CAAC,GAAG,GAAG,QAAQ;QACpC,OAAO,SAAS,CAAC,GAAG,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;aAClC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5B,OAAO,EAAE,YAAY,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC;SACrC,CAAC,CAAC,CAAC;IACR,CAAC;IAED,oDAAoD;IACpD,SAAS,WAAW,CAAC,QAAQ,GAAG,eAAe;QAC7C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;IACnE,CAAC;IAED,+CAA+C;IAC/C,SAAS,SAAS,CAAC,QAAgB;QACjC,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,OAAO;QACL,YAAY;QACZ,SAAS;QACT,YAAY;QACZ,cAAc;QACd,WAAW;QACX,SAAS;KACV,CAAC;AACJ,CAAC"}
@@ -91,10 +91,21 @@ max_journal_lines: 2000
91
91
  # unless explicitly killed or given `--timeout`).
92
92
  # `max_live_workers: 0` disables the spawn-time budget check.
93
93
  #
94
+ # `trusted_context_dirs` extends the `--file`/`--jsonl`/`--agent` containment
95
+ # check beyond the worker cwd — useful when `.trellis/tasks` or
96
+ # `.trellis/workspace` is a symlink to an external directory. Realpaths under
97
+ # any listed dir are accepted in addition to cwd.
98
+ # `auto_trust_trellis_symlinks: false` disables the narrow auto-trust of
99
+ # `.trellis/tasks` / `.trellis/workspace` when either is itself a top-level
100
+ # symlink (auto-trust is on by default).
101
+ #
94
102
  channel:
95
103
  worker_guard:
96
104
  idle_timeout: 5m
97
105
  max_live_workers: 6
106
+ # trusted_context_dirs:
107
+ # - /work/user/trellis_workspace
108
+ # auto_trust_trellis_symlinks: false
98
109
 
99
110
  #-------------------------------------------------------------------------------
100
111
  # Codex (dispatch behavior)
@@ -108,5 +119,40 @@ channel:
108
119
  # main session. "sub-agent" remains a backwards-compatible alias for "auto".
109
120
  # Invalid explicit values safely use inline mode.
110
121
  #
122
+ # In "auto" mode, dispatched sub-agents inherit the main session's model
123
+ # unless you pin one. To use a cheaper/faster model for implement/check/
124
+ # research sub-agent work, edit `model` / `model_reasoning_effort` directly
125
+ # on the generated `.codex/agents/trellis-*.toml` files (see the commented
126
+ # hint lines in those files) — there is no config.yaml knob for this,
127
+ # `trellis update` preserves your edits across regeneration.
128
+ #
111
129
  # codex:
112
130
  # dispatch_mode: auto # or "inline"; legacy alias: "sub-agent"
131
+
132
+ #-------------------------------------------------------------------------------
133
+ # Sub-agent context injection limits
134
+ #-------------------------------------------------------------------------------
135
+ # Caps how much task context (implement.jsonl / check.jsonl referenced files,
136
+ # plus prd.md / design.md / implement.md) gets inlined into a sub-agent's
137
+ # first prompt. Oversized files are truncated with a notice; once the total
138
+ # payload cap is reached, remaining files degrade to index lines (path +
139
+ # reason + size) instead of being inlined.
140
+ #
141
+ # All values are byte counts. `0` disables the corresponding limit.
142
+ #
143
+ # context_injection:
144
+ # max_file_bytes: 32768 # per implement.jsonl / check.jsonl referenced file
145
+ # max_artifact_bytes: 65536 # per task artifact (prd.md / design.md / implement.md)
146
+ # max_total_bytes: 131072 # whole injected payload; overflow degrades to index lines
147
+
148
+ #-------------------------------------------------------------------------------
149
+ # Per-turn prompt injection
150
+ #-------------------------------------------------------------------------------
151
+ # Escape hatch for the per-turn <workflow-state> breadcrumb. When a user
152
+ # prompt contains the skip keyword as a standalone word (case-insensitive,
153
+ # word-boundary match — "no-trellisfoo" does NOT count), the breadcrumb is
154
+ # skipped for that turn only. Does not affect SessionStart or sub-agent
155
+ # context injection.
156
+ #
157
+ # prompt_injection:
158
+ # skip_keyword: "no-trellis" # "" disables the escape hatch entirely
@@ -0,0 +1,9 @@
1
+ # Trellis: append-only developer journals should merge cleanly across
2
+ # parallel sessions/worktrees — each session only appends a new block, so
3
+ # there is nothing to actually conflict on.
4
+ #
5
+ # Do NOT add a rule for workspace/*/index.md here — it is fully regenerated
6
+ # every session, so a real conflict there is expected and safe to resolve by
7
+ # picking either side (task state lives in task.json, not index.md). See
8
+ # .trellis/spec/cli/backend/directory-structure.md for details.
9
+ .trellis/workspace/*/journal-*.md merge=union
@@ -15,7 +15,8 @@
15
15
  * ├── scripts-shell-archive/ # Archived shell scripts (for reference)
16
16
  * ├── workflow.md # Workflow guide
17
17
  * ├── config.yaml # Trellis configuration
18
- * └── gitignore.txt # .gitignore content
18
+ * ├── gitignore.txt # .gitignore content
19
+ * └── gitattributes.txt # project-root .gitattributes content
19
20
  */
20
21
  export declare const scriptsInit: string;
21
22
  export declare const commonInit: string;
@@ -47,6 +48,7 @@ export declare const addSessionScript: string;
47
48
  export declare const workflowMdTemplate: string;
48
49
  export declare const configYamlTemplate: string;
49
50
  export declare const gitignoreTemplate: string;
51
+ export declare const gitattributesTemplate: string;
50
52
  export declare const implementAgentTemplate: string;
51
53
  export declare const checkAgentTemplate: string;
52
54
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAcH,eAAO,MAAM,WAAW,QAAsC,CAAC;AAG/D,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,YAAY,QAA2C,CAAC;AACrE,eAAO,MAAM,QAAQ,QAAuC,CAAC;AAC7D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAChF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,qBAAqB,QAEjC,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AACF,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAG9E,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,UAAU,QAAkC,CAAC;AAC1D,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AAGvE,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAM/D,eAAO,MAAM,sBAAsB,QAAsC,CAAC;AAC1E,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AAElE;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAqCnD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAKlD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAcH,eAAO,MAAM,WAAW,QAAsC,CAAC;AAG/D,eAAO,MAAM,UAAU,QAA6C,CAAC;AACrE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAC9E,eAAO,MAAM,YAAY,QAA2C,CAAC;AACrE,eAAO,MAAM,QAAQ,QAAuC,CAAC;AAC7D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,SAAS,QAAwC,CAAC;AAC/D,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,WAAW,QAA0C,CAAC;AACnE,eAAO,MAAM,iBAAiB,QAAiD,CAAC;AAChF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,oBAAoB,QAEhC,CAAC;AACF,eAAO,MAAM,qBAAqB,QAEjC,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AACF,eAAO,MAAM,mBAAmB,QAE/B,CAAC;AACF,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAG9E,eAAO,MAAM,kBAAkB,QAA2C,CAAC;AAC3E,eAAO,MAAM,mBAAmB,QAA4C,CAAC;AAC7E,eAAO,MAAM,UAAU,QAAkC,CAAC;AAC1D,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AACvE,eAAO,MAAM,gBAAgB,QAAyC,CAAC;AAGvE,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,eAAO,MAAM,iBAAiB,QAAgC,CAAC;AAC/D,eAAO,MAAM,qBAAqB,QAAoC,CAAC;AAMvE,eAAO,MAAM,sBAAsB,QAAsC,CAAC;AAC1E,eAAO,MAAM,kBAAkB,QAAkC,CAAC;AAElE;;GAEG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAqCnD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAKlD"}
@@ -15,7 +15,8 @@
15
15
  * ├── scripts-shell-archive/ # Archived shell scripts (for reference)
16
16
  * ├── workflow.md # Workflow guide
17
17
  * ├── config.yaml # Trellis configuration
18
- * └── gitignore.txt # .gitignore content
18
+ * ├── gitignore.txt # .gitignore content
19
+ * └── gitattributes.txt # project-root .gitattributes content
19
20
  */
20
21
  import { readFileSync } from "node:fs";
21
22
  import { dirname, join } from "node:path";
@@ -59,6 +60,7 @@ export const addSessionScript = readTemplate("scripts/add_session.py");
59
60
  export const workflowMdTemplate = readTemplate("workflow.md");
60
61
  export const configYamlTemplate = readTemplate("config.yaml");
61
62
  export const gitignoreTemplate = readTemplate("gitignore.txt");
63
+ export const gitattributesTemplate = readTemplate("gitattributes.txt");
62
64
  // Channel runtime agent definitions (loaded by
63
65
  // `packages/cli/src/commands/channel/agent-loader.ts` from `.trellis/agents/`).
64
66
  // These are platform-agnostic Trellis runtime files dispatched at `trellis init`
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/trellis/index.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,9 @@ Usage:
12
12
  <session content here>
13
13
  EOF
14
14
 
15
+ # Structured content (repeatable; a section with no bullets is omitted):
16
+ python3 add_session.py --title "Title" --change "Did X" --test "Ran Y" --next-step "Do Z"
17
+
15
18
  Branch resolution order:
16
19
  1. --branch CLI arg (explicit)
17
20
  2. task.json branch field (from active task, if still exists)
@@ -38,6 +41,7 @@ from common.paths import (
38
41
  )
39
42
  from common.developer import ensure_developer
40
43
  from common.git import run_git
44
+ from common.log import Colors, colored
41
45
  from common.safe_commit import (
42
46
  print_gitignore_warning,
43
47
  safe_git_add,
@@ -56,12 +60,6 @@ from common.config import (
56
60
  )
57
61
 
58
62
 
59
- DEFAULT_MAIN_CHANGES = (
60
- "- Detailed change bullets were not supplied; see the summary above."
61
- )
62
- DEFAULT_TESTING = "- Validation was not recorded for this session."
63
-
64
-
65
63
  # =============================================================================
66
64
  # Helper Functions
67
65
  # =============================================================================
@@ -183,6 +181,49 @@ def resolve_session_branch(
183
181
  return None
184
182
 
185
183
 
184
+ def is_git_worktree(repo_root: Path) -> bool:
185
+ """Return True when repo_root is a linked worktree (not the main working tree).
186
+
187
+ Standard test: `git rev-parse --git-dir` (per-worktree) differs from
188
+ `git rev-parse --git-common-dir` (shared across all worktrees) once both
189
+ are resolved to absolute paths. In the main working tree these are the
190
+ same directory.
191
+ """
192
+ rc_dir, git_dir, _ = run_git(["rev-parse", "--git-dir"], cwd=repo_root)
193
+ rc_common, git_common_dir, _ = run_git(
194
+ ["rev-parse", "--git-common-dir"], cwd=repo_root
195
+ )
196
+ if rc_dir != 0 or rc_common != 0:
197
+ return False
198
+
199
+ git_dir_path = (repo_root / git_dir.strip()).resolve()
200
+ git_common_dir_path = (repo_root / git_common_dir.strip()).resolve()
201
+ return git_dir_path != git_common_dir_path
202
+
203
+
204
+ def warn_if_parallel_worktree(repo_root: Path) -> None:
205
+ """Non-blocking note: index.md conflicts across parallel worktrees/branches
206
+ are expected and safe. Only fires when running in a linked git worktree
207
+ (not the main tree) with `session_auto_commit` enabled (#415 quick-fix tier).
208
+ """
209
+ if not get_session_auto_commit(repo_root):
210
+ return
211
+ if not is_git_worktree(repo_root):
212
+ return
213
+ print(
214
+ colored(
215
+ "[NOTE] Running in a git worktree with session_auto_commit enabled: "
216
+ "journal-*.md files auto-merge via .gitattributes, but index.md "
217
+ "conflicts across parallel worktrees/branches are expected and safe "
218
+ "to resolve by picking either side (task state lives in task.json, "
219
+ "not index.md). See .trellis/spec/cli/backend/directory-structure.md "
220
+ '("Workspace Journal Merge Behavior").',
221
+ Colors.YELLOW,
222
+ ),
223
+ file=sys.stderr,
224
+ )
225
+
226
+
186
227
  def create_new_journal_file(
187
228
  dev_dir: Path, num: int, developer: str, today: str, max_lines: int = 2000,
188
229
  ) -> Path:
@@ -202,16 +243,39 @@ def create_new_journal_file(
202
243
  return new_file
203
244
 
204
245
 
246
+ def _render_bullet_section(header: str, items: list[str], bullet_prefix: str = "- ") -> str:
247
+ """Render a Markdown section as bullets, or "" when there is no content.
248
+
249
+ A section with zero provided values is omitted entirely from the
250
+ rendered entry rather than falling back to a placeholder string.
251
+ """
252
+ if not items:
253
+ return ""
254
+ bullets = "\n".join(f"{bullet_prefix}{item}" for item in items)
255
+ return f"\n\n### {header}\n\n{bullets}"
256
+
257
+
258
+ def _render_main_changes(changes: list[str], extra_content: str | None) -> str:
259
+ """Render the Main Changes section from --change bullets or freeform content."""
260
+ if changes:
261
+ return _render_bullet_section("Main Changes", changes)
262
+ if extra_content:
263
+ return f"\n\n### Main Changes\n\n{extra_content}"
264
+ return ""
265
+
266
+
205
267
  def generate_session_content(
206
268
  session_num: int,
207
269
  title: str,
208
270
  commit: str,
209
271
  summary: str,
210
- extra_content: str,
211
272
  today: str,
212
273
  package: str | None = None,
213
274
  branch: str | None = None,
214
- testing_content: str = DEFAULT_TESTING,
275
+ changes: list[str] | None = None,
276
+ extra_content: str | None = None,
277
+ tests: list[str] | None = None,
278
+ next_steps: list[str] | None = None,
215
279
  ) -> str:
216
280
  """Generate session content."""
217
281
  if commit and commit != "-":
@@ -226,6 +290,10 @@ def generate_session_content(
226
290
  package_line = f"\n**Package**: {package}" if package else ""
227
291
  branch_line = f"\n**Branch**: `{branch}`" if branch else ""
228
292
 
293
+ main_changes_section = _render_main_changes(changes or [], extra_content)
294
+ testing_section = _render_bullet_section("Testing", tests or [], bullet_prefix="- [OK] ")
295
+ next_steps_section = _render_bullet_section("Next Steps", next_steps or [])
296
+
229
297
  return f"""
230
298
 
231
299
  ## Session {session_num}: {title}
@@ -235,27 +303,15 @@ def generate_session_content(
235
303
 
236
304
  ### Summary
237
305
 
238
- {summary}
239
-
240
- ### Main Changes
241
-
242
- {extra_content}
306
+ {summary}{main_changes_section}
243
307
 
244
308
  ### Git Commits
245
309
 
246
- {commit_table}
247
-
248
- ### Testing
249
-
250
- {testing_content}
310
+ {commit_table}{testing_section}
251
311
 
252
312
  ### Status
253
313
 
254
- [OK] **Completed**
255
-
256
- ### Next Steps
257
-
258
- - None - task complete
314
+ [OK] **Completed**{next_steps_section}
259
315
  """
260
316
 
261
317
 
@@ -454,13 +510,17 @@ def add_session(
454
510
  title: str,
455
511
  commit: str = "-",
456
512
  summary: str = "Session summary was not supplied.",
457
- extra_content: str = DEFAULT_MAIN_CHANGES,
513
+ changes: list[str] | None = None,
514
+ extra_content: str | None = None,
515
+ tests: list[str] | None = None,
516
+ next_steps: list[str] | None = None,
458
517
  auto_commit: bool = True,
459
518
  package: str | None = None,
460
519
  branch: str | None = None,
461
520
  ) -> int:
462
521
  """Add a new session."""
463
522
  repo_root = get_repo_root()
523
+ warn_if_parallel_worktree(repo_root)
464
524
  ensure_developer(repo_root)
465
525
 
466
526
  developer = get_developer(repo_root)
@@ -483,8 +543,9 @@ def add_session(
483
543
  new_session = current_session + 1
484
544
 
485
545
  session_content = generate_session_content(
486
- new_session, title, commit, summary, extra_content, today, package,
487
- branch,
546
+ new_session, title, commit, summary, today, package, branch,
547
+ changes=changes, extra_content=extra_content, tests=tests,
548
+ next_steps=next_steps,
488
549
  )
489
550
  content_lines = len(session_content.splitlines())
490
551
 
@@ -565,6 +626,9 @@ def main() -> int:
565
626
  parser.add_argument("--content-file", help="Path to file with detailed content")
566
627
  parser.add_argument("--package", help="Package name tag (e.g., cli, docs-site)")
567
628
  parser.add_argument("--branch", help="Branch name (auto-detected if omitted)")
629
+ parser.add_argument("--change", action="append", help="Main Changes bullet (repeatable)")
630
+ parser.add_argument("--test", action="append", help="Testing bullet (repeatable)")
631
+ parser.add_argument("--next-step", action="append", help="Next Steps bullet (repeatable)")
568
632
  parser.add_argument("--no-commit", action="store_true",
569
633
  help="Skip auto-commit of workspace changes")
570
634
  parser.add_argument("--stdin", action="store_true",
@@ -572,7 +636,7 @@ def main() -> int:
572
636
 
573
637
  args = parser.parse_args()
574
638
 
575
- extra_content = DEFAULT_MAIN_CHANGES
639
+ extra_content: str | None = None
576
640
  if args.content_file:
577
641
  content_path = Path(args.content_file)
578
642
  if content_path.is_file():
@@ -604,7 +668,9 @@ def main() -> int:
604
668
  branch = resolve_session_branch(repo_root, args.branch, task_data)
605
669
 
606
670
  return add_session(
607
- args.title, args.commit, args.summary, extra_content,
671
+ args.title, args.commit, args.summary,
672
+ changes=args.change, extra_content=extra_content, tests=args.test,
673
+ next_steps=args.next_step,
608
674
  auto_commit=not args.no_commit,
609
675
  package=package,
610
676
  branch=branch,
@@ -47,6 +47,7 @@ _KNOWN_PLATFORMS = {
47
47
  "grok",
48
48
  "kimi",
49
49
  "zcode",
50
+ "snow",
50
51
  }
51
52
 
52
53
  _ENV_SESSION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
@@ -67,6 +68,9 @@ _ENV_SESSION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
67
68
  # only fires when the resolver already detected "zcode" — no collision with
68
69
  # the claude entry above.
69
70
  ("zcode", ("CLAUDE_SESSION_ID",)),
71
+ # Snow CLI exports SNOW_SESSION_ID into hook/terminal/sub-agent children.
72
+ # TRELLIS_CONTEXT_ID remains the preferred override when present.
73
+ ("snow", ("SNOW_SESSION_ID",)),
70
74
  )
71
75
  _ENV_CONVERSATION_KEYS: tuple[tuple[str, tuple[str, ...]], ...] = (
72
76
  ("cursor", ("CURSOR_CONVERSATION_ID", "CURSOR_CONVERSATIONID")),
@@ -117,11 +117,12 @@ def _parse_yaml_block(
117
117
  key, _, value = stripped.partition(":")
118
118
  key = key.strip()
119
119
  value = _strip_inline_comment(value).strip()
120
+ was_quoted = len(value) >= 2 and value[0] == value[-1] and value[0] in ('"', "'")
120
121
  value = _unquote(value)
121
122
  current_list = None
122
123
 
123
- if value:
124
- # key: value
124
+ if value or was_quoted:
125
+ # key: value (an explicit quoted "" is a value, not "no value")
125
126
  target[key] = value
126
127
  i += 1
127
128
  else:
@@ -280,6 +281,92 @@ def get_codex_dispatch_mode(repo_root: Path | None = None) -> str:
280
281
  return "inline"
281
282
 
282
283
 
284
+ DEFAULT_CONTEXT_INJECTION_MAX_FILE_BYTES = 32768
285
+ DEFAULT_CONTEXT_INJECTION_MAX_ARTIFACT_BYTES = 65536
286
+ DEFAULT_CONTEXT_INJECTION_MAX_TOTAL_BYTES = 131072
287
+
288
+
289
+ def get_context_injection_limits(repo_root: Path | None = None) -> dict[str, int]:
290
+ """Return sub-agent context injection byte limits.
291
+
292
+ Reads the ``context_injection:`` section of ``.trellis/config.yaml``:
293
+
294
+ context_injection:
295
+ max_file_bytes: 32768
296
+ max_artifact_bytes: 65536
297
+ max_total_bytes: 131072
298
+
299
+ ``0`` disables the corresponding limit. Missing keys use their default;
300
+ invalid (non-int or negative) values fall back to the default for that
301
+ key with a stderr warning.
302
+ """
303
+ defaults = {
304
+ "max_file_bytes": DEFAULT_CONTEXT_INJECTION_MAX_FILE_BYTES,
305
+ "max_artifact_bytes": DEFAULT_CONTEXT_INJECTION_MAX_ARTIFACT_BYTES,
306
+ "max_total_bytes": DEFAULT_CONTEXT_INJECTION_MAX_TOTAL_BYTES,
307
+ }
308
+
309
+ config = _load_config(repo_root)
310
+ section = config.get("context_injection")
311
+ if not isinstance(section, dict):
312
+ return defaults
313
+
314
+ result = dict(defaults)
315
+ for key, default_value in defaults.items():
316
+ if key not in section:
317
+ continue
318
+ raw = section[key]
319
+ try:
320
+ value = int(raw)
321
+ except (TypeError, ValueError):
322
+ print(
323
+ f"[WARN] invalid context_injection.{key} value: {raw!r}; "
324
+ f"using default {default_value}",
325
+ file=sys.stderr,
326
+ )
327
+ continue
328
+ if value < 0:
329
+ print(
330
+ f"[WARN] invalid context_injection.{key} value: {raw!r}; "
331
+ f"using default {default_value}",
332
+ file=sys.stderr,
333
+ )
334
+ continue
335
+ result[key] = value
336
+
337
+ return result
338
+
339
+
340
+ DEFAULT_PROMPT_INJECTION_SKIP_KEYWORD = "no-trellis"
341
+
342
+
343
+ def get_prompt_injection_config(repo_root: Path | None = None) -> dict[str, str]:
344
+ """Return per-turn prompt injection config.
345
+
346
+ Reads the ``prompt_injection:`` section of ``.trellis/config.yaml``:
347
+
348
+ prompt_injection:
349
+ skip_keyword: "no-trellis" # "" disables the escape hatch entirely
350
+
351
+ ``skip_keyword`` is the word-boundary, case-insensitive keyword that, when
352
+ present in the user's prompt, makes the per-turn workflow-state injection
353
+ emit nothing for that turn. Defaults to ``"no-trellis"``. A non-string
354
+ value falls back to the default.
355
+ """
356
+ defaults = {"skip_keyword": DEFAULT_PROMPT_INJECTION_SKIP_KEYWORD}
357
+
358
+ config = _load_config(repo_root)
359
+ section = config.get("prompt_injection")
360
+ if not isinstance(section, dict):
361
+ return defaults
362
+
363
+ result = dict(defaults)
364
+ raw = section.get("skip_keyword", DEFAULT_PROMPT_INJECTION_SKIP_KEYWORD)
365
+ if isinstance(raw, str):
366
+ result["skip_keyword"] = raw
367
+ return result
368
+
369
+
283
370
  def get_hooks(event: str, repo_root: Path | None = None) -> list[str]:
284
371
  """Get hook commands for a lifecycle event.
285
372