@akagilnc/pi-workflow-roles 0.1.5303 → 0.1.5312

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 (35) hide show
  1. package/dist/acp-host/description.js +0 -11
  2. package/dist/acp-host/production-host.js +577 -604
  3. package/dist/analyst-ledger.js +16 -1
  4. package/dist/analyst-metric-families/acceptance-success-rework.js +16 -15
  5. package/dist/analyst-metric-families/b2-frame-buckets-actions.js +3 -8
  6. package/dist/analyst-metric-families/gate-cycles.js +2 -8
  7. package/dist/analyst-metric-families/leg-wall-clock.js +4 -13
  8. package/dist/analyst-metric-families/round-timeline.js +1 -4
  9. package/dist/analyst-model-groups.js +1 -7
  10. package/dist/analyst-page.js +4 -13
  11. package/dist/headless-host/description.js +0 -11
  12. package/dist/headless-host/production-host.js +679 -718
  13. package/dist/host-descriptions.js +13 -0
  14. package/dist/prepared-role-turn.js +4 -0
  15. package/dist/public-cli/machine-method-skills.js +5 -5
  16. package/dist/public-cli/main.js +291 -313
  17. package/package.json +1 -1
  18. package/src/acp-host/description.ts +2 -12
  19. package/src/acp-host/production-host.ts +3 -2
  20. package/src/acp-host/role-turn-host.ts +7 -42
  21. package/src/analyst-ledger.ts +20 -1
  22. package/src/analyst-metric-families/acceptance-success-rework.ts +5 -15
  23. package/src/analyst-metric-families/b2-frame-buckets-actions.ts +3 -7
  24. package/src/analyst-metric-families/gate-cycles.ts +2 -8
  25. package/src/analyst-metric-families/leg-wall-clock.ts +4 -16
  26. package/src/analyst-metric-families/round-timeline.ts +1 -5
  27. package/src/analyst-model-groups.ts +1 -10
  28. package/src/analyst-page.ts +4 -16
  29. package/src/external-host-turn-loop.ts +36 -16
  30. package/src/headless-host/description.ts +3 -18
  31. package/src/headless-host/production-host.ts +3 -2
  32. package/src/headless-host/role-turn-host.ts +10 -68
  33. package/src/host-descriptions.ts +18 -0
  34. package/src/prepared-role-turn.ts +8 -0
  35. package/src/public-cli/machine-method-skills.ts +5 -5
@@ -212,11 +212,26 @@ function admitFrameSpanFromRows(rows) {
212
212
  }
213
213
  return {
214
214
  models,
215
- frameSpan: { startedAt: span.startedAt, endedAt: span.endedAt },
215
+ frameSpan: { startedAt: span.startedAt, endedAt: span.endedAt, wallMs: endedMs - startedMs },
216
216
  partialFirstFrameAt: { status: "present", at: span.startedAt },
217
217
  partialLastFrameAt: { status: "present", at: span.endedAt },
218
218
  };
219
219
  }
220
+ /** Total wall clock for exactly the readable runs supplied by the caller. */
221
+ export function sumAnalystRunWallMs(runs) {
222
+ let total = 0;
223
+ for (const run of runs)
224
+ total += run.frameSpan.wallMs;
225
+ return total;
226
+ }
227
+ /** Shared identity order for readable legs and their page/metric projections. */
228
+ export function compareAnalystLegs(a, b) {
229
+ if (a.book !== b.book)
230
+ return a.book.localeCompare(b.book);
231
+ if (a.role !== b.role)
232
+ return a.role.localeCompare(b.role);
233
+ return a.runId.localeCompare(b.runId);
234
+ }
220
235
  async function classifyScopedRun(input) {
221
236
  const missingSources = [];
222
237
  const reasons = [];
@@ -1,3 +1,15 @@
1
+ /**
2
+ * B3 metric family: acceptance terminal mapping, rework lens, first-pass / success rates.
3
+ *
4
+ * Consumes only A2 typed per-run facts (frame span + terminal face). Drop-in
5
+ * registration via analyst-metric-families/ discovery — no shared skeleton edits.
6
+ *
7
+ * Denominator contract (PRD #298 + ticket #327 票面补正):
8
+ * - first-pass rate den = appearance lanes (no-receipt first call stays in den)
9
+ * - success rate den = success-eligible accepted legs (no-receipt out; planned out)
10
+ * - planned = plan-duty acceptance; never success numerator or denominator
11
+ */
12
+ import { compareAnalystLegs, sumAnalystRunWallMs } from "../analyst-ledger.js";
1
13
  import { medianNumber } from "../analyst-median.js";
2
14
  import { packagedAnalystTerminal } from "../packaged-role-registry.js";
3
15
  const WORKER_ROLES = new Set(["coder", "fixer"]);
@@ -23,9 +35,6 @@ const SUCCESS_STATUS = {
23
35
  function isRecord(value) {
24
36
  return typeof value === "object" && value !== null && !Array.isArray(value);
25
37
  }
26
- function wallMsFromSpan(span) {
27
- return Date.parse(span.endedAt) - Date.parse(span.startedAt);
28
- }
29
38
  /** Locate collector groups array: receipt.groups or top-level groups. */
30
39
  function findCollectorGroups(body) {
31
40
  if (Array.isArray(body.groups))
@@ -143,7 +152,7 @@ function projectLegs(runs) {
143
152
  book: run.book,
144
153
  role: run.role,
145
154
  startedAt: run.frameSpan.startedAt,
146
- wallMs: wallMsFromSpan(run.frameSpan),
155
+ wallMs: run.frameSpan.wallMs,
147
156
  terminalLabel: mapped.terminalLabel,
148
157
  accepted: mapped.accepted,
149
158
  success: mapped.success,
@@ -154,13 +163,7 @@ function projectLegs(runs) {
154
163
  });
155
164
  }
156
165
  // Stable page order: book, role, runId (match A1 leg sort).
157
- return legs.sort((a, b) => {
158
- if (a.book !== b.book)
159
- return a.book.localeCompare(b.book);
160
- if (a.role !== b.role)
161
- return a.role.localeCompare(b.role);
162
- return a.runId.localeCompare(b.runId);
163
- });
166
+ return legs.sort(compareAnalystLegs);
164
167
  }
165
168
  function aggregateByRole(legs) {
166
169
  const roles = [...new Set(legs.map((leg) => leg.role))].sort((a, b) => a.localeCompare(b));
@@ -207,12 +210,10 @@ function aggregateByRole(legs) {
207
210
  };
208
211
  });
209
212
  }
210
- function reworkLens(legs) {
213
+ function reworkLens(legs, totalWallMs) {
211
214
  let reworkWallMs = 0;
212
- let totalWallMs = 0;
213
215
  let reworkLegCount = 0;
214
216
  for (const leg of legs) {
215
- totalWallMs += leg.wallMs;
216
217
  if (leg.rework) {
217
218
  reworkWallMs += leg.wallMs;
218
219
  reworkLegCount += 1;
@@ -234,7 +235,7 @@ export function buildAcceptanceSuccessReworkSection(runs) {
234
235
  kind: "analyst-acceptance-success-rework",
235
236
  legs,
236
237
  byRole: aggregateByRole(legs),
237
- rework: reworkLens(legs),
238
+ rework: reworkLens(legs, sumAnalystRunWallMs(runs)),
238
239
  };
239
240
  }
240
241
  const acceptanceSuccessReworkFamily = {
@@ -1,4 +1,5 @@
1
1
  import { medianNumber } from "../analyst-median.js";
2
+ import { compareAnalystLegs } from "../analyst-ledger.js";
2
3
  function timestampMs(iso) {
3
4
  const ms = Date.parse(iso);
4
5
  if (!Number.isFinite(ms)) {
@@ -141,7 +142,7 @@ function sortActionsDescending(actions) {
141
142
  export function computeAnalystB2RunMetrics(facts) {
142
143
  const frameStartMs = timestampMs(facts.frameSpan.startedAt);
143
144
  const frameEndMs = timestampMs(facts.frameSpan.endedAt);
144
- const wallMs = Math.max(0, frameEndMs - frameStartMs);
145
+ const wallMs = facts.frameSpan.wallMs;
145
146
  // Single frame-bounded core: clip → union once → bucket/complement/actions.
146
147
  const tools = clipToolsToFrame(closedTools(facts.toolIntervals), frameStartMs, frameEndMs);
147
148
  const toolUnion = mergeUnion(tools);
@@ -172,13 +173,7 @@ const b2FrameBucketsActionsFamily = {
172
173
  return undefined;
173
174
  const runs = [...input.runs]
174
175
  .map(computeAnalystB2RunMetrics)
175
- .sort((a, b) => {
176
- if (a.book !== b.book)
177
- return a.book.localeCompare(b.book);
178
- if (a.role !== b.role)
179
- return a.role.localeCompare(b.role);
180
- return a.runId.localeCompare(b.runId);
181
- });
176
+ .sort(compareAnalystLegs);
182
177
  const section = {
183
178
  kind: "analyst-b2-frame-buckets-actions",
184
179
  runs,
@@ -1,3 +1,4 @@
1
+ import { compareAnalystLegs } from "../analyst-ledger.js";
1
2
  function projectRound(round) {
2
3
  return {
3
4
  roundIndex: round.roundIndex,
@@ -18,13 +19,6 @@ function projectLeg(facts) {
18
19
  rounds,
19
20
  };
20
21
  }
21
- function compareLegs(a, b) {
22
- if (a.book !== b.book)
23
- return a.book.localeCompare(b.book);
24
- if (a.role !== b.role)
25
- return a.role.localeCompare(b.role);
26
- return a.runId.localeCompare(b.runId);
27
- }
28
22
  function emptyAccum() {
29
23
  return { rounds: 0, bounceCount: 0, passCount: 0, wallSum: 0 };
30
24
  }
@@ -65,7 +59,7 @@ const gateCyclesFamily = {
65
59
  contribute(input) {
66
60
  if (input.runs.length === 0)
67
61
  return undefined;
68
- const legs = input.runs.map(projectLeg).sort(compareLegs);
62
+ const legs = input.runs.map(projectLeg).sort(compareAnalystLegs);
69
63
  const section = {
70
64
  kind: "analyst-gate-cycles",
71
65
  legs,
@@ -6,25 +6,19 @@
6
6
  * Registers by file drop under analyst-metric-families/ (A2 discovery).
7
7
  */
8
8
  import { medianNumber } from "../analyst-median.js";
9
- function frameSpanWallMs(span) {
10
- return Date.parse(span.endedAt) - Date.parse(span.startedAt);
11
- }
9
+ import { compareAnalystLegs, sumAnalystRunWallMs } from "../analyst-ledger.js";
12
10
  function projectEntry(facts) {
13
11
  return {
14
12
  runId: facts.runId,
15
13
  book: facts.book,
16
14
  role: facts.role,
17
- wallMs: frameSpanWallMs(facts.frameSpan),
15
+ wallMs: facts.frameSpan.wallMs,
18
16
  };
19
17
  }
20
18
  function compareRankingDesc(a, b) {
21
19
  if (b.wallMs !== a.wallMs)
22
20
  return b.wallMs - a.wallMs;
23
- if (a.book !== b.book)
24
- return a.book.localeCompare(b.book);
25
- if (a.role !== b.role)
26
- return a.role.localeCompare(b.role);
27
- return a.runId.localeCompare(b.runId);
21
+ return compareAnalystLegs(a, b);
28
22
  }
29
23
  /** Discovered by analyst-metric-families loader (default export). */
30
24
  const legWallClockFamily = {
@@ -41,14 +35,11 @@ const legWallClockFamily = {
41
35
  if (medianWallMs === undefined) {
42
36
  return undefined;
43
37
  }
44
- let totalElapsedMs = 0;
45
- for (const wallMs of walls)
46
- totalElapsedMs += wallMs;
47
38
  const section = {
48
39
  kind: "analyst-leg-wall-clock",
49
40
  ranking,
50
41
  medianWallMs,
51
- totalElapsedMs,
42
+ totalElapsedMs: sumAnalystRunWallMs(input.runs),
52
43
  };
53
44
  return { legWallClock: section };
54
45
  },
@@ -2,9 +2,6 @@ import { extractStatus } from "./acceptance-success-rework.js";
2
2
  function isRecord(value) {
3
3
  return typeof value === "object" && value !== null && !Array.isArray(value);
4
4
  }
5
- function wallMsFromSpan(startedAt, endedAt) {
6
- return Date.parse(endedAt) - Date.parse(startedAt);
7
- }
8
5
  function readClassCount(body) {
9
6
  if (!isRecord(body.outcome))
10
7
  return undefined;
@@ -44,7 +41,7 @@ function projectRunRow(facts) {
44
41
  role: facts.role,
45
42
  startedAt,
46
43
  endedAt,
47
- wallMs: wallMsFromSpan(startedAt, endedAt),
44
+ wallMs: facts.frameSpan.wallMs,
48
45
  terminal: projectTerminal(facts),
49
46
  };
50
47
  }
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import { buildAcceptanceSuccessReworkSection } from "./analyst-metric-families/acceptance-success-rework.js";
12
12
  import { medianNumber } from "./analyst-median.js";
13
+ import { sortUnreadable } from "./analyst-page.js";
13
14
  /**
14
15
  * Build the raw group key for one leg from its ordered-unique model sequence.
15
16
  * Empty sequence → undefined (no inventable group; caller lists as typed vacancy).
@@ -33,13 +34,6 @@ function displayNameFor(rawGroupKey, combinationMapping) {
33
34
  const aliased = combinationMapping[rawGroupKey];
34
35
  return aliased === undefined ? rawGroupKey : aliased;
35
36
  }
36
- function sortUnreadable(unreadable) {
37
- return [...unreadable].sort((a, b) => {
38
- if (a.book !== b.book)
39
- return a.book.localeCompare(b.book);
40
- return a.runId.localeCompare(b.runId);
41
- });
42
- }
43
37
  /**
44
38
  * Legs with no usable session model identity cannot join any model group.
45
39
  * Reuse the typed unreadable path (locatable missing-source) — not an empty-key group.
@@ -10,6 +10,7 @@ import { createHash } from "node:crypto";
10
10
  import { dirname, join } from "node:path";
11
11
  import { writeFileAtomically } from "./atomic-write.js";
12
12
  import { assertLedgerFileInsideHome, ensureRealDirectoryTree, physicalPathIdentity, } from "./activation-ledger-topology.js";
13
+ import { compareAnalystLegs, sumAnalystRunWallMs } from "./analyst-ledger.js";
13
14
  import { loadAnalystIssueMetricFamilies } from "./analyst-metric-families.js";
14
15
  import { composeAnalystMetricFamilySections } from "./analyst-metric-family.js";
15
16
  export function analystIssuePageKey(address) {
@@ -35,15 +36,9 @@ export function analystIssuePageAddressFromPage(page) {
35
36
  };
36
37
  }
37
38
  function sortLegs(legs) {
38
- return [...legs].sort((a, b) => {
39
- if (a.book !== b.book)
40
- return a.book.localeCompare(b.book);
41
- if (a.role !== b.role)
42
- return a.role.localeCompare(b.role);
43
- return a.runId.localeCompare(b.runId);
44
- });
39
+ return [...legs].sort(compareAnalystLegs);
45
40
  }
46
- function sortUnreadable(unreadable) {
41
+ export function sortUnreadable(unreadable) {
47
42
  return [...unreadable].sort((a, b) => {
48
43
  if (a.book !== b.book)
49
44
  return a.book.localeCompare(b.book);
@@ -95,19 +90,15 @@ export function computeAnalystMsPerKLines(totalElapsedMs, changedLines) {
95
90
  value: totalElapsedMs / (changedLines.value / 1000),
96
91
  };
97
92
  }
98
- function frameSpanWallMs(span) {
99
- return Date.parse(span.endedAt) - Date.parse(span.startedAt);
100
- }
101
93
  /**
102
94
  * Σ readable wall clocks + max end-frame across ALL runs (C1 efficiency / index).
103
95
  * Unreadable runs never enter totalElapsedMs; their available lastFrameAt still
104
96
  * competes for lastActivityAt (PRD ②: 全部 run 末帧之最大者).
105
97
  */
106
98
  export function summarizeAnalystRunEfficiency(runs, unreadable = []) {
107
- let totalElapsedMs = 0;
99
+ const totalElapsedMs = sumAnalystRunWallMs(runs);
108
100
  let latestEndedAt;
109
101
  for (const run of runs) {
110
- totalElapsedMs += frameSpanWallMs(run.frameSpan);
111
102
  const endedAt = run.frameSpan.endedAt;
112
103
  if (latestEndedAt === undefined || endedAt > latestEndedAt) {
113
104
  latestEndedAt = endedAt;
@@ -1,20 +1,9 @@
1
- /**
2
- * Headless CLI host descriptions (#645 / #646 / #752).
3
- * Shared lifecycle owns spawn/bind/close; each protocol owns argv + parse shape.
4
- * Claude print-mode and codex exec differ enough that #752 host-specific
5
- * assembly lives here as sibling helpers — not a third unified abstraction.
6
- */
7
- import { join } from "node:path";
8
1
  export function isClaudePrintDescription(description) {
9
2
  return description.protocol === "claude-print";
10
3
  }
11
4
  export function isCodexExecDescription(description) {
12
5
  return description.protocol === "codex-exec";
13
6
  }
14
- /** Absolute agent binary for one operator home. */
15
- export function resolveHeadlessBinary(description, operatorHome) {
16
- return join(operatorHome, ...description.binaryFromHome);
17
- }
18
7
  /**
19
8
  * Build one Claude print-mode argv for a single process turn.
20
9
  * Shape: `<promptFlag> <fixedArgs…> <system/schema/mcp/model/effort/session…>`.