@amaster.ai/employee-runtime-connector 0.1.1-beta.0 → 0.1.1-beta.2

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/README.md CHANGED
@@ -40,7 +40,7 @@ Pi execution uses three separate evidence layers:
40
40
  2. a durable, inspectable Runtime Action receipt or finalized Runtime Artifact;
41
41
  3. process cleanup disposition.
42
42
 
43
- An exact process-kill `EPERM` error emitted only after the first two layers have completed may be isolated as a failed `cleanupDisposition` warning without changing the command's successful business result. Both accepted shapes require `kill` and `EPERM`; generic filesystem/process permission text such as `EPERM: operation not permitted, unlink ...` is a business error. A `runtime_action.status` readback is evidence only when its call/plan ref matches an earlier submit/commit receipt in the same transcript. The diagnostic and durable evidence reference remain in the result. Text-only or action-only-without-assistant-output streams, standalone governed reads, non-effect Runtime Action tools, rejected or pending effects, pre-terminal errors, provider failures, timeout, cancellation, resource limits, any signal, live residue, and uncertain ownership remain failures.
43
+ An exact process-kill `EPERM` error emitted only after the first two layers have completed may be isolated as a failed `cleanupDisposition` warning without changing the command's successful business result. Both accepted shapes require `kill` and `EPERM`; generic filesystem/process permission text such as `EPERM: operation not permitted, unlink ...` is a business error. Durable evidence is limited to a completed Runtime Action, a finalized Runtime Artifact, or an accepted `company_diagnosis_brief` provider receipt whose invocation and returned Diagnosis/document/work-product identities are exact. A `runtime_action.status` readback is evidence only when its call/plan ref matches an earlier submit/commit receipt in the same transcript. The diagnostic and durable evidence reference remain in the result. Text-only or action-only-without-assistant-output streams, standalone governed reads, non-effect Runtime Action tools, rejected or pending effects, pre-terminal errors, provider failures, timeout, cancellation, resource limits, any signal, live residue, and uncertain ownership remain failures.
44
44
 
45
45
  This isolation does not schedule a retry or a second business continuation. Command result delivery and the result outbox remain the sole idempotency boundary.
46
46
 
@@ -2,9 +2,9 @@
2
2
  // MirrorX runtime connector daemon bundle.
3
3
 
4
4
  // src/amaster-runtime-daemon.mjs
5
- import { createHash as createHash10 } from "node:crypto";
6
- import { chmodSync as chmodSync6, copyFileSync as copyFileSync3, existsSync as existsSync14, lstatSync as lstatSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync11, readdirSync as readdirSync9, realpathSync as realpathSync5, renameSync as renameSync6, rmSync as rmSync7, statSync as statSync7, symlinkSync as symlinkSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
7
- import { arch as arch3, homedir as homedir3, hostname as hostname2, platform as platform3 } from "node:os";
5
+ import { createHash as createHash11 } from "node:crypto";
6
+ import { chmodSync as chmodSync6, copyFileSync as copyFileSync3, existsSync as existsSync14, lstatSync as lstatSync7, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync11, readdirSync as readdirSync9, realpathSync as realpathSync5, renameSync as renameSync6, rmSync as rmSync7, statSync as statSync7, symlinkSync as symlinkSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
7
+ import { arch as arch3, homedir as homedir3, hostname as hostname2, platform as platform3, tmpdir } from "node:os";
8
8
  import { basename as basename6, delimiter as delimiter2, dirname as dirname9, extname as extname2, isAbsolute as isAbsolute8, join as join15, relative as relative9, resolve as resolve12 } from "node:path";
9
9
  import { spawn as spawn2, spawnSync as spawnSync6 } from "node:child_process";
10
10
 
@@ -1607,7 +1607,7 @@ var MANAGED_PI_PROVIDER_PROTECTED_ENV_NAMES = Object.freeze([
1607
1607
  function isRecord(value) {
1608
1608
  return value && typeof value === "object" && !Array.isArray(value);
1609
1609
  }
1610
- function readJsonFile2(filePath) {
1610
+ function readJsonFile(filePath) {
1611
1611
  try {
1612
1612
  const parsed = JSON.parse(readFileSync2(filePath, "utf8"));
1613
1613
  return asRecord(parsed);
@@ -1679,7 +1679,7 @@ function syncAmasterProviderModels(agentDir, executorEnv) {
1679
1679
  const apiKey = readString(executorEnv.AMASTER_API_KEY);
1680
1680
  if (!apiKey) return false;
1681
1681
  const modelsPath = join3(agentDir, "models.json");
1682
- const config = readJsonFile2(modelsPath);
1682
+ const config = readJsonFile(modelsPath);
1683
1683
  const providers = asRecord(config.providers);
1684
1684
  const amaster = { ...asRecord(providers.amaster) };
1685
1685
  amaster.apiKey = managedApiKeyConfigValue(executorEnv, apiKey);
@@ -1707,7 +1707,7 @@ function syncAmasterProviderSettings(agentDir, executorEnv) {
1707
1707
  if (!apiKey) return false;
1708
1708
  const settingsPath = join3(agentDir, "settings.json");
1709
1709
  if (!existsSync2(settingsPath)) return false;
1710
- const settings = readJsonFile2(settingsPath);
1710
+ const settings = readJsonFile(settingsPath);
1711
1711
  const baseUrl = readString(executorEnv.AMASTER_PROVIDER_BASE_URL);
1712
1712
  const defaultModel = readString(executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL);
1713
1713
  const imageGenBaseUrl = imageGenBaseUrlFromProviderBaseUrl(baseUrl);
@@ -1828,19 +1828,161 @@ function escapeLiteralJsonStringControlCharacters(value) {
1828
1828
  }
1829
1829
  return changed ? output : value;
1830
1830
  }
1831
+ function escapeLikelyLiteralJsonStringQuotes(value) {
1832
+ let output = "";
1833
+ let inString = false;
1834
+ let escaped = false;
1835
+ let changed = false;
1836
+ let stringRole = null;
1837
+ let previousSignificantCharacter = null;
1838
+ function followingObjectProperty(offset) {
1839
+ let cursor = offset;
1840
+ while (cursor < value.length && /\s/u.test(value[cursor])) cursor += 1;
1841
+ if (value[cursor] !== '"') return { valid: false, simpleIdentifier: false };
1842
+ cursor += 1;
1843
+ let propertyName = "";
1844
+ let propertyEscaped = false;
1845
+ for (; cursor < value.length; cursor += 1) {
1846
+ const propertyCharacter = value[cursor];
1847
+ if (propertyEscaped) {
1848
+ propertyName += propertyCharacter;
1849
+ propertyEscaped = false;
1850
+ continue;
1851
+ }
1852
+ if (propertyCharacter === "\\") {
1853
+ propertyEscaped = true;
1854
+ continue;
1855
+ }
1856
+ if (propertyCharacter !== '"') {
1857
+ propertyName += propertyCharacter;
1858
+ continue;
1859
+ }
1860
+ cursor += 1;
1861
+ while (cursor < value.length && /\s/u.test(value[cursor])) cursor += 1;
1862
+ return {
1863
+ valid: value[cursor] === ":",
1864
+ simpleIdentifier: /^[A-Za-z_][A-Za-z0-9_-]*$/u.test(propertyName)
1865
+ };
1866
+ }
1867
+ return { valid: false, simpleIdentifier: false };
1868
+ }
1869
+ for (let index = 0; index < value.length; index += 1) {
1870
+ const character = value[index];
1871
+ if (!inString) {
1872
+ output += character;
1873
+ if (character === '"') {
1874
+ inString = true;
1875
+ stringRole = previousSignificantCharacter === ":" ? "object_value" : null;
1876
+ } else if (!/\s/u.test(character)) {
1877
+ previousSignificantCharacter = character;
1878
+ }
1879
+ continue;
1880
+ }
1881
+ if (escaped) {
1882
+ output += character;
1883
+ escaped = false;
1884
+ continue;
1885
+ }
1886
+ if (character === "\\") {
1887
+ output += character;
1888
+ escaped = true;
1889
+ continue;
1890
+ }
1891
+ if (character !== '"') {
1892
+ output += character;
1893
+ continue;
1894
+ }
1895
+ let nextIndex = index + 1;
1896
+ while (nextIndex < value.length && /\s/u.test(value[nextIndex])) nextIndex += 1;
1897
+ const nextCharacter = value[nextIndex];
1898
+ if (nextCharacter === "," && stringRole === "object_value") {
1899
+ const following = followingObjectProperty(nextIndex + 1);
1900
+ if (!following.valid && !following.simpleIdentifier) {
1901
+ output += '\\"';
1902
+ changed = true;
1903
+ continue;
1904
+ }
1905
+ }
1906
+ if (nextCharacter === void 0 || [":", ",", "}", "]"].includes(nextCharacter)) {
1907
+ output += character;
1908
+ inString = false;
1909
+ stringRole = null;
1910
+ previousSignificantCharacter = character;
1911
+ } else {
1912
+ output += '\\"';
1913
+ changed = true;
1914
+ }
1915
+ }
1916
+ return changed ? output : value;
1917
+ }
1918
+ function insertSingleMissingObjectPropertyComma(value) {
1919
+ let parseError;
1920
+ try {
1921
+ JSON.parse(value);
1922
+ return value;
1923
+ } catch (error) {
1924
+ parseError = error;
1925
+ }
1926
+ const positionMatch = String(parseError?.message ?? "").match(
1927
+ /Expected ',' or '\}' after property value in JSON at position (\d+)/u
1928
+ );
1929
+ if (!positionMatch) return value;
1930
+ const position = Number(positionMatch[1]);
1931
+ if (!Number.isSafeInteger(position) || position < 1 || position >= value.length) return value;
1932
+ let propertyStart = position;
1933
+ while (propertyStart < value.length && /\s/u.test(value[propertyStart])) propertyStart += 1;
1934
+ if (value[propertyStart] !== '"') return value;
1935
+ let cursor = propertyStart + 1;
1936
+ let escaped = false;
1937
+ let propertyName = "";
1938
+ for (; cursor < value.length; cursor += 1) {
1939
+ const character = value[cursor];
1940
+ if (escaped) {
1941
+ propertyName += character;
1942
+ escaped = false;
1943
+ continue;
1944
+ }
1945
+ if (character === "\\") {
1946
+ escaped = true;
1947
+ continue;
1948
+ }
1949
+ if (character === '"') break;
1950
+ propertyName += character;
1951
+ }
1952
+ if (cursor >= value.length || !/^[A-Za-z_][A-Za-z0-9_-]*$/u.test(propertyName)) return value;
1953
+ cursor += 1;
1954
+ while (cursor < value.length && /\s/u.test(value[cursor])) cursor += 1;
1955
+ if (value[cursor] !== ":") return value;
1956
+ let previous = position - 1;
1957
+ while (previous >= 0 && /\s/u.test(value[previous])) previous -= 1;
1958
+ if (previous < 0 || !['"', "}", "]", "e", "l"].includes(value[previous]) && !/[0-9]/u.test(value[previous])) {
1959
+ return value;
1960
+ }
1961
+ const candidate = `${value.slice(0, position)},${value.slice(position)}`;
1962
+ try {
1963
+ return isJsonObject(JSON.parse(candidate)) ? candidate : value;
1964
+ } catch {
1965
+ return value;
1966
+ }
1967
+ }
1831
1968
  function normalizePiMcpProxyArgs(value) {
1832
1969
  if (typeof value !== "string") return { value, repaired: false };
1833
1970
  try {
1834
1971
  JSON.parse(value);
1835
1972
  return { value, repaired: false };
1836
1973
  } catch {
1837
- const repairedValue = escapeLiteralJsonStringControlCharacters(value);
1838
- if (repairedValue === value) return { value, repaired: false };
1839
- try {
1840
- return isJsonObject(JSON.parse(repairedValue)) ? { value: repairedValue, repaired: true } : { value, repaired: false };
1841
- } catch {
1842
- return { value, repaired: false };
1974
+ const repairedControlCharacters = escapeLiteralJsonStringControlCharacters(value);
1975
+ const repairedValue = escapeLikelyLiteralJsonStringQuotes(repairedControlCharacters);
1976
+ if (repairedValue !== value) {
1977
+ try {
1978
+ if (isJsonObject(JSON.parse(repairedValue))) {
1979
+ return { value: repairedValue, repaired: true };
1980
+ }
1981
+ } catch {
1982
+ }
1843
1983
  }
1984
+ const commaRepairedValue = insertSingleMissingObjectPropertyComma(repairedControlCharacters);
1985
+ return commaRepairedValue !== value ? { value: commaRepairedValue, repaired: true } : { value, repaired: false };
1844
1986
  }
1845
1987
  }
1846
1988
  function registerManagedPiMcpArgsNormalizer(pi) {
@@ -1854,6 +1996,8 @@ function managedPiMcpArgsNormalizerExtensionSource() {
1854
1996
  return [
1855
1997
  isJsonObject.toString(),
1856
1998
  escapeLiteralJsonStringControlCharacters.toString(),
1999
+ escapeLikelyLiteralJsonStringQuotes.toString(),
2000
+ insertSingleMissingObjectPropertyComma.toString(),
1857
2001
  normalizePiMcpProxyArgs.toString(),
1858
2002
  `export default ${registerManagedPiMcpArgsNormalizer.toString()};`,
1859
2003
  ""
@@ -2264,7 +2408,12 @@ function createManagedPiMcpProfileApi(options = {}) {
2264
2408
  if (!existsSync3(packagePath) || lstatSync2(packagePath).isSymbolicLink() || !lstatSync2(packagePath).isFile()) {
2265
2409
  throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package is unavailable`);
2266
2410
  }
2267
- const packageMetadata = readJsonFile(packagePath, `package:${MANAGED_WEB_ACCESS_PACKAGE}`, null);
2411
+ let packageMetadata;
2412
+ try {
2413
+ packageMetadata = JSON.parse(readFileSync3(packagePath, "utf8"));
2414
+ } catch {
2415
+ throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package metadata is invalid`);
2416
+ }
2268
2417
  if (!packageMetadata || packageMetadata.name !== MANAGED_WEB_ACCESS_PACKAGE) {
2269
2418
  throw new Error(`pi_managed_mcp_attestation_failed: configured ${MANAGED_WEB_ACCESS_PACKAGE} package identity mismatch`);
2270
2419
  }
@@ -2318,44 +2467,11 @@ function createManagedPiMcpProfileApi(options = {}) {
2318
2467
  }
2319
2468
  }
2320
2469
  const browserUse = selectManagedBrowserUse(sourceSettings, npmSource);
2321
- const webAccess = selectManagedWebAccess(sourceSettings, npmSource);
2470
+ const webAccess = sourceAcquisition ? null : selectManagedWebAccess(sourceSettings, npmSource);
2322
2471
  const telemetry = selectManagedTelemetry(sourceSettings, npmSource);
2323
- if (sourceAcquisition && (!browserUse || !webAccess)) {
2472
+ if (sourceAcquisition && !browserUse) {
2324
2473
  throw new Error("pi_managed_mcp_source_acquisition_packages_missing");
2325
2474
  }
2326
- const sourceProfile = record6(sourceAcquisition?.profile);
2327
- const sourceAccess = record6(sourceProfile.access);
2328
- const sourceTransport = record6(sourceProfile.transport);
2329
- const sourceObservation = sourceAcquisition ? {
2330
- runId: sourceProfile.runId,
2331
- retention: sourceProfile.retention
2332
- } : null;
2333
- const sourceWebAccessConfig = sourceAcquisition ? {
2334
- ...webAccess.config,
2335
- fetch: {
2336
- ...record6(webAccess.config.fetch),
2337
- mode: sourceTransport.webFetchMode,
2338
- observation: sourceObservation,
2339
- ...!record6(webAccess.config.fetch).provider && !record6(webAccess.config.fetch).summary && typeof sourceSettings.defaultProvider === "string" && typeof sourceSettings.defaultModel === "string" ? { summary: { provider: sourceSettings.defaultProvider, model: sourceSettings.defaultModel } } : {}
2340
- }
2341
- } : null;
2342
- const sourceBrowserConfig = sourceAcquisition ? {
2343
- ...browserUse.config,
2344
- sessionMode: sourceTransport.browserMode,
2345
- ...sourceAccess.mode === "authenticated" ? { userDataDir: sourceAcquisition.userDataDir } : {},
2346
- readPolicy: {
2347
- version: "browser_read_policy_v1",
2348
- accessMode: sourceAccess.mode,
2349
- allowedTopLevelLocators: [sourceAccess.exactLocator, ...Array.isArray(sourceAccess.declaredPageLocators) ? sourceAccess.declaredPageLocators : []],
2350
- allowedTopLevelOrigins: sourceAccess.allowedTopLevelOrigins,
2351
- subresources: "public_or_same_origin",
2352
- privateCrossOriginSubresources: "deny",
2353
- popups: "deny",
2354
- downloads: "deny",
2355
- newTargets: "deny",
2356
- observation: sourceObservation
2357
- }
2358
- } : null;
2359
2475
  const settings = {
2360
2476
  ...typeof sourceSettings.defaultProvider === "string" ? { defaultProvider: sourceSettings.defaultProvider } : {},
2361
2477
  ...typeof sourceSettings.defaultModel === "string" ? { defaultModel: sourceSettings.defaultModel } : {},
@@ -2363,15 +2479,15 @@ function createManagedPiMcpProfileApi(options = {}) {
2363
2479
  "npm:pi-mcp-adapter",
2364
2480
  ...telemetry ? [telemetry.packageSpec] : [],
2365
2481
  ...webAccess ? [webAccess.packageSpec] : [],
2366
- ...browserUse ? [browserUse.packageSpec] : []
2482
+ ...!sourceAcquisition && browserUse ? [browserUse.packageSpec] : []
2367
2483
  ],
2368
2484
  ...telemetry ? { "pi-telemetry": telemetry.config } : {},
2369
- ...webAccess ? { "pi-web-access": sourceWebAccessConfig ?? webAccess.config } : {},
2370
- ...browserUse ? {
2485
+ ...webAccess ? { "pi-web-access": webAccess.config } : {},
2486
+ ...!sourceAcquisition && browserUse ? {
2371
2487
  plugins: {
2372
2488
  [MANAGED_BROWSER_USE_PLUGIN]: browserUse.plugin
2373
2489
  },
2374
- "pi-browser-use": sourceBrowserConfig ?? browserUse.config
2490
+ "pi-browser-use": browserUse.config
2375
2491
  } : {}
2376
2492
  };
2377
2493
  writePrivateFile2(join4(agentDir, "settings.json"), `${JSON.stringify(settings, null, 2)}
@@ -2382,6 +2498,12 @@ function createManagedPiMcpProfileApi(options = {}) {
2382
2498
  join4(extensionsDir, MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME),
2383
2499
  managedPiMcpArgsNormalizerExtensionSource()
2384
2500
  );
2501
+ if (sourceAcquisition && !copyPrivateFile(
2502
+ join4(source, "extensions", "amaster-source-acquisition.js"),
2503
+ join4(extensionsDir, "amaster-source-acquisition.js")
2504
+ )) {
2505
+ throw new Error("pi_managed_mcp_source_acquisition_extension_missing");
2506
+ }
2385
2507
  copyPrivateFile(join4(source, "models.json"), join4(agentDir, "models.json"));
2386
2508
  const authSource = join4(source, "auth.json");
2387
2509
  const protectedValues = [];
@@ -2501,6 +2623,9 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
2501
2623
  const restoredNativeSession = restoreManagedPiSessionRollout(input, sessionsRoot, runDir, executorHome, authority);
2502
2624
  const configPath = join4(piCodingAgentDir, "mcp.json");
2503
2625
  const config = {
2626
+ settings: {
2627
+ toolPrefix: "none"
2628
+ },
2504
2629
  mcpServers: {
2505
2630
  [SUPPORTED_SERVER_NAME2]: {
2506
2631
  type: "http",
@@ -2523,8 +2648,6 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
2523
2648
  PI_AGENT_MCP_SERVERS_FILE: configPath,
2524
2649
  TMPDIR: tmp,
2525
2650
  ...input.sourceAcquisition ? {
2526
- PI_WEB_ACCESS_RUNTIME_FETCH_MODE: record6(input.sourceAcquisition.profile).transport?.webFetchMode,
2527
- PI_WEB_ACCESS_RUNTIME_OBSERVATION: "required",
2528
2651
  PI_BROWSER_USE_RUNTIME_READ_POLICY: "required"
2529
2652
  } : {}
2530
2653
  };
@@ -3393,13 +3516,16 @@ function wikiAccessRuleLine(input) {
3393
3516
  return "";
3394
3517
  }
3395
3518
  function fixedRules(input, includeIssueLine) {
3519
+ const issue = asRecord(asRecord(input.context).paperclipIssue);
3520
+ const businessOutcome = asRecord(asRecord(issue.taskRequirements).businessOutcome);
3521
+ const serverOwnedBusinessOutcomeReview = businessOutcome.mode === "required";
3396
3522
  return [
3397
3523
  "## AMaster Runtime Connector Task",
3398
3524
  "MirrorX task.",
3399
3525
  "Use only the declared workspace; make concrete progress and report concisely.",
3400
3526
  "Before changing the task status to done, audit every explicit requirement in the task against the final evidence. A successful tool or document write proves delivery, not acceptance: inspect the delivered content for required sections, diagrams, tables, and factual constraints.",
3401
3527
  "Do not leave stale in-progress wording such as \u201Ccurrent run\u201D in a terminal deliverable; rewrite it to the final observed state. Do not list finalization itself as remaining or next work in a terminal deliverable.",
3402
- "If any requirement is missing or cannot be verified, do not mark done. To request review, use create_interaction with kind request_confirmation and payload.resolutionMode review; never call update_parent with status in_review. Otherwise keep the issue todo or blocked with the exact gap and next owner.",
3528
+ serverOwnedBusinessOutcomeReview ? "If any requirement is missing or cannot be verified, do not mark done or request final completion or Business Outcome review. Keep the issue in_progress or blocked with the exact gap and next owner. An intermediate review remains available only for an exact document revision that must be approved before execution can continue: use create_interaction with kind request_confirmation, payload.resolutionMode review, and purposeCode review_document_revision; never use that interaction as final completion or Outcome acceptance." : "If any requirement is missing or cannot be verified, do not mark done. To request review, use create_interaction with kind request_confirmation and payload.resolutionMode review; never call update_parent with status in_review. Otherwise keep the issue todo or blocked with the exact gap and next owner.",
3403
3529
  DEADLINE_POSTURE_GUARD,
3404
3530
  "Do not install operating-system or user-global packages, and do not use host package managers such as brew, apt, yum, or global pip/npm installs. Use tools already available or workspace-local dependencies or virtual environments. If a required renderer or evaluator is unavailable, keep the source artifact, record the exact verification gap, and do not mutate the host.",
3405
3531
  `- command id: ${input.commandId}`,
@@ -3433,7 +3559,7 @@ function interactionResolutionText(context) {
3433
3559
  if (Object.keys(resolution).length === 0) return "";
3434
3560
  const target = asRecord(resolution.target);
3435
3561
  const exactDocumentRevisionDirective = readString(resolution.status) === "changes_requested" && readString(target.type) === "issue_document" && readString(target.issueId) && readString(target.documentId) && readString(target.key) && readString(target.revisionId) ? [
3436
- "The review target is an exact issue_document revision. Revise that same document with upsert_document_revision: copy target.issueId, target.documentId, and target.key, and use target.revisionId as baseRevisionId.",
3562
+ "The review target is an exact issue_document revision. Revise that same document with upsert_document_revision: copy target.issueId, target.documentId, and target.key, use target.revisionId as baseRevisionId, and put the complete revised markdown in the required action.body; metadata-only revisions are invalid.",
3437
3563
  "Do not copy the reviewed document into the current issue and do not restart its revision lineage at 1."
3438
3564
  ].join(" ") : "";
3439
3565
  return [
@@ -3544,7 +3670,10 @@ function runtimeAuthorizationText(context, mode, { suppressOrdinaryCompletionCon
3544
3670
  optionId: readString(optionId)
3545
3671
  })).filter((entry) => entry.optionId && !allowed.has(entry.authorizationClass));
3546
3672
  const issue = asRecord(context.paperclipIssue);
3547
- const completion = asRecord(asRecord(issue.taskRequirements).completion);
3673
+ const requirements = asRecord(issue.taskRequirements);
3674
+ const completion = asRecord(requirements.completion);
3675
+ const delivery = asRecord(requirements.delivery);
3676
+ const businessOutcome = asRecord(requirements.businessOutcome);
3548
3677
  const completionRole = readString(completion.role);
3549
3678
  const completionDeliverable = readString(completion.deliverable);
3550
3679
  const manifestRefreshOnly = isManifestRefreshOnly(context);
@@ -3554,13 +3683,26 @@ function runtimeAuthorizationText(context, mode, { suppressOrdinaryCompletionCon
3554
3683
  firstDocumentCheckpoint,
3555
3684
  "If work remains in an ordinary productive run, call update_parent with status: in_progress and a concrete next action so bounded continuation recovery can preserve a live path. Status: todo does not queue a normal continuation from an ordinary productive run. Only a server-issued successful-run handoff recovery may use status: todo, and only according to its exact Recovery Instruction. Otherwise use a supported terminal or waiting disposition."
3556
3685
  ].filter(Boolean).join(" ") : "";
3686
+ const businessOutcomeOwnershipContract = businessOutcome.mode === "required" ? [
3687
+ "Business Outcome review is owned by the Server terminal reconciler.",
3688
+ "Do not create a generic review-mode request_confirmation to ask the Board to accept final completion or the Outcome, and do not mark the issue done yourself. This does not prohibit an explicit intermediate review of an exact document revision before execution continues."
3689
+ ].join(" ") : "";
3690
+ const businessOutcomeTerminalContract = !suppressOrdinaryCompletionContract && businessOutcome.mode === "required" ? [
3691
+ delivery.mode === "required" ? "When every acceptance criterion is satisfied and the exact current Delivery Manifest is ready, record the final execution disposition with update_parent status in_progress and a concise evidence summary, then end the run successfully without creating a final review interaction." : "When every acceptance criterion is satisfied, record the final execution disposition with update_parent status in_progress and a concise evidence summary, then end the run successfully without creating a final review interaction.",
3692
+ delivery.mode === "required" ? "Only after the run and command succeed does the Server bind the exact current Delivery Manifest and terminal Outcome evidence, create the formal Board review before generic continuation handoff is evaluated, and move the issue to in_review. Board acceptance then finalizes the issue as done atomically." : "Only after the run and command succeed does the Server bind the terminal Outcome evidence, create the formal Board review before generic continuation handoff is evaluated, and move the issue to in_review. Board acceptance then finalizes the issue as done atomically."
3693
+ ].join(" ") : "";
3557
3694
  const authorizationContract = missing.length > 0 ? [
3558
3695
  `Current allowed action classes: ${[...allowed].join(", ") || "task_governance"}.`,
3559
3696
  "If the task requires a missing runtime action class, create a request_checkbox_confirmation interaction using the exact option id below and wait for its accepted continuation:",
3560
3697
  ...missing.map((entry) => `- ${entry.authorizationClass}: ${entry.optionId}`),
3561
3698
  "Never use request_confirmation to authorize a runtime action class."
3562
3699
  ].join("\n") : "";
3563
- return [completionContract, authorizationContract].filter(Boolean).join("\n");
3700
+ return [
3701
+ completionContract,
3702
+ businessOutcomeOwnershipContract,
3703
+ businessOutcomeTerminalContract,
3704
+ authorizationContract
3705
+ ].filter(Boolean).join("\n");
3564
3706
  }
3565
3707
  function runtimeDecompositionRequirementText(context) {
3566
3708
  const issue = asRecord(context.paperclipIssue);
@@ -3685,12 +3827,13 @@ function piMcpProxyExamplesText(input) {
3685
3827
  args: JSON.stringify(args)
3686
3828
  });
3687
3829
  return [
3688
- "The Pi native tool is the outer `mcp` proxy. Emit these as actual tool calls; `args` is the stringified inner canonical object:",
3830
+ "The Pi native tool is the outer `mcp` proxy. Emit these as actual tool calls; `args` is the stringified inner canonical object. Pi validates this string schema before extension hooks, so never send object-valued `args`:",
3689
3831
  "Keep review payload strings short. Reference the exact document key and revision in `target`; do not duplicate the reviewed document body in `prompt` or `detailsMarkdown`.",
3832
+ "payload.supersedesInteractionId is invalid. provenance.supersedesInteractionId is only for replacing a currently pending governed interaction; after changes_requested or rejected resolution, do not send a supersession id.",
3690
3833
  "update_parent.comment creates a separate persistent issue comment. Omit it when add_comment already recorded the message.",
3691
3834
  `- describe: ${proxy("runtime_action.describe", { schemaVersion: "runtime-action-v1", actionType: "update_parent" })}`,
3692
3835
  `- submit: ${proxy("runtime_action.submit", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-progress", action: { type: "update_parent", status: "in_progress" } })}`,
3693
- `- submit review interaction: ${proxy("runtime_action.submit", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-review", action: { type: "create_interaction", kind: "request_confirmation", continuationPolicy: "wake_assignee_on_accept", provenance: { purposeCode: "review_document_revision", requirementRefs: ["acceptance:document_review"], attentionOwner: { kind: "board", id: "board" }, epochKey: "document_revision:22222222-2222-4222-8222-222222222222" }, payload: { version: 1, resolutionMode: "review", prompt: "Review `plan` revision 1.", target: { type: "issue_document", issueId: "11111111-1111-4111-8111-111111111111", documentId: "33333333-3333-4333-8333-333333333333", key: "plan", revisionId: "22222222-2222-4222-8222-222222222222", revisionNumber: 1 } } } })}`,
3836
+ `- submit intermediate document review interaction: ${proxy("runtime_action.submit", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-review", action: { type: "create_interaction", kind: "request_confirmation", continuationPolicy: "wake_assignee_on_accept", provenance: { purposeCode: "review_document_revision", requirementRefs: ["acceptance:document_review"], attentionOwner: { kind: "board", id: "board" }, epochKey: "document_revision:22222222-2222-4222-8222-222222222222" }, payload: { version: 1, resolutionMode: "review", prompt: "Review `plan` revision 1.", target: { type: "issue_document", issueId: "11111111-1111-4111-8111-111111111111", documentId: "33333333-3333-4333-8333-333333333333", key: "plan", revisionId: "22222222-2222-4222-8222-222222222222", revisionNumber: 1 } } } })}`,
3694
3837
  `- plan: ${proxy("runtime_action.plan", { schemaVersion: "runtime-action-v1", idempotencyKey: "task-123-plan", actions: [{ type: "update_parent", status: "in_progress" }] })}`,
3695
3838
  `- commit the returned plan revision: ${proxy("runtime_action.commit", { schemaVersion: "runtime-action-v1", planId: "11111111-1111-4111-8111-111111111111", revision: "plan-revision-1" })}`,
3696
3839
  `- read document: ${proxy("amaster.read_issue_document", { issueId: "AM-123", key: "plan" })}`
@@ -4177,16 +4320,38 @@ function tcReadNumber(value, fallback = 0) {
4177
4320
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
4178
4321
  }
4179
4322
  var TC_PI_ARGUMENT_VALIDATION_NODE_BUDGET = 4e3;
4180
- function tcContainsPiArgumentValidation(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(), budget = { remaining: TC_PI_ARGUMENT_VALIDATION_NODE_BUDGET }) {
4181
- if (budget.remaining <= 0) return false;
4323
+ var TC_PI_ARGUMENT_VALIDATION_PATTERN = /\binvalid(?:[_ -]+)tool(?:[_ -]+)arguments?\b|\binvalid args json\b|\btool[- ]arguments? (?:failed )?validation\b/i;
4324
+ function tcFindPiArgumentValidationText(value, depth = 0, seen = /* @__PURE__ */ new WeakSet(), budget = { remaining: TC_PI_ARGUMENT_VALIDATION_NODE_BUDGET }) {
4325
+ if (budget.remaining <= 0) return null;
4182
4326
  budget.remaining -= 1;
4183
4327
  if (typeof value === "string") {
4184
- return /\binvalid(?:[_ -]+)tool(?:[_ -]+)arguments?\b|\binvalid args json\b|\btool[- ]arguments? (?:failed )?validation\b/i.test(value.slice(0, 2e4));
4328
+ const bounded = value.slice(0, 2e4);
4329
+ return TC_PI_ARGUMENT_VALIDATION_PATTERN.test(bounded) ? bounded : null;
4185
4330
  }
4186
- if (!value || typeof value !== "object" || depth >= 6 || seen.has(value)) return false;
4331
+ if (!value || typeof value !== "object" || depth >= 6 || seen.has(value)) return null;
4187
4332
  seen.add(value);
4188
4333
  const entries = Array.isArray(value) ? value.slice(0, 40).map((entry, index) => [String(index), entry]) : Object.entries(value).slice(0, 80);
4189
- return entries.some(([, entry]) => tcContainsPiArgumentValidation(entry, depth + 1, seen, budget));
4334
+ for (const [, entry] of entries) {
4335
+ const match = tcFindPiArgumentValidationText(entry, depth + 1, seen, budget);
4336
+ if (match) return match;
4337
+ }
4338
+ return null;
4339
+ }
4340
+ function tcPiArgumentValidationDiagnostic(value) {
4341
+ const text = tcFindPiArgumentValidationText(value);
4342
+ if (!text) return null;
4343
+ const normalized = text.toLowerCase();
4344
+ const validationSource = /\binvalid args json\b/iu.test(text) ? "invalid_args_json" : /\binvalid(?:[_ -]+)tool(?:[_ -]+)arguments?\b/iu.test(text) ? "invalid_tool_arguments" : "tool_argument_validation";
4345
+ const parseErrorKind = validationSource !== "invalid_args_json" ? null : normalized.includes("unexpected end") ? "unexpected_end" : normalized.includes("unexpected token") || normalized.includes("unexpected non-whitespace") ? "unexpected_token" : normalized.includes("unterminated string") ? "unterminated_string" : normalized.includes("bad control character") ? "bad_control_character" : normalized.includes("bad escaped character") || normalized.includes("invalid escape") ? "bad_escape" : /expected (?:','|'\}'|':'|property name|double-quoted property)/u.test(normalized) ? "missing_delimiter" : "other";
4346
+ const rawPosition = validationSource === "invalid_args_json" ? text.match(/\bposition\s+(\d{1,9})\b/iu)?.[1] : null;
4347
+ const parseErrorPosition = rawPosition ? Number(rawPosition) : null;
4348
+ return {
4349
+ validationSource,
4350
+ validationPath: validationSource === "invalid_args_json" ? "$.args" : "$",
4351
+ pathPrecision: validationSource === "invalid_args_json" ? "exact" : "root_only",
4352
+ ...parseErrorKind ? { parseErrorKind } : {},
4353
+ ...typeof parseErrorPosition === "number" && Number.isSafeInteger(parseErrorPosition) && parseErrorPosition >= 0 ? { parseErrorPosition } : {}
4354
+ };
4190
4355
  }
4191
4356
  function tcTruncateText(value, maxChars = 16e3) {
4192
4357
  const text = String(value ?? "");
@@ -4559,7 +4724,7 @@ function summarizePiEvent(event) {
4559
4724
  if (type === "tool_execution_start" || type === "tool_execution_end") {
4560
4725
  const toolName = tcReadString(event.toolName) ?? "unknown";
4561
4726
  const completed = type === "tool_execution_end";
4562
- const argumentValidationFailed = completed && event.isError === true && tcContainsPiArgumentValidation(event.result);
4727
+ const argumentValidationDiagnostic = completed && event.isError === true ? tcPiArgumentValidationDiagnostic(event.result) : null;
4563
4728
  return {
4564
4729
  stream: "system",
4565
4730
  level: completed && event.isError === true ? "error" : "info",
@@ -4570,7 +4735,7 @@ function summarizePiEvent(event) {
4570
4735
  toolName,
4571
4736
  toolCallId: tcReadString(event.toolCallId),
4572
4737
  status: completed ? event.isError === true ? "failed" : "completed" : "started",
4573
- ...argumentValidationFailed ? { errorCode: "invalid_tool_arguments" } : {}
4738
+ ...argumentValidationDiagnostic ? { errorCode: "invalid_tool_arguments", ...argumentValidationDiagnostic } : {}
4574
4739
  }
4575
4740
  };
4576
4741
  }
@@ -4726,6 +4891,7 @@ function governedMcpToolResult(structuredContent) {
4726
4891
  if (!status) return null;
4727
4892
  const invocationId = readString(structuredContent.invocationId);
4728
4893
  const providerContent = asRecord(structuredContent.content);
4894
+ const providerReceipt = asRecord(structuredContent.providerReceipt);
4729
4895
  const providerStatus = readString(providerContent.status);
4730
4896
  const providerResult = asRecord(providerContent.result);
4731
4897
  const effectResult = asRecord(providerResult.effectResult);
@@ -4742,12 +4908,23 @@ function governedMcpToolResult(structuredContent) {
4742
4908
  ...readString(providerResult.planId) ? { planId: readString(providerResult.planId) } : {},
4743
4909
  ...readString(providerResult.status) ? { resultStatus: readString(providerResult.status) } : {}
4744
4910
  } : null;
4911
+ const diagnosisId = readString(providerContent.diagnosisId);
4912
+ const diagnosisRevision = readNumber(providerContent.diagnosisRevision, 0);
4913
+ const documentRevisionId = readString(providerContent.documentRevisionId);
4914
+ const workProductId = readString(providerContent.workProductId);
4915
+ const diagnosisBrief = status === "succeeded" && invocationId && readString(providerReceipt.provider) === "amaster_actions" && readString(providerReceipt.invocationId) === invocationId && readString(providerReceipt.status) === "accepted" && readString(providerReceipt.writeKind) === "company_diagnosis_brief" && diagnosisId && Number.isSafeInteger(diagnosisRevision) && diagnosisRevision > 0 && documentRevisionId && workProductId ? {
4916
+ diagnosisId,
4917
+ diagnosisRevision,
4918
+ documentRevisionId,
4919
+ workProductId
4920
+ } : null;
4745
4921
  return {
4746
4922
  ...invocationId ? { invocationId } : {},
4747
4923
  status,
4748
4924
  ...providerStatus ? { providerStatus } : {},
4749
4925
  ...artifactIntent ? { artifactIntent } : {},
4750
- ...runtimeAction ? { runtimeAction } : {}
4926
+ ...runtimeAction ? { runtimeAction } : {},
4927
+ ...diagnosisBrief ? { diagnosisBrief } : {}
4751
4928
  };
4752
4929
  }
4753
4930
  function dedupeGovernedMcpToolResults(results) {
@@ -4820,10 +4997,23 @@ function finalizedPiRuntimeArtifactEvidence(runtimeArtifacts) {
4820
4997
  ...intentId ? { intentId } : {}
4821
4998
  };
4822
4999
  }
5000
+ function durablePiDiagnosisBriefEvidence(results) {
5001
+ const result3 = (Array.isArray(results) ? results : []).map(asRecord).find((entry) => readString(entry.status) === "succeeded" && Object.keys(asRecord(entry.diagnosisBrief)).length > 0);
5002
+ if (!result3) return null;
5003
+ const brief = asRecord(result3.diagnosisBrief);
5004
+ return {
5005
+ kind: "company_diagnosis_brief",
5006
+ invocationId: readString(result3.invocationId),
5007
+ diagnosisId: readString(brief.diagnosisId),
5008
+ diagnosisRevision: readNumber(brief.diagnosisRevision, 0),
5009
+ documentRevisionId: readString(brief.documentRevisionId),
5010
+ workProductId: readString(brief.workProductId)
5011
+ };
5012
+ }
4823
5013
  function classifyPiTerminalCleanupDisposition(parsed, runtimeArtifacts) {
4824
5014
  const diagnostics = Array.isArray(parsed?.cleanupDiagnostics) ? parsed.cleanupDiagnostics.map(asRecord) : [];
4825
5015
  if (parsed?.terminalEventType !== "agent_end" || readString(parsed?.stopReason) || parsed?.hasAssistantOutput !== true || diagnostics.length === 0 || diagnostics.some((diagnostic) => readString(diagnostic.phase) !== "post_terminal" || readString(diagnostic.code) !== "pi_terminal_cleanup_permission_denied") || readNumber(parsed?.nonCleanupErrorCount, 0) > 0) return null;
4826
- const durableEvidence = durablePiRuntimeActionEvidence(parsed?.mcpToolResults) ?? finalizedPiRuntimeArtifactEvidence(runtimeArtifacts);
5016
+ const durableEvidence = durablePiRuntimeActionEvidence(parsed?.mcpToolResults) ?? durablePiDiagnosisBriefEvidence(parsed?.mcpToolResults) ?? finalizedPiRuntimeArtifactEvidence(runtimeArtifacts);
4827
5017
  if (!durableEvidence) return null;
4828
5018
  return {
4829
5019
  status: "failed",
@@ -6764,7 +6954,7 @@ function within3(candidate, root) {
6764
6954
  const rel = relative6(root, candidate);
6765
6955
  return rel === "" || !rel.startsWith("..") && !isAbsolute6(rel);
6766
6956
  }
6767
- function readJsonFile3(path, label, fallback = {}) {
6957
+ function readJsonFile2(path, label, fallback = {}) {
6768
6958
  if (!existsSync11(path)) return fallback;
6769
6959
  const stat = lstatSync6(path);
6770
6960
  if (!stat.isFile() || stat.isSymbolicLink()) {
@@ -6815,8 +7005,8 @@ function copyTreeNoLinks(source, target) {
6815
7005
  chmodSync5(target, 384 | stat.mode & 73);
6816
7006
  }
6817
7007
  function mergeMcp(seedRoot, overlayRoot, governedConfig) {
6818
- const seed = record5(readJsonFile3(join12(seedRoot, "mcp.json"), "seed_mcp", { mcpServers: {} }));
6819
- const overlay = record5(readJsonFile3(join12(overlayRoot, "mcp.json"), "overlay_mcp", { mcpServers: {} }));
7008
+ const seed = record5(readJsonFile2(join12(seedRoot, "mcp.json"), "seed_mcp", { mcpServers: {} }));
7009
+ const overlay = record5(readJsonFile2(join12(overlayRoot, "mcp.json"), "overlay_mcp", { mcpServers: {} }));
6820
7010
  assertNoPersistentSecrets(seed, ["seed", "mcp.json"]);
6821
7011
  assertNoPersistentSecrets(overlay, ["overlay", "mcp.json"]);
6822
7012
  const seedServers = record5(seed.mcpServers);
@@ -6852,7 +7042,7 @@ function assertEnabledPackagesAvailable(settings, npmRoot) {
6852
7042
  }
6853
7043
  for (const name of requiredNames) {
6854
7044
  const metadataPath = join12(npmRoot, "node_modules", ...name.split("/"), "package.json");
6855
- const metadata = readJsonFile3(metadataPath, `package:${name}`, null);
7045
+ const metadata = readJsonFile2(metadataPath, `package:${name}`, null);
6856
7046
  if (!metadata || metadata.name !== name) {
6857
7047
  throw new Error(`pi_trusted_runtime_package_unavailable:${name}`);
6858
7048
  }
@@ -6880,8 +7070,8 @@ function materializeTrustedPiRuntimeProfile(input) {
6880
7070
  }
6881
7071
  const mergedJson = {};
6882
7072
  for (const entry of JSON_ENTRIES) {
6883
- const seed = readJsonFile3(join12(seedRoot, entry), `seed_${entry}`, {});
6884
- const overlay = readJsonFile3(join12(overlayRoot, entry), `overlay_${entry}`, {});
7073
+ const seed = readJsonFile2(join12(seedRoot, entry), `seed_${entry}`, {});
7074
+ const overlay = readJsonFile2(join12(overlayRoot, entry), `overlay_${entry}`, {});
6885
7075
  const merged = deepMerge(seed, overlay);
6886
7076
  if (entry === "settings.json") {
6887
7077
  merged["pi-security"] = {
@@ -6901,7 +7091,7 @@ function materializeTrustedPiRuntimeProfile(input) {
6901
7091
  chmodSync5(join12(agentDir, entry), 384);
6902
7092
  mergedJson[entry] = merged;
6903
7093
  }
6904
- const governedConfig = readJsonFile3(input.governedMcpConfigPath, "governed_mcp");
7094
+ const governedConfig = readJsonFile2(input.governedMcpConfigPath, "governed_mcp");
6905
7095
  const mcp = mergeMcp(seedRoot, overlayRoot, governedConfig);
6906
7096
  writeFileSync8(input.governedMcpConfigPath, `${JSON.stringify(mcp, null, 2)}
6907
7097
  `, { mode: 384 });
@@ -7947,20 +8137,17 @@ async function executeBrowserSessionCommand(command, dependencies = {}) {
7947
8137
  }
7948
8138
 
7949
8139
  // src/amaster-runtime-daemon/source-acquisition-invocation.mjs
8140
+ import { createHash as createHash10 } from "node:crypto";
7950
8141
  var SOURCE_ACQUISITION_PUBLIC_TOOLS = Object.freeze([
7951
- "web_fetch",
7952
- "browser_list_pages",
7953
- "browser_navigate_page",
7954
- "browser_take_snapshot",
7955
- "browser_take_screenshot",
7956
- "browser_analyze_screenshot",
7957
- "browser_wait_for",
8142
+ "source_open",
8143
+ "source_snapshot",
8144
+ "source_screenshot",
8145
+ "source_analyze_screenshot",
8146
+ "source_wait",
7958
8147
  "runtime_action.submit",
7959
8148
  "runtime_action.status"
7960
8149
  ]);
7961
- var SOURCE_ACQUISITION_AUTHENTICATED_TOOLS = Object.freeze(
7962
- SOURCE_ACQUISITION_PUBLIC_TOOLS.filter((tool) => tool !== "web_fetch")
7963
- );
8150
+ var SOURCE_ACQUISITION_AUTHENTICATED_TOOLS = SOURCE_ACQUISITION_PUBLIC_TOOLS;
7964
8151
  function exactToolsFor(profile) {
7965
8152
  if (profile?.access?.mode === "public") return SOURCE_ACQUISITION_PUBLIC_TOOLS;
7966
8153
  if (profile?.access?.mode === "authenticated") return SOURCE_ACQUISITION_AUTHENTICATED_TOOLS;
@@ -7982,6 +8169,34 @@ function sourceAcquisitionPiInvocationArgs(profile) {
7982
8169
  "--no-session"
7983
8170
  ];
7984
8171
  }
8172
+ function serializeSourceAcquisitionProfile(profile) {
8173
+ if (!profile || typeof profile !== "object" || Array.isArray(profile)) return null;
8174
+ const input = Buffer.from(JSON.stringify(profile), "utf8");
8175
+ return {
8176
+ input,
8177
+ sha256: createHash10("sha256").update(input).digest("hex")
8178
+ };
8179
+ }
8180
+ function sourceAcquisitionManagedInputs(options) {
8181
+ return [
8182
+ options.managedInput ? { fd: 3, input: options.managedInput, code: "managed_runtime_assertion" } : null,
8183
+ options.sourceProfileInput ? { fd: 4, input: options.sourceProfileInput, code: "source_acquisition_profile" } : null
8184
+ ].filter(Boolean);
8185
+ }
8186
+ function sourceAcquisitionManagedStdio(inputs) {
8187
+ const stdio = ["pipe", "pipe", "pipe"];
8188
+ for (const { fd } of inputs) {
8189
+ while (stdio.length <= fd) stdio.push("ignore");
8190
+ stdio[fd] = "pipe";
8191
+ }
8192
+ return stdio;
8193
+ }
8194
+ function deliverSourceAcquisitionManagedInputs(child, inputs, onError) {
8195
+ for (const { fd, input, code } of inputs) {
8196
+ child.stdio[fd].once("error", (error) => onError(code, error));
8197
+ child.stdio[fd].end(input);
8198
+ }
8199
+ }
7985
8200
  function assertSourceAcquisitionRuntimeAuthority({
7986
8201
  profile,
7987
8202
  executorKind,
@@ -7995,17 +8210,17 @@ function assertSourceAcquisitionRuntimeAuthority({
7995
8210
  }
7996
8211
 
7997
8212
  // src/amaster-runtime-daemon.mjs
7998
- var CONNECTOR_VERSION = "0.1.1-beta.0";
8213
+ var CONNECTOR_VERSION = "0.1.1-beta.2";
7999
8214
  var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
8000
8215
  var SOURCE_ACQUISITION_CAPABILITY = "source_acquisition_v1";
8001
8216
  var SOURCE_ACQUISITION_PROFILE_VERSION = "source_acquisition_v1";
8002
8217
  var SOURCE_ACQUISITION_RETENTION_VERSION = "source_summary_only_v1";
8003
8218
  var SOURCE_ACQUISITION_ACTION_VERSION = "complete_source_acquisition_v1";
8219
+ var SOURCE_ACQUISITION_HEADLESS_ADAPTER = "pi_browser_use_headless_v1";
8220
+ var SOURCE_ACQUISITION_DESKTOP_ADAPTER = "browser_skill_desktop_v1";
8004
8221
  var SOURCE_ACQUISITION_PACKAGE_VERSIONS = Object.freeze({
8005
- "@amaster.ai/pi-web-access": "0.1.2-beta.52",
8006
8222
  "@amaster.ai/pi-browser-use": "0.1.2-beta.52"
8007
8223
  });
8008
- var SOURCE_ACQUISITION_CONNECTOR_VERSION = "0.1.1-beta.0";
8009
8224
  var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
8010
8225
  var CHECKPOINT_TTL_MS = 24 * 60 * 60 * 1e3;
8011
8226
  var AMASTER_PI_PROHIBITED_EXTRA_ARGS = /* @__PURE__ */ new Set(["--no-extensions", "--no-skills", "--no-tools", "--no-session"]);
@@ -8536,14 +8751,11 @@ function sourceAcquisitionPackageMetadata(packageName2) {
8536
8751
  if (!existsSync14(packagePath)) return null;
8537
8752
  const stat = lstatSync7(packagePath);
8538
8753
  if (!stat.isFile() || stat.isSymbolicLink()) return null;
8539
- const metadata = readJsonFile4(packagePath);
8754
+ const metadata = readJsonFile3(packagePath);
8540
8755
  return metadata.name === packageName2 && readString(metadata.version) ? metadata : null;
8541
8756
  }
8542
8757
  function sourceAcquisitionRuntimeReadiness(config) {
8543
8758
  const unavailable = (reason) => ({ ready: false, reason });
8544
- if (CONNECTOR_VERSION !== SOURCE_ACQUISITION_CONNECTOR_VERSION) {
8545
- return unavailable("source_acquisition_connector_version_mismatch");
8546
- }
8547
8759
  const piExecutor = config.executors.find((executor) => executor.kind === "pi");
8548
8760
  if (!piExecutor || !commandExists(piExecutor.command, {
8549
8761
  ...process.env,
@@ -8565,9 +8777,16 @@ function sourceAcquisitionRuntimeReadiness(config) {
8565
8777
  return unavailable("source_acquisition_trusted_runtime_invalid");
8566
8778
  }
8567
8779
  const packageDigests = {
8568
- "@amaster.ai/pi-web-access": readString(process.env.AMASTER_SOURCE_ACQUISITION_PI_WEB_ACCESS_DIGEST),
8569
8780
  "@amaster.ai/pi-browser-use": readString(process.env.AMASTER_SOURCE_ACQUISITION_PI_BROWSER_USE_DIGEST)
8570
8781
  };
8782
+ const extensionDigest = readString(process.env.AMASTER_SOURCE_ACQUISITION_EXTENSION_DIGEST);
8783
+ if (!extensionDigest || !/^[a-f0-9]{64}$/.test(extensionDigest)) {
8784
+ return unavailable("source_acquisition_extension_digest_unavailable");
8785
+ }
8786
+ const adapters = (readString(process.env.AMASTER_SOURCE_ACQUISITION_ADAPTERS) ?? "").split(",").map((value) => value.trim()).filter(Boolean);
8787
+ if (adapters.length === 0 || adapters.some((adapter) => ![SOURCE_ACQUISITION_HEADLESS_ADAPTER, SOURCE_ACQUISITION_DESKTOP_ADAPTER].includes(adapter))) {
8788
+ return unavailable("source_acquisition_adapter_attestation_invalid");
8789
+ }
8571
8790
  const connectorDigest = readString(process.env.AMASTER_SOURCE_ACQUISITION_CONNECTOR_DIGEST);
8572
8791
  if (!connectorDigest || !/^[a-f0-9]{64}$/.test(connectorDigest)) {
8573
8792
  return unavailable("source_acquisition_connector_digest_unavailable");
@@ -8589,6 +8808,8 @@ function sourceAcquisitionRuntimeReadiness(config) {
8589
8808
  profileVersion: SOURCE_ACQUISITION_PROFILE_VERSION,
8590
8809
  retentionVersion: SOURCE_ACQUISITION_RETENTION_VERSION,
8591
8810
  actionVersion: SOURCE_ACQUISITION_ACTION_VERSION,
8811
+ extension: { digest: extensionDigest },
8812
+ adapters,
8592
8813
  connector: {
8593
8814
  version: CONNECTOR_VERSION,
8594
8815
  digest: connectorDigest
@@ -8703,10 +8924,10 @@ function piAgentSystemDataDir(config) {
8703
8924
  return configured ? resolve12(expandHomePath(configured)) : null;
8704
8925
  }
8705
8926
  function readPiAgentLocalPlatformCredential(credentialsDir) {
8706
- const pointer = readJsonFile4(join15(credentialsDir, "latest.json"));
8927
+ const pointer = readJsonFile3(join15(credentialsDir, "latest.json"));
8707
8928
  const credentialRef = readString(pointer.credentialRef);
8708
8929
  if (!credentialRef || !/^[a-f0-9]{64}$/i.test(credentialRef)) return null;
8709
- const credential = readJsonFile4(join15(credentialsDir, `${credentialRef}.json`));
8930
+ const credential = readJsonFile3(join15(credentialsDir, `${credentialRef}.json`));
8710
8931
  const organizationId = readString(credential.organizationId);
8711
8932
  const apiKey = readString(credential.apiKey);
8712
8933
  if (credential.version !== 1 || !organizationId || !apiKey) return null;
@@ -9270,16 +9491,16 @@ function sourceAcquisitionRuntimeProfile(config, command) {
9270
9491
  const access = asRecord(profile.access);
9271
9492
  const transport = asRecord(profile.transport);
9272
9493
  const tools = asRecord(profile.tools);
9273
- if (profile.purpose !== "source_acquisition_v1" || profile.retention !== "source_summary_only_v1" || readString(profile.runId) !== commandRunId(command) || !Array.isArray(tools.exactAllowlist) || tools.exactAllowlist.length === 0 || !["public", "authenticated"].includes(access.mode) || !["isolated", "existing"].includes(transport.browserMode) || !["provider_jina_or_local", "local_only"].includes(transport.webFetchMode)) {
9494
+ if (profile.purpose !== "source_acquisition_v1" || profile.retention !== "source_summary_only_v1" || readString(profile.runId) !== commandRunId(command) || !Array.isArray(tools.exactAllowlist) || tools.exactAllowlist.length === 0 || !["public", "authenticated"].includes(access.mode) || !["isolated", "existing"].includes(transport.browserMode) || ![SOURCE_ACQUISITION_HEADLESS_ADAPTER, SOURCE_ACQUISITION_DESKTOP_ADAPTER].includes(transport.adapter)) {
9274
9495
  throw new Error("source_acquisition_profile_invalid");
9275
9496
  }
9276
9497
  if (access.mode === "public") {
9277
- if (transport.browserMode !== "isolated" || transport.webFetchMode !== "provider_jina_or_local") {
9498
+ if (transport.browserMode !== "isolated" || transport.adapter !== SOURCE_ACQUISITION_HEADLESS_ADAPTER) {
9278
9499
  throw new Error("source_acquisition_profile_invalid");
9279
9500
  }
9280
9501
  return { profile };
9281
9502
  }
9282
- if (transport.browserMode !== "existing" || transport.webFetchMode !== "local_only") {
9503
+ if (transport.browserMode !== "existing" || transport.adapter !== SOURCE_ACQUISITION_DESKTOP_ADAPTER) {
9283
9504
  throw new Error("source_acquisition_profile_invalid");
9284
9505
  }
9285
9506
  const companyId = readString(profile.companyId);
@@ -9288,12 +9509,12 @@ function sourceAcquisitionRuntimeProfile(config, command) {
9288
9509
  if (!companyId || !bindingId || !/^profile_[a-z0-9]{16,64}$/i.test(localOpaqueRef ?? "")) {
9289
9510
  throw new Error("source_acquisition_profile_invalid");
9290
9511
  }
9291
- const profileName2 = createHash10("sha256").update(`${companyId}\0${bindingId}\0${localOpaqueRef}`).digest("hex");
9512
+ const profileName2 = createHash11("sha256").update(`${companyId}\0${bindingId}\0${localOpaqueRef}`).digest("hex");
9292
9513
  const stateRoot = resolve12(config.browserSessionStateRoot);
9293
9514
  const userDataDir = resolve12(stateRoot, profileName2);
9294
9515
  if (!pathWithin2(userDataDir, stateRoot)) throw new Error("source_acquisition_browser_profile_invalid");
9295
9516
  const markerPath = join15(userDataDir, ".amaster-browser-session.json");
9296
- const marker = readJsonFile4(markerPath);
9517
+ const marker = readJsonFile3(markerPath);
9297
9518
  if (marker.version !== 1 || marker.companyId !== companyId || marker.bindingId !== bindingId || marker.localOpaqueRef !== localOpaqueRef || Object.keys(marker).length !== 4) {
9298
9519
  throw new Error("source_acquisition_browser_profile_invalid");
9299
9520
  }
@@ -9309,7 +9530,7 @@ function trustedPiRuntimeSources(config) {
9309
9530
  policyFile: config.piRuntimeEffectivePolicyFile
9310
9531
  };
9311
9532
  }
9312
- function readJsonFile4(filePath) {
9533
+ function readJsonFile3(filePath) {
9313
9534
  try {
9314
9535
  const parsed = JSON.parse(readFileSync11(filePath, "utf8"));
9315
9536
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
@@ -9554,6 +9775,60 @@ function buildExecutorEnv(config, command, workspace) {
9554
9775
  AMASTER_EMPLOYEE_COMPANY_ID: companyId
9555
9776
  };
9556
9777
  }
9778
+ function copyPiModelCallConfig(sourceRoot, targetRoot, fileName, required) {
9779
+ const source = join15(sourceRoot, fileName);
9780
+ if (!existsSync14(source)) {
9781
+ if (required) throw new Error(`pi_model_call_profile_missing: ${fileName}`);
9782
+ return;
9783
+ }
9784
+ const sourceStat = lstatSync7(source);
9785
+ if (!sourceStat.isFile() || sourceStat.isSymbolicLink()) {
9786
+ throw new Error(`pi_model_call_profile_unsafe: ${fileName}`);
9787
+ }
9788
+ const target = join15(targetRoot, fileName);
9789
+ copyFileSync3(source, target);
9790
+ chmodSync6(target, 384);
9791
+ }
9792
+ function preparePiModelCallProfile(commandId, baseEnv) {
9793
+ const sourceRoot = readString(process.env.PI_CODING_AGENT_DIR) ?? readString(process.env.PI_AGENT_HOME) ?? readString(process.env["AMASTER-CLI_CODING_AGENT_DIR"]);
9794
+ if (!sourceRoot) throw new Error("pi_model_call_profile_missing: source Pi home");
9795
+ const sourceStat = lstatSync7(sourceRoot);
9796
+ if (!sourceStat.isDirectory() || sourceStat.isSymbolicLink()) {
9797
+ throw new Error("pi_model_call_profile_unsafe: source Pi home");
9798
+ }
9799
+ const profileRoot = mkdtempSync(join15(tmpdir(), "amaster-pi-model-call-"));
9800
+ const home = join15(profileRoot, "home");
9801
+ const agentDir = join15(profileRoot, "agent");
9802
+ const sessionsDir = join15(profileRoot, "sessions");
9803
+ const tempDir = join15(profileRoot, "tmp");
9804
+ for (const directory of [home, agentDir, sessionsDir, tempDir]) {
9805
+ mkdirSync9(directory, { recursive: true, mode: 448 });
9806
+ }
9807
+ try {
9808
+ copyPiModelCallConfig(sourceRoot, agentDir, "models.json", true);
9809
+ copyPiModelCallConfig(sourceRoot, agentDir, "auth.json", false);
9810
+ return {
9811
+ profileRoot,
9812
+ env: {
9813
+ ...baseEnv,
9814
+ HOME: home,
9815
+ PI_AGENT_HOME: agentDir,
9816
+ PI_CODING_AGENT_DIR: agentDir,
9817
+ "AMASTER-CLI_CODING_AGENT_DIR": agentDir,
9818
+ PI_CODING_AGENT_SESSION_DIR: sessionsDir,
9819
+ "AMASTER-CLI_CODING_AGENT_SESSION_DIR": sessionsDir,
9820
+ TMPDIR: tempDir,
9821
+ AMASTER_RUNTIME_COMMAND_ID: commandId
9822
+ }
9823
+ };
9824
+ } catch (error) {
9825
+ rmSync7(profileRoot, { recursive: true, force: true });
9826
+ throw error;
9827
+ }
9828
+ }
9829
+ function cleanupPiModelCallProfile(profile) {
9830
+ if (profile?.profileRoot) rmSync7(profile.profileRoot, { recursive: true, force: true });
9831
+ }
9557
9832
  function splitExtraArgs(value) {
9558
9833
  return splitList(value).flatMap((entry) => entry.split(/\s+/).filter(Boolean));
9559
9834
  }
@@ -9714,15 +9989,27 @@ async function executeModelCallCommand(config, command, signal) {
9714
9989
  purpose: readString(payload.purpose) ?? null,
9715
9990
  promptBytes: Buffer.byteLength(prompt, "utf8")
9716
9991
  });
9717
- const execution = await runExecutor(invocation.command, invocation.args, {
9718
- cwd: process.cwd(),
9719
- env: buildExecutorEnv(config, command, { managed: false, cwd: process.cwd(), sourceWorkspacePath: process.cwd() }),
9720
- stdin: invocation.stdin === "prompt" ? prompt : "",
9721
- timeoutSeconds,
9722
- maxOutputBytes,
9723
- executorKind: executor.kind,
9724
- signal
9725
- });
9992
+ let piModelCallProfile = null;
9993
+ let execution;
9994
+ try {
9995
+ const baseEnv = buildExecutorEnv(config, command, {
9996
+ managed: false,
9997
+ cwd: process.cwd(),
9998
+ sourceWorkspacePath: process.cwd()
9999
+ });
10000
+ piModelCallProfile = executor.kind === "pi" ? preparePiModelCallProfile(command.commandId, baseEnv) : null;
10001
+ execution = await runExecutor(invocation.command, invocation.args, {
10002
+ cwd: process.cwd(),
10003
+ env: piModelCallProfile?.env ?? baseEnv,
10004
+ stdin: invocation.stdin === "prompt" ? prompt : "",
10005
+ timeoutSeconds,
10006
+ maxOutputBytes,
10007
+ executorKind: executor.kind,
10008
+ signal
10009
+ });
10010
+ } finally {
10011
+ cleanupPiModelCallProfile(piModelCallProfile);
10012
+ }
9726
10013
  if (execution.stdout) {
9727
10014
  await ingestLog(config, command, "stdout", "info", truncateText(execution.stdout, 4e3));
9728
10015
  }
@@ -10330,11 +10617,12 @@ function runExecutor(command, args, options) {
10330
10617
  const maxRssMb = parsePositiveInteger(options.maxRssMb, 0);
10331
10618
  const maxRssBytes = maxRssMb * 1024 * 1024;
10332
10619
  const spawnInvocation = managedChildSpawnInvocation(command, args, options.spawnIdentity);
10620
+ const managedInputs = sourceAcquisitionManagedInputs(options);
10333
10621
  const child = spawn2(spawnInvocation.command, spawnInvocation.args, {
10334
10622
  cwd: options.cwd,
10335
10623
  env: options.env,
10336
10624
  detached: process.platform !== "win32",
10337
- stdio: options.managedInput ? ["pipe", "pipe", "pipe", "pipe"] : ["pipe", "pipe", "pipe"],
10625
+ stdio: sourceAcquisitionManagedStdio(managedInputs),
10338
10626
  ...spawnInvocation.spawnIdentity
10339
10627
  });
10340
10628
  const processGroupId = processGroupIdForChild(child);
@@ -10370,13 +10658,10 @@ function runExecutor(command, args, options) {
10370
10658
  signalExecutorProcess(child, "SIGTERM", processGroupId);
10371
10659
  scheduleStopKill();
10372
10660
  };
10373
- if (options.managedInput) {
10374
- child.stdio[3].once("error", (error) => {
10375
- spawnError = `managed_runtime_assertion_delivery_failed: ${error.message}`;
10376
- requestStop("managed_runtime_assertion_delivery_failed");
10377
- });
10378
- child.stdio[3].end(options.managedInput);
10379
- }
10661
+ deliverSourceAcquisitionManagedInputs(child, managedInputs, (code, error) => {
10662
+ spawnError = `${code}_delivery_failed: ${error.message}`;
10663
+ requestStop(`${code}_delivery_failed`);
10664
+ });
10380
10665
  const reapStoppedWorkspaceResidents = () => {
10381
10666
  if (settled || !stopReason || stopReason === "completion_cleanup") return;
10382
10667
  const residents = listWorkspaceResidentProcesses(options.cwd, processGroupId, {
@@ -10980,6 +11265,7 @@ async function executeRunExitClosureTurn(config, inputState, options = {}) {
10980
11265
  executorKind,
10981
11266
  ...readNumber(storedSpawnIdentity.uid, 0) > 0 ? { spawnIdentity: storedSpawnIdentity } : {},
10982
11267
  ...readString(executionConfig.managedInput) ? { managedInput: readString(executionConfig.managedInput) } : {},
11268
+ ...readString(executionConfig.sourceProfileInput) ? { sourceProfileInput: readString(executionConfig.sourceProfileInput) } : {},
10983
11269
  onOutput: (stream, chunk, rawBytes) => {
10984
11270
  noteActiveRunOutput(command, stream, chunk, rawBytes);
10985
11271
  liveOutputLogger.write(stream, chunk);
@@ -10995,24 +11281,24 @@ async function executeRunExitClosureTurn(config, inputState, options = {}) {
10995
11281
  const memoryLimit = asRecord(execution.memoryLimit);
10996
11282
  const hasMemoryLimit = readNumber(memoryLimit.rssBytes, 0) > 0;
10997
11283
  const parsed = parseExecutorTurnOutput(executorKind, execution, liveOutputLogger, hasOutputFlood);
11284
+ const mcpToolResults = dedupeGovernedMcpToolResults([
11285
+ ...Array.isArray(parsed.mcpToolResults) ? parsed.mcpToolResults.map(asRecord) : [],
11286
+ ...liveOutputLogger.mcpToolResults().map(asRecord)
11287
+ ]);
10998
11288
  const outputTelemetry = liveOutputLogger.snapshot({
10999
11289
  outputBytes: execution.outputBytes,
11000
11290
  floodLimitBytes: Math.max(1, readNumber(executionConfig.maxOutputBytes, config.executorMaxOutputBytes)),
11001
11291
  outputTokens: readNumber(parsed.usage?.outputTokens, 0)
11002
11292
  });
11003
11293
  const completionOutputStopped = executorKind === "pi" && piCompletionOutputStopped(parsed, execution);
11004
- const cleanupDisposition = executorKind === "pi" && execution.cancelled !== true && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition(parsed, []) : null;
11294
+ const cleanupDisposition = executorKind === "pi" && execution.cancelled !== true && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition({ ...parsed, mcpToolResults }, []) : null;
11005
11295
  const parsedForValidation = cleanupDisposition ? { ...parsed, errorMessage: null } : parsed;
11006
11296
  const piInvalidOutputError = executorKind === "pi" ? piOutputValidationError(parsedForValidation, {
11007
11297
  allowMissingTurnEnd: completionOutputStopped || Boolean(cleanupDisposition),
11008
11298
  allowMissingAssistantOutput: false
11009
11299
  }) : null;
11010
- const parsedError = hasOutputFlood ? "Run-exit closure output exceeded the configured limit" : hasMemoryLimit ? "Run-exit closure exceeded the configured memory limit" : execution.timedOut ? "Run-exit closure timed out" : execution.spawnError ?? piInvalidOutputError ?? parsedForValidation.errorMessage ?? ((execution.exitCode ?? 0) === 0 ? null : `Run-exit closure exited with code ${execution.exitCode ?? "unknown"}`);
11300
+ const parsedError = hasOutputFlood ? "Run-exit closure output exceeded the configured limit" : hasMemoryLimit ? "Run-exit closure exceeded the configured memory limit" : execution.timedOut ? "Run-exit closure timed out" : execution.spawnError ?? piInvalidOutputError ?? parsedForValidation.errorMessage ?? ((execution.exitCode ?? 0) === 0 || cleanupDisposition ? null : `Run-exit closure exited with code ${execution.exitCode ?? "unknown"}`);
11011
11301
  const succeeded = execution.cancelled !== true && !hasOutputFlood && !hasMemoryLimit && (execution.exitCode === 0 || completionOutputStopped || Boolean(cleanupDisposition)) && !execution.timedOut && !execution.spawnError && !parsedError;
11012
- const mcpToolResults = dedupeGovernedMcpToolResults([
11013
- ...Array.isArray(parsed.mcpToolResults) ? parsed.mcpToolResults.map(asRecord) : [],
11014
- ...liveOutputLogger.mcpToolResults().map(asRecord)
11015
- ]);
11016
11302
  await ingestLog(config, command, "system", succeeded ? "info" : "error", succeeded ? "Run-exit disposition closure turn completed" : `Run-exit disposition closure turn failed: ${parsedError}`, {
11017
11303
  presentationKind: "run_exit_disposition_closure",
11018
11304
  closureAttempt: 1,
@@ -11033,6 +11319,7 @@ async function executeRunExitClosureTurn(config, inputState, options = {}) {
11033
11319
  timedOut: execution.timedOut,
11034
11320
  summary: truncateText(readString(parsed.summary) ?? "", 2e3),
11035
11321
  outputTelemetry,
11322
+ cleanupDisposition,
11036
11323
  toolResults: mcpToolResults.slice(0, 10).map((result3) => ({
11037
11324
  status: readString(result3.status),
11038
11325
  toolName: readString(result3.toolName) ?? readString(result3.name) ?? readString(asRecord(result3.runtimeAction).toolName),
@@ -11955,7 +12242,7 @@ async function materializeIssueAttachments(config, command, workspace) {
11955
12242
  const body = await runtimeApiBuffer(runtimeAuth, contentPath);
11956
12243
  writeFileSync9(targetPath, body);
11957
12244
  const attachmentId = readString(attachment.id);
11958
- const actualSha256 = createHash10("sha256").update(body).digest("hex");
12245
+ const actualSha256 = createHash11("sha256").update(body).digest("hex");
11959
12246
  const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
11960
12247
  const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
11961
12248
  if (lineageCandidates.length > 0 && !lineage) {
@@ -12047,7 +12334,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
12047
12334
  throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
12048
12335
  }
12049
12336
  const body = await runtimeApiBuffer(runtimeAuth, contentPath);
12050
- const actualSha256 = createHash10("sha256").update(body).digest("hex");
12337
+ const actualSha256 = createHash11("sha256").update(body).digest("hex");
12051
12338
  if (body.byteLength !== byteSize || actualSha256 !== sha256) {
12052
12339
  throw new Error(
12053
12340
  `artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha256} actualSha256=${actualSha256}`
@@ -12117,7 +12404,7 @@ function safeCheckpointRelativePath(rawPath) {
12117
12404
  return normalized;
12118
12405
  }
12119
12406
  function hashFileSha256(filePath) {
12120
- return createHash10("sha256").update(readFileSync11(filePath)).digest("hex");
12407
+ return createHash11("sha256").update(readFileSync11(filePath)).digest("hex");
12121
12408
  }
12122
12409
  async function materializeIssueCheckpoint(config, command, workspace) {
12123
12410
  const checkpointDir = issueCheckpointDir(workspace);
@@ -12330,6 +12617,7 @@ async function executeRunCommand(config, command) {
12330
12617
  };
12331
12618
  let completionOwnsManagedMcpProfile = false;
12332
12619
  const sourceAcquisition = sourceAcquisitionRuntimeProfile(config, command);
12620
+ const sourceProfile = serializeSourceAcquisitionProfile(sourceAcquisition?.profile ?? null);
12333
12621
  const trustedPiRuntimeAssertion = commandTrustedPiRuntimeAssertion(command);
12334
12622
  assertSourceAcquisitionRuntimeAuthority({
12335
12623
  profile: sourceAcquisition,
@@ -12457,6 +12745,13 @@ async function executeRunCommand(config, command) {
12457
12745
  inheritedEntries: trustedPiRuntimeProfile.facts.inheritedEntries
12458
12746
  });
12459
12747
  }
12748
+ if (sourceProfile) {
12749
+ executorEnv = {
12750
+ ...executorEnv,
12751
+ AMASTER_SOURCE_ACQUISITION_PROFILE_FD: "4",
12752
+ AMASTER_SOURCE_ACQUISITION_PROFILE_SHA256: sourceProfile.sha256
12753
+ };
12754
+ }
12460
12755
  if (executor.kind === "pi" && piResolvedProviderConfig) {
12461
12756
  const agentDir = managedMcpProfile ? readString(managedMcpProfile.env.PI_CODING_AGENT_DIR) ?? readString(managedMcpProfile.env.PI_AGENT_HOME) ?? null : piAgentLocalPlatformRunnerEnabled(config) ? readString(executorEnv.PI_AGENT_HOME) ?? readString(executorEnv.PI_CODING_AGENT_DIR) ?? null : readString(executorEnv.PI_CODING_AGENT_DIR) ?? readString(executorEnv.PI_AGENT_HOME) ?? null;
12462
12757
  try {
@@ -12591,6 +12886,7 @@ async function executeRunCommand(config, command) {
12591
12886
  managedInput: `${JSON.stringify(trustedPiRuntimeAssertion)}
12592
12887
  `
12593
12888
  } : {},
12889
+ ...sourceProfile ? { sourceProfileInput: sourceProfile.input } : {},
12594
12890
  onOutput: (stream, chunk, rawBytes) => {
12595
12891
  noteActiveRunOutput(command, stream, chunk, rawBytes);
12596
12892
  liveOutputLogger.write(stream, chunk);
@@ -12759,7 +13055,10 @@ async function executeRunCommand(config, command) {
12759
13055
  const memoryLimitError = hasMemoryLimit ? `${executor.kind === "pi" ? "Pi Agent" : "Executor"} memory limit exceeded: RSS ${readNumber(memoryLimit.rssBytes, 0)} bytes exceeded ${readNumber(memoryLimit.limitBytes, config.executorMaxRssMb * 1024 * 1024)} bytes` : null;
12760
13056
  const piUsageDiagnostic = executor.kind === "pi" && !hasOutputFlood && piOutputUsageMetadataMissing(parsed) ? "Pi Agent exited without usage metadata" : null;
12761
13057
  const completionOutputStopped = executor.kind === "pi" && piCompletionOutputStopped(parsed, execution);
12762
- const cleanupDisposition = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition(parsed, runtimeArtifacts) : null;
13058
+ const cleanupDisposition = executor.kind === "pi" && !cancelled && !hasOutputFlood && !hasMemoryLimit && execution.timedOut !== true && !execution.spawnError && execution.signal === null ? classifyPiTerminalCleanupDisposition(
13059
+ { ...parsed, mcpToolResults },
13060
+ runtimeArtifacts
13061
+ ) : null;
12763
13062
  if (cleanupDisposition) {
12764
13063
  await ingestLog(
12765
13064
  config,
@@ -12933,7 +13232,8 @@ async function executeRunCommand(config, command) {
12933
13232
  maxRssMb: config.executorMaxRssMb,
12934
13233
  ...piChildIsolation ? { spawnIdentity: piChildIsolation.spawn } : {},
12935
13234
  ...trustedPiRuntime ? { managedInput: `${JSON.stringify(trustedPiRuntimeAssertion)}
12936
- ` } : {}
13235
+ ` } : {},
13236
+ ...sourceProfile ? { sourceProfileInput: sourceProfile.input } : {}
12937
13237
  }
12938
13238
  },
12939
13239
  completionRequest: {
@@ -5,7 +5,7 @@ import { dirname, join, resolve } from "node:path";
5
5
  import { homedir, hostname } from "node:os";
6
6
  import { fileURLToPath } from "node:url";
7
7
 
8
- const CONNECTOR_VERSION = "0.1.1-beta.0";
8
+ const CONNECTOR_VERSION = "0.1.1-beta.2";
9
9
 
10
10
  const CAPABILITIES = [
11
11
  "remote_registration",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/employee-runtime-connector",
3
- "version": "0.1.1-beta.0",
3
+ "version": "0.1.1-beta.2",
4
4
  "description": "MirrorX runtime connector CLI and daemon",
5
5
  "license": "MIT",
6
6
  "type": "module",