@mindfoldhq/trellis 0.6.8 → 0.6.10
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/dist/cli/index.js +1 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/channel/agent-loader.d.ts +2 -2
- package/dist/commands/channel/agent-loader.d.ts.map +1 -1
- package/dist/commands/channel/agent-loader.js +9 -5
- package/dist/commands/channel/agent-loader.js.map +1 -1
- package/dist/commands/channel/context-loader.d.ts +1 -1
- package/dist/commands/channel/context-loader.d.ts.map +1 -1
- package/dist/commands/channel/context-loader.js +36 -15
- package/dist/commands/channel/context-loader.js.map +1 -1
- package/dist/commands/channel/context-trust.d.ts +31 -0
- package/dist/commands/channel/context-trust.d.ts.map +1 -0
- package/dist/commands/channel/context-trust.js +139 -0
- package/dist/commands/channel/context-trust.js.map +1 -0
- package/dist/commands/channel/spawn.d.ts.map +1 -1
- package/dist/commands/channel/spawn.js +4 -2
- package/dist/commands/channel/spawn.js.map +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +17 -0
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/codex.d.ts +36 -0
- package/dist/configurators/codex.d.ts.map +1 -1
- package/dist/configurators/codex.js +100 -1
- package/dist/configurators/codex.js.map +1 -1
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +5 -0
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +1 -0
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/snow.d.ts +31 -0
- package/dist/configurators/snow.d.ts.map +1 -0
- package/dist/configurators/snow.js +95 -0
- package/dist/configurators/snow.js.map +1 -0
- package/dist/configurators/workflow.d.ts +14 -0
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +37 -1
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/migrations/manifests/0.6.10.json +9 -0
- package/dist/migrations/manifests/0.6.9.json +9 -0
- package/dist/templates/codex/agents/trellis-check.toml +7 -3
- package/dist/templates/codex/agents/trellis-implement.toml +7 -3
- package/dist/templates/codex/agents/trellis-research.toml +13 -6
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +1 -1
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +4 -2
- package/dist/templates/kimi/agents/trellis-research.md +7 -3
- package/dist/templates/omp/extensions/trellis/index.ts.txt +114 -4
- package/dist/templates/opencode/lib/trellis-context.js +263 -43
- package/dist/templates/opencode/plugins/inject-subagent-context.js +89 -35
- package/dist/templates/opencode/plugins/inject-workflow-state.js +90 -5
- package/dist/templates/pi/extensions/trellis/index.ts.txt +270 -22
- package/dist/templates/shared-hooks/inject-subagent-context.py +311 -83
- package/dist/templates/shared-hooks/inject-workflow-state.py +36 -1
- package/dist/templates/snow/SNOW.md +86 -0
- package/dist/templates/snow/agents/trellis-check.md +135 -0
- package/dist/templates/snow/agents/trellis-implement.md +153 -0
- package/dist/templates/snow/agents/trellis-research.md +114 -0
- package/dist/templates/snow/hooks/beforeSubAgentStart.json +15 -0
- package/dist/templates/snow/hooks/onSessionStart.json +15 -0
- package/dist/templates/snow/hooks/onUserMessage.json +15 -0
- package/dist/templates/snow/hooks/write-trellis-context.py +644 -0
- package/dist/templates/snow/index.d.ts +26 -0
- package/dist/templates/snow/index.d.ts.map +1 -0
- package/dist/templates/snow/index.js +36 -0
- package/dist/templates/snow/index.js.map +1 -0
- package/dist/templates/template-utils.d.ts.map +1 -1
- package/dist/templates/template-utils.js +5 -1
- package/dist/templates/template-utils.js.map +1 -1
- package/dist/templates/trellis/config.yaml +46 -0
- package/dist/templates/trellis/gitattributes.txt +9 -0
- package/dist/templates/trellis/index.d.ts +3 -1
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +3 -1
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/add_session.py +94 -28
- package/dist/templates/trellis/scripts/common/active_task.py +9 -2
- package/dist/templates/trellis/scripts/common/config.py +89 -2
- package/dist/templates/trellis/scripts/common/task_context.py +84 -6
- package/dist/templates/trellis/scripts/common/task_store.py +63 -1
- package/dist/templates/trellis/scripts/common/trellis_config.py +2 -1
- package/dist/templates/trellis/scripts/task.py +21 -2
- package/dist/templates/trellis/workflow.md +14 -14
- package/dist/types/ai-tools.d.ts +3 -3
- package/dist/types/ai-tools.d.ts.map +1 -1
- package/dist/types/ai-tools.js +38 -0
- package/dist/types/ai-tools.js.map +1 -1
- 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,
|
|
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
|
-
|
|
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;
|
|
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
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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":"AAAA
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
487
|
-
|
|
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 =
|
|
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,
|
|
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")),
|
|
@@ -608,13 +612,16 @@ def clear_active_task(
|
|
|
608
612
|
platform_input: dict[str, Any] | None = None,
|
|
609
613
|
platform: str | None = None,
|
|
610
614
|
) -> ActiveTask:
|
|
611
|
-
"""Clear the active task by deleting
|
|
615
|
+
"""Clear the active task by deleting its resolved session context file."""
|
|
612
616
|
context_key = resolve_context_key(platform_input, platform)
|
|
613
617
|
if not context_key:
|
|
614
618
|
return ActiveTask(None, "none")
|
|
615
619
|
|
|
616
620
|
previous = resolve_active_task(repo_root, platform_input, platform)
|
|
617
|
-
|
|
621
|
+
if not previous.task_path or not previous.context_key:
|
|
622
|
+
return previous
|
|
623
|
+
|
|
624
|
+
context_path = _context_path(repo_root, previous.context_key)
|
|
618
625
|
if context_path.is_file():
|
|
619
626
|
_remove_file(context_path)
|
|
620
627
|
return previous
|
|
@@ -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
|
|