@akagilnc/pi-workflow-roles 0.1.3783 → 0.1.3795

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.
Files changed (37) hide show
  1. package/README.md +3 -1
  2. package/README.zh-CN.md +3 -1
  3. package/dist/acp-host/production-host.js +681 -269
  4. package/dist/atomic-write.js +23 -0
  5. package/dist/collector-evidence.js +4 -1
  6. package/dist/collector-github.js +1 -0
  7. package/dist/collector-handbook.js +142 -0
  8. package/dist/collector-identity.js +11 -0
  9. package/dist/collector-ledger.js +109 -63
  10. package/dist/collector-role.js +182 -18
  11. package/dist/collector-tool-schemas.js +40 -3
  12. package/dist/headless-host/production-host.js +682 -270
  13. package/dist/pi/role-turn-host.js +1 -0
  14. package/dist/public-cli/invocation.js +15 -0
  15. package/dist/public-cli/main.js +45 -77
  16. package/dist/public-cli/option-definitions.js +16 -2
  17. package/dist/public-cli/run-lifecycle.js +8 -0
  18. package/dist/role-runtime.js +3 -0
  19. package/extensions/role-runtime.ts +2 -0
  20. package/package.json +1 -1
  21. package/resources/collector-bot-handbook.md +33 -0
  22. package/src/acp-host/production-host.ts +4 -0
  23. package/src/acp-host/role-envelope.ts +1 -0
  24. package/src/collector-evidence.ts +6 -1
  25. package/src/collector-github.ts +3 -0
  26. package/src/collector-handbook.ts +194 -0
  27. package/src/collector-identity.ts +14 -0
  28. package/src/collector-ledger.ts +132 -80
  29. package/src/collector-role.ts +198 -14
  30. package/src/collector-tool-schemas.ts +42 -3
  31. package/src/host-contracts.ts +2 -0
  32. package/src/pi/role-turn-host.ts +1 -0
  33. package/src/public-cli/collector-run.ts +2 -0
  34. package/src/public-cli/invocation.ts +21 -0
  35. package/src/public-cli/option-definitions.ts +16 -2
  36. package/src/public-cli/run-lifecycle.ts +10 -0
  37. package/src/role-runtime.ts +5 -0
@@ -95,6 +95,7 @@ function buildActivationFlagArgs(activation) {
95
95
  ...(activation.requestManifestPath === undefined
96
96
  ? []
97
97
  : ["--ak-collector-request-manifest", activation.requestManifestPath]),
98
+ ...(activation.waitMs === undefined ? [] : ["--ak-collector-wait-ms", activation.waitMs]),
98
99
  ];
99
100
  case "doctor":
100
101
  return ["--ak-role", "doctor", "--ak-doctor-case", activation.casePath];
@@ -982,6 +982,7 @@ export function parseCollectorArgv(args) {
982
982
  let repo;
983
983
  let prNumber;
984
984
  let requestManifestPath;
985
+ let waitWindowMs;
985
986
  const positional = [];
986
987
  const tokens = [...args];
987
988
  const definitions = roleOptions("collector");
@@ -1014,6 +1015,17 @@ export function parseCollectorArgv(args) {
1014
1015
  requestManifestPath = requireOptionPath(taken.def.canonical, taken.value);
1015
1016
  continue;
1016
1017
  }
1018
+ if (taken.def.id === "wait-ms") {
1019
+ if (taken.value === undefined || !/^[1-9]\d*$/.test(taken.value.trim())) {
1020
+ throw new CliUsageError("--wait-ms requires a positive safe-integer millisecond value");
1021
+ }
1022
+ const parsed = Number(taken.value.trim());
1023
+ if (!Number.isSafeInteger(parsed) || parsed < 1) {
1024
+ throw new CliUsageError("--wait-ms requires a positive safe-integer millisecond value");
1025
+ }
1026
+ waitWindowMs = parsed;
1027
+ continue;
1028
+ }
1017
1029
  throw new CliUsageError(`unknown collector option: ${taken.def.canonical}`);
1018
1030
  }
1019
1031
  const token = tokens.shift();
@@ -1032,6 +1044,7 @@ export function parseCollectorArgv(args) {
1032
1044
  ...(project === undefined ? {} : { project }),
1033
1045
  ...(repo === undefined ? {} : { repo }),
1034
1046
  ...(requestManifestPath === undefined ? {} : { requestManifestPath }),
1047
+ ...(waitWindowMs === undefined ? {} : { waitWindowMs }),
1035
1048
  };
1036
1049
  }
1037
1050
  /**
@@ -1168,6 +1181,7 @@ export async function admitCollectorInvocation(options) {
1168
1181
  repository: repository.canonical,
1169
1182
  repositoryDisplay: repository.display,
1170
1183
  ...(requestManifestPath === undefined ? {} : { requestManifestPath }),
1184
+ ...(options.waitWindowMs === undefined ? {} : { waitWindowMs: options.waitWindowMs }),
1171
1185
  manifestDigest,
1172
1186
  attachments: attachments.map((a) => ({
1173
1187
  provenancePath: a.provenancePath,
@@ -1197,6 +1211,7 @@ export async function admitCollectorInvocation(options) {
1197
1211
  ...(prNumber === undefined ? {} : { prNumber }),
1198
1212
  repository,
1199
1213
  ...(requestManifestPath === undefined ? {} : { requestManifestPath }),
1214
+ ...(options.waitWindowMs === undefined ? {} : { waitWindowMs: options.waitWindowMs }),
1200
1215
  manifestDigest,
1201
1216
  };
1202
1217
  }
@@ -16645,7 +16645,8 @@ function buildActivationFlagArgs(activation) {
16645
16645
  "--ak-collector-repo",
16646
16646
  activation.repo,
16647
16647
  ...activation.pr === void 0 ? [] : ["--ak-collector-pr", activation.pr],
16648
- ...activation.requestManifestPath === void 0 ? [] : ["--ak-collector-request-manifest", activation.requestManifestPath]
16648
+ ...activation.requestManifestPath === void 0 ? [] : ["--ak-collector-request-manifest", activation.requestManifestPath],
16649
+ ...activation.waitMs === void 0 ? [] : ["--ak-collector-wait-ms", activation.waitMs]
16649
16650
  ];
16650
16651
  case "doctor":
16651
16652
  return ["--ak-role", "doctor", "--ak-doctor-case", activation.casePath];
@@ -18491,6 +18492,7 @@ async function loadResumableRunRecord(home, runId, authority) {
18491
18492
  let repositoryDisplay;
18492
18493
  let requestManifestPath;
18493
18494
  let manifestDigest;
18495
+ let waitWindowMs;
18494
18496
  let issueNumber;
18495
18497
  let caseRunsPath;
18496
18498
  let caseIdentity2;
@@ -18544,6 +18546,9 @@ async function loadResumableRunRecord(home, runId, authority) {
18544
18546
  if (typeof record4.manifestDigest === "string" && record4.manifestDigest.trim() !== "") {
18545
18547
  manifestDigest = record4.manifestDigest;
18546
18548
  }
18549
+ if (typeof record4.waitWindowMs === "number" && Number.isSafeInteger(record4.waitWindowMs) && record4.waitWindowMs >= 1) {
18550
+ waitWindowMs = record4.waitWindowMs;
18551
+ }
18547
18552
  if (typeof record4.issueNumber === "number" && Number.isSafeInteger(record4.issueNumber) && record4.issueNumber >= 1) {
18548
18553
  issueNumber = record4.issueNumber;
18549
18554
  }
@@ -18659,6 +18664,7 @@ async function loadResumableRunRecord(home, runId, authority) {
18659
18664
  ...repositoryDisplay === void 0 ? {} : { repositoryDisplay },
18660
18665
  ...requestManifestPath === void 0 ? {} : { requestManifestPath },
18661
18666
  ...manifestDigest === void 0 ? {} : { manifestDigest },
18667
+ ...waitWindowMs === void 0 ? {} : { waitWindowMs },
18662
18668
  ...issueNumber === void 0 ? {} : { issueNumber },
18663
18669
  ...caseRunsPath === void 0 ? {} : { caseRunsPath },
18664
18670
  ...caseIdentity2 === void 0 ? {} : { caseIdentity: caseIdentity2 },
@@ -18916,6 +18922,7 @@ async function loadResumableCollectorRun(home, runId, authority) {
18916
18922
  ...prNumber === void 0 ? {} : { prNumber },
18917
18923
  repository: parsedRepository,
18918
18924
  ...loaded.admittedFields.requestManifestPath === void 0 ? {} : { requestManifestPath: loaded.admittedFields.requestManifestPath },
18925
+ ...loaded.admittedFields.waitWindowMs === void 0 ? {} : { waitWindowMs: loaded.admittedFields.waitWindowMs },
18919
18926
  manifestDigest
18920
18927
  };
18921
18928
  return seatLoadedResult(loaded, admitted);
@@ -19741,8 +19748,22 @@ var init_option_definitions = __esm({
19741
19748
  repeatable: false,
19742
19749
  form: "option",
19743
19750
  description: {
19744
- en: "Optional request manifest JSON path ({requests:[{id,body}]}).",
19745
- zh: "\u53EF\u9009 request manifest JSON \u8DEF\u5F84\uFF08{requests:[{id,body}]}\uFF09\u3002"
19751
+ en: "Optional request manifest JSON path ({requests:[{id,body}]}). Role may also decide request bodies from handbook/field activity without this file.",
19752
+ zh: "\u53EF\u9009 request manifest JSON \u8DEF\u5F84\uFF08{requests:[{id,body}]}\uFF09\u3002\u89D2\u8272\u4EA6\u53EF\u4F9D\u624B\u518C/\u73B0\u573A\u81EA\u884C\u5224\u5B9A\u8BF7\u6C42\u6B63\u6587\uFF0C\u4E0D\u5FC5\u4F9D\u8D56\u672C\u6587\u4EF6\u3002"
19753
+ }
19754
+ },
19755
+ {
19756
+ id: "wait-ms",
19757
+ owner: "collector",
19758
+ canonical: "--wait-ms",
19759
+ aliases: [],
19760
+ valueMetavar: "ms",
19761
+ required: false,
19762
+ repeatable: false,
19763
+ form: "option",
19764
+ description: {
19765
+ en: "Wait-window duration in milliseconds after the work step opens (default 600000 = 10 minutes). Does not require a code change to adjust.",
19766
+ zh: "\u5DE5\u4F5C\u6B65\u9AA4\u5F00\u542F\u540E\u7684\u7B49\u5F85\u7A97\u65F6\u957F\uFF08\u6BEB\u79D2\uFF1B\u9ED8\u8BA4 600000\uFF1D\u5341\u5206\u949F\uFF09\u3002\u6539\u914D\u7F6E\u5373\u53EF\uFF0C\u65E0\u9700\u6539\u4EE3\u7801\u3002"
19746
19767
  }
19747
19768
  }
19748
19769
  ];
@@ -21024,6 +21045,7 @@ function parseCollectorArgv(args) {
21024
21045
  let repo;
21025
21046
  let prNumber;
21026
21047
  let requestManifestPath;
21048
+ let waitWindowMs;
21027
21049
  const positional = [];
21028
21050
  const tokens = [...args];
21029
21051
  const definitions = roleOptions("collector");
@@ -21056,6 +21078,17 @@ function parseCollectorArgv(args) {
21056
21078
  requestManifestPath = requireOptionPath(taken.def.canonical, taken.value);
21057
21079
  continue;
21058
21080
  }
21081
+ if (taken.def.id === "wait-ms") {
21082
+ if (taken.value === void 0 || !/^[1-9]\d*$/.test(taken.value.trim())) {
21083
+ throw new CliUsageError("--wait-ms requires a positive safe-integer millisecond value");
21084
+ }
21085
+ const parsed = Number(taken.value.trim());
21086
+ if (!Number.isSafeInteger(parsed) || parsed < 1) {
21087
+ throw new CliUsageError("--wait-ms requires a positive safe-integer millisecond value");
21088
+ }
21089
+ waitWindowMs = parsed;
21090
+ continue;
21091
+ }
21059
21092
  throw new CliUsageError(`unknown collector option: ${taken.def.canonical}`);
21060
21093
  }
21061
21094
  const token = tokens.shift();
@@ -21071,7 +21104,8 @@ function parseCollectorArgv(args) {
21071
21104
  attachmentPaths,
21072
21105
  ...project === void 0 ? {} : { project },
21073
21106
  ...repo === void 0 ? {} : { repo },
21074
- ...requestManifestPath === void 0 ? {} : { requestManifestPath }
21107
+ ...requestManifestPath === void 0 ? {} : { requestManifestPath },
21108
+ ...waitWindowMs === void 0 ? {} : { waitWindowMs }
21075
21109
  };
21076
21110
  }
21077
21111
  function resolveGitHubRemoteRepository(projectRoot) {
@@ -21196,6 +21230,7 @@ async function admitCollectorInvocation(options) {
21196
21230
  repository: repository.canonical,
21197
21231
  repositoryDisplay: repository.display,
21198
21232
  ...requestManifestPath === void 0 ? {} : { requestManifestPath },
21233
+ ...options.waitWindowMs === void 0 ? {} : { waitWindowMs: options.waitWindowMs },
21199
21234
  manifestDigest,
21200
21235
  attachments: attachments.map((a) => ({
21201
21236
  provenancePath: a.provenancePath,
@@ -21225,6 +21260,7 @@ async function admitCollectorInvocation(options) {
21225
21260
  ...prNumber === void 0 ? {} : { prNumber },
21226
21261
  repository,
21227
21262
  ...requestManifestPath === void 0 ? {} : { requestManifestPath },
21263
+ ...options.waitWindowMs === void 0 ? {} : { waitWindowMs: options.waitWindowMs },
21228
21264
  manifestDigest
21229
21265
  };
21230
21266
  }
@@ -23597,11 +23633,11 @@ var init_reviewer_dispatch_rejection = __esm({
23597
23633
  });
23598
23634
 
23599
23635
  // src/collector-evidence.ts
23600
- var COLLECTOR_ELIGIBILITY_MS;
23636
+ var COLLECTOR_DEFAULT_WAIT_WINDOW_MS;
23601
23637
  var init_collector_evidence = __esm({
23602
23638
  "src/collector-evidence.ts"() {
23603
23639
  "use strict";
23604
- COLLECTOR_ELIGIBILITY_MS = 15 * 60 * 1e3;
23640
+ COLLECTOR_DEFAULT_WAIT_WINDOW_MS = 10 * 60 * 1e3;
23605
23641
  }
23606
23642
  });
23607
23643
 
@@ -23613,84 +23649,14 @@ var init_collector_identity = __esm({
23613
23649
  }
23614
23650
  });
23615
23651
 
23616
- // src/collector-tool-schemas.ts
23617
- var collectorObserveArgsSchema, collectorRequestArgsSchema, collectorReadArgsSchema, collectorWaitArgsSchema, collectorBindTargetArgsSchema, collectorFindingItemDeclaration, collectorOutputBaseSchema, collectorOutputArgsSchema;
23618
- var init_collector_tool_schemas = __esm({
23619
- "src/collector-tool-schemas.ts"() {
23620
- "use strict";
23621
- init_build();
23622
- init_collector_evidence();
23623
- init_open_tool_schema();
23624
- init_terminating_infrastructure();
23625
- collectorObserveArgsSchema = typebox_exports.Object({}, { additionalProperties: false });
23626
- collectorRequestArgsSchema = typebox_exports.Object({
23627
- requestId: typebox_exports.String({ minLength: 1, description: "\u914D\u7F6E\u8BF7\u6C42\u8EAB\u4EFD" }),
23628
- snapshotId: typebox_exports.String({ minLength: 1, description: "\u6700\u65B0\u7559\u5B58\u89C2\u5BDF\u5FEB\u7167" })
23629
- }, { additionalProperties: false });
23630
- collectorReadArgsSchema = typebox_exports.Object({
23631
- evidenceId: typebox_exports.String({ minLength: 1, description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u8BC1\u636E id\uFF08evidenceId\uFF09" })
23632
- }, { additionalProperties: false });
23633
- collectorWaitArgsSchema = typebox_exports.Object({
23634
- durationMs: typebox_exports.Integer({ minimum: 1, maximum: COLLECTOR_ELIGIBILITY_MS, description: "\u7B49\u5F85\u6BEB\u79D2\uFF1B\u5355\u6B21\u4E0A\u9650\u4E94\u5206\u949F\u4E14\u4E0D\u8D85\u5269\u4F59\u8D44\u683C" })
23635
- }, { additionalProperties: false });
23636
- collectorBindTargetArgsSchema = typebox_exports.Object({
23637
- prNumber: typebox_exports.Optional(typebox_exports.Unknown({
23638
- description: "\u89D2\u8272\u5224\u5B9A\u7684\u672C\u4ED3 PR \u53F7\uFF08\u6B63\u6574\u6570\uFF09\u3002\u4E0E issueNumber \u4E8C\u9009\u4E00\u6216\u540C\u6307\u552F\u4E00\u76EE\u6807\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
23639
- })),
23640
- issueNumber: typebox_exports.Optional(typebox_exports.Unknown({
23641
- description: "\u89D2\u8272\u5224\u5B9A\u7684\u672C\u4ED3 issue \u53F7\uFF08\u6B63\u6574\u6570\uFF09\uFF1Bruntime \u7ECF\u7EBF\u4E0A\u5173\u8054\u89E3\u6790\u552F\u4E00 PR\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
23642
- }))
23643
- }, { additionalProperties: true });
23644
- collectorFindingItemDeclaration = (() => {
23645
- const item = typebox_exports.Object(
23646
- {
23647
- evidenceId: typebox_exports.Unknown({
23648
- description: "observe \u8FD4\u56DE\u7684\u6750\u6599\u6307\u9488\uFF08\u5FC5\u586B\u8BED\u4E49\uFF09"
23649
- }),
23650
- category: typebox_exports.Unknown({
23651
- description: "\u7B80\u77ED\u5F52\u7C7B\u6807\u7B7E\uFF0C\u4E0D\u662F\u6458\u8981"
23652
- }),
23653
- summary: typebox_exports.Unknown({
23654
- description: "\u54EA\u4E2A bot\u3001\u4EC0\u4E48\u95EE\u9898\u7684\u6458\u8981\uFF1B\u4E0D\u8A8A\u6284\u6B63\u6587"
23655
- })
23656
- },
23657
- {
23658
- additionalProperties: true,
23659
- description: "\u5355\u6761 finding \u6307\u9488\uFF1AevidenceId + \u53EF\u9009 category/summary\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
23660
- }
23661
- );
23662
- item.required = [];
23663
- return item;
23664
- })();
23665
- collectorOutputBaseSchema = openToolObject(
23666
- typebox_exports.Object({
23667
- // No root type:array — host must not shape-reject non-array findings (#676 C).
23668
- // Nested item declarations ride `items` for registration preservation (ADR 0057).
23669
- findings: typebox_exports.Unsafe({
23670
- description: "\u672C\u6B21\u6536\u96C6\u5230\u7684\u9010\u6761 findings\uFF08\u6307\u9488\u6570\u7EC4\u4E3A\u89C4\u8303\u5F62\uFF09\u3002\u96F6 finding \u7684\u6A21\u677F\u901A\u77E5\u4E0D\u5F97\u8FDB\u5165\uFF1B\u6B63\u5E38\u5B8C\u5DE5\u65E0 finding \u65F6\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002",
23671
- items: collectorFindingItemDeclaration
23672
- }),
23673
- unfinishedReasons: typebox_exports.Unknown({
23674
- description: "\u672A\u5B8C\u6210\u539F\u56E0\u5B57\u7B26\u4E32\u6570\u7EC4\uFF08\u989D\u5EA6/\u6545\u969C/\u7B49\u5F85\u5C4A\u6EE1\u7B49\u73B0\u573A\u4F9D\u636E\uFF09\uFF1B\u4E0D\u5F97\u628A\u672A\u5B8C\u6210\u8868\u8FF0\u4E3A\u65E0\u95EE\u9898\u3002\u65E0\u53EF\u62A5\u544A\u65F6\u7701\u7565\u3002\u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\u3002"
23675
- })
23676
- })
23677
- );
23678
- collectorOutputArgsSchema = withInfrastructureFailureDeclaration(
23679
- collectorOutputBaseSchema
23680
- );
23681
- }
23682
- });
23683
-
23684
23652
  // src/collector-ledger.ts
23685
23653
  var COLLECTOR_OBSERVE_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, COLLECTOR_BIND_TARGET_TOOL;
23686
23654
  var init_collector_ledger = __esm({
23687
23655
  "src/collector-ledger.ts"() {
23688
23656
  "use strict";
23689
- init_value2();
23690
23657
  init_collector_evidence();
23691
23658
  init_collector_github();
23692
23659
  init_collector_identity();
23693
- init_collector_tool_schemas();
23694
23660
  init_collector_output();
23695
23661
  COLLECTOR_OBSERVE_TOOL = "ak_collector_observe";
23696
23662
  COLLECTOR_READ_TOOL = "ak_collector_read";
@@ -28019,7 +27985,8 @@ function buildCollectorTurnRequest(admitted, options) {
28019
27985
  repo: admitted.repository.display,
28020
27986
  // #676 A: omit pr when unbound — role binds via ak_collector_bind_target.
28021
27987
  ...admitted.prNumber === void 0 ? {} : { pr: String(admitted.prNumber) },
28022
- ...admitted.requestManifestPath === void 0 ? {} : { requestManifestPath: admitted.requestManifestPath }
27988
+ ...admitted.requestManifestPath === void 0 ? {} : { requestManifestPath: admitted.requestManifestPath },
27989
+ ...admitted.waitWindowMs === void 0 ? {} : { waitMs: String(admitted.waitWindowMs) }
28023
27990
  }
28024
27991
  },
28025
27992
  options
@@ -28039,6 +28006,7 @@ async function runPublicCollector(argv, env, io, parseCollectorArgv2) {
28039
28006
  ...parsed.project === void 0 ? {} : { project: parsed.project },
28040
28007
  ...parsed.repo === void 0 ? {} : { repo: parsed.repo },
28041
28008
  ...parsed.requestManifestPath === void 0 ? {} : { requestManifestPath: parsed.requestManifestPath },
28009
+ ...parsed.waitWindowMs === void 0 ? {} : { waitWindowMs: parsed.waitWindowMs },
28042
28010
  ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId },
28043
28011
  ...env.model === void 0 ? {} : { model: env.model }
28044
28012
  });
@@ -483,8 +483,22 @@ const COLLECTOR_OPTIONS = [
483
483
  repeatable: false,
484
484
  form: "option",
485
485
  description: {
486
- en: "Optional request manifest JSON path ({requests:[{id,body}]}).",
487
- zh: "可选 request manifest JSON 路径({requests:[{id,body}]})。",
486
+ en: "Optional request manifest JSON path ({requests:[{id,body}]}). Role may also decide request bodies from handbook/field activity without this file.",
487
+ zh: "可选 request manifest JSON 路径({requests:[{id,body}]})。角色亦可依手册/现场自行判定请求正文,不必依赖本文件。",
488
+ },
489
+ },
490
+ {
491
+ id: "wait-ms",
492
+ owner: "collector",
493
+ canonical: "--wait-ms",
494
+ aliases: [],
495
+ valueMetavar: "ms",
496
+ required: false,
497
+ repeatable: false,
498
+ form: "option",
499
+ description: {
500
+ en: "Wait-window duration in milliseconds after the work step opens (default 600000 = 10 minutes). Does not require a code change to adjust.",
501
+ zh: "工作步骤开启后的等待窗时长(毫秒;默认 600000=十分钟)。改配置即可,无需改代码。",
488
502
  },
489
503
  },
490
504
  ];
@@ -880,6 +880,7 @@ async function loadResumableRunRecord(home, runId, authority) {
880
880
  let repositoryDisplay;
881
881
  let requestManifestPath;
882
882
  let manifestDigest;
883
+ let waitWindowMs;
883
884
  let issueNumber;
884
885
  let caseRunsPath;
885
886
  let caseIdentity;
@@ -934,6 +935,9 @@ async function loadResumableRunRecord(home, runId, authority) {
934
935
  if (typeof record.manifestDigest === "string" && record.manifestDigest.trim() !== "") {
935
936
  manifestDigest = record.manifestDigest;
936
937
  }
938
+ if (typeof record.waitWindowMs === "number" && Number.isSafeInteger(record.waitWindowMs) && record.waitWindowMs >= 1) {
939
+ waitWindowMs = record.waitWindowMs;
940
+ }
937
941
  // Doctor — admitted single-case identity (#633 resume).
938
942
  if (typeof record.issueNumber === "number" && Number.isSafeInteger(record.issueNumber) && record.issueNumber >= 1) {
939
943
  issueNumber = record.issueNumber;
@@ -1074,6 +1078,7 @@ async function loadResumableRunRecord(home, runId, authority) {
1074
1078
  ...(repositoryDisplay === undefined ? {} : { repositoryDisplay }),
1075
1079
  ...(requestManifestPath === undefined ? {} : { requestManifestPath }),
1076
1080
  ...(manifestDigest === undefined ? {} : { manifestDigest }),
1081
+ ...(waitWindowMs === undefined ? {} : { waitWindowMs }),
1077
1082
  ...(issueNumber === undefined ? {} : { issueNumber }),
1078
1083
  ...(caseRunsPath === undefined ? {} : { caseRunsPath }),
1079
1084
  ...(caseIdentity === undefined ? {} : { caseIdentity }),
@@ -1338,6 +1343,9 @@ export async function loadResumableCollectorRun(home, runId, authority) {
1338
1343
  ...(loaded.admittedFields.requestManifestPath === undefined
1339
1344
  ? {}
1340
1345
  : { requestManifestPath: loaded.admittedFields.requestManifestPath }),
1346
+ ...(loaded.admittedFields.waitWindowMs === undefined
1347
+ ? {}
1348
+ : { waitWindowMs: loaded.admittedFields.waitWindowMs }),
1341
1349
  manifestDigest,
1342
1350
  };
1343
1351
  return seatLoadedResult(loaded, admitted);
@@ -1223,6 +1223,9 @@ export function createRoleRuntimeExtension(dependencies) {
1223
1223
  ...(dependencies.createCollectorClock === undefined
1224
1224
  ? {}
1225
1225
  : { createClock: dependencies.createCollectorClock }),
1226
+ ...(dependencies.loadCollectorHandbookSeed === undefined
1227
+ ? {}
1228
+ : { loadHandbookSeed: dependencies.loadCollectorHandbookSeed }),
1226
1229
  }, hostActions);
1227
1230
  // #676 J1: business tools + tool_call gate register only behind admission/activation.
1228
1231
  // before_agent_start / tool_result collector branches live on the shared envelope hooks above.
@@ -40,6 +40,7 @@ import { loadGatekeeperSessionMaterials, loadMainRoleSessionMaterials } from "..
40
40
  const extensionPath = fileURLToPath(import.meta.url);
41
41
  const packageRoot = fileURLToPath(new URL("..", import.meta.url));
42
42
  const navigatorRoutePlaybookPath = fileURLToPath(new URL("../resources/navigator-route-playbook.md", import.meta.url));
43
+ const collectorHandbookSeedPath = fileURLToPath(new URL("../resources/collector-bot-handbook.md", import.meta.url));
43
44
  // #675: nested public summons (gate/auditor) resolve root via env under jiti.
44
45
  if (process.env.AK_ROLE_PACKAGE_ROOT === undefined || process.env.AK_ROLE_PACKAGE_ROOT.trim() === "") {
45
46
  process.env.AK_ROLE_PACKAGE_ROOT = packageRoot;
@@ -122,6 +123,7 @@ export default function roleRuntime(pi: ExtensionAPI): void {
122
123
  createReviewerPinnedGitReader: () => createReviewerPinnedGitReader(),
123
124
  createReviewerIssueFetcher: () => createGhIssueSoftFetcher(),
124
125
  loadCollectorSoul: () => loadMainRoleSessionMaterials("collector"),
126
+ loadCollectorHandbookSeed: () => readFile(collectorHandbookSeedPath, "utf8"),
125
127
  createCollectorTransport: () => createGhCollectorGitHubTransport(),
126
128
  loadDoctorSoul: () => loadMainRoleSessionMaterials("doctor"),
127
129
  loadDoctorCase,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.3783",
3
+ "version": "0.1.3795",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -0,0 +1,33 @@
1
+ # 通进司 bot 工作记忆(通用)
2
+
3
+ 薄手册:触发方式、自动/手动条件、完成与不可继续的识别线索、官方出处。
4
+ 内容是角色阅读与修正的工作记忆,不是代码状态规则;临时额度/故障不得固化为永久行为。
5
+ 参与者依本仓使用与现场活动辨认,不把下列名称当作全仓固定名单。
6
+
7
+ ## Codex(hosted GitHub connector)
8
+
9
+ - 官方:https://learn.chatgpt.com/docs/third-party/github
10
+ - 常见主动请求:`@codex review`
11
+ - 新建 PR 常有自动评审;是否已在审当前提交以现场 reviews/comments 为准
12
+
13
+ ## CodeRabbit
14
+
15
+ - 官方:https://docs.coderabbit.ai/configuration/auto-review
16
+ - 命令:https://docs.coderabbit.ai/guides/commands
17
+ - 常见主动请求:`@coderabbitai review`;全量:`@coderabbitai full review`
18
+ - 默认常为增量;本仓实际自动/暂停以现场与仓库差异条为准
19
+
20
+ ## Sourcery
21
+
22
+ - 官方:https://docs.sourcery.ai/reviews/ 与 https://docs.sourcery.ai/reviews/commands/
23
+ - 新建/更新与主动请求依文档与本仓现场
24
+
25
+ ## Cursor Bugbot / 自动化
26
+
27
+ - 官方:https://prod.cursor.com/help/ai-features/bugbot 与 automations 文档
28
+ - 内置 Bugbot 与同账号自定义任务须区分;某任务额度耗尽不推断其他任务失效
29
+
30
+ ## 修正规则
31
+
32
+ - 优先引用官方文档;现场差异记入仓库差异条并附 PR/证据指针
33
+ - 未知或暂未响应 ≠ 通过或确定死亡
@@ -39,6 +39,9 @@ export type ProductionAcpHostOptions = Readonly<{
39
39
  const navigatorRoutePlaybookPath = fileURLToPath(
40
40
  new URL("../../resources/navigator-route-playbook.md", import.meta.url),
41
41
  );
42
+ const collectorHandbookSeedPath = fileURLToPath(
43
+ new URL("../../resources/collector-bot-handbook.md", import.meta.url),
44
+ );
42
45
 
43
46
  /** Host-neutral packaged role runtime deps for the ACP parent-process envelope. */
44
47
  export function createAcpRoleRuntimeDependencies(packageRoot: string): RoleRuntimeDependencies {
@@ -55,6 +58,7 @@ export function createAcpRoleRuntimeDependencies(packageRoot: string): RoleRunti
55
58
  createReviewerPinnedGitReader: () => createReviewerPinnedGitReader(),
56
59
  createReviewerIssueFetcher: () => createGhIssueSoftFetcher(),
57
60
  loadCollectorSoul: () => loadMainRoleSessionMaterials("collector"),
61
+ loadCollectorHandbookSeed: () => readFile(collectorHandbookSeedPath, "utf8"),
58
62
  createCollectorTransport: () => createGhCollectorGitHubTransport(),
59
63
  loadDoctorSoul: () => loadMainRoleSessionMaterials("doctor"),
60
64
  loadDoctorCase,
@@ -98,6 +98,7 @@ export function projectAcpActivationFlags(request: RoleTurnRequest): Map<string,
98
98
  // #676 D1: pr optional at admission; omit flag when role binds from materials.
99
99
  if (activation.pr !== undefined) flags.set("ak-collector-pr", activation.pr);
100
100
  if (activation.requestManifestPath !== undefined) flags.set("ak-collector-request-manifest", activation.requestManifestPath);
101
+ if (activation.waitMs !== undefined) flags.set("ak-collector-wait-ms", activation.waitMs);
101
102
  }
102
103
  return flags;
103
104
  }
@@ -11,7 +11,8 @@ import type {
11
11
  GitHubUser,
12
12
  } from "./collector-github.ts";
13
13
 
14
- export const COLLECTOR_ELIGIBILITY_MS = 15 * 60 * 1000;
14
+ /** Default collector wait window (D4): 10 minutes from the work-step open, not from session activation. */
15
+ export const COLLECTOR_DEFAULT_WAIT_WINDOW_MS = 10 * 60 * 1000;
15
16
 
16
17
  export type WindowRelation = "before" | "within" | "after" | "uncertain";
17
18
  export type HeadRelation = "current" | "prior";
@@ -73,6 +74,8 @@ export type CollectorSnapshot = {
73
74
  prNumber: number;
74
75
  prState: string;
75
76
  headOid: string;
77
+ /** PR create success time when GitHub supplies it (#678 new-PR wait start). */
78
+ prCreatedAt?: string;
76
79
  complete: boolean;
77
80
  evidenceIds: string[];
78
81
  pageDiagnostics: GitHubPageDiagnostics[];
@@ -177,6 +180,7 @@ export function normalizePullRequestEvidence(
177
180
  number: pr.number,
178
181
  state: pr.state,
179
182
  headOid: pr.headOid,
183
+ createdAt: pr.createdAt ?? null,
180
184
  updatedAt: pr.updatedAt ?? null,
181
185
  htmlUrl: pr.url,
182
186
  });
@@ -190,6 +194,7 @@ export function normalizePullRequestEvidence(
190
194
  state: pr.state,
191
195
  commitOid: pr.headOid,
192
196
  htmlUrl: pr.url,
197
+ // Version clock stays updatedAt. Create success for the wait window is snapshot.prCreatedAt only (#678).
193
198
  authoritativeTime: pr.updatedAt ?? null,
194
199
  firstObservedAt: observedAt,
195
200
  raw: pr.raw,
@@ -7,6 +7,8 @@ export type GitHubPullRequest = {
7
7
  number: number;
8
8
  state: string;
9
9
  headOid: string;
10
+ /** GitHub PR created_at — work-step start for new-PR auto-trigger rounds (#678 D4). */
11
+ createdAt?: string;
10
12
  updatedAt?: string;
11
13
  url: string;
12
14
  raw: unknown;
@@ -491,6 +493,7 @@ export function normalizePullRequest(raw: unknown): GitHubPullRequest {
491
493
  number,
492
494
  state,
493
495
  headOid: head["sha"],
496
+ ...(typeof raw["created_at"] === "string" ? { createdAt: raw["created_at"] } : {}),
494
497
  ...(typeof raw["updated_at"] === "string" ? { updatedAt: raw["updated_at"] } : {}),
495
498
  url: htmlUrl,
496
499
  raw,