trellis-herbivore 0.1.0
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/bin/trellis.js +3 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +174 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/commands/channel/adapters/claude.d.ts +38 -0
- package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
- package/dist/commands/channel/adapters/claude.js +209 -0
- package/dist/commands/channel/adapters/claude.js.map +1 -0
- package/dist/commands/channel/adapters/codex.d.ts +77 -0
- package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
- package/dist/commands/channel/adapters/codex.js +495 -0
- package/dist/commands/channel/adapters/codex.js.map +1 -0
- package/dist/commands/channel/adapters/index.d.ts +79 -0
- package/dist/commands/channel/adapters/index.d.ts.map +1 -0
- package/dist/commands/channel/adapters/index.js +109 -0
- package/dist/commands/channel/adapters/index.js.map +1 -0
- package/dist/commands/channel/adapters/types.d.ts +33 -0
- package/dist/commands/channel/adapters/types.d.ts.map +1 -0
- package/dist/commands/channel/adapters/types.js +2 -0
- package/dist/commands/channel/adapters/types.js.map +1 -0
- package/dist/commands/channel/agent-loader.d.ts +32 -0
- package/dist/commands/channel/agent-loader.d.ts.map +1 -0
- package/dist/commands/channel/agent-loader.js +154 -0
- package/dist/commands/channel/agent-loader.js.map +1 -0
- package/dist/commands/channel/context-loader.d.ts +26 -0
- package/dist/commands/channel/context-loader.d.ts.map +1 -0
- package/dist/commands/channel/context-loader.js +290 -0
- package/dist/commands/channel/context-loader.js.map +1 -0
- package/dist/commands/channel/context.d.ts +16 -0
- package/dist/commands/channel/context.d.ts.map +1 -0
- package/dist/commands/channel/context.js +83 -0
- package/dist/commands/channel/context.js.map +1 -0
- package/dist/commands/channel/create.d.ts +27 -0
- package/dist/commands/channel/create.d.ts.map +1 -0
- package/dist/commands/channel/create.js +39 -0
- package/dist/commands/channel/create.js.map +1 -0
- package/dist/commands/channel/dev-parse-trace.d.ts +14 -0
- package/dist/commands/channel/dev-parse-trace.d.ts.map +1 -0
- package/dist/commands/channel/dev-parse-trace.js +70 -0
- package/dist/commands/channel/dev-parse-trace.js.map +1 -0
- package/dist/commands/channel/index.d.ts +3 -0
- package/dist/commands/channel/index.d.ts.map +1 -0
- package/dist/commands/channel/index.js +496 -0
- package/dist/commands/channel/index.js.map +1 -0
- package/dist/commands/channel/kill.d.ts +7 -0
- package/dist/commands/channel/kill.d.ts.map +1 -0
- package/dist/commands/channel/kill.js +121 -0
- package/dist/commands/channel/kill.js.map +1 -0
- package/dist/commands/channel/list.d.ts +17 -0
- package/dist/commands/channel/list.d.ts.map +1 -0
- package/dist/commands/channel/list.js +233 -0
- package/dist/commands/channel/list.js.map +1 -0
- package/dist/commands/channel/messages.d.ts +16 -0
- package/dist/commands/channel/messages.d.ts.map +1 -0
- package/dist/commands/channel/messages.js +237 -0
- package/dist/commands/channel/messages.js.map +1 -0
- package/dist/commands/channel/rm.d.ts +27 -0
- package/dist/commands/channel/rm.d.ts.map +1 -0
- package/dist/commands/channel/rm.js +216 -0
- package/dist/commands/channel/rm.js.map +1 -0
- package/dist/commands/channel/run.d.ts +31 -0
- package/dist/commands/channel/run.d.ts.map +1 -0
- package/dist/commands/channel/run.js +137 -0
- package/dist/commands/channel/run.js.map +1 -0
- package/dist/commands/channel/send.d.ts +12 -0
- package/dist/commands/channel/send.d.ts.map +1 -0
- package/dist/commands/channel/send.js +24 -0
- package/dist/commands/channel/send.js.map +1 -0
- package/dist/commands/channel/spawn.d.ts +25 -0
- package/dist/commands/channel/spawn.d.ts.map +1 -0
- package/dist/commands/channel/spawn.js +192 -0
- package/dist/commands/channel/spawn.js.map +1 -0
- package/dist/commands/channel/store/events.d.ts +39 -0
- package/dist/commands/channel/store/events.d.ts.map +1 -0
- package/dist/commands/channel/store/events.js +87 -0
- package/dist/commands/channel/store/events.js.map +1 -0
- package/dist/commands/channel/store/filter.d.ts +3 -0
- package/dist/commands/channel/store/filter.d.ts.map +1 -0
- package/dist/commands/channel/store/filter.js +2 -0
- package/dist/commands/channel/store/filter.js.map +1 -0
- package/dist/commands/channel/store/lock.d.ts +23 -0
- package/dist/commands/channel/store/lock.d.ts.map +1 -0
- package/dist/commands/channel/store/lock.js +99 -0
- package/dist/commands/channel/store/lock.js.map +1 -0
- package/dist/commands/channel/store/paths.d.ts +63 -0
- package/dist/commands/channel/store/paths.d.ts.map +1 -0
- package/dist/commands/channel/store/paths.js +246 -0
- package/dist/commands/channel/store/paths.js.map +1 -0
- package/dist/commands/channel/store/schema.d.ts +27 -0
- package/dist/commands/channel/store/schema.d.ts.map +1 -0
- package/dist/commands/channel/store/schema.js +34 -0
- package/dist/commands/channel/store/schema.js.map +1 -0
- package/dist/commands/channel/store/thread-state.d.ts +5 -0
- package/dist/commands/channel/store/thread-state.d.ts.map +1 -0
- package/dist/commands/channel/store/thread-state.js +16 -0
- package/dist/commands/channel/store/thread-state.js.map +1 -0
- package/dist/commands/channel/store/watch.d.ts +19 -0
- package/dist/commands/channel/store/watch.d.ts.map +1 -0
- package/dist/commands/channel/store/watch.js +130 -0
- package/dist/commands/channel/store/watch.js.map +1 -0
- package/dist/commands/channel/supervisor/inbox.d.ts +25 -0
- package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/inbox.js +99 -0
- package/dist/commands/channel/supervisor/inbox.js.map +1 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts +66 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/shutdown.js +143 -0
- package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
- package/dist/commands/channel/supervisor/stdout.d.ts +49 -0
- package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/stdout.js +107 -0
- package/dist/commands/channel/supervisor/stdout.js.map +1 -0
- package/dist/commands/channel/supervisor.d.ts +47 -0
- package/dist/commands/channel/supervisor.d.ts.map +1 -0
- package/dist/commands/channel/supervisor.js +283 -0
- package/dist/commands/channel/supervisor.js.map +1 -0
- package/dist/commands/channel/text-body.d.ts +13 -0
- package/dist/commands/channel/text-body.d.ts.map +1 -0
- package/dist/commands/channel/text-body.js +47 -0
- package/dist/commands/channel/text-body.js.map +1 -0
- package/dist/commands/channel/threads.d.ts +39 -0
- package/dist/commands/channel/threads.d.ts.map +1 -0
- package/dist/commands/channel/threads.js +106 -0
- package/dist/commands/channel/threads.js.map +1 -0
- package/dist/commands/channel/title.d.ts +12 -0
- package/dist/commands/channel/title.d.ts.map +1 -0
- package/dist/commands/channel/title.js +24 -0
- package/dist/commands/channel/title.js.map +1 -0
- package/dist/commands/channel/wait.d.ts +18 -0
- package/dist/commands/channel/wait.d.ts.map +1 -0
- package/dist/commands/channel/wait.js +76 -0
- package/dist/commands/channel/wait.js.map +1 -0
- package/dist/commands/init.d.ts +57 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +1466 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mem.d.ts +234 -0
- package/dist/commands/mem.d.ts.map +1 -0
- package/dist/commands/mem.js +1869 -0
- package/dist/commands/mem.js.map +1 -0
- package/dist/commands/uninstall.d.ts +27 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +339 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +72 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +1926 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/upgrade.d.ts +28 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +84 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/configurators/antigravity.d.ts +7 -0
- package/dist/configurators/antigravity.d.ts.map +1 -0
- package/dist/configurators/antigravity.js +19 -0
- package/dist/configurators/antigravity.js.map +1 -0
- package/dist/configurators/claude.d.ts +9 -0
- package/dist/configurators/claude.d.ts.map +1 -0
- package/dist/configurators/claude.js +72 -0
- package/dist/configurators/claude.js.map +1 -0
- package/dist/configurators/codebuddy.d.ts +10 -0
- package/dist/configurators/codebuddy.d.ts.map +1 -0
- package/dist/configurators/codebuddy.js +30 -0
- package/dist/configurators/codebuddy.js.map +1 -0
- package/dist/configurators/codex.d.ts +8 -0
- package/dist/configurators/codex.d.ts.map +1 -0
- package/dist/configurators/codex.js +87 -0
- package/dist/configurators/codex.js.map +1 -0
- package/dist/configurators/copilot.d.ts +10 -0
- package/dist/configurators/copilot.d.ts.map +1 -0
- package/dist/configurators/copilot.js +51 -0
- package/dist/configurators/copilot.js.map +1 -0
- package/dist/configurators/cursor.d.ts +10 -0
- package/dist/configurators/cursor.d.ts.map +1 -0
- package/dist/configurators/cursor.js +29 -0
- package/dist/configurators/cursor.js.map +1 -0
- package/dist/configurators/droid.d.ts +10 -0
- package/dist/configurators/droid.d.ts.map +1 -0
- package/dist/configurators/droid.js +30 -0
- package/dist/configurators/droid.js.map +1 -0
- package/dist/configurators/gemini.d.ts +16 -0
- package/dist/configurators/gemini.d.ts.map +1 -0
- package/dist/configurators/gemini.js +38 -0
- package/dist/configurators/gemini.js.map +1 -0
- package/dist/configurators/index.d.ts +65 -0
- package/dist/configurators/index.d.ts.map +1 -0
- package/dist/configurators/index.js +367 -0
- package/dist/configurators/index.js.map +1 -0
- package/dist/configurators/kilo.d.ts +7 -0
- package/dist/configurators/kilo.d.ts.map +1 -0
- package/dist/configurators/kilo.js +19 -0
- package/dist/configurators/kilo.js.map +1 -0
- package/dist/configurators/kiro.d.ts +8 -0
- package/dist/configurators/kiro.d.ts.map +1 -0
- package/dist/configurators/kiro.js +24 -0
- package/dist/configurators/kiro.js.map +1 -0
- package/dist/configurators/opencode.d.ts +14 -0
- package/dist/configurators/opencode.d.ts.map +1 -0
- package/dist/configurators/opencode.js +96 -0
- package/dist/configurators/opencode.js.map +1 -0
- package/dist/configurators/pi.d.ts +3 -0
- package/dist/configurators/pi.d.ts.map +1 -0
- package/dist/configurators/pi.js +45 -0
- package/dist/configurators/pi.js.map +1 -0
- package/dist/configurators/qoder.d.ts +11 -0
- package/dist/configurators/qoder.d.ts.map +1 -0
- package/dist/configurators/qoder.js +31 -0
- package/dist/configurators/qoder.js.map +1 -0
- package/dist/configurators/shared.d.ts +178 -0
- package/dist/configurators/shared.d.ts.map +1 -0
- package/dist/configurators/shared.js +538 -0
- package/dist/configurators/shared.js.map +1 -0
- package/dist/configurators/windsurf.d.ts +7 -0
- package/dist/configurators/windsurf.d.ts.map +1 -0
- package/dist/configurators/windsurf.js +19 -0
- package/dist/configurators/windsurf.js.map +1 -0
- package/dist/configurators/workflow.d.ts +29 -0
- package/dist/configurators/workflow.d.ts.map +1 -0
- package/dist/configurators/workflow.js +163 -0
- package/dist/configurators/workflow.js.map +1 -0
- package/dist/constants/paths.d.ts +70 -0
- package/dist/constants/paths.d.ts.map +1 -0
- package/dist/constants/paths.js +79 -0
- package/dist/constants/paths.js.map +1 -0
- package/dist/constants/version.d.ts +9 -0
- package/dist/constants/version.d.ts.map +1 -0
- package/dist/constants/version.js +15 -0
- package/dist/constants/version.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/index.d.ts +62 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +187 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/manifests/0.1.9.json +30 -0
- package/dist/migrations/manifests/0.2.0.json +49 -0
- package/dist/migrations/manifests/0.2.12.json +9 -0
- package/dist/migrations/manifests/0.2.13.json +9 -0
- package/dist/migrations/manifests/0.2.14.json +175 -0
- package/dist/migrations/manifests/0.2.15.json +33 -0
- package/dist/migrations/manifests/0.3.0-beta.0.json +297 -0
- package/dist/migrations/manifests/0.3.0-beta.1.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.11.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.12.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.13.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.15.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.16.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.2.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.3.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.4.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.5.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.6.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.7.json +11 -0
- package/dist/migrations/manifests/0.3.0-beta.8.json +9 -0
- package/dist/migrations/manifests/0.3.0-beta.9.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.0.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.1.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.2.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.3.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.4.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.5.json +9 -0
- package/dist/migrations/manifests/0.3.0-rc.6.json +9 -0
- package/dist/migrations/manifests/0.3.0.json +11 -0
- package/dist/migrations/manifests/0.3.1.json +9 -0
- package/dist/migrations/manifests/0.3.10.json +9 -0
- package/dist/migrations/manifests/0.3.2.json +9 -0
- package/dist/migrations/manifests/0.3.3.json +9 -0
- package/dist/migrations/manifests/0.3.4.json +21 -0
- package/dist/migrations/manifests/0.3.5.json +9 -0
- package/dist/migrations/manifests/0.3.6.json +9 -0
- package/dist/migrations/manifests/0.3.7.json +9 -0
- package/dist/migrations/manifests/0.3.8.json +9 -0
- package/dist/migrations/manifests/0.3.9.json +9 -0
- package/dist/migrations/manifests/0.4.0-beta.1.json +228 -0
- package/dist/migrations/manifests/0.4.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.4.0-beta.2.json +9 -0
- package/dist/migrations/manifests/0.4.0-beta.3.json +9 -0
- package/dist/migrations/manifests/0.4.0-beta.4.json +9 -0
- package/dist/migrations/manifests/0.4.0-beta.5.json +9 -0
- package/dist/migrations/manifests/0.4.0-beta.6.json +9 -0
- package/dist/migrations/manifests/0.4.0-beta.7.json +9 -0
- package/dist/migrations/manifests/0.4.0-beta.8.json +34 -0
- package/dist/migrations/manifests/0.4.0-beta.9.json +9 -0
- package/dist/migrations/manifests/0.4.0-rc.0.json +9 -0
- package/dist/migrations/manifests/0.4.0-rc.1.json +9 -0
- package/dist/migrations/manifests/0.4.0.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.0.json +1646 -0
- package/dist/migrations/manifests/0.5.0-beta.1.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.11.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.12.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.13.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.15.json +116 -0
- package/dist/migrations/manifests/0.5.0-beta.16.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.17.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.18.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.19.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.2.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.3.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.4.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.5.json +222 -0
- package/dist/migrations/manifests/0.5.0-beta.6.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.7.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.8.json +9 -0
- package/dist/migrations/manifests/0.5.0-beta.9.json +48 -0
- package/dist/migrations/manifests/0.5.0-rc.0.json +9 -0
- package/dist/migrations/manifests/0.5.0-rc.1.json +9 -0
- package/dist/migrations/manifests/0.5.0-rc.2.json +9 -0
- package/dist/migrations/manifests/0.5.0-rc.3.json +9 -0
- package/dist/migrations/manifests/0.5.0-rc.4.json +9 -0
- package/dist/migrations/manifests/0.5.0-rc.5.json +9 -0
- package/dist/migrations/manifests/0.5.0-rc.6.json +9 -0
- package/dist/migrations/manifests/0.5.0-rc.7.json +9 -0
- package/dist/migrations/manifests/0.5.0.json +9 -0
- package/dist/migrations/manifests/0.5.1.json +9 -0
- package/dist/migrations/manifests/0.5.10.json +9 -0
- package/dist/migrations/manifests/0.5.11.json +16 -0
- package/dist/migrations/manifests/0.5.12.json +9 -0
- package/dist/migrations/manifests/0.5.13.json +9 -0
- package/dist/migrations/manifests/0.5.14.json +9 -0
- package/dist/migrations/manifests/0.5.15.json +9 -0
- package/dist/migrations/manifests/0.5.2.json +9 -0
- package/dist/migrations/manifests/0.5.3.json +9 -0
- package/dist/migrations/manifests/0.5.4.json +9 -0
- package/dist/migrations/manifests/0.5.5.json +9 -0
- package/dist/migrations/manifests/0.5.6.json +9 -0
- package/dist/migrations/manifests/0.5.7.json +16 -0
- package/dist/migrations/manifests/0.5.8.json +9 -0
- package/dist/migrations/manifests/0.5.9.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.0.json +16 -0
- package/dist/migrations/manifests/0.6.0-beta.1.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.10.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.11.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.12.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.13.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.14.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.2.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.3.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.4.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.5.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.6.json +16 -0
- package/dist/migrations/manifests/0.6.0-beta.7.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.8.json +9 -0
- package/dist/migrations/manifests/0.6.0-beta.9.json +9 -0
- package/dist/templates/claude/agents/trellis-check.md +114 -0
- package/dist/templates/claude/agents/trellis-implement.md +113 -0
- package/dist/templates/claude/agents/trellis-research.md +137 -0
- package/dist/templates/claude/index.d.ts +22 -0
- package/dist/templates/claude/index.d.ts.map +1 -0
- package/dist/templates/claude/index.js +46 -0
- package/dist/templates/claude/index.js.map +1 -0
- package/dist/templates/claude/settings.json +73 -0
- package/dist/templates/codebuddy/agents/trellis-check.md +109 -0
- package/dist/templates/codebuddy/agents/trellis-implement.md +110 -0
- package/dist/templates/codebuddy/agents/trellis-research.md +137 -0
- package/dist/templates/codebuddy/index.d.ts +15 -0
- package/dist/templates/codebuddy/index.d.ts.map +1 -0
- package/dist/templates/codebuddy/index.js +15 -0
- package/dist/templates/codebuddy/index.js.map +1 -0
- package/dist/templates/codebuddy/settings.json +59 -0
- package/dist/templates/codex/agents/trellis-check.toml +84 -0
- package/dist/templates/codex/agents/trellis-implement.toml +65 -0
- package/dist/templates/codex/agents/trellis-research.toml +73 -0
- package/dist/templates/codex/config.toml +35 -0
- package/dist/templates/codex/hooks/session-start.py +545 -0
- package/dist/templates/codex/hooks.json +15 -0
- package/dist/templates/codex/index.d.ts +39 -0
- package/dist/templates/codex/index.d.ts.map +1 -0
- package/dist/templates/codex/index.js +85 -0
- package/dist/templates/codex/index.js.map +1 -0
- package/dist/templates/codex/skills/before-dev/SKILL.md +40 -0
- package/dist/templates/codex/skills/brainstorm/SKILL.md +112 -0
- package/dist/templates/codex/skills/break-loop/SKILL.md +130 -0
- package/dist/templates/codex/skills/check/SKILL.md +98 -0
- package/dist/templates/codex/skills/check-cross-layer/SKILL.md +158 -0
- package/dist/templates/codex/skills/create-command/SKILL.md +101 -0
- package/dist/templates/codex/skills/finish-work/SKILL.md +90 -0
- package/dist/templates/codex/skills/improve-ut/SKILL.md +69 -0
- package/dist/templates/codex/skills/integrate-skill/SKILL.md +221 -0
- package/dist/templates/codex/skills/onboard/SKILL.md +363 -0
- package/dist/templates/codex/skills/record-session/SKILL.md +67 -0
- package/dist/templates/codex/skills/start/SKILL.md +64 -0
- package/dist/templates/codex/skills/update-spec/SKILL.md +335 -0
- package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +73 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/add-project-local-conventions.md +83 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +54 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-context-loading.md +84 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +57 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +78 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-spec-structure.md +83 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-task-lifecycle.md +90 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-workflow.md +65 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +55 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/context-injection.md +68 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +80 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +51 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/spec-system.md +102 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/task-system.md +103 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workflow.md +75 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/workspace-memory.md +71 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +80 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +69 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +59 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +74 -0
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +83 -0
- package/dist/templates/common/commands/continue.md +56 -0
- package/dist/templates/common/commands/finish-work.md +66 -0
- package/dist/templates/common/commands/start.md +59 -0
- package/dist/templates/common/index.d.ts +48 -0
- package/dist/templates/common/index.d.ts.map +1 -0
- package/dist/templates/common/index.js +104 -0
- package/dist/templates/common/index.js.map +1 -0
- package/dist/templates/common/skills/before-dev.md +35 -0
- package/dist/templates/common/skills/brainstorm.md +112 -0
- package/dist/templates/common/skills/break-loop.md +125 -0
- package/dist/templates/common/skills/check.md +93 -0
- package/dist/templates/common/skills/update-spec.md +351 -0
- package/dist/templates/copilot/hooks/session-start.py +547 -0
- package/dist/templates/copilot/hooks.json +19 -0
- package/dist/templates/copilot/index.d.ts +23 -0
- package/dist/templates/copilot/index.d.ts.map +1 -0
- package/dist/templates/copilot/index.js +54 -0
- package/dist/templates/copilot/index.js.map +1 -0
- package/dist/templates/copilot/prompts/before-dev.prompt.md +39 -0
- package/dist/templates/copilot/prompts/brainstorm.prompt.md +111 -0
- package/dist/templates/copilot/prompts/break-loop.prompt.md +129 -0
- package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +157 -0
- package/dist/templates/copilot/prompts/check.prompt.md +97 -0
- package/dist/templates/copilot/prompts/create-command.prompt.md +116 -0
- package/dist/templates/copilot/prompts/finish-work.prompt.md +99 -0
- package/dist/templates/copilot/prompts/integrate-skill.prompt.md +223 -0
- package/dist/templates/copilot/prompts/onboard.prompt.md +362 -0
- package/dist/templates/copilot/prompts/parallel.prompt.md +204 -0
- package/dist/templates/copilot/prompts/record-session.prompt.md +66 -0
- package/dist/templates/copilot/prompts/start.prompt.md +63 -0
- package/dist/templates/copilot/prompts/update-spec.prompt.md +358 -0
- package/dist/templates/cursor/agents/trellis-check.md +108 -0
- package/dist/templates/cursor/agents/trellis-implement.md +109 -0
- package/dist/templates/cursor/agents/trellis-research.md +136 -0
- package/dist/templates/cursor/hooks.json +30 -0
- package/dist/templates/cursor/index.d.ts +13 -0
- package/dist/templates/cursor/index.d.ts.map +1 -0
- package/dist/templates/cursor/index.js +13 -0
- package/dist/templates/cursor/index.js.map +1 -0
- package/dist/templates/droid/droids/trellis-check.md +101 -0
- package/dist/templates/droid/droids/trellis-implement.md +102 -0
- package/dist/templates/droid/droids/trellis-research.md +137 -0
- package/dist/templates/droid/index.d.ts +15 -0
- package/dist/templates/droid/index.d.ts.map +1 -0
- package/dist/templates/droid/index.js +15 -0
- package/dist/templates/droid/index.js.map +1 -0
- package/dist/templates/droid/settings.json +59 -0
- package/dist/templates/extract.d.ts +40 -0
- package/dist/templates/extract.d.ts.map +1 -0
- package/dist/templates/extract.js +106 -0
- package/dist/templates/extract.js.map +1 -0
- package/dist/templates/gemini/agents/trellis-check.md +101 -0
- package/dist/templates/gemini/agents/trellis-implement.md +102 -0
- package/dist/templates/gemini/agents/trellis-research.md +136 -0
- package/dist/templates/gemini/index.d.ts +13 -0
- package/dist/templates/gemini/index.d.ts.map +1 -0
- package/dist/templates/gemini/index.js +13 -0
- package/dist/templates/gemini/index.js.map +1 -0
- package/dist/templates/gemini/settings.json +28 -0
- package/dist/templates/kiro/agents/trellis-check.json +26 -0
- package/dist/templates/kiro/agents/trellis-implement.json +26 -0
- package/dist/templates/kiro/agents/trellis-research.json +30 -0
- package/dist/templates/kiro/index.d.ts +18 -0
- package/dist/templates/kiro/index.d.ts.map +1 -0
- package/dist/templates/kiro/index.js +18 -0
- package/dist/templates/kiro/index.js.map +1 -0
- package/dist/templates/markdown/agents.md +21 -0
- package/dist/templates/markdown/gitignore.txt +15 -0
- package/dist/templates/markdown/index.d.ts +27 -0
- package/dist/templates/markdown/index.d.ts.map +1 -0
- package/dist/templates/markdown/index.js +52 -0
- package/dist/templates/markdown/index.js.map +1 -0
- package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/backend/directory-structure.md.txt +54 -0
- package/dist/templates/markdown/spec/backend/error-handling.md.txt +51 -0
- package/dist/templates/markdown/spec/backend/index.md.txt +38 -0
- package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +59 -0
- package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +54 -0
- package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/frontend/index.md.txt +39 -0
- package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +51 -0
- package/dist/templates/markdown/spec/frontend/state-management.md.txt +51 -0
- package/dist/templates/markdown/spec/frontend/type-safety.md.txt +51 -0
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +223 -0
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +259 -0
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +595 -0
- package/dist/templates/markdown/spec/guides/index.md.txt +97 -0
- package/dist/templates/markdown/workspace-index.md +125 -0
- package/dist/templates/markdown/worktree.yaml.txt +58 -0
- package/dist/templates/opencode/agents/trellis-check.md +116 -0
- package/dist/templates/opencode/agents/trellis-implement.md +118 -0
- package/dist/templates/opencode/agents/trellis-research.md +145 -0
- package/dist/templates/opencode/lib/session-utils.js +521 -0
- package/dist/templates/opencode/lib/trellis-context.js +381 -0
- package/dist/templates/opencode/package.json +5 -0
- package/dist/templates/opencode/plugins/inject-subagent-context.js +513 -0
- package/dist/templates/opencode/plugins/inject-workflow-state.js +159 -0
- package/dist/templates/opencode/plugins/session-start.js +101 -0
- package/dist/templates/pi/agents/trellis-check.md +36 -0
- package/dist/templates/pi/agents/trellis-implement.md +41 -0
- package/dist/templates/pi/agents/trellis-research.md +25 -0
- package/dist/templates/pi/extensions/trellis/index.ts.txt +1174 -0
- package/dist/templates/pi/index.d.ts +5 -0
- package/dist/templates/pi/index.d.ts.map +1 -0
- package/dist/templates/pi/index.js +12 -0
- package/dist/templates/pi/index.js.map +1 -0
- package/dist/templates/pi/settings.json +21 -0
- package/dist/templates/qoder/agents/trellis-check.md +102 -0
- package/dist/templates/qoder/agents/trellis-implement.md +103 -0
- package/dist/templates/qoder/agents/trellis-research.md +137 -0
- package/dist/templates/qoder/index.d.ts +15 -0
- package/dist/templates/qoder/index.d.ts.map +1 -0
- package/dist/templates/qoder/index.js +15 -0
- package/dist/templates/qoder/index.js.map +1 -0
- package/dist/templates/qoder/settings.json +47 -0
- package/dist/templates/shared-hooks/index.d.ts +50 -0
- package/dist/templates/shared-hooks/index.d.ts.map +1 -0
- package/dist/templates/shared-hooks/index.js +89 -0
- package/dist/templates/shared-hooks/index.js.map +1 -0
- package/dist/templates/shared-hooks/inject-shell-session-context.py +183 -0
- package/dist/templates/shared-hooks/inject-subagent-context.py +771 -0
- package/dist/templates/shared-hooks/inject-workflow-state.py +363 -0
- package/dist/templates/shared-hooks/session-start.py +827 -0
- package/dist/templates/template-utils.d.ts +26 -0
- package/dist/templates/template-utils.d.ts.map +1 -0
- package/dist/templates/template-utils.js +60 -0
- package/dist/templates/template-utils.js.map +1 -0
- package/dist/templates/trellis/config.yaml +90 -0
- package/dist/templates/trellis/gitignore.txt +32 -0
- package/dist/templates/trellis/index.d.ts +52 -0
- package/dist/templates/trellis/index.d.ts.map +1 -0
- package/dist/templates/trellis/index.js +97 -0
- package/dist/templates/trellis/index.js.map +1 -0
- package/dist/templates/trellis/scripts/__init__.py +5 -0
- package/dist/templates/trellis/scripts/add_session.py +547 -0
- package/dist/templates/trellis/scripts/common/__init__.py +92 -0
- package/dist/templates/trellis/scripts/common/active_task.py +626 -0
- package/dist/templates/trellis/scripts/common/cli_adapter.py +811 -0
- package/dist/templates/trellis/scripts/common/config.py +445 -0
- package/dist/templates/trellis/scripts/common/developer.py +190 -0
- package/dist/templates/trellis/scripts/common/git.py +31 -0
- package/dist/templates/trellis/scripts/common/git_context.py +106 -0
- package/dist/templates/trellis/scripts/common/io.py +37 -0
- package/dist/templates/trellis/scripts/common/log.py +45 -0
- package/dist/templates/trellis/scripts/common/packages_context.py +238 -0
- package/dist/templates/trellis/scripts/common/paths.py +447 -0
- package/dist/templates/trellis/scripts/common/safe_commit.py +285 -0
- package/dist/templates/trellis/scripts/common/session_context.py +821 -0
- package/dist/templates/trellis/scripts/common/task_context.py +223 -0
- package/dist/templates/trellis/scripts/common/task_queue.py +188 -0
- package/dist/templates/trellis/scripts/common/task_store.py +698 -0
- package/dist/templates/trellis/scripts/common/task_utils.py +274 -0
- package/dist/templates/trellis/scripts/common/tasks.py +112 -0
- package/dist/templates/trellis/scripts/common/trellis_config.py +131 -0
- package/dist/templates/trellis/scripts/common/types.py +110 -0
- package/dist/templates/trellis/scripts/common/workflow_phase.py +212 -0
- package/dist/templates/trellis/scripts/get_context.py +16 -0
- package/dist/templates/trellis/scripts/get_developer.py +26 -0
- package/dist/templates/trellis/scripts/hooks/linear_sync.py +243 -0
- package/dist/templates/trellis/scripts/init_developer.py +51 -0
- package/dist/templates/trellis/scripts/task.py +500 -0
- package/dist/templates/trellis/tasks/.gitkeep +0 -0
- package/dist/templates/trellis/workflow.md +690 -0
- package/dist/types/ai-tools.d.ts +95 -0
- package/dist/types/ai-tools.d.ts.map +1 -0
- package/dist/types/ai-tools.js +280 -0
- package/dist/types/ai-tools.js.map +1 -0
- package/dist/types/migration.d.ts +125 -0
- package/dist/types/migration.d.ts.map +1 -0
- package/dist/types/migration.js +8 -0
- package/dist/types/migration.js.map +1 -0
- package/dist/utils/compare-versions.d.ts +12 -0
- package/dist/utils/compare-versions.d.ts.map +1 -0
- package/dist/utils/compare-versions.js +86 -0
- package/dist/utils/compare-versions.js.map +1 -0
- package/dist/utils/cwd-guard.d.ts +38 -0
- package/dist/utils/cwd-guard.d.ts.map +1 -0
- package/dist/utils/cwd-guard.js +62 -0
- package/dist/utils/cwd-guard.js.map +1 -0
- package/dist/utils/file-writer.d.ts +36 -0
- package/dist/utils/file-writer.d.ts.map +1 -0
- package/dist/utils/file-writer.js +203 -0
- package/dist/utils/file-writer.js.map +1 -0
- package/dist/utils/manifest-prune.d.ts +61 -0
- package/dist/utils/manifest-prune.d.ts.map +1 -0
- package/dist/utils/manifest-prune.js +136 -0
- package/dist/utils/manifest-prune.js.map +1 -0
- package/dist/utils/posix.d.ts +13 -0
- package/dist/utils/posix.d.ts.map +1 -0
- package/dist/utils/posix.js +15 -0
- package/dist/utils/posix.js.map +1 -0
- package/dist/utils/project-detector.d.ts +46 -0
- package/dist/utils/project-detector.d.ts.map +1 -0
- package/dist/utils/project-detector.js +666 -0
- package/dist/utils/project-detector.js.map +1 -0
- package/dist/utils/proxy.d.ts +25 -0
- package/dist/utils/proxy.d.ts.map +1 -0
- package/dist/utils/proxy.js +60 -0
- package/dist/utils/proxy.js.map +1 -0
- package/dist/utils/task-json.d.ts +13 -0
- package/dist/utils/task-json.d.ts.map +1 -0
- package/dist/utils/task-json.js +12 -0
- package/dist/utils/task-json.js.map +1 -0
- package/dist/utils/template-fetcher.d.ts +150 -0
- package/dist/utils/template-fetcher.d.ts.map +1 -0
- package/dist/utils/template-fetcher.js +907 -0
- package/dist/utils/template-fetcher.js.map +1 -0
- package/dist/utils/template-hash.d.ts +123 -0
- package/dist/utils/template-hash.d.ts.map +1 -0
- package/dist/utils/template-hash.js +334 -0
- package/dist/utils/template-hash.js.map +1 -0
- package/dist/utils/uninstall-scrubbers.d.ts +66 -0
- package/dist/utils/uninstall-scrubbers.d.ts.map +1 -0
- package/dist/utils/uninstall-scrubbers.js +342 -0
- package/dist/utils/uninstall-scrubbers.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Task utility functions.
|
|
4
|
+
|
|
5
|
+
Provides:
|
|
6
|
+
is_safe_task_path - Validate task path is safe to operate on
|
|
7
|
+
find_task_by_name - Find task directory by name
|
|
8
|
+
resolve_task_dir - Resolve task directory from name, relative, or absolute path
|
|
9
|
+
archive_task_dir - Archive task to monthly directory
|
|
10
|
+
run_task_hooks - Run lifecycle hooks for task events
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import shutil
|
|
16
|
+
import sys
|
|
17
|
+
from datetime import datetime
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
from .paths import get_repo_root, get_tasks_dir
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# =============================================================================
|
|
24
|
+
# Path Safety
|
|
25
|
+
# =============================================================================
|
|
26
|
+
|
|
27
|
+
def is_safe_task_path(task_path: str, repo_root: Path | None = None) -> bool:
|
|
28
|
+
"""Check if a relative task path is safe to operate on.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
task_path: Task path (relative to repo_root).
|
|
32
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
True if safe, False if dangerous.
|
|
36
|
+
"""
|
|
37
|
+
if repo_root is None:
|
|
38
|
+
repo_root = get_repo_root()
|
|
39
|
+
|
|
40
|
+
normalized = task_path.replace("\\", "/")
|
|
41
|
+
|
|
42
|
+
# Check empty or null
|
|
43
|
+
if not normalized or normalized == "null":
|
|
44
|
+
print("Error: empty or null task path", file=sys.stderr)
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
# Reject absolute paths
|
|
48
|
+
if Path(task_path).is_absolute():
|
|
49
|
+
print(f"Error: absolute path not allowed: {task_path}", file=sys.stderr)
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
# Reject ".", "..", paths starting with "./" or "../", or containing ".."
|
|
53
|
+
if normalized in (".", "..") or normalized.startswith("./") or normalized.startswith("../") or ".." in normalized:
|
|
54
|
+
print(f"Error: path traversal not allowed: {task_path}", file=sys.stderr)
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
# Final check: ensure resolved path is not the repo root
|
|
58
|
+
abs_path = repo_root / Path(normalized)
|
|
59
|
+
if abs_path.exists():
|
|
60
|
+
try:
|
|
61
|
+
resolved = abs_path.resolve()
|
|
62
|
+
root_resolved = repo_root.resolve()
|
|
63
|
+
if resolved == root_resolved:
|
|
64
|
+
print(f"Error: path resolves to repo root: {task_path}", file=sys.stderr)
|
|
65
|
+
return False
|
|
66
|
+
except (OSError, IOError):
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
return True
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# =============================================================================
|
|
73
|
+
# Task Lookup
|
|
74
|
+
# =============================================================================
|
|
75
|
+
|
|
76
|
+
def find_task_by_name(task_name: str, tasks_dir: Path) -> Path | None:
|
|
77
|
+
"""Find task directory by name (exact or suffix match).
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
task_name: Task name to find.
|
|
81
|
+
tasks_dir: Tasks directory path.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Absolute path to task directory, or None if not found.
|
|
85
|
+
"""
|
|
86
|
+
if not task_name or not tasks_dir or not tasks_dir.is_dir():
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
# Try exact match first
|
|
90
|
+
exact_match = tasks_dir / task_name
|
|
91
|
+
if exact_match.is_dir():
|
|
92
|
+
return exact_match
|
|
93
|
+
|
|
94
|
+
# Try suffix match (e.g., "my-task" matches "01-21-my-task")
|
|
95
|
+
for d in tasks_dir.iterdir():
|
|
96
|
+
if d.is_dir() and d.name.endswith(f"-{task_name}"):
|
|
97
|
+
return d
|
|
98
|
+
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# =============================================================================
|
|
103
|
+
# Archive Operations
|
|
104
|
+
# =============================================================================
|
|
105
|
+
|
|
106
|
+
def archive_task_dir(task_dir_abs: Path, repo_root: Path | None = None) -> Path | None:
|
|
107
|
+
"""Archive a task directory to archive/{YYYY-MM}/.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
task_dir_abs: Absolute path to task directory.
|
|
111
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Path to archived directory, or None on error.
|
|
115
|
+
"""
|
|
116
|
+
if not task_dir_abs.is_dir():
|
|
117
|
+
print(f"Error: task directory not found: {task_dir_abs}", file=sys.stderr)
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
# Get tasks directory (parent of the task)
|
|
121
|
+
tasks_dir = task_dir_abs.parent
|
|
122
|
+
archive_dir = tasks_dir / "archive"
|
|
123
|
+
year_month = datetime.now().strftime("%Y-%m")
|
|
124
|
+
month_dir = archive_dir / year_month
|
|
125
|
+
|
|
126
|
+
# Create archive directory
|
|
127
|
+
try:
|
|
128
|
+
month_dir.mkdir(parents=True, exist_ok=True)
|
|
129
|
+
except (OSError, IOError) as e:
|
|
130
|
+
print(f"Error: Failed to create archive directory: {e}", file=sys.stderr)
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
# Move task to archive
|
|
134
|
+
task_name = task_dir_abs.name
|
|
135
|
+
dest = month_dir / task_name
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
shutil.move(str(task_dir_abs), str(dest))
|
|
139
|
+
except (OSError, IOError, shutil.Error) as e:
|
|
140
|
+
print(f"Error: Failed to move task to archive: {e}", file=sys.stderr)
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
return dest
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def archive_task_complete(
|
|
147
|
+
task_dir_abs: Path,
|
|
148
|
+
repo_root: Path | None = None
|
|
149
|
+
) -> dict[str, str]:
|
|
150
|
+
"""Complete archive workflow: archive directory.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
task_dir_abs: Absolute path to task directory.
|
|
154
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Dict with archive result info.
|
|
158
|
+
"""
|
|
159
|
+
if not task_dir_abs.is_dir():
|
|
160
|
+
print(f"Error: task directory not found: {task_dir_abs}", file=sys.stderr)
|
|
161
|
+
return {}
|
|
162
|
+
|
|
163
|
+
archive_dest = archive_task_dir(task_dir_abs, repo_root)
|
|
164
|
+
if archive_dest:
|
|
165
|
+
return {"archived_to": str(archive_dest)}
|
|
166
|
+
|
|
167
|
+
return {}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# =============================================================================
|
|
171
|
+
# Task Directory Resolution
|
|
172
|
+
# =============================================================================
|
|
173
|
+
|
|
174
|
+
def resolve_task_dir(target_dir: str, repo_root: Path) -> Path:
|
|
175
|
+
"""Resolve task directory to absolute path.
|
|
176
|
+
|
|
177
|
+
Supports:
|
|
178
|
+
- Absolute path: /path/to/task
|
|
179
|
+
- Relative path: .trellis/tasks/01-31-my-task
|
|
180
|
+
- Task name: my-task (uses find_task_by_name for lookup)
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
target_dir: Task directory specification.
|
|
184
|
+
repo_root: Repository root path.
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Resolved absolute path.
|
|
188
|
+
"""
|
|
189
|
+
if not target_dir:
|
|
190
|
+
return Path()
|
|
191
|
+
|
|
192
|
+
normalized = target_dir.replace("\\", "/")
|
|
193
|
+
while normalized.startswith("./"):
|
|
194
|
+
normalized = normalized[2:]
|
|
195
|
+
|
|
196
|
+
# Absolute path
|
|
197
|
+
if Path(target_dir).is_absolute():
|
|
198
|
+
return Path(target_dir)
|
|
199
|
+
|
|
200
|
+
# Relative path (contains path separator or starts with .trellis)
|
|
201
|
+
if "/" in normalized or normalized.startswith(".trellis"):
|
|
202
|
+
return repo_root / Path(normalized)
|
|
203
|
+
|
|
204
|
+
# Task name - try to find in tasks directory
|
|
205
|
+
tasks_dir = get_tasks_dir(repo_root)
|
|
206
|
+
found = find_task_by_name(target_dir, tasks_dir)
|
|
207
|
+
if found:
|
|
208
|
+
return found
|
|
209
|
+
|
|
210
|
+
# Fallback to treating as relative path
|
|
211
|
+
return repo_root / Path(normalized)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
# =============================================================================
|
|
215
|
+
# Lifecycle Hooks
|
|
216
|
+
# =============================================================================
|
|
217
|
+
|
|
218
|
+
def run_task_hooks(event: str, task_json_path: Path, repo_root: Path) -> None:
|
|
219
|
+
"""Run lifecycle hooks for a task event.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
event: Event name (e.g. "after_create").
|
|
223
|
+
task_json_path: Absolute path to the task's task.json.
|
|
224
|
+
repo_root: Repository root for cwd and config lookup.
|
|
225
|
+
"""
|
|
226
|
+
import os
|
|
227
|
+
import subprocess
|
|
228
|
+
|
|
229
|
+
from .config import get_hooks
|
|
230
|
+
from .log import Colors, colored
|
|
231
|
+
|
|
232
|
+
commands = get_hooks(event, repo_root)
|
|
233
|
+
if not commands:
|
|
234
|
+
return
|
|
235
|
+
|
|
236
|
+
env = {**os.environ, "TASK_JSON_PATH": str(task_json_path)}
|
|
237
|
+
|
|
238
|
+
for cmd in commands:
|
|
239
|
+
try:
|
|
240
|
+
result = subprocess.run(
|
|
241
|
+
cmd,
|
|
242
|
+
shell=True,
|
|
243
|
+
cwd=repo_root,
|
|
244
|
+
env=env,
|
|
245
|
+
capture_output=True,
|
|
246
|
+
text=True,
|
|
247
|
+
encoding="utf-8",
|
|
248
|
+
errors="replace",
|
|
249
|
+
)
|
|
250
|
+
if result.returncode != 0:
|
|
251
|
+
print(
|
|
252
|
+
colored(f"[WARN] Hook failed ({event}): {cmd}", Colors.YELLOW),
|
|
253
|
+
file=sys.stderr,
|
|
254
|
+
)
|
|
255
|
+
if result.stderr.strip():
|
|
256
|
+
print(f" {result.stderr.strip()}", file=sys.stderr)
|
|
257
|
+
except Exception as e:
|
|
258
|
+
print(
|
|
259
|
+
colored(f"[WARN] Hook error ({event}): {cmd} — {e}", Colors.YELLOW),
|
|
260
|
+
file=sys.stderr,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
# =============================================================================
|
|
265
|
+
# Main Entry (for testing)
|
|
266
|
+
# =============================================================================
|
|
267
|
+
|
|
268
|
+
if __name__ == "__main__":
|
|
269
|
+
repo = get_repo_root()
|
|
270
|
+
tasks = get_tasks_dir(repo)
|
|
271
|
+
|
|
272
|
+
print(f"Tasks dir: {tasks}")
|
|
273
|
+
print(f"is_safe_task_path('.trellis/tasks/test'): {is_safe_task_path('.trellis/tasks/test', repo)}")
|
|
274
|
+
print(f"is_safe_task_path('../test'): {is_safe_task_path('../test', repo)}")
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Task data access layer.
|
|
3
|
+
|
|
4
|
+
Single source of truth for loading and iterating task directories.
|
|
5
|
+
Replaces scattered task.json parsing across 9+ files.
|
|
6
|
+
|
|
7
|
+
Provides:
|
|
8
|
+
load_task — Load a single task by directory path
|
|
9
|
+
iter_active_tasks — Iterate all non-archived tasks (sorted)
|
|
10
|
+
get_all_statuses — Get {dir_name: status} map for children progress
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from collections.abc import Iterator
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
from .io import read_json
|
|
19
|
+
from .paths import FILE_TASK_JSON
|
|
20
|
+
from .types import TaskInfo
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def load_task(task_dir: Path) -> TaskInfo | None:
|
|
24
|
+
"""Load task from a directory containing task.json.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
task_dir: Absolute path to the task directory.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
TaskInfo if task.json exists and is valid, None otherwise.
|
|
31
|
+
"""
|
|
32
|
+
task_json = task_dir / FILE_TASK_JSON
|
|
33
|
+
if not task_json.is_file():
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
data = read_json(task_json)
|
|
37
|
+
if not data:
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
return TaskInfo(
|
|
41
|
+
dir_name=task_dir.name,
|
|
42
|
+
directory=task_dir,
|
|
43
|
+
title=data.get("title") or data.get("name") or "unknown",
|
|
44
|
+
status=data.get("status", "unknown"),
|
|
45
|
+
assignee=data.get("assignee", ""),
|
|
46
|
+
priority=data.get("priority", "P2"),
|
|
47
|
+
children=tuple(data.get("children", [])),
|
|
48
|
+
parent=data.get("parent"),
|
|
49
|
+
package=data.get("package"),
|
|
50
|
+
raw=data,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def iter_active_tasks(tasks_dir: Path) -> Iterator[TaskInfo]:
|
|
55
|
+
"""Iterate all active (non-archived) tasks, sorted by directory name.
|
|
56
|
+
|
|
57
|
+
Skips the "archive" directory and directories without valid task.json.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
tasks_dir: Path to the tasks directory.
|
|
61
|
+
|
|
62
|
+
Yields:
|
|
63
|
+
TaskInfo for each valid task.
|
|
64
|
+
"""
|
|
65
|
+
if not tasks_dir.is_dir():
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
for d in sorted(tasks_dir.iterdir()):
|
|
69
|
+
if not d.is_dir() or d.name == "archive":
|
|
70
|
+
continue
|
|
71
|
+
info = load_task(d)
|
|
72
|
+
if info is not None:
|
|
73
|
+
yield info
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def get_all_statuses(tasks_dir: Path) -> dict[str, str]:
|
|
77
|
+
"""Get a {dir_name: status} mapping for all active tasks.
|
|
78
|
+
|
|
79
|
+
Useful for computing children progress without loading full TaskInfo.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
tasks_dir: Path to the tasks directory.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
Dict mapping directory names to status strings.
|
|
86
|
+
"""
|
|
87
|
+
return {t.dir_name: t.status for t in iter_active_tasks(tasks_dir)}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def children_progress(
|
|
91
|
+
children: tuple[str, ...] | list[str],
|
|
92
|
+
all_statuses: dict[str, str],
|
|
93
|
+
) -> str:
|
|
94
|
+
"""Format children progress string like " [2/3 done]".
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
children: List of child directory names.
|
|
98
|
+
all_statuses: Status map from get_all_statuses().
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Formatted string, or "" if no children.
|
|
102
|
+
"""
|
|
103
|
+
if not children:
|
|
104
|
+
return ""
|
|
105
|
+
# A child missing from active statuses has been archived (cmd_archive
|
|
106
|
+
# sets status=completed before moving the dir). Count it as done so
|
|
107
|
+
# parent progress doesn't regress when children are archived.
|
|
108
|
+
done = sum(
|
|
109
|
+
1 for c in children
|
|
110
|
+
if c not in all_statuses or all_statuses.get(c) in ("completed", "done")
|
|
111
|
+
)
|
|
112
|
+
return f" [{done}/{len(children)} done]"
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Standalone reader for .trellis/config.yaml.
|
|
4
|
+
|
|
5
|
+
Mirrors a minimal subset of common.config so callers (hooks, workflow_phase)
|
|
6
|
+
can read configuration without importing the full task/repo helpers. Returns
|
|
7
|
+
an empty dict on missing/malformed files so callers stay simple.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
CONFIG_REL_PATH = ".trellis/config.yaml"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _unquote(value: str) -> str:
|
|
20
|
+
if len(value) >= 2 and value[0] == value[-1] and value[0] in ('"', "'"):
|
|
21
|
+
return value[1:-1]
|
|
22
|
+
return value
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _strip_inline_comment(value: str) -> str:
|
|
26
|
+
"""Strip ` # …` inline comments while preserving `#` inside quoted strings.
|
|
27
|
+
|
|
28
|
+
YAML treats ` #` (space-hash) as a comment opener; bare `#` inside a token
|
|
29
|
+
is part of the value. Quoted strings are immune.
|
|
30
|
+
"""
|
|
31
|
+
in_quote: str | None = None
|
|
32
|
+
for idx, ch in enumerate(value):
|
|
33
|
+
if in_quote:
|
|
34
|
+
if ch == in_quote:
|
|
35
|
+
in_quote = None
|
|
36
|
+
continue
|
|
37
|
+
if ch in ('"', "'"):
|
|
38
|
+
in_quote = ch
|
|
39
|
+
continue
|
|
40
|
+
if ch == "#" and (idx == 0 or value[idx - 1].isspace()):
|
|
41
|
+
return value[:idx]
|
|
42
|
+
return value
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _next_content_line(lines: list[str], start: int) -> tuple[int, str]:
|
|
46
|
+
i = start
|
|
47
|
+
while i < len(lines):
|
|
48
|
+
stripped = lines[i].strip()
|
|
49
|
+
if stripped and not stripped.startswith("#"):
|
|
50
|
+
return i, lines[i]
|
|
51
|
+
i += 1
|
|
52
|
+
return i, ""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _parse_yaml_block(
|
|
56
|
+
lines: list[str], start: int, min_indent: int, target: dict
|
|
57
|
+
) -> int:
|
|
58
|
+
i = start
|
|
59
|
+
current_list: list | None = None
|
|
60
|
+
|
|
61
|
+
while i < len(lines):
|
|
62
|
+
line = lines[i]
|
|
63
|
+
stripped = line.strip()
|
|
64
|
+
|
|
65
|
+
if not stripped or stripped.startswith("#"):
|
|
66
|
+
i += 1
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
indent = len(line) - len(line.lstrip())
|
|
70
|
+
if indent < min_indent:
|
|
71
|
+
break
|
|
72
|
+
|
|
73
|
+
if stripped.startswith("- "):
|
|
74
|
+
if current_list is not None:
|
|
75
|
+
current_list.append(_unquote(stripped[2:].strip()))
|
|
76
|
+
i += 1
|
|
77
|
+
elif ":" in stripped:
|
|
78
|
+
key, _, value = stripped.partition(":")
|
|
79
|
+
key = key.strip()
|
|
80
|
+
value = _strip_inline_comment(value).strip()
|
|
81
|
+
value = _unquote(value)
|
|
82
|
+
current_list = None
|
|
83
|
+
|
|
84
|
+
if value:
|
|
85
|
+
target[key] = value
|
|
86
|
+
i += 1
|
|
87
|
+
else:
|
|
88
|
+
next_i, next_line = _next_content_line(lines, i + 1)
|
|
89
|
+
if next_i >= len(lines):
|
|
90
|
+
target[key] = {}
|
|
91
|
+
i = next_i
|
|
92
|
+
elif next_line.strip().startswith("- "):
|
|
93
|
+
current_list = []
|
|
94
|
+
target[key] = current_list
|
|
95
|
+
i += 1
|
|
96
|
+
else:
|
|
97
|
+
next_indent = len(next_line) - len(next_line.lstrip())
|
|
98
|
+
if next_indent > indent:
|
|
99
|
+
nested: dict = {}
|
|
100
|
+
target[key] = nested
|
|
101
|
+
i = _parse_yaml_block(lines, i + 1, next_indent, nested)
|
|
102
|
+
else:
|
|
103
|
+
target[key] = {}
|
|
104
|
+
i += 1
|
|
105
|
+
else:
|
|
106
|
+
i += 1
|
|
107
|
+
|
|
108
|
+
return i
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def parse_simple_yaml(content: str) -> dict:
|
|
112
|
+
"""Parse a small subset of YAML. See common.config for full doc."""
|
|
113
|
+
lines = content.splitlines()
|
|
114
|
+
result: dict = {}
|
|
115
|
+
_parse_yaml_block(lines, 0, 0, result)
|
|
116
|
+
return result
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def read_trellis_config(repo_root: Optional[Path] = None) -> dict:
|
|
120
|
+
"""Read .trellis/config.yaml. Returns {} on missing or malformed file."""
|
|
121
|
+
root = repo_root or Path.cwd()
|
|
122
|
+
config_file = root / CONFIG_REL_PATH
|
|
123
|
+
try:
|
|
124
|
+
content = config_file.read_text(encoding="utf-8")
|
|
125
|
+
except (FileNotFoundError, OSError):
|
|
126
|
+
return {}
|
|
127
|
+
try:
|
|
128
|
+
parsed = parse_simple_yaml(content)
|
|
129
|
+
except Exception:
|
|
130
|
+
return {}
|
|
131
|
+
return parsed if isinstance(parsed, dict) else {}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core type definitions for Trellis task data.
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
TaskData — TypedDict for task.json shape (read-path type hints only)
|
|
6
|
+
TaskInfo — Frozen dataclass for loaded task (the public API type)
|
|
7
|
+
AgentRecord — TypedDict for registry.json agent entries
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import TypedDict
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# =============================================================================
|
|
18
|
+
# task.json shape (TypedDict — used only for read-path type hints)
|
|
19
|
+
# =============================================================================
|
|
20
|
+
|
|
21
|
+
class TaskData(TypedDict, total=False):
|
|
22
|
+
"""Shape of task.json on disk.
|
|
23
|
+
|
|
24
|
+
Used only for type annotations when reading task.json.
|
|
25
|
+
Writes must use the original dict to avoid losing unknown fields.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
id: str
|
|
29
|
+
name: str
|
|
30
|
+
title: str
|
|
31
|
+
description: str
|
|
32
|
+
status: str
|
|
33
|
+
dev_type: str
|
|
34
|
+
scope: str | None
|
|
35
|
+
package: str | None
|
|
36
|
+
priority: str
|
|
37
|
+
creator: str
|
|
38
|
+
assignee: str
|
|
39
|
+
createdAt: str
|
|
40
|
+
completedAt: str | None
|
|
41
|
+
branch: str | None
|
|
42
|
+
base_branch: str | None
|
|
43
|
+
worktree_path: str | None
|
|
44
|
+
commit: str | None
|
|
45
|
+
pr_url: str | None
|
|
46
|
+
subtasks: list[str]
|
|
47
|
+
children: list[str]
|
|
48
|
+
parent: str | None
|
|
49
|
+
relatedFiles: list[str]
|
|
50
|
+
notes: str
|
|
51
|
+
meta: dict
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# =============================================================================
|
|
55
|
+
# Loaded task object (frozen dataclass — the public API type)
|
|
56
|
+
# =============================================================================
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True)
|
|
59
|
+
class TaskInfo:
|
|
60
|
+
"""Immutable view of a loaded task.
|
|
61
|
+
|
|
62
|
+
Created by load_task() / iter_active_tasks().
|
|
63
|
+
Contains the commonly accessed fields; the original dict
|
|
64
|
+
is preserved in `raw` for write-back and uncommon field access.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
dir_name: str
|
|
68
|
+
directory: Path
|
|
69
|
+
title: str
|
|
70
|
+
status: str
|
|
71
|
+
assignee: str
|
|
72
|
+
priority: str
|
|
73
|
+
children: tuple[str, ...]
|
|
74
|
+
parent: str | None
|
|
75
|
+
package: str | None
|
|
76
|
+
raw: dict # original dict — use for writes and uncommon fields
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def name(self) -> str:
|
|
80
|
+
"""Task name (id or name field)."""
|
|
81
|
+
return self.raw.get("name") or self.raw.get("id") or self.dir_name
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def description(self) -> str:
|
|
85
|
+
return self.raw.get("description", "")
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def branch(self) -> str | None:
|
|
89
|
+
return self.raw.get("branch")
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def meta(self) -> dict:
|
|
93
|
+
return self.raw.get("meta", {})
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# =============================================================================
|
|
97
|
+
# registry.json agent entry
|
|
98
|
+
# =============================================================================
|
|
99
|
+
|
|
100
|
+
class AgentRecord(TypedDict, total=False):
|
|
101
|
+
"""Shape of an agent entry in registry.json."""
|
|
102
|
+
|
|
103
|
+
id: str
|
|
104
|
+
pid: int
|
|
105
|
+
task_dir: str
|
|
106
|
+
worktree_path: str
|
|
107
|
+
branch: str
|
|
108
|
+
platform: str
|
|
109
|
+
started_at: str
|
|
110
|
+
status: str
|