harnery 0.39.0 → 0.40.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.
@@ -237,7 +237,10 @@ async function handleStateAction(root, action, rest) {
237
237
  // same durable, idempotent pool path used by normal SessionStart.
238
238
  if (task && before && humanFacing && !before.name?.trim()) {
239
239
  const { assignName } = await import("./state/names.js");
240
- const name = assignName(root, owner, "session");
240
+ const { coordFreshnessSeconds } = await import("../config.js");
241
+ const name = assignName(root, owner, "session", {
242
+ freshnessSecs: coordFreshnessSeconds(root),
243
+ });
241
244
  before = writer.setAssignedNameCache(root, owner, name, "session");
242
245
  if (!before) {
243
246
  process.stderr.write(`agent-coord set-task: could not restore assigned name for ${owner}\n`);
@@ -273,7 +276,9 @@ async function handleStateAction(root, action, rest) {
273
276
  currentHumanFacing &&
274
277
  (!hb.name?.trim() || /^Agent unknown - /.test(hb.suggested_session_name ?? ""))) {
275
278
  const { assignName } = await import("./state/names.js");
276
- const name = hb.name?.trim() || assignName(root, owner, "session");
279
+ const { coordFreshnessSeconds } = await import("../config.js");
280
+ const name = hb.name?.trim() ||
281
+ assignName(root, owner, "session", { freshnessSecs: coordFreshnessSeconds(root) });
277
282
  hb = writer.setAssignedNameCache(root, owner, name, "session");
278
283
  }
279
284
  }
@@ -557,7 +562,11 @@ async function handleAssignName(root, rest) {
557
562
  process.stderr.write(`agent-coord assign-name: invalid kind ${kindArg}\n`);
558
563
  return 2;
559
564
  }
560
- const name = assignName(root, owner, kindArg, forkedFrom ? { forkedFrom } : undefined);
565
+ const { coordFreshnessSeconds } = await import("../config.js");
566
+ const name = assignName(root, owner, kindArg, {
567
+ freshnessSecs: coordFreshnessSeconds(root),
568
+ ...(forkedFrom ? { forkedFrom } : {}),
569
+ });
561
570
  process.stdout.write(`${JSON.stringify({
562
571
  instance_id: owner,
563
572
  name,
@@ -95,9 +95,9 @@ export declare function recordNameAssumption(coordRoot: string, instanceId: stri
95
95
  * the freshness window costs one skipped pool slot; a live agent missing from
96
96
  * the cache just restores the old counter-only behavior for that assignment.
97
97
  */
98
- export declare function readLiveNames(coordRoot: string, opts?: {
98
+ export declare function readLiveNames(coordRoot: string, opts: {
99
+ freshnessSecs: number;
99
100
  nowMs?: number;
100
- freshnessSecs?: number;
101
101
  }): Set<string>;
102
102
  /**
103
103
  * Assign a name to <instanceId> with the given <kind>. Counter-consuming when
@@ -109,10 +109,10 @@ export declare function readLiveNames(coordRoot: string, opts?: {
109
109
  * free name means all 260 are genuinely live, so the raw counter slot is used:
110
110
  * a duplicate name beats refusing to name an agent at all.
111
111
  */
112
- export declare function assignName(coordRoot: string, instanceId: string, kind: NameKind, opts?: {
112
+ export declare function assignName(coordRoot: string, instanceId: string, kind: NameKind, opts: {
113
+ freshnessSecs: number;
113
114
  forkedFrom?: string;
114
115
  nowMs?: number;
115
- freshnessSecs?: number;
116
116
  }): string;
117
117
  /** One step of recorded fork lineage: the latest row for <instanceId> that
118
118
  * carries `forked_from` (latest-row-wins, matching resolveName). */
@@ -1 +1 @@
1
- {"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/state/names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAaH,qBAAqB;AACrB,eAAO,MAAM,WAAW,85EA+Qd,CAAC;AAMX,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAE/E,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;2DAEuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAsCD;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4B5D;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,QAAoB,GACzB,oBAAoB,CAoBtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD,GAAG,CAAC,MAAM,CAAC,CA6Bb;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,QAAQ,EACd,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GACrE,MAAM,CA4CR;AAED;oEACoE;AACpE,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAUrD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAYrD"}
1
+ {"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/state/names.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAYH,qBAAqB;AACrB,eAAO,MAAM,WAAW,85EA+Qd,CAAC;AAMX,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,gBAAgB,CAAC;AAE/E,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;2DAEuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAsCD;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA4B5D;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,QAAoB,GACzB,oBAAoB,CAoBtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9C,GAAG,CAAC,MAAM,CAAC,CA4Bb;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACnE,MAAM,CA4CR;AAED;oEACoE;AACpE,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAUrD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAYrD"}
@@ -35,7 +35,6 @@
35
35
  */
36
36
  import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
37
37
  import { dirname, join } from "node:path";
38
- import { coordFreshnessSeconds } from "../../config.js";
39
38
  /** All 260 names. */
40
39
  export const COORD_NAMES = [
41
40
  // Pass 1 — female-first (A=female), alternating to Z
@@ -425,9 +424,8 @@ export function readLiveNames(coordRoot, opts) {
425
424
  catch {
426
425
  return live; // No cache yet (fresh checkout) → nothing is live.
427
426
  }
428
- const nowMs = opts?.nowMs ?? Date.now();
429
- const freshnessSecs = opts?.freshnessSecs ?? coordFreshnessSeconds(coordRoot);
430
- const cutoffMs = nowMs - freshnessSecs * 1000;
427
+ const nowMs = opts.nowMs ?? Date.now();
428
+ const cutoffMs = nowMs - opts.freshnessSecs * 1000;
431
429
  for (const entry of entries) {
432
430
  if (!entry.endsWith(".json"))
433
431
  continue;
@@ -471,8 +469,8 @@ export function assignName(coordRoot, instanceId, kind, opts) {
471
469
  // concurrent assignments can collide on one slot; doing the directory scan
472
470
  // first keeps that window exactly as narrow as it was before the skip existed.
473
471
  const live = readLiveNames(coordRoot, {
474
- ...(opts?.nowMs !== undefined ? { nowMs: opts.nowMs } : {}),
475
- ...(opts?.freshnessSecs !== undefined ? { freshnessSecs: opts.freshnessSecs } : {}),
472
+ freshnessSecs: opts.freshnessSecs,
473
+ ...(opts.nowMs !== undefined ? { nowMs: opts.nowMs } : {}),
476
474
  });
477
475
  const cPath = counterPath(coordRoot);
478
476
  let counter = 0;
@@ -491,7 +489,7 @@ export function assignName(coordRoot, instanceId, kind, opts) {
491
489
  }
492
490
  const name = COORD_NAMES[chosen % 260];
493
491
  atomicWrite(cPath, String(chosen + 1));
494
- const forkedFrom = opts?.forkedFrom;
492
+ const forkedFrom = opts.forkedFrom;
495
493
  appendHistory(coordRoot, {
496
494
  instance_id: instanceId,
497
495
  name,
@@ -31,7 +31,7 @@ import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.
31
31
  import { ensureLiveCoordinationHeartbeat } from "../agents/state/live-coordination-writer.js";
32
32
  import { assignName } from "../agents/state/names.js";
33
33
  import { writePidmapRow } from "../agents/state/pidmap.js";
34
- import { agentsRequireGitFinalization, hostPromptContextConfig, resolveBinName, } from "../config.js";
34
+ import { agentsRequireGitFinalization, coordFreshnessSeconds, hostPromptContextConfig, resolveBinName, } from "../config.js";
35
35
  import { checkpointContext, completeContextRecovery, extractContextSample, markContextCompactionCompleted, prepareContextRecovery, readContextState, recordContextSample, } from "../context/index.js";
36
36
  import { tryWriteLiveDisplayV3 } from "../events/v3/live-feed.js";
37
37
  import { liveHookSignalDefersDrainV3, reconcileLivePendingRuntimeContextV3, recordLiveDelegatedChildSessionV3, recordLiveHookSignalV3, resolveLiveEventLedgerRouteV3, } from "../events/v3/live-routing.js";
@@ -153,7 +153,10 @@ function logError(coordRoot, err, context) {
153
153
  */
154
154
  function assignNameInProcess(coordRoot, instanceId, kind, forkedFrom) {
155
155
  try {
156
- const name = assignName(coordRoot, instanceId, kind, forkedFrom ? { forkedFrom } : undefined);
156
+ const name = assignName(coordRoot, instanceId, kind, {
157
+ freshnessSecs: coordFreshnessSeconds(coordRoot),
158
+ ...(forkedFrom ? { forkedFrom } : {}),
159
+ });
157
160
  return { name, kind };
158
161
  }
159
162
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"live-session-v3.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/live-session-v3.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,SAAS,EAEf,MAAM,qCAAqC,CAAC;AAW7C,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,8FAA8F;AAC9F,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,2BAA2B,GAAG,SAAS,CA+CzF;AAED,2FAA2F;AAC3F,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,2BAA2B,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GAC1D,IAAI,CAmBN;AAiBD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"live-session-v3.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/live-session-v3.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,SAAS,EAEf,MAAM,qCAAqC,CAAC;AAY7C,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,8FAA8F;AAC9F,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,2BAA2B,GAAG,SAAS,CAiDzF;AAED,2FAA2F;AAC3F,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,2BAA2B,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GAC1D,IAAI,CAmBN;AAiBD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
@@ -4,6 +4,7 @@ import { clearCoordinationCache, setIdentityCache, } from "../agents/state/heart
4
4
  import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.js";
5
5
  import { ensureLiveCoordinationHeartbeat } from "../agents/state/live-coordination-writer.js";
6
6
  import { assignName } from "../agents/state/names.js";
7
+ import { coordFreshnessSeconds } from "../config.js";
7
8
  import { ensureEventLedgerV3 } from "../events/v3/bootstrap.js";
8
9
  import { recordLiveHookSignalV3, resolveLiveEventLedgerRouteV3, } from "../events/v3/live-routing.js";
9
10
  import { stableScopeId } from "./scope-id.js";
@@ -34,7 +35,9 @@ export function startWorkflowChildSessionV3(input) {
34
35
  const cache = ensureLiveCoordinationHeartbeat(input.coordRoot, input.instanceId, sessionId, adapter, input.model);
35
36
  if (!cache)
36
37
  throw new Error("workflow_child_v3_cache_missing");
37
- const name = assignName(input.coordRoot, input.instanceId, "workflow-child");
38
+ const name = assignName(input.coordRoot, input.instanceId, "workflow-child", {
39
+ freshnessSecs: coordFreshnessSeconds(input.coordRoot),
40
+ });
38
41
  if (input.label) {
39
42
  recordLiveTaskChangeV3({
40
43
  coordRoot: input.coordRoot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harnery",
3
- "version": "0.39.0",
3
+ "version": "0.40.0",
4
4
  "description": "Multi-agent coordination for AI coding agents - Claude Code, Cursor, and Codex.",
5
5
  "license": "MIT",
6
6
  "author": "Ryan Kelly",
@@ -260,7 +260,10 @@ async function handleStateAction(root: string, action: string, rest: string[]):
260
260
  // same durable, idempotent pool path used by normal SessionStart.
261
261
  if (task && before && humanFacing && !before.name?.trim()) {
262
262
  const { assignName } = await import("./state/names.ts");
263
- const name = assignName(root, owner, "session");
263
+ const { coordFreshnessSeconds } = await import("../config.ts");
264
+ const name = assignName(root, owner, "session", {
265
+ freshnessSecs: coordFreshnessSeconds(root),
266
+ });
264
267
  before = writer.setAssignedNameCache(root, owner, name, "session");
265
268
  if (!before) {
266
269
  process.stderr.write(
@@ -302,7 +305,10 @@ async function handleStateAction(root: string, action: string, rest: string[]):
302
305
  (!hb.name?.trim() || /^Agent unknown - /.test(hb.suggested_session_name ?? ""))
303
306
  ) {
304
307
  const { assignName } = await import("./state/names.ts");
305
- const name = hb.name?.trim() || assignName(root, owner, "session");
308
+ const { coordFreshnessSeconds } = await import("../config.ts");
309
+ const name =
310
+ hb.name?.trim() ||
311
+ assignName(root, owner, "session", { freshnessSecs: coordFreshnessSeconds(root) });
306
312
  hb = writer.setAssignedNameCache(root, owner, name, "session");
307
313
  }
308
314
  } catch (error) {
@@ -640,7 +646,11 @@ async function handleAssignName(root: string, rest: string[]): Promise<number> {
640
646
  process.stderr.write(`agent-coord assign-name: invalid kind ${kindArg}\n`);
641
647
  return 2;
642
648
  }
643
- const name = assignName(root, owner, kindArg, forkedFrom ? { forkedFrom } : undefined);
649
+ const { coordFreshnessSeconds } = await import("../config.ts");
650
+ const name = assignName(root, owner, kindArg, {
651
+ freshnessSecs: coordFreshnessSeconds(root),
652
+ ...(forkedFrom ? { forkedFrom } : {}),
653
+ });
644
654
  process.stdout.write(
645
655
  `${JSON.stringify({
646
656
  instance_id: owner,
@@ -43,7 +43,6 @@ import {
43
43
  writeFileSync,
44
44
  } from "node:fs";
45
45
  import { dirname, join } from "node:path";
46
- import { coordFreshnessSeconds } from "../../config.ts";
47
46
 
48
47
  /** All 260 names. */
49
48
  export const COORD_NAMES = [
@@ -472,7 +471,7 @@ export function recordNameAssumption(
472
471
  */
473
472
  export function readLiveNames(
474
473
  coordRoot: string,
475
- opts?: { nowMs?: number; freshnessSecs?: number },
474
+ opts: { freshnessSecs: number; nowMs?: number },
476
475
  ): Set<string> {
477
476
  const live = new Set<string>();
478
477
  const dir = join(coordRoot, ".harnery", "active");
@@ -483,9 +482,8 @@ export function readLiveNames(
483
482
  return live; // No cache yet (fresh checkout) → nothing is live.
484
483
  }
485
484
 
486
- const nowMs = opts?.nowMs ?? Date.now();
487
- const freshnessSecs = opts?.freshnessSecs ?? coordFreshnessSeconds(coordRoot);
488
- const cutoffMs = nowMs - freshnessSecs * 1000;
485
+ const nowMs = opts.nowMs ?? Date.now();
486
+ const cutoffMs = nowMs - opts.freshnessSecs * 1000;
489
487
 
490
488
  for (const entry of entries) {
491
489
  if (!entry.endsWith(".json")) continue;
@@ -518,7 +516,7 @@ export function assignName(
518
516
  coordRoot: string,
519
517
  instanceId: string,
520
518
  kind: NameKind,
521
- opts?: { forkedFrom?: string; nowMs?: number; freshnessSecs?: number },
519
+ opts: { freshnessSecs: number; forkedFrom?: string; nowMs?: number },
522
520
  ): string {
523
521
  // Check 1: existing history row → original name. A resume re-enters here,
524
522
  // which also makes fork stamping naturally idempotent: lineage lands only on
@@ -531,8 +529,8 @@ export function assignName(
531
529
  // concurrent assignments can collide on one slot; doing the directory scan
532
530
  // first keeps that window exactly as narrow as it was before the skip existed.
533
531
  const live = readLiveNames(coordRoot, {
534
- ...(opts?.nowMs !== undefined ? { nowMs: opts.nowMs } : {}),
535
- ...(opts?.freshnessSecs !== undefined ? { freshnessSecs: opts.freshnessSecs } : {}),
532
+ freshnessSecs: opts.freshnessSecs,
533
+ ...(opts.nowMs !== undefined ? { nowMs: opts.nowMs } : {}),
536
534
  });
537
535
 
538
536
  const cPath = counterPath(coordRoot);
@@ -553,7 +551,7 @@ export function assignName(
553
551
 
554
552
  const name = COORD_NAMES[chosen % 260]!;
555
553
  atomicWrite(cPath, String(chosen + 1));
556
- const forkedFrom = opts?.forkedFrom;
554
+ const forkedFrom = opts.forkedFrom;
557
555
  appendHistory(coordRoot, {
558
556
  instance_id: instanceId,
559
557
  name,
@@ -58,6 +58,7 @@ import { assignName } from "../agents/state/names.ts";
58
58
  import { writePidmapRow } from "../agents/state/pidmap.ts";
59
59
  import {
60
60
  agentsRequireGitFinalization,
61
+ coordFreshnessSeconds,
61
62
  hostPromptContextConfig,
62
63
  resolveBinName,
63
64
  } from "../config.ts";
@@ -251,7 +252,10 @@ function assignNameInProcess(
251
252
  forkedFrom?: string,
252
253
  ): { name: string; kind: string } | null {
253
254
  try {
254
- const name = assignName(coordRoot, instanceId, kind, forkedFrom ? { forkedFrom } : undefined);
255
+ const name = assignName(coordRoot, instanceId, kind, {
256
+ freshnessSecs: coordFreshnessSeconds(coordRoot),
257
+ ...(forkedFrom ? { forkedFrom } : {}),
258
+ });
255
259
  return { name, kind };
256
260
  } catch {
257
261
  return null;
@@ -9,6 +9,7 @@ import {
9
9
  import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.ts";
10
10
  import { ensureLiveCoordinationHeartbeat } from "../agents/state/live-coordination-writer.ts";
11
11
  import { assignName } from "../agents/state/names.ts";
12
+ import { coordFreshnessSeconds } from "../config.ts";
12
13
  import { ensureEventLedgerV3 } from "../events/v3/bootstrap.ts";
13
14
  import {
14
15
  recordLiveHookSignalV3,
@@ -59,7 +60,9 @@ export function startWorkflowChildSessionV3(input: WorkflowChildSessionV3Input):
59
60
  input.model,
60
61
  );
61
62
  if (!cache) throw new Error("workflow_child_v3_cache_missing");
62
- const name = assignName(input.coordRoot, input.instanceId, "workflow-child");
63
+ const name = assignName(input.coordRoot, input.instanceId, "workflow-child", {
64
+ freshnessSecs: coordFreshnessSeconds(input.coordRoot),
65
+ });
63
66
  if (input.label) {
64
67
  recordLiveTaskChangeV3({
65
68
  coordRoot: input.coordRoot,