@osfactory/har 0.64.2 → 1.0.0-rc.1
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/dist/index.js +15675 -6536
- package/dist/prompts/system-authoring.md +155 -0
- package/dist/templates/adaptation-prompt-init.md +67 -43
- package/dist/templates/adaptation-prompt-maintain.md +38 -38
- package/dist/templates/agent-skills/har-maintain.md +2 -2
- package/dist/templates/agent-skills/setup-har.md +6 -4
- package/dist/templates/cursor-rule.mdc.template +3 -3
- package/dist/templates/har-boilerplate/docker-compose.agent.yml +1 -1
- package/dist/templates/har-boilerplate/harness.env +11 -155
- package/dist/templates/har-boilerplate/stages.json +51 -2
- package/dist/templates/har-boilerplate-cli/docker-compose.agent.yml +1 -1
- package/dist/templates/har-boilerplate-cli/harness.env +12 -138
- package/dist/templates/har-boilerplate-cli/stages.json +42 -2
- package/dist/templates/har-boilerplate-ios/harness.env +10 -126
- package/dist/templates/har-boilerplate-ios/stages.json +42 -2
- package/dist/templates/migration-prompt.md +54 -0
- package/dist/templates/plugins/custom-stage-skeleton.sh +11 -20
- package/dist/templates/plugins/gitleaks/.github/workflows/gitleaks.yml +1 -1
- package/dist/templates/plugins/gitleaks/.har/stages/GITLEAKS.md +1 -1
- package/dist/templates/plugins/gitleaks/.har/stages/secrets-scan.sh +8 -23
- package/dist/templates/plugins/gitleaks/README.md +1 -1
- package/dist/templates/plugins/gitleaks/template.manifest.json +20 -5
- package/dist/templates/plugins/kerno/.github/workflows/kerno.yml +1 -1
- package/dist/templates/plugins/kerno/.har/stages/backend-validation.sh +8 -23
- package/dist/templates/plugins/kerno/README.md +1 -1
- package/dist/templates/plugins/kerno/template.manifest.json +20 -9
- package/dist/templates/plugins/local-plugin-skeleton/README.md +46 -0
- package/dist/templates/plugins/playwright/.har/stages/browser-e2e.sh +8 -23
- package/dist/templates/plugins/playwright/template.manifest.json +36 -13
- package/dist/templates/plugins/rocketsim/.har/stages/rocketsim-flows.sh +8 -23
- package/dist/templates/plugins/rocketsim/template.manifest.json +20 -8
- package/dist/templates/plugins/semgrep/.har/stages/sast.sh +10 -26
- package/dist/templates/plugins/semgrep/README.md +1 -1
- package/dist/templates/plugins/semgrep/template.manifest.json +16 -7
- package/dist/templates/plugins/trivy/.har/stages/vuln-scan.sh +8 -23
- package/dist/templates/plugins/trivy/README.md +1 -1
- package/dist/templates/plugins/trivy/template.manifest.json +20 -8
- package/dist/templates/{har-boilerplate-cli/CLAUDE.agent.md → profiles/cli/docs/claude-agent/definition-of-done.md} +0 -42
- package/dist/templates/profiles/cli/docs/claude-agent/do-not.md +6 -0
- package/dist/templates/profiles/cli/docs/claude-agent/environment.md +12 -0
- package/dist/templates/profiles/cli/docs/claude-agent/project-commands.md +10 -0
- package/dist/templates/profiles/cli/docs/claude-agent/readiness.md +6 -0
- package/dist/templates/profiles/cli/docs/readme/for-coding-agents.md +9 -0
- package/dist/templates/profiles/cli/docs/readme/intro.md +7 -0
- package/dist/templates/profiles/cli/docs/readme/port-shared-services-cli-profile.md +25 -0
- package/dist/templates/profiles/cli/docs/readme/quick-start.md +24 -0
- package/dist/templates/profiles/cli/docs/readme/verification-contract.md +22 -0
- package/dist/templates/profiles/cli/docs/readme/what-s-in-here.md +27 -0
- package/dist/templates/profiles/cli/profile.manifest.json +56 -1
- package/dist/templates/profiles/default/docs/claude-agent/definition-of-done.md +24 -0
- package/dist/templates/profiles/default/docs/claude-agent/do-not.md +10 -0
- package/dist/templates/profiles/default/docs/claude-agent/environment.md +19 -0
- package/dist/templates/profiles/default/docs/claude-agent/project-commands.md +10 -0
- package/dist/templates/profiles/default/docs/claude-agent/readiness.md +12 -0
- package/dist/templates/profiles/default/docs/readme/architecture.md +11 -0
- package/dist/templates/profiles/default/docs/readme/for-coding-agents.md +9 -0
- package/dist/templates/profiles/default/docs/readme/intro.md +7 -0
- package/dist/templates/profiles/default/docs/readme/port-shared-services.md +41 -0
- package/dist/templates/profiles/default/docs/readme/quick-start.md +24 -0
- package/dist/templates/profiles/default/docs/readme/readiness-layers.md +16 -0
- package/dist/templates/profiles/default/docs/readme/verification-contract.md +17 -0
- package/dist/templates/profiles/default/docs/readme/what-s-in-here.md +28 -0
- package/dist/templates/profiles/default/profile.manifest.json +62 -1
- package/dist/templates/profiles/ios/docs/claude-agent/definition-of-done.md +23 -0
- package/dist/templates/profiles/ios/docs/claude-agent/do-not.md +6 -0
- package/dist/templates/profiles/ios/docs/claude-agent/environment.md +14 -0
- package/dist/templates/profiles/ios/docs/claude-agent/intro.md +3 -0
- package/dist/templates/profiles/ios/docs/claude-agent/project-commands.md +21 -0
- package/dist/templates/profiles/ios/docs/claude-agent/readiness.md +6 -0
- package/dist/templates/profiles/ios/docs/claude-agent/user-flow-validation-rocketsim.md +11 -0
- package/dist/templates/profiles/ios/docs/readme/configuration.md +7 -0
- package/dist/templates/profiles/ios/docs/readme/intro.md +7 -0
- package/dist/templates/profiles/ios/docs/readme/port-shared-services-ios-profile.md +25 -0
- package/dist/templates/profiles/ios/docs/readme/quick-start.md +22 -0
- package/dist/templates/profiles/ios/docs/readme/simulators.md +45 -0
- package/dist/templates/profiles/ios/docs/readme/user-flow-validation.md +9 -0
- package/dist/templates/profiles/ios/docs/readme/verification-contract.md +13 -0
- package/dist/templates/profiles/ios/docs/readme/what-s-in-here.md +27 -0
- package/dist/templates/profiles/ios/profile.manifest.json +59 -3
- package/dist/templates/runtime-bundles/pm2-runtime/attach.sh +8 -15
- package/dist/templates/runtime-bundles/pm2-runtime/env.template +1 -1
- package/dist/templates/runtime-bundles/pm2-runtime/stages/api-health.sh +9 -0
- package/dist/templates/runtime-bundles/shared-kernel/STAGES.md +32 -18
- package/dist/templates/runtime-bundles/shared-kernel/agent-cli.sh +35 -0
- package/dist/templates/runtime-bundles/shared-kernel/launch.sh +35 -0
- package/dist/templates/runtime-bundles/shared-kernel/lib/verify-runner.mjs +129 -0
- package/dist/templates/runtime-bundles/shared-kernel/preflight.sh +35 -0
- package/dist/templates/runtime-bundles/shared-kernel/setup-infra.sh +35 -0
- package/dist/templates/runtime-bundles/shared-kernel/stages/README.sh +1 -1
- package/dist/templates/runtime-bundles/shared-kernel/stages/readiness.sh +14 -0
- package/dist/templates/runtime-bundles/shared-kernel/teardown.sh +35 -0
- package/dist/templates/runtime-bundles/shared-kernel/verify.sh +35 -0
- package/dist/templates/shared-docs/claude-agent/intro.md +3 -0
- package/dist/templates/shared-docs/readme/maintaining-this-harness.md +14 -0
- package/dist/templates/shared-docs/readme/run-history.md +5 -0
- package/dist/templates/shared-docs/readme/session-lifecycle.md +20 -0
- package/package.json +1 -1
- package/dist/templates/har-boilerplate/CLAUDE.agent.md +0 -83
- package/dist/templates/har-boilerplate/README.md +0 -199
- package/dist/templates/har-boilerplate/STAGES.md +0 -99
- package/dist/templates/har-boilerplate/agent-cli.sh +0 -225
- package/dist/templates/har-boilerplate/agent-slot.sh +0 -850
- package/dist/templates/har-boilerplate/attach.sh +0 -22
- package/dist/templates/har-boilerplate/ecosystem.agent.template.cjs +0 -52
- package/dist/templates/har-boilerplate/env.template +0 -40
- package/dist/templates/har-boilerplate/launch.sh +0 -323
- package/dist/templates/har-boilerplate/preflight.sh +0 -32
- package/dist/templates/har-boilerplate/provision-toolchain.sh +0 -766
- package/dist/templates/har-boilerplate/setup-infra.sh +0 -178
- package/dist/templates/har-boilerplate/stages/README.sh +0 -11
- package/dist/templates/har-boilerplate/teardown.sh +0 -87
- package/dist/templates/har-boilerplate/verify.sh +0 -249
- package/dist/templates/har-boilerplate-cli/README.md +0 -157
- package/dist/templates/har-boilerplate-cli/STAGES.md +0 -99
- package/dist/templates/har-boilerplate-cli/agent-cli.sh +0 -160
- package/dist/templates/har-boilerplate-cli/agent-slot.sh +0 -832
- package/dist/templates/har-boilerplate-cli/launch.sh +0 -216
- package/dist/templates/har-boilerplate-cli/preflight.sh +0 -28
- package/dist/templates/har-boilerplate-cli/provision-toolchain.sh +0 -766
- package/dist/templates/har-boilerplate-cli/setup-infra.sh +0 -178
- package/dist/templates/har-boilerplate-cli/stages/README.sh +0 -11
- package/dist/templates/har-boilerplate-cli/teardown.sh +0 -66
- package/dist/templates/har-boilerplate-cli/verify.sh +0 -210
- package/dist/templates/har-boilerplate-ios/ADAPT-PROMPT.md +0 -63
- package/dist/templates/har-boilerplate-ios/CLAUDE.agent.md +0 -90
- package/dist/templates/har-boilerplate-ios/README.md +0 -173
- package/dist/templates/har-boilerplate-ios/STAGES.md +0 -99
- package/dist/templates/har-boilerplate-ios/agent-cli.sh +0 -149
- package/dist/templates/har-boilerplate-ios/agent-slot.sh +0 -479
- package/dist/templates/har-boilerplate-ios/launch.sh +0 -206
- package/dist/templates/har-boilerplate-ios/provision-toolchain.sh +0 -766
- package/dist/templates/har-boilerplate-ios/setup-infra.sh +0 -112
- package/dist/templates/har-boilerplate-ios/simulator.sh +0 -492
- package/dist/templates/har-boilerplate-ios/stages/README.sh +0 -11
- package/dist/templates/har-boilerplate-ios/teardown.sh +0 -68
- package/dist/templates/har-boilerplate-ios/verify.sh +0 -185
- package/dist/templates/runtime-bundles/pm2-runtime/README.md +0 -4
- package/dist/templates/runtime-bundles/shared-kernel/README.md +0 -3
- package/dist/templates/runtime-bundles/shared-kernel/provision-toolchain.sh +0 -766
- package/dist/templates/runtime-bundles/xcode-sim/README.md +0 -4
- package/dist/templates/runtime-bundles/xcode-sim/simulator.sh +0 -492
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
# .har — Agent Harness (iOS mobile app profile)
|
|
2
|
-
|
|
3
|
-
This directory is the **agent harness** for this iOS mobile app repository. It lets AI coding agents build, test, and validate the app in isolated git worktrees against a running iOS Simulator.
|
|
4
|
-
|
|
5
|
-
Generated and maintained by [`har`](https://github.com/os-factory/har). Run `har env maintain` when the repo stack changes.
|
|
6
|
-
|
|
7
|
-
**The harness is how you run this project.** Launch a slot to exercise the code in isolation; don't hand-roll Xcode/simulator setup. If a harness command fails, fix the harness or report it — don't silently fall back to ad-hoc commands.
|
|
8
|
-
|
|
9
|
-
## What's in here
|
|
10
|
-
|
|
11
|
-
| File | Purpose |
|
|
12
|
-
|------|---------|
|
|
13
|
-
| `README.md` | This file — index of the harness |
|
|
14
|
-
| `manifest.json` | Generator metadata (version, profile, checksums) — do not edit |
|
|
15
|
-
| `harness.env` | Shared config: Xcode scheme, simulator name, bundle ID, toolchain provisioning, infra flags |
|
|
16
|
-
| `stages.json` | Machine-readable registry of runnable harness stages |
|
|
17
|
-
| `stages/` | Optional custom stage scripts registered from `stages.json` |
|
|
18
|
-
| `runs/` | Run history from `har env` / MCP — gitignored |
|
|
19
|
-
| `artifacts/` | Stage outputs: test results, screenshots, logs |
|
|
20
|
-
| `agent-slot.sh` | Shared agent-id validation and slot registry helpers |
|
|
21
|
-
| `setup-infra.sh` | Check the toolchain; start optional Docker services |
|
|
22
|
-
| `simulator.sh` | Create, boot and delete one iOS Simulator per agent slot |
|
|
23
|
-
| `launch.sh` | Launch one agent slot (git worktree, toolchain provisioning, simulator, env file) |
|
|
24
|
-
| `provision-toolchain.sh` | Generate the Xcode project when it is a build product (Tuist / XcodeGen / CocoaPods) and write Xcode paths (`XCODEBUILD_BIN`, …) to `.env.agent.<id>` |
|
|
25
|
-
| `verify.sh` | Verification pipeline (build smoke by default; --full adds tests, lint, flows) |
|
|
26
|
-
| `teardown.sh` | Tear down one agent slot (worktree + env file) |
|
|
27
|
-
| `agent-cli.sh` | Inspect slot status, run xcodebuild commands, install/launch app |
|
|
28
|
-
| `docker-compose.agent.yml` | Optional shared backend services |
|
|
29
|
-
| `CLAUDE.agent.md` | Detailed instructions for coding agents |
|
|
30
|
-
| `justfile` | Optional shortcuts (requires `just`) |
|
|
31
|
-
|
|
32
|
-
No PM2 or web-port wiring in this profile — agents run xcodebuild commands directly in their worktree.
|
|
33
|
-
|
|
34
|
-
## Quick start
|
|
35
|
-
|
|
36
|
-
**Preferred — har CLI or MCP** (persists run history under `.har/runs/`):
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
har env launch 1
|
|
40
|
-
har env verify 1
|
|
41
|
-
har env verify 1 --full
|
|
42
|
-
har env teardown 1
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
In Cursor with HAR MCP configured: use `har_launch_environment`, `har_run_verification`, and `har_teardown_environment`.
|
|
46
|
-
|
|
47
|
-
**Shell fallback** (no CLI/MCP installed):
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
./.har/setup-infra.sh # boots the iOS Simulator
|
|
51
|
-
./.har/launch.sh 1
|
|
52
|
-
./.har/verify.sh 1 # quick: build smoke (compile-only)
|
|
53
|
-
./.har/verify.sh 1 --full # + unit tests, lint, rocketsim-flows (if installed)
|
|
54
|
-
./.har/teardown.sh 1
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## User-flow validation
|
|
58
|
-
|
|
59
|
-
Add the RocketSim plugin to get reusable UI flow validation:
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
har env add-plugin rocketsim
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
This installs `.har/stages/rocketsim-flows.sh` and a `flows/` directory. Add flow scripts under `flows/` (see `.har/stages/ROCKETSIM.md`). Full verify automatically runs all flows.
|
|
66
|
-
|
|
67
|
-
## Verification contract
|
|
68
|
-
|
|
69
|
-
Steps in `verify.sh` are **project-specific examples** — adapt them to your stack.
|
|
70
|
-
The table describes each tier's intent, not a fixed command list.
|
|
71
|
-
|
|
72
|
-
| Mode | Command | Typical steps |
|
|
73
|
-
|------|---------|---------------|
|
|
74
|
-
| Quick | `har env verify <id>` | build smoke (compile-only) |
|
|
75
|
-
| Full | `har env verify <id> --full` | + unit tests, lint, optional readiness smoke, **rocketsim-flows** when installed |
|
|
76
|
-
|
|
77
|
-
For apps that depend on local backends, auth, seeded state, or simulator flows,
|
|
78
|
-
distinguish build/test health from agent usability. Document any skipped full
|
|
79
|
-
dev setup and add a readiness command when agents need a real workflow to pass.
|
|
80
|
-
|
|
81
|
-
## Configuration
|
|
82
|
-
|
|
83
|
-
Edit **`harness.env`** to set:
|
|
84
|
-
- `HARNESS_XCODE_SCHEME` — your app's shared Xcode scheme
|
|
85
|
-
- `HARNESS_XCODE_WORKSPACE` or `HARNESS_XCODE_PROJECT` — path to the project file
|
|
86
|
-
- `HARNESS_SIMULATOR_NAME` — preferred simulator, matched by exact name
|
|
87
|
-
- `HARNESS_BUNDLE_ID` — app bundle identifier
|
|
88
|
-
|
|
89
|
-
## Simulators
|
|
90
|
-
|
|
91
|
-
Slots do not share a simulator. Each launch **creates**
|
|
92
|
-
`har-<project>-agent-<id>-<model>` — `har-storefront-agent-2-iPhone-17`, say — and
|
|
93
|
-
teardown deletes it, so two agents never collide on a destination, on an installed
|
|
94
|
-
bundle id, or on a UI session, and the simulators you use by hand are never touched.
|
|
95
|
-
Every launch also starts from a pristine device: no app installed, no leftover
|
|
96
|
-
store, nothing carried over from the previous session.
|
|
97
|
-
|
|
98
|
-
| Setting | Effect |
|
|
99
|
-
|---------|--------|
|
|
100
|
-
| `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`. |
|
|
101
|
-
| `HARNESS_SIMULATOR_FAMILY` | `auto` (read from the name) \| `iPhone` \| `iPad`. An iPad is only created when this resolves to iPad. |
|
|
102
|
-
| `HARNESS_SIMULATOR_UDID` | Run every slot on one existing device instead. Slots then share it — for one-off debugging. |
|
|
103
|
-
| `HARNESS_SIMULATOR_SHARED` | `true` restores one shared simulator for all slots, booted by `setup-infra.sh`. |
|
|
104
|
-
|
|
105
|
-
The runtime is the newest installed iOS that supports the model — a model retired
|
|
106
|
-
from recent runtimes still resolves against an older one. When nothing matches,
|
|
107
|
-
launch fails and lists the models this machine can create.
|
|
108
|
-
|
|
109
|
-
If `HARNESS_SIMULATOR_NAME` is not a model but names an existing device, that
|
|
110
|
-
device is used as-is and never deleted — how a hand-renamed simulator is targeted.
|
|
111
|
-
|
|
112
|
-
### Running from an agent sandbox
|
|
113
|
-
|
|
114
|
-
`xcrun simctl` reaches CoreSimulatorService over XPC. Coding agents that sandbox
|
|
115
|
-
their shell (Codex, Claude Code and others) usually deny that lookup, so `simctl`
|
|
116
|
-
fails while `xcodebuild` keeps working — every simulator command then dies with
|
|
117
|
-
`CoreSimulatorService connection became invalid`. Nothing is missing on the machine.
|
|
118
|
-
|
|
119
|
-
Launch and teardown say so when it happens. Either run `har env launch <id>` and
|
|
120
|
-
`har env teardown <id>` from a normal terminal and let the agent work in the
|
|
121
|
-
worktree, or grant the agent unsandboxed access to `xcrun simctl` — the escalation
|
|
122
|
-
must cover every subcommand the harness uses (`list`, `create`, `boot`,
|
|
123
|
-
`bootstatus`, `shutdown`, `delete`), not just `list`.
|
|
124
|
-
|
|
125
|
-
The same messages distinguish a second cause: if `xcrun simctl` is missing from
|
|
126
|
-
the selected developer directory — no Xcode, or `xcode-select` pointing at the
|
|
127
|
-
Command Line Tools — they say so and print the current selection instead of
|
|
128
|
-
blaming a sandbox.
|
|
129
|
-
|
|
130
|
-
The device lands in `.env.agent.<id>` as `HARNESS_SIMULATOR_UDID`,
|
|
131
|
-
`HARNESS_SIMULATOR_DEVICE_NAME` and `HARNESS_IOS_DESTINATION` — the model stays in
|
|
132
|
-
`HARNESS_SIMULATOR_NAME`, so the two never mean the same thing in one place; what a slot holds is tracked in `.har/simulators/`.
|
|
133
|
-
Use `./.har/agent-cli.sh <id> simulator` to see it.
|
|
134
|
-
|
|
135
|
-
## Port & shared services (iOS profile)
|
|
136
|
-
|
|
137
|
-
Pure iOS apps have **no per-slot TCP ports** — agents build and run on a shared iOS Simulator. Optional backend containers (mock API, etc.) use the same shared-infra model as other profiles.
|
|
138
|
-
|
|
139
|
-
### Port allocation
|
|
140
|
-
|
|
141
|
-
| Layer | Scope | Rule | On conflict |
|
|
142
|
-
|-------|-------|------|-------------|
|
|
143
|
-
| Optional backend (compose) | Per machine | `HARNESS_*_PORT_DEFAULT` for that service | Scan configured ranges in `harness.env` |
|
|
144
|
-
| iOS Simulator | Per slot | One device created per agent — no harness port | None: `har-<project>-agent-<id>-<model>` is unique per slot |
|
|
145
|
-
|
|
146
|
-
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.
|
|
147
|
-
|
|
148
|
-
### Shared vs per-slot
|
|
149
|
-
|
|
150
|
-
| Resource | Model | Configuration |
|
|
151
|
-
|----------|-------|---------------|
|
|
152
|
-
| iOS Simulator | One device created per slot, deleted at teardown | `HARNESS_SIMULATOR_*`, `launch.sh` |
|
|
153
|
-
| Optional backend | One shared compose service | `HARNESS_INFRA_SERVICES` (e.g. `"mock-server"`) |
|
|
154
|
-
| Application code | Isolated git worktree per slot | `HARNESS_USE_WORKTREE=true` |
|
|
155
|
-
|
|
156
|
-
### Do not
|
|
157
|
-
|
|
158
|
-
- Hardcode backend ports in RocketSim flows or unit tests — read from agent env
|
|
159
|
-
- Run raw `docker compose` for harness infrastructure — use `setup-infra.sh`
|
|
160
|
-
|
|
161
|
-
## Session lifecycle
|
|
162
|
-
|
|
163
|
-
Every `launch` starts a **fresh session**: a new git worktree from the **main
|
|
164
|
-
checkout's current HEAD** at
|
|
165
|
-
`~/worktrees/<base-branch>-<sha4>-har-agent-<id>-<rand4>`, on a branch of the same name.
|
|
166
|
-
Switch that checkout to your intended base before launch. The session is recorded in
|
|
167
|
-
`.har/slots/agent-<id>.json`.
|
|
168
|
-
|
|
169
|
-
- Occupied slots always block a new launch: `har env complete <id>` (or `teardown <id>`),
|
|
170
|
-
then `har env launch <id>`. A new launch never chooses `main` for you — switch the
|
|
171
|
-
main checkout to your intended base first.
|
|
172
|
-
- `teardown` removes the worktree but **keeps the session branch** for push / PR.
|
|
173
|
-
- `har env complete <id>` finishes a session: full verify + teardown, branch kept.
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
# HAR Stages — authoring guide
|
|
2
|
-
|
|
3
|
-
Stages are the harness's single vocabulary for runnable checks and lifecycle
|
|
4
|
-
actions. Everything — shipped plugins (`playwright`, `rocketsim`, `kerno`, `gitleaks`, `trivy`, `semgrep`), your
|
|
5
|
-
project's test/lint commands, bespoke validation scripts — registers in
|
|
6
|
-
`.har/stages.json` with the same schema, and agents interact with stages only
|
|
7
|
-
through that registry (CLI `har env verify`, MCP `har_run_stage` /
|
|
8
|
-
`har_run_verification`), never through stack-specific tooling.
|
|
9
|
-
|
|
10
|
-
Philosophy: *plugins install stages; agents only talk to the stage registry.*
|
|
11
|
-
|
|
12
|
-
## The registry: `.har/stages.json`
|
|
13
|
-
|
|
14
|
-
```jsonc
|
|
15
|
-
{
|
|
16
|
-
"verificationStages": ["typecheck", "unit-tests", "api-health", "browser-e2e"],
|
|
17
|
-
"stages": [
|
|
18
|
-
{
|
|
19
|
-
"id": "browser-e2e", // stable, shell-friendly slug
|
|
20
|
-
"kind": "test", // setup | launch | verify | test | inspect | reset | teardown | custom
|
|
21
|
-
"description": "Playwright E2E",
|
|
22
|
-
"script": "stages/browser-e2e.sh", // relative to .har/ — OR use "command"
|
|
23
|
-
"requiresAgentId": true, // default true for test/verify/custom kinds
|
|
24
|
-
"artifacts": [{ "path": ".har/artifacts/browser-e2e", "kind": "directory" }]
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"id": "unit-tests-fast",
|
|
28
|
-
"kind": "test",
|
|
29
|
-
"command": "npm test -- --agent {agentId}" // {agentId} is substituted at run time
|
|
30
|
-
}
|
|
31
|
-
]
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Optional stage fields: `cwd` (working directory), `env` (extra env vars),
|
|
36
|
-
`group`, `acceptsArgs` (extra CLI args the stage accepts, e.g. `["--full"]`).
|
|
37
|
-
|
|
38
|
-
## Two ways to define a stage
|
|
39
|
-
|
|
40
|
-
**Command stages** — the default for simple checks (`npm test`, `swiftlint`,
|
|
41
|
-
`make check`). One JSON entry, zero files:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
har env add-stage unit-tests-fast --custom --kind test --command "npm test" --verification
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**Script stages** — for anything that needs the slot's env, ports, or
|
|
48
|
-
artifacts. Scaffold a contract-compliant skeleton:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
har env add-stage db-integrity --custom --script --description "Check DB invariants"
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
then implement the TODO block in `.har/stages/db-integrity.sh`.
|
|
55
|
-
|
|
56
|
-
## The stage script contract
|
|
57
|
-
|
|
58
|
-
Every script under `.har/stages/` must:
|
|
59
|
-
|
|
60
|
-
1. Source `harness.env` and `agent-slot.sh` from `.har/`. Before sourcing,
|
|
61
|
-
set `SCRIPT_DIR` to the `.har/` directory (not `stages/`) — `agent-slot.sh`
|
|
62
|
-
resolves the slot registry via `$SCRIPT_DIR/slots/...`.
|
|
63
|
-
2. Take the agent slot id as `$1` (validate with `validate_agent_id`); extra
|
|
64
|
-
args may follow.
|
|
65
|
-
3. Load the slot env via `resolve_agent_env_file` and run checks from the
|
|
66
|
-
agent's work dir (`resolve_agent_work_dir`).
|
|
67
|
-
4. Write artifacts (reports, screenshots, logs) under `.har/artifacts/<id>/`.
|
|
68
|
-
5. Print **only** the normalized JSON result object on stdout
|
|
69
|
-
(`status`, `stageId`, `agent_id`, `total_ms`, …); log progress to stderr.
|
|
70
|
-
6. Exit with the real status code (0 = pass).
|
|
71
|
-
|
|
72
|
-
The scaffolded skeleton implements all of this — replace its TODO block.
|
|
73
|
-
|
|
74
|
-
## Verification membership
|
|
75
|
-
|
|
76
|
-
Listing a stage id in `verificationStages` is what includes it in
|
|
77
|
-
`har env verify <id> --full`. Ids that match a registered stage run via their
|
|
78
|
-
script/command; ids without a registry entry (e.g. `typecheck`, `api-health`)
|
|
79
|
-
are inline steps owned by `.har/verify.sh`. Lifecycle kinds
|
|
80
|
-
(`setup`/`launch`/`reset`/`teardown`/`inspect`) and `verify` itself never run
|
|
81
|
-
as part of verification, even if listed.
|
|
82
|
-
|
|
83
|
-
## Commit gate
|
|
84
|
-
|
|
85
|
-
The registry also holds the optional `commitGate` config (installed via
|
|
86
|
-
`har hooks install`): `{ "commitGate": { "mode": "block" | "warn", "scope":
|
|
87
|
-
"worktrees" | "all" } }` controls whether unverified change batches may be
|
|
88
|
-
committed.
|
|
89
|
-
|
|
90
|
-
## Shipped plugins
|
|
91
|
-
|
|
92
|
-
`har env add-plugin --list` shows available plugins; `har env add-plugin
|
|
93
|
-
playwright` (web), `har env add-plugin rocketsim` (iOS), or `har env
|
|
94
|
-
add-plugin kerno` (backend), `har env add-plugin gitleaks` (secrets scanning, any
|
|
95
|
-
stack), or `har env add-plugin trivy` (dependency + IaC security scan, any stack),
|
|
96
|
-
or `har env add-plugin semgrep` (SAST, any stack)
|
|
97
|
-
installs one. A
|
|
98
|
-
plugin is just packaging: it copies files, merges `package.json` fragments,
|
|
99
|
-
and registers stages through the exact same registry as `add-stage --custom`.
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Namespaced CLI for managing an iOS mobile app agent slot.
|
|
3
|
-
#
|
|
4
|
-
# Usage: ./.har/agent-cli.sh <agent-id> <command> [args...]
|
|
5
|
-
set -euo pipefail
|
|
6
|
-
|
|
7
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
-
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
9
|
-
|
|
10
|
-
# shellcheck source=/dev/null
|
|
11
|
-
source "$SCRIPT_DIR/harness.env"
|
|
12
|
-
# shellcheck source=/dev/null
|
|
13
|
-
source "$SCRIPT_DIR/agent-slot.sh"
|
|
14
|
-
# shellcheck source=/dev/null
|
|
15
|
-
source "$SCRIPT_DIR/simulator.sh"
|
|
16
|
-
|
|
17
|
-
AGENT_ID="${1:?Usage: agent-cli.sh <agent-id> <command> [args...]}"
|
|
18
|
-
COMMAND="${2:?Usage: agent-cli.sh <agent-id> <command> [args...]}"
|
|
19
|
-
|
|
20
|
-
validate_agent_id "$AGENT_ID"
|
|
21
|
-
|
|
22
|
-
WORKTREE_DIR="$(existing_slot_worktree "$AGENT_ID")"
|
|
23
|
-
|
|
24
|
-
# simctl target for this slot: its own device when one is reserved, else whatever
|
|
25
|
-
# is booted — never another slot's simulator.
|
|
26
|
-
slot_sim_target() {
|
|
27
|
-
local claim udid
|
|
28
|
-
claim="$(har_sim_claim_file "$AGENT_ID")"
|
|
29
|
-
if [ -f "$claim" ]; then
|
|
30
|
-
udid="$(read_slot_field "$claim" udid || true)"
|
|
31
|
-
[ -n "$udid" ] && { echo "$udid"; return; }
|
|
32
|
-
fi
|
|
33
|
-
echo "booted"
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
resolve_work_dir() {
|
|
37
|
-
local env_file
|
|
38
|
-
env_file="$(resolve_agent_env_file "$AGENT_ID" "$REPO_ROOT")" || {
|
|
39
|
-
echo "No active environment for agent ${AGENT_ID}" >&2
|
|
40
|
-
har_suggest_launch "$AGENT_ID"
|
|
41
|
-
exit 1
|
|
42
|
-
}
|
|
43
|
-
# shellcheck source=/dev/null
|
|
44
|
-
source "$env_file"
|
|
45
|
-
resolve_agent_work_dir "$env_file" "$AGENT_ID"
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
case "$COMMAND" in
|
|
49
|
-
status)
|
|
50
|
-
ENV_FILE="$(resolve_agent_env_file "$AGENT_ID" "$REPO_ROOT" || true)"
|
|
51
|
-
|
|
52
|
-
if [ -n "$ENV_FILE" ]; then
|
|
53
|
-
# shellcheck source=/dev/null
|
|
54
|
-
source "$ENV_FILE"
|
|
55
|
-
echo "Agent ${AGENT_ID}: active"
|
|
56
|
-
echo " Work dir: $(resolve_agent_work_dir "$ENV_FILE" "$AGENT_ID")"
|
|
57
|
-
[ -n "$WORKTREE_DIR" ] && [ -d "$WORKTREE_DIR" ] && echo " Worktree: $WORKTREE_DIR"
|
|
58
|
-
echo " Scheme: ${HARNESS_XCODE_SCHEME:-not set}"
|
|
59
|
-
echo " Simulator: ${HARNESS_SIMULATOR_DEVICE_NAME:-${HARNESS_SIMULATOR_NAME:-not set}} ($(slot_sim_target))"
|
|
60
|
-
echo " Bundle ID: ${HARNESS_BUNDLE_ID:-not set}"
|
|
61
|
-
else
|
|
62
|
-
echo "No active environment for agent ${AGENT_ID}"
|
|
63
|
-
har_suggest_launch "$AGENT_ID"
|
|
64
|
-
fi
|
|
65
|
-
;;
|
|
66
|
-
|
|
67
|
-
simulator)
|
|
68
|
-
# Show the device reserved for this slot, or the configured one when idle.
|
|
69
|
-
TARGET="$(slot_sim_target)"
|
|
70
|
-
if [ "$TARGET" != "booted" ]; then
|
|
71
|
-
echo "Simulator: $(har_sim_device_name "$TARGET") (${TARGET})"
|
|
72
|
-
echo "State: $(har_sim_device_state "$TARGET")"
|
|
73
|
-
echo "Reserved: $(har_sim_claim_file "$AGENT_ID")"
|
|
74
|
-
else
|
|
75
|
-
SIM_NAME="${HARNESS_SIMULATOR_NAME:-iPhone 16}"
|
|
76
|
-
echo "Simulator: ${SIM_NAME} (no device reserved — the slot is not launched)"
|
|
77
|
-
RESOLVED="$(har_sim_resolve_configured)"
|
|
78
|
-
if [ -n "$RESOLVED" ]; then
|
|
79
|
-
echo "Configured device: ${RESOLVED#*$'\t'} (${RESOLVED%%$'\t'*})"
|
|
80
|
-
else
|
|
81
|
-
echo " (no matching simulator found — check HARNESS_SIMULATOR_NAME in harness.env)"
|
|
82
|
-
fi
|
|
83
|
-
fi
|
|
84
|
-
;;
|
|
85
|
-
|
|
86
|
-
logs)
|
|
87
|
-
echo "iOS profile has no managed processes." >&2
|
|
88
|
-
echo "Use 'exec' to run project commands, or check Console.app for simulator logs." >&2
|
|
89
|
-
exit 1
|
|
90
|
-
;;
|
|
91
|
-
|
|
92
|
-
restart)
|
|
93
|
-
echo "iOS profile has no managed processes to restart." >&2
|
|
94
|
-
echo "Relaunch the slot or reinstall the app with:" >&2
|
|
95
|
-
echo " ./.har/agent-cli.sh ${AGENT_ID} install <path-to.app>" >&2
|
|
96
|
-
exit 1
|
|
97
|
-
;;
|
|
98
|
-
|
|
99
|
-
install)
|
|
100
|
-
APP_PATH="${3:-}"
|
|
101
|
-
if [ -z "$APP_PATH" ]; then
|
|
102
|
-
echo "Usage: agent-cli.sh ${AGENT_ID} install <path-to.app>" >&2
|
|
103
|
-
exit 1
|
|
104
|
-
fi
|
|
105
|
-
TARGET="$(slot_sim_target)"
|
|
106
|
-
echo "==> Installing ${APP_PATH} on ${TARGET}..."
|
|
107
|
-
xcrun simctl install "$TARGET" "$APP_PATH"
|
|
108
|
-
echo "✓ Installed"
|
|
109
|
-
;;
|
|
110
|
-
|
|
111
|
-
launch-app)
|
|
112
|
-
BUNDLE="${3:-${HARNESS_BUNDLE_ID:-}}"
|
|
113
|
-
if [ -z "$BUNDLE" ]; then
|
|
114
|
-
echo "Usage: agent-cli.sh ${AGENT_ID} launch-app [bundle-id]" >&2
|
|
115
|
-
echo " or set HARNESS_BUNDLE_ID in harness.env" >&2
|
|
116
|
-
exit 1
|
|
117
|
-
fi
|
|
118
|
-
TARGET="$(slot_sim_target)"
|
|
119
|
-
echo "==> Launching ${BUNDLE} on ${TARGET}..."
|
|
120
|
-
xcrun simctl launch "$TARGET" "$BUNDLE"
|
|
121
|
-
;;
|
|
122
|
-
|
|
123
|
-
url)
|
|
124
|
-
WORK_DIR="$(resolve_work_dir 2>/dev/null || echo "$REPO_ROOT")"
|
|
125
|
-
echo "Work dir: $WORK_DIR"
|
|
126
|
-
[ -d "$WORKTREE_DIR" ] && echo "Worktree: $WORKTREE_DIR"
|
|
127
|
-
echo "Scheme: ${HARNESS_XCODE_SCHEME:-not set}"
|
|
128
|
-
echo "Simulator: ${HARNESS_SIMULATOR_DEVICE_NAME:-${HARNESS_SIMULATOR_NAME:-not set}} ($(slot_sim_target))"
|
|
129
|
-
echo "Bundle ID: ${HARNESS_BUNDLE_ID:-not set}"
|
|
130
|
-
har_infra_enabled mock-server && echo "Mock: check docker-compose.agent.yml for port"
|
|
131
|
-
;;
|
|
132
|
-
|
|
133
|
-
exec)
|
|
134
|
-
shift 2
|
|
135
|
-
if [ $# -eq 0 ]; then
|
|
136
|
-
echo "Usage: agent-cli.sh ${AGENT_ID} exec <command>" >&2
|
|
137
|
-
exit 1
|
|
138
|
-
fi
|
|
139
|
-
WORK_DIR="$(resolve_work_dir)"
|
|
140
|
-
bash -c "cd '$WORK_DIR' && $*"
|
|
141
|
-
;;
|
|
142
|
-
|
|
143
|
-
*)
|
|
144
|
-
echo "Unknown command: $COMMAND" >&2
|
|
145
|
-
echo ""
|
|
146
|
-
echo "Commands: status, simulator, install <app>, launch-app [bundle-id], url, exec <cmd>"
|
|
147
|
-
exit 1
|
|
148
|
-
;;
|
|
149
|
-
esac
|