@unbrained/pm-cli 2026.9.2 → 2026.9.3

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 (123) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +17 -0
  3. package/dist/cli/after-command-context-usage.js +16 -3
  4. package/dist/cli-bundle/bundle-manifest.json +154 -154
  5. package/dist/cli-bundle/chunks/{chunk-T6H5BZCP.js → chunk-34HASX3S.js} +2 -2
  6. package/dist/cli-bundle/chunks/chunk-AY324UJ5.js +9 -0
  7. package/dist/cli-bundle/chunks/{chunk-TAG4VC22.js → chunk-DKGP3QLE.js} +27 -27
  8. package/dist/cli-bundle/chunks/chunk-E5RBBCXO.js +230 -0
  9. package/dist/cli-bundle/chunks/{chunk-DTGWEL23.js → chunk-EDPIS7EB.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-X4RCGLTX.js → chunk-IEHHE6GA.js} +5 -5
  11. package/dist/cli-bundle/chunks/{chunk-UDW64J2W.js → chunk-L7B7343B.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-FZ4Z2J4F.js → chunk-LENC656S.js} +41 -41
  13. package/dist/cli-bundle/chunks/{chunk-ZLJIFSOE.js → chunk-LISESA7W.js} +33 -33
  14. package/dist/cli-bundle/chunks/{chunk-3WICXLVT.js → chunk-UPPM2FOZ.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-Y7VOMSZT.js → chunk-Y4PJ6HPK.js} +2 -2
  16. package/dist/cli-bundle/chunks/{register-list-query-XYNX4ASQ.js → register-list-query-W2ZTOMKP.js} +2 -2
  17. package/dist/cli-bundle/chunks/{register-mutation-WFQ7MJTX.js → register-mutation-RVND5NCG.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-operations-JVTI7JPP.js → register-operations-TTROIVC4.js} +2 -2
  19. package/dist/cli-bundle/chunks/{register-setup-KVNC5KPL.js → register-setup-D3ZFHY3L.js} +2 -2
  20. package/dist/cli-bundle/focused-chunks/chunk-3ZBI35HU.js +176 -0
  21. package/dist/cli-bundle/focused-chunks/{chunk-SVXJYD6G.js → chunk-4HJFY4MB.js} +2 -2
  22. package/dist/cli-bundle/focused-chunks/chunk-4RRHC3S4.js +6 -0
  23. package/dist/cli-bundle/focused-chunks/chunk-4WR46RMG.js +9 -0
  24. package/dist/cli-bundle/focused-chunks/chunk-5RFXUPN5.js +3 -0
  25. package/dist/cli-bundle/focused-chunks/chunk-BWKHEIVF.js +2 -0
  26. package/dist/cli-bundle/focused-chunks/{chunk-4O4CJAR6.js → chunk-D7KXFBXV.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/{chunk-MKHG3T76.js → chunk-GHCZ3YFR.js} +3 -3
  28. package/dist/cli-bundle/focused-chunks/{chunk-KB5OFSFD.js → chunk-GT7MXDLW.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/chunk-KBLZRU62.js +2 -0
  30. package/dist/cli-bundle/focused-chunks/chunk-KZ2NB3ET.js +2 -0
  31. package/dist/cli-bundle/focused-chunks/chunk-M5M6SVHS.js +3 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-BEVHCEWG.js → chunk-OL5EH6I3.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-MEASX544.js → chunk-Q45NHPF2.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-O67VDLOT.js → chunk-QKHCSUGJ.js} +42 -42
  35. package/dist/cli-bundle/focused-chunks/chunk-S27XMBIN.js +8 -0
  36. package/dist/cli-bundle/focused-chunks/chunk-TXE4TSHM.js +12 -0
  37. package/dist/cli-bundle/focused-chunks/chunk-UCLO3XDU.js +2 -0
  38. package/dist/cli-bundle/main.js +15 -15
  39. package/dist/cli-bundle/sdk-authoring.js +1 -1
  40. package/dist/cli-bundle/sdk-contracts.js +1 -1
  41. package/dist/cli-bundle/sdk-core.js +28 -28
  42. package/dist/cli-bundle/sdk-governance.js +1 -1
  43. package/dist/cli-bundle/sdk-graph.js +1 -1
  44. package/dist/cli-bundle/sdk-merge.js +35 -33
  45. package/dist/cli-bundle/sdk-query.js +1 -1
  46. package/dist/cli-bundle/sdk-runtime.js +1 -1
  47. package/dist/cli-bundle/sdk-testing.js +1 -1
  48. package/dist/cli-bundle/sdk.js +9 -9
  49. package/dist/core/history/event-classification.d.ts +21 -0
  50. package/dist/core/history/event-classification.js +109 -0
  51. package/dist/core/history/event-index.d.ts +14 -3
  52. package/dist/core/history/event-index.js +543 -88
  53. package/dist/core/history/history.js +47 -18
  54. package/dist/core/history/workspace-history.js +7 -6
  55. package/dist/core/lock/lock.d.ts +22 -2
  56. package/dist/core/lock/lock.js +121 -19
  57. package/dist/core/output/output.js +31 -7
  58. package/dist/core/shared/time.d.ts +2 -0
  59. package/dist/core/shared/time.js +8 -2
  60. package/dist/core/store/item-metadata-query-index.js +5 -5
  61. package/dist/sdk/context/recency.d.ts +9 -0
  62. package/dist/sdk/context/recency.js +34 -0
  63. package/dist/sdk/context/usage-egress.d.ts +9 -0
  64. package/dist/sdk/context/usage-egress.js +30 -0
  65. package/dist/sdk/context-intent-contracts.js +7 -3
  66. package/dist/sdk/context-relevance.d.ts +23 -0
  67. package/dist/sdk/context-relevance.js +94 -23
  68. package/dist/sdk/context-signal-store.d.ts +7 -3
  69. package/dist/sdk/context-signal-store.js +155 -42
  70. package/dist/sdk/context-usage.d.ts +54 -0
  71. package/dist/sdk/context-usage.js +245 -16
  72. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +14 -14
  73. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +14 -2
  74. package/dist/sdk/index.d.ts +2 -0
  75. package/dist/sdk/index.js +4 -2
  76. package/dist/sdk/init.d.ts +2 -0
  77. package/dist/sdk/init.js +18 -9
  78. package/dist/sdk/query/context.d.ts +3 -1
  79. package/dist/sdk/query/context.js +21 -9
  80. package/dist/sdk/query/next.js +18 -9
  81. package/dist/sdk/runtime-input.d.ts +2 -0
  82. package/dist/sdk/runtime-input.js +25 -2
  83. package/dist/sdk/runtime.d.ts +1 -0
  84. package/dist/sdk/runtime.js +17 -26
  85. package/dist/types.d.ts +2 -0
  86. package/dist/types.js +2 -2
  87. package/docs/CONTEXT_RELEVANCE.md +44 -1
  88. package/docs/PERFORMANCE.md +6 -3
  89. package/docs/READ_OUTPUT_CONTRACTS.md +9 -1
  90. package/docs/SDK.md +11 -8
  91. package/docs/SDK_CONTEXT.md +7 -0
  92. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +4 -3
  93. package/marketplace.json +2 -2
  94. package/package.json +4 -4
  95. package/packages/pm-beads/package.json +1 -1
  96. package/packages/pm-calendar/package.json +1 -1
  97. package/packages/pm-command-kit/package.json +1 -1
  98. package/packages/pm-digital-twin/package.json +1 -1
  99. package/packages/pm-governance-audit/package.json +1 -1
  100. package/packages/pm-guide-shell/package.json +1 -1
  101. package/packages/pm-kanban/package.json +1 -1
  102. package/packages/pm-lifecycle-hooks/package.json +1 -1
  103. package/packages/pm-linked-test-adapters/package.json +1 -1
  104. package/packages/pm-search-advanced/package.json +1 -1
  105. package/packages/pm-templates/package.json +1 -1
  106. package/packages/pm-todos/package.json +1 -1
  107. package/packages/pm-vcs/package.json +1 -1
  108. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  109. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  110. package/sdk/public-surface.json +241 -24
  111. package/dist/cli-bundle/chunks/chunk-GOACULJW.js +0 -13
  112. package/dist/cli-bundle/chunks/chunk-NOPL37X4.js +0 -205
  113. package/dist/cli-bundle/focused-chunks/chunk-242AXYB2.js +0 -2
  114. package/dist/cli-bundle/focused-chunks/chunk-2FEZ5SKM.js +0 -3
  115. package/dist/cli-bundle/focused-chunks/chunk-6GCRSLPG.js +0 -2
  116. package/dist/cli-bundle/focused-chunks/chunk-7VATS5QY.js +0 -16
  117. package/dist/cli-bundle/focused-chunks/chunk-JEFKLWMM.js +0 -2
  118. package/dist/cli-bundle/focused-chunks/chunk-PF3E6Q36.js +0 -8
  119. package/dist/cli-bundle/focused-chunks/chunk-QDFJIRKN.js +0 -4
  120. package/dist/cli-bundle/focused-chunks/chunk-RMRCQPWU.js +0 -2
  121. package/dist/cli-bundle/focused-chunks/chunk-S4U5CN5Q.js +0 -2
  122. package/dist/cli-bundle/focused-chunks/chunk-T2LXXSOD.js +0 -158
  123. package/dist/cli-bundle/focused-chunks/chunk-Z2USIBR2.js +0 -5
@@ -4,18 +4,20 @@
4
4
  * Implements append-only history and replay behavior for History.
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]="60d6ec0e-a8ed-5a5d-b5bd-d29da8532a79")}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]="1f78448d-a042-588a-84ce-369bd9ce8726")}catch(e){}}();
8
8
  import jsonPatch from "fast-json-patch";
9
- import { ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
9
+ import { EXIT_CODE, ITEM_METADATA_KEY_ORDER } from "../shared/constants.js";
10
10
  import { runActiveServiceOverride } from "../extensions/index.js";
11
11
  import { appendLineAtomic } from "../fs/fs-utils.js";
12
12
  import { canonicalDocument } from "../item/item-format.js";
13
13
  import { toItemRecord } from "../item/item-record.js";
14
14
  import { orderObject, sha256Hex, stableStringify, } from "../shared/serialization.js";
15
- import { nowIso } from "../shared/time.js";
15
+ import { isMillisecondPrecisionRfc3339DateTime, nowIso, } from "../shared/time.js";
16
16
  import { diagnoseAgentIdentity, resolveHistoryAgentIdentity, resolveHistoryAuthorSource, } from "../shared/author.js";
17
- import { removeHistoryEventIndexForHistoryPath, updateHistoryEventIndexAfterAppend, } from "./event-index.js";
17
+ import { appendHistoryEntryWithEventIndex, removeHistoryEventIndexForHistoryPath, } from "./event-index.js";
18
+ import { classifyHistoryEvent } from "./event-classification.js";
18
19
  import { invalidateHistoryDriftCacheForPath } from "./drift-cache.js";
20
+ import { PmCliError } from "../shared/errors.js";
19
21
  const EMPTY_LEGACY_HASH_DOCUMENT = {
20
22
  front_matter: {},
21
23
  body: "",
@@ -42,7 +44,8 @@ function compareLegacyLinkedTests(left, right) {
42
44
  compareOptionalStrings(left.command, right.command),
43
45
  compareOptionalNumbers(left.timeout_seconds, right.timeout_seconds),
44
46
  compareOptionalStrings(left.pm_context_mode, right.pm_context_mode),
45
- Number(Boolean(left.shared_host_safe)) - Number(Boolean(right.shared_host_safe)),
47
+ Number(Boolean(left.shared_host_safe)) -
48
+ Number(Boolean(right.shared_host_safe)),
46
49
  compareJsonValues(left.env_clear, right.env_clear, []),
47
50
  compareJsonValues(left.env_set, right.env_set, {}),
48
51
  compareJsonValues(left.assert_stdout_contains, right.assert_stdout_contains, []),
@@ -222,13 +225,14 @@ export function createHistoryEntry(params) {
222
225
  const provenanceOutcomes = agentIdentity.harness
223
226
  ? Object.fromEntries(Object.entries(diagnoseAgentIdentity().provenance_outcomes).filter(([, outcome]) => outcome.resolver !== undefined && outcome.status !== "resolved"))
224
227
  : undefined;
225
- const context = provenanceOutcomes === undefined || Object.keys(provenanceOutcomes).length === 0
228
+ const context = provenanceOutcomes === undefined ||
229
+ Object.keys(provenanceOutcomes).length === 0
226
230
  ? params.context
227
231
  : {
228
232
  ...params.context,
229
233
  agent_provenance_outcomes: provenanceOutcomes,
230
234
  };
231
- return {
235
+ const entry = {
232
236
  ts: params.nowIso,
233
237
  author: params.author,
234
238
  author_source: params.authorSource ?? resolveHistoryAuthorSource(params.author),
@@ -243,9 +247,7 @@ export function createHistoryEntry(params) {
243
247
  ...(agentIdentity.provenance
244
248
  ? { agent_provenance: agentIdentity.provenance }
245
249
  : {}),
246
- ...(agentIdentity.episode
247
- ? { agent_episode: agentIdentity.episode }
248
- : {}),
250
+ ...(agentIdentity.episode ? { agent_episode: agentIdentity.episode } : {}),
249
251
  op: params.op,
250
252
  patch,
251
253
  before_hash: sha256Hex(stableStringify(beforeHashCanonical)),
@@ -254,17 +256,34 @@ export function createHistoryEntry(params) {
254
256
  message: params.message === undefined ? undefined : params.message,
255
257
  ...(context === undefined ? {} : { context }),
256
258
  };
259
+ return { ...entry, event_class: classifyHistoryEvent(entry) };
257
260
  }
258
261
  function isRecord(value) {
259
262
  return typeof value === "object" && value !== null && !Array.isArray(value);
260
263
  }
264
+ function invalidHistoryTimestamp(message) {
265
+ return new PmCliError(message, EXIT_CODE.GENERIC_FAILURE, {
266
+ code: "history_timestamp_invalid",
267
+ });
268
+ }
261
269
  function fallbackHistoryTimestamp(entry) {
262
270
  const ts = entry.ts.trim();
263
- return ts.length > 0 ? ts : nowIso();
271
+ if (ts.length === 0)
272
+ return nowIso();
273
+ if (!isMillisecondPrecisionRfc3339DateTime(ts)) {
274
+ throw invalidHistoryTimestamp("History timestamp must be a valid RFC 3339 date-time with millisecond precision");
275
+ }
276
+ if (ts !== entry.ts) {
277
+ throw invalidHistoryTimestamp("History timestamp must not contain surrounding whitespace");
278
+ }
279
+ return entry.ts;
264
280
  }
265
281
  function withHistoryTimestamp(value, fallbackTs) {
266
282
  const ts = value.ts;
267
283
  if (typeof ts === "string" && ts.trim().length > 0) {
284
+ if (!isMillisecondPrecisionRfc3339DateTime(ts)) {
285
+ throw invalidHistoryTimestamp("History timestamp must be a valid RFC 3339 date-time with millisecond precision");
286
+ }
268
287
  return value;
269
288
  }
270
289
  return { ...value, ts: fallbackTs };
@@ -272,14 +291,16 @@ function withHistoryTimestamp(value, fallbackTs) {
272
291
  function serializeHistoryLine(value, fallbackEntry) {
273
292
  const fallbackTs = fallbackHistoryTimestamp(fallbackEntry);
274
293
  if (typeof value === "string") {
294
+ let parsed;
275
295
  try {
276
- const parsed = JSON.parse(value);
277
- if (isRecord(parsed)) {
278
- return JSON.stringify(withHistoryTimestamp(parsed, fallbackTs));
279
- }
296
+ parsed = JSON.parse(value);
280
297
  }
281
298
  catch {
282
299
  // Non-JSON extension lines are preserved for compatibility.
300
+ return value;
301
+ }
302
+ if (isRecord(parsed)) {
303
+ return JSON.stringify(withHistoryTimestamp(parsed, fallbackTs));
283
304
  }
284
305
  return value;
285
306
  }
@@ -324,9 +345,17 @@ export async function appendHistoryEntry(historyPath, entry) {
324
345
  return;
325
346
  }
326
347
  }
327
- await appendLineAtomic(historyPath, serializeHistoryLine(entry, entry));
348
+ const timestampedEntry = entry.ts.trim().length > 0
349
+ ? entry
350
+ : { ...entry, ts: fallbackHistoryTimestamp(entry) };
351
+ const normalizedEntry = {
352
+ ...timestampedEntry,
353
+ event_class: classifyHistoryEvent(timestampedEntry),
354
+ };
355
+ await appendHistoryEntryWithEventIndex(historyPath, normalizedEntry, async () => {
356
+ await appendLineAtomic(historyPath, serializeHistoryLine(normalizedEntry, normalizedEntry));
357
+ });
328
358
  await invalidateHistoryDriftCacheForPath(historyPath);
329
- await updateHistoryEventIndexAfterAppend(historyPath, entry);
330
359
  }
331
360
  /** Public contract for test only, shared by SDK and presentation-layer consumers. */
332
361
  export const _testOnly = {
@@ -334,4 +363,4 @@ export const _testOnly = {
334
363
  isDefinedPointerPath,
335
364
  };
336
365
  //# sourceMappingURL=history.js.map
337
- //# debugId=60d6ec0e-a8ed-5a5d-b5bd-d29da8532a79
366
+ //# debugId=1f78448d-a042-588a-84ce-369bd9ce8726
@@ -5,7 +5,7 @@
5
5
  * HistoryEntry format used by item mutations.
6
6
  */
7
7
 
8
- !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]="9027d972-ce29-5511-ba81-27e17d97446e")}catch(e){}}();
8
+ !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]="4df21a17-43c0-5b63-adf3-657699e6a058")}catch(e){}}();
9
9
  import fs from "node:fs/promises";
10
10
  import path from "node:path";
11
11
  import { readFileIfExists, writeFileAtomic } from "../fs/fs-utils.js";
@@ -13,6 +13,7 @@ import { acquireLock } from "../lock/lock.js";
13
13
  import { EMPTY_CANONICAL_DOCUMENT, EXIT_CODE } from "../shared/constants.js";
14
14
  import { PmCliError } from "../shared/errors.js";
15
15
  import { stableStringify } from "../shared/serialization.js";
16
+ import { nowIso } from "../shared/time.js";
16
17
  import { appendHistoryEntry, createHistoryEntry } from "./history.js";
17
18
  import { readHistoryEntries } from "./read.js";
18
19
  import { cloneEmptyReplayDocument, replayToItemDocument, tryApplyReplayPatch, verifyHistoryChain, } from "./replay.js";
@@ -153,7 +154,7 @@ async function appendWorkspaceHistoryChangeLocked(change) {
153
154
  if (idempotentEntry) {
154
155
  return { entry: idempotentEntry, historyPath };
155
156
  }
156
- const timestamp = new Date().toISOString();
157
+ const timestamp = nowIso();
157
158
  const beforeDocument = entries.length === 0
158
159
  ? EMPTY_CANONICAL_DOCUMENT
159
160
  : replayWorkspaceEntries(entries);
@@ -222,7 +223,7 @@ export async function appendWorkspaceAuditEvent(options) {
222
223
  ? EMPTY_CANONICAL_DOCUMENT
223
224
  : replayWorkspaceEntries(entries);
224
225
  const entry = createHistoryEntry({
225
- nowIso: new Date().toISOString(),
226
+ nowIso: nowIso(),
226
227
  author: options.author,
227
228
  op: options.op,
228
229
  before: beforeDocument,
@@ -340,7 +341,7 @@ export async function reconcileWorkspaceJsonHistory(options) {
340
341
  if (stableStringify(priorDocuments[documentPath]) === stableStringify(current)) {
341
342
  return { changed: false, historyPath };
342
343
  }
343
- const timestamp = new Date().toISOString();
344
+ const timestamp = nowIso();
344
345
  const entry = createHistoryEntry({
345
346
  nowIso: timestamp,
346
347
  author: options.author,
@@ -393,7 +394,7 @@ export async function restoreWorkspaceJsonFromHistory(options) {
393
394
  changed: false,
394
395
  };
395
396
  const beforeDocument = replayWorkspaceEntries(entries);
396
- const timestamp = new Date().toISOString();
397
+ const timestamp = nowIso();
397
398
  const entry = createHistoryEntry({
398
399
  nowIso: timestamp,
399
400
  author: options.author,
@@ -430,4 +431,4 @@ export async function restoreWorkspaceJsonFromHistory(options) {
430
431
  }
431
432
  }
432
433
  //# sourceMappingURL=workspace-history.js.map
433
- //# debugId=9027d972-ce29-5511-ba81-27e17d97446e
434
+ //# debugId=4df21a17-43c0-5b63-adf3-657699e6a058
@@ -2,6 +2,7 @@ interface LockInfo {
2
2
  id: string;
3
3
  pid: number;
4
4
  owner: string;
5
+ token?: string;
5
6
  created_at: string;
6
7
  ttl_seconds: number;
7
8
  }
@@ -14,14 +15,31 @@ interface StaleLockRemovalResult {
14
15
  shouldRetryCreate: boolean;
15
16
  staleRemovalCounted: boolean;
16
17
  }
18
+ /** Stable operating-system identity for a process when the host exposes one. */
19
+ export interface ProcessIdentity {
20
+ /** Operating-system process identifier captured with the owner record. */
21
+ pid: number;
22
+ /** Host process-start coordinate that distinguishes reuse of the same PID. */
23
+ process_start_identity?: string;
24
+ }
17
25
  declare function parseLockInfo(raw: string): LockReadResult;
18
- declare function readLockInfo(lockPath: string): Promise<LockReadResult>;
26
+ declare function readLockInfo(lockPath: string, emitReadHook?: boolean): Promise<LockReadResult>;
19
27
  declare function isErrno(error: unknown, code: string): boolean;
20
- declare function buildLockPayload(id: string, owner: string, ttlSeconds: number): LockInfo;
28
+ declare function buildLockPayload(id: string, owner: string, ttlSeconds: number, token?: string): LockInfo;
21
29
  declare function isStaleLock(info: LockInfo | null, ttlSeconds: number): boolean;
22
30
  declare function lockOwnerSuffix(info: LockInfo | null): string;
23
31
  /** Resolves the effective bounded wait budget for a contended lock: the PM_LOCK_WAIT_MS environment override wins when it parses as a non-negative integer, then the caller-provided budget (settings `locks.wait_ms`), then 0 (fail-fast, the pre-wait behavior). */
24
32
  declare function resolveLockWaitMs(waitMs: number | undefined): number;
33
+ declare function parseLinuxProcessStartIdentity(raw: string): string | null;
34
+ /** Read the host process-start coordinate used to distinguish PID reuse. */
35
+ export declare function readProcessStartIdentity(pid: number): Promise<string | null>;
36
+ /** Capture the current PID plus a host process-start coordinate when available. */
37
+ export declare function captureProcessIdentity(pid?: number): Promise<ProcessIdentity>;
38
+ /**
39
+ * Verify that a captured process owner still exists, with a bounded grace
40
+ * period when the host cannot expose a reusable-PID-safe start coordinate.
41
+ */
42
+ export declare function isProcessIdentityAlive(identity: ProcessIdentity, unverifiedAgeMs: number, maxUnverifiedAgeMs: number): Promise<boolean>;
25
43
  declare function acquireStaleCleanupGate(lockPath: string, _id: string): Promise<(() => Promise<void>) | null>;
26
44
  declare function removeConfirmedStaleLock(params: {
27
45
  lockPath: string;
@@ -43,6 +61,8 @@ export declare const _testOnly: {
43
61
  isStaleLock: typeof isStaleLock;
44
62
  lockOwnerSuffix: typeof lockOwnerSuffix;
45
63
  resolveLockWaitMs: typeof resolveLockWaitMs;
64
+ parseLinuxProcessStartIdentity: typeof parseLinuxProcessStartIdentity;
65
+ readProcessStartIdentity: typeof readProcessStartIdentity;
46
66
  acquireStaleCleanupGate: typeof acquireStaleCleanupGate;
47
67
  removeConfirmedStaleLock: typeof removeConfirmedStaleLock;
48
68
  };
@@ -4,7 +4,7 @@
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]="a9ad8a9f-de6e-5bce-8685-844f1129d5fb")}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]="7352375d-55f2-5751-934e-ba0cd5c358d5")}catch(e){}}();
8
8
  import { isFileMissingError } from "../fs/fs-utils.js";
9
9
  import fs from "node:fs/promises";
10
10
  import path from "node:path";
@@ -36,12 +36,15 @@ function parseLockInfo(raw) {
36
36
  const id = candidate.id;
37
37
  const pid = candidate.pid;
38
38
  const owner = candidate.owner;
39
+ const token = candidate.token;
39
40
  const createdAt = candidate.created_at;
40
41
  const ttlSeconds = candidate.ttl_seconds;
41
42
  if (typeof id !== "string" ||
42
43
  typeof pid !== "number" ||
43
44
  !Number.isFinite(pid) ||
44
45
  typeof owner !== "string" ||
46
+ (token !== undefined &&
47
+ (typeof token !== "string" || token.trim().length === 0)) ||
45
48
  typeof createdAt !== "string" ||
46
49
  typeof ttlSeconds !== "number" ||
47
50
  !Number.isFinite(ttlSeconds)) {
@@ -55,19 +58,22 @@ function parseLockInfo(raw) {
55
58
  id,
56
59
  pid,
57
60
  owner,
61
+ ...(typeof token === "string" ? { token } : {}),
58
62
  created_at: createdAt,
59
63
  ttl_seconds: ttlSeconds,
60
64
  },
61
65
  warnings: [],
62
66
  };
63
67
  }
64
- async function readLockInfo(lockPath) {
68
+ async function readLockInfo(lockPath, emitReadHook = true) {
65
69
  try {
66
70
  const raw = await fs.readFile(lockPath, "utf8");
67
- await runActiveOnReadHooks({
68
- path: lockPath,
69
- scope: "project",
70
- });
71
+ if (emitReadHook) {
72
+ await runActiveOnReadHooks({
73
+ path: lockPath,
74
+ scope: "project",
75
+ });
76
+ }
71
77
  return parseLockInfo(raw);
72
78
  }
73
79
  catch (error) {
@@ -96,20 +102,21 @@ async function emitLockWriteHook(lockPath, op) {
96
102
  op,
97
103
  });
98
104
  }
99
- function buildLockPayload(id, owner, ttlSeconds) {
105
+ function buildLockPayload(id, owner, ttlSeconds, token = randomUUID()) {
100
106
  return {
101
107
  id,
102
108
  pid: process.pid,
103
109
  owner,
110
+ token,
104
111
  created_at: nowIso(),
105
112
  ttl_seconds: ttlSeconds,
106
113
  };
107
114
  }
108
- async function createLockFile(lockPath, id, owner, ttlSeconds) {
115
+ async function createLockFile(lockPath, id, owner, ttlSeconds, token) {
109
116
  await fs.mkdir(path.dirname(lockPath), { recursive: true });
110
117
  const handle = await fs.open(lockPath, "wx");
111
118
  try {
112
- await handle.writeFile(`${JSON.stringify(buildLockPayload(id, owner, ttlSeconds), null, 2)}\n`, "utf8");
119
+ await handle.writeFile(`${JSON.stringify(buildLockPayload(id, owner, ttlSeconds, token), null, 2)}\n`, "utf8");
113
120
  }
114
121
  finally {
115
122
  await handle.close();
@@ -127,6 +134,41 @@ async function unlinkLockWithHook(lockPath, op) {
127
134
  return false;
128
135
  }
129
136
  }
137
+ async function releaseOwnedLock(lockPath, id, owner, token) {
138
+ const startedAtMs = Date.now();
139
+ let backoffMs = LOCK_WAIT_INITIAL_DELAY_MS;
140
+ for (;;) {
141
+ const releaseCleanupGate = await acquireStaleCleanupGate(lockPath, id);
142
+ if (releaseCleanupGate !== null) {
143
+ try {
144
+ const current = await readLockInfo(lockPath, false);
145
+ if (isOwnedLock(current.info, id, owner, token)) {
146
+ await unlinkLockWithHook(lockPath, "lock:release");
147
+ }
148
+ }
149
+ finally {
150
+ await releaseCleanupGate();
151
+ }
152
+ return;
153
+ }
154
+ const current = await readLockInfo(lockPath, false);
155
+ if (!isOwnedLock(current.info, id, owner, token)) {
156
+ return;
157
+ }
158
+ const elapsedMs = Date.now() - startedAtMs;
159
+ if (elapsedMs >= LOCK_RELEASE_GATE_WAIT_MS) {
160
+ return;
161
+ }
162
+ await sleepWithJitter(Math.min(backoffMs, LOCK_RELEASE_GATE_WAIT_MS - elapsedMs));
163
+ backoffMs = Math.min(backoffMs * 2, LOCK_WAIT_MAX_DELAY_MS);
164
+ }
165
+ }
166
+ function isOwnedLock(info, id, owner, token) {
167
+ return (info?.id === id &&
168
+ info.pid === process.pid &&
169
+ info.owner === owner &&
170
+ info.token === token);
171
+ }
130
172
  function isStaleLock(info, ttlSeconds) {
131
173
  const createdAtMs = info?.created_at
132
174
  ? Date.parse(info.created_at)
@@ -146,8 +188,8 @@ const MAX_STALE_LOCK_REMOVALS = 3;
146
188
  const STALE_CLEANUP_GATE_SUFFIX = ".stale-cleanup";
147
189
  const STALE_CLEANUP_GATE_OWNER_FILE = "owner.json";
148
190
  const STALE_CLEANUP_GATE_STALE_MS = 10_000;
149
- // Bounds PID-reuse false positives: a live recycled PID can delay cleanup, but not indefinitely.
150
- const STALE_CLEANUP_GATE_MAX_ACTIVE_MS = 5 * 60_000;
191
+ const LOCK_RELEASE_GATE_WAIT_MS = STALE_CLEANUP_GATE_STALE_MS + LOCK_WAIT_MAX_DELAY_MS;
192
+ const STALE_CLEANUP_GATE_MAX_UNVERIFIED_MS = 60 * 60_000;
151
193
  function parseNonNegativeIntegerWaitMs(value) {
152
194
  if (typeof value === "string") {
153
195
  const trimmed = value.trim();
@@ -220,14 +262,24 @@ function parseStaleCleanupGateOwner(raw) {
220
262
  const candidate = parsed;
221
263
  const pid = candidate.pid;
222
264
  const token = candidate.token;
265
+ const processStartIdentity = candidate.process_start_identity;
223
266
  if (typeof pid !== "number" ||
224
267
  !Number.isInteger(pid) ||
225
268
  pid <= 0 ||
226
269
  typeof token !== "string" ||
227
- token.length === 0) {
270
+ token.length === 0 ||
271
+ (processStartIdentity !== undefined &&
272
+ (typeof processStartIdentity !== "string" ||
273
+ !/^\d+$/u.test(processStartIdentity)))) {
228
274
  return null;
229
275
  }
230
- return { pid, token };
276
+ return {
277
+ pid,
278
+ token,
279
+ ...(typeof processStartIdentity === "string"
280
+ ? { process_start_identity: processStartIdentity }
281
+ : {}),
282
+ };
231
283
  }
232
284
  async function readStaleCleanupGateOwner(gatePath) {
233
285
  try {
@@ -238,6 +290,8 @@ async function readStaleCleanupGateOwner(gatePath) {
238
290
  }
239
291
  }
240
292
  function isProcessAlive(pid) {
293
+ if (!Number.isSafeInteger(pid) || pid <= 0)
294
+ return false;
241
295
  try {
242
296
  process.kill(pid, 0);
243
297
  return true;
@@ -249,6 +303,49 @@ function isProcessAlive(pid) {
249
303
  return true;
250
304
  }
251
305
  }
306
+ function parseLinuxProcessStartIdentity(raw) {
307
+ const closeParenIndex = raw.lastIndexOf(")");
308
+ if (closeParenIndex < 0)
309
+ return null;
310
+ const startTime = raw
311
+ .slice(closeParenIndex + 2)
312
+ .trim()
313
+ .split(/\s+/u)[19];
314
+ return startTime !== undefined && /^\d+$/u.test(startTime) ? startTime : null;
315
+ }
316
+ /** Read the host process-start coordinate used to distinguish PID reuse. */
317
+ export async function readProcessStartIdentity(pid) {
318
+ try {
319
+ return parseLinuxProcessStartIdentity(await fs.readFile(`/proc/${pid}/stat`, "utf8"));
320
+ }
321
+ catch {
322
+ return null;
323
+ }
324
+ }
325
+ /** Capture the current PID plus a host process-start coordinate when available. */
326
+ export async function captureProcessIdentity(pid = process.pid) {
327
+ const processStartIdentity = await readProcessStartIdentity(pid);
328
+ return {
329
+ pid,
330
+ ...(processStartIdentity === null
331
+ ? {}
332
+ : { process_start_identity: processStartIdentity }),
333
+ };
334
+ }
335
+ /**
336
+ * Verify that a captured process owner still exists, with a bounded grace
337
+ * period when the host cannot expose a reusable-PID-safe start coordinate.
338
+ */
339
+ export async function isProcessIdentityAlive(identity, unverifiedAgeMs, maxUnverifiedAgeMs) {
340
+ if (!isProcessAlive(identity.pid))
341
+ return false;
342
+ const currentStartIdentity = await readProcessStartIdentity(identity.pid);
343
+ if (identity.process_start_identity !== undefined &&
344
+ currentStartIdentity !== null) {
345
+ return currentStartIdentity === identity.process_start_identity;
346
+ }
347
+ return unverifiedAgeMs <= maxUnverifiedAgeMs;
348
+ }
252
349
  async function removeStaleCleanupGateDirectory(gatePath) {
253
350
  try {
254
351
  await fs.rm(gatePath, { recursive: true, force: true });
@@ -275,7 +372,10 @@ async function tryCreateStaleCleanupGate(gatePath) {
275
372
  }
276
373
  return null;
277
374
  }
278
- const owner = { pid: process.pid, token: randomUUID() };
375
+ const owner = {
376
+ ...(await captureProcessIdentity()),
377
+ token: randomUUID(),
378
+ };
279
379
  try {
280
380
  await fs.writeFile(path.join(gatePath, STALE_CLEANUP_GATE_OWNER_FILE), `${JSON.stringify(owner)}\n`, "utf8");
281
381
  }
@@ -299,8 +399,7 @@ async function removeExpiredStaleCleanupGate(gatePath) {
299
399
  }
300
400
  const owner = await readStaleCleanupGateOwner(gatePath);
301
401
  if (owner !== null &&
302
- isProcessAlive(owner.pid) &&
303
- gateAgeMs <= STALE_CLEANUP_GATE_MAX_ACTIVE_MS) {
402
+ (await isProcessIdentityAlive(owner, gateAgeMs, STALE_CLEANUP_GATE_MAX_UNVERIFIED_MS))) {
304
403
  return false;
305
404
  }
306
405
  return removeStaleCleanupGateDirectory(gatePath);
@@ -369,6 +468,8 @@ export const _testOnly = {
369
468
  isStaleLock,
370
469
  lockOwnerSuffix,
371
470
  resolveLockWaitMs,
471
+ parseLinuxProcessStartIdentity,
472
+ readProcessStartIdentity,
372
473
  acquireStaleCleanupGate,
373
474
  removeConfirmedStaleLock,
374
475
  };
@@ -400,11 +501,12 @@ export async function acquireLock(pmRoot, id, ttlSeconds, owner, force = false,
400
501
  const startedAtMs = Date.now();
401
502
  let staleRemovals = 0;
402
503
  let backoffMs = LOCK_WAIT_INITIAL_DELAY_MS;
504
+ const token = randomUUID();
403
505
  for (;;) {
404
506
  try {
405
- await createLockFile(lockPath, id, owner, ttlSeconds);
507
+ await createLockFile(lockPath, id, owner, ttlSeconds, token);
406
508
  return async () => {
407
- await unlinkLockWithHook(lockPath, "lock:release");
509
+ await releaseOwnedLock(lockPath, id, owner, token);
408
510
  await runActiveServiceOverride("lock_release", {
409
511
  pm_root: pmRoot,
410
512
  id,
@@ -447,4 +549,4 @@ export async function acquireLock(pmRoot, id, ttlSeconds, owner, force = false,
447
549
  }
448
550
  }
449
551
  //# sourceMappingURL=lock.js.map
450
- //# debugId=a9ad8a9f-de6e-5bce-8685-844f1129d5fb
552
+ //# debugId=7352375d-55f2-5751-934e-ba0cd5c358d5
@@ -4,13 +4,14 @@
4
4
  * Formats compact human and machine output for Output.
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]="202cbb3e-71fe-5701-a1f5-eb515bf56561")}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]="fa89762b-915f-5ef0-a091-f05338c11683")}catch(e){}}();
8
8
  import { getActiveCommandContext, runActiveCommandOverride, runActiveRendererOverride, runActiveServiceOverrideSync, setActiveCommandResult, } from "../extensions/index.js";
9
9
  import { EXIT_CODE } from "../shared/constants.js";
10
10
  import { isHostOutputSuppressed } from "./output-control.js";
11
11
  import { projectMutationResult } from "./mutation-projection.js";
12
12
  import { attachReadOutputContracts } from "../../sdk/context-intent-contracts.js";
13
13
  import { attachOutputTokenAccounting } from "../../sdk/output-token-accounting.js";
14
+ import { propagateContextUsageServingReceipt } from "../../sdk/context-usage.js";
14
15
  import { isReadOutputBudgetExceeded, resolveReadOutputEncoding, } from "../../sdk/read-output-contracts.js";
15
16
  import { encode as encodeToon } from "@toon-format/toon";
16
17
  const DECLARED_PROCESS_EXIT_CODES = new Set(Object.values(EXIT_CODE));
@@ -19,6 +20,18 @@ let streamErrorHandlersInstalled = false;
19
20
  function isPlainObject(value) {
20
21
  return typeof value === "object" && value !== null && !Array.isArray(value);
21
22
  }
23
+ function setActiveCommandResultOmitted(source) {
24
+ const omitted = { read_output: { result_omitted: true } };
25
+ propagateContextUsageServingReceipt(source, omitted);
26
+ setActiveCommandResult(omitted);
27
+ }
28
+ function setActiveCommandDeliveryResult(result, receiptSource, structuredDeliveryPreserved) {
29
+ if (structuredDeliveryPreserved) {
30
+ setActiveCommandResult(result);
31
+ return;
32
+ }
33
+ setActiveCommandResultOmitted(receiptSource);
34
+ }
22
35
  function shouldUseNativeOutput(result) {
23
36
  return isPlainObject(result) && result[NATIVE_OUTPUT_MARKER] === true;
24
37
  }
@@ -346,11 +359,13 @@ function resolveOutputService(effectiveResult, nativeOutput, options, format) {
346
359
  rendered: serviceOverride.result.endsWith("\n")
347
360
  ? serviceOverride.result
348
361
  : `${serviceOverride.result}\n`,
362
+ structuredDeliveryPreserved: false,
349
363
  };
350
364
  }
351
365
  return {
352
366
  result: serviceOverride.handled ? serviceOverride.result : effectiveResult,
353
367
  rendered: null,
368
+ structuredDeliveryPreserved: !serviceOverride.handled || isPlainObject(serviceOverride.result),
354
369
  };
355
370
  }
356
371
  /** Formats a command result after command-level output ownership is resolved. */
@@ -382,9 +397,12 @@ function formatEffectiveOutput(effectiveResult, nativeOutput, options) {
382
397
  commandOptions: resolvedCommandOptions,
383
398
  };
384
399
  const service = resolveOutputService(effectiveResult, nativeOutput, effectiveOptions, format);
385
- if (service.rendered !== null)
400
+ if (service.rendered !== null) {
401
+ setActiveCommandResultOmitted(effectiveResult);
386
402
  return service.rendered;
403
+ }
387
404
  const outputResult = service.result;
405
+ propagateContextUsageServingReceipt(effectiveResult, outputResult);
388
406
  const projectedOutputResult = command === "test"
389
407
  ? projectLinkedTestEvidence(outputResult, options.lean === true)
390
408
  : outputResult;
@@ -392,6 +410,7 @@ function formatEffectiveOutput(effectiveResult, nativeOutput, options) {
392
410
  if (isReadOutputBudgetExceeded(intentOutputResult)) {
393
411
  process.exitCode ||= EXIT_CODE.USAGE;
394
412
  }
413
+ let { structuredDeliveryPreserved } = service;
395
414
  const renderResolvedOutput = (value) => {
396
415
  if (format === "toon") {
397
416
  const markdownDefault = renderDefaultMarkdownResult(value);
@@ -402,6 +421,7 @@ function formatEffectiveOutput(effectiveResult, nativeOutput, options) {
402
421
  ? { rendered: null }
403
422
  : runActiveRendererOverride(format, value);
404
423
  if (rendererOverride.rendered !== null) {
424
+ structuredDeliveryPreserved = false;
405
425
  return rendererOverride.rendered.endsWith("\n")
406
426
  ? rendererOverride.rendered
407
427
  : `${rendererOverride.rendered}\n`;
@@ -414,7 +434,9 @@ function formatEffectiveOutput(effectiveResult, nativeOutput, options) {
414
434
  const accountedOutputResult = options.tokenAccounting === true
415
435
  ? attachOutputTokenAccounting(intentOutputResult, renderResolvedOutput)
416
436
  : intentOutputResult;
417
- return renderResolvedOutput(accountedOutputResult);
437
+ const rendered = renderResolvedOutput(accountedOutputResult);
438
+ setActiveCommandDeliveryResult(accountedOutputResult, effectiveResult, options.quiet !== true && structuredDeliveryPreserved);
439
+ return rendered;
418
440
  }
419
441
  /** Implements format output for the public runtime surface of this module. */
420
442
  export function formatOutput(result, options) {
@@ -427,9 +449,11 @@ export function formatOutput(result, options) {
427
449
  ? suppressedOutput.result
428
450
  : stripNativeOutputMarker(commandOverride.result);
429
451
  setActiveCommandResult(effectiveResult);
430
- return suppressedOutput
431
- ? ""
432
- : formatEffectiveOutput(effectiveResult, nativeOutput, options);
452
+ if (suppressedOutput) {
453
+ setActiveCommandResultOmitted(effectiveResult);
454
+ return "";
455
+ }
456
+ return formatEffectiveOutput(effectiveResult, nativeOutput, options);
433
457
  }
434
458
  /** Implements print result for the public runtime surface of this module. */
435
459
  export function printResult(result, options) {
@@ -468,4 +492,4 @@ export const outputTestOnly = {
468
492
  renderToonValue,
469
493
  };
470
494
  //# sourceMappingURL=output.js.map
471
- //# debugId=202cbb3e-71fe-5701-a1f5-eb515bf56561
495
+ //# debugId=fa89762b-915f-5ef0-a091-f05338c11683
@@ -4,6 +4,8 @@ export declare function nowIso(): string;
4
4
  export declare function isTimestampLiteral(input: string): boolean;
5
5
  /** Return whether a string is a calendar-valid RFC 3339 date-time. */
6
6
  export declare function isRfc3339DateTime(input: string): boolean;
7
+ /** Return whether a value is a calendar-valid RFC 3339 date-time whose fractional seconds carry no sub-millisecond information. */
8
+ export declare function isMillisecondPrecisionRfc3339DateTime(input: string): boolean;
7
9
  /** Implements compare timestamp strings for the public runtime surface of this module. */
8
10
  export declare function compareTimestampStrings(left: string, right: string): number;
9
11
  /** Timestamp-bearing record accepted by shared inclusive bound filtering. */
@@ -4,7 +4,7 @@
4
4
  * Provides shared primitives and utilities for Time.
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]="7887e752-b1b8-5c5e-9dd8-93b41cb757af")}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]="fb1102d4-1beb-5de8-87e6-af2efebafe39")}catch(e){}}();
8
8
  import { PmCliError } from "./errors.js";
9
9
  import { evictOldestMemoEntries } from "./memo.js";
10
10
  import { EXIT_CODE } from "./constants.js";
@@ -48,6 +48,12 @@ export function isRfc3339DateTime(input) {
48
48
  (offsetHourRaw === undefined || Number(offsetHourRaw) <= 23) &&
49
49
  (offsetMinuteRaw === undefined || Number(offsetMinuteRaw) <= 59));
50
50
  }
51
+ /** Return whether a value is a calendar-valid RFC 3339 date-time whose fractional seconds carry no sub-millisecond information. */
52
+ export function isMillisecondPrecisionRfc3339DateTime(input) {
53
+ const fraction = /\.(\d+)(?:Z|[+-]\d{2}:\d{2})$/iu.exec(input)?.[1];
54
+ return (isRfc3339DateTime(input) &&
55
+ (fraction === undefined || /^\d{0,3}0*$/u.test(fraction)));
56
+ }
51
57
  /**
52
58
  * Memoized `Date.parse` for {@link compareTimestampStrings}. Sort comparators call it
53
59
  * O(n log n) times over a corpus whose timestamp strings repeat heavily, and
@@ -298,4 +304,4 @@ export const _testOnly = {
298
304
  isWhitespaceCharacter,
299
305
  };
300
306
  //# sourceMappingURL=time.js.map
301
- //# debugId=7887e752-b1b8-5c5e-9dd8-93b41cb757af
307
+ //# debugId=fb1102d4-1beb-5de8-87e6-af2efebafe39