@osfactory/har 1.0.0-rc.2 → 1.0.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.
Files changed (59) hide show
  1. package/dist/index.js +4827 -8265
  2. package/dist/templates/AGENTS.md.template +19 -66
  3. package/dist/templates/CLAUDE.md.template +1 -5
  4. package/dist/templates/adaptation-prompt-init.md +7 -6
  5. package/dist/templates/adaptation-prompt-maintain.md +4 -4
  6. package/dist/templates/agent-skills/har-wt.md +1 -1
  7. package/dist/templates/cursor-rule.mdc.template +7 -72
  8. package/dist/templates/har-boilerplate/gitignore.template +3 -1
  9. package/dist/templates/har-boilerplate-cli/gitignore.template +3 -1
  10. package/dist/templates/har-boilerplate-ios/gitignore.template +2 -0
  11. package/dist/templates/migration-prompt.md +2 -1
  12. package/dist/templates/profiles/cli/docs/{claude-agent → readme}/definition-of-done.md +3 -3
  13. package/dist/templates/profiles/cli/docs/{claude-agent → readme}/do-not.md +1 -1
  14. package/dist/templates/profiles/cli/docs/{claude-agent → readme}/environment.md +3 -3
  15. package/dist/templates/profiles/cli/docs/readme/for-coding-agents.md +5 -7
  16. package/dist/templates/profiles/cli/docs/readme/port-shared-services-cli-profile.md +3 -3
  17. package/dist/templates/profiles/cli/docs/readme/quick-start.md +3 -9
  18. package/dist/templates/profiles/cli/docs/readme/verification-contract.md +2 -2
  19. package/dist/templates/profiles/cli/docs/readme/what-s-in-here.md +2 -2
  20. package/dist/templates/profiles/cli/profile.manifest.json +14 -11
  21. package/dist/templates/profiles/default/docs/readme/architecture.md +1 -1
  22. package/dist/templates/profiles/default/docs/{claude-agent → readme}/definition-of-done.md +3 -3
  23. package/dist/templates/profiles/default/docs/{claude-agent → readme}/do-not.md +2 -2
  24. package/dist/templates/profiles/default/docs/readme/environment.md +19 -0
  25. package/dist/templates/profiles/default/docs/readme/for-coding-agents.md +4 -6
  26. package/dist/templates/profiles/default/docs/readme/port-shared-services.md +5 -5
  27. package/dist/templates/profiles/default/docs/readme/quick-start.md +3 -9
  28. package/dist/templates/profiles/default/docs/readme/readiness-layers.md +4 -4
  29. package/dist/templates/profiles/default/docs/{claude-agent → readme}/readiness.md +1 -1
  30. package/dist/templates/profiles/default/docs/readme/verification-contract.md +1 -1
  31. package/dist/templates/profiles/default/docs/readme/what-s-in-here.md +2 -2
  32. package/dist/templates/profiles/default/profile.manifest.json +21 -13
  33. package/dist/templates/profiles/ios/docs/{claude-agent → readme}/definition-of-done.md +3 -3
  34. package/dist/templates/profiles/ios/docs/{claude-agent → readme}/do-not.md +1 -1
  35. package/dist/templates/profiles/ios/docs/{claude-agent → readme}/environment.md +4 -4
  36. package/dist/templates/profiles/ios/docs/readme/port-shared-services-ios-profile.md +3 -3
  37. package/dist/templates/profiles/ios/docs/{claude-agent → readme}/project-commands.md +4 -4
  38. package/dist/templates/profiles/ios/docs/readme/quick-start.md +3 -9
  39. package/dist/templates/profiles/ios/docs/readme/simulators.md +2 -2
  40. package/dist/templates/profiles/ios/docs/{claude-agent → readme}/user-flow-validation-rocketsim.md +2 -2
  41. package/dist/templates/profiles/ios/docs/readme/verification-contract.md +1 -1
  42. package/dist/templates/profiles/ios/docs/readme/what-s-in-here.md +2 -2
  43. package/dist/templates/profiles/ios/profile.manifest.json +15 -12
  44. package/dist/templates/runtime-bundles/pm2-runtime/attach.sh +44 -6
  45. package/dist/templates/runtime-bundles/shared-kernel/agent-cli.sh +20 -3
  46. package/dist/templates/runtime-bundles/shared-kernel/launch.sh +20 -3
  47. package/dist/templates/runtime-bundles/shared-kernel/preflight.sh +20 -3
  48. package/dist/templates/runtime-bundles/shared-kernel/setup-infra.sh +20 -3
  49. package/dist/templates/runtime-bundles/shared-kernel/teardown.sh +20 -3
  50. package/dist/templates/runtime-bundles/shared-kernel/verify.sh +20 -3
  51. package/package.json +2 -1
  52. package/dist/prompts/system-authoring.md +0 -155
  53. package/dist/templates/profiles/default/docs/claude-agent/environment.md +0 -19
  54. package/dist/templates/profiles/ios/docs/claude-agent/intro.md +0 -3
  55. package/dist/templates/shared-docs/claude-agent/intro.md +0 -3
  56. /package/dist/templates/profiles/cli/docs/{claude-agent → readme}/project-commands.md +0 -0
  57. /package/dist/templates/profiles/cli/docs/{claude-agent → readme}/readiness.md +0 -0
  58. /package/dist/templates/profiles/default/docs/{claude-agent → readme}/project-commands.md +0 -0
  59. /package/dist/templates/profiles/ios/docs/{claude-agent → readme}/readiness.md +0 -0
@@ -12,7 +12,7 @@
12
12
  | Mailpit | Per machine | `HARNESS_MAILPIT_*_PORT_DEFAULT` | Scan configured ranges |
13
13
  | Headless browser | Per machine | `HARNESS_BROWSER_PORT_DEFAULT` | Scan configured ranges |
14
14
 
15
- Resolved ports may differ from the formula when something else is already bound. Always use `./.har/agent-cli.sh <id>` or read `.har/slots/agent-<id>.json` — never hardcode `3010`, `15432`, etc. in app code or tests.
15
+ Resolved ports may differ from the formula when something else is already bound. Always use `har env agent <id>` or read `.har/slots/agent-<id>.json` — never hardcode `3010`, `15432`, etc. in app code or tests.
16
16
 
17
17
  ### Shared vs per-slot
18
18
 
@@ -24,18 +24,18 @@ Resolved ports may differ from the formula when something else is already bound.
24
24
  | Primary application | One PM2 ecosystem per slot (isolated ports) | `HARNESS_PRIMARY_APP`, `ecosystem.agent.template.cjs` |
25
25
  | Internal supporting services | Shared across all slots | `docker-compose.agent.yml` or `ecosystem.shared.config.cjs` |
26
26
 
27
- Shared infra starts once via `./.har/setup-infra.sh` (also run automatically by `launch.sh`). Per-slot databases are cloned in `launch.sh`.
27
+ Shared infra starts once via `har env setup-infra` (also run automatically by `har env launch`). Per-slot databases are cloned in `har env launch`.
28
28
 
29
29
  ### Do not
30
30
 
31
31
  - Hardcode default ports (`3000`, `15432`, `3847`, …) in application code, tests, or agent docs — read from `.env.agent.<id>`, `agent-cli.sh`, or the slot registry
32
- - Run raw `docker compose` for harness infrastructure — use `setup-infra.sh` / `launch.sh` so ports are scanned and persisted in `.har/state/infra.env`
32
+ - Run raw `docker compose` for harness infrastructure — use `har env setup-infra` / `har env launch` so ports are scanned and persisted in `.har/state/infra.env`
33
33
 
34
34
  ### Primary app vs shared services
35
35
 
36
36
  Each slot runs **only the primary application** (`HARNESS_PRIMARY_APP` in `harness.env`) — the app agents modify. Everything else runs **once**, shared by all slots on fixed ports:
37
37
 
38
- - **External dependencies** (Postgres, Redis, mail, ...): services in `docker-compose.agent.yml`, enabled via the `HARNESS_INFRA_SERVICES` list in `harness.env`, started by `setup-infra.sh`.
39
- - **Internal supporting services** (other services of a monolith/monorepo the agent depends on but does not change): either compose services in `docker-compose.agent.yml`, or PM2 processes in an optional `.har/ecosystem.shared.config.cjs` (named `har-shared-<name>`, started by `setup-infra.sh`).
38
+ - **External dependencies** (Postgres, Redis, mail, ...): services in `docker-compose.agent.yml`, enabled via the `HARNESS_INFRA_SERVICES` list in `harness.env`, started by `har env setup-infra`.
39
+ - **Internal supporting services** (other services of a monolith/monorepo the agent depends on but does not change): either compose services in `docker-compose.agent.yml`, or PM2 processes in an optional `.har/ecosystem.shared.config.cjs` (named `har-shared-<name>`, started by `har env setup-infra`).
40
40
 
41
41
  Isolation still applies where it matters: each slot gets its own database (`agent_<id>`, cloned from the template DB), ports, and git worktree.
@@ -11,14 +11,8 @@ har env teardown 1
11
11
 
12
12
  In Cursor with HAR MCP configured: use `har_launch_environment`, `har_run_verification`, and `har_teardown_environment`.
13
13
 
14
- **Shell shims** (same runtime — each `./.har/*.sh` forwards to `har env`, with a pinned `npx @osfactory/har` fallback):
15
-
16
- ```bash
17
- ./.har/setup-infra.sh # when HARNESS_INFRA_SERVICES is non-empty
18
- ./.har/launch.sh 1
19
- ./.har/verify.sh 1 # quick: ecosystem smoke + health
20
- ./.har/verify.sh 1 --full # + conventional tests/lint, browser-e2e (if installed)
21
- ./.har/teardown.sh 1
22
- ```
14
+ `./.har/*.sh` exist as compatibility shims over the same runtime — generated,
15
+ never edited, and not the way to drive the harness. Take explicit ownership of
16
+ them with `har env eject`.
23
17
 
24
18
  Read **`stages.json`** for registered stages and **`verificationStages`** for the expected pass set.
@@ -5,10 +5,10 @@ section for the repository:
5
5
 
6
6
  | Layer | What it means | Where to encode it |
7
7
  |-------|---------------|--------------------|
8
- | Infra ready | Shared services and template data stores exist | `setup-infra.sh`, `docker-compose.agent.yml` |
9
- | Slot data ready | Every per-slot data store is created/cloned | `launch.sh` |
10
- | Process ready | Primary app is running and health passes | `launch.sh`, `verify.sh` |
11
- | Agent usable | Login/API/UI smoke works with documented data | `HARNESS_READINESS_CMD`, browser-e2e, `CLAUDE.agent.md` |
8
+ | Infra ready | Shared services and template data stores exist | `har env setup-infra`, `docker-compose.agent.yml` |
9
+ | Slot data ready | Every per-slot data store is created/cloned | `har env launch` |
10
+ | Process ready | Primary app is running and health passes | `har env launch`, `har env verify` |
11
+ | Agent usable | Login/API/UI smoke works with documented data | `HARNESS_READINESS_CMD`, browser-e2e, `.har/README.md` |
12
12
 
13
13
  If full local-dev setup is too heavy to run in the harness, document the skipped
14
14
  steps and add the minimum substitute directly in `.har/` scripts (for example an
@@ -3,7 +3,7 @@
3
3
  Adapt this section for the repository. A passing health check means the process
4
4
  is alive; it does not automatically mean an agent can use the app.
5
5
 
6
- - **Health**: `./.har/agent-cli.sh ${AGENT_ID} health`
6
+ - **Health**: `har env agent <id> health`
7
7
  - **Agent-usable smoke**: document the login/API/UI workflow agents should try,
8
8
  or wire it into `HARNESS_READINESS_CMD` / full verify.
9
9
  - **Credentials/default data**: document any test users, tenants, projects, or
@@ -1,6 +1,6 @@
1
1
  ## Verification contract
2
2
 
3
- Steps in `verify.sh` are **project-specific examples** — adapt them to your stack
3
+ Steps in `har env verify` are **project-specific examples** — adapt them to your stack
4
4
  during `har env init` / `har env maintain`. The table describes each tier's intent,
5
5
  not a fixed command list.
6
6
 
@@ -14,7 +14,7 @@
14
14
  | `ecosystem.agent.template.cjs` | PM2 processes for the **primary app only** (expanded at launch) |
15
15
  | `ecosystem.shared.config.cjs` | Optional — shared app services started once with the infra (only when the repo has supporting services) |
16
16
  | `docker-compose.agent.yml` | Shared infrastructure containers (services listed in `HARNESS_INFRA_SERVICES`) |
17
- | `CLAUDE.agent.md` | Detailed instructions for coding agents |
17
+ | `.har/README.md` | Detailed instructions for coding agents |
18
18
  | `STAGES.md` | Stage registry and script-contract guide |
19
19
  | `justfile` | Optional shortcuts (requires `just`) |
20
20
 
@@ -22,7 +22,7 @@
22
22
 
23
23
  | File | Purpose |
24
24
  |------|---------|
25
- | `launch.sh` / `verify.sh` / `teardown.sh` / `setup-infra.sh` / `preflight.sh` / `agent-cli.sh` / `attach.sh` | Thin shims forwarding to the packaged runtime (`har env …`); same run records on every surface |
25
+ | `har env launch` / `har env verify` / `har env teardown` / `har env setup-infra` / `preflight.sh` / `agent-cli.sh` / `attach.sh` | Thin shims forwarding to the packaged runtime (`har env …`); same run records on every surface |
26
26
  | `manifest.json` | Runtime version, profile, checksums — managed by the har CLI |
27
27
  | `runs/` | Run history from every entry point — `.har/runs/YYYY-MM-DD/HH-mm-ss_<stageId>_agent-<id>.json` (gitignored) |
28
28
  | `artifacts/` | Stage outputs: reports, traces, screenshots, logs |
@@ -1,16 +1,27 @@
1
1
  {
2
2
  "id": "default",
3
- "description": "Web app — shared kernel + PM2 runtime + Docker infra",
3
+ "description": "Web app \u2014 shared kernel + PM2 runtime + Docker infra",
4
4
  "bundles": [
5
- { "id": "shared-kernel", "path": "runtime-bundles/shared-kernel" },
6
- { "id": "pm2-runtime", "path": "runtime-bundles/pm2-runtime" },
7
- { "id": "runtime-default", "path": "har-boilerplate" }
5
+ {
6
+ "id": "shared-kernel",
7
+ "path": "runtime-bundles/shared-kernel"
8
+ },
9
+ {
10
+ "id": "pm2-runtime",
11
+ "path": "runtime-bundles/pm2-runtime"
12
+ },
13
+ {
14
+ "id": "runtime-default",
15
+ "path": "har-boilerplate"
16
+ }
8
17
  ],
9
18
  "capabilities": {
10
19
  "processManager": "pm2",
11
20
  "appPortLanes": true,
12
21
  "infra": {
13
- "defaultServices": ["db"],
22
+ "defaultServices": [
23
+ "db"
24
+ ],
14
25
  "portLanes": "db=15432:15432-15499 minio=19000:19000-19049 minio-console=19050:19050-19099 browser=13001:13001-13099 mailpit-web=18025:18025-18099 mailpit-smtp=11025:11025-11099"
15
26
  },
16
27
  "defaultStages": [
@@ -49,22 +60,19 @@
49
60
  "intro",
50
61
  "what-s-in-here",
51
62
  "quick-start",
63
+ "environment",
52
64
  "verification-contract",
65
+ "definition-of-done",
66
+ "readiness",
53
67
  "readiness-layers",
54
68
  "run-history",
55
69
  "for-coding-agents",
70
+ "project-commands",
56
71
  "architecture",
57
72
  "port-shared-services",
73
+ "do-not",
58
74
  "maintaining-this-harness",
59
75
  "session-lifecycle"
60
- ],
61
- "CLAUDE.agent.md": [
62
- "intro",
63
- "environment",
64
- "readiness",
65
- "definition-of-done",
66
- "project-commands",
67
- "do-not"
68
76
  ]
69
77
  }
70
78
  }
@@ -1,12 +1,12 @@
1
1
  ## Definition of done
2
2
 
3
- - [ ] Full verification returns `"status": "pass"` (`har env verify ${AGENT_ID} --full`, MCP `har_run_verification` with `full: true`, or `./.har/verify.sh ${AGENT_ID} --full`)
3
+ - [ ] Full verification returns `"status": "pass"` (`har env verify <id> --full`, MCP `har_run_verification` with `full: true`, or `har env verify <id> --full`)
4
4
  - [ ] The slot is agent-usable for this repo's documented smoke workflow when runtime services are involved
5
5
  - [ ] When `stages/rocketsim-flows.sh` exists, full verify includes user-flow validation — add or update flow scripts in `flows/` for UI changes
6
6
  - [ ] New behavior has automated test coverage (unit tests via XCTest)
7
7
  - [ ] Changes committed **in the session worktree** with a clear message
8
8
  - [ ] Present session handoff (summary, branch, preview URLs) and **wait for user** before `complete`, push, or PR
9
- - [ ] On user approval of the default: push + open PR (when `gh`/GitHub MCP available), then `har env complete ${AGENT_ID}` (or MCP `har_complete_environment`) — full verify + validation + teardown, branch kept
9
+ - [ ] On user approval of the default: push + open PR (when `gh`/GitHub MCP available), then `har env complete <id>` (or MCP `har_complete_environment`) — full verify + validation + teardown, branch kept
10
10
 
11
11
  ### Session handoff
12
12
 
@@ -18,6 +18,6 @@ else as alternatives. If PR tooling is unavailable, recommend complete and repor
18
18
  the session branch for a manual push. Prefer `complete` over bare `teardown` when
19
19
  the work succeeded. See `.cursor/rules/har-workflow.mdc` for the handoff shape.
20
20
 
21
- Quick loop: MCP `har_run_verification`, `har env verify ${AGENT_ID}`, or `./.har/verify.sh ${AGENT_ID}`
21
+ Quick loop: MCP `har_run_verification`, `har env verify <id>`, or `har env verify <id>`
22
22
 
23
23
  Stages are the harness's single vocabulary for checks: templates and custom stages compile to generic kinds in `.har/stages.json`, and you interact with them only through the registry (`har_run_stage`, `verify`), never stack-specific tooling. Authoring guide: `.har/STAGES.md`.
@@ -1,6 +1,6 @@
1
1
  ## Do not
2
2
 
3
3
  - Work around a failing harness command with ad-hoc setup — fix the harness or report the failure
4
- - Edit `.env.agent.${AGENT_ID}` by hand
4
+ - Edit `.env.agent.<id>` by hand
5
5
  - Run verify before launch (the simulator and worktree must be set up first)
6
6
  - Edit the main checkout — all edits go under the session work dir
@@ -2,13 +2,13 @@
2
2
 
3
3
  | | |
4
4
  |--|--|
5
- | **Agent ID** | ${AGENT_ID} |
6
- | **Work dir** | Fresh session worktree per launch — see the launch output or `.har/slots/agent-${AGENT_ID}.json` |
7
- | **Simulator** | Created for this slot at launch — `HARNESS_SIMULATOR_UDID` in `.env.agent.${AGENT_ID}` |
5
+ | **Agent ID** | <id> |
6
+ | **Work dir** | Fresh session worktree per launch — see the launch output or `.har/slots/agent-<id>.json` |
7
+ | **Simulator** | Created for this slot at launch — `HARNESS_SIMULATOR_UDID` in `.env.agent.<id>` |
8
8
  | **Scheme** | Configured in `.har/harness.env` — `HARNESS_XCODE_SCHEME` |
9
9
 
10
10
  **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.
11
11
 
12
12
  ```bash
13
- ./.har/agent-cli.sh ${AGENT_ID} status
13
+ har env agent <id> status
14
14
  ```
@@ -9,17 +9,17 @@ Pure iOS apps have **no per-slot TCP ports** — agents build and run on a share
9
9
  | Optional backend (compose) | Per machine | `HARNESS_*_PORT_DEFAULT` for that service | Scan configured ranges in `harness.env` |
10
10
  | iOS Simulator | Per slot | One device created per agent — no harness port | None: `har-<project>-agent-<id>-<model>` is unique per slot |
11
11
 
12
- When your app talks to a local backend, read the resolved host port from `.env.agent.<id>` (set by `setup-infra.sh`) — never hardcode `15432` or similar in tests or flow scripts.
12
+ When your app talks to a local backend, read the resolved host port from `.env.agent.<id>` (set by `har env setup-infra`) — never hardcode `15432` or similar in tests or flow scripts.
13
13
 
14
14
  ### Shared vs per-slot
15
15
 
16
16
  | Resource | Model | Configuration |
17
17
  |----------|-------|---------------|
18
- | iOS Simulator | One device created per slot, deleted at teardown | `HARNESS_SIMULATOR_*`, `launch.sh` |
18
+ | iOS Simulator | One device created per slot, deleted at teardown | `HARNESS_SIMULATOR_*`, `har env launch` |
19
19
  | Optional backend | One shared compose service | `HARNESS_INFRA_SERVICES` (e.g. `"mock-server"`) |
20
20
  | Application code | Isolated git worktree per slot | `HARNESS_USE_WORKTREE=true` |
21
21
 
22
22
  ### Do not
23
23
 
24
24
  - Hardcode backend ports in RocketSim flows or unit tests — read from agent env
25
- - Run raw `docker compose` for harness infrastructure — use `setup-infra.sh`
25
+ - Run raw `docker compose` for harness infrastructure — use `har env setup-infra`
@@ -2,10 +2,10 @@
2
2
 
3
3
  Target **this slot's** simulator, never `booted` — another agent's device may also
4
4
  be booted. `HARNESS_IOS_DESTINATION` and `HARNESS_SIMULATOR_UDID` come from
5
- `.env.agent.${AGENT_ID}`.
5
+ `.env.agent.<id>`.
6
6
 
7
7
  ```bash
8
- source .env.agent.${AGENT_ID}
8
+ source .env.agent.<id>
9
9
 
10
10
  # Build
11
11
  xcodebuild build -scheme MyApp -destination "$HARNESS_IOS_DESTINATION" CODE_SIGNING_ALLOWED=NO
@@ -14,8 +14,8 @@ xcodebuild build -scheme MyApp -destination "$HARNESS_IOS_DESTINATION" CODE_SIGN
14
14
  xcodebuild test -scheme MyApp -destination "$HARNESS_IOS_DESTINATION"
15
15
 
16
16
  # Install and launch on this slot's device
17
- ./.har/agent-cli.sh ${AGENT_ID} install path/to/MyApp.app
18
- ./.har/agent-cli.sh ${AGENT_ID} launch-app
17
+ har env agent <id> install path/to/MyApp.app
18
+ har env agent <id> launch-app
19
19
  ```
20
20
 
21
21
  Adapt for your scheme — see `.har/harness.env`.
@@ -11,12 +11,6 @@ har env teardown 1
11
11
 
12
12
  In Cursor with HAR MCP configured: use `har_launch_environment`, `har_run_verification`, and `har_teardown_environment`.
13
13
 
14
- **Shell shims** (same runtime — each `./.har/*.sh` forwards to `har env`, with a pinned `npx @osfactory/har` fallback):
15
-
16
- ```bash
17
- ./.har/setup-infra.sh # boots the iOS Simulator
18
- ./.har/launch.sh 1
19
- ./.har/verify.sh 1 # quick: build smoke (compile-only)
20
- ./.har/verify.sh 1 --full # + unit tests, lint, rocketsim-flows (if installed)
21
- ./.har/teardown.sh 1
22
- ```
14
+ `./.har/*.sh` exist as compatibility shims over the same runtime — generated,
15
+ never edited, and not the way to drive the harness. Take explicit ownership of
16
+ them with `har env eject`.
@@ -12,7 +12,7 @@ store, nothing carried over from the previous session.
12
12
  | `HARNESS_SIMULATOR_NAME` | The model to create — `iPhone 16`, `iPhone 17 Pro`, `iPad Air 11-inch (M2)`. Empty means the newest model of the family. See `xcrun simctl list devicetypes`. |
13
13
  | `HARNESS_SIMULATOR_FAMILY` | `auto` (read from the name) \| `iPhone` \| `iPad`. An iPad is only created when this resolves to iPad. |
14
14
  | `HARNESS_SIMULATOR_UDID` | Run every slot on one existing device instead. Slots then share it — for one-off debugging. |
15
- | `HARNESS_SIMULATOR_SHARED` | `true` restores one shared simulator for all slots, booted by `setup-infra.sh`. |
15
+ | `HARNESS_SIMULATOR_SHARED` | `true` restores one shared simulator for all slots, booted by `har env setup-infra`. |
16
16
 
17
17
  The runtime is the newest installed iOS that supports the model — a model retired
18
18
  from recent runtimes still resolves against an older one. When nothing matches,
@@ -42,4 +42,4 @@ blaming a sandbox.
42
42
  The device lands in `.env.agent.<id>` as `HARNESS_SIMULATOR_UDID`,
43
43
  `HARNESS_SIMULATOR_DEVICE_NAME` and `HARNESS_IOS_DESTINATION` — the model stays in
44
44
  `HARNESS_SIMULATOR_NAME`, so the two never mean the same thing in one place; what a slot holds is tracked in `.har/simulators/`.
45
- Use `./.har/agent-cli.sh <id> simulator` to see it.
45
+ Use `har env agent <id> simulator` to see it.
@@ -3,9 +3,9 @@
3
3
  If the RocketSim plugin is installed (`har env add-plugin rocketsim`):
4
4
 
5
5
  ```bash
6
- ./.har/stages/rocketsim-flows.sh ${AGENT_ID}
6
+ ./.har/stages/rocketsim-flows.sh <id>
7
7
  # included in:
8
- ./.har/verify.sh ${AGENT_ID} --full
8
+ har env verify <id> --full
9
9
  ```
10
10
 
11
11
  Add and edit user flow scripts in `flows/`. Read `.har/stages/ROCKETSIM.md` for the full authoring guide.
@@ -1,6 +1,6 @@
1
1
  ## Verification contract
2
2
 
3
- Steps in `verify.sh` are **project-specific examples** — adapt them to your stack.
3
+ Steps in `har env verify` are **project-specific examples** — adapt them to your stack.
4
4
  The table describes each tier's intent, not a fixed command list.
5
5
 
6
6
  | Mode | Command | Typical steps |
@@ -11,7 +11,7 @@
11
11
  | `hooks/` | Optional lifecycle hooks (`pre-launch.sh`, `post-launch.sh`, `pre-verify.sh`, `pre-teardown.sh`, `post-teardown.sh`) |
12
12
  | `plugins/` | Optional local plugins (`har plugin create <id>`) |
13
13
  | `docker-compose.agent.yml` | Optional shared backend services |
14
- | `CLAUDE.agent.md` | Detailed instructions for coding agents |
14
+ | `.har/README.md` | Detailed instructions for coding agents |
15
15
  | `STAGES.md` | Stage registry and script-contract guide |
16
16
  | `justfile` | Optional shortcuts (requires `just`) |
17
17
 
@@ -19,7 +19,7 @@
19
19
 
20
20
  | File | Purpose |
21
21
  |------|---------|
22
- | `launch.sh` / `verify.sh` / `teardown.sh` / `setup-infra.sh` / `preflight.sh` / `agent-cli.sh` | Thin shims forwarding to the packaged runtime (`har env …`); same run records on every surface |
22
+ | `har env launch` / `har env verify` / `har env teardown` / `har env setup-infra` / `preflight.sh` / `agent-cli.sh` | Thin shims forwarding to the packaged runtime (`har env …`); same run records on every surface |
23
23
  | `manifest.json` | Runtime version, profile, checksums — managed by the har CLI |
24
24
  | `runs/` | Run history from every entry point — `.har/runs/YYYY-MM-DD/HH-mm-ss_<stageId>_agent-<id>.json` (gitignored) |
25
25
  | `artifacts/` | Stage outputs: test results, screenshots, logs |
@@ -1,9 +1,15 @@
1
1
  {
2
2
  "id": "ios",
3
- "description": "iOS — shared kernel + Xcode/Simulator overlay (simulator runtime lives in the package)",
3
+ "description": "iOS \u2014 shared kernel + Xcode/Simulator overlay (simulator runtime lives in the package)",
4
4
  "bundles": [
5
- { "id": "shared-kernel", "path": "runtime-bundles/shared-kernel" },
6
- { "id": "runtime-ios", "path": "har-boilerplate-ios" }
5
+ {
6
+ "id": "shared-kernel",
7
+ "path": "runtime-bundles/shared-kernel"
8
+ },
9
+ {
10
+ "id": "runtime-ios",
11
+ "path": "har-boilerplate-ios"
12
+ }
7
13
  ],
8
14
  "capabilities": {
9
15
  "processManager": "simulator",
@@ -45,21 +51,18 @@
45
51
  "intro",
46
52
  "what-s-in-here",
47
53
  "quick-start",
54
+ "environment",
48
55
  "user-flow-validation",
49
56
  "verification-contract",
57
+ "definition-of-done",
58
+ "readiness",
59
+ "project-commands",
60
+ "user-flow-validation-rocketsim",
50
61
  "configuration",
51
62
  "simulators",
52
63
  "port-shared-services-ios-profile",
64
+ "do-not",
53
65
  "session-lifecycle"
54
- ],
55
- "CLAUDE.agent.md": [
56
- "intro",
57
- "environment",
58
- "readiness",
59
- "definition-of-done",
60
- "project-commands",
61
- "user-flow-validation-rocketsim",
62
- "do-not"
63
66
  ]
64
67
  }
65
68
  }
@@ -5,11 +5,49 @@
5
5
  set -euo pipefail
6
6
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
7
  REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
8
- AGENT_ID="${1:?Usage: attach.sh <agent-id>}"
9
- if command -v har >/dev/null 2>&1; then
10
- exec har env agent "$AGENT_ID" attach
11
- elif [ -x "$REPO_ROOT/node_modules/.bin/har" ]; then
12
- exec "$REPO_ROOT/node_modules/.bin/har" env agent "$AGENT_ID" attach
8
+ # Loop guard (#291): a pre-1.0 har does not own this runtime kind in the
9
+ # package — it executes this script as authoritative, which would exec back
10
+ # into har forever (one node process per cycle). Trip on re-entry for this
11
+ # harness root, and skip har binaries older than the pinned runtime (#298).
12
+ HAR_SHIM_GUARD="attach@${REPO_ROOT}"
13
+ case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
14
+ echo "Error: runtime loop detected — the har CLI that ran this shim delegated back into it." >&2
15
+ echo " The har runtime handling this repo is older than the harness contract (pinned: @osfactory/har@__HAR_VERSION__)." >&2
16
+ echo " Fix: npm i -g @osfactory/har@latest # or in this repo: npm i -D @osfactory/har" >&2
17
+ exit 86
18
+ ;;
19
+ esac
20
+ export HAR_SHIM_REENTRY="${HAR_SHIM_REENTRY:-}:${HAR_SHIM_GUARD}"
21
+ # True when $1 reports a version >= the pinned runtime. Comparing only the
22
+ # major (#298) made the floor inert for the whole 0.x line: every pre-1.0 har
23
+ # passed it and then bounced straight back into this shim. Compare the full
24
+ # release triple, and treat anything unparseable as unusable.
25
+ har_runtime_compatible() {
26
+ local v pinned="__HAR_VERSION__" i a b
27
+ v="$("$1" --version 2>/dev/null | head -n1)" || return 1
28
+ v="${v#v}"
29
+ v="${v%%[-+ ]*}"
30
+ local -a have pin
31
+ IFS=. read -r -a have <<<"$v"
32
+ IFS=. read -r -a pin <<<"${pinned%%[-+]*}"
33
+ for i in 0 1 2; do
34
+ a="${have[i]:-0}"
35
+ b="${pin[i]:-0}"
36
+ case "$a" in ''|*[!0-9]*) return 1 ;; esac
37
+ case "$b" in ''|*[!0-9]*) return 1 ;; esac
38
+ [ "$a" -gt "$b" ] && return 0
39
+ [ "$a" -lt "$b" ] && return 1
40
+ done
41
+ return 0
42
+ }
43
+ # `$1` (not a named var) so `har env eject` can lift this delegate verbatim.
44
+ if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
45
+ exec har env agent "${1:?Usage: attach.sh <agent-id>}" attach
46
+ elif [ -x "$REPO_ROOT/node_modules/.bin/har" ] && har_runtime_compatible "$REPO_ROOT/node_modules/.bin/har"; then
47
+ exec "$REPO_ROOT/node_modules/.bin/har" env agent "${1:?Usage: attach.sh <agent-id>}" attach
48
+ elif command -v npx >/dev/null 2>&1; then
49
+ exec npx --yes @osfactory/har@__HAR_VERSION__ env agent "${1:?Usage: attach.sh <agent-id>}" attach
13
50
  fi
14
- echo "Error: the 'har' CLI is not available. Install @osfactory/har (npm i -D @osfactory/har) or run: npx @osfactory/har env agent" >&2
51
+ echo "Error: cannot run the HAR runtime — 'har' is not on PATH and Node.js (npx) is unavailable." >&2
52
+ echo " Install Node.js, then: npm i -D @osfactory/har # or: npx @osfactory/har@__HAR_VERSION__ env agent" >&2
15
53
  exit 127
@@ -8,7 +8,7 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
8
8
  # Loop guard (#291): a pre-1.0 har does not own this runtime kind in the
9
9
  # package — it executes this script as authoritative, which would exec back
10
10
  # into har forever (one node process per cycle). Trip on re-entry for this
11
- # harness root, and skip har binaries older than the pinned runtime's major.
11
+ # harness root, and skip har binaries older than the pinned runtime (#298).
12
12
  HAR_SHIM_GUARD="agent@${REPO_ROOT}"
13
13
  case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
14
14
  echo "Error: runtime loop detected — the har CLI that ran this shim delegated back into it." >&2
@@ -18,10 +18,27 @@ case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
18
18
  ;;
19
19
  esac
20
20
  export HAR_SHIM_REENTRY="${HAR_SHIM_REENTRY:-}:${HAR_SHIM_GUARD}"
21
+ # True when $1 reports a version >= the pinned runtime. Comparing only the
22
+ # major (#298) made the floor inert for the whole 0.x line: every pre-1.0 har
23
+ # passed it and then bounced straight back into this shim. Compare the full
24
+ # release triple, and treat anything unparseable as unusable.
21
25
  har_runtime_compatible() {
22
- local v pinned="__HAR_VERSION__"
26
+ local v pinned="__HAR_VERSION__" i a b
23
27
  v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
- [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
28
+ v="${v#v}"
29
+ v="${v%%[-+ ]*}"
30
+ local -a have pin
31
+ IFS=. read -r -a have <<<"$v"
32
+ IFS=. read -r -a pin <<<"${pinned%%[-+]*}"
33
+ for i in 0 1 2; do
34
+ a="${have[i]:-0}"
35
+ b="${pin[i]:-0}"
36
+ case "$a" in ''|*[!0-9]*) return 1 ;; esac
37
+ case "$b" in ''|*[!0-9]*) return 1 ;; esac
38
+ [ "$a" -gt "$b" ] && return 0
39
+ [ "$a" -lt "$b" ] && return 1
40
+ done
41
+ return 0
25
42
  }
26
43
  if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
44
  exec har env agent "$@"
@@ -8,7 +8,7 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
8
8
  # Loop guard (#291): a pre-1.0 har does not own this runtime kind in the
9
9
  # package — it executes this script as authoritative, which would exec back
10
10
  # into har forever (one node process per cycle). Trip on re-entry for this
11
- # harness root, and skip har binaries older than the pinned runtime's major.
11
+ # harness root, and skip har binaries older than the pinned runtime (#298).
12
12
  HAR_SHIM_GUARD="launch@${REPO_ROOT}"
13
13
  case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
14
14
  echo "Error: runtime loop detected — the har CLI that ran this shim delegated back into it." >&2
@@ -18,10 +18,27 @@ case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
18
18
  ;;
19
19
  esac
20
20
  export HAR_SHIM_REENTRY="${HAR_SHIM_REENTRY:-}:${HAR_SHIM_GUARD}"
21
+ # True when $1 reports a version >= the pinned runtime. Comparing only the
22
+ # major (#298) made the floor inert for the whole 0.x line: every pre-1.0 har
23
+ # passed it and then bounced straight back into this shim. Compare the full
24
+ # release triple, and treat anything unparseable as unusable.
21
25
  har_runtime_compatible() {
22
- local v pinned="__HAR_VERSION__"
26
+ local v pinned="__HAR_VERSION__" i a b
23
27
  v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
- [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
28
+ v="${v#v}"
29
+ v="${v%%[-+ ]*}"
30
+ local -a have pin
31
+ IFS=. read -r -a have <<<"$v"
32
+ IFS=. read -r -a pin <<<"${pinned%%[-+]*}"
33
+ for i in 0 1 2; do
34
+ a="${have[i]:-0}"
35
+ b="${pin[i]:-0}"
36
+ case "$a" in ''|*[!0-9]*) return 1 ;; esac
37
+ case "$b" in ''|*[!0-9]*) return 1 ;; esac
38
+ [ "$a" -gt "$b" ] && return 0
39
+ [ "$a" -lt "$b" ] && return 1
40
+ done
41
+ return 0
25
42
  }
26
43
  if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
44
  exec har env launch "$@"
@@ -8,7 +8,7 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
8
8
  # Loop guard (#291): a pre-1.0 har does not own this runtime kind in the
9
9
  # package — it executes this script as authoritative, which would exec back
10
10
  # into har forever (one node process per cycle). Trip on re-entry for this
11
- # harness root, and skip har binaries older than the pinned runtime's major.
11
+ # harness root, and skip har binaries older than the pinned runtime (#298).
12
12
  HAR_SHIM_GUARD="preflight@${REPO_ROOT}"
13
13
  case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
14
14
  echo "Error: runtime loop detected — the har CLI that ran this shim delegated back into it." >&2
@@ -18,10 +18,27 @@ case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
18
18
  ;;
19
19
  esac
20
20
  export HAR_SHIM_REENTRY="${HAR_SHIM_REENTRY:-}:${HAR_SHIM_GUARD}"
21
+ # True when $1 reports a version >= the pinned runtime. Comparing only the
22
+ # major (#298) made the floor inert for the whole 0.x line: every pre-1.0 har
23
+ # passed it and then bounced straight back into this shim. Compare the full
24
+ # release triple, and treat anything unparseable as unusable.
21
25
  har_runtime_compatible() {
22
- local v pinned="__HAR_VERSION__"
26
+ local v pinned="__HAR_VERSION__" i a b
23
27
  v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
- [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
28
+ v="${v#v}"
29
+ v="${v%%[-+ ]*}"
30
+ local -a have pin
31
+ IFS=. read -r -a have <<<"$v"
32
+ IFS=. read -r -a pin <<<"${pinned%%[-+]*}"
33
+ for i in 0 1 2; do
34
+ a="${have[i]:-0}"
35
+ b="${pin[i]:-0}"
36
+ case "$a" in ''|*[!0-9]*) return 1 ;; esac
37
+ case "$b" in ''|*[!0-9]*) return 1 ;; esac
38
+ [ "$a" -gt "$b" ] && return 0
39
+ [ "$a" -lt "$b" ] && return 1
40
+ done
41
+ return 0
25
42
  }
26
43
  if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
44
  exec har env preflight "$@"
@@ -8,7 +8,7 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
8
8
  # Loop guard (#291): a pre-1.0 har does not own this runtime kind in the
9
9
  # package — it executes this script as authoritative, which would exec back
10
10
  # into har forever (one node process per cycle). Trip on re-entry for this
11
- # harness root, and skip har binaries older than the pinned runtime's major.
11
+ # harness root, and skip har binaries older than the pinned runtime (#298).
12
12
  HAR_SHIM_GUARD="setup-infra@${REPO_ROOT}"
13
13
  case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
14
14
  echo "Error: runtime loop detected — the har CLI that ran this shim delegated back into it." >&2
@@ -18,10 +18,27 @@ case ":${HAR_SHIM_REENTRY:-}:" in *":${HAR_SHIM_GUARD}:"*)
18
18
  ;;
19
19
  esac
20
20
  export HAR_SHIM_REENTRY="${HAR_SHIM_REENTRY:-}:${HAR_SHIM_GUARD}"
21
+ # True when $1 reports a version >= the pinned runtime. Comparing only the
22
+ # major (#298) made the floor inert for the whole 0.x line: every pre-1.0 har
23
+ # passed it and then bounced straight back into this shim. Compare the full
24
+ # release triple, and treat anything unparseable as unusable.
21
25
  har_runtime_compatible() {
22
- local v pinned="__HAR_VERSION__"
26
+ local v pinned="__HAR_VERSION__" i a b
23
27
  v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
- [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
28
+ v="${v#v}"
29
+ v="${v%%[-+ ]*}"
30
+ local -a have pin
31
+ IFS=. read -r -a have <<<"$v"
32
+ IFS=. read -r -a pin <<<"${pinned%%[-+]*}"
33
+ for i in 0 1 2; do
34
+ a="${have[i]:-0}"
35
+ b="${pin[i]:-0}"
36
+ case "$a" in ''|*[!0-9]*) return 1 ;; esac
37
+ case "$b" in ''|*[!0-9]*) return 1 ;; esac
38
+ [ "$a" -gt "$b" ] && return 0
39
+ [ "$a" -lt "$b" ] && return 1
40
+ done
41
+ return 0
25
42
  }
26
43
  if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
44
  exec har env setup-infra "$@"