@amaster.ai/employee-runtime-connector 0.1.1-beta.265 → 0.1.1-beta.267

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.
@@ -18,9 +18,16 @@ export const BUILD_SUPPORTED_CAPABILITIES = Object.freeze([
18
18
  "logs_cost_workspace_status",
19
19
  "browser_credential_ref_fill_v1",
20
20
  "execution_lanes_v1",
21
+ "mirrorx_initialization_context_v1",
22
+ "mirrorx_initialization_completion_v1",
21
23
  ]);
22
24
 
23
25
  const DYNAMIC_READINESS = Object.freeze({
26
+ mirrorx_initialization_completion_v1: {
27
+ reasonCode: "managed_linux_pi_required",
28
+ ready: (input) => process.platform === "linux" && input.runnerKind === "cloud_managed"
29
+ && input.executors.some((executor) => executor.kind === "pi"),
30
+ },
24
31
  artifact_template_catalog_v1: {
25
32
  reasonCode: "artifact_template_catalog_not_ready",
26
33
  ready: (input) => {
@@ -5114,7 +5114,9 @@ var AMASTER_RUNTIME_CONNECTOR_CAPABILITIES = [
5114
5114
  "continue_task_v1",
5115
5115
  "run_exit_live_path_closure_v1",
5116
5116
  "browser_credential_ref_fill_v1",
5117
- "execution_lanes_v1"
5117
+ "execution_lanes_v1",
5118
+ "mirrorx_initialization_context_v1",
5119
+ "mirrorx_initialization_completion_v1"
5118
5120
  ];
5119
5121
  var RUNTIME_EXECUTION_LANES = ["business", "conversation"];
5120
5122
  var runtimeExecutionLaneSchema = external_exports.enum(RUNTIME_EXECUTION_LANES);
@@ -13795,7 +13797,11 @@ var governedBusinessTaskEnrollmentReadModelSchema = external_exports.object({
13795
13797
  discoverySource: governedBusinessTaskDiscoverySourceSchema.nullable(),
13796
13798
  finding: external_exports.object({
13797
13799
  code: external_exports.string().trim().min(1),
13798
- message: external_exports.string().trim().min(1)
13800
+ message: external_exports.string().trim().min(1),
13801
+ invalidFields: external_exports.array(external_exports.object({
13802
+ path: external_exports.string().trim().min(1),
13803
+ code: external_exports.string().trim().min(1)
13804
+ }).strict()).max(20).optional()
13799
13805
  }).strict().nullable()
13800
13806
  }).strict();
13801
13807
 
@@ -16742,7 +16748,8 @@ var companyArtifactSchema = external_exports.object({
16742
16748
  issue: external_exports.object({
16743
16749
  id: external_exports.string().uuid(),
16744
16750
  identifier: external_exports.string(),
16745
- title: external_exports.string()
16751
+ title: external_exports.string(),
16752
+ status: external_exports.string().optional()
16746
16753
  }),
16747
16754
  project: external_exports.object({
16748
16755
  id: external_exports.string().uuid(),
@@ -16761,7 +16768,8 @@ var companyArtifactGroupSchema = external_exports.object({
16761
16768
  issue: external_exports.object({
16762
16769
  id: external_exports.string().uuid(),
16763
16770
  identifier: external_exports.string(),
16764
- title: external_exports.string()
16771
+ title: external_exports.string(),
16772
+ status: external_exports.string().optional()
16765
16773
  }),
16766
16774
  title: external_exports.string(),
16767
16775
  count: external_exports.number().int().min(0),
@@ -22066,6 +22074,343 @@ function reconcileManagedCodebuddyMcpProfiles(rootPath, options = {}) {
22066
22074
  };
22067
22075
  }
22068
22076
 
22077
+ // src/amaster-runtime-daemon/pi-initialization-completion.mjs
22078
+ async function runInitializationCompletion({ plan, authority, call, sleep, now, onReceipt = () => {
22079
+ }, timeoutMs = 12e4 }) {
22080
+ const deadline = now() + timeoutMs;
22081
+ const receipts = [];
22082
+ let stage = "upload";
22083
+ let callId;
22084
+ const fail3 = (code, detail) => {
22085
+ throw Object.assign(new Error(code), { detail });
22086
+ };
22087
+ async function invoke(name, args) {
22088
+ if (now() >= deadline) fail3("initialization_completion_deadline");
22089
+ let envelope;
22090
+ for (let transportFailures = 0; ; ) {
22091
+ if (now() >= deadline) fail3("initialization_completion_deadline");
22092
+ try {
22093
+ envelope = await call(name, args, Math.min(45e3, deadline - now()));
22094
+ break;
22095
+ } catch (error) {
22096
+ if (error?.retryable !== true) throw error;
22097
+ const leaseWait = error.code === "invocation_in_progress" && Number.isSafeInteger(error.retryAfterMs) && error.retryAfterMs >= 0;
22098
+ if (!leaseWait && ++transportFailures >= 3) throw error;
22099
+ const delay = leaseWait ? Math.max(1e3, error.retryAfterMs) : 1e3 * transportFailures;
22100
+ await sleep(Math.min(delay, Math.max(0, deadline - now())));
22101
+ }
22102
+ }
22103
+ const content = envelope?.content;
22104
+ const provider = envelope?.providerReceipt;
22105
+ if (!envelope?.invocationId || provider?.invocationId !== envelope.invocationId || provider?.provider !== "amaster_actions" || !["runId", "commandId", "issueId"].every((key) => authority[key] && provider[key] === authority[key]) || content?.schemaVersion !== "runtime-action-v1" || content?.toolName !== name.replace("runtime_action_", "runtime_action.")) {
22106
+ fail3("initialization_completion_receipt_mismatch");
22107
+ }
22108
+ if (envelope.status !== "succeeded" || !["accepted", "pending_reconcile"].includes(content.status)) {
22109
+ fail3("initialization_completion_action_not_accepted", content.error ?? { status: envelope.status });
22110
+ }
22111
+ const result2 = content.result;
22112
+ await onReceipt(envelope);
22113
+ receipts.push({
22114
+ stage,
22115
+ invocationId: envelope.invocationId,
22116
+ callId: result2?.callId,
22117
+ planId: result2?.planId,
22118
+ status: result2?.status
22119
+ });
22120
+ if (!result2 || result2.error) fail3("initialization_completion_action_failed", result2?.error);
22121
+ return result2;
22122
+ }
22123
+ async function settleCall(value, actionType) {
22124
+ callId = value.callId;
22125
+ if (!callId || value.actionType !== actionType) fail3("initialization_completion_call_mismatch");
22126
+ for (let attempt = 0; ; attempt++) {
22127
+ if (value.callId !== callId || value.actionType !== actionType) fail3("initialization_completion_call_mismatch");
22128
+ if (value.status === "succeeded") return value;
22129
+ if (!["pending_reconcile", "claimed", "executing"].includes(value.status)) {
22130
+ fail3("initialization_completion_action_incomplete", { status: value.status, error: value.error });
22131
+ }
22132
+ if (now() >= deadline) fail3("initialization_completion_deadline");
22133
+ await sleep(Math.min(1e3 * (attempt + 1), 5e3));
22134
+ value = await invoke("runtime_action_status", { callId });
22135
+ }
22136
+ }
22137
+ try {
22138
+ const doc = plan.initializationDocument;
22139
+ const materialized = plan.initializationDocumentMaterialization;
22140
+ if (!plan.planId || !plan.revision || !["planned", "committing", "pending_reconcile", "completed"].includes(plan.status) || materialized?.status !== "materialized" || materialized.planId !== plan.planId || materialized.revision !== plan.revision || materialized.sha256 !== doc?.sha256 || materialized.byteSize !== doc?.byteSize || materialized.path !== doc?.path) {
22141
+ fail3("initialization_completion_invalid_plan");
22142
+ }
22143
+ const prefix = "initialization-complete:" + plan.planId;
22144
+ const { createHash: createHash19 } = await import("node:crypto");
22145
+ const uploadKey = prefix + ":upload:" + createHash19("sha256").update(materialized.path).digest("hex");
22146
+ const upload = await settleCall(await invoke("runtime_action_submit", {
22147
+ idempotencyKey: uploadKey,
22148
+ action: {
22149
+ type: "upload_artifact",
22150
+ idempotencyKey: uploadKey,
22151
+ path: materialized.path,
22152
+ title: "Organization Plan",
22153
+ contentType: "text/markdown",
22154
+ artifactPurpose: "initialization_organization_plan",
22155
+ createWorkProduct: true,
22156
+ evidenceRole: "source",
22157
+ isPrimary: true,
22158
+ status: "ready_for_review"
22159
+ }
22160
+ }), "upload_artifact");
22161
+ if (upload.postcondition?.artifactFinalized !== true || upload.postcondition?.attachmentReadback !== true || upload.postcondition?.workProductReadback !== true || upload.effectResult?.sha256 !== doc.sha256 || upload.effectResult?.byteSize !== doc.byteSize || !upload.effectResult?.attachmentId || !upload.effectResult?.workProductId) {
22162
+ fail3("initialization_completion_artifact_mismatch");
22163
+ }
22164
+ stage = "commit";
22165
+ callId = void 0;
22166
+ const committed = await invoke("runtime_action_commit", { planId: plan.planId, revision: plan.revision });
22167
+ if (committed.planId !== plan.planId || committed.revision !== plan.revision || committed.status !== "completed" || committed.failure || committed.nextActionIndex !== committed.actionCount) {
22168
+ fail3("initialization_completion_plan_incomplete", { status: committed.status, failure: committed.failure });
22169
+ }
22170
+ stage = "ready";
22171
+ const completed = await settleCall(await invoke("runtime_action_submit", {
22172
+ idempotencyKey: prefix + ":done",
22173
+ action: { type: "update_parent", status: "done" }
22174
+ }), "update_parent");
22175
+ if (completed.effectResult?.issueId !== authority.issueId || completed.effectResult?.status !== "done" || completed.postcondition?.issuePersisted !== true || completed.postcondition?.status !== "done" || completed.postcondition?.issueTerminalizationDeferred === true) {
22176
+ fail3("initialization_completion_ready_not_confirmed");
22177
+ }
22178
+ return {
22179
+ status: "completed",
22180
+ planId: plan.planId,
22181
+ revision: plan.revision,
22182
+ attachmentId: upload.effectResult.attachmentId,
22183
+ workProductId: upload.effectResult.workProductId,
22184
+ completionCallId: completed.callId,
22185
+ receipts
22186
+ };
22187
+ } catch (error) {
22188
+ return {
22189
+ status: "incomplete",
22190
+ stage,
22191
+ planId: plan.planId,
22192
+ revision: plan.revision,
22193
+ callId,
22194
+ code: error.message,
22195
+ detail: error.detail,
22196
+ receipts
22197
+ };
22198
+ }
22199
+ }
22200
+ function managedPiInitializationCompletionSource() {
22201
+ return `const runInitializationCompletion = ${runInitializationCompletion.toString()};
22202
+ async function initializationCompletionCall(name, args, timeoutMs = 45000) {
22203
+ const server = JSON.parse(fs.readFileSync(configPath, "utf8")).mcpServers.amaster;
22204
+ const id = randomUUID();
22205
+ const chunks = []; let size = 0; let status;
22206
+ try {
22207
+ const response = await fetch(server.url, { method: "POST", redirect: "error",
22208
+ headers: { ...server.headers, "Content-Type": "application/json", Accept: "application/json" },
22209
+ body: JSON.stringify({ jsonrpc: "2.0", id, method: "tools/call", params: { name, arguments: args } }),
22210
+ signal: AbortSignal.timeout(timeoutMs) });
22211
+ status = response.status;
22212
+ if (!response.ok && status !== 409) {
22213
+ await response.body?.cancel();
22214
+ throw Object.assign(new Error("initialization_completion_http_" + response.status), {
22215
+ retryable: [429, 500, 502, 503, 504].includes(response.status),
22216
+ });
22217
+ }
22218
+ for await (const part of response.body) {
22219
+ size += part.length;
22220
+ if (size > 256 * 1024) throw new Error("initialization_completion_response_too_large");
22221
+ chunks.push(part);
22222
+ }
22223
+ } catch (error) {
22224
+ if (["TypeError", "TimeoutError", "AbortError"].includes(error?.name)) error.retryable = true;
22225
+ throw error;
22226
+ }
22227
+ const rpc = JSON.parse(Buffer.concat(chunks).toString("utf8"));
22228
+ if (status === 409) {
22229
+ const data = rpc?.error?.data;
22230
+ const leaseWait = rpc?.jsonrpc === "2.0" && rpc.id === id
22231
+ && data?.reasonCode === "invocation_in_progress"
22232
+ && Number.isSafeInteger(data.retryAfterMs) && data.retryAfterMs >= 0;
22233
+ throw Object.assign(new Error(leaseWait ? "invocation_in_progress" : "initialization_completion_http_409"), {
22234
+ retryable: leaseWait, code: leaseWait ? "invocation_in_progress" : undefined,
22235
+ retryAfterMs: leaseWait ? data.retryAfterMs : undefined,
22236
+ });
22237
+ }
22238
+ if (rpc?.id !== id || rpc.error) throw new Error("initialization_completion_rpc_error");
22239
+ return JSON.parse(rpc.result?.content?.[0]?.text);
22240
+ }`;
22241
+ }
22242
+
22243
+ // src/amaster-runtime-daemon/pi-initialization-document.mjs
22244
+ function managedPiInitializationDocumentExtensionSource(cwd, configPath = `${cwd}/.pi/mcp.json`, completionAuthority = null) {
22245
+ return `import fs from "node:fs";
22246
+ import { createHash, randomUUID } from "node:crypto";
22247
+ const cwd = ${JSON.stringify(cwd)};
22248
+ const configPath = ${JSON.stringify(configPath)};
22249
+ const completionAuthority = ${JSON.stringify(completionAuthority)};
22250
+ ${managedPiInitializationCompletionSource()}
22251
+ export default function(pi) {
22252
+ pi.on("tool_result", async (event) => {
22253
+ // Linux dir-fd paths prevent a concurrent directory replacement redirecting writes.
22254
+ // Other executors retain the original document workflow.
22255
+ if (process.platform !== "linux" || event.isError || event.details?.server !== "amaster"
22256
+ || !["runtime_action_plan", "runtime_action_status"].includes(event.toolName)) return;
22257
+ if (!Array.isArray(event.content) || event.content.length !== 1 || event.content[0].type !== "text") return;
22258
+ let envelope;
22259
+ try { envelope = JSON.parse(event.content[0].text); } catch { return; }
22260
+ const call = envelope?.content;
22261
+ const result = call?.result;
22262
+ const doc = result?.initializationDocument;
22263
+ if (envelope?.status !== "succeeded" || call?.status !== "accepted"
22264
+ || call?.schemaVersion !== "runtime-action-v1"
22265
+ || !["runtime_action.plan", "runtime_action.status"].includes(call?.toolName) || !doc) return;
22266
+ let root, parent, file, temp;
22267
+ const canonicalName = "organization-plan-" + result.planId + ".md";
22268
+ let targetName = canonicalName;
22269
+ try {
22270
+ if (doc.version !== 1 || (doc.path !== "deliverables/" + targetName
22271
+ && !(typeof doc.markdown === "string" && doc.path === "deliverables/organization-plan.md"))
22272
+ || doc.contentType !== "text/markdown" || !/^[0-9a-f]{64}$/.test(doc.sha256)
22273
+ || !/^[0-9a-f-]{36}$/.test(result.planId) || !result.revision || !doc.initializationId
22274
+ || !Number.isSafeInteger(doc.initializationRevision) || doc.initializationRevision < 1
22275
+ || !Number.isSafeInteger(doc.byteSize) || doc.byteSize < 1 || doc.byteSize > 64 * 1024 * 1024) {
22276
+ throw new Error("invalid_document_snapshot");
22277
+ }
22278
+ if (doc.contentRef && (doc.contentRef.kind !== "initialization_plan_document"
22279
+ || doc.contentRef.planId !== result.planId || doc.contentRef.readTool !== "runtime_action.status")) {
22280
+ throw new Error("invalid_document_reference");
22281
+ }
22282
+ // Pin the directory and verify existing bytes before loading credentials or reading chunks.
22283
+ const flags = fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW;
22284
+ root = fs.openSync(cwd, flags);
22285
+ const rootPath = "/proc/self/fd/" + root;
22286
+ try { fs.mkdirSync(rootPath + "/deliverables", { mode: 0o700 }); }
22287
+ catch (error) { if (error.code !== "EEXIST") throw error; }
22288
+ parent = fs.openSync(rootPath + "/deliverables", flags);
22289
+ const parentPath = "/proc/self/fd/" + parent;
22290
+ let target;
22291
+ // Preserve conflicts and select a stable alternate; replay verifies these same candidates.
22292
+ function selectTarget() {
22293
+ for (let attempt = 0; attempt < 32; attempt++) {
22294
+ targetName = attempt === 0 ? canonicalName
22295
+ : "organization-plan-" + result.planId + "-" + doc.sha256 + "-" + attempt + ".md";
22296
+ target = parentPath + "/" + targetName;
22297
+ let existing;
22298
+ try {
22299
+ existing = fs.openSync(target, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
22300
+ const stat = fs.fstatSync(existing);
22301
+ if (stat.isFile() && stat.size === doc.byteSize
22302
+ && createHash("sha256").update(fs.readFileSync(existing)).digest("hex") === doc.sha256) return true;
22303
+ } catch (error) {
22304
+ if (error.code === "ENOENT") return false;
22305
+ if (!["ELOOP", "EACCES", "EISDIR"].includes(error.code)) throw error;
22306
+ } finally { if (existing !== undefined) fs.closeSync(existing); }
22307
+ }
22308
+ throw new Error("document_recovery_paths_exhausted");
22309
+ }
22310
+ let replayed = selectTarget();
22311
+ if (!replayed) {
22312
+ let bytes;
22313
+ if (doc.contentRef) {
22314
+ // Use this run's existing governed session; references cannot select an endpoint or credential.
22315
+ const server = JSON.parse(fs.readFileSync(configPath, "utf8")).mcpServers.amaster;
22316
+ const chunks = [];
22317
+ let offset = 0;
22318
+ while (offset < doc.byteSize) {
22319
+ const id = randomUUID();
22320
+ const response = await fetch(server.url, { method: "POST", redirect: "error",
22321
+ headers: { ...server.headers, "Content-Type": "application/json", Accept: "application/json" },
22322
+ body: JSON.stringify({ jsonrpc: "2.0", id, method: "tools/call", params: {
22323
+ name: "runtime_action_status", arguments: { planId: result.planId, documentOffset: offset },
22324
+ } }), signal: AbortSignal.timeout(30000) });
22325
+ if (!response.ok) { await response.body?.cancel(); throw new Error("document_read_denied"); }
22326
+ const parts = [];
22327
+ let size = 0;
22328
+ for await (const part of response.body) {
22329
+ size += part.length;
22330
+ if (size > 256 * 1024) throw new Error("document_chunk_response_too_large");
22331
+ parts.push(part);
22332
+ }
22333
+ const rpc = JSON.parse(Buffer.concat(parts).toString("utf8"));
22334
+ const readEnvelope = JSON.parse(rpc.result?.content?.[0]?.text);
22335
+ const read = readEnvelope?.content;
22336
+ const value = read?.result;
22337
+ const chunk = value?.initializationDocumentChunk;
22338
+ if (rpc.id !== id || readEnvelope.status !== "succeeded" || read?.status !== "accepted"
22339
+ || value?.planId !== result.planId || value?.revision !== result.revision
22340
+ || value?.initializationDocument?.sha256 !== doc.sha256
22341
+ || value?.initializationDocument?.byteSize !== doc.byteSize
22342
+ || chunk?.encoding !== "base64" || chunk.offset !== offset || typeof chunk.data !== "string") {
22343
+ throw new Error("invalid_document_chunk");
22344
+ }
22345
+ const part = Buffer.from(chunk.data, "base64");
22346
+ if (!part.length || part.length > 48 * 1024 || part.toString("base64") !== chunk.data
22347
+ || offset + part.length > doc.byteSize
22348
+ || chunk.nextOffset !== (offset + part.length < doc.byteSize ? offset + part.length : null)) {
22349
+ throw new Error("invalid_document_chunk_range");
22350
+ }
22351
+ chunks.push(part);
22352
+ offset += part.length;
22353
+ }
22354
+ bytes = Buffer.concat(chunks);
22355
+ } else {
22356
+ // Rolling-upgrade compatibility for inline receipts from an older Server.
22357
+ if (typeof doc.markdown !== "string") throw new Error("missing_document_content");
22358
+ bytes = Buffer.from(doc.markdown, "utf8");
22359
+ }
22360
+ if (bytes.length !== doc.byteSize || createHash("sha256").update(bytes).digest("hex") !== doc.sha256) {
22361
+ throw new Error("invalid_document_snapshot");
22362
+ }
22363
+ temp = parentPath + "/.organization-plan-" + randomUUID();
22364
+ file = fs.openSync(temp, "wx", 0o600);
22365
+ fs.writeFileSync(file, bytes);
22366
+ fs.fsyncSync(file);
22367
+ // link is atomic and refuses replacement, including a raced-in symlink.
22368
+ for (let attempt = 0; ; attempt++) {
22369
+ try { fs.linkSync(temp, target); break; }
22370
+ catch (error) {
22371
+ if (error.code !== "EEXIST" || attempt >= 31) throw error;
22372
+ if (selectTarget()) { replayed = true; break; }
22373
+ }
22374
+ }
22375
+ }
22376
+ doc.path = "deliverables/" + targetName;
22377
+ result.initializationDocumentMaterialization = {
22378
+ status: "materialized", path: doc.path, sha256: doc.sha256, byteSize: doc.byteSize,
22379
+ planId: result.planId, revision: result.revision, replayed, uploaded: false,
22380
+ };
22381
+ } catch {
22382
+ // Preserve the authoritative successful plan receipt; local failure is separate.
22383
+ result.initializationDocumentMaterialization = { status: "failed", uploaded: false,
22384
+ reason: "Runner document recovery could not complete within safe limits; retry through the governed runtime recovery path before publishing." };
22385
+ } finally {
22386
+ if (file !== undefined) fs.closeSync(file);
22387
+ if (temp) { try { fs.unlinkSync(temp); } catch {} }
22388
+ if (parent !== undefined) fs.closeSync(parent);
22389
+ if (root !== undefined) fs.closeSync(root);
22390
+ }
22391
+ // Only an explicitly negotiated planning call starts effects. Status/document reads stay reads.
22392
+ const provider = envelope.providerReceipt;
22393
+ if (completionAuthority && event.toolName === "runtime_action_plan"
22394
+ && result.initializationDocumentMaterialization?.status === "materialized"
22395
+ && provider?.provider === "amaster_actions" && provider.invocationId === envelope.invocationId
22396
+ && provider.planId === result.planId
22397
+ && ["runId", "commandId", "issueId"].every((key) => completionAuthority[key] && provider[key] === completionAuthority[key])) {
22398
+ result.initializationCompletion = await runInitializationCompletion({ plan: result, authority: completionAuthority,
22399
+ call: initializationCompletionCall, sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)), now: Date.now,
22400
+ // Pi redirects extension stdout.write to stderr. This is an explicit
22401
+ // daemon JSON protocol event, so use fd 1 rather than extension logging.
22402
+ onReceipt: (receipt) => fs.writeSync(1, JSON.stringify({ type: "mirrorx_initialization_action_receipt", receipt }) + "\\n"),
22403
+ });
22404
+ if (result.initializationCompletion.status === "completed") result.initializationDocumentMaterialization.uploaded = true;
22405
+ }
22406
+ // A completed issue is not a mustEndRun handoff. Let Pi emit its ordinary
22407
+ // final summary; stopAfterTurn here is classified as exhausted tool work.
22408
+ return { content: [{ type: "text", text: JSON.stringify(envelope) }] };
22409
+ });
22410
+ }
22411
+ `;
22412
+ }
22413
+
22069
22414
  // src/amaster-runtime-daemon/pi-managed-mcp-profile.mjs
22070
22415
  import { createHash as createHash8 } from "node:crypto";
22071
22416
  import {
@@ -23514,10 +23859,12 @@ function createManagedPiMcpProfileApi(options = {}) {
23514
23859
  const fullWikiCount = fullWikiReadCount + (hasWikiWrite ? 1 : 0);
23515
23860
  const fullConnectorCount = countIn(FULL_DIRECT_TYPED_V1_CONNECTOR_TOOL_NAMES);
23516
23861
  const fullCatalog = mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE && tools.length === FULL_DIRECT_TYPED_V1_BASE_TOOL_NAMES.size + fullWikiCount + fullConnectorCount && covers(FULL_DIRECT_TYPED_V1_BASE_TOOL_NAMES) && (fullWikiReadCount === 0 && !hasWikiWrite || fullWikiReadCount === FULL_DIRECT_TYPED_V1_WIKI_READ_TOOL_NAMES.size) && (fullConnectorCount === 0 || fullConnectorCount === FULL_DIRECT_TYPED_V1_CONNECTOR_TOOL_NAMES.size) && tools.every((tool) => FULL_DIRECT_TYPED_V1_TOOL_NAMES.has(tool.name));
23517
- if (mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE && !fullCatalog) {
23862
+ const initializationNames = new Set([...FULL_DIRECT_TYPED_V1_BASE_TOOL_NAMES].filter((name) => name !== "runtime_action.list" && name !== "mirrorx.list_issues"));
23863
+ const initializationCatalog = tools.length === initializationNames.size + fullWikiReadCount && covers(initializationNames) && !hasWikiWrite && fullConnectorCount === 0 && (fullWikiReadCount === 0 || fullWikiReadCount === FULL_DIRECT_TYPED_V1_WIKI_READ_TOOL_NAMES.size);
23864
+ if (mcpToolMode === MANAGED_PI_DIRECT_TYPED_MCP_TOOL_MODE && !fullCatalog && !initializationCatalog) {
23518
23865
  throw new Error("pi_managed_mcp_invalid: direct tool catalog size mismatch");
23519
23866
  }
23520
- const catalogKind = "full";
23867
+ const catalogKind = initializationCatalog ? "initialization" : "full";
23521
23868
  const admittedToolNames = FULL_DIRECT_TYPED_V1_TOOL_NAMES;
23522
23869
  const names = /* @__PURE__ */ new Set();
23523
23870
  const exposedNames = /* @__PURE__ */ new Set();
@@ -24650,6 +24997,14 @@ ${result2.stderr ?? ""}`, "Pi", MINIMUM_PI_VERSION);
24650
24997
  managedPiRunTerminationExtensionSource()
24651
24998
  );
24652
24999
  }
25000
+ if (directCatalog?.tools.some((tool) => tool.name === "runtime_action.plan")) {
25001
+ const automaticCompletion = directCatalog.tools.find((tool) => tool.name === "runtime_action.plan")?.inputSchema?.$comment === "mirrorx.initialization-completion.v1";
25002
+ writeProfileExtension("amaster-initialization-document.js", managedPiInitializationDocumentExtensionSource(
25003
+ cwd,
25004
+ `${cwd}/.pi/mcp.json`,
25005
+ automaticCompletion ? authority : null
25006
+ ));
25007
+ }
24653
25008
  const adapterVersion = piMcpAdapterVersion(sharedRuntime.home);
24654
25009
  if (directCatalog) assertPiMcpAdapterDirectCatalogSupport(adapterVersion);
24655
25010
  const {
@@ -28223,7 +28578,7 @@ function maybeCapturePiMessage(event, messages, usage) {
28223
28578
  }
28224
28579
  return capturedAssistantOutput;
28225
28580
  }
28226
- function piMcpToolResults(event) {
28581
+ function piMcpToolResults(event, expectedAuthority = null) {
28227
28582
  const results = [];
28228
28583
  const seen = /* @__PURE__ */ new Set();
28229
28584
  const retain = (parsed) => {
@@ -28278,6 +28633,14 @@ function piMcpToolResults(event) {
28278
28633
  if (readString(event?.type) === "tool_execution_end") {
28279
28634
  retainMcpResult(event?.result);
28280
28635
  }
28636
+ if (readString(event?.type) === "mirrorx_initialization_action_receipt" && expectedAuthority) {
28637
+ const receipt = asRecord(event.receipt);
28638
+ const provider = asRecord(receipt.providerReceipt);
28639
+ const content = asRecord(receipt.content);
28640
+ if (content.schemaVersion === "runtime-action-v1" && ["runtime_action.submit", "runtime_action.status", "runtime_action.commit"].includes(content.toolName) && ["runId", "commandId", "issueId"].every((key) => readString(expectedAuthority[key]) && provider[key] === expectedAuthority[key])) {
28641
+ retainMcpResult({ details: { server: "amaster" }, content: [{ type: "text", text: JSON.stringify(receipt) }] });
28642
+ }
28643
+ }
28281
28644
  return results;
28282
28645
  }
28283
28646
  function piGovernedMcpUnavailableEvidence(event) {
@@ -30109,6 +30472,14 @@ function wikiAccessRuleLine(input) {
30109
30472
  const access = asRecord(input.wikiAccess);
30110
30473
  const tools = input.hasGovernedMcp === true && access.tools === true;
30111
30474
  const treePath = readString(access.treePath);
30475
+ const catalogTools = asRecord(input.managedMcpToolCatalog).tools;
30476
+ if (input.managedMcpToolMode === "direct_typed" && Array.isArray(catalogTools)) {
30477
+ const wikiNames = tools ? catalogTools.map((tool) => readString(asRecord(tool).exposedName)).filter((name) => ["wiki_list", "wiki_search", "wiki_read", "wiki_write", "wiki_list_versions", "wiki_diff_versions"].includes(name)) : [];
30478
+ if (wikiNames.length > 0) {
30479
+ return `- Company wiki access in this run: ${wikiNames.join(" / ")} via the amaster MCP${treePath ? `, and the wiki tree at ${treePath}` : ""}. Use targeted reads for relevant evidence; only the listed tools are available.`;
30480
+ }
30481
+ return treePath ? `- Company wiki access in this run: the wiki tree at ${treePath}. Read wiki/index.md then the relevant pages; wiki_* tools are not available.` : "";
30482
+ }
30112
30483
  if (tools && treePath) {
30113
30484
  return `- Company wiki access in this run: the six tools wiki_list / wiki_search / wiki_read / wiki_write / wiki_list_versions / wiki_diff_versions via the amaster MCP, and the wiki tree at ${treePath} (read wiki/index.md there first).`;
30114
30485
  }
@@ -31341,7 +31712,17 @@ ${resolvedDependencies.details.content}` : resolvedDependencies.details.content
31341
31712
  const taskContextAuthority = taskContextAuthoritySection(context);
31342
31713
  const continuationPostconditionGap = continuationPostconditionGapSection(context, input);
31343
31714
  const companyInitializationAuthority = companyInitializationAuthoritySection(context);
31344
- const runtimeTemplateCatalog = runtimeTemplateCatalogSection(input);
31715
+ const rawManagedTools = asRecord(input.managedMcpToolCatalog).tools;
31716
+ const managedTools = Array.isArray(rawManagedTools) ? rawManagedTools : [];
31717
+ const planTool = managedTools.find((tool) => asRecord(tool).name === "runtime_action.plan");
31718
+ const documentSchema = asRecord(asRecord(asRecord(asRecord(planTool).inputSchema).properties).initializationOrganization).properties;
31719
+ const serverDocumentWorkflow = companyInitializationAuthority && asRecord(context.companyInitializationAuthority).organizationMutationAuthorityMode === "initialization_plan" && input.hasGovernedMcp && input.executorKind === "pi" && input.managedMcpToolMode === "direct_typed" && !managedTools.some((tool) => asRecord(tool).name === "runtime_action.list") && asRecord(documentSchema).documentReasoning;
31720
+ const fallbackTemplateCatalog = runtimeTemplateCatalogSection(input);
31721
+ const automaticCompletion = asRecord(asRecord(planTool).inputSchema).$comment === "mirrorx.initialization-completion.v1";
31722
+ const runtimeTemplateCatalog = serverDocumentWorkflow ? {
31723
+ sourceRef: "company_initialization_server_document_renderer",
31724
+ content: (automaticCompletion ? "Submit your final company-specific organization decisions once through initializationOrganization with documentReasoning. This negotiated plan call requests automatic completion: Server renders the seven-section document; Runner materializes, uploads through Artifact Saga, waits for verified delivery, commits the exact plan and requests Server-validated ready completion. Do not queue upload/status/commit/done or filesystem template searches alongside the plan. The automatic sequence preserves all Server authorization, version, artifact and ready gates. A completed initializationCompletion receipt ends this run. An incomplete receipt identifies the exact stage and durable IDs for existing recovery; revise business decisions only when the error requires it. Explicit actions, omitted documentReasoning or missing initializationDocument retain the original document/upload/commit workflow." : "The initialization Organization Plan uses the Server-owned seven-section renderer. This satisfies the pre-draft template selection step for this artifact; do not search or copy filesystem templates. Submit company-specific decisions once through initializationOrganization.documentReasoning. The Runner verifies and materializes returned document bytes; a materialized receipt requires no extra file/hash inspection. Use the exact returned path in upload_artifact, then follow Artifact Saga, commit and the Server ready gates. If using explicit actions, omitting documentReasoning, or receiving no initializationDocument, use the original document workflow and configured template catalog; never claim materialization without its successful receipt.") + (fallbackTemplateCatalog ? ` Fallback-only exact catalog path: ${asRecord(input.runtimeTemplateCatalog).targetDir}` : "")
31725
+ } : fallbackTemplateCatalog;
31345
31726
  const rawSections = [
31346
31727
  { name: "recovery_instruction", title: "Recovery Instruction", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: completeRecoveryInstruction, truncationReason: completeRecoveryInstruction ? null : "mode_selection" },
31347
31728
  { name: "approval_continuation", title: "Approved Runtime Action Continuation", priority: 100, sourceRef: `run:${input.runId ?? "unknown"}`, content: approvalContinuationText(input), truncationReason: mode === "continuation" ? null : "mode_selection" },
@@ -31878,9 +32259,15 @@ var BUILD_SUPPORTED_CAPABILITIES = Object.freeze([
31878
32259
  "run_terminate",
31879
32260
  "logs_cost_workspace_status",
31880
32261
  "browser_credential_ref_fill_v1",
31881
- "execution_lanes_v1"
32262
+ "execution_lanes_v1",
32263
+ "mirrorx_initialization_context_v1",
32264
+ "mirrorx_initialization_completion_v1"
31882
32265
  ]);
31883
32266
  var DYNAMIC_READINESS = Object.freeze({
32267
+ mirrorx_initialization_completion_v1: {
32268
+ reasonCode: "managed_linux_pi_required",
32269
+ ready: (input) => process.platform === "linux" && input.runnerKind === "cloud_managed" && input.executors.some((executor) => executor.kind === "pi")
32270
+ },
31884
32271
  artifact_template_catalog_v1: {
31885
32272
  reasonCode: "artifact_template_catalog_not_ready",
31886
32273
  ready: (input) => {
@@ -34017,7 +34404,7 @@ function assertRequiredTaskAttachmentMaterialized(input, materialized) {
34017
34404
  }
34018
34405
 
34019
34406
  // src/amaster-runtime-daemon.mjs
34020
- var CONNECTOR_VERSION = "0.1.1-beta.265";
34407
+ var CONNECTOR_VERSION = "0.1.1-beta.267";
34021
34408
  var CONNECTOR_CONTRACT_VERSION = "2026-06-04.v1";
34022
34409
  var daemonRequire = createRequire2(import.meta.url);
34023
34410
  var MAX_CHECKPOINT_BYTES = 20 * 1024 * 1024;
@@ -36392,7 +36779,7 @@ function createLiveOutputLogger(config, command, executorKind, protectedValues =
36392
36779
  }
36393
36780
  }
36394
36781
  if (MIRRORX_FORMAL_TASK_EXECUTOR_KINDS.includes(executorKind) && event) {
36395
- const results = executorKind === "codex" ? codexMcpToolResults(event) : executorKind === "codebuddy" ? codebuddyMcpToolResults(event) : piMcpToolResults(event);
36782
+ const results = executorKind === "codex" ? codexMcpToolResults(event) : executorKind === "codebuddy" ? codebuddyMcpToolResults(event) : piMcpToolResults(event, { runId: commandRunId(command), commandId: command.commandId, issueId: commandIssueId(command) });
36396
36783
  liveMcpToolResults.push(...results);
36397
36784
  if (results.length > 0) onMcpToolResults?.(results);
36398
36785
  }
@@ -7,7 +7,7 @@ import { homedir, hostname } from "node:os";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { BUILD_SUPPORTED_CAPABILITIES } from "./amaster-runtime-daemon/capability-registry.mjs";
9
9
 
10
- const CONNECTOR_VERSION = "0.1.1-beta.265";
10
+ const CONNECTOR_VERSION = "0.1.1-beta.267";
11
11
 
12
12
  const CONFIG_KEY_MAP = new Map([
13
13
  ["server_url", "AMASTER_EMPLOYEE_SERVER_URL"],
@@ -43,8 +43,8 @@
43
43
  },
44
44
  {
45
45
  "name": "内容发布交接单模板.md",
46
- "bytes": 11250,
47
- "sha256": "05f7fca0333b51e4d453deb7de9b9d1dbd3c58515e8e28499475aa99211af9df"
46
+ "bytes": 12591,
47
+ "sha256": "35b43e739c88188f0e660f8a15acbb429faa984fadf2c56ba4c2c59957abca3a"
48
48
  },
49
49
  {
50
50
  "name": "内容计划与排期模板.md",
@@ -41,6 +41,9 @@
41
41
 
42
42
  - 当前进度以相关任务及最新证据为准;Wiki 保存确认内容、截至某时的历史发布记录与有来源的复盘,不充当发布队列或新授权。
43
43
  - 使用当前已提供且获授权的 Wiki 操作,普通用户只需打开已返回的成果链接,不要求进入开发模式。没有可用能力时保留任务成果,明确归档未安排/失败及负责处理方。
44
+ - 普通运营任务先用 Wiki 读取工具在当前公司默认共享空间查重;不要调用未开放的 `wiki_write`,也不要猜测或索取 operationId。需要归档时先保存一份独立归档文档,包含已确认发布包的准确版本、稳定成果引用、来源任务和确认回执,以及未发布/待审核限制;不修改已确认的清单或媒体。
45
+ - 使用 `runtime_action.describe(upsert_external_wait)` 获取当前合同,通过 `upsert_external_wait` 提交 `reasonCode=wiki_operation_context_missing`、`ownerType=user`、`actionKind=approval` 和 `wikiPublicationSelection`:绑定归档文档的 `documentKey/expectedRevisionId` 及 `destination` 的默认 Wiki、共享空间和稳定 `wiki/...md` 路径;已有页面更新须提供刚读取的准确 `expectedPageHash`,新页面不覆盖现有内容。这是任务页的受控归档入口,不是外部平台发文。
46
+ - 绑定完成后结束本轮,说明用户可在任务页查看准确文档版本并点击“归档到 Wiki”。收到服务端真实成功回执后再读取页面、核对来源与版本、将链接记入独立交接记录;失败、版本变化或成功未关联时保留明确待处理状态,不冒充已归档,不重复提交确认或生成媒体。没有准确归档文档或目标权限时先报告缺口。
44
47
  - 核对目标 Company/空间、来源和读者权限;明确 Wiki 是原验收必交时取得成功页面与版本后才能完成,否则不擅自追加归档门禁。
45
48
  - 原始图片/视频留在成果/附件中,Wiki 保存内容说明与稳定来源引用,不假定任务摄取会复制视频或 Office 原件,不持久化临时签名地址。
46
49
  - 同一来源版本复用现有归档;重试归档不重复生成或再次发布。新任务复用旧内容时重新核对产品事实和有效期。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amaster.ai/employee-runtime-connector",
3
- "version": "0.1.1-beta.265",
3
+ "version": "0.1.1-beta.267",
4
4
  "description": "MirrorX runtime connector CLI and daemon",
5
5
  "license": "MIT",
6
6
  "type": "module",