@fifine/aim-studio 0.0.1
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/LICENSE +21 -0
- package/README.md +159 -0
- package/bin/aim.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 +89 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +513 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/update.d.ts +27 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +1275 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/configurators/claude.d.ts +32 -0
- package/dist/configurators/claude.d.ts.map +1 -0
- package/dist/configurators/claude.js +98 -0
- package/dist/configurators/claude.js.map +1 -0
- package/dist/configurators/index.d.ts +51 -0
- package/dist/configurators/index.d.ts.map +1 -0
- package/dist/configurators/index.js +113 -0
- package/dist/configurators/index.js.map +1 -0
- package/dist/configurators/shared.d.ts +12 -0
- package/dist/configurators/shared.d.ts.map +1 -0
- package/dist/configurators/shared.js +21 -0
- package/dist/configurators/shared.js.map +1 -0
- package/dist/configurators/workflow.d.ts +28 -0
- package/dist/configurators/workflow.d.ts.map +1 -0
- package/dist/configurators/workflow.js +147 -0
- package/dist/configurators/workflow.js.map +1 -0
- package/dist/constants/paths.d.ts +68 -0
- package/dist/constants/paths.d.ts.map +1 -0
- package/dist/constants/paths.js +77 -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 +54 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +160 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/manifests/0.0.1.json +9 -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 +278 -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/templates/CLAUDE.md +71 -0
- package/dist/templates/aim/gitignore.txt +29 -0
- package/dist/templates/aim/index.d.ts +49 -0
- package/dist/templates/aim/index.d.ts.map +1 -0
- package/dist/templates/aim/index.js +92 -0
- package/dist/templates/aim/index.js.map +1 -0
- package/dist/templates/aim/scripts/__init__.py +5 -0
- package/dist/templates/aim/scripts/add_session.py +392 -0
- package/dist/templates/aim/scripts/common/__init__.py +80 -0
- package/dist/templates/aim/scripts/common/cli_adapter.py +435 -0
- package/dist/templates/aim/scripts/common/developer.py +190 -0
- package/dist/templates/aim/scripts/common/git_context.py +383 -0
- package/dist/templates/aim/scripts/common/paths.py +347 -0
- package/dist/templates/aim/scripts/common/phase.py +253 -0
- package/dist/templates/aim/scripts/common/registry.py +366 -0
- package/dist/templates/aim/scripts/common/task_queue.py +255 -0
- package/dist/templates/aim/scripts/common/task_utils.py +178 -0
- package/dist/templates/aim/scripts/common/worktree.py +219 -0
- package/dist/templates/aim/scripts/create_bootstrap.py +290 -0
- package/dist/templates/aim/scripts/get_context.py +16 -0
- package/dist/templates/aim/scripts/get_developer.py +26 -0
- package/dist/templates/aim/scripts/init_developer.py +51 -0
- package/dist/templates/aim/scripts/multi_agent/__init__.py +5 -0
- package/dist/templates/aim/scripts/multi_agent/cleanup.py +403 -0
- package/dist/templates/aim/scripts/multi_agent/create_pr.py +329 -0
- package/dist/templates/aim/scripts/multi_agent/plan.py +233 -0
- package/dist/templates/aim/scripts/multi_agent/start.py +461 -0
- package/dist/templates/aim/scripts/multi_agent/status.py +817 -0
- package/dist/templates/aim/scripts/task.py +1068 -0
- package/dist/templates/aim/scripts-shell-archive/add-session.sh +384 -0
- package/dist/templates/aim/scripts-shell-archive/common/developer.sh +129 -0
- package/dist/templates/aim/scripts-shell-archive/common/git-context.sh +263 -0
- package/dist/templates/aim/scripts-shell-archive/common/paths.sh +208 -0
- package/dist/templates/aim/scripts-shell-archive/common/phase.sh +150 -0
- package/dist/templates/aim/scripts-shell-archive/common/registry.sh +247 -0
- package/dist/templates/aim/scripts-shell-archive/common/task-queue.sh +142 -0
- package/dist/templates/aim/scripts-shell-archive/common/task-utils.sh +151 -0
- package/dist/templates/aim/scripts-shell-archive/common/worktree.sh +128 -0
- package/dist/templates/aim/scripts-shell-archive/create-bootstrap.sh +299 -0
- package/dist/templates/aim/scripts-shell-archive/get-context.sh +7 -0
- package/dist/templates/aim/scripts-shell-archive/get-developer.sh +15 -0
- package/dist/templates/aim/scripts-shell-archive/init-developer.sh +34 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/cleanup.sh +396 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/create-pr.sh +241 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/plan.sh +207 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/start.sh +317 -0
- package/dist/templates/aim/scripts-shell-archive/multi-agent/status.sh +828 -0
- package/dist/templates/aim/scripts-shell-archive/task.sh +1204 -0
- package/dist/templates/aim/tasks/.gitkeep +0 -0
- package/dist/templates/aim/workflow.md +258 -0
- package/dist/templates/aim/worktree.yaml +47 -0
- package/dist/templates/claude/agents/check.md +122 -0
- package/dist/templates/claude/agents/debug.md +106 -0
- package/dist/templates/claude/agents/dispatch.md +230 -0
- package/dist/templates/claude/agents/implement.md +96 -0
- package/dist/templates/claude/agents/plan.md +396 -0
- package/dist/templates/claude/agents/research.md +120 -0
- package/dist/templates/claude/agents/story.md +53 -0
- package/dist/templates/claude/commands/aim/before-backend-dev.md +13 -0
- package/dist/templates/claude/commands/aim/before-frontend-dev.md +13 -0
- package/dist/templates/claude/commands/aim/break-loop.md +153 -0
- package/dist/templates/claude/commands/aim/check-backend.md +13 -0
- package/dist/templates/claude/commands/aim/check-cross-layer.md +153 -0
- package/dist/templates/claude/commands/aim/check-frontend.md +13 -0
- package/dist/templates/claude/commands/aim/check-story.md +59 -0
- package/dist/templates/claude/commands/aim/create-command.md +154 -0
- package/dist/templates/claude/commands/aim/export.md +187 -0
- package/dist/templates/claude/commands/aim/finish-work.md +104 -0
- package/dist/templates/claude/commands/aim/integrate-skill.md +219 -0
- package/dist/templates/claude/commands/aim/onboard.md +358 -0
- package/dist/templates/claude/commands/aim/parallel.md +217 -0
- package/dist/templates/claude/commands/aim/portrait.md +170 -0
- package/dist/templates/claude/commands/aim/record-session.md +92 -0
- package/dist/templates/claude/commands/aim/start.md +112 -0
- package/dist/templates/claude/commands/aim/story.md +140 -0
- package/dist/templates/claude/commands/aim/update-spec.md +285 -0
- package/dist/templates/claude/commands/aim/visualize.md +182 -0
- package/dist/templates/claude/commands/trellis/before-backend-dev.md +13 -0
- package/dist/templates/claude/commands/trellis/before-frontend-dev.md +13 -0
- package/dist/templates/claude/commands/trellis/break-loop.md +125 -0
- package/dist/templates/claude/commands/trellis/check-backend.md +13 -0
- package/dist/templates/claude/commands/trellis/check-cross-layer.md +153 -0
- package/dist/templates/claude/commands/trellis/check-frontend.md +13 -0
- package/dist/templates/claude/commands/trellis/create-command.md +154 -0
- package/dist/templates/claude/commands/trellis/finish-work.md +129 -0
- package/dist/templates/claude/commands/trellis/integrate-skill.md +219 -0
- package/dist/templates/claude/commands/trellis/onboard.md +358 -0
- package/dist/templates/claude/commands/trellis/parallel.md +193 -0
- package/dist/templates/claude/commands/trellis/record-session.md +62 -0
- package/dist/templates/claude/commands/trellis/start.md +280 -0
- package/dist/templates/claude/commands/trellis/update-spec.md +285 -0
- package/dist/templates/claude/hooks/inject-subagent-context.py +772 -0
- package/dist/templates/claude/hooks/ralph-loop.py +388 -0
- package/dist/templates/claude/hooks/session-start.py +142 -0
- package/dist/templates/claude/index.d.ts +54 -0
- package/dist/templates/claude/index.d.ts.map +1 -0
- package/dist/templates/claude/index.js +85 -0
- package/dist/templates/claude/index.js.map +1 -0
- package/dist/templates/claude/settings.json +41 -0
- package/dist/templates/extract.d.ts +68 -0
- package/dist/templates/extract.d.ts.map +1 -0
- package/dist/templates/extract.js +128 -0
- package/dist/templates/extract.js.map +1 -0
- package/dist/templates/markdown/agents.md +25 -0
- package/dist/templates/markdown/gitignore.txt +12 -0
- package/dist/templates/markdown/index.d.ts +32 -0
- package/dist/templates/markdown/index.d.ts.map +1 -0
- package/dist/templates/markdown/index.js +58 -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 +40 -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/backend/script-conventions.md +467 -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 +118 -0
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +92 -0
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +94 -0
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md +394 -0
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +319 -0
- package/dist/templates/markdown/spec/guides/index.md.txt +89 -0
- package/dist/templates/markdown/spec/story/character.md.txt +95 -0
- package/dist/templates/markdown/spec/story/index.md.txt +31 -0
- package/dist/templates/markdown/spec/story/script.md.txt +313 -0
- package/dist/templates/markdown/spec/story/world.md.txt +92 -0
- package/dist/templates/markdown/workspace-index.md +123 -0
- package/dist/templates/markdown/worktree.yaml.txt +58 -0
- package/dist/templates/trellis/gitignore.txt +29 -0
- package/dist/templates/trellis/index.d.ts +49 -0
- package/dist/templates/trellis/index.d.ts.map +1 -0
- package/dist/templates/trellis/index.js +92 -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 +392 -0
- package/dist/templates/trellis/scripts/common/__init__.py +80 -0
- package/dist/templates/trellis/scripts/common/cli_adapter.py +435 -0
- package/dist/templates/trellis/scripts/common/developer.py +190 -0
- package/dist/templates/trellis/scripts/common/git_context.py +383 -0
- package/dist/templates/trellis/scripts/common/paths.py +347 -0
- package/dist/templates/trellis/scripts/common/phase.py +253 -0
- package/dist/templates/trellis/scripts/common/registry.py +366 -0
- package/dist/templates/trellis/scripts/common/task_queue.py +255 -0
- package/dist/templates/trellis/scripts/common/task_utils.py +178 -0
- package/dist/templates/trellis/scripts/common/worktree.py +219 -0
- package/dist/templates/trellis/scripts/create_bootstrap.py +290 -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/init_developer.py +51 -0
- package/dist/templates/trellis/scripts/multi_agent/__init__.py +5 -0
- package/dist/templates/trellis/scripts/multi_agent/cleanup.py +403 -0
- package/dist/templates/trellis/scripts/multi_agent/create_pr.py +329 -0
- package/dist/templates/trellis/scripts/multi_agent/plan.py +233 -0
- package/dist/templates/trellis/scripts/multi_agent/start.py +461 -0
- package/dist/templates/trellis/scripts/multi_agent/status.py +817 -0
- package/dist/templates/trellis/scripts/task.py +1056 -0
- package/dist/templates/trellis/scripts-shell-archive/add-session.sh +384 -0
- package/dist/templates/trellis/scripts-shell-archive/common/developer.sh +129 -0
- package/dist/templates/trellis/scripts-shell-archive/common/git-context.sh +263 -0
- package/dist/templates/trellis/scripts-shell-archive/common/paths.sh +208 -0
- package/dist/templates/trellis/scripts-shell-archive/common/phase.sh +150 -0
- package/dist/templates/trellis/scripts-shell-archive/common/registry.sh +247 -0
- package/dist/templates/trellis/scripts-shell-archive/common/task-queue.sh +142 -0
- package/dist/templates/trellis/scripts-shell-archive/common/task-utils.sh +151 -0
- package/dist/templates/trellis/scripts-shell-archive/common/worktree.sh +128 -0
- package/dist/templates/trellis/scripts-shell-archive/create-bootstrap.sh +299 -0
- package/dist/templates/trellis/scripts-shell-archive/get-context.sh +7 -0
- package/dist/templates/trellis/scripts-shell-archive/get-developer.sh +15 -0
- package/dist/templates/trellis/scripts-shell-archive/init-developer.sh +34 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/cleanup.sh +396 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/create-pr.sh +241 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/plan.sh +207 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/start.sh +317 -0
- package/dist/templates/trellis/scripts-shell-archive/multi-agent/status.sh +828 -0
- package/dist/templates/trellis/scripts-shell-archive/task.sh +1204 -0
- package/dist/templates/trellis/tasks/.gitkeep +0 -0
- package/dist/templates/trellis/workflow.md +416 -0
- package/dist/templates/trellis/worktree.yaml +47 -0
- package/dist/types/ai-tools.d.ts +48 -0
- package/dist/types/ai-tools.d.ts.map +1 -0
- package/dist/types/ai-tools.js +32 -0
- package/dist/types/ai-tools.js.map +1 -0
- package/dist/types/migration.d.ts +86 -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 +76 -0
- package/dist/utils/compare-versions.js.map +1 -0
- package/dist/utils/file-writer.d.ts +23 -0
- package/dist/utils/file-writer.d.ts.map +1 -0
- package/dist/utils/file-writer.js +140 -0
- package/dist/utils/file-writer.js.map +1 -0
- package/dist/utils/project-detector.d.ts +16 -0
- package/dist/utils/project-detector.d.ts.map +1 -0
- package/dist/utils/project-detector.js +188 -0
- package/dist/utils/project-detector.js.map +1 -0
- package/dist/utils/template-fetcher.d.ts +51 -0
- package/dist/utils/template-fetcher.d.ts.map +1 -0
- package/dist/utils/template-fetcher.js +174 -0
- package/dist/utils/template-fetcher.js.map +1 -0
- package/dist/utils/template-hash.d.ts +78 -0
- package/dist/utils/template-hash.d.ts.map +1 -0
- package/dist/utils/template-hash.js +239 -0
- package/dist/utils/template-hash.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,1204 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Task Management Script for Multi-Agent Pipeline
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./.aim-studio/scripts/task.sh create "<title>" [--slug <name>] [--assignee <dev>] [--priority P0|P1|P2|P3]
|
|
6
|
+
# ./.aim-studio/scripts/task.sh init-context <dir> <type> # Initialize jsonl files
|
|
7
|
+
# ./.aim-studio/scripts/task.sh add-context <dir> <file> <path> [reason] # Add jsonl entry
|
|
8
|
+
# ./.aim-studio/scripts/task.sh validate <dir> # Validate jsonl files
|
|
9
|
+
# ./.aim-studio/scripts/task.sh list-context <dir> # List jsonl entries
|
|
10
|
+
# ./.aim-studio/scripts/task.sh start <dir> # Set as current task
|
|
11
|
+
# ./.aim-studio/scripts/task.sh finish # Clear current task
|
|
12
|
+
# ./.aim-studio/scripts/task.sh set-branch <dir> <branch> # Set git branch
|
|
13
|
+
# ./.aim-studio/scripts/task.sh set-scope <dir> <scope> # Set scope for PR title
|
|
14
|
+
# ./.aim-studio/scripts/task.sh create-pr [dir] [--dry-run] # Create PR from task
|
|
15
|
+
# ./.aim-studio/scripts/task.sh archive <task-name> # Archive completed task
|
|
16
|
+
# ./.aim-studio/scripts/task.sh list # List active tasks
|
|
17
|
+
# ./.aim-studio/scripts/task.sh list-archive [month] # List archived tasks
|
|
18
|
+
#
|
|
19
|
+
# Task Directory Structure:
|
|
20
|
+
# tasks/
|
|
21
|
+
# ├── 01-21-my-task/
|
|
22
|
+
# │ ├── task.json # Metadata
|
|
23
|
+
# │ ├── prd.md # Requirements
|
|
24
|
+
# │ ├── info.md # Technical design (optional)
|
|
25
|
+
# │ ├── implement.jsonl # Implement agent context
|
|
26
|
+
# │ ├── check.jsonl # Check agent context
|
|
27
|
+
# │ └── debug.jsonl # Debug agent context
|
|
28
|
+
# └── archive/
|
|
29
|
+
# └── 2026-01/
|
|
30
|
+
# └── 01-21-old-task/
|
|
31
|
+
|
|
32
|
+
set -e
|
|
33
|
+
|
|
34
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
35
|
+
source "$SCRIPT_DIR/common/paths.sh"
|
|
36
|
+
source "$SCRIPT_DIR/common/developer.sh"
|
|
37
|
+
source "$SCRIPT_DIR/common/task-queue.sh"
|
|
38
|
+
source "$SCRIPT_DIR/common/task-utils.sh"
|
|
39
|
+
|
|
40
|
+
# Colors
|
|
41
|
+
RED='\033[0;31m'
|
|
42
|
+
GREEN='\033[0;32m'
|
|
43
|
+
YELLOW='\033[1;33m'
|
|
44
|
+
BLUE='\033[0;34m'
|
|
45
|
+
CYAN='\033[0;36m'
|
|
46
|
+
NC='\033[0m'
|
|
47
|
+
|
|
48
|
+
REPO_ROOT=$(get_repo_root)
|
|
49
|
+
|
|
50
|
+
# Platform (claude | cursor), can be overridden via --platform flag
|
|
51
|
+
PLATFORM="claude"
|
|
52
|
+
|
|
53
|
+
# Get command file path based on platform
|
|
54
|
+
# Claude: .claude/commands/trellis/<name>.md
|
|
55
|
+
# Cursor: .cursor/commands/trellis-<name>.md
|
|
56
|
+
get_command_path() {
|
|
57
|
+
local name="$1"
|
|
58
|
+
if [[ "$PLATFORM" == "cursor" ]]; then
|
|
59
|
+
echo ".cursor/commands/trellis-${name}.md"
|
|
60
|
+
else
|
|
61
|
+
echo ".claude/commands/trellis/${name}.md"
|
|
62
|
+
fi
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# =============================================================================
|
|
66
|
+
# Helper Functions
|
|
67
|
+
# =============================================================================
|
|
68
|
+
|
|
69
|
+
# Convert title to slug (only works with ASCII)
|
|
70
|
+
_slugify() {
|
|
71
|
+
local result=$(echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//')
|
|
72
|
+
echo "$result"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# =============================================================================
|
|
76
|
+
# jsonl Default Content Generators
|
|
77
|
+
# =============================================================================
|
|
78
|
+
|
|
79
|
+
get_implement_base() {
|
|
80
|
+
cat << EOF
|
|
81
|
+
{"file": "$DIR_WORKFLOW/workflow.md", "reason": "Project workflow and conventions"}
|
|
82
|
+
{"file": "$DIR_WORKFLOW/$DIR_SPEC/shared/index.md", "reason": "Shared coding standards"}
|
|
83
|
+
EOF
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
get_implement_backend() {
|
|
87
|
+
cat << EOF
|
|
88
|
+
{"file": "$DIR_WORKFLOW/$DIR_SPEC/backend/index.md", "reason": "Backend development guide"}
|
|
89
|
+
{"file": "$DIR_WORKFLOW/$DIR_SPEC/backend/api-module.md", "reason": "API module conventions"}
|
|
90
|
+
{"file": "$DIR_WORKFLOW/$DIR_SPEC/backend/quality.md", "reason": "Code quality requirements"}
|
|
91
|
+
EOF
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get_implement_frontend() {
|
|
95
|
+
cat << EOF
|
|
96
|
+
{"file": "$DIR_WORKFLOW/$DIR_SPEC/frontend/index.md", "reason": "Frontend development guide"}
|
|
97
|
+
{"file": "$DIR_WORKFLOW/$DIR_SPEC/frontend/components.md", "reason": "Component conventions"}
|
|
98
|
+
EOF
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
get_check_context() {
|
|
102
|
+
local dev_type="$1"
|
|
103
|
+
local finish_work=$(get_command_path "finish-work")
|
|
104
|
+
local check_backend=$(get_command_path "check-backend")
|
|
105
|
+
local check_frontend=$(get_command_path "check-frontend")
|
|
106
|
+
|
|
107
|
+
cat << EOF
|
|
108
|
+
{"file": "${finish_work}", "reason": "Finish work checklist"}
|
|
109
|
+
{"file": "$DIR_WORKFLOW/$DIR_SPEC/shared/index.md", "reason": "Shared coding standards"}
|
|
110
|
+
EOF
|
|
111
|
+
|
|
112
|
+
if [[ "$dev_type" == "backend" ]] || [[ "$dev_type" == "fullstack" ]]; then
|
|
113
|
+
echo "{\"file\": \"${check_backend}\", \"reason\": \"Backend check spec\"}"
|
|
114
|
+
fi
|
|
115
|
+
if [[ "$dev_type" == "frontend" ]] || [[ "$dev_type" == "fullstack" ]]; then
|
|
116
|
+
echo "{\"file\": \"${check_frontend}\", \"reason\": \"Frontend check spec\"}"
|
|
117
|
+
fi
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
get_debug_context() {
|
|
121
|
+
local dev_type="$1"
|
|
122
|
+
local check_backend=$(get_command_path "check-backend")
|
|
123
|
+
local check_frontend=$(get_command_path "check-frontend")
|
|
124
|
+
|
|
125
|
+
echo "{\"file\": \"$DIR_WORKFLOW/$DIR_SPEC/shared/index.md\", \"reason\": \"Shared coding standards\"}"
|
|
126
|
+
|
|
127
|
+
if [[ "$dev_type" == "backend" ]] || [[ "$dev_type" == "fullstack" ]]; then
|
|
128
|
+
echo "{\"file\": \"${check_backend}\", \"reason\": \"Backend check spec\"}"
|
|
129
|
+
fi
|
|
130
|
+
if [[ "$dev_type" == "frontend" ]] || [[ "$dev_type" == "fullstack" ]]; then
|
|
131
|
+
echo "{\"file\": \"${check_frontend}\", \"reason\": \"Frontend check spec\"}"
|
|
132
|
+
fi
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# =============================================================================
|
|
136
|
+
# Task Operations
|
|
137
|
+
# =============================================================================
|
|
138
|
+
|
|
139
|
+
ensure_tasks_dir() {
|
|
140
|
+
local tasks_dir=$(get_tasks_dir)
|
|
141
|
+
local archive_dir="$tasks_dir/archive"
|
|
142
|
+
|
|
143
|
+
if [[ ! -d "$tasks_dir" ]]; then
|
|
144
|
+
mkdir -p "$tasks_dir"
|
|
145
|
+
echo -e "${GREEN}Created tasks directory: $tasks_dir${NC}" >&2
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
if [[ ! -d "$archive_dir" ]]; then
|
|
149
|
+
mkdir -p "$archive_dir"
|
|
150
|
+
fi
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# =============================================================================
|
|
154
|
+
# Command: create
|
|
155
|
+
# =============================================================================
|
|
156
|
+
|
|
157
|
+
cmd_create() {
|
|
158
|
+
local title=""
|
|
159
|
+
local assignee=""
|
|
160
|
+
local priority="P2"
|
|
161
|
+
local slug=""
|
|
162
|
+
local description=""
|
|
163
|
+
|
|
164
|
+
# Parse arguments
|
|
165
|
+
while [[ $# -gt 0 ]]; do
|
|
166
|
+
case "$1" in
|
|
167
|
+
--assignee|-a)
|
|
168
|
+
assignee="$2"
|
|
169
|
+
shift 2
|
|
170
|
+
;;
|
|
171
|
+
--priority|-p)
|
|
172
|
+
priority="$2"
|
|
173
|
+
shift 2
|
|
174
|
+
;;
|
|
175
|
+
--slug|-s)
|
|
176
|
+
slug="$2"
|
|
177
|
+
shift 2
|
|
178
|
+
;;
|
|
179
|
+
--description|-d)
|
|
180
|
+
description="$2"
|
|
181
|
+
shift 2
|
|
182
|
+
;;
|
|
183
|
+
-*)
|
|
184
|
+
echo -e "${RED}Error: Unknown option $1${NC}" >&2
|
|
185
|
+
exit 1
|
|
186
|
+
;;
|
|
187
|
+
*)
|
|
188
|
+
if [[ -z "$title" ]]; then
|
|
189
|
+
title="$1"
|
|
190
|
+
fi
|
|
191
|
+
shift
|
|
192
|
+
;;
|
|
193
|
+
esac
|
|
194
|
+
done
|
|
195
|
+
|
|
196
|
+
# Validate required fields
|
|
197
|
+
if [[ -z "$title" ]]; then
|
|
198
|
+
echo -e "${RED}Error: title is required${NC}" >&2
|
|
199
|
+
echo "Usage: $0 create <title> [--assignee <dev>] [--priority P0|P1|P2|P3] [--slug <slug>]" >&2
|
|
200
|
+
exit 1
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
# Default assignee to current developer
|
|
204
|
+
if [[ -z "$assignee" ]]; then
|
|
205
|
+
assignee=$(get_developer "$REPO_ROOT")
|
|
206
|
+
if [[ -z "$assignee" ]]; then
|
|
207
|
+
echo -e "${RED}Error: No developer set. Run init-developer.sh first or use --assignee${NC}" >&2
|
|
208
|
+
exit 1
|
|
209
|
+
fi
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
ensure_tasks_dir
|
|
213
|
+
|
|
214
|
+
# Get current developer as creator
|
|
215
|
+
local creator=$(get_developer "$REPO_ROOT")
|
|
216
|
+
if [[ -z "$creator" ]]; then
|
|
217
|
+
creator="$assignee"
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
# Generate slug if not provided
|
|
221
|
+
if [[ -z "$slug" ]]; then
|
|
222
|
+
slug=$(_slugify "$title")
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# Validate slug
|
|
226
|
+
if [[ -z "$slug" ]]; then
|
|
227
|
+
echo -e "${RED}Error: could not generate slug from title${NC}" >&2
|
|
228
|
+
exit 1
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
# Create task directory with MM-DD-slug format
|
|
232
|
+
local tasks_dir=$(get_tasks_dir)
|
|
233
|
+
local date_prefix=$(generate_task_date_prefix)
|
|
234
|
+
local dir_name="${date_prefix}-${slug}"
|
|
235
|
+
local task_dir="$tasks_dir/$dir_name"
|
|
236
|
+
local task_json="$task_dir/$FILE_TASK_JSON"
|
|
237
|
+
|
|
238
|
+
if [[ -d "$task_dir" ]]; then
|
|
239
|
+
echo -e "${YELLOW}Warning: Task directory already exists: $dir_name${NC}" >&2
|
|
240
|
+
else
|
|
241
|
+
mkdir -p "$task_dir"
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
local today=$(date +%Y-%m-%d)
|
|
245
|
+
# Record current branch as base_branch (PR target)
|
|
246
|
+
local current_branch=$(git branch --show-current 2>/dev/null || echo "main")
|
|
247
|
+
|
|
248
|
+
cat > "$task_json" << EOF
|
|
249
|
+
{
|
|
250
|
+
"id": "$slug",
|
|
251
|
+
"name": "$slug",
|
|
252
|
+
"title": "$title",
|
|
253
|
+
"description": "$description",
|
|
254
|
+
"status": "planning",
|
|
255
|
+
"dev_type": null,
|
|
256
|
+
"scope": null,
|
|
257
|
+
"priority": "$priority",
|
|
258
|
+
"creator": "$creator",
|
|
259
|
+
"assignee": "$assignee",
|
|
260
|
+
"createdAt": "$today",
|
|
261
|
+
"completedAt": null,
|
|
262
|
+
"branch": null,
|
|
263
|
+
"base_branch": "$current_branch",
|
|
264
|
+
"worktree_path": null,
|
|
265
|
+
"current_phase": 0,
|
|
266
|
+
"next_action": [
|
|
267
|
+
{"phase": 1, "action": "implement"},
|
|
268
|
+
{"phase": 2, "action": "check"},
|
|
269
|
+
{"phase": 3, "action": "finish"},
|
|
270
|
+
{"phase": 4, "action": "create-pr"}
|
|
271
|
+
],
|
|
272
|
+
"commit": null,
|
|
273
|
+
"pr_url": null,
|
|
274
|
+
"subtasks": [],
|
|
275
|
+
"relatedFiles": [],
|
|
276
|
+
"notes": ""
|
|
277
|
+
}
|
|
278
|
+
EOF
|
|
279
|
+
|
|
280
|
+
echo -e "${GREEN}Created task: $dir_name${NC}" >&2
|
|
281
|
+
echo -e "" >&2
|
|
282
|
+
echo -e "${BLUE}Next steps:${NC}" >&2
|
|
283
|
+
echo -e " 1. Create prd.md with requirements" >&2
|
|
284
|
+
echo -e " 2. Run: $0 init-context <dir> <dev_type>" >&2
|
|
285
|
+
echo -e " 3. Run: $0 start <dir>" >&2
|
|
286
|
+
echo "" >&2
|
|
287
|
+
|
|
288
|
+
# Output relative path for script chaining
|
|
289
|
+
echo "$DIR_WORKFLOW/$DIR_TASKS/$dir_name"
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# =============================================================================
|
|
293
|
+
# Command: init-context
|
|
294
|
+
# =============================================================================
|
|
295
|
+
|
|
296
|
+
cmd_init_context() {
|
|
297
|
+
local target_dir=""
|
|
298
|
+
local dev_type=""
|
|
299
|
+
|
|
300
|
+
# Parse arguments
|
|
301
|
+
while [[ $# -gt 0 ]]; do
|
|
302
|
+
case "$1" in
|
|
303
|
+
--platform)
|
|
304
|
+
PLATFORM="$2"
|
|
305
|
+
shift 2
|
|
306
|
+
;;
|
|
307
|
+
-*)
|
|
308
|
+
echo -e "${RED}Error: Unknown option $1${NC}"
|
|
309
|
+
exit 1
|
|
310
|
+
;;
|
|
311
|
+
*)
|
|
312
|
+
if [[ -z "$target_dir" ]]; then
|
|
313
|
+
target_dir="$1"
|
|
314
|
+
elif [[ -z "$dev_type" ]]; then
|
|
315
|
+
dev_type="$1"
|
|
316
|
+
fi
|
|
317
|
+
shift
|
|
318
|
+
;;
|
|
319
|
+
esac
|
|
320
|
+
done
|
|
321
|
+
|
|
322
|
+
if [[ -z "$target_dir" ]] || [[ -z "$dev_type" ]]; then
|
|
323
|
+
echo -e "${RED}Error: Missing arguments${NC}"
|
|
324
|
+
echo "Usage: $0 init-context <task-dir> <dev_type> [--platform claude|cursor]"
|
|
325
|
+
echo " dev_type: backend | frontend | fullstack | test | docs"
|
|
326
|
+
echo " --platform: claude (default) | cursor"
|
|
327
|
+
exit 1
|
|
328
|
+
fi
|
|
329
|
+
|
|
330
|
+
# Support relative paths
|
|
331
|
+
if [[ ! "$target_dir" = /* ]]; then
|
|
332
|
+
target_dir="$REPO_ROOT/$target_dir"
|
|
333
|
+
fi
|
|
334
|
+
|
|
335
|
+
if [[ ! -d "$target_dir" ]]; then
|
|
336
|
+
echo -e "${RED}Error: Directory not found: $target_dir${NC}"
|
|
337
|
+
exit 1
|
|
338
|
+
fi
|
|
339
|
+
|
|
340
|
+
echo -e "${BLUE}=== Initializing Agent Context Files ===${NC}"
|
|
341
|
+
echo -e "Target dir: $target_dir"
|
|
342
|
+
echo -e "Dev type: $dev_type"
|
|
343
|
+
echo ""
|
|
344
|
+
|
|
345
|
+
# implement.jsonl
|
|
346
|
+
echo -e "${CYAN}Creating implement.jsonl...${NC}"
|
|
347
|
+
local implement_file="$target_dir/implement.jsonl"
|
|
348
|
+
{
|
|
349
|
+
get_implement_base
|
|
350
|
+
case "$dev_type" in
|
|
351
|
+
backend|test) get_implement_backend ;;
|
|
352
|
+
frontend) get_implement_frontend ;;
|
|
353
|
+
fullstack)
|
|
354
|
+
get_implement_backend
|
|
355
|
+
get_implement_frontend
|
|
356
|
+
;;
|
|
357
|
+
esac
|
|
358
|
+
} > "$implement_file"
|
|
359
|
+
echo -e " ${GREEN}✓${NC} $(wc -l < "$implement_file" | tr -d ' ') entries"
|
|
360
|
+
|
|
361
|
+
# check.jsonl
|
|
362
|
+
echo -e "${CYAN}Creating check.jsonl...${NC}"
|
|
363
|
+
local check_file="$target_dir/check.jsonl"
|
|
364
|
+
get_check_context "$dev_type" > "$check_file"
|
|
365
|
+
echo -e " ${GREEN}✓${NC} $(wc -l < "$check_file" | tr -d ' ') entries"
|
|
366
|
+
|
|
367
|
+
# debug.jsonl
|
|
368
|
+
echo -e "${CYAN}Creating debug.jsonl...${NC}"
|
|
369
|
+
local debug_file="$target_dir/debug.jsonl"
|
|
370
|
+
get_debug_context "$dev_type" > "$debug_file"
|
|
371
|
+
echo -e " ${GREEN}✓${NC} $(wc -l < "$debug_file" | tr -d ' ') entries"
|
|
372
|
+
|
|
373
|
+
echo ""
|
|
374
|
+
echo -e "${GREEN}✓ All context files created${NC}"
|
|
375
|
+
echo -e ""
|
|
376
|
+
echo -e "${BLUE}Next steps:${NC}"
|
|
377
|
+
echo -e " 1. Add task-specific specs: $0 add-context <dir> <jsonl> <path>"
|
|
378
|
+
echo -e " 2. Set as current: $0 start <dir>"
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
# =============================================================================
|
|
382
|
+
# Command: add-context
|
|
383
|
+
# =============================================================================
|
|
384
|
+
|
|
385
|
+
cmd_add_context() {
|
|
386
|
+
local target_dir="$1"
|
|
387
|
+
local jsonl_name="$2"
|
|
388
|
+
local path="$3"
|
|
389
|
+
local reason="${4:-Added manually}"
|
|
390
|
+
|
|
391
|
+
if [[ -z "$target_dir" ]] || [[ -z "$jsonl_name" ]] || [[ -z "$path" ]]; then
|
|
392
|
+
echo -e "${RED}Error: Missing arguments${NC}"
|
|
393
|
+
echo "Usage: $0 add-context <task-dir> <jsonl-file> <path> [reason]"
|
|
394
|
+
echo " jsonl-file: implement | check | debug (or full filename)"
|
|
395
|
+
exit 1
|
|
396
|
+
fi
|
|
397
|
+
|
|
398
|
+
# Support relative paths
|
|
399
|
+
if [[ ! "$target_dir" = /* ]]; then
|
|
400
|
+
target_dir="$REPO_ROOT/$target_dir"
|
|
401
|
+
fi
|
|
402
|
+
|
|
403
|
+
# Support shorthand
|
|
404
|
+
if [[ "$jsonl_name" != *.jsonl ]]; then
|
|
405
|
+
jsonl_name="${jsonl_name}.jsonl"
|
|
406
|
+
fi
|
|
407
|
+
|
|
408
|
+
local jsonl_file="$target_dir/$jsonl_name"
|
|
409
|
+
local full_path="$REPO_ROOT/$path"
|
|
410
|
+
local entry_type="file"
|
|
411
|
+
|
|
412
|
+
if [[ -d "$full_path" ]]; then
|
|
413
|
+
entry_type="directory"
|
|
414
|
+
[[ "$path" != */ ]] && path="$path/"
|
|
415
|
+
elif [[ ! -f "$full_path" ]]; then
|
|
416
|
+
echo -e "${RED}Error: Path not found: $path${NC}"
|
|
417
|
+
exit 1
|
|
418
|
+
fi
|
|
419
|
+
|
|
420
|
+
# Check if already exists
|
|
421
|
+
if [[ -f "$jsonl_file" ]] && grep -q "\"$path\"" "$jsonl_file" 2>/dev/null; then
|
|
422
|
+
echo -e "${YELLOW}Warning: Entry already exists for $path${NC}"
|
|
423
|
+
exit 0
|
|
424
|
+
fi
|
|
425
|
+
|
|
426
|
+
# Add entry
|
|
427
|
+
if [[ "$entry_type" == "directory" ]]; then
|
|
428
|
+
echo "{\"file\": \"$path\", \"type\": \"directory\", \"reason\": \"$reason\"}" >> "$jsonl_file"
|
|
429
|
+
else
|
|
430
|
+
echo "{\"file\": \"$path\", \"reason\": \"$reason\"}" >> "$jsonl_file"
|
|
431
|
+
fi
|
|
432
|
+
|
|
433
|
+
echo -e "${GREEN}Added $entry_type: $path${NC}"
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
# =============================================================================
|
|
437
|
+
# Command: validate
|
|
438
|
+
# =============================================================================
|
|
439
|
+
|
|
440
|
+
validate_jsonl() {
|
|
441
|
+
local jsonl_file="$1"
|
|
442
|
+
local file_name=$(basename "$jsonl_file")
|
|
443
|
+
local errors=0
|
|
444
|
+
local line_num=0
|
|
445
|
+
|
|
446
|
+
if [[ ! -f "$jsonl_file" ]]; then
|
|
447
|
+
echo -e " ${YELLOW}$file_name: not found (skipped)${NC}"
|
|
448
|
+
return 0
|
|
449
|
+
fi
|
|
450
|
+
|
|
451
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
452
|
+
line_num=$((line_num + 1))
|
|
453
|
+
[[ -z "$line" ]] && continue
|
|
454
|
+
|
|
455
|
+
if ! echo "$line" | jq -e . > /dev/null 2>&1; then
|
|
456
|
+
echo -e " ${RED}$file_name:$line_num: Invalid JSON${NC}"
|
|
457
|
+
errors=$((errors + 1))
|
|
458
|
+
continue
|
|
459
|
+
fi
|
|
460
|
+
|
|
461
|
+
local file_path=$(echo "$line" | jq -r '.file // empty')
|
|
462
|
+
local entry_type=$(echo "$line" | jq -r '.type // "file"')
|
|
463
|
+
|
|
464
|
+
if [[ -z "$file_path" ]]; then
|
|
465
|
+
echo -e " ${RED}$file_name:$line_num: Missing 'file' field${NC}"
|
|
466
|
+
errors=$((errors + 1))
|
|
467
|
+
continue
|
|
468
|
+
fi
|
|
469
|
+
|
|
470
|
+
local full_path="$REPO_ROOT/$file_path"
|
|
471
|
+
if [[ "$entry_type" == "directory" ]]; then
|
|
472
|
+
if [[ ! -d "$full_path" ]]; then
|
|
473
|
+
echo -e " ${RED}$file_name:$line_num: Directory not found: $file_path${NC}"
|
|
474
|
+
errors=$((errors + 1))
|
|
475
|
+
fi
|
|
476
|
+
else
|
|
477
|
+
if [[ ! -f "$full_path" ]]; then
|
|
478
|
+
echo -e " ${RED}$file_name:$line_num: File not found: $file_path${NC}"
|
|
479
|
+
errors=$((errors + 1))
|
|
480
|
+
fi
|
|
481
|
+
fi
|
|
482
|
+
done < "$jsonl_file"
|
|
483
|
+
|
|
484
|
+
if [[ $errors -eq 0 ]]; then
|
|
485
|
+
echo -e " ${GREEN}$file_name: ✓ ($line_num entries)${NC}"
|
|
486
|
+
else
|
|
487
|
+
echo -e " ${RED}$file_name: ✗ ($errors errors)${NC}"
|
|
488
|
+
fi
|
|
489
|
+
|
|
490
|
+
return $errors
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
cmd_validate() {
|
|
494
|
+
local target_dir="$1"
|
|
495
|
+
|
|
496
|
+
if [[ -z "$target_dir" ]]; then
|
|
497
|
+
echo -e "${RED}Error: task directory required${NC}"
|
|
498
|
+
exit 1
|
|
499
|
+
fi
|
|
500
|
+
|
|
501
|
+
if [[ ! "$target_dir" = /* ]]; then
|
|
502
|
+
target_dir="$REPO_ROOT/$target_dir"
|
|
503
|
+
fi
|
|
504
|
+
|
|
505
|
+
echo -e "${BLUE}=== Validating Context Files ===${NC}"
|
|
506
|
+
echo -e "Target dir: $target_dir"
|
|
507
|
+
echo ""
|
|
508
|
+
|
|
509
|
+
local total_errors=0
|
|
510
|
+
for jsonl_file in "$target_dir"/{implement,check,debug}.jsonl; do
|
|
511
|
+
validate_jsonl "$jsonl_file"
|
|
512
|
+
total_errors=$((total_errors + $?))
|
|
513
|
+
done
|
|
514
|
+
|
|
515
|
+
echo ""
|
|
516
|
+
if [[ $total_errors -eq 0 ]]; then
|
|
517
|
+
echo -e "${GREEN}✓ All validations passed${NC}"
|
|
518
|
+
else
|
|
519
|
+
echo -e "${RED}✗ Validation failed ($total_errors errors)${NC}"
|
|
520
|
+
exit 1
|
|
521
|
+
fi
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
# =============================================================================
|
|
525
|
+
# Command: list-context
|
|
526
|
+
# =============================================================================
|
|
527
|
+
|
|
528
|
+
cmd_list_context() {
|
|
529
|
+
local target_dir="$1"
|
|
530
|
+
|
|
531
|
+
if [[ -z "$target_dir" ]]; then
|
|
532
|
+
echo -e "${RED}Error: task directory required${NC}"
|
|
533
|
+
exit 1
|
|
534
|
+
fi
|
|
535
|
+
|
|
536
|
+
if [[ ! "$target_dir" = /* ]]; then
|
|
537
|
+
target_dir="$REPO_ROOT/$target_dir"
|
|
538
|
+
fi
|
|
539
|
+
|
|
540
|
+
echo -e "${BLUE}=== Context Files ===${NC}"
|
|
541
|
+
echo ""
|
|
542
|
+
|
|
543
|
+
for jsonl_file in "$target_dir"/{implement,check,debug}.jsonl; do
|
|
544
|
+
local file_name=$(basename "$jsonl_file")
|
|
545
|
+
[[ ! -f "$jsonl_file" ]] && continue
|
|
546
|
+
|
|
547
|
+
echo -e "${CYAN}[$file_name]${NC}"
|
|
548
|
+
|
|
549
|
+
local count=0
|
|
550
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
551
|
+
[[ -z "$line" ]] && continue
|
|
552
|
+
|
|
553
|
+
local file_path=$(echo "$line" | jq -r '.file // "?"')
|
|
554
|
+
local entry_type=$(echo "$line" | jq -r '.type // "file"')
|
|
555
|
+
local reason=$(echo "$line" | jq -r '.reason // "-"')
|
|
556
|
+
count=$((count + 1))
|
|
557
|
+
|
|
558
|
+
if [[ "$entry_type" == "directory" ]]; then
|
|
559
|
+
echo -e " ${GREEN}$count.${NC} [DIR] $file_path"
|
|
560
|
+
else
|
|
561
|
+
echo -e " ${GREEN}$count.${NC} $file_path"
|
|
562
|
+
fi
|
|
563
|
+
echo -e " ${YELLOW}→${NC} $reason"
|
|
564
|
+
done < "$jsonl_file"
|
|
565
|
+
|
|
566
|
+
echo ""
|
|
567
|
+
done
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
# =============================================================================
|
|
571
|
+
# Command: start / finish
|
|
572
|
+
# =============================================================================
|
|
573
|
+
|
|
574
|
+
cmd_start() {
|
|
575
|
+
local task_dir="$1"
|
|
576
|
+
|
|
577
|
+
if [[ -z "$task_dir" ]]; then
|
|
578
|
+
echo -e "${RED}Error: task directory required${NC}"
|
|
579
|
+
exit 1
|
|
580
|
+
fi
|
|
581
|
+
|
|
582
|
+
# Convert to relative path
|
|
583
|
+
if [[ "$task_dir" = /* ]]; then
|
|
584
|
+
task_dir="${task_dir#$REPO_ROOT/}"
|
|
585
|
+
fi
|
|
586
|
+
|
|
587
|
+
# Verify directory exists
|
|
588
|
+
if [[ ! -d "$REPO_ROOT/$task_dir" ]]; then
|
|
589
|
+
echo -e "${RED}Error: Task directory not found: $task_dir${NC}"
|
|
590
|
+
exit 1
|
|
591
|
+
fi
|
|
592
|
+
|
|
593
|
+
set_current_task "$task_dir"
|
|
594
|
+
echo -e "${GREEN}✓ Current task set to: $task_dir${NC}"
|
|
595
|
+
echo ""
|
|
596
|
+
echo -e "${BLUE}The hook will now inject context from this task's jsonl files.${NC}"
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
cmd_finish() {
|
|
600
|
+
local current=$(get_current_task)
|
|
601
|
+
|
|
602
|
+
if [[ -z "$current" ]]; then
|
|
603
|
+
echo -e "${YELLOW}No current task set${NC}"
|
|
604
|
+
exit 0
|
|
605
|
+
fi
|
|
606
|
+
|
|
607
|
+
clear_current_task
|
|
608
|
+
echo -e "${GREEN}✓ Cleared current task (was: $current)${NC}"
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
# =============================================================================
|
|
612
|
+
# Command: archive
|
|
613
|
+
# =============================================================================
|
|
614
|
+
|
|
615
|
+
cmd_archive() {
|
|
616
|
+
local task_name="$1"
|
|
617
|
+
|
|
618
|
+
if [[ -z "$task_name" ]]; then
|
|
619
|
+
echo -e "${RED}Error: Task name is required${NC}" >&2
|
|
620
|
+
echo "Usage: $0 archive <task-name>" >&2
|
|
621
|
+
exit 1
|
|
622
|
+
fi
|
|
623
|
+
|
|
624
|
+
local tasks_dir=$(get_tasks_dir)
|
|
625
|
+
|
|
626
|
+
# Find task directory using common function
|
|
627
|
+
local task_dir=$(find_task_by_name "$task_name" "$tasks_dir")
|
|
628
|
+
|
|
629
|
+
if [[ -z "$task_dir" ]] || [[ ! -d "$task_dir" ]]; then
|
|
630
|
+
echo -e "${RED}Error: Task not found: $task_name${NC}" >&2
|
|
631
|
+
echo "Active tasks:" >&2
|
|
632
|
+
cmd_list >&2
|
|
633
|
+
exit 1
|
|
634
|
+
fi
|
|
635
|
+
|
|
636
|
+
local dir_name=$(basename "$task_dir")
|
|
637
|
+
local task_json="$task_dir/$FILE_TASK_JSON"
|
|
638
|
+
|
|
639
|
+
# Update status before archiving
|
|
640
|
+
local today=$(date +%Y-%m-%d)
|
|
641
|
+
if [[ -f "$task_json" ]] && command -v jq &> /dev/null; then
|
|
642
|
+
local temp_file=$(mktemp)
|
|
643
|
+
jq --arg date "$today" '.status = "completed" | .completedAt = $date' "$task_json" > "$temp_file"
|
|
644
|
+
mv "$temp_file" "$task_json"
|
|
645
|
+
fi
|
|
646
|
+
|
|
647
|
+
# Clear if current task
|
|
648
|
+
local current=$(get_current_task)
|
|
649
|
+
if [[ "$current" == *"$dir_name"* ]]; then
|
|
650
|
+
clear_current_task
|
|
651
|
+
fi
|
|
652
|
+
|
|
653
|
+
# Use common archive function
|
|
654
|
+
local result=$(archive_task_complete "$task_dir" "$REPO_ROOT")
|
|
655
|
+
local archive_dest=""
|
|
656
|
+
|
|
657
|
+
echo "$result" | while IFS= read -r line; do
|
|
658
|
+
case "$line" in
|
|
659
|
+
archived_to:*)
|
|
660
|
+
archive_dest="${line#archived_to:}"
|
|
661
|
+
local year_month=$(basename "$(dirname "$archive_dest")")
|
|
662
|
+
echo -e "${GREEN}Archived: $dir_name -> archive/$year_month/${NC}" >&2
|
|
663
|
+
;;
|
|
664
|
+
esac
|
|
665
|
+
done
|
|
666
|
+
|
|
667
|
+
# Return the archive path
|
|
668
|
+
local year_month=$(date +%Y-%m)
|
|
669
|
+
echo "$DIR_WORKFLOW/$DIR_TASKS/$DIR_ARCHIVE/$year_month/$dir_name"
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
# =============================================================================
|
|
673
|
+
# Command: list
|
|
674
|
+
# =============================================================================
|
|
675
|
+
|
|
676
|
+
cmd_list() {
|
|
677
|
+
local filter_mine=false
|
|
678
|
+
local filter_status=""
|
|
679
|
+
|
|
680
|
+
# Parse arguments
|
|
681
|
+
while [[ $# -gt 0 ]]; do
|
|
682
|
+
case "$1" in
|
|
683
|
+
--mine|-m)
|
|
684
|
+
filter_mine=true
|
|
685
|
+
shift
|
|
686
|
+
;;
|
|
687
|
+
--status|-s)
|
|
688
|
+
filter_status="$2"
|
|
689
|
+
shift 2
|
|
690
|
+
;;
|
|
691
|
+
*)
|
|
692
|
+
shift
|
|
693
|
+
;;
|
|
694
|
+
esac
|
|
695
|
+
done
|
|
696
|
+
|
|
697
|
+
local tasks_dir=$(get_tasks_dir)
|
|
698
|
+
local current_task=$(get_current_task)
|
|
699
|
+
local developer=$(get_developer "$REPO_ROOT")
|
|
700
|
+
|
|
701
|
+
if [[ "$filter_mine" == "true" ]]; then
|
|
702
|
+
if [[ -z "$developer" ]]; then
|
|
703
|
+
echo -e "${RED}Error: No developer set. Run init-developer.sh first${NC}" >&2
|
|
704
|
+
exit 1
|
|
705
|
+
fi
|
|
706
|
+
echo -e "${BLUE}My tasks (assignee: $developer):${NC}"
|
|
707
|
+
else
|
|
708
|
+
echo -e "${BLUE}All active tasks:${NC}"
|
|
709
|
+
fi
|
|
710
|
+
echo ""
|
|
711
|
+
|
|
712
|
+
local count=0
|
|
713
|
+
|
|
714
|
+
for d in "$tasks_dir"/*/; do
|
|
715
|
+
if [[ -d "$d" ]] && [[ "$(basename "$d")" != "archive" ]]; then
|
|
716
|
+
local dir_name=$(basename "$d")
|
|
717
|
+
local task_json="$d/$FILE_TASK_JSON"
|
|
718
|
+
local status="unknown"
|
|
719
|
+
local assignee="-"
|
|
720
|
+
local relative_path="$DIR_WORKFLOW/$DIR_TASKS/$dir_name"
|
|
721
|
+
|
|
722
|
+
if [[ -f "$task_json" ]] && command -v jq &> /dev/null; then
|
|
723
|
+
status=$(jq -r '.status // "unknown"' "$task_json")
|
|
724
|
+
assignee=$(jq -r '.assignee // "-"' "$task_json")
|
|
725
|
+
fi
|
|
726
|
+
|
|
727
|
+
# Apply --mine filter
|
|
728
|
+
if [[ "$filter_mine" == "true" ]] && [[ "$assignee" != "$developer" ]]; then
|
|
729
|
+
continue
|
|
730
|
+
fi
|
|
731
|
+
|
|
732
|
+
# Apply --status filter
|
|
733
|
+
if [[ -n "$filter_status" ]] && [[ "$status" != "$filter_status" ]]; then
|
|
734
|
+
continue
|
|
735
|
+
fi
|
|
736
|
+
|
|
737
|
+
local marker=""
|
|
738
|
+
if [[ "$relative_path" == "$current_task" ]]; then
|
|
739
|
+
marker=" ${GREEN}<- current${NC}"
|
|
740
|
+
fi
|
|
741
|
+
|
|
742
|
+
if [[ "$filter_mine" == "true" ]]; then
|
|
743
|
+
echo -e " - $dir_name/ ($status)$marker"
|
|
744
|
+
else
|
|
745
|
+
echo -e " - $dir_name/ ($status) [${CYAN}$assignee${NC}]$marker"
|
|
746
|
+
fi
|
|
747
|
+
((count++))
|
|
748
|
+
fi
|
|
749
|
+
done
|
|
750
|
+
|
|
751
|
+
if [[ $count -eq 0 ]]; then
|
|
752
|
+
if [[ "$filter_mine" == "true" ]]; then
|
|
753
|
+
echo " (no tasks assigned to you)"
|
|
754
|
+
else
|
|
755
|
+
echo " (no active tasks)"
|
|
756
|
+
fi
|
|
757
|
+
fi
|
|
758
|
+
|
|
759
|
+
echo ""
|
|
760
|
+
echo "Total: $count task(s)"
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
# =============================================================================
|
|
764
|
+
# Command: list-archive
|
|
765
|
+
# =============================================================================
|
|
766
|
+
|
|
767
|
+
cmd_list_archive() {
|
|
768
|
+
local month="$1"
|
|
769
|
+
|
|
770
|
+
local tasks_dir=$(get_tasks_dir)
|
|
771
|
+
local archive_dir="$tasks_dir/archive"
|
|
772
|
+
|
|
773
|
+
echo -e "${BLUE}Archived tasks:${NC}"
|
|
774
|
+
echo ""
|
|
775
|
+
|
|
776
|
+
if [[ -n "$month" ]]; then
|
|
777
|
+
local month_dir="$archive_dir/$month"
|
|
778
|
+
if [[ -d "$month_dir" ]]; then
|
|
779
|
+
echo "[$month]"
|
|
780
|
+
for d in "$month_dir"/*/; do
|
|
781
|
+
if [[ -d "$d" ]]; then
|
|
782
|
+
echo " - $(basename "$d")/"
|
|
783
|
+
fi
|
|
784
|
+
done
|
|
785
|
+
else
|
|
786
|
+
echo " No archives for $month"
|
|
787
|
+
fi
|
|
788
|
+
else
|
|
789
|
+
for month_dir in "$archive_dir"/*/; do
|
|
790
|
+
if [[ -d "$month_dir" ]]; then
|
|
791
|
+
local month_name=$(basename "$month_dir")
|
|
792
|
+
local count=$(find "$month_dir" -maxdepth 1 -type d ! -name "$(basename "$month_dir")" | wc -l | tr -d ' ')
|
|
793
|
+
echo "[$month_name] - $count task(s)"
|
|
794
|
+
fi
|
|
795
|
+
done
|
|
796
|
+
fi
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
# =============================================================================
|
|
800
|
+
# Command: set-branch
|
|
801
|
+
# =============================================================================
|
|
802
|
+
|
|
803
|
+
cmd_set_branch() {
|
|
804
|
+
local target_dir="$1"
|
|
805
|
+
local branch="$2"
|
|
806
|
+
|
|
807
|
+
if [[ -z "$target_dir" ]] || [[ -z "$branch" ]]; then
|
|
808
|
+
echo -e "${RED}Error: Missing arguments${NC}"
|
|
809
|
+
echo "Usage: $0 set-branch <task-dir> <branch-name>"
|
|
810
|
+
echo "Example: $0 set-branch <dir> task/my-task"
|
|
811
|
+
exit 1
|
|
812
|
+
fi
|
|
813
|
+
|
|
814
|
+
# Support relative paths
|
|
815
|
+
if [[ ! "$target_dir" = /* ]]; then
|
|
816
|
+
target_dir="$REPO_ROOT/$target_dir"
|
|
817
|
+
fi
|
|
818
|
+
|
|
819
|
+
local task_json="$target_dir/$FILE_TASK_JSON"
|
|
820
|
+
if [[ ! -f "$task_json" ]]; then
|
|
821
|
+
echo -e "${RED}Error: task.json not found at $target_dir${NC}"
|
|
822
|
+
exit 1
|
|
823
|
+
fi
|
|
824
|
+
|
|
825
|
+
# Update branch field
|
|
826
|
+
jq --arg branch "$branch" '.branch = $branch' "$task_json" > "${task_json}.tmp"
|
|
827
|
+
mv "${task_json}.tmp" "$task_json"
|
|
828
|
+
|
|
829
|
+
echo -e "${GREEN}✓ Branch set to: $branch${NC}"
|
|
830
|
+
echo ""
|
|
831
|
+
echo -e "${BLUE}Now you can start the multi-agent pipeline:${NC}"
|
|
832
|
+
echo " ./.aim-studio/scripts/multi-agent/start.sh $1"
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
# =============================================================================
|
|
836
|
+
# Command: set-base-branch
|
|
837
|
+
# =============================================================================
|
|
838
|
+
|
|
839
|
+
cmd_set_base_branch() {
|
|
840
|
+
local target_dir="$1"
|
|
841
|
+
local base_branch="$2"
|
|
842
|
+
|
|
843
|
+
if [[ -z "$target_dir" ]] || [[ -z "$base_branch" ]]; then
|
|
844
|
+
echo -e "${RED}Error: Missing arguments${NC}"
|
|
845
|
+
echo "Usage: $0 set-base-branch <task-dir> <base-branch>"
|
|
846
|
+
echo "Example: $0 set-base-branch <dir> develop"
|
|
847
|
+
echo ""
|
|
848
|
+
echo "This sets the target branch for PR (the branch your feature will merge into)."
|
|
849
|
+
exit 1
|
|
850
|
+
fi
|
|
851
|
+
|
|
852
|
+
# Support relative paths
|
|
853
|
+
if [[ ! "$target_dir" = /* ]]; then
|
|
854
|
+
target_dir="$REPO_ROOT/$target_dir"
|
|
855
|
+
fi
|
|
856
|
+
|
|
857
|
+
local task_json="$target_dir/$FILE_TASK_JSON"
|
|
858
|
+
if [[ ! -f "$task_json" ]]; then
|
|
859
|
+
echo -e "${RED}Error: task.json not found at $target_dir${NC}"
|
|
860
|
+
exit 1
|
|
861
|
+
fi
|
|
862
|
+
|
|
863
|
+
# Update base_branch field
|
|
864
|
+
jq --arg base "$base_branch" '.base_branch = $base' "$task_json" > "${task_json}.tmp"
|
|
865
|
+
mv "${task_json}.tmp" "$task_json"
|
|
866
|
+
|
|
867
|
+
echo -e "${GREEN}✓ Base branch set to: $base_branch${NC}"
|
|
868
|
+
echo -e " PR will target: $base_branch"
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
# =============================================================================
|
|
872
|
+
# Command: set-scope
|
|
873
|
+
# =============================================================================
|
|
874
|
+
|
|
875
|
+
cmd_set_scope() {
|
|
876
|
+
local target_dir="$1"
|
|
877
|
+
local scope="$2"
|
|
878
|
+
|
|
879
|
+
if [[ -z "$target_dir" ]] || [[ -z "$scope" ]]; then
|
|
880
|
+
echo -e "${RED}Error: Missing arguments${NC}"
|
|
881
|
+
echo "Usage: $0 set-scope <task-dir> <scope>"
|
|
882
|
+
echo "Example: $0 set-scope <dir> api"
|
|
883
|
+
exit 1
|
|
884
|
+
fi
|
|
885
|
+
|
|
886
|
+
# Support relative paths
|
|
887
|
+
if [[ ! "$target_dir" = /* ]]; then
|
|
888
|
+
target_dir="$REPO_ROOT/$target_dir"
|
|
889
|
+
fi
|
|
890
|
+
|
|
891
|
+
local task_json="$target_dir/$FILE_TASK_JSON"
|
|
892
|
+
if [[ ! -f "$task_json" ]]; then
|
|
893
|
+
echo -e "${RED}Error: task.json not found at $target_dir${NC}"
|
|
894
|
+
exit 1
|
|
895
|
+
fi
|
|
896
|
+
|
|
897
|
+
# Update scope field
|
|
898
|
+
jq --arg scope "$scope" '.scope = $scope' "$task_json" > "${task_json}.tmp"
|
|
899
|
+
mv "${task_json}.tmp" "$task_json"
|
|
900
|
+
|
|
901
|
+
echo -e "${GREEN}✓ Scope set to: $scope${NC}"
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
# =============================================================================
|
|
905
|
+
# Command: create-pr
|
|
906
|
+
# =============================================================================
|
|
907
|
+
|
|
908
|
+
cmd_create_pr() {
|
|
909
|
+
local target_dir=""
|
|
910
|
+
local dry_run=false
|
|
911
|
+
|
|
912
|
+
# Parse arguments
|
|
913
|
+
while [[ $# -gt 0 ]]; do
|
|
914
|
+
case "$1" in
|
|
915
|
+
--dry-run)
|
|
916
|
+
dry_run=true
|
|
917
|
+
shift
|
|
918
|
+
;;
|
|
919
|
+
*)
|
|
920
|
+
if [[ -z "$target_dir" ]]; then
|
|
921
|
+
target_dir="$1"
|
|
922
|
+
fi
|
|
923
|
+
shift
|
|
924
|
+
;;
|
|
925
|
+
esac
|
|
926
|
+
done
|
|
927
|
+
|
|
928
|
+
# Get task directory
|
|
929
|
+
if [[ -z "$target_dir" ]]; then
|
|
930
|
+
target_dir=$(get_current_task)
|
|
931
|
+
if [[ -z "$target_dir" ]]; then
|
|
932
|
+
echo -e "${RED}Error: No task directory specified and no current task set${NC}"
|
|
933
|
+
echo "Usage: $0 create-pr [task-dir] [--dry-run]"
|
|
934
|
+
exit 1
|
|
935
|
+
fi
|
|
936
|
+
fi
|
|
937
|
+
|
|
938
|
+
# Support relative paths
|
|
939
|
+
if [[ ! "$target_dir" = /* ]]; then
|
|
940
|
+
target_dir="$REPO_ROOT/$target_dir"
|
|
941
|
+
fi
|
|
942
|
+
|
|
943
|
+
local task_json="$target_dir/$FILE_TASK_JSON"
|
|
944
|
+
if [[ ! -f "$task_json" ]]; then
|
|
945
|
+
echo -e "${RED}Error: task.json not found at $target_dir${NC}"
|
|
946
|
+
exit 1
|
|
947
|
+
fi
|
|
948
|
+
|
|
949
|
+
echo -e "${BLUE}=== Create PR ===${NC}"
|
|
950
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
951
|
+
echo -e "${YELLOW}[DRY-RUN MODE] No actual changes will be made${NC}"
|
|
952
|
+
fi
|
|
953
|
+
echo ""
|
|
954
|
+
|
|
955
|
+
# Read task config
|
|
956
|
+
local task_name=$(jq -r '.name' "$task_json")
|
|
957
|
+
local base_branch=$(jq -r '.base_branch // "main"' "$task_json")
|
|
958
|
+
local scope=$(jq -r '.scope // "core"' "$task_json")
|
|
959
|
+
local dev_type=$(jq -r '.dev_type // "feature"' "$task_json")
|
|
960
|
+
|
|
961
|
+
# Map dev_type to commit prefix
|
|
962
|
+
local commit_prefix
|
|
963
|
+
case "$dev_type" in
|
|
964
|
+
feature|frontend|backend|fullstack) commit_prefix="feat" ;;
|
|
965
|
+
bugfix|fix) commit_prefix="fix" ;;
|
|
966
|
+
refactor) commit_prefix="refactor" ;;
|
|
967
|
+
docs) commit_prefix="docs" ;;
|
|
968
|
+
test) commit_prefix="test" ;;
|
|
969
|
+
*) commit_prefix="feat" ;;
|
|
970
|
+
esac
|
|
971
|
+
|
|
972
|
+
echo -e "Task: ${task_name}"
|
|
973
|
+
echo -e "Base branch: ${base_branch}"
|
|
974
|
+
echo -e "Scope: ${scope}"
|
|
975
|
+
echo -e "Commit prefix: ${commit_prefix}"
|
|
976
|
+
echo ""
|
|
977
|
+
|
|
978
|
+
# Get current branch
|
|
979
|
+
local current_branch=$(git branch --show-current)
|
|
980
|
+
echo -e "Current branch: ${current_branch}"
|
|
981
|
+
|
|
982
|
+
# Check for changes
|
|
983
|
+
echo -e "${YELLOW}Checking for changes...${NC}"
|
|
984
|
+
|
|
985
|
+
# Stage changes (even in dry-run to detect what would be committed)
|
|
986
|
+
git add -A
|
|
987
|
+
# Exclude workspace and temp files
|
|
988
|
+
git reset "$DIR_WORKFLOW/$DIR_WORKSPACE/" 2>/dev/null || true
|
|
989
|
+
git reset .agent-log .agent-runner.sh 2>/dev/null || true
|
|
990
|
+
|
|
991
|
+
# Check if there are staged changes
|
|
992
|
+
if git diff --cached --quiet 2>/dev/null; then
|
|
993
|
+
echo -e "${YELLOW}No staged changes to commit${NC}"
|
|
994
|
+
|
|
995
|
+
# Check for unpushed commits
|
|
996
|
+
local unpushed=$(git log "origin/${current_branch}..HEAD" --oneline 2>/dev/null | wc -l | tr -d ' ' || echo "0")
|
|
997
|
+
if [[ "$unpushed" -eq 0 ]] 2>/dev/null; then
|
|
998
|
+
# In dry-run, also reset the staging
|
|
999
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
1000
|
+
git reset HEAD >/dev/null 2>&1 || true
|
|
1001
|
+
fi
|
|
1002
|
+
echo -e "${RED}No changes to create PR${NC}"
|
|
1003
|
+
exit 1
|
|
1004
|
+
fi
|
|
1005
|
+
echo -e "Found ${unpushed} unpushed commit(s)"
|
|
1006
|
+
else
|
|
1007
|
+
# Commit changes
|
|
1008
|
+
echo -e "${YELLOW}Committing changes...${NC}"
|
|
1009
|
+
local commit_msg="${commit_prefix}(${scope}): ${task_name}"
|
|
1010
|
+
|
|
1011
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
1012
|
+
echo -e "[DRY-RUN] Would commit with message: ${commit_msg}"
|
|
1013
|
+
echo -e "[DRY-RUN] Staged files:"
|
|
1014
|
+
git diff --cached --name-only | sed 's/^/ - /'
|
|
1015
|
+
else
|
|
1016
|
+
git commit -m "$commit_msg"
|
|
1017
|
+
echo -e "${GREEN}Committed: ${commit_msg}${NC}"
|
|
1018
|
+
fi
|
|
1019
|
+
fi
|
|
1020
|
+
|
|
1021
|
+
# Push to remote
|
|
1022
|
+
echo -e "${YELLOW}Pushing to remote...${NC}"
|
|
1023
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
1024
|
+
echo -e "[DRY-RUN] Would push to: origin/${current_branch}"
|
|
1025
|
+
else
|
|
1026
|
+
git push -u origin "$current_branch"
|
|
1027
|
+
echo -e "${GREEN}Pushed to origin/${current_branch}${NC}"
|
|
1028
|
+
fi
|
|
1029
|
+
|
|
1030
|
+
# Create PR
|
|
1031
|
+
echo -e "${YELLOW}Creating PR...${NC}"
|
|
1032
|
+
local pr_title="${commit_prefix}(${scope}): ${task_name}"
|
|
1033
|
+
local pr_url=""
|
|
1034
|
+
|
|
1035
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
1036
|
+
echo -e "[DRY-RUN] Would create PR:"
|
|
1037
|
+
echo -e " Title: ${pr_title}"
|
|
1038
|
+
echo -e " Base: ${base_branch}"
|
|
1039
|
+
echo -e " Head: ${current_branch}"
|
|
1040
|
+
if [[ -f "$target_dir/prd.md" ]]; then
|
|
1041
|
+
echo -e " Body: (from prd.md)"
|
|
1042
|
+
fi
|
|
1043
|
+
pr_url="https://github.com/example/repo/pull/DRY-RUN"
|
|
1044
|
+
else
|
|
1045
|
+
# Check if PR already exists
|
|
1046
|
+
local existing_pr=$(gh pr list --head "$current_branch" --base "$base_branch" --json url --jq '.[0].url' 2>/dev/null || echo "")
|
|
1047
|
+
|
|
1048
|
+
if [[ -n "$existing_pr" ]]; then
|
|
1049
|
+
echo -e "${YELLOW}PR already exists: ${existing_pr}${NC}"
|
|
1050
|
+
pr_url="$existing_pr"
|
|
1051
|
+
else
|
|
1052
|
+
# Read PRD as PR body
|
|
1053
|
+
local pr_body=""
|
|
1054
|
+
if [[ -f "$target_dir/prd.md" ]]; then
|
|
1055
|
+
pr_body=$(cat "$target_dir/prd.md")
|
|
1056
|
+
fi
|
|
1057
|
+
|
|
1058
|
+
# Create PR
|
|
1059
|
+
pr_url=$(gh pr create \
|
|
1060
|
+
--draft \
|
|
1061
|
+
--base "$base_branch" \
|
|
1062
|
+
--title "$pr_title" \
|
|
1063
|
+
--body "$pr_body" \
|
|
1064
|
+
2>&1)
|
|
1065
|
+
|
|
1066
|
+
echo -e "${GREEN}PR created: ${pr_url}${NC}"
|
|
1067
|
+
fi
|
|
1068
|
+
fi
|
|
1069
|
+
|
|
1070
|
+
# Update task.json
|
|
1071
|
+
echo -e "${YELLOW}Updating task status...${NC}"
|
|
1072
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
1073
|
+
echo -e "[DRY-RUN] Would update task.json:"
|
|
1074
|
+
echo -e " status: review"
|
|
1075
|
+
echo -e " pr_url: ${pr_url}"
|
|
1076
|
+
echo -e " current_phase: (set to create-pr phase)"
|
|
1077
|
+
else
|
|
1078
|
+
# Find the phase number for create-pr action
|
|
1079
|
+
local create_pr_phase=$(jq -r '.next_action[] | select(.action == "create-pr") | .phase // 4' "$task_json")
|
|
1080
|
+
jq --arg url "$pr_url" --argjson phase "$create_pr_phase" \
|
|
1081
|
+
'.status = "review" | .pr_url = $url | .current_phase = $phase' "$task_json" > "${task_json}.tmp"
|
|
1082
|
+
mv "${task_json}.tmp" "$task_json"
|
|
1083
|
+
echo -e "${GREEN}Task status updated to 'review', phase ${create_pr_phase}${NC}"
|
|
1084
|
+
fi
|
|
1085
|
+
|
|
1086
|
+
# In dry-run, reset the staging area
|
|
1087
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
1088
|
+
git reset HEAD >/dev/null 2>&1 || true
|
|
1089
|
+
fi
|
|
1090
|
+
|
|
1091
|
+
echo ""
|
|
1092
|
+
echo -e "${GREEN}=== PR Created Successfully ===${NC}"
|
|
1093
|
+
echo -e "PR URL: ${pr_url}"
|
|
1094
|
+
echo -e "Target: ${base_branch}"
|
|
1095
|
+
echo -e "Source: ${current_branch}"
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
# =============================================================================
|
|
1099
|
+
# Help
|
|
1100
|
+
# =============================================================================
|
|
1101
|
+
|
|
1102
|
+
show_usage() {
|
|
1103
|
+
cat << EOF
|
|
1104
|
+
Task Management Script for Multi-Agent Pipeline
|
|
1105
|
+
|
|
1106
|
+
Usage:
|
|
1107
|
+
$0 create <title> Create new task directory
|
|
1108
|
+
$0 init-context <dir> <type> [--platform claude|cursor] Initialize jsonl files
|
|
1109
|
+
$0 add-context <dir> <jsonl> <path> [reason] Add entry to jsonl
|
|
1110
|
+
$0 validate <dir> Validate jsonl files
|
|
1111
|
+
$0 list-context <dir> List jsonl entries
|
|
1112
|
+
$0 start <dir> Set as current task
|
|
1113
|
+
$0 finish Clear current task
|
|
1114
|
+
$0 set-branch <dir> <branch> Set git branch for multi-agent
|
|
1115
|
+
$0 set-scope <dir> <scope> Set scope for PR title
|
|
1116
|
+
$0 create-pr [dir] [--dry-run] Create PR from task
|
|
1117
|
+
$0 archive <task-name> Archive completed task
|
|
1118
|
+
$0 list [--mine] [--status <status>] List tasks
|
|
1119
|
+
$0 list-archive [YYYY-MM] List archived tasks
|
|
1120
|
+
|
|
1121
|
+
Arguments:
|
|
1122
|
+
dev_type: backend | frontend | fullstack | test | docs
|
|
1123
|
+
|
|
1124
|
+
List options:
|
|
1125
|
+
--mine, -m Show only tasks assigned to current developer
|
|
1126
|
+
--status, -s <s> Filter by status (planning, in_progress, review, completed)
|
|
1127
|
+
|
|
1128
|
+
Examples:
|
|
1129
|
+
$0 create "Add login feature" --slug add-login
|
|
1130
|
+
$0 init-context .aim-studio/tasks/01-21-add-login backend
|
|
1131
|
+
$0 init-context .aim-studio/tasks/01-21-add-login frontend --platform cursor
|
|
1132
|
+
$0 add-context <dir> implement .aim-studio/spec/backend/auth.md "Auth guidelines"
|
|
1133
|
+
$0 set-branch <dir> task/add-login
|
|
1134
|
+
$0 start .aim-studio/tasks/01-21-add-login
|
|
1135
|
+
$0 create-pr # Uses current task
|
|
1136
|
+
$0 create-pr <dir> --dry-run # Preview without changes
|
|
1137
|
+
$0 finish
|
|
1138
|
+
$0 archive add-login
|
|
1139
|
+
$0 list # List all active tasks
|
|
1140
|
+
$0 list --mine # List my tasks only
|
|
1141
|
+
$0 list --mine --status in_progress # List my in-progress tasks
|
|
1142
|
+
EOF
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
# =============================================================================
|
|
1146
|
+
# Main Entry
|
|
1147
|
+
# =============================================================================
|
|
1148
|
+
|
|
1149
|
+
case "${1:-}" in
|
|
1150
|
+
create)
|
|
1151
|
+
shift
|
|
1152
|
+
cmd_create "$@"
|
|
1153
|
+
;;
|
|
1154
|
+
init-context)
|
|
1155
|
+
shift
|
|
1156
|
+
cmd_init_context "$@"
|
|
1157
|
+
;;
|
|
1158
|
+
add-context)
|
|
1159
|
+
cmd_add_context "$2" "$3" "$4" "$5"
|
|
1160
|
+
;;
|
|
1161
|
+
validate)
|
|
1162
|
+
cmd_validate "$2"
|
|
1163
|
+
;;
|
|
1164
|
+
list-context)
|
|
1165
|
+
cmd_list_context "$2"
|
|
1166
|
+
;;
|
|
1167
|
+
start)
|
|
1168
|
+
cmd_start "$2"
|
|
1169
|
+
;;
|
|
1170
|
+
finish)
|
|
1171
|
+
cmd_finish
|
|
1172
|
+
;;
|
|
1173
|
+
set-branch)
|
|
1174
|
+
cmd_set_branch "$2" "$3"
|
|
1175
|
+
;;
|
|
1176
|
+
set-base-branch)
|
|
1177
|
+
cmd_set_base_branch "$2" "$3"
|
|
1178
|
+
;;
|
|
1179
|
+
set-scope)
|
|
1180
|
+
cmd_set_scope "$2" "$3"
|
|
1181
|
+
;;
|
|
1182
|
+
create-pr)
|
|
1183
|
+
# Delegate to multi-agent/create-pr.sh
|
|
1184
|
+
shift
|
|
1185
|
+
"$SCRIPT_DIR/multi-agent/create-pr.sh" "$@"
|
|
1186
|
+
;;
|
|
1187
|
+
archive)
|
|
1188
|
+
cmd_archive "$2"
|
|
1189
|
+
;;
|
|
1190
|
+
list)
|
|
1191
|
+
shift
|
|
1192
|
+
cmd_list "$@"
|
|
1193
|
+
;;
|
|
1194
|
+
list-archive)
|
|
1195
|
+
cmd_list_archive "$2"
|
|
1196
|
+
;;
|
|
1197
|
+
-h|--help|help)
|
|
1198
|
+
show_usage
|
|
1199
|
+
;;
|
|
1200
|
+
*)
|
|
1201
|
+
show_usage
|
|
1202
|
+
exit 1
|
|
1203
|
+
;;
|
|
1204
|
+
esac
|