harnery 0.34.0 → 0.35.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/commander.d.ts.map +1 -1
- package/dist/commander.js +2 -0
- package/dist/commands/agents.d.ts +15 -4
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +91 -162
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +26 -2
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +2 -2
- package/dist/commands/events.d.ts.map +1 -1
- package/dist/commands/events.js +18 -1
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +2 -2
- package/dist/commands/semantic.d.ts +4 -0
- package/dist/commands/semantic.d.ts.map +1 -0
- package/dist/commands/semantic.js +147 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +17 -0
- package/dist/core/agents/canonical-emit.d.ts +3 -0
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +12 -0
- package/dist/core/agents/claim-path.d.ts +11 -0
- package/dist/core/agents/claim-path.d.ts.map +1 -0
- package/dist/core/agents/claim-path.js +22 -0
- package/dist/core/agents/coord-client.d.ts +29 -3
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +88 -9
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +1 -3
- package/dist/core/agents/live-lifecycle-v3.js +3 -3
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +2 -2
- package/dist/core/agents/render/prompt-context.js +12 -10
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +23 -11
- package/dist/core/agents/session-name-display.d.ts +2 -1
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +10 -3
- package/dist/core/agents/state/heartbeat-reader.d.ts +46 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -0
- package/dist/core/agents/state/heartbeat-reader.js +25 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts +3 -48
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +16 -34
- package/dist/core/agents/state/live-coordination-view.d.ts +1 -1
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +25 -1
- package/dist/core/agents/state/names.d.ts +9 -1
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +190 -182
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +23 -5
- package/dist/core/artifacts/constants.d.ts +5 -0
- package/dist/core/artifacts/constants.d.ts.map +1 -0
- package/dist/core/artifacts/constants.js +4 -0
- package/dist/core/artifacts/index.d.ts +3 -3
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +50 -7
- package/dist/core/events/v3/base-contract.d.ts +795 -0
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +33 -0
- package/dist/core/events/v3/capabilities.d.ts +11 -0
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +23 -0
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/index.d.ts +4 -3
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +4 -3
- package/dist/core/events/v3/latency.d.ts +31 -1
- package/dist/core/events/v3/latency.d.ts.map +1 -1
- package/dist/core/events/v3/latency.js +127 -3
- package/dist/core/events/v3/live-routing.d.ts +30 -0
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +109 -1
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +10 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +14 -3
- package/dist/core/events/v3/producers/hook-base.d.ts +17 -1
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +82 -1
- package/dist/core/events/v3/producers/intake.d.ts +6 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +11 -0
- package/dist/core/events/v3/producers/recorder.d.ts +62 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +654 -18
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +51 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +54 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +9 -0
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.d.ts +3 -0
- package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.js +14 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +119 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -0
- package/dist/core/hooks/adapter/runtime-telemetry.js +568 -0
- package/dist/core/hooks/cli.js +114 -38
- package/dist/core/hooks/remediation-cap.d.ts +34 -0
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -0
- package/dist/core/hooks/remediation-cap.js +71 -0
- package/dist/core/hooks/resolve/transcript.d.ts +25 -9
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +35 -17
- package/dist/core/semantic/adapters.d.ts +34 -0
- package/dist/core/semantic/adapters.d.ts.map +1 -0
- package/dist/core/semantic/adapters.js +222 -0
- package/dist/core/semantic/contract.d.ts +588 -0
- package/dist/core/semantic/contract.d.ts.map +1 -0
- package/dist/core/semantic/contract.js +230 -0
- package/dist/core/semantic/evidence.d.ts +11 -0
- package/dist/core/semantic/evidence.d.ts.map +1 -0
- package/dist/core/semantic/evidence.js +262 -0
- package/dist/core/semantic/index.d.ts +10 -0
- package/dist/core/semantic/index.d.ts.map +1 -0
- package/dist/core/semantic/index.js +9 -0
- package/dist/core/semantic/once.d.ts +33 -0
- package/dist/core/semantic/once.d.ts.map +1 -0
- package/dist/core/semantic/once.js +293 -0
- package/dist/core/semantic/prompt.d.ts +12 -0
- package/dist/core/semantic/prompt.d.ts.map +1 -0
- package/dist/core/semantic/prompt.js +70 -0
- package/dist/core/semantic/scheduler.d.ts +16 -0
- package/dist/core/semantic/scheduler.d.ts.map +1 -0
- package/dist/core/semantic/scheduler.js +67 -0
- package/dist/core/semantic/service-status.d.ts +31 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -0
- package/dist/core/semantic/service-status.js +84 -0
- package/dist/core/semantic/service.d.ts +51 -0
- package/dist/core/semantic/service.d.ts.map +1 -0
- package/dist/core/semantic/service.js +470 -0
- package/dist/core/semantic/storage.d.ts +71 -0
- package/dist/core/semantic/storage.d.ts.map +1 -0
- package/dist/core/semantic/storage.js +179 -0
- package/dist/core/semantic/validate.d.ts +16 -0
- package/dist/core/semantic/validate.d.ts.map +1 -0
- package/dist/core/semantic/validate.js +174 -0
- package/dist/lib/browser/client.d.ts +11 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +13 -0
- package/dist/lib/browser/index.d.ts +1 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/standalone-html.d.ts +25 -0
- package/dist/lib/browser/standalone-html.d.ts.map +1 -0
- package/dist/lib/browser/standalone-html.js +284 -0
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +1 -0
- package/dist/lib/instructions/templates.d.ts +2 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +144 -4
- package/package.json +6 -1
- package/schemas/event-v3.schema.json +2758 -478
- package/src/commander.ts +2 -0
- package/src/commands/agents.ts +104 -152
- package/src/commands/browse.ts +25 -2
- package/src/commands/decision.ts +8 -2
- package/src/commands/events.ts +21 -1
- package/src/commands/presence.ts +7 -2
- package/src/commands/semantic.ts +179 -0
- package/src/commands/web.ts +15 -0
- package/src/core/agents/canonical-emit.ts +15 -0
- package/src/core/agents/claim-path.ts +23 -0
- package/src/core/agents/coord-client.ts +92 -8
- package/src/core/agents/live-authority-v3.ts +1 -4
- package/src/core/agents/live-lifecycle-v3.ts +8 -3
- package/src/core/agents/live-observation-v3.ts +7 -2
- package/src/core/agents/render/prompt-context.ts +13 -10
- package/src/core/agents/rules/stop-hook.ts +24 -11
- package/src/core/agents/session-name-display.ts +11 -3
- package/src/core/agents/state/heartbeat-reader.ts +69 -0
- package/src/core/agents/state/heartbeat-writer.ts +20 -84
- package/src/core/agents/state/live-coordination-view.ts +26 -1
- package/src/core/agents/state/names.ts +190 -182
- package/src/core/agents/state/stale-sweep.ts +25 -5
- package/src/core/artifacts/constants.ts +4 -0
- package/src/core/artifacts/index.ts +49 -7
- package/src/core/events/v3/base-contract.ts +39 -0
- package/src/core/events/v3/capabilities.ts +34 -0
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/index.ts +21 -0
- package/src/core/events/v3/latency.ts +213 -2
- package/src/core/events/v3/live-routing.ts +120 -1
- package/src/core/events/v3/producers/command-recorder.ts +10 -1
- package/src/core/events/v3/producers/coordination-recorder.ts +17 -5
- package/src/core/events/v3/producers/hook-base.ts +115 -1
- package/src/core/events/v3/producers/intake.ts +18 -0
- package/src/core/events/v3/producers/recorder.ts +856 -21
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +137 -0
- package/src/core/events/v3/turn-telemetry.ts +10 -0
- package/src/core/hooks/adapter/parse.ts +16 -0
- package/src/core/hooks/adapter/runtime-telemetry.ts +805 -0
- package/src/core/hooks/cli.ts +126 -41
- package/src/core/hooks/remediation-cap.ts +77 -0
- package/src/core/hooks/resolve/transcript.ts +49 -17
- package/src/core/semantic/adapters.ts +293 -0
- package/src/core/semantic/contract.ts +298 -0
- package/src/core/semantic/evidence.ts +336 -0
- package/src/core/semantic/index.ts +127 -0
- package/src/core/semantic/once.ts +410 -0
- package/src/core/semantic/prompt.ts +84 -0
- package/src/core/semantic/scheduler.ts +107 -0
- package/src/core/semantic/service-status.ts +118 -0
- package/src/core/semantic/service.ts +580 -0
- package/src/core/semantic/storage.ts +286 -0
- package/src/core/semantic/validate.ts +212 -0
- package/src/lib/browser/client.ts +21 -0
- package/src/lib/browser/index.ts +4 -0
- package/src/lib/browser/standalone-html.ts +312 -0
- package/src/lib/instructions/apply.ts +1 -0
- package/src/lib/instructions/templates.ts +149 -4
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Read-only access to the generation-bound heartbeat cache. */
|
|
2
|
+
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, resolve, sep } from "node:path";
|
|
5
|
+
import type { AgentActivity, TaskState } from "./session-state.ts";
|
|
6
|
+
|
|
7
|
+
export interface Heartbeat {
|
|
8
|
+
schema_version?: number;
|
|
9
|
+
instance_id: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
kind?: string;
|
|
12
|
+
agent_id?: string;
|
|
13
|
+
session_id: string;
|
|
14
|
+
/** Native adapter session ID retained only in a generation-bound local projection. */
|
|
15
|
+
native_session_id?: string;
|
|
16
|
+
subagent_call_id?: string;
|
|
17
|
+
model?: string;
|
|
18
|
+
platform?: string;
|
|
19
|
+
started_at?: string;
|
|
20
|
+
last_heartbeat: string;
|
|
21
|
+
files_touched: string[];
|
|
22
|
+
task?: string;
|
|
23
|
+
task_updated_at?: string | null;
|
|
24
|
+
activity?: AgentActivity;
|
|
25
|
+
activity_updated_at?: string;
|
|
26
|
+
activity_source?: string;
|
|
27
|
+
task_state?: TaskState;
|
|
28
|
+
task_state_updated_at?: string;
|
|
29
|
+
task_state_reason?: string;
|
|
30
|
+
/** Session name built on the first non-empty set-task (never rebuilt). */
|
|
31
|
+
suggested_session_name?: string;
|
|
32
|
+
/** Stamped once the suggested name is seen in assistant reply text. */
|
|
33
|
+
session_name_seen_at?: string;
|
|
34
|
+
/** The specific suggested name proven present by the sighting stamp. */
|
|
35
|
+
session_name_seen_for?: string;
|
|
36
|
+
last_status_at?: string;
|
|
37
|
+
current_turn_id?: string;
|
|
38
|
+
parent_instance_id?: string;
|
|
39
|
+
workflow_run_id?: string;
|
|
40
|
+
workflow_agent_id?: string;
|
|
41
|
+
/** Disposable-cache bindings that prove a row belongs to the current V3 generation. */
|
|
42
|
+
v3_instance_id?: `inst_${string}`;
|
|
43
|
+
v3_generation_id?: `gen_${string}`;
|
|
44
|
+
v3_projection_event_id?: string;
|
|
45
|
+
v3_task_state?: "set" | "cleared";
|
|
46
|
+
[extra: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function heartbeatPath(coordRoot: string, instanceId: string): string {
|
|
50
|
+
if (!/^[A-Za-z0-9_-]{1,128}$/.test(instanceId)) {
|
|
51
|
+
throw new Error("instance_id must be 1-128 ASCII letters, digits, hyphens, or underscores");
|
|
52
|
+
}
|
|
53
|
+
const root = resolve(coordRoot, ".harnery", "active");
|
|
54
|
+
const candidate = resolve(root, `${instanceId}.json`);
|
|
55
|
+
if (!candidate.startsWith(`${root}${sep}`) || dirname(candidate) !== root) {
|
|
56
|
+
throw new Error("coordination filename must resolve directly beneath its root");
|
|
57
|
+
}
|
|
58
|
+
return candidate;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function readHeartbeat(coordRoot: string, instanceId: string): Heartbeat | null {
|
|
62
|
+
const path = heartbeatPath(coordRoot, instanceId);
|
|
63
|
+
if (!existsSync(path)) return null;
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(readFileSync(path, "utf8")) as Heartbeat;
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -23,65 +23,12 @@ import {
|
|
|
23
23
|
unlinkSync,
|
|
24
24
|
writeFileSync,
|
|
25
25
|
} from "node:fs";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import type
|
|
26
|
+
import { dirname, join } from "node:path";
|
|
27
|
+
import { canonicalClaimPath } from "../claim-path.ts";
|
|
28
|
+
import { type Heartbeat, heartbeatPath, readHeartbeat } from "./heartbeat-reader.ts";
|
|
29
|
+
import type { TaskState } from "./session-state.ts";
|
|
29
30
|
|
|
30
|
-
export
|
|
31
|
-
schema_version?: number;
|
|
32
|
-
instance_id: string;
|
|
33
|
-
name?: string;
|
|
34
|
-
kind?: string;
|
|
35
|
-
agent_id?: string;
|
|
36
|
-
session_id: string;
|
|
37
|
-
/** Native adapter session ID retained only in a generation-bound local projection. */
|
|
38
|
-
native_session_id?: string;
|
|
39
|
-
subagent_call_id?: string;
|
|
40
|
-
model?: string;
|
|
41
|
-
platform?: string;
|
|
42
|
-
started_at?: string;
|
|
43
|
-
last_heartbeat: string;
|
|
44
|
-
files_touched: string[];
|
|
45
|
-
task?: string;
|
|
46
|
-
task_updated_at?: string | null;
|
|
47
|
-
activity?: AgentActivity;
|
|
48
|
-
activity_updated_at?: string;
|
|
49
|
-
activity_source?: string;
|
|
50
|
-
task_state?: TaskState;
|
|
51
|
-
task_state_updated_at?: string;
|
|
52
|
-
task_state_reason?: string;
|
|
53
|
-
/** Session name built on the first non-empty set-task (never rebuilt). Its
|
|
54
|
-
* presence is the "this session has been named" signal the prompt-context
|
|
55
|
-
* nudge and the Stop-hook naming rule key on. */
|
|
56
|
-
suggested_session_name?: string;
|
|
57
|
-
/** Stamped by turn.completed once the suggested name is seen in assistant reply
|
|
58
|
-
* text, ending the per-turn transcript scan. */
|
|
59
|
-
session_name_seen_at?: string;
|
|
60
|
-
/** WHICH name that sighting was for. The scan is skipped only while this
|
|
61
|
-
* matches the current suggested name, so a re-minted name is detectable
|
|
62
|
-
* again rather than being suppressed by the earlier sighting. */
|
|
63
|
-
session_name_seen_for?: string;
|
|
64
|
-
last_status_at?: string;
|
|
65
|
-
current_turn_id?: string;
|
|
66
|
-
parent_instance_id?: string;
|
|
67
|
-
workflow_run_id?: string;
|
|
68
|
-
workflow_agent_id?: string;
|
|
69
|
-
/** Disposable-cache bindings that prove a row belongs to the current V3 generation. */
|
|
70
|
-
v3_instance_id?: `inst_${string}`;
|
|
71
|
-
v3_generation_id?: `gen_${string}`;
|
|
72
|
-
v3_projection_event_id?: string;
|
|
73
|
-
v3_task_state?: "set" | "cleared";
|
|
74
|
-
[extra: string]: unknown;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function heartbeatPath(coordRoot: string, instanceId: string): string {
|
|
78
|
-
assertSafeInstanceId(instanceId);
|
|
79
|
-
const safeInstanceId = basename(instanceId);
|
|
80
|
-
if (safeInstanceId !== instanceId) {
|
|
81
|
-
throw new Error("instance_id must be a direct-child coordination basename");
|
|
82
|
-
}
|
|
83
|
-
return resolveContainedFile(join(coordRoot, ".harnery", "active"), `${safeInstanceId}.json`);
|
|
84
|
-
}
|
|
31
|
+
export { type Heartbeat, readHeartbeat } from "./heartbeat-reader.ts";
|
|
85
32
|
|
|
86
33
|
function nowIsoSeconds(): string {
|
|
87
34
|
return new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
@@ -94,16 +41,6 @@ function atomicWrite(path: string, content: string): void {
|
|
|
94
41
|
renameSync(tmp, path);
|
|
95
42
|
}
|
|
96
43
|
|
|
97
|
-
export function readHeartbeat(coordRoot: string, instanceId: string): Heartbeat | null {
|
|
98
|
-
const path = heartbeatPath(coordRoot, instanceId);
|
|
99
|
-
if (!existsSync(path)) return null;
|
|
100
|
-
try {
|
|
101
|
-
return JSON.parse(readFileSync(path, "utf8")) as Heartbeat;
|
|
102
|
-
} catch {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
44
|
/** Persist operator-facing lifecycle prose in the generation-bound cache only. */
|
|
108
45
|
export function setLifecycleCache(
|
|
109
46
|
coordRoot: string,
|
|
@@ -221,16 +158,12 @@ export function releaseClaim(
|
|
|
221
158
|
instanceId: string,
|
|
222
159
|
path: string,
|
|
223
160
|
): Heartbeat | null {
|
|
224
|
-
|
|
225
|
-
// monorepo-relative entries; normalize both sides so release matches
|
|
226
|
-
// regardless of the form the caller passes (the old exact-string filter
|
|
227
|
-
// silently no-op'd on a form mismatch).
|
|
228
|
-
const norm = (p: string): string =>
|
|
229
|
-
p.startsWith(`${coordRoot}/`) ? p.slice(coordRoot.length + 1) : p;
|
|
230
|
-
const target = norm(path);
|
|
161
|
+
const target = canonicalClaimPath(coordRoot, path);
|
|
231
162
|
return mutate(coordRoot, instanceId, (hb) => ({
|
|
232
163
|
...hb,
|
|
233
|
-
files_touched: (hb.files_touched ?? []).filter(
|
|
164
|
+
files_touched: (hb.files_touched ?? []).filter(
|
|
165
|
+
(candidate) => canonicalClaimPath(coordRoot, candidate) !== target,
|
|
166
|
+
),
|
|
234
167
|
}));
|
|
235
168
|
}
|
|
236
169
|
|
|
@@ -240,12 +173,15 @@ export function acquireClaim(
|
|
|
240
173
|
instanceId: string,
|
|
241
174
|
path: string,
|
|
242
175
|
): Heartbeat | null {
|
|
243
|
-
const
|
|
244
|
-
p.startsWith(`${coordRoot}/`) ? p.slice(coordRoot.length + 1) : p;
|
|
245
|
-
const target = norm(path);
|
|
176
|
+
const target = canonicalClaimPath(coordRoot, path);
|
|
246
177
|
return mutate(coordRoot, instanceId, (hb) => ({
|
|
247
178
|
...hb,
|
|
248
|
-
files_touched: [
|
|
179
|
+
files_touched: [
|
|
180
|
+
...new Set([
|
|
181
|
+
...(hb.files_touched ?? []).map((candidate) => canonicalClaimPath(coordRoot, candidate)),
|
|
182
|
+
target,
|
|
183
|
+
]),
|
|
184
|
+
].sort(),
|
|
249
185
|
}));
|
|
250
186
|
}
|
|
251
187
|
|
|
@@ -282,9 +218,7 @@ export function findGroupClaims(
|
|
|
282
218
|
if (!groupId || !path) return hits;
|
|
283
219
|
const activeDir = join(coordRoot, ".harnery", "active");
|
|
284
220
|
if (!existsSync(activeDir)) return hits;
|
|
285
|
-
const
|
|
286
|
-
p.startsWith(`${coordRoot}/`) ? p.slice(coordRoot.length + 1) : p;
|
|
287
|
-
const target = norm(path);
|
|
221
|
+
const target = canonicalClaimPath(coordRoot, path);
|
|
288
222
|
for (const f of readdirSync(activeDir)) {
|
|
289
223
|
if (!f.endsWith(".json")) continue;
|
|
290
224
|
const hbPath = join(activeDir, f);
|
|
@@ -298,7 +232,9 @@ export function findGroupClaims(
|
|
|
298
232
|
(body.session_id as string | undefined) ?? (body.instance_id as string | undefined);
|
|
299
233
|
if (peerSession !== groupId) continue;
|
|
300
234
|
const files = (body.files_touched as string[] | undefined) ?? [];
|
|
301
|
-
if (!files.some((candidate) =>
|
|
235
|
+
if (!files.some((candidate) => canonicalClaimPath(coordRoot, candidate) === target)) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
302
238
|
hits.push({
|
|
303
239
|
instance_id: (body.instance_id as string | undefined) ?? f.replace(/\.json$/, ""),
|
|
304
240
|
session_id: body.session_id as string | undefined,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
nativeInstanceIdV3,
|
|
20
20
|
resolveLiveEventLedgerRouteV3,
|
|
21
21
|
} from "../../events/v3/live-routing.ts";
|
|
22
|
-
import { type Heartbeat, readHeartbeat } from "./heartbeat-
|
|
22
|
+
import { type Heartbeat, readHeartbeat } from "./heartbeat-reader.ts";
|
|
23
23
|
import { resolveName } from "./names.ts";
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -141,8 +141,33 @@ export function ensureLiveCoordinationHeartbeat(
|
|
|
141
141
|
|
|
142
142
|
const resolved = resolveName(coordRoot, nativeInstanceId, nativeSessionId);
|
|
143
143
|
const projected = projectHeartbeatV3(coordRoot, generation, undefined, nativeInstanceId);
|
|
144
|
+
// A generation reopen (resume, mid-flight onboarding) discards the stale
|
|
145
|
+
// cache, but the adapter tab it names is unchanged: same native session,
|
|
146
|
+
// same agent identity. Rebuilding without the naming evidence re-mints a
|
|
147
|
+
// fresh suggested name on the next set-task, so a multi-day session
|
|
148
|
+
// accumulates titles it is asked to display over and over. Carry the
|
|
149
|
+
// naming evidence across generations; everything else re-projects from V3.
|
|
150
|
+
// Same native session id means the same adapter tab; drop the carry only
|
|
151
|
+
// when the durable identity observably changed (a reassumed name would make
|
|
152
|
+
// the old "Agent <name> - …" block wrong for the new owner).
|
|
153
|
+
const identityUnchanged = !resolved?.name || !current?.name || resolved.name === current.name;
|
|
154
|
+
const carriedNaming =
|
|
155
|
+
current && current.session_id === nativeSessionId && identityUnchanged
|
|
156
|
+
? {
|
|
157
|
+
...(current.suggested_session_name
|
|
158
|
+
? { suggested_session_name: current.suggested_session_name }
|
|
159
|
+
: {}),
|
|
160
|
+
...(current.session_name_seen_for
|
|
161
|
+
? { session_name_seen_for: current.session_name_seen_for }
|
|
162
|
+
: {}),
|
|
163
|
+
...(current.session_name_seen_at
|
|
164
|
+
? { session_name_seen_at: current.session_name_seen_at }
|
|
165
|
+
: {}),
|
|
166
|
+
}
|
|
167
|
+
: {};
|
|
144
168
|
const materialized: V3HeartbeatMaterialization = {
|
|
145
169
|
...projected,
|
|
170
|
+
...carriedNaming,
|
|
146
171
|
schema_version: 2,
|
|
147
172
|
instance_id: nativeInstanceId,
|
|
148
173
|
session_id: nativeSessionId,
|