@osfactory/har 0.20.0 → 0.21.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.
@@ -21,6 +21,17 @@ har env launch <id> # or ./.har/launch.sh <id>
21
21
 
22
22
  Launch creates a fresh session worktree from HEAD and prints its **work dir** (also recorded in `.har/slots/agent-<id>.json`, path like `~/worktrees/<base>-<sha4>-har-agent-<id>-<rand4>`). If a previous launch failed partway, retry with `--resume` instead of replacing.
23
23
 
24
+ If the task already has a stable issue or ticket ID, bind it without changing the
25
+ methodology that produced it:
26
+
27
+ ```bash
28
+ har env launch <id> --work-id "<provider-neutral-id>" --work-title "<title>"
29
+ ```
30
+
31
+ External planning/TDD/review skills remain in control of implementation strategy.
32
+ They must delegate worktree creation, runtime launch, final verification, and
33
+ completion to HAR.
34
+
24
35
  ## 3. Do ALL work in the work dir
25
36
 
26
37
  - `cd` into the work dir; every read-modify-write of project files happens there.
@@ -447,7 +447,7 @@ try {
447
447
  # required: SLOT_AGENT_ID, SLOT_MODE (worktree|root), SLOT_WORK_DIR
448
448
  # optional: SLOT_SUFFIX, SLOT_WORKTREE_PATH, SLOT_BRANCH, SLOT_BASE_BRANCH,
449
449
  # SLOT_BASE_COMMIT, SLOT_PORTS_JSON, SLOT_PREVIEW_URLS_JSON,
450
- # SLOT_STATUS, SLOT_LAST_ERROR
450
+ # SLOT_STATUS, SLOT_LAST_ERROR, SLOT_WORK_UNIT_ID, SLOT_ATTEMPT_ID
451
451
  write_slot_registry() {
452
452
  local file
453
453
  file="$(slot_registry_file "$SLOT_AGENT_ID")"
@@ -470,6 +470,8 @@ if (e.SLOT_BRANCH) entry.branch = e.SLOT_BRANCH;
470
470
  if (e.SLOT_BASE_BRANCH) entry.baseBranch = e.SLOT_BASE_BRANCH;
471
471
  if (e.SLOT_BASE_COMMIT) entry.baseCommit = e.SLOT_BASE_COMMIT;
472
472
  if (e.SLOT_LAST_ERROR) entry.lastError = e.SLOT_LAST_ERROR;
473
+ if (e.SLOT_WORK_UNIT_ID) entry.workUnitId = e.SLOT_WORK_UNIT_ID;
474
+ if (e.SLOT_ATTEMPT_ID) entry.attemptId = e.SLOT_ATTEMPT_ID;
473
475
  for (const [key, env] of [["ports", "SLOT_PORTS_JSON"], ["previewUrls", "SLOT_PREVIEW_URLS_JSON"]]) {
474
476
  if (e[env]) try { entry[key] = JSON.parse(e[env]); } catch {}
475
477
  }
@@ -2,6 +2,9 @@
2
2
  logs/
3
3
  runs/
4
4
  validations/
5
+ work-units/
6
+ work-attempts/
7
+ validation-bindings/
5
8
  artifacts/
6
9
  state/
7
10
  maintain/
@@ -20,6 +20,8 @@ USE_CLAUDE=false
20
20
  FORCE=false
21
21
  REPLACE=false
22
22
  RESUME=false
23
+ WORK_UNIT_ID="${HAR_WORK_UNIT_ID:-}"
24
+ ATTEMPT_ID="${HAR_ATTEMPT_ID:-}"
23
25
 
24
26
  for arg in "$@"; do
25
27
  case "$arg" in
@@ -29,9 +31,17 @@ for arg in "$@"; do
29
31
  --replace) REPLACE=true ;;
30
32
  --force) FORCE=true ;;
31
33
  --resume) RESUME=true ;;
34
+ --work-id=*) WORK_UNIT_ID="${arg#*=}" ;;
35
+ --attempt-id=*) ATTEMPT_ID="${arg#*=}" ;;
32
36
  esac
33
37
  done
34
38
 
39
+ if [[ -n "$WORK_UNIT_ID" && -z "$ATTEMPT_ID" ]]; then
40
+ ATTEMPT_ID="$(node -e 'process.stdout.write(require("crypto").randomUUID())')"
41
+ fi
42
+ export SLOT_WORK_UNIT_ID="$WORK_UNIT_ID"
43
+ export SLOT_ATTEMPT_ID="$ATTEMPT_ID"
44
+
35
45
  if [[ -z "$AGENT_ID" ]]; then
36
46
  har_load_agent_slot_limits
37
47
  echo "Usage: $0 <agent-id> [--no-worktree] [--claude] [--replace] [--force] [--resume] " >&2
@@ -427,7 +427,7 @@ try {
427
427
  # required: SLOT_AGENT_ID, SLOT_MODE (worktree|root), SLOT_WORK_DIR
428
428
  # optional: SLOT_SUFFIX, SLOT_WORKTREE_PATH, SLOT_BRANCH, SLOT_BASE_BRANCH,
429
429
  # SLOT_BASE_COMMIT, SLOT_PORTS_JSON, SLOT_PREVIEW_URLS_JSON,
430
- # SLOT_STATUS, SLOT_LAST_ERROR
430
+ # SLOT_STATUS, SLOT_LAST_ERROR, SLOT_WORK_UNIT_ID, SLOT_ATTEMPT_ID
431
431
  write_slot_registry() {
432
432
  local file
433
433
  file="$(slot_registry_file "$SLOT_AGENT_ID")"
@@ -450,6 +450,8 @@ if (e.SLOT_BRANCH) entry.branch = e.SLOT_BRANCH;
450
450
  if (e.SLOT_BASE_BRANCH) entry.baseBranch = e.SLOT_BASE_BRANCH;
451
451
  if (e.SLOT_BASE_COMMIT) entry.baseCommit = e.SLOT_BASE_COMMIT;
452
452
  if (e.SLOT_LAST_ERROR) entry.lastError = e.SLOT_LAST_ERROR;
453
+ if (e.SLOT_WORK_UNIT_ID) entry.workUnitId = e.SLOT_WORK_UNIT_ID;
454
+ if (e.SLOT_ATTEMPT_ID) entry.attemptId = e.SLOT_ATTEMPT_ID;
453
455
  for (const [key, env] of [["ports", "SLOT_PORTS_JSON"], ["previewUrls", "SLOT_PREVIEW_URLS_JSON"]]) {
454
456
  if (e[env]) try { entry[key] = JSON.parse(e[env]); } catch {}
455
457
  }
@@ -2,6 +2,9 @@
2
2
  logs/
3
3
  runs/
4
4
  validations/
5
+ work-units/
6
+ work-attempts/
7
+ validation-bindings/
5
8
  artifacts/
6
9
  state/
7
10
  maintain/
@@ -19,6 +19,8 @@ USE_WORKTREE="${HARNESS_USE_WORKTREE:-true}"
19
19
  FORCE=false
20
20
  REPLACE=false
21
21
  RESUME=false
22
+ WORK_UNIT_ID="${HAR_WORK_UNIT_ID:-}"
23
+ ATTEMPT_ID="${HAR_ATTEMPT_ID:-}"
22
24
 
23
25
  for arg in "$@"; do
24
26
  case "$arg" in
@@ -27,9 +29,17 @@ for arg in "$@"; do
27
29
  --replace) REPLACE=true ;;
28
30
  --force) FORCE=true ;;
29
31
  --resume) RESUME=true ;;
32
+ --work-id=*) WORK_UNIT_ID="${arg#*=}" ;;
33
+ --attempt-id=*) ATTEMPT_ID="${arg#*=}" ;;
30
34
  esac
31
35
  done
32
36
 
37
+ if [[ -n "$WORK_UNIT_ID" && -z "$ATTEMPT_ID" ]]; then
38
+ ATTEMPT_ID="$(node -e 'process.stdout.write(require("crypto").randomUUID())')"
39
+ fi
40
+ export SLOT_WORK_UNIT_ID="$WORK_UNIT_ID"
41
+ export SLOT_ATTEMPT_ID="$ATTEMPT_ID"
42
+
33
43
  if [[ -z "$AGENT_ID" ]]; then
34
44
  har_load_agent_slot_limits
35
45
  echo "Usage: $0 <agent-id> [--no-worktree] [--replace] [--force] [--resume] " >&2
@@ -88,7 +88,7 @@ try {
88
88
  # required: SLOT_AGENT_ID, SLOT_MODE (worktree|root), SLOT_WORK_DIR
89
89
  # optional: SLOT_SUFFIX, SLOT_WORKTREE_PATH, SLOT_BRANCH, SLOT_BASE_BRANCH,
90
90
  # SLOT_BASE_COMMIT, SLOT_PORTS_JSON, SLOT_PREVIEW_URLS_JSON,
91
- # SLOT_STATUS, SLOT_LAST_ERROR
91
+ # SLOT_STATUS, SLOT_LAST_ERROR, SLOT_WORK_UNIT_ID, SLOT_ATTEMPT_ID
92
92
  write_slot_registry() {
93
93
  local file
94
94
  file="$(slot_registry_file "$SLOT_AGENT_ID")"
@@ -111,6 +111,8 @@ if (e.SLOT_BRANCH) entry.branch = e.SLOT_BRANCH;
111
111
  if (e.SLOT_BASE_BRANCH) entry.baseBranch = e.SLOT_BASE_BRANCH;
112
112
  if (e.SLOT_BASE_COMMIT) entry.baseCommit = e.SLOT_BASE_COMMIT;
113
113
  if (e.SLOT_LAST_ERROR) entry.lastError = e.SLOT_LAST_ERROR;
114
+ if (e.SLOT_WORK_UNIT_ID) entry.workUnitId = e.SLOT_WORK_UNIT_ID;
115
+ if (e.SLOT_ATTEMPT_ID) entry.attemptId = e.SLOT_ATTEMPT_ID;
114
116
  for (const [key, env] of [["ports", "SLOT_PORTS_JSON"], ["previewUrls", "SLOT_PREVIEW_URLS_JSON"]]) {
115
117
  if (e[env]) try { entry[key] = JSON.parse(e[env]); } catch {}
116
118
  }
@@ -2,6 +2,9 @@
2
2
  logs/
3
3
  runs/
4
4
  validations/
5
+ work-units/
6
+ work-attempts/
7
+ validation-bindings/
5
8
  artifacts/
6
9
  AGENT.md.proposed
7
10
  AGENT.md.proposed.meta.json
@@ -18,6 +18,8 @@ AGENT_ID="${1:-}"
18
18
  USE_WORKTREE="${HARNESS_USE_WORKTREE:-true}"
19
19
  FORCE=false
20
20
  REPLACE=false
21
+ WORK_UNIT_ID="${HAR_WORK_UNIT_ID:-}"
22
+ ATTEMPT_ID="${HAR_ATTEMPT_ID:-}"
21
23
 
22
24
  for arg in "$@"; do
23
25
  case "$arg" in
@@ -25,9 +27,17 @@ for arg in "$@"; do
25
27
  --worktree) USE_WORKTREE=true ;;
26
28
  --replace) REPLACE=true ;;
27
29
  --force) FORCE=true ;;
30
+ --work-id=*) WORK_UNIT_ID="${arg#*=}" ;;
31
+ --attempt-id=*) ATTEMPT_ID="${arg#*=}" ;;
28
32
  esac
29
33
  done
30
34
 
35
+ if [[ -n "$WORK_UNIT_ID" && -z "$ATTEMPT_ID" ]]; then
36
+ ATTEMPT_ID="$(node -e 'process.stdout.write(require("crypto").randomUUID())')"
37
+ fi
38
+ export SLOT_WORK_UNIT_ID="$WORK_UNIT_ID"
39
+ export SLOT_ATTEMPT_ID="$ATTEMPT_ID"
40
+
31
41
  if [[ -z "$AGENT_ID" ]]; then
32
42
  har_load_agent_slot_limits
33
43
  echo "Usage: $0 <agent-id> [--no-worktree] [--replace] [--force] " >&2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osfactory/har",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "description": "LLM-powered CLI for reproducible agent development environments",
5
5
  "keywords": [
6
6
  "har",