@osfactory/har 0.64.2 → 1.0.0-rc.2

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 (142) hide show
  1. package/dist/index.js +15751 -6548
  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/adaptation-prompt-plugin.md +40 -0
  6. package/dist/templates/agent-skills/har-maintain.md +2 -2
  7. package/dist/templates/agent-skills/setup-har.md +6 -4
  8. package/dist/templates/cursor-rule.mdc.template +3 -3
  9. package/dist/templates/har-boilerplate/docker-compose.agent.yml +1 -1
  10. package/dist/templates/har-boilerplate/harness.env +11 -155
  11. package/dist/templates/har-boilerplate/stages.json +51 -2
  12. package/dist/templates/har-boilerplate-cli/docker-compose.agent.yml +1 -1
  13. package/dist/templates/har-boilerplate-cli/harness.env +12 -138
  14. package/dist/templates/har-boilerplate-cli/stages.json +42 -2
  15. package/dist/templates/har-boilerplate-ios/harness.env +10 -126
  16. package/dist/templates/har-boilerplate-ios/stages.json +42 -2
  17. package/dist/templates/migration-prompt.md +54 -0
  18. package/dist/templates/plugins/custom-stage-skeleton.sh +11 -20
  19. package/dist/templates/plugins/gitleaks/.github/workflows/gitleaks.yml +1 -1
  20. package/dist/templates/plugins/gitleaks/.har/stages/GITLEAKS.md +1 -1
  21. package/dist/templates/plugins/gitleaks/.har/stages/secrets-scan.sh +8 -23
  22. package/dist/templates/plugins/gitleaks/README.md +1 -1
  23. package/dist/templates/plugins/gitleaks/template.manifest.json +20 -5
  24. package/dist/templates/plugins/kerno/.github/workflows/kerno.yml +1 -1
  25. package/dist/templates/plugins/kerno/.har/stages/backend-validation.sh +8 -23
  26. package/dist/templates/plugins/kerno/README.md +1 -1
  27. package/dist/templates/plugins/kerno/template.manifest.json +20 -9
  28. package/dist/templates/plugins/local-plugin-skeleton/README.md +46 -0
  29. package/dist/templates/plugins/playwright/.har/stages/browser-e2e.sh +8 -23
  30. package/dist/templates/plugins/playwright/template.manifest.json +36 -13
  31. package/dist/templates/plugins/rocketsim/.har/stages/rocketsim-flows.sh +8 -23
  32. package/dist/templates/plugins/rocketsim/template.manifest.json +20 -8
  33. package/dist/templates/plugins/semgrep/.har/stages/sast.sh +10 -26
  34. package/dist/templates/plugins/semgrep/README.md +1 -1
  35. package/dist/templates/plugins/semgrep/template.manifest.json +16 -7
  36. package/dist/templates/plugins/trivy/.har/stages/vuln-scan.sh +8 -23
  37. package/dist/templates/plugins/trivy/README.md +1 -1
  38. package/dist/templates/plugins/trivy/template.manifest.json +20 -8
  39. package/dist/templates/{har-boilerplate-cli/CLAUDE.agent.md → profiles/cli/docs/claude-agent/definition-of-done.md} +0 -42
  40. package/dist/templates/profiles/cli/docs/claude-agent/do-not.md +6 -0
  41. package/dist/templates/profiles/cli/docs/claude-agent/environment.md +12 -0
  42. package/dist/templates/profiles/cli/docs/claude-agent/project-commands.md +10 -0
  43. package/dist/templates/profiles/cli/docs/claude-agent/readiness.md +6 -0
  44. package/dist/templates/profiles/cli/docs/readme/for-coding-agents.md +9 -0
  45. package/dist/templates/profiles/cli/docs/readme/intro.md +7 -0
  46. package/dist/templates/profiles/cli/docs/readme/port-shared-services-cli-profile.md +25 -0
  47. package/dist/templates/profiles/cli/docs/readme/quick-start.md +24 -0
  48. package/dist/templates/profiles/cli/docs/readme/verification-contract.md +22 -0
  49. package/dist/templates/profiles/cli/docs/readme/what-s-in-here.md +27 -0
  50. package/dist/templates/profiles/cli/profile.manifest.json +56 -1
  51. package/dist/templates/profiles/default/docs/claude-agent/definition-of-done.md +24 -0
  52. package/dist/templates/profiles/default/docs/claude-agent/do-not.md +10 -0
  53. package/dist/templates/profiles/default/docs/claude-agent/environment.md +19 -0
  54. package/dist/templates/profiles/default/docs/claude-agent/project-commands.md +10 -0
  55. package/dist/templates/profiles/default/docs/claude-agent/readiness.md +12 -0
  56. package/dist/templates/profiles/default/docs/readme/architecture.md +11 -0
  57. package/dist/templates/profiles/default/docs/readme/for-coding-agents.md +9 -0
  58. package/dist/templates/profiles/default/docs/readme/intro.md +7 -0
  59. package/dist/templates/profiles/default/docs/readme/port-shared-services.md +41 -0
  60. package/dist/templates/profiles/default/docs/readme/quick-start.md +24 -0
  61. package/dist/templates/profiles/default/docs/readme/readiness-layers.md +16 -0
  62. package/dist/templates/profiles/default/docs/readme/verification-contract.md +17 -0
  63. package/dist/templates/profiles/default/docs/readme/what-s-in-here.md +28 -0
  64. package/dist/templates/profiles/default/profile.manifest.json +62 -1
  65. package/dist/templates/profiles/ios/docs/claude-agent/definition-of-done.md +23 -0
  66. package/dist/templates/profiles/ios/docs/claude-agent/do-not.md +6 -0
  67. package/dist/templates/profiles/ios/docs/claude-agent/environment.md +14 -0
  68. package/dist/templates/profiles/ios/docs/claude-agent/intro.md +3 -0
  69. package/dist/templates/profiles/ios/docs/claude-agent/project-commands.md +21 -0
  70. package/dist/templates/profiles/ios/docs/claude-agent/readiness.md +6 -0
  71. package/dist/templates/profiles/ios/docs/claude-agent/user-flow-validation-rocketsim.md +11 -0
  72. package/dist/templates/profiles/ios/docs/readme/configuration.md +7 -0
  73. package/dist/templates/profiles/ios/docs/readme/intro.md +7 -0
  74. package/dist/templates/profiles/ios/docs/readme/port-shared-services-ios-profile.md +25 -0
  75. package/dist/templates/profiles/ios/docs/readme/quick-start.md +22 -0
  76. package/dist/templates/profiles/ios/docs/readme/simulators.md +45 -0
  77. package/dist/templates/profiles/ios/docs/readme/user-flow-validation.md +9 -0
  78. package/dist/templates/profiles/ios/docs/readme/verification-contract.md +13 -0
  79. package/dist/templates/profiles/ios/docs/readme/what-s-in-here.md +27 -0
  80. package/dist/templates/profiles/ios/profile.manifest.json +59 -3
  81. package/dist/templates/runtime-bundles/pm2-runtime/attach.sh +8 -15
  82. package/dist/templates/runtime-bundles/pm2-runtime/env.template +1 -1
  83. package/dist/templates/runtime-bundles/pm2-runtime/stages/api-health.sh +9 -0
  84. package/dist/templates/runtime-bundles/shared-kernel/STAGES.md +32 -18
  85. package/dist/templates/runtime-bundles/shared-kernel/agent-cli.sh +35 -0
  86. package/dist/templates/runtime-bundles/shared-kernel/launch.sh +35 -0
  87. package/dist/templates/runtime-bundles/shared-kernel/lib/verify-runner.mjs +129 -0
  88. package/dist/templates/runtime-bundles/shared-kernel/preflight.sh +35 -0
  89. package/dist/templates/runtime-bundles/shared-kernel/setup-infra.sh +35 -0
  90. package/dist/templates/runtime-bundles/shared-kernel/stages/README.sh +1 -1
  91. package/dist/templates/runtime-bundles/shared-kernel/stages/readiness.sh +14 -0
  92. package/dist/templates/runtime-bundles/shared-kernel/teardown.sh +35 -0
  93. package/dist/templates/runtime-bundles/shared-kernel/verify.sh +35 -0
  94. package/dist/templates/shared-docs/claude-agent/intro.md +3 -0
  95. package/dist/templates/shared-docs/readme/maintaining-this-harness.md +14 -0
  96. package/dist/templates/shared-docs/readme/run-history.md +5 -0
  97. package/dist/templates/shared-docs/readme/session-lifecycle.md +20 -0
  98. package/package.json +1 -1
  99. package/dist/templates/har-boilerplate/CLAUDE.agent.md +0 -83
  100. package/dist/templates/har-boilerplate/README.md +0 -199
  101. package/dist/templates/har-boilerplate/STAGES.md +0 -99
  102. package/dist/templates/har-boilerplate/agent-cli.sh +0 -225
  103. package/dist/templates/har-boilerplate/agent-slot.sh +0 -850
  104. package/dist/templates/har-boilerplate/attach.sh +0 -22
  105. package/dist/templates/har-boilerplate/ecosystem.agent.template.cjs +0 -52
  106. package/dist/templates/har-boilerplate/env.template +0 -40
  107. package/dist/templates/har-boilerplate/launch.sh +0 -323
  108. package/dist/templates/har-boilerplate/preflight.sh +0 -32
  109. package/dist/templates/har-boilerplate/provision-toolchain.sh +0 -766
  110. package/dist/templates/har-boilerplate/setup-infra.sh +0 -178
  111. package/dist/templates/har-boilerplate/stages/README.sh +0 -11
  112. package/dist/templates/har-boilerplate/teardown.sh +0 -87
  113. package/dist/templates/har-boilerplate/verify.sh +0 -249
  114. package/dist/templates/har-boilerplate-cli/README.md +0 -157
  115. package/dist/templates/har-boilerplate-cli/STAGES.md +0 -99
  116. package/dist/templates/har-boilerplate-cli/agent-cli.sh +0 -160
  117. package/dist/templates/har-boilerplate-cli/agent-slot.sh +0 -832
  118. package/dist/templates/har-boilerplate-cli/launch.sh +0 -216
  119. package/dist/templates/har-boilerplate-cli/preflight.sh +0 -28
  120. package/dist/templates/har-boilerplate-cli/provision-toolchain.sh +0 -766
  121. package/dist/templates/har-boilerplate-cli/setup-infra.sh +0 -178
  122. package/dist/templates/har-boilerplate-cli/stages/README.sh +0 -11
  123. package/dist/templates/har-boilerplate-cli/teardown.sh +0 -66
  124. package/dist/templates/har-boilerplate-cli/verify.sh +0 -210
  125. package/dist/templates/har-boilerplate-ios/ADAPT-PROMPT.md +0 -63
  126. package/dist/templates/har-boilerplate-ios/CLAUDE.agent.md +0 -90
  127. package/dist/templates/har-boilerplate-ios/README.md +0 -173
  128. package/dist/templates/har-boilerplate-ios/STAGES.md +0 -99
  129. package/dist/templates/har-boilerplate-ios/agent-cli.sh +0 -149
  130. package/dist/templates/har-boilerplate-ios/agent-slot.sh +0 -479
  131. package/dist/templates/har-boilerplate-ios/launch.sh +0 -206
  132. package/dist/templates/har-boilerplate-ios/provision-toolchain.sh +0 -766
  133. package/dist/templates/har-boilerplate-ios/setup-infra.sh +0 -112
  134. package/dist/templates/har-boilerplate-ios/simulator.sh +0 -492
  135. package/dist/templates/har-boilerplate-ios/stages/README.sh +0 -11
  136. package/dist/templates/har-boilerplate-ios/teardown.sh +0 -68
  137. package/dist/templates/har-boilerplate-ios/verify.sh +0 -185
  138. package/dist/templates/runtime-bundles/pm2-runtime/README.md +0 -4
  139. package/dist/templates/runtime-bundles/shared-kernel/README.md +0 -3
  140. package/dist/templates/runtime-bundles/shared-kernel/provision-toolchain.sh +0 -766
  141. package/dist/templates/runtime-bundles/xcode-sim/README.md +0 -4
  142. package/dist/templates/runtime-bundles/xcode-sim/simulator.sh +0 -492
@@ -38,32 +38,36 @@ Optional stage fields: `cwd` (working directory), `env` (extra env vars),
38
38
  ## Two ways to define a stage
39
39
 
40
40
  **Command stages** — the default for simple checks (`npm test`, `swiftlint`,
41
- `make check`). One JSON entry, zero files:
41
+ `make check`). One JSON entry in `.har/stages.json`, zero files:
42
42
 
43
- ```bash
44
- har env add-stage unit-tests-fast --custom --kind test --command "npm test" --verification
43
+ ```json
44
+ { "id": "unit-tests-fast", "kind": "test", "command": "npm test", "tier": "quick" }
45
45
  ```
46
46
 
47
+ (add the id to `verificationStages` to run it during verify).
48
+
47
49
  **Script stages** — for anything that needs the slot's env, ports, or
48
- artifacts. Scaffold a contract-compliant skeleton:
50
+ artifacts. Scaffold a project-owned plugin with a contract-compliant skeleton:
49
51
 
50
52
  ```bash
51
- har env add-stage db-integrity --custom --script --description "Check DB invariants"
53
+ har plugin create db-integrity --description "Check DB invariants"
54
+ har env add-plugin db-integrity
52
55
  ```
53
56
 
54
- then implement the TODO block in `.har/stages/db-integrity.sh`.
57
+ then implement the TODO block in `.har/plugins/db-integrity/stages/db-integrity.sh`
58
+ and reinstall with `har env add-plugin db-integrity --force`.
55
59
 
56
60
  ## The stage script contract
57
61
 
58
62
  Every script under `.har/stages/` must:
59
63
 
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`).
64
+ 1. Assume the 1.0 stage surface: the runner exports `WORK_DIR`, `ENV_FILE`,
65
+ `AGENT_ID` and `HAR_HARNESS_DIR`, with `harness.env` and the slot env file
66
+ already sourced. Never source `agent-slot.sh` — it is retired in 1.0.
67
+ 2. Take the agent slot id as `$1`, falling back to the exported `AGENT_ID`
68
+ (`AGENT_ID="${1:-${AGENT_ID:?...}}"`); extra args may follow.
69
+ 3. Guard the runner contract with `${ENV_FILE:?...}` / `${WORK_DIR:?...}`
70
+ (pointing at `./.har/launch.sh <id>`) and run checks from `$WORK_DIR`.
67
71
  4. Write artifacts (reports, screenshots, logs) under `.har/artifacts/<id>/`.
68
72
  5. Print **only** the normalized JSON result object on stdout
69
73
  (`status`, `stageId`, `agent_id`, `total_ms`, …); log progress to stderr.
@@ -73,10 +77,17 @@ The scaffolded skeleton implements all of this — replace its TODO block.
73
77
 
74
78
  ## Verification membership
75
79
 
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
+ `verificationStages` is the single namespace for the verification pipeline:
81
+ every id listed must resolve to a registered stage of kind `test` or `custom`,
82
+ and the list order is the execution order. There are no inline steps — the
83
+ ecosystem defaults (`typecheck`, `unit-tests`, `lint`, `readiness`, and
84
+ `api-health` on web profiles) are ordinary registered stages, written at init
85
+ from `HARNESS_ECOSYSTEM`.
86
+
87
+ Each stage may declare `"tier": "quick" | "full"` (default `full`). Plain
88
+ `har env verify <id>` runs the `quick`-tier stages; `--full` runs the whole
89
+ list. Unresolvable ids are reported by validation (and `har env doctor`) and
90
+ skipped with a warning at run time. Lifecycle kinds
80
91
  (`setup`/`launch`/`reset`/`teardown`/`inspect`) and `verify` itself never run
81
92
  as part of verification, even if listed.
82
93
 
@@ -96,4 +107,7 @@ stack), or `har env add-plugin trivy` (dependency + IaC security scan, any stack
96
107
  or `har env add-plugin semgrep` (SAST, any stack)
97
108
  installs one. A
98
109
  plugin is just packaging: it copies files, merges `package.json` fragments,
99
- and registers stages through the exact same registry as `add-stage --custom`.
110
+ and registers stages through the exact same registry as everything else.
111
+ Project-owned plugins live in `.har/plugins/<id>/` (`har plugin create <id>`)
112
+ and install from any of four sources — bundled, local, npm, or git — with the
113
+ same format.
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # Namespaced CLI for managing a running agent environment.
3
+ # The runtime lives in the HAR package (#234) — this file only forwards to it.
4
+ # Usage: ./.har/agent-cli.sh <agent-id> <command> [args...]
5
+ set -euo pipefail
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
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's major.
12
+ HAR_SHIM_GUARD="agent@${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
+ har_runtime_compatible() {
22
+ local v pinned="__HAR_VERSION__"
23
+ v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
+ [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
25
+ }
26
+ if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
+ exec har env agent "$@"
28
+ elif [ -x "$REPO_ROOT/node_modules/.bin/har" ] && har_runtime_compatible "$REPO_ROOT/node_modules/.bin/har"; then
29
+ exec "$REPO_ROOT/node_modules/.bin/har" env agent "$@"
30
+ elif command -v npx >/dev/null 2>&1; then
31
+ exec npx --yes @osfactory/har@__HAR_VERSION__ env agent "$@"
32
+ fi
33
+ echo "Error: cannot run the HAR runtime — 'har' is not on PATH and Node.js (npx) is unavailable." >&2
34
+ echo " Install Node.js, then: npm i -D @osfactory/har # or: npx @osfactory/har@__HAR_VERSION__ env agent" >&2
35
+ exit 127
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # Launch an isolated agent environment slot (fresh suffixed worktree; occupied slots block).
3
+ # The runtime lives in the HAR package (#234) — this file only forwards to it.
4
+ # Usage: ./.har/launch.sh <agent-id> [--no-worktree] [--resume]
5
+ set -euo pipefail
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
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's major.
12
+ HAR_SHIM_GUARD="launch@${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
+ har_runtime_compatible() {
22
+ local v pinned="__HAR_VERSION__"
23
+ v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
+ [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
25
+ }
26
+ if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
+ exec har env launch "$@"
28
+ elif [ -x "$REPO_ROOT/node_modules/.bin/har" ] && har_runtime_compatible "$REPO_ROOT/node_modules/.bin/har"; then
29
+ exec "$REPO_ROOT/node_modules/.bin/har" env launch "$@"
30
+ elif command -v npx >/dev/null 2>&1; then
31
+ exec npx --yes @osfactory/har@__HAR_VERSION__ env launch "$@"
32
+ fi
33
+ echo "Error: cannot run the HAR runtime — 'har' is not on PATH and Node.js (npx) is unavailable." >&2
34
+ echo " Install Node.js, then: npm i -D @osfactory/har # or: npx @osfactory/har@__HAR_VERSION__ env launch" >&2
35
+ exit 127
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+ // Verification runner: executes the stages.json verification plan.
3
+ // Invoked by .har/verify.sh after it sources harness.env and the agent env
4
+ // file (so the full slot environment is inherited). Replaces the bash
5
+ // run_step/run_http_step/RESULTS_JSON plumbing: step names may contain any
6
+ // characters, no result is ever silently dropped, and stage env vars are
7
+ // passed as real environment entries instead of eval'd shell prefixes.
8
+ //
9
+ // Usage: verify-runner.mjs --agent <id> [--full]
10
+ // Env: HAR_HARNESS_DIR (the .har dir), WORK_DIR (step cwd)
11
+ //
12
+ // Contract (stdout): { status, agent_id, total_ms, stages: [{name, pass, ms, output?}] }
13
+ // Quick mode stops at the first failing step; full mode runs the whole plan.
14
+
15
+ import { spawnSync } from 'node:child_process';
16
+ import { readFileSync } from 'node:fs';
17
+ import { resolve, join } from 'node:path';
18
+
19
+ const RUNNABLE_KINDS = new Set(['test', 'custom']);
20
+
21
+ const args = process.argv.slice(2);
22
+ const full = args.includes('--full');
23
+ const agentIdx = args.indexOf('--agent');
24
+ const agentId = agentIdx >= 0 ? Number(args[agentIdx + 1]) : NaN;
25
+ if (!Number.isInteger(agentId)) {
26
+ process.stderr.write('verify-runner: --agent <id> is required\n');
27
+ process.exit(2);
28
+ }
29
+
30
+ const harnessDir = process.env.HAR_HARNESS_DIR;
31
+ const workDir = process.env.WORK_DIR;
32
+ if (!harnessDir || !workDir) {
33
+ process.stderr.write('verify-runner: HAR_HARNESS_DIR and WORK_DIR must be set\n');
34
+ process.exit(2);
35
+ }
36
+
37
+ let registry;
38
+ try {
39
+ registry = JSON.parse(readFileSync(join(harnessDir, 'stages.json'), 'utf8'));
40
+ } catch (err) {
41
+ process.stderr.write(`verify-runner: cannot read ${join(harnessDir, 'stages.json')}: ${err.message}\n`);
42
+ process.exit(2);
43
+ }
44
+
45
+ const ids = Array.isArray(registry.verificationStages) ? registry.verificationStages : [];
46
+ const stages = Array.isArray(registry.stages) ? registry.stages : [];
47
+
48
+ const plan = [];
49
+ const phantoms = [];
50
+ for (const id of ids) {
51
+ const stage = stages.find((s) => s && s.id === id);
52
+ if (!stage || !RUNNABLE_KINDS.has(stage.kind)) {
53
+ phantoms.push(id);
54
+ continue;
55
+ }
56
+ if (!full && stage.tier !== 'quick') continue;
57
+ plan.push(stage);
58
+ }
59
+
60
+ for (const id of phantoms) {
61
+ process.stderr.write(
62
+ ` ! verificationStages id "${id}" has no registered runnable stage — fix .har/stages.json (har env doctor reports this)\n`,
63
+ );
64
+ }
65
+
66
+ function stepCommand(stage) {
67
+ if (stage.script) {
68
+ const script = resolve(harnessDir, stage.script);
69
+ const quoted = `'${script.replace(/'/g, "'\\''")}'`;
70
+ return stage.requiresAgentId === false ? quoted : `${quoted} ${agentId}`;
71
+ }
72
+ if (stage.command) {
73
+ return stage.command.split('{agentId}').join(String(agentId));
74
+ }
75
+ return null;
76
+ }
77
+
78
+ const results = [];
79
+ let overallPass = true;
80
+ const startTotal = Date.now();
81
+
82
+ for (const stage of plan) {
83
+ const cmd = stepCommand(stage);
84
+ if (cmd === null) {
85
+ results.push({ name: stage.id, pass: false, ms: 0, output: 'stage has neither script nor command' });
86
+ overallPass = false;
87
+ if (!full) break;
88
+ continue;
89
+ }
90
+
91
+ process.stderr.write(` → ${`${stage.id}...`.padEnd(40)}`);
92
+ const start = Date.now();
93
+ const child = spawnSync('bash', ['-c', cmd], {
94
+ cwd: stage.cwd ? resolve(workDir, stage.cwd) : workDir,
95
+ env: { ...process.env, ...(stage.env ?? {}), HAR_AGENT_ID: String(agentId) },
96
+ encoding: 'utf8',
97
+ maxBuffer: 64 * 1024 * 1024,
98
+ });
99
+ const ms = Date.now() - start;
100
+ const output = `${child.stdout ?? ''}${child.stderr ?? ''}`.trim();
101
+ const pass = child.status === 0;
102
+
103
+ if (pass) {
104
+ process.stderr.write(`✓ (${ms}ms)\n`);
105
+ results.push({ name: stage.id, pass: true, ms });
106
+ } else {
107
+ process.stderr.write(`✗ (${ms}ms)\n`);
108
+ for (const line of output.split('\n').slice(0, 30)) {
109
+ process.stderr.write(` ${line}\n`);
110
+ }
111
+ results.push({
112
+ name: stage.id,
113
+ pass: false,
114
+ ms,
115
+ output: output.split('\n').slice(0, 50).join('\n'),
116
+ });
117
+ overallPass = false;
118
+ if (!full) break;
119
+ }
120
+ }
121
+
122
+ const out = {
123
+ status: overallPass && results.length > 0 ? 'pass' : 'fail',
124
+ agent_id: agentId,
125
+ total_ms: Date.now() - startTotal,
126
+ stages: results,
127
+ };
128
+ process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
129
+ process.exit(out.status === 'pass' ? 0 : 1);
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # Launch readiness gate — run before launch.sh or standalone.
3
+ # The runtime lives in the HAR package (#234) — this file only forwards to it.
4
+ # Usage: ./.har/preflight.sh <agent-id>
5
+ set -euo pipefail
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
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's major.
12
+ HAR_SHIM_GUARD="preflight@${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
+ har_runtime_compatible() {
22
+ local v pinned="__HAR_VERSION__"
23
+ v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
+ [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
25
+ }
26
+ if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
+ exec har env preflight "$@"
28
+ elif [ -x "$REPO_ROOT/node_modules/.bin/har" ] && har_runtime_compatible "$REPO_ROOT/node_modules/.bin/har"; then
29
+ exec "$REPO_ROOT/node_modules/.bin/har" env preflight "$@"
30
+ elif command -v npx >/dev/null 2>&1; then
31
+ exec npx --yes @osfactory/har@__HAR_VERSION__ env preflight "$@"
32
+ fi
33
+ echo "Error: cannot run the HAR runtime — 'har' is not on PATH and Node.js (npx) is unavailable." >&2
34
+ echo " Install Node.js, then: npm i -D @osfactory/har # or: npx @osfactory/har@__HAR_VERSION__ env preflight" >&2
35
+ exit 127
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # Set up shared infrastructure for all agent slots. Idempotent.
3
+ # The runtime lives in the HAR package (#234) — this file only forwards to it.
4
+ # Usage: ./.har/setup-infra.sh
5
+ set -euo pipefail
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
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's major.
12
+ HAR_SHIM_GUARD="setup-infra@${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
+ har_runtime_compatible() {
22
+ local v pinned="__HAR_VERSION__"
23
+ v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
+ [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
25
+ }
26
+ if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
+ exec har env setup-infra "$@"
28
+ elif [ -x "$REPO_ROOT/node_modules/.bin/har" ] && har_runtime_compatible "$REPO_ROOT/node_modules/.bin/har"; then
29
+ exec "$REPO_ROOT/node_modules/.bin/har" env setup-infra "$@"
30
+ elif command -v npx >/dev/null 2>&1; then
31
+ exec npx --yes @osfactory/har@__HAR_VERSION__ env setup-infra "$@"
32
+ fi
33
+ echo "Error: cannot run the HAR runtime — 'har' is not on PATH and Node.js (npx) is unavailable." >&2
34
+ echo " Install Node.js, then: npm i -D @osfactory/har # or: npx @osfactory/har@__HAR_VERSION__ env setup-infra" >&2
35
+ exit 127
@@ -5,7 +5,7 @@
5
5
  # command vs script stages, and how verificationStages controls verify --full.
6
6
  #
7
7
  # Scaffold a new one with:
8
- # har env add-stage <id> --custom --script
8
+ # har plugin create <id> # then: har env add-plugin <id>
9
9
 
10
10
  echo "Add stage scripts under .har/stages/ and register them in stages.json — see .har/STAGES.md." >&2
11
11
  exit 1
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env bash
2
+ # Project readiness smoke: runs HARNESS_READINESS_CMD from harness.env, an
3
+ # optional project-owned "agent usable" check beyond health. Registered as the
4
+ # `readiness` verification stage (tier: full).
5
+ set -euo pipefail
6
+
7
+ AGENT_ID="${1:?Usage: readiness.sh <agent-id>}"
8
+
9
+ if [ -z "${HARNESS_READINESS_CMD:-}" ]; then
10
+ echo "No HARNESS_READINESS_CMD configured; skipping readiness smoke."
11
+ exit 0
12
+ fi
13
+
14
+ eval "${HARNESS_READINESS_CMD//\{agentId\}/$AGENT_ID}"
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # Tear down one agent slot: stop processes, release resources, keep the session branch.
3
+ # The runtime lives in the HAR package (#234) — this file only forwards to it.
4
+ # Usage: ./.har/teardown.sh <agent-id> [--delete-branch]
5
+ set -euo pipefail
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
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's major.
12
+ HAR_SHIM_GUARD="teardown@${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
+ har_runtime_compatible() {
22
+ local v pinned="__HAR_VERSION__"
23
+ v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
+ [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
25
+ }
26
+ if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
+ exec har env teardown "$@"
28
+ elif [ -x "$REPO_ROOT/node_modules/.bin/har" ] && har_runtime_compatible "$REPO_ROOT/node_modules/.bin/har"; then
29
+ exec "$REPO_ROOT/node_modules/.bin/har" env teardown "$@"
30
+ elif command -v npx >/dev/null 2>&1; then
31
+ exec npx --yes @osfactory/har@__HAR_VERSION__ env teardown "$@"
32
+ fi
33
+ echo "Error: cannot run the HAR runtime — 'har' is not on PATH and Node.js (npx) is unavailable." >&2
34
+ echo " Install Node.js, then: npm i -D @osfactory/har # or: npx @osfactory/har@__HAR_VERSION__ env teardown" >&2
35
+ exit 127
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # Verification pipeline (stages.json verificationStages; quick by default, --full for the whole list).
3
+ # The runtime lives in the HAR package (#234) — this file only forwards to it.
4
+ # Usage: ./.har/verify.sh <agent-id> [--full] [--json] (human output; pass --json for the structured result)
5
+ set -euo pipefail
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
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's major.
12
+ HAR_SHIM_GUARD="verify@${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
+ har_runtime_compatible() {
22
+ local v pinned="__HAR_VERSION__"
23
+ v="$("$1" --version 2>/dev/null | head -n1)" || return 1
24
+ [ "${v%%.*}" -ge "${pinned%%.*}" ] 2>/dev/null
25
+ }
26
+ if command -v har >/dev/null 2>&1 && har_runtime_compatible har; then
27
+ exec har env verify "$@"
28
+ elif [ -x "$REPO_ROOT/node_modules/.bin/har" ] && har_runtime_compatible "$REPO_ROOT/node_modules/.bin/har"; then
29
+ exec "$REPO_ROOT/node_modules/.bin/har" env verify "$@"
30
+ elif command -v npx >/dev/null 2>&1; then
31
+ exec npx --yes @osfactory/har@__HAR_VERSION__ env verify "$@"
32
+ fi
33
+ echo "Error: cannot run the HAR runtime — 'har' is not on PATH and Node.js (npx) is unavailable." >&2
34
+ echo " Install Node.js, then: npm i -D @osfactory/har # or: npx @osfactory/har@__HAR_VERSION__ env verify" >&2
35
+ exit 127
@@ -0,0 +1,3 @@
1
+ # Agent ${AGENT_ID} — Development Environment
2
+
3
+ > [`AGENTS.md`](../AGENTS.md) · [`.har/README.md`](./README.md) · [`stages.json`](./stages.json)
@@ -0,0 +1,14 @@
1
+ ## Maintaining this harness
2
+
3
+ When the project stack changes (new services, different test commands, new env vars):
4
+
5
+ ```bash
6
+ har env maintain
7
+ ```
8
+
9
+ The authoring agent reconciles the config surface and this README. Review changes before committing.
10
+
11
+ Customize through the contract — config (`harness.env`), stages (`stages.json` +
12
+ `stages/`), hooks (`hooks/`), plugins (`plugins/`). The `*.sh` files are generated
13
+ shims over the packaged runtime: don't edit them (`har env eject` exists for full
14
+ ownership). `har env doctor` validates the result.
@@ -0,0 +1,5 @@
1
+ ## Run history
2
+
3
+ Every entry point — `./.har/*.sh`, `har env …`, MCP — runs the same packaged runtime and writes the same records under the main checkout `.har/runs/YYYY-MM-DD/`.
4
+
5
+ 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.
@@ -0,0 +1,20 @@
1
+ ## Session lifecycle
2
+
3
+ Every `launch` starts a **fresh session**: a new git worktree from the **main
4
+ checkout's current HEAD** at
5
+ `~/worktrees/<base-branch>-<sha4>-har-agent-<id>-<rand4>`, on a branch of the same name.
6
+ Switch that checkout to your intended base before launch. The session is recorded in
7
+ `.har/slots/agent-<id>.json` (the slot registry) — status, verify, and teardown resolve
8
+ the work dir through it. Make ALL file edits under the work dir printed by launch,
9
+ never in the main checkout.
10
+
11
+ - Occupied slots always block a new launch: `har env complete <id>` (or `teardown <id>`),
12
+ then `har env launch <id>`. A new launch never chooses `main` for you — switch the
13
+ main checkout to your intended base first.
14
+ - `teardown` removes the worktree but **keeps the session branch** so you can push it
15
+ or open a PR (`--delete-branch` to drop it).
16
+ - If launch fails after creating a worktree/env file, the registry records `status: failed`.
17
+ Resume it instead of starting fresh: `har env launch <id> --resume` or `har env recover <id>`.
18
+ - `har env complete <id>` finishes a session: full verify (recorded as a validation),
19
+ then teardown — branch kept.
20
+ - `--no-worktree` runs the slot from the repo root instead (single-agent mode).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osfactory/har",
3
- "version": "0.64.2",
3
+ "version": "1.0.0-rc.2",
4
4
  "description": "HAR: open agent harness CLI and MCP server for coding agents, isolated worktrees, and software-factory workflows",
5
5
  "keywords": [
6
6
  "har",
@@ -1,83 +0,0 @@
1
- # Agent ${AGENT_ID} — Development Environment
2
-
3
- > [`AGENTS.md`](../AGENTS.md) · [`.har/README.md`](./README.md) · [`stages.json`](./stages.json)
4
-
5
- ## Environment
6
-
7
- | | |
8
- |--|--|
9
- | **Agent ID** | ${AGENT_ID} |
10
- | **Frontend** | http://localhost:${FE_PORT} |
11
- | **API** | http://localhost:${API_PORT} |
12
- | **Database** | `agent_${AGENT_ID}` on `localhost:${DB_PORT}` (when `db` is in `HARNESS_INFRA_SERVICES`) |
13
- | **Work dir** | Fresh session worktree per launch — see the launch output or `.har/slots/agent-${AGENT_ID}.json` |
14
-
15
- **Never edit the main checkout** — launch FIRST, then make ALL file edits under the work dir from the launch output. Edits there hot-reload in the running slot; use `./.har/agent-cli.sh ${AGENT_ID} restart` if a change doesn't take. An occupied slot always blocks a new launch — run `./.har/teardown.sh ${AGENT_ID}` (or `complete`) first, then launch again.
16
-
17
- This slot runs **only the primary application** (`HARNESS_PRIMARY_APP`). External dependencies and any supporting services run once, shared by all slots — `setup-infra.sh` manages them; never start them yourself.
18
-
19
- ```bash
20
- ./.har/agent-cli.sh ${AGENT_ID} status
21
- ./.har/agent-cli.sh ${AGENT_ID} logs api
22
- ./.har/agent-cli.sh ${AGENT_ID} health
23
- ```
24
-
25
- ## Readiness
26
-
27
- Adapt this section for the repository. A passing health check means the process
28
- is alive; it does not automatically mean an agent can use the app.
29
-
30
- - **Health**: `./.har/agent-cli.sh ${AGENT_ID} health`
31
- - **Agent-usable smoke**: document the login/API/UI workflow agents should try,
32
- or wire it into `HARNESS_READINESS_CMD` / full verify.
33
- - **Credentials/default data**: document any test users, tenants, projects, or
34
- settings created by the harness.
35
- - **Skipped full-dev setup**: document anything intentionally omitted from the
36
- upstream developer setup and the minimal substitute in `.har/`.
37
-
38
- ## Definition of done
39
-
40
- - [ ] 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`)
41
- - [ ] The slot is agent-usable for this repo's documented smoke workflow, not only health-check green
42
- - [ ] Full verify runs every registered stage in `stages.json` `verificationStages` (Playwright, custom checks, …) — when `stages/browser-e2e.sh` exists, adapt specs under `tests/` for UI changes
43
- - [ ] New behavior has automated test coverage (unit and/or browser as appropriate)
44
- - [ ] Changes committed **in the session worktree** with a clear message
45
- - [ ] The user got the preview URLs to test the app themselves
46
- - [ ] Present session handoff (summary, branch, preview URLs) and **wait for user** before `complete`, push, or PR
47
- - [ ] 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
48
-
49
- ### Session handoff
50
-
51
- After full verify and commit, stop and propose next steps. Never autonomously run
52
- `complete`, `teardown`, `git push`, or open a PR. **Default recommendation:** when
53
- `gh` or GitHub MCP is available, complete the slot **and** open a PR (push → PR →
54
- `har env complete` / `har_complete_environment`). Offer complete-only or something
55
- else as alternatives. If PR tooling is unavailable, recommend complete and report
56
- the session branch for a manual push. Prefer `complete` over bare `teardown` when
57
- the work succeeded. See `.cursor/rules/har-workflow.mdc` for the handoff shape.
58
-
59
- Quick loop during development: MCP `har_run_verification`, `har env verify ${AGENT_ID}`, or `./.har/verify.sh ${AGENT_ID}` (smoke + health only; `--full` adds the registered verification stages).
60
-
61
- 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`.
62
-
63
- ## Project commands
64
-
65
- ```bash
66
- # TODO: adapt for this repository (see package.json, Makefile, pyproject.toml, CI, etc.)
67
- # npm run typecheck
68
- # pytest -q
69
- # go test ./...
70
- # cargo test
71
- # make test
72
- ```
73
-
74
- ## Do not
75
-
76
- - Hand-roll docker/dev-server startup — `launch` is how you run the app (manual testing, browser, screenshots included)
77
- - Work around a failing harness command with ad-hoc setup — fix the harness or report the failure
78
- - Hardcode ports — use agent env / `agent-cli.sh url`
79
- - Run raw `docker compose` for shared harness infra — use `setup-infra.sh`
80
- - Start other services of the repo in your slot — only the primary app runs per-slot; shared services are already running
81
- - Edit `.env.agent.${AGENT_ID}` or PM2 ecosystem files by hand
82
- - Run `verify` before `launch` when health or e2e steps need a running server
83
- - Edit the main checkout — all edits go under the session work dir