@chinhae/atw-cli 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/COPYRIGHT +14 -0
- package/LICENSE +77 -0
- package/README.md +122 -0
- package/bin/atw.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 +299 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/commands/ablate.d.ts +14 -0
- package/dist/commands/ablate.d.ts.map +1 -0
- package/dist/commands/ablate.js +307 -0
- package/dist/commands/ablate.js.map +1 -0
- package/dist/commands/channel/adapters/claude.d.ts +53 -0
- package/dist/commands/channel/adapters/claude.d.ts.map +1 -0
- package/dist/commands/channel/adapters/claude.js +225 -0
- package/dist/commands/channel/adapters/claude.js.map +1 -0
- package/dist/commands/channel/adapters/codex.d.ts +93 -0
- package/dist/commands/channel/adapters/codex.d.ts.map +1 -0
- package/dist/commands/channel/adapters/codex.js +573 -0
- package/dist/commands/channel/adapters/codex.js.map +1 -0
- package/dist/commands/channel/adapters/index.d.ts +94 -0
- package/dist/commands/channel/adapters/index.d.ts.map +1 -0
- package/dist/commands/channel/adapters/index.js +116 -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 +158 -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 +311 -0
- package/dist/commands/channel/context-loader.js.map +1 -0
- 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/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/guard.d.ts +150 -0
- package/dist/commands/channel/guard.d.ts.map +1 -0
- package/dist/commands/channel/guard.js +479 -0
- package/dist/commands/channel/guard.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 +535 -0
- package/dist/commands/channel/index.js.map +1 -0
- package/dist/commands/channel/interrupt.d.ts +10 -0
- package/dist/commands/channel/interrupt.d.ts.map +1 -0
- package/dist/commands/channel/interrupt.js +22 -0
- package/dist/commands/channel/interrupt.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 +130 -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 +15 -0
- package/dist/commands/channel/messages.d.ts.map +1 -0
- package/dist/commands/channel/messages.js +245 -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 +30 -0
- package/dist/commands/channel/run.d.ts.map +1 -0
- package/dist/commands/channel/run.js +130 -0
- package/dist/commands/channel/run.js.map +1 -0
- package/dist/commands/channel/send.d.ts +11 -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 +43 -0
- package/dist/commands/channel/spawn.d.ts.map +1 -0
- package/dist/commands/channel/spawn.js +247 -0
- package/dist/commands/channel/spawn.js.map +1 -0
- package/dist/commands/channel/store/events.d.ts +22 -0
- package/dist/commands/channel/store/events.d.ts.map +1 -0
- package/dist/commands/channel/store/events.js +43 -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 +77 -0
- package/dist/commands/channel/store/paths.d.ts.map +1 -0
- package/dist/commands/channel/store/paths.js +272 -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 +153 -0
- package/dist/commands/channel/store/watch.js.map +1 -0
- package/dist/commands/channel/supervisor/idle.d.ts +45 -0
- package/dist/commands/channel/supervisor/idle.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/idle.js +70 -0
- package/dist/commands/channel/supervisor/idle.js.map +1 -0
- package/dist/commands/channel/supervisor/inbox.d.ts +30 -0
- package/dist/commands/channel/supervisor/inbox.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/inbox.js +160 -0
- package/dist/commands/channel/supervisor/inbox.js.map +1 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts +68 -0
- package/dist/commands/channel/supervisor/shutdown.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/shutdown.js +146 -0
- package/dist/commands/channel/supervisor/shutdown.js.map +1 -0
- package/dist/commands/channel/supervisor/stdout.d.ts +71 -0
- package/dist/commands/channel/supervisor/stdout.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/stdout.js +229 -0
- package/dist/commands/channel/supervisor/stdout.js.map +1 -0
- package/dist/commands/channel/supervisor/turns.d.ts +31 -0
- package/dist/commands/channel/supervisor/turns.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/turns.js +45 -0
- package/dist/commands/channel/supervisor/turns.js.map +1 -0
- package/dist/commands/channel/supervisor/warning.d.ts +48 -0
- package/dist/commands/channel/supervisor/warning.d.ts.map +1 -0
- package/dist/commands/channel/supervisor/warning.js +77 -0
- package/dist/commands/channel/supervisor/warning.js.map +1 -0
- package/dist/commands/channel/supervisor.d.ts +91 -0
- package/dist/commands/channel/supervisor.d.ts.map +1 -0
- package/dist/commands/channel/supervisor.js +463 -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 +17 -0
- package/dist/commands/channel/wait.d.ts.map +1 -0
- package/dist/commands/channel/wait.js +75 -0
- package/dist/commands/channel/wait.js.map +1 -0
- package/dist/commands/init.d.ts +71 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +1612 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mem.d.ts +30 -0
- package/dist/commands/mem.d.ts.map +1 -0
- package/dist/commands/mem.js +423 -0
- package/dist/commands/mem.js.map +1 -0
- package/dist/commands/uninstall.d.ts +36 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +205 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +133 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +2255 -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/commands/workflow.d.ts +35 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +232 -0
- package/dist/commands/workflow.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 +11 -0
- package/dist/configurators/antigravity.js.map +1 -0
- package/dist/configurators/claude.d.ts +23 -0
- package/dist/configurators/claude.d.ts.map +1 -0
- package/dist/configurators/claude.js +123 -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 +24 -0
- package/dist/configurators/codebuddy.js.map +1 -0
- package/dist/configurators/codex.d.ts +57 -0
- package/dist/configurators/codex.d.ts.map +1 -0
- package/dist/configurators/codex.js +170 -0
- package/dist/configurators/codex.js.map +1 -0
- package/dist/configurators/copilot.d.ts +18 -0
- package/dist/configurators/copilot.d.ts.map +1 -0
- package/dist/configurators/copilot.js +50 -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 +23 -0
- package/dist/configurators/cursor.js.map +1 -0
- package/dist/configurators/devin.d.ts +8 -0
- package/dist/configurators/devin.d.ts.map +1 -0
- package/dist/configurators/devin.js +12 -0
- package/dist/configurators/devin.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 +24 -0
- package/dist/configurators/droid.js.map +1 -0
- package/dist/configurators/dsh.d.ts +29 -0
- package/dist/configurators/dsh.d.ts.map +1 -0
- package/dist/configurators/dsh.js +64 -0
- package/dist/configurators/dsh.js.map +1 -0
- package/dist/configurators/gemini.d.ts +19 -0
- package/dist/configurators/gemini.d.ts.map +1 -0
- package/dist/configurators/gemini.js +40 -0
- package/dist/configurators/gemini.js.map +1 -0
- package/dist/configurators/grok.d.ts +17 -0
- package/dist/configurators/grok.d.ts.map +1 -0
- package/dist/configurators/grok.js +38 -0
- package/dist/configurators/grok.js.map +1 -0
- package/dist/configurators/index.d.ts +68 -0
- package/dist/configurators/index.d.ts.map +1 -0
- package/dist/configurators/index.js +191 -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 +11 -0
- package/dist/configurators/kilo.js.map +1 -0
- package/dist/configurators/kimi.d.ts +26 -0
- package/dist/configurators/kimi.d.ts.map +1 -0
- package/dist/configurators/kimi.js +74 -0
- package/dist/configurators/kimi.js.map +1 -0
- package/dist/configurators/kiro.d.ts +11 -0
- package/dist/configurators/kiro.d.ts.map +1 -0
- package/dist/configurators/kiro.js +30 -0
- package/dist/configurators/kiro.js.map +1 -0
- package/dist/configurators/omp.d.ts +6 -0
- package/dist/configurators/omp.d.ts.map +1 -0
- package/dist/configurators/omp.js +28 -0
- package/dist/configurators/omp.js.map +1 -0
- package/dist/configurators/opencode.d.ts +5 -0
- package/dist/configurators/opencode.d.ts.map +1 -0
- package/dist/configurators/opencode.js +80 -0
- package/dist/configurators/opencode.js.map +1 -0
- package/dist/configurators/pi.d.ts +5 -0
- package/dist/configurators/pi.d.ts.map +1 -0
- package/dist/configurators/pi.js +39 -0
- package/dist/configurators/pi.js.map +1 -0
- package/dist/configurators/qoder.d.ts +12 -0
- package/dist/configurators/qoder.d.ts.map +1 -0
- package/dist/configurators/qoder.js +30 -0
- package/dist/configurators/qoder.js.map +1 -0
- package/dist/configurators/reasonix.d.ts +17 -0
- package/dist/configurators/reasonix.d.ts.map +1 -0
- package/dist/configurators/reasonix.js +37 -0
- package/dist/configurators/reasonix.js.map +1 -0
- package/dist/configurators/shared.d.ts +196 -0
- package/dist/configurators/shared.d.ts.map +1 -0
- package/dist/configurators/shared.js +600 -0
- package/dist/configurators/shared.js.map +1 -0
- package/dist/configurators/snow.d.ts +25 -0
- package/dist/configurators/snow.d.ts.map +1 -0
- package/dist/configurators/snow.js +69 -0
- package/dist/configurators/snow.js.map +1 -0
- package/dist/configurators/trae.d.ts +16 -0
- package/dist/configurators/trae.d.ts.map +1 -0
- package/dist/configurators/trae.js +34 -0
- package/dist/configurators/trae.js.map +1 -0
- package/dist/configurators/workflow.d.ts +51 -0
- package/dist/configurators/workflow.d.ts.map +1 -0
- package/dist/configurators/workflow.js +210 -0
- package/dist/configurators/workflow.js.map +1 -0
- package/dist/configurators/zcode.d.ts +19 -0
- package/dist/configurators/zcode.d.ts.map +1 -0
- package/dist/configurators/zcode.js +51 -0
- package/dist/configurators/zcode.js.map +1 -0
- package/dist/constants/paths.d.ts +74 -0
- package/dist/constants/paths.d.ts.map +1 -0
- package/dist/constants/paths.js +83 -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 +65 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +202 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/templates/atw/agents/implement-agent.md +69 -0
- package/dist/templates/atw/agents/review.md +68 -0
- package/dist/templates/atw/config.yaml +158 -0
- package/dist/templates/atw/gitattributes.txt +9 -0
- package/dist/templates/atw/gitignore.txt +32 -0
- package/dist/templates/atw/index.d.ts +70 -0
- package/dist/templates/atw/index.d.ts.map +1 -0
- package/dist/templates/atw/index.js +137 -0
- package/dist/templates/atw/index.js.map +1 -0
- package/dist/templates/atw/scripts/__init__.py +5 -0
- package/dist/templates/atw/scripts/add_session.py +1545 -0
- package/dist/templates/atw/scripts/common/__init__.py +94 -0
- package/dist/templates/atw/scripts/common/active_task.py +857 -0
- package/dist/templates/atw/scripts/common/atw_config.py +239 -0
- package/dist/templates/atw/scripts/common/cli_adapter.py +949 -0
- package/dist/templates/atw/scripts/common/config.py +482 -0
- package/dist/templates/atw/scripts/common/developer.py +192 -0
- package/dist/templates/atw/scripts/common/git.py +203 -0
- package/dist/templates/atw/scripts/common/git_context.py +106 -0
- package/dist/templates/atw/scripts/common/io.py +160 -0
- package/dist/templates/atw/scripts/common/log.py +45 -0
- package/dist/templates/atw/scripts/common/packages_context.py +238 -0
- package/dist/templates/atw/scripts/common/paths.py +543 -0
- package/dist/templates/atw/scripts/common/safe_commit.py +322 -0
- package/dist/templates/atw/scripts/common/session_context.py +892 -0
- package/dist/templates/atw/scripts/common/task_context.py +470 -0
- package/dist/templates/atw/scripts/common/task_queue.py +188 -0
- package/dist/templates/atw/scripts/common/task_store.py +1940 -0
- package/dist/templates/atw/scripts/common/task_utils.py +498 -0
- package/dist/templates/atw/scripts/common/tasks.py +122 -0
- package/dist/templates/atw/scripts/common/types.py +110 -0
- package/dist/templates/atw/scripts/common/workflow_phase.py +242 -0
- package/dist/templates/atw/scripts/get_context.py +16 -0
- package/dist/templates/atw/scripts/get_developer.py +26 -0
- package/dist/templates/atw/scripts/github_sync.py +391 -0
- package/dist/templates/atw/scripts/hooks/linear_sync.py +243 -0
- package/dist/templates/atw/scripts/init_developer.py +51 -0
- package/dist/templates/atw/scripts/task.py +833 -0
- package/dist/templates/atw/scripts/tickets.py +495 -0
- package/dist/templates/atw/tasks/.gitkeep +0 -0
- package/dist/templates/atw/workflow.md +754 -0
- package/dist/templates/claude/agents/atw-implement-agent.md +107 -0
- package/dist/templates/claude/agents/atw-review.md +113 -0
- package/dist/templates/claude/hooks/statusline.py +332 -0
- package/dist/templates/claude/index.d.ts +31 -0
- package/dist/templates/claude/index.d.ts.map +1 -0
- package/dist/templates/claude/index.js +57 -0
- package/dist/templates/claude/index.js.map +1 -0
- package/dist/templates/claude/settings.json +73 -0
- package/dist/templates/codebuddy/agents/atw-implement-agent.md +107 -0
- package/dist/templates/codebuddy/agents/atw-review.md +113 -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 +69 -0
- package/dist/templates/codex/agents/atw-implement-agent.toml +37 -0
- package/dist/templates/codex/agents/atw-review.toml +56 -0
- package/dist/templates/codex/config.toml +39 -0
- package/dist/templates/codex/hooks/session-start.py +514 -0
- package/dist/templates/codex/hooks.json +27 -0
- package/dist/templates/codex/index.d.ts +35 -0
- package/dist/templates/codex/index.d.ts.map +1 -0
- package/dist/templates/codex/index.js +67 -0
- package/dist/templates/codex/index.js.map +1 -0
- package/dist/templates/common/bundled-skills/atw-askme/SKILL.md +7 -0
- package/dist/templates/common/bundled-skills/atw-askme/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-askme-with-docs/SKILL.md +7 -0
- package/dist/templates/common/bundled-skills/atw-askme-with-docs/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-channel/SKILL.md +67 -0
- package/dist/templates/common/bundled-skills/atw-channel/references/command-reference.md +480 -0
- package/dist/templates/common/bundled-skills/atw-channel/references/forum.md +233 -0
- package/dist/templates/common/bundled-skills/atw-channel/references/progress-debugging.md +226 -0
- package/dist/templates/common/bundled-skills/atw-channel/references/workers.md +274 -0
- package/dist/templates/common/bundled-skills/atw-channel/references/workflows.md +125 -0
- package/dist/templates/common/bundled-skills/atw-code-review/SKILL.md +113 -0
- package/dist/templates/common/bundled-skills/atw-code-review/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-codebase-design/DEEPENING.md +37 -0
- package/dist/templates/common/bundled-skills/atw-codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/dist/templates/common/bundled-skills/atw-codebase-design/SKILL.md +114 -0
- package/dist/templates/common/bundled-skills/atw-codebase-design/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-diagnosing-bugs/SKILL.md +138 -0
- package/dist/templates/common/bundled-skills/atw-diagnosing-bugs/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
- package/dist/templates/common/bundled-skills/atw-domain-modeling/ADR-FORMAT.md +47 -0
- package/dist/templates/common/bundled-skills/atw-domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/dist/templates/common/bundled-skills/atw-domain-modeling/SKILL.md +74 -0
- package/dist/templates/common/bundled-skills/atw-domain-modeling/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-handoff/SKILL.md +16 -0
- package/dist/templates/common/bundled-skills/atw-handoff/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-implement/SKILL.md +21 -0
- package/dist/templates/common/bundled-skills/atw-implement/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/dist/templates/common/bundled-skills/atw-improve-codebase-architecture/SKILL.md +71 -0
- package/dist/templates/common/bundled-skills/atw-improve-codebase-architecture/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/SKILL.md +130 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/references/domain.md +51 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw-local.md +133 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-atw.md +109 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-github.md +45 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-gitlab.md +46 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/references/issue-tracker-local.md +30 -0
- package/dist/templates/common/bundled-skills/atw-init-repo/references/triage-labels.md +15 -0
- package/dist/templates/common/bundled-skills/atw-interview/SKILL.md +22 -0
- package/dist/templates/common/bundled-skills/atw-interview/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-map/SKILL.md +128 -0
- package/dist/templates/common/bundled-skills/atw-map/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-merge/SKILL.md +14 -0
- package/dist/templates/common/bundled-skills/atw-merge/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-meta/SKILL.md +85 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/add-project-local-conventions.md +83 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-agents.md +55 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-context-loading.md +80 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-hooks.md +57 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-skills-or-commands.md +123 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-spec-structure.md +83 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-task-lifecycle.md +91 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/change-workflow.md +59 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/customize-local/overview.md +55 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/bundled-skills.md +159 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/context-injection.md +68 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/generated-files.md +80 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/multi-agent-channel.md +69 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/overview.md +51 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/spec-system.md +102 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/task-system.md +126 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/workflow.md +79 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/local-architecture/workspace-memory.md +71 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/platform-files/agents.md +80 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/platform-files/hooks-and-settings.md +72 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/platform-files/overview.md +59 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/platform-files/platform-map.md +112 -0
- package/dist/templates/common/bundled-skills/atw-meta/references/platform-files/skills-and-commands.md +86 -0
- package/dist/templates/common/bundled-skills/atw-prototype/LOGIC.md +67 -0
- package/dist/templates/common/bundled-skills/atw-prototype/SKILL.md +26 -0
- package/dist/templates/common/bundled-skills/atw-prototype/UI.md +112 -0
- package/dist/templates/common/bundled-skills/atw-prototype/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-research/SKILL.md +14 -0
- package/dist/templates/common/bundled-skills/atw-research/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-session-insight/SKILL.md +81 -0
- package/dist/templates/common/bundled-skills/atw-session-insight/references/cli-quick-reference.md +65 -0
- package/dist/templates/common/bundled-skills/atw-session-insight/references/triggering-patterns.md +93 -0
- package/dist/templates/common/bundled-skills/atw-spec/SKILL.md +75 -0
- package/dist/templates/common/bundled-skills/atw-spec/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-spec-bootstrap/SKILL.md +41 -0
- package/dist/templates/common/bundled-skills/atw-spec-bootstrap/references/mcp-setup.md +90 -0
- package/dist/templates/common/bundled-skills/atw-spec-bootstrap/references/repository-analysis.md +59 -0
- package/dist/templates/common/bundled-skills/atw-spec-bootstrap/references/spec-task-planning.md +61 -0
- package/dist/templates/common/bundled-skills/atw-spec-bootstrap/references/spec-writing.md +70 -0
- package/dist/templates/common/bundled-skills/atw-tdd/SKILL.md +38 -0
- package/dist/templates/common/bundled-skills/atw-tdd/agents/openai.yaml +3 -0
- package/dist/templates/common/bundled-skills/atw-tdd/mocking.md +59 -0
- package/dist/templates/common/bundled-skills/atw-tdd/tests.md +77 -0
- package/dist/templates/common/bundled-skills/atw-tickets/SKILL.md +105 -0
- package/dist/templates/common/bundled-skills/atw-tickets/agents/openai.yaml +5 -0
- package/dist/templates/common/bundled-skills/atw-triage/AGENT-BRIEF.md +207 -0
- package/dist/templates/common/bundled-skills/atw-triage/OUT-OF-SCOPE.md +105 -0
- package/dist/templates/common/bundled-skills/atw-triage/SKILL.md +112 -0
- package/dist/templates/common/bundled-skills/atw-triage/agents/openai.yaml +5 -0
- package/dist/templates/common/commands/continue.md +55 -0
- package/dist/templates/common/commands/finish-work.md +69 -0
- package/dist/templates/common/commands/start.md +68 -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 +44 -0
- package/dist/templates/common/skills/brainstorm.md +194 -0
- package/dist/templates/common/skills/update-spec.md +351 -0
- package/dist/templates/copilot/copilot-instructions.md +11 -0
- package/dist/templates/copilot/hooks/session-start.py +510 -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 +48 -0
- package/dist/templates/copilot/index.js.map +1 -0
- package/dist/templates/cursor/agents/atw-implement-agent.md +106 -0
- package/dist/templates/cursor/agents/atw-review.md +112 -0
- package/dist/templates/cursor/hooks.json +24 -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/atw-implement-agent.md +99 -0
- package/dist/templates/droid/droids/atw-review.md +105 -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 +69 -0
- package/dist/templates/dsh/DSH.md +56 -0
- package/dist/templates/dsh/index.d.ts +21 -0
- package/dist/templates/dsh/index.d.ts.map +1 -0
- package/dist/templates/dsh/index.js +25 -0
- package/dist/templates/dsh/index.js.map +1 -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/atw-implement-agent.md +99 -0
- package/dist/templates/gemini/agents/atw-review.md +105 -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 +40 -0
- package/dist/templates/grok/agents/atw-implement-agent.md +115 -0
- package/dist/templates/grok/agents/atw-review.md +105 -0
- package/dist/templates/grok/index.d.ts +15 -0
- package/dist/templates/grok/index.d.ts.map +1 -0
- package/dist/templates/grok/index.js +18 -0
- package/dist/templates/grok/index.js.map +1 -0
- package/dist/templates/kimi/agents/atw-implement-agent.md +114 -0
- package/dist/templates/kimi/agents/atw-review.md +103 -0
- package/dist/templates/kimi/index.d.ts +20 -0
- package/dist/templates/kimi/index.d.ts.map +1 -0
- package/dist/templates/kimi/index.js +23 -0
- package/dist/templates/kimi/index.js.map +1 -0
- package/dist/templates/kiro/agents/atw-implement-agent.json +26 -0
- package/dist/templates/kiro/agents/atw-review.json +26 -0
- package/dist/templates/kiro/agents/atw.json +34 -0
- package/dist/templates/kiro/hooks/atw-workflow-state.kiro.hook +14 -0
- package/dist/templates/kiro/index.d.ts +32 -0
- package/dist/templates/kiro/index.d.ts.map +1 -0
- package/dist/templates/kiro/index.js +28 -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 +290 -0
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +634 -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/omp/agents/atw-implement-agent.md +45 -0
- package/dist/templates/omp/agents/atw-review.md +41 -0
- package/dist/templates/omp/extensions/atw/index.ts.txt +1109 -0
- package/dist/templates/omp/index.d.ts +4 -0
- package/dist/templates/omp/index.d.ts.map +1 -0
- package/dist/templates/omp/index.js +9 -0
- package/dist/templates/omp/index.js.map +1 -0
- package/dist/templates/opencode/agents/atw-implement-agent.md +115 -0
- package/dist/templates/opencode/agents/atw-review.md +120 -0
- package/dist/templates/opencode/lib/atw-context.js +637 -0
- package/dist/templates/opencode/lib/context-visibility.js +148 -0
- package/dist/templates/opencode/lib/session-utils.js +474 -0
- package/dist/templates/opencode/package.json +6 -0
- package/dist/templates/opencode/plugins/inject-subagent-context.js +390 -0
- package/dist/templates/opencode/plugins/inject-workflow-state.js +240 -0
- package/dist/templates/opencode/plugins/session-start.js +65 -0
- package/dist/templates/pi/agents/atw-implement-agent.md +42 -0
- package/dist/templates/pi/agents/atw-review.md +37 -0
- package/dist/templates/pi/extensions/atw/index.ts.txt +2014 -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 +9 -0
- package/dist/templates/qoder/agents/atw-implement-agent.md +100 -0
- package/dist/templates/qoder/agents/atw-review.md +106 -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 +59 -0
- package/dist/templates/reasonix/agents/atw-implement-agent.md +41 -0
- package/dist/templates/reasonix/agents/atw-review.md +36 -0
- package/dist/templates/reasonix/index.d.ts +13 -0
- package/dist/templates/reasonix/index.d.ts.map +1 -0
- package/dist/templates/reasonix/index.js +16 -0
- package/dist/templates/reasonix/index.js.map +1 -0
- package/dist/templates/shared-hooks/index.d.ts +77 -0
- package/dist/templates/shared-hooks/index.d.ts.map +1 -0
- package/dist/templates/shared-hooks/index.js +140 -0
- package/dist/templates/shared-hooks/index.js.map +1 -0
- package/dist/templates/shared-hooks/inject-shell-session-context.py +292 -0
- package/dist/templates/shared-hooks/inject-subagent-context.py +1178 -0
- package/dist/templates/shared-hooks/inject-workflow-state.py +488 -0
- package/dist/templates/shared-hooks/session-start.py +889 -0
- package/dist/templates/snow/SNOW.md +86 -0
- package/dist/templates/snow/agents/atw-implement-agent.md +152 -0
- package/dist/templates/snow/agents/atw-review.md +135 -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-atw-context.py +637 -0
- package/dist/templates/snow/index.d.ts +25 -0
- package/dist/templates/snow/index.d.ts.map +1 -0
- package/dist/templates/snow/index.js +35 -0
- package/dist/templates/snow/index.js.map +1 -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 +64 -0
- package/dist/templates/template-utils.js.map +1 -0
- package/dist/templates/trae/agents/atw-implement-agent.md +100 -0
- package/dist/templates/trae/agents/atw-review.md +106 -0
- package/dist/templates/trae/hooks.json +39 -0
- package/dist/templates/trae/index.d.ts +15 -0
- package/dist/templates/trae/index.d.ts.map +1 -0
- package/dist/templates/trae/index.js +15 -0
- package/dist/templates/trae/index.js.map +1 -0
- package/dist/templates/zcode/agents/atw-implement-agent.md +108 -0
- package/dist/templates/zcode/agents/atw-review.md +109 -0
- package/dist/templates/zcode/config.json +52 -0
- package/dist/templates/zcode/index.d.ts +22 -0
- package/dist/templates/zcode/index.d.ts.map +1 -0
- package/dist/templates/zcode/index.js +26 -0
- package/dist/templates/zcode/index.js.map +1 -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 +494 -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/ablation-store.d.ts +123 -0
- package/dist/utils/ablation-store.d.ts.map +1 -0
- package/dist/utils/ablation-store.js +749 -0
- package/dist/utils/ablation-store.js.map +1 -0
- package/dist/utils/agent-refs.d.ts +31 -0
- package/dist/utils/agent-refs.d.ts.map +1 -0
- package/dist/utils/agent-refs.js +63 -0
- package/dist/utils/agent-refs.js.map +1 -0
- package/dist/utils/atomic-write.d.ts +12 -0
- package/dist/utils/atomic-write.d.ts.map +1 -0
- package/dist/utils/atomic-write.js +30 -0
- package/dist/utils/atomic-write.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 +204 -0
- package/dist/utils/file-writer.js.map +1 -0
- package/dist/utils/managed-paths.d.ts +5 -0
- package/dist/utils/managed-paths.d.ts.map +1 -0
- package/dist/utils/managed-paths.js +51 -0
- package/dist/utils/managed-paths.js.map +1 -0
- package/dist/utils/managed-removal.d.ts +74 -0
- package/dist/utils/managed-removal.d.ts.map +1 -0
- package/dist/utils/managed-removal.js +270 -0
- package/dist/utils/managed-removal.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 +135 -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/registry-config.d.ts +7 -0
- package/dist/utils/registry-config.d.ts.map +1 -0
- package/dist/utils/registry-config.js +172 -0
- package/dist/utils/registry-config.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 +161 -0
- package/dist/utils/template-fetcher.d.ts.map +1 -0
- package/dist/utils/template-fetcher.js +994 -0
- package/dist/utils/template-fetcher.js.map +1 -0
- package/dist/utils/template-hash.d.ts +127 -0
- package/dist/utils/template-hash.d.ts.map +1 -0
- package/dist/utils/template-hash.js +335 -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 +417 -0
- package/dist/utils/uninstall-scrubbers.js.map +1 -0
- package/dist/utils/workflow-resolver.d.ts +86 -0
- package/dist/utils/workflow-resolver.d.ts.map +1 -0
- package/dist/utils/workflow-resolver.js +265 -0
- package/dist/utils/workflow-resolver.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Task JSONL context management.
|
|
4
|
+
|
|
5
|
+
Provides:
|
|
6
|
+
cmd_add_context - Add entry to JSONL context file
|
|
7
|
+
cmd_validate - Validate JSONL context files
|
|
8
|
+
cmd_list_context - List JSONL context entries
|
|
9
|
+
|
|
10
|
+
Note:
|
|
11
|
+
``cmd_init_context`` no longer exists. JSONL context files
|
|
12
|
+
are created empty at ``task.py create`` time; the AI agent curates real
|
|
13
|
+
entries during planning when the task needs sub-agent/spec context. See
|
|
14
|
+
``.atw/workflow.md`` for the current planning artifact contract.
|
|
15
|
+
|
|
16
|
+
Older ATW versions seeded those files with a ``{"_example": ...}``
|
|
17
|
+
placeholder row. ``cmd_validate`` now rejects that row so a task cannot
|
|
18
|
+
validate locally and then fail PR preflight, which treats it as
|
|
19
|
+
unresolved scaffolding.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import json
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
|
|
28
|
+
from .config import get_context_injection_limits
|
|
29
|
+
from .git import branch_exists_locally
|
|
30
|
+
from .io import read_json
|
|
31
|
+
from .log import Colors, colored
|
|
32
|
+
from .paths import DIR_ARCHIVE, DIR_TASKS, DIR_WORKFLOW, FILE_TASK_JSON, get_repo_root
|
|
33
|
+
from .task_utils import resolve_task_dir
|
|
34
|
+
|
|
35
|
+
# Extensions that look like code rather than spec/research docs. Entries with
|
|
36
|
+
# one of these extensions outside .atw/spec/, docs/docs-site, or the
|
|
37
|
+
# task's own directory get a hygiene warning in `task.py validate` — the
|
|
38
|
+
# reader is a sub-agent, not a human, so code paths belong in the diff the
|
|
39
|
+
# agent reads itself, not in implement.jsonl / check.jsonl.
|
|
40
|
+
_CODE_FILE_EXTENSIONS = {
|
|
41
|
+
".ts",
|
|
42
|
+
".tsx",
|
|
43
|
+
".js",
|
|
44
|
+
".jsx",
|
|
45
|
+
".mjs",
|
|
46
|
+
".cjs",
|
|
47
|
+
".py",
|
|
48
|
+
".go",
|
|
49
|
+
".rs",
|
|
50
|
+
".java",
|
|
51
|
+
".rb",
|
|
52
|
+
".c",
|
|
53
|
+
".cc",
|
|
54
|
+
".cpp",
|
|
55
|
+
".h",
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# =============================================================================
|
|
60
|
+
# Command: add-context
|
|
61
|
+
# =============================================================================
|
|
62
|
+
|
|
63
|
+
def cmd_add_context(args: argparse.Namespace) -> int:
|
|
64
|
+
"""Add entry to JSONL context file."""
|
|
65
|
+
repo_root = get_repo_root()
|
|
66
|
+
target_dir = resolve_task_dir(args.dir, repo_root)
|
|
67
|
+
if target_dir is None:
|
|
68
|
+
return 1
|
|
69
|
+
|
|
70
|
+
jsonl_name = args.file
|
|
71
|
+
path = args.path
|
|
72
|
+
reason = args.reason or "Added manually"
|
|
73
|
+
|
|
74
|
+
if not target_dir or not target_dir.is_dir():
|
|
75
|
+
print(colored(f"Error: Directory not found: {target_dir}", Colors.RED))
|
|
76
|
+
return 1
|
|
77
|
+
|
|
78
|
+
# The JSONL name is user input joined onto the task dir — keep it a plain
|
|
79
|
+
# filename so it cannot create files elsewhere.
|
|
80
|
+
if "/" in jsonl_name or "\\" in jsonl_name or jsonl_name in (".", ".."):
|
|
81
|
+
print(colored(
|
|
82
|
+
f"Error: context file must be a plain name (e.g. implement, check): {jsonl_name}",
|
|
83
|
+
Colors.RED,
|
|
84
|
+
))
|
|
85
|
+
return 1
|
|
86
|
+
|
|
87
|
+
# Support shorthand
|
|
88
|
+
if not jsonl_name.endswith(".jsonl"):
|
|
89
|
+
jsonl_name = f"{jsonl_name}.jsonl"
|
|
90
|
+
|
|
91
|
+
jsonl_file = target_dir / jsonl_name
|
|
92
|
+
full_path = repo_root / path
|
|
93
|
+
|
|
94
|
+
entry_type = "file"
|
|
95
|
+
if full_path.is_dir():
|
|
96
|
+
entry_type = "directory"
|
|
97
|
+
if not path.endswith("/"):
|
|
98
|
+
path = f"{path}/"
|
|
99
|
+
elif not full_path.is_file():
|
|
100
|
+
print(colored(f"Error: Path not found: {path}", Colors.RED))
|
|
101
|
+
return 1
|
|
102
|
+
|
|
103
|
+
# Check if already exists
|
|
104
|
+
if jsonl_file.is_file():
|
|
105
|
+
content = jsonl_file.read_text(encoding="utf-8")
|
|
106
|
+
if f'"{path}"' in content:
|
|
107
|
+
print(colored(f"Warning: Entry already exists for {path}", Colors.YELLOW))
|
|
108
|
+
return 0
|
|
109
|
+
|
|
110
|
+
# Add entry
|
|
111
|
+
entry: dict
|
|
112
|
+
if entry_type == "directory":
|
|
113
|
+
entry = {"file": path, "type": "directory", "reason": reason}
|
|
114
|
+
else:
|
|
115
|
+
entry = {"file": path, "reason": reason}
|
|
116
|
+
|
|
117
|
+
with jsonl_file.open("a", encoding="utf-8") as f:
|
|
118
|
+
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
|
119
|
+
|
|
120
|
+
print(colored(f"Added {entry_type}: {path}", Colors.GREEN))
|
|
121
|
+
return 0
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# =============================================================================
|
|
125
|
+
# Command: validate
|
|
126
|
+
# =============================================================================
|
|
127
|
+
|
|
128
|
+
def curated_entry_count(jsonl_file: Path) -> int | None:
|
|
129
|
+
"""Count curated entries in a jsonl context manifest.
|
|
130
|
+
|
|
131
|
+
Returns None when the file does not exist — `task.py create` seeds the
|
|
132
|
+
manifests only on sub-agent-capable platforms, so an absent file means no
|
|
133
|
+
sub-agent will ever read it and callers should not gate on it. A curated
|
|
134
|
+
entry is a JSON object row carrying a truthy ``file`` (or legacy ``path``)
|
|
135
|
+
value: the same rows the sub-agent injection hook materializes.
|
|
136
|
+
"""
|
|
137
|
+
if not jsonl_file.is_file():
|
|
138
|
+
return None
|
|
139
|
+
try:
|
|
140
|
+
lines = jsonl_file.read_text(encoding="utf-8").splitlines()
|
|
141
|
+
except OSError:
|
|
142
|
+
return 0
|
|
143
|
+
count = 0
|
|
144
|
+
for line in lines:
|
|
145
|
+
line = line.strip()
|
|
146
|
+
if not line:
|
|
147
|
+
continue
|
|
148
|
+
try:
|
|
149
|
+
data = json.loads(line)
|
|
150
|
+
except json.JSONDecodeError:
|
|
151
|
+
continue
|
|
152
|
+
if isinstance(data, dict) and (data.get("file") or data.get("path")):
|
|
153
|
+
count += 1
|
|
154
|
+
return count
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def cmd_validate(args: argparse.Namespace) -> int:
|
|
158
|
+
"""Validate JSONL context files."""
|
|
159
|
+
repo_root = get_repo_root()
|
|
160
|
+
target_dir = resolve_task_dir(args.dir, repo_root)
|
|
161
|
+
|
|
162
|
+
if target_dir is None or not target_dir.is_dir():
|
|
163
|
+
print(colored("Error: task directory required", Colors.RED))
|
|
164
|
+
return 1
|
|
165
|
+
|
|
166
|
+
print(colored("=== Validating Context Files ===", Colors.BLUE))
|
|
167
|
+
print(f"Target dir: {target_dir}")
|
|
168
|
+
print()
|
|
169
|
+
|
|
170
|
+
# Warn (don't fail validation) when the recorded branch is stale — it
|
|
171
|
+
# was likely already merged and deleted.
|
|
172
|
+
task_json_path = target_dir / FILE_TASK_JSON
|
|
173
|
+
if task_json_path.is_file():
|
|
174
|
+
task_data = read_json(task_json_path)
|
|
175
|
+
stored_branch = task_data.get("branch") if task_data else None
|
|
176
|
+
if stored_branch and not branch_exists_locally(stored_branch, repo_root):
|
|
177
|
+
print(
|
|
178
|
+
colored(
|
|
179
|
+
f"Warning: recorded branch '{stored_branch}' no longer exists locally "
|
|
180
|
+
"(likely merged and deleted).",
|
|
181
|
+
Colors.YELLOW,
|
|
182
|
+
)
|
|
183
|
+
)
|
|
184
|
+
print()
|
|
185
|
+
|
|
186
|
+
total_errors = 0
|
|
187
|
+
for jsonl_name in ["implement.jsonl", "check.jsonl"]:
|
|
188
|
+
jsonl_file = target_dir / jsonl_name
|
|
189
|
+
errors = _validate_jsonl(jsonl_file, repo_root, target_dir)
|
|
190
|
+
total_errors += errors
|
|
191
|
+
|
|
192
|
+
print()
|
|
193
|
+
if total_errors == 0:
|
|
194
|
+
print(colored("✓ All validations passed", Colors.GREEN))
|
|
195
|
+
return 0
|
|
196
|
+
else:
|
|
197
|
+
print(colored(f"✗ Validation failed ({total_errors} errors)", Colors.RED))
|
|
198
|
+
return 1
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _is_exempt_from_code_file_warning(file_path: str, task_rel: str) -> bool:
|
|
202
|
+
"""Whether a jsonl entry path is exempt from the code-file hygiene warning.
|
|
203
|
+
|
|
204
|
+
Exempt: spec docs (``.atw/spec/``), documentation (``docs``,
|
|
205
|
+
``docs-site``), and the task's own directory (execution plans, generated
|
|
206
|
+
artifacts, etc. legitimately live there).
|
|
207
|
+
"""
|
|
208
|
+
posix_path = file_path.replace("\\", "/").lstrip("/")
|
|
209
|
+
exempt_prefixes = (".atw/spec/", "docs/", "docs-site/")
|
|
210
|
+
if posix_path.startswith(exempt_prefixes):
|
|
211
|
+
return True
|
|
212
|
+
if task_rel and (posix_path == task_rel or posix_path.startswith(f"{task_rel}/")):
|
|
213
|
+
return True
|
|
214
|
+
return False
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _resolve_context_entry_path(
|
|
218
|
+
file_path: str, repo_root: Path, task_dir: Path | None
|
|
219
|
+
) -> Path | None:
|
|
220
|
+
"""Resolve a JSONL entry, binding archived self-references to the archive copy.
|
|
221
|
+
|
|
222
|
+
Exact historical self-references are remapped only for archived tasks.
|
|
223
|
+
``None`` means the remapped path traversed or resolved outside that archive.
|
|
224
|
+
"""
|
|
225
|
+
repo_path = repo_root / file_path
|
|
226
|
+
if task_dir is None:
|
|
227
|
+
return repo_path
|
|
228
|
+
|
|
229
|
+
try:
|
|
230
|
+
task_parts = task_dir.resolve().relative_to(repo_root.resolve()).parts
|
|
231
|
+
except ValueError:
|
|
232
|
+
return repo_path
|
|
233
|
+
|
|
234
|
+
archive_prefix = (DIR_WORKFLOW, DIR_TASKS, DIR_ARCHIVE)
|
|
235
|
+
if len(task_parts) != 5 or task_parts[:3] != archive_prefix:
|
|
236
|
+
return repo_path
|
|
237
|
+
|
|
238
|
+
year_month = task_parts[3]
|
|
239
|
+
if (
|
|
240
|
+
len(year_month) != 7
|
|
241
|
+
or year_month[4] != "-"
|
|
242
|
+
or not year_month[:4].isdigit()
|
|
243
|
+
or not year_month[5:].isdigit()
|
|
244
|
+
):
|
|
245
|
+
return repo_path
|
|
246
|
+
|
|
247
|
+
historical_root = f"{DIR_WORKFLOW}/{DIR_TASKS}/{task_dir.name}"
|
|
248
|
+
posix_path = file_path.replace("\\", "/")
|
|
249
|
+
if posix_path == historical_root:
|
|
250
|
+
relative_parts: tuple[str, ...] = ()
|
|
251
|
+
elif posix_path.startswith(f"{historical_root}/"):
|
|
252
|
+
relative_path = posix_path[len(historical_root) + 1 :]
|
|
253
|
+
if relative_path.endswith("/"):
|
|
254
|
+
relative_path = relative_path[:-1]
|
|
255
|
+
relative_parts = tuple(relative_path.split("/")) if relative_path else ()
|
|
256
|
+
if any(part in ("", ".", "..") for part in relative_parts):
|
|
257
|
+
return None
|
|
258
|
+
else:
|
|
259
|
+
return repo_path
|
|
260
|
+
|
|
261
|
+
try:
|
|
262
|
+
archive_root = task_dir.resolve()
|
|
263
|
+
resolved_path = task_dir.joinpath(*relative_parts).resolve()
|
|
264
|
+
resolved_path.relative_to(archive_root)
|
|
265
|
+
except (OSError, RuntimeError, ValueError):
|
|
266
|
+
return None
|
|
267
|
+
return resolved_path
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def _validate_jsonl(jsonl_file: Path, repo_root: Path, task_dir: Path | None = None) -> int:
|
|
271
|
+
"""Validate a single JSONL file.
|
|
272
|
+
|
|
273
|
+
``{"_example": ...}`` placeholder rows written by older ATW versions
|
|
274
|
+
are hard errors: PR preflight rejects them as unresolved scaffolding, so
|
|
275
|
+
accepting them here would pass locally and fail later. Other rows without
|
|
276
|
+
a ``file`` field are skipped silently, matching what consumers do.
|
|
277
|
+
|
|
278
|
+
Beyond hard errors (missing file/dir, invalid JSON), this also prints
|
|
279
|
+
non-blocking hygiene warnings (never counted in ``errors``, never change
|
|
280
|
+
the exit code): entries that look like code files rather than
|
|
281
|
+
spec/research docs, and entries whose file size exceeds the configured
|
|
282
|
+
sub-agent context injection cap (``context_injection.max_file_bytes``).
|
|
283
|
+
"""
|
|
284
|
+
file_name = jsonl_file.name
|
|
285
|
+
errors = 0
|
|
286
|
+
|
|
287
|
+
if not jsonl_file.is_file():
|
|
288
|
+
print(f" {colored(f'{file_name}: not found (skipped)', Colors.YELLOW)}")
|
|
289
|
+
return 0
|
|
290
|
+
|
|
291
|
+
task_rel = ""
|
|
292
|
+
if task_dir is not None:
|
|
293
|
+
try:
|
|
294
|
+
task_rel = task_dir.resolve().relative_to(repo_root.resolve()).as_posix()
|
|
295
|
+
except ValueError:
|
|
296
|
+
task_rel = ""
|
|
297
|
+
|
|
298
|
+
max_file_bytes = get_context_injection_limits(repo_root).get("max_file_bytes", 0)
|
|
299
|
+
|
|
300
|
+
line_num = 0
|
|
301
|
+
real_entries = 0
|
|
302
|
+
for line in jsonl_file.read_text(encoding="utf-8").splitlines():
|
|
303
|
+
line_num += 1
|
|
304
|
+
if not line.strip():
|
|
305
|
+
continue
|
|
306
|
+
|
|
307
|
+
try:
|
|
308
|
+
data = json.loads(line)
|
|
309
|
+
except json.JSONDecodeError:
|
|
310
|
+
print(f" {colored(f'{file_name}:{line_num}: Invalid JSON', Colors.RED)}")
|
|
311
|
+
errors += 1
|
|
312
|
+
continue
|
|
313
|
+
|
|
314
|
+
if not isinstance(data, dict):
|
|
315
|
+
print(
|
|
316
|
+
f" {colored(f'{file_name}:{line_num}: Expected a JSON object', Colors.RED)}"
|
|
317
|
+
)
|
|
318
|
+
errors += 1
|
|
319
|
+
continue
|
|
320
|
+
|
|
321
|
+
if "_example" in data:
|
|
322
|
+
error_message = (
|
|
323
|
+
f"{file_name}:{line_num}: Placeholder `_example` row left by an older "
|
|
324
|
+
"task.py create — delete this line, or replace it with "
|
|
325
|
+
'{"file": "<path>", "reason": "<why>"}'
|
|
326
|
+
)
|
|
327
|
+
print(f" {colored(error_message, Colors.RED)}")
|
|
328
|
+
errors += 1
|
|
329
|
+
continue
|
|
330
|
+
|
|
331
|
+
file_path = data.get("file")
|
|
332
|
+
entry_type = data.get("type", "file")
|
|
333
|
+
|
|
334
|
+
if not file_path:
|
|
335
|
+
# Comment / unknown row without a path — skip silently
|
|
336
|
+
continue
|
|
337
|
+
|
|
338
|
+
if not isinstance(file_path, str):
|
|
339
|
+
# A truthy non-string (e.g. {"file": 1}) reached path joining and
|
|
340
|
+
# raised TypeError, so validation crashed on the row it exists to
|
|
341
|
+
# report.
|
|
342
|
+
print(
|
|
343
|
+
f" {colored(f'{file_name}:{line_num}: `file` must be a string path', Colors.RED)}"
|
|
344
|
+
)
|
|
345
|
+
errors += 1
|
|
346
|
+
continue
|
|
347
|
+
|
|
348
|
+
real_entries += 1
|
|
349
|
+
full_path = _resolve_context_entry_path(file_path, repo_root, task_dir)
|
|
350
|
+
if entry_type == "directory":
|
|
351
|
+
if full_path is None or not full_path.is_dir():
|
|
352
|
+
print(f" {colored(f'{file_name}:{line_num}: Directory not found: {file_path}', Colors.RED)}")
|
|
353
|
+
errors += 1
|
|
354
|
+
continue
|
|
355
|
+
|
|
356
|
+
if full_path is None or not full_path.is_file():
|
|
357
|
+
print(f" {colored(f'{file_name}:{line_num}: File not found: {file_path}', Colors.RED)}")
|
|
358
|
+
errors += 1
|
|
359
|
+
continue
|
|
360
|
+
|
|
361
|
+
extension = Path(file_path).suffix.lower()
|
|
362
|
+
if extension in _CODE_FILE_EXTENSIONS and not _is_exempt_from_code_file_warning(
|
|
363
|
+
file_path, task_rel
|
|
364
|
+
):
|
|
365
|
+
warning_message = (
|
|
366
|
+
f"{file_name}:{line_num}: Warning: {file_path} looks like a code file — "
|
|
367
|
+
"implement/check.jsonl should reference spec/research docs; "
|
|
368
|
+
"agents read code themselves"
|
|
369
|
+
)
|
|
370
|
+
print(f" {colored(warning_message, Colors.YELLOW)}")
|
|
371
|
+
|
|
372
|
+
if max_file_bytes:
|
|
373
|
+
# Advisory hygiene warning, so it must never be what fails
|
|
374
|
+
# `validate`. `stat()` can still raise after the `is_file()` check
|
|
375
|
+
# above — a permission change, or the file removed in between.
|
|
376
|
+
try:
|
|
377
|
+
size: int | None = full_path.stat().st_size
|
|
378
|
+
except OSError:
|
|
379
|
+
size = None
|
|
380
|
+
if size is not None and size > max_file_bytes:
|
|
381
|
+
warning_message = (
|
|
382
|
+
f"{file_name}:{line_num}: Warning: {file_path} is {size} bytes, "
|
|
383
|
+
f"exceeds context_injection.max_file_bytes ({max_file_bytes}); "
|
|
384
|
+
"injection will truncate it"
|
|
385
|
+
)
|
|
386
|
+
print(f" {colored(warning_message, Colors.YELLOW)}")
|
|
387
|
+
|
|
388
|
+
if errors == 0 and real_entries == 0:
|
|
389
|
+
# Seed-only / empty manifest: sub-agents dispatched for this task
|
|
390
|
+
# would run with zero spec context. Silent-green here is how
|
|
391
|
+
# more than half the tasks in the report ended up uncurated.
|
|
392
|
+
action = file_name.split(".", 1)[0]
|
|
393
|
+
print(
|
|
394
|
+
f" {colored(f'{file_name}: ✗ (0 curated entries — sub-agents would get zero spec context)', Colors.RED)}"
|
|
395
|
+
)
|
|
396
|
+
print(
|
|
397
|
+
f" Curate it: python3 .atw/scripts/task.py add-context <task> {action} <path> \"<why>\""
|
|
398
|
+
)
|
|
399
|
+
print(
|
|
400
|
+
" Intentionally empty? Bypass at start: task.py start <task> --allow-empty-context"
|
|
401
|
+
)
|
|
402
|
+
return 1
|
|
403
|
+
|
|
404
|
+
if errors == 0:
|
|
405
|
+
print(f" {colored(f'{file_name}: ✓ ({real_entries} entries)', Colors.GREEN)}")
|
|
406
|
+
else:
|
|
407
|
+
print(f" {colored(f'{file_name}: ✗ ({errors} errors)', Colors.RED)}")
|
|
408
|
+
|
|
409
|
+
return errors
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
# =============================================================================
|
|
413
|
+
# Command: list-context
|
|
414
|
+
# =============================================================================
|
|
415
|
+
|
|
416
|
+
def cmd_list_context(args: argparse.Namespace) -> int:
|
|
417
|
+
"""List JSONL context entries."""
|
|
418
|
+
repo_root = get_repo_root()
|
|
419
|
+
target_dir = resolve_task_dir(args.dir, repo_root)
|
|
420
|
+
|
|
421
|
+
if target_dir is None or not target_dir.is_dir():
|
|
422
|
+
print(colored("Error: task directory required", Colors.RED))
|
|
423
|
+
return 1
|
|
424
|
+
|
|
425
|
+
print(colored("=== Context Files ===", Colors.BLUE))
|
|
426
|
+
print()
|
|
427
|
+
|
|
428
|
+
for jsonl_name in ["implement.jsonl", "check.jsonl"]:
|
|
429
|
+
jsonl_file = target_dir / jsonl_name
|
|
430
|
+
if not jsonl_file.is_file():
|
|
431
|
+
continue
|
|
432
|
+
|
|
433
|
+
print(colored(f"[{jsonl_name}]", Colors.CYAN))
|
|
434
|
+
|
|
435
|
+
count = 0
|
|
436
|
+
curated = False
|
|
437
|
+
for line in jsonl_file.read_text(encoding="utf-8").splitlines():
|
|
438
|
+
if not line.strip():
|
|
439
|
+
continue
|
|
440
|
+
|
|
441
|
+
try:
|
|
442
|
+
data = json.loads(line)
|
|
443
|
+
except json.JSONDecodeError:
|
|
444
|
+
continue
|
|
445
|
+
|
|
446
|
+
if not isinstance(data, dict):
|
|
447
|
+
continue
|
|
448
|
+
|
|
449
|
+
file_path = data.get("file")
|
|
450
|
+
if not file_path:
|
|
451
|
+
# Placeholder / comment row — don't count as a real entry
|
|
452
|
+
continue
|
|
453
|
+
curated = True
|
|
454
|
+
|
|
455
|
+
count += 1
|
|
456
|
+
entry_type = data.get("type", "file")
|
|
457
|
+
reason = data.get("reason", "-")
|
|
458
|
+
|
|
459
|
+
if entry_type == "directory":
|
|
460
|
+
print(f" {colored(f'{count}.', Colors.GREEN)} [DIR] {file_path}")
|
|
461
|
+
else:
|
|
462
|
+
print(f" {colored(f'{count}.', Colors.GREEN)} {file_path}")
|
|
463
|
+
print(f" {colored('→', Colors.YELLOW)} {reason}")
|
|
464
|
+
|
|
465
|
+
if not curated:
|
|
466
|
+
print(f" {colored('(no curated entries yet)', Colors.YELLOW)}")
|
|
467
|
+
|
|
468
|
+
print()
|
|
469
|
+
|
|
470
|
+
return 0
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Task queue utility functions.
|
|
4
|
+
|
|
5
|
+
Provides:
|
|
6
|
+
list_tasks_by_status - List tasks by status
|
|
7
|
+
list_pending_tasks - List tasks with pending status
|
|
8
|
+
list_tasks_by_assignee - List tasks by assignee
|
|
9
|
+
list_my_tasks - List tasks assigned to current developer
|
|
10
|
+
get_task_stats - Get P0/P1/P2/P3 counts
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from .paths import (
|
|
18
|
+
get_repo_root,
|
|
19
|
+
get_developer,
|
|
20
|
+
get_tasks_dir,
|
|
21
|
+
)
|
|
22
|
+
from .tasks import iter_active_tasks
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# =============================================================================
|
|
26
|
+
# Internal helper
|
|
27
|
+
# =============================================================================
|
|
28
|
+
|
|
29
|
+
def _task_to_dict(t) -> dict:
|
|
30
|
+
"""Convert TaskInfo to the dict format callers expect."""
|
|
31
|
+
return {
|
|
32
|
+
"priority": t.priority,
|
|
33
|
+
"id": t.raw.get("id", ""),
|
|
34
|
+
"title": t.title,
|
|
35
|
+
"status": t.status,
|
|
36
|
+
"assignee": t.assignee or "-",
|
|
37
|
+
"dir": t.dir_name,
|
|
38
|
+
"children": list(t.children),
|
|
39
|
+
"parent": t.parent,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# =============================================================================
|
|
44
|
+
# Public Functions
|
|
45
|
+
# =============================================================================
|
|
46
|
+
|
|
47
|
+
def list_tasks_by_status(
|
|
48
|
+
filter_status: str | None = None,
|
|
49
|
+
repo_root: Path | None = None
|
|
50
|
+
) -> list[dict]:
|
|
51
|
+
"""List tasks by status.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
filter_status: Optional status filter.
|
|
55
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
List of task info dicts with keys: priority, id, title, status, assignee.
|
|
59
|
+
"""
|
|
60
|
+
if repo_root is None:
|
|
61
|
+
repo_root = get_repo_root()
|
|
62
|
+
|
|
63
|
+
tasks_dir = get_tasks_dir(repo_root)
|
|
64
|
+
results = []
|
|
65
|
+
|
|
66
|
+
for t in iter_active_tasks(tasks_dir):
|
|
67
|
+
if filter_status and t.status != filter_status:
|
|
68
|
+
continue
|
|
69
|
+
results.append(_task_to_dict(t))
|
|
70
|
+
|
|
71
|
+
return results
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def list_pending_tasks(repo_root: Path | None = None) -> list[dict]:
|
|
75
|
+
"""List pending tasks.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
List of task info dicts.
|
|
82
|
+
"""
|
|
83
|
+
return list_tasks_by_status("discover", repo_root)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def list_tasks_by_assignee(
|
|
87
|
+
assignee: str,
|
|
88
|
+
filter_status: str | None = None,
|
|
89
|
+
repo_root: Path | None = None
|
|
90
|
+
) -> list[dict]:
|
|
91
|
+
"""List tasks assigned to a specific developer.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
assignee: Developer name.
|
|
95
|
+
filter_status: Optional status filter.
|
|
96
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
List of task info dicts.
|
|
100
|
+
"""
|
|
101
|
+
if repo_root is None:
|
|
102
|
+
repo_root = get_repo_root()
|
|
103
|
+
|
|
104
|
+
tasks_dir = get_tasks_dir(repo_root)
|
|
105
|
+
results = []
|
|
106
|
+
|
|
107
|
+
for t in iter_active_tasks(tasks_dir):
|
|
108
|
+
if (t.assignee or "-") != assignee:
|
|
109
|
+
continue
|
|
110
|
+
if filter_status and t.status != filter_status:
|
|
111
|
+
continue
|
|
112
|
+
results.append(_task_to_dict(t))
|
|
113
|
+
|
|
114
|
+
return results
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def list_my_tasks(
|
|
118
|
+
filter_status: str | None = None,
|
|
119
|
+
repo_root: Path | None = None
|
|
120
|
+
) -> list[dict]:
|
|
121
|
+
"""List tasks assigned to current developer.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
filter_status: Optional status filter.
|
|
125
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
List of task info dicts.
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
ValueError: If developer not set.
|
|
132
|
+
"""
|
|
133
|
+
if repo_root is None:
|
|
134
|
+
repo_root = get_repo_root()
|
|
135
|
+
|
|
136
|
+
developer = get_developer(repo_root)
|
|
137
|
+
if not developer:
|
|
138
|
+
raise ValueError("Developer not set")
|
|
139
|
+
|
|
140
|
+
return list_tasks_by_assignee(developer, filter_status, repo_root)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def get_task_stats(repo_root: Path | None = None) -> dict[str, int]:
|
|
144
|
+
"""Get task statistics.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
repo_root: Repository root path. Defaults to auto-detected.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Dict with keys: P0, P1, P2, P3, Total.
|
|
151
|
+
"""
|
|
152
|
+
if repo_root is None:
|
|
153
|
+
repo_root = get_repo_root()
|
|
154
|
+
|
|
155
|
+
tasks_dir = get_tasks_dir(repo_root)
|
|
156
|
+
stats = {"P0": 0, "P1": 0, "P2": 0, "P3": 0, "Total": 0}
|
|
157
|
+
|
|
158
|
+
for t in iter_active_tasks(tasks_dir):
|
|
159
|
+
if t.priority in stats:
|
|
160
|
+
stats[t.priority] += 1
|
|
161
|
+
stats["Total"] += 1
|
|
162
|
+
|
|
163
|
+
return stats
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def format_task_stats(stats: dict[str, int]) -> str:
|
|
167
|
+
"""Format task stats as string.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
stats: Stats dict from get_task_stats.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Formatted string like "P0:0 P1:1 P2:2 P3:0 Total:3".
|
|
174
|
+
"""
|
|
175
|
+
return f"P0:{stats['P0']} P1:{stats['P1']} P2:{stats['P2']} P3:{stats['P3']} Total:{stats['Total']}"
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# =============================================================================
|
|
179
|
+
# Main Entry (for testing)
|
|
180
|
+
# =============================================================================
|
|
181
|
+
|
|
182
|
+
if __name__ == "__main__":
|
|
183
|
+
stats = get_task_stats()
|
|
184
|
+
print(format_task_stats(stats))
|
|
185
|
+
print()
|
|
186
|
+
print("Pending tasks:")
|
|
187
|
+
for task in list_pending_tasks():
|
|
188
|
+
print(f" {task['priority']}|{task['id']}|{task['title']}|{task['status']}|{task['assignee']}")
|