@osfactory/har 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/index.js +1817 -651
- package/dist/prompts/system-authoring.md +27 -2
- package/dist/templates/adaptation-prompt-init.md +60 -5
- package/dist/templates/adaptation-prompt-maintain.md +7 -4
- package/dist/templates/har-boilerplate/CLAUDE.agent.md +5 -3
- package/dist/templates/har-boilerplate/README.md +51 -9
- package/dist/templates/har-boilerplate/agent-cli.sh +72 -26
- package/dist/templates/har-boilerplate/agent-slot.sh +351 -0
- package/dist/templates/har-boilerplate/attach.sh +7 -1
- package/dist/templates/har-boilerplate/ecosystem.agent.template.cjs +3 -1
- package/dist/templates/har-boilerplate/env.template +4 -1
- package/dist/templates/har-boilerplate/harness.env +32 -0
- package/dist/templates/har-boilerplate/launch.sh +167 -120
- package/dist/templates/har-boilerplate/preflight.sh +41 -0
- package/dist/templates/har-boilerplate/provision-toolchain.sh +285 -0
- package/dist/templates/har-boilerplate/setup-infra.sh +87 -11
- package/dist/templates/har-boilerplate/teardown.sh +2 -1
- package/dist/templates/har-boilerplate/verify.sh +91 -11
- package/dist/templates/har-boilerplate-cli/CLAUDE.agent.md +5 -2
- package/dist/templates/har-boilerplate-cli/README.md +40 -6
- package/dist/templates/har-boilerplate-cli/agent-cli.sh +1 -1
- package/dist/templates/har-boilerplate-cli/agent-slot.sh +331 -0
- package/dist/templates/har-boilerplate-cli/harness.env +13 -0
- package/dist/templates/har-boilerplate-cli/launch.sh +140 -95
- package/dist/templates/har-boilerplate-cli/preflight.sh +37 -0
- package/dist/templates/har-boilerplate-cli/provision-toolchain.sh +285 -0
- package/dist/templates/har-boilerplate-cli/setup-infra.sh +87 -11
- package/dist/templates/har-boilerplate-cli/verify.sh +93 -12
- package/dist/templates/har-boilerplate-ios/README.md +29 -2
- package/dist/templates/har-boilerplate-ios/harness.env +6 -1
- package/dist/templates/har-boilerplate-ios/launch.sh +8 -13
- package/dist/templates/har-boilerplate-ios/provision-toolchain.sh +285 -0
- package/dist/templates/har-boilerplate-ios/verify.sh +20 -20
- package/package.json +1 -1
- package/dist/templates/har-boilerplate-ios/ADAPT-PROMPT.md +0 -57
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Every launch starts a FRESH session: any previous session for the slot is torn
|
|
4
4
|
# down (its branch is kept) and a new suffixed worktree is created from HEAD.
|
|
5
5
|
#
|
|
6
|
-
# Usage: ./.har/launch.sh <agent-id> [--no-worktree] [--claude] [--replace] [--force]
|
|
6
|
+
# Usage: ./.har/launch.sh <agent-id> [--no-worktree] [--claude] [--replace] [--force] [--resume]
|
|
7
7
|
set -euo pipefail
|
|
8
8
|
|
|
9
9
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -19,6 +19,7 @@ USE_WORKTREE="${HARNESS_USE_WORKTREE:-true}"
|
|
|
19
19
|
USE_CLAUDE=false
|
|
20
20
|
FORCE=false
|
|
21
21
|
REPLACE=false
|
|
22
|
+
RESUME=false
|
|
22
23
|
PURPOSE="${HAR_SESSION_PURPOSE:-}"
|
|
23
24
|
|
|
24
25
|
for arg in "$@"; do
|
|
@@ -28,12 +29,13 @@ for arg in "$@"; do
|
|
|
28
29
|
--claude) USE_CLAUDE=true ;;
|
|
29
30
|
--replace) REPLACE=true ;;
|
|
30
31
|
--force) FORCE=true ;;
|
|
32
|
+
--resume) RESUME=true ;;
|
|
31
33
|
--purpose=*) PURPOSE="${arg#--purpose=}" ;;
|
|
32
34
|
esac
|
|
33
35
|
done
|
|
34
36
|
|
|
35
37
|
if [[ -z "$AGENT_ID" ]]; then
|
|
36
|
-
echo "Usage: $0 <agent-id> [--no-worktree] [--claude] [--replace] [--force] [--purpose=label]" >&2
|
|
38
|
+
echo "Usage: $0 <agent-id> [--no-worktree] [--claude] [--replace] [--force] [--resume] [--purpose=label]" >&2
|
|
37
39
|
echo " agent-id must be between ${HARNESS_AGENT_SLOT_MIN} and ${HARNESS_AGENT_SLOT_MAX}" >&2
|
|
38
40
|
exit 1
|
|
39
41
|
fi
|
|
@@ -42,24 +44,65 @@ validate_agent_id "$AGENT_ID"
|
|
|
42
44
|
|
|
43
45
|
log() { echo "==> [agent-$AGENT_ID] $*" >&2; }
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
WORK_DIR="$REPO_ROOT"
|
|
48
|
+
WORKTREE_DIR=""
|
|
49
|
+
BRANCH=""
|
|
50
|
+
SUFFIX=""
|
|
51
|
+
BASE_BRANCH=""
|
|
52
|
+
BASE_COMMIT=""
|
|
53
|
+
ENV_FILE=""
|
|
54
|
+
REGISTRY_WRITTEN=false
|
|
55
|
+
|
|
56
|
+
if [ "$RESUME" = true ]; then
|
|
57
|
+
har_launch_preflight "$AGENT_ID" "$FORCE" "$REPLACE" true || exit $?
|
|
58
|
+
eval "$(har_resume_session_assignments "$AGENT_ID")"
|
|
59
|
+
REGISTRY_WRITTEN=true
|
|
60
|
+
mark_slot_failed() {
|
|
61
|
+
local exit_code="$?"
|
|
62
|
+
if [ "$exit_code" != "0" ] && [ "$REGISTRY_WRITTEN" = true ]; then
|
|
63
|
+
log "Resume failed. Recording failed slot state..."
|
|
64
|
+
set +e
|
|
65
|
+
SLOT_AGENT_ID="$AGENT_ID" \
|
|
66
|
+
SLOT_MODE="$([ "$USE_WORKTREE" = true ] && echo worktree || echo root)" \
|
|
67
|
+
SLOT_WORK_DIR="$WORK_DIR" \
|
|
68
|
+
SLOT_SUFFIX="${SUFFIX:-}" \
|
|
69
|
+
SLOT_WORKTREE_PATH="${WORKTREE_DIR:-}" \
|
|
70
|
+
SLOT_BRANCH="${BRANCH:-}" \
|
|
71
|
+
SLOT_BASE_BRANCH="${BASE_BRANCH:-}" \
|
|
72
|
+
SLOT_BASE_COMMIT="${BASE_COMMIT:-}" \
|
|
73
|
+
SLOT_PURPOSE="${PURPOSE}" \
|
|
74
|
+
SLOT_PORTS_JSON="{\"frontend\":${FE_PORT},\"api\":${API_PORT},\"debug\":${DEBUG_PORT},\"db\":${DB_PORT}}" \
|
|
75
|
+
SLOT_PREVIEW_URLS_JSON="{\"frontend\":\"http://localhost:${FE_PORT}\",\"api\":\"http://localhost:${API_PORT}\"}" \
|
|
76
|
+
SLOT_STATUS="failed" \
|
|
77
|
+
SLOT_LAST_ERROR="launch.sh --resume exited with code ${exit_code}" \
|
|
78
|
+
write_slot_registry
|
|
79
|
+
log " Work dir: ${WORK_DIR}"
|
|
80
|
+
log " Env file: ${ENV_FILE}"
|
|
81
|
+
log " Recovery: ./.har/launch.sh ${AGENT_ID} --resume"
|
|
82
|
+
fi
|
|
83
|
+
}
|
|
84
|
+
trap mark_slot_failed EXIT
|
|
85
|
+
else
|
|
86
|
+
# Preflight before worktree/install — ports, foreign PM2, Docker, occupied slot.
|
|
87
|
+
har_launch_preflight "$AGENT_ID" "$FORCE" "$REPLACE" || exit $?
|
|
51
88
|
|
|
52
|
-
|
|
89
|
+
# Replace any previous session for this slot — requires explicit confirmation.
|
|
90
|
+
if slot_is_occupied "$AGENT_ID"; then
|
|
91
|
+
require_slot_replace_confirm "$AGENT_ID" "$FORCE" "$REPLACE"
|
|
92
|
+
log "Replacing previous session for slot ${AGENT_ID}..."
|
|
93
|
+
"$SCRIPT_DIR/teardown.sh" "$AGENT_ID" >&2
|
|
94
|
+
fi
|
|
95
|
+
fi
|
|
53
96
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
require_slot_replace_confirm "$AGENT_ID" "$FORCE" "$REPLACE"
|
|
57
|
-
log "Replacing previous session for slot ${AGENT_ID}..."
|
|
58
|
-
"$SCRIPT_DIR/teardown.sh" "$AGENT_ID" >&2
|
|
97
|
+
if har_harness_uses_pm2; then
|
|
98
|
+
log "Ports: frontend=$FE_PORT api=$API_PORT debug=$DEBUG_PORT"
|
|
59
99
|
fi
|
|
60
100
|
|
|
61
|
-
# Ensure shared infra is running
|
|
101
|
+
# Ensure shared infra is running (persists host ports in .har/state/infra.env).
|
|
62
102
|
"$SCRIPT_DIR/setup-infra.sh"
|
|
103
|
+
DB_PORT="${AGENT_DB_PORT:-${HARNESS_DB_PORT_DEFAULT:-15432}}"
|
|
104
|
+
MINIO_PORT="${AGENT_MINIO_PORT:-${HARNESS_MINIO_PORT_DEFAULT:-19000}}"
|
|
105
|
+
BROWSER_PORT="${AGENT_BROWSER_PORT:-${HARNESS_BROWSER_PORT_DEFAULT:-13001}}"
|
|
63
106
|
|
|
64
107
|
# Clone agent database from template
|
|
65
108
|
if har_infra_enabled db && [ -n "${HARNESS_TEMPLATE_DB:-}" ]; then
|
|
@@ -85,111 +128,113 @@ if har_infra_enabled minio; then
|
|
|
85
128
|
fi
|
|
86
129
|
|
|
87
130
|
# Session worktree (default — use --no-worktree to work in repo root).
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
fi
|
|
112
|
-
|
|
113
|
-
# Install dependencies (fresh worktrees have no node_modules — PM2 config needs them at load time)
|
|
114
|
-
if [ -f "$WORK_DIR/package.json" ] && [ ! -d "$WORK_DIR/node_modules" ]; then
|
|
115
|
-
log "Installing dependencies in $WORK_DIR..."
|
|
116
|
-
(cd "$WORK_DIR" && npm install --silent)
|
|
117
|
-
elif [ -f "$WORK_DIR/go.mod" ] && [ ! -d "$WORK_DIR/vendor" ]; then
|
|
118
|
-
log "Go module detected in work dir (run go mod download if needed)"
|
|
119
|
-
fi
|
|
131
|
+
if [ "$RESUME" != true ]; then
|
|
132
|
+
# Name encodes what the session is based on: <base-branch>-<sha4>-har-agent-<id>-<rand4>.
|
|
133
|
+
WORK_DIR="$REPO_ROOT"
|
|
134
|
+
WORKTREE_DIR=""
|
|
135
|
+
BRANCH=""
|
|
136
|
+
SUFFIX=""
|
|
137
|
+
BASE_BRANCH="$(git -C "$REPO_ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "detached")"
|
|
138
|
+
BASE_COMMIT="$(git -C "$REPO_ROOT" rev-parse HEAD 2>/dev/null || true)"
|
|
139
|
+
if [ "$USE_WORKTREE" = true ]; then
|
|
140
|
+
SHORT_SHA="$(git -C "$REPO_ROOT" rev-parse --short=4 HEAD)"
|
|
141
|
+
SUFFIX="$(LC_ALL=C tr -dc 'a-z0-9' </dev/urandom 2>/dev/null | head -c 4 || true)"
|
|
142
|
+
[ -n "$SUFFIX" ] || SUFFIX="$(printf '%04d' $(( RANDOM % 10000 )))"
|
|
143
|
+
SESSION_NAME="${BASE_BRANCH//\//-}-${SHORT_SHA}-har-agent-${AGENT_ID}-${SUFFIX}"
|
|
144
|
+
BRANCH="$SESSION_NAME"
|
|
145
|
+
WORKTREE_DIR="$HOME/worktrees/${SESSION_NAME}"
|
|
146
|
+
log "Creating session worktree at $WORKTREE_DIR (branch $BRANCH)..."
|
|
147
|
+
git -C "$REPO_ROOT" worktree add "$WORKTREE_DIR" -b "$BRANCH"
|
|
148
|
+
REL_PREFIX="$(git -C "$REPO_ROOT" rev-parse --show-prefix 2>/dev/null || true)"
|
|
149
|
+
WORK_DIR="${WORKTREE_DIR%/}/${REL_PREFIX}"
|
|
150
|
+
WORK_DIR="${WORK_DIR%/}"
|
|
151
|
+
else
|
|
152
|
+
log "Using repo root (worktree disabled)"
|
|
153
|
+
REL_PREFIX="$(git -C "$REPO_ROOT" rev-parse --show-prefix 2>/dev/null || true)"
|
|
154
|
+
fi
|
|
120
155
|
|
|
121
|
-
|
|
122
|
-
if [ -n "$
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
156
|
+
GIT_EXCLUDE="$(git -C "$REPO_ROOT" rev-parse --git-common-dir 2>/dev/null)/info/exclude"
|
|
157
|
+
if [ -n "$GIT_EXCLUDE" ] && [ -d "$(dirname "$GIT_EXCLUDE")" ]; then
|
|
158
|
+
for pattern in '.env.agent.*' 'ecosystem.agent.*.config.cjs' '.har/venv'; do
|
|
159
|
+
grep -qxF "$pattern" "$GIT_EXCLUDE" 2>/dev/null || echo "$pattern" >> "$GIT_EXCLUDE"
|
|
160
|
+
done
|
|
161
|
+
fi
|
|
126
162
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
GIT_EXCLUDE="$(git -C "$REPO_ROOT" rev-parse --git-common-dir 2>/dev/null)/info/exclude"
|
|
131
|
-
if [ -n "$GIT_EXCLUDE" ] && [ -d "$(dirname "$GIT_EXCLUDE")" ]; then
|
|
132
|
-
for pattern in '.env.agent.*' 'ecosystem.agent.*.config.cjs'; do
|
|
133
|
-
grep -qxF "$pattern" "$GIT_EXCLUDE" 2>/dev/null || echo "$pattern" >> "$GIT_EXCLUDE"
|
|
134
|
-
done
|
|
135
|
-
fi
|
|
163
|
+
ENV_FILE="$WORK_DIR/.env.agent.${AGENT_ID}"
|
|
164
|
+
log "Generating $ENV_FILE..."
|
|
165
|
+
har_regenerate_agent_env_file "$AGENT_ID" "$WORK_DIR" "$ENV_FILE"
|
|
136
166
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
167
|
+
REGISTRY_WRITTEN=false
|
|
168
|
+
mark_slot_failed() {
|
|
169
|
+
local exit_code="$?"
|
|
170
|
+
if [ "$exit_code" != "0" ] && [ "$REGISTRY_WRITTEN" = true ]; then
|
|
171
|
+
log "Launch failed after creating the session. Recording failed slot state..."
|
|
172
|
+
set +e
|
|
173
|
+
SLOT_AGENT_ID="$AGENT_ID" \
|
|
174
|
+
SLOT_MODE="$([ "$USE_WORKTREE" = true ] && echo worktree || echo root)" \
|
|
175
|
+
SLOT_WORK_DIR="$WORK_DIR" \
|
|
176
|
+
SLOT_SUFFIX="${SUFFIX:-}" \
|
|
177
|
+
SLOT_WORKTREE_PATH="${WORKTREE_DIR:-}" \
|
|
178
|
+
SLOT_BRANCH="${BRANCH:-}" \
|
|
179
|
+
SLOT_BASE_BRANCH="${BASE_BRANCH:-}" \
|
|
180
|
+
SLOT_BASE_COMMIT="${BASE_COMMIT:-}" \
|
|
181
|
+
SLOT_PURPOSE="${PURPOSE}" \
|
|
182
|
+
SLOT_PORTS_JSON="{\"frontend\":${FE_PORT},\"api\":${API_PORT},\"debug\":${DEBUG_PORT},\"db\":${DB_PORT}}" \
|
|
183
|
+
SLOT_PREVIEW_URLS_JSON="{\"frontend\":\"http://localhost:${FE_PORT}\",\"api\":\"http://localhost:${API_PORT}\"}" \
|
|
184
|
+
SLOT_STATUS="failed" \
|
|
185
|
+
SLOT_LAST_ERROR="launch.sh exited with code ${exit_code}" \
|
|
186
|
+
write_slot_registry
|
|
187
|
+
log " Work dir: ${WORK_DIR}"
|
|
188
|
+
log " Env file: ${ENV_FILE}"
|
|
189
|
+
log " Recovery: ./.har/launch.sh ${AGENT_ID} --resume"
|
|
190
|
+
fi
|
|
191
|
+
}
|
|
192
|
+
trap mark_slot_failed EXIT
|
|
149
193
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
194
|
+
SLOT_AGENT_ID="$AGENT_ID" \
|
|
195
|
+
SLOT_MODE="$([ "$USE_WORKTREE" = true ] && echo worktree || echo root)" \
|
|
196
|
+
SLOT_WORK_DIR="$WORK_DIR" \
|
|
197
|
+
SLOT_SUFFIX="${SUFFIX:-}" \
|
|
198
|
+
SLOT_WORKTREE_PATH="${WORKTREE_DIR:-}" \
|
|
199
|
+
SLOT_BRANCH="${BRANCH:-}" \
|
|
200
|
+
SLOT_BASE_BRANCH="${BASE_BRANCH:-}" \
|
|
201
|
+
SLOT_BASE_COMMIT="${BASE_COMMIT:-}" \
|
|
202
|
+
SLOT_PURPOSE="${PURPOSE}" \
|
|
203
|
+
SLOT_PORTS_JSON="{\"frontend\":${FE_PORT},\"api\":${API_PORT},\"debug\":${DEBUG_PORT},\"db\":${DB_PORT}}" \
|
|
204
|
+
SLOT_PREVIEW_URLS_JSON="{\"frontend\":\"http://localhost:${FE_PORT}\",\"api\":\"http://localhost:${API_PORT}\"}" \
|
|
205
|
+
SLOT_STATUS="starting" \
|
|
206
|
+
write_slot_registry
|
|
207
|
+
REGISTRY_WRITTEN=true
|
|
208
|
+
else
|
|
209
|
+
REL_PREFIX="$(git -C "$REPO_ROOT" rev-parse --show-prefix 2>/dev/null || true)"
|
|
210
|
+
log "Resuming session at ${WORK_DIR}"
|
|
211
|
+
har_regenerate_agent_env_file "$AGENT_ID" "$WORK_DIR" "$ENV_FILE"
|
|
212
|
+
SLOT_AGENT_ID="$AGENT_ID" \
|
|
213
|
+
SLOT_MODE="$([ "$USE_WORKTREE" = true ] && echo worktree || echo root)" \
|
|
214
|
+
SLOT_WORK_DIR="$WORK_DIR" \
|
|
215
|
+
SLOT_SUFFIX="${SUFFIX:-}" \
|
|
216
|
+
SLOT_WORKTREE_PATH="${WORKTREE_DIR:-}" \
|
|
217
|
+
SLOT_BRANCH="${BRANCH:-}" \
|
|
218
|
+
SLOT_BASE_BRANCH="${BASE_BRANCH:-}" \
|
|
219
|
+
SLOT_BASE_COMMIT="${BASE_COMMIT:-}" \
|
|
220
|
+
SLOT_PURPOSE="${PURPOSE}" \
|
|
221
|
+
SLOT_PORTS_JSON="{\"frontend\":${FE_PORT},\"api\":${API_PORT},\"debug\":${DEBUG_PORT},\"db\":${DB_PORT}}" \
|
|
222
|
+
SLOT_PREVIEW_URLS_JSON="{\"frontend\":\"http://localhost:${FE_PORT}\",\"api\":\"http://localhost:${API_PORT}\"}" \
|
|
223
|
+
SLOT_STATUS="starting" \
|
|
224
|
+
write_slot_registry
|
|
225
|
+
fi
|
|
176
226
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
SLOT_PORTS_JSON="{\"frontend\":${FE_PORT},\"api\":${API_PORT},\"debug\":${DEBUG_PORT}}" \
|
|
189
|
-
SLOT_PREVIEW_URLS_JSON="{\"frontend\":\"http://localhost:${FE_PORT}\",\"api\":\"http://localhost:${API_PORT}\"}" \
|
|
190
|
-
SLOT_STATUS="starting" \
|
|
191
|
-
write_slot_registry
|
|
192
|
-
REGISTRY_WRITTEN=true
|
|
227
|
+
if [ "$RESUME" = true ] && har_toolchain_ready "$WORK_DIR"; then
|
|
228
|
+
log "Toolchain already provisioned — skipping install."
|
|
229
|
+
else
|
|
230
|
+
log "Provisioning toolchain (see harness.env: HARNESS_ECOSYSTEM, HARNESS_INSTALL_CMD)..."
|
|
231
|
+
HAR_WORK_DIR="$WORK_DIR" \
|
|
232
|
+
HAR_ENV_FILE="$ENV_FILE" \
|
|
233
|
+
HAR_WORKTREE_DIR="${WORKTREE_DIR:-}" \
|
|
234
|
+
HAR_REL_PREFIX="${REL_PREFIX:-}" \
|
|
235
|
+
HAR_AGENT_ID="$AGENT_ID" \
|
|
236
|
+
"$SCRIPT_DIR/provision-toolchain.sh"
|
|
237
|
+
fi
|
|
193
238
|
|
|
194
239
|
if [ -n "${HARNESS_DB_MINIMAL_BOOTSTRAP_CMD:-}" ]; then
|
|
195
240
|
log "Running minimal data bootstrap..."
|
|
@@ -200,13 +245,15 @@ fi
|
|
|
200
245
|
ECOSYSTEM_FILE="$WORK_DIR/ecosystem.agent.${AGENT_ID}.config.cjs"
|
|
201
246
|
log "Generating $ECOSYSTEM_FILE..."
|
|
202
247
|
AGENT_ID="$AGENT_ID" \
|
|
248
|
+
HARNESS_PROJECT_NAME="$HARNESS_PROJECT_NAME" \
|
|
203
249
|
FE_PORT="$FE_PORT" \
|
|
204
250
|
DEBUG_PORT="$DEBUG_PORT" \
|
|
205
|
-
envsubst '${AGENT_ID} ${FE_PORT} ${DEBUG_PORT}' \
|
|
251
|
+
envsubst '${AGENT_ID} ${HARNESS_PROJECT_NAME} ${FE_PORT} ${DEBUG_PORT}' \
|
|
206
252
|
< "$SCRIPT_DIR/ecosystem.agent.template.cjs" > "$ECOSYSTEM_FILE"
|
|
207
253
|
|
|
208
|
-
|
|
209
|
-
|
|
254
|
+
PM2_REGEX="$(har_pm2_delete_regex "$AGENT_ID")"
|
|
255
|
+
# Stop existing processes for this agent (project-scoped — never touch other harnesses).
|
|
256
|
+
npx --yes pm2 delete "$PM2_REGEX" 2>/dev/null || true
|
|
210
257
|
|
|
211
258
|
# Start PM2 processes
|
|
212
259
|
log "Starting PM2 processes..."
|
|
@@ -246,14 +293,14 @@ SLOT_BRANCH="${BRANCH:-}" \
|
|
|
246
293
|
SLOT_BASE_BRANCH="${BASE_BRANCH:-}" \
|
|
247
294
|
SLOT_BASE_COMMIT="${BASE_COMMIT:-}" \
|
|
248
295
|
SLOT_PURPOSE="${PURPOSE}" \
|
|
249
|
-
SLOT_PORTS_JSON="{\"frontend\":${FE_PORT},\"api\":${API_PORT},\"debug\":${DEBUG_PORT}}" \
|
|
296
|
+
SLOT_PORTS_JSON="{\"frontend\":${FE_PORT},\"api\":${API_PORT},\"debug\":${DEBUG_PORT},\"db\":${DB_PORT}}" \
|
|
250
297
|
SLOT_PREVIEW_URLS_JSON="{\"frontend\":\"http://localhost:${FE_PORT}\",\"api\":\"http://localhost:${API_PORT}\"}" \
|
|
251
298
|
SLOT_STATUS="active" \
|
|
252
299
|
write_slot_registry
|
|
253
300
|
|
|
254
301
|
# Launch Claude Code in tmux (optional)
|
|
255
302
|
if [ "$USE_CLAUDE" = true ]; then
|
|
256
|
-
TMUX_SESSION="
|
|
303
|
+
TMUX_SESSION="$(har_tmux_session "$AGENT_ID")"
|
|
257
304
|
if tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
|
|
258
305
|
tmux kill-session -t "$TMUX_SESSION"
|
|
259
306
|
fi
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Launch readiness gate — run before launch.sh or standalone.
|
|
3
|
+
# Usage: ./.har/preflight.sh <agent-id> [--replace] [--force]
|
|
4
|
+
# JSON: har env preflight <id> --json
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
9
|
+
|
|
10
|
+
# shellcheck source=/dev/null
|
|
11
|
+
source "$SCRIPT_DIR/harness.env"
|
|
12
|
+
# shellcheck source=/dev/null
|
|
13
|
+
source "$SCRIPT_DIR/agent-slot.sh"
|
|
14
|
+
|
|
15
|
+
AGENT_ID="${1:-}"
|
|
16
|
+
FORCE=false
|
|
17
|
+
REPLACE=false
|
|
18
|
+
|
|
19
|
+
for arg in "$@"; do
|
|
20
|
+
case "$arg" in
|
|
21
|
+
--replace) REPLACE=true ;;
|
|
22
|
+
--force) FORCE=true ;;
|
|
23
|
+
esac
|
|
24
|
+
done
|
|
25
|
+
|
|
26
|
+
if [[ -z "$AGENT_ID" ]]; then
|
|
27
|
+
echo "Usage: $0 <agent-id> [--replace] [--force]" >&2
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
validate_agent_id "$AGENT_ID"
|
|
32
|
+
|
|
33
|
+
if har_launch_preflight "$AGENT_ID" "$FORCE" "$REPLACE"; then
|
|
34
|
+
echo "Slot ${AGENT_ID}: ready to launch."
|
|
35
|
+
if har_harness_uses_pm2; then
|
|
36
|
+
echo " Ports: frontend=${FE_PORT} api=${API_PORT} debug=${DEBUG_PORT}"
|
|
37
|
+
fi
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
exit $?
|