@akagilnc/pi-workflow-roles 0.1.3826 → 0.1.3837

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.
@@ -1913,6 +1913,7 @@ var role_turn_host_exports = {};
1913
1913
  __export(role_turn_host_exports, {
1914
1914
  EXPLICIT_INTERNAL_LOAD_PROBE_ARGS: () => EXPLICIT_INTERNAL_LOAD_PROBE_ARGS,
1915
1915
  appendPiSessionCustomEntry: () => appendPiSessionCustomEntry,
1916
+ applyPiNativeSkillInvocation: () => applyPiNativeSkillInvocation,
1916
1917
  buildExplicitInternalActivationArgs: () => buildExplicitInternalActivationArgs,
1917
1918
  buildPiTurnExtraArgs: () => buildPiTurnExtraArgs,
1918
1919
  createDefaultPiSpawnRunner: () => createDefaultPiSpawnRunner,
@@ -1922,7 +1923,7 @@ __export(role_turn_host_exports, {
1922
1923
  import { execFile, spawn as spawn3 } from "node:child_process";
1923
1924
  import { constants } from "node:fs";
1924
1925
  import { access, appendFile, readFile as readFile4, realpath as realpath2 } from "node:fs/promises";
1925
- import { delimiter, isAbsolute as isAbsolute3, join as join7, resolve as resolve6 } from "node:path";
1926
+ import { basename as basename4, delimiter, dirname as dirname6, isAbsolute as isAbsolute3, join as join7, resolve as resolve6 } from "node:path";
1926
1927
  import { platform } from "node:process";
1927
1928
  import { promisify } from "node:util";
1928
1929
  import { randomUUID as randomUUID2 } from "node:crypto";
@@ -2030,12 +2031,26 @@ function buildMethodArgs(methods) {
2030
2031
  }
2031
2032
  return skillArgs;
2032
2033
  }
2034
+ function applyPiNativeSkillInvocation(methods, prompt) {
2035
+ const skills = methods.filter((method) => method.kind === "skill");
2036
+ if (skills.length !== 1) return prompt;
2037
+ const name = basename4(dirname6(skills[0].path));
2038
+ if (name.length === 0) return prompt;
2039
+ const token = `/skill:${name}`;
2040
+ const trimmed = prompt.trimStart();
2041
+ if (trimmed === token || trimmed.startsWith(`${token} `) || trimmed.startsWith(`${token}
2042
+ `)) {
2043
+ return prompt;
2044
+ }
2045
+ return prompt.length === 0 ? token : `${token} ${prompt}`;
2046
+ }
2033
2047
  function buildPiTurnExtraArgs(request, authority, extraPiArgs = []) {
2034
2048
  const { sessionFile, sessionDirectory } = authority.decode(request.principal);
2035
- const prompt = request.continuation.kind === "initial" || request.continuation.kind === "resume" ? request.continuation.prompt : (() => {
2049
+ const rawPrompt = request.continuation.kind === "initial" || request.continuation.kind === "resume" ? request.continuation.prompt : (() => {
2036
2050
  const _exhaustive = request.continuation;
2037
2051
  return _exhaustive;
2038
2052
  })();
2053
+ const prompt = applyPiNativeSkillInvocation(request.methods, rawPrompt);
2039
2054
  return [
2040
2055
  "--no-skills",
2041
2056
  ...buildMethodArgs(request.methods),
@@ -3946,7 +3961,7 @@ var init_terminating_tools = __esm({
3946
3961
 
3947
3962
  // src/doctor-evidence.ts
3948
3963
  import { readdir, readFile as readFile6, realpath as realpath3, stat } from "node:fs/promises";
3949
- import { dirname as dirname6, relative as relative2, resolve as resolve7, sep as sep2 } from "node:path";
3964
+ import { dirname as dirname7, relative as relative2, resolve as resolve7, sep as sep2 } from "node:path";
3950
3965
  function record3(value) {
3951
3966
  return typeof value === "object" && value !== null && !Array.isArray(value);
3952
3967
  }
@@ -3985,7 +4000,7 @@ async function stableRunsIdentity(root) {
3985
4000
  } catch (error) {
3986
4001
  if (!isMissingPathError(error)) throw error;
3987
4002
  }
3988
- const parent = dirname6(cursor);
4003
+ const parent = dirname7(cursor);
3989
4004
  if (parent === cursor) return root;
3990
4005
  cursor = parent;
3991
4006
  }
@@ -5433,7 +5448,7 @@ __export(notary_source_run_exports, {
5433
5448
  loadNotarySourceRunLocator: () => loadNotarySourceRunLocator,
5434
5449
  resolveNotarySourceRunLocator: () => resolveNotarySourceRunLocator
5435
5450
  });
5436
- import { dirname as dirname7, isAbsolute as isAbsolute5, join as join12, resolve as resolve8, basename as basename4 } from "node:path";
5451
+ import { dirname as dirname8, isAbsolute as isAbsolute5, join as join12, resolve as resolve8, basename as basename5 } from "node:path";
5437
5452
  import { lstat as lstat2, realpath as realpath4 } from "node:fs/promises";
5438
5453
  function parseRunDirectoryName(name) {
5439
5454
  const match = RUN_DIR_NAME.exec(name);
@@ -5464,10 +5479,10 @@ async function requireRunDirectory(candidate, display) {
5464
5479
  `notary --source-run must be a run directory: ${display}`
5465
5480
  );
5466
5481
  }
5467
- const identity = parseRunDirectoryName(basename4(real));
5482
+ const identity = parseRunDirectoryName(basename5(real));
5468
5483
  if (identity === void 0) {
5469
5484
  throw new NotarySourceRunError(
5470
- `notary --source-run must be named <runId>@<role>: ${basename4(real)}`
5485
+ `notary --source-run must be named <runId>@<role>: ${basename5(real)}`
5471
5486
  );
5472
5487
  }
5473
5488
  return real;
@@ -5488,9 +5503,9 @@ async function resolveNotarySourceRunLocator(options) {
5488
5503
  candidate = isAbsolute5(raw) ? raw : resolve8(options.projectRoot, raw);
5489
5504
  }
5490
5505
  const real = await requireRunDirectory(candidate, raw);
5491
- const identity = parseRunDirectoryName(basename4(real));
5506
+ const identity = parseRunDirectoryName(basename5(real));
5492
5507
  const runsRootIdentity = physicalPathIdentity(bookRunsRoot);
5493
- const parentIdentity = physicalPathIdentity(dirname7(real));
5508
+ const parentIdentity = physicalPathIdentity(dirname8(real));
5494
5509
  if (parentIdentity !== runsRootIdentity) {
5495
5510
  throw new NotarySourceRunError(
5496
5511
  "notary --source-run must resolve to a retained run under the project machine-ledger book"
@@ -5525,7 +5540,7 @@ async function resolveNotarySourceRunLocator(options) {
5525
5540
  }
5526
5541
  async function loadNotarySourceRunLocator(path) {
5527
5542
  const real = await requireRunDirectory(path, path);
5528
- const identity = parseRunDirectoryName(basename4(real));
5543
+ const identity = parseRunDirectoryName(basename5(real));
5529
5544
  const runState = await readRoleRunIdentity(real);
5530
5545
  if (runState === void 0) {
5531
5546
  throw new NotarySourceRunError(
@@ -6631,7 +6646,7 @@ import {
6631
6646
  realpath as realpath5,
6632
6647
  writeFile as writeFile4
6633
6648
  } from "node:fs/promises";
6634
- import { basename as basename5, isAbsolute as isAbsolute6, join as join13, resolve as resolve9, sep as sep3 } from "node:path";
6649
+ import { basename as basename6, isAbsolute as isAbsolute6, join as join13, resolve as resolve9, sep as sep3 } from "node:path";
6635
6650
  function issueAdmissionPlacement(authority, request) {
6636
6651
  const principal = authority.issue(request);
6637
6652
  const { sessionDirectory, sessionFile } = authority.decode(principal);
@@ -7070,7 +7085,7 @@ async function freezeRegularFileAttachment(sourcePath, destinationDir, index) {
7070
7085
  );
7071
7086
  }
7072
7087
  const bytes = await readFile9(absolute);
7073
- const name = `${String(index).padStart(2, "0")}-${basename5(absolute)}`;
7088
+ const name = `${String(index).padStart(2, "0")}-${basename6(absolute)}`;
7074
7089
  const frozenPath = join13(destinationDir, name);
7075
7090
  await writeFile4(frozenPath, bytes);
7076
7091
  return {
@@ -8525,9 +8540,7 @@ async function admitMergerInvocation(options) {
8525
8540
  };
8526
8541
  }
8527
8542
  function buildMergerTransportPrompt(admitted, engineMaterial) {
8528
- const lines = [
8529
- `/skill:resolving-merge-conflicts ${admitted.instruction}`
8530
- ];
8543
+ const lines = [admitted.instruction];
8531
8544
  if (admitted.attachments.length > 0) {
8532
8545
  lines.push("");
8533
8546
  lines.push("\u5DF2\u53D7\u7406\u9644\u4EF6\uFF08\u51BB\u7ED3\u5FEB\u7167\u8DEF\u5F84\uFF09\uFF1A");
@@ -9568,7 +9581,7 @@ __export(config_exports, {
9568
9581
  validatePublicCliConfigAxes: () => validatePublicCliConfigAxes
9569
9582
  });
9570
9583
  import { mkdir as mkdir2, readFile as readFile10, writeFile as writeFile5 } from "node:fs/promises";
9571
- import { dirname as dirname8, join as join17 } from "node:path";
9584
+ import { dirname as dirname9, join as join17 } from "node:path";
9572
9585
  function isGateOfficerSeat(value) {
9573
9586
  return GATE_OFFICER_SEATS.includes(value);
9574
9587
  }
@@ -9592,7 +9605,7 @@ async function loadPublicCliConfig(home) {
9592
9605
  }
9593
9606
  async function savePublicCliConfig(config, home) {
9594
9607
  const path = publicCliConfigPath(home);
9595
- await mkdir2(dirname8(path), { recursive: true });
9608
+ await mkdir2(dirname9(path), { recursive: true });
9596
9609
  const normalized = parsePublicCliConfig(config);
9597
9610
  await writeFile5(
9598
9611
  path,
@@ -10329,7 +10342,7 @@ var init_case_dossier_delivery = __esm({
10329
10342
 
10330
10343
  // src/host-transition-prior-native.ts
10331
10344
  import { access as access2, readdir as readdir3 } from "node:fs/promises";
10332
- import { dirname as dirname9, join as join19 } from "node:path";
10345
+ import { dirname as dirname10, join as join19 } from "node:path";
10333
10346
  function isEnoent2(error) {
10334
10347
  return typeof error === "object" && error !== null && error.code === "ENOENT";
10335
10348
  }
@@ -10343,7 +10356,7 @@ async function listPiNativeRecordPaths(sessionFile) {
10343
10356
  }
10344
10357
  }
10345
10358
  async function listSitianRecordPaths(sessionParent) {
10346
- const sessionRoot = dirname9(sessionParent);
10359
+ const sessionRoot = dirname10(sessionParent);
10347
10360
  let entries;
10348
10361
  try {
10349
10362
  entries = await readdir3(sessionRoot, { withFileTypes: true });
@@ -10421,9 +10434,9 @@ var init_public_run_credentials = __esm({
10421
10434
  });
10422
10435
 
10423
10436
  // src/run-terminal-artifacts.ts
10424
- import { basename as basename6, dirname as dirname10, join as join20 } from "node:path";
10437
+ import { basename as basename7, dirname as dirname11, join as join20 } from "node:path";
10425
10438
  function runIdFromRunDirectory(runDirectory) {
10426
- const name = basename6(runDirectory);
10439
+ const name = basename7(runDirectory);
10427
10440
  const at = name.lastIndexOf("@");
10428
10441
  if (at <= 0 || at === name.length - 1) return void 0;
10429
10442
  return name.slice(0, at);
@@ -11131,15 +11144,15 @@ var init_analyst_gate_cycles_read = __esm({
11131
11144
  // src/session-opening-materials.ts
11132
11145
  import { existsSync as existsSync7 } from "node:fs";
11133
11146
  import { readFile as readFile12 } from "node:fs/promises";
11134
- import { dirname as dirname11, join as join22 } from "node:path";
11147
+ import { dirname as dirname12, join as join22 } from "node:path";
11135
11148
  import { fileURLToPath, pathToFileURL as pathToFileURL3 } from "node:url";
11136
11149
  function resolvePackageRootDir(moduleUrl = import.meta.url) {
11137
- let dir = dirname11(fileURLToPath(moduleUrl));
11150
+ let dir = dirname12(fileURLToPath(moduleUrl));
11138
11151
  for (let i = 0; i < 8; i += 1) {
11139
11152
  if (existsSync7(join22(dir, "package.json")) && existsSync7(join22(dir, "souls"))) {
11140
11153
  return dir;
11141
11154
  }
11142
- const parent = dirname11(dir);
11155
+ const parent = dirname12(dir);
11143
11156
  if (parent === dir) break;
11144
11157
  dir = parent;
11145
11158
  }
@@ -14066,7 +14079,7 @@ var init_terminal = __esm({
14066
14079
  // src/public-cli/settlement.ts
14067
14080
  import { randomUUID as randomUUID3 } from "node:crypto";
14068
14081
  import { appendFile as appendFile2, readFile as readFile15, readdir as readdir5, writeFile as writeFile6 } from "node:fs/promises";
14069
- import { dirname as dirname12, join as join25 } from "node:path";
14082
+ import { dirname as dirname13, join as join25 } from "node:path";
14070
14083
  function sealedLedgerHome(admitted) {
14071
14084
  return homeFromRunDirectory(admitted.runDirectory);
14072
14085
  }
@@ -14455,7 +14468,7 @@ async function readSitianRetainedAuditorProviderStop(sessionFile) {
14455
14468
  kind: "auditor",
14456
14469
  sessionParent: sessionFile,
14457
14470
  // Path is driven by sessionParent when under ledger home; cwd is a fallback only.
14458
- cwd: dirname12(sessionFile)
14471
+ cwd: dirname13(sessionFile)
14459
14472
  });
14460
14473
  const { records: records2 } = await readSitianRecords(recordFile);
14461
14474
  for (let i = records2.length - 1; i >= 0; i -= 1) {
@@ -14481,7 +14494,7 @@ async function readSessionProviderStop(sessionFile) {
14481
14494
  }
14482
14495
  }
14483
14496
  async function readBoundEvidenceChildKnownFailure(sessionFile) {
14484
- const childDirectory = join25(dirname12(sessionFile), "evidence-children");
14497
+ const childDirectory = join25(dirname13(sessionFile), "evidence-children");
14485
14498
  let names;
14486
14499
  try {
14487
14500
  names = await readdir5(childDirectory);
@@ -14546,7 +14559,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
14546
14559
  latestParentUserIndex = i;
14547
14560
  break;
14548
14561
  }
14549
- const childDirectories = [join25(dirname12(sessionFile), "auditor-roles")];
14562
+ const childDirectories = [join25(dirname13(sessionFile), "auditor-roles")];
14550
14563
  const valid = [];
14551
14564
  let sawAnyDirectory = false;
14552
14565
  for (const childDirectory of childDirectories) {
@@ -15495,7 +15508,7 @@ function publicationAttemptFromError(path, error) {
15495
15508
  }
15496
15509
  function uniqueFailureFallbackDirs(runDirectory, baseDir) {
15497
15510
  const dirs = [];
15498
- for (const dir of [baseDir, runDirectory, dirname12(runDirectory)]) {
15511
+ for (const dir of [baseDir, runDirectory, dirname13(runDirectory)]) {
15499
15512
  if (!dirs.includes(dir)) dirs.push(dir);
15500
15513
  }
15501
15514
  return dirs;
@@ -18452,7 +18465,7 @@ __export(archivist_record_entry_exports, {
18452
18465
  subjectKeyedRecordDirectory: () => subjectKeyedRecordDirectory
18453
18466
  });
18454
18467
  import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
18455
- import { dirname as dirname13, resolve as resolve13, join as join30 } from "node:path";
18468
+ import { dirname as dirname14, resolve as resolve13, join as join30 } from "node:path";
18456
18469
  import { SessionManager } from "@earendil-works/pi-coding-agent";
18457
18470
  function readCurrentSession(sessionDir) {
18458
18471
  const ledger = join30(sessionDir, CURRENT_SESSION_LEDGER);
@@ -18531,7 +18544,7 @@ function createRecordSessionOpen(options) {
18531
18544
  return { session: SessionManager.inMemory(cwd), resumed: false };
18532
18545
  } else {
18533
18546
  const parentResolved = resolve13(parentFile);
18534
- sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join30(dirname13(parentResolved), options.kind) : join30(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
18547
+ sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join30(dirname14(parentResolved), options.kind) : join30(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
18535
18548
  parentSession = parentFile;
18536
18549
  }
18537
18550
  const nestAlreadyExists = existsSync10(sessionDir);
@@ -18570,7 +18583,7 @@ function createRecordSession(options) {
18570
18583
  return createRecordSessionOpen(options).session;
18571
18584
  }
18572
18585
  function bookDirectOfficerRunPointer(options) {
18573
- const nest = join30(dirname13(options.parentSessionFile), "auditor-roles");
18586
+ const nest = join30(dirname14(options.parentSessionFile), "auditor-roles");
18574
18587
  mkdirSync4(nest, { recursive: true });
18575
18588
  const pointer = {
18576
18589
  version: 1,
@@ -20001,7 +20014,7 @@ import {
20001
20014
  openSync,
20002
20015
  writeSync
20003
20016
  } from "node:fs";
20004
- import { dirname as dirname16, isAbsolute as isAbsolute9, resolve as resolve17 } from "node:path";
20017
+ import { dirname as dirname17, isAbsolute as isAbsolute9, resolve as resolve17 } from "node:path";
20005
20018
  function correlationIdentityFromEnv(env = process.env) {
20006
20019
  const raw = env.AK_CORRELATION_ID;
20007
20020
  if (typeof raw === "string" && raw.trim().length > 0) {
@@ -20037,7 +20050,7 @@ function appendActivationLedgerLine(ledgerPath, line2, options) {
20037
20050
  }
20038
20051
  const resolvedLedger = resolve17(ledgerPath);
20039
20052
  const resolvedHome = resolve17(options.ledgerHome);
20040
- const parent = dirname16(resolvedLedger);
20053
+ const parent = dirname17(resolvedLedger);
20041
20054
  ensureRealDirectoryTree(resolvedHome, parent);
20042
20055
  assertLedgerFileInsideHome(resolvedLedger, resolvedHome);
20043
20056
  if (typeof constants2.O_NOFOLLOW !== "number") {
@@ -20281,9 +20294,9 @@ var init_tool_execution_observation = __esm({
20281
20294
  // src/atomic-write.ts
20282
20295
  import { randomUUID as randomUUID6 } from "node:crypto";
20283
20296
  import { rename, rm as rm2, writeFile as writeFile8 } from "node:fs/promises";
20284
- import { dirname as dirname17, join as join32 } from "node:path";
20297
+ import { dirname as dirname18, join as join32 } from "node:path";
20285
20298
  async function writeFileAtomically(destination, contents) {
20286
- const parent = dirname17(destination);
20299
+ const parent = dirname18(destination);
20287
20300
  const temporary = join32(parent, `.atomic-write-${randomUUID6()}.tmp`);
20288
20301
  try {
20289
20302
  await writeFile8(temporary, contents);
@@ -22573,6 +22586,10 @@ function createCoderRoleRuntime(pi, dependencies, hostActions) {
22573
22586
  });
22574
22587
  return {
22575
22588
  async activate(ctx) {
22589
+ tddInvocationInjected = false;
22590
+ originalRequest = void 0;
22591
+ expansionPending = false;
22592
+ expansionCaptured = false;
22576
22593
  soul = (await dependencies.loadSoul()).trim();
22577
22594
  if (soul.length === 0) throw new Error("Coder soul is empty");
22578
22595
  const selectedPhase = pi.getFlag("ak-coder-phase");
@@ -22655,17 +22672,8 @@ function createCoderRoleRuntime(pi, dependencies, hostActions) {
22655
22672
  }
22656
22673
  tddInvocationInjected = true;
22657
22674
  expansionPending = true;
22658
- const isNativeTdd = event.text === "/skill:tdd" || event.text.startsWith("/skill:tdd ");
22659
- if (isNativeTdd) {
22660
- originalRequest = event.text.slice("/skill:tdd".length).trim();
22661
- return { action: "continue" };
22662
- }
22663
- originalRequest = event.text.trim();
22664
- return {
22665
- action: "transform",
22666
- text: binding?.invocation(event.text) ?? `/skill:tdd ${event.text}`,
22667
- ...event.images === void 0 ? {} : { images: event.images }
22668
- };
22675
+ originalRequest = binding === void 0 ? event.text : pi.capabilities?.skillOriginalRequest?.(binding.name, event.text) ?? event.text;
22676
+ return { action: "continue" };
22669
22677
  });
22670
22678
  pi.on("before_agent_start", (event, ctx2) => {
22671
22679
  if (soul === void 0) throw new Error("\u5C06\u4F5C\u76D1\u804C\u5206\u672A\u88C5\u8F7D");
@@ -23438,12 +23446,11 @@ function createRoleRuntimeExtension(dependencies) {
23438
23446
  const role = roleHost.getFlag(ROLE_FLAG.name);
23439
23447
  if (role !== void 0 && !admitted) return { action: "handled" };
23440
23448
  if (role === "reviewer" && admitted && activeReviewerParent !== void 0 && reviewerOriginalRequest === void 0) {
23441
- reviewerOriginalRequest = event.text;
23442
- return {
23443
- action: "transform",
23444
- text: activeReviewerParent.skillBinding.invocation(event.text),
23445
- ...event.images === void 0 ? {} : { images: event.images }
23446
- };
23449
+ reviewerOriginalRequest = roleHost.capabilities?.skillOriginalRequest?.(
23450
+ activeReviewerParent.skillBinding.name,
23451
+ event.text
23452
+ ) ?? event.text;
23453
+ return { action: "continue" };
23447
23454
  }
23448
23455
  return { action: "continue" };
23449
23456
  });
@@ -24434,6 +24441,16 @@ function createPiRoleHostAdapter(pi, options = {}) {
24434
24441
  content: parsed.content,
24435
24442
  userMessage
24436
24443
  });
24444
+ },
24445
+ /** Recover plain original request from Pi-native `/skill:` turn text (ADR 0082). */
24446
+ skillOriginalRequest(name, text) {
24447
+ const token = `/skill:${name}`;
24448
+ const trimmed = text.trimStart();
24449
+ if (trimmed === token || trimmed.startsWith(`${token} `) || trimmed.startsWith(`${token}
24450
+ `)) {
24451
+ return text.slice(text.indexOf(token) + token.length).trim();
24452
+ }
24453
+ return text.trim();
24437
24454
  }
24438
24455
  },
24439
24456
  registerFlag: (name, definition) => pi.registerFlag(name, definition),
@@ -25758,9 +25775,6 @@ async function loadCanonicalSkillBinding(name) {
25758
25775
  const binding = {
25759
25776
  name,
25760
25777
  snapshot,
25761
- invocation(originalRequest) {
25762
- return `/skill:${name} ${originalRequest}`;
25763
- },
25764
25778
  captureExpansion(evidence, originalRequest) {
25765
25779
  return captureCanonicalSkillExpansion(
25766
25780
  name,
@@ -25879,7 +25893,7 @@ async function loadNavigatorWorkContext(options) {
25879
25893
  init_notary_source_run();
25880
25894
 
25881
25895
  // src/package-resources/method-skill-binding.ts
25882
- import { dirname as dirname15 } from "node:path";
25896
+ import { dirname as dirname16 } from "node:path";
25883
25897
  init_method_skill();
25884
25898
  async function loadPackagedCanonicalSkillBinding(packageRoot, name) {
25885
25899
  const material = await loadPackagedMethodSkillMaterial(packageRoot, name);
@@ -25887,16 +25901,13 @@ async function loadPackagedCanonicalSkillBinding(packageRoot, name) {
25887
25901
  const snapshot = Object.freeze({
25888
25902
  raw: material.raw,
25889
25903
  path: material.skillPath,
25890
- baseDir: dirname15(material.skillPath),
25904
+ baseDir: dirname16(material.skillPath),
25891
25905
  body: material.body,
25892
25906
  snapshotIdentity: Object.freeze({ text: material.raw })
25893
25907
  });
25894
25908
  const binding = {
25895
25909
  name,
25896
25910
  snapshot,
25897
- invocation(originalRequest) {
25898
- return `/skill:${name} ${originalRequest}`;
25899
- },
25900
25911
  captureExpansion(evidence, originalRequest) {
25901
25912
  return captureCanonicalSkillExpansion(
25902
25913
  name,
@@ -25925,7 +25936,7 @@ init_role_runtime();
25925
25936
  import { randomUUID as randomUUID7 } from "node:crypto";
25926
25937
  import { mkdir as mkdir5, readFile as readFile19, writeFile as writeFile9 } from "node:fs/promises";
25927
25938
  import { createServer } from "node:net";
25928
- import { basename as basename7, dirname as dirname18, join as join37 } from "node:path";
25939
+ import { basename as basename8, dirname as dirname19, join as join37 } from "node:path";
25929
25940
  import { fileURLToPath as fileURLToPath2 } from "node:url";
25930
25941
 
25931
25942
  // src/acp-host/role-turn-host.ts
@@ -25937,23 +25948,19 @@ function renderAcpSystemPromptOverride(authority) {
25937
25948
  // src/acp-host/role-envelope.ts
25938
25949
  init_submission_correctable_error();
25939
25950
  init_navigator_invocation_identity();
25940
- function parseCanonicalSkillInvocation(prompt) {
25941
- const match = /^\/skill:([A-Za-z0-9_-]+)(?:\s+([\s\S]*))?$/s.exec(prompt.trim());
25942
- if (match === null) return void 0;
25943
- return { name: match[1], userMessage: (match[2] ?? "").trim() };
25944
- }
25945
25951
  function buildAcpSkillExpansion(methodSkills, prompt) {
25946
- const parsed = parseCanonicalSkillInvocation(prompt);
25947
- if (parsed === void 0) return void 0;
25948
- const method = methodSkills.get(parsed.name);
25949
- if (method === void 0) return void 0;
25952
+ if (methodSkills.size !== 1) return void 0;
25953
+ const entry = methodSkills.entries().next().value;
25954
+ if (entry === void 0) return void 0;
25955
+ const [name, method] = entry;
25950
25956
  return Object.freeze({
25951
- name: parsed.name,
25957
+ name,
25952
25958
  location: method.path,
25953
- content: `References are relative to ${dirname18(method.path)}.
25959
+ content: `References are relative to ${dirname19(method.path)}.
25954
25960
 
25955
25961
  ${method.body}`,
25956
- userMessage: parsed.userMessage
25962
+ // Non-pi typed chain keeps original task bytes (ticket #822 r3); no consumer trim.
25963
+ userMessage: prompt
25957
25964
  });
25958
25965
  }
25959
25966
  function projectAcpActivationFlags(request) {
@@ -26027,12 +26034,12 @@ async function prepareAcpRoleEnvelope(options) {
26027
26034
  await mkdir5(request.runDirectory, { recursive: true });
26028
26035
  for (const method of request.methods) {
26029
26036
  if (method.kind !== "skill") continue;
26030
- const name = basename7(dirname18(method.path));
26037
+ const name = basename8(dirname19(method.path));
26031
26038
  const raw = await readFile19(method.path, "utf8");
26032
26039
  methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
26033
26040
  }
26034
26041
  let sessionFile = options.sessionFile ?? join37(request.runDirectory, "session", "session.jsonl");
26035
- await mkdir5(dirname18(sessionFile), { recursive: true });
26042
+ await mkdir5(dirname19(sessionFile), { recursive: true });
26036
26043
  if (request.continuation.kind !== "resume") {
26037
26044
  try {
26038
26045
  await writeFile9(
@@ -26059,7 +26066,7 @@ async function prepareAcpRoleEnvelope(options) {
26059
26066
  getLeafEntry: () => sessionEntries.at(-1),
26060
26067
  getLeafId: () => runId,
26061
26068
  getEntries: () => sessionEntries,
26062
- getSessionDir: () => dirname18(sessionFile),
26069
+ getSessionDir: () => dirname19(sessionFile),
26063
26070
  getSessionFile: () => sessionFile,
26064
26071
  getHeader: () => ({ type: "session", id: runId }),
26065
26072
  setSessionFile(path) {
@@ -26517,7 +26524,7 @@ async function prepareAcpRoleEnvelope(options) {
26517
26524
 
26518
26525
  // src/acp-host/session-identity.ts
26519
26526
  import { mkdir as mkdir6, readFile as readFile20, rename as rename2, writeFile as writeFile10 } from "node:fs/promises";
26520
- import { dirname as dirname19, join as join38 } from "node:path";
26527
+ import { dirname as dirname20, join as join38 } from "node:path";
26521
26528
  function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
26522
26529
  const bindingPath = (principal) => join38(authority.decode(principal).sessionDirectory, sessionBindingFile);
26523
26530
  return {
@@ -26538,7 +26545,7 @@ function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
26538
26545
  },
26539
26546
  async bind(principal, sessionId) {
26540
26547
  const target = bindingPath(principal);
26541
- await mkdir6(dirname19(target), { recursive: true });
26548
+ await mkdir6(dirname20(target), { recursive: true });
26542
26549
  const temporary = `${target}.${process.pid}.tmp`;
26543
26550
  await writeFile10(temporary, `${JSON.stringify({ sessionId })}
26544
26551
  `, { encoding: "utf8", mode: 384 });
@@ -106,6 +106,17 @@ export function createPiRoleHostAdapter(pi, options = {}) {
106
106
  userMessage,
107
107
  });
108
108
  },
109
+ /** Recover plain original request from Pi-native `/skill:` turn text (ADR 0082). */
110
+ skillOriginalRequest(name, text) {
111
+ const token = `/skill:${name}`;
112
+ const trimmed = text.trimStart();
113
+ if (trimmed === token
114
+ || trimmed.startsWith(`${token} `)
115
+ || trimmed.startsWith(`${token}\n`)) {
116
+ return text.slice(text.indexOf(token) + token.length).trim();
117
+ }
118
+ return text.trim();
119
+ },
109
120
  },
110
121
  registerFlag: (name, definition) => pi.registerFlag(name, definition),
111
122
  getFlag: (name) => pi.getFlag(name),
@@ -6,7 +6,7 @@
6
6
  import { execFile, spawn } from "node:child_process";
7
7
  import { constants } from "node:fs";
8
8
  import { access, appendFile, readFile, realpath } from "node:fs/promises";
9
- import { delimiter, isAbsolute, join, resolve } from "node:path";
9
+ import { basename, delimiter, dirname, isAbsolute, join, resolve } from "node:path";
10
10
  import { platform } from "node:process";
11
11
  import { promisify } from "node:util";
12
12
  import { randomUUID } from "node:crypto";
@@ -144,18 +144,41 @@ function buildMethodArgs(methods) {
144
144
  }
145
145
  return skillArgs;
146
146
  }
147
+ /**
148
+ * Pi-native `/skill:<name>` for a single forced method (ADR 0082 `pi-no-privilege`).
149
+ * Driven by typed RoleTurnRequest.methods — middle-layer decision, Pi-only syntax.
150
+ * Zero/many methods leave the prompt alone (Fixer optional pair stays `--skill` only).
151
+ */
152
+ export function applyPiNativeSkillInvocation(methods, prompt) {
153
+ const skills = methods.filter((method) => method.kind === "skill");
154
+ if (skills.length !== 1)
155
+ return prompt;
156
+ const name = basename(dirname(skills[0].path));
157
+ if (name.length === 0)
158
+ return prompt;
159
+ const token = `/skill:${name}`;
160
+ const trimmed = prompt.trimStart();
161
+ if (trimmed === token
162
+ || trimmed.startsWith(`${token} `)
163
+ || trimmed.startsWith(`${token}\n`)) {
164
+ return prompt;
165
+ }
166
+ return prompt.length === 0 ? token : `${token} ${prompt}`;
167
+ }
147
168
  /**
148
169
  * Translate a closed RoleTurnRequest into Pi argv after `--no-extensions -e entry`.
149
170
  * Controlled session constants and session coordinates are adapter-internal.
171
+ * Single forced method → Pi-native `/skill:` on the argv prompt (coder/reviewer/merger).
150
172
  */
151
173
  export function buildPiTurnExtraArgs(request, authority, extraPiArgs = []) {
152
174
  const { sessionFile, sessionDirectory } = authority.decode(request.principal);
153
- const prompt = request.continuation.kind === "initial" || request.continuation.kind === "resume"
175
+ const rawPrompt = request.continuation.kind === "initial" || request.continuation.kind === "resume"
154
176
  ? request.continuation.prompt
155
177
  : (() => {
156
178
  const _exhaustive = request.continuation;
157
179
  return _exhaustive;
158
180
  })();
181
+ const prompt = applyPiNativeSkillInvocation(request.methods, rawPrompt);
159
182
  return [
160
183
  "--no-skills",
161
184
  ...buildMethodArgs(request.methods),
@@ -2025,13 +2025,12 @@ export async function admitMergerInvocation(options) {
2025
2025
  };
2026
2026
  }
2027
2027
  /**
2028
- * Build the Pi prompt transport for an admitted Merger request.
2029
- * Every invocation forces package merge-only method expansion before conflict work.
2028
+ * Build the host-neutral prompt transport for an admitted Merger request.
2029
+ * Method material binds on RoleTurnRequest.methods; Pi-native `/skill:` form
2030
+ * is adapter-internal only (ADR 0082).
2030
2031
  */
2031
2032
  export function buildMergerTransportPrompt(admitted, engineMaterial) {
2032
- const lines = [
2033
- `/skill:resolving-merge-conflicts ${admitted.instruction}`,
2034
- ];
2033
+ const lines = [admitted.instruction];
2035
2034
  if (admitted.attachments.length > 0) {
2036
2035
  lines.push("");
2037
2036
  lines.push("已受理附件(冻结快照路径):");