@unbrained/pm-cli 2026.9.3 → 2026.9.4

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 (120) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +27 -0
  3. package/dist/cli-bundle/bundle-manifest.json +146 -146
  4. package/dist/cli-bundle/chunks/{chunk-E5RBBCXO.js → chunk-6XSKPNCF.js} +75 -75
  5. package/dist/cli-bundle/chunks/chunk-A24WAVE6.js +8 -0
  6. package/dist/cli-bundle/chunks/{chunk-DKGP3QLE.js → chunk-HI6BHPCU.js} +2 -2
  7. package/dist/cli-bundle/chunks/{chunk-Y4PJ6HPK.js → chunk-I2AS367G.js} +2 -2
  8. package/dist/cli-bundle/chunks/{chunk-IEHHE6GA.js → chunk-OGBVU67G.js} +2 -2
  9. package/dist/cli-bundle/chunks/{chunk-EDPIS7EB.js → chunk-RI4XNOYS.js} +2 -2
  10. package/dist/cli-bundle/chunks/chunk-TXW6VL33.js +38 -0
  11. package/dist/cli-bundle/chunks/{chunk-LENC656S.js → chunk-V72UV7QS.js} +76 -79
  12. package/dist/cli-bundle/chunks/chunk-VGLHECAP.js +9 -0
  13. package/dist/cli-bundle/chunks/{chunk-34HASX3S.js → chunk-X6CMGV6L.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-UPPM2FOZ.js → chunk-YW4QK2G7.js} +2 -2
  15. package/dist/cli-bundle/chunks/{register-list-query-W2ZTOMKP.js → register-list-query-Z5YYSJJG.js} +2 -2
  16. package/dist/cli-bundle/chunks/{register-mutation-RVND5NCG.js → register-mutation-ELSP6I4I.js} +2 -2
  17. package/dist/cli-bundle/chunks/{register-operations-TTROIVC4.js → register-operations-OH7R3ZT4.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-setup-D3ZFHY3L.js → register-setup-E2AE72QG.js} +2 -2
  19. package/dist/cli-bundle/focused-chunks/{chunk-Q45NHPF2.js → chunk-25UJBH4M.js} +2 -2
  20. package/dist/cli-bundle/focused-chunks/{chunk-4HJFY4MB.js → chunk-3646BZ4W.js} +2 -2
  21. package/dist/cli-bundle/focused-chunks/{chunk-TXE4TSHM.js → chunk-4YRAVI43.js} +2 -2
  22. package/dist/cli-bundle/focused-chunks/{chunk-M5M6SVHS.js → chunk-53IHPICX.js} +2 -2
  23. package/dist/cli-bundle/focused-chunks/chunk-5P4HVOWG.js +176 -0
  24. package/dist/cli-bundle/focused-chunks/chunk-636VVQ7F.js +54 -0
  25. package/dist/cli-bundle/focused-chunks/{chunk-D7KXFBXV.js → chunk-6PWPQKDN.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/{chunk-S27XMBIN.js → chunk-7N2TV7WZ.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/{chunk-5RFXUPN5.js → chunk-AJR3OP2E.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-KZ2NB3ET.js → chunk-B3A6MJYE.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-BWKHEIVF.js → chunk-BFDDJ2T2.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-4WR46RMG.js → chunk-BHUIRZWQ.js} +8 -8
  31. package/dist/cli-bundle/focused-chunks/{chunk-4RRHC3S4.js → chunk-JADHHPY6.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-GT7MXDLW.js → chunk-MHKUIPJW.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/chunk-NBMJD6MK.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/chunk-NSKBLHVI.js +20 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-OL5EH6I3.js → chunk-P2GOAOQN.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-UCLO3XDU.js → chunk-YARWJM2B.js} +2 -2
  37. package/dist/cli-bundle/main.js +2 -2
  38. package/dist/cli-bundle/sdk-authoring.js +1 -1
  39. package/dist/cli-bundle/sdk-contracts.js +1 -1
  40. package/dist/cli-bundle/sdk-core.js +28 -31
  41. package/dist/cli-bundle/sdk-governance.js +1 -1
  42. package/dist/cli-bundle/sdk-graph.js +1 -1
  43. package/dist/cli-bundle/sdk-merge.js +42 -37
  44. package/dist/cli-bundle/sdk-query.js +1 -1
  45. package/dist/cli-bundle/sdk-runtime.js +1 -1
  46. package/dist/cli-bundle/sdk-testing.js +1 -1
  47. package/dist/cli-bundle/sdk.js +10 -10
  48. package/dist/core/diagnostics/remediation.js +4 -4
  49. package/dist/core/history/history.d.ts +37 -1
  50. package/dist/core/history/history.js +278 -58
  51. package/dist/core/history/replay.js +68 -34
  52. package/dist/core/lock/lock.d.ts +10 -0
  53. package/dist/core/lock/lock.js +42 -3
  54. package/dist/core/shared/author.d.ts +3 -1
  55. package/dist/core/shared/author.js +111 -23
  56. package/dist/sdk/environment/agent-environment.d.ts +296 -0
  57. package/dist/sdk/environment/agent-environment.js +467 -0
  58. package/dist/sdk/environment/project-runtime-compatibility.d.ts +19 -1
  59. package/dist/sdk/environment/project-runtime-compatibility.js +118 -21
  60. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +14 -2
  61. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -14
  62. package/dist/sdk/governance/health.js +13 -44
  63. package/dist/sdk/governance/merge-receipt-history.d.ts +62 -0
  64. package/dist/sdk/governance/merge-receipt-history.js +207 -0
  65. package/dist/sdk/governance/provenance-health.js +9 -3
  66. package/dist/sdk/history-compact.js +14 -5
  67. package/dist/sdk/history-redact.js +58 -23
  68. package/dist/sdk/history-repair.js +16 -6
  69. package/dist/sdk/index.d.ts +2 -0
  70. package/dist/sdk/index.js +4 -2
  71. package/dist/sdk/merge/driver.d.ts +3 -1
  72. package/dist/sdk/merge/driver.js +9 -9
  73. package/dist/sdk/merge/index.d.ts +1 -1
  74. package/dist/sdk/merge/index.js +3 -3
  75. package/dist/sdk/merge/receipts.d.ts +17 -6
  76. package/dist/sdk/merge/receipts.js +246 -75
  77. package/dist/sdk/merge/reconcile.d.ts +9 -7
  78. package/dist/sdk/merge/reconcile.js +175 -12
  79. package/dist/sdk/merge/three-way.d.ts +22 -2
  80. package/dist/sdk/merge/three-way.js +92 -25
  81. package/dist/sdk/runtime-primitives.d.ts +2 -2
  82. package/dist/sdk/runtime-primitives.js +4 -4
  83. package/dist/types.d.ts +25 -0
  84. package/dist/types.js +2 -2
  85. package/docs/AGENT_ENVIRONMENTS.md +47 -0
  86. package/docs/AGENT_PROVENANCE_ADR.md +17 -2
  87. package/docs/CONTEXT_INTEGRITY_CONTRACTS.md +38 -1
  88. package/docs/MERGE_SAFETY.md +119 -23
  89. package/docs/README.md +1 -0
  90. package/docs/SDK_CONTEXT_EVIDENCE_CONTRACTS.md +24 -2
  91. package/docs/SDK_RUNTIME_BOUNDARIES.md +17 -1
  92. package/docs/examples/sdk-agent-environment/README.md +14 -0
  93. package/docs/examples/sdk-agent-environment/package.json +8 -0
  94. package/docs/examples/sdk-agent-environment/run-agent-environment.mjs +154 -0
  95. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +4 -3
  96. package/marketplace.json +2 -2
  97. package/package.json +2 -2
  98. package/packages/pm-beads/package.json +1 -1
  99. package/packages/pm-calendar/package.json +1 -1
  100. package/packages/pm-command-kit/package.json +1 -1
  101. package/packages/pm-digital-twin/package.json +1 -1
  102. package/packages/pm-governance-audit/package.json +1 -1
  103. package/packages/pm-guide-shell/package.json +1 -1
  104. package/packages/pm-kanban/package.json +1 -1
  105. package/packages/pm-lifecycle-hooks/package.json +1 -1
  106. package/packages/pm-linked-test-adapters/package.json +1 -1
  107. package/packages/pm-search-advanced/package.json +1 -1
  108. package/packages/pm-templates/package.json +1 -1
  109. package/packages/pm-todos/package.json +1 -1
  110. package/packages/pm-vcs/package.json +1 -1
  111. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  112. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  113. package/sdk/public-surface.json +534 -24
  114. package/dist/cli-bundle/chunks/chunk-AY324UJ5.js +0 -9
  115. package/dist/cli-bundle/chunks/chunk-L7B7343B.js +0 -8
  116. package/dist/cli-bundle/chunks/chunk-LISESA7W.js +0 -35
  117. package/dist/cli-bundle/focused-chunks/chunk-3ZBI35HU.js +0 -176
  118. package/dist/cli-bundle/focused-chunks/chunk-GHCZ3YFR.js +0 -20
  119. package/dist/cli-bundle/focused-chunks/chunk-KBLZRU62.js +0 -2
  120. package/dist/cli-bundle/focused-chunks/chunk-QKHCSUGJ.js +0 -51
@@ -4,8 +4,9 @@
4
4
  * Coordinates tracker lock ownership and cleanup for Lock.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7352375d-55f2-5751-934e-ba0cd5c358d5")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b21a63b8-9da9-5c7c-b288-3a2dae342bef")}catch(e){}}();
8
8
  import { isFileMissingError } from "../fs/fs-utils.js";
9
+ import { constants as fsConstants } from "node:fs";
9
10
  import fs from "node:fs/promises";
10
11
  import path from "node:path";
11
12
  import { randomUUID } from "node:crypto";
@@ -95,6 +96,43 @@ function isErrno(error, code) {
95
96
  "code" in error &&
96
97
  error.code === code);
97
98
  }
99
+ /**
100
+ * Classify exclusive-create failures that prove another lock lifecycle is in
101
+ * flight. Windows can report `EPERM`, `EACCES`, or `EBUSY` while a just-unlinked
102
+ * lock is still delete-pending; treating those as fatal makes bounded lock
103
+ * waiting fail nondeterministically. Existing paths are contention on every
104
+ * host. A missing or temporarily unstatable Windows path is contention only
105
+ * when its parent remains writable, preserving genuine permission failures.
106
+ */
107
+ async function isLockCreateContention(error, lockPath, platform = process.platform) {
108
+ if (isErrno(error, "EEXIST"))
109
+ return true;
110
+ if (!isErrno(error, "EPERM") &&
111
+ !isErrno(error, "EACCES") &&
112
+ !isErrno(error, "EBUSY")) {
113
+ return false;
114
+ }
115
+ try {
116
+ await fs.lstat(lockPath);
117
+ return true;
118
+ }
119
+ catch (probeError) {
120
+ if (platform !== "win32" ||
121
+ (!isFileMissingError(probeError) &&
122
+ !isErrno(probeError, "EPERM") &&
123
+ !isErrno(probeError, "EACCES") &&
124
+ !isErrno(probeError, "EBUSY"))) {
125
+ return false;
126
+ }
127
+ }
128
+ try {
129
+ await fs.access(path.dirname(lockPath), fsConstants.W_OK);
130
+ return true;
131
+ }
132
+ catch {
133
+ return false;
134
+ }
135
+ }
98
136
  async function emitLockWriteHook(lockPath, op) {
99
137
  await runActiveOnWriteHooks({
100
138
  path: lockPath,
@@ -464,6 +502,7 @@ export const _testOnly = {
464
502
  parseLockInfo,
465
503
  readLockInfo,
466
504
  isErrno,
505
+ isLockCreateContention,
467
506
  buildLockPayload,
468
507
  isStaleLock,
469
508
  lockOwnerSuffix,
@@ -515,7 +554,7 @@ export async function acquireLock(pmRoot, id, ttlSeconds, owner, force = false,
515
554
  };
516
555
  }
517
556
  catch (error) {
518
- if (!isErrno(error, "EEXIST")) {
557
+ if (!(await isLockCreateContention(error, lockPath))) {
519
558
  throw new PmCliError(`Failed to acquire lock for ${id}: ${toErrorMessage(error)}`, EXIT_CODE.GENERIC_FAILURE);
520
559
  }
521
560
  let lockInfo = await readLockInfo(lockPath);
@@ -549,4 +588,4 @@ export async function acquireLock(pmRoot, id, ttlSeconds, owner, force = false,
549
588
  }
550
589
  }
551
590
  //# sourceMappingURL=lock.js.map
552
- //# debugId=7352375d-55f2-5751-934e-ba0cd5c358d5
591
+ //# debugId=b21a63b8-9da9-5c7c-b288-3a2dae342bef
@@ -26,7 +26,7 @@ export interface AgentProvenanceObservation {
26
26
  */
27
27
  export type AgentProvenance = Readonly<Record<string, AgentProvenanceObservation | null>>;
28
28
  /** Bounded reason explaining why one declared provenance dimension was absent. */
29
- export type AgentProvenanceAbsenceReason = "harness_unavailable" | "resolver_failed" | "resolver_not_configured" | "probes_disabled" | "invalid_value";
29
+ export type AgentProvenanceAbsenceReason = "harness_unavailable" | "resolver_input_missing" | "resolver_failed" | "resolver_not_configured" | "probes_disabled" | "invalid_value";
30
30
  /** Machine-readable resolution outcome for one provenance dimension. */
31
31
  export interface AgentProvenanceOutcome {
32
32
  /** Whether the dimension resolved without retaining private source material. */
@@ -168,6 +168,8 @@ export interface HarnessDetectionSignals {
168
168
  cwd?: string;
169
169
  /** Home directory override used by embedders and isolated tests. */
170
170
  home_dir?: string;
171
+ /** Explicit harness-owned session file supplied by an embedding host. */
172
+ session_file?: string;
171
173
  }
172
174
  /** Built-in agent descriptors evaluated before package and workspace additions. */
173
175
  export declare const BUILTIN_HARNESS_SIGNAL_DESCRIPTORS: readonly HarnessSignalDescriptor[];
@@ -4,7 +4,7 @@
4
4
  * Provides shared primitives and utilities for Author.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="cf550961-0040-5e04-9d8d-16e316027e43")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="dfbf4eb8-1f02-5880-a70a-0e7ed9b9784a")}catch(e){}}();
8
8
  import { AsyncLocalStorage } from "node:async_hooks";
9
9
  import { createHash } from "node:crypto";
10
10
  import fs from "node:fs";
@@ -12,6 +12,7 @@ import os from "node:os";
12
12
  import path from "node:path";
13
13
  import { resolveAgentSessionContextFromSignals, } from "./agent-session-context.js";
14
14
  import { readAgentSemanticAttributionSync, } from "../session/session-state.js";
15
+ import { isFileAbsentError } from "../fs/fs-utils.js";
15
16
  /** Stable built-in provenance dimensions understood by the default runtime. */
16
17
  export const AGENT_PROVENANCE_DIMENSIONS = [
17
18
  "model",
@@ -357,18 +358,83 @@ function parseClaudeProvenanceLine(line) {
357
358
  }
358
359
  return Object.freeze({ model, version });
359
360
  }
360
- function readClaudeSessionProvenance(dimension, signals, env) {
361
+ /** Classify one candidate without following symlinks or leaking filesystem detail. */
362
+ function claudeTranscriptCandidateStatus(candidate) {
363
+ try {
364
+ return fs.lstatSync(candidate).isFile() ? "available" : "missing";
365
+ }
366
+ catch (error) {
367
+ return isFileAbsentError(error) ? "missing" : "failed";
368
+ }
369
+ }
370
+ /** Resolve a bounded cross-workspace Claude transcript discovery result. */
371
+ function discoverClaudeSessionFile(projectsRoot, session) {
372
+ let discovered;
373
+ try {
374
+ discovered = fs
375
+ .readdirSync(projectsRoot, { withFileTypes: true })
376
+ .filter((entry) => entry.isDirectory())
377
+ .sort((left, right) => left.name.localeCompare(right.name))
378
+ .slice(0, 512)
379
+ .map((entry) => {
380
+ const candidate = path.join(projectsRoot, entry.name, `${session}.jsonl`);
381
+ return {
382
+ candidate,
383
+ status: claudeTranscriptCandidateStatus(candidate),
384
+ };
385
+ });
386
+ }
387
+ catch (error) {
388
+ return { status: isFileAbsentError(error) ? "missing" : "failed" };
389
+ }
390
+ const matches = discovered
391
+ .filter(({ status }) => status === "available")
392
+ .map(({ candidate }) => candidate);
393
+ if (matches.length === 0) {
394
+ return {
395
+ status: discovered.some(({ status }) => status === "failed")
396
+ ? "failed"
397
+ : "missing",
398
+ };
399
+ }
400
+ if (matches.length > 1)
401
+ return { status: "ambiguous" };
402
+ return { status: "available", path: matches[0] };
403
+ }
404
+ /** Resolve one Claude transcript by stable session identity without exposing its path. */
405
+ function resolveClaudeSessionFile(signals, env) {
361
406
  const session = nonBlank(env.CLAUDE_CODE_SESSION_ID);
362
- if (!session || !/^[A-Za-z0-9_-]{1,128}$/u.test(session))
363
- return undefined;
407
+ if (!session || !/^[A-Za-z0-9_-]{1,128}$/u.test(session)) {
408
+ return { status: "unavailable" };
409
+ }
364
410
  const workspace = path.resolve(signals.cwd ?? process.cwd());
365
411
  const encodedWorkspace = workspace.replaceAll(/[^A-Za-z0-9-]/gu, "-");
366
- const sessionPath = path.join(signals.home_dir ?? os.homedir(), ".claude", "projects", encodedWorkspace, `${session}.jsonl`);
412
+ const projectsRoot = path.join(signals.home_dir ?? os.homedir(), ".claude", "projects");
413
+ const directPath = path.join(projectsRoot, encodedWorkspace, `${session}.jsonl`);
414
+ const explicitPath = nonBlank(signals.session_file);
415
+ const suppliedPath = explicitPath && path.basename(explicitPath) === `${session}.jsonl`
416
+ ? explicitPath
417
+ : undefined;
418
+ for (const candidate of [suppliedPath, directPath]) {
419
+ if (!candidate)
420
+ continue;
421
+ const status = claudeTranscriptCandidateStatus(candidate);
422
+ if (status === "available")
423
+ return { status, path: candidate };
424
+ if (status === "failed")
425
+ return { status };
426
+ }
427
+ return discoverClaudeSessionFile(projectsRoot, session);
428
+ }
429
+ function readClaudeSessionProvenance(dimension, signals, env) {
430
+ const resolution = resolveClaudeSessionFile(signals, env);
431
+ if (resolution.status !== "available")
432
+ return undefined;
367
433
  try {
368
- const file = fs.openSync(sessionPath, "r");
434
+ const file = fs.openSync(resolution.path, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
369
435
  try {
370
436
  const stats = fs.fstatSync(file);
371
- const cacheKey = `${sessionPath}\u0000${stats.size}\u0000${stats.mtimeMs}`;
437
+ const cacheKey = `${resolution.path}\u0000${stats.size}\u0000${stats.mtimeMs}`;
372
438
  const cached = claudeProvenanceSnapshotCache.get(cacheKey);
373
439
  if (cached)
374
440
  return cached[dimension];
@@ -553,14 +619,20 @@ function resolveProvenanceProbe(dimension, signals, env, descriptor) {
553
619
  }
554
620
  return undefined;
555
621
  }
556
- function provenanceResolverHasInput(resolver, descriptor, env) {
622
+ function provenanceResolverHasInput(resolver, descriptor, signals, env) {
557
623
  if (resolver === "ai_agent_version") {
558
624
  const value = nonBlank(env.AI_AGENT);
559
- return (value !== undefined && literalSignalMatches(value, descriptor.harness));
625
+ return value !== undefined &&
626
+ literalSignalMatches(value, descriptor.harness)
627
+ ? "available"
628
+ : "unavailable";
629
+ }
630
+ if (resolver === "codex_session_file") {
631
+ return nonBlank(env.CODEX_THREAD_ID) !== undefined
632
+ ? "available"
633
+ : "unavailable";
560
634
  }
561
- return resolver === "codex_session_file"
562
- ? nonBlank(env.CODEX_THREAD_ID) !== undefined
563
- : nonBlank(env.CLAUDE_CODE_SESSION_ID) !== undefined;
635
+ return resolveClaudeSessionFile(signals, env).status;
564
636
  }
565
637
  function effectiveHarnessDetectionSignals(signals) {
566
638
  if (signals)
@@ -907,7 +979,17 @@ export function detectAgentIdentity(signals) {
907
979
  ];
908
980
  return Object.fromEntries(entries.filter((entry) => entry[1] !== undefined));
909
981
  }
910
- function resolveProvenanceOutcome(dimension, identity, descriptor, env, probesEnabled, invalidValue) {
982
+ /** Classify one configured resolver's privacy-safe absence outcome. */
983
+ function provenanceResolverAbsence(resolverInput) {
984
+ if (resolverInput === "unavailable") {
985
+ return { status: "unavailable", reason: "harness_unavailable" };
986
+ }
987
+ if (resolverInput === "missing") {
988
+ return { status: "unavailable", reason: "resolver_input_missing" };
989
+ }
990
+ return { status: "failed", reason: "resolver_failed" };
991
+ }
992
+ function resolveProvenanceOutcome(dimension, identity, descriptor, signals, env, probesEnabled, invalidValue) {
911
993
  const resolver = descriptor?.provenance_resolvers[dimension];
912
994
  if (identity.provenance?.[dimension]) {
913
995
  return {
@@ -924,14 +1006,20 @@ function resolveProvenanceOutcome(dimension, identity, descriptor, env, probesEn
924
1006
  };
925
1007
  }
926
1008
  if (resolver) {
927
- const resolverHasInput = provenanceResolverHasInput(resolver, descriptor, env);
928
- const status = resolverHasInput && probesEnabled ? "failed" : "unavailable";
929
- const reason = !resolverHasInput
930
- ? "harness_unavailable"
931
- : probesEnabled
932
- ? "resolver_failed"
933
- : "probes_disabled";
934
- return { status, reason, resolver, rule_version: "v1" };
1009
+ if (!probesEnabled) {
1010
+ return {
1011
+ status: "unavailable",
1012
+ reason: "probes_disabled",
1013
+ resolver,
1014
+ rule_version: "v1",
1015
+ };
1016
+ }
1017
+ const resolverInput = provenanceResolverHasInput(resolver, descriptor, signals, env);
1018
+ return {
1019
+ ...provenanceResolverAbsence(resolverInput),
1020
+ resolver,
1021
+ rule_version: "v1",
1022
+ };
935
1023
  }
936
1024
  return {
937
1025
  status: descriptor?.provenance_unavailable_dimensions.includes(dimension)
@@ -972,7 +1060,7 @@ export function diagnoseAgentIdentity(signals) {
972
1060
  });
973
1061
  const outcomes = Object.fromEntries(AGENT_PROVENANCE_DIMENSIONS.map((dimension) => [
974
1062
  dimension,
975
- resolveProvenanceOutcome(dimension, identity, descriptor, env, probesEnabled, dimension === "role" && invalidRoleValue),
1063
+ resolveProvenanceOutcome(dimension, identity, descriptor, effectiveSignals, env, probesEnabled, dimension === "role" && invalidRoleValue),
976
1064
  ]));
977
1065
  return { ...identity, provenance_outcomes: outcomes };
978
1066
  }
@@ -1082,4 +1170,4 @@ export function resolveAuthor(candidate, fallback) {
1082
1170
  return identity.author;
1083
1171
  }
1084
1172
  //# sourceMappingURL=author.js.map
1085
- //# debugId=cf550961-0040-5e04-9d8d-16e316027e43
1173
+ //# debugId=dfbf4eb8-1f02-5880-a70a-0e7ed9b9784a
@@ -0,0 +1,296 @@
1
+ import { type WorkspaceRecipe } from "../workspace-recipe.js";
2
+ /** Schema identifier for a portable observation contract. */
3
+ export declare const PM_OBSERVATION_SCHEMA: "pm.agent-observation/v1";
4
+ /** Schema identifier for a deterministic verdict contract. */
5
+ export declare const PM_VERDICT_SCHEMA: "pm.agent-verdict/v1";
6
+ /** Schema identifier for a bounded agent-environment episode. */
7
+ export declare const PM_EPISODE_SCHEMA: "pm.agent-episode/v1";
8
+ /** A JSON-compatible object used as immutable recorded workspace state. */
9
+ export type RecordedStateObject = Readonly<Record<string, unknown>>;
10
+ /** One declared read and its guaranteed token ceiling. */
11
+ export interface ObservationReadDeclaration {
12
+ /** Public SDK or CLI command name used to collect the read. */
13
+ command: string;
14
+ /** Maximum tokens this read may consume. */
15
+ budget_tokens: number;
16
+ }
17
+ /** Emitted-byte calibration for a representative observation corpus. */
18
+ export interface ObservationCalibration {
19
+ /** Stable measurement basis; serialized payload bytes are authoritative. */
20
+ basis: "emitted_bytes";
21
+ /** Historical emitted-byte measurements used to calibrate expectations. */
22
+ samples: readonly number[];
23
+ /** Expected serialized payload size before an observation is served. */
24
+ expected_emitted_bytes: number;
25
+ /** Accepted drift around the expected emitted-byte measurement. */
26
+ tolerance_bytes: number;
27
+ }
28
+ /** Declares whether observation cost varies with corpus size. */
29
+ export type ObservationCorpusDependence = {
30
+ readonly kind: "independent";
31
+ } | {
32
+ readonly kind: "bounded";
33
+ readonly dimension: string;
34
+ readonly maximum: number;
35
+ };
36
+ /** One ordered disclosure tier in an observation degradation ladder. */
37
+ export interface ObservationTier {
38
+ /** Stable tier identity included in every observation receipt. */
39
+ id: string;
40
+ /** Maximum tokens this tier is permitted to emit. */
41
+ max_tokens: number;
42
+ /** Dot-separated recorded-state fields disclosed by the tier. */
43
+ fields: readonly string[];
44
+ }
45
+ /** Portable declaration for a bounded, calibrated observation. */
46
+ export interface ObservationContract {
47
+ /** Versioned schema identity. */
48
+ schema: typeof PM_OBSERVATION_SCHEMA;
49
+ /** Stable contract identity. */
50
+ id: string;
51
+ /** Positive contract revision. */
52
+ version: number;
53
+ /** Reads whose ceilings form the guaranteed collection cost. */
54
+ reads: readonly ObservationReadDeclaration[];
55
+ /** Emitted-byte calibration visible before collection starts. */
56
+ calibration: ObservationCalibration;
57
+ /** Explicit corpus-size dependence of the cost model. */
58
+ corpus_dependence: ObservationCorpusDependence;
59
+ /** Ordered richest-to-smallest degradation ladder. */
60
+ tiers: readonly ObservationTier[];
61
+ }
62
+ /** Pre-call observation-cost description available to schedulers. */
63
+ export interface ObservationCostDescription {
64
+ /** Stable observation identity. */
65
+ contract_id: string;
66
+ /** Observation revision. */
67
+ contract_version: number;
68
+ /** Sum of all declared collection ceilings. */
69
+ guaranteed_ceiling_tokens: number;
70
+ /** Calibrated expected serialized payload size. */
71
+ expected_emitted_bytes: number;
72
+ /** Conservative token estimate derived from emitted bytes. */
73
+ expected_tokens: number;
74
+ /** Accepted emitted-byte calibration drift. */
75
+ tolerance_bytes: number;
76
+ /** Stable calibration basis. */
77
+ calibration_basis: "emitted_bytes";
78
+ /** Declared corpus-size dependence. */
79
+ corpus_dependence: ObservationCorpusDependence;
80
+ }
81
+ /** Audit receipt emitted for every served or refused observation. */
82
+ export interface ObservationReceipt {
83
+ /** Stable observation identity. */
84
+ contract_id: string;
85
+ /** Observation revision. */
86
+ contract_version: number;
87
+ /** Tier whose payload was returned, or null after truthful refusal. */
88
+ served_tier: string | null;
89
+ /** Whether a smaller tier was attempted or served. */
90
+ degraded: boolean;
91
+ /** Tier identities evaluated in deterministic order. */
92
+ attempted_tiers: readonly string[];
93
+ /** Exact serialized payload bytes, or null when nothing was served. */
94
+ emitted_bytes: number | null;
95
+ /** Conservative token estimate, or null when nothing was served. */
96
+ estimated_tokens: number | null;
97
+ /** Stable measurement basis. */
98
+ calibration_basis: "emitted_bytes";
99
+ }
100
+ /** Successful bounded observation with its explicit receipt. */
101
+ export interface ServedObservation<T> {
102
+ /** Discriminator for a payload-bearing response. */
103
+ status: "served";
104
+ /** Payload produced by the declared tier. */
105
+ payload: T;
106
+ /** Cost and degradation evidence. */
107
+ receipt: ObservationReceipt;
108
+ }
109
+ /** Refusal returned when no declared tier can fit the caller's ceiling. */
110
+ export interface RefusedObservation {
111
+ /** Discriminator for a payload-free refusal. */
112
+ status: "refused";
113
+ /** Stable reason callers can route without parsing prose. */
114
+ reason: "no_declared_tier_fits_budget";
115
+ /** Cost and degradation evidence. */
116
+ receipt: ObservationReceipt;
117
+ }
118
+ /** Complete outcome of attempting one declared observation. */
119
+ export type ObservationResult<T> = ServedObservation<T> | RefusedObservation;
120
+ /** Caller-imposed ceiling for one observation response. */
121
+ export interface ObservationRequest {
122
+ /** Maximum response tokens accepted by the caller. */
123
+ budget_tokens: number;
124
+ }
125
+ /** Predicate supported by the versioned total-verdict interpreter. */
126
+ export type VerdictPredicate = {
127
+ readonly id: string;
128
+ readonly kind: "field_equals";
129
+ readonly path: string;
130
+ readonly expected: unknown;
131
+ } | {
132
+ readonly id: string;
133
+ readonly kind: "field_present";
134
+ readonly path: string;
135
+ } | {
136
+ readonly id: string;
137
+ readonly kind: "field_absent";
138
+ readonly path: string;
139
+ };
140
+ /** Declarative composition applied to predicate outcomes. */
141
+ export interface VerdictComposition {
142
+ /** Whether every or at least one referenced predicate must satisfy. */
143
+ operator: "all" | "any";
144
+ /** Ordered predicate identities evaluated by the total verdict. */
145
+ predicate_ids: readonly string[];
146
+ }
147
+ /** Portable named and versioned total-verdict declaration. */
148
+ export interface VerdictContract {
149
+ /** Versioned schema identity. */
150
+ schema: typeof PM_VERDICT_SCHEMA;
151
+ /** Stable contract identity. */
152
+ id: string;
153
+ /** Positive contract revision. */
154
+ version: number;
155
+ /** Predicates evaluated exclusively over recorded state. */
156
+ predicates: readonly VerdictPredicate[];
157
+ /** Explicit deterministic predicate composition. */
158
+ composition: VerdictComposition;
159
+ }
160
+ /** Recorded state and stable snapshot identity supplied by an adapter. */
161
+ export interface WorkspaceRecordedState {
162
+ /** Stable identity of the exact state being evaluated. */
163
+ snapshot_id: string;
164
+ /** Recorded, JSON-compatible project state. */
165
+ state: RecordedStateObject;
166
+ }
167
+ /** Per-predicate evidence in a deterministic total verdict. */
168
+ export interface PredicateVerdict {
169
+ /** Declared predicate identity. */
170
+ id: string;
171
+ /** Whether the predicate is satisfied by recorded state. */
172
+ outcome: "satisfied" | "violated";
173
+ /** Snapshot-qualified JSON pointer to the inspected field. */
174
+ evidence_pointer: string;
175
+ /** Hash of the observed value without duplicating potentially private data. */
176
+ evidence_digest: string;
177
+ }
178
+ /** Total, reproducible result produced by a verdict contract. */
179
+ export interface VerdictResult {
180
+ /** Stable verdict identity. */
181
+ contract_id: string;
182
+ /** Verdict revision. */
183
+ contract_version: number;
184
+ /** Exact recorded-state snapshot evaluated. */
185
+ snapshot_id: string;
186
+ /** Total outcome, including an explicit empty-contract state. */
187
+ outcome: "satisfied" | "violated" | "not_applicable";
188
+ /** Satisfied fraction, or null when no predicates are declared. */
189
+ score: number | null;
190
+ /** Explicitly separates evaluation from reward or learning signals. */
191
+ policy: "verdict_only_no_reward";
192
+ /** Stable explanation for a not-applicable verdict. */
193
+ reason?: "no_predicates_declared";
194
+ /** Ordered predicate evidence. */
195
+ predicates: readonly PredicateVerdict[];
196
+ }
197
+ /** Hard limits enforced within one isolated episode. */
198
+ export interface EpisodeLimits {
199
+ /** Maximum ordinary project-management actions. */
200
+ max_actions: number;
201
+ /** Maximum observations, including the close-time grading read. */
202
+ max_observations: number;
203
+ /** Per-observation response ceiling. */
204
+ max_tokens_per_observation: number;
205
+ }
206
+ /** Portable specification shared by evaluation and training harnesses. */
207
+ export interface EpisodeSpecification {
208
+ /** Versioned schema identity. */
209
+ schema: typeof PM_EPISODE_SCHEMA;
210
+ /** Stable episode identity and session provenance key. */
211
+ id: string;
212
+ /** Positive episode revision. */
213
+ version: number;
214
+ /** Consumer intent without coupling the runtime to a training framework. */
215
+ mode: "benchmark" | "evaluation" | "training" | "scale_transfer";
216
+ /** Deterministic workspace construction recipe. */
217
+ recipe: WorkspaceRecipe;
218
+ /** Canonical pm items that define the task set. */
219
+ task_item_ids: readonly string[];
220
+ /** State fields that observations may disclose. */
221
+ observable_fields: readonly string[];
222
+ /** Grading-only fields that must never enter observations. */
223
+ withheld_fields: readonly string[];
224
+ /** Bounded observation declaration. */
225
+ observation: ObservationContract;
226
+ /** Recorded-state verdict declaration. */
227
+ verdict: VerdictContract;
228
+ /** Hard action and observation limits. */
229
+ limits: EpisodeLimits;
230
+ }
231
+ /** Reset receipt returned by an episode adapter. */
232
+ export interface EpisodeResetReceipt {
233
+ /** Adapter-defined isolated workspace identity. */
234
+ workspace_id: string;
235
+ /** Stable state identity after reset. */
236
+ state_id: string;
237
+ }
238
+ /** Action receipt returned by an episode adapter. */
239
+ export interface EpisodeActionReceipt<TOutput> {
240
+ /** Stable state identity after the action. */
241
+ state_id: string;
242
+ /** Adapter-defined ordinary command result. */
243
+ output: TOutput;
244
+ }
245
+ /** Host boundary for ordinary pm SDK actions and recorded-state reads. */
246
+ export interface EpisodeRuntimeAdapter<TAction, TOutput = unknown> {
247
+ /** Construct a fresh isolated workspace using the declared recipe. */
248
+ reset(recipe: WorkspaceRecipe): Promise<EpisodeResetReceipt>;
249
+ /** Execute one ordinary action, normally by calling `PmClient.run`. */
250
+ execute(action: TAction): Promise<EpisodeActionReceipt<TOutput>>;
251
+ /** Read immutable grading state from the workspace system of record. */
252
+ readRecordedState(): Promise<WorkspaceRecordedState>;
253
+ }
254
+ /** One deterministic entry in a portable episode trajectory. */
255
+ export interface EpisodeTrajectoryEntry {
256
+ /** Monotonic event number within the isolated episode. */
257
+ sequence: number;
258
+ /** Stable event classification. */
259
+ kind: "reset" | "observation" | "action" | "verdict" | "close";
260
+ /** Snapshot, state, or observation tier associated with the event. */
261
+ state_id: string;
262
+ }
263
+ /** Closed episode evidence without reward or framework-specific shaping. */
264
+ export interface ClosedEpisode {
265
+ /** Deterministic total verdict. */
266
+ verdict: VerdictResult;
267
+ /** Complete bounded trajectory. */
268
+ trajectory: readonly EpisodeTrajectoryEntry[];
269
+ /** Explicitly absent to prevent verdicts from becoming reward signals. */
270
+ reward?: never;
271
+ }
272
+ /** Isolated runtime returned for one declared agent episode. */
273
+ export interface PmEpisodeSession<TAction, TOutput> {
274
+ /** Observe recorded state through the declared disclosure ladder. */
275
+ observe(): Promise<ObservationResult<RecordedStateObject>>;
276
+ /** Execute one bounded ordinary project-management action. */
277
+ step(action: TAction): Promise<EpisodeActionReceipt<TOutput>>;
278
+ /** Evaluate the current recorded state without closing the session. */
279
+ score(): Promise<VerdictResult>;
280
+ /** Evaluate and close the episode, returning immutable evidence. */
281
+ close(): Promise<ClosedEpisode>;
282
+ }
283
+ /** Validate, clone, and freeze a portable observation declaration. */
284
+ export declare function defineObservationContract(declaration: ObservationContract): ObservationContract;
285
+ /** Describe guaranteed and calibrated observation cost before collection. */
286
+ export declare function describeObservationCost(contract: ObservationContract): ObservationCostDescription;
287
+ /** Serve the richest declared tier that fits both caller and tier ceilings. */
288
+ export declare function serveDeclaredObservation<T>(contract: ObservationContract, collect: (tier: ObservationTier) => Promise<T>, request: ObservationRequest): Promise<ObservationResult<T>>;
289
+ /** Validate, clone, and freeze a portable total-verdict declaration. */
290
+ export declare function defineVerdictContract(declaration: VerdictContract): VerdictContract;
291
+ /** Evaluate a total verdict exclusively from one immutable recorded snapshot. */
292
+ export declare function evaluateVerdictContract(contract: VerdictContract, recorded: WorkspaceRecordedState): VerdictResult;
293
+ /** Validate, clone, and freeze a portable episode specification. */
294
+ export declare function defineEpisodeSpecification(declaration: EpisodeSpecification): EpisodeSpecification;
295
+ /** Open one isolated, deterministic episode around an adapter's ordinary actions. */
296
+ export declare function openPmEpisode<TAction, TOutput = unknown>(specification: EpisodeSpecification, adapter: EpisodeRuntimeAdapter<TAction, TOutput>): Promise<PmEpisodeSession<TAction, TOutput>>;