@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.
- package/README.md +31 -0
- package/dist/index.js +1019 -563
- package/dist/templates/agent-skills/har-maintain.md +34 -0
- package/dist/templates/agent-skills/har-wt.md +47 -0
- package/dist/templates/agent-skills/setup-har.md +59 -0
- package/dist/templates/agent-skills/skills.manifest.json +48 -0
- package/dist/templates/claude-worktree-guard.sh.template +38 -0
- package/dist/templates/stage-templates/playwright/.har/stages/browser-e2e.sh +2 -2
- package/dist/templates/stage-templates/rocketsim/.har/stages/rocketsim-flows.sh +9 -5
- package/package.json +1 -1
|
@@ -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=$(
|
|
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=$(
|
|
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
|
-
|
|
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=$(
|
|
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=$(
|
|
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=$(
|
|
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=$(
|
|
169
|
+
END_TOTAL=$(now_ms)
|
|
166
170
|
TOTAL_MS=$(( END_TOTAL - START_TOTAL ))
|
|
167
171
|
|
|
168
172
|
# ── Output ────────────────────────────────────────────────────────────────────
|