@osfactory/har 0.16.1 → 0.17.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
@@ -28652,6 +28652,20 @@ function readSlotRegistry(repoPath, agentId) {
28652
28652
  }
28653
28653
 
28654
28654
  // src/core/local-executor.ts
28655
+ function quoteShellArg(arg) {
28656
+ if (/^[A-Za-z0-9_./:=+-]+$/.test(arg)) return arg;
28657
+ return `'${arg.replace(/'/g, `'\\''`)}'`;
28658
+ }
28659
+ function buildLaunchFlagArgs(flags) {
28660
+ const args = [];
28661
+ if (flags.worktree === false) args.push("--no-worktree");
28662
+ if (flags.claude) args.push("--claude");
28663
+ if (flags.confirmReplace) args.push("--replace");
28664
+ if (flags.force) args.push("--force");
28665
+ if (flags.resume) args.push("--resume");
28666
+ if (flags.purpose) args.push(`--purpose=${flags.purpose}`);
28667
+ return args;
28668
+ }
28655
28669
  function resolveRepoPath(repoPath) {
28656
28670
  return path24.resolve(repoPath);
28657
28671
  }
@@ -28729,18 +28743,14 @@ function buildExecutionPlan(repoPath, stage, options) {
28729
28743
  };
28730
28744
  const cwd = stage.cwd ? path24.resolve(resolvedRepo, stage.cwd) : resolvedRepo;
28731
28745
  const extraArgs = options.args ?? [];
28732
- const launchFlagArgs = [];
28733
- if (stage.kind === "launch" && options.launchFlags) {
28734
- if (options.launchFlags.worktree === false) launchFlagArgs.push("--no-worktree");
28735
- if (options.launchFlags.claude) launchFlagArgs.push("--claude");
28736
- if (options.launchFlags.confirmReplace) launchFlagArgs.push("--replace");
28737
- if (options.launchFlags.force) launchFlagArgs.push("--force");
28738
- if (options.launchFlags.resume) launchFlagArgs.push("--resume");
28746
+ const launchFlagArgs = stage.kind === "launch" && options.launchFlags ? buildLaunchFlagArgs(options.launchFlags) : [];
28747
+ if (stage.kind === "launch" && options.launchFlags?.purpose) {
28748
+ mergedEnv.HAR_SESSION_PURPOSE = options.launchFlags.purpose;
28739
28749
  }
28740
28750
  if (stage.command) {
28741
28751
  let shellCommand = substituteAgentId(stage.command, options.agentId);
28742
28752
  for (const extra of [...extraArgs, ...launchFlagArgs]) {
28743
- shellCommand = `${shellCommand} ${extra}`;
28753
+ shellCommand = `${shellCommand} ${quoteShellArg(extra)}`;
28744
28754
  }
28745
28755
  return { mode: "shell", shellCommand, args: [], cwd, env: mergedEnv };
28746
28756
  }
@@ -29309,6 +29319,7 @@ function collectOccupiedSlot(repoPath, agentId) {
29309
29319
  sessionStatus: session?.status,
29310
29320
  lastError: session?.lastError,
29311
29321
  sessionCreatedAt: session?.createdAt,
29322
+ purpose: session?.purpose,
29312
29323
  dirty,
29313
29324
  harnessUsage: "none"
29314
29325
  };
@@ -29319,6 +29330,7 @@ function formatOccupiedSlot(slot, resume) {
29319
29330
  slot.worktreePath ? ` Worktree: ${slot.worktreePath}` : void 0,
29320
29331
  slot.branch ? ` Branch: ${slot.branch}` : void 0,
29321
29332
  slot.workDir ? ` Work dir: ${slot.workDir}` : void 0,
29333
+ slot.purpose ? ` Purpose: ${slot.purpose}` : void 0,
29322
29334
  slot.sessionStatus ? ` Status: ${slot.sessionStatus}` : void 0,
29323
29335
  slot.lastError ? ` Error: ${slot.lastError}` : void 0,
29324
29336
  slot.sessionCreatedAt ? ` Since: ${slot.sessionCreatedAt}` : void 0,
@@ -31105,7 +31117,8 @@ var RunService = class {
31105
31117
  worktreePath: slot.worktreePath,
31106
31118
  branch: slot.branch,
31107
31119
  dirty: slot.dirty,
31108
- sessionCreatedAt: slot.sessionCreatedAt
31120
+ sessionCreatedAt: slot.sessionCreatedAt,
31121
+ purpose: slot.purpose
31109
31122
  } : void 0
31110
31123
  };
31111
31124
  }
@@ -31134,7 +31147,8 @@ Usage from Claude Code / Codex will appear under Worktrees. Disable: har telemet
31134
31147
  claude: options.claude,
31135
31148
  confirmReplace: options.confirmReplace,
31136
31149
  force: options.force,
31137
- resume: options.resume
31150
+ resume: options.resume,
31151
+ purpose: options.purpose
31138
31152
  },
31139
31153
  trigger: "cli"
31140
31154
  });
@@ -31453,6 +31467,9 @@ var envCommand = {
31453
31467
  type: "boolean",
31454
31468
  default: false,
31455
31469
  describe: "Resume a failed or partial launch without creating a new worktree"
31470
+ }).option("purpose", {
31471
+ type: "string",
31472
+ describe: "Optional session label stored in the slot registry (shown in status and occupied-slot warnings)"
31456
31473
  }),
31457
31474
  handleLaunch
31458
31475
  ).command(
@@ -31838,6 +31855,7 @@ async function handleLaunch(argv) {
31838
31855
  confirmReplace,
31839
31856
  force,
31840
31857
  resume: argv.resume,
31858
+ purpose: argv.purpose,
31841
31859
  capture: false
31842
31860
  });
31843
31861
  if (result.blocked) {
@@ -39872,7 +39890,10 @@ var LaunchEnvironmentInputSchema = external_exports.object({
39872
39890
  force: external_exports.boolean().default(false).describe(
39873
39891
  "Discard uncommitted changes in a dirty occupied worktree. Requires confirmReplace=true and explicit user approval \u2014 never set autonomously."
39874
39892
  ),
39875
- resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree.")
39893
+ resume: external_exports.boolean().default(false).describe("Resume a failed or partial launch without creating a new worktree."),
39894
+ purpose: external_exports.string().optional().describe(
39895
+ "Optional session label stored in the slot registry (shown in status and occupied-slot warnings)."
39896
+ )
39876
39897
  });
39877
39898
  var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
39878
39899
  previewUrls: external_exports.record(external_exports.string()).optional(),
@@ -39886,7 +39907,8 @@ var LaunchEnvironmentOutputSchema = ShellRunOutputSchema.extend({
39886
39907
  worktreePath: external_exports.string().optional(),
39887
39908
  branch: external_exports.string().optional(),
39888
39909
  dirty: external_exports.boolean().optional(),
39889
- sessionCreatedAt: external_exports.string().optional()
39910
+ sessionCreatedAt: external_exports.string().optional(),
39911
+ purpose: external_exports.string().optional()
39890
39912
  }).optional()
39891
39913
  });
39892
39914
  var PreflightEnvironmentInputSchema = external_exports.object({
@@ -40011,6 +40033,10 @@ var HAR_MCP_TOOLS = [
40011
40033
  resume: {
40012
40034
  type: "boolean",
40013
40035
  description: "Resume a failed or partial launch (status failed/starting) without --replace. Preserves worktree and env."
40036
+ },
40037
+ purpose: {
40038
+ type: "string",
40039
+ description: "Optional session label stored in the slot registry (shown in status and occupied-slot warnings)."
40014
40040
  }
40015
40041
  },
40016
40042
  ["agentId"]
@@ -40194,6 +40220,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
40194
40220
  confirmReplace: input.confirmReplace,
40195
40221
  force: input.force,
40196
40222
  resume: input.resume,
40223
+ purpose: input.purpose,
40197
40224
  capture: true
40198
40225
  });
40199
40226
  const parsed = LaunchEnvironmentOutputSchema.parse(result);
@@ -30,7 +30,7 @@ Relaunching a slot **replaces** its previous session (the old branch is kept). R
30
30
  - **Never** set `force`/`confirmReplace` without the user explicitly approving replacement.
31
31
  - **Commit early and often** in the session worktree — teardown keeps the branch, not uncommitted work.
32
32
  - **Gitignored paths are ephemeral** (`state/`, `runs/`, local clones) — they are lost when the worktree is removed.
33
- - Optional: set `HAR_SESSION_PURPOSE=label` or `--purpose=label` on launch so occupied-slot warnings show what you were doing.
33
+ - Optional: set `har env launch <id> --purpose=label`, `HAR_SESSION_PURPOSE=label`, or `./.har/launch.sh <id> --purpose=label` so occupied-slot warnings show what you were doing.
34
34
 
35
35
  <!-- Monorepo: if this repository contains multiple .har harnesses, list them here
36
36
  and pick by the files you are changing. Example:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osfactory/har",
3
- "version": "0.16.1",
3
+ "version": "0.17.0",
4
4
  "description": "LLM-powered CLI for reproducible agent development environments",
5
5
  "keywords": [
6
6
  "har",