@mindfoldhq/trellis 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{templates/agents/bodies → .claude/agents}/check.md +7 -0
- package/dist/{templates/agents/bodies → .claude/agents}/debug.md +7 -0
- package/dist/{templates/agents/bodies → .claude/agents}/dispatch.md +11 -8
- package/dist/{templates/agents/bodies → .claude/agents}/implement.md +7 -0
- package/dist/.claude/agents/plan.md +396 -0
- package/dist/{templates/agents/bodies → .claude/agents}/research.md +7 -0
- package/dist/{templates/commands/common/check-cross-layer.txt → .claude/commands/check-cross-layer.md} +29 -29
- package/dist/{templates → .claude}/hooks/inject-subagent-context.py +63 -0
- package/dist/.cursor/commands/before-backend-dev.md +13 -0
- package/dist/.cursor/commands/before-frontend-dev.md +13 -0
- package/dist/.cursor/commands/break-loop.md +107 -0
- package/dist/.cursor/commands/check-backend.md +13 -0
- package/dist/.cursor/commands/check-cross-layer.md +153 -0
- package/dist/.cursor/commands/check-frontend.md +13 -0
- package/dist/.cursor/commands/create-command.md +154 -0
- package/dist/.cursor/commands/finish-work.md +129 -0
- package/dist/.cursor/commands/integrate-skill.md +219 -0
- package/dist/.cursor/commands/onboard-developer.md +355 -0
- package/dist/.cursor/commands/record-agent-flow.md +62 -0
- package/dist/.trellis/scripts/common/phase.sh +150 -0
- package/dist/{templates/scripts/feature.sh.txt → .trellis/scripts/feature.sh} +8 -3
- package/dist/{templates/scripts/multi-agent/cleanup.sh.txt → .trellis/scripts/multi-agent/cleanup.sh} +107 -18
- package/dist/.trellis/scripts/multi-agent/create-pr.sh +241 -0
- package/dist/.trellis/scripts/multi-agent/plan.sh +232 -0
- package/dist/{templates/scripts/multi-agent/start.sh.txt → .trellis/scripts/multi-agent/start.sh} +21 -0
- package/dist/{templates/scripts/multi-agent/status.sh.txt → .trellis/scripts/multi-agent/status.sh} +282 -10
- package/dist/.trellis/structure/backend/database-guidelines.md +51 -0
- package/dist/.trellis/structure/backend/directory-structure.md +209 -0
- package/dist/.trellis/structure/backend/error-handling.md +278 -0
- package/dist/.trellis/structure/backend/index.md +38 -0
- package/dist/.trellis/structure/backend/logging-guidelines.md +266 -0
- package/dist/.trellis/structure/backend/quality-guidelines.md +313 -0
- package/dist/.trellis/structure/frontend/component-guidelines.md +59 -0
- package/dist/.trellis/structure/frontend/directory-structure.md +54 -0
- package/dist/.trellis/structure/frontend/hook-guidelines.md +51 -0
- package/dist/.trellis/structure/frontend/index.md +39 -0
- package/dist/.trellis/structure/frontend/quality-guidelines.md +51 -0
- package/dist/.trellis/structure/frontend/state-management.md +51 -0
- package/dist/.trellis/structure/frontend/type-safety.md +51 -0
- package/dist/.trellis/structure/guides/code-reuse-thinking-guide.md +92 -0
- package/dist/.trellis/structure/guides/cross-layer-thinking-guide.md +94 -0
- package/dist/.trellis/structure/guides/index.md +79 -0
- package/dist/{templates/scripts/worktree.yaml.txt → .trellis/worktree.yaml} +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +5 -16
- package/dist/commands/init.js.map +1 -1
- package/dist/configurators/claude.d.ts +17 -17
- package/dist/configurators/claude.d.ts.map +1 -1
- package/dist/configurators/claude.js +29 -59
- package/dist/configurators/claude.js.map +1 -1
- package/dist/configurators/cursor.d.ts +3 -3
- package/dist/configurators/cursor.d.ts.map +1 -1
- package/dist/configurators/cursor.js +11 -15
- package/dist/configurators/cursor.js.map +1 -1
- package/dist/configurators/opencode.d.ts +11 -10
- package/dist/configurators/opencode.d.ts.map +1 -1
- package/dist/configurators/opencode.js +14 -33
- package/dist/configurators/opencode.js.map +1 -1
- package/dist/configurators/workflow.d.ts +7 -0
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +30 -99
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/templates/extract.d.ts +73 -8
- package/dist/templates/extract.d.ts.map +1 -1
- package/dist/templates/extract.js +149 -10
- package/dist/templates/extract.js.map +1 -1
- package/dist/templates/markdown/gitignore.txt +6 -1
- package/dist/templates/markdown/index.d.ts +5 -1
- package/dist/templates/markdown/index.d.ts.map +1 -1
- package/dist/templates/markdown/index.js +54 -26
- package/dist/templates/markdown/index.js.map +1 -1
- package/dist/templates/markdown/structure/backend/directory-structure.md.txt +6 -6
- package/dist/templates/markdown/structure/backend/error-handling.md.txt +8 -8
- package/dist/templates/markdown/structure/backend/index.md.txt +5 -5
- package/dist/templates/markdown/structure/backend/logging-guidelines.md.txt +8 -8
- package/dist/templates/markdown/structure/frontend/index.md.txt +6 -6
- package/dist/templates/markdown/structure/guides/cross-layer-thinking-guide.md.txt +5 -5
- package/dist/templates/markdown/structure/guides/index.md.txt +7 -7
- package/dist/templates/markdown/worktree.yaml.txt +58 -0
- package/package.json +1 -1
- package/dist/configurators/templates.d.ts +0 -40
- package/dist/configurators/templates.d.ts.map +0 -1
- package/dist/configurators/templates.js +0 -67
- package/dist/configurators/templates.js.map +0 -1
- package/dist/templates/agents/index.d.ts +0 -42
- package/dist/templates/agents/index.d.ts.map +0 -1
- package/dist/templates/agents/index.js +0 -148
- package/dist/templates/agents/index.js.map +0 -1
- package/dist/templates/agents/metadata.d.ts +0 -48
- package/dist/templates/agents/metadata.d.ts.map +0 -1
- package/dist/templates/agents/metadata.js +0 -101
- package/dist/templates/agents/metadata.js.map +0 -1
- package/dist/templates/commands/index.d.ts +0 -48
- package/dist/templates/commands/index.d.ts.map +0 -1
- package/dist/templates/commands/index.js +0 -167
- package/dist/templates/commands/index.js.map +0 -1
- package/dist/templates/commands/opencode/start.md.txt +0 -127
- package/dist/templates/hooks/index.d.ts +0 -33
- package/dist/templates/hooks/index.d.ts.map +0 -1
- package/dist/templates/hooks/index.js +0 -53
- package/dist/templates/hooks/index.js.map +0 -1
- package/dist/templates/scripts/index.d.ts +0 -36
- package/dist/templates/scripts/index.d.ts.map +0 -1
- package/dist/templates/scripts/index.js +0 -41
- package/dist/templates/scripts/index.js.map +0 -1
- /package/dist/{templates/commands/common/before-backend-dev.txt → .claude/commands/before-backend-dev.md} +0 -0
- /package/dist/{templates/commands/common/before-frontend-dev.txt → .claude/commands/before-frontend-dev.md} +0 -0
- /package/dist/{templates/commands/common/break-loop.txt → .claude/commands/break-loop.md} +0 -0
- /package/dist/{templates/commands/common/check-backend.txt → .claude/commands/check-backend.md} +0 -0
- /package/dist/{templates/commands/common/check-frontend.txt → .claude/commands/check-frontend.md} +0 -0
- /package/dist/{templates/commands/common/create-command.txt → .claude/commands/create-command.md} +0 -0
- /package/dist/{templates/commands/common/finish-work.txt → .claude/commands/finish-work.md} +0 -0
- /package/dist/{templates/commands/common/integrate-skill.txt → .claude/commands/integrate-skill.md} +0 -0
- /package/dist/{templates/commands/common/onboard-developer.txt → .claude/commands/onboard-developer.md} +0 -0
- /package/dist/{templates/commands/claude/parallel.md.txt → .claude/commands/parallel.md} +0 -0
- /package/dist/{templates/commands/common/record-agent-flow.txt → .claude/commands/record-agent-flow.md} +0 -0
- /package/dist/{templates/commands/claude/start.md.txt → .claude/commands/start.md} +0 -0
- /package/dist/{templates/hooks → .claude}/settings.json +0 -0
- /package/dist/{templates/commands/cursor/start.md.txt → .cursor/commands/start.md} +0 -0
- /package/dist/{templates/markdown/agent-traces-index.md.txt → .trellis/agent-traces/index.md} +0 -0
- /package/dist/{templates/scripts/add-session.sh.txt → .trellis/scripts/add-session.sh} +0 -0
- /package/dist/{templates/scripts/common/developer.sh.txt → .trellis/scripts/common/developer.sh} +0 -0
- /package/dist/{templates/scripts/common/git-context.sh.txt → .trellis/scripts/common/git-context.sh} +0 -0
- /package/dist/{templates/scripts/common/paths.sh.txt → .trellis/scripts/common/paths.sh} +0 -0
- /package/dist/{templates/scripts/common/worktree.sh.txt → .trellis/scripts/common/worktree.sh} +0 -0
- /package/dist/{templates/scripts/create-bootstrap.sh.txt → .trellis/scripts/create-bootstrap.sh} +0 -0
- /package/dist/{templates/scripts/get-context.sh.txt → .trellis/scripts/get-context.sh} +0 -0
- /package/dist/{templates/scripts/get-developer.sh.txt → .trellis/scripts/get-developer.sh} +0 -0
- /package/dist/{templates/scripts/init-developer.sh.txt → .trellis/scripts/init-developer.sh} +0 -0
- /package/dist/{templates/markdown/workflow.md.txt → .trellis/workflow.md} +0 -0
- /package/dist/templates/markdown/{agents.md.txt → agents.md} +0 -0
- /package/dist/templates/markdown/{init-agent.md.txt → init-agent.md} +0 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# Multi-Agent Pipeline: Plan Agent Launcher
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# Usage: ./plan.sh --name <feature-name> --type <dev-type> --requirement "<requirement>"
|
|
6
|
+
#
|
|
7
|
+
# This script:
|
|
8
|
+
# 1. Creates feature directory
|
|
9
|
+
# 2. Starts Plan Agent in background
|
|
10
|
+
# 3. Plan Agent produces fully configured feature directory
|
|
11
|
+
#
|
|
12
|
+
# After completion, use start.sh to launch the Dispatch Agent.
|
|
13
|
+
#
|
|
14
|
+
# Prerequisites:
|
|
15
|
+
# - .claude/agents/plan.md must exist
|
|
16
|
+
# - Developer must be initialized
|
|
17
|
+
# =============================================================================
|
|
18
|
+
|
|
19
|
+
set -e
|
|
20
|
+
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
|
+
source "$SCRIPT_DIR/../common/paths.sh"
|
|
23
|
+
source "$SCRIPT_DIR/../common/developer.sh"
|
|
24
|
+
|
|
25
|
+
# Colors
|
|
26
|
+
RED='\033[0;31m'
|
|
27
|
+
GREEN='\033[0;32m'
|
|
28
|
+
YELLOW='\033[1;33m'
|
|
29
|
+
BLUE='\033[0;34m'
|
|
30
|
+
NC='\033[0m'
|
|
31
|
+
|
|
32
|
+
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
33
|
+
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
34
|
+
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
35
|
+
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
36
|
+
|
|
37
|
+
# =============================================================================
|
|
38
|
+
# Constants
|
|
39
|
+
# =============================================================================
|
|
40
|
+
PROJECT_ROOT=$(get_repo_root)
|
|
41
|
+
PLAN_MD_PATH=".claude/agents/plan.md"
|
|
42
|
+
|
|
43
|
+
# =============================================================================
|
|
44
|
+
# Parse Arguments
|
|
45
|
+
# =============================================================================
|
|
46
|
+
FEATURE_NAME=""
|
|
47
|
+
DEV_TYPE=""
|
|
48
|
+
REQUIREMENT=""
|
|
49
|
+
|
|
50
|
+
show_usage() {
|
|
51
|
+
cat << EOF
|
|
52
|
+
Usage: $0 --name <feature-name> --type <dev-type> --requirement "<requirement>"
|
|
53
|
+
|
|
54
|
+
Arguments:
|
|
55
|
+
--name, -n Feature name (e.g., user-auth, add-rate-limiting)
|
|
56
|
+
--type, -t Development type: backend | frontend | fullstack
|
|
57
|
+
--requirement, -r Requirement description (quote if contains spaces)
|
|
58
|
+
|
|
59
|
+
Examples:
|
|
60
|
+
$0 --name user-auth --type backend --requirement "Add JWT-based user authentication"
|
|
61
|
+
$0 -n rate-limit -t backend -r "Add rate limiting to API endpoints"
|
|
62
|
+
|
|
63
|
+
The Plan Agent runs in background. Monitor with:
|
|
64
|
+
tail -f <feature-dir>/.plan-log
|
|
65
|
+
EOF
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
while [[ $# -gt 0 ]]; do
|
|
69
|
+
case $1 in
|
|
70
|
+
--name|-n)
|
|
71
|
+
FEATURE_NAME="$2"
|
|
72
|
+
shift 2
|
|
73
|
+
;;
|
|
74
|
+
--type|-t)
|
|
75
|
+
DEV_TYPE="$2"
|
|
76
|
+
shift 2
|
|
77
|
+
;;
|
|
78
|
+
--requirement|-r)
|
|
79
|
+
REQUIREMENT="$2"
|
|
80
|
+
shift 2
|
|
81
|
+
;;
|
|
82
|
+
--help|-h)
|
|
83
|
+
show_usage
|
|
84
|
+
exit 0
|
|
85
|
+
;;
|
|
86
|
+
*)
|
|
87
|
+
log_error "Unknown argument: $1"
|
|
88
|
+
show_usage
|
|
89
|
+
exit 1
|
|
90
|
+
;;
|
|
91
|
+
esac
|
|
92
|
+
done
|
|
93
|
+
|
|
94
|
+
# =============================================================================
|
|
95
|
+
# Validation
|
|
96
|
+
# =============================================================================
|
|
97
|
+
if [ -z "$FEATURE_NAME" ]; then
|
|
98
|
+
log_error "Feature name is required (--name)"
|
|
99
|
+
show_usage
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
if [ -z "$DEV_TYPE" ]; then
|
|
104
|
+
log_error "Development type is required (--type)"
|
|
105
|
+
show_usage
|
|
106
|
+
exit 1
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
if [[ ! "$DEV_TYPE" =~ ^(backend|frontend|fullstack)$ ]]; then
|
|
110
|
+
log_error "Invalid dev type: $DEV_TYPE (must be: backend, frontend, fullstack)"
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
if [ -z "$REQUIREMENT" ]; then
|
|
115
|
+
log_error "Requirement is required (--requirement)"
|
|
116
|
+
show_usage
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
PLAN_MD="${PROJECT_ROOT}/${PLAN_MD_PATH}"
|
|
121
|
+
if [ ! -f "$PLAN_MD" ]; then
|
|
122
|
+
log_error "plan.md not found at ${PLAN_MD}"
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
ensure_developer "$PROJECT_ROOT"
|
|
127
|
+
|
|
128
|
+
# =============================================================================
|
|
129
|
+
# Step 1: Create Feature Directory
|
|
130
|
+
# =============================================================================
|
|
131
|
+
echo ""
|
|
132
|
+
echo -e "${BLUE}=== Multi-Agent Pipeline: Plan ===${NC}"
|
|
133
|
+
log_info "Feature: ${FEATURE_NAME}"
|
|
134
|
+
log_info "Type: ${DEV_TYPE}"
|
|
135
|
+
log_info "Requirement: ${REQUIREMENT}"
|
|
136
|
+
echo ""
|
|
137
|
+
|
|
138
|
+
log_info "Step 1: Creating feature directory..."
|
|
139
|
+
|
|
140
|
+
FEATURE_DIR=$("$SCRIPT_DIR/../feature.sh" create "$FEATURE_NAME")
|
|
141
|
+
FEATURE_DIR_ABS="${PROJECT_ROOT}/${FEATURE_DIR}"
|
|
142
|
+
|
|
143
|
+
log_success "Feature directory: ${FEATURE_DIR}"
|
|
144
|
+
|
|
145
|
+
# =============================================================================
|
|
146
|
+
# Step 2: Prepare and Start Plan Agent
|
|
147
|
+
# =============================================================================
|
|
148
|
+
log_info "Step 2: Starting Plan Agent in background..."
|
|
149
|
+
|
|
150
|
+
# Extract plan.md content (skip frontmatter)
|
|
151
|
+
PLAN_PROMPT=$(awk '
|
|
152
|
+
BEGIN { in_frontmatter = 0; started = 0 }
|
|
153
|
+
/^---$/ {
|
|
154
|
+
if (!started) { in_frontmatter = 1; started = 1; next }
|
|
155
|
+
else if (in_frontmatter) { in_frontmatter = 0; next }
|
|
156
|
+
}
|
|
157
|
+
!in_frontmatter { print }
|
|
158
|
+
' "$PLAN_MD")
|
|
159
|
+
|
|
160
|
+
LOG_FILE="${FEATURE_DIR_ABS}/.plan-log"
|
|
161
|
+
touch "$LOG_FILE"
|
|
162
|
+
|
|
163
|
+
# Create a temporary runner script (will be deleted after agent starts)
|
|
164
|
+
RUNNER_SCRIPT=$(mktemp)
|
|
165
|
+
cat > "$RUNNER_SCRIPT" << RUNNER_EOF
|
|
166
|
+
#!/bin/bash
|
|
167
|
+
cd "${PROJECT_ROOT}"
|
|
168
|
+
|
|
169
|
+
export PLAN_FEATURE_NAME="${FEATURE_NAME}"
|
|
170
|
+
export PLAN_DEV_TYPE="${DEV_TYPE}"
|
|
171
|
+
export PLAN_FEATURE_DIR="${FEATURE_DIR}"
|
|
172
|
+
export PLAN_REQUIREMENT="${REQUIREMENT}"
|
|
173
|
+
|
|
174
|
+
export https_proxy="\${AGENT_HTTPS_PROXY:-}"
|
|
175
|
+
export http_proxy="\${AGENT_HTTP_PROXY:-}"
|
|
176
|
+
export all_proxy="\${AGENT_ALL_PROXY:-}"
|
|
177
|
+
|
|
178
|
+
# Create prompt content inline (no temp file needed)
|
|
179
|
+
claude -p --dangerously-skip-permissions --output-format stream-json --verbose << 'PROMPT_EOF'
|
|
180
|
+
# Environment Variables
|
|
181
|
+
|
|
182
|
+
The following environment variables are set for this planning session:
|
|
183
|
+
|
|
184
|
+
\`\`\`
|
|
185
|
+
PLAN_FEATURE_NAME=${FEATURE_NAME}
|
|
186
|
+
PLAN_DEV_TYPE=${DEV_TYPE}
|
|
187
|
+
PLAN_FEATURE_DIR=${FEATURE_DIR}
|
|
188
|
+
PLAN_REQUIREMENT=${REQUIREMENT}
|
|
189
|
+
\`\`\`
|
|
190
|
+
|
|
191
|
+
You can read these directly from the environment or use the values above.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
${PLAN_PROMPT}
|
|
196
|
+
PROMPT_EOF
|
|
197
|
+
|
|
198
|
+
# Self-delete the runner script
|
|
199
|
+
rm -f "\$0"
|
|
200
|
+
RUNNER_EOF
|
|
201
|
+
chmod +x "$RUNNER_SCRIPT"
|
|
202
|
+
|
|
203
|
+
# Start agent in background
|
|
204
|
+
AGENT_HTTPS_PROXY="${https_proxy:-}" \
|
|
205
|
+
AGENT_HTTP_PROXY="${http_proxy:-}" \
|
|
206
|
+
AGENT_ALL_PROXY="${all_proxy:-}" \
|
|
207
|
+
nohup "$RUNNER_SCRIPT" > "$LOG_FILE" 2>&1 &
|
|
208
|
+
AGENT_PID=$!
|
|
209
|
+
|
|
210
|
+
log_success "Plan Agent started (PID: ${AGENT_PID})"
|
|
211
|
+
|
|
212
|
+
# =============================================================================
|
|
213
|
+
# Summary
|
|
214
|
+
# =============================================================================
|
|
215
|
+
echo ""
|
|
216
|
+
echo -e "${GREEN}=== Plan Agent Running ===${NC}"
|
|
217
|
+
echo ""
|
|
218
|
+
echo " Feature: $FEATURE_NAME"
|
|
219
|
+
echo " Type: $DEV_TYPE"
|
|
220
|
+
echo " Dir: $FEATURE_DIR"
|
|
221
|
+
echo " Log: $LOG_FILE"
|
|
222
|
+
echo " PID: $AGENT_PID"
|
|
223
|
+
echo ""
|
|
224
|
+
echo -e "${YELLOW}To monitor:${NC}"
|
|
225
|
+
echo " tail -f $LOG_FILE"
|
|
226
|
+
echo ""
|
|
227
|
+
echo -e "${YELLOW}To check status:${NC}"
|
|
228
|
+
echo " ps -p $AGENT_PID"
|
|
229
|
+
echo " ls -la $FEATURE_DIR"
|
|
230
|
+
echo ""
|
|
231
|
+
echo -e "${YELLOW}After completion, run:${NC}"
|
|
232
|
+
echo " ./.trellis/scripts/multi-agent/start.sh $FEATURE_DIR"
|
package/dist/{templates/scripts/multi-agent/start.sh.txt → .trellis/scripts/multi-agent/start.sh}
RENAMED
|
@@ -95,8 +95,29 @@ log_info "Feature: ${FEATURE_DIR_ABS}"
|
|
|
95
95
|
|
|
96
96
|
BRANCH=$(jq -r '.branch' "$FEATURE_JSON")
|
|
97
97
|
FEATURE_NAME=$(jq -r '.name' "$FEATURE_JSON")
|
|
98
|
+
FEATURE_STATUS=$(jq -r '.status' "$FEATURE_JSON")
|
|
98
99
|
WORKTREE_PATH=$(jq -r '.worktree_path // empty' "$FEATURE_JSON")
|
|
99
100
|
|
|
101
|
+
# Check if feature was rejected
|
|
102
|
+
if [ "$FEATURE_STATUS" = "rejected" ]; then
|
|
103
|
+
log_error "Feature was rejected by Plan Agent"
|
|
104
|
+
if [ -f "${FEATURE_DIR_ABS}/REJECTED.md" ]; then
|
|
105
|
+
echo ""
|
|
106
|
+
echo -e "${YELLOW}Rejection reason:${NC}"
|
|
107
|
+
cat "${FEATURE_DIR_ABS}/REJECTED.md"
|
|
108
|
+
fi
|
|
109
|
+
echo ""
|
|
110
|
+
log_info "To retry, delete this directory and run plan.sh again with revised requirements"
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Check if prd.md exists (plan completed successfully)
|
|
115
|
+
if [ ! -f "${FEATURE_DIR_ABS}/prd.md" ]; then
|
|
116
|
+
log_error "prd.md not found - Plan Agent may not have completed"
|
|
117
|
+
log_info "Check plan log: ${FEATURE_DIR_ABS}/.plan-log"
|
|
118
|
+
exit 1
|
|
119
|
+
fi
|
|
120
|
+
|
|
100
121
|
if [ -z "$BRANCH" ] || [ "$BRANCH" = "null" ]; then
|
|
101
122
|
log_error "branch field not set in feature.json"
|
|
102
123
|
log_info "Please set branch field first, e.g.:"
|
package/dist/{templates/scripts/multi-agent/status.sh.txt → .trellis/scripts/multi-agent/status.sh}
RENAMED
|
@@ -17,6 +17,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
17
17
|
source "$SCRIPT_DIR/../common/paths.sh"
|
|
18
18
|
source "$SCRIPT_DIR/../common/worktree.sh"
|
|
19
19
|
source "$SCRIPT_DIR/../common/developer.sh"
|
|
20
|
+
source "$SCRIPT_DIR/../common/phase.sh"
|
|
20
21
|
|
|
21
22
|
# Colors
|
|
22
23
|
RED='\033[0;31m'
|
|
@@ -56,6 +57,11 @@ while [[ $# -gt 0 ]]; do
|
|
|
56
57
|
TARGET="$2"
|
|
57
58
|
shift 2
|
|
58
59
|
;;
|
|
60
|
+
--progress)
|
|
61
|
+
ACTION="progress"
|
|
62
|
+
TARGET="$2"
|
|
63
|
+
shift 2
|
|
64
|
+
;;
|
|
59
65
|
--registry)
|
|
60
66
|
ACTION="registry"
|
|
61
67
|
shift
|
|
@@ -113,6 +119,62 @@ find_agent() {
|
|
|
113
119
|
echo "$agent"
|
|
114
120
|
}
|
|
115
121
|
|
|
122
|
+
# Get the last tool call from agent log
|
|
123
|
+
get_last_tool() {
|
|
124
|
+
local log_file="$1"
|
|
125
|
+
if [ ! -f "$log_file" ]; then
|
|
126
|
+
echo ""
|
|
127
|
+
return
|
|
128
|
+
fi
|
|
129
|
+
# Use tail -r on macOS, tac on Linux
|
|
130
|
+
if command -v tac &>/dev/null; then
|
|
131
|
+
tac "$log_file" 2>/dev/null | head -100 | jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' 2>/dev/null | head -1
|
|
132
|
+
else
|
|
133
|
+
tail -r "$log_file" 2>/dev/null | head -100 | jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' 2>/dev/null | head -1
|
|
134
|
+
fi
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
# Get the last assistant text from agent log
|
|
138
|
+
get_last_message() {
|
|
139
|
+
local log_file="$1"
|
|
140
|
+
local max_len="${2:-100}"
|
|
141
|
+
if [ ! -f "$log_file" ]; then
|
|
142
|
+
echo ""
|
|
143
|
+
return
|
|
144
|
+
fi
|
|
145
|
+
local text
|
|
146
|
+
# Use tail -r on macOS, tac on Linux
|
|
147
|
+
if command -v tac &>/dev/null; then
|
|
148
|
+
text=$(tac "$log_file" 2>/dev/null | head -100 | jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="text") | .text' 2>/dev/null | head -1)
|
|
149
|
+
else
|
|
150
|
+
text=$(tail -r "$log_file" 2>/dev/null | head -100 | jq -r 'select(.type=="assistant") | .message.content[]? | select(.type=="text") | .text' 2>/dev/null | head -1)
|
|
151
|
+
fi
|
|
152
|
+
if [ -n "$text" ] && [ "$text" != "null" ]; then
|
|
153
|
+
echo "${text:0:$max_len}"
|
|
154
|
+
fi
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# Get recent task notifications from agent log
|
|
158
|
+
# Looks for async_launched tasks and infers completion from current_phase
|
|
159
|
+
get_recent_tasks() {
|
|
160
|
+
local log_file="$1"
|
|
161
|
+
local count="${2:-5}"
|
|
162
|
+
local current_phase="${3:-0}"
|
|
163
|
+
if [ ! -f "$log_file" ]; then
|
|
164
|
+
return
|
|
165
|
+
fi
|
|
166
|
+
# Get async_launched tasks with phase number extracted from description
|
|
167
|
+
tail -500 "$log_file" 2>/dev/null | jq -r --argjson current_phase "$current_phase" '
|
|
168
|
+
select(.type=="user" and .tool_use_result.status == "async_launched" and .tool_use_result.description != null) |
|
|
169
|
+
.tool_use_result.description as $desc |
|
|
170
|
+
# Extract phase number from "Phase N:" pattern
|
|
171
|
+
($desc | capture("Phase (?<num>[0-9]+)") | .num | tonumber) as $phase_num |
|
|
172
|
+
# If current_phase > this phase, it is completed
|
|
173
|
+
(if $phase_num < $current_phase then "completed" else "async_launched" end) as $status |
|
|
174
|
+
"\($status)|\($desc)"
|
|
175
|
+
' 2>/dev/null | tail -"$count"
|
|
176
|
+
}
|
|
177
|
+
|
|
116
178
|
# =============================================================================
|
|
117
179
|
# Commands
|
|
118
180
|
# =============================================================================
|
|
@@ -125,12 +187,14 @@ Usage:
|
|
|
125
187
|
$0 Show summary of all features
|
|
126
188
|
$0 --list List all worktrees and agents
|
|
127
189
|
$0 --detail <feature> Detailed feature status
|
|
190
|
+
$0 --progress <feature> Quick progress view with recent activity
|
|
128
191
|
$0 --watch <feature> Watch agent log in real-time
|
|
129
192
|
$0 --log <feature> Show recent log entries
|
|
130
193
|
$0 --registry Show agent registry
|
|
131
194
|
|
|
132
195
|
Examples:
|
|
133
196
|
$0 --detail my-feature
|
|
197
|
+
$0 --progress my-feature
|
|
134
198
|
$0 --watch 16-worktree-support
|
|
135
199
|
$0 --log worktree-support
|
|
136
200
|
EOF
|
|
@@ -174,6 +238,52 @@ cmd_list() {
|
|
|
174
238
|
done
|
|
175
239
|
}
|
|
176
240
|
|
|
241
|
+
# Calculate elapsed time from ISO timestamp
|
|
242
|
+
calc_elapsed() {
|
|
243
|
+
local started="$1"
|
|
244
|
+
if [ -z "$started" ] || [ "$started" = "null" ]; then
|
|
245
|
+
echo "N/A"
|
|
246
|
+
return
|
|
247
|
+
fi
|
|
248
|
+
|
|
249
|
+
# Parse started time (handle both formats: with and without timezone)
|
|
250
|
+
local start_epoch
|
|
251
|
+
if command -v gdate &>/dev/null; then
|
|
252
|
+
start_epoch=$(gdate -d "$started" +%s 2>/dev/null)
|
|
253
|
+
else
|
|
254
|
+
# Try to parse ISO format
|
|
255
|
+
start_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%S" "${started%%+*}" +%s 2>/dev/null || date -d "$started" +%s 2>/dev/null)
|
|
256
|
+
fi
|
|
257
|
+
|
|
258
|
+
if [ -z "$start_epoch" ]; then
|
|
259
|
+
echo "N/A"
|
|
260
|
+
return
|
|
261
|
+
fi
|
|
262
|
+
|
|
263
|
+
local now_epoch=$(date +%s)
|
|
264
|
+
local elapsed=$((now_epoch - start_epoch))
|
|
265
|
+
|
|
266
|
+
if [ $elapsed -lt 60 ]; then
|
|
267
|
+
echo "${elapsed}s"
|
|
268
|
+
elif [ $elapsed -lt 3600 ]; then
|
|
269
|
+
echo "$((elapsed / 60))m $((elapsed % 60))s"
|
|
270
|
+
else
|
|
271
|
+
echo "$((elapsed / 3600))h $((elapsed % 3600 / 60))m"
|
|
272
|
+
fi
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
# Note: get_phase_info is now in common/phase.sh
|
|
276
|
+
|
|
277
|
+
# Count modified files in worktree
|
|
278
|
+
count_modified_files() {
|
|
279
|
+
local worktree="$1"
|
|
280
|
+
if [ -d "$worktree" ]; then
|
|
281
|
+
cd "$worktree" && git status --short 2>/dev/null | wc -l | tr -d ' '
|
|
282
|
+
else
|
|
283
|
+
echo "0"
|
|
284
|
+
fi
|
|
285
|
+
}
|
|
286
|
+
|
|
177
287
|
cmd_summary() {
|
|
178
288
|
ensure_developer
|
|
179
289
|
|
|
@@ -183,12 +293,26 @@ cmd_summary() {
|
|
|
183
293
|
exit 0
|
|
184
294
|
fi
|
|
185
295
|
|
|
186
|
-
echo -e "${BLUE}=== Feature Summary ===${NC}"
|
|
187
|
-
echo ""
|
|
188
|
-
|
|
189
296
|
AGENTS_DIR=$(get_agents_dir)
|
|
190
297
|
REGISTRY_FILE="${AGENTS_DIR}/registry.json"
|
|
191
298
|
|
|
299
|
+
# Count running agents
|
|
300
|
+
local running_count=0
|
|
301
|
+
local total_agents=0
|
|
302
|
+
if [ -f "$REGISTRY_FILE" ]; then
|
|
303
|
+
total_agents=$(jq -r '.agents | length' "$REGISTRY_FILE" 2>/dev/null || echo "0")
|
|
304
|
+
while read -r pid; do
|
|
305
|
+
is_running "$pid" && ((running_count++))
|
|
306
|
+
done < <(jq -r '.agents[].pid' "$REGISTRY_FILE" 2>/dev/null)
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
echo -e "${BLUE}=== Multi-Agent Status ===${NC}"
|
|
310
|
+
echo -e " Agents: ${GREEN}${running_count}${NC} running / ${total_agents} registered"
|
|
311
|
+
echo ""
|
|
312
|
+
|
|
313
|
+
# Check if any agents are running and show detailed view
|
|
314
|
+
local has_running_agent=false
|
|
315
|
+
|
|
192
316
|
for d in "$features_dir"/*/; do
|
|
193
317
|
[ ! -d "$d" ] && continue
|
|
194
318
|
[[ "$(basename "$d")" == "archive" ]] && continue
|
|
@@ -196,29 +320,174 @@ cmd_summary() {
|
|
|
196
320
|
local name=$(basename "$d")
|
|
197
321
|
local feature_json="$d/feature.json"
|
|
198
322
|
local status="unknown"
|
|
199
|
-
local agent_status=""
|
|
200
323
|
|
|
201
324
|
if [ -f "$feature_json" ]; then
|
|
202
325
|
status=$(jq -r '.status // "unknown"' "$feature_json")
|
|
203
326
|
fi
|
|
204
327
|
|
|
205
328
|
# Check agent status
|
|
329
|
+
local agent_info=""
|
|
330
|
+
local pid=""
|
|
331
|
+
local worktree=""
|
|
332
|
+
local started=""
|
|
333
|
+
local is_agent_running=false
|
|
334
|
+
|
|
206
335
|
if [ -f "$REGISTRY_FILE" ]; then
|
|
207
|
-
|
|
336
|
+
agent_info=$(jq -r --arg name "$name" '.agents[] | select(.feature_dir | contains($name))' "$REGISTRY_FILE" 2>/dev/null)
|
|
208
337
|
if [ -n "$agent_info" ] && [ "$agent_info" != "null" ]; then
|
|
209
|
-
|
|
338
|
+
pid=$(echo "$agent_info" | jq -r '.pid')
|
|
339
|
+
worktree=$(echo "$agent_info" | jq -r '.worktree_path')
|
|
340
|
+
started=$(echo "$agent_info" | jq -r '.started_at')
|
|
210
341
|
if is_running "$pid"; then
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
agent_status=" ${RED}[agent stopped]${NC}"
|
|
342
|
+
is_agent_running=true
|
|
343
|
+
has_running_agent=true
|
|
214
344
|
fi
|
|
215
345
|
fi
|
|
216
346
|
fi
|
|
217
347
|
|
|
218
348
|
local color=$(status_color "$status")
|
|
219
|
-
|
|
349
|
+
|
|
350
|
+
if [ "$is_agent_running" = true ]; then
|
|
351
|
+
# Detailed view for running agents
|
|
352
|
+
# Read feature.json from worktree (has live phase info)
|
|
353
|
+
local feature_dir_rel=$(echo "$agent_info" | jq -r '.feature_dir')
|
|
354
|
+
local worktree_feature_json="$worktree/$feature_dir_rel/feature.json"
|
|
355
|
+
local phase_source="$feature_json"
|
|
356
|
+
[ -f "$worktree_feature_json" ] && phase_source="$worktree_feature_json"
|
|
357
|
+
|
|
358
|
+
local phase_info=$(get_phase_info "$phase_source")
|
|
359
|
+
local elapsed=$(calc_elapsed "$started")
|
|
360
|
+
local modified=$(count_modified_files "$worktree")
|
|
361
|
+
local branch=$(jq -r '.branch // "N/A"' "$phase_source" 2>/dev/null)
|
|
362
|
+
|
|
363
|
+
# Get recent activity from log
|
|
364
|
+
local log_file="$worktree/.agent-log"
|
|
365
|
+
local last_tool=$(get_last_tool "$log_file")
|
|
366
|
+
|
|
367
|
+
echo -e "${GREEN}▶${NC} ${CYAN}${name}${NC} ${GREEN}[running]${NC}"
|
|
368
|
+
echo -e " Phase: ${phase_info}"
|
|
369
|
+
echo -e " Elapsed: ${elapsed}"
|
|
370
|
+
echo -e " Branch: ${DIM}${branch}${NC}"
|
|
371
|
+
echo -e " Modified: ${modified} file(s)"
|
|
372
|
+
if [ -n "$last_tool" ]; then
|
|
373
|
+
echo -e " Activity: ${YELLOW}${last_tool}${NC}"
|
|
374
|
+
fi
|
|
375
|
+
echo -e " PID: ${DIM}${pid}${NC}"
|
|
376
|
+
echo ""
|
|
377
|
+
elif [ -n "$agent_info" ] && [ "$agent_info" != "null" ]; then
|
|
378
|
+
# Stopped agent
|
|
379
|
+
echo -e "${RED}○${NC} ${name} ${RED}[stopped]${NC}"
|
|
380
|
+
echo -e " ${DIM}PID ${pid} is no longer running${NC}"
|
|
381
|
+
echo ""
|
|
382
|
+
else
|
|
383
|
+
# No agent, just show status
|
|
384
|
+
echo -e " ${color}●${NC} ${name} (${status})"
|
|
385
|
+
fi
|
|
220
386
|
done
|
|
221
387
|
|
|
388
|
+
if [ "$has_running_agent" = true ]; then
|
|
389
|
+
echo -e "${DIM}─────────────────────────────────────${NC}"
|
|
390
|
+
echo -e "${DIM}Use --progress <name> for quick activity view${NC}"
|
|
391
|
+
echo -e "${DIM}Use --detail <name> for more info${NC}"
|
|
392
|
+
fi
|
|
393
|
+
echo ""
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
cmd_progress() {
|
|
397
|
+
if [ -z "$TARGET" ]; then
|
|
398
|
+
echo "Usage: $0 --progress <feature>"
|
|
399
|
+
exit 1
|
|
400
|
+
fi
|
|
401
|
+
|
|
402
|
+
local agent=$(find_agent "$TARGET")
|
|
403
|
+
if [ -z "$agent" ] || [ "$agent" = "null" ]; then
|
|
404
|
+
echo "Agent not found: $TARGET"
|
|
405
|
+
exit 1
|
|
406
|
+
fi
|
|
407
|
+
|
|
408
|
+
local id=$(echo "$agent" | jq -r '.id')
|
|
409
|
+
local pid=$(echo "$agent" | jq -r '.pid')
|
|
410
|
+
local worktree=$(echo "$agent" | jq -r '.worktree_path')
|
|
411
|
+
local feature_dir=$(echo "$agent" | jq -r '.feature_dir')
|
|
412
|
+
local started=$(echo "$agent" | jq -r '.started_at')
|
|
413
|
+
local log_file="$worktree/.agent-log"
|
|
414
|
+
|
|
415
|
+
if [ ! -f "$log_file" ]; then
|
|
416
|
+
echo "Log file not found: $log_file"
|
|
417
|
+
exit 1
|
|
418
|
+
fi
|
|
419
|
+
|
|
420
|
+
# Get phase info from worktree's feature.json
|
|
421
|
+
local worktree_feature_json="$worktree/$feature_dir/feature.json"
|
|
422
|
+
local phase_info="N/A"
|
|
423
|
+
local current_phase=0
|
|
424
|
+
if [ -f "$worktree_feature_json" ]; then
|
|
425
|
+
phase_info=$(get_phase_info "$worktree_feature_json")
|
|
426
|
+
current_phase=$(jq -r '.current_phase // 0' "$worktree_feature_json")
|
|
427
|
+
fi
|
|
428
|
+
|
|
429
|
+
local elapsed=$(calc_elapsed "$started")
|
|
430
|
+
local modified=$(count_modified_files "$worktree")
|
|
431
|
+
|
|
432
|
+
# Check if running
|
|
433
|
+
local status_str
|
|
434
|
+
if is_running "$pid"; then
|
|
435
|
+
status_str="${GREEN}running${NC}"
|
|
436
|
+
else
|
|
437
|
+
status_str="${RED}stopped${NC}"
|
|
438
|
+
fi
|
|
439
|
+
|
|
440
|
+
echo ""
|
|
441
|
+
echo -e "${BLUE}=== Progress: ${id} ===${NC}"
|
|
442
|
+
echo ""
|
|
443
|
+
|
|
444
|
+
# Basic info (like summary)
|
|
445
|
+
echo -e "${CYAN}Status:${NC}"
|
|
446
|
+
echo -e " State: ${status_str}"
|
|
447
|
+
echo -e " Phase: ${phase_info}"
|
|
448
|
+
echo -e " Elapsed: ${elapsed}"
|
|
449
|
+
echo -e " Modified: ${modified} file(s)"
|
|
450
|
+
echo ""
|
|
451
|
+
|
|
452
|
+
# Recent task notifications
|
|
453
|
+
echo -e "${CYAN}Recent Tasks:${NC}"
|
|
454
|
+
local has_tasks=false
|
|
455
|
+
while IFS='|' read -r status summary; do
|
|
456
|
+
[ -z "$status" ] && continue
|
|
457
|
+
has_tasks=true
|
|
458
|
+
local icon
|
|
459
|
+
case "$status" in
|
|
460
|
+
completed) icon="${GREEN}✓${NC}" ;;
|
|
461
|
+
failed) icon="${RED}✗${NC}" ;;
|
|
462
|
+
async_launched) icon="${BLUE}▶${NC}" ;;
|
|
463
|
+
*) icon="${YELLOW}○${NC}" ;;
|
|
464
|
+
esac
|
|
465
|
+
echo -e " ${icon} ${summary}"
|
|
466
|
+
done < <(get_recent_tasks "$log_file" 5 "$current_phase")
|
|
467
|
+
|
|
468
|
+
if [ "$has_tasks" = false ]; then
|
|
469
|
+
echo -e " ${DIM}(no task notifications yet)${NC}"
|
|
470
|
+
fi
|
|
471
|
+
echo ""
|
|
472
|
+
|
|
473
|
+
# Current activity
|
|
474
|
+
echo -e "${CYAN}Current Activity:${NC}"
|
|
475
|
+
local last_tool=$(get_last_tool "$log_file")
|
|
476
|
+
if [ -n "$last_tool" ]; then
|
|
477
|
+
echo -e " Tool: ${YELLOW}${last_tool}${NC}"
|
|
478
|
+
else
|
|
479
|
+
echo -e " ${DIM}(no recent tool calls)${NC}"
|
|
480
|
+
fi
|
|
481
|
+
echo ""
|
|
482
|
+
|
|
483
|
+
# Last message
|
|
484
|
+
echo -e "${CYAN}Last Message:${NC}"
|
|
485
|
+
local last_msg=$(get_last_message "$log_file" 200)
|
|
486
|
+
if [ -n "$last_msg" ]; then
|
|
487
|
+
echo -e " \"${last_msg}...\""
|
|
488
|
+
else
|
|
489
|
+
echo -e " ${DIM}(no recent messages)${NC}"
|
|
490
|
+
fi
|
|
222
491
|
echo ""
|
|
223
492
|
}
|
|
224
493
|
|
|
@@ -408,6 +677,9 @@ case "$ACTION" in
|
|
|
408
677
|
summary)
|
|
409
678
|
cmd_summary
|
|
410
679
|
;;
|
|
680
|
+
progress)
|
|
681
|
+
cmd_progress
|
|
682
|
+
;;
|
|
411
683
|
detail)
|
|
412
684
|
cmd_detail
|
|
413
685
|
;;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Database Guidelines
|
|
2
|
+
|
|
3
|
+
> Database patterns and conventions for this project.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
<!--
|
|
10
|
+
Document your project's database conventions here.
|
|
11
|
+
|
|
12
|
+
Questions to answer:
|
|
13
|
+
- What ORM/query library do you use?
|
|
14
|
+
- How are migrations managed?
|
|
15
|
+
- What are the naming conventions for tables/columns?
|
|
16
|
+
- How do you handle transactions?
|
|
17
|
+
-->
|
|
18
|
+
|
|
19
|
+
(To be filled by the team)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Query Patterns
|
|
24
|
+
|
|
25
|
+
<!-- How should queries be written? Batch operations? -->
|
|
26
|
+
|
|
27
|
+
(To be filled by the team)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Migrations
|
|
32
|
+
|
|
33
|
+
<!-- How to create and run migrations -->
|
|
34
|
+
|
|
35
|
+
(To be filled by the team)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Naming Conventions
|
|
40
|
+
|
|
41
|
+
<!-- Table names, column names, index names -->
|
|
42
|
+
|
|
43
|
+
(To be filled by the team)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Common Mistakes
|
|
48
|
+
|
|
49
|
+
<!-- Database-related mistakes your team has made -->
|
|
50
|
+
|
|
51
|
+
(To be filled by the team)
|