@akagilnc/pi-workflow-roles 0.1.3541 → 0.1.3549

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.
@@ -16863,7 +16863,6 @@ async function discoverCaseFiles(root) {
16863
16863
  for (const item of await readdir(dir, { withFileTypes: true })) {
16864
16864
  const path = resolve5(dir, item.name);
16865
16865
  if (item.isDirectory()) {
16866
- if (item.name === GROK_HOME_DIR_NAME) continue;
16867
16866
  await walk(path, depth + 1);
16868
16867
  } else if (item.isFile() && (item.name.endsWith(".jsonl") || item.name === "stderr.log" && depth === 1)) found.push(path);
16869
16868
  }
@@ -16992,13 +16991,11 @@ async function loadDoctorCase(runsPath) {
16992
16991
  const cost2 = { invocations: sourceList(runDirs.length, runDirs), legs: sourceList(legs.length, legs), modelApiTurns: sourceList(turns.count, turns.sources), outputTokens: sourceList(tokens.count, tokens.sources), toolCalls: sourceList(calls.count, calls.sources), retries: { ...sourceList(retryDirs.length, retryDirs), evidence: "literal run-dir naming" }, statuses, commits, sessions, outputBytes: { ...sourceList(rawBytes, legs), payload: "raw JSONL bytes", providerWireBytes: "unavailable" } };
16993
16992
  return { version: 1, identity: { issueNumber: Number(match[1]), runsPath: await stableRunsIdentity(root) }, evidence, cost: cost2 };
16994
16993
  }
16995
- var GROK_HOME_DIR_NAME;
16996
16994
  var init_doctor_evidence = __esm({
16997
16995
  "src/doctor-evidence.ts"() {
16998
16996
  "use strict";
16999
16997
  init_sha256();
17000
16998
  init_terminating_tools();
17001
- GROK_HOME_DIR_NAME = "grok-home";
17002
16999
  }
17003
17000
  });
17004
17001
 
@@ -27905,7 +27902,7 @@ var init_turn_request = __esm({
27905
27902
 
27906
27903
  // src/host-transition-prior-native.ts
27907
27904
  import { access as access2, readdir as readdir6 } from "node:fs/promises";
27908
- import { join as join26 } from "node:path";
27905
+ import { dirname as dirname11, join as join26 } from "node:path";
27909
27906
  function isKnownRoleTurnHost(value) {
27910
27907
  return KNOWN_ROLE_TURN_HOSTS.includes(value);
27911
27908
  }
@@ -27921,41 +27918,28 @@ async function listPiNativeRecordPaths(sessionFile) {
27921
27918
  throw error;
27922
27919
  }
27923
27920
  }
27924
- async function listGrokNativeRecordPaths(runDirectory) {
27925
- const grokSessionsDir = join26(runDirectory, "grok-home", "sessions");
27926
- let encodedCwds;
27921
+ async function listSitianRecordPaths(sessionParent) {
27922
+ const sessionRoot = dirname11(sessionParent);
27923
+ let entries;
27927
27924
  try {
27928
- encodedCwds = await readdir6(grokSessionsDir, { withFileTypes: true });
27925
+ entries = await readdir6(sessionRoot, { withFileTypes: true });
27929
27926
  } catch (error) {
27930
27927
  if (isEnoent2(error)) return [];
27931
27928
  throw error;
27932
27929
  }
27933
- const updatesPaths = [];
27934
- for (const cwdEntry of encodedCwds) {
27935
- if (!cwdEntry.isDirectory()) continue;
27936
- let sessionDirs;
27937
- try {
27938
- sessionDirs = await readdir6(join26(grokSessionsDir, cwdEntry.name), { withFileTypes: true });
27939
- } catch (error) {
27940
- if (isEnoent2(error)) continue;
27941
- throw error;
27942
- }
27943
- for (const sessEntry of sessionDirs) {
27944
- if (!sessEntry.isDirectory()) continue;
27945
- updatesPaths.push(join26(grokSessionsDir, cwdEntry.name, sessEntry.name, "updates.jsonl"));
27946
- }
27947
- }
27948
- updatesPaths.sort();
27949
- const present = [];
27950
- for (const updatesFile of updatesPaths) {
27930
+ const recordPaths = [];
27931
+ for (const entry of entries) {
27932
+ if (!entry.isDirectory()) continue;
27933
+ const recordFile = join26(sessionRoot, entry.name, "records.jsonl");
27951
27934
  try {
27952
- await access2(updatesFile);
27953
- present.push(updatesFile);
27935
+ await access2(recordFile);
27936
+ recordPaths.push(recordFile);
27954
27937
  } catch (error) {
27955
27938
  if (!isEnoent2(error)) throw error;
27956
27939
  }
27957
27940
  }
27958
- return present;
27941
+ recordPaths.sort();
27942
+ return recordPaths;
27959
27943
  }
27960
27944
  async function projectHostTransitionPriorNative(input) {
27961
27945
  if (input.previousHost === input.liveHost) return void 0;
@@ -27969,7 +27953,7 @@ async function projectHostTransitionPriorNative(input) {
27969
27953
  priorNativePaths: paths2
27970
27954
  };
27971
27955
  }
27972
- const paths = await listGrokNativeRecordPaths(input.runDirectory);
27956
+ const paths = await listSitianRecordPaths(input.piSessionFile);
27973
27957
  return {
27974
27958
  previousHost: "grok-build",
27975
27959
  priorNativePaths: paths
@@ -28458,7 +28442,6 @@ async function dispatchPostAdmissionTurn(input) {
28458
28442
  const hostTransition = previousHost !== void 0 && liveHost !== void 0 && principalCoordinates !== void 0 ? await projectHostTransitionPriorNative({
28459
28443
  previousHost,
28460
28444
  liveHost,
28461
- runDirectory: admitted.runDirectory,
28462
28445
  piSessionFile: principalCoordinates.sessionFile
28463
28446
  }) : void 0;
28464
28447
  turnRequest = request;
@@ -30884,9 +30867,9 @@ var init_analyst_book_key = __esm({
30884
30867
  // src/atomic-write.ts
30885
30868
  import { randomUUID as randomUUID6 } from "node:crypto";
30886
30869
  import { rename, rm as rm2, writeFile as writeFile10 } from "node:fs/promises";
30887
- import { dirname as dirname11, join as join30 } from "node:path";
30870
+ import { dirname as dirname12, join as join30 } from "node:path";
30888
30871
  async function writeFileAtomically(destination, contents) {
30889
- const parent = dirname11(destination);
30872
+ const parent = dirname12(destination);
30890
30873
  const temporary = join30(parent, `.atomic-write-${randomUUID6()}.tmp`);
30891
30874
  try {
30892
30875
  await writeFile10(temporary, contents);
@@ -30904,7 +30887,7 @@ var init_atomic_write = __esm({
30904
30887
 
30905
30888
  // src/analyst-index.ts
30906
30889
  import { open as open3, readFile as readFile17, unlink as unlink4 } from "node:fs/promises";
30907
- import { dirname as dirname12, join as join31 } from "node:path";
30890
+ import { dirname as dirname13, join as join31 } from "node:path";
30908
30891
  function sleep(ms) {
30909
30892
  return new Promise((resolve12) => {
30910
30893
  setTimeout(resolve12, ms);
@@ -30912,8 +30895,8 @@ function sleep(ms) {
30912
30895
  }
30913
30896
  async function withAnalystLibraryIndexLock(ledgerHome, fn) {
30914
30897
  const indexPath = analystLibraryIndexPath(ledgerHome);
30915
- ensureRealDirectoryTree(ledgerHome, dirname12(indexPath));
30916
- const lockPath = join31(dirname12(indexPath), LIBRARY_INDEX_LOCK_NAME);
30898
+ ensureRealDirectoryTree(ledgerHome, dirname13(indexPath));
30899
+ const lockPath = join31(dirname13(indexPath), LIBRARY_INDEX_LOCK_NAME);
30917
30900
  assertLedgerFileInsideHome(lockPath, ledgerHome);
30918
30901
  const startedAt = Date.now();
30919
30902
  while (true) {
@@ -31049,7 +31032,7 @@ async function readAnalystLibraryIndexPage(ledgerHome) {
31049
31032
  }
31050
31033
  async function writeAnalystLibraryIndexPage(ledgerHome, page) {
31051
31034
  const path = analystLibraryIndexPath(ledgerHome);
31052
- ensureRealDirectoryTree(ledgerHome, dirname12(path));
31035
+ ensureRealDirectoryTree(ledgerHome, dirname13(path));
31053
31036
  assertLedgerFileInsideHome(path, ledgerHome);
31054
31037
  await writeFileAtomically(path, `${JSON.stringify(page, null, 2)}
31055
31038
  `);
@@ -32426,7 +32409,7 @@ var init_analyst_metric_family = __esm({
32426
32409
 
32427
32410
  // src/analyst-page.ts
32428
32411
  import { createHash as createHash7 } from "node:crypto";
32429
- import { dirname as dirname13, join as join33 } from "node:path";
32412
+ import { dirname as dirname14, join as join33 } from "node:path";
32430
32413
  function analystIssuePageKey(address) {
32431
32414
  const parts = ["book", address.bookKey];
32432
32415
  if (address.issueNumber !== void 0) {
@@ -32556,7 +32539,7 @@ async function buildAnalystIssueMetricsPage(input) {
32556
32539
  }
32557
32540
  async function writeAnalystIssueMetricsPage(ledgerHome, page) {
32558
32541
  const path = analystIssuePagePath(ledgerHome, analystIssuePageAddressFromPage(page));
32559
- ensureRealDirectoryTree(ledgerHome, dirname13(path));
32542
+ ensureRealDirectoryTree(ledgerHome, dirname14(path));
32560
32543
  assertLedgerFileInsideHome(path, ledgerHome);
32561
32544
  await writeFileAtomically(path, `${JSON.stringify(page, null, 2)}
32562
32545
  `);
@@ -34014,7 +33997,7 @@ var init_cli = __esm({
34014
33997
 
34015
33998
  // src/public-cli/main.ts
34016
33999
  import { existsSync as existsSync11 } from "node:fs";
34017
- import { dirname as dirname14, join as join35 } from "node:path";
34000
+ import { dirname as dirname15, join as join35 } from "node:path";
34018
34001
  import { fileURLToPath as fileURLToPath4 } from "node:url";
34019
34002
 
34020
34003
  // src/public-cli/host-pi-runtime.ts
@@ -34101,7 +34084,7 @@ function linkPackage(packageRoot2, name, targetDir) {
34101
34084
  }
34102
34085
 
34103
34086
  // src/public-cli/main.ts
34104
- var here = dirname14(fileURLToPath4(import.meta.url));
34087
+ var here = dirname15(fileURLToPath4(import.meta.url));
34105
34088
  function resolvePackageRoot(binDir) {
34106
34089
  const canonical = join35(binDir, "..", "..");
34107
34090
  if (existsSync11(join35(canonical, "package.json"))) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.3541",
3
+ "version": "0.1.3549",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -5,14 +5,7 @@ import type { DoctorCase, DoctorCaseCost, DoctorCount, DoctorEvidenceEntry } fro
5
5
  import { AcceptedDetailsContractError, acceptedFacts, isTerminatingToolName, validateAcceptedDetails } from "./package-contracts/terminating-tools.ts";
6
6
 
7
7
  function record(value: unknown): value is Record<string, unknown> { return typeof value === "object" && value !== null && !Array.isArray(value); }
8
- /**
9
- * Grok controlled-home ledger directory under a run (ADR 0077 / #594).
10
- * Native journals (e.g. updates.jsonl) are retained for dossier parity but are
11
- * not Pi session records — walking them into deriveSession yields false incomplete
12
- * legs. Explicit skip is the leave-trace exclusion until a grok parser exists.
13
- */
14
- const GROK_HOME_DIR_NAME = "grok-home";
15
- async function discoverCaseFiles(root: string): Promise<string[]> { const found: string[] = []; async function walk(dir: string, depth: number) { for (const item of await readdir(dir, { withFileTypes: true })) { const path = resolve(dir, item.name); if (item.isDirectory()) { if (item.name === GROK_HOME_DIR_NAME) continue; await walk(path, depth + 1); } else if (item.isFile() && (item.name.endsWith(".jsonl") || (item.name === "stderr.log" && depth === 1))) found.push(path); } } await walk(root, 0); return found.sort(); }
8
+ async function discoverCaseFiles(root: string): Promise<string[]> { const found: string[] = []; async function walk(dir: string, depth: number) { for (const item of await readdir(dir, { withFileTypes: true })) { const path = resolve(dir, item.name); if (item.isDirectory()) { await walk(path, depth + 1); } else if (item.isFile() && (item.name.endsWith(".jsonl") || (item.name === "stderr.log" && depth === 1))) found.push(path); } } await walk(root, 0); return found.sort(); }
16
9
  function sourceList(count: number, sources: string[]) { return { count, sources: [...new Set(sources)].sort() }; }
17
10
  function accumulate(metric: DoctorCount, value: number, source: string) { metric.count += value; if (value) metric.sources.push(source); }
18
11
  function timestamp(row: Record<string, unknown>) { return typeof row.timestamp === "string" && Number.isFinite(Date.parse(row.timestamp)) ? row.timestamp : undefined; }
@@ -1,20 +1,12 @@
1
1
  /**
2
- * Production composition for the grok-build RoleTurnHost adapter (#580 / #522 / #594).
2
+ * Production composition for the grok-build RoleTurnHost adapter (#580 / #522 / #717).
3
3
  * Owns injectables around the S6 true adapter; does not alter S6 adapter behavior.
4
4
  *
5
- * Isolation contract: subprocess GROK_HOME, Fixer seatbelt hang root, and auth
6
- * copy share one directory under the runDirectory ledger (grok-home). The grok
7
- * binary still resolves from the operator home. Callers pass that isolated home
8
- * into S6 as request.home (bash-seatbelt.ts: "callers must pass the isolated home").
9
- * Auth is copied from the operator home into grok-home for the turn and scrubbed
10
- * on settle together with AK seatbelt hook residue; the session dossier directly
11
- * written under grok-home survives settlement (ADR 0048 / ADR 0077 / #594).
12
- *
13
- * Known residual risk: a hard process crash between auth copy and settle can leave
14
- * auth.json in the retained run ledger for one crash window. The next open scrubs
15
- * residual auth before recopying; single-crash-window residue is accepted.
5
+ * Grok CLI uses the operator home (`~/.grok`) and credentials in place. The
6
+ * factory does not create a run-scoped grok home, does not rewrite HOME, and
7
+ * does not copy or scrub auth.json. Sititian records on the run are the dossier.
16
8
  */
17
- import { readFile, rm, writeFile } from "node:fs/promises";
9
+ import { readFile } from "node:fs/promises";
18
10
  import { join } from "node:path";
19
11
  import { fileURLToPath } from "node:url";
20
12
 
@@ -22,7 +14,7 @@ import { loadCanonicalSkillBinding as loadHomeCanonicalSkillBinding } from "../c
22
14
  import { createGhCollectorGitHubTransport, createGhIssueSoftFetcher } from "../collector-github.ts";
23
15
  import { createPiDoctorAuditor } from "../doctor-auditor.ts";
24
16
  import { loadDoctorCase } from "../doctor-evidence.ts";
25
- import type { DurablePrincipalAuthority, RoleTurnHost, RoleTurnRequest } from "../host-contracts.ts";
17
+ import type { DurablePrincipalAuthority, RoleTurnHost } from "../host-contracts.ts";
26
18
  import { createPiJudgeAuditor } from "../judge-auditor.ts";
27
19
  import { createProductionMergerGitState } from "../merger-git-state.ts";
28
20
  import { createNativeNavigatorSessionFactory, createNavigatorAttendance } from "../navigator-attendance.ts";
@@ -35,28 +27,11 @@ import { createReviewerPinnedGitReader } from "../reviewer-pinned-git.ts";
35
27
  import { loadGatekeeperSessionMaterials, loadMainRoleSessionMaterials } from "../session-opening-materials.ts";
36
28
  import { createComposedGrokRoleTurnHost } from "./role-envelope.ts";
37
29
  import {
38
- assertControlledGrokAuthIsNotSymlink,
39
- assertControlledGrokHomeIsRealDirectory,
40
30
  connectGrokAcpStdio,
41
31
  controlledGrokChildEnv,
42
- inspectControlledGrok,
43
- prepareControlledGrokHome,
44
- scrubAkBashSeatbeltHooks,
45
- type GrokCapabilityDeclaration,
46
32
  } from "./role-turn-host.ts";
47
33
  import { createGrokSessionIdentityAuthority } from "./session-identity.ts";
48
34
 
49
- /**
50
- * Authoritative production isolation binding consumed by inspect/connect and by
51
- * the S6 request.home rewrite (controlledHome).
52
- */
53
- export type ProductionGrokIsolationBinding = Readonly<{
54
- operatorHome: string;
55
- controlledHome: string;
56
- binary: string;
57
- env: NodeJS.ProcessEnv;
58
- }>;
59
-
60
35
  export type ProductionGrokHostOptions = Readonly<{
61
36
  packageRoot: string;
62
37
  principalAuthority: DurablePrincipalAuthority;
@@ -66,137 +41,13 @@ function resolveGrokBinary(operatorHome: string): string {
66
41
  return join(operatorHome, ".grok", "bin", "grok");
67
42
  }
68
43
 
69
- /**
70
- * Primary-failure state for cleanup settlement. `undefined` is a legal primary
71
- * value (throw/reject undefined), so presence is an explicit discriminant — never
72
- * inferred from `value !== undefined`.
73
- */
74
- export type ProductionGrokPrimaryFailure =
75
- | Readonly<{ present: false }>
76
- | Readonly<{ present: true; value: unknown }>;
77
-
78
- export const NO_PRODUCTION_GROK_PRIMARY_FAILURE = {
79
- present: false,
80
- } as const satisfies ProductionGrokPrimaryFailure;
81
-
82
- /**
83
- * Sole cleanup settlement for production controlled homes: scrub auth secrets
84
- * (auth.json) and AK seatbelt hook residue while preserving the session dossier
85
- * under the runDirectory ledger. Refuses symlink home/auth so rm never follows a
86
- * redirect (#594 F1/F4). Cleanup failure is never silenced. When a primary failure
87
- * is present and cleanup also fails, both surface as AggregateError (including
88
- * primary value `undefined`); cleanup success rethrows the primary value as-is.
89
- */
90
- export async function settleProductionGrokHomeCleanup(
91
- controlledHome: string,
92
- primaryFailure: ProductionGrokPrimaryFailure,
93
- concurrentMessage: string,
94
- ): Promise<void> {
95
- try {
96
- await assertControlledGrokHomeIsRealDirectory(controlledHome);
97
- const authPath = join(controlledHome, "auth.json");
98
- await assertControlledGrokAuthIsNotSymlink(authPath);
99
- await rm(authPath, { force: true });
100
- await scrubAkBashSeatbeltHooks(controlledHome);
101
- } catch (cleanupFailure) {
102
- if (primaryFailure.present) {
103
- throw new AggregateError([primaryFailure.value, cleanupFailure], concurrentMessage, {
104
- cause: primaryFailure.value,
105
- });
106
- }
107
- throw cleanupFailure;
108
- }
109
- if (primaryFailure.present) {
110
- throw primaryFailure.value;
111
- }
112
- }
113
-
114
- /**
115
- * Open the production isolation root under runDirectory: auth copy into grok-home.
116
- * If auth copy fails after the root is created, auth secrets are scrubbed; open
117
- * failure and cleanup failure both surface (AggregateError when concurrent).
118
- */
119
- export async function openProductionGrokHome(
120
- runDirectory: string,
121
- operatorHome: string,
122
- ): Promise<string> {
123
- const controlledHome = join(runDirectory, "grok-home");
124
- try {
125
- await prepareControlledGrokHome(operatorHome, controlledHome);
126
- return controlledHome;
127
- } catch (error) {
128
- await settleProductionGrokHomeCleanup(
129
- controlledHome,
130
- { present: true, value: error },
131
- "production grok home open failed and its cleanup also failed",
132
- );
133
- // settle always throws when primaryFailure is present.
134
- throw error;
135
- }
136
- }
137
-
138
- function childEnv(controlledHome: string, packageRoot: string): NodeJS.ProcessEnv {
44
+ function childEnv(packageRoot: string): NodeJS.ProcessEnv {
139
45
  return {
140
- ...controlledGrokChildEnv(process.env, controlledHome),
46
+ ...controlledGrokChildEnv(process.env),
141
47
  AK_PACKAGE_ROOT: packageRoot,
142
48
  };
143
49
  }
144
50
 
145
- /**
146
- * Single production isolation binding: auth root, GROK_HOME/HOME, and binary
147
- * resolution. Production executeTurn passes controlledHome as S6 request.home
148
- * (seatbelt hang root proven separately by S6 seatbelt tests).
149
- */
150
- export async function bindProductionGrokIsolation(
151
- runDirectory: string,
152
- operatorHome: string,
153
- packageRoot: string,
154
- ): Promise<ProductionGrokIsolationBinding> {
155
- const controlledHome = await openProductionGrokHome(runDirectory, operatorHome);
156
- return {
157
- operatorHome,
158
- controlledHome,
159
- binary: resolveGrokBinary(operatorHome),
160
- env: childEnv(controlledHome, packageRoot),
161
- };
162
- }
163
-
164
- /**
165
- * Bind isolation under runDirectory, run the turn body, always scrub auth.json
166
- * and AK seatbelt hooks via settleProductionGrokHomeCleanup (no silent catch)
167
- * while preserving the session dossier under runDirectory/grok-home. Success,
168
- * typed-result, and throw paths all clean up; cleanup failure and primary+cleanup
169
- * both surface. Same-run Grok isolation only — no cross-run home override (#637).
170
- */
171
- export async function withProductionGrokIsolation<T>(
172
- runDirectory: string,
173
- operatorHome: string,
174
- packageRoot: string,
175
- run: (binding: ProductionGrokIsolationBinding) => Promise<T>,
176
- ): Promise<T> {
177
- let binding: ProductionGrokIsolationBinding | undefined;
178
- let primaryFailure: ProductionGrokPrimaryFailure = NO_PRODUCTION_GROK_PRIMARY_FAILURE;
179
- let value!: T;
180
- try {
181
- binding = await bindProductionGrokIsolation(runDirectory, operatorHome, packageRoot);
182
- value = await run(binding);
183
- } catch (error) {
184
- primaryFailure = { present: true, value: error };
185
- }
186
-
187
- if (binding !== undefined) {
188
- // No catch: settle throws cleanup failure or AggregateError with primary.
189
- await settleProductionGrokHomeCleanup(
190
- binding.controlledHome,
191
- primaryFailure,
192
- "production grok isolation turn and cleanup failed",
193
- );
194
- }
195
-
196
- if (primaryFailure.present) throw primaryFailure.value;
197
- return value;
198
- }
199
-
200
51
  const navigatorRoutePlaybookPath = fileURLToPath(
201
52
  new URL("../../resources/navigator-route-playbook.md", import.meta.url),
202
53
  );
@@ -267,78 +118,24 @@ export function createGrokRoleRuntimeDependencies(packageRoot: string): RoleRunt
267
118
  };
268
119
  }
269
120
 
270
- async function recordGrokCapabilities(
271
- request: RoleTurnRequest,
272
- declaration: GrokCapabilityDeclaration,
273
- ): Promise<void> {
274
- await writeFile(
275
- join(request.runDirectory, "grok-capabilities.json"),
276
- `${JSON.stringify(declaration)}\n`,
277
- "utf8",
278
- );
279
- }
280
-
281
121
  /**
282
122
  * Assemble the production grok-build RoleTurnHost from the S6 true adapter.
283
- * Isolation always under the live request.runDirectory (same-run resume keeps it).
123
+ * Grok subprocesses inherit the operator home; the run directory is sitian-only.
284
124
  */
285
125
  export function createProductionGrokRoleTurnHost(options: ProductionGrokHostOptions): RoleTurnHost {
286
126
  const { packageRoot, principalAuthority } = options;
287
- // Single-slot turn isolation; outer serial keeps operator/controlled pairing intact.
288
- let turn: ProductionGrokIsolationBinding | undefined;
289
- let serial = Promise.resolve();
127
+ const env = childEnv(packageRoot);
290
128
 
291
- const inner = createComposedGrokRoleTurnHost({
129
+ return createComposedGrokRoleTurnHost({
292
130
  sessionIdentity: createGrokSessionIdentityAuthority(principalAuthority),
293
131
  roleRuntimeDependencies: createGrokRoleRuntimeDependencies(packageRoot),
294
- recordCapabilities: recordGrokCapabilities,
295
- async inspect(request) {
296
- if (turn === undefined) {
297
- throw new Error("production grok inspect requires an active isolated turn");
298
- }
299
- return inspectControlledGrok({
300
- binary: turn.binary,
301
- cwd: request.cwd,
302
- env: turn.env,
303
- packageRoot,
304
- });
305
- },
306
132
  async connect(request) {
307
- if (turn === undefined) {
308
- throw new Error("production grok connect requires an active isolated turn");
309
- }
310
133
  return connectGrokAcpStdio({
311
- binary: turn.binary,
134
+ binary: resolveGrokBinary(request.home),
312
135
  cwd: request.cwd,
313
- env: turn.env,
136
+ env,
314
137
  ...(request.model === undefined ? {} : { model: request.model.model }),
315
138
  });
316
139
  },
317
140
  });
318
-
319
- return {
320
- executeTurn(request) {
321
- const execution = serial.then(() =>
322
- withProductionGrokIsolation(
323
- request.runDirectory,
324
- request.home,
325
- packageRoot,
326
- async (binding) => {
327
- turn = binding;
328
- try {
329
- // S6 seatbelt hangs on request.home — same isolated root as GROK_HOME.
330
- return await inner.executeTurn({ ...request, home: binding.controlledHome });
331
- } finally {
332
- turn = undefined;
333
- }
334
- },
335
- ),
336
- );
337
- serial = execution.then(
338
- () => undefined,
339
- () => undefined,
340
- );
341
- return execution;
342
- },
343
- };
344
141
  }