@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.
Files changed (141) hide show
  1. package/dist/index.js +15675 -6536
  2. package/dist/prompts/system-authoring.md +155 -0
  3. package/dist/templates/adaptation-prompt-init.md +67 -43
  4. package/dist/templates/adaptation-prompt-maintain.md +38 -38
  5. package/dist/templates/agent-skills/har-maintain.md +2 -2
  6. package/dist/templates/agent-skills/setup-har.md +6 -4
  7. package/dist/templates/cursor-rule.mdc.template +3 -3
  8. package/dist/templates/har-boilerplate/docker-compose.agent.yml +1 -1
  9. package/dist/templates/har-boilerplate/harness.env +11 -155
  10. package/dist/templates/har-boilerplate/stages.json +51 -2
  11. package/dist/templates/har-boilerplate-cli/docker-compose.agent.yml +1 -1
  12. package/dist/templates/har-boilerplate-cli/harness.env +12 -138
  13. package/dist/templates/har-boilerplate-cli/stages.json +42 -2
  14. package/dist/templates/har-boilerplate-ios/harness.env +10 -126
  15. package/dist/templates/har-boilerplate-ios/stages.json +42 -2
  16. package/dist/templates/migration-prompt.md +54 -0
  17. package/dist/templates/plugins/custom-stage-skeleton.sh +11 -20
  18. package/dist/templates/plugins/gitleaks/.github/workflows/gitleaks.yml +1 -1
  19. package/dist/templates/plugins/gitleaks/.har/stages/GITLEAKS.md +1 -1
  20. package/dist/templates/plugins/gitleaks/.har/stages/secrets-scan.sh +8 -23
  21. package/dist/templates/plugins/gitleaks/README.md +1 -1
  22. package/dist/templates/plugins/gitleaks/template.manifest.json +20 -5
  23. package/dist/templates/plugins/kerno/.github/workflows/kerno.yml +1 -1
  24. package/dist/templates/plugins/kerno/.har/stages/backend-validation.sh +8 -23
  25. package/dist/templates/plugins/kerno/README.md +1 -1
  26. package/dist/templates/plugins/kerno/template.manifest.json +20 -9
  27. package/dist/templates/plugins/local-plugin-skeleton/README.md +46 -0
  28. package/dist/templates/plugins/playwright/.har/stages/browser-e2e.sh +8 -23
  29. package/dist/templates/plugins/playwright/template.manifest.json +36 -13
  30. package/dist/templates/plugins/rocketsim/.har/stages/rocketsim-flows.sh +8 -23
  31. package/dist/templates/plugins/rocketsim/template.manifest.json +20 -8
  32. package/dist/templates/plugins/semgrep/.har/stages/sast.sh +10 -26
  33. package/dist/templates/plugins/semgrep/README.md +1 -1
  34. package/dist/templates/plugins/semgrep/template.manifest.json +16 -7
  35. package/dist/templates/plugins/trivy/.har/stages/vuln-scan.sh +8 -23
  36. package/dist/templates/plugins/trivy/README.md +1 -1
  37. package/dist/templates/plugins/trivy/template.manifest.json +20 -8
  38. package/dist/templates/{har-boilerplate-cli/CLAUDE.agent.md → profiles/cli/docs/claude-agent/definition-of-done.md} +0 -42
  39. package/dist/templates/profiles/cli/docs/claude-agent/do-not.md +6 -0
  40. package/dist/templates/profiles/cli/docs/claude-agent/environment.md +12 -0
  41. package/dist/templates/profiles/cli/docs/claude-agent/project-commands.md +10 -0
  42. package/dist/templates/profiles/cli/docs/claude-agent/readiness.md +6 -0
  43. package/dist/templates/profiles/cli/docs/readme/for-coding-agents.md +9 -0
  44. package/dist/templates/profiles/cli/docs/readme/intro.md +7 -0
  45. package/dist/templates/profiles/cli/docs/readme/port-shared-services-cli-profile.md +25 -0
  46. package/dist/templates/profiles/cli/docs/readme/quick-start.md +24 -0
  47. package/dist/templates/profiles/cli/docs/readme/verification-contract.md +22 -0
  48. package/dist/templates/profiles/cli/docs/readme/what-s-in-here.md +27 -0
  49. package/dist/templates/profiles/cli/profile.manifest.json +56 -1
  50. package/dist/templates/profiles/default/docs/claude-agent/definition-of-done.md +24 -0
  51. package/dist/templates/profiles/default/docs/claude-agent/do-not.md +10 -0
  52. package/dist/templates/profiles/default/docs/claude-agent/environment.md +19 -0
  53. package/dist/templates/profiles/default/docs/claude-agent/project-commands.md +10 -0
  54. package/dist/templates/profiles/default/docs/claude-agent/readiness.md +12 -0
  55. package/dist/templates/profiles/default/docs/readme/architecture.md +11 -0
  56. package/dist/templates/profiles/default/docs/readme/for-coding-agents.md +9 -0
  57. package/dist/templates/profiles/default/docs/readme/intro.md +7 -0
  58. package/dist/templates/profiles/default/docs/readme/port-shared-services.md +41 -0
  59. package/dist/templates/profiles/default/docs/readme/quick-start.md +24 -0
  60. package/dist/templates/profiles/default/docs/readme/readiness-layers.md +16 -0
  61. package/dist/templates/profiles/default/docs/readme/verification-contract.md +17 -0
  62. package/dist/templates/profiles/default/docs/readme/what-s-in-here.md +28 -0
  63. package/dist/templates/profiles/default/profile.manifest.json +62 -1
  64. package/dist/templates/profiles/ios/docs/claude-agent/definition-of-done.md +23 -0
  65. package/dist/templates/profiles/ios/docs/claude-agent/do-not.md +6 -0
  66. package/dist/templates/profiles/ios/docs/claude-agent/environment.md +14 -0
  67. package/dist/templates/profiles/ios/docs/claude-agent/intro.md +3 -0
  68. package/dist/templates/profiles/ios/docs/claude-agent/project-commands.md +21 -0
  69. package/dist/templates/profiles/ios/docs/claude-agent/readiness.md +6 -0
  70. package/dist/templates/profiles/ios/docs/claude-agent/user-flow-validation-rocketsim.md +11 -0
  71. package/dist/templates/profiles/ios/docs/readme/configuration.md +7 -0
  72. package/dist/templates/profiles/ios/docs/readme/intro.md +7 -0
  73. package/dist/templates/profiles/ios/docs/readme/port-shared-services-ios-profile.md +25 -0
  74. package/dist/templates/profiles/ios/docs/readme/quick-start.md +22 -0
  75. package/dist/templates/profiles/ios/docs/readme/simulators.md +45 -0
  76. package/dist/templates/profiles/ios/docs/readme/user-flow-validation.md +9 -0
  77. package/dist/templates/profiles/ios/docs/readme/verification-contract.md +13 -0
  78. package/dist/templates/profiles/ios/docs/readme/what-s-in-here.md +27 -0
  79. package/dist/templates/profiles/ios/profile.manifest.json +59 -3
  80. package/dist/templates/runtime-bundles/pm2-runtime/attach.sh +8 -15
  81. package/dist/templates/runtime-bundles/pm2-runtime/env.template +1 -1
  82. package/dist/templates/runtime-bundles/pm2-runtime/stages/api-health.sh +9 -0
  83. package/dist/templates/runtime-bundles/shared-kernel/STAGES.md +32 -18
  84. package/dist/templates/runtime-bundles/shared-kernel/agent-cli.sh +35 -0
  85. package/dist/templates/runtime-bundles/shared-kernel/launch.sh +35 -0
  86. package/dist/templates/runtime-bundles/shared-kernel/lib/verify-runner.mjs +129 -0
  87. package/dist/templates/runtime-bundles/shared-kernel/preflight.sh +35 -0
  88. package/dist/templates/runtime-bundles/shared-kernel/setup-infra.sh +35 -0
  89. package/dist/templates/runtime-bundles/shared-kernel/stages/README.sh +1 -1
  90. package/dist/templates/runtime-bundles/shared-kernel/stages/readiness.sh +14 -0
  91. package/dist/templates/runtime-bundles/shared-kernel/teardown.sh +35 -0
  92. package/dist/templates/runtime-bundles/shared-kernel/verify.sh +35 -0
  93. package/dist/templates/shared-docs/claude-agent/intro.md +3 -0
  94. package/dist/templates/shared-docs/readme/maintaining-this-harness.md +14 -0
  95. package/dist/templates/shared-docs/readme/run-history.md +5 -0
  96. package/dist/templates/shared-docs/readme/session-lifecycle.md +20 -0
  97. package/package.json +1 -1
  98. package/dist/templates/har-boilerplate/CLAUDE.agent.md +0 -83
  99. package/dist/templates/har-boilerplate/README.md +0 -199
  100. package/dist/templates/har-boilerplate/STAGES.md +0 -99
  101. package/dist/templates/har-boilerplate/agent-cli.sh +0 -225
  102. package/dist/templates/har-boilerplate/agent-slot.sh +0 -850
  103. package/dist/templates/har-boilerplate/attach.sh +0 -22
  104. package/dist/templates/har-boilerplate/ecosystem.agent.template.cjs +0 -52
  105. package/dist/templates/har-boilerplate/env.template +0 -40
  106. package/dist/templates/har-boilerplate/launch.sh +0 -323
  107. package/dist/templates/har-boilerplate/preflight.sh +0 -32
  108. package/dist/templates/har-boilerplate/provision-toolchain.sh +0 -766
  109. package/dist/templates/har-boilerplate/setup-infra.sh +0 -178
  110. package/dist/templates/har-boilerplate/stages/README.sh +0 -11
  111. package/dist/templates/har-boilerplate/teardown.sh +0 -87
  112. package/dist/templates/har-boilerplate/verify.sh +0 -249
  113. package/dist/templates/har-boilerplate-cli/README.md +0 -157
  114. package/dist/templates/har-boilerplate-cli/STAGES.md +0 -99
  115. package/dist/templates/har-boilerplate-cli/agent-cli.sh +0 -160
  116. package/dist/templates/har-boilerplate-cli/agent-slot.sh +0 -832
  117. package/dist/templates/har-boilerplate-cli/launch.sh +0 -216
  118. package/dist/templates/har-boilerplate-cli/preflight.sh +0 -28
  119. package/dist/templates/har-boilerplate-cli/provision-toolchain.sh +0 -766
  120. package/dist/templates/har-boilerplate-cli/setup-infra.sh +0 -178
  121. package/dist/templates/har-boilerplate-cli/stages/README.sh +0 -11
  122. package/dist/templates/har-boilerplate-cli/teardown.sh +0 -66
  123. package/dist/templates/har-boilerplate-cli/verify.sh +0 -210
  124. package/dist/templates/har-boilerplate-ios/ADAPT-PROMPT.md +0 -63
  125. package/dist/templates/har-boilerplate-ios/CLAUDE.agent.md +0 -90
  126. package/dist/templates/har-boilerplate-ios/README.md +0 -173
  127. package/dist/templates/har-boilerplate-ios/STAGES.md +0 -99
  128. package/dist/templates/har-boilerplate-ios/agent-cli.sh +0 -149
  129. package/dist/templates/har-boilerplate-ios/agent-slot.sh +0 -479
  130. package/dist/templates/har-boilerplate-ios/launch.sh +0 -206
  131. package/dist/templates/har-boilerplate-ios/provision-toolchain.sh +0 -766
  132. package/dist/templates/har-boilerplate-ios/setup-infra.sh +0 -112
  133. package/dist/templates/har-boilerplate-ios/simulator.sh +0 -492
  134. package/dist/templates/har-boilerplate-ios/stages/README.sh +0 -11
  135. package/dist/templates/har-boilerplate-ios/teardown.sh +0 -68
  136. package/dist/templates/har-boilerplate-ios/verify.sh +0 -185
  137. package/dist/templates/runtime-bundles/pm2-runtime/README.md +0 -4
  138. package/dist/templates/runtime-bundles/shared-kernel/README.md +0 -3
  139. package/dist/templates/runtime-bundles/shared-kernel/provision-toolchain.sh +0 -766
  140. package/dist/templates/runtime-bundles/xcode-sim/README.md +0 -4
  141. package/dist/templates/runtime-bundles/xcode-sim/simulator.sh +0 -492
@@ -1,199 +0,0 @@
1
- # .har — Agent Harness
2
-
3
- This directory is the **agent harness** for this repository. It lets AI coding agents (Cursor, Claude Code, etc.) run the project in isolated environments with their own ports, database, and verification workflow.
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.** Need the app live — manual testing, a browser session, screenshots? `launch` a slot; don't hand-roll docker/dev-server startup. 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, checksums) — do not edit |
15
- | `harness.env` | Shared config: primary app, ports, agent slot limits, `HARNESS_INFRA_SERVICES`, toolchain provisioning, migrate/seed commands |
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 only — `.har/runs/YYYY-MM-DD/HH-mm-ss_<stageId>_agent-<id>.json` (gitignore) |
19
- | `artifacts/` | Stage outputs: reports, traces, screenshots, logs |
20
- | `agent-slot.sh` | Shared agent-id validation (reads limits from `harness.env`) |
21
- | `setup-infra.sh` | Start shared Docker infra + create template database |
22
- | `launch.sh` | Launch one agent slot (ports, DB clone, toolchain provisioning, PM2 processes) |
23
- | `provision-toolchain.sh` | Install deps and write toolchain paths to `.env.agent.<id>` |
24
- | `verify.sh` | Verification pipeline (smoke by default; --full adds tests, lint, e2e) |
25
- | `teardown.sh` | Tear down one agent slot |
26
- | `agent-cli.sh` | Manage a running agent (status, logs, psql, health) |
27
- | `attach.sh` | Attach to agent tmux session |
28
- | `env.template` | Per-agent env vars (expanded by `launch.sh`) |
29
- | `ecosystem.agent.template.cjs` | PM2 processes for the **primary app only** (expanded by `launch.sh`) |
30
- | `ecosystem.shared.config.cjs` | Optional — shared app services started once by `setup-infra.sh` (only when the repo has supporting services) |
31
- | `docker-compose.agent.yml` | Shared infrastructure containers |
32
- | `CLAUDE.agent.md` | Detailed instructions for coding agents |
33
- | `justfile` | Optional shortcuts (requires `just`) |
34
-
35
- ## Quick start
36
-
37
- **Preferred — har CLI or MCP** (persists run history under `.har/runs/`):
38
-
39
- ```bash
40
- har env launch 1
41
- har env verify 1
42
- har env verify 1 --full
43
- har env teardown 1
44
- ```
45
-
46
- In Cursor with HAR MCP configured: use `har_launch_environment`, `har_run_verification`, and `har_teardown_environment`.
47
-
48
- **Shell fallback** (no CLI/MCP installed):
49
-
50
- ```bash
51
- ./.har/setup-infra.sh # when HARNESS_INFRA_SERVICES is non-empty
52
- ./.har/launch.sh 1
53
- ./.har/verify.sh 1 # quick: ecosystem smoke + health
54
- ./.har/verify.sh 1 --full # + conventional tests/lint, browser-e2e (if installed)
55
- ./.har/teardown.sh 1
56
- ```
57
-
58
- Read **`stages.json`** for registered stages and **`verificationStages`** for the expected pass set.
59
-
60
- ## Verification contract
61
-
62
- Steps in `verify.sh` are **project-specific examples** — adapt them to your stack
63
- during `har env init` / `har env maintain`. The table describes each tier's intent,
64
- not a fixed command list.
65
-
66
- | Mode | Command | Typical steps |
67
- |------|---------|---------------|
68
- | Quick | `har env verify <id>` or `verify.sh <id>` | Stock ecosystem smoke + health (stops early on failure) |
69
- | Full | `har env verify <id> --full` or `verify.sh <id> --full` | Stock conventional tests/lint, optional readiness smoke + **`browser-e2e`** when `.har/stages/browser-e2e.sh` exists |
70
-
71
- The stock commands are deliberately generic conventions keyed by
72
- `HARNESS_ECOSYSTEM`. Replace them with the repository's real commands during
73
- adaptation; do not leave Node/npm, Python, Go, Rust, Java, or Ruby defaults in
74
- place when they do not match the project.
75
-
76
- Install Playwright plugin: `har env add-plugin playwright` (optional). UI changes should add or update specs under `tests/`.
77
-
78
- ## Readiness layers
79
-
80
- Do not treat a health endpoint as the whole definition of success. Adapt this
81
- section for the repository:
82
-
83
- | Layer | What it means | Where to encode it |
84
- |-------|---------------|--------------------|
85
- | Infra ready | Shared services and template data stores exist | `setup-infra.sh`, `docker-compose.agent.yml` |
86
- | Slot data ready | Every per-slot data store is created/cloned | `launch.sh` |
87
- | Process ready | Primary app is running and health passes | `launch.sh`, `verify.sh` |
88
- | Agent usable | Login/API/UI smoke works with documented data | `HARNESS_READINESS_CMD`, browser-e2e, `CLAUDE.agent.md` |
89
-
90
- If full local-dev setup is too heavy to run in the harness, document the skipped
91
- steps and add the minimum substitute directly in `.har/` scripts (for example an
92
- idempotent bootstrap for required users/tenants/settings). Health alone is not
93
- enough for UI/auth apps.
94
-
95
- ## Run history
96
-
97
- | Entry point | Writes `.har/runs/`? |
98
- |-------------|------------------------|
99
- | `./.har/*.sh` | No — same scripts, no run record |
100
- | `har env …` / MCP | Yes — under main checkout `.har/runs/YYYY-MM-DD/` |
101
-
102
- With git worktree slots, verification runs code in the worktree but run JSON stays in the main repo `.har/runs/`. Each record includes `workDir` when a slot is active.
103
-
104
- ## For coding agents
105
-
106
- 1. Read repo [`AGENTS.md`](../AGENTS.md)
107
- 2. Read this file and `stages.json`
108
- 3. After launch, read `.har/CLAUDE.agent.md` for slot URLs and definition of done
109
-
110
- Prefer HAR MCP tools or `har env …` for launch, verify, and teardown. Use `./.har/*.sh` only when the CLI is not installed.
111
-
112
- Always use `./.har/agent-cli.sh <id> ...` — never hardcoded ports.
113
-
114
- ## Architecture
115
-
116
- Each agent slot gets isolated app ports. Defaults follow `BASE + (AGENT_ID × HARNESS_PORT_STEP)`; when a default is busy, `launch.sh` scans the slot lane (`STEP` increments) and writes the resolved ports to `.env.agent.<id>` and `.har/slots/agent-<id>.json`.
117
-
118
- Configure how many slots your machine can run in parallel in `.har/stages.json` (`agentSlots`). Bash scripts and the CLI read that first; `harness.env` keeps legacy `HARNESS_AGENT_SLOT_*` exports in sync via `har env maintain --finalize`.
119
-
120
- | Service | Agent 1 (default) | Agent 2 (default) |
121
- |---------|-------------------|-------------------|
122
- | Frontend | 3010 | 3020 |
123
- | API | 8010 | 8020 |
124
- | Node debug | 9210 | 9220 |
125
-
126
- ## Port & shared services
127
-
128
- ### Port allocation
129
-
130
- | Layer | Scope | Rule | On conflict |
131
- |-------|-------|------|-------------|
132
- | App — frontend | Per slot | `HARNESS_FE_BASE_PORT + (AGENT_ID × HARNESS_PORT_STEP)` | Scan `STEP` increments within the slot lane |
133
- | App — API | Per slot | `HARNESS_API_BASE_PORT + (AGENT_ID × STEP)` | Same scan policy |
134
- | Node debug | Per slot | `9200 + (AGENT_ID × STEP)` | Same scan policy |
135
- | Shared Postgres | Per machine | `HARNESS_DB_PORT_DEFAULT` | Scan `HARNESS_DB_PORT_SCAN_START..END` |
136
- | MinIO / S3 | Per machine | `HARNESS_MINIO_PORT_DEFAULT` (+ console port) | Scan configured ranges in `harness.env` |
137
- | Mailpit | Per machine | `HARNESS_MAILPIT_*_PORT_DEFAULT` | Scan configured ranges |
138
- | Headless browser | Per machine | `HARNESS_BROWSER_PORT_DEFAULT` | Scan configured ranges |
139
-
140
- 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.
141
-
142
- ### Shared vs per-slot
143
-
144
- | Resource | Model | Configuration |
145
- |----------|-------|---------------|
146
- | Postgres | One shared container; per-slot database `agent_<id>` cloned from template | `HARNESS_INFRA_SERVICES="db"` |
147
- | MinIO / S3 | One shared container; per-slot bucket `agent-<id>` | `HARNESS_INFRA_SERVICES="... minio"` |
148
- | Mailpit, Redis, etc. | One shared container on a scanned host port | Listed in `HARNESS_INFRA_SERVICES` |
149
- | Primary application | One PM2 ecosystem per slot (isolated ports) | `HARNESS_PRIMARY_APP`, `ecosystem.agent.template.cjs` |
150
- | Internal supporting services | Shared across all slots | `docker-compose.agent.yml` or `ecosystem.shared.config.cjs` |
151
-
152
- Shared infra starts once via `./.har/setup-infra.sh` (also run automatically by `launch.sh`). Per-slot databases are cloned in `launch.sh`.
153
-
154
- ### Do not
155
-
156
- - 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
157
- - Run raw `docker compose` for harness infrastructure — use `setup-infra.sh` / `launch.sh` so ports are scanned and persisted in `.har/state/infra.env`
158
-
159
- ### Primary app vs shared services
160
-
161
- 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:
162
-
163
- - **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`.
164
- - **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`).
165
-
166
- Isolation still applies where it matters: each slot gets its own database (`agent_<id>`, cloned from the template DB), ports, and git worktree.
167
-
168
- ## Maintaining this harness
169
-
170
- When the project stack changes (new services, different test commands, new env vars):
171
-
172
- ```bash
173
- har env maintain
174
- ```
175
-
176
- The authoring agent updates scripts and this README. Review changes before committing.
177
-
178
- **Do not** put runtime behavior in YAML — edit the scripts directly.
179
-
180
- ## Session lifecycle
181
-
182
- Every `launch` starts a **fresh session**: a new git worktree from the **main
183
- checkout's current HEAD** at
184
- `~/worktrees/<base-branch>-<sha4>-har-agent-<id>-<rand4>`, on a branch of the same name.
185
- Switch that checkout to your intended base before launch. The session is recorded in
186
- `.har/slots/agent-<id>.json` (the slot registry) — status, verify, and teardown resolve
187
- the work dir through it. Make ALL file edits under the work dir printed by launch,
188
- never in the main checkout.
189
-
190
- - Occupied slots always block a new launch: `har env complete <id>` (or `teardown <id>`),
191
- then `har env launch <id>`. A new launch never chooses `main` for you — switch the
192
- main checkout to your intended base first.
193
- - `teardown` removes the worktree but **keeps the session branch** so you can push it
194
- or open a PR (`--delete-branch` to drop it).
195
- - If launch fails after creating a worktree/env file, the registry records `status: failed`.
196
- Resume it instead of starting fresh: `har env launch <id> --resume` or `har env recover <id>`.
197
- - `har env complete <id>` finishes a session: full verify (recorded as a validation),
198
- then teardown — branch kept.
199
- - `--no-worktree` runs the slot from the repo root instead (single-agent mode).
@@ -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,225 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Namespaced CLI for managing a running agent environment.
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
-
15
- AGENT_ID="${1:?Usage: agent-cli.sh <agent-id> <command> [args...]}"
16
- COMMAND="${2:?Usage: agent-cli.sh <agent-id> <command> [args...]}"
17
-
18
- validate_agent_id "$AGENT_ID"
19
-
20
- load_agent_ports "$AGENT_ID" "$REPO_ROOT"
21
- DB_PORT="${DB_PORT:-${AGENT_DB_PORT:-${HARNESS_DB_PORT_DEFAULT:-15432}}}"
22
- export PGPASSWORD="password"
23
-
24
- PM2_SLOT_PREFIX="$(har_pm2_slot_prefix "$AGENT_ID")"
25
-
26
- case "$COMMAND" in
27
- status)
28
- ENV_FILE="$(resolve_agent_env_file "$AGENT_ID" "$REPO_ROOT" || true)"
29
- WORKTREE_DIR="$(existing_slot_worktree "$AGENT_ID")"
30
- REG_FILE="$(slot_registry_file "$AGENT_ID")"
31
- PM2_RAW=$($(har_pkg_exec) pm2 jlist 2>/dev/null || true)
32
- PM2_FOUND=false
33
- PM2_FOREIGN=false
34
- PM2_LEGACY=false
35
-
36
- if [ -n "$PM2_RAW" ]; then
37
- set +e
38
- echo "$PM2_RAW" | node -e "
39
- const agentId = '${AGENT_ID}';
40
- const project = '${HARNESS_PROJECT_NAME}';
41
- const slotPrefix = 'har-' + project + '-agent-' + agentId + '-';
42
- const legacyPrefix = 'agent-' + agentId + '-';
43
- let raw = '';
44
- process.stdin.on('data', c => raw += c);
45
- process.stdin.on('end', () => {
46
- try {
47
- const arr = JSON.parse(raw);
48
- if (!Array.isArray(arr)) process.exit(1);
49
- const owned = arr.filter(x => x.name && x.name.startsWith(slotPrefix));
50
- const foreignProject = arr.filter(x =>
51
- x.name && x.name.startsWith('har-') && x.name.includes('-agent-' + agentId + '-') && !x.name.startsWith(slotPrefix));
52
- const legacy = arr.filter(x => x.name && x.name.startsWith(legacyPrefix) && !x.name.startsWith('har-'));
53
- if (owned.length > 0) {
54
- console.log('Agent ' + agentId + ' processes (' + project + '):');
55
- owned.forEach(p => {
56
- const s = (p.pm2_env?.status || 'unknown').padEnd(10);
57
- const mem = Math.round((p.monit?.memory || 0) / 1024 / 1024) + 'MB';
58
- const cpu = (p.monit?.cpu || 0) + '%';
59
- const cwd = p.pm2_env?.pm_cwd || p.pm2_env?.cwd || '';
60
- console.log(' ' + p.name.padEnd(48) + s + ' mem=' + mem + ' cpu=' + cpu);
61
- if (cwd) console.log(' cwd: ' + cwd);
62
- });
63
- process.exit(0);
64
- }
65
- if (foreignProject.length > 0 || legacy.length > 0) {
66
- if (foreignProject.length > 0) {
67
- console.log('ERROR: foreign PM2 processes match agent ' + agentId + ' but belong to another harness:');
68
- foreignProject.forEach(p => console.log(' ' + p.name + ' cwd=' + (p.pm2_env?.pm_cwd || p.pm2_env?.cwd || 'unknown')));
69
- }
70
- if (legacy.length > 0) {
71
- console.log('ERROR: legacy PM2 processes (pre project-scoping) match agent ' + agentId + ':');
72
- legacy.forEach(p => console.log(' ' + p.name + ' cwd=' + (p.pm2_env?.pm_cwd || p.pm2_env?.cwd || 'unknown')));
73
- }
74
- process.exit(2);
75
- }
76
- process.exit(1);
77
- } catch {
78
- process.exit(1);
79
- }
80
- });
81
- "
82
- pm2_status=$?
83
- set -e
84
- case "$pm2_status" in
85
- 0) PM2_FOUND=true ;;
86
- 2) PM2_FOREIGN=true ;;
87
- esac
88
- fi
89
-
90
- if [ "$PM2_FOREIGN" = true ]; then
91
- exit 1
92
- fi
93
-
94
- if [ "$PM2_FOUND" = true ]; then
95
- if [ ! -f "$REG_FILE" ]; then
96
- echo "ERROR: slot registry missing at $REG_FILE but PM2 processes exist for this project." >&2
97
- echo " Another harness may have been torn down incorrectly, or this slot was started outside launch.sh." >&2
98
- exit 1
99
- fi
100
- REG_PROJECT="$(read_slot_field "$REG_FILE" projectName || true)"
101
- if [ -n "$REG_PROJECT" ] && [ "$REG_PROJECT" != "$HARNESS_PROJECT_NAME" ]; then
102
- echo "ERROR: slot registry projectName=${REG_PROJECT} does not match harness ${HARNESS_PROJECT_NAME}." >&2
103
- exit 1
104
- fi
105
- if [ -z "$ENV_FILE" ]; then
106
- echo "ERROR: .env.agent.${AGENT_ID} could not be resolved — teardown this slot, then relaunch." >&2
107
- exit 1
108
- fi
109
- elif [ -n "$ENV_FILE" ] && [ -f "$ENV_FILE" ]; then
110
- echo "Agent ${AGENT_ID}: active (no PM2 processes)"
111
- # shellcheck source=/dev/null
112
- source "$ENV_FILE" 2>/dev/null || true
113
- echo " Work dir: $(resolve_agent_work_dir "$ENV_FILE" "$AGENT_ID")"
114
- [ -n "$WORKTREE_DIR" ] && [ -d "$WORKTREE_DIR" ] && echo " Worktree: $WORKTREE_DIR"
115
- echo " Frontend: http://localhost:${FE_PORT}"
116
- echo " API: http://localhost:${API_PORT}"
117
- else
118
- echo "No active environment for agent ${AGENT_ID}"
119
- har_suggest_launch "$AGENT_ID"
120
- fi
121
- ;;
122
-
123
- logs)
124
- SERVICE="${3:-}"
125
- if [ -n "$SERVICE" ]; then
126
- $(har_pkg_exec) pm2 logs "${PM2_SLOT_PREFIX}-${SERVICE}" --lines 100
127
- else
128
- $(har_pkg_exec) pm2 logs --name "${PM2_SLOT_PREFIX}" --lines 100
129
- fi
130
- ;;
131
-
132
- restart)
133
- SERVICE="${3:-}"
134
- PKG_EXEC="$(har_pkg_exec)"
135
- if [ -n "$SERVICE" ]; then
136
- $(har_pkg_exec) pm2 restart "${PM2_SLOT_PREFIX}-${SERVICE}"
137
- else
138
- $(har_pkg_exec) pm2 jlist 2>/dev/null | node -e "
139
- const prefix = '${PM2_SLOT_PREFIX}-';
140
- const d = JSON.parse(require('fs').readFileSync('/dev/stdin','utf8'));
141
- const names = d.filter(x => x.name && x.name.startsWith(prefix)).map(x => x.name);
142
- names.forEach(n => require('child_process').execSync('${PKG_EXEC} pm2 restart ' + n, {stdio:'inherit'}));
143
- if (names.length === 0) console.log('No processes found for ${PM2_SLOT_PREFIX}');
144
- " 2>/dev/null || true
145
- fi
146
- ;;
147
-
148
- psql)
149
- QUERY="${3:-}"
150
- if [ -n "$QUERY" ]; then
151
- har_pg psql -d "agent_${AGENT_ID}" -c "$QUERY"
152
- else
153
- har_pg psql -d "agent_${AGENT_ID}"
154
- fi
155
- ;;
156
-
157
- health)
158
- if [ -n "${HARNESS_HEALTH_CHECK_PATH:-}" ]; then
159
- curl -sf "http://localhost:${API_PORT}${HARNESS_HEALTH_CHECK_PATH}" | node -e "
160
- const d = require('fs').readFileSync('/dev/stdin','utf8');
161
- try { console.log(JSON.stringify(JSON.parse(d), null, 2)); } catch { console.log(d); }
162
- " || curl -v "http://localhost:${API_PORT}${HARNESS_HEALTH_CHECK_PATH}"
163
- else
164
- echo "No health check path configured in harness.env"
165
- fi
166
- ;;
167
-
168
- url)
169
- echo "Frontend: http://localhost:${FE_PORT}"
170
- echo "API: http://localhost:${API_PORT}"
171
- har_infra_enabled db && echo "Database: agent_${AGENT_ID} @ localhost:${DB_PORT}"
172
- har_infra_enabled minio && echo "MinIO: http://localhost:${AGENT_MINIO_CONSOLE_PORT:-19001}"
173
- har_infra_enabled headless-browser && echo "Browser: http://localhost:${AGENT_BROWSER_PORT:-13001}"
174
- har_infra_enabled mailpit && echo "Mailpit: http://localhost:${AGENT_MAILPIT_WEB_PORT:-18025}"
175
- ;;
176
-
177
- reset-db)
178
- echo "==> Resetting database for agent ${AGENT_ID}..."
179
- har_pg psql -d postgres -c \
180
- "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='agent_${AGENT_ID}';" \
181
- >/dev/null
182
- har_pg dropdb --if-exists "agent_${AGENT_ID}"
183
- har_pg createdb -T "$HARNESS_TEMPLATE_DB" "agent_${AGENT_ID}"
184
- echo "✓ Database reset to clean state"
185
- ;;
186
-
187
- slow-queries)
188
- har_pg psql -d "agent_${AGENT_ID}" -c "
189
- SELECT round(mean_exec_time::numeric, 2) AS mean_ms,
190
- calls,
191
- left(query, 120) AS query
192
- FROM pg_stat_statements
193
- ORDER BY mean_exec_time DESC
194
- LIMIT 20;" 2>/dev/null || echo "pg_stat_statements extension not available"
195
- ;;
196
-
197
- exec)
198
- shift 2
199
- if [ $# -eq 0 ]; then
200
- echo "Usage: agent-cli.sh ${AGENT_ID} exec <command>" >&2
201
- exit 1
202
- fi
203
- WORK_DIR="$(resolve_agent_work_dir "" "$AGENT_ID" 2>/dev/null || true)"
204
- [ -n "$WORK_DIR" ] && [ -d "$WORK_DIR" ] || WORK_DIR="$REPO_ROOT"
205
- PGHOST=localhost PGPORT="$DB_PORT" PGUSER=postgres PGDATABASE="agent_${AGENT_ID}" \
206
- bash -c "cd '$WORK_DIR' && $*"
207
- ;;
208
-
209
- attach)
210
- SESSION="$(har_tmux_session "$AGENT_ID")"
211
- if ! tmux has-session -t "$SESSION" 2>/dev/null; then
212
- echo "No tmux session found: $SESSION" >&2
213
- exit 1
214
- fi
215
- tmux attach -t "$SESSION"
216
- ;;
217
-
218
- *)
219
- echo "Unknown command: $COMMAND" >&2
220
- echo ""
221
- echo "Commands: status, logs [service], restart [service], psql [query],"
222
- echo " health, url, reset-db, slow-queries, exec <cmd>, attach"
223
- exit 1
224
- ;;
225
- esac