@deskwork/core 0.15.0 → 0.17.0

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 (84) hide show
  1. package/dist/doctor/rules/legacy-stage-artifact-path.d.ts +28 -0
  2. package/dist/doctor/rules/legacy-stage-artifact-path.d.ts.map +1 -0
  3. package/dist/doctor/rules/legacy-stage-artifact-path.js +232 -0
  4. package/dist/doctor/rules/legacy-stage-artifact-path.js.map +1 -0
  5. package/dist/doctor/rules/legacy-stage-artifact-path.ts +285 -0
  6. package/dist/doctor/runner.d.ts.map +1 -1
  7. package/dist/doctor/runner.js +2 -0
  8. package/dist/doctor/runner.js.map +1 -1
  9. package/dist/entry/annotations.d.ts +38 -3
  10. package/dist/entry/annotations.d.ts.map +1 -1
  11. package/dist/entry/annotations.js +164 -3
  12. package/dist/entry/annotations.js.map +1 -1
  13. package/dist/entry/approve.d.ts +21 -4
  14. package/dist/entry/approve.d.ts.map +1 -1
  15. package/dist/entry/approve.js +74 -7
  16. package/dist/entry/approve.js.map +1 -1
  17. package/dist/entry/snapshot.d.ts +51 -0
  18. package/dist/entry/snapshot.d.ts.map +1 -0
  19. package/dist/entry/snapshot.js +95 -0
  20. package/dist/entry/snapshot.js.map +1 -0
  21. package/dist/ingest-derive.d.ts +1 -1
  22. package/dist/ingest-derive.d.ts.map +1 -1
  23. package/dist/ingest-derive.js +10 -7
  24. package/dist/ingest-derive.js.map +1 -1
  25. package/dist/ingest-id.d.ts +33 -0
  26. package/dist/ingest-id.d.ts.map +1 -0
  27. package/dist/ingest-id.js +60 -0
  28. package/dist/ingest-id.js.map +1 -0
  29. package/dist/ingest.d.ts.map +1 -1
  30. package/dist/ingest.js +23 -0
  31. package/dist/ingest.js.map +1 -1
  32. package/dist/iterate/iterate.d.ts.map +1 -1
  33. package/dist/iterate/iterate.js +37 -25
  34. package/dist/iterate/iterate.js.map +1 -1
  35. package/dist/review/types.d.ts +56 -1
  36. package/dist/review/types.d.ts.map +1 -1
  37. package/dist/review/types.js.map +1 -1
  38. package/dist/schema/draft-annotation.d.ts +108 -24
  39. package/dist/schema/draft-annotation.d.ts.map +1 -1
  40. package/dist/schema/draft-annotation.js +23 -0
  41. package/dist/schema/draft-annotation.js.map +1 -1
  42. package/dist/schema/journal-events.d.ts +240 -104
  43. package/dist/schema/journal-events.d.ts.map +1 -1
  44. package/dist/scrapbook/crud-at-dir.d.ts +47 -0
  45. package/dist/scrapbook/crud-at-dir.d.ts.map +1 -0
  46. package/dist/scrapbook/crud-at-dir.js +114 -0
  47. package/dist/scrapbook/crud-at-dir.js.map +1 -0
  48. package/dist/scrapbook/crud-slug.d.ts +33 -0
  49. package/dist/scrapbook/crud-slug.d.ts.map +1 -0
  50. package/dist/scrapbook/crud-slug.js +99 -0
  51. package/dist/scrapbook/crud-slug.js.map +1 -0
  52. package/dist/scrapbook/format.d.ts +10 -0
  53. package/dist/scrapbook/format.d.ts.map +1 -0
  54. package/dist/scrapbook/format.js +41 -0
  55. package/dist/scrapbook/format.js.map +1 -0
  56. package/dist/scrapbook/listing.d.ts +94 -0
  57. package/dist/scrapbook/listing.d.ts.map +1 -0
  58. package/dist/scrapbook/listing.js +167 -0
  59. package/dist/scrapbook/listing.js.map +1 -0
  60. package/dist/scrapbook/paths.d.ts +115 -0
  61. package/dist/scrapbook/paths.d.ts.map +1 -0
  62. package/dist/scrapbook/paths.js +149 -0
  63. package/dist/scrapbook/paths.js.map +1 -0
  64. package/dist/scrapbook/read.d.ts +54 -0
  65. package/dist/scrapbook/read.d.ts.map +1 -0
  66. package/dist/scrapbook/read.js +62 -0
  67. package/dist/scrapbook/read.js.map +1 -0
  68. package/dist/scrapbook/seed.d.ts +19 -0
  69. package/dist/scrapbook/seed.d.ts.map +1 -0
  70. package/dist/scrapbook/seed.js +46 -0
  71. package/dist/scrapbook/seed.js.map +1 -0
  72. package/dist/scrapbook/types.d.ts +44 -0
  73. package/dist/scrapbook/types.d.ts.map +1 -0
  74. package/dist/scrapbook/types.js +11 -0
  75. package/dist/scrapbook/types.js.map +1 -0
  76. package/dist/scrapbook/validation.d.ts +28 -0
  77. package/dist/scrapbook/validation.d.ts.map +1 -0
  78. package/dist/scrapbook/validation.js +98 -0
  79. package/dist/scrapbook/validation.js.map +1 -0
  80. package/dist/scrapbook.d.ts +43 -277
  81. package/dist/scrapbook.d.ts.map +1 -1
  82. package/dist/scrapbook.js +42 -535
  83. package/dist/scrapbook.js.map +1 -1
  84. package/package.json +5 -1
@@ -16,19 +16,54 @@
16
16
  * entry-keyed here) intentionally do not interoperate — workflow
17
17
  * annotations are NOT visible from the entry-keyed listing, and vice
18
18
  * versa. See the `routes/api.ts` header for the split contract.
19
+ *
20
+ * Phase 35 (issue #199) — append-only edit + delete journal:
21
+ * - `edit-comment` annotations replace a prior comment's text /
22
+ * range / category / anchor in the FOLDED view.
23
+ * - `delete-comment` annotations tombstone a prior comment in the
24
+ * FOLDED view.
25
+ *
26
+ * `listEntryAnnotations` returns the FOLDED view by default. The raw
27
+ * unfolded stream (for audit views) is accessible via
28
+ * `listEntryAnnotationsRaw`.
19
29
  */
20
30
  import type { DraftAnnotation } from '../review/types.ts';
21
31
  /**
22
32
  * Append an entry-keyed annotation. The annotation should already have
23
33
  * its `id` and `createdAt` minted (use `mintEntryAnnotation`).
34
+ *
35
+ * Phase 35: validates that `edit-comment` and `delete-comment`
36
+ * annotations reference an existing `comment` annotation in the same
37
+ * entry's stream. Throws when the referent is missing — preferable to
38
+ * silently persisting an orphan that the folder will skip over.
24
39
  */
25
40
  export declare function addEntryAnnotation(projectRoot: string, entryId: string, annotation: DraftAnnotation): Promise<void>;
26
41
  /**
27
- * List every entry-keyed annotation for `entryId`, in chronological
28
- * order. Returns an empty array when there are none — never throws,
29
- * never returns null.
42
+ * List the FOLDED active-comment view of every entry-keyed annotation
43
+ * for `entryId`, in chronological order:
44
+ *
45
+ * - For each `comment`, apply every later `edit-comment` whose
46
+ * `commentId` matches (in journal order). Missing fields preserve
47
+ * the prior value.
48
+ * - Drop any `comment` for which a `delete-comment` annotation
49
+ * exists.
50
+ *
51
+ * Non-comment annotations (resolve / address / approve / reject / edit
52
+ * / orphaned edit-comment / delete-comment) pass through unchanged so
53
+ * the renderer can still see them. (Edit-comment / delete-comment that
54
+ * fail validation at write time can never reach this code — only ones
55
+ * whose target later disappeared via journal damage would surface.)
56
+ *
57
+ * Returns an empty array when there are none — never throws, never
58
+ * returns null.
30
59
  */
31
60
  export declare function listEntryAnnotations(projectRoot: string, entryId: string): Promise<DraftAnnotation[]>;
61
+ /**
62
+ * List the RAW (unfolded) entry-keyed annotation stream — every
63
+ * `comment` / `edit-comment` / `delete-comment` / etc. as recorded on
64
+ * disk, in chronological order. Useful for audit views.
65
+ */
66
+ export declare function listEntryAnnotationsRaw(projectRoot: string, entryId: string): Promise<DraftAnnotation[]>;
32
67
  /**
33
68
  * Mint a server-assigned `id` and `createdAt` onto a draft annotation.
34
69
  *
@@ -1 +1 @@
1
- {"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/entry/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AA4E1D;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,eAAe,GAC1B,OAAO,CAAC,IAAI,CAAC,CAOf;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,EAAE,CAAC,CAS5B;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,SAAS,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,WAAW,CAAC,EACnD,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAMnD"}
1
+ {"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/entry/annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAMH,OAAO,KAAK,EAEV,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAqG5B;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,eAAe,GAC1B,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,EAAE,CAAC,CAG5B;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,EAAE,CAAC,CAS5B;AA4FD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,SAAS,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,WAAW,CAAC,EACnD,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAMnD"}
@@ -16,6 +16,16 @@
16
16
  * entry-keyed here) intentionally do not interoperate — workflow
17
17
  * annotations are NOT visible from the entry-keyed listing, and vice
18
18
  * versa. See the `routes/api.ts` header for the split contract.
19
+ *
20
+ * Phase 35 (issue #199) — append-only edit + delete journal:
21
+ * - `edit-comment` annotations replace a prior comment's text /
22
+ * range / category / anchor in the FOLDED view.
23
+ * - `delete-comment` annotations tombstone a prior comment in the
24
+ * FOLDED view.
25
+ *
26
+ * `listEntryAnnotations` returns the FOLDED view by default. The raw
27
+ * unfolded stream (for audit views) is accessible via
28
+ * `listEntryAnnotationsRaw`.
19
29
  */
20
30
  import { randomUUID } from 'node:crypto';
21
31
  import { appendJournalEvent } from "../journal/append.js";
@@ -76,13 +86,52 @@ function toDraftAnnotation(stored) {
76
86
  disposition: stored.disposition,
77
87
  ...(stored.reason !== undefined ? { reason: stored.reason } : {}),
78
88
  };
89
+ case 'edit-comment':
90
+ return {
91
+ ...base,
92
+ type: 'edit-comment',
93
+ commentId: stored.commentId,
94
+ ...(stored.text !== undefined ? { text: stored.text } : {}),
95
+ ...(stored.range !== undefined
96
+ ? { range: { start: stored.range.start, end: stored.range.end } }
97
+ : {}),
98
+ ...(stored.category !== undefined ? { category: stored.category } : {}),
99
+ ...(stored.anchor !== undefined ? { anchor: stored.anchor } : {}),
100
+ };
101
+ case 'delete-comment':
102
+ return {
103
+ ...base,
104
+ type: 'delete-comment',
105
+ commentId: stored.commentId,
106
+ };
107
+ case 'archive-comment':
108
+ return {
109
+ ...base,
110
+ type: 'archive-comment',
111
+ commentId: stored.commentId,
112
+ ...(stored.priorStage !== undefined ? { priorStage: stored.priorStage } : {}),
113
+ };
79
114
  }
80
115
  }
81
116
  /**
82
117
  * Append an entry-keyed annotation. The annotation should already have
83
118
  * its `id` and `createdAt` minted (use `mintEntryAnnotation`).
119
+ *
120
+ * Phase 35: validates that `edit-comment` and `delete-comment`
121
+ * annotations reference an existing `comment` annotation in the same
122
+ * entry's stream. Throws when the referent is missing — preferable to
123
+ * silently persisting an orphan that the folder will skip over.
84
124
  */
85
125
  export async function addEntryAnnotation(projectRoot, entryId, annotation) {
126
+ if (annotation.type === 'edit-comment' ||
127
+ annotation.type === 'delete-comment' ||
128
+ annotation.type === 'archive-comment') {
129
+ const raw = await listEntryAnnotationsRaw(projectRoot, entryId);
130
+ const referent = raw.find((a) => a.type === 'comment' && a.id === annotation.commentId);
131
+ if (!referent) {
132
+ throw new Error(`addEntryAnnotation refused: ${annotation.type} references unknown commentId ${annotation.commentId}`);
133
+ }
134
+ }
86
135
  await appendJournalEvent(projectRoot, {
87
136
  kind: 'entry-annotation',
88
137
  at: annotation.createdAt,
@@ -91,11 +140,34 @@ export async function addEntryAnnotation(projectRoot, entryId, annotation) {
91
140
  });
92
141
  }
93
142
  /**
94
- * List every entry-keyed annotation for `entryId`, in chronological
95
- * order. Returns an empty array when there are none — never throws,
96
- * never returns null.
143
+ * List the FOLDED active-comment view of every entry-keyed annotation
144
+ * for `entryId`, in chronological order:
145
+ *
146
+ * - For each `comment`, apply every later `edit-comment` whose
147
+ * `commentId` matches (in journal order). Missing fields preserve
148
+ * the prior value.
149
+ * - Drop any `comment` for which a `delete-comment` annotation
150
+ * exists.
151
+ *
152
+ * Non-comment annotations (resolve / address / approve / reject / edit
153
+ * / orphaned edit-comment / delete-comment) pass through unchanged so
154
+ * the renderer can still see them. (Edit-comment / delete-comment that
155
+ * fail validation at write time can never reach this code — only ones
156
+ * whose target later disappeared via journal damage would surface.)
157
+ *
158
+ * Returns an empty array when there are none — never throws, never
159
+ * returns null.
97
160
  */
98
161
  export async function listEntryAnnotations(projectRoot, entryId) {
162
+ const raw = await listEntryAnnotationsRaw(projectRoot, entryId);
163
+ return foldAnnotations(raw);
164
+ }
165
+ /**
166
+ * List the RAW (unfolded) entry-keyed annotation stream — every
167
+ * `comment` / `edit-comment` / `delete-comment` / etc. as recorded on
168
+ * disk, in chronological order. Useful for audit views.
169
+ */
170
+ export async function listEntryAnnotationsRaw(projectRoot, entryId) {
99
171
  const events = await readJournalEvents(projectRoot, { entryId });
100
172
  const out = [];
101
173
  for (const event of events) {
@@ -105,6 +177,95 @@ export async function listEntryAnnotations(projectRoot, entryId) {
105
177
  }
106
178
  return out;
107
179
  }
180
+ /**
181
+ * Pure fold over the raw annotation stream. Single pass to gather
182
+ * edit + delete journals indexed by `commentId`, then one walk to emit
183
+ * either the (possibly-edited) comment or skip it (if deleted) — and
184
+ * pass non-comment annotations through unchanged.
185
+ *
186
+ * Chronological order is taken from the input array's order (callers
187
+ * must pass the journal-sorted stream from `readJournalEvents`).
188
+ */
189
+ function foldAnnotations(raw) {
190
+ const editsByCommentId = new Map();
191
+ const deletedCommentIds = new Set();
192
+ const archivedCommentIds = new Set();
193
+ for (const a of raw) {
194
+ if (a.type === 'edit-comment') {
195
+ const arr = editsByCommentId.get(a.commentId) ?? [];
196
+ arr.push(a);
197
+ editsByCommentId.set(a.commentId, arr);
198
+ }
199
+ else if (a.type === 'delete-comment') {
200
+ deletedCommentIds.add(a.commentId);
201
+ }
202
+ else if (a.type === 'archive-comment') {
203
+ archivedCommentIds.add(a.commentId);
204
+ }
205
+ }
206
+ const out = [];
207
+ for (const a of raw) {
208
+ if (a.type === 'edit-comment' ||
209
+ a.type === 'delete-comment' ||
210
+ a.type === 'archive-comment') {
211
+ // Fold-only events; not surfaced in the active view.
212
+ continue;
213
+ }
214
+ if (a.type === 'comment') {
215
+ if (deletedCommentIds.has(a.id))
216
+ continue;
217
+ if (archivedCommentIds.has(a.id))
218
+ continue;
219
+ const edits = editsByCommentId.get(a.id);
220
+ if (!edits || edits.length === 0) {
221
+ out.push(a);
222
+ continue;
223
+ }
224
+ out.push(applyEdits(a, edits));
225
+ continue;
226
+ }
227
+ // Drop resolve/address annotations whose target comment was archived
228
+ // — without this, the marginalia column would render an "address"
229
+ // badge or a "resolve" status against a comment that no longer
230
+ // appears in the active sidebar.
231
+ if ((a.type === 'resolve' || a.type === 'address') &&
232
+ archivedCommentIds.has(a.commentId)) {
233
+ continue;
234
+ }
235
+ out.push(a);
236
+ }
237
+ return out;
238
+ }
239
+ function applyEdits(comment, edits) {
240
+ let text = comment.text;
241
+ let range = comment.range;
242
+ let category = comment.category;
243
+ let anchor = comment.anchor;
244
+ for (const e of edits) {
245
+ if (e.type !== 'edit-comment')
246
+ continue;
247
+ if (e.text !== undefined)
248
+ text = e.text;
249
+ if (e.range !== undefined)
250
+ range = { start: e.range.start, end: e.range.end };
251
+ if (e.category !== undefined)
252
+ category = e.category;
253
+ if (e.anchor !== undefined)
254
+ anchor = e.anchor;
255
+ }
256
+ const out = {
257
+ id: comment.id,
258
+ workflowId: comment.workflowId,
259
+ createdAt: comment.createdAt,
260
+ type: 'comment',
261
+ version: comment.version,
262
+ range,
263
+ text,
264
+ ...(category !== undefined ? { category } : {}),
265
+ ...(anchor !== undefined ? { anchor } : {}),
266
+ };
267
+ return out;
268
+ }
108
269
  /**
109
270
  * Mint a server-assigned `id` and `createdAt` onto a draft annotation.
110
271
  *
@@ -1 +1 @@
1
- {"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/entry/annotations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"annotations.js","sourceRoot":"","sources":["../../src/entry/annotations.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,15 @@ interface ApproveResult {
6
6
  readonly entryId: string;
7
7
  readonly fromStage: Stage;
8
8
  readonly toStage: Stage;
9
+ /** True when an `index.md` snapshot was preserved at
10
+ * `<dir>/scrapbook/<priorStage>.md`. False when there was no
11
+ * `index.md` to snapshot (common at Ideas) or the entry has no
12
+ * `artifactPath` (legacy entries pre-doctor migration). */
13
+ readonly snapshotted: boolean;
14
+ /** Number of `comment` annotations archived as part of the transition
15
+ * (issue #200 — comments don't auto-rebase across document evolution;
16
+ * archive-on-approve sidesteps the anchor-stability problem). */
17
+ readonly archivedComments: number;
9
18
  }
10
19
  /**
11
20
  * Graduate an entry to the next linear-pipeline stage.
@@ -15,10 +24,18 @@ interface ApproveResult {
15
24
  * - Published (terminal)
16
25
  * - Blocked / Cancelled (off-pipeline; induct first)
17
26
  *
18
- * On success:
19
- * - sidecar.currentStage advances to nextStage(currentStage)
20
- * - sidecar.reviewState is cleared (stage-transition resets review)
21
- * - a stage-transition journal event is appended
27
+ * On success, in this order (so a kill-power between any two steps
28
+ * leaves a recoverable state):
29
+ * - Atomic snapshot of `<dir>/index.md` `<dir>/scrapbook/<priorStage>.md`
30
+ * (issue #222 Option B + hybrid refinement). Skipped when
31
+ * `index.md` doesn't exist on disk.
32
+ * - Archive every active `comment` annotation as the entry's prior
33
+ * stage's content goes into the freezer (issue #200 — anchor
34
+ * stability under document evolution; comments authored against
35
+ * the just-archived content cannot reliably rebase).
36
+ * - Append a `stage-transition` journal event.
37
+ * - Mutate the sidecar (currentStage advances; reviewState clears).
38
+ * - Regenerate `calendar.md` (issue #148).
22
39
  */
23
40
  export declare function approveEntryStage(projectRoot: string, opts: ApproveOptions): Promise<ApproveResult>;
24
41
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"approve.d.ts","sourceRoot":"","sources":["../../src/entry/approve.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAS,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEvD,UAAU,cAAc;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;CACzB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,aAAa,CAAC,CA0CxB"}
1
+ {"version":3,"file":"approve.d.ts","sourceRoot":"","sources":["../../src/entry/approve.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAS,KAAK,EAAE,MAAM,oBAAoB,CAAC;AASvD,UAAU,cAAc;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB;;;gEAG4D;IAC5D,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;sEAEkE;IAClE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,aAAa,CAAC,CAqExB"}
@@ -3,6 +3,8 @@ import { writeSidecar } from "../sidecar/write.js";
3
3
  import { appendJournalEvent } from "../journal/append.js";
4
4
  import { regenerateCalendar } from "../calendar/regenerate.js";
5
5
  import { nextStage } from "../schema/entry.js";
6
+ import { snapshotIndexForStage } from "./snapshot.js";
7
+ import { addEntryAnnotation, listEntryAnnotationsRaw, mintEntryAnnotation, } from "./annotations.js";
6
8
  /**
7
9
  * Graduate an entry to the next linear-pipeline stage.
8
10
  *
@@ -11,10 +13,18 @@ import { nextStage } from "../schema/entry.js";
11
13
  * - Published (terminal)
12
14
  * - Blocked / Cancelled (off-pipeline; induct first)
13
15
  *
14
- * On success:
15
- * - sidecar.currentStage advances to nextStage(currentStage)
16
- * - sidecar.reviewState is cleared (stage-transition resets review)
17
- * - a stage-transition journal event is appended
16
+ * On success, in this order (so a kill-power between any two steps
17
+ * leaves a recoverable state):
18
+ * - Atomic snapshot of `<dir>/index.md` `<dir>/scrapbook/<priorStage>.md`
19
+ * (issue #222 Option B + hybrid refinement). Skipped when
20
+ * `index.md` doesn't exist on disk.
21
+ * - Archive every active `comment` annotation as the entry's prior
22
+ * stage's content goes into the freezer (issue #200 — anchor
23
+ * stability under document evolution; comments authored against
24
+ * the just-archived content cannot reliably rebase).
25
+ * - Append a `stage-transition` journal event.
26
+ * - Mutate the sidecar (currentStage advances; reviewState clears).
27
+ * - Regenerate `calendar.md` (issue #148).
18
28
  */
19
29
  export async function approveEntryStage(projectRoot, opts) {
20
30
  const sidecar = await readSidecar(projectRoot, opts.uuid);
@@ -33,8 +43,27 @@ export async function approveEntryStage(projectRoot, opts) {
33
43
  throw new Error(`Cannot approve from stage ${from} (no successor).`);
34
44
  }
35
45
  const at = new Date().toISOString();
36
- // Strip reviewState on stage transition. exactOptionalPropertyTypes
37
- // requires us to omit the key entirely rather than set undefined.
46
+ // 1. Atomic snapshot of index.md → scrapbook/<priorStage>.md (#222).
47
+ // Throws on conflicting prior snapshot operator resolves and
48
+ // re-runs.
49
+ const snapshot = await snapshotIndexForStage(projectRoot, sidecar, from);
50
+ // 2. Archive every still-active comment annotation (#200). The
51
+ // `archive-comment` annotation is fold-only — it doesn't physically
52
+ // remove the original comment from the journal. The audit trail is
53
+ // preserved via `listEntryAnnotationsRaw`.
54
+ const raw = await listEntryAnnotationsRaw(projectRoot, sidecar.uuid);
55
+ const archived = collectActiveCommentIds(raw);
56
+ for (const commentId of archived) {
57
+ const annotation = mintEntryAnnotation({
58
+ type: 'archive-comment',
59
+ workflowId: sidecar.uuid,
60
+ commentId,
61
+ priorStage: from,
62
+ });
63
+ await addEntryAnnotation(projectRoot, sidecar.uuid, annotation);
64
+ }
65
+ // 3. Strip reviewState on stage transition. exactOptionalPropertyTypes
66
+ // requires us to omit the key entirely rather than set undefined.
38
67
  const { reviewState: _drop, ...rest } = sidecar;
39
68
  void _drop;
40
69
  const updated = {
@@ -54,6 +83,44 @@ export async function approveEntryStage(projectRoot, opts) {
54
83
  // this, the canonical visible representation of the pipeline lags
55
84
  // the SSOT until `doctor --fix=all` is run.
56
85
  await regenerateCalendar(projectRoot);
57
- return { entryId: sidecar.uuid, fromStage: from, toStage: to };
86
+ return {
87
+ entryId: sidecar.uuid,
88
+ fromStage: from,
89
+ toStage: to,
90
+ snapshotted: snapshot.snapshotted,
91
+ archivedComments: archived.length,
92
+ };
93
+ }
94
+ /**
95
+ * Walk the raw annotation stream and return the ids of every comment
96
+ * that is still active at the moment of approve — a comment is "active"
97
+ * if it has not already been deleted, archived, or implicitly resolved
98
+ * earlier in the journal.
99
+ *
100
+ * The fold is one-pass: we record delete/archive/resolve sets first,
101
+ * then the second loop emits comment ids that are not in any kill set.
102
+ * (resolve != deleted/archived — a resolved comment is still a comment;
103
+ * we only avoid double-archiving a comment that was already archived.)
104
+ */
105
+ function collectActiveCommentIds(raw) {
106
+ const deleted = new Set();
107
+ const archived = new Set();
108
+ for (const a of raw) {
109
+ if (a.type === 'delete-comment')
110
+ deleted.add(a.commentId);
111
+ else if (a.type === 'archive-comment')
112
+ archived.add(a.commentId);
113
+ }
114
+ const out = [];
115
+ for (const a of raw) {
116
+ if (a.type !== 'comment')
117
+ continue;
118
+ if (deleted.has(a.id))
119
+ continue;
120
+ if (archived.has(a.id))
121
+ continue;
122
+ out.push(a.id);
123
+ }
124
+ return out;
58
125
  }
59
126
  //# sourceMappingURL=approve.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"approve.js","sourceRoot":"","sources":["../../src/entry/approve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAa/C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,IAAoB;IAEpB,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;IAClC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,2CAA2C,CAC5E,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,kBAAkB,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEpC,oEAAoE;IACpE,kEAAkE;IAClE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAChD,KAAK,KAAK,CAAC;IACX,MAAM,OAAO,GAAU;QACrB,GAAG,IAAI;QACP,YAAY,EAAE,EAAE;QAChB,SAAS,EAAE,EAAE;KACd,CAAC;IACF,MAAM,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,kBAAkB,CAAC,WAAW,EAAE;QACpC,IAAI,EAAE,kBAAkB;QACxB,EAAE;QACF,OAAO,EAAE,OAAO,CAAC,IAAI;QACrB,IAAI;QACJ,EAAE;KACH,CAAC,CAAC;IACH,iEAAiE;IACjE,kEAAkE;IAClE,4CAA4C;IAC5C,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACtC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AACjE,CAAC"}
1
+ {"version":3,"file":"approve.js","sourceRoot":"","sources":["../../src/entry/approve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Snapshot the entry's current `index.md` to its scrapbook on stage
3
+ * approve (Issue #222 — Option B + hybrid refinement).
4
+ *
5
+ * Behavior contract (called from `approveEntryStage` BEFORE any sidecar
6
+ * mutation, so a kill-power between snapshot and sidecar-write leaves
7
+ * the snapshot durable on disk):
8
+ *
9
+ * 1. Resolve the entry's `<dir>/index.md` from `dirname(artifactPath)`.
10
+ * `dirname` is the keying field — `artifactPath` itself may already
11
+ * be `<dir>/index.md` (the common case post-T1) or some other
12
+ * per-stage file (legacy entries pre-doctor migration).
13
+ * 2. If `index.md` doesn't exist on disk: skip (no content to
14
+ * preserve; common at Ideas where only `idea.md` exists).
15
+ * 3. If `<dir>/scrapbook/<priorStage>.md` already exists with the
16
+ * same content as `index.md`: no-op (idempotent — re-approve
17
+ * after a `repair` should not error).
18
+ * 4. If `<dir>/scrapbook/<priorStage>.md` exists with DIFFERENT
19
+ * content: refuse with a clear error. The fix path is operator
20
+ * resolution (they likely hand-edited a prior snapshot); silent
21
+ * overwrite would erase prior approved history.
22
+ * 5. Atomic write: write content to `<target>.<pid>.tmp`, then
23
+ * `rename` to `<target>`. Mirrors `writeSidecar`'s pattern in
24
+ * `packages/core/src/sidecar/write.ts`.
25
+ *
26
+ * Stage-name-in-filename is lowercase for consistency with the existing
27
+ * `scrapbook/outline.md` / `scrapbook/idea.md` / `scrapbook/plan.md`
28
+ * convention. `Drafting` → `scrapbook/drafting.md`.
29
+ */
30
+ import type { Entry, Stage } from '../schema/entry.ts';
31
+ export interface SnapshotResult {
32
+ /** True when a snapshot file was written (or already matched on disk). */
33
+ readonly snapshotted: boolean;
34
+ /** Absolute path to the snapshot target (when `snapshotted`). */
35
+ readonly snapshotPath?: string;
36
+ /** Reason for skip when `snapshotted` is false. */
37
+ readonly skipReason?: 'no-index-md' | 'no-snapshot-dir';
38
+ }
39
+ /**
40
+ * Snapshot the entry's `index.md` into `scrapbook/<priorStage>.md`.
41
+ *
42
+ * `projectRoot` is the absolute project root. `entry.artifactPath` is
43
+ * resolved relative to it. `priorStage` is the stage being graduated
44
+ * AWAY FROM (the stage whose content the snapshot preserves).
45
+ *
46
+ * Throws when a prior snapshot exists with conflicting content. Returns
47
+ * a `{ snapshotted: false }` result for legitimate skips (no `index.md`
48
+ * on disk, or no `artifactPath` on the sidecar).
49
+ */
50
+ export declare function snapshotIndexForStage(projectRoot: string, entry: Entry, priorStage: Stage): Promise<SnapshotResult>;
51
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/entry/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAUH,OAAO,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,UAAU,CAAC,EAAE,aAAa,GAAG,iBAAiB,CAAC;CACzD;AAqBD;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,KAAK,GAChB,OAAO,CAAC,cAAc,CAAC,CA+CzB"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Snapshot the entry's current `index.md` to its scrapbook on stage
3
+ * approve (Issue #222 — Option B + hybrid refinement).
4
+ *
5
+ * Behavior contract (called from `approveEntryStage` BEFORE any sidecar
6
+ * mutation, so a kill-power between snapshot and sidecar-write leaves
7
+ * the snapshot durable on disk):
8
+ *
9
+ * 1. Resolve the entry's `<dir>/index.md` from `dirname(artifactPath)`.
10
+ * `dirname` is the keying field — `artifactPath` itself may already
11
+ * be `<dir>/index.md` (the common case post-T1) or some other
12
+ * per-stage file (legacy entries pre-doctor migration).
13
+ * 2. If `index.md` doesn't exist on disk: skip (no content to
14
+ * preserve; common at Ideas where only `idea.md` exists).
15
+ * 3. If `<dir>/scrapbook/<priorStage>.md` already exists with the
16
+ * same content as `index.md`: no-op (idempotent — re-approve
17
+ * after a `repair` should not error).
18
+ * 4. If `<dir>/scrapbook/<priorStage>.md` exists with DIFFERENT
19
+ * content: refuse with a clear error. The fix path is operator
20
+ * resolution (they likely hand-edited a prior snapshot); silent
21
+ * overwrite would erase prior approved history.
22
+ * 5. Atomic write: write content to `<target>.<pid>.tmp`, then
23
+ * `rename` to `<target>`. Mirrors `writeSidecar`'s pattern in
24
+ * `packages/core/src/sidecar/write.ts`.
25
+ *
26
+ * Stage-name-in-filename is lowercase for consistency with the existing
27
+ * `scrapbook/outline.md` / `scrapbook/idea.md` / `scrapbook/plan.md`
28
+ * convention. `Drafting` → `scrapbook/drafting.md`.
29
+ */
30
+ import { mkdir, readFile, rename, stat, writeFile, } from 'node:fs/promises';
31
+ import { basename, dirname, join } from 'node:path';
32
+ function fileExists(absPath) {
33
+ return stat(absPath).then((s) => s.isFile(), () => false);
34
+ }
35
+ /**
36
+ * Atomic write via tmp-file + rename (same defense as `writeSidecar`).
37
+ * The tmp filename embeds the PID so concurrent processes don't clobber
38
+ * each other's tmp state mid-rename.
39
+ */
40
+ async function atomicWrite(absPath, content) {
41
+ await mkdir(dirname(absPath), { recursive: true });
42
+ const tmpPath = `${absPath}.${process.pid}.tmp`;
43
+ await writeFile(tmpPath, content);
44
+ await rename(tmpPath, absPath);
45
+ }
46
+ /**
47
+ * Snapshot the entry's `index.md` into `scrapbook/<priorStage>.md`.
48
+ *
49
+ * `projectRoot` is the absolute project root. `entry.artifactPath` is
50
+ * resolved relative to it. `priorStage` is the stage being graduated
51
+ * AWAY FROM (the stage whose content the snapshot preserves).
52
+ *
53
+ * Throws when a prior snapshot exists with conflicting content. Returns
54
+ * a `{ snapshotted: false }` result for legitimate skips (no `index.md`
55
+ * on disk, or no `artifactPath` on the sidecar).
56
+ */
57
+ export async function snapshotIndexForStage(projectRoot, entry, priorStage) {
58
+ if (!entry.artifactPath) {
59
+ // Legacy entries without an artifactPath: no anchor for the
60
+ // snapshot dir. The doctor migration rule
61
+ // (`legacy-stage-artifact-path`) sets `artifactPath` to
62
+ // `<dir>/index.md`; once it runs, this branch becomes unreachable.
63
+ return { snapshotted: false, skipReason: 'no-snapshot-dir' };
64
+ }
65
+ const absArtifact = join(projectRoot, entry.artifactPath);
66
+ // Resolve the entry's "document directory":
67
+ // - When artifactPath ends `<dir>/<file>.md`, the doc dir is <dir>.
68
+ // - When artifactPath ends `<dir>/scrapbook/<file>.md` (legacy
69
+ // per-stage shape), the doc dir is <dir> — i.e. the scrapbook's
70
+ // parent. We strip one extra level so snapshots land in
71
+ // `<dir>/scrapbook/`, not `<dir>/scrapbook/scrapbook/`.
72
+ const dir = basename(dirname(absArtifact)) === 'scrapbook'
73
+ ? dirname(dirname(absArtifact))
74
+ : dirname(absArtifact);
75
+ const indexPath = join(dir, 'index.md');
76
+ if (!(await fileExists(indexPath))) {
77
+ return { snapshotted: false, skipReason: 'no-index-md' };
78
+ }
79
+ const content = await readFile(indexPath, 'utf8');
80
+ const targetPath = join(dir, 'scrapbook', `${priorStage.toLowerCase()}.md`);
81
+ if (await fileExists(targetPath)) {
82
+ const existing = await readFile(targetPath, 'utf8');
83
+ if (existing === content) {
84
+ // Idempotent re-approve — same content already on disk.
85
+ return { snapshotted: true, snapshotPath: targetPath };
86
+ }
87
+ throw new Error(`snapshotIndexForStage refused: ${targetPath} already exists with ` +
88
+ `different content; refusing to overwrite a prior approved ` +
89
+ `snapshot. Resolve the conflict (delete or rename the existing ` +
90
+ `snapshot file) before re-running approve.`);
91
+ }
92
+ await atomicWrite(targetPath, content);
93
+ return { snapshotted: true, snapshotPath: targetPath };
94
+ }
95
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/entry/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAYpD,SAAS,UAAU,CAAC,OAAe;IACjC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CACvB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,EACjB,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,OAAe;IACzD,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,GAAG,OAAO,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IAChD,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACjC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,WAAmB,EACnB,KAAY,EACZ,UAAiB;IAEjB,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;QACxB,4DAA4D;QAC5D,0CAA0C;QAC1C,wDAAwD;QACxD,mEAAmE;QACnE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAC/D,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC1D,4CAA4C;IAC5C,qEAAqE;IACrE,gEAAgE;IAChE,mEAAmE;IACnE,2DAA2D;IAC3D,2DAA2D;IAC3D,MAAM,GAAG,GACP,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,KAAK,WAAW;QAC5C,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC/B,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAExC,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;IAC3D,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,IAAI,CACrB,GAAG,EACH,WAAW,EACX,GAAG,UAAU,CAAC,WAAW,EAAE,KAAK,CACjC,CAAC;IAEF,IAAI,MAAM,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACpD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YACzB,wDAAwD;YACxD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;QACzD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kCAAkC,UAAU,uBAAuB;YACjE,4DAA4D;YAC5D,gEAAgE;YAChE,2CAA2C,CAC9C,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACzD,CAAC"}
@@ -14,7 +14,7 @@ import type { FrontmatterData } from './frontmatter.ts';
14
14
  * Where a derived value came from. `'frontmatter'` is reserved for
15
15
  * values that actually appear in the file's frontmatter — when a field
16
16
  * is absent and we substitute a hardcoded fallback (e.g. defaulting
17
- * state to `Ideas` when the frontmatter has no `state:` key), the
17
+ * state to `Drafting` when the frontmatter has no `state:` key), the
18
18
  * source is `'default'`. The dry-run plan surfaces this so the
19
19
  * operator can tell at a glance whether a row reflects the file or
20
20
  * was filled in by the ingest layer.
@@ -1 +1 @@
1
- {"version":3,"file":"ingest-derive.d.ts","sourceRoot":"","sources":["../src/ingest-derive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAW,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,MAAM,GACN,OAAO,GACP,OAAO,GACP,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAKD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAe/C,CAAC;AAMF,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,aAAa,GAAG,MAAM,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CAYjE;AA0HD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,eAAe,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,aAAa,GAAG,eAAe,CAAC;IAC3C,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,eAAe,CA+BpE;AAiBD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CA8BjE;AAMD,wBAAgB,WAAW,CACzB,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,MAAM,CAWR;AAED,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,MAAM,GAChB,MAAM,CAER"}
1
+ {"version":3,"file":"ingest-derive.d.ts","sourceRoot":"","sources":["../src/ingest-derive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAW,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;;;;;;;GAQG;AACH,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,MAAM,GACN,OAAO,GACP,OAAO,GACP,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAKD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAe/C,CAAC;AAMF,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,aAAa,GAAG,MAAM,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CAYjE;AA0HD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,eAAe,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,aAAa,GAAG,eAAe,CAAC;IAC3C,aAAa,CAAC,EAAE,KAAK,CAAC;IACtB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,eAAe,CAkCpE;AAiBD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,cAAc,CA8BjE;AAMD,wBAAgB,WAAW,CACzB,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,MAAM,CAWR;AAED,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,eAAe,EAC5B,SAAS,EAAE,MAAM,GAChB,MAAM,CAER"}