@osfactory/har 0.8.0 → 0.10.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.
@@ -0,0 +1,34 @@
1
+ # Maintain / repair the har harness
2
+
3
+ The `.har/` harness has drifted from the repository (stack changed, launch/verify broken, stale scripts or docs). Bring it back in sync — do every step yourself.
4
+
5
+ ## 1. Run maintain
6
+
7
+ ```bash
8
+ har env maintain
9
+ ```
10
+
11
+ This compares the harness against the current templates and repository, refreshes har-owned files, and prints an adaptation prompt (also written to `.har/ADAPT-PROMPT.md`).
12
+
13
+ ## 2. Perform the adaptation yourself
14
+
15
+ Read `.har/ADAPT-PROMPT.md` and execute its instructions now, in this session: reconcile `.har/` scripts (`launch.sh`, `verify.sh`, `setup-infra.sh`, `harness.env`, `stages.json`) and `AGENT.md` with the repository's current stack, ports, and commands. Preserve intentional project-specific customizations — fix drift, don't blindly reset.
16
+
17
+ ## 3. Finalize and prove it works
18
+
19
+ ```bash
20
+ har env maintain --finalize
21
+ har env launch 1
22
+ har env verify 1 --full
23
+ ```
24
+
25
+ Fix the harness until launch and full verify pass. Tear down afterwards if the slot isn't needed (`har env teardown 1`).
26
+
27
+ ## 4. Commit
28
+
29
+ After the user confirms:
30
+
31
+ ```bash
32
+ git add .har/ AGENT.md
33
+ git commit -m "chore: maintain har harness"
34
+ ```
@@ -0,0 +1,47 @@
1
+ # Work in a har worktree slot
2
+
3
+ This repository uses a `.har/` harness. All code changes happen inside a **har session worktree**, never in the main checkout. Follow this flow for the current task.
4
+
5
+ Use har's worktree, not your own: do not create git worktrees yourself and do not use any built-in worktree/isolation feature of your agent harness — the har slot already provides the worktree plus ports, env, and lifecycle.
6
+
7
+ ## 1. Pick a slot
8
+
9
+ ```bash
10
+ har env status # or ./.har/agent-cli.sh 1 status
11
+ ```
12
+
13
+ - One slot ≈ one task. If slot 1 is occupied by unrelated work, use slot 2+ (limit: `agentSlots` in `.har/stages.json`).
14
+ - Never replace an occupied slot (`--replace`/`--force`) without the user explicitly approving it.
15
+
16
+ ## 2. Launch — BEFORE editing any file
17
+
18
+ ```bash
19
+ har env launch <id> # or ./.har/launch.sh <id>
20
+ ```
21
+
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
+
24
+ ## 3. Do ALL work in the work dir
25
+
26
+ - `cd` into the work dir; every read-modify-write of project files happens there.
27
+ - The main checkout must stay clean (`git status` there shows no changes from you).
28
+ - Edits hot-reload in the running slot; use `./.har/agent-cli.sh <id> restart` if a change doesn't take.
29
+ - Commit early and often on the session branch — teardown keeps the branch, not uncommitted work.
30
+ - After launch, read `.har/CLAUDE.agent.md` in the worktree for slot URLs and the definition of done.
31
+
32
+ ## 4. Verify through the harness
33
+
34
+ ```bash
35
+ har env verify <id> # fast loop while iterating
36
+ har env verify <id> --full # required before declaring work done
37
+ ```
38
+
39
+ Do not substitute ad-hoc test commands for harness verification. Any edit after a full verify — even one character — requires re-running it.
40
+
41
+ ## 5. Finish
42
+
43
+ ```bash
44
+ har env complete <id> # full verify + validation record + teardown, keeps the session branch
45
+ ```
46
+
47
+ Report to the user: verification result, the session branch name (so they can push / open a PR), and the slot preview URLs if the app is running.
@@ -0,0 +1,59 @@
1
+ # Set up the har harness in this repository
2
+
3
+ You are onboarding this repository onto har (an agent-harness orchestrator). Do every step yourself — do not ask the user to paste prompts or run commands unless a step needs their approval.
4
+
5
+ ## 1. Ensure the har CLI is installed
6
+
7
+ ```bash
8
+ har --version
9
+ ```
10
+
11
+ If missing, install it and re-check:
12
+
13
+ ```bash
14
+ npm install -g @osfactory/har
15
+ ```
16
+
17
+ ## 2. Pick a harness profile
18
+
19
+ Inspect the repository and choose the profile that matches how agents will run it:
20
+
21
+ | Profile | Use when |
22
+ |---------|----------|
23
+ | `default` | Web app / server with a long-running process (Next.js, Rails, Django, APIs) |
24
+ | `cli` | CLI tool, library, or npm package — no dev server to keep alive |
25
+ | `ios` | iOS / Swift app built with xcodebuild + Simulator |
26
+
27
+ Tell the user which profile you picked and why before continuing.
28
+
29
+ ## 3. Initialize the harness
30
+
31
+ ```bash
32
+ har env init --profile <profile> # omit --profile for default
33
+ ```
34
+
35
+ If `.har/` already exists, stop and suggest `/har-maintain` instead.
36
+
37
+ ## 4. Perform the adaptation yourself
38
+
39
+ `har env init` prints an adaptation prompt and writes it to `.har/ADAPT-PROMPT.md`. Read that file and **execute its instructions yourself, now, in this session** — tailor `.har/` scripts (`launch.sh`, `verify.sh`, `setup-infra.sh`, `harness.env`, `stages.json`) and `AGENT.md` to this repository's real stack, ports, and commands. Do not use `--auto` and do not ask the user to paste anything.
40
+
41
+ ## 5. Prove the harness works
42
+
43
+ ```bash
44
+ har env launch 1
45
+ har env verify 1
46
+ ```
47
+
48
+ Fix the harness scripts until both pass. Then tear down or keep the slot as the user prefers (`har env teardown 1` keeps the branch).
49
+
50
+ ## 6. Commit
51
+
52
+ After the user confirms, commit the harness:
53
+
54
+ ```bash
55
+ git add .har/ AGENT.md CLAUDE.md .claude/ .cursor/ 2>/dev/null || git add .har/ AGENT.md
56
+ git commit -m "chore: add har agent harness"
57
+ ```
58
+
59
+ Optionally recommend `har hooks install` (commit gate) and `har hooks install --claude` (worktree guard for Claude Code).
@@ -0,0 +1,48 @@
1
+ {
2
+ "version": 1,
3
+ "skills": [
4
+ {
5
+ "id": "setup-har",
6
+ "body": "setup-har.md",
7
+ "title": "Set up the har harness in this repository",
8
+ "claude": {
9
+ "frontmatter": {
10
+ "name": "setup-har",
11
+ "description": "Install the har CLI and scaffold the .har/ agent harness in this repository (init, adapt, launch, verify, commit). User-invoked onboarding.",
12
+ "disable-model-invocation": true,
13
+ "allowed-tools": "Bash(har *) Bash(npm *) Bash(git *) Read Grep Glob Edit Write"
14
+ }
15
+ },
16
+ "cursor": { "command": true },
17
+ "codex": { "promptName": "har-setup" }
18
+ },
19
+ {
20
+ "id": "har-wt",
21
+ "body": "har-wt.md",
22
+ "title": "Work in a har worktree slot",
23
+ "claude": {
24
+ "frontmatter": {
25
+ "name": "har-wt",
26
+ "description": "Use BEFORE making any code change in this repository. Launches a har harness slot, which creates an isolated git session worktree — all edits must happen there, never in the main checkout — and verifies the work through the harness when done."
27
+ }
28
+ },
29
+ "cursor": { "command": true },
30
+ "codex": { "promptName": "har-wt" }
31
+ },
32
+ {
33
+ "id": "har-maintain",
34
+ "body": "har-maintain.md",
35
+ "title": "Maintain / repair the har harness",
36
+ "claude": {
37
+ "frontmatter": {
38
+ "name": "har-maintain",
39
+ "description": "Repair or update the .har/ harness when it has drifted from the repository (stack changes, broken launch/verify, stale scripts). Runs har env maintain and applies the adaptation.",
40
+ "disable-model-invocation": true,
41
+ "allowed-tools": "Bash(har *) Bash(git *) Read Grep Glob Edit Write"
42
+ }
43
+ },
44
+ "cursor": { "command": true },
45
+ "codex": { "promptName": "har-maintain" }
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,38 @@
1
+ #!/bin/sh
2
+ # Managed by `har hooks install --claude` — do not edit; reinstall to update.
3
+ # Claude Code PreToolUse guard: block file edits in the MAIN checkout of a har repo.
4
+ # Edits belong in a har session worktree (launch one with /har-wt). Fails open on errors.
5
+
6
+ [ "$HAR_SKIP_WT_GUARD" = "1" ] && exit 0
7
+
8
+ input="$(cat 2>/dev/null)" || exit 0
9
+ [ -n "$input" ] || exit 0
10
+ command -v node >/dev/null 2>&1 || exit 0
11
+
12
+ file_path="$(printf '%s' "$input" | node -e '
13
+ let d = "";
14
+ process.stdin.on("data", (c) => (d += c)).on("end", () => {
15
+ try {
16
+ const t = JSON.parse(d).tool_input || {};
17
+ process.stdout.write(t.file_path || t.notebook_path || "");
18
+ } catch {}
19
+ });' 2>/dev/null)" || exit 0
20
+ [ -n "$file_path" ] || exit 0
21
+
22
+ dir="$(dirname "$file_path")"
23
+ while [ ! -d "$dir" ] && [ "$dir" != "/" ]; do dir="$(dirname "$dir")"; done
24
+ toplevel="$(cd "$dir" 2>/dev/null && git rev-parse --show-toplevel 2>/dev/null)" || exit 0
25
+ [ -n "$toplevel" ] || exit 0
26
+
27
+ # Only guard har-managed repos.
28
+ [ -f "$toplevel/.har/manifest.json" ] || [ -f "$toplevel/.har/stages.json" ] || exit 0
29
+
30
+ # Linked worktrees (git-dir != common-dir) are session worktrees — allowed.
31
+ gitdir="$(cd "$toplevel" && git rev-parse --absolute-git-dir 2>/dev/null)"
32
+ commondir="$(cd "$toplevel" && git rev-parse --path-format=absolute --git-common-dir 2>/dev/null)"
33
+ if [ -n "$gitdir" ] && [ -n "$commondir" ] && [ "$gitdir" != "$commondir" ]; then
34
+ exit 0
35
+ fi
36
+
37
+ echo "har: edit blocked — $file_path is in the MAIN checkout of a har-managed repo. Run /har-wt to launch a harness slot and make all edits in its session worktree. (Human bypass: HAR_SKIP_WT_GUARD=1)" >&2
38
+ exit 2
@@ -43,7 +43,7 @@ mkdir -p "$ARTIFACT_DIR"
43
43
  log "Running Playwright against $BASE_URL (API: $API_URL)"
44
44
  log "Work dir: $WORK_DIR"
45
45
 
46
- START_TOTAL=$(date +%s%3N 2>/dev/null || echo "0")
46
+ START_TOTAL=$(now_ms)
47
47
 
48
48
  set +e
49
49
  cd "$WORK_DIR"
@@ -51,7 +51,7 @@ PW_OUTPUT=$(npx playwright test 2>&1)
51
51
  PW_EXIT=$?
52
52
  set -e
53
53
 
54
- END_TOTAL=$(date +%s%3N 2>/dev/null || echo "0")
54
+ END_TOTAL=$(now_ms)
55
55
  TOTAL_MS=$(( END_TOTAL - START_TOTAL ))
56
56
 
57
57
  echo "$PW_OUTPUT" >&2
@@ -78,7 +78,11 @@ if [ -n "$FLOW_FILTER" ]; then
78
78
  exit 1
79
79
  fi
80
80
  else
81
- mapfile -t FLOW_SCRIPTS < <(find "$FLOWS_DIR" -maxdepth 1 -name "*.sh" ! -name ".*" | sort)
81
+ # while-read instead of mapfile: stock macOS bash is 3.2, which lacks mapfile.
82
+ FLOW_SCRIPTS=()
83
+ while IFS= read -r flow_script; do
84
+ FLOW_SCRIPTS+=("$flow_script")
85
+ done < <(find "$FLOWS_DIR" -maxdepth 1 -name "*.sh" ! -name ".*" | sort)
82
86
  fi
83
87
 
84
88
  if [ ${#FLOW_SCRIPTS[@]} -eq 0 ]; then
@@ -103,7 +107,7 @@ mkdir -p "$ARTIFACT_DIR"
103
107
  log "Running ${#FLOW_SCRIPTS[@]} flow(s) against simulator..."
104
108
 
105
109
  OVERALL_PASS=true
106
- START_TOTAL=$(date +%s%3N 2>/dev/null || echo "0")
110
+ START_TOTAL=$(now_ms)
107
111
  FLOW_RESULTS="[]"
108
112
 
109
113
  for FLOW_SCRIPT in "${FLOW_SCRIPTS[@]}"; do
@@ -113,7 +117,7 @@ for FLOW_SCRIPT in "${FLOW_SCRIPTS[@]}"; do
113
117
  FLOW_ARTIFACT_DIR="$ARTIFACT_DIR/$FLOW_NAME"
114
118
  mkdir -p "$FLOW_ARTIFACT_DIR"
115
119
 
116
- FLOW_START=$(date +%s%3N 2>/dev/null || echo "0")
120
+ FLOW_START=$(now_ms)
117
121
 
118
122
  set +e
119
123
  FLOW_OUTPUT=$(
@@ -128,7 +132,7 @@ for FLOW_SCRIPT in "${FLOW_SCRIPTS[@]}"; do
128
132
  FLOW_EXIT=$?
129
133
  set -e
130
134
 
131
- FLOW_END=$(date +%s%3N 2>/dev/null || echo "0")
135
+ FLOW_END=$(now_ms)
132
136
  FLOW_MS=$(( FLOW_END - FLOW_START ))
133
137
 
134
138
  if [ "$FLOW_EXIT" = "0" ]; then
@@ -162,7 +166,7 @@ process.stdout.write(JSON.stringify(arr));
162
166
  " 2>/dev/null || echo "$FLOW_RESULTS")
163
167
  done
164
168
 
165
- END_TOTAL=$(date +%s%3N 2>/dev/null || echo "0")
169
+ END_TOTAL=$(now_ms)
166
170
  TOTAL_MS=$(( END_TOTAL - START_TOTAL ))
167
171
 
168
172
  # ── Output ────────────────────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osfactory/har",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "description": "LLM-powered CLI for reproducible agent development environments",
5
5
  "keywords": [
6
6
  "har",