@osfactory/har 0.36.2 → 0.38.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.
@@ -11,7 +11,7 @@
11
11
  | **Simulator** | Configured in `.har/harness.env` — `HARNESS_SIMULATOR_NAME` |
12
12
  | **Scheme** | Configured in `.har/harness.env` — `HARNESS_XCODE_SCHEME` |
13
13
 
14
- **Never edit the main checkout** — launch FIRST, then make ALL file edits under the work dir from the launch output. Relaunching replaces the session (branch kept) and requires explicit confirmation; dirty worktrees also need `--force` after user approval.
14
+ **Never edit the main checkout** — launch FIRST, then make ALL file edits under the work dir from the launch output. An occupied slot always blocks a new launch — run `har env teardown <id>` (or `complete <id>`) first, then launch again.
15
15
 
16
16
  ```bash
17
17
  ./.har/agent-cli.sh ${AGENT_ID} status
@@ -119,8 +119,8 @@ checkout's current HEAD** at
119
119
  Switch that checkout to your intended base before launch. The session is recorded in
120
120
  `.har/slots/agent-<id>.json`.
121
121
 
122
- - Prefer `complete` / `teardown` when a task is finished, then launch.
123
- - `--replace` destroys the previous worktree; it does **not** choose `main`.
124
- Uncommitted changes also require `--force` after explicit approval.
122
+ - Occupied slots always block a new launch: `har env complete <id>` (or `teardown <id>`),
123
+ then `har env launch <id>`. A new launch never chooses `main` for you — switch the
124
+ main checkout to your intended base first.
125
125
  - `teardown` removes the worktree but **keeps the session branch** for push / PR.
126
126
  - `har env complete <id>` finishes a session: full verify + teardown, branch kept.
@@ -53,12 +53,18 @@ validate_agent_id() {
53
53
  fi
54
54
 
55
55
  if [[ -z "$id" ]] || ! [[ "$id" =~ ^[0-9]+$ ]]; then
56
- echo "Error: agent-id must be a positive integer between ${min} and ${max}" >&2
56
+ echo "Error: invalid agent slot id: ${id:-"(missing)"}" >&2
57
+ echo " Must be an integer between ${min} and ${max} (see .har/stages.json → agentSlots)" >&2
57
58
  exit 1
58
59
  fi
59
60
 
60
61
  if (( id < min || id > max )); then
61
- echo "Error: agent-id must be between ${min} and ${max}" >&2
62
+ echo "Error: invalid agent slot id: ${id}" >&2
63
+ echo " Valid slots: ${min}–${max} (configured in .har/stages.json → agentSlots)" >&2
64
+ echo " Run: har env status # see which slots are in use" >&2
65
+ if (( id > max )); then
66
+ echo " To allow slot ${id}, raise agentSlots.max in .har/stages.json." >&2
67
+ fi
62
68
  exit 1
63
69
  fi
64
70
  }
@@ -152,8 +158,8 @@ slot_dirty_summary() {
152
158
  echo "dirty (${count} changed)"
153
159
  }
154
160
 
155
- # Print a warning before replacing an occupied slot (stdout — visible to agents).
156
- print_slot_replace_warning() {
161
+ # Print details about an occupied slot (stdout — visible to agents).
162
+ print_slot_occupied_warning() {
157
163
  local agent_id="$1"
158
164
  local reg wt branch work_dir created status last_error dirty_summary head
159
165
  reg="$(slot_registry_file "$agent_id")"
@@ -169,7 +175,7 @@ print_slot_replace_warning() {
169
175
  fi
170
176
 
171
177
  echo "" >&2
172
- echo "⚠ Slot ${agent_id} is already in use — replacing will REMOVE the worktree." >&2
178
+ echo "⚠ Slot ${agent_id} is already in use." >&2
173
179
  [ -n "$wt" ] && echo " Worktree: ${wt}" >&2
174
180
  [ -n "$work_dir" ] && echo " Work dir: ${work_dir}" >&2
175
181
  [ -n "$branch" ] && echo " Branch: ${branch}${head:+ @ ${head}}" >&2
@@ -185,54 +191,21 @@ print_slot_replace_warning() {
185
191
  base_sha="$(git -C "$base_root" rev-parse --short HEAD 2>/dev/null || true)"
186
192
  echo " New session will be based on: ${base_branch}${base_sha:+ @ ${base_sha}}" >&2
187
193
  echo " (HEAD of ${base_root})" >&2
188
- echo " --replace does not choose this base — switch that checkout first for a new unrelated task." >&2
194
+ echo " Switch that checkout to your intended base before launching a new session." >&2
189
195
  echo "" >&2
190
196
  fi
191
- echo " Prefer complete/teardown when the previous task is finished, then launch." >&2
192
- echo " The session branch is kept only if you committed. Gitignored paths" >&2
193
- echo " (state/, runs/, local clones, .env.local) are NOT preserved." >&2
194
- echo "" >&2
195
- }
196
-
197
- # Require explicit confirmation before replacing an occupied slot.
198
- # $1 agent_id $2 force(true/false) $3 replace(true/false)
199
- # Exits 1 when replacement must not proceed.
200
- require_slot_replace_confirm() {
201
- local agent_id="$1"
202
- local force="$2"
203
- local replace="$3"
204
- local wt
205
-
206
- slot_is_occupied "$agent_id" || return 0
207
-
208
- print_slot_replace_warning "$agent_id"
209
- wt="$(existing_slot_worktree "$agent_id")"
210
-
211
- if [ -n "$wt" ] && slot_worktree_dirty "$wt" && [ "$force" != true ]; then
212
- echo "ERROR: previous session for slot ${agent_id} has uncommitted changes." >&2
213
- echo " Commit them in the worktree (branch is kept on teardown), or pass --force to discard." >&2
214
- echo " --force destroys uncommitted work — only use after explicit user approval." >&2
215
- exit 1
216
- fi
217
-
218
- if [ "$replace" = true ] || [ "${HAR_CONFIRM_REPLACE:-}" = "1" ]; then
219
- return 0
220
- fi
221
-
222
- if [ -t 0 ] && [ -t 1 ]; then
223
- local answer
224
- read -r -p "Replace slot ${agent_id}? Uncommitted work is lost unless committed. [y/N] " answer
225
- if [[ "$answer" =~ ^[Yy]$ ]]; then
226
- return 0
227
- fi
228
- echo "Aborted — slot ${agent_id} left unchanged." >&2
229
- exit 2
197
+ if [ "$dirty_summary" != "clean" ] && [ "$dirty_summary" != "unknown" ]; then
198
+ echo " Commit or discard changes in the worktree, then teardown/complete the slot:" >&2
199
+ else
200
+ echo " Free the slot, then launch again:" >&2
230
201
  fi
231
-
232
- echo "ERROR: slot ${agent_id} is occupied." >&2
233
- echo " Pass --replace (or set HAR_CONFIRM_REPLACE=1) after reviewing the warning above." >&2
234
- echo " If the worktree is dirty, also pass --force (only after explicit user approval)." >&2
235
- exit 2
202
+ echo " har env complete ${agent_id} # or: har env teardown ${agent_id}" >&2
203
+ echo " har env launch ${agent_id}" >&2
204
+ echo "" >&2
205
+ echo " complete/teardown remove the worktree. The session branch is kept only if" >&2
206
+ echo " you committed. Gitignored paths (state/, runs/, local clones, .env.local)" >&2
207
+ echo " are NOT preserved." >&2
208
+ echo "" >&2
236
209
  }
237
210
 
238
211
  git_common_dir() {
@@ -2,8 +2,9 @@
2
2
  # Launch an agent slot for iOS mobile app repos (git worktree by default).
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
+ # Occupied slots always block: run ./.har/teardown.sh (or complete it) first, then relaunch.
5
6
  #
6
- # Usage: ./.har/launch.sh <agent-id> [--no-worktree] [--replace] [--force]
7
+ # Usage: ./.har/launch.sh <agent-id> [--no-worktree]
7
8
  set -euo pipefail
8
9
 
9
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -16,8 +17,6 @@ source "$SCRIPT_DIR/agent-slot.sh"
16
17
 
17
18
  AGENT_ID="${1:-}"
18
19
  USE_WORKTREE="${HARNESS_USE_WORKTREE:-true}"
19
- FORCE=false
20
- REPLACE=false
21
20
  WORK_UNIT_ID="${HAR_WORK_UNIT_ID:-}"
22
21
  ATTEMPT_ID="${HAR_ATTEMPT_ID:-}"
23
22
 
@@ -25,8 +24,6 @@ for arg in "$@"; do
25
24
  case "$arg" in
26
25
  --no-worktree) USE_WORKTREE=false ;;
27
26
  --worktree) USE_WORKTREE=true ;;
28
- --replace) REPLACE=true ;;
29
- --force) FORCE=true ;;
30
27
  --work-id=*) WORK_UNIT_ID="${arg#*=}" ;;
31
28
  --attempt-id=*) ATTEMPT_ID="${arg#*=}" ;;
32
29
  esac
@@ -40,7 +37,7 @@ export SLOT_ATTEMPT_ID="$ATTEMPT_ID"
40
37
 
41
38
  if [[ -z "$AGENT_ID" ]]; then
42
39
  har_load_agent_slot_limits
43
- echo "Usage: $0 <agent-id> [--no-worktree] [--replace] [--force] " >&2
40
+ echo "Usage: $0 <agent-id> [--no-worktree]" >&2
44
41
  echo " agent-id must be between ${HARNESS_AGENT_SLOT_MIN} and ${HARNESS_AGENT_SLOT_MAX}" >&2
45
42
  exit 1
46
43
  fi
@@ -49,11 +46,12 @@ validate_agent_id "$AGENT_ID"
49
46
 
50
47
  log() { echo "==> [agent-$AGENT_ID] $*" >&2; }
51
48
 
52
- # Replace any previous session for this slot — requires explicit confirmation.
49
+ # Occupied slots always block a new launch — teardown/complete first, then relaunch.
53
50
  if slot_is_occupied "$AGENT_ID"; then
54
- require_slot_replace_confirm "$AGENT_ID" "$FORCE" "$REPLACE"
55
- log "Replacing previous session for slot ${AGENT_ID}..."
56
- "$SCRIPT_DIR/teardown.sh" "$AGENT_ID" >&2
51
+ print_slot_occupied_warning "$AGENT_ID"
52
+ echo "ERROR: slot ${AGENT_ID} is occupied." >&2
53
+ echo " Free it first: har env teardown ${AGENT_ID} (or complete ${AGENT_ID}), then har env launch ${AGENT_ID}." >&2
54
+ exit 2
57
55
  fi
58
56
 
59
57
  "$SCRIPT_DIR/setup-infra.sh"
@@ -122,7 +120,7 @@ mark_slot_failed() {
122
120
  write_slot_registry
123
121
  log " Work dir: ${WORK_DIR}"
124
122
  log " Env file: ${ENV_FILE}"
125
- log " Recovery: fix the failure, then relaunch with --replace when ready."
123
+ log " Recovery: fix the failure, then: har env teardown ${AGENT_ID} (or complete), then har env launch ${AGENT_ID}."
126
124
  fi
127
125
  }
128
126
  trap mark_slot_failed EXIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osfactory/har",
3
- "version": "0.36.2",
3
+ "version": "0.38.0",
4
4
  "description": "LLM-powered CLI for reproducible agent development environments",
5
5
  "keywords": [
6
6
  "har",
@@ -73,7 +73,7 @@
73
73
  "homepage": "https://harproject.dev/",
74
74
  "bugs": "https://github.com/os-factory/har/issues",
75
75
  "author": "Antoine Frau",
76
- "license": "AGPL-3.0-only",
76
+ "license": "Apache-2.0",
77
77
  "publishConfig": {
78
78
  "access": "public",
79
79
  "registry": "https://registry.npmjs.org/"