@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.
- 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.9.json +9 -0
- package/dist/templates/codex/agents/trellis-check.toml +2 -0
- package/dist/templates/codex/agents/trellis-implement.toml +2 -0
- package/dist/templates/codex/agents/trellis-research.toml +2 -0
- 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 +4 -0
- package/dist/templates/trellis/scripts/common/config.py +89 -2
- package/dist/templates/trellis/scripts/common/task_context.py +82 -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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/configurators/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,2DAA2D;AAC3D,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GACb,MAAM,+BAA+B,CAAC;AAEvC,4BAA4B;AAC5B,OAAO,EACL,yBAAyB;AACzB,gCAAgC;AAChC,mBAAmB,EACnB,gCAAgC,EAChC,gCAAgC,EAChC,+BAA+B,EAC/B,+BAA+B,EAC/B,2BAA2B;AAC3B,iCAAiC;AACjC,oBAAoB,EACpB,iCAAiC,EACjC,yBAAyB,EACzB,6BAA6B,EAC7B,kCAAkC,EAClC,gCAAgC,EAChC,8BAA8B;AAC9B,mBAAmB;AACnB,kBAAkB,EAClB,oCAAoC,EACpC,mCAAmC,GACpC,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,EACL,eAAe,GAGhB,MAAM,8BAA8B,CAAC;AA6BtC;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAW,EACX,OAAyB;IAEzB,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,WAAW,CAAC;IACxD,MAAM,iBAAiB,GAAG,OAAO,EAAE,iBAAiB,IAAI,KAAK,CAAC;IAC9D,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAC;IACnC,MAAM,kBAAkB,GAAG,OAAO,EAAE,kBAAkB,CAAC;IACvD,MAAM,UAAU,GAAG,OAAO,EAAE,kBAAkB,IAAI,kBAAkB,CAAC;IAErE,iCAAiC;IACjC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE9C,yCAAyC;IACzC,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE;QAC7D,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IAEH,6EAA6E;IAC7E,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,mBAAmB,CAAC,EACzC,4BAA4B,CAAC,UAAU,CAAC,CACzC,CAAC;IAEF,iCAAiC;IACjC,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC,EAChD,iBAAiB,CAClB,CAAC;IAEF,kCAAkC;IAClC,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,EACjD,kBAAkB,CACnB,CAAC;IAEF,0EAA0E;IAC1E,2EAA2E;IAC3E,wEAAwE;IACxE,4EAA4E;IAC5E,4EAA4E;IAC5E,eAAe;IACf,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,YAAY,EAAE,EAAE,CAAC;QAClD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,kCAAkC;IAClC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3C,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,EAC3C,4BAA4B,CAAC,yBAAyB,CAAC,CACxD,CAAC;IAEF,0BAA0B;IAC1B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAEvC,8CAA8C;IAC9C,wEAAwE;IACxE,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,qDAAqD;QACrD,MAAM,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IAC5E,CAAC;SAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC9B,uEAAuE;QACvE,MAAM,mBAAmB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAClD,SAAS,CAAC,UAAU,CAAC,CAAC;IACtB,MAAM,IAAI,GAAoB;QAC5B,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,mBAAmB,EAAE;QAClD;YACE,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,gCAAgC;SAC1C;QACD;YACE,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,gCAAgC;SAC1C;QACD,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,+BAA+B,EAAE;QAC3E,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,+BAA+B,EAAE;QAC3E,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,2BAA2B,EAAE;KACpE,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACpD,SAAS,CAAC,WAAW,CAAC,CAAC;IACvB,MAAM,IAAI,GAAoB;QAC5B,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,oBAAoB,EAAE;QACnD;YACE,IAAI,EAAE,wBAAwB;YAC9B,OAAO,EAAE,iCAAiC;SAC3C;QACD,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,yBAAyB,EAAE;QAC9D,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,6BAA6B,EAAE;QACtE;YACE,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,kCAAkC;SAC5C;QACD;YACE,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,gCAAgC;SAC1C;QACD,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,8BAA8B,EAAE;KACzE,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB,CAC7B,QAAgB,EAChB,WAAwB;IAExB,IAAI,WAAW,KAAK,UAAU,EAAE,CAAC;QAC/B,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,GAAW,EACX,WAAwB,EACxB,QAA4B,EAC5B,kBAAgC;IAEhC,+BAA+B;IAC/B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtC,6CAA6C;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,SAAS,CAAC,CAAC;IACzD,SAAS,CAAC,SAAS,CAAC,CAAC;IACrB,MAAM,UAAU,GAAoB;QAClC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,kBAAkB,EAAE;QACjD;YACE,IAAI,EAAE,+BAA+B;YACrC,OAAO,EAAE,oCAAoC;SAC9C;QACD;YACE,IAAI,EAAE,8BAA8B;YACpC,OAAO,EAAE,mCAAmC;SAC7C;KACF,CAAC;IACF,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,sDAAsD;QACtD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,kBAAkB,EAAE,GAAG,CAAC,OAAO,CAAC;gBAAE,SAAS;YAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;YAC/D,SAAS,CAAC,WAAW,CAAC,CAAC;YACvB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;YAChE,MAAM,gBAAgB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;SAAM,CAAC;QACN,mBAAmB;QACnB,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC;IAClE,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/configurators/workflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.6.9",
|
|
3
|
+
"description": "Snow CLI platform, sub-agent context injection caps (Python/Pi/OpenCode) with binary-file handling, no-trellis skip keyword, durable Codex sub-agent model config, channel trusted context dirs, and journal merge conflict relief.",
|
|
4
|
+
"breaking": false,
|
|
5
|
+
"recommendMigrate": false,
|
|
6
|
+
"changelog": "**Enhancements:**\n- feat(cli): add Snow CLI as class-1 Trellis platform — `trellis init --snow` (#443)\n- feat(hooks): cap sub-agent context injection with configurable limits across the Python hook, Pi extension, and OpenCode plugin — `context_injection` in config.yaml (#441, #456)\n- fix(cli): sub-agent context injection now detects binary referenced files and emits a reference-only notice instead of corrupting output (#471)\n- feat(hooks): `no-trellis` keyword in a prompt mutes per-turn workflow-state injection for that turn — `prompt_injection.skip_keyword` in config.yaml (#427)\n- feat(codex): user-set `model` / `model_reasoning_effort` in `.codex/agents/trellis-*.toml` now survive `trellis update` regeneration; templates ship commented hints (#459)\n- feat(channel): `channel.trusted_context_dirs` config plus narrow auto-trust of symlinked `.trellis/tasks` / `.trellis/workspace` for context loading (#414)\n- feat(scripts): `add_session.py` gains repeatable `--change` / `--test` / `--next-step` flags; empty sections are omitted instead of rendering placeholder text (#394)\n- feat(scripts): `task.py list` renders a dangling parent reference flat instead of hiding the task (#402)\n- feat(scripts): `task.py create --meta key=value` (repeatable) and `task.py set-meta` expose the task.json `meta` field\n\n**Bug Fixes:**\n- fix(kimi): `trellis-research` now persists findings through the writable built-in `coder` sub-agent instead of losing them (#457)\n- feat(workspace): `.gitattributes` ships `journal-*.md merge=union` so parallel-worktree session merges no longer conflict on append-only journal content; `index.md` conflicts are documented as expected and safe to resolve by picking either side (#415)",
|
|
7
|
+
"migrations": [],
|
|
8
|
+
"notes": "Pi Agent users on 0.6.8: skills already moved to .agents/skills/. Codex users: agent model config now persists across update — edit .codex/agents/trellis-*.toml directly."
|
|
9
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
name = "trellis-check"
|
|
2
2
|
description = "Workspace-write Trellis reviewer that self-fixes spec drift, lint/type-check failures, and missing tests."
|
|
3
3
|
sandbox_mode = "workspace-write"
|
|
4
|
+
# model = "gpt-5.6-terra"
|
|
5
|
+
# model_reasoning_effort = "high"
|
|
4
6
|
|
|
5
7
|
developer_instructions = """
|
|
6
8
|
You are running as the `trellis-check` sub-agent. The main session has dispatched you to review and self-fix.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
name = "trellis-implement"
|
|
2
2
|
description = "Workspace-write Trellis implementer that follows specs and keeps generated templates in sync."
|
|
3
3
|
sandbox_mode = "workspace-write"
|
|
4
|
+
# model = "gpt-5.6-terra"
|
|
5
|
+
# model_reasoning_effort = "high"
|
|
4
6
|
|
|
5
7
|
developer_instructions = """
|
|
6
8
|
You are running as the `trellis-implement` sub-agent. The main session has dispatched you to do the work.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
name = "trellis-research"
|
|
2
2
|
description = "Trellis researcher for specs, code patterns, and affected files. Writes findings into {TASK_DIR}/research/ — read-only elsewhere."
|
|
3
3
|
sandbox_mode = "workspace-write"
|
|
4
|
+
# model = "gpt-5.6-terra"
|
|
5
|
+
# model_reasoning_effort = "high"
|
|
4
6
|
|
|
5
7
|
developer_instructions = """
|
|
6
8
|
You are the Trellis researcher agent.
|
package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md
CHANGED
|
@@ -34,7 +34,7 @@ Agent files should not become generic chat prompts. They should define input sou
|
|
|
34
34
|
| Pi Agent | `.pi/agents/trellis-*.md` |
|
|
35
35
|
| Reasonix | `.reasonix/skills/trellis-*/SKILL.md` (subagent frontmatter) |
|
|
36
36
|
| ZCode | `.zcode/agents/trellis-*.md` |
|
|
37
|
-
| Kimi Code | `.kimi-code/skills/trellis-*/SKILL.md` (agent prompts as skills, dispatched to the built-in coder
|
|
37
|
+
| Kimi Code | `.kimi-code/skills/trellis-*/SKILL.md` (agent prompts as skills, dispatched to the built-in `coder`; research needs its file-editing tools to persist findings) |
|
|
38
38
|
|
|
39
39
|
GitHub Copilot agent/prompt support is provided by a combination of directories such as `.github/agents/`, `.github/prompts/`, and `.github/skills/`; inspect the files actually generated in the user project.
|
|
40
40
|
|
package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md
CHANGED
|
@@ -5,7 +5,7 @@ Trellis connects the same local architecture to different AI tools. `.trellis/`
|
|
|
5
5
|
When a local AI modifies Trellis, it should distinguish two file categories first:
|
|
6
6
|
|
|
7
7
|
- **Shared files**: `.trellis/workflow.md`, `.trellis/tasks/`, `.trellis/spec/`, `.trellis/scripts/`.
|
|
8
|
-
- **Platform files**: `.claude/`, `.codex/`, `.cursor/`, `.opencode/`, `.kiro/`, `.gemini/`, `.qoder/`, `.codebuddy/`, `.github/`, `.factory/`, `.pi/`, `.trae/`, `.kilocode/`, `.agent/`, `.devin/`, `.reasonix/`, `.zcode/`, `.kimi-code/`, and similar directories.
|
|
8
|
+
- **Platform files**: `.claude/`, `.snow/`, `.codex/`, `.cursor/`, `.opencode/`, `.kiro/`, `.gemini/`, `.qoder/`, `.codebuddy/`, `.github/`, `.factory/`, `.pi/`, `.trae/`, `.kilocode/`, `.agent/`, `.devin/`, `.reasonix/`, `.zcode/`, `.kimi-code/`, and similar directories.
|
|
9
9
|
|
|
10
10
|
Platform files do not store business state. They let the corresponding AI tool read Trellis state, call Trellis scripts, and load Trellis skills/agents/hooks.
|
|
11
11
|
|
package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md
CHANGED
|
@@ -24,7 +24,8 @@ This page lists common Trellis file locations in a user project by platform. Whe
|
|
|
24
24
|
| Reasonix | `--reasonix` | `.reasonix/` | `.reasonix/skills/` | None — sub-agents are skills with `runAs: subagent` frontmatter | None |
|
|
25
25
|
| ZCode | `--zcode` | `.zcode/` | `.zcode/skills/` | `.zcode/agents/` | `.zcode/hooks/` + `.zcode/config.json` (SessionStart + UserPromptSubmit + PreToolUse Agent/Task); sub-agents use hook-injected context |
|
|
26
26
|
| Grok Build | `--grok` | `.grok/` | `.grok/skills/` | `.grok/agents/` | pull-based prelude (no hooks; flat `.grok/commands/trellis-*.md`) |
|
|
27
|
-
| Kimi Code | `--kimi` | `.kimi-code/` | `.agents/skills/` (shared) + `.kimi-code/skills/` | None — agent prompts are skills under `.kimi-code/skills/`
|
|
27
|
+
| Kimi Code | `--kimi` | `.kimi-code/` | `.agents/skills/` (shared) + `.kimi-code/skills/` | None — agent prompts are skills under `.kimi-code/skills/` and dispatch to the built-in `coder` | None (pull-based prelude; no project hooks/settings) |
|
|
28
|
+
| Snow CLI | `--snow` | `.snow/` | `.snow/skills/` | `.snow/agents/` (auto-discovered; primary path) | class-1: auto inject + project agents + `beforeSubAgentStart` (`.snow/hooks/` `session`/`user`/`subagent` modes -> `additionalContext` JSON); no legacy sub-agent JSON; commands `.snow/commands/trellis-*.json` |
|
|
28
29
|
|
|
29
30
|
## Capability Groups
|
|
30
31
|
|
|
@@ -47,7 +48,8 @@ These platforms usually have `trellis-research`, `trellis-implement`, and `trell
|
|
|
47
48
|
- Reasonix (delivered as skills with `runAs: subagent` under `.reasonix/skills/`, not as a separate `agents/` directory)
|
|
48
49
|
- ZCode
|
|
49
50
|
- Grok Build (`.grok/agents/`; dispatch via `spawn_subagent` with `subagent_type`)
|
|
50
|
-
- Kimi Code (delivered as skills under `.kimi-code/skills/`; dispatched to the built-in coder
|
|
51
|
+
- Kimi Code (delivered as skills under `.kimi-code/skills/`; dispatched to the built-in `coder`, including research because it must persist files)
|
|
52
|
+
- Snow CLI (`.snow/agents/`; auto-discovered project agents + class-1 hooks)
|
|
51
53
|
|
|
52
54
|
When changing implementation/check/research behavior, look for the corresponding platform agent files first.
|
|
53
55
|
|
|
@@ -4,8 +4,8 @@ description: |
|
|
|
4
4
|
Code and tech search expert for Trellis. Finds files, patterns, and tech
|
|
5
5
|
solutions, and PERSISTS every finding to the current task's research/
|
|
6
6
|
directory. No code modifications outside that directory. On Kimi Code the
|
|
7
|
-
main session dispatches the built-in
|
|
8
|
-
|
|
7
|
+
main session dispatches the built-in coder sub-agent with these instructions
|
|
8
|
+
because it is the only built-in sub-agent with file-editing tools.
|
|
9
9
|
---
|
|
10
10
|
# Research Agent
|
|
11
11
|
|
|
@@ -19,7 +19,11 @@ Conversations get compacted; files don't. Every research output MUST end up as a
|
|
|
19
19
|
|
|
20
20
|
## Dispatch note (main session)
|
|
21
21
|
|
|
22
|
-
Kimi Code has no project-level custom sub-agent definitions — only the built-in `coder` / `explore` / `plan` sub-agents. The main session dispatches the built-in `
|
|
22
|
+
Kimi Code has no project-level custom sub-agent definitions — only the built-in `coder` / `explore` / `plan` sub-agents. The built-in `explore` sub-agent is read-only, so it cannot satisfy this agent's persistence contract. The main session dispatches the built-in `coder` sub-agent via the Agent tool with a prompt that:
|
|
23
|
+
|
|
24
|
+
1. Starts with `Active task: <path from task.py current>`
|
|
25
|
+
2. Includes this skill's instructions (`.kimi-code/skills/trellis-research/SKILL.md`)
|
|
26
|
+
3. States that the spawned agent is already `trellis-research` and may write only under the active task's `research/` directory
|
|
23
27
|
|
|
24
28
|
---
|
|
25
29
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
|
|
2
|
-
import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
2
|
+
import { existsSync, lstatSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
3
3
|
import { join, dirname, isAbsolute, relative, resolve } from "node:path";
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
@@ -58,11 +58,118 @@ function isInsideRoot(root: string, candidate: string): boolean {
|
|
|
58
58
|
return rel === "" || (rel !== ".." && !rel.startsWith("../") && !rel.startsWith("..\\") && !isAbsolute(rel));
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Trusted context roots (mirrors packages/cli/src/commands/channel/context-trust.ts;
|
|
63
|
+
// standalone copy since templates don't import from the CLI package).
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
const AUTO_TRUST_ENTRIES = ["tasks", "workspace"];
|
|
67
|
+
|
|
68
|
+
function stripTrustValue(s: string): string {
|
|
69
|
+
return s.trim().replace(/\s*#.*$/, "").trim().replace(/^['"]|['"]$/g, "");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function parseChannelTrustSection(content: string): { trustedDirs: string[]; autoTrustSymlinks?: boolean } {
|
|
73
|
+
const lines = content.split("\n");
|
|
74
|
+
const trustedDirs: string[] = [];
|
|
75
|
+
let autoTrustSymlinks: boolean | undefined;
|
|
76
|
+
let inChannel = false;
|
|
77
|
+
let inList = false;
|
|
78
|
+
|
|
79
|
+
for (const raw of lines) {
|
|
80
|
+
const line = raw.replace(/\r$/, "");
|
|
81
|
+
const trimmed = line.trimEnd();
|
|
82
|
+
if (trimmed.trim().startsWith("#")) continue;
|
|
83
|
+
|
|
84
|
+
if (/^channel:\s*$/.test(trimmed)) {
|
|
85
|
+
inChannel = true;
|
|
86
|
+
inList = false;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (!inChannel) continue;
|
|
90
|
+
|
|
91
|
+
if (trimmed.trim() !== "" && /^\S/.test(line)) {
|
|
92
|
+
inChannel = false;
|
|
93
|
+
inList = false;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (trimmed.trim() === "") continue;
|
|
97
|
+
|
|
98
|
+
if (inList) {
|
|
99
|
+
const item = trimmed.match(/^ {4}-\s*(.+)$/);
|
|
100
|
+
if (item) {
|
|
101
|
+
const val = stripTrustValue(item[1]!);
|
|
102
|
+
if (val) trustedDirs.push(val);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
inList = false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (/^ {2}trusted_context_dirs:\s*$/.test(trimmed)) {
|
|
109
|
+
inList = true;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const boolMatch = trimmed.match(/^ {2}auto_trust_trellis_symlinks:\s*(.+)$/);
|
|
114
|
+
if (boolMatch) {
|
|
115
|
+
const val = stripTrustValue(boolMatch[1]!).toLowerCase();
|
|
116
|
+
if (val === "false") autoTrustSymlinks = false;
|
|
117
|
+
else if (val === "true") autoTrustSymlinks = true;
|
|
118
|
+
else process.stderr.write(`[channel] channel.auto_trust_trellis_symlinks: invalid value '${val}', ignoring\n`);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return { trustedDirs, autoTrustSymlinks };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function resolveTrustedRoots(projectRoot: string): string[] {
|
|
127
|
+
const configPath = join(projectRoot, ".trellis", "config.yaml");
|
|
128
|
+
let config: { trustedDirs: string[]; autoTrustSymlinks?: boolean } = { trustedDirs: [] };
|
|
129
|
+
if (existsSync(configPath)) {
|
|
130
|
+
try {
|
|
131
|
+
config = parseChannelTrustSection(readFileSync(configPath, "utf-8"));
|
|
132
|
+
} catch {
|
|
133
|
+
// ignore
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const roots: string[] = [];
|
|
138
|
+
for (const entry of config.trustedDirs) {
|
|
139
|
+
try {
|
|
140
|
+
roots.push(realpathSync(resolve(projectRoot, entry)));
|
|
141
|
+
} catch {
|
|
142
|
+
// entry not found or invalid — skip
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (config.autoTrustSymlinks !== false) {
|
|
147
|
+
for (const entryName of AUTO_TRUST_ENTRIES) {
|
|
148
|
+
const entryPath = join(projectRoot, ".trellis", entryName);
|
|
149
|
+
try {
|
|
150
|
+
if (lstatSync(entryPath).isSymbolicLink()) {
|
|
151
|
+
roots.push(realpathSync(entryPath));
|
|
152
|
+
}
|
|
153
|
+
} catch {
|
|
154
|
+
// missing / broken symlink — nothing to trust
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return [...new Set(roots)];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function resolveProjectFile(
|
|
163
|
+
projectRoot: string,
|
|
164
|
+
file: string,
|
|
165
|
+
trustedRoots: string[],
|
|
166
|
+
): string | null {
|
|
62
167
|
try {
|
|
63
168
|
const rootReal = realpathSync(projectRoot);
|
|
64
169
|
const targetReal = realpathSync(resolve(projectRoot, file));
|
|
65
|
-
|
|
170
|
+
if (isInsideRoot(rootReal, targetReal)) return targetReal;
|
|
171
|
+
if (trustedRoots.some((root) => isInsideRoot(root, targetReal))) return targetReal;
|
|
172
|
+
return null;
|
|
66
173
|
} catch {
|
|
67
174
|
return null;
|
|
68
175
|
}
|
|
@@ -171,6 +278,9 @@ type AgentType = "trellis-implement" | "trellis-check" | "trellis-research" | nu
|
|
|
171
278
|
|
|
172
279
|
function buildTaskContext(projectRoot: string, taskDir: string, agentType?: AgentType): string {
|
|
173
280
|
const parts: string[] = [];
|
|
281
|
+
// Resolved once per call (not per referenced file) — avoids re-parsing
|
|
282
|
+
// config.yaml for every jsonl row.
|
|
283
|
+
const trustedRoots = resolveTrustedRoots(projectRoot);
|
|
174
284
|
|
|
175
285
|
// prd.md and info.md — always included
|
|
176
286
|
let prd = "";
|
|
@@ -212,7 +322,7 @@ function buildTaskContext(projectRoot: string, taskDir: string, agentType?: Agen
|
|
|
212
322
|
const row = JSON.parse(trimmed) as Record<string, unknown>;
|
|
213
323
|
const file = typeof row.file === "string" ? row.file.trim() : "";
|
|
214
324
|
if (!file) continue;
|
|
215
|
-
const targetPath = resolveProjectFile(projectRoot, file);
|
|
325
|
+
const targetPath = resolveProjectFile(projectRoot, file, trustedRoots);
|
|
216
326
|
if (!targetPath) continue;
|
|
217
327
|
let content = "";
|
|
218
328
|
try { content = readFileSync(targetPath, "utf-8"); } catch { }
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
* JSONL parsing, and context building capabilities.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { existsSync, readFileSync, appendFileSync, readdirSync } from "fs"
|
|
8
|
+
import { existsSync, readFileSync, appendFileSync, readdirSync, statSync } from "fs"
|
|
9
9
|
import { isAbsolute, join } from "path"
|
|
10
10
|
import { platform } from "os"
|
|
11
11
|
import { execSync } from "child_process"
|
|
12
12
|
import { createHash } from "crypto"
|
|
13
|
+
import { Buffer, isUtf8 } from "buffer"
|
|
13
14
|
import process from "process"
|
|
14
15
|
|
|
15
16
|
const PYTHON_CMD = platform() === "win32" ? "python" : "python3"
|
|
@@ -78,6 +79,240 @@ export function isTrellisSubagent(input) {
|
|
|
78
79
|
return TRELLIS_SUBAGENT_RE.test(agent)
|
|
79
80
|
}
|
|
80
81
|
|
|
82
|
+
// ============================================================
|
|
83
|
+
// Context Injection Limits (issue #441)
|
|
84
|
+
//
|
|
85
|
+
// Notice text and behavior mirrored byte-for-byte from the shared-hooks
|
|
86
|
+
// Python sub-agent context injection hook and the Pi extension. Changing
|
|
87
|
+
// wording here requires changing it there too.
|
|
88
|
+
// ============================================================
|
|
89
|
+
|
|
90
|
+
const DEFAULT_CONTEXT_INJECTION_LIMITS = {
|
|
91
|
+
max_file_bytes: 32768,
|
|
92
|
+
max_artifact_bytes: 65536,
|
|
93
|
+
max_total_bytes: 131072,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Truncate `buf` to at most `cap` bytes without splitting a UTF-8
|
|
98
|
+
* multi-byte sequence. `cap <= 0` means "no limit".
|
|
99
|
+
*/
|
|
100
|
+
function truncateUtf8(buf, cap) {
|
|
101
|
+
if (cap <= 0 || buf.length <= cap) return buf
|
|
102
|
+
let i = cap
|
|
103
|
+
// Back off over continuation bytes (10xxxxxx) to find the lead byte.
|
|
104
|
+
while (i > 0 && (buf[i - 1] & 0xc0) === 0x80) i--
|
|
105
|
+
if (i === 0) return Buffer.alloc(0)
|
|
106
|
+
const lead = buf[i - 1]
|
|
107
|
+
if (lead & 0x80) {
|
|
108
|
+
let seqLen = 1
|
|
109
|
+
if ((lead & 0xe0) === 0xc0) seqLen = 2
|
|
110
|
+
else if ((lead & 0xf0) === 0xe0) seqLen = 3
|
|
111
|
+
else if ((lead & 0xf8) === 0xf0) seqLen = 4
|
|
112
|
+
// Drop the lead byte too if its full sequence didn't fit.
|
|
113
|
+
if (i - 1 + seqLen > cap) i--
|
|
114
|
+
}
|
|
115
|
+
return buf.subarray(0, i)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function stripInlineComment(value) {
|
|
119
|
+
let inQuote = null
|
|
120
|
+
for (let idx = 0; idx < value.length; idx++) {
|
|
121
|
+
const ch = value[idx]
|
|
122
|
+
if (inQuote) {
|
|
123
|
+
if (ch === inQuote) inQuote = null
|
|
124
|
+
continue
|
|
125
|
+
}
|
|
126
|
+
if (ch === '"' || ch === "'") {
|
|
127
|
+
inQuote = ch
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
if (ch === "#" && (idx === 0 || /\s/.test(value[idx - 1]))) {
|
|
131
|
+
return value.slice(0, idx)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return value
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function unquoteYaml(s) {
|
|
138
|
+
if (s.length >= 2 && s[0] === s[s.length - 1] && (s[0] === '"' || s[0] === "'")) {
|
|
139
|
+
return s.slice(1, -1)
|
|
140
|
+
}
|
|
141
|
+
return s
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Line-based parser for ONLY the `context_injection:` block of
|
|
146
|
+
* `.trellis/config.yaml`. Not a general YAML parser — mirrors
|
|
147
|
+
* `common.config.get_context_injection_limits()` semantics for this
|
|
148
|
+
* section only (missing keys keep the default; invalid/negative values
|
|
149
|
+
* fall back to the default for that key with a debugLog warning).
|
|
150
|
+
*/
|
|
151
|
+
function readContextInjectionLimits(repoRoot) {
|
|
152
|
+
const limits = { ...DEFAULT_CONTEXT_INJECTION_LIMITS }
|
|
153
|
+
let text = null
|
|
154
|
+
try {
|
|
155
|
+
text = readFileSync(join(repoRoot, ".trellis", "config.yaml"), "utf-8")
|
|
156
|
+
} catch {
|
|
157
|
+
return limits
|
|
158
|
+
}
|
|
159
|
+
if (!text) return limits
|
|
160
|
+
|
|
161
|
+
let inSection = false
|
|
162
|
+
let sectionIndent = -1
|
|
163
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
164
|
+
const trimmed = rawLine.trim()
|
|
165
|
+
if (!inSection) {
|
|
166
|
+
if (/^context_injection\s*:\s*(#.*)?$/.test(trimmed)) {
|
|
167
|
+
inSection = true
|
|
168
|
+
sectionIndent = rawLine.length - rawLine.trimStart().length
|
|
169
|
+
}
|
|
170
|
+
continue
|
|
171
|
+
}
|
|
172
|
+
if (!trimmed || trimmed.startsWith("#")) continue
|
|
173
|
+
const indent = rawLine.length - rawLine.trimStart().length
|
|
174
|
+
if (indent <= sectionIndent) break
|
|
175
|
+
const m = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*(.*)$/)
|
|
176
|
+
if (!m) continue
|
|
177
|
+
const key = m[1]
|
|
178
|
+
if (!(key in limits)) continue
|
|
179
|
+
const raw = unquoteYaml(stripInlineComment(m[2]).trim()).trim()
|
|
180
|
+
if (!/^-?\d+$/.test(raw) || parseInt(raw, 10) < 0) {
|
|
181
|
+
// invalid/negative -> keep default (Python warns on stderr)
|
|
182
|
+
debugLog("context", `invalid context_injection.${key} value: ${raw}; using default ${limits[key]}`)
|
|
183
|
+
continue
|
|
184
|
+
}
|
|
185
|
+
limits[key] = parseInt(raw, 10)
|
|
186
|
+
}
|
|
187
|
+
return limits
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Tracks the running total of bytes emitted into the sub-agent context. */
|
|
191
|
+
class ContextBudget {
|
|
192
|
+
constructor(maxTotalBytes) {
|
|
193
|
+
this.maxTotalBytes = maxTotalBytes
|
|
194
|
+
this.used = 0
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
hasRoom(size) {
|
|
198
|
+
if (this.maxTotalBytes <= 0) return true
|
|
199
|
+
return this.used + size <= this.maxTotalBytes
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
add(size) {
|
|
203
|
+
this.used += size
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function truncateNotice(path, cap) {
|
|
208
|
+
return `\n[Trellis: truncated at ${cap} bytes — read ${path} for the full content]`
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function isBinaryContent(data) {
|
|
212
|
+
return data.includes(0) || !isUtf8(data)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function binaryNotice(path, size, reason) {
|
|
216
|
+
return `[Trellis: not inlined (binary file) — ${path} (${size} bytes): ${reason}]`
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function indexNotice(path, size, reason) {
|
|
220
|
+
return `[Trellis: not inlined (total context limit reached) — ${path} (${size} bytes): ${reason}]`
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Return an inlined `=== header ===` block, or degrade to an index
|
|
225
|
+
* notice once the total context budget is exhausted.
|
|
226
|
+
*/
|
|
227
|
+
function budgetedBlock(budget, header, plainPath, content, reason, sizeForIndex) {
|
|
228
|
+
const block = `=== ${header} ===\n${content}`
|
|
229
|
+
const blockBytes = Buffer.byteLength(block, "utf-8")
|
|
230
|
+
if (!budget.hasRoom(blockBytes)) {
|
|
231
|
+
const notice = indexNotice(plainPath, sizeForIndex, reason)
|
|
232
|
+
budget.add(Buffer.byteLength(notice, "utf-8"))
|
|
233
|
+
return notice
|
|
234
|
+
}
|
|
235
|
+
budget.add(blockBytes)
|
|
236
|
+
return block
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Read raw file bytes, return null if file doesn't exist. */
|
|
240
|
+
function readFileBytes(basePath, filePath) {
|
|
241
|
+
const fullPath = isAbsolute(filePath) ? filePath : join(basePath, filePath)
|
|
242
|
+
try {
|
|
243
|
+
if (!statSync(fullPath).isFile()) return null
|
|
244
|
+
} catch {
|
|
245
|
+
return null
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
return readFileSync(fullPath)
|
|
249
|
+
} catch {
|
|
250
|
+
return null
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/** Read a JSONL-referenced file, apply the per-file cap, then budget it. */
|
|
255
|
+
function materializeFile(basePath, filePath, reason, limits, budget) {
|
|
256
|
+
const data = readFileBytes(basePath, filePath)
|
|
257
|
+
if (data === null) return null
|
|
258
|
+
|
|
259
|
+
const size = data.length
|
|
260
|
+
if (isBinaryContent(data)) {
|
|
261
|
+
const notice = binaryNotice(filePath, size, reason)
|
|
262
|
+
budget.add(Buffer.byteLength(notice, "utf-8"))
|
|
263
|
+
return notice
|
|
264
|
+
}
|
|
265
|
+
const cap = limits.max_file_bytes
|
|
266
|
+
const truncated = truncateUtf8(data, cap)
|
|
267
|
+
let content = truncated.toString("utf-8")
|
|
268
|
+
if (truncated.length < size) content += truncateNotice(filePath, cap)
|
|
269
|
+
|
|
270
|
+
return budgetedBlock(budget, filePath, filePath, content, reason, size)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Read all .md files in a directory, applying the same per-file and
|
|
275
|
+
* total caps as a single-file JSONL entry.
|
|
276
|
+
*/
|
|
277
|
+
function materializeDirectory(basePath, dirPath, reason, limits, budget, maxFiles = 20) {
|
|
278
|
+
const blocks = []
|
|
279
|
+
const fullPath = isAbsolute(dirPath) ? dirPath : join(basePath, dirPath)
|
|
280
|
+
|
|
281
|
+
let files
|
|
282
|
+
try {
|
|
283
|
+
if (!statSync(fullPath).isDirectory()) return blocks
|
|
284
|
+
files = readdirSync(fullPath)
|
|
285
|
+
.filter(f => f.endsWith(".md") && statSync(join(fullPath, f)).isFile())
|
|
286
|
+
.sort()
|
|
287
|
+
} catch {
|
|
288
|
+
return blocks
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
for (const filename of files.slice(0, maxFiles)) {
|
|
292
|
+
const relativePath = join(dirPath, filename)
|
|
293
|
+
const block = materializeFile(basePath, relativePath, reason, limits, budget)
|
|
294
|
+
if (block) blocks.push(block)
|
|
295
|
+
}
|
|
296
|
+
return blocks
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Read a task artifact (prd/design/implement.md), apply the per-artifact
|
|
301
|
+
* cap, then budget it.
|
|
302
|
+
*/
|
|
303
|
+
function materializeArtifact(basePath, filePath, headerLabel, reason, limits, budget) {
|
|
304
|
+
const data = readFileBytes(basePath, filePath)
|
|
305
|
+
if (data === null) return null
|
|
306
|
+
|
|
307
|
+
const size = data.length
|
|
308
|
+
const cap = limits.max_artifact_bytes
|
|
309
|
+
const truncated = truncateUtf8(data, cap)
|
|
310
|
+
let content = truncated.toString("utf-8")
|
|
311
|
+
if (truncated.length < size) content += truncateNotice(filePath, cap)
|
|
312
|
+
|
|
313
|
+
return budgetedBlock(budget, headerLabel, filePath, content, reason, size)
|
|
314
|
+
}
|
|
315
|
+
|
|
81
316
|
/**
|
|
82
317
|
* Trellis Context Manager
|
|
83
318
|
*/
|
|
@@ -282,44 +517,21 @@ export class TrellisContext {
|
|
|
282
517
|
// JSONL Reading
|
|
283
518
|
// ============================================================
|
|
284
519
|
|
|
285
|
-
readDirectoryMdFiles(dirPath, maxFiles = 20) {
|
|
286
|
-
const results = []
|
|
287
|
-
const fullPath = join(this.directory, dirPath)
|
|
288
|
-
|
|
289
|
-
if (!existsSync(fullPath)) {
|
|
290
|
-
return results
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
try {
|
|
294
|
-
const files = readdirSync(fullPath)
|
|
295
|
-
.filter(f => f.endsWith(".md"))
|
|
296
|
-
.sort()
|
|
297
|
-
.slice(0, maxFiles)
|
|
298
|
-
|
|
299
|
-
for (const filename of files) {
|
|
300
|
-
const filePath = join(dirPath, filename)
|
|
301
|
-
const content = this.readProjectFile(filePath)
|
|
302
|
-
if (content) {
|
|
303
|
-
results.push({ path: filePath, content })
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
} catch {
|
|
307
|
-
// Ignore directory read errors
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return results
|
|
311
|
-
}
|
|
312
|
-
|
|
313
520
|
/**
|
|
314
|
-
* Read a JSONL file and
|
|
521
|
+
* Read a JSONL file and materialize referenced files/directories into
|
|
522
|
+
* context blocks, applying per-file caps and the shared total budget
|
|
523
|
+
* (issue #441). Mirrors Python `_materialize_jsonl_entries`.
|
|
315
524
|
* Supports:
|
|
316
525
|
* {"file": "path/to/file.md", "reason": "..."}
|
|
317
526
|
* {"file": "path/to/dir/", "type": "directory", "reason": "..."}
|
|
527
|
+
*
|
|
528
|
+
* Missing referenced files are skipped silently (Python `_materialize_file`
|
|
529
|
+
* returns None for them).
|
|
318
530
|
*/
|
|
319
|
-
readJsonlWithFiles(jsonlPath) {
|
|
320
|
-
const
|
|
531
|
+
readJsonlWithFiles(jsonlPath, limits, budget) {
|
|
532
|
+
const blocks = []
|
|
321
533
|
const content = this.readFile(jsonlPath)
|
|
322
|
-
if (!content) return
|
|
534
|
+
if (!content) return blocks
|
|
323
535
|
|
|
324
536
|
for (const line of content.split("\n")) {
|
|
325
537
|
if (!line.trim()) continue
|
|
@@ -327,28 +539,25 @@ export class TrellisContext {
|
|
|
327
539
|
const item = JSON.parse(line)
|
|
328
540
|
const file = item.file || item.path
|
|
329
541
|
const entryType = item.type || "file"
|
|
542
|
+
const reason = item.reason || "-"
|
|
330
543
|
|
|
331
544
|
if (!file) continue
|
|
332
545
|
|
|
333
546
|
if (entryType === "directory") {
|
|
334
|
-
|
|
335
|
-
results.push(...dirEntries)
|
|
547
|
+
blocks.push(...materializeDirectory(this.directory, file, reason, limits, budget))
|
|
336
548
|
} else {
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
if (fileContent) {
|
|
340
|
-
results.push({ path: file, content: fileContent })
|
|
341
|
-
}
|
|
549
|
+
const block = materializeFile(this.directory, file, reason, limits, budget)
|
|
550
|
+
if (block) blocks.push(block)
|
|
342
551
|
}
|
|
343
552
|
} catch {
|
|
344
553
|
// Ignore parse errors for individual lines
|
|
345
554
|
}
|
|
346
555
|
}
|
|
347
|
-
return
|
|
556
|
+
return blocks
|
|
348
557
|
}
|
|
349
558
|
|
|
350
|
-
buildContextFromEntries(
|
|
351
|
-
return
|
|
559
|
+
buildContextFromEntries(blocks) {
|
|
560
|
+
return blocks.join("\n\n")
|
|
352
561
|
}
|
|
353
562
|
}
|
|
354
563
|
|
|
@@ -379,3 +588,14 @@ export const contextCollector = new ContextCollector()
|
|
|
379
588
|
|
|
380
589
|
// Export debug log for plugins
|
|
381
590
|
export { debugLog }
|
|
591
|
+
|
|
592
|
+
// Context injection limits (issue #441) — exported for plugins and tests
|
|
593
|
+
export {
|
|
594
|
+
DEFAULT_CONTEXT_INJECTION_LIMITS,
|
|
595
|
+
truncateUtf8,
|
|
596
|
+
readContextInjectionLimits,
|
|
597
|
+
ContextBudget,
|
|
598
|
+
materializeFile,
|
|
599
|
+
materializeDirectory,
|
|
600
|
+
materializeArtifact,
|
|
601
|
+
}
|