@osfactory/har 0.64.2 → 1.0.0-rc.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.
Files changed (141) hide show
  1. package/dist/index.js +15675 -6536
  2. package/dist/prompts/system-authoring.md +155 -0
  3. package/dist/templates/adaptation-prompt-init.md +67 -43
  4. package/dist/templates/adaptation-prompt-maintain.md +38 -38
  5. package/dist/templates/agent-skills/har-maintain.md +2 -2
  6. package/dist/templates/agent-skills/setup-har.md +6 -4
  7. package/dist/templates/cursor-rule.mdc.template +3 -3
  8. package/dist/templates/har-boilerplate/docker-compose.agent.yml +1 -1
  9. package/dist/templates/har-boilerplate/harness.env +11 -155
  10. package/dist/templates/har-boilerplate/stages.json +51 -2
  11. package/dist/templates/har-boilerplate-cli/docker-compose.agent.yml +1 -1
  12. package/dist/templates/har-boilerplate-cli/harness.env +12 -138
  13. package/dist/templates/har-boilerplate-cli/stages.json +42 -2
  14. package/dist/templates/har-boilerplate-ios/harness.env +10 -126
  15. package/dist/templates/har-boilerplate-ios/stages.json +42 -2
  16. package/dist/templates/migration-prompt.md +54 -0
  17. package/dist/templates/plugins/custom-stage-skeleton.sh +11 -20
  18. package/dist/templates/plugins/gitleaks/.github/workflows/gitleaks.yml +1 -1
  19. package/dist/templates/plugins/gitleaks/.har/stages/GITLEAKS.md +1 -1
  20. package/dist/templates/plugins/gitleaks/.har/stages/secrets-scan.sh +8 -23
  21. package/dist/templates/plugins/gitleaks/README.md +1 -1
  22. package/dist/templates/plugins/gitleaks/template.manifest.json +20 -5
  23. package/dist/templates/plugins/kerno/.github/workflows/kerno.yml +1 -1
  24. package/dist/templates/plugins/kerno/.har/stages/backend-validation.sh +8 -23
  25. package/dist/templates/plugins/kerno/README.md +1 -1
  26. package/dist/templates/plugins/kerno/template.manifest.json +20 -9
  27. package/dist/templates/plugins/local-plugin-skeleton/README.md +46 -0
  28. package/dist/templates/plugins/playwright/.har/stages/browser-e2e.sh +8 -23
  29. package/dist/templates/plugins/playwright/template.manifest.json +36 -13
  30. package/dist/templates/plugins/rocketsim/.har/stages/rocketsim-flows.sh +8 -23
  31. package/dist/templates/plugins/rocketsim/template.manifest.json +20 -8
  32. package/dist/templates/plugins/semgrep/.har/stages/sast.sh +10 -26
  33. package/dist/templates/plugins/semgrep/README.md +1 -1
  34. package/dist/templates/plugins/semgrep/template.manifest.json +16 -7
  35. package/dist/templates/plugins/trivy/.har/stages/vuln-scan.sh +8 -23
  36. package/dist/templates/plugins/trivy/README.md +1 -1
  37. package/dist/templates/plugins/trivy/template.manifest.json +20 -8
  38. package/dist/templates/{har-boilerplate-cli/CLAUDE.agent.md → profiles/cli/docs/claude-agent/definition-of-done.md} +0 -42
  39. package/dist/templates/profiles/cli/docs/claude-agent/do-not.md +6 -0
  40. package/dist/templates/profiles/cli/docs/claude-agent/environment.md +12 -0
  41. package/dist/templates/profiles/cli/docs/claude-agent/project-commands.md +10 -0
  42. package/dist/templates/profiles/cli/docs/claude-agent/readiness.md +6 -0
  43. package/dist/templates/profiles/cli/docs/readme/for-coding-agents.md +9 -0
  44. package/dist/templates/profiles/cli/docs/readme/intro.md +7 -0
  45. package/dist/templates/profiles/cli/docs/readme/port-shared-services-cli-profile.md +25 -0
  46. package/dist/templates/profiles/cli/docs/readme/quick-start.md +24 -0
  47. package/dist/templates/profiles/cli/docs/readme/verification-contract.md +22 -0
  48. package/dist/templates/profiles/cli/docs/readme/what-s-in-here.md +27 -0
  49. package/dist/templates/profiles/cli/profile.manifest.json +56 -1
  50. package/dist/templates/profiles/default/docs/claude-agent/definition-of-done.md +24 -0
  51. package/dist/templates/profiles/default/docs/claude-agent/do-not.md +10 -0
  52. package/dist/templates/profiles/default/docs/claude-agent/environment.md +19 -0
  53. package/dist/templates/profiles/default/docs/claude-agent/project-commands.md +10 -0
  54. package/dist/templates/profiles/default/docs/claude-agent/readiness.md +12 -0
  55. package/dist/templates/profiles/default/docs/readme/architecture.md +11 -0
  56. package/dist/templates/profiles/default/docs/readme/for-coding-agents.md +9 -0
  57. package/dist/templates/profiles/default/docs/readme/intro.md +7 -0
  58. package/dist/templates/profiles/default/docs/readme/port-shared-services.md +41 -0
  59. package/dist/templates/profiles/default/docs/readme/quick-start.md +24 -0
  60. package/dist/templates/profiles/default/docs/readme/readiness-layers.md +16 -0
  61. package/dist/templates/profiles/default/docs/readme/verification-contract.md +17 -0
  62. package/dist/templates/profiles/default/docs/readme/what-s-in-here.md +28 -0
  63. package/dist/templates/profiles/default/profile.manifest.json +62 -1
  64. package/dist/templates/profiles/ios/docs/claude-agent/definition-of-done.md +23 -0
  65. package/dist/templates/profiles/ios/docs/claude-agent/do-not.md +6 -0
  66. package/dist/templates/profiles/ios/docs/claude-agent/environment.md +14 -0
  67. package/dist/templates/profiles/ios/docs/claude-agent/intro.md +3 -0
  68. package/dist/templates/profiles/ios/docs/claude-agent/project-commands.md +21 -0
  69. package/dist/templates/profiles/ios/docs/claude-agent/readiness.md +6 -0
  70. package/dist/templates/profiles/ios/docs/claude-agent/user-flow-validation-rocketsim.md +11 -0
  71. package/dist/templates/profiles/ios/docs/readme/configuration.md +7 -0
  72. package/dist/templates/profiles/ios/docs/readme/intro.md +7 -0
  73. package/dist/templates/profiles/ios/docs/readme/port-shared-services-ios-profile.md +25 -0
  74. package/dist/templates/profiles/ios/docs/readme/quick-start.md +22 -0
  75. package/dist/templates/profiles/ios/docs/readme/simulators.md +45 -0
  76. package/dist/templates/profiles/ios/docs/readme/user-flow-validation.md +9 -0
  77. package/dist/templates/profiles/ios/docs/readme/verification-contract.md +13 -0
  78. package/dist/templates/profiles/ios/docs/readme/what-s-in-here.md +27 -0
  79. package/dist/templates/profiles/ios/profile.manifest.json +59 -3
  80. package/dist/templates/runtime-bundles/pm2-runtime/attach.sh +8 -15
  81. package/dist/templates/runtime-bundles/pm2-runtime/env.template +1 -1
  82. package/dist/templates/runtime-bundles/pm2-runtime/stages/api-health.sh +9 -0
  83. package/dist/templates/runtime-bundles/shared-kernel/STAGES.md +32 -18
  84. package/dist/templates/runtime-bundles/shared-kernel/agent-cli.sh +35 -0
  85. package/dist/templates/runtime-bundles/shared-kernel/launch.sh +35 -0
  86. package/dist/templates/runtime-bundles/shared-kernel/lib/verify-runner.mjs +129 -0
  87. package/dist/templates/runtime-bundles/shared-kernel/preflight.sh +35 -0
  88. package/dist/templates/runtime-bundles/shared-kernel/setup-infra.sh +35 -0
  89. package/dist/templates/runtime-bundles/shared-kernel/stages/README.sh +1 -1
  90. package/dist/templates/runtime-bundles/shared-kernel/stages/readiness.sh +14 -0
  91. package/dist/templates/runtime-bundles/shared-kernel/teardown.sh +35 -0
  92. package/dist/templates/runtime-bundles/shared-kernel/verify.sh +35 -0
  93. package/dist/templates/shared-docs/claude-agent/intro.md +3 -0
  94. package/dist/templates/shared-docs/readme/maintaining-this-harness.md +14 -0
  95. package/dist/templates/shared-docs/readme/run-history.md +5 -0
  96. package/dist/templates/shared-docs/readme/session-lifecycle.md +20 -0
  97. package/package.json +1 -1
  98. package/dist/templates/har-boilerplate/CLAUDE.agent.md +0 -83
  99. package/dist/templates/har-boilerplate/README.md +0 -199
  100. package/dist/templates/har-boilerplate/STAGES.md +0 -99
  101. package/dist/templates/har-boilerplate/agent-cli.sh +0 -225
  102. package/dist/templates/har-boilerplate/agent-slot.sh +0 -850
  103. package/dist/templates/har-boilerplate/attach.sh +0 -22
  104. package/dist/templates/har-boilerplate/ecosystem.agent.template.cjs +0 -52
  105. package/dist/templates/har-boilerplate/env.template +0 -40
  106. package/dist/templates/har-boilerplate/launch.sh +0 -323
  107. package/dist/templates/har-boilerplate/preflight.sh +0 -32
  108. package/dist/templates/har-boilerplate/provision-toolchain.sh +0 -766
  109. package/dist/templates/har-boilerplate/setup-infra.sh +0 -178
  110. package/dist/templates/har-boilerplate/stages/README.sh +0 -11
  111. package/dist/templates/har-boilerplate/teardown.sh +0 -87
  112. package/dist/templates/har-boilerplate/verify.sh +0 -249
  113. package/dist/templates/har-boilerplate-cli/README.md +0 -157
  114. package/dist/templates/har-boilerplate-cli/STAGES.md +0 -99
  115. package/dist/templates/har-boilerplate-cli/agent-cli.sh +0 -160
  116. package/dist/templates/har-boilerplate-cli/agent-slot.sh +0 -832
  117. package/dist/templates/har-boilerplate-cli/launch.sh +0 -216
  118. package/dist/templates/har-boilerplate-cli/preflight.sh +0 -28
  119. package/dist/templates/har-boilerplate-cli/provision-toolchain.sh +0 -766
  120. package/dist/templates/har-boilerplate-cli/setup-infra.sh +0 -178
  121. package/dist/templates/har-boilerplate-cli/stages/README.sh +0 -11
  122. package/dist/templates/har-boilerplate-cli/teardown.sh +0 -66
  123. package/dist/templates/har-boilerplate-cli/verify.sh +0 -210
  124. package/dist/templates/har-boilerplate-ios/ADAPT-PROMPT.md +0 -63
  125. package/dist/templates/har-boilerplate-ios/CLAUDE.agent.md +0 -90
  126. package/dist/templates/har-boilerplate-ios/README.md +0 -173
  127. package/dist/templates/har-boilerplate-ios/STAGES.md +0 -99
  128. package/dist/templates/har-boilerplate-ios/agent-cli.sh +0 -149
  129. package/dist/templates/har-boilerplate-ios/agent-slot.sh +0 -479
  130. package/dist/templates/har-boilerplate-ios/launch.sh +0 -206
  131. package/dist/templates/har-boilerplate-ios/provision-toolchain.sh +0 -766
  132. package/dist/templates/har-boilerplate-ios/setup-infra.sh +0 -112
  133. package/dist/templates/har-boilerplate-ios/simulator.sh +0 -492
  134. package/dist/templates/har-boilerplate-ios/stages/README.sh +0 -11
  135. package/dist/templates/har-boilerplate-ios/teardown.sh +0 -68
  136. package/dist/templates/har-boilerplate-ios/verify.sh +0 -185
  137. package/dist/templates/runtime-bundles/pm2-runtime/README.md +0 -4
  138. package/dist/templates/runtime-bundles/shared-kernel/README.md +0 -3
  139. package/dist/templates/runtime-bundles/shared-kernel/provision-toolchain.sh +0 -766
  140. package/dist/templates/runtime-bundles/xcode-sim/README.md +0 -4
  141. package/dist/templates/runtime-bundles/xcode-sim/simulator.sh +0 -492
@@ -1,178 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Sets up shared infrastructure for all agents.
3
- # Starts the docker compose services listed in HARNESS_INFRA_SERVICES, creates
4
- # the template database (when "db" is enabled), and starts optional shared app
5
- # services (ecosystem.shared.config.cjs). One instance serves every agent slot.
6
- # Idempotent — safe to run multiple times.
7
- #
8
- # Usage: ./.har/setup-infra.sh
9
- set -euo pipefail
10
-
11
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
- REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
13
- COMPOSE_FILE="$SCRIPT_DIR/docker-compose.agent.yml"
14
- INFRA_STATE="$SCRIPT_DIR/state/infra.env"
15
-
16
- # shellcheck source=/dev/null
17
- source "$SCRIPT_DIR/harness.env"
18
- # shellcheck source=/dev/null
19
- source "$SCRIPT_DIR/agent-slot.sh"
20
-
21
- COMPOSE_PROJECT="har-${HARNESS_PROJECT_NAME}"
22
- PSQL="har_pg psql -d postgres"
23
-
24
- log() { echo "==> $*" >&2; }
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
-
99
- SERVICES="${HARNESS_INFRA_SERVICES:-}"
100
-
101
- if [ -n "$SERVICES" ]; then
102
- log "Starting shared infrastructure (project: $COMPOSE_PROJECT): $SERVICES"
103
- AGENT_DB_PORT="$DB_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" \
109
- docker compose -p "$COMPOSE_PROJECT" -f "$COMPOSE_FILE" up -d $SERVICES
110
- else
111
- log "No shared infra services enabled in harness.env (HARNESS_INFRA_SERVICES)"
112
- fi
113
-
114
- # Wait for PostgreSQL and prepare the template database
115
- if har_infra_enabled db; then
116
- log "Waiting for PostgreSQL on port $DB_PORT..."
117
- for i in $(seq 1 30); do
118
- if har_pg pg_isready -q 2>/dev/null; then
119
- log "PostgreSQL is ready."
120
- break
121
- fi
122
- if [ "$i" = "30" ]; then
123
- echo "Error: PostgreSQL did not become ready within 30 seconds." >&2
124
- exit 1
125
- fi
126
- sleep 1
127
- done
128
-
129
- log "Enabling pg_stat_statements extension..."
130
- $PSQL -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements" 2>/dev/null || true
131
-
132
- if [ -n "${HARNESS_TEMPLATE_DB:-}" ]; then
133
- if $PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = '$HARNESS_TEMPLATE_DB'" | grep -q 1; then
134
- log "Template database '$HARNESS_TEMPLATE_DB' already exists. Skipping creation."
135
- else
136
- log "Creating template database '$HARNESS_TEMPLATE_DB'..."
137
- $PSQL -c "CREATE DATABASE $HARNESS_TEMPLATE_DB"
138
-
139
- if [ -n "${HARNESS_DB_MIGRATE_CMD:-}" ] && [ "$HARNESS_DB_MIGRATE_CMD" != "echo 'TODO: set migrate command'" ]; then
140
- log "Running migrations..."
141
- PGPASSWORD=password PGHOST=localhost PGPORT="$DB_PORT" PGUSER=postgres \
142
- PGDATABASE="$HARNESS_TEMPLATE_DB" \
143
- bash -c "cd '$REPO_ROOT' && $HARNESS_DB_MIGRATE_CMD"
144
- fi
145
-
146
- if [ -n "${HARNESS_DB_SEED_CMD:-}" ] && [ "$HARNESS_DB_SEED_CMD" != "echo 'TODO: set seed command'" ]; then
147
- log "Running seeds..."
148
- PGPASSWORD=password PGHOST=localhost PGPORT="$DB_PORT" PGUSER=postgres \
149
- PGDATABASE="$HARNESS_TEMPLATE_DB" \
150
- bash -c "cd '$REPO_ROOT' && $HARNESS_DB_SEED_CMD"
151
- fi
152
-
153
- log "Marking '$HARNESS_TEMPLATE_DB' as a PostgreSQL template..."
154
- $PSQL -c "UPDATE pg_database SET datistemplate = true WHERE datname = '$HARNESS_TEMPLATE_DB'"
155
- log "Template database ready: $HARNESS_TEMPLATE_DB"
156
- fi
157
- fi
158
- fi
159
-
160
- # Shared app services — supporting services of a monolith/monorepo that agents
161
- # depend on but do not modify. Started ONCE on fixed ports, shared by all slots.
162
- # Create .har/ecosystem.shared.config.cjs (PM2 format, processes named
163
- # "har-${HARNESS_PROJECT_NAME}-shared-<name>") only when the primary app needs
164
- # sibling services running.
165
- SHARED_ECOSYSTEM="$SCRIPT_DIR/ecosystem.shared.config.cjs"
166
- if [ -f "$SHARED_ECOSYSTEM" ]; then
167
- log "Starting shared app services from ecosystem.shared.config.cjs..."
168
- (cd "$REPO_ROOT" && $(har_pkg_exec) pm2 startOrReload "$SHARED_ECOSYSTEM" >/dev/null)
169
- log "Shared app services running (pm2 ls | grep har-${HARNESS_PROJECT_NAME}-shared-)."
170
- fi
171
-
172
- echo ""
173
- log "Infrastructure is ready."
174
- har_infra_enabled db && log " PostgreSQL: localhost:$DB_PORT"
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}"
178
- exit 0
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Per-stage scripts live here (e.g. ./.har/stages/browser-e2e.sh <agent-id>).
3
- #
4
- # Read .har/STAGES.md for the authoring guide: the stage script contract,
5
- # command vs script stages, and how verificationStages controls verify --full.
6
- #
7
- # Scaffold a new one with:
8
- # har env add-stage <id> --custom --script
9
-
10
- echo "Add stage scripts under .har/stages/ and register them in stages.json — see .har/STAGES.md." >&2
11
- exit 1
@@ -1,87 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Safely tears down one agent: stops PM2, drops DB, removes bucket, cleans up files.
3
- # The session's git branch is KEPT by default so you can push it / open a PR —
4
- # pass --delete-branch to remove it too.
5
- #
6
- # Usage: ./.har/teardown.sh <agent-id> [--delete-branch]
7
- set -euo pipefail
8
-
9
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
- REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
11
-
12
- # shellcheck source=/dev/null
13
- source "$SCRIPT_DIR/harness.env"
14
- # shellcheck source=/dev/null
15
- source "$SCRIPT_DIR/agent-slot.sh"
16
-
17
- AGENT_ID="${1:?Usage: teardown.sh <agent-id> [--delete-branch]}"
18
- DELETE_BRANCH=false
19
-
20
- for arg in "${@:2}"; do
21
- case "$arg" in
22
- --delete-branch) DELETE_BRANCH=true ;;
23
- esac
24
- done
25
-
26
- validate_agent_id "$AGENT_ID"
27
-
28
- echo "==> Tearing down agent ${AGENT_ID}..."
29
-
30
- # Resolve the session from the registry; fall back to the legacy fixed path so
31
- # pre-registry sessions stay removable.
32
- REGISTRY_FILE="$(slot_registry_file "$AGENT_ID")"
33
- WORKTREE_PATH=""
34
- WORK_DIR=""
35
- BRANCH=""
36
- if [ -f "$REGISTRY_FILE" ]; then
37
- WORKTREE_PATH="$(read_slot_field "$REGISTRY_FILE" worktreePath || true)"
38
- WORK_DIR="$(read_slot_field "$REGISTRY_FILE" workDir || true)"
39
- BRANCH="$(read_slot_field "$REGISTRY_FILE" branch || true)"
40
- fi
41
- [ -n "$WORKTREE_PATH" ] || WORKTREE_PATH="$HOME/worktrees/${HARNESS_PROJECT_NAME}-agent-${AGENT_ID}"
42
-
43
- PM2_REGEX="$(har_pm2_delete_regex "$AGENT_ID")"
44
- $(har_pkg_exec) pm2 delete "$PM2_REGEX" 2>/dev/null || true
45
- echo "✓ Stopped PM2 processes"
46
-
47
- if har_infra_enabled db; then
48
- har_pg psql -d postgres -c \
49
- "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='agent_${AGENT_ID}';" \
50
- >/dev/null 2>&1 || true
51
- har_pg dropdb --if-exists "agent_${AGENT_ID}" 2>/dev/null || true
52
- echo "✓ Dropped database: agent_${AGENT_ID}"
53
- fi
54
-
55
- if har_infra_enabled minio; then
56
- curl -sf -X DELETE "http://minioadmin:minioadmin@localhost:19000/agent-${AGENT_ID}?force=true" \
57
- >/dev/null 2>&1 || true
58
- echo "✓ Removed MinIO bucket: agent-${AGENT_ID}"
59
- fi
60
-
61
- rm -f "$REPO_ROOT/.env.agent.${AGENT_ID}"
62
- rm -f "$REPO_ROOT/ecosystem.agent.${AGENT_ID}.config.cjs"
63
- if [ -n "$WORK_DIR" ] && [ -d "$WORK_DIR" ]; then
64
- rm -f "$WORK_DIR/.env.agent.${AGENT_ID}"
65
- rm -f "$WORK_DIR/ecosystem.agent.${AGENT_ID}.config.cjs"
66
- fi
67
-
68
- if [ -d "$WORKTREE_PATH" ]; then
69
- rm -f "$WORKTREE_PATH/.env.agent.${AGENT_ID}"
70
- rm -f "$WORKTREE_PATH/ecosystem.agent.${AGENT_ID}.config.cjs"
71
- git -C "$REPO_ROOT" worktree remove "$WORKTREE_PATH" --force 2>/dev/null || rm -rf "$WORKTREE_PATH"
72
- echo "✓ Removed worktree: $WORKTREE_PATH"
73
- fi
74
- git -C "$REPO_ROOT" worktree prune 2>/dev/null || true
75
-
76
- if [ -n "$BRANCH" ]; then
77
- if [ "$DELETE_BRANCH" = true ]; then
78
- git -C "$REPO_ROOT" branch -D "$BRANCH" 2>/dev/null || true
79
- echo "✓ Deleted branch: $BRANCH"
80
- else
81
- echo "✓ Kept branch: $BRANCH (push it or delete with: git branch -D $BRANCH)"
82
- fi
83
- fi
84
-
85
- remove_slot_registry "$AGENT_ID"
86
-
87
- echo "✓ Agent ${AGENT_ID} torn down"
@@ -1,249 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Progressive verification pipeline for an agent environment.
3
- # Outputs JSON to stdout (machine contract), human-readable progress to stderr.
4
- # Passing steps omit `output`. `har env verify` streams progress only.
5
- #
6
- # Usage: ./.har/verify.sh <agent-id> [--full]
7
- #
8
- # Quick (default): ecosystem smoke + health only
9
- # Full (--full): + conventional tests, lint, readiness, and every registered
10
- # stage in stages.json verificationStages (see .har/STAGES.md)
11
- # Stock steps are examples. Replace them during adaptation to match this repo.
12
- set -euo pipefail
13
-
14
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
- REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
16
-
17
- # shellcheck source=/dev/null
18
- source "$SCRIPT_DIR/harness.env"
19
- # shellcheck source=/dev/null
20
- source "$SCRIPT_DIR/agent-slot.sh"
21
-
22
- AGENT_ID="${1:?Usage: verify.sh <agent-id> [--full]}"
23
- FULL=""
24
-
25
- for arg in "${@:2}"; do
26
- [ "$arg" = "--full" ] && FULL=1
27
- done
28
-
29
- validate_agent_id "$AGENT_ID"
30
-
31
- API_PORT=$(( HARNESS_API_BASE_PORT + AGENT_ID * 10 ))
32
-
33
- ENV_FILE="$(resolve_agent_env_file "$AGENT_ID" "$REPO_ROOT")" || {
34
- echo "No .env.agent.${AGENT_ID} found." >&2
35
- har_suggest_launch "$AGENT_ID" >&2
36
- exit 1
37
- }
38
-
39
- set -a
40
- # shellcheck source=/dev/null
41
- source "$ENV_FILE"
42
- set +a
43
-
44
- WORK_DIR="$(resolve_agent_work_dir "$ENV_FILE")"
45
- API_PORT="${API_PORT:-$(( HARNESS_API_BASE_PORT + AGENT_ID * 10 ))}"
46
-
47
- echo "==> Verifying agent ${AGENT_ID} (work dir: ${WORK_DIR})..." >&2
48
- REG_FILE="$(slot_registry_file "$AGENT_ID")"
49
- echo " Work dir: ${WORK_DIR}" >&2
50
- echo " Env file: ${ENV_FILE}" >&2
51
- if [ -f "$REG_FILE" ]; then
52
- echo " Registry: ${REG_FILE}" >&2
53
- else
54
- echo " Registry: missing (${REG_FILE})" >&2
55
- fi
56
-
57
- OVERALL_PASS=true
58
- START_TOTAL=$(now_ms)
59
- RESULTS_JSON="[]"
60
-
61
- run_step() {
62
- local name="$1"
63
- local cmd="$2"
64
- local start end elapsed exit_code output
65
-
66
- printf " → %-40s" "$name..." >&2
67
- start=$(now_ms)
68
-
69
- set +e
70
- output=$(cd "$WORK_DIR" && set -a && . "$ENV_FILE" && set +a && eval "$cmd" 2>&1)
71
- exit_code=$?
72
- set -e
73
-
74
- end=$(now_ms)
75
- elapsed=$(( end - start ))
76
-
77
- local pass_bool
78
- if [ "$exit_code" = "0" ]; then
79
- echo "✓ (${elapsed}ms)" >&2
80
- pass_bool="true"
81
- else
82
- echo "✗ (${elapsed}ms)" >&2
83
- echo "$output" | head -30 | sed 's/^/ /' >&2
84
- pass_bool="false"
85
- OVERALL_PASS=false
86
- fi
87
-
88
- record_step_result "$name" "$pass_bool" "$elapsed" "$output"
89
-
90
- if [ "$pass_bool" = "false" ] && [ -z "$FULL" ]; then
91
- return 1
92
- fi
93
- }
94
-
95
- run_http_step() {
96
- local name="$1"
97
- local url="$2"
98
- local start end elapsed exit_code output
99
-
100
- printf " → %-40s" "$name..." >&2
101
- start=$(now_ms)
102
-
103
- set +e
104
- output=$(curl -sf "$url" 2>&1)
105
- exit_code=$?
106
- set -e
107
-
108
- end=$(now_ms)
109
- elapsed=$(( end - start ))
110
-
111
- local pass_bool
112
- if [ "$exit_code" = "0" ]; then
113
- echo "✓ (${elapsed}ms)" >&2
114
- pass_bool="true"
115
- else
116
- echo "✗ (${elapsed}ms)" >&2
117
- pass_bool="false"
118
- OVERALL_PASS=false
119
- fi
120
-
121
- record_step_result "$name" "$pass_bool" "$elapsed" "$output"
122
-
123
- if [ "$pass_bool" = "false" ] && [ -z "$FULL" ]; then
124
- return 1
125
- fi
126
- }
127
-
128
- node_package_script_exists() {
129
- local script="$1"
130
- "${NODE_BIN:-node}" -e "
131
- const fs = require('fs');
132
- const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
133
- const script = process.argv[1];
134
- process.exit(pkg.scripts && pkg.scripts[script] ? 0 : 1);
135
- " "$script"
136
- }
137
-
138
- run_node_script_or_skip() {
139
- local name="$1"
140
- local script="$2"
141
- if node_package_script_exists "$script"; then
142
- run_step "$name" "${NPM_BIN:-npm} run ${script}"
143
- else
144
- run_step "$name" "echo 'No ${script} script configured; skipping.'"
145
- fi
146
- }
147
-
148
- run_node_quick_smoke() {
149
- if node_package_script_exists typecheck; then
150
- run_step "node-typecheck" '${NPM_BIN:-npm} run typecheck'
151
- elif node_package_script_exists build; then
152
- run_step "node-build" '${NPM_BIN:-npm} run build'
153
- else
154
- run_step "node-package-load" '${NODE_BIN:-node} -e "require(\"./package.json\")"'
155
- fi
156
- }
157
-
158
- run_quick_smoke() {
159
- case "${HARNESS_ECOSYSTEM:-none}" in
160
- node)
161
- run_node_quick_smoke
162
- ;;
163
- python)
164
- run_step "python-compile" '${PYTHON_BIN:-python3} -m compileall -q .'
165
- ;;
166
- go)
167
- run_step "go-build" '${GO_BIN:-go} build ./...'
168
- ;;
169
- rust)
170
- run_step "rust-check" '${CARGO_BIN:-cargo} check'
171
- ;;
172
- java)
173
- run_step "java-compile" 'if [ -x ./mvnw ]; then ./mvnw -q -DskipTests compile; elif command -v mvn >/dev/null 2>&1; then mvn -q -DskipTests compile; elif [ -x ./gradlew ]; then ./gradlew classes; elif command -v gradle >/dev/null 2>&1; then gradle classes; else echo "No Maven/Gradle command found; adapt verify.sh for this Java repo."; fi'
174
- ;;
175
- ruby)
176
- run_step "ruby-smoke" '${RUBY_BIN:-ruby} -e "puts RUBY_VERSION"'
177
- ;;
178
- custom|none|*)
179
- run_step "smoke-not-configured" 'echo "No stock smoke for HARNESS_ECOSYSTEM=${HARNESS_ECOSYSTEM:-none}; adapt .har/verify.sh for this repo."'
180
- ;;
181
- esac
182
- }
183
-
184
- run_full_checks() {
185
- case "${HARNESS_ECOSYSTEM:-none}" in
186
- node)
187
- run_node_script_or_skip "unit-tests" test || true
188
- run_node_script_or_skip "lint" lint || true
189
- ;;
190
- python)
191
- run_step "unit-tests" 'if ${PYTHON_BIN:-python3} -c "import pytest" >/dev/null 2>&1; then ${PYTHON_BIN:-python3} -m pytest -q; else echo "pytest not installed; adapt verify.sh for this Python repo."; fi' || true
192
- ;;
193
- go)
194
- run_step "unit-tests" '${GO_BIN:-go} test ./...' || true
195
- ;;
196
- rust)
197
- run_step "unit-tests" '${CARGO_BIN:-cargo} test' || true
198
- ;;
199
- java)
200
- run_step "unit-tests" 'if [ -x ./mvnw ]; then ./mvnw -q test; elif command -v mvn >/dev/null 2>&1; then mvn -q test; elif [ -x ./gradlew ]; then ./gradlew test; elif command -v gradle >/dev/null 2>&1; then gradle test; else echo "No Maven/Gradle command found; adapt verify.sh for this Java repo."; fi' || true
201
- ;;
202
- ruby)
203
- run_step "unit-tests" 'if command -v "${BUNDLE_BIN:-bundle}" >/dev/null 2>&1 && [ -f Gemfile ]; then "${BUNDLE_BIN:-bundle}" exec rake test 2>/dev/null || "${BUNDLE_BIN:-bundle}" exec rspec; else echo "No Ruby test command detected; adapt verify.sh for this Ruby repo."; fi' || true
204
- ;;
205
- custom|none|*)
206
- run_step "unit-tests" 'echo "No stock full checks for HARNESS_ECOSYSTEM=${HARNESS_ECOSYSTEM:-none}; adapt .har/verify.sh for this repo."' || true
207
- ;;
208
- esac
209
- }
210
-
211
- # ── Verification stages ─────────────────────────────────────────────────────
212
- # These stock steps are intentionally generic conventions. Adapt this section
213
- # to the repository's real commands from package.json, Makefile, CI, pyproject,
214
- # Cargo.toml, go.mod, pom.xml, etc.
215
- run_quick_smoke || { [ -z "$FULL" ] && true; }
216
- run_http_step "api-health" "http://localhost:${API_PORT}${HARNESS_HEALTH_CHECK_PATH}" || { [ -z "$FULL" ] && true; }
217
-
218
- if [ -n "$FULL" ]; then
219
- run_full_checks
220
- run_step "readiness" "run_readiness_if_configured \"$AGENT_ID\"" || true
221
- # Registered verification stages from .har/stages.json (see .har/STAGES.md).
222
- # Every stage listed in verificationStages with a registered script/command
223
- # runs here -- plugins and custom stages alike.
224
- while IFS=$'\t' read -r STAGE_ID STAGE_CMD; do
225
- [ -n "$STAGE_ID" ] || continue
226
- run_step "$STAGE_ID" "$STAGE_CMD" || true
227
- done < <(list_registered_verification_stage_commands "$SCRIPT_DIR" "$AGENT_ID")
228
- fi
229
-
230
- # ── Output results ────────────────────────────────────────────────────────────
231
-
232
- END_TOTAL=$(now_ms)
233
- TOTAL_MS=$(( END_TOTAL - START_TOTAL ))
234
-
235
- node -e "
236
- const results = $RESULTS_JSON;
237
- const overall = results.length > 0 && results.every(r => r.pass);
238
- const out = {
239
- status: overall ? 'pass' : 'fail',
240
- agent_id: $AGENT_ID,
241
- total_ms: $TOTAL_MS,
242
- stages: results,
243
- };
244
- process.stdout.write(JSON.stringify(out, null, 2) + '\n');
245
- " 2>/dev/null || echo "{\"status\":\"fail\",\"agent_id\":${AGENT_ID},\"stages\":[]}"
246
-
247
- if [ "$OVERALL_PASS" = "false" ]; then
248
- exit 1
249
- fi
@@ -1,157 +0,0 @@
1
- # .har — Agent Harness (CLI / library profile)
2
-
3
- This directory is the **agent harness** for this repository. It lets AI coding agents run the project in isolated git worktrees with optional Docker-backed shared infra.
4
-
5
- Generated and maintained by [`har`](https://github.com/os-factory/har). Run `har env maintain` when the repo stack changes.
6
-
7
- **The harness is how you run this project.** Launch a slot to exercise the code in isolation; don't hand-roll setup. If a harness command fails, fix the harness or report it — don't silently fall back to ad-hoc commands.
8
-
9
- ## What's in here
10
-
11
- | File | Purpose |
12
- |------|---------|
13
- | `README.md` | This file — index of the harness |
14
- | `manifest.json` | Generator metadata (version, profile, checksums) — do not edit |
15
- | `harness.env` | Shared config: worktree default, `HARNESS_INFRA_SERVICES`, toolchain provisioning (`HARNESS_ECOSYSTEM`, `HARNESS_INSTALL_CMD`), migrate/seed commands |
16
- | `stages.json` | Machine-readable registry of runnable harness stages |
17
- | `stages/` | Optional custom stage scripts registered from `stages.json` |
18
- | `runs/` | Run history from `har env` / MCP only — `.har/runs/YYYY-MM-DD/HH-mm-ss_<stageId>_agent-<id>.json` (gitignore) |
19
- | `artifacts/` | Stage outputs: reports, traces, screenshots, logs |
20
- | `agent-slot.sh` | Shared agent-id validation (reads limits from `harness.env`) |
21
- | `setup-infra.sh` | Start optional Docker Compose stack + template database |
22
- | `launch.sh` | Launch one agent slot (git worktree by default, toolchain provisioning, env file) |
23
- | `provision-toolchain.sh` | Install deps and write toolchain paths (`PYTHON_BIN`, `NPM_BIN`, …) to `.env.agent.<id>` |
24
- | `verify.sh` | Verification pipeline (smoke by default; --full adds tests, lint, e2e) |
25
- | `teardown.sh` | Tear down one agent slot (worktree + env file) |
26
- | `agent-cli.sh` | Inspect slot status, run commands in the work dir |
27
- | `docker-compose.agent.yml` | Shared infrastructure containers (services listed in `HARNESS_INFRA_SERVICES`) |
28
- | `CLAUDE.agent.md` | Detailed instructions for coding agents |
29
- | `justfile` | Optional shortcuts (requires `just`) |
30
-
31
- No PM2 or `ecosystem.agent.template.cjs` in this profile — agents run project commands directly in their worktree.
32
-
33
- ## Quick start
34
-
35
- **Preferred — har CLI or MCP** (persists run history under `.har/runs/`):
36
-
37
- ```bash
38
- har env launch 1
39
- har env verify 1
40
- har env verify 1 --full
41
- har env teardown 1
42
- ```
43
-
44
- In Cursor with HAR MCP configured: use `har_launch_environment`, `har_run_verification`, and `har_teardown_environment`.
45
-
46
- **Shell fallback** (no CLI/MCP installed):
47
-
48
- ```bash
49
- ./.har/setup-infra.sh # when HARNESS_INFRA_SERVICES is non-empty
50
- ./.har/launch.sh 1
51
- ./.har/verify.sh 1 # quick: ecosystem smoke (compile/import/build)
52
- ./.har/verify.sh 1 --full # + conventional tests, lint, browser-e2e (if installed)
53
- ./.har/teardown.sh 1
54
- ```
55
-
56
- Read **`stages.json`** and **`verificationStages`**. Optional: `har env add-plugin playwright`.
57
-
58
- ## Verification contract
59
-
60
- Steps in `verify.sh` are **project-specific examples** — adapt them to your stack
61
- during `har env init` / `har env maintain` / benchmark setup. The table describes
62
- each tier's intent, not a fixed command list.
63
-
64
- | Mode | Command | Typical steps |
65
- |------|---------|---------------|
66
- | Quick | `har env verify <id>` or `verify.sh <id>` | Stock ecosystem smoke: compile / import / build conventions |
67
- | Full | `har env verify <id> --full` or `verify.sh <id> --full` | Stock conventional tests/lint + optional readiness smoke, **browser-e2e** when `stages/browser-e2e.sh` exists |
68
-
69
- The stock commands are deliberately generic conventions keyed by
70
- `HARNESS_ECOSYSTEM`. Replace them with the repository's real commands during
71
- adaptation; do not leave Node/npm, Python, Go, Rust, Java, or Ruby defaults in
72
- place when they do not match the project.
73
-
74
- For repos that need runtime services, distinguish health from usability. If the
75
- harness skips slow local-dev setup, document the skipped steps and add a minimal
76
- bootstrap/readiness check when agents need default data, credentials, or an
77
- authenticated workflow.
78
-
79
- Use `har env launch 1 --no-worktree` or `./.har/launch.sh 1 --no-worktree` only when working in the repo root.
80
-
81
- ## Run history
82
-
83
- | Entry point | Writes `.har/runs/`? |
84
- |-------------|------------------------|
85
- | `./.har/*.sh` | No |
86
- | `har env …` / MCP | Yes — main checkout `.har/runs/YYYY-MM-DD/` |
87
-
88
- With worktree slots, tests run in the worktree; run JSON lives in the main repo. See `workDir` in each record.
89
-
90
- ## For coding agents
91
-
92
- **Start here:** read [`AGENTS.md`](../AGENTS.md) at the repo root for a short pointer, then [`.har/CLAUDE.agent.md`](./CLAUDE.agent.md) for full instructions.
93
-
94
- Prefer HAR MCP tools or `har env …` for launch, verify, and teardown. Use `./.har/*.sh` only when the CLI is not installed.
95
-
96
- Work in the isolated git worktree created by launch. Use `./.har/agent-cli.sh <id> exec ...` to run ad-hoc project commands in that work dir.
97
-
98
- When the project needs Postgres, Redis, or similar, add the service to `docker-compose.agent.yml` (or keep one from the menu), list it in `HARNESS_INFRA_SERVICES` in `harness.env`, and use `setup-infra.sh` — never run raw `docker compose` for shared infra. Shared services run once on fixed ports and serve every agent slot.
99
-
100
- ## Port & shared services (CLI profile)
101
-
102
- This profile has **no PM2 app ports** — agents run project commands directly in their worktree. Port variables in `harness.env` exist for optional test servers and for shared Docker infra.
103
-
104
- ### Port allocation
105
-
106
- | Layer | Scope | Rule | On conflict |
107
- |-------|-------|------|-------------|
108
- | Shared Postgres | Per machine | `HARNESS_DB_PORT_DEFAULT` | Scan `HARNESS_DB_PORT_SCAN_START..END` |
109
- | Other compose services | Per machine | `HARNESS_*_PORT_DEFAULT` for that service | Scan configured ranges in `harness.env` |
110
-
111
- When a repo adds a local HTTP server for integration tests, prefer reading ports from `.env.agent.<id>` or `./.har/agent-cli.sh <id>` rather than hardcoding values.
112
-
113
- ### Shared vs per-slot
114
-
115
- | Resource | Model | Configuration |
116
- |----------|-------|---------------|
117
- | Postgres / Redis / mail / … | One shared container on a scanned host port | `HARNESS_INFRA_SERVICES` + matching vars in `harness.env` |
118
- | Per-slot databases | Cloned from template DB when `db` is enabled | `launch.sh` |
119
- | Application code | Isolated git worktree per slot | `HARNESS_USE_WORKTREE=true` |
120
-
121
- ### Do not
122
-
123
- - Hardcode `15432` or other default infra ports in tests — read `AGENT_DB_PORT` from `.env.agent.<id>` or `har_pg`
124
- - Run raw `docker compose` for harness infrastructure — use `setup-infra.sh`
125
-
126
- ## Maintaining this harness
127
-
128
- When the project stack changes (new test commands, database needs, env vars):
129
-
130
- ```bash
131
- har env maintain
132
- ```
133
-
134
- The authoring agent updates scripts and this README. Review changes before committing.
135
-
136
- **Do not** put runtime behavior in YAML — edit the scripts directly.
137
-
138
- ## Session lifecycle
139
-
140
- Every `launch` starts a **fresh session**: a new git worktree from the **main
141
- checkout's current HEAD** at
142
- `~/worktrees/<base-branch>-<sha4>-har-agent-<id>-<rand4>`, on a branch of the same name.
143
- Switch that checkout to your intended base before launch. The session is recorded in
144
- `.har/slots/agent-<id>.json` (the slot registry) — status, verify, and teardown resolve
145
- the work dir through it. Make ALL file edits under the work dir printed by launch,
146
- never in the main checkout.
147
-
148
- - Occupied slots always block a new launch: `har env complete <id>` (or `teardown <id>`),
149
- then `har env launch <id>`. A new launch never chooses `main` for you — switch the
150
- main checkout to your intended base first.
151
- - `teardown` removes the worktree but **keeps the session branch** so you can push it
152
- or open a PR (`--delete-branch` to drop it).
153
- - If launch fails after creating a worktree/env file, resume with
154
- `har env launch <id> --resume` or `har env recover <id>`.
155
- - `har env complete <id>` finishes a session: full verify (recorded as a validation),
156
- then teardown — branch kept.
157
- - `--no-worktree` runs the slot from the repo root instead (single-agent mode).