@akagilnc/pi-workflow-roles 0.1.5241 → 0.1.5252

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 (41) hide show
  1. package/README.md +2 -3
  2. package/README.zh-CN.md +2 -3
  3. package/dist/acp-host/production-host.js +482 -3141
  4. package/dist/collector-config.js +0 -1
  5. package/dist/headless-host/production-host.js +590 -3249
  6. package/dist/migrate-book-topology.js +40 -107
  7. package/dist/navigator-invocation-identity.js +0 -57
  8. package/dist/package-contracts/collector-output.js +1 -90
  9. package/dist/package-contracts/terminating-tools.js +2 -2
  10. package/dist/packaged-role-registry.js +8 -11
  11. package/dist/public-cli/invocation.js +2 -22
  12. package/dist/public-cli/main.js +256 -749
  13. package/dist/public-cli/option-definitions.js +4 -19
  14. package/dist/public-cli/settlement.js +12 -138
  15. package/package.json +1 -1
  16. package/resources/collector-bot-handbook.md +4 -2
  17. package/src/collector-config.ts +0 -1
  18. package/src/collector-role.ts +40 -535
  19. package/src/collector-tool-schemas.ts +7 -117
  20. package/src/gh-api-runner.ts +102 -0
  21. package/src/navigator-invocation-identity.ts +4 -121
  22. package/src/package-contracts/collector-output.ts +15 -174
  23. package/src/package-contracts/terminating-tools.ts +0 -2
  24. package/src/packaged-role-registry.ts +7 -10
  25. package/src/public-cli/invocation.ts +3 -27
  26. package/src/public-cli/option-definitions.ts +4 -19
  27. package/src/public-cli/settlement.ts +11 -177
  28. package/src/role-runtime-dependencies.ts +0 -4
  29. package/src/role-runtime.ts +39 -103
  30. package/src/ticket-snapshot.ts +1 -1
  31. package/dist/collector-evidence.js +0 -319
  32. package/dist/collector-github.js +0 -725
  33. package/dist/collector-identity.js +0 -92
  34. package/dist/collector-ledger.js +0 -888
  35. package/dist/collector-target.js +0 -169
  36. package/src/collector-evidence.ts +0 -466
  37. package/src/collector-github.ts +0 -1032
  38. package/src/collector-handbook.ts +0 -194
  39. package/src/collector-identity.ts +0 -151
  40. package/src/collector-ledger.ts +0 -1186
  41. package/src/collector-target.ts +0 -207
@@ -429,13 +429,12 @@ const COLLECTOR_OPTIONS = [
429
429
  canonical: "--pr",
430
430
  aliases: [],
431
431
  valueMetavar: "number",
432
- // #676 D1: optional when context uniquely determines the PR; ambiguous → require explicit.
433
432
  required: false,
434
433
  repeatable: false,
435
434
  form: "option",
436
435
  description: {
437
- en: "Positive GitHub pull request number. Optional when unique branch/HEAD association binds the PR, or when the Collector role can decide the target from task materials via bind-target; multi-candidate git context or a role that cannot decide requires an explicit value.",
438
- zh: "正整数 GitHub PR 号。分支/HEAD 唯一关联可绑定时可省略;亦可由通进司从任务材料经 bind-target 判定。git 多候选或角色无法判定时必须显式提供。",
436
+ en: "Positive GitHub pull request number. Optional when the Collector role locates the PR via host CLI from task materials.",
437
+ zh: "正整数 GitHub PR 号。可选;省略时由通进司经宿主 CLI 从任务材料自行定位。",
439
438
  },
440
439
  },
441
440
  {
@@ -462,22 +461,8 @@ const COLLECTOR_OPTIONS = [
462
461
  repeatable: false,
463
462
  form: "option",
464
463
  description: {
465
- en: "Optional request manifest JSON path ({requests:[{id,body}]}). Role may also decide request bodies from handbook/field activity without this file.",
466
- zh: "可选 request manifest JSON 路径({requests:[{id,body}]})。角色亦可依手册/现场自行判定请求正文,不必依赖本文件。",
467
- },
468
- },
469
- {
470
- id: "wait-ms",
471
- owner: "collector",
472
- canonical: "--wait-ms",
473
- aliases: [],
474
- valueMetavar: "ms",
475
- required: false,
476
- repeatable: false,
477
- form: "option",
478
- description: {
479
- en: "Wait-window duration in milliseconds after the work step opens (default 600000 = 10 minutes). Does not require a code change to adjust.",
480
- zh: "工作步骤开启后的等待窗时长(毫秒;默认 600000=十分钟)。改配置即可,无需改代码。",
464
+ en: "Optional request manifest JSON path ({requests:[{id,body}]}). Parsed for semantics and passed to the Collector as materials — not a machine collection directive.",
465
+ zh: "可选 request manifest JSON 路径({requests:[{id,body}]})。按语义解析后作为材料递给通进司,不是机器代收 finding 的指令。",
481
466
  },
482
467
  },
483
468
  ];
@@ -17,18 +17,16 @@ import { isV1ResumableProvider, readLatestTypedProviderHttpObservation, readType
17
17
  import { AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE, AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE, COMPLIANCE_RESPONSE_ENTRY_TYPE, readComplianceCandidate, } from "../compliance-transport.js";
18
18
  // COMPLIANCE_RESPONSE_ENTRY_TYPE remains for boundRetainedAuditResponse (call/result
19
19
  // interval binding on historical session bytes). Provider-stop retain authority is Sitian.
20
- import { COLLECTOR_BIND_TARGET_TOOL, COLLECTOR_OBSERVE_TOOL, COLLECTOR_READ_TOOL, COLLECTOR_REQUEST_TOOL, COLLECTOR_WAIT_TOOL, } from "../collector-ledger.js";
21
- import { ENGINE_DETOUR_TOOL_NAME } from "../engine-detour.js";
20
+ import { ENGINE_DETOUR_TOOL_NAME, } from "../engine-detour.js";
22
21
  import { projectEngineDetourToolUsageForPublicTerminal, readEngineDetourToolUsage, readInvocationEngineMounted, runDirectoryFromSessionDirectory, sessionFileFromSessionDirectory, withEngineDetourToolUsageFact, } from "../engine-detour-usage.js";
23
22
  import { JUDGE_OUTPUT_TOOL_NAME, } from "../package-contracts/judge-output.js";
24
- import { COLLECTOR_OUTPUT_TOOL, } from "../package-contracts/collector-output.js";
25
23
  import { CODER_OUTPUT_TOOL_NAME, FIXER_OUTPUT_TOOL_NAME, } from "../package-contracts/worker-output.js";
26
24
  import { DOCTOR_OUTPUT_TOOL_NAME, } from "../doctor-contracts.js";
27
25
  import { DOCTOR_CANDIDATE_ENTRY_TYPE } from "../dossier-resolution.js";
28
26
  import { REVIEWER_OUTPUT_TOOL_NAME, } from "../package-contracts/reviewer-output.js";
29
- import { packagedAuditToolName, packagedDurableOfficerEntry, packagedProjectsTargetBindRejection, packagedRoleAcceptedOutputTool, packagedRoleMetadata, packagedSkipsGateOnInfrastructureStage, } from "../packaged-role-registry.js";
27
+ import { packagedAuditToolName, packagedDurableOfficerEntry, packagedRoleAcceptedOutputTool, packagedRoleMetadata, packagedSkipsGateOnInfrastructureStage, } from "../packaged-role-registry.js";
30
28
  import { SECRETARIAT_COUNTERSIGN_TERMINAL_FACT_KEY, SECRETARIAT_GATE_OFFICER_ENTRY_TYPE, } from "../secretariat-contracts.js";
31
- import { classifyPackagedRoleTerminalResult, findLatestDurablePackagedRoleTerminal, hasNavigatorInfrastructureFailureBase, isAcceptedPackagedRoleTerminalResult, isReceiptSettlementBindingClear, NAVIGATOR_INVOCATION_ENTRY, NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY, parseInvocationMarkerIdentity, } from "../navigator-invocation-identity.js";
29
+ import { classifyPackagedRoleTerminalResult, findLatestDurablePackagedRoleTerminal, hasNavigatorInfrastructureFailureBase, isAcceptedPackagedRoleTerminalResult, NAVIGATOR_ROUTE_PLAYBOOK_FAILURE_ENTRY, } from "../navigator-invocation-identity.js";
32
30
  import { NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, RECEIPT_DELIVERY_TURN_LIMIT, noReceiptLifecycleFacts, parseNoReceiptLifecycleFacts, } from "../receipt-delivery-policy.js";
33
31
  import { roleRunArtifactsDirectory } from "../role-run-placement.js";
34
32
  import { rewriteRunDirectoryPathValue } from "../role-run-relocation.js";
@@ -1037,35 +1035,6 @@ function toolResultText(message) {
1037
1035
  .join("")
1038
1036
  .trim();
1039
1037
  }
1040
- /**
1041
- * #676 D1/J3: durable bind-target rejection on the current attempt → public no_receipt facts.
1042
- * Callers must learn they need explicit --pr without opening the session 正本.
1043
- * Authority is the latest bind-target toolResult only — a later success clears an earlier failure.
1044
- */
1045
- function extractCollectorTargetBindRejection(entries) {
1046
- for (let i = entries.length - 1; i >= 0; i -= 1) {
1047
- const entry = entries[i];
1048
- if (entry?.type !== "message")
1049
- continue;
1050
- const message = entry.message;
1051
- if (message?.role !== "toolResult")
1052
- continue;
1053
- if (message.toolName !== COLLECTOR_BIND_TARGET_TOOL)
1054
- continue;
1055
- // Latest bind result wins: success means the attempt is no longer rejected.
1056
- if (message.isError !== true)
1057
- return undefined;
1058
- const diagnostic = toolResultText(message);
1059
- if (diagnostic.length === 0)
1060
- return undefined;
1061
- const details = message.details;
1062
- const code = isRecord(details) && typeof details.code === "string" && details.code.trim() !== ""
1063
- ? details.code
1064
- : undefined;
1065
- return code === undefined ? { diagnostic } : { diagnostic, code };
1066
- }
1067
- return undefined;
1068
- }
1069
1038
  function boundErroredToolCandidate(entries, resultIndex, message, toolName) {
1070
1039
  if (message.toolName !== toolName || message.isError !== true)
1071
1040
  return undefined;
@@ -1075,21 +1044,6 @@ function boundErroredToolCandidate(entries, resultIndex, message, toolName) {
1075
1044
  ? undefined
1076
1045
  : { candidate: bound.candidate, diagnostic, callIndex: bound.callIndex };
1077
1046
  }
1078
- /** Collector operational tools that fail closed via host infrastructure abort. */
1079
- const COLLECTOR_INFRASTRUCTURE_TOOLS = new Set([
1080
- COLLECTOR_OBSERVE_TOOL,
1081
- COLLECTOR_READ_TOOL,
1082
- COLLECTOR_REQUEST_TOOL,
1083
- COLLECTOR_WAIT_TOOL,
1084
- ]);
1085
- const COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC = {
1086
- matchTool: (toolName) => COLLECTOR_INFRASTRUCTURE_TOOLS.has(toolName),
1087
- cause: "activation",
1088
- identityName: "CollectorInfrastructureError",
1089
- // read alone has a correctable rejection mode (unknown/non-openable pointers);
1090
- // only its typed infrastructure-failure fact counts as a real host failure.
1091
- requireInfrastructureFact: (toolName) => toolName === COLLECTOR_READ_TOOL,
1092
- };
1093
1047
  const ENGINE_DETOUR_INFRASTRUCTURE_FAILURE_SPEC = {
1094
1048
  matchTool: (toolName) => toolName === ENGINE_DETOUR_TOOL_NAME,
1095
1049
  cause: "output",
@@ -1146,21 +1100,6 @@ async function readInfrastructureToolFailure(sessionFile, spec, options = {}) {
1146
1100
  return undefined;
1147
1101
  }
1148
1102
  }
1149
- /**
1150
- * Prefer a real Collector infrastructure tool failure already on the session
1151
- * principal over a later secondary provider-stop (failure-honesty).
1152
- * Observe/request/wait host failures keep their diagnostic identity (e.g. HTTP 404).
1153
- */
1154
- export function extractCollectorInfrastructureFailure(entries) {
1155
- return extractInfrastructureToolFailure(entries, COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC);
1156
- }
1157
- /** Read the bound session principal for a Collector infrastructure tool failure. */
1158
- export async function readCollectorInfrastructureFailure(sessionFile) {
1159
- return readInfrastructureToolFailure(sessionFile, COLLECTOR_INFRASTRUCTURE_FAILURE_SPEC,
1160
- // Multi-attempt resume: only a current-attempt infrastructure failure
1161
- // may preempt the current failure cause (#633).
1162
- { currentAttemptOnly: true });
1163
- }
1164
1103
  /**
1165
1104
  * Prefer a real engine-detour infrastructure tool failure already on the session
1166
1105
  * principal over a later secondary provider-stop (failure-honesty / #357 T2).
@@ -1189,10 +1128,6 @@ const RUNNER_FAILURE_POLICY = {
1189
1128
  read: readEngineDetourInfrastructureFailure,
1190
1129
  rank: "record-first",
1191
1130
  },
1192
- "collector-known-first": {
1193
- read: readCollectorInfrastructureFailure,
1194
- rank: "known-first",
1195
- },
1196
1131
  };
1197
1132
  /**
1198
1133
  * Runner-failure rank for one seat. The composition-root `runnerFailure`
@@ -1418,19 +1353,6 @@ export async function appendRunAttemptHistory(source, outcome) {
1418
1353
  }
1419
1354
  catch { }
1420
1355
  }
1421
- /**
1422
- * Minimal attendance provenance against the bound marker (ADR 0043).
1423
- * Keep only invocationId + post-terminal ordering. Runtime-self-produced
1424
- * role/phase/subject/version are not re-reconciled here (ADR 0042).
1425
- */
1426
- function navigatorAttendanceCorrelatedWithBoundMarker(details, attendanceIndex, terminalIndex, marker) {
1427
- if (attendanceIndex <= terminalIndex)
1428
- return false;
1429
- // Exact current invocation token is the bound marker principal.
1430
- if (details.invocationId !== marker.invocationId)
1431
- return false;
1432
- return true;
1433
- }
1434
1356
  function parseNavigatorAttendanceDetails(details) {
1435
1357
  const disposition = details.disposition;
1436
1358
  const advisoryDiagnostic = typeof details.routePlaybookReadFailure === "string"
@@ -1651,10 +1573,9 @@ export function extractNavigatorFact(entries) {
1651
1573
  return message === undefined ? fact : { ...fact, advisoryDiagnostic: message };
1652
1574
  }
1653
1575
  function extractNavigatorAttendanceFact(entries) {
1654
- // Affirmative attendance only. Missing / uncorrelated / unparseable is never no-advice.
1655
- // Minimal provenance: latest durable terminal + nearest preceding marker +
1656
- // invocationId + post-terminal order. Marker↔terminal cardinality belongs to
1657
- // receipt settlement (isReceiptSettlementBindingClear), not attendance extraction.
1576
+ // Affirmative attendance only. Missing / unparseable is never no-advice.
1577
+ // The shared lifecycle places the settled event on this submission's closure;
1578
+ // an unrelated attendance message cannot supply another call's result.
1658
1579
  const terminal = findLatestDurablePackagedRoleTerminal(entries);
1659
1580
  if (terminal === undefined) {
1660
1581
  return {
@@ -1663,49 +1584,14 @@ function extractNavigatorAttendanceFact(entries) {
1663
1584
  reason: "Navigator attendance has no durable packaged role terminal",
1664
1585
  };
1665
1586
  }
1666
- let markerIndex = -1;
1667
- for (let i = terminal.index - 1; i >= 0; i -= 1) {
1587
+ for (let i = terminal.index; i < entries.length; i += 1) {
1668
1588
  const entry = entries[i];
1669
- if (entry?.type === "custom" && entry.customType === NAVIGATOR_INVOCATION_ENTRY) {
1670
- markerIndex = i;
1589
+ if (entry?.type !== "custom" || entry.customType !== "ak-role-submission-closure")
1590
+ continue;
1591
+ const details = isRecord(entry.data) ? entry.data.navigator : undefined;
1592
+ if (!isRecord(details))
1671
1593
  break;
1672
- }
1673
- }
1674
- if (markerIndex < 0) {
1675
- return {
1676
- disposition: "unavailable",
1677
- source: "unknown",
1678
- reason: "Navigator attendance is uncorrelated with session invocation facts",
1679
- };
1680
- }
1681
- const marker = parseInvocationMarkerIdentity(entries[markerIndex]?.data);
1682
- if (marker === undefined) {
1683
- return {
1684
- disposition: "unavailable",
1685
- source: "unknown",
1686
- reason: "Navigator attendance is uncorrelated with session invocation facts",
1687
- };
1688
- }
1689
- for (let i = entries.length - 1; i >= 0; i -= 1) {
1690
- const entry = entries[i];
1691
- if (entry?.type === "custom_message" && entry.customType === "ak-navigator-attendance") {
1692
- const details = entry.message?.details ?? entry.details;
1693
- if (!isRecord(details)) {
1694
- return {
1695
- disposition: "unavailable",
1696
- source: "unknown",
1697
- reason: "Navigator attendance is unparseable",
1698
- };
1699
- }
1700
- if (!navigatorAttendanceCorrelatedWithBoundMarker(details, i, terminal.index, marker)) {
1701
- return {
1702
- disposition: "unavailable",
1703
- source: "unknown",
1704
- reason: "Navigator attendance is uncorrelated with session invocation facts",
1705
- };
1706
- }
1707
- return parseNavigatorAttendanceDetails(details);
1708
- }
1594
+ return parseNavigatorAttendanceDetails(details);
1709
1595
  }
1710
1596
  // Absence is not successful no-advice — require affirmative typed attendance.
1711
1597
  return {
@@ -2441,18 +2327,6 @@ export async function settleFailureTerminalResult(admitted, failure, authority,
2441
2327
  facts.runPointer === admitted.runDirectory &&
2442
2328
  facts.attemptPointer === `current:${admitted.runDirectory}`) {
2443
2329
  let decisiveFacts = facts;
2444
- // #676 D1/J3: project durable bind-target rejection onto public no_receipt facts.
2445
- if (packagedProjectsTargetBindRejection(admitted.role)) {
2446
- const bindRejection = extractCollectorTargetBindRejection(entries.slice(attemptStart));
2447
- if (bindRejection !== undefined) {
2448
- decisiveFacts = {
2449
- ...facts,
2450
- targetBindRejected: true,
2451
- targetBindDiagnostic: bindRejection.diagnostic,
2452
- ...(bindRejection.code === undefined ? {} : { targetBindCode: bindRejection.code }),
2453
- };
2454
- }
2455
- }
2456
2330
  // #478: no_receipt is still a public Terminal — project accepted gate facts.
2457
2331
  // #953: empty public terminal face — clear every reader-adoptable prior face.
2458
2332
  await clearOppositeTerminalArtifactFace(admitted.runDirectory);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.5241",
3
+ "version": "0.1.5252",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -4,6 +4,8 @@
4
4
  内容是角色阅读与修正的工作记忆,不是代码状态规则;临时额度/故障不得固化为永久行为。
5
5
  参与者依本仓使用与现场活动辨认,不把下列名称当作全仓固定名单。
6
6
 
7
+ #1088:用宿主 CLI(如 `gh`)自行取证与请求;代码不代收、不选择、不归并 finding。取证受限时如实报告。
8
+
7
9
  ## Codex(hosted GitHub connector)
8
10
 
9
11
  - 官方:https://learn.chatgpt.com/docs/third-party/github
@@ -29,9 +31,9 @@
29
31
 
30
32
  ## 工序
31
33
 
32
- 判定任务材料后绑定本仓唯一 PR(prNumber,或由 issueNumber 解析到唯一 PR)。已有显式 PR 绑定时不必再绑。多义或无法确定时不猜,交给调用方明确目标。未绑定前不观察。观察把证据存成不可变快照;上下文里的正文只到头部,其余按 evidenceId 开卷。请求发在所引最新快照 HEAD 上;清单外的 requestId 要带上正文。交卷交 findings 指针,不把模板通知当成 finding;没有 finding 就不要编一条。未完成写现场原因,不写成没问题。
34
+ 从任务材料与 `--pr` / `--request-manifest` 材料判定目标后,用宿主 CLI 读取有评审的 PR,按各 reviewer 已记录的完成形态收集 findings,整理并交卷。未绑定 PR 时用 `gh` 等自行定位;无法确定时不猜,交给调用方明确目标。交卷交按机器身份归组的出席、材料与 findings;没有 finding 就不要编一条。未完成写现场原因,不写成没问题。
33
35
 
34
36
  ## 修正规则
35
37
 
36
- - 优先引用官方文档;现场差异记入仓库差异条并附 PR/证据指针
38
+ - 优先引用官方文档;现场差异附 PR/证据指针
37
39
  - 未知或暂未响应 ≠ 通过或确定死亡
@@ -1,7 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { readFile } from "node:fs/promises";
3
3
 
4
- export const COLLECTOR_HOST = "github.com" as const;
5
4
  export const COLLECTOR_OWNER_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
6
5
  export const COLLECTOR_REPO_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,98}[A-Za-z0-9])?$/;
7
6