@osfactory/har 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4796,7 +4796,9 @@ var init_schema = __esm({
4796
4796
  toolCallId: external_exports.string().optional(),
4797
4797
  correlationId: external_exports.string().optional(),
4798
4798
  workUnitId: WorkUnitIdSchema.optional(),
4799
- attemptId: WorkAttemptIdSchema.optional()
4799
+ attemptId: WorkAttemptIdSchema.optional(),
4800
+ /** One occupancy of a slot (#316) — records are scoped to it, not to slot id. */
4801
+ occupancyKey: external_exports.string().min(1).optional()
4800
4802
  }).passthrough();
4801
4803
  AgentTrajectoryRecordSchema = AgentTrajectoryRecordV1Schema;
4802
4804
  USAGE_HARVEST_VERSION = 2;
@@ -4811,6 +4813,8 @@ var init_schema = __esm({
4811
4813
  suffix: external_exports.string().optional(),
4812
4814
  workUnitId: WorkUnitIdSchema.optional(),
4813
4815
  attemptId: WorkAttemptIdSchema.optional(),
4816
+ /** One occupancy of a slot (#316) — usage is scoped to it, not to slot id. */
4817
+ occupancyKey: external_exports.string().min(1).optional(),
4814
4818
  tokensInput: external_exports.number().nonnegative().default(0),
4815
4819
  tokensOutput: external_exports.number().nonnegative().default(0),
4816
4820
  tokensCacheRead: external_exports.number().nonnegative().default(0),
@@ -32752,6 +32756,13 @@ function findValidation(checkoutDir, treeHash) {
32752
32756
  return void 0;
32753
32757
  }
32754
32758
  }
32759
+ function findPassingFullValidation(input) {
32760
+ if (!isCheckoutRoot(input.checkoutDir)) return void 0;
32761
+ const { treeHash } = computeWorktreeSnapshot(input.checkoutDir);
32762
+ const record2 = findValidation(input.checkoutDir, treeHash) ?? (input.harnessRoot ? findValidation(input.harnessRoot, treeHash) : void 0);
32763
+ if (record2?.status === "pass" && record2.full) return record2;
32764
+ return void 0;
32765
+ }
32755
32766
  function attachCommit(checkoutDir, treeHash, commitSha) {
32756
32767
  const record2 = findValidation(checkoutDir, treeHash);
32757
32768
  if (!record2) return void 0;
@@ -59038,10 +59049,12 @@ var require_run_async = __commonJS({
59038
59049
  // src/core/otel-hooks.ts
59039
59050
  var otel_hooks_exports = {};
59040
59051
  __export(otel_hooks_exports, {
59052
+ HOOK_TIMEOUT_SECONDS: () => HOOK_TIMEOUT_SECONDS,
59041
59053
  LEGACY_CURSOR_ONLY_HOOK_EVENTS: () => LEGACY_CURSOR_ONLY_HOOK_EVENTS,
59042
59054
  OTEL_HOOKS_AGENTS: () => OTEL_HOOKS_AGENTS,
59043
59055
  OTEL_HOOKS_PACKAGE: () => OTEL_HOOKS_PACKAGE,
59044
59056
  OTEL_HOOKS_PROVIDERS: () => OTEL_HOOKS_PROVIDERS,
59057
+ buildOtelHookSetupArgs: () => buildOtelHookSetupArgs,
59045
59058
  buildOtelHooksConfig: () => buildOtelHooksConfig,
59046
59059
  disableOtelHooksExport: () => disableOtelHooksExport,
59047
59060
  ensureOtelHooks: () => ensureOtelHooks,
@@ -59147,11 +59160,22 @@ function writeOtelHooksWrapper(otelHookCommand, hooksHome = getOtelHooksHome())
59147
59160
  const stateDir = getOtelHooksStateDir(hooksHome);
59148
59161
  const script = `#!/usr/bin/env bash
59149
59162
  # Managed by har telemetry \u2014 invokes @osfactory/otel-hook with HAR config.
59150
- set -euo pipefail
59151
- exec "${otelHookCommand}" run \\
59163
+ #
59164
+ # Two rules for this wrapper (#328):
59165
+ # 1. Bounded. Export and flush budgets keep it well inside the per-hook
59166
+ # timeout the agent enforces, so an unreachable Mission Control costs
59167
+ # milliseconds instead of stalling the session.
59168
+ # 2. Silent about its own failures. Dropped telemetry must never fail an
59169
+ # agent turn, so the exit status is always 0 \u2014 a non-zero hook exit can
59170
+ # block a tool call.
59171
+ set -uo pipefail
59172
+ "${otelHookCommand}" run \\
59152
59173
  --config-file "${configPath}" \\
59153
59174
  --state-dir "${stateDir}" \\
59154
- "$@"
59175
+ --timeout-ms ${HOOK_EXPORT_TIMEOUT_MS} \\
59176
+ --flush-timeout-ms ${HOOK_FLUSH_TIMEOUT_MS} \\
59177
+ "$@" || true
59178
+ exit 0
59155
59179
  `;
59156
59180
  fs68.writeFileSync(wrapperPath, script, { mode: 493 });
59157
59181
  try {
@@ -59244,23 +59268,30 @@ function isOtelHookCommand(command2, wrapperPath) {
59244
59268
  function normalizeLegacyProviderFlagsInCommand(command2) {
59245
59269
  return command2.replace(/(^|\s)--cursor(?=\s|$)/g, "$1--provider cursor").replace(/(^|\s)--claude(?=\s|$)/g, "$1--provider claude-code").replace(/(^|\s)--codex(?=\s|$)/g, "$1--provider codex");
59246
59270
  }
59271
+ function buildOtelHookSetupArgs(providerId, hookCommand) {
59272
+ return [
59273
+ "setup",
59274
+ "--provider",
59275
+ providerId,
59276
+ "--scope",
59277
+ "global",
59278
+ "--hook-command",
59279
+ hookCommand,
59280
+ "--managed-marker",
59281
+ "otel-hook",
59282
+ // Written into each generated hook entry so the agent bounds it (#328).
59283
+ // Without this the agent falls back to its own default and an unreachable
59284
+ // collector stalls the session before its first model request.
59285
+ "--timeout-seconds",
59286
+ String(HOOK_TIMEOUT_SECONDS)
59287
+ ];
59288
+ }
59247
59289
  function runSetupProvider(providerId, otelHookCommand, wrapperPath) {
59248
59290
  const hookCommand = `${wrapperPath} --provider ${providerId}`;
59249
- const result = (0, import_child_process19.spawnSync)(
59250
- otelHookCommand,
59251
- [
59252
- "setup",
59253
- "--provider",
59254
- providerId,
59255
- "--scope",
59256
- "global",
59257
- "--hook-command",
59258
- hookCommand,
59259
- "--managed-marker",
59260
- "otel-hook"
59261
- ],
59262
- { encoding: "utf8", timeout: 6e4 }
59263
- );
59291
+ const result = (0, import_child_process19.spawnSync)(otelHookCommand, buildOtelHookSetupArgs(providerId, hookCommand), {
59292
+ encoding: "utf8",
59293
+ timeout: 6e4
59294
+ });
59264
59295
  if (result.status === 0) {
59265
59296
  return { ok: true, detail: `setup --provider ${providerId}` };
59266
59297
  }
@@ -59487,7 +59518,7 @@ function ensureOtelHooks(options) {
59487
59518
  function disableOtelHooksExport() {
59488
59519
  return writeOtelHooksConfig(buildOtelHooksConfig({ enabled: false }));
59489
59520
  }
59490
- var import_child_process19, fs68, os22, path76, OTEL_HOOKS_PACKAGE, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
59521
+ var import_child_process19, fs68, os22, path76, OTEL_HOOKS_PACKAGE, HOOK_TIMEOUT_SECONDS, HOOK_EXPORT_TIMEOUT_MS, HOOK_FLUSH_TIMEOUT_MS, OTEL_HOOKS_PROVIDERS, OTEL_HOOKS_AGENTS, LEGACY_CURSOR_ONLY_HOOK_EVENTS;
59491
59522
  var init_otel_hooks = __esm({
59492
59523
  "src/core/otel-hooks.ts"() {
59493
59524
  "use strict";
@@ -59498,6 +59529,9 @@ var init_otel_hooks = __esm({
59498
59529
  init_control_config();
59499
59530
  init_telemetry_config();
59500
59531
  OTEL_HOOKS_PACKAGE = "@osfactory/otel-hook@0.2.0";
59532
+ HOOK_TIMEOUT_SECONDS = 10;
59533
+ HOOK_EXPORT_TIMEOUT_MS = 1500;
59534
+ HOOK_FLUSH_TIMEOUT_MS = 500;
59501
59535
  OTEL_HOOKS_PROVIDERS = [
59502
59536
  { id: "cursor", label: "cursor" },
59503
59537
  { id: "claude-code", label: "claude" },
@@ -79330,9 +79364,9 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
79330
79364
  return envResult;
79331
79365
  }
79332
79366
  /**
79333
- * Finish a session: full verification (recorded as a validation keyed by the
79334
- * worktree tree hash), then teardown. The session branch is kept so the user
79335
- * can push it and open a PR.
79367
+ * Finish a session: reuse the last matching passing full validation (or
79368
+ * re-run verify when asked), then teardown. The session branch is kept so
79369
+ * the user can push it and open a PR.
79336
79370
  */
79337
79371
  async completeEnvironment(options) {
79338
79372
  const harnessRoot = resolveHarnessRoot(options.repoPath);
@@ -79344,9 +79378,11 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
79344
79378
  stderr: `No active session for agent ${options.agentId}. Run launch first.`
79345
79379
  };
79346
79380
  }
79381
+ const runVerify = shouldReverifyOnComplete(options);
79347
79382
  let verification;
79348
79383
  let validation2;
79349
- if (!options.skipVerify) {
79384
+ let reusedValidation = false;
79385
+ if (runVerify) {
79350
79386
  const verify = await this.runVerification({
79351
79387
  repoPath: options.repoPath,
79352
79388
  agentId: options.agentId,
@@ -79359,11 +79395,27 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
79359
79395
  if (verify.code !== 0 || verification?.status !== "pass") {
79360
79396
  return {
79361
79397
  ...verify,
79362
- stderr: verify.stderr + "\nVerification failed \u2014 session NOT completed. Fix the failures and rerun, or complete with skipVerify."
79398
+ stderr: verify.stderr + "\nVerification failed \u2014 session NOT completed. Fix the failures and rerun `complete --verify`, or use teardown to free the slot without claiming completion."
79363
79399
  };
79364
79400
  }
79401
+ } else {
79402
+ const checkoutDir = resolveValidationCheckoutDir({
79403
+ worktreePath: session.worktreePath,
79404
+ workDir: session.workDir,
79405
+ harnessRoot
79406
+ });
79407
+ validation2 = findPassingFullValidation({ checkoutDir, harnessRoot });
79408
+ if (!validation2) {
79409
+ return {
79410
+ code: 1,
79411
+ stdout: "",
79412
+ stderr: `No passing full validation matches the current worktree. The tree may have changed since the last \`har env verify --full\`. Re-run verification with: har env complete ${options.agentId} --verify
79413
+ Or free the slot without claiming completion: har env teardown ${options.agentId}`
79414
+ };
79415
+ }
79416
+ reusedValidation = true;
79365
79417
  }
79366
- if (session.workUnitId && session.attemptId && !options.skipVerify && !validation2) {
79418
+ if (session.workUnitId && session.attemptId && runVerify && !validation2) {
79367
79419
  return {
79368
79420
  code: 1,
79369
79421
  stdout: "",
@@ -79387,11 +79439,13 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
79387
79439
  trigger: options.trigger
79388
79440
  });
79389
79441
  if (teardown.code !== 0) return { ...teardown, verification };
79442
+ const reusedNote = reusedValidation && validation2 ? `Reused passing full validation ${validation2.validationId} for tree ${validation2.treeHash}.
79443
+ ` : "";
79390
79444
  const branchNote = session.branch ? `Branch kept: ${session.branch} \u2014 push it with: git push -u origin ${session.branch}
79391
79445
  ` : "";
79392
79446
  return {
79393
79447
  ...teardown,
79394
- stdout: teardown.stdout + branchNote,
79448
+ stdout: teardown.stdout + reusedNote + branchNote,
79395
79449
  branch: session.branch,
79396
79450
  workDir: session.workDir,
79397
79451
  worktreePath: session.worktreePath,
@@ -79430,6 +79484,10 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
79430
79484
  return toEnvironmentRunResult(result);
79431
79485
  }
79432
79486
  };
79487
+ function shouldReverifyOnComplete(options) {
79488
+ if (options.verify === true) return true;
79489
+ return options.skipVerify === false;
79490
+ }
79433
79491
  var defaultRunService = new RunService();
79434
79492
  function createRunService(executor = localScriptExecutor) {
79435
79493
  return new RunService(executor);
@@ -79919,12 +79977,12 @@ Typical agent workflow:
79919
79977
  har env launch <id> # new session from the main checkout's HEAD
79920
79978
  # \u2026edit only under the printed work dir\u2026
79921
79979
  har env verify <id> --full
79922
- har env complete <id> # done: verify + free the slot (branch kept for PR)
79980
+ har env complete <id> # done: reuse last full validation + free the slot (branch kept for PR)
79923
79981
 
79924
79982
  Slot lifecycle (do not confuse these):
79925
79983
  launch start a NEW session (worktree from $REPO_ROOT HEAD)
79926
79984
  recover resume a failed/partial launch (keeps the existing worktree)
79927
- complete finish successfully: full verify, then teardown (frees the slot)
79985
+ complete finish successfully: reuse last matching full validation, then teardown (frees the slot)
79928
79986
  teardown abandon / free the slot without a completion validation
79929
79987
 
79930
79988
  Occupied slots always block a new launch:
@@ -79940,7 +79998,7 @@ var HAR_ENV_EPILOG = `Environment lifecycle:
79940
79998
  launch <id> fresh session worktree from the main checkout's current HEAD
79941
79999
  recover <id> alias for launch --resume (failed/starting only)
79942
80000
  verify <id> run checks (--full before declaring done)
79943
- complete <id> full verify + teardown; keeps branch for push/PR (frees slot)
80001
+ complete <id> reuse last full validation + teardown; --verify to re-run; keeps branch (frees slot)
79944
80002
  teardown <id> free the slot without recording a completion validation
79945
80003
 
79946
80004
  Occupied slots:
@@ -80168,11 +80226,15 @@ var envCommand = {
80168
80226
  handleTeardown
80169
80227
  ).command(
80170
80228
  "complete <id>",
80171
- "Finish a session: full verify (recorded as validation), teardown, keep the branch for a PR",
80172
- (y) => y.positional("id", { type: "number", describe: "Agent slot id (see .har/stages.json agentSlots)" }).option("repo", { type: "string", default: "." }).option("skip-verify", {
80229
+ "Finish a session: reuse the last matching full validation, teardown, keep the branch for a PR",
80230
+ (y) => y.positional("id", { type: "number", describe: "Agent slot id (see .har/stages.json agentSlots)" }).option("repo", { type: "string", default: "." }).option("verify", {
80173
80231
  type: "boolean",
80174
80232
  default: false,
80175
- describe: "Tear down without running verification (no validation is recorded)"
80233
+ describe: "Re-run full verification before teardown (use when the tree may have changed since the last passing --full)"
80234
+ }).option("skip-verify", {
80235
+ type: "boolean",
80236
+ hidden: true,
80237
+ describe: "Deprecated no-op: complete already skips re-verification by default"
80176
80238
  }),
80177
80239
  handleComplete
80178
80240
  ).command(
@@ -80694,6 +80756,7 @@ async function handleComplete(argv) {
80694
80756
  const result = await completeEnvironment({
80695
80757
  repoPath: repo,
80696
80758
  agentId,
80759
+ verify: argv.verify,
80697
80760
  skipVerify: argv.skipVerify,
80698
80761
  capture: false
80699
80762
  });
@@ -90261,6 +90324,14 @@ async function runLineGate(options) {
90261
90324
  }
90262
90325
  const registry2 = readStageRegistry(repoPath);
90263
90326
  const registeredIds = new Set(registry2.stages.map((s) => s.id));
90327
+ if (options.agentId === void 0) {
90328
+ const needSlot = required2.filter((stage) => registry2.stages.find((s) => s.id === stage.id)?.requiresAgentId).map((stage) => stage.id);
90329
+ if (needSlot.length > 0) {
90330
+ throw new Error(
90331
+ `Gate stage(s) ${needSlot.join(", ")} run in an agent slot \u2014 pass --agent <id> (har line gate ${options.station} --line ${lineId} --agent 1).`
90332
+ );
90333
+ }
90334
+ }
90264
90335
  const results = [];
90265
90336
  let pass = true;
90266
90337
  for (const stage of required2) {
@@ -90431,7 +90502,12 @@ var PreflightEnvironmentOutputSchema = ShellRunOutputSchema.extend({
90431
90502
  var CompleteEnvironmentInputSchema = external_exports.object({
90432
90503
  repo: external_exports.string().default("."),
90433
90504
  agentId: agentIdSchema,
90434
- skipVerify: external_exports.boolean().default(false).describe("Tear down without running verification (no validation is recorded)")
90505
+ verify: external_exports.boolean().optional().describe(
90506
+ "Re-run full verification before teardown when the tree may have changed since the last passing --full"
90507
+ ),
90508
+ skipVerify: external_exports.boolean().optional().describe(
90509
+ "Deprecated. Complete already skips re-verification by default. Pass verify=true to re-run; skipVerify=false still forces a re-run."
90510
+ )
90435
90511
  });
90436
90512
  var CompleteEnvironmentOutputSchema = ShellRunOutputSchema.extend({
90437
90513
  branch: external_exports.string().optional().describe("Session branch kept for the user to push / open a PR"),
@@ -90739,14 +90815,18 @@ var HAR_MCP_TOOLS = [
90739
90815
  },
90740
90816
  {
90741
90817
  name: "har_complete_environment",
90742
- description: "Finish a session when the work is done: runs full verification (recorded as a validation of the worktree tree hash), tears the slot down, and KEEPS the session branch so the user can push it and open a PR.",
90818
+ description: "Finish a session when the work is done: reuses the last passing full validation for the current worktree (or re-runs verify when verify=true), tears the slot down, and KEEPS the session branch so the user can push it and open a PR.",
90743
90819
  inputSchema: objectJsonSchema(
90744
90820
  {
90745
90821
  repo: repoJsonProperty,
90746
90822
  agentId: agentIdJsonProperty,
90823
+ verify: {
90824
+ type: "boolean",
90825
+ description: "Re-run full verification before teardown when the tree may have changed since the last passing --full"
90826
+ },
90747
90827
  skipVerify: {
90748
90828
  type: "boolean",
90749
- description: "Tear down without running verification (no validation is recorded)"
90829
+ description: "Deprecated. Complete already skips re-verification by default. Pass verify=true to re-run."
90750
90830
  }
90751
90831
  },
90752
90832
  ["agentId"]
@@ -91083,6 +91163,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
91083
91163
  const result = await completeEnvironment({
91084
91164
  repoPath: repo,
91085
91165
  agentId,
91166
+ verify: input.verify,
91086
91167
  skipVerify: input.skipVerify,
91087
91168
  capture: true,
91088
91169
  trigger: "mcp"
@@ -91277,7 +91358,7 @@ var ONBOARDING_GUIDE_STEPS = [
91277
91358
  body: [
91278
91359
  "Quick: har env verify <id>",
91279
91360
  "Done: har env verify <id> --full then har env complete <id>",
91280
- "`complete` records a validation, frees the slot, and keeps the session branch for a PR."
91361
+ "`complete` reuses the last matching full validation, frees the slot, and keeps the session branch for a PR. Pass --verify if the tree changed."
91281
91362
  ].join("\n")
91282
91363
  },
91283
91364
  {
@@ -92459,6 +92540,12 @@ async function handleStatus3(argv) {
92459
92540
  info(`Mission Control: ${apiUrl} (${reachable ? "reachable" : "not reachable"})`);
92460
92541
  info(`OTLP endpoint: ${payload.otelEndpoint}`);
92461
92542
  info(`Hooks home: ${payload.otelHooksHome}`);
92543
+ if (enabled && !reachable) {
92544
+ warn(
92545
+ "Agent hooks are installed but Mission Control is not reachable \u2014 each turn pays the export timeout for telemetry nobody receives."
92546
+ );
92547
+ info("Start it with: har control up \u2022 or stop exporting: har telemetry off");
92548
+ }
92462
92549
  printSignals();
92463
92550
  }
92464
92551
  async function handleOn(argv) {
@@ -57,7 +57,8 @@ Do not substitute ad-hoc test commands for harness verification. Any edit after
57
57
  ## 5. Finish
58
58
 
59
59
  ```bash
60
- har env complete <id> # full verify + validation record + teardown, keeps the session branch
60
+ har env complete <id> # reuse last passing full validation + teardown, keeps the session branch
61
+ har env complete <id> --verify # re-run full verify first if the tree may have changed
61
62
  ```
62
63
 
63
64
  Report to the user: verification result, the session branch name (so they can push / open a PR), and the slot preview URLs if the app is running.
@@ -6,7 +6,7 @@
6
6
  - [ ] New behavior has automated test coverage
7
7
  - [ ] Changes committed **in the session worktree** with a clear message
8
8
  - [ ] Present session handoff (summary, branch, preview URLs) and **wait for user** before `complete`, push, or PR
9
- - [ ] On user approval of the default: push + open PR (when `gh`/GitHub MCP available), then `har env complete <id>` (or MCP `har_complete_environment`) — full verify + validation + teardown, branch kept
9
+ - [ ] On user approval of the default: push + open PR (when `gh`/GitHub MCP available), then `har env complete <id>` (or MCP `har_complete_environment`) — reuse last passing full validation + teardown, branch kept. Pass `--verify` / `verify: true` if the tree may have changed.
10
10
 
11
11
  ### Session handoff
12
12
 
@@ -7,7 +7,7 @@
7
7
  - [ ] Changes committed **in the session worktree** with a clear message
8
8
  - [ ] The user got the preview URLs to test the app themselves
9
9
  - [ ] Present session handoff (summary, branch, preview URLs) and **wait for user** before `complete`, push, or PR
10
- - [ ] On user approval of the default: push + open PR (when `gh`/GitHub MCP available), then `har env complete <id>` (or MCP `har_complete_environment`) — full verify + validation + teardown, branch kept
10
+ - [ ] On user approval of the default: push + open PR (when `gh`/GitHub MCP available), then `har env complete <id>` (or MCP `har_complete_environment`) — reuse last passing full validation + teardown, branch kept. Pass `--verify` / `verify: true` if the tree may have changed.
11
11
 
12
12
  ### Session handoff
13
13
 
@@ -6,7 +6,7 @@
6
6
  - [ ] New behavior has automated test coverage (unit tests via XCTest)
7
7
  - [ ] Changes committed **in the session worktree** with a clear message
8
8
  - [ ] Present session handoff (summary, branch, preview URLs) and **wait for user** before `complete`, push, or PR
9
- - [ ] On user approval of the default: push + open PR (when `gh`/GitHub MCP available), then `har env complete <id>` (or MCP `har_complete_environment`) — full verify + validation + teardown, branch kept
9
+ - [ ] On user approval of the default: push + open PR (when `gh`/GitHub MCP available), then `har env complete <id>` (or MCP `har_complete_environment`) — reuse last passing full validation + teardown, branch kept. Pass `--verify` / `verify: true` if the tree may have changed.
10
10
 
11
11
  ### Session handoff
12
12
 
@@ -15,6 +15,7 @@ never in the main checkout.
15
15
  or open a PR (`--delete-branch` to drop it).
16
16
  - If launch fails after creating a worktree/env file, the registry records `status: failed`.
17
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.
18
+ - `har env complete <id>` finishes a session: reuses the last matching passing
19
+ full validation, then teardown — branch kept. Pass `--verify` to re-run full
20
+ verify if the tree may have changed.
20
21
  - `--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": "1.3.0",
3
+ "version": "1.5.0",
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",