@osfactory/har 0.6.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 +1811 -648
- package/dist/prompts/system-authoring.md +27 -2
- package/dist/templates/adaptation-prompt-init.md +32 -2
- package/dist/templates/adaptation-prompt-maintain.md +5 -2
- package/dist/templates/har-boilerplate/README.md +39 -3
- 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 +1 -1
- package/dist/templates/har-boilerplate/env.template +1 -1
- package/dist/templates/har-boilerplate/harness.env +27 -0
- package/dist/templates/har-boilerplate/launch.sh +167 -114
- package/dist/templates/har-boilerplate/preflight.sh +41 -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-cli/README.md +28 -0
- package/dist/templates/har-boilerplate-cli/agent-slot.sh +331 -0
- package/dist/templates/har-boilerplate-cli/harness.env +7 -0
- package/dist/templates/har-boilerplate-cli/launch.sh +145 -95
- package/dist/templates/har-boilerplate-cli/preflight.sh +37 -0
- package/dist/templates/har-boilerplate-cli/setup-infra.sh +87 -11
- package/dist/templates/har-boilerplate-ios/README.md +26 -0
- package/dist/templates/har-boilerplate-ios/harness.env +2 -1
- package/package.json +1 -1
- package/dist/templates/har-boilerplate-ios/ADAPT-PROMPT.md +0 -57
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Launch readiness gate for CLI/library harnesses (occupied slot only).
|
|
3
|
+
# Usage: ./.har/preflight.sh <agent-id> [--replace] [--force]
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
8
|
+
|
|
9
|
+
# shellcheck source=/dev/null
|
|
10
|
+
source "$SCRIPT_DIR/harness.env"
|
|
11
|
+
# shellcheck source=/dev/null
|
|
12
|
+
source "$SCRIPT_DIR/agent-slot.sh"
|
|
13
|
+
|
|
14
|
+
AGENT_ID="${1:-}"
|
|
15
|
+
FORCE=false
|
|
16
|
+
REPLACE=false
|
|
17
|
+
|
|
18
|
+
for arg in "$@"; do
|
|
19
|
+
case "$arg" in
|
|
20
|
+
--replace) REPLACE=true ;;
|
|
21
|
+
--force) FORCE=true ;;
|
|
22
|
+
esac
|
|
23
|
+
done
|
|
24
|
+
|
|
25
|
+
if [[ -z "$AGENT_ID" ]]; then
|
|
26
|
+
echo "Usage: $0 <agent-id> [--replace] [--force]" >&2
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
validate_agent_id "$AGENT_ID"
|
|
31
|
+
|
|
32
|
+
if har_launch_preflight "$AGENT_ID" "$FORCE" "$REPLACE"; then
|
|
33
|
+
echo "Slot ${AGENT_ID}: ready to launch."
|
|
34
|
+
exit 0
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
exit $?
|
|
@@ -11,26 +11,101 @@ set -euo pipefail
|
|
|
11
11
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
12
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
13
13
|
COMPOSE_FILE="$SCRIPT_DIR/docker-compose.agent.yml"
|
|
14
|
+
INFRA_STATE="$SCRIPT_DIR/state/infra.env"
|
|
14
15
|
|
|
15
16
|
# shellcheck source=/dev/null
|
|
16
17
|
source "$SCRIPT_DIR/harness.env"
|
|
18
|
+
# shellcheck source=/dev/null
|
|
19
|
+
source "$SCRIPT_DIR/agent-slot.sh"
|
|
17
20
|
|
|
18
21
|
COMPOSE_PROJECT="har-${HARNESS_PROJECT_NAME}"
|
|
19
|
-
DB_PORT="${AGENT_DB_PORT:-15432}"
|
|
20
22
|
PSQL="har_pg psql -d postgres"
|
|
21
23
|
|
|
22
24
|
log() { echo "==> $*" >&2; }
|
|
23
25
|
|
|
26
|
+
har_compose_service_running() {
|
|
27
|
+
local service="$1"
|
|
28
|
+
docker ps --filter "name=${COMPOSE_PROJECT}-${service}-1" --format '{{.Names}}' 2>/dev/null \
|
|
29
|
+
| grep -q "^${COMPOSE_PROJECT}-${service}-1\$"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
har_resolve_infra_port() {
|
|
33
|
+
local var_name="$1"
|
|
34
|
+
local default_port="$2"
|
|
35
|
+
local scan_start="$3"
|
|
36
|
+
local scan_end="$4"
|
|
37
|
+
local service="${5:-}"
|
|
38
|
+
local current="${!var_name:-}"
|
|
39
|
+
|
|
40
|
+
if [ -n "$current" ] && { ! port_in_use "$current" || { [ -n "$service" ] && har_compose_service_running "$service"; }; }; then
|
|
41
|
+
echo "$current"
|
|
42
|
+
return 0
|
|
43
|
+
fi
|
|
44
|
+
har_allocate_port "$default_port" "$scan_start" "$scan_end"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
mkdir -p "$(dirname "$INFRA_STATE")"
|
|
48
|
+
if [ -f "$INFRA_STATE" ]; then
|
|
49
|
+
# shellcheck source=/dev/null
|
|
50
|
+
source "$INFRA_STATE"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
DB_PORT="$(har_resolve_infra_port AGENT_DB_PORT \
|
|
54
|
+
"${HARNESS_DB_PORT_DEFAULT:-15432}" \
|
|
55
|
+
"${HARNESS_DB_PORT_SCAN_START:-15432}" \
|
|
56
|
+
"${HARNESS_DB_PORT_SCAN_END:-15499}" \
|
|
57
|
+
db)"
|
|
58
|
+
MINIO_PORT="$(har_resolve_infra_port AGENT_MINIO_PORT \
|
|
59
|
+
"${HARNESS_MINIO_PORT_DEFAULT:-19000}" \
|
|
60
|
+
"${HARNESS_MINIO_PORT_SCAN_START:-19000}" \
|
|
61
|
+
"${HARNESS_MINIO_PORT_SCAN_END:-19099}" \
|
|
62
|
+
minio)"
|
|
63
|
+
MINIO_CONSOLE_PORT="$(har_resolve_infra_port AGENT_MINIO_CONSOLE_PORT \
|
|
64
|
+
"${HARNESS_MINIO_CONSOLE_PORT_DEFAULT:-19001}" \
|
|
65
|
+
"${HARNESS_MINIO_CONSOLE_PORT_SCAN_START:-19001}" \
|
|
66
|
+
"${HARNESS_MINIO_CONSOLE_PORT_SCAN_END:-19099}")"
|
|
67
|
+
BROWSER_PORT="$(har_resolve_infra_port AGENT_BROWSER_PORT \
|
|
68
|
+
"${HARNESS_BROWSER_PORT_DEFAULT:-13001}" \
|
|
69
|
+
"${HARNESS_BROWSER_PORT_SCAN_START:-13001}" \
|
|
70
|
+
"${HARNESS_BROWSER_PORT_SCAN_END:-13099}" \
|
|
71
|
+
headless-browser)"
|
|
72
|
+
MAILPIT_WEB_PORT="$(har_resolve_infra_port AGENT_MAILPIT_WEB_PORT \
|
|
73
|
+
"${HARNESS_MAILPIT_WEB_PORT_DEFAULT:-18025}" \
|
|
74
|
+
"${HARNESS_MAILPIT_WEB_PORT_SCAN_START:-18025}" \
|
|
75
|
+
"${HARNESS_MAILPIT_WEB_PORT_SCAN_END:-18099}" \
|
|
76
|
+
mailpit)"
|
|
77
|
+
MAILPIT_SMTP_PORT="$(har_resolve_infra_port AGENT_MAILPIT_SMTP_PORT \
|
|
78
|
+
"${HARNESS_MAILPIT_SMTP_PORT_DEFAULT:-11025}" \
|
|
79
|
+
"${HARNESS_MAILPIT_SMTP_PORT_SCAN_START:-11025}" \
|
|
80
|
+
"${HARNESS_MAILPIT_SMTP_PORT_SCAN_END:-11099}")"
|
|
81
|
+
|
|
82
|
+
export AGENT_DB_PORT="$DB_PORT"
|
|
83
|
+
export AGENT_MINIO_PORT="$MINIO_PORT"
|
|
84
|
+
export AGENT_MINIO_CONSOLE_PORT="$MINIO_CONSOLE_PORT"
|
|
85
|
+
export AGENT_BROWSER_PORT="$BROWSER_PORT"
|
|
86
|
+
export AGENT_MAILPIT_WEB_PORT="$MAILPIT_WEB_PORT"
|
|
87
|
+
export AGENT_MAILPIT_SMTP_PORT="$MAILPIT_SMTP_PORT"
|
|
88
|
+
|
|
89
|
+
cat > "$INFRA_STATE" <<EOF
|
|
90
|
+
# Persisted by setup-infra.sh — host ports for shared docker compose services.
|
|
91
|
+
export AGENT_DB_PORT=${DB_PORT}
|
|
92
|
+
export AGENT_MINIO_PORT=${MINIO_PORT}
|
|
93
|
+
export AGENT_MINIO_CONSOLE_PORT=${MINIO_CONSOLE_PORT}
|
|
94
|
+
export AGENT_BROWSER_PORT=${BROWSER_PORT}
|
|
95
|
+
export AGENT_MAILPIT_WEB_PORT=${MAILPIT_WEB_PORT}
|
|
96
|
+
export AGENT_MAILPIT_SMTP_PORT=${MAILPIT_SMTP_PORT}
|
|
97
|
+
EOF
|
|
98
|
+
|
|
24
99
|
SERVICES="${HARNESS_INFRA_SERVICES:-}"
|
|
25
100
|
|
|
26
101
|
if [ -n "$SERVICES" ]; then
|
|
27
102
|
log "Starting shared infrastructure (project: $COMPOSE_PROJECT): $SERVICES"
|
|
28
103
|
AGENT_DB_PORT="$DB_PORT" \
|
|
29
|
-
AGENT_MINIO_PORT="$
|
|
30
|
-
AGENT_MINIO_CONSOLE_PORT="$
|
|
31
|
-
AGENT_BROWSER_PORT="$
|
|
32
|
-
AGENT_MAILPIT_WEB_PORT="$
|
|
33
|
-
AGENT_MAILPIT_SMTP_PORT="$
|
|
104
|
+
AGENT_MINIO_PORT="$MINIO_PORT" \
|
|
105
|
+
AGENT_MINIO_CONSOLE_PORT="$MINIO_CONSOLE_PORT" \
|
|
106
|
+
AGENT_BROWSER_PORT="$BROWSER_PORT" \
|
|
107
|
+
AGENT_MAILPIT_WEB_PORT="$MAILPIT_WEB_PORT" \
|
|
108
|
+
AGENT_MAILPIT_SMTP_PORT="$MAILPIT_SMTP_PORT" \
|
|
34
109
|
docker compose -p "$COMPOSE_PROJECT" -f "$COMPOSE_FILE" up -d $SERVICES
|
|
35
110
|
else
|
|
36
111
|
log "No shared infra services enabled in harness.env (HARNESS_INFRA_SERVICES)"
|
|
@@ -85,18 +160,19 @@ fi
|
|
|
85
160
|
# Shared app services — supporting services of a monolith/monorepo that agents
|
|
86
161
|
# depend on but do not modify. Started ONCE on fixed ports, shared by all slots.
|
|
87
162
|
# Create .har/ecosystem.shared.config.cjs (PM2 format, processes named
|
|
88
|
-
# "har-shared-<name>") only when the primary app needs
|
|
163
|
+
# "har-${HARNESS_PROJECT_NAME}-shared-<name>") only when the primary app needs
|
|
164
|
+
# sibling services running.
|
|
89
165
|
SHARED_ECOSYSTEM="$SCRIPT_DIR/ecosystem.shared.config.cjs"
|
|
90
166
|
if [ -f "$SHARED_ECOSYSTEM" ]; then
|
|
91
167
|
log "Starting shared app services from ecosystem.shared.config.cjs..."
|
|
92
168
|
(cd "$REPO_ROOT" && npx --yes pm2 startOrReload "$SHARED_ECOSYSTEM" >/dev/null)
|
|
93
|
-
log "Shared app services running (pm2 ls | grep har-shared-)."
|
|
169
|
+
log "Shared app services running (pm2 ls | grep har-${HARNESS_PROJECT_NAME}-shared-)."
|
|
94
170
|
fi
|
|
95
171
|
|
|
96
172
|
echo ""
|
|
97
173
|
log "Infrastructure is ready."
|
|
98
174
|
har_infra_enabled db && log " PostgreSQL: localhost:$DB_PORT"
|
|
99
|
-
har_infra_enabled minio && log " MinIO: http://localhost:${
|
|
100
|
-
har_infra_enabled headless-browser && log " Browser: http://localhost:${
|
|
101
|
-
har_infra_enabled mailpit && log " Mailpit: http://localhost:${
|
|
175
|
+
har_infra_enabled minio && log " MinIO: http://localhost:${MINIO_CONSOLE_PORT}"
|
|
176
|
+
har_infra_enabled headless-browser && log " Browser: http://localhost:${BROWSER_PORT}"
|
|
177
|
+
har_infra_enabled mailpit && log " Mailpit: http://localhost:${MAILPIT_WEB_PORT}"
|
|
102
178
|
exit 0
|
|
@@ -85,6 +85,32 @@ Edit **`harness.env`** to set:
|
|
|
85
85
|
- `HARNESS_SIMULATOR_NAME` — target simulator (must be listed in `xcrun simctl list devices`)
|
|
86
86
|
- `HARNESS_BUNDLE_ID` — app bundle identifier
|
|
87
87
|
|
|
88
|
+
## Port & shared services (iOS profile)
|
|
89
|
+
|
|
90
|
+
Pure iOS apps have **no per-slot TCP ports** — agents build and run on a shared iOS Simulator. Optional backend containers (mock API, etc.) use the same shared-infra model as other profiles.
|
|
91
|
+
|
|
92
|
+
### Port allocation
|
|
93
|
+
|
|
94
|
+
| Layer | Scope | Rule | On conflict |
|
|
95
|
+
|-------|-------|------|-------------|
|
|
96
|
+
| Optional backend (compose) | Per machine | `HARNESS_*_PORT_DEFAULT` for that service | Scan configured ranges in `harness.env` |
|
|
97
|
+
| iOS Simulator | Shared | No harness port — one booted simulator for all slots | N/A |
|
|
98
|
+
|
|
99
|
+
When your app talks to a local backend, read the resolved host port from `.env.agent.<id>` (set by `setup-infra.sh`) — never hardcode `15432` or similar in tests or flow scripts.
|
|
100
|
+
|
|
101
|
+
### Shared vs per-slot
|
|
102
|
+
|
|
103
|
+
| Resource | Model | Configuration |
|
|
104
|
+
|----------|-------|---------------|
|
|
105
|
+
| iOS Simulator | One booted simulator shared by all slots | `HARNESS_SIMULATOR_NAME`, `setup-infra.sh` |
|
|
106
|
+
| Optional backend | One shared compose service | `HARNESS_INFRA_SERVICES` (e.g. `"mock-server"`) |
|
|
107
|
+
| Application code | Isolated git worktree per slot | `HARNESS_USE_WORKTREE=true` |
|
|
108
|
+
|
|
109
|
+
### Do not
|
|
110
|
+
|
|
111
|
+
- Hardcode backend ports in RocketSim flows or unit tests — read from agent env
|
|
112
|
+
- Run raw `docker compose` for harness infrastructure — use `setup-infra.sh`
|
|
113
|
+
|
|
88
114
|
## Session lifecycle
|
|
89
115
|
|
|
90
116
|
Every `launch` starts a **fresh session**: a new git worktree from the current HEAD at
|
|
@@ -33,8 +33,9 @@ export HARNESS_IOS_DESTINATION="platform=iOS Simulator,name=${HARNESS_SIMULATOR_
|
|
|
33
33
|
export HARNESS_SWIFTLINT_CMD="${HARNESS_SWIFTLINT_CMD:-swiftlint}"
|
|
34
34
|
|
|
35
35
|
# ── Infrastructure ────────────────────────────────────────────────────────────
|
|
36
|
-
# No Docker infra for pure iOS apps. Set
|
|
36
|
+
# No Docker infra for pure iOS apps. Set service names here (space-separated)
|
|
37
37
|
# only if your app needs a local backend container (e.g. a mock server).
|
|
38
|
+
# When enabled, add matching HARNESS_*_PORT_DEFAULT / SCAN_* vars for each service.
|
|
38
39
|
export HARNESS_INFRA_SERVICES=""
|
|
39
40
|
|
|
40
41
|
# Returns 0 when a shared infra service is enabled: har_infra_enabled mock-server
|
package/package.json
CHANGED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Adapt this iOS harness to the project
|
|
2
|
-
|
|
3
|
-
You are adapting a freshly scaffolded iOS mobile app harness. Read the existing repo
|
|
4
|
-
structure, then make the changes listed below. Commit when done.
|
|
5
|
-
|
|
6
|
-
## 1 — Read before editing
|
|
7
|
-
|
|
8
|
-
- `AGENT.md` at the repo root (overview and do-nots)
|
|
9
|
-
- `.har/README.md` (harness index)
|
|
10
|
-
- `.har/harness.env` (all config vars)
|
|
11
|
-
- `.har/stages.json` (stage registry)
|
|
12
|
-
- Root of the repo: look for `*.xcworkspace`, `*.xcodeproj`, `Podfile`, `Package.swift`
|
|
13
|
-
|
|
14
|
-
## 2 — Set Xcode project config in `.har/harness.env`
|
|
15
|
-
|
|
16
|
-
| Variable | What to set |
|
|
17
|
-
|----------|-------------|
|
|
18
|
-
| `HARNESS_XCODE_WORKSPACE` | Relative path to `.xcworkspace` (e.g. `MyApp.xcworkspace`). Use when CocoaPods or a workspace is present. Leave empty otherwise. |
|
|
19
|
-
| `HARNESS_XCODE_PROJECT` | Relative path to `.xcodeproj` (e.g. `MyApp.xcodeproj`). Only set when no workspace. |
|
|
20
|
-
| `HARNESS_XCODE_SCHEME` | Name of the shared Xcode scheme (must be marked Shared in Xcode → Product → Scheme → Manage Schemes). |
|
|
21
|
-
| `HARNESS_SIMULATOR_NAME` | Display name exactly as shown in `xcrun simctl list devices` (e.g. `iPhone 16`). |
|
|
22
|
-
| `HARNESS_BUNDLE_ID` | App bundle identifier from the Xcode target (e.g. `com.example.myapp`). |
|
|
23
|
-
|
|
24
|
-
Run `./.har/setup-infra.sh` after editing to confirm the simulator boots.
|
|
25
|
-
|
|
26
|
-
## 3 — Verify `.har/verify.sh` builds and tests correctly
|
|
27
|
-
|
|
28
|
-
Run `./.har/launch.sh 1`, then `./.har/verify.sh 1`.
|
|
29
|
-
|
|
30
|
-
Common adaptations:
|
|
31
|
-
- If the project uses a custom test plan, add `-testPlan MyTests` to the `xcodebuild test` invocation.
|
|
32
|
-
- If SwiftLint is not used, remove or comment out the `lint` step.
|
|
33
|
-
- If there are UI tests that require a running app, move them to a RocketSim flow (`har env add-stage rocketsim`) rather than xcodebuild tests.
|
|
34
|
-
|
|
35
|
-
## 4 — Add the RocketSim stage template (recommended)
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
har env add-stage rocketsim
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Then adapt `flows/example-smoke.sh` to navigate to your app's main screen and verify it loads.
|
|
42
|
-
Read `.har/stages/ROCKETSIM.md` for the full authoring guide.
|
|
43
|
-
|
|
44
|
-
## 5 — Update `AGENT.md` (repo root)
|
|
45
|
-
|
|
46
|
-
Replace the TODO section with:
|
|
47
|
-
- Which Xcode scheme and simulator are used
|
|
48
|
-
- How to run unit tests manually
|
|
49
|
-
- How to add a new RocketSim user flow
|
|
50
|
-
|
|
51
|
-
## 6 — Verify everything passes
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
./.har/verify.sh 1 --full
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
All steps should return ✓. Commit the adapted harness in the session worktree.
|