@unbrained/pm-cli 2026.5.18 → 2026.5.24

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 (225) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +2 -1
  3. package/dist/cli/commander-usage.js +16 -2
  4. package/dist/cli/commander-usage.js.map +1 -1
  5. package/dist/cli/commands/annotation-command.d.ts +49 -0
  6. package/dist/cli/commands/annotation-command.js +135 -0
  7. package/dist/cli/commands/annotation-command.js.map +1 -0
  8. package/dist/cli/commands/append.js +3 -7
  9. package/dist/cli/commands/append.js.map +1 -1
  10. package/dist/cli/commands/calendar.js +3 -6
  11. package/dist/cli/commands/calendar.js.map +1 -1
  12. package/dist/cli/commands/claim.js +12 -22
  13. package/dist/cli/commands/claim.js.map +1 -1
  14. package/dist/cli/commands/close.js +61 -9
  15. package/dist/cli/commands/close.js.map +1 -1
  16. package/dist/cli/commands/comments.d.ts +5 -0
  17. package/dist/cli/commands/comments.js +27 -117
  18. package/dist/cli/commands/comments.js.map +1 -1
  19. package/dist/cli/commands/completion.js +102 -15
  20. package/dist/cli/commands/completion.js.map +1 -1
  21. package/dist/cli/commands/context.js +4 -10
  22. package/dist/cli/commands/context.js.map +1 -1
  23. package/dist/cli/commands/contracts.js +168 -36
  24. package/dist/cli/commands/contracts.js.map +1 -1
  25. package/dist/cli/commands/create.js +49 -44
  26. package/dist/cli/commands/create.js.map +1 -1
  27. package/dist/cli/commands/dedupe-audit.js +7 -4
  28. package/dist/cli/commands/dedupe-audit.js.map +1 -1
  29. package/dist/cli/commands/delete.d.ts +3 -0
  30. package/dist/cli/commands/delete.js +9 -8
  31. package/dist/cli/commands/delete.js.map +1 -1
  32. package/dist/cli/commands/docs.d.ts +1 -0
  33. package/dist/cli/commands/docs.js +4 -8
  34. package/dist/cli/commands/docs.js.map +1 -1
  35. package/dist/cli/commands/event-validation-messages.d.ts +3 -0
  36. package/dist/cli/commands/event-validation-messages.js +44 -0
  37. package/dist/cli/commands/event-validation-messages.js.map +1 -0
  38. package/dist/cli/commands/extension.d.ts +1 -0
  39. package/dist/cli/commands/extension.js +138 -21
  40. package/dist/cli/commands/extension.js.map +1 -1
  41. package/dist/cli/commands/files.js +6 -13
  42. package/dist/cli/commands/files.js.map +1 -1
  43. package/dist/cli/commands/gc.js +17 -4
  44. package/dist/cli/commands/gc.js.map +1 -1
  45. package/dist/cli/commands/get.d.ts +3 -2
  46. package/dist/cli/commands/get.js +50 -8
  47. package/dist/cli/commands/get.js.map +1 -1
  48. package/dist/cli/commands/health.d.ts +10 -0
  49. package/dist/cli/commands/health.js +254 -75
  50. package/dist/cli/commands/health.js.map +1 -1
  51. package/dist/cli/commands/history-redact.d.ts +8 -0
  52. package/dist/cli/commands/history-redact.js +14 -97
  53. package/dist/cli/commands/history-redact.js.map +1 -1
  54. package/dist/cli/commands/history-repair.d.ts +33 -0
  55. package/dist/cli/commands/history-repair.js +166 -0
  56. package/dist/cli/commands/history-repair.js.map +1 -0
  57. package/dist/cli/commands/history.d.ts +4 -4
  58. package/dist/cli/commands/history.js +10 -88
  59. package/dist/cli/commands/history.js.map +1 -1
  60. package/dist/cli/commands/index.d.ts +3 -1
  61. package/dist/cli/commands/index.js +5 -3
  62. package/dist/cli/commands/index.js.map +1 -1
  63. package/dist/cli/commands/init.d.ts +28 -0
  64. package/dist/cli/commands/init.js +23 -2
  65. package/dist/cli/commands/init.js.map +1 -1
  66. package/dist/cli/commands/learnings.js +20 -119
  67. package/dist/cli/commands/learnings.js.map +1 -1
  68. package/dist/cli/commands/linked-test-entry.d.ts +3 -0
  69. package/dist/cli/commands/linked-test-entry.js +62 -0
  70. package/dist/cli/commands/linked-test-entry.js.map +1 -0
  71. package/dist/cli/commands/list.js +32 -22
  72. package/dist/cli/commands/list.js.map +1 -1
  73. package/dist/cli/commands/notes.js +20 -119
  74. package/dist/cli/commands/notes.js.map +1 -1
  75. package/dist/cli/commands/plan.d.ts +3 -0
  76. package/dist/cli/commands/plan.js +184 -22
  77. package/dist/cli/commands/plan.js.map +1 -1
  78. package/dist/cli/commands/restore.js +7 -50
  79. package/dist/cli/commands/restore.js.map +1 -1
  80. package/dist/cli/commands/schema.d.ts +31 -0
  81. package/dist/cli/commands/schema.js +98 -0
  82. package/dist/cli/commands/schema.js.map +1 -0
  83. package/dist/cli/commands/search.js +151 -40
  84. package/dist/cli/commands/search.js.map +1 -1
  85. package/dist/cli/commands/templates.d.ts +4 -0
  86. package/dist/cli/commands/templates.js +89 -17
  87. package/dist/cli/commands/templates.js.map +1 -1
  88. package/dist/cli/commands/test-all.js +4 -8
  89. package/dist/cli/commands/test-all.js.map +1 -1
  90. package/dist/cli/commands/test.d.ts +1 -0
  91. package/dist/cli/commands/test.js +7 -10
  92. package/dist/cli/commands/test.js.map +1 -1
  93. package/dist/cli/commands/update-many.js +4 -8
  94. package/dist/cli/commands/update-many.js.map +1 -1
  95. package/dist/cli/commands/update.js +109 -51
  96. package/dist/cli/commands/update.js.map +1 -1
  97. package/dist/cli/commands/validate.d.ts +3 -1
  98. package/dist/cli/commands/validate.js +23 -71
  99. package/dist/cli/commands/validate.js.map +1 -1
  100. package/dist/cli/error-guidance.js +96 -6
  101. package/dist/cli/error-guidance.js.map +1 -1
  102. package/dist/cli/extension-command-help.d.ts +0 -1
  103. package/dist/cli/extension-command-help.js +2 -13
  104. package/dist/cli/extension-command-help.js.map +1 -1
  105. package/dist/cli/extension-command-options.d.ts +1 -0
  106. package/dist/cli/extension-command-options.js +106 -7
  107. package/dist/cli/extension-command-options.js.map +1 -1
  108. package/dist/cli/help-content.d.ts +0 -1
  109. package/dist/cli/help-content.js +13 -9
  110. package/dist/cli/help-content.js.map +1 -1
  111. package/dist/cli/help-json-payload.d.ts +1 -0
  112. package/dist/cli/help-json-payload.js +33 -3
  113. package/dist/cli/help-json-payload.js.map +1 -1
  114. package/dist/cli/main.js +35 -29
  115. package/dist/cli/main.js.map +1 -1
  116. package/dist/cli/register-list-query.d.ts +1 -1
  117. package/dist/cli/register-list-query.js +40 -17
  118. package/dist/cli/register-list-query.js.map +1 -1
  119. package/dist/cli/register-mutation.d.ts +1 -1
  120. package/dist/cli/register-mutation.js +232 -64
  121. package/dist/cli/register-mutation.js.map +1 -1
  122. package/dist/cli/register-operations.js +16 -11
  123. package/dist/cli/register-operations.js.map +1 -1
  124. package/dist/cli/register-setup.js +26 -14
  125. package/dist/cli/register-setup.js.map +1 -1
  126. package/dist/cli/registration-helpers.d.ts +0 -2
  127. package/dist/cli/registration-helpers.js +13 -40
  128. package/dist/cli/registration-helpers.js.map +1 -1
  129. package/dist/cli.js +23 -3
  130. package/dist/cli.js.map +1 -1
  131. package/dist/core/extensions/index.d.ts +0 -1
  132. package/dist/core/extensions/index.js +2 -14
  133. package/dist/core/extensions/index.js.map +1 -1
  134. package/dist/core/extensions/loader.js +3 -9
  135. package/dist/core/extensions/loader.js.map +1 -1
  136. package/dist/core/fs/path-utils.d.ts +1 -0
  137. package/dist/core/fs/path-utils.js +12 -0
  138. package/dist/core/fs/path-utils.js.map +1 -0
  139. package/dist/core/history/drift-scan.d.ts +11 -0
  140. package/dist/core/history/drift-scan.js +67 -0
  141. package/dist/core/history/drift-scan.js.map +1 -0
  142. package/dist/core/history/replay.d.ts +82 -0
  143. package/dist/core/history/replay.js +249 -0
  144. package/dist/core/history/replay.js.map +1 -0
  145. package/dist/core/item/item-format.js +11 -8
  146. package/dist/core/item/item-format.js.map +1 -1
  147. package/dist/core/item/item-type-definition.d.ts +52 -0
  148. package/dist/core/item/item-type-definition.js +123 -0
  149. package/dist/core/item/item-type-definition.js.map +1 -0
  150. package/dist/core/item/parse.js +3 -2
  151. package/dist/core/item/parse.js.map +1 -1
  152. package/dist/core/item/priority.d.ts +23 -0
  153. package/dist/core/item/priority.js +55 -0
  154. package/dist/core/item/priority.js.map +1 -0
  155. package/dist/core/item/status.d.ts +14 -1
  156. package/dist/core/item/status.js +22 -2
  157. package/dist/core/item/status.js.map +1 -1
  158. package/dist/core/item/toon-decode.d.ts +19 -0
  159. package/dist/core/item/toon-decode.js +69 -0
  160. package/dist/core/item/toon-decode.js.map +1 -0
  161. package/dist/core/item/type-registry.js +13 -84
  162. package/dist/core/item/type-registry.js.map +1 -1
  163. package/dist/core/packages/manifest.js +3 -9
  164. package/dist/core/packages/manifest.js.map +1 -1
  165. package/dist/core/schema/item-types-file.d.ts +85 -0
  166. package/dist/core/schema/item-types-file.js +243 -0
  167. package/dist/core/schema/item-types-file.js.map +1 -0
  168. package/dist/core/schema/runtime-schema.d.ts +2 -1
  169. package/dist/core/schema/runtime-schema.js +11 -9
  170. package/dist/core/schema/runtime-schema.js.map +1 -1
  171. package/dist/core/search/semantic-defaults.js +3 -3
  172. package/dist/core/search/semantic-defaults.js.map +1 -1
  173. package/dist/core/shared/author.d.ts +1 -0
  174. package/dist/core/shared/author.js +9 -0
  175. package/dist/core/shared/author.js.map +1 -0
  176. package/dist/core/shared/lazy-module.d.ts +1 -0
  177. package/dist/core/shared/lazy-module.js +11 -0
  178. package/dist/core/shared/lazy-module.js.map +1 -0
  179. package/dist/core/shared/option-alias-visibility.d.ts +44 -0
  180. package/dist/core/shared/option-alias-visibility.js +76 -0
  181. package/dist/core/shared/option-alias-visibility.js.map +1 -0
  182. package/dist/core/shared/text-normalization.d.ts +0 -1
  183. package/dist/core/shared/text-normalization.js +2 -5
  184. package/dist/core/shared/text-normalization.js.map +1 -1
  185. package/dist/core/store/item-store.d.ts +2 -0
  186. package/dist/core/store/item-store.js +70 -39
  187. package/dist/core/store/item-store.js.map +1 -1
  188. package/dist/core/store/settings-validator.d.ts +106 -0
  189. package/dist/core/store/settings-validator.js +279 -0
  190. package/dist/core/store/settings-validator.js.map +1 -0
  191. package/dist/core/store/settings.js +6 -343
  192. package/dist/core/store/settings.js.map +1 -1
  193. package/dist/core/telemetry/runtime.js +5 -3
  194. package/dist/core/telemetry/runtime.js.map +1 -1
  195. package/dist/mcp/server.js +64 -13
  196. package/dist/mcp/server.js.map +1 -1
  197. package/dist/sdk/cli-contracts.d.ts +9 -2
  198. package/dist/sdk/cli-contracts.js +204 -13
  199. package/dist/sdk/cli-contracts.js.map +1 -1
  200. package/dist/sdk/runtime.d.ts +25 -1
  201. package/dist/sdk/runtime.js +46 -3
  202. package/dist/sdk/runtime.js.map +1 -1
  203. package/dist/types.d.ts +6 -0
  204. package/dist/types.js +10 -2
  205. package/dist/types.js.map +1 -1
  206. package/docs/AGENT_GUIDE.md +7 -1
  207. package/docs/ARCHITECTURE.md +1 -1
  208. package/docs/COMMANDS.md +39 -6
  209. package/docs/CONFIGURATION.md +1 -1
  210. package/docs/RELEASING.md +11 -7
  211. package/docs/SDK.md +11 -2
  212. package/package.json +12 -11
  213. package/packages/pm-calendar/README.md +3 -1
  214. package/packages/pm-calendar/extensions/calendar/index.js +21 -2
  215. package/packages/pm-calendar/extensions/calendar/index.ts +21 -2
  216. package/packages/pm-search-advanced/README.md +8 -0
  217. package/packages/pm-search-advanced/extensions/search-advanced/index.js +74 -0
  218. package/packages/pm-search-advanced/extensions/search-advanced/index.ts +74 -0
  219. package/packages/pm-search-advanced/extensions/search-advanced/runtime.js +67 -9
  220. package/packages/pm-search-advanced/extensions/search-advanced/runtime.ts +67 -9
  221. package/packages/pm-templates/extensions/templates/runtime.js +11 -202
  222. package/packages/pm-templates/extensions/templates/runtime.ts +38 -230
  223. package/dist/core/output/command-aware.d.ts +0 -1
  224. package/dist/core/output/command-aware.js +0 -397
  225. package/dist/core/output/command-aware.js.map +0 -1
@@ -0,0 +1 @@
1
+ export declare function isPathWithinDirectory(directory: string, targetPath: string): boolean;
@@ -0,0 +1,12 @@
1
+
2
+ !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]="e8f4f66b-8f68-5a07-8905-ff2602564716")}catch(e){}}();
3
+ import path from "path";
4
+ export function isPathWithinDirectory(directory, targetPath) {
5
+ const relative = path.relative(directory, targetPath);
6
+ if (relative.length === 0) {
7
+ return true;
8
+ }
9
+ return !relative.startsWith("..") && !path.isAbsolute(relative);
10
+ }
11
+ //# sourceMappingURL=path-utils.js.map
12
+ //# debugId=e8f4f66b-8f68-5a07-8905-ff2602564716
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.js","sources":["core/fs/path-utils.ts"],"sourceRoot":"/","sourcesContent":["import path from \"path\";\n\nexport function isPathWithinDirectory(directory: string, targetPath: string): boolean {\n const relative = path.relative(directory, targetPath);\n if (relative.length === 0) {\n return true;\n }\n return !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n"],"names":[],"mappings":";;AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,UAAU,qBAAqB,CAAC,SAAiB,EAAE,UAAkB;IACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACtD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AAClE,CAAC","debugId":"e8f4f66b-8f68-5a07-8905-ff2602564716"}
@@ -0,0 +1,11 @@
1
+ import type { ItemMetadata } from "../../types/index.js";
2
+ export interface DriftScanResult {
3
+ missingStreams: string[];
4
+ unreadableStreams: string[];
5
+ hashMismatches: string[];
6
+ chainMismatches: string[];
7
+ driftedItems: string[];
8
+ }
9
+ export declare function scanHistoryDrift(pmRoot: string, items: Array<ItemMetadata & {
10
+ body: string;
11
+ }>): Promise<DriftScanResult>;
@@ -0,0 +1,67 @@
1
+
2
+ !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]="ac6b8edd-33a1-58cc-aaa7-1846bde3e340")}catch(e){}}();
3
+ import fs from "fs/promises";
4
+ import { getHistoryPath } from "../store/paths.js";
5
+ import { hashDocument } from "./history.js";
6
+ import { verifyHistoryChain } from "./replay.js";
7
+ export async function scanHistoryDrift(pmRoot, items) {
8
+ const missingStreams = [];
9
+ const unreadableStreams = [];
10
+ const hashMismatches = [];
11
+ const chainMismatches = [];
12
+ for (const item of items) {
13
+ const historyPath = getHistoryPath(pmRoot, item.id);
14
+ let latestAfterHash = null;
15
+ try {
16
+ const raw = await fs.readFile(historyPath, "utf8");
17
+ if (raw.trim().length === 0) {
18
+ missingStreams.push(item.id);
19
+ continue;
20
+ }
21
+ const entries = [];
22
+ for (const line of raw.split(/\r?\n/)) {
23
+ const trimmed = line.trim();
24
+ if (trimmed.length === 0) {
25
+ continue;
26
+ }
27
+ const parsed = JSON.parse(trimmed);
28
+ if (typeof parsed.after_hash !== "string" || parsed.after_hash.trim().length === 0) {
29
+ throw new Error("missing after_hash");
30
+ }
31
+ entries.push(parsed);
32
+ latestAfterHash = parsed.after_hash;
33
+ }
34
+ const chainVerification = verifyHistoryChain(entries);
35
+ if (!chainVerification.ok) {
36
+ chainMismatches.push(item.id);
37
+ }
38
+ }
39
+ catch (error) {
40
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") {
41
+ missingStreams.push(item.id);
42
+ }
43
+ else {
44
+ unreadableStreams.push(item.id);
45
+ }
46
+ continue;
47
+ }
48
+ /* c8 ignore start -- defensive guard for future history schema changes. */
49
+ if (!latestAfterHash) {
50
+ missingStreams.push(item.id);
51
+ continue;
52
+ }
53
+ /* c8 ignore stop */
54
+ const { body, ...frontMatter } = item;
55
+ const currentHash = hashDocument({
56
+ metadata: frontMatter,
57
+ body,
58
+ });
59
+ if (currentHash !== latestAfterHash) {
60
+ hashMismatches.push(item.id);
61
+ }
62
+ }
63
+ const driftedItems = [...new Set([...missingStreams, ...unreadableStreams, ...hashMismatches, ...chainMismatches])].sort((a, b) => a.localeCompare(b));
64
+ return { missingStreams, unreadableStreams, hashMismatches, chainMismatches, driftedItems };
65
+ }
66
+ //# sourceMappingURL=drift-scan.js.map
67
+ //# debugId=ac6b8edd-33a1-58cc-aaa7-1846bde3e340
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift-scan.js","sources":["core/history/drift-scan.ts"],"sourceRoot":"/","sourcesContent":["import fs from \"fs/promises\";\nimport { getHistoryPath } from \"../store/paths.js\";\nimport { hashDocument } from \"./history.js\";\nimport { verifyHistoryChain } from \"./replay.js\";\nimport type { HistoryEntry, ItemMetadata } from \"../../types/index.js\";\n\nexport interface DriftScanResult {\n missingStreams: string[];\n unreadableStreams: string[];\n hashMismatches: string[];\n chainMismatches: string[];\n driftedItems: string[];\n}\n\nexport async function scanHistoryDrift(\n pmRoot: string,\n items: Array<ItemMetadata & { body: string }>,\n): Promise<DriftScanResult> {\n const missingStreams: string[] = [];\n const unreadableStreams: string[] = [];\n const hashMismatches: string[] = [];\n const chainMismatches: string[] = [];\n\n for (const item of items) {\n const historyPath = getHistoryPath(pmRoot, item.id);\n let latestAfterHash: string | null = null;\n try {\n const raw = await fs.readFile(historyPath, \"utf8\");\n if (raw.trim().length === 0) {\n missingStreams.push(item.id);\n continue;\n }\n const entries: HistoryEntry[] = [];\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (trimmed.length === 0) {\n continue;\n }\n const parsed = JSON.parse(trimmed) as HistoryEntry;\n if (typeof parsed.after_hash !== \"string\" || parsed.after_hash.trim().length === 0) {\n throw new Error(\"missing after_hash\");\n }\n entries.push(parsed);\n latestAfterHash = parsed.after_hash;\n }\n const chainVerification = verifyHistoryChain(entries);\n if (!chainVerification.ok) {\n chainMismatches.push(item.id);\n }\n } catch (error: unknown) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && (error as { code?: string }).code === \"ENOENT\") {\n missingStreams.push(item.id);\n } else {\n unreadableStreams.push(item.id);\n }\n continue;\n }\n /* c8 ignore start -- defensive guard for future history schema changes. */\n if (!latestAfterHash) {\n missingStreams.push(item.id);\n continue;\n }\n /* c8 ignore stop */\n const { body, ...frontMatter } = item;\n const currentHash = hashDocument({\n metadata: frontMatter as ItemMetadata,\n body,\n });\n if (currentHash !== latestAfterHash) {\n hashMismatches.push(item.id);\n }\n }\n\n const driftedItems = [...new Set([...missingStreams, ...unreadableStreams, ...hashMismatches, ...chainMismatches])].sort((a, b) =>\n a.localeCompare(b),\n );\n return { missingStreams, unreadableStreams, hashMismatches, chainMismatches, driftedItems };\n}\n"],"names":[],"mappings":"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","debugId":"ac6b8edd-33a1-58cc-aaa7-1846bde3e340"}
@@ -0,0 +1,82 @@
1
+ import type { HistoryEntry, HistoryPatchOp, ItemDocument } from "../../types/index.js";
2
+ /**
3
+ * Shared history replay/patch mechanics single-sourced for the history, restore,
4
+ * history-redact, and history-repair commands plus the health/validate drift checks.
5
+ *
6
+ * Each command keeps its own thin error-formatting wrapper so the exact CLI error
7
+ * contracts (restore's rich patch-failure context, redact's op tag, history's
8
+ * generic message) are preserved; only the underlying replay/patch logic is shared.
9
+ */
10
+ export interface ReplayDocument {
11
+ metadata: Record<string, unknown>;
12
+ body: string;
13
+ }
14
+ export declare const EMPTY_REPLAY_DOCUMENT: ReplayDocument;
15
+ export declare function cloneEmptyReplayDocument(): ReplayDocument;
16
+ export declare function replayHash(document: ReplayDocument): string;
17
+ export declare function replayToItemDocument(document: ReplayDocument): ItemDocument;
18
+ /**
19
+ * Canonicalize an item document into the ordered replay form used when comparing
20
+ * a replayed chain against the on-disk item (restore + history-repair reconciliation).
21
+ */
22
+ export declare function toReplayDocument(document: ItemDocument): ReplayDocument;
23
+ export declare function normalizeReplayPatchPath(path: string): string;
24
+ export declare function normalizeReplayPatchOps(patch: HistoryPatchOp[]): HistoryPatchOp[];
25
+ export type ReplayApplyResult = {
26
+ ok: true;
27
+ document: ReplayDocument;
28
+ } | {
29
+ ok: false;
30
+ error: unknown;
31
+ };
32
+ /**
33
+ * Strictly apply a history patch (front_matter->metadata normalized) to a replay
34
+ * document. Returns a result envelope rather than throwing so each caller can
35
+ * format its own error contract.
36
+ */
37
+ export declare function tryApplyReplayPatch(current: ReplayDocument, patch: HistoryPatchOp[]): ReplayApplyResult;
38
+ /**
39
+ * Deterministically verify a history chain: each entry's before_hash must equal
40
+ * the prior replayed after_hash, the patch must strictly apply, and the recorded
41
+ * after_hash must equal the replayed result.
42
+ */
43
+ export declare function verifyHistoryChain(entries: HistoryEntry[]): {
44
+ ok: boolean;
45
+ errors: string[];
46
+ };
47
+ export interface LenientApplyResult {
48
+ document: ReplayDocument;
49
+ convertedReplaceToAdd: number;
50
+ skippedOps: number;
51
+ }
52
+ /**
53
+ * Apply a legacy patch op-by-op, recovering from drift that strict replay rejects:
54
+ * a `replace` whose path no longer exists is retried as `add`, and any op that
55
+ * still cannot apply against the current replay state is skipped. The resulting
56
+ * document is what the repaired entry's recomputed patch should target.
57
+ */
58
+ export declare function lenientApplyReplayPatch(current: ReplayDocument, patch: HistoryPatchOp[]): LenientApplyResult;
59
+ export interface ReanchorEntryDetail {
60
+ index: number;
61
+ rehashed: boolean;
62
+ patch_repaired: boolean;
63
+ converted_replace_to_add: number;
64
+ skipped_ops: number;
65
+ }
66
+ export interface ReanchorResult {
67
+ entries: HistoryEntry[];
68
+ finalDocument: ReplayDocument;
69
+ entriesRehashed: number;
70
+ entriesPatchRepaired: number;
71
+ convertedReplaceToAdd: number;
72
+ skippedOps: number;
73
+ details: ReanchorEntryDetail[];
74
+ }
75
+ /**
76
+ * Re-anchor a drifted history chain: replay every entry from empty, recompute the
77
+ * before/after hashes, and only rewrite a patch when the original op set no longer
78
+ * strictly applies (legacy drift). Clean entries keep their patch verbatim so the
79
+ * on-disk diff stays minimal. The returned chain verifies via verifyHistoryChain.
80
+ */
81
+ export declare function reanchorHistoryEntries(entries: HistoryEntry[]): ReanchorResult;
82
+ export declare function historyEntriesToRaw(entries: HistoryEntry[]): string;
@@ -0,0 +1,249 @@
1
+
2
+ !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]="9f6d7165-e26e-5815-9ac5-aad4ce4d3877")}catch(e){}}();
3
+ import jsonPatch from "fast-json-patch";
4
+ import { FRONT_MATTER_KEY_ORDER } from "../shared/constants.js";
5
+ import { canonicalDocument } from "../item/item-format.js";
6
+ import { orderObject, sha256Hex, stableStringify } from "../shared/serialization.js";
7
+ import { hashDocument } from "./history.js";
8
+ export const EMPTY_REPLAY_DOCUMENT = {
9
+ metadata: {},
10
+ body: "",
11
+ };
12
+ export function cloneEmptyReplayDocument() {
13
+ return structuredClone(EMPTY_REPLAY_DOCUMENT);
14
+ }
15
+ export function replayHash(document) {
16
+ try {
17
+ return hashDocument({
18
+ metadata: document.metadata,
19
+ body: document.body,
20
+ });
21
+ }
22
+ catch {
23
+ // Legacy/malformed replay states (for example a stream whose first entry never
24
+ // established a full `create` document, so the canonicalizer cannot normalize it)
25
+ // cannot be canonically hashed. Fall back to a deterministic structural hash so
26
+ // re-anchor and verification stay internally consistent for these streams. Fully
27
+ // formed documents always take the canonical path above, so valid streams are
28
+ // unaffected.
29
+ return sha256Hex(stableStringify({ replay_fallback: true, metadata: document.metadata, body: document.body }));
30
+ }
31
+ }
32
+ export function replayToItemDocument(document) {
33
+ return {
34
+ metadata: document.metadata,
35
+ body: document.body,
36
+ };
37
+ }
38
+ /**
39
+ * Canonicalize an item document into the ordered replay form used when comparing
40
+ * a replayed chain against the on-disk item (restore + history-repair reconciliation).
41
+ */
42
+ export function toReplayDocument(document) {
43
+ if (!document.metadata || Object.keys(document.metadata).length === 0) {
44
+ return {
45
+ metadata: {},
46
+ body: document.body ?? "",
47
+ };
48
+ }
49
+ const canonical = canonicalDocument(document);
50
+ return {
51
+ metadata: orderObject(canonical.metadata, FRONT_MATTER_KEY_ORDER),
52
+ body: canonical.body,
53
+ };
54
+ }
55
+ export function normalizeReplayPatchPath(path) {
56
+ if (path === "/front_matter") {
57
+ return "/metadata";
58
+ }
59
+ if (path.startsWith("/front_matter/")) {
60
+ return `/metadata/${path.slice("/front_matter/".length)}`;
61
+ }
62
+ return path;
63
+ }
64
+ export function normalizeReplayPatchOps(patch) {
65
+ return patch.map((operation) => ({
66
+ ...operation,
67
+ path: normalizeReplayPatchPath(operation.path),
68
+ from: operation.from ? normalizeReplayPatchPath(operation.from) : undefined,
69
+ }));
70
+ }
71
+ function isReplayDocumentShape(value) {
72
+ return (typeof value === "object" &&
73
+ value !== null &&
74
+ "metadata" in value &&
75
+ "body" in value &&
76
+ typeof value.body === "string" &&
77
+ typeof value.metadata === "object" &&
78
+ value.metadata !== null);
79
+ }
80
+ /**
81
+ * Strictly apply a history patch (front_matter->metadata normalized) to a replay
82
+ * document. Returns a result envelope rather than throwing so each caller can
83
+ * format its own error contract.
84
+ */
85
+ export function tryApplyReplayPatch(current, patch) {
86
+ try {
87
+ const normalizedPatch = normalizeReplayPatchOps(patch);
88
+ const applied = jsonPatch.applyPatch(structuredClone(current), normalizedPatch, true, false).newDocument;
89
+ if (!isReplayDocumentShape(applied)) {
90
+ return { ok: false, error: new Error("history_replay_invalid_document_shape") };
91
+ }
92
+ return { ok: true, document: { metadata: applied.metadata, body: applied.body } };
93
+ }
94
+ catch (error) {
95
+ return { ok: false, error };
96
+ }
97
+ }
98
+ /**
99
+ * Deterministically verify a history chain: each entry's before_hash must equal
100
+ * the prior replayed after_hash, the patch must strictly apply, and the recorded
101
+ * after_hash must equal the replayed result.
102
+ */
103
+ export function verifyHistoryChain(entries) {
104
+ let replay = cloneEmptyReplayDocument();
105
+ for (let index = 0; index < entries.length; index += 1) {
106
+ const entry = entries[index];
107
+ if (replayHash(replay) !== entry.before_hash) {
108
+ return {
109
+ ok: false,
110
+ errors: [`verify_failed:before_hash_mismatch:entry_${index + 1}`],
111
+ };
112
+ }
113
+ const applied = tryApplyReplayPatch(replay, entry.patch);
114
+ if (!applied.ok) {
115
+ return {
116
+ ok: false,
117
+ errors: [`verify_failed:patch_apply_failed:entry_${index + 1}`],
118
+ };
119
+ }
120
+ replay = applied.document;
121
+ if (replayHash(replay) !== entry.after_hash) {
122
+ return {
123
+ ok: false,
124
+ errors: [`verify_failed:after_hash_mismatch:entry_${index + 1}`],
125
+ };
126
+ }
127
+ }
128
+ return { ok: true, errors: [] };
129
+ }
130
+ function tryApplySingleOp(document, op) {
131
+ try {
132
+ const applied = jsonPatch.applyPatch(structuredClone(document), [op], true, false).newDocument;
133
+ return { ok: true, document: applied };
134
+ }
135
+ catch {
136
+ return { ok: false };
137
+ }
138
+ }
139
+ /**
140
+ * Apply a legacy patch op-by-op, recovering from drift that strict replay rejects:
141
+ * a `replace` whose path no longer exists is retried as `add`, and any op that
142
+ * still cannot apply against the current replay state is skipped. The resulting
143
+ * document is what the repaired entry's recomputed patch should target.
144
+ */
145
+ export function lenientApplyReplayPatch(current, patch) {
146
+ let working = structuredClone(current);
147
+ let convertedReplaceToAdd = 0;
148
+ let skippedOps = 0;
149
+ for (const op of normalizeReplayPatchOps(patch)) {
150
+ const direct = tryApplySingleOp(working, op);
151
+ if (direct.ok) {
152
+ working = direct.document;
153
+ continue;
154
+ }
155
+ if (op.op === "replace") {
156
+ const asAdd = tryApplySingleOp(working, { ...op, op: "add" });
157
+ if (asAdd.ok) {
158
+ working = asAdd.document;
159
+ convertedReplaceToAdd += 1;
160
+ continue;
161
+ }
162
+ }
163
+ skippedOps += 1;
164
+ }
165
+ const candidate = working;
166
+ const document = {
167
+ metadata: typeof candidate.metadata === "object" && candidate.metadata !== null
168
+ ? candidate.metadata
169
+ : {},
170
+ body: typeof candidate.body === "string" ? candidate.body : current.body,
171
+ };
172
+ return { document, convertedReplaceToAdd, skippedOps };
173
+ }
174
+ /**
175
+ * Re-anchor a drifted history chain: replay every entry from empty, recompute the
176
+ * before/after hashes, and only rewrite a patch when the original op set no longer
177
+ * strictly applies (legacy drift). Clean entries keep their patch verbatim so the
178
+ * on-disk diff stays minimal. The returned chain verifies via verifyHistoryChain.
179
+ */
180
+ export function reanchorHistoryEntries(entries) {
181
+ let replay = cloneEmptyReplayDocument();
182
+ const rewritten = [];
183
+ const details = [];
184
+ let entriesRehashed = 0;
185
+ let entriesPatchRepaired = 0;
186
+ let convertedReplaceToAdd = 0;
187
+ let skippedOps = 0;
188
+ for (let index = 0; index < entries.length; index += 1) {
189
+ const entry = entries[index];
190
+ const beforeHash = replayHash(replay);
191
+ const strict = tryApplyReplayPatch(replay, entry.patch);
192
+ let next;
193
+ let outPatch;
194
+ let patchRepaired = false;
195
+ let entryConverted = 0;
196
+ let entrySkipped = 0;
197
+ if (strict.ok) {
198
+ next = strict.document;
199
+ outPatch = entry.patch;
200
+ }
201
+ else {
202
+ const lenient = lenientApplyReplayPatch(replay, entry.patch);
203
+ next = lenient.document;
204
+ outPatch = jsonPatch.compare(replay, next);
205
+ patchRepaired = true;
206
+ entryConverted = lenient.convertedReplaceToAdd;
207
+ entrySkipped = lenient.skippedOps;
208
+ convertedReplaceToAdd += entryConverted;
209
+ skippedOps += entrySkipped;
210
+ entriesPatchRepaired += 1;
211
+ }
212
+ const afterHash = replayHash(next);
213
+ const rehashed = beforeHash !== entry.before_hash || afterHash !== entry.after_hash;
214
+ if (rehashed) {
215
+ entriesRehashed += 1;
216
+ }
217
+ rewritten.push({
218
+ ...entry,
219
+ patch: outPatch,
220
+ before_hash: beforeHash,
221
+ after_hash: afterHash,
222
+ });
223
+ details.push({
224
+ index: index + 1,
225
+ rehashed,
226
+ patch_repaired: patchRepaired,
227
+ converted_replace_to_add: entryConverted,
228
+ skipped_ops: entrySkipped,
229
+ });
230
+ replay = next;
231
+ }
232
+ return {
233
+ entries: rewritten,
234
+ finalDocument: replay,
235
+ entriesRehashed,
236
+ entriesPatchRepaired,
237
+ convertedReplaceToAdd,
238
+ skippedOps,
239
+ details,
240
+ };
241
+ }
242
+ export function historyEntriesToRaw(entries) {
243
+ if (entries.length === 0) {
244
+ return "";
245
+ }
246
+ return `${entries.map((entry) => JSON.stringify(entry)).join("\n")}\n`;
247
+ }
248
+ //# sourceMappingURL=replay.js.map
249
+ //# debugId=9f6d7165-e26e-5815-9ac5-aad4ce4d3877
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sources":["core/history/replay.ts"],"sourceRoot":"/","sourcesContent":["import jsonPatch from \"fast-json-patch\";\nimport { FRONT_MATTER_KEY_ORDER } from \"../shared/constants.js\";\nimport { canonicalDocument } from \"../item/item-format.js\";\nimport { orderObject, sha256Hex, stableStringify } from \"../shared/serialization.js\";\nimport { hashDocument } from \"./history.js\";\nimport type { HistoryEntry, HistoryPatchOp, ItemDocument, ItemMetadata } from \"../../types/index.js\";\n\n/**\n * Shared history replay/patch mechanics single-sourced for the history, restore,\n * history-redact, and history-repair commands plus the health/validate drift checks.\n *\n * Each command keeps its own thin error-formatting wrapper so the exact CLI error\n * contracts (restore's rich patch-failure context, redact's op tag, history's\n * generic message) are preserved; only the underlying replay/patch logic is shared.\n */\n\nexport interface ReplayDocument {\n metadata: Record<string, unknown>;\n body: string;\n}\n\nexport const EMPTY_REPLAY_DOCUMENT: ReplayDocument = {\n metadata: {},\n body: \"\",\n};\n\nexport function cloneEmptyReplayDocument(): ReplayDocument {\n return structuredClone(EMPTY_REPLAY_DOCUMENT);\n}\n\nexport function replayHash(document: ReplayDocument): string {\n try {\n return hashDocument({\n metadata: document.metadata as unknown as ItemMetadata,\n body: document.body,\n });\n } catch {\n // Legacy/malformed replay states (for example a stream whose first entry never\n // established a full `create` document, so the canonicalizer cannot normalize it)\n // cannot be canonically hashed. Fall back to a deterministic structural hash so\n // re-anchor and verification stay internally consistent for these streams. Fully\n // formed documents always take the canonical path above, so valid streams are\n // unaffected.\n return sha256Hex(stableStringify({ replay_fallback: true, metadata: document.metadata, body: document.body }));\n }\n}\n\nexport function replayToItemDocument(document: ReplayDocument): ItemDocument {\n return {\n metadata: document.metadata as unknown as ItemMetadata,\n body: document.body,\n };\n}\n\n/**\n * Canonicalize an item document into the ordered replay form used when comparing\n * a replayed chain against the on-disk item (restore + history-repair reconciliation).\n */\nexport function toReplayDocument(document: ItemDocument): ReplayDocument {\n if (!document.metadata || Object.keys(document.metadata).length === 0) {\n return {\n metadata: {},\n body: document.body ?? \"\",\n };\n }\n const canonical = canonicalDocument(document);\n return {\n metadata: orderObject(canonical.metadata as unknown as Record<string, unknown>, FRONT_MATTER_KEY_ORDER),\n body: canonical.body,\n };\n}\n\nexport function normalizeReplayPatchPath(path: string): string {\n if (path === \"/front_matter\") {\n return \"/metadata\";\n }\n if (path.startsWith(\"/front_matter/\")) {\n return `/metadata/${path.slice(\"/front_matter/\".length)}`;\n }\n return path;\n}\n\nexport function normalizeReplayPatchOps(patch: HistoryPatchOp[]): HistoryPatchOp[] {\n return patch.map((operation) => ({\n ...operation,\n path: normalizeReplayPatchPath(operation.path),\n from: operation.from ? normalizeReplayPatchPath(operation.from) : undefined,\n }));\n}\n\nfunction isReplayDocumentShape(value: unknown): value is { metadata: Record<string, unknown>; body: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"metadata\" in value &&\n \"body\" in value &&\n typeof (value as { body: unknown }).body === \"string\" &&\n typeof (value as { metadata: unknown }).metadata === \"object\" &&\n (value as { metadata: unknown }).metadata !== null\n );\n}\n\nexport type ReplayApplyResult =\n | { ok: true; document: ReplayDocument }\n | { ok: false; error: unknown };\n\n/**\n * Strictly apply a history patch (front_matter->metadata normalized) to a replay\n * document. Returns a result envelope rather than throwing so each caller can\n * format its own error contract.\n */\nexport function tryApplyReplayPatch(current: ReplayDocument, patch: HistoryPatchOp[]): ReplayApplyResult {\n try {\n const normalizedPatch = normalizeReplayPatchOps(patch);\n const applied = jsonPatch.applyPatch(\n structuredClone(current),\n normalizedPatch as jsonPatch.Operation[],\n true,\n false,\n ).newDocument as unknown;\n if (!isReplayDocumentShape(applied)) {\n return { ok: false, error: new Error(\"history_replay_invalid_document_shape\") };\n }\n return { ok: true, document: { metadata: applied.metadata, body: applied.body } };\n } catch (error) {\n return { ok: false, error };\n }\n}\n\n/**\n * Deterministically verify a history chain: each entry's before_hash must equal\n * the prior replayed after_hash, the patch must strictly apply, and the recorded\n * after_hash must equal the replayed result.\n */\nexport function verifyHistoryChain(entries: HistoryEntry[]): { ok: boolean; errors: string[] } {\n let replay = cloneEmptyReplayDocument();\n for (let index = 0; index < entries.length; index += 1) {\n const entry = entries[index];\n if (replayHash(replay) !== entry.before_hash) {\n return {\n ok: false,\n errors: [`verify_failed:before_hash_mismatch:entry_${index + 1}`],\n };\n }\n const applied = tryApplyReplayPatch(replay, entry.patch);\n if (!applied.ok) {\n return {\n ok: false,\n errors: [`verify_failed:patch_apply_failed:entry_${index + 1}`],\n };\n }\n replay = applied.document;\n if (replayHash(replay) !== entry.after_hash) {\n return {\n ok: false,\n errors: [`verify_failed:after_hash_mismatch:entry_${index + 1}`],\n };\n }\n }\n return { ok: true, errors: [] };\n}\n\nexport interface LenientApplyResult {\n document: ReplayDocument;\n convertedReplaceToAdd: number;\n skippedOps: number;\n}\n\nfunction tryApplySingleOp(document: unknown, op: HistoryPatchOp): { ok: true; document: unknown } | { ok: false } {\n try {\n const applied = jsonPatch.applyPatch(\n structuredClone(document),\n [op as jsonPatch.Operation],\n true,\n false,\n ).newDocument as unknown;\n return { ok: true, document: applied };\n } catch {\n return { ok: false };\n }\n}\n\n/**\n * Apply a legacy patch op-by-op, recovering from drift that strict replay rejects:\n * a `replace` whose path no longer exists is retried as `add`, and any op that\n * still cannot apply against the current replay state is skipped. The resulting\n * document is what the repaired entry's recomputed patch should target.\n */\nexport function lenientApplyReplayPatch(current: ReplayDocument, patch: HistoryPatchOp[]): LenientApplyResult {\n let working: unknown = structuredClone(current);\n let convertedReplaceToAdd = 0;\n let skippedOps = 0;\n\n for (const op of normalizeReplayPatchOps(patch)) {\n const direct = tryApplySingleOp(working, op);\n if (direct.ok) {\n working = direct.document;\n continue;\n }\n if (op.op === \"replace\") {\n const asAdd = tryApplySingleOp(working, { ...op, op: \"add\" });\n if (asAdd.ok) {\n working = asAdd.document;\n convertedReplaceToAdd += 1;\n continue;\n }\n }\n skippedOps += 1;\n }\n\n const candidate = working as { metadata?: unknown; body?: unknown };\n const document: ReplayDocument = {\n metadata:\n typeof candidate.metadata === \"object\" && candidate.metadata !== null\n ? (candidate.metadata as Record<string, unknown>)\n : {},\n body: typeof candidate.body === \"string\" ? candidate.body : current.body,\n };\n return { document, convertedReplaceToAdd, skippedOps };\n}\n\nexport interface ReanchorEntryDetail {\n index: number;\n rehashed: boolean;\n patch_repaired: boolean;\n converted_replace_to_add: number;\n skipped_ops: number;\n}\n\nexport interface ReanchorResult {\n entries: HistoryEntry[];\n finalDocument: ReplayDocument;\n entriesRehashed: number;\n entriesPatchRepaired: number;\n convertedReplaceToAdd: number;\n skippedOps: number;\n details: ReanchorEntryDetail[];\n}\n\n/**\n * Re-anchor a drifted history chain: replay every entry from empty, recompute the\n * before/after hashes, and only rewrite a patch when the original op set no longer\n * strictly applies (legacy drift). Clean entries keep their patch verbatim so the\n * on-disk diff stays minimal. The returned chain verifies via verifyHistoryChain.\n */\nexport function reanchorHistoryEntries(entries: HistoryEntry[]): ReanchorResult {\n let replay = cloneEmptyReplayDocument();\n const rewritten: HistoryEntry[] = [];\n const details: ReanchorEntryDetail[] = [];\n let entriesRehashed = 0;\n let entriesPatchRepaired = 0;\n let convertedReplaceToAdd = 0;\n let skippedOps = 0;\n\n for (let index = 0; index < entries.length; index += 1) {\n const entry = entries[index];\n const beforeHash = replayHash(replay);\n const strict = tryApplyReplayPatch(replay, entry.patch);\n\n let next: ReplayDocument;\n let outPatch: HistoryPatchOp[];\n let patchRepaired = false;\n let entryConverted = 0;\n let entrySkipped = 0;\n\n if (strict.ok) {\n next = strict.document;\n outPatch = entry.patch;\n } else {\n const lenient = lenientApplyReplayPatch(replay, entry.patch);\n next = lenient.document;\n outPatch = jsonPatch.compare(replay, next) as HistoryPatchOp[];\n patchRepaired = true;\n entryConverted = lenient.convertedReplaceToAdd;\n entrySkipped = lenient.skippedOps;\n convertedReplaceToAdd += entryConverted;\n skippedOps += entrySkipped;\n entriesPatchRepaired += 1;\n }\n\n const afterHash = replayHash(next);\n const rehashed = beforeHash !== entry.before_hash || afterHash !== entry.after_hash;\n if (rehashed) {\n entriesRehashed += 1;\n }\n\n rewritten.push({\n ...entry,\n patch: outPatch,\n before_hash: beforeHash,\n after_hash: afterHash,\n });\n details.push({\n index: index + 1,\n rehashed,\n patch_repaired: patchRepaired,\n converted_replace_to_add: entryConverted,\n skipped_ops: entrySkipped,\n });\n replay = next;\n }\n\n return {\n entries: rewritten,\n finalDocument: replay,\n entriesRehashed,\n entriesPatchRepaired,\n convertedReplaceToAdd,\n skippedOps,\n details,\n };\n}\n\nexport function historyEntriesToRaw(entries: HistoryEntry[]): string {\n if (entries.length === 0) {\n return \"\";\n }\n return `${entries.map((entry) => JSON.stringify(entry)).join(\"\\n\")}\\n`;\n}\n"],"names":[],"mappings":"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","debugId":"9f6d7165-e26e-5815-9ac5-aad4ce4d3877"}
@@ -1,10 +1,11 @@
1
1
 
2
- !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]="db4086f4-7818-5cc1-a6c0-67949132208c")}catch(e){}}();
3
- import { decode as decodeToon, encode as encodeToon } from "@toon-format/toon";
4
- import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RECURRENCE_FREQUENCY_VALUES, RECURRENCE_WEEKDAY_VALUES, STATUS_VALUES, } from "../../types/index.js";
2
+ !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]="7ce34b61-0ca0-51e3-8969-50ee0dbe020b")}catch(e){}}();
3
+ import { encode as encodeToon } from "@toon-format/toon";
4
+ import { CONFIDENCE_TEXT_VALUES, ISSUE_SEVERITY_VALUES, RECURRENCE_FREQUENCY_VALUES, RECURRENCE_WEEKDAY_VALUES, STATUS_VALUES, weekdayOrderIndex, } from "../../types/index.js";
5
5
  import { coerceRuntimeFieldValue } from "../schema/runtime-field-values.js";
6
6
  import { resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, } from "../schema/runtime-schema.js";
7
7
  import { normalizeStatusInput } from "./status.js";
8
+ import { decodeToonItemContent } from "./toon-decode.js";
8
9
  import { EXIT_CODE, FRONT_MATTER_KEY_ORDER } from "../shared/constants.js";
9
10
  import { findFirstMergeConflictMarker } from "../shared/conflict-markers.js";
10
11
  import { PmCliError } from "../shared/errors.js";
@@ -42,9 +43,6 @@ function runtimeFieldRequiredForType(definition, typeName) {
42
43
  }
43
44
  return definition.required_types.map((value) => value.toLowerCase()).includes(typeName.trim().toLowerCase());
44
45
  }
45
- function weekdayOrderIndex(value) {
46
- return RECURRENCE_WEEKDAY_VALUES.indexOf(value);
47
- }
48
46
  function validationError(message) {
49
47
  throw new PmCliError(`Invalid item front matter: ${message}`, EXIT_CODE.GENERIC_FAILURE);
50
48
  }
@@ -1059,7 +1057,12 @@ function parseJsonMarkdownItemDocument(content, runtimeContext, options = {}) {
1059
1057
  function parseToonItemDocument(content, runtimeContext, options = {}) {
1060
1058
  let parsed;
1061
1059
  try {
1062
- parsed = decodeToon(content);
1060
+ // decodeToonItemContent transparently recovers documents that the upstream
1061
+ // strict decoder rejects (bracketed-token-then-colon inside a quoted value;
1062
+ // see toon-decode.ts). The recovery is lossless, so it stays silent rather
1063
+ // than emitting a per-read warning that would perpetually flip pm health
1064
+ // red for legacy files. The behavior is pinned by toon-decode.spec.ts.
1065
+ parsed = decodeToonItemContent(content).value;
1063
1066
  }
1064
1067
  catch {
1065
1068
  validationError("TOON item document is not valid TOON");
@@ -1126,4 +1129,4 @@ export function canonicalDocument(document, options = {}) {
1126
1129
  };
1127
1130
  }
1128
1131
  //# sourceMappingURL=item-format.js.map
1129
- //# debugId=db4086f4-7818-5cc1-a6c0-67949132208c
1132
+ //# debugId=7ce34b61-0ca0-51e3-8969-50ee0dbe020b