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

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.
@@ -2,7 +2,7 @@
2
2
  // MirrorX runtime connector daemon bundle.
3
3
 
4
4
  // src/amaster-runtime-daemon.mjs
5
- import { createHash as createHash11 } from "node:crypto";
5
+ import { createHash as createHash12 } from "node:crypto";
6
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
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";
@@ -1560,7 +1560,7 @@ function reconcileManagedCodexMcpProfiles(rootPath, options = {}) {
1560
1560
  }
1561
1561
 
1562
1562
  // src/amaster-runtime-daemon/pi-managed-mcp-profile.mjs
1563
- import { createHash as createHash2 } from "node:crypto";
1563
+ import { createHash as createHash3 } from "node:crypto";
1564
1564
  import {
1565
1565
  chmodSync as chmodSync2,
1566
1566
  copyFileSync,
@@ -1593,8 +1593,6 @@ var MANAGED_PI_PROVIDER_ENV_NAMES = Object.freeze([
1593
1593
  "AMASTER_MODEL_CREDENTIAL_REF",
1594
1594
  "AMASTER_API_KEY",
1595
1595
  "AMASTER_PROVIDER_BASE_URL",
1596
- "AMASTER_PROVIDER_DEFAULT_MODEL",
1597
- "AMASTER_PROVIDER_FLASH_MODEL",
1598
1596
  "AMASTER_PLATFORM_OAUTH_TOKEN",
1599
1597
  "AMASTER_PLATFORM_ORGANIZATION_ID",
1600
1598
  "AMASTER_BILLING_TURN_ID"
@@ -1636,28 +1634,6 @@ function imageGenBaseUrlFromProviderBaseUrl(value) {
1636
1634
  return input.replace(/\/v1\/?$/, "");
1637
1635
  }
1638
1636
  }
1639
- function ensureAmasterProviderModel(models, modelId, flash) {
1640
- const id = readString(modelId);
1641
- if (!id) return;
1642
- const existing = Array.isArray(models) ? models : [];
1643
- const index = existing.findIndex((entry) => asRecord(entry).id === id);
1644
- if (index >= 0) {
1645
- existing[index] = {
1646
- ...asRecord(existing[index]),
1647
- id,
1648
- input: readStringArray(asRecord(existing[index]).input).length > 0 ? asRecord(existing[index]).input : ["text", "image"],
1649
- reasoning: asRecord(existing[index]).reasoning ?? true,
1650
- ...flash ? { flash: true } : {}
1651
- };
1652
- return;
1653
- }
1654
- existing.push({
1655
- id,
1656
- input: ["text", "image"],
1657
- reasoning: true,
1658
- ...flash ? { flash: true } : {}
1659
- });
1660
- }
1661
1637
  function withoutManagedBillingHeaders(value) {
1662
1638
  const headers = { ...asRecord(value) };
1663
1639
  for (const name of Object.keys(AMASTER_BILLING_HEADER_ENV_REFERENCES)) {
@@ -1689,10 +1665,6 @@ function syncAmasterProviderModels(agentDir, executorEnv) {
1689
1665
  const headers = syncManagedBillingHeaders(amaster.headers, executorEnv);
1690
1666
  if (headers) amaster.headers = headers;
1691
1667
  else delete amaster.headers;
1692
- const models = Array.isArray(amaster.models) ? [...amaster.models] : [];
1693
- ensureAmasterProviderModel(models, executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL, false);
1694
- ensureAmasterProviderModel(models, executorEnv.AMASTER_PROVIDER_FLASH_MODEL, true);
1695
- if (models.length > 0) amaster.models = models;
1696
1668
  writeJsonFileAtomic(modelsPath, {
1697
1669
  ...config,
1698
1670
  providers: {
@@ -1709,19 +1681,8 @@ function syncAmasterProviderSettings(agentDir, executorEnv) {
1709
1681
  if (!existsSync2(settingsPath)) return false;
1710
1682
  const settings = readJsonFile(settingsPath);
1711
1683
  const baseUrl = readString(executorEnv.AMASTER_PROVIDER_BASE_URL);
1712
- const defaultModel = readString(executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL);
1713
1684
  const imageGenBaseUrl = imageGenBaseUrlFromProviderBaseUrl(baseUrl);
1714
1685
  let changed = false;
1715
- if (defaultModel) {
1716
- if (settings.defaultProvider !== "amaster") {
1717
- settings.defaultProvider = "amaster";
1718
- changed = true;
1719
- }
1720
- if (settings.defaultModel !== defaultModel) {
1721
- settings.defaultModel = defaultModel;
1722
- changed = true;
1723
- }
1724
- }
1725
1686
  const imageGen = settings["pi-image-gen"];
1726
1687
  if (isRecord(imageGen) && isRecord(imageGen.customProviders) && isRecord(imageGen.customProviders.amaster)) {
1727
1688
  const customProviders = imageGen.customProviders;
@@ -2004,8 +1965,207 @@ function managedPiMcpArgsNormalizerExtensionSource() {
2004
1965
  ].join("\n\n");
2005
1966
  }
2006
1967
 
1968
+ // src/amaster-runtime-daemon/pi-effective-tools-attestor.mjs
1969
+ import { createHash as createHash2 } from "node:crypto";
1970
+ var MANAGED_PI_EFFECTIVE_TOOLS_ATTESTOR_FILENAME = "amaster-effective-tools-attestor.js";
1971
+ var MANAGED_PI_EFFECTIVE_TOOLS_SCHEMA_VERSION = "amaster.pi-effective-tools.v1";
1972
+ function normalizedSchema(value, adapterNormalized) {
1973
+ const schema = value && typeof value === "object" && !Array.isArray(value) ? value : {};
1974
+ if (!adapterNormalized) return schema;
1975
+ const { $schema: _schema, additionalProperties: _additionalProperties, ...normalized } = schema;
1976
+ return normalized;
1977
+ }
1978
+ function stablePiJson(value) {
1979
+ if (value === null || value === void 0 || typeof value !== "object") {
1980
+ const serialized = JSON.stringify(value);
1981
+ return serialized === void 0 ? "undefined" : serialized;
1982
+ }
1983
+ if (Array.isArray(value)) return `[${value.map(stablePiJson).join(",")}]`;
1984
+ const keys = Object.keys(value).sort();
1985
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${stablePiJson(value[key])}`).join(",")}}`;
1986
+ }
1987
+ function stablePiToolSchemaHash(schema, options = {}) {
1988
+ return createHash2("sha256").update(stablePiJson(normalizedSchema(schema, options.adapterNormalized === true))).digest("hex");
1989
+ }
1990
+ function stablePiEffectiveToolSetHash(entries) {
1991
+ const normalized = entries.map((entry) => ({ name: entry.name, schemaHash: entry.schemaHash ?? entry.effectiveSchemaHash })).sort((left, right) => left.name.localeCompare(right.name));
1992
+ return createHash2("sha256").update(stablePiJson(normalized)).digest("hex");
1993
+ }
1994
+ function stablePiDirectCatalogSetHash(entries) {
1995
+ const normalized = entries.map((entry) => ({ name: entry.name, exposedName: entry.exposedName, schemaHash: entry.schemaHash, riskLevel: entry.riskLevel })).sort((left, right) => left.name.localeCompare(right.name));
1996
+ return createHash2("sha256").update(stablePiJson(normalized)).digest("hex");
1997
+ }
1998
+ function managedPiEffectiveToolsAttestorExtensionSource() {
1999
+ return String.raw`import { createHash } from "node:crypto";
2000
+ import { readFileSync, writeFileSync } from "node:fs";
2001
+ import { fileURLToPath } from "node:url";
2002
+ import { Value } from "typebox/value";
2003
+
2004
+ const SCHEMA_VERSION = ${JSON.stringify(MANAGED_PI_EFFECTIVE_TOOLS_SCHEMA_VERSION)};
2005
+
2006
+ function record(value) {
2007
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
2008
+ }
2009
+
2010
+ function stableJson(value) {
2011
+ if (value === null || value === undefined || typeof value !== "object") {
2012
+ const serialized = JSON.stringify(value);
2013
+ return serialized === undefined ? "undefined" : serialized;
2014
+ }
2015
+ if (Array.isArray(value)) return "[" + value.map(stableJson).join(",") + "]";
2016
+ const keys = Object.keys(value).sort();
2017
+ return "{" + keys.map((key) => JSON.stringify(key) + ":" + stableJson(value[key])).join(",") + "}";
2018
+ }
2019
+
2020
+ function sha256(value) {
2021
+ return createHash("sha256").update(value).digest("hex");
2022
+ }
2023
+
2024
+ function schemaHash(value) {
2025
+ return sha256(stableJson(record(value)));
2026
+ }
2027
+
2028
+ function toolSetHash(entries) {
2029
+ return sha256(stableJson(entries
2030
+ .map((entry) => ({ name: entry.name, schemaHash: entry.schemaHash }))
2031
+ .sort((left, right) => left.name.localeCompare(right.name))));
2032
+ }
2033
+
2034
+ function requiredPath(name) {
2035
+ const value = process.env[name];
2036
+ if (typeof value !== "string" || value.trim() === "") throw new Error(name + " is required");
2037
+ return value;
2038
+ }
2039
+
2040
+ function sourceIsMcpAdapter(sourceInfo) {
2041
+ return stableJson(sourceInfo).includes("pi-mcp-adapter");
2042
+ }
2043
+
2044
+ function safeWriteReceipt(receiptPath, receipt) {
2045
+ writeFileSync(receiptPath, JSON.stringify(receipt) + "\n", { encoding: "utf8", mode: 0o600 });
2046
+ }
2047
+
2048
+ function validationErrorPath(error) {
2049
+ if (typeof error.path === "string" && error.path) return error.path;
2050
+ const base = typeof error.instancePath === "string" ? error.instancePath : "";
2051
+ const params = record(error.params);
2052
+ const additional = Array.isArray(params.additionalProperties) ? params.additionalProperties[0] : null;
2053
+ if (typeof additional === "string" && additional) return base + "/" + additional;
2054
+ const required = Array.isArray(params.requiredProperties) ? params.requiredProperties[0] : null;
2055
+ if (typeof required === "string" && required) return base + "/" + required;
2056
+ return base || "/";
2057
+ }
2058
+
2059
+ function inputErrorReason(schema, input) {
2060
+ const errors = [...Value.Errors(schema, input)];
2061
+ if (errors.length === 0) return null;
2062
+ return errors.slice(0, 8).map((error) => validationErrorPath(error) + ": " + error.message).join("; ");
2063
+ }
2064
+
2065
+ export default function amasterEffectiveToolsAttestor(pi) {
2066
+ const mode = process.env.AMASTER_PI_EFFECTIVE_TOOLS_MODE;
2067
+ if (mode !== "probe" && mode !== "enforce") return;
2068
+ const manifestPath = requiredPath("AMASTER_PI_EFFECTIVE_TOOLS_MANIFEST");
2069
+ const receiptPath = requiredPath("AMASTER_PI_EFFECTIVE_TOOLS_RECEIPT");
2070
+ const cachePath = requiredPath("AMASTER_PI_EFFECTIVE_TOOLS_CACHE");
2071
+ const configPath = requiredPath("AMASTER_PI_EFFECTIVE_TOOLS_CONFIG");
2072
+
2073
+ pi.on("session_start", async () => {
2074
+ let receipt;
2075
+ try {
2076
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
2077
+ if (manifest.schemaVersion !== SCHEMA_VERSION || manifest.serverName !== "amaster") {
2078
+ throw new Error("effective tool manifest identity mismatch");
2079
+ }
2080
+ const sourceDigest = sha256(readFileSync(fileURLToPath(import.meta.url)));
2081
+ if (sourceDigest !== manifest.attestorSourceSha256) throw new Error("attestor source digest mismatch");
2082
+ const configDigest = sha256(readFileSync(configPath));
2083
+ if (configDigest !== manifest.configSha256) throw new Error("managed MCP config digest mismatch");
2084
+ const cacheDigest = sha256(readFileSync(cachePath));
2085
+ if (cacheDigest !== manifest.cacheSha256) throw new Error("managed MCP cache digest mismatch");
2086
+
2087
+ const expectedEntries = Array.isArray(manifest.entries) ? manifest.entries : [];
2088
+ if (expectedEntries.length === 0) throw new Error("effective tool manifest is empty");
2089
+ const expectedByName = new Map(expectedEntries.map((entry) => [entry.name, entry]));
2090
+ if (expectedByName.size !== expectedEntries.length) throw new Error("effective tool manifest has duplicate names");
2091
+ for (const entry of expectedEntries) {
2092
+ const validatorSelfTest = inputErrorReason(entry.schema, { __amasterUnexpected: true });
2093
+ if (!validatorSelfTest || !validatorSelfTest.includes("/__amasterUnexpected")) {
2094
+ throw new Error("strict input validator self-test failed for " + entry.name);
2095
+ }
2096
+ }
2097
+
2098
+ const allTools = pi.getAllTools();
2099
+ const proxyPresent = allTools.some((tool) => tool.name === "mcp");
2100
+ const adapterTools = allTools.filter((tool) => sourceIsMcpAdapter(tool.sourceInfo));
2101
+ const directTools = adapterTools.filter((tool) => tool.name !== "mcp").map((tool) => ({
2102
+ name: tool.name,
2103
+ schemaHash: schemaHash(tool.parameters),
2104
+ }));
2105
+ const actualByName = new Map(directTools.map((entry) => [entry.name, entry]));
2106
+ const missing = [...expectedByName.keys()].filter((name) => !actualByName.has(name)).sort();
2107
+ const unexpected = [...actualByName.keys()].filter((name) => !expectedByName.has(name)).sort();
2108
+ const schemaMismatches = [...expectedByName.entries()].flatMap(([name, expected]) => {
2109
+ const actual = actualByName.get(name);
2110
+ return actual && actual.schemaHash !== expected.effectiveSchemaHash
2111
+ ? [{ name, expected: expected.effectiveSchemaHash, actual: actual.schemaHash }]
2112
+ : [];
2113
+ });
2114
+ const effectiveSetHash = toolSetHash(directTools);
2115
+ if (proxyPresent || missing.length > 0 || unexpected.length > 0 || schemaMismatches.length > 0) {
2116
+ throw new Error("effective tool surface mismatch: proxy=" + proxyPresent + " missing=" + missing.join(",") + " unexpected=" + unexpected.join(",") + " schemas=" + schemaMismatches.map((entry) => entry.name).join(","));
2117
+ }
2118
+ if (effectiveSetHash !== manifest.effectiveSetHash) throw new Error("effective tool set hash mismatch");
2119
+ receipt = {
2120
+ schemaVersion: SCHEMA_VERSION,
2121
+ status: "attested",
2122
+ mode,
2123
+ proxyPresent,
2124
+ effectiveSetHash,
2125
+ effectiveTools: directTools.sort((left, right) => left.name.localeCompare(right.name)),
2126
+ effectiveToolBindings: expectedEntries
2127
+ .map((entry) => ({ canonicalName: entry.canonicalName, exposedName: entry.name, effectiveSchemaHash: entry.effectiveSchemaHash }))
2128
+ .sort((left, right) => left.canonicalName.localeCompare(right.canonicalName)),
2129
+ attestorSourceSha256: sourceDigest,
2130
+ configSha256: configDigest,
2131
+ cacheSha256: cacheDigest,
2132
+ strictInputValidatorSelfTest: true,
2133
+ modelInvocationStarted: false,
2134
+ attestedAt: new Date().toISOString(),
2135
+ };
2136
+ safeWriteReceipt(receiptPath, receipt);
2137
+ if (mode === "probe") process.exit(0);
2138
+ } catch (error) {
2139
+ receipt = {
2140
+ schemaVersion: SCHEMA_VERSION,
2141
+ status: "rejected",
2142
+ mode,
2143
+ error: error instanceof Error ? error.message : String(error),
2144
+ modelInvocationStarted: false,
2145
+ attestedAt: new Date().toISOString(),
2146
+ };
2147
+ safeWriteReceipt(receiptPath, receipt);
2148
+ process.exit(78);
2149
+ }
2150
+ });
2151
+
2152
+ pi.on("tool_call", (event) => {
2153
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
2154
+ const entry = Array.isArray(manifest.entries)
2155
+ ? manifest.entries.find((candidate) => candidate.name === event.toolName)
2156
+ : null;
2157
+ if (!entry) return;
2158
+ const reason = inputErrorReason(entry.schema, event.input);
2159
+ if (!reason) return;
2160
+ return { block: true, reason: "Governed tool input rejected: " + reason };
2161
+ });
2162
+ }
2163
+ `;
2164
+ }
2165
+
2007
2166
  // src/amaster-runtime-daemon/pi-managed-mcp-profile.mjs
2008
2167
  var MANAGED_PI_MCP_TOOL_MODE = "proxy_only";
2168
+ var MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE = "direct_typed";
2009
2169
  var MANAGED_PI_MCP_ARGS_NORMALIZATION = "json_string_control_characters_v1";
2010
2170
  var MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME = "amaster-mcp-args-normalizer.js";
2011
2171
  function createManagedPiMcpProfileApi(options = {}) {
@@ -2013,6 +2173,14 @@ function createManagedPiMcpProfileApi(options = {}) {
2013
2173
  const nowImpl = typeof options.now === "function" ? options.now : Date.now;
2014
2174
  const SUPPORTED_SCHEMA_VERSION2 = "amaster.governed-mcp.v1";
2015
2175
  const SUPPORTED_SERVER_NAME2 = "amaster";
2176
+ const DIRECT_CATALOG_SCHEMA_VERSION = "amaster.governed-mcp-direct-catalog.v1";
2177
+ const DIRECT_TYPED_V1_TOOL_NAMES = /* @__PURE__ */ new Set([
2178
+ "runtime_action.submit",
2179
+ "amaster.read_company_diagnosis",
2180
+ "amaster.publish_company_diagnosis_brief"
2181
+ ]);
2182
+ const PROVIDER_SAFE_TOOL_NAME = /^[A-Za-z][A-Za-z0-9_-]*$/;
2183
+ const PI_BUILTIN_TOOL_NAMES = /* @__PURE__ */ new Set(["read", "bash", "edit", "write", "grep", "find", "ls", "mcp"]);
2016
2184
  const MINIMUM_PI_VERSION = [0, 73, 1];
2017
2185
  const MINIMUM_MCP_ADAPTER_VERSION = [2, 6, 1];
2018
2186
  const MANAGED_BROWSER_USE_PACKAGE = "@amaster.ai/pi-browser-use";
@@ -2179,7 +2347,7 @@ function createManagedPiMcpProfileApi(options = {}) {
2179
2347
  nonEmpty2(session.invocationId, "nativeSession.invocationId");
2180
2348
  const sourceWorkspacePath = nonEmpty2(session.cwd, "nativeSession.cwd");
2181
2349
  const issueRoot = dirname3(runDir);
2182
- const managedSourceRunDirName = `${sourceRunId}-${createHash2("sha256").update(sourceRunId).digest("hex").slice(0, 8)}`;
2350
+ const managedSourceRunDirName = `${sourceRunId}-${createHash3("sha256").update(sourceRunId).digest("hex").slice(0, 8)}`;
2183
2351
  const sourceRunDirs = readdirSync2(issueRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() && (entry.name === sourceRunId || entry.name === managedSourceRunDirName)).map((entry) => join4(issueRoot, entry.name));
2184
2352
  if (sourceRunDirs.length !== 1) {
2185
2353
  throw new Error(`pi_managed_mcp_session_rollout_missing: expected one source run directory for ${sourceRunId}, received ${sourceRunDirs.length}`);
@@ -2224,6 +2392,82 @@ function createManagedPiMcpProfileApi(options = {}) {
2224
2392
  if (!Number.isFinite(value)) throw new Error("pi_managed_mcp_attestation_failed: invalid attestation clock");
2225
2393
  return value;
2226
2394
  }
2395
+ function sha256(value) {
2396
+ return createHash3("sha256").update(value).digest("hex");
2397
+ }
2398
+ function adapterServerConfigHash(definition) {
2399
+ return sha256(stablePiJson({
2400
+ command: definition.command,
2401
+ args: definition.args,
2402
+ env: definition.env,
2403
+ cwd: definition.cwd,
2404
+ url: definition.url,
2405
+ headers: definition.headers,
2406
+ auth: definition.auth,
2407
+ bearerToken: definition.bearerToken,
2408
+ bearerTokenEnv: definition.bearerTokenEnv,
2409
+ exposeResources: definition.exposeResources,
2410
+ excludeTools: definition.excludeTools
2411
+ }));
2412
+ }
2413
+ function validateDirectCatalog(gateway) {
2414
+ const catalog = record6(gateway.toolCatalog);
2415
+ if (catalog.schemaVersion !== DIRECT_CATALOG_SCHEMA_VERSION) {
2416
+ throw new Error("pi_managed_mcp_invalid: direct tool catalog schema mismatch");
2417
+ }
2418
+ const tools = Array.isArray(catalog.tools) ? catalog.tools.map(record6) : [];
2419
+ if (tools.length !== DIRECT_TYPED_V1_TOOL_NAMES.size) {
2420
+ throw new Error("pi_managed_mcp_invalid: direct tool catalog size mismatch");
2421
+ }
2422
+ const names = /* @__PURE__ */ new Set();
2423
+ const exposedNames = /* @__PURE__ */ new Set();
2424
+ const normalized = tools.map((tool) => {
2425
+ const name = nonEmpty2(tool.name, "toolCatalog.tools.name");
2426
+ if (!DIRECT_TYPED_V1_TOOL_NAMES.has(name) || names.has(name)) {
2427
+ throw new Error("pi_managed_mcp_invalid: direct tool catalog name mismatch");
2428
+ }
2429
+ names.add(name);
2430
+ const exposedName = nonEmpty2(tool.exposedName, `toolCatalog.tools.exposedName:${name}`);
2431
+ if (!PROVIDER_SAFE_TOOL_NAME.test(exposedName) || PI_BUILTIN_TOOL_NAMES.has(exposedName)) {
2432
+ throw new Error(`pi_managed_mcp_invalid: direct tool exposed name is unsafe for ${name}`);
2433
+ }
2434
+ if (exposedNames.has(exposedName)) {
2435
+ throw new Error(`pi_managed_mcp_invalid: direct tool exposed name collision for ${exposedName}`);
2436
+ }
2437
+ exposedNames.add(exposedName);
2438
+ const inputSchema = record6(tool.inputSchema);
2439
+ if (inputSchema.type !== "object" || inputSchema.additionalProperties !== false) {
2440
+ throw new Error(`pi_managed_mcp_invalid: direct tool schema is not strict for ${name}`);
2441
+ }
2442
+ const schemaHash = stablePiToolSchemaHash(inputSchema);
2443
+ if (tool.schemaHash !== schemaHash) {
2444
+ throw new Error(`pi_managed_mcp_invalid: direct tool schema hash mismatch for ${name}`);
2445
+ }
2446
+ const riskLevel = nonEmpty2(tool.riskLevel, `toolCatalog.tools.riskLevel:${name}`);
2447
+ if (!(/* @__PURE__ */ new Set(["read", "write", "destructive"])).has(riskLevel)) {
2448
+ throw new Error(`pi_managed_mcp_invalid: direct tool risk level mismatch for ${name}`);
2449
+ }
2450
+ return {
2451
+ name,
2452
+ exposedName,
2453
+ description: typeof tool.description === "string" ? tool.description : "",
2454
+ inputSchema,
2455
+ schemaHash,
2456
+ riskLevel,
2457
+ effectiveSchemaHash: stablePiToolSchemaHash(inputSchema, { adapterNormalized: true })
2458
+ };
2459
+ });
2460
+ const setHash = stablePiDirectCatalogSetHash(normalized.map((tool) => ({
2461
+ name: tool.name,
2462
+ exposedName: tool.exposedName,
2463
+ schemaHash: tool.schemaHash,
2464
+ riskLevel: tool.riskLevel
2465
+ })));
2466
+ if (catalog.setHash !== setHash) {
2467
+ throw new Error("pi_managed_mcp_invalid: direct tool catalog set hash mismatch");
2468
+ }
2469
+ return { setHash, tools: normalized.sort((left, right) => left.name.localeCompare(right.name)) };
2470
+ }
2227
2471
  function piExecutableIdentity(executorCommand) {
2228
2472
  try {
2229
2473
  const realPath = realpathSync2(executorCommand);
@@ -2231,8 +2475,8 @@ function createManagedPiMcpProfileApi(options = {}) {
2231
2475
  if (!executableStat.isFile() || executableStat.isSymbolicLink()) {
2232
2476
  throw Object.assign(new Error("Pi executable is not a regular file"), { code: "EUNSAFE" });
2233
2477
  }
2234
- const contentSha256 = createHash2("sha256").update(readFileSync3(realPath)).digest("hex");
2235
- return `sha256:${createHash2("sha256").update(JSON.stringify({ realPath, contentSha256 })).digest("hex")}`;
2478
+ const contentSha256 = createHash3("sha256").update(readFileSync3(realPath)).digest("hex");
2479
+ return `sha256:${createHash3("sha256").update(JSON.stringify({ realPath, contentSha256 })).digest("hex")}`;
2236
2480
  } catch (error) {
2237
2481
  const errorCode = typeof error?.code === "string" ? error.code : "UNKNOWN";
2238
2482
  throw new Error(`pi_managed_mcp_attestation_failed: --version error=${errorCode}`);
@@ -2278,7 +2522,15 @@ function createManagedPiMcpProfileApi(options = {}) {
2278
2522
  throw new Error("pi_managed_mcp_invalid: Gateway authority mismatch");
2279
2523
  }
2280
2524
  if ((runtimeAuth.issueId ?? null) !== (headers["x-amaster-issue-id"] ?? null)) throw new Error("pi_managed_mcp_invalid: issue authority mismatch");
2281
- return { gateway, gatewayUrl, sessionToken, headers, runId };
2525
+ const mcpToolMode = gateway.mcpToolMode ?? MANAGED_PI_MCP_TOOL_MODE;
2526
+ if (mcpToolMode !== MANAGED_PI_MCP_TOOL_MODE && mcpToolMode !== MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE) {
2527
+ throw new Error("pi_managed_mcp_invalid: unsupported managed Pi MCP tool mode");
2528
+ }
2529
+ const directCatalog = mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE ? validateDirectCatalog(gateway) : null;
2530
+ if (mcpToolMode === MANAGED_PI_MCP_TOOL_MODE && gateway.toolCatalog !== void 0) {
2531
+ throw new Error("pi_managed_mcp_invalid: proxy-only authority cannot carry a direct tool catalog");
2532
+ }
2533
+ return { gateway, gatewayUrl, sessionToken, headers, runId, mcpToolMode, directCatalog };
2282
2534
  }
2283
2535
  function isSensitiveAuthKey2(key) {
2284
2536
  const normalized = String(key).trim().replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().replaceAll("-", "_");
@@ -2443,8 +2695,13 @@ function createManagedPiMcpProfileApi(options = {}) {
2443
2695
  config: record6(sourceSettings["pi-telemetry"])
2444
2696
  };
2445
2697
  }
2446
- function seedPiRuntime(sourceHome, agentDir, sourceAcquisition = null) {
2698
+ function seedPiRuntime(sourceHome, agentDir, sourceAcquisition = null, mcpToolMode = MANAGED_PI_MCP_TOOL_MODE) {
2447
2699
  const source = resolve2(nonEmpty2(sourceHome, "sourcePiHome"));
2700
+ const sourceStat = lstatSync2(source);
2701
+ if (!sourceStat.isDirectory() || sourceStat.isSymbolicLink()) {
2702
+ throw new Error("pi_managed_mcp_source_config_unsafe: Pi home");
2703
+ }
2704
+ chmodSync2(source, sourceStat.mode & 511 | 1);
2448
2705
  const npmSource = join4(source, "npm");
2449
2706
  const adapterPackagePath = join4(npmSource, "node_modules", "pi-mcp-adapter", "package.json");
2450
2707
  if (!existsSync3(adapterPackagePath) || lstatSync2(adapterPackagePath).isSymbolicLink()) {
@@ -2494,10 +2751,17 @@ function createManagedPiMcpProfileApi(options = {}) {
2494
2751
  `);
2495
2752
  const extensionsDir = join4(agentDir, "extensions");
2496
2753
  mkdirSync3(extensionsDir, { recursive: true, mode: 448 });
2497
- writePrivateFile2(
2498
- join4(extensionsDir, MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME),
2499
- managedPiMcpArgsNormalizerExtensionSource()
2500
- );
2754
+ if (mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE) {
2755
+ writePrivateFile2(
2756
+ join4(extensionsDir, MANAGED_PI_EFFECTIVE_TOOLS_ATTESTOR_FILENAME),
2757
+ managedPiEffectiveToolsAttestorExtensionSource()
2758
+ );
2759
+ } else {
2760
+ writePrivateFile2(
2761
+ join4(extensionsDir, MANAGED_PI_MCP_ARGS_NORMALIZER_FILENAME),
2762
+ managedPiMcpArgsNormalizerExtensionSource()
2763
+ );
2764
+ }
2501
2765
  if (sourceAcquisition && !copyPrivateFile(
2502
2766
  join4(source, "extensions", "amaster-source-acquisition.js"),
2503
2767
  join4(extensionsDir, "amaster-source-acquisition.js")
@@ -2590,9 +2854,62 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
2590
2854
  liveProbeAgeMs
2591
2855
  };
2592
2856
  }
2857
+ function attestDirectPiTools(executorCommand, env, input) {
2858
+ const result3 = spawnSyncImpl(executorCommand, [
2859
+ "--no-session",
2860
+ "--no-skills",
2861
+ "--no-context-files",
2862
+ "--no-builtin-tools",
2863
+ "--print",
2864
+ "probe effective tools"
2865
+ ], {
2866
+ cwd: env.AMASTER_RUNTIME_EXECUTION_WORKDIR,
2867
+ env: { ...env, AMASTER_PI_EFFECTIVE_TOOLS_MODE: "probe" },
2868
+ encoding: "utf8",
2869
+ timeout: PI_ATTESTATION_TIMEOUT_MS,
2870
+ killSignal: "SIGKILL",
2871
+ maxBuffer: 1024 * 1024
2872
+ });
2873
+ if (result3.error) {
2874
+ const code = typeof result3.error.code === "string" ? result3.error.code : "UNKNOWN";
2875
+ throw new Error(`pi_managed_mcp_effective_tools_failed: probe error=${code}`);
2876
+ }
2877
+ if (result3.status !== 0) {
2878
+ let receiptError = "receipt unavailable";
2879
+ try {
2880
+ const rejectedReceipt = JSON.parse(readFileSync3(input.receiptPath, "utf8"));
2881
+ if (typeof rejectedReceipt.error === "string" && rejectedReceipt.error.length > 0) {
2882
+ receiptError = rejectedReceipt.error.slice(0, 512);
2883
+ }
2884
+ } catch {
2885
+ }
2886
+ throw new Error(`pi_managed_mcp_effective_tools_failed: probe exit=${result3.status ?? "unknown"} reason=${receiptError}`);
2887
+ }
2888
+ let receipt;
2889
+ try {
2890
+ receipt = JSON.parse(readFileSync3(input.receiptPath, "utf8"));
2891
+ } catch {
2892
+ throw new Error("pi_managed_mcp_effective_tools_failed: probe receipt missing");
2893
+ }
2894
+ if (receipt.status !== "attested" || receipt.mode !== "probe" || receipt.proxyPresent !== false || receipt.effectiveSetHash !== input.effectiveSetHash || receipt.attestorSourceSha256 !== input.attestorSourceSha256 || receipt.configSha256 !== input.configSha256 || receipt.cacheSha256 !== input.cacheSha256) {
2895
+ throw new Error("pi_managed_mcp_effective_tools_failed: probe receipt mismatch");
2896
+ }
2897
+ if (sha256(readFileSync3(input.configPath)) !== input.configSha256) {
2898
+ throw new Error("pi_managed_mcp_effective_tools_failed: config drifted during probe");
2899
+ }
2900
+ if (sha256(readFileSync3(input.cachePath)) !== input.cacheSha256) {
2901
+ throw new Error("pi_managed_mcp_effective_tools_failed: cache drifted during probe");
2902
+ }
2903
+ return {
2904
+ effectiveToolSetHash: receipt.effectiveSetHash,
2905
+ effectiveToolProbeDigest: sha256(stablePiJson(receipt)),
2906
+ effectiveToolProbeAt: receipt.attestedAt,
2907
+ effectiveToolBindings: receipt.effectiveToolBindings
2908
+ };
2909
+ }
2593
2910
  function prepareManagedPiMcpProfile2(input) {
2594
2911
  assertInvocationIsolation2(input);
2595
- const { gateway, gatewayUrl, sessionToken, headers, runId } = validateAuthority2(input);
2912
+ const { gateway, gatewayUrl, sessionToken, headers, runId, mcpToolMode, directCatalog } = validateAuthority2(input);
2596
2913
  const runDir = resolve2(nonEmpty2(input.runDir, "runDir"));
2597
2914
  const executorHome = resolve2(nonEmpty2(input.executorHome, "executorHome"));
2598
2915
  if (!within4(executorHome, join4(runDir, "executors"))) throw new Error("pi_managed_mcp_owner_mismatch: executorHome is outside the managed run");
@@ -2619,24 +2936,82 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
2619
2936
  commandId: input.commandId
2620
2937
  });
2621
2938
  const sourcePiHome = nonEmpty2(input.baseEnv?.PI_CODING_AGENT_DIR ?? input.baseEnv?.PI_AGENT_HOME, "sourcePiHome");
2622
- const seededRuntime = seedPiRuntime(sourcePiHome, piCodingAgentDir, input.sourceAcquisition);
2939
+ const seededRuntime = seedPiRuntime(sourcePiHome, piCodingAgentDir, input.sourceAcquisition, mcpToolMode);
2623
2940
  const restoredNativeSession = restoreManagedPiSessionRollout(input, sessionsRoot, runDir, executorHome, authority);
2624
2941
  const configPath = join4(piCodingAgentDir, "mcp.json");
2942
+ const directToolNames = directCatalog?.tools.map((tool) => tool.exposedName) ?? [];
2943
+ const serverConfig = {
2944
+ type: "http",
2945
+ url: gatewayUrl,
2946
+ headers: { Authorization: `Bearer ${sessionToken}`, ...headers },
2947
+ lifecycle: directCatalog ? "lazy" : "eager",
2948
+ ...directCatalog ? { exposeResources: false, directTools: directToolNames } : {}
2949
+ };
2625
2950
  const config = {
2626
2951
  settings: {
2627
- toolPrefix: "none"
2952
+ toolPrefix: "none",
2953
+ ...directCatalog ? { disableProxyTool: true } : {}
2628
2954
  },
2629
2955
  mcpServers: {
2630
- [SUPPORTED_SERVER_NAME2]: {
2631
- type: "http",
2632
- url: gatewayUrl,
2633
- headers: { Authorization: `Bearer ${sessionToken}`, ...headers },
2634
- lifecycle: "eager"
2635
- }
2956
+ [SUPPORTED_SERVER_NAME2]: serverConfig
2636
2957
  }
2637
2958
  };
2638
2959
  writePrivateFile2(configPath, `${JSON.stringify(config, null, 2)}
2639
2960
  `);
2961
+ let directAttestationInput = null;
2962
+ if (directCatalog) {
2963
+ const cachePath = join4(piCodingAgentDir, "mcp-cache.json");
2964
+ const cache = {
2965
+ version: 1,
2966
+ servers: {
2967
+ [SUPPORTED_SERVER_NAME2]: {
2968
+ configHash: adapterServerConfigHash(serverConfig),
2969
+ tools: directCatalog.tools.map((tool) => ({
2970
+ name: tool.exposedName,
2971
+ description: tool.description,
2972
+ inputSchema: tool.inputSchema
2973
+ })),
2974
+ resources: [],
2975
+ cachedAt: currentTimeMs()
2976
+ }
2977
+ }
2978
+ };
2979
+ writePrivateFile2(cachePath, `${JSON.stringify(cache, null, 2)}
2980
+ `);
2981
+ const cacheSha256 = sha256(readFileSync3(cachePath));
2982
+ const attestorSourceSha256 = sha256(managedPiEffectiveToolsAttestorExtensionSource());
2983
+ const manifestPath = join4(piCodingAgentDir, "effective-tools-manifest.json");
2984
+ const receiptPath = join4(tmp, "effective-tools-receipt.json");
2985
+ const manifest = {
2986
+ schemaVersion: MANAGED_PI_EFFECTIVE_TOOLS_SCHEMA_VERSION,
2987
+ serverName: SUPPORTED_SERVER_NAME2,
2988
+ entries: directCatalog.tools.map((tool) => ({
2989
+ name: tool.exposedName,
2990
+ canonicalName: tool.name,
2991
+ schema: tool.inputSchema,
2992
+ effectiveSchemaHash: tool.effectiveSchemaHash
2993
+ })),
2994
+ effectiveSetHash: stablePiEffectiveToolSetHash(directCatalog.tools.map((tool) => ({
2995
+ name: tool.exposedName,
2996
+ schemaHash: tool.effectiveSchemaHash
2997
+ }))),
2998
+ attestorSourceSha256,
2999
+ configSha256: sha256(readFileSync3(configPath)),
3000
+ cacheSha256
3001
+ };
3002
+ writePrivateFile2(manifestPath, `${JSON.stringify(manifest, null, 2)}
3003
+ `);
3004
+ directAttestationInput = {
3005
+ cachePath,
3006
+ manifestPath,
3007
+ receiptPath,
3008
+ cacheSha256,
3009
+ configPath,
3010
+ configSha256: sha256(readFileSync3(configPath)),
3011
+ attestorSourceSha256,
3012
+ effectiveSetHash: manifest.effectiveSetHash
3013
+ };
3014
+ }
2640
3015
  const env = {
2641
3016
  ...buildIsolatedEnvironment2(input.baseEnv, input.commandEnv),
2642
3017
  HOME: home,
@@ -2647,18 +3022,30 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
2647
3022
  "AMASTER-CLI_CODING_AGENT_SESSION_DIR": sessionsRoot,
2648
3023
  PI_AGENT_MCP_SERVERS_FILE: configPath,
2649
3024
  TMPDIR: tmp,
3025
+ ...directAttestationInput ? {
3026
+ AMASTER_PI_EFFECTIVE_TOOLS_MODE: "enforce",
3027
+ AMASTER_PI_EFFECTIVE_TOOLS_MANIFEST: directAttestationInput.manifestPath,
3028
+ AMASTER_PI_EFFECTIVE_TOOLS_RECEIPT: directAttestationInput.receiptPath,
3029
+ AMASTER_PI_EFFECTIVE_TOOLS_CACHE: directAttestationInput.cachePath,
3030
+ AMASTER_PI_EFFECTIVE_TOOLS_CONFIG: directAttestationInput.configPath
3031
+ } : {},
2650
3032
  ...input.sourceAcquisition ? {
2651
3033
  PI_BROWSER_USE_RUNTIME_READ_POLICY: "required"
2652
3034
  } : {}
2653
3035
  };
2654
3036
  const executorAttestation = attestPi(nonEmpty2(input.executorCommand, "executorCommand"), env, configPath, config);
3037
+ const effectiveToolsAttestation = directAttestationInput ? attestDirectPiTools(nonEmpty2(input.executorCommand, "executorCommand"), env, directAttestationInput) : {};
2655
3038
  const attestationFacts = {
2656
3039
  connectorVersion: nonEmpty2(input.connectorVersion, "connectorVersion"),
2657
3040
  executorKind: "pi",
2658
3041
  ...executorAttestation,
2659
3042
  mcpAdapterVersion: seededRuntime.adapterVersion,
2660
- mcpToolMode: MANAGED_PI_MCP_TOOL_MODE,
2661
- mcpArgsNormalization: MANAGED_PI_MCP_ARGS_NORMALIZATION,
3043
+ mcpToolMode,
3044
+ mcpArgsNormalization: directCatalog ? "none" : MANAGED_PI_MCP_ARGS_NORMALIZATION,
3045
+ ...directCatalog ? {
3046
+ catalogSetHash: directCatalog.setHash,
3047
+ ...effectiveToolsAttestation
3048
+ } : {},
2662
3049
  configMode: "isolated_home_run_scoped_mcp_file",
2663
3050
  namespace: SUPPORTED_SERVER_NAME2,
2664
3051
  schemaVersion: SUPPORTED_SCHEMA_VERSION2,
@@ -2684,7 +3071,7 @@ ${result3.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
2684
3071
  ])],
2685
3072
  attestation: {
2686
3073
  ...attestationFacts,
2687
- attestationId: createHash2("sha256").update(JSON.stringify(attestationFacts)).digest("hex"),
3074
+ attestationId: createHash3("sha256").update(JSON.stringify(attestationFacts)).digest("hex"),
2688
3075
  attestedAt: (/* @__PURE__ */ new Date()).toISOString()
2689
3076
  }
2690
3077
  };
@@ -3505,10 +3892,10 @@ function wikiAccessRuleLine(input) {
3505
3892
  const tools = input.hasGovernedMcp === true && access.tools === true;
3506
3893
  const treePath = readString(access.treePath);
3507
3894
  if (tools && treePath) {
3508
- return `- Company wiki access in this run: the governed tools wiki_search / wiki_read_page / wiki_list_pages via the amaster MCP, and the wiki tree at ${treePath} (read wiki/index.md there first).`;
3895
+ return `- Company wiki access in this run: the governed tools wiki_search / wiki_read_page / wiki_list_pages / wiki_read_source / wiki_write_page via the amaster MCP, and the wiki tree at ${treePath} (read wiki/index.md there first).`;
3509
3896
  }
3510
3897
  if (tools) {
3511
- return "- Company wiki access in this run: the governed tools wiki_search / wiki_read_page / wiki_list_pages via the amaster MCP. Use them for targeted lookup before re-deriving knowledge the company already holds.";
3898
+ return "- Company wiki access in this run: the governed tools wiki_search / wiki_read_page / wiki_list_pages / wiki_read_source / wiki_write_page via the amaster MCP. Use them for governed lookup and durable Wiki updates; Company Knowledge operations must use the exact operationId and sourceRefs named by the issue.";
3512
3899
  }
3513
3900
  if (treePath) {
3514
3901
  return `- Company wiki access in this run: the wiki tree at ${treePath}. Read wiki/index.md first (every page listed with a one-line summary), then open the specific pages you need; wiki_* tools are not available in this run.`;
@@ -3606,6 +3993,13 @@ function continuationRuntimeActionEnvelope(context) {
3606
3993
  if (!readString(envelope.schemaVersion) || !readString(envelope.idempotencyKey) || action.type !== "update_parent" || action.status !== "todo" || !readString(action.comment)) return null;
3607
3994
  return envelope;
3608
3995
  }
3996
+ function managedDirectToolName(input, canonicalName) {
3997
+ if (input.managedMcpToolMode !== "direct_typed") return null;
3998
+ const catalog = asRecord(input.managedMcpToolCatalog);
3999
+ const tools = Array.isArray(catalog.tools) ? catalog.tools.map(asRecord) : [];
4000
+ const match = tools.find((tool) => readString(tool.name) === canonicalName);
4001
+ return readString(match?.exposedName) ?? null;
4002
+ }
3609
4003
  function runtimeActionContinuationOptionText(input) {
3610
4004
  if (!isRecoveryWakeReason(input.wakeReason)) return "";
3611
4005
  const heading = "### Runtime Action Continuation Option";
@@ -3619,6 +4013,20 @@ Runtime Action continuation is unavailable: managed governed MCP capability is m
3619
4013
  Runtime Action continuation is unavailable: continuationRuntimeActionEnvelope is missing or invalid. Do not guess a tool call.`;
3620
4014
  }
3621
4015
  if (input.executorKind === "pi") {
4016
+ if (input.managedMcpToolMode === "direct_typed") {
4017
+ const toolName = managedDirectToolName(input, "runtime_action.submit");
4018
+ if (!toolName) {
4019
+ return `${heading}
4020
+ Runtime Action continuation is unavailable: the run catalog does not advertise the required typed submit tool. Do not guess a tool call.`;
4021
+ }
4022
+ return [
4023
+ heading,
4024
+ `Only after selecting continuation/todo from the disposition menu, emit an actual \`${toolName}\` typed tool call with the exact object arguments below. Do not print this JSON as prose.`,
4025
+ "```json",
4026
+ jsonText(envelope),
4027
+ "```"
4028
+ ].join("\n");
4029
+ }
3622
4030
  if (input.managedMcpToolMode !== "proxy_only") {
3623
4031
  return `${heading}
3624
4032
  Runtime Action continuation is unavailable: managed Pi MCP tool mode is not proxy_only. Do not guess a proxy or direct-tool call.`;
@@ -3839,6 +4247,19 @@ function piMcpProxyExamplesText(input) {
3839
4247
  `- read document: ${proxy("amaster.read_issue_document", { issueId: "AM-123", key: "plan" })}`
3840
4248
  ].join("\n");
3841
4249
  }
4250
+ function piDirectTypedToolsText(input) {
4251
+ if (!input.hasGovernedMcp || input.executorKind !== "pi" || input.managedMcpToolMode !== "direct_typed") return "";
4252
+ const catalog = asRecord(input.managedMcpToolCatalog);
4253
+ const tools = (Array.isArray(catalog.tools) ? catalog.tools : []).map(asRecord).map((tool) => ({ name: readString(tool.exposedName), description: readString(tool.description) })).filter((tool) => tool.name);
4254
+ if (tools.length === 0) {
4255
+ return "Direct typed governed tools are unavailable because the run catalog snapshot is empty. Do not guess a proxy or tool name.";
4256
+ }
4257
+ return [
4258
+ "This run uses the attested direct typed Governed MCP surface below. Call these exact names with object arguments; do not call the `mcp` proxy and do not stringify an inner argument envelope.",
4259
+ ...tools.map((tool) => `- ${tool.name}${tool.description ? `: ${tool.description}` : ""}`),
4260
+ "A tool not listed above is unavailable in this run. Do not infer a namespace or fall back to REST/bare MCP."
4261
+ ].join("\n");
4262
+ }
3842
4263
  function sectionText(section) {
3843
4264
  if (!section.content) return "";
3844
4265
  return section.title ? `## ${section.title}
@@ -3945,10 +4366,14 @@ function compileCommandPromptWithManifest(input, options = {}) {
3945
4366
  resolvedDependencies.details.content ? `Auxiliary predecessor context (may be truncated):
3946
4367
  ${resolvedDependencies.details.content}` : ""
3947
4368
  ].filter(Boolean).join("\n\n") : "";
3948
- const piMcpProxyExamples = resolvedDependencies.required.content ? "" : piMcpProxyExamplesText(input);
4369
+ const piMcpProxyExamples = resolvedDependencies.required.content ? "" : [piMcpProxyExamplesText(input), piDirectTypedToolsText(input)].filter(Boolean).join("\n");
3949
4370
  const deliveryReadinessContent = runtimeDeliveryReadinessText(context, input);
3950
4371
  const rawSections = [
3951
- { name: "runtime_rules", title: "", priority: 100, sourceRef: `command:${input.commandId}`, content: fixedRules(input, !hasTask) },
4372
+ { name: "recovery_instruction", title: "Recovery Instruction", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: completeRecoveryInstruction, truncationReason: completeRecoveryInstruction ? null : "mode_selection" },
4373
+ { name: "approval_continuation", title: "Approved Runtime Action Continuation", priority: 99, sourceRef: `run:${input.runId ?? "unknown"}`, content: approvalContinuationText(input), truncationReason: mode === "continuation" ? null : "mode_selection" },
4374
+ { name: "wake_comments", title: wakeDeltaTitle, priority: interactionResolution ? 99 : 95, sourceRef: wakeDeltaSourceRefs, originalContent: wakeDeltaOriginal, content: wakeDeltaContent, truncationReason: commentsSelected ? null : "duplicate_task_context" },
4375
+ { name: "task", title: "Task Context", priority: 90, sourceRef: `issue:${input.issueId ?? "unknown"}`, originalContent: [taskText, taskCommentRefGuidance(input)].filter(Boolean).join("\n"), content: includeTask ? [taskText, taskCommentRefGuidance(input)].filter(Boolean).join("\n") : "", truncationReason: includeTask ? null : "mode_selection" },
4376
+ { name: "continuation_summary", title: "Continuation Summary", priority: 97, sourceRef: readString(asRecord(context.paperclipContinuationSummary).key) ?? `issue:${input.issueId ?? "unknown"}`, observedAt: readString(asRecord(context.paperclipContinuationSummary).updatedAt), originalContent: continuationSummary, content: mode === "cold" ? "" : continuationSummary, truncationReason: mode === "cold" ? "mode_selection" : null },
3952
4377
  ...resolvedDependencyContent ? [{
3953
4378
  name: "resolved_dependencies",
3954
4379
  title: "Resolved Dependency Outputs",
@@ -3957,16 +4382,12 @@ ${resolvedDependencies.details.content}` : ""
3957
4382
  content: resolvedDependencyContent,
3958
4383
  mandatoryContent: resolvedDependencies.required.content
3959
4384
  }] : [],
3960
- { name: "recovery_instruction", title: "Recovery Instruction", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: completeRecoveryInstruction, truncationReason: completeRecoveryInstruction ? null : "mode_selection" },
3961
- { name: "approval_continuation", title: "Approved Runtime Action Continuation", priority: 99, sourceRef: `run:${input.runId ?? "unknown"}`, content: approvalContinuationText(input), truncationReason: mode === "continuation" ? null : "mode_selection" },
4385
+ ...deliveryReadinessContent ? [{ name: "runtime_delivery_readiness", title: "Current Delivery Readiness", priority: 99, sourceRef: `issue:${input.issueId ?? "unknown"}:delivery`, content: deliveryReadinessContent }] : [],
4386
+ { name: "runtime_rules", title: "", priority: 100, sourceRef: `command:${input.commandId}`, content: fixedRules(input, !hasTask) },
3962
4387
  { name: "runtime_authorization", title: "Runtime Action Contract", priority: 98, sourceRef: `run:${input.runId ?? "unknown"}`, content: runtimeAuthorizationText(context, mode, { suppressOrdinaryCompletionContract }) },
3963
4388
  { name: "runtime_decomposition_requirement", title: "Required Task Decomposition", priority: 98, sourceRef: `issue:${input.issueId ?? "unknown"}`, content: runtimeDecompositionRequirementText(context) },
3964
- ...deliveryReadinessContent ? [{ name: "runtime_delivery_readiness", title: "Current Delivery Readiness", priority: 99, sourceRef: `issue:${input.issueId ?? "unknown"}:delivery`, content: deliveryReadinessContent }] : [],
3965
- ...piMcpProxyExamples ? [{ name: "pi_mcp_proxy_examples", title: "Pi MCP Proxy Examples", priority: 96, sourceRef: "amaster_governed_mcp_proxy_contract", content: piMcpProxyExamples }] : [],
3966
- { name: "continuation_summary", title: "Continuation Summary", priority: 97, sourceRef: readString(asRecord(context.paperclipContinuationSummary).key) ?? `issue:${input.issueId ?? "unknown"}`, observedAt: readString(asRecord(context.paperclipContinuationSummary).updatedAt), originalContent: continuationSummary, content: mode === "cold" ? "" : continuationSummary, truncationReason: mode === "cold" ? "mode_selection" : null },
3967
4389
  ...verifiedCompanyContext.content ? [{ name: "verified_company_context", title: "Verified Company Context", priority: 96, sourceRef: verifiedCompanyContext.sourceRef, observedAt: verifiedCompanyContext.observedAt, freshness: { kind: "run_snapshot" }, content: verifiedCompanyContext.content }] : [],
3968
- { name: "wake_comments", title: wakeDeltaTitle, priority: interactionResolution ? 99 : 95, sourceRef: wakeDeltaSourceRefs, originalContent: wakeDeltaOriginal, content: wakeDeltaContent, truncationReason: commentsSelected ? null : "duplicate_task_context" },
3969
- { name: "task", title: "Task Context", priority: 90, sourceRef: `issue:${input.issueId ?? "unknown"}`, originalContent: [taskText, taskCommentRefGuidance(input)].filter(Boolean).join("\n"), content: includeTask ? [taskText, taskCommentRefGuidance(input)].filter(Boolean).join("\n") : "", truncationReason: includeTask ? null : "mode_selection" },
4390
+ ...piMcpProxyExamples ? [{ name: "pi_mcp_proxy_examples", title: "Pi MCP Proxy Examples", priority: 96, sourceRef: "amaster_governed_mcp_proxy_contract", content: piMcpProxyExamples }] : [],
3970
4391
  { name: "governed_reads", title: "Governed External Reads", priority: 88, sourceRef: governedReads.provenance.map((entry) => entry.sourceRef), observedAt: governedReads.provenance.map((entry) => entry.observedAt), freshness: governedReads.provenance.map((entry) => entry.freshness), scope: governedReads.provenance.map((entry) => entry.scope), content: governedReads.content },
3971
4392
  { name: "agent_instructions", title: "Agent Instructions", priority: 100, sourceRef: "agent_instructions_bundle", content: readString(input.agentInstructions) ?? "" },
3972
4393
  { name: "attachments", title: "Materialized Inputs", priority: 80, sourceRef: "materialized_attachments", content: readString(input.attachmentsText) ?? "" },
@@ -5830,7 +6251,7 @@ var postJsonWithRetry = postRuntimeConnectorJsonWithRetry;
5830
6251
  var bestEffortPostJson = bestEffortPostRuntimeConnectorJson;
5831
6252
 
5832
6253
  // src/amaster-runtime-daemon/runtime-artifact-upload.mjs
5833
- import { createHash as createHash3 } from "node:crypto";
6254
+ import { createHash as createHash4 } from "node:crypto";
5834
6255
  import { lstatSync as lstatSync3, readFileSync as readFileSync6, realpathSync as realpathSync3 } from "node:fs";
5835
6256
  import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve3 } from "node:path";
5836
6257
  var SHA256_PATTERN = /^[a-f0-9]{64}$/;
@@ -5873,7 +6294,7 @@ function prepareRuntimeArtifactUploads(cwd, mcpToolResults) {
5873
6294
  throw new Error(`Runtime Artifact ${intentId} source is not an owned regular file`);
5874
6295
  }
5875
6296
  const body = readFileSync6(sourcePath);
5876
- const actualSha256 = createHash3("sha256").update(body).digest("hex");
6297
+ const actualSha256 = createHash4("sha256").update(body).digest("hex");
5877
6298
  if (body.length !== expectedByteSize || actualSha256 !== expectedSha256) {
5878
6299
  throw new Error(`Runtime Artifact ${intentId} bytes do not match the governed ownership manifest`);
5879
6300
  }
@@ -5963,7 +6384,7 @@ function createRuntimeArtifactIngestQueue({ ingest, onError }) {
5963
6384
  }
5964
6385
 
5965
6386
  // src/amaster-runtime-daemon/workspace-guard.mjs
5966
- import { createHash as createHash4 } from "node:crypto";
6387
+ import { createHash as createHash5 } from "node:crypto";
5967
6388
  import { existsSync as existsSync7, mkdirSync as mkdirSync6, realpathSync as realpathSync4, statSync as statSync3 } from "node:fs";
5968
6389
  import { basename as basename4, join as join8, isAbsolute as isAbsolute4, relative as relative4, resolve as resolve4 } from "node:path";
5969
6390
 
@@ -6074,7 +6495,7 @@ function resolveWorkspaceCwd(config, command) {
6074
6495
  return cwd;
6075
6496
  }
6076
6497
  function shortHash(value, length = 12) {
6077
- return createHash4("sha256").update(String(value)).digest("hex").slice(0, length);
6498
+ return createHash5("sha256").update(String(value)).digest("hex").slice(0, length);
6078
6499
  }
6079
6500
  function safeSegment(value, fallback) {
6080
6501
  const raw = String(value ?? "").trim();
@@ -6506,7 +6927,7 @@ function summarizeAmasterRuntimeVersionDrift(input = {}) {
6506
6927
  }
6507
6928
 
6508
6929
  // src/amaster-runtime-daemon/pi-child-isolation.mjs
6509
- import { createHash as createHash5 } from "node:crypto";
6930
+ import { createHash as createHash6 } from "node:crypto";
6510
6931
  import {
6511
6932
  chmodSync as chmodSync3,
6512
6933
  chownSync,
@@ -6517,7 +6938,7 @@ import {
6517
6938
  import { resolve as resolve7, sep } from "node:path";
6518
6939
  var defaultFs = { chmodSync: chmodSync3, chownSync, lchownSync, lstatSync: lstatSync4, readdirSync: readdirSync6 };
6519
6940
  function defaultHashRunId(runId) {
6520
- return Number.parseInt(createHash5("sha256").update(runId).digest("hex").slice(0, 8), 16);
6941
+ return Number.parseInt(createHash6("sha256").update(runId).digest("hex").slice(0, 8), 16);
6521
6942
  }
6522
6943
  function positiveInteger(value, label) {
6523
6944
  if (!Number.isSafeInteger(value) || value <= 0) {
@@ -6641,7 +7062,7 @@ function preparePiChildIsolation(input) {
6641
7062
  }
6642
7063
 
6643
7064
  // src/amaster-runtime-daemon/pi-company-memory.mjs
6644
- import { createHash as createHash6 } from "node:crypto";
7065
+ import { createHash as createHash7 } from "node:crypto";
6645
7066
  import {
6646
7067
  chmodSync as chmodSync4,
6647
7068
  chownSync as chownSync2,
@@ -6727,7 +7148,7 @@ function safeCompanyPiHomeSegment(companyId) {
6727
7148
  const raw = requiredString2(companyId, "companyId");
6728
7149
  if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,119}$/.test(raw)) return raw;
6729
7150
  const normalized = raw.replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "").slice(0, 80);
6730
- const hash = createHash6("sha256").update(raw).digest("hex").slice(0, 12);
7151
+ const hash = createHash7("sha256").update(raw).digest("hex").slice(0, 12);
6731
7152
  return normalized ? `${normalized}-${hash}` : `company-${hash}`;
6732
7153
  }
6733
7154
  function ensureMemoryRoot(root, fs) {
@@ -6766,7 +7187,7 @@ function allocateCompanyGid(root, companyId, input, fs) {
6766
7187
  if (groups[companyId]) return groups[companyId];
6767
7188
  const used = new Set(Object.values(groups));
6768
7189
  const initialOffset = Number.parseInt(
6769
- createHash6("sha256").update(companyId).digest("hex").slice(0, 12),
7190
+ createHash7("sha256").update(companyId).digest("hex").slice(0, 12),
6770
7191
  16
6771
7192
  ) % gidSpan;
6772
7193
  let gid = null;
@@ -6868,7 +7289,7 @@ function prepareCompanyPiMemory(input, fs = defaultFs2) {
6868
7289
  }
6869
7290
 
6870
7291
  // src/amaster-runtime-daemon/pi-trusted-runtime-profile.mjs
6871
- import { createHash as createHash7 } from "node:crypto";
7292
+ import { createHash as createHash8 } from "node:crypto";
6872
7293
  import {
6873
7294
  chmodSync as chmodSync5,
6874
7295
  copyFileSync as copyFileSync2,
@@ -6886,6 +7307,8 @@ var ASSERTION_VERSION = "2026-07-25.v1";
6886
7307
  var SHA256 = /^[a-f0-9]{64}$/;
6887
7308
  var COPY_ENTRIES = ["SYSTEM.md", "policy", "skills", "agents", "bundles", "extensions"];
6888
7309
  var JSON_ENTRIES = ["settings.json", "models.json"];
7310
+ var ROLE_SKILLS_DIR = "role-skills";
7311
+ var DISABLE_MODEL_INVOCATION_LINE = /^[ \t]*disable-model-invocation:[ \t]*true[ \t]*\r?$/m;
6889
7312
  var SECRET_KEY = /(authorization|cookie|api[_-]?key|password|secret|token)$/i;
6890
7313
  var SECRET_VALUE = /(?:authorization|cookie|api[_-]?key|password|secret|token)\s*[:=]\s*(?:bearer\s+)?[^\s"',;]+|bearer\s+[^\s"',;]+/i;
6891
7314
  var MAX_AUDIT_BYTES = 1024 * 1024;
@@ -6906,7 +7329,7 @@ function sha256File(path, label) {
6906
7329
  if (!stat.isFile() || stat.isSymbolicLink()) {
6907
7330
  throw new Error(`pi_trusted_runtime_source_unsafe:${label}`);
6908
7331
  }
6909
- return createHash7("sha256").update(readFileSync9(path)).digest("hex");
7332
+ return createHash8("sha256").update(readFileSync9(path)).digest("hex");
6910
7333
  }
6911
7334
  function verifyDeclaredFiles(manifest, root, label, ignoredPaths = [], enforceComplete = true) {
6912
7335
  if (!Array.isArray(manifest.files) || manifest.files.length === 0) {
@@ -7004,6 +7427,53 @@ function copyTreeNoLinks(source, target) {
7004
7427
  copyFileSync2(source, target);
7005
7428
  chmodSync5(target, 384 | stat.mode & 73);
7006
7429
  }
7430
+ var SKILL_PROFILE_NAME = /^[a-z0-9-]+$/;
7431
+ function readSkillProfile(seedRoot, skillProfile) {
7432
+ const agentsRoot = resolve9(seedRoot, "agents");
7433
+ const agentFile = resolve9(agentsRoot, `${skillProfile}.md`);
7434
+ if (!SKILL_PROFILE_NAME.test(skillProfile) || !within3(agentFile, agentsRoot) || !existsSync11(agentFile)) {
7435
+ throw new Error(`pi_trusted_runtime_skill_profile_unknown:${skillProfile}`);
7436
+ }
7437
+ const declared = readFileSync9(agentFile, "utf8").match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1].match(/^skills:\s*(.+)$/m)?.[1].split(",").map((entry) => entry.trim()).filter(Boolean) ?? [];
7438
+ const bundlesRoot = resolve9(seedRoot, "bundles");
7439
+ const profile = [];
7440
+ for (const name of declared) {
7441
+ let source = join12(bundlesRoot, skillProfile, "skills", name);
7442
+ if (!existsSync11(join12(source, "SKILL.md"))) {
7443
+ const candidates = [];
7444
+ for (const category of readdirSync7(bundlesRoot).sort()) {
7445
+ if (category === skillProfile) continue;
7446
+ const candidate = join12(bundlesRoot, category, "skills", name);
7447
+ if (existsSync11(join12(candidate, "SKILL.md"))) candidates.push(candidate);
7448
+ }
7449
+ if (candidates.length > 1) {
7450
+ throw new Error(`pi_trusted_runtime_skill_profile_ambiguous:${skillProfile}:${name}`);
7451
+ }
7452
+ source = candidates[0];
7453
+ }
7454
+ if (source) profile.push({ name, source });
7455
+ }
7456
+ if (profile.length === 0) {
7457
+ throw new Error(`pi_trusted_runtime_skill_profile_unknown:${skillProfile}`);
7458
+ }
7459
+ return profile;
7460
+ }
7461
+ function materializeRoleSkills(seedRoot, agentDir, skillProfile) {
7462
+ const profile = readSkillProfile(seedRoot, skillProfile);
7463
+ const bundlesRoot = resolve9(seedRoot, "bundles");
7464
+ const enabled = [];
7465
+ for (const entry of profile) {
7466
+ const target = join12(agentDir, ROLE_SKILLS_DIR, entry.name);
7467
+ rmSync6(target, { recursive: true, force: true });
7468
+ copyTreeNoLinks(entry.source, target);
7469
+ const skillFile = join12(target, "SKILL.md");
7470
+ writeFileSync8(skillFile, readFileSync9(skillFile, "utf8").replace(DISABLE_MODEL_INVOCATION_LINE, ""), {
7471
+ mode: 384
7472
+ });
7473
+ enabled.push({ name: entry.name, path: relative6(bundlesRoot, entry.source).split("\\").join("/") });
7474
+ }
7475
+ return enabled;
7476
+ }
7007
7477
  function mergeMcp(seedRoot, overlayRoot, governedConfig) {
7008
7478
  const seed = record5(readJsonFile2(join12(seedRoot, "mcp.json"), "seed_mcp", { mcpServers: {} }));
7009
7479
  const overlay = record5(readJsonFile2(join12(overlayRoot, "mcp.json"), "overlay_mcp", { mcpServers: {} }));
@@ -7068,6 +7538,8 @@ function materializeTrustedPiRuntimeProfile(input) {
7068
7538
  if (existsSync11(source)) copyTreeNoLinks(source, target);
7069
7539
  }
7070
7540
  }
7541
+ const skillProfile = typeof input.skillProfile === "string" && input.skillProfile.trim() ? input.skillProfile.trim() : null;
7542
+ const enabledSkills = skillProfile ? materializeRoleSkills(seedRoot, agentDir, skillProfile) : [];
7071
7543
  const mergedJson = {};
7072
7544
  for (const entry of JSON_ENTRIES) {
7073
7545
  const seed = readJsonFile2(join12(seedRoot, entry), `seed_${entry}`, {});
@@ -7082,6 +7554,13 @@ function materializeTrustedPiRuntimeProfile(input) {
7082
7554
  allowSessionGrants: false
7083
7555
  }
7084
7556
  };
7557
+ if (skillProfile) {
7558
+ const current = Array.isArray(merged.skills) ? merged.skills : [];
7559
+ merged.skills = [
7560
+ ROLE_SKILLS_DIR,
7561
+ ...current.filter((value) => value !== ROLE_SKILLS_DIR)
7562
+ ];
7563
+ }
7085
7564
  }
7086
7565
  assertNoPersistentSecrets(merged, [entry]);
7087
7566
  writeFileSync8(join12(agentDir, entry), `${JSON.stringify(merged, null, 2)}
@@ -7113,11 +7592,17 @@ function materializeTrustedPiRuntimeProfile(input) {
7113
7592
  runtimeEnforcementDigest: input.verifiedAssertion.digests.runtimeEnforcementDigest,
7114
7593
  unknownToolMode: input.verifiedAssertion.unknownToolMode,
7115
7594
  directToolBudget: input.verifiedAssertion.directToolBudget,
7116
- inheritedEntries: [...COPY_ENTRIES, ...JSON_ENTRIES, "mcp.json", "npm"]
7595
+ inheritedEntries: [...COPY_ENTRIES, ...JSON_ENTRIES, "mcp.json", "npm"],
7596
+ // What the model can actually see this run: which profile and which exact
7597
+ // bundle skills were enabled. Absent profile => main skills only.
7598
+ ...skillProfile ? {
7599
+ skillProfile,
7600
+ enabledSkillsDigest: createHash8("sha256").update(JSON.stringify(enabledSkills)).digest("hex")
7601
+ } : {}
7117
7602
  };
7118
7603
  return {
7119
7604
  facts,
7120
- attestationId: createHash7("sha256").update(JSON.stringify(facts)).digest("hex")
7605
+ attestationId: createHash8("sha256").update(JSON.stringify(facts)).digest("hex")
7121
7606
  };
7122
7607
  }
7123
7608
  function assertAuditArgsRedacted(value) {
@@ -7313,7 +7798,7 @@ function verifyTrustedPiRuntimeAssertion(input) {
7313
7798
  if (hasSourceAssertion) {
7314
7799
  const exactTools = Array.isArray(record5(sourceProfile.tools).exactAllowlist) ? record5(sourceProfile.tools).exactAllowlist : [];
7315
7800
  const exactActions = Array.isArray(record5(sourceProfile.actions).exactAllowlist) ? record5(sourceProfile.actions).exactAllowlist : [];
7316
- const profileHash = createHash7("sha256").update(JSON.stringify(sourceProfile)).digest("hex");
7801
+ const profileHash = createHash8("sha256").update(JSON.stringify(sourceProfile)).digest("hex");
7317
7802
  if (assertion.unknownToolMode !== "deny" || maxCalls !== 0 || sourceAssertion.profileVersion !== sourceProfile.purpose || sourceAssertion.profileHash !== profileHash || sourceAssertion.retentionVersion !== sourceProfile.retention || JSON.stringify(sourceAssertion.exactTools) !== JSON.stringify(exactTools) || JSON.stringify(sourceAssertion.exactActions) !== JSON.stringify(exactActions) || sourceAssertion.sourceId !== sourceProfile.sourceId || sourceAssertion.sourceRevisionId !== sourceProfile.sourceRevisionId || sourceAssertion.sourceRevision !== sourceProfile.sourceRevision || sourceAssertion.attemptId !== sourceProfile.attemptId || sourceAssertion.epoch !== sourceProfile.epoch) {
7318
7803
  throw new Error("pi_trusted_runtime_assertion_binding_mismatch:sourceAcquisition");
7319
7804
  }
@@ -7342,7 +7827,7 @@ function verifyTrustedPiRuntimeAssertion(input) {
7342
7827
 
7343
7828
  // src/amaster-runtime-daemon/workspace-status.mjs
7344
7829
  import { spawnSync as spawnSync4 } from "node:child_process";
7345
- import { createHash as createHash8 } from "node:crypto";
7830
+ import { createHash as createHash9 } from "node:crypto";
7346
7831
  import { existsSync as existsSync12, readdirSync as readdirSync8, readFileSync as readFileSync10, statSync as statSync6 } from "node:fs";
7347
7832
  import { basename as basename5, extname, isAbsolute as isAbsolute7, join as join13, relative as relative7, resolve as resolve10 } from "node:path";
7348
7833
  var WORKSPACE_RUNTIME_SERVICES_FILENAME = ".amaster-runtime-services.json";
@@ -7414,7 +7899,7 @@ function sanitizeTrackedChange(line) {
7414
7899
  return isSafeRelativePath(path) ? line : null;
7415
7900
  }
7416
7901
  function sha256File2(filePath) {
7417
- return createHash8("sha256").update(readFileSync10(filePath)).digest("hex");
7902
+ return createHash9("sha256").update(readFileSync10(filePath)).digest("hex");
7418
7903
  }
7419
7904
  function artifactHashCacheKey(relativePath, stat) {
7420
7905
  return `${relativePath}\0${stat.size}\0${stat.mtimeMs}`;
@@ -7615,7 +8100,7 @@ function readWorkspaceStatus(cwd, opts = {}) {
7615
8100
  }
7616
8101
 
7617
8102
  // src/amaster-runtime-daemon/pi-browser-session-adapter.mjs
7618
- import { createHash as createHash9 } from "node:crypto";
8103
+ import { createHash as createHash10 } from "node:crypto";
7619
8104
  import { spawn, spawnSync as spawnSync5 } from "node:child_process";
7620
8105
  import { existsSync as existsSync13 } from "node:fs";
7621
8106
  import {
@@ -7738,7 +8223,7 @@ function fail(code) {
7738
8223
  throw Object.assign(new Error(code), { code });
7739
8224
  }
7740
8225
  function profileName(identity2) {
7741
- return createHash9("sha256").update(`${identity2.companyId}\0${identity2.bindingId}\0${identity2.localOpaqueRef}`).digest("hex");
8226
+ return createHash10("sha256").update(`${identity2.companyId}\0${identity2.bindingId}\0${identity2.localOpaqueRef}`).digest("hex");
7742
8227
  }
7743
8228
  function expectedMarker(identity2) {
7744
8229
  return {
@@ -8137,7 +8622,7 @@ async function executeBrowserSessionCommand(command, dependencies = {}) {
8137
8622
  }
8138
8623
 
8139
8624
  // src/amaster-runtime-daemon/source-acquisition-invocation.mjs
8140
- import { createHash as createHash10 } from "node:crypto";
8625
+ import { createHash as createHash11 } from "node:crypto";
8141
8626
  var SOURCE_ACQUISITION_PUBLIC_TOOLS = Object.freeze([
8142
8627
  "source_open",
8143
8628
  "source_snapshot",
@@ -8174,7 +8659,7 @@ function serializeSourceAcquisitionProfile(profile) {
8174
8659
  const input = Buffer.from(JSON.stringify(profile), "utf8");
8175
8660
  return {
8176
8661
  input,
8177
- sha256: createHash10("sha256").update(input).digest("hex")
8662
+ sha256: createHash11("sha256").update(input).digest("hex")
8178
8663
  };
8179
8664
  }
8180
8665
  function sourceAcquisitionManagedInputs(options) {
@@ -8210,7 +8695,7 @@ function assertSourceAcquisitionRuntimeAuthority({
8210
8695
  }
8211
8696
 
8212
8697
  // src/amaster-runtime-daemon.mjs
8213
- var CONNECTOR_VERSION = "0.1.1-beta.2";
8698
+ var CONNECTOR_VERSION = "0.1.1-beta.4";
8214
8699
  var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
8215
8700
  var SOURCE_ACQUISITION_CAPABILITY = "source_acquisition_v1";
8216
8701
  var SOURCE_ACQUISITION_PROFILE_VERSION = "source_acquisition_v1";
@@ -8934,9 +9419,7 @@ function readPiAgentLocalPlatformCredential(credentialsDir) {
8934
9419
  return {
8935
9420
  organizationId,
8936
9421
  apiKey,
8937
- ...readString(credential.baseUrl) ? { baseUrl: readString(credential.baseUrl) } : {},
8938
- ...readString(credential.defaultModel) ? { defaultModel: readString(credential.defaultModel) } : {},
8939
- ...readString(credential.flashModel) ? { flashModel: readString(credential.flashModel) } : {}
9422
+ ...readString(credential.baseUrl) ? { baseUrl: readString(credential.baseUrl) } : {}
8940
9423
  };
8941
9424
  }
8942
9425
  function piAgentLocalPlatformCredentials(config) {
@@ -9509,7 +9992,7 @@ function sourceAcquisitionRuntimeProfile(config, command) {
9509
9992
  if (!companyId || !bindingId || !/^profile_[a-z0-9]{16,64}$/i.test(localOpaqueRef ?? "")) {
9510
9993
  throw new Error("source_acquisition_profile_invalid");
9511
9994
  }
9512
- const profileName2 = createHash11("sha256").update(`${companyId}\0${bindingId}\0${localOpaqueRef}`).digest("hex");
9995
+ const profileName2 = createHash12("sha256").update(`${companyId}\0${bindingId}\0${localOpaqueRef}`).digest("hex");
9513
9996
  const stateRoot = resolve12(config.browserSessionStateRoot);
9514
9997
  const userDataDir = resolve12(stateRoot, profileName2);
9515
9998
  if (!pathWithin2(userDataDir, stateRoot)) throw new Error("source_acquisition_browser_profile_invalid");
@@ -9557,9 +10040,7 @@ async function syncPiExecutorProviderConfig(config, command, agentDir, resolvedP
9557
10040
  modelsSynced,
9558
10041
  settingsSynced,
9559
10042
  credentialSource,
9560
- providerBaseUrlConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_BASE_URL)),
9561
- defaultModelConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_DEFAULT_MODEL)),
9562
- flashModelConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_FLASH_MODEL))
10043
+ providerBaseUrlConfigured: Boolean(readString(providerConfig.AMASTER_PROVIDER_BASE_URL))
9563
10044
  });
9564
10045
  }
9565
10046
  }
@@ -9573,9 +10054,7 @@ function piAgentLocalPlatformCredentialForCommand(config, command) {
9573
10054
  if (!credential) return null;
9574
10055
  return {
9575
10056
  AMASTER_API_KEY: credential.apiKey,
9576
- ...credential.baseUrl ? { AMASTER_PROVIDER_BASE_URL: credential.baseUrl } : {},
9577
- ...credential.defaultModel ? { AMASTER_PROVIDER_DEFAULT_MODEL: credential.defaultModel } : {},
9578
- ...credential.flashModel ? { AMASTER_PROVIDER_FLASH_MODEL: credential.flashModel } : {}
10057
+ ...credential.baseUrl ? { AMASTER_PROVIDER_BASE_URL: credential.baseUrl } : {}
9579
10058
  };
9580
10059
  }
9581
10060
  function normalizeWorkspaceContext(workspace) {
@@ -9710,6 +10189,7 @@ function buildCommandPrompt(command, workspace, materializedAttachments = [], op
9710
10189
  hasGovernedMcp,
9711
10190
  executorKind: options.executorKind,
9712
10191
  managedMcpToolMode: options.managedMcpToolMode,
10192
+ managedMcpToolCatalog: options.managedMcpToolCatalog,
9713
10193
  agentInstructions,
9714
10194
  taskMarkdown,
9715
10195
  attachmentsText,
@@ -12242,7 +12722,7 @@ async function materializeIssueAttachments(config, command, workspace) {
12242
12722
  const body = await runtimeApiBuffer(runtimeAuth, contentPath);
12243
12723
  writeFileSync9(targetPath, body);
12244
12724
  const attachmentId = readString(attachment.id);
12245
- const actualSha256 = createHash11("sha256").update(body).digest("hex");
12725
+ const actualSha256 = createHash12("sha256").update(body).digest("hex");
12246
12726
  const lineageCandidates = lineageCandidatesByAttachmentId.get(attachmentId) ?? [];
12247
12727
  const lineage = selectAttachmentLineage(lineageCandidates, actualSha256);
12248
12728
  if (lineageCandidates.length > 0 && !lineage) {
@@ -12334,7 +12814,7 @@ async function materializeRequiredArtifactInputs(config, command, workspace) {
12334
12814
  throw new Error(`artifact_input_manifest_invalid: entry ${index} contentPath does not match attachmentId`);
12335
12815
  }
12336
12816
  const body = await runtimeApiBuffer(runtimeAuth, contentPath);
12337
- const actualSha256 = createHash11("sha256").update(body).digest("hex");
12817
+ const actualSha256 = createHash12("sha256").update(body).digest("hex");
12338
12818
  if (body.byteLength !== byteSize || actualSha256 !== sha256) {
12339
12819
  throw new Error(
12340
12820
  `artifact_input_integrity_mismatch: workProductId=${workProductId} expectedBytes=${byteSize} actualBytes=${body.byteLength} expectedSha256=${sha256} actualSha256=${actualSha256}`
@@ -12404,7 +12884,7 @@ function safeCheckpointRelativePath(rawPath) {
12404
12884
  return normalized;
12405
12885
  }
12406
12886
  function hashFileSha256(filePath) {
12407
- return createHash11("sha256").update(readFileSync11(filePath)).digest("hex");
12887
+ return createHash12("sha256").update(readFileSync11(filePath)).digest("hex");
12408
12888
  }
12409
12889
  async function materializeIssueCheckpoint(config, command, workspace) {
12410
12890
  const checkpointDir = issueCheckpointDir(workspace);
@@ -12590,7 +13070,8 @@ async function executeRunCommand(config, command) {
12590
13070
  await ingestWorkspaceStatus(config, command, cwd);
12591
13071
  const promptCompilation = buildCommandPrompt(command, workspace, materializedAttachments, {
12592
13072
  executorKind: executor.kind,
12593
- managedMcpToolMode: executor.kind === "pi" && Object.keys(governedMcp).length > 0 ? MANAGED_PI_MCP_TOOL_MODE : null,
13073
+ managedMcpToolMode: executor.kind === "pi" && Object.keys(governedMcp).length > 0 ? readString(governedMcp.mcpToolMode) ?? MANAGED_PI_MCP_TOOL_MODE : null,
13074
+ managedMcpToolCatalog: asRecord(governedMcp.toolCatalog),
12594
13075
  artifactVerifierCommands: config.artifactVerifierCommands,
12595
13076
  workspaceBindings: config.workspaceBindings
12596
13077
  });
@@ -12647,8 +13128,6 @@ async function executeRunCommand(config, command) {
12647
13128
  if (piAgentLocalPlatformRunnerEnabled(config)) {
12648
13129
  delete executorEnv.AMASTER_API_KEY;
12649
13130
  delete executorEnv.AMASTER_PROVIDER_BASE_URL;
12650
- delete executorEnv.AMASTER_PROVIDER_DEFAULT_MODEL;
12651
- delete executorEnv.AMASTER_PROVIDER_FLASH_MODEL;
12652
13131
  }
12653
13132
  piResolvedProviderConfig = resolvePiExecutorProviderConfig(config, command, executorEnv);
12654
13133
  for (const envName of ["AMASTER_API_KEY", "AMASTER_PLATFORM_OAUTH_TOKEN"]) {
@@ -12715,7 +13194,8 @@ async function executeRunCommand(config, command) {
12715
13194
  profileRoot: managedMcpProfile.profileRoot,
12716
13195
  agentDir: managedMcpProfile.env.PI_CODING_AGENT_DIR,
12717
13196
  governedMcpConfigPath: managedMcpProfile.configPath,
12718
- verifiedAssertion: trustedPiRuntime
13197
+ verifiedAssertion: trustedPiRuntime,
13198
+ skillProfile: readString(asRecord(command.payload).skillProfile)
12719
13199
  });
12720
13200
  executorEnv = {
12721
13201
  ...executorEnv,
@@ -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.2";
8
+ const CONNECTOR_VERSION = "0.1.1-beta.4";
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.2",
3
+ "version": "0.1.1-beta.4",
4
4
  "description": "MirrorX runtime connector CLI and daemon",
5
5
  "license": "MIT",
6
6
  "type": "module",