@akagilnc/pi-workflow-roles 0.1.3549 → 0.1.3552

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.
@@ -6952,6 +6952,16 @@ var SUPPORT_COMMAND_HELP = {
6952
6952
  "ak-role --host grok-build resume 01abc\u2026",
6953
6953
  "ak-role --engine agy resume 01abc\u2026"
6954
6954
  ]
6955
+ },
6956
+ new: {
6957
+ command: "new",
6958
+ summary: "Explicit fresh summons: same role options as a direct call, but always mint a new run (skip same-ticket auto-resume). Caller chooses new vs resume; no overflow judgment.",
6959
+ usage: ["ak-role new <role> [options] \u2026"],
6960
+ examples: [
6961
+ 'ak-role new countersign --attach ./ticket.md "\u88C1\uFF1A\u672C\u7968 #708 \u662F\u5426\u8DB3\u4EE5\u5F00\u5DE5\u3002"',
6962
+ "ak-role new notary --source-run 01abc\u2026@countersign",
6963
+ "ak-role --host grok-build new inspector --attach ./change.patch"
6964
+ ]
6955
6965
  }
6956
6966
  };
6957
6967
  var PUBLIC_COMMAND_HELP = {
@@ -15270,7 +15270,8 @@ var init_registry2 = __esm({
15270
15270
  "roles",
15271
15271
  "config",
15272
15272
  "help",
15273
- "resume"
15273
+ "resume",
15274
+ "new"
15274
15275
  ];
15275
15276
  STARTUP_CANDIDATES = {
15276
15277
  judge: [
@@ -19356,6 +19357,16 @@ var init_option_definitions = __esm({
19356
19357
  "ak-role --host grok-build resume 01abc\u2026",
19357
19358
  "ak-role --engine agy resume 01abc\u2026"
19358
19359
  ]
19360
+ },
19361
+ new: {
19362
+ command: "new",
19363
+ summary: "Explicit fresh summons: same role options as a direct call, but always mint a new run (skip same-ticket auto-resume). Caller chooses new vs resume; no overflow judgment.",
19364
+ usage: ["ak-role new <role> [options] \u2026"],
19365
+ examples: [
19366
+ 'ak-role new countersign --attach ./ticket.md "\u88C1\uFF1A\u672C\u7968 #708 \u662F\u5426\u8DB3\u4EE5\u5F00\u5DE5\u3002"',
19367
+ "ak-role new notary --source-run 01abc\u2026@countersign",
19368
+ "ak-role --host grok-build new inspector --attach ./change.patch"
19369
+ ]
19359
19370
  }
19360
19371
  };
19361
19372
  PUBLIC_COMMAND_HELP = {
@@ -23705,6 +23716,7 @@ async function resolveSeatTicketBinding(admitted, env = {}) {
23705
23716
  return resolution;
23706
23717
  }
23707
23718
  async function tryResumeSameTicketSeatRun(input) {
23719
+ if (input.freshSummons === true) return void 0;
23708
23720
  const previousRunId = await findLatestRunIdForSeatTicket({
23709
23721
  home: input.home,
23710
23722
  bookKey: resolveBookKeyFromGit(input.projectRoot),
@@ -29353,6 +29365,7 @@ async function runPublicCountersign(argv, env, io, parseCountersignArgv2) {
29353
29365
  projectRoot,
29354
29366
  role: "countersign",
29355
29367
  ticketNumber: probedTicketNumber,
29368
+ freshSummons: env.freshSummons,
29356
29369
  summons,
29357
29370
  resume: (runId, materials) => runPublicCountersignResume(
29358
29371
  { runId, ...materials === void 0 ? {} : { summons: materials } },
@@ -29978,6 +29991,7 @@ async function runPublicNotary(argv, env, io, parseNotaryArgv2) {
29978
29991
  projectRoot,
29979
29992
  role: "notary",
29980
29993
  ticketNumber,
29994
+ freshSummons: env.freshSummons,
29981
29995
  summons,
29982
29996
  resume: (runId, materials) => runPublicNotaryResume(
29983
29997
  { runId, ...materials === void 0 ? {} : { summons: materials } },
@@ -30133,6 +30147,7 @@ async function runPublicInspector(argv, env, io, parseInspectorArgv2) {
30133
30147
  projectRoot,
30134
30148
  role: "inspector",
30135
30149
  ticketNumber: probedTicketNumber,
30150
+ freshSummons: env.freshSummons,
30136
30151
  summons,
30137
30152
  resume: (runId, materials) => runPublicInspectorResume(
30138
30153
  { runId, ...materials === void 0 ? {} : { summons: materials } },
@@ -33060,7 +33075,8 @@ function createRoleEnvironment(env, options) {
33060
33075
  ...projectSeatHost(options.seat),
33061
33076
  ...timeoutMs === void 0 ? {} : { timeoutMs },
33062
33077
  ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId },
33063
- ...options.config?.autoResumeLimit === void 0 ? {} : { autoResumeLimit: options.config.autoResumeLimit }
33078
+ ...options.config?.autoResumeLimit === void 0 ? {} : { autoResumeLimit: options.config.autoResumeLimit },
33079
+ ...env.freshSummons === true ? { freshSummons: true } : {}
33064
33080
  };
33065
33081
  }
33066
33082
  function cliResultFromRoleRun(result2) {
@@ -33547,8 +33563,8 @@ async function runAkRole(argv, env) {
33547
33563
  packageRoot: await realpath6(env.packageRoot),
33548
33564
  principalAuthority: env.principalAuthority ?? piDurablePrincipalAuthority
33549
33565
  };
33550
- const parsed = parseArgv(argv);
33551
- const acceptsSeatAxes = parsed.command !== void 0 && (isPublicCallableRole(parsed.command) || parsed.command === "resume");
33566
+ let parsed = parseArgv(argv);
33567
+ const acceptsSeatAxes = parsed.command !== void 0 && (isPublicCallableRole(parsed.command) || parsed.command === "resume" || parsed.command === "new");
33552
33568
  if (parsed.host !== void 0 && !parsed.help && parsed.command !== void 0 && parsed.command !== "help" && !acceptsSeatAxes) {
33553
33569
  throw new CliUsageError(`host axis is role commands only; refused command ${parsed.command}`);
33554
33570
  }
@@ -33593,6 +33609,21 @@ async function runAkRole(argv, env) {
33593
33609
  exitCode: await runConfigCommand(parsed.args, home, env.packageRoot, io)
33594
33610
  };
33595
33611
  }
33612
+ if (parsed.command === "new") {
33613
+ const role = parsed.args[0];
33614
+ if (role === void 0) {
33615
+ throw new CliUsageError("usage: ak-role new <role> \u2026");
33616
+ }
33617
+ if (!isPublicCallableRole(role)) {
33618
+ throw new CliUsageError(`usage: ak-role new <role> \u2026; unknown role: ${role}`);
33619
+ }
33620
+ parsed = {
33621
+ ...parsed,
33622
+ command: role,
33623
+ args: parsed.args.slice(1)
33624
+ };
33625
+ env = { ...env, freshSummons: true };
33626
+ }
33596
33627
  if (parsed.command === "resume") {
33597
33628
  const agentDir = resolveAgentDir(env, home);
33598
33629
  const cwd = env.cwd ?? process.cwd();
@@ -33622,7 +33653,7 @@ async function runAkRole(argv, env) {
33622
33653
  );
33623
33654
  return cliResultFromRoleRun(result2);
33624
33655
  }
33625
- if (isPublicCliSupportCommand(parsed.command)) {
33656
+ if (parsed.command !== void 0 && isPublicCliSupportCommand(parsed.command)) {
33626
33657
  throw new CliUsageError(`unhandled support command: ${parsed.command}`);
33627
33658
  }
33628
33659
  if (parsed.command === "judge") {
@@ -12,7 +12,8 @@ const PUBLIC_CLI_SUPPORT_COMMANDS = [
12
12
  "roles",
13
13
  "config",
14
14
  "help",
15
- "resume"
15
+ "resume",
16
+ "new"
16
17
  ];
17
18
  function seatModelOnly(seat) {
18
19
  if (seat?.provider === void 0 || seat.model === void 0) return void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.3549",
3
+ "version": "0.1.3552",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -294,6 +294,11 @@ export type CliEnv = {
294
294
  /** Override Notary role-run timeout (tests). */
295
295
  notaryTimeoutMs?: number;
296
296
  createRunId?: () => string;
297
+ /**
298
+ * #724: set by the `new` support verb before role dispatch; seat runners
299
+ * skip same-ticket auto-resume. Not a public flag — the verb is the choice.
300
+ */
301
+ freshSummons?: true;
297
302
  };
298
303
 
299
304
  /** Compose the Pi turn host for one role dispatch (sole public-cli → pi contact). */
@@ -437,6 +442,7 @@ function createRoleEnvironment(
437
442
  ...(options.config?.autoResumeLimit === undefined
438
443
  ? {}
439
444
  : { autoResumeLimit: options.config.autoResumeLimit }),
445
+ ...(env.freshSummons === true ? { freshSummons: true as const } : {}),
440
446
  };
441
447
  }
442
448
 
@@ -1084,12 +1090,14 @@ export async function runAkRole(
1084
1090
  packageRoot: await realpath(env.packageRoot),
1085
1091
  principalAuthority: env.principalAuthority ?? piDurablePrincipalAuthority,
1086
1092
  };
1087
- const parsed = parseArgv(argv);
1088
- // Host/engine axes: callable roles + resume (#617 DK-3: resume shares seat axes).
1093
+ let parsed = parseArgv(argv);
1094
+ // Host/engine axes: callable roles + resume + new (#617 DK-3; #724 new shares seat axes).
1089
1095
  // Support commands (roles/config/…) still refuse both flags.
1090
1096
  const acceptsSeatAxes =
1091
1097
  parsed.command !== undefined &&
1092
- (isPublicCallableRole(parsed.command) || parsed.command === "resume");
1098
+ (isPublicCallableRole(parsed.command) ||
1099
+ parsed.command === "resume" ||
1100
+ parsed.command === "new");
1093
1101
  if (
1094
1102
  parsed.host !== undefined &&
1095
1103
  !parsed.help &&
@@ -1160,6 +1168,24 @@ export async function runAkRole(
1160
1168
  };
1161
1169
  }
1162
1170
 
1171
+ // #724 explicit fresh summons: `ak-role new <role> …` — same role argv, always mint.
1172
+ // Rewrites onto the role command with freshSummons; auto-resume and resume stay intact.
1173
+ if (parsed.command === "new") {
1174
+ const role = parsed.args[0];
1175
+ if (role === undefined) {
1176
+ throw new CliUsageError("usage: ak-role new <role> …");
1177
+ }
1178
+ if (!isPublicCallableRole(role)) {
1179
+ throw new CliUsageError(`usage: ak-role new <role> …; unknown role: ${role}`);
1180
+ }
1181
+ parsed = {
1182
+ ...parsed,
1183
+ command: role,
1184
+ args: parsed.args.slice(1),
1185
+ };
1186
+ env = { ...env, freshSummons: true };
1187
+ }
1188
+
1163
1189
  // Resume reopens an exact Role run (#416): caller decides; session principal
1164
1190
  // must still exist. Seat and dispatch follow the durable admitted role.
1165
1191
  // #471: unique parser owns {runId, message?}; five role paths only consume it.
@@ -1202,7 +1228,10 @@ export async function runAkRole(
1202
1228
  return cliResultFromRoleRun(result);
1203
1229
  }
1204
1230
 
1205
- if (isPublicCliSupportCommand(parsed.command)) {
1231
+ if (
1232
+ parsed.command !== undefined &&
1233
+ isPublicCliSupportCommand(parsed.command)
1234
+ ) {
1206
1235
  throw new CliUsageError(`unhandled support command: ${parsed.command}`);
1207
1236
  }
1208
1237
 
@@ -122,6 +122,7 @@ export async function runPublicCountersign(
122
122
  projectRoot,
123
123
  role: "countersign",
124
124
  ticketNumber: probedTicketNumber,
125
+ freshSummons: env.freshSummons,
125
126
  summons,
126
127
  resume: (runId, materials) =>
127
128
  runPublicCountersignResume(
@@ -109,6 +109,7 @@ export async function runPublicInspector(
109
109
  projectRoot,
110
110
  role: "inspector",
111
111
  ticketNumber: probedTicketNumber,
112
+ freshSummons: env.freshSummons,
112
113
  summons,
113
114
  resume: (runId, materials) =>
114
115
  runPublicInspectorResume(
@@ -119,6 +119,7 @@ export async function runPublicNotary(
119
119
  projectRoot,
120
120
  role: "notary",
121
121
  ticketNumber,
122
+ freshSummons: env.freshSummons,
122
123
  summons,
123
124
  resume: (runId, materials) =>
124
125
  runPublicNotaryResume(
@@ -1271,6 +1271,17 @@ const SUPPORT_COMMAND_HELP = {
1271
1271
  "ak-role --engine agy resume 01abc…",
1272
1272
  ],
1273
1273
  },
1274
+ new: {
1275
+ command: "new",
1276
+ summary:
1277
+ "Explicit fresh summons: same role options as a direct call, but always mint a new run (skip same-ticket auto-resume). Caller chooses new vs resume; no overflow judgment.",
1278
+ usage: ["ak-role new <role> [options] …"],
1279
+ examples: [
1280
+ 'ak-role new countersign --attach ./ticket.md "裁:本票 #708 是否足以开工。"',
1281
+ "ak-role new notary --source-run 01abc…@countersign",
1282
+ "ak-role --host grok-build new inspector --attach ./change.patch",
1283
+ ],
1284
+ },
1274
1285
  } as const satisfies Record<string, PublicCommandHelpFacts>;
1275
1286
 
1276
1287
  /**
@@ -110,6 +110,11 @@ export type PostAdmissionEnv = {
110
110
  sessionAppender: SessionCustomEntryAppender;
111
111
  autoResumeLimit?: number;
112
112
  createRunId?: () => string;
113
+ /**
114
+ * #724 explicit fresh summons (`ak-role new <role>`): skip same-ticket auto-resume
115
+ * and mint a new run. Absent on ordinary role commands and on `ak-role resume`.
116
+ */
117
+ freshSummons?: true;
113
118
  };
114
119
 
115
120
  /**
@@ -27,6 +27,7 @@ export const PUBLIC_CLI_SUPPORT_COMMANDS = [
27
27
  "config",
28
28
  "help",
29
29
  "resume",
30
+ "new",
30
31
  ] as const;
31
32
 
32
33
  export type PublicCliSupportCommand = (typeof PUBLIC_CLI_SUPPORT_COMMANDS)[number];
@@ -149,22 +149,26 @@ export async function resolveSeatTicketBinding(
149
149
  }
150
150
 
151
151
  /**
152
- * Shared same-ticket → resume decision (#637).
152
+ * Sole same-ticket → resume decision (#637 / #724).
153
153
  * Looks up the latest retained run for seat+ticket; when found, runs resume with
154
154
  * this summons' materials. Lookup/resume failures propagate (失败诚实) — never
155
- * wash into a fresh mint. Returns undefined only when no prior run exists.
155
+ * wash into a fresh mint. Returns undefined when the caller declared an explicit
156
+ * fresh summons (`ak-role new`) or when no prior run exists; both mint new.
157
+ * freshSummons is required so no seat can drift back into its own skip branch.
156
158
  */
157
159
  export async function tryResumeSameTicketSeatRun<T>(input: {
158
160
  readonly home: string;
159
161
  readonly projectRoot: string;
160
162
  readonly role: RoleRunRecord["role"];
161
163
  readonly ticketNumber: number;
164
+ readonly freshSummons: true | undefined;
162
165
  readonly summons?: SameTicketSummonsMaterials;
163
166
  readonly resume: (
164
167
  runId: string,
165
168
  summons: SameTicketSummonsMaterials | undefined,
166
169
  ) => Promise<T>;
167
170
  }): Promise<T | undefined> {
171
+ if (input.freshSummons === true) return undefined;
168
172
  const previousRunId = await findLatestRunIdForSeatTicket({
169
173
  home: input.home,
170
174
  bookKey: resolveBookKeyFromGit(input.projectRoot),