@osfactory/har 1.3.0 → 1.4.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 +76 -18
- package/dist/templates/agent-skills/har-wt.md +2 -1
- package/dist/templates/profiles/cli/docs/readme/definition-of-done.md +1 -1
- package/dist/templates/profiles/default/docs/readme/definition-of-done.md +1 -1
- package/dist/templates/profiles/ios/docs/readme/definition-of-done.md +1 -1
- package/dist/templates/shared-docs/readme/session-lifecycle.md +3 -2
- package/package.json +1 -1
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;
|
|
@@ -79330,9 +79341,9 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
79330
79341
|
return envResult;
|
|
79331
79342
|
}
|
|
79332
79343
|
/**
|
|
79333
|
-
* Finish a session:
|
|
79334
|
-
*
|
|
79335
|
-
* can push it and open a PR.
|
|
79344
|
+
* Finish a session: reuse the last matching passing full validation (or
|
|
79345
|
+
* re-run verify when asked), then teardown. The session branch is kept so
|
|
79346
|
+
* the user can push it and open a PR.
|
|
79336
79347
|
*/
|
|
79337
79348
|
async completeEnvironment(options) {
|
|
79338
79349
|
const harnessRoot = resolveHarnessRoot(options.repoPath);
|
|
@@ -79344,9 +79355,11 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
79344
79355
|
stderr: `No active session for agent ${options.agentId}. Run launch first.`
|
|
79345
79356
|
};
|
|
79346
79357
|
}
|
|
79358
|
+
const runVerify = shouldReverifyOnComplete(options);
|
|
79347
79359
|
let verification;
|
|
79348
79360
|
let validation2;
|
|
79349
|
-
|
|
79361
|
+
let reusedValidation = false;
|
|
79362
|
+
if (runVerify) {
|
|
79350
79363
|
const verify = await this.runVerification({
|
|
79351
79364
|
repoPath: options.repoPath,
|
|
79352
79365
|
agentId: options.agentId,
|
|
@@ -79359,11 +79372,27 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
79359
79372
|
if (verify.code !== 0 || verification?.status !== "pass") {
|
|
79360
79373
|
return {
|
|
79361
79374
|
...verify,
|
|
79362
|
-
stderr: verify.stderr + "\nVerification failed \u2014 session NOT completed. Fix the failures and rerun
|
|
79375
|
+
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."
|
|
79376
|
+
};
|
|
79377
|
+
}
|
|
79378
|
+
} else {
|
|
79379
|
+
const checkoutDir = resolveValidationCheckoutDir({
|
|
79380
|
+
worktreePath: session.worktreePath,
|
|
79381
|
+
workDir: session.workDir,
|
|
79382
|
+
harnessRoot
|
|
79383
|
+
});
|
|
79384
|
+
validation2 = findPassingFullValidation({ checkoutDir, harnessRoot });
|
|
79385
|
+
if (!validation2) {
|
|
79386
|
+
return {
|
|
79387
|
+
code: 1,
|
|
79388
|
+
stdout: "",
|
|
79389
|
+
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
|
|
79390
|
+
Or free the slot without claiming completion: har env teardown ${options.agentId}`
|
|
79363
79391
|
};
|
|
79364
79392
|
}
|
|
79393
|
+
reusedValidation = true;
|
|
79365
79394
|
}
|
|
79366
|
-
if (session.workUnitId && session.attemptId &&
|
|
79395
|
+
if (session.workUnitId && session.attemptId && runVerify && !validation2) {
|
|
79367
79396
|
return {
|
|
79368
79397
|
code: 1,
|
|
79369
79398
|
stdout: "",
|
|
@@ -79387,11 +79416,13 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
79387
79416
|
trigger: options.trigger
|
|
79388
79417
|
});
|
|
79389
79418
|
if (teardown.code !== 0) return { ...teardown, verification };
|
|
79419
|
+
const reusedNote = reusedValidation && validation2 ? `Reused passing full validation ${validation2.validationId} for tree ${validation2.treeHash}.
|
|
79420
|
+
` : "";
|
|
79390
79421
|
const branchNote = session.branch ? `Branch kept: ${session.branch} \u2014 push it with: git push -u origin ${session.branch}
|
|
79391
79422
|
` : "";
|
|
79392
79423
|
return {
|
|
79393
79424
|
...teardown,
|
|
79394
|
-
stdout: teardown.stdout + branchNote,
|
|
79425
|
+
stdout: teardown.stdout + reusedNote + branchNote,
|
|
79395
79426
|
branch: session.branch,
|
|
79396
79427
|
workDir: session.workDir,
|
|
79397
79428
|
worktreePath: session.worktreePath,
|
|
@@ -79430,6 +79461,10 @@ Usage from Cursor / Claude / Codex (@osfactory/otel-hook) will appear under Work
|
|
|
79430
79461
|
return toEnvironmentRunResult(result);
|
|
79431
79462
|
}
|
|
79432
79463
|
};
|
|
79464
|
+
function shouldReverifyOnComplete(options) {
|
|
79465
|
+
if (options.verify === true) return true;
|
|
79466
|
+
return options.skipVerify === false;
|
|
79467
|
+
}
|
|
79433
79468
|
var defaultRunService = new RunService();
|
|
79434
79469
|
function createRunService(executor = localScriptExecutor) {
|
|
79435
79470
|
return new RunService(executor);
|
|
@@ -79919,12 +79954,12 @@ Typical agent workflow:
|
|
|
79919
79954
|
har env launch <id> # new session from the main checkout's HEAD
|
|
79920
79955
|
# \u2026edit only under the printed work dir\u2026
|
|
79921
79956
|
har env verify <id> --full
|
|
79922
|
-
har env complete <id> # done:
|
|
79957
|
+
har env complete <id> # done: reuse last full validation + free the slot (branch kept for PR)
|
|
79923
79958
|
|
|
79924
79959
|
Slot lifecycle (do not confuse these):
|
|
79925
79960
|
launch start a NEW session (worktree from $REPO_ROOT HEAD)
|
|
79926
79961
|
recover resume a failed/partial launch (keeps the existing worktree)
|
|
79927
|
-
complete finish successfully: full
|
|
79962
|
+
complete finish successfully: reuse last matching full validation, then teardown (frees the slot)
|
|
79928
79963
|
teardown abandon / free the slot without a completion validation
|
|
79929
79964
|
|
|
79930
79965
|
Occupied slots always block a new launch:
|
|
@@ -79940,7 +79975,7 @@ var HAR_ENV_EPILOG = `Environment lifecycle:
|
|
|
79940
79975
|
launch <id> fresh session worktree from the main checkout's current HEAD
|
|
79941
79976
|
recover <id> alias for launch --resume (failed/starting only)
|
|
79942
79977
|
verify <id> run checks (--full before declaring done)
|
|
79943
|
-
complete <id> full
|
|
79978
|
+
complete <id> reuse last full validation + teardown; --verify to re-run; keeps branch (frees slot)
|
|
79944
79979
|
teardown <id> free the slot without recording a completion validation
|
|
79945
79980
|
|
|
79946
79981
|
Occupied slots:
|
|
@@ -80168,11 +80203,15 @@ var envCommand = {
|
|
|
80168
80203
|
handleTeardown
|
|
80169
80204
|
).command(
|
|
80170
80205
|
"complete <id>",
|
|
80171
|
-
"Finish a session:
|
|
80172
|
-
(y) => y.positional("id", { type: "number", describe: "Agent slot id (see .har/stages.json agentSlots)" }).option("repo", { type: "string", default: "." }).option("
|
|
80206
|
+
"Finish a session: reuse the last matching full validation, teardown, keep the branch for a PR",
|
|
80207
|
+
(y) => y.positional("id", { type: "number", describe: "Agent slot id (see .har/stages.json agentSlots)" }).option("repo", { type: "string", default: "." }).option("verify", {
|
|
80173
80208
|
type: "boolean",
|
|
80174
80209
|
default: false,
|
|
80175
|
-
describe: "
|
|
80210
|
+
describe: "Re-run full verification before teardown (use when the tree may have changed since the last passing --full)"
|
|
80211
|
+
}).option("skip-verify", {
|
|
80212
|
+
type: "boolean",
|
|
80213
|
+
hidden: true,
|
|
80214
|
+
describe: "Deprecated no-op: complete already skips re-verification by default"
|
|
80176
80215
|
}),
|
|
80177
80216
|
handleComplete
|
|
80178
80217
|
).command(
|
|
@@ -80694,6 +80733,7 @@ async function handleComplete(argv) {
|
|
|
80694
80733
|
const result = await completeEnvironment({
|
|
80695
80734
|
repoPath: repo,
|
|
80696
80735
|
agentId,
|
|
80736
|
+
verify: argv.verify,
|
|
80697
80737
|
skipVerify: argv.skipVerify,
|
|
80698
80738
|
capture: false
|
|
80699
80739
|
});
|
|
@@ -90261,6 +90301,14 @@ async function runLineGate(options) {
|
|
|
90261
90301
|
}
|
|
90262
90302
|
const registry2 = readStageRegistry(repoPath);
|
|
90263
90303
|
const registeredIds = new Set(registry2.stages.map((s) => s.id));
|
|
90304
|
+
if (options.agentId === void 0) {
|
|
90305
|
+
const needSlot = required2.filter((stage) => registry2.stages.find((s) => s.id === stage.id)?.requiresAgentId).map((stage) => stage.id);
|
|
90306
|
+
if (needSlot.length > 0) {
|
|
90307
|
+
throw new Error(
|
|
90308
|
+
`Gate stage(s) ${needSlot.join(", ")} run in an agent slot \u2014 pass --agent <id> (har line gate ${options.station} --line ${lineId} --agent 1).`
|
|
90309
|
+
);
|
|
90310
|
+
}
|
|
90311
|
+
}
|
|
90264
90312
|
const results = [];
|
|
90265
90313
|
let pass = true;
|
|
90266
90314
|
for (const stage of required2) {
|
|
@@ -90431,7 +90479,12 @@ var PreflightEnvironmentOutputSchema = ShellRunOutputSchema.extend({
|
|
|
90431
90479
|
var CompleteEnvironmentInputSchema = external_exports.object({
|
|
90432
90480
|
repo: external_exports.string().default("."),
|
|
90433
90481
|
agentId: agentIdSchema,
|
|
90434
|
-
|
|
90482
|
+
verify: external_exports.boolean().optional().describe(
|
|
90483
|
+
"Re-run full verification before teardown when the tree may have changed since the last passing --full"
|
|
90484
|
+
),
|
|
90485
|
+
skipVerify: external_exports.boolean().optional().describe(
|
|
90486
|
+
"Deprecated. Complete already skips re-verification by default. Pass verify=true to re-run; skipVerify=false still forces a re-run."
|
|
90487
|
+
)
|
|
90435
90488
|
});
|
|
90436
90489
|
var CompleteEnvironmentOutputSchema = ShellRunOutputSchema.extend({
|
|
90437
90490
|
branch: external_exports.string().optional().describe("Session branch kept for the user to push / open a PR"),
|
|
@@ -90739,14 +90792,18 @@ var HAR_MCP_TOOLS = [
|
|
|
90739
90792
|
},
|
|
90740
90793
|
{
|
|
90741
90794
|
name: "har_complete_environment",
|
|
90742
|
-
description: "Finish a session when the work is done:
|
|
90795
|
+
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
90796
|
inputSchema: objectJsonSchema(
|
|
90744
90797
|
{
|
|
90745
90798
|
repo: repoJsonProperty,
|
|
90746
90799
|
agentId: agentIdJsonProperty,
|
|
90800
|
+
verify: {
|
|
90801
|
+
type: "boolean",
|
|
90802
|
+
description: "Re-run full verification before teardown when the tree may have changed since the last passing --full"
|
|
90803
|
+
},
|
|
90747
90804
|
skipVerify: {
|
|
90748
90805
|
type: "boolean",
|
|
90749
|
-
description: "
|
|
90806
|
+
description: "Deprecated. Complete already skips re-verification by default. Pass verify=true to re-run."
|
|
90750
90807
|
}
|
|
90751
90808
|
},
|
|
90752
90809
|
["agentId"]
|
|
@@ -91083,6 +91140,7 @@ async function handleMcpToolCall(toolName, args, defaultRepo = ".") {
|
|
|
91083
91140
|
const result = await completeEnvironment({
|
|
91084
91141
|
repoPath: repo,
|
|
91085
91142
|
agentId,
|
|
91143
|
+
verify: input.verify,
|
|
91086
91144
|
skipVerify: input.skipVerify,
|
|
91087
91145
|
capture: true,
|
|
91088
91146
|
trigger: "mcp"
|
|
@@ -91277,7 +91335,7 @@ var ONBOARDING_GUIDE_STEPS = [
|
|
|
91277
91335
|
body: [
|
|
91278
91336
|
"Quick: har env verify <id>",
|
|
91279
91337
|
"Done: har env verify <id> --full then har env complete <id>",
|
|
91280
|
-
"`complete`
|
|
91338
|
+
"`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
91339
|
].join("\n")
|
|
91282
91340
|
},
|
|
91283
91341
|
{
|
|
@@ -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> #
|
|
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`) —
|
|
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`) —
|
|
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`) —
|
|
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:
|
|
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).
|