@lannguyensi/harness 0.24.1 → 0.25.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.25.1] - 2026-05-20
11
+
12
+ **Headline: `harness init --interactive` works again on migrated installs.** A patch for the one regression in v0.25.0's interactive installer: on an install whose state was migrated to `~/.harness/` (v0.24.0), the wizard probed the legacy `~/.claude/` path, mis-reported the manifest as absent, prompted for the wrong path, and then refused to write, ignoring `--force`. `detect()` now resolves the manifest through `resolveHomeDir()` like the rest of harness, and `--force` is threaded into the wizard. **Operator action**: `npm i -g @lannguyensi/harness` to upgrade; no manifest or config changes.
13
+
14
+ ### Fixed
15
+
16
+ - **`harness init --interactive` no longer mis-detects the manifest on a v0.24.0-migrated install, and `--force` is honored** (agent-tasks/418cebd4). On an install whose state was migrated to `~/.harness/`, `harness init --interactive` probed `~/.claude/harness.yaml` (the legacy claude-code runtime dir), reported "manifest absent", offered to write to that legacy path, and then `init()` (which resolves the real path via `resolveHomeDir()`) refused on the actual `~/.harness/harness.yaml` with "pass --force to overwrite", even when `--force` had been passed. Two root causes, both v0.24.0 home-dir-migration regressions in the interactive path. (1) `detect()` resolved the manifest path by hardcoding the claude-code runtime dir (`~/.claude/`) instead of calling `resolveHomeDir()`; it now resolves through `resolveHomeDir()` (runtime-neutral `~/.harness/`, falling back to legacy `~/.claude/` only when harness state physically lives there), so the wizard, its environment probe, and `init()` all agree on where the manifest lives. The claude-code and codex runtime detection is unchanged. (2) The init command's `--interactive` branch never passed `--force` into `runInteractive`'s `forceOverwrite`, so the flag was silently dropped; it is now threaded, and `harness init --interactive --force` skips the overwrite prompt as documented. The wizard's `homeDir` bridging to `init()` / `apply()` is also corrected to pass the resolved harness root rather than `$HOME/.claude`. New regression tests cover `detect()` resolving `~/.harness/` versus the legacy `~/.claude/` fallback, and the wizard detecting plus force-overwriting an existing `~/.harness/` manifest.
17
+
18
+ ## [0.25.0] - 2026-05-20
19
+
20
+ **Headline: batch pre-approval for the understanding gate, plus three gate and CLI fixes.** PR #218 makes `harness approve understanding --task` variadic, so a multi-task session (e.g. a CVE sweep across N repos) is pre-approved in one operator action instead of one round-trip per `task_finish`. Three fixes ride along: `harness pause` is a top-level command again (#220, it had been mis-registered as a subcommand of `migrate-home` and dropped from `harness --help`), the `harness approve understanding` session resolver no longer guesses a stale unrelated session from a finished gate cycle (#221), and the Full init template floors agent-preflight at 0.2.0 so secret-detection no longer hard-fails preflight on a normal gitignored `.env` (#219). **Operator action**: none; re-run `npm i -g @lannguyensi/harness` to upgrade.
21
+
22
+ ### Changed
23
+
24
+ - **FULL_TEMPLATE `git-preflight` hook floors agent-preflight at 0.2.0** (agent-tasks/feffe938). agent-preflight 0.2.0 makes secret detection git-aware and diff-scoped: a gitignored+untracked `.env` holding real credentials (the normal, correct state), a `.md` doc, a non-git directory, or a secret in a tracked file the current branch never touched is reported as a non-blocking `warn` instead of a hard `fail`. Pre-0.2.0 installs hard-fail preflight on that normal state, so the `git-preflight` SessionStart producer (`harness session-start preflight`) never writes a `preflight:` tag and the `preflight-before-*` policies stay closed forever on any repo with a local `.env`. The `min_version` floor on the FULL_TEMPLATE `git-preflight` hook moves `0.1.1` to `0.2.0` (probed by `harness doctor` via `preflight --version`), and the `PROFILE_DEPENDENCIES.full` preflight entry in the `harness init` wizard gains a matching `minVersion: "0.2.0"` so the dependency table surfaces the floor (it previously carried none, the only Full-profile dep without one). The floor is a doctor-warn / wizard-hint, not a forced install: an operator on a stale 0.1.x build still runs, just with the secret-detection footgun and a doctor warning. The `PreflightJson` consumer in `src/cli/session-start/index.ts` is unaffected: it filters checks by `status === "fail" | "error"`, so reclassified `warn` findings drop out cleanly, and the new agent-preflight `path:line` finding format is not parsed. The `init-full-template-pins.test.ts` drift guard moves with the floor.
25
+
26
+ ### Added
27
+
28
+ - **`harness approve understanding --task` accepts multiple ids: pre-approve a whole task batch in one operator action** (agent-tasks/0dce3880). The understanding gate is task-scoped: the `expire_on_tool_match` PostToolUse hook expires the approval on every `task_finish`, so a multi-task session (e.g. a CVE sweep across N repos) previously needed one `harness approve understanding` round-trip per task. `--task` is now variadic (`--task a b c`, or comma-joined `--task a,b,c`); each id gets its own task-scoped marker written up front. As the agent's active claim cycles through the listed tasks, each `task_start` finds its marker already present, so the operator approves once for the whole batch. The gate stays genuinely task-scoped: the operator's Understanding Report still has to enumerate every task it covers, only the round-trip count collapses. `ApproveUnderstandingOptions` gains `tasks?: string[]` (the back-compat single `task?: string` still works; `tasks` wins when both are set); the result's `taskMarker` field becomes `taskMarkers: TaskMarkerOutcome[]` (empty when no task resolved, one entry per id otherwise). Entries are comma-split, trimmed, and de-duplicated. The CLI prints one `task: ✓ …` line per id plus a batch summary when more than one was written.
29
+
30
+ ### Fixed
31
+
32
+ - **`harness pause` is registered as a top-level command again** (agent-tasks/8c4825e9). `harness pause` resolved as "unknown command" and was missing from `harness --help`. In `src/cli/index.ts` the `.command("pause")` call was chained directly onto the `migrate-home` command's `.action()`; because Commander's `.command()` returns the newly created subcommand (and `.description()/.option()/.action()` return `this`), that chain registered `pause` as `harness migrate-home pause` rather than as a sibling of the top-level `resume` command. The fix terminates the `migrate-home` chain and starts `pause` as its own `program.command("pause")` statement; the handler and options are unchanged. `migrate-home` itself was never broken (its action still runs when no subcommand is given). New `tests/cli/pause-command-registration.test.ts` drives `buildProgram()` + `run(["--help"])` to assert `pause` is top-level, is not a `migrate-home` subcommand, and appears in the help banner; the pre-existing `pause.test.ts` exercises the `pause()` function directly and so never covered the CLI wiring.
33
+ - **`harness approve understanding` no longer binds a session to a stale, unrelated Understanding Report** (agent-tasks/0dce3880, friction #1). Surfaced 2026-05-20 during a multi-repo CVE sweep: on a fresh session, `harness approve understanding` flipped a two-day-old report from a different investigation to `approved`, because `findLatestReportForSession`'s tolerant fallback adopted any report lacking a `sessionId` field, including one already cycled to `expired` by a prior task. Two complementary fixes: (1) `findLatestReportForSession` gains a `tolerantFallback` option; `harness approve understanding` passes `"uncompleted"`, which makes the sessionId-null fallback skip reports whose `approvalStatus` is a terminal `approved` / `expired` (those belong to a finished cycle and must not be re-adopted) while still accepting a fresh `pending` report. The gate read path (`checkPersistedReport`) and post-tool-use expiry keep the default `"any"` behaviour for back-compat. (2) When `harness approve understanding` flips a report that lacks a `sessionId`, it now stamps the current session id onto the report, so every later lookup strict-matches it and the tolerant fallback can never re-adopt it for a different session. The CLI surfaces this as `; stamped sessionId` on the `report:` line and `persistedReport.sessionIdStamped` in the result. Reports that already carry a `sessionId` are left untouched. The complete fix also wants the standalone `@lannguyensi/understanding-gate` Stop hook to write `sessionId` into reports at capture time; that cross-package change is tracked separately.
34
+ - **`harness approve understanding` no longer guesses a stale, unrelated session from a finished gate cycle** (agent-tasks/56f51f2b). When run without `--session`, without `$CLAUDE_SESSION_ID` / `$CODEX_SESSION_ID`, and without a gate-staged `.pending-approval`, the session-id resolver falls through to tier 5: read the id from the freshest persisted Understanding Report. That tier adopted the newest report regardless of its `approvalStatus`, so an `approved` / `expired` report from a different session days ago (e.g. a stale Codex session) could be picked, the approval marker written for that session, and the live session left gated. Tier 5 now only adopts a `pending` report (a fresh gate cycle no approval has consumed yet), mirroring the `tolerantFallback: "uncompleted"` restriction PR #218 applied to the report-flip path. When every report is already `approved` / `expired`, the command fails loudly with the existing no-session-id error instead of silently approving the wrong session. The residual case (a stale session left a never-approved `pending` report) is now caught by a loud CLI warning: when the id comes from tier 5, `harness approve understanding` prints a `⚠ WARNING` block naming the report file it guessed from and telling the operator to confirm the id against the running agent before trusting the marker. `ApproveUnderstandingResult` gains `newestReportPath`, set only for the `newest-report` source. This is distinct from the report-flip fix above (agent-tasks/0dce3880): that one stopped a stale report being *flipped*, this one stops a stale session id being *resolved*.
35
+
10
36
  ## [0.24.1] - 2026-05-19
11
37
 
12
38
  **Headline: post-migration Codex apply fix.** v0.24.0 dogfood found that `harness apply --runtime codex --install` refused on drift after a default claude-code apply had rewritten `.last-apply` without the prior `codex/config.toml` entry. Two helpers close the gap: forward-merge of orphan `.last-apply` entries across runtimes, and banner-prefix recovery of an on-disk harness-generated Codex artifact when the entry is missing. The `CODEX_GENERATED_HEADER_LINE` literal is now exported from `generate-codex-config.ts` (single source of truth) and pinned via a regression test so a future banner re-word can't silently disable recovery. **Operator action**: none. The next `harness apply --runtime codex --install` after upgrading to v0.24.1 auto-recovers; subsequent applies are idempotent no-ops. Operators still on v0.24.0 who hit drift-refuse can either upgrade to v0.24.1 or run `harness apply --runtime codex --install --overwrite-drift` once.
@@ -17,8 +17,24 @@ export interface ApproveUnderstandingOptions extends LoaderOptions {
17
17
  * exists, its content is used as the task id. If absent, no task
18
18
  * marker is written — the session marker is the only one (v1
19
19
  * back-compat).
20
+ *
21
+ * Single-id back-compat field. For pre-approving a batch use `tasks`;
22
+ * when both are set, `tasks` wins.
20
23
  */
21
24
  task?: string;
25
+ /**
26
+ * Multiple agent-tasks task ids to pre-approve in one operator action
27
+ * (harness/0dce3880 friction #2). One task-scoped marker is written
28
+ * per id. As the agent's active claim cycles through the listed
29
+ * tasks, each `task_start` finds its own marker already present, so a
30
+ * homogeneous batch (e.g. a CVE sweep across N repos) needs a single
31
+ * `harness approve understanding --task a b c` instead of one
32
+ * approval per `task_finish`. The understanding gate stays
33
+ * task-scoped: the operator's report still has to enumerate every
34
+ * task it covers; only the round-trip count collapses. Empty / blank
35
+ * entries are dropped and duplicates de-duplicated.
36
+ */
37
+ tasks?: string[];
22
38
  /** Override the reports directory (test injection). */
23
39
  reportsDir?: string;
24
40
  /** Override the harness.generated/ directory (test injection). */
@@ -37,6 +53,19 @@ export interface ApproveUnderstandingOptions extends LoaderOptions {
37
53
  reason: string;
38
54
  }>;
39
55
  }
56
+ /** Outcome of writing one task-scoped approval marker. */
57
+ export type TaskMarkerOutcome = {
58
+ ok: true;
59
+ taskId: string;
60
+ filePath: string;
61
+ approvedAt: string;
62
+ source: "flag" | "active-claim";
63
+ } | {
64
+ ok: false;
65
+ taskId: string;
66
+ reason: string;
67
+ source: "flag" | "active-claim";
68
+ };
40
69
  export interface ApproveUnderstandingResult {
41
70
  sessionId: string;
42
71
  /**
@@ -45,6 +74,14 @@ export interface ApproveUnderstandingResult {
45
74
  * which is the moment to sanity-check it against the live session.
46
75
  */
47
76
  sessionSource: "flag" | "env-claude" | "env-codex" | "pending-approval" | "newest-report";
77
+ /**
78
+ * When `sessionSource` is `"newest-report"`, the absolute path of the
79
+ * persisted report the session id was guessed from. Undefined for
80
+ * every other source. The CLI names this file in its loud tier-5
81
+ * "verify this is your live session" warning so the operator can open
82
+ * it and check before trusting the marker (harness/56f51f2b).
83
+ */
84
+ newestReportPath?: string;
48
85
  /**
49
86
  * Canonical gate-satisfying signal as of agent-tasks/88ca4bb3.
50
87
  * `ok: false` means the marker file could not be written (rare:
@@ -61,27 +98,17 @@ export interface ApproveUnderstandingResult {
61
98
  reason: string;
62
99
  };
63
100
  /**
64
- * Task-scoped marker write outcome. Present when --task / opts.task
65
- * was supplied OR when the active-claim file resolved one
66
- * (harness/494fd1e5). Null when no task was resolved through either
67
- * surface so a regression cannot silently flip session-only sessions
68
- * into task-mode.
101
+ * Task-scoped marker write outcomes, one entry per resolved task id
102
+ * (harness/0dce3880). Populated when `--task` / `opts.task` /
103
+ * `opts.tasks` was supplied OR when the active-claim file resolved an
104
+ * id (harness/494fd1e5). Empty array when no task was resolved
105
+ * through any surface, so a regression cannot silently flip
106
+ * session-only sessions into task-mode.
69
107
  *
70
- * The `source` field tells the operator which surface fed the id so
108
+ * The `source` field tells the operator which surface fed each id so
71
109
  * a wrong claim file can be spotted before it lands in the marker.
72
110
  */
73
- taskMarker: {
74
- ok: true;
75
- taskId: string;
76
- filePath: string;
77
- approvedAt: string;
78
- source: "flag" | "active-claim";
79
- } | {
80
- ok: false;
81
- taskId: string;
82
- reason: string;
83
- source: "flag" | "active-claim";
84
- } | null;
111
+ taskMarkers: TaskMarkerOutcome[];
85
112
  ledger: {
86
113
  ok: boolean;
87
114
  tag: string;
@@ -92,9 +119,18 @@ export interface ApproveUnderstandingResult {
92
119
  filePath: string;
93
120
  previousStatus: string | null;
94
121
  approvedAt: string;
122
+ /** True when this approval stamped a missing `sessionId` onto the report. */
123
+ sessionIdStamped: boolean;
95
124
  } | {
96
125
  ok: false;
97
126
  reason: string;
98
127
  };
99
128
  }
129
+ /**
130
+ * Normalise a list of task ids supplied via `opts.tasks` (or the CLI's
131
+ * variadic `--task`). Each entry is comma-split (so `--task a,b` and
132
+ * `--task a b` are equivalent), trimmed, blank entries dropped, and the
133
+ * result de-duplicated while preserving first-seen order.
134
+ */
135
+ export declare function dedupeTaskIds(raw: string[]): string[];
100
136
  export declare function approveUnderstanding(opts?: ApproveUnderstandingOptions): Promise<ApproveUnderstandingResult>;
@@ -136,15 +136,48 @@ function findLatestParseError(dir, sessionId) {
136
136
  }
137
137
  return null;
138
138
  }
139
- function rewriteReportApproved(filePath, approvedAt, approvedBy) {
139
+ function rewriteReportApproved(filePath, approvedAt, approvedBy, sessionId) {
140
140
  const raw = fs.readFileSync(filePath, "utf8");
141
141
  const parsed = JSON.parse(raw);
142
142
  const previousStatus = typeof parsed["approvalStatus"] === "string" ? parsed["approvalStatus"] : null;
143
143
  parsed["approvalStatus"] = "approved";
144
144
  parsed["approvedAt"] = approvedAt;
145
145
  parsed["approvedBy"] = approvedBy;
146
+ // Stamp the session id when the report lacks one (older Stop-hook
147
+ // package versions write reports without a `sessionId` field). This
148
+ // binds the report to the session that approved it, so every later
149
+ // lookup strict-matches it and the sessionId-null tolerant fallback
150
+ // can never re-adopt it for a different session (harness/0dce3880
151
+ // friction #1). A report that already carries a sessionId is left
152
+ // untouched — it is not this command's place to rewrite identity.
153
+ let sessionIdStamped = false;
154
+ const existing = parsed["sessionId"];
155
+ if (typeof existing !== "string" || existing.length === 0) {
156
+ parsed["sessionId"] = sessionId;
157
+ sessionIdStamped = true;
158
+ }
146
159
  atomicWriteFile(filePath, `${JSON.stringify(parsed, null, 2)}\n`);
147
- return { previousStatus };
160
+ return { previousStatus, sessionIdStamped };
161
+ }
162
+ /**
163
+ * Normalise a list of task ids supplied via `opts.tasks` (or the CLI's
164
+ * variadic `--task`). Each entry is comma-split (so `--task a,b` and
165
+ * `--task a b` are equivalent), trimmed, blank entries dropped, and the
166
+ * result de-duplicated while preserving first-seen order.
167
+ */
168
+ export function dedupeTaskIds(raw) {
169
+ const seen = new Set();
170
+ const out = [];
171
+ for (const entry of raw) {
172
+ for (const part of entry.split(",")) {
173
+ const id = part.trim();
174
+ if (id.length === 0 || seen.has(id))
175
+ continue;
176
+ seen.add(id);
177
+ out.push(id);
178
+ }
179
+ }
180
+ return out;
148
181
  }
149
182
  export async function approveUnderstanding(opts = {}) {
150
183
  // harness.generated/ holds the `.pending-approval` staging file (the
@@ -182,6 +215,7 @@ export async function approveUnderstanding(opts = {}) {
182
215
  defaultReportsDir(path.dirname(resolvePaths(opts).base));
183
216
  let sessionId = "";
184
217
  let sessionSource = "flag";
218
+ let newestReportPath;
185
219
  if (typeof opts.session === "string" && opts.session.length > 0) {
186
220
  sessionId = opts.session;
187
221
  sessionSource = "flag";
@@ -203,21 +237,36 @@ export async function approveUnderstanding(opts = {}) {
203
237
  sessionSource = "pending-approval";
204
238
  }
205
239
  else {
206
- const newest = listPersistedReports(reportsDir).find((r) => r.sessionId !== null);
240
+ // Tier 5: guess the session from the freshest persisted report.
241
+ // Restricted to `pending` reports. An `approved` / `expired`
242
+ // report belongs to a finished gate cycle (often a different
243
+ // session days ago); adopting its sessionId silently approves an
244
+ // unrelated session while the live one stays gated
245
+ // (harness/56f51f2b). A `pending` report is one the Stop hook
246
+ // just produced that no approval has consumed yet, so it is far
247
+ // more likely to be the current session's. This mirrors the
248
+ // `tolerantFallback: "uncompleted"` restriction PR #218 applied
249
+ // to the report-flip path below. The residual case — a stale
250
+ // session left a never-approved `pending` report — is caught by
251
+ // the loud tier-5 warning the CLI prints, which names the report
252
+ // file so the operator can verify before trusting the marker.
253
+ const newest = listPersistedReports(reportsDir).find((r) => r.sessionId !== null && r.approvalStatus === "pending");
207
254
  if (newest && newest.sessionId !== null) {
208
255
  sessionId = newest.sessionId;
209
256
  sessionSource = "newest-report";
257
+ newestReportPath = newest.filePath;
210
258
  }
211
259
  }
212
260
  }
213
261
  if (sessionId === "") {
214
262
  // Reaching here means: no --session flag, no $CLAUDE_SESSION_ID /
215
263
  // $CODEX_SESSION_ID env, no staged `.pending-approval`, AND no
216
- // persisted Understanding Report under <reportsDir> carries a
217
- // sessionId field. The gate has never blocked this session and the
218
- // agent never produced a report or every report's sessionId is
219
- // null (very old package versions). Spell out the retrieval paths
220
- // so the operator does not have to dig through docs.
264
+ // `pending` persisted Understanding Report under <reportsDir>
265
+ // carries a sessionId field. Either the gate has never blocked this
266
+ // session and the agent never produced a report, or every report is
267
+ // already approved/expired or sessionId-null (tier 5 only adopts a
268
+ // fresh `pending` report). Spell out the retrieval paths so the
269
+ // operator does not have to dig through docs.
221
270
  throw new HarnessExitError([
222
271
  "no session id available. Pass --session <id>, or set $CLAUDE_SESSION_ID / $CODEX_SESSION_ID.",
223
272
  "",
@@ -276,47 +325,54 @@ export async function approveUnderstanding(opts = {}) {
276
325
  reason: `failed to write approval marker: ${err.message}`,
277
326
  };
278
327
  }
279
- // Task-scoped marker (harness/1ee26e77 + v2 auto-resolve in
280
- // harness/494fd1e5). Written alongside the session marker when:
281
- // - --task / opts.task was supplied (explicit, source: "flag"), OR
282
- // - the active-claim file resolves to a taskId (source: "active-claim").
283
- // A failure here is surfaced loudly but does not abort the approve
284
- // flow; the session marker still satisfies the gate as a fallback.
285
- let taskMarkerResult = null;
286
- let resolvedTaskId = null;
328
+ // Task-scoped markers (harness/1ee26e77 + v2 auto-resolve in
329
+ // harness/494fd1e5 + multi-task batch in harness/0dce3880). Written
330
+ // alongside the session marker. Resolution precedence:
331
+ // - opts.tasks (explicit, multi) pre-approve a whole batch, OR
332
+ // - opts.task (explicit, single, back-compat), OR
333
+ // - the active-claim file (source: "active-claim").
334
+ // A failure on any one id is surfaced loudly but does not abort the
335
+ // approve flow; the session marker still satisfies the gate as a
336
+ // fallback, and the other ids still get their markers.
337
+ let resolvedTaskIds = [];
287
338
  let taskSource = "flag";
288
- if (typeof opts.task === "string" && opts.task.length > 0) {
289
- resolvedTaskId = opts.task;
339
+ if (opts.tasks && opts.tasks.length > 0) {
340
+ resolvedTaskIds = dedupeTaskIds(opts.tasks);
341
+ taskSource = "flag";
342
+ }
343
+ else if (typeof opts.task === "string" && opts.task.length > 0) {
344
+ resolvedTaskIds = [opts.task];
290
345
  taskSource = "flag";
291
346
  }
292
347
  else {
293
348
  const fromFile = readActiveClaim(generatedDir);
294
349
  if (fromFile !== null) {
295
- resolvedTaskId = fromFile;
350
+ resolvedTaskIds = [fromFile];
296
351
  taskSource = "active-claim";
297
352
  }
298
353
  }
299
- if (resolvedTaskId !== null) {
354
+ const taskMarkers = [];
355
+ for (const taskId of resolvedTaskIds) {
300
356
  try {
301
- const filePath = writeTaskApprovalMarker(generatedDir, resolvedTaskId, {
357
+ const filePath = writeTaskApprovalMarker(generatedDir, taskId, {
302
358
  approvedAt: approvedAtMarker,
303
359
  approvedBy: approvedByMarker,
304
360
  });
305
- taskMarkerResult = {
361
+ taskMarkers.push({
306
362
  ok: true,
307
- taskId: resolvedTaskId,
363
+ taskId,
308
364
  filePath,
309
365
  approvedAt: approvedAtMarker,
310
366
  source: taskSource,
311
- };
367
+ });
312
368
  }
313
369
  catch (err) {
314
- taskMarkerResult = {
370
+ taskMarkers.push({
315
371
  ok: false,
316
- taskId: resolvedTaskId,
372
+ taskId,
317
373
  reason: `failed to write task marker: ${err.message}`,
318
374
  source: taskSource,
319
- };
375
+ });
320
376
  }
321
377
  }
322
378
  const tag = approvedLedgerTagFor(sessionId);
@@ -327,7 +383,14 @@ export async function approveUnderstanding(opts = {}) {
327
383
  // resolved up front (alongside session-id tier-5 lookup) so both
328
384
  // paths agree on the same directory.
329
385
  const reports = listPersistedReports(reportsDir);
330
- const latest = findLatestReportForSession(reports, sessionId);
386
+ // `tolerantFallback: "uncompleted"` never adopt a sessionId-null
387
+ // report that is already `approved` / `expired`. Such a report is
388
+ // from a prior, finished cycle (often a different task days ago);
389
+ // flipping it would bind the live session to a stale, unrelated
390
+ // Understanding Report (harness/0dce3880 friction #1).
391
+ const latest = findLatestReportForSession(reports, sessionId, {
392
+ tolerantFallback: "uncompleted",
393
+ });
331
394
  let persistedReport;
332
395
  if (!latest) {
333
396
  // When no matching report exists, look at the sibling parse-errors
@@ -355,12 +418,13 @@ export async function approveUnderstanding(opts = {}) {
355
418
  const approvedAt = (opts.now ?? new Date()).toISOString();
356
419
  const approvedBy = opts.approvedBy ?? DEFAULT_APPROVED_BY;
357
420
  try {
358
- const { previousStatus } = rewriteReportApproved(latest.filePath, approvedAt, approvedBy);
421
+ const { previousStatus, sessionIdStamped } = rewriteReportApproved(latest.filePath, approvedAt, approvedBy, sessionId);
359
422
  persistedReport = {
360
423
  ok: true,
361
424
  filePath: latest.filePath,
362
425
  previousStatus,
363
426
  approvedAt,
427
+ sessionIdStamped,
364
428
  };
365
429
  }
366
430
  catch (err) {
@@ -380,8 +444,9 @@ export async function approveUnderstanding(opts = {}) {
380
444
  return {
381
445
  sessionId,
382
446
  sessionSource,
447
+ ...(newestReportPath !== undefined ? { newestReportPath } : {}),
383
448
  marker: markerResult,
384
- taskMarker: taskMarkerResult,
449
+ taskMarkers,
385
450
  ledger: ledgerResult.ok
386
451
  ? { ok: true, tag }
387
452
  : { ok: false, tag, reason: ledgerResult.reason },
@@ -1 +1 @@
1
- {"version":3,"file":"understanding.js","sourceRoot":"","sources":["../../../src/cli/approve/understanding.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"understanding.js","sourceRoot":"","sources":["../../../src/cli/approve/understanding.ts"],"names":[],"mappings":"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"}
package/dist/cli/index.js CHANGED
@@ -250,7 +250,16 @@ export function buildProgram(opts = {}) {
250
250
  if (options.template !== undefined || options.config !== undefined) {
251
251
  throw new HarnessExitError("--interactive owns its own template + path choices; do not combine with --template / --config", EX_USAGE);
252
252
  }
253
- const r = await runInteractive({ stdout, stderr });
253
+ // Thread --force into the wizard's forceOverwrite: without it
254
+ // an existing manifest makes the wizard re-prompt, and
255
+ // `harness init --interactive --force` looked like it should
256
+ // overwrite non-interactively but the flag never reached
257
+ // runInteractive (harness/418cebd4).
258
+ const r = await runInteractive({
259
+ stdout,
260
+ stderr,
261
+ ...(options.force ? { forceOverwrite: true } : {}),
262
+ });
254
263
  if (r.aborted) {
255
264
  return;
256
265
  }
@@ -873,7 +882,7 @@ export function buildProgram(opts = {}) {
873
882
  .option("--config <path>", "manifest path (default: ~/.harness/harness.yaml; legacy fallback ~/.claude/harness.yaml)")
874
883
  .option("--project <name>", "apply per-project overrides")
875
884
  .option("--session <id>", "explicit session id (default: $CLAUDE_SESSION_ID)")
876
- .option("--task <id>", "agent-tasks task id — when set, also writes a task-scoped marker so the next task re-prompts for an Understanding Report (harness/1ee26e77)")
885
+ .option("--task <ids...>", "agent-tasks task id(s)writes one task-scoped marker per id. Pass several (--task a b c, or --task a,b,c) to pre-approve a whole batch in a single operator action so a multi-task session does not re-prompt per task_finish (harness/1ee26e77, harness/0dce3880)")
877
886
  .option("--reports-dir <path>", "override the persisted-report directory (default: ./.understanding-gate/reports)")
878
887
  .option("--approved-by <actor>", "actor to record on the persisted report (default: harness-approve-cli)")
879
888
  .action(async (options) => {
@@ -884,8 +893,10 @@ export function buildProgram(opts = {}) {
884
893
  cliOpts.project = options.project;
885
894
  if (options.session)
886
895
  cliOpts.session = options.session;
887
- if (options.task)
888
- cliOpts.task = options.task;
896
+ // Commander's variadic `<ids...>` yields a string[]; comma-split
897
+ // and de-dup happen inside approveUnderstanding (dedupeTaskIds).
898
+ if (options.task && options.task.length > 0)
899
+ cliOpts.tasks = options.task;
889
900
  if (options.reportsDir)
890
901
  cliOpts.reportsDir = options.reportsDir;
891
902
  if (options.approvedBy)
@@ -901,9 +912,29 @@ export function buildProgram(opts = {}) {
901
912
  : result.sessionSource === "env-codex"
902
913
  ? " (from $CODEX_SESSION_ID)"
903
914
  : result.sessionSource === "newest-report"
904
- ? " (resolved from sessionId field of the newest persisted Understanding Report)"
915
+ ? " (GUESSED from the newest pending Understanding Report)"
905
916
  : "";
906
917
  lines.push(`session: ${result.sessionId}${sourceNote}`);
918
+ if (result.sessionSource === "newest-report") {
919
+ // Tier-5 is a guess: no --session, no env var, no gate-staged
920
+ // .pending-approval. It is restricted to `pending` reports
921
+ // (harness/56f51f2b), but a stale session that left a never-
922
+ // approved report can still be picked. Name the report file
923
+ // so the operator can open it and confirm the id before
924
+ // trusting a marker that may approve the wrong session.
925
+ lines.push("");
926
+ lines.push("⚠ WARNING: the session id was GUESSED, not confirmed. There was no");
927
+ lines.push(" --session flag, no $CLAUDE_SESSION_ID / $CODEX_SESSION_ID, and no");
928
+ lines.push(" gate-staged .pending-approval, so it was read from the newest pending");
929
+ lines.push(" Understanding Report:");
930
+ if (result.newestReportPath) {
931
+ lines.push(` ${result.newestReportPath}`);
932
+ }
933
+ lines.push(" If that is not your live session, the marker above approves the wrong");
934
+ lines.push(" session and the gate stays blocked. Confirm the id matches the running");
935
+ lines.push(" agent ($CLAUDE_SESSION_ID / $CODEX_SESSION_ID); if it differs, re-run");
936
+ lines.push(" with --session <live-id>.");
937
+ }
907
938
  if (result.marker.ok) {
908
939
  lines.push(`marker: ✓ ${result.marker.filePath} (canonical gate signal)`);
909
940
  }
@@ -911,18 +942,22 @@ export function buildProgram(opts = {}) {
911
942
  lines.push(`marker: ✗ FAILED (${result.marker.reason})`);
912
943
  lines.push(" the gate WILL block the next tool call until the marker exists.");
913
944
  }
914
- if (result.taskMarker !== null) {
915
- const sourceNote = result.taskMarker.source === "active-claim"
945
+ for (const tm of result.taskMarkers) {
946
+ const sourceNote = tm.source === "active-claim"
916
947
  ? " (auto-resolved from active-claim file)"
917
948
  : "";
918
- if (result.taskMarker.ok) {
919
- lines.push(`task: ✓ ${result.taskMarker.filePath} (task-scoped, expires when this task ends)${sourceNote}`);
949
+ if (tm.ok) {
950
+ lines.push(`task: ✓ ${tm.filePath} (task-scoped, expires when this task ends)${sourceNote}`);
920
951
  }
921
952
  else {
922
- lines.push(`task: ✗ FAILED for task ${result.taskMarker.taskId}${sourceNote} (${result.taskMarker.reason})`);
953
+ lines.push(`task: ✗ FAILED for task ${tm.taskId}${sourceNote} (${tm.reason})`);
923
954
  lines.push(" the session marker above is still in effect; the task-scoped path is degraded.");
924
955
  }
925
956
  }
957
+ if (result.taskMarkers.length > 1) {
958
+ const okCount = result.taskMarkers.filter((t) => t.ok).length;
959
+ lines.push(` (${okCount}/${result.taskMarkers.length} task markers written — the batch is pre-approved)`);
960
+ }
926
961
  if (result.ledger.ok) {
927
962
  lines.push(`ledger: ✓ wrote ${result.ledger.tag} (audit only)`);
928
963
  }
@@ -931,7 +966,10 @@ export function buildProgram(opts = {}) {
931
966
  }
932
967
  if (result.persistedReport.ok) {
933
968
  const prev = result.persistedReport.previousStatus ?? "<missing>";
934
- lines.push(`report: ✓ ${result.persistedReport.filePath} (approvalStatus: ${prev} → approved)`);
969
+ const stampNote = result.persistedReport.sessionIdStamped
970
+ ? "; stamped sessionId"
971
+ : "";
972
+ lines.push(`report: ✓ ${result.persistedReport.filePath} (approvalStatus: ${prev} → approved${stampNote})`);
935
973
  }
936
974
  else {
937
975
  lines.push(`report: ⚠ skipped (${result.persistedReport.reason})`);
@@ -1453,7 +1491,14 @@ export function buildProgram(opts = {}) {
1453
1491
  if (result.outcome === "target-conflict") {
1454
1492
  throw new HarnessExitError("", EX_FAIL);
1455
1493
  }
1456
- })
1494
+ });
1495
+ // `harness pause` / `harness resume`: operator-only kill switch.
1496
+ // Sibling top-level commands: `pause` must start its own
1497
+ // `program.command(...)` statement. It was previously chained onto the
1498
+ // `migrate-home` block above, which (Commander's `.command()` returns
1499
+ // the new subcommand) registered it as `harness migrate-home pause`
1500
+ // and dropped it from top-level `harness --help`.
1501
+ program
1457
1502
  .command("pause")
1458
1503
  .description("Temporarily make all harness hooks dormant by writing a sentinel under harness.generated/. " +
1459
1504
  "Operator-only (refuses when $CLAUDE_SESSION_ID is set or stdin is non-TTY). Intended for " +