harnery 0.37.0 → 0.38.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.
Files changed (184) hide show
  1. package/dist/commander.d.ts +9 -0
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +7 -2
  4. package/dist/commands/admission.d.ts +21 -0
  5. package/dist/commands/admission.d.ts.map +1 -0
  6. package/dist/commands/admission.js +565 -0
  7. package/dist/commands/agents.d.ts +7 -0
  8. package/dist/commands/agents.d.ts.map +1 -1
  9. package/dist/commands/agents.js +61 -1
  10. package/dist/commands/artifacts.d.ts.map +1 -1
  11. package/dist/commands/artifacts.js +48 -2
  12. package/dist/commands/browse-ai.d.ts +2 -2
  13. package/dist/commands/browse-ai.d.ts.map +1 -1
  14. package/dist/commands/browse-ai.js +6 -4
  15. package/dist/commands/browse.d.ts.map +1 -1
  16. package/dist/commands/browse.js +349 -21
  17. package/dist/commands/fetch.js +1 -0
  18. package/dist/commands/qa-record.d.ts +144 -0
  19. package/dist/commands/qa-record.d.ts.map +1 -0
  20. package/dist/commands/qa-record.js +0 -0
  21. package/dist/commands/qa-run.d.ts +7 -3
  22. package/dist/commands/qa-run.d.ts.map +1 -1
  23. package/dist/commands/qa-run.js +268 -13
  24. package/dist/commands/qa-status.d.ts +71 -0
  25. package/dist/commands/qa-status.d.ts.map +1 -0
  26. package/dist/commands/qa-status.js +490 -0
  27. package/dist/commands/qa-verify.d.ts +40 -0
  28. package/dist/commands/qa-verify.d.ts.map +1 -0
  29. package/dist/commands/qa-verify.js +180 -0
  30. package/dist/commands/review-pack.d.ts +4 -0
  31. package/dist/commands/review-pack.d.ts.map +1 -0
  32. package/dist/commands/review-pack.js +1001 -0
  33. package/dist/core/agents/qa-signal.d.ts +111 -0
  34. package/dist/core/agents/qa-signal.d.ts.map +1 -0
  35. package/dist/core/agents/qa-signal.js +231 -0
  36. package/dist/core/agents/session-name-display.d.ts +20 -5
  37. package/dist/core/agents/session-name-display.d.ts.map +1 -1
  38. package/dist/core/agents/session-name-display.js +67 -7
  39. package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
  40. package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
  41. package/dist/core/agents/state/heartbeat-writer.d.ts +11 -0
  42. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  43. package/dist/core/agents/state/heartbeat-writer.js +17 -0
  44. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  45. package/dist/core/agents/state/live-coordination-view.js +1 -0
  46. package/dist/core/agents/state/live-coordination-writer.js +5 -0
  47. package/dist/core/artifacts/constants.d.ts +1 -1
  48. package/dist/core/artifacts/constants.js +1 -1
  49. package/dist/core/artifacts/index.d.ts +57 -6
  50. package/dist/core/artifacts/index.d.ts.map +1 -1
  51. package/dist/core/artifacts/index.js +265 -10
  52. package/dist/core/config.d.ts +8 -0
  53. package/dist/core/config.d.ts.map +1 -1
  54. package/dist/core/config.js +16 -0
  55. package/dist/core/diagnostics/bundle.d.ts +16 -0
  56. package/dist/core/diagnostics/bundle.d.ts.map +1 -1
  57. package/dist/core/diagnostics/bundle.js +101 -7
  58. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  59. package/dist/core/events/v3/bootstrap.js +10 -0
  60. package/dist/core/events/v3/coordination-view.d.ts +3 -0
  61. package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
  62. package/dist/core/events/v3/coordination-view.js +69 -8
  63. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  64. package/dist/core/events/v3/producers/intake.js +9 -2
  65. package/dist/core/events/v3/producers/recorder.d.ts +23 -0
  66. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  67. package/dist/core/events/v3/producers/recorder.js +264 -18
  68. package/dist/core/hooks/cli.js +120 -27
  69. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  70. package/dist/core/hooks/resolve/transcript.js +10 -3
  71. package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
  72. package/dist/core/hooks/session-name-presence.js +4 -1
  73. package/dist/core/qa-artifacts.d.ts +20 -0
  74. package/dist/core/qa-artifacts.d.ts.map +1 -0
  75. package/dist/core/qa-artifacts.js +110 -0
  76. package/dist/core/resources/contract.d.ts +6 -0
  77. package/dist/core/resources/contract.d.ts.map +1 -1
  78. package/dist/core/resources/sampler.d.ts +7 -0
  79. package/dist/core/resources/sampler.d.ts.map +1 -1
  80. package/dist/core/resources/sampler.js +106 -5
  81. package/dist/lib/admission.d.ts +71 -0
  82. package/dist/lib/admission.d.ts.map +1 -0
  83. package/dist/lib/admission.js +264 -0
  84. package/dist/lib/agent-browser/client.d.ts +1 -1
  85. package/dist/lib/agent-browser/client.d.ts.map +1 -1
  86. package/dist/lib/agent-browser/client.js +1 -5
  87. package/dist/lib/browser/capture-fidelity.d.ts +39 -0
  88. package/dist/lib/browser/capture-fidelity.d.ts.map +1 -0
  89. package/dist/lib/browser/capture-fidelity.js +84 -0
  90. package/dist/lib/browser/client.d.ts +41 -1
  91. package/dist/lib/browser/client.d.ts.map +1 -1
  92. package/dist/lib/browser/client.js +167 -9
  93. package/dist/lib/browser/critique.d.ts +38 -1
  94. package/dist/lib/browser/critique.d.ts.map +1 -1
  95. package/dist/lib/browser/critique.js +34 -6
  96. package/dist/lib/browser/index.d.ts +4 -2
  97. package/dist/lib/browser/index.d.ts.map +1 -1
  98. package/dist/lib/browser/index.js +2 -0
  99. package/dist/lib/browser/page-review-judge.d.ts +64 -0
  100. package/dist/lib/browser/page-review-judge.d.ts.map +1 -0
  101. package/dist/lib/browser/page-review-judge.js +270 -0
  102. package/dist/lib/browser/page-review-pack.d.ts +613 -0
  103. package/dist/lib/browser/page-review-pack.d.ts.map +1 -0
  104. package/dist/lib/browser/page-review-pack.js +1751 -0
  105. package/dist/lib/browser/qa-run-contracts.d.ts +214 -10
  106. package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
  107. package/dist/lib/browser/qa-run-contracts.js +136 -1
  108. package/dist/lib/browser/qa-run.d.ts +100 -10
  109. package/dist/lib/browser/qa-run.d.ts.map +1 -1
  110. package/dist/lib/browser/qa-run.js +768 -169
  111. package/dist/lib/browser/request-diagnostics.d.ts +13 -0
  112. package/dist/lib/browser/request-diagnostics.d.ts.map +1 -0
  113. package/dist/lib/browser/request-diagnostics.js +18 -0
  114. package/dist/lib/browser/tiling.d.ts +19 -0
  115. package/dist/lib/browser/tiling.d.ts.map +1 -1
  116. package/dist/lib/browser/tiling.js +28 -0
  117. package/dist/lib/cookies/client.d.ts +9 -0
  118. package/dist/lib/cookies/client.d.ts.map +1 -1
  119. package/dist/lib/cookies/client.js +197 -44
  120. package/dist/lib/cookies/extra.d.ts +18 -0
  121. package/dist/lib/cookies/extra.d.ts.map +1 -0
  122. package/dist/lib/cookies/extra.js +14 -0
  123. package/dist/lib/cookies/index.d.ts +2 -1
  124. package/dist/lib/cookies/index.d.ts.map +1 -1
  125. package/dist/lib/cookies/index.js +2 -1
  126. package/dist/lib/durable-job.d.ts +124 -0
  127. package/dist/lib/durable-job.d.ts.map +1 -0
  128. package/dist/lib/durable-job.js +296 -0
  129. package/dist/lib/http/client.d.ts +7 -1
  130. package/dist/lib/http/client.d.ts.map +1 -1
  131. package/dist/lib/http/client.js +2 -0
  132. package/dist/lib/instructions/templates.d.ts.map +1 -1
  133. package/dist/lib/instructions/templates.js +5 -2
  134. package/package.json +8 -2
  135. package/src/commander.ts +50 -2
  136. package/src/commands/admission.ts +699 -0
  137. package/src/commands/agents.ts +87 -1
  138. package/src/commands/artifacts.ts +97 -21
  139. package/src/commands/browse-ai.ts +10 -5
  140. package/src/commands/browse.ts +481 -20
  141. package/src/commands/fetch.ts +1 -0
  142. package/src/commands/qa-record.ts +682 -0
  143. package/src/commands/qa-run.ts +335 -16
  144. package/src/commands/qa-status.ts +608 -0
  145. package/src/commands/qa-verify.ts +238 -0
  146. package/src/commands/review-pack.ts +1281 -0
  147. package/src/core/agents/qa-signal.ts +261 -0
  148. package/src/core/agents/session-name-display.ts +78 -7
  149. package/src/core/agents/state/heartbeat-reader.ts +7 -0
  150. package/src/core/agents/state/heartbeat-writer.ts +23 -0
  151. package/src/core/agents/state/live-coordination-view.ts +1 -0
  152. package/src/core/agents/state/live-coordination-writer.ts +5 -0
  153. package/src/core/artifacts/constants.ts +1 -1
  154. package/src/core/artifacts/index.ts +370 -21
  155. package/src/core/config.ts +23 -0
  156. package/src/core/diagnostics/bundle.ts +119 -11
  157. package/src/core/events/v3/bootstrap.ts +10 -0
  158. package/src/core/events/v3/coordination-view.ts +100 -11
  159. package/src/core/events/v3/producers/intake.ts +9 -2
  160. package/src/core/events/v3/producers/recorder.ts +312 -18
  161. package/src/core/hooks/cli.ts +140 -32
  162. package/src/core/hooks/resolve/transcript.ts +10 -3
  163. package/src/core/hooks/session-name-presence.ts +6 -1
  164. package/src/core/qa-artifacts.ts +126 -0
  165. package/src/core/resources/contract.ts +7 -0
  166. package/src/core/resources/sampler.ts +138 -6
  167. package/src/lib/admission.ts +347 -0
  168. package/src/lib/agent-browser/client.ts +2 -10
  169. package/src/lib/browser/capture-fidelity.ts +98 -0
  170. package/src/lib/browser/client.ts +206 -10
  171. package/src/lib/browser/critique.ts +62 -7
  172. package/src/lib/browser/index.ts +36 -0
  173. package/src/lib/browser/page-review-judge.ts +360 -0
  174. package/src/lib/browser/page-review-pack.ts +2384 -0
  175. package/src/lib/browser/qa-run-contracts.ts +366 -3
  176. package/src/lib/browser/qa-run.ts +868 -190
  177. package/src/lib/browser/request-diagnostics.ts +27 -0
  178. package/src/lib/browser/tiling.ts +32 -0
  179. package/src/lib/cookies/client.ts +228 -42
  180. package/src/lib/cookies/extra.ts +28 -0
  181. package/src/lib/cookies/index.ts +2 -0
  182. package/src/lib/durable-job.ts +407 -0
  183. package/src/lib/http/client.ts +13 -1
  184. package/src/lib/instructions/templates.ts +5 -2
@@ -21,6 +21,7 @@
21
21
  *
22
22
  * Never throws: coordination telemetry must not take down a hook.
23
23
  */
24
+ import { sessionNameDisplayAcceptedNames } from "../agents/session-name-display.js";
24
25
  import { stampSessionNameSeen } from "../agents/state/heartbeat-writer.js";
25
26
  import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.js";
26
27
  export function sessionNamePresence(coordRoot, instanceId, scanAssistantText) {
@@ -32,7 +33,9 @@ export function sessionNamePresence(coordRoot, instanceId, scanAssistantText) {
32
33
  if (row?.session_name_seen_for === name) {
33
34
  return { session_name_present: true, session_name_present_for: name };
34
35
  }
35
- const present = scanAssistantText(name);
36
+ // A display of the title Harnery last asked for counts here too, so Stop
37
+ // and the PreToolUse gate cannot disagree about the same reply.
38
+ const present = sessionNameDisplayAcceptedNames(row).some((candidate) => scanAssistantText(candidate));
36
39
  if (present)
37
40
  stampSessionNameSeen(coordRoot, instanceId, name);
38
41
  return { session_name_present: present, session_name_present_for: name };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Managed output workspaces for page-QA commands.
3
+ *
4
+ * An implicit qa-run/qa-record output is working evidence, not project source.
5
+ * Keep it in the bounded artifact store. Callers that pass --out-dir retain
6
+ * full control of that explicit destination.
7
+ */
8
+ import type { HarneryProgramContext } from "../commander.js";
9
+ export type QaArtifactKind = "qa-run" | "qa-record" | "review-pack";
10
+ export declare function resolveQaRepoRoot(context?: HarneryProgramContext): string;
11
+ export declare function createManagedQaOutParent(repoRoot: string, kind: QaArtifactKind, opts?: {
12
+ retentionMinutes?: number;
13
+ }): string;
14
+ /**
15
+ * Find the newest run in a valid managed QA workspace. This keeps no-path
16
+ * `qa-status` useful even though every implicit invocation gets an isolated
17
+ * artifact workspace instead of sharing one root-level `.qa-run` directory.
18
+ */
19
+ export declare function latestManagedQaRun(repoRoot: string): string | null;
20
+ //# sourceMappingURL=qa-artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qa-artifacts.d.ts","sourceRoot":"","sources":["../../src/core/qa-artifacts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAW7D,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,WAAW,GAAG,aAAa,CAAC;AAEpE,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAEzE;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,cAAc,EACpB,IAAI,GAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,MAAM,CAcR;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuClE"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Managed output workspaces for page-QA commands.
3
+ *
4
+ * An implicit qa-run/qa-record output is working evidence, not project source.
5
+ * Keep it in the bounded artifact store. Callers that pass --out-dir retain
6
+ * full control of that explicit destination.
7
+ */
8
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
9
+ import { join, resolve } from "node:path";
10
+ import { monorepoRoot } from "./agents/index.js";
11
+ import { ARTIFACT_MANIFEST, artifactsRoot, configuredArtifactRetentionDays, createArtifact, parseArtifactManifest, } from "./artifacts/index.js";
12
+ export function resolveQaRepoRoot(context) {
13
+ return resolve(context?.repoRoot ?? monorepoRoot() ?? process.cwd());
14
+ }
15
+ export function createManagedQaOutParent(repoRoot, kind, opts = {}) {
16
+ return createArtifact(repoRoot, {
17
+ slug: kind,
18
+ purpose: kind === "qa-run"
19
+ ? "Page QA run evidence"
20
+ : kind === "review-pack"
21
+ ? "Page review pack"
22
+ : "Hand-recorded page QA evidence",
23
+ retentionDays: configuredArtifactRetentionDays(repoRoot),
24
+ // A standalone review-pack workspace IS the pack, so the artifact store's
25
+ // own expiry follows the pack's (90 minutes by default, ruled 2026-09-02).
26
+ ...(opts.retentionMinutes !== undefined ? { retentionMinutes: opts.retentionMinutes } : {}),
27
+ }).path;
28
+ }
29
+ /**
30
+ * Find the newest run in a valid managed QA workspace. This keeps no-path
31
+ * `qa-status` useful even though every implicit invocation gets an isolated
32
+ * artifact workspace instead of sharing one root-level `.qa-run` directory.
33
+ */
34
+ export function latestManagedQaRun(repoRoot) {
35
+ const root = artifactsRoot(repoRoot);
36
+ if (!existsSync(root))
37
+ return null;
38
+ let workspaceNames;
39
+ try {
40
+ workspaceNames = readdirSync(root).sort();
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ let latest = null;
46
+ for (const workspaceName of workspaceNames) {
47
+ const workspace = join(root, workspaceName);
48
+ const manifest = readQaManifest(join(workspace, ARTIFACT_MANIFEST));
49
+ if (!manifest)
50
+ continue;
51
+ let runNames;
52
+ try {
53
+ runNames = readdirSync(workspace)
54
+ .filter((name) => name.startsWith("run-"))
55
+ .sort();
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ for (const runName of runNames) {
61
+ const runDir = join(workspace, runName);
62
+ const startedAtMs = readStartedAtMs(runDir);
63
+ if (startedAtMs === null)
64
+ continue;
65
+ if (latest === null ||
66
+ startedAtMs > latest.startedAtMs ||
67
+ (startedAtMs === latest.startedAtMs && runDir > latest.path)) {
68
+ latest = { path: runDir, startedAtMs };
69
+ }
70
+ }
71
+ }
72
+ return latest?.path ?? null;
73
+ }
74
+ function readQaManifest(path) {
75
+ try {
76
+ const parsed = parseArtifactManifest(JSON.parse(readFileSync(path, "utf8")));
77
+ if (!parsed.ok)
78
+ return null;
79
+ if (parsed.manifest.slug !== "qa-run" && parsed.manifest.slug !== "qa-record")
80
+ return null;
81
+ return parsed.manifest;
82
+ }
83
+ catch {
84
+ return null;
85
+ }
86
+ }
87
+ function readStartedAtMs(runDir) {
88
+ for (const file of ["run-status.json", "page-qa-result.json"]) {
89
+ try {
90
+ const value = JSON.parse(readFileSync(join(runDir, file), "utf8"));
91
+ const run = value.run;
92
+ const startedAt = typeof value.started_at === "string"
93
+ ? value.started_at
94
+ : run &&
95
+ typeof run === "object" &&
96
+ typeof run.started_at === "string"
97
+ ? run.started_at
98
+ : null;
99
+ if (!startedAt)
100
+ continue;
101
+ const parsed = Date.parse(startedAt);
102
+ if (!Number.isNaN(parsed))
103
+ return parsed;
104
+ }
105
+ catch {
106
+ // Try the other authoritative run document.
107
+ }
108
+ }
109
+ return null;
110
+ }
@@ -14,6 +14,7 @@ export interface ResourceProcessSample {
14
14
  owner_kind: "agent" | "service" | "unattributed";
15
15
  owner_id: string | null;
16
16
  owner_root_pid: number | null;
17
+ owner_source?: "pid-map" | "session-environment" | "service";
17
18
  }
18
19
  export interface ResourceProcessGroup {
19
20
  kind: ResourceProcessSample["owner_kind"];
@@ -82,6 +83,11 @@ export interface ResourceSamplerState {
82
83
  cpu_total_ticks: number;
83
84
  cpu_idle_ticks: number;
84
85
  process_ticks: Map<string, number>;
86
+ process_owners: Map<string, ResourceProcessOwnerProof>;
87
+ }
88
+ export interface ResourceProcessOwnerProof {
89
+ session_id: string;
90
+ instance_id: string;
85
91
  }
86
92
  export interface ResourceSampleResult {
87
93
  snapshot: ResourceSnapshot;
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/core/resources/contract.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../../src/core/resources/contract.ts"],"names":[],"mappings":"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"}
@@ -8,10 +8,17 @@ interface ResourceSamplerOptions {
8
8
  pid: number;
9
9
  id: string;
10
10
  }[];
11
+ sessionOwners?: readonly SessionOwner[];
11
12
  unattributedCpuFloor?: number;
12
13
  unattributedRssFloor?: number;
13
14
  maxProcesses?: number;
14
15
  }
16
+ interface SessionOwner {
17
+ nativeSessionId: string;
18
+ instanceId: string;
19
+ platform: string;
20
+ kind: string;
21
+ }
15
22
  export declare function sampleResources(coordRoot: string, previous?: ResourceSamplerState, options?: ResourceSamplerOptions): ResourceSampleResult;
16
23
  export declare function parseLinuxProcessStat(line: string): {
17
24
  pid: number;
@@ -1 +1 @@
1
- {"version":3,"file":"sampler.d.ts","sourceRoot":"","sources":["../../../src/core/resources/sampler.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAE1B,MAAM,eAAe,CAAC;AA0BvB,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAKD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,OAAO,GAAE,sBAA2B,GACnC,oBAAoB,CAgItB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CA0BP;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAuB7D"}
1
+ {"version":3,"file":"sampler.d.ts","sourceRoot":"","sources":["../../../src/core/resources/sampler.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAE1B,MAAM,eAAe,CAAC;AA0BvB,UAAU,sBAAsB;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAKD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,OAAO,GAAE,sBAA2B,GACnC,oBAAoB,CAmJtB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CA0BP;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAuB7D"}
@@ -3,6 +3,7 @@ import { existsSync, readdirSync, readFileSync, readlinkSync } from "node:fs";
3
3
  import { cpus, loadavg, platform, release } from "node:os";
4
4
  import { basename, join } from "node:path";
5
5
  import { performance } from "node:perf_hooks";
6
+ import { readLiveCoordinationRows } from "../agents/state/live-coordination-view.js";
6
7
  import { parsePidmapRow } from "../agents/state/pidmap.js";
7
8
  import { checkPidToken } from "../agents/state/proc-start.js";
8
9
  import { RESOURCE_SNAPSHOT_SCHEMA_VERSION, } from "./contract.js";
@@ -36,7 +37,15 @@ export function sampleResources(coordRoot, previous, options = {}) {
36
37
  const cpu = parseLinuxCpu(readFileSync(join(procRoot, "stat"), "utf8"));
37
38
  const memory = parseMeminfo(readFileSync(join(procRoot, "meminfo"), "utf8"));
38
39
  const readings = readLinuxProcesses(procRoot, clockTicks, pageSize, uptimeSeconds);
39
- const anchors = readOwnershipAnchors(coordRoot, readings, options.services ?? []);
40
+ const liveSessionOwners = uniqueLiveCodexSessionOwners(options.sessionOwners ??
41
+ readLiveCoordinationRows(coordRoot).map((row) => ({
42
+ nativeSessionId: row.native_session_id ?? "",
43
+ instanceId: row.instance_id,
44
+ platform: row.platform ?? "",
45
+ kind: row.kind ?? "",
46
+ })));
47
+ const ownership = readOwnershipAnchors(coordRoot, procRoot, readings, options.services ?? [], liveSessionOwners, previous?.process_owners);
48
+ const anchors = ownership.anchors;
40
49
  const byPid = new Map(readings.map((reading) => [reading.pid, reading]));
41
50
  const processTicks = new Map();
42
51
  const intervalMs = previous ? Math.max(0, nowMs - previous.sampled_at_ms) : null;
@@ -64,6 +73,7 @@ export function sampleResources(coordRoot, previous, options = {}) {
64
73
  owner_kind: ownership?.kind ?? "unattributed",
65
74
  owner_id: ownership?.id ?? null,
66
75
  owner_root_pid: ownership?.rootPid ?? null,
76
+ ...(ownership ? { owner_source: ownership.source } : {}),
67
77
  };
68
78
  });
69
79
  const visible = processes
@@ -121,6 +131,7 @@ export function sampleResources(coordRoot, previous, options = {}) {
121
131
  cpu_total_ticks: cpu.total,
122
132
  cpu_idle_ticks: cpu.idle,
123
133
  process_ticks: processTicks,
134
+ process_owners: ownership.processOwners,
124
135
  },
125
136
  };
126
137
  }
@@ -212,7 +223,7 @@ function readLinuxProcesses(procRoot, clockTicks, pageSize, uptimeSeconds) {
212
223
  }
213
224
  return rows;
214
225
  }
215
- function readOwnershipAnchors(coordRoot, readings, services) {
226
+ function readOwnershipAnchors(coordRoot, procRoot, readings, services, liveSessionOwners, previousOwners) {
216
227
  const byPid = new Set(readings.map((row) => row.pid));
217
228
  const directory = join(coordRoot, ".harnery", "pid-map");
218
229
  const anchors = new Map();
@@ -227,19 +238,109 @@ function readOwnershipAnchors(coordRoot, readings, services) {
227
238
  const row = parsePidmapRow(readFileSync(join(directory, entry), "utf8"));
228
239
  if (!row.instanceId || checkPidToken(pid, row.startToken) === "mismatch")
229
240
  continue;
230
- anchors.set(pid, { kind: "agent", id: row.instanceId });
241
+ anchors.set(pid, { kind: "agent", id: row.instanceId, source: "pid-map" });
231
242
  }
232
243
  catch {
233
244
  // An unreadable or racing row cannot prove ownership.
234
245
  }
235
246
  }
236
247
  }
248
+ const processOwners = readBridgeProcessOwners(procRoot, readings, liveSessionOwners, previousOwners);
249
+ const byReadingPid = new Map(readings.map((row) => [row.pid, row]));
250
+ for (const reading of readings) {
251
+ const identity = `${reading.pid}:${reading.startTicks}`;
252
+ const owner = processOwners.get(identity);
253
+ if (!owner || anchors.has(reading.pid))
254
+ continue;
255
+ const parent = byReadingPid.get(reading.ppid);
256
+ const parentOwner = parent
257
+ ? processOwners.get(`${parent.pid}:${parent.startTicks}`)
258
+ : undefined;
259
+ if (parentOwner?.instance_id === owner.instance_id)
260
+ continue;
261
+ anchors.set(reading.pid, {
262
+ kind: "agent",
263
+ id: owner.instance_id,
264
+ source: "session-environment",
265
+ });
266
+ }
237
267
  for (const service of services) {
238
268
  if (byPid.has(service.pid) && service.id.trim()) {
239
- anchors.set(service.pid, { kind: "service", id: service.id.trim() });
269
+ anchors.set(service.pid, { kind: "service", id: service.id.trim(), source: "service" });
270
+ }
271
+ }
272
+ return { anchors, processOwners };
273
+ }
274
+ function uniqueLiveCodexSessionOwners(rows) {
275
+ const candidates = new Map();
276
+ for (const row of rows) {
277
+ const sessionId = row.nativeSessionId.trim();
278
+ const instanceId = row.instanceId.trim();
279
+ if (row.platform !== "codex" || row.kind !== "session" || !sessionId || !instanceId)
280
+ continue;
281
+ const owners = candidates.get(sessionId) ?? new Set();
282
+ owners.add(instanceId);
283
+ candidates.set(sessionId, owners);
284
+ }
285
+ const result = new Map();
286
+ for (const [sessionId, owners] of candidates) {
287
+ if (owners.size === 1)
288
+ result.set(sessionId, [...owners][0]);
289
+ }
290
+ return result;
291
+ }
292
+ function readBridgeProcessOwners(procRoot, readings, liveSessionOwners, previousOwners) {
293
+ const result = new Map();
294
+ if (liveSessionOwners.size === 0)
295
+ return result;
296
+ for (const reading of readings) {
297
+ const identity = `${reading.pid}:${reading.startTicks}`;
298
+ const previous = previousOwners?.get(identity);
299
+ if (previous && liveSessionOwners.get(previous.session_id) === previous.instance_id) {
300
+ result.set(identity, previous);
301
+ continue;
240
302
  }
303
+ const sessionId = readCodexWslBridgeSessionId(procRoot, reading.pid);
304
+ if (!sessionId)
305
+ continue;
306
+ const instanceId = liveSessionOwners.get(sessionId);
307
+ if (instanceId)
308
+ result.set(identity, { session_id: sessionId, instance_id: instanceId });
241
309
  }
242
- return anchors;
310
+ return result;
311
+ }
312
+ function readCodexWslBridgeSessionId(procRoot, pid) {
313
+ try {
314
+ const entries = readFileSync(join(procRoot, String(pid), "environ"), "utf8").split("\0");
315
+ let bridge;
316
+ let platform;
317
+ let coordinationSessionId;
318
+ let codexThreadId;
319
+ for (const entry of entries) {
320
+ if (entry.startsWith("HARNERY_AGENT_COORD_BRIDGE=")) {
321
+ bridge = entry.slice("HARNERY_AGENT_COORD_BRIDGE=".length);
322
+ }
323
+ else if (entry.startsWith("HARNERY_AGENT_COORD_PLATFORM=")) {
324
+ platform = entry.slice("HARNERY_AGENT_COORD_PLATFORM=".length);
325
+ }
326
+ else if (entry.startsWith("HARNERY_AGENT_COORD_SESSION_ID=")) {
327
+ coordinationSessionId = entry.slice("HARNERY_AGENT_COORD_SESSION_ID=".length);
328
+ }
329
+ else if (entry.startsWith("CODEX_THREAD_ID=")) {
330
+ codexThreadId = entry.slice("CODEX_THREAD_ID=".length);
331
+ }
332
+ }
333
+ if (bridge === "codex-wsl" &&
334
+ platform === "codex" &&
335
+ coordinationSessionId &&
336
+ coordinationSessionId === codexThreadId) {
337
+ return coordinationSessionId;
338
+ }
339
+ }
340
+ catch {
341
+ // An unreadable or racing environment cannot prove ownership.
342
+ }
343
+ return undefined;
243
344
  }
244
345
  function resolveOwnership(pid, byPid, anchors) {
245
346
  const seen = new Set();
@@ -0,0 +1,71 @@
1
+ export interface AdmissionConfig {
2
+ /** Base directory holding one subdirectory per resource. */
3
+ dir: string;
4
+ /** Resource name, e.g. "browser-qa" or "build". */
5
+ resource: string;
6
+ /** Maximum concurrent holders. */
7
+ capacity: number;
8
+ /** Poll interval while waiting (default 500ms). */
9
+ pollMs?: number;
10
+ /** Entries older than this are pruned regardless of PID (default 6h). */
11
+ ttlMs?: number;
12
+ }
13
+ export interface AdmissionEntry {
14
+ pid: number;
15
+ label: string;
16
+ created_at: string;
17
+ /** Set on holders once admitted. */
18
+ acquired_at?: string;
19
+ }
20
+ export interface AdmissionWaitInfo {
21
+ /** 1-based position in the ticket queue. */
22
+ position: number;
23
+ holders: AdmissionEntry[];
24
+ }
25
+ export interface AdmissionAcquireOptions {
26
+ /** Human-readable holder description shown in status listings. */
27
+ label: string;
28
+ /** Maximum wait before AdmissionTimeoutError (default 20 minutes). */
29
+ timeoutMs?: number;
30
+ /** Progress callback, invoked at most once per poll while waiting. */
31
+ onWait?: (info: AdmissionWaitInfo) => void;
32
+ }
33
+ export interface AdmissionHandle {
34
+ /** The held entry's filename (diagnostics). */
35
+ entry: string;
36
+ /** Milliseconds spent waiting in the queue. */
37
+ waitedMs: number;
38
+ /** Give the slot back. Safe to call more than once. */
39
+ release: () => void;
40
+ }
41
+ export declare class AdmissionTimeoutError extends Error {
42
+ readonly holders: AdmissionEntry[];
43
+ constructor(resource: string, timeoutMs: number, holders: AdmissionEntry[]);
44
+ }
45
+ /** Is a PID alive on this machine? EPERM counts as alive; only ESRCH counts
46
+ * as dead (fail toward respecting holders rather than stealing slots). */
47
+ export declare function pidAlive(pid: number): boolean;
48
+ /**
49
+ * Join the FIFO queue for one resource and resolve once a slot is held.
50
+ * Throws AdmissionTimeoutError (with the holders snapshot) when no slot
51
+ * frees within the timeout — the caller decides whether that is fatal.
52
+ */
53
+ export declare function acquireAdmission(config: AdmissionConfig, options: AdmissionAcquireOptions): Promise<AdmissionHandle>;
54
+ export interface AdmissionStatus {
55
+ resource: string;
56
+ capacity?: number;
57
+ holders: AdmissionEntry[];
58
+ waiters: AdmissionEntry[];
59
+ }
60
+ /** Snapshot the queue for one resource, pruning dead entries on the way. */
61
+ export declare function admissionStatus(config: Pick<AdmissionConfig, "dir" | "resource" | "ttlMs">): AdmissionStatus;
62
+ /**
63
+ * Base directory for admission queue state. tmpdir clears on reboot, which
64
+ * is correct — stale queue state must not outlive the boot. Override with
65
+ * HARNERY_ADMISSION_DIR. Host CLIs and harn commands must share this helper
66
+ * so they join the same machine-wide queues.
67
+ */
68
+ export declare function admissionBaseDir(): string;
69
+ /** Resources present under an admission base directory. */
70
+ export declare function listAdmissionResources(dir: string): string[];
71
+ //# sourceMappingURL=admission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../src/lib/admission.ts"],"names":[],"mappings":"AAmCA,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;gBACvB,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE;CAW3E;AASD;0EAC0E;AAC1E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAY7C;AA2FD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,eAAe,CAAC,CAyF1B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAC7B,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,KAAK,GAAG,UAAU,GAAG,OAAO,CAAC,GAC1D,eAAe,CAQjB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,2DAA2D;AAC3D,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAS5D"}