emdash-emit 0.1.17 → 0.1.18

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 (177) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/cli/commands/pull.d.ts +2 -10
  3. package/dist/cli/commands/pull.d.ts.map +1 -1
  4. package/dist/cli/commands/pull.js +12 -30
  5. package/dist/cli/commands/pull.js.map +1 -1
  6. package/dist/client/auth.d.ts.map +1 -1
  7. package/dist/client/auth.js +2 -1
  8. package/dist/client/auth.js.map +1 -1
  9. package/dist/client/endpoints.d.ts +19 -0
  10. package/dist/client/endpoints.d.ts.map +1 -0
  11. package/dist/client/endpoints.js +69 -0
  12. package/dist/client/endpoints.js.map +1 -0
  13. package/dist/client/http.d.ts +4 -2
  14. package/dist/client/http.d.ts.map +1 -1
  15. package/dist/client/http.js.map +1 -1
  16. package/dist/client/lock.d.ts.map +1 -1
  17. package/dist/client/lock.js +4 -3
  18. package/dist/client/lock.js.map +1 -1
  19. package/dist/client/mapper.d.ts.map +1 -1
  20. package/dist/client/mapper.js +5 -3
  21. package/dist/client/mapper.js.map +1 -1
  22. package/dist/client/media-id.d.ts +2 -0
  23. package/dist/client/media-id.d.ts.map +1 -0
  24. package/dist/client/media-id.js +23 -0
  25. package/dist/client/media-id.js.map +1 -0
  26. package/dist/client/media.d.ts +8 -7
  27. package/dist/client/media.d.ts.map +1 -1
  28. package/dist/client/media.js +58 -17
  29. package/dist/client/media.js.map +1 -1
  30. package/dist/db/baseline.d.ts +37 -0
  31. package/dist/db/baseline.d.ts.map +1 -0
  32. package/dist/db/baseline.js +74 -0
  33. package/dist/db/baseline.js.map +1 -0
  34. package/dist/db/cache.d.ts +3 -2
  35. package/dist/db/cache.d.ts.map +1 -1
  36. package/dist/db/cache.js +3 -2
  37. package/dist/db/cache.js.map +1 -1
  38. package/dist/index.d.ts +4 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +4 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/mcp/tools/sync-pull.d.ts.map +1 -1
  43. package/dist/mcp/tools/sync-pull.js +15 -2
  44. package/dist/mcp/tools/sync-pull.js.map +1 -1
  45. package/dist/presentation/article_report.d.ts +40 -0
  46. package/dist/presentation/article_report.d.ts.map +1 -0
  47. package/dist/presentation/article_report.js +80 -0
  48. package/dist/presentation/article_report.js.map +1 -0
  49. package/dist/sync/bylines.d.ts.map +1 -1
  50. package/dist/sync/bylines.js +2 -1
  51. package/dist/sync/bylines.js.map +1 -1
  52. package/dist/sync/conflicts.js +1 -1
  53. package/dist/sync/conflicts.js.map +1 -1
  54. package/dist/sync/delete.d.ts +0 -5
  55. package/dist/sync/delete.d.ts.map +1 -1
  56. package/dist/sync/delete.js +5 -11
  57. package/dist/sync/delete.js.map +1 -1
  58. package/dist/sync/diff.d.ts.map +1 -1
  59. package/dist/sync/diff.js +4 -5
  60. package/dist/sync/diff.js.map +1 -1
  61. package/dist/sync/doctor.d.ts.map +1 -1
  62. package/dist/sync/doctor.js +11 -14
  63. package/dist/sync/doctor.js.map +1 -1
  64. package/dist/sync/guards.d.ts +5 -0
  65. package/dist/sync/guards.d.ts.map +1 -1
  66. package/dist/sync/guards.js +61 -0
  67. package/dist/sync/guards.js.map +1 -1
  68. package/dist/sync/media/body_scan.d.ts.map +1 -1
  69. package/dist/sync/media/body_scan.js +9 -3
  70. package/dist/sync/media/body_scan.js.map +1 -1
  71. package/dist/sync/media/companions.d.ts +2 -9
  72. package/dist/sync/media/companions.d.ts.map +1 -1
  73. package/dist/sync/media/companions.js +5 -23
  74. package/dist/sync/media/companions.js.map +1 -1
  75. package/dist/sync/media/mirror_item.d.ts.map +1 -1
  76. package/dist/sync/media/mirror_item.js +33 -21
  77. package/dist/sync/media/mirror_item.js.map +1 -1
  78. package/dist/sync/media/pull_article.d.ts.map +1 -1
  79. package/dist/sync/media/pull_article.js +3 -2
  80. package/dist/sync/media/pull_article.js.map +1 -1
  81. package/dist/sync/media/pull_library.d.ts.map +1 -1
  82. package/dist/sync/media/pull_library.js +16 -11
  83. package/dist/sync/media/pull_library.js.map +1 -1
  84. package/dist/sync/media/remote_index.d.ts.map +1 -1
  85. package/dist/sync/media/remote_index.js +2 -1
  86. package/dist/sync/media/remote_index.js.map +1 -1
  87. package/dist/sync/media/types.d.ts +4 -3
  88. package/dist/sync/media/types.d.ts.map +1 -1
  89. package/dist/sync/media/types.js.map +1 -1
  90. package/dist/sync/preflight.d.ts +3 -2
  91. package/dist/sync/preflight.d.ts.map +1 -1
  92. package/dist/sync/preflight.js +19 -10
  93. package/dist/sync/preflight.js.map +1 -1
  94. package/dist/sync/pull.d.ts +6 -44
  95. package/dist/sync/pull.d.ts.map +1 -1
  96. package/dist/sync/pull.js +37 -145
  97. package/dist/sync/pull.js.map +1 -1
  98. package/dist/sync/push/commit.d.ts +60 -0
  99. package/dist/sync/push/commit.d.ts.map +1 -0
  100. package/dist/sync/push/commit.js +230 -0
  101. package/dist/sync/push/commit.js.map +1 -0
  102. package/dist/sync/push/guards.d.ts +33 -0
  103. package/dist/sync/push/guards.d.ts.map +1 -0
  104. package/dist/sync/push/guards.js +110 -0
  105. package/dist/sync/push/guards.js.map +1 -0
  106. package/dist/sync/push/index.d.ts +9 -0
  107. package/dist/sync/push/index.d.ts.map +1 -0
  108. package/dist/sync/push/index.js +350 -0
  109. package/dist/sync/push/index.js.map +1 -0
  110. package/dist/sync/push/media_stage.d.ts +41 -0
  111. package/dist/sync/push/media_stage.d.ts.map +1 -0
  112. package/dist/sync/push/media_stage.js +309 -0
  113. package/dist/sync/push/media_stage.js.map +1 -0
  114. package/dist/sync/push/merge_stage.d.ts +37 -0
  115. package/dist/sync/push/merge_stage.d.ts.map +1 -0
  116. package/dist/sync/push/merge_stage.js +243 -0
  117. package/dist/sync/push/merge_stage.js.map +1 -0
  118. package/dist/sync/push/preflight_stage.d.ts +6 -0
  119. package/dist/sync/push/preflight_stage.d.ts.map +1 -0
  120. package/dist/sync/push/preflight_stage.js +40 -0
  121. package/dist/sync/push/preflight_stage.js.map +1 -0
  122. package/dist/sync/push/tax_audit.d.ts +24 -0
  123. package/dist/sync/push/tax_audit.d.ts.map +1 -0
  124. package/dist/sync/push/tax_audit.js +70 -0
  125. package/dist/sync/push/tax_audit.js.map +1 -0
  126. package/dist/sync/push/taxonomy_plan.d.ts +36 -0
  127. package/dist/sync/push/taxonomy_plan.d.ts.map +1 -0
  128. package/dist/sync/push/taxonomy_plan.js +136 -0
  129. package/dist/sync/push/taxonomy_plan.js.map +1 -0
  130. package/dist/sync/push/transport.d.ts +10 -0
  131. package/dist/sync/push/transport.d.ts.map +1 -0
  132. package/dist/sync/push/transport.js +74 -0
  133. package/dist/sync/push/transport.js.map +1 -0
  134. package/dist/sync/push/types.d.ts +62 -0
  135. package/dist/sync/push/types.d.ts.map +1 -0
  136. package/dist/sync/push/types.js +23 -0
  137. package/dist/sync/push/types.js.map +1 -0
  138. package/dist/sync/push.d.ts +2 -57
  139. package/dist/sync/push.d.ts.map +1 -1
  140. package/dist/sync/push.js +2 -1184
  141. package/dist/sync/push.js.map +1 -1
  142. package/dist/sync/status.d.ts.map +1 -1
  143. package/dist/sync/status.js +5 -4
  144. package/dist/sync/status.js.map +1 -1
  145. package/dist/sync/taxonomies.d.ts.map +1 -1
  146. package/dist/sync/taxonomies.js +2 -1
  147. package/dist/sync/taxonomies.js.map +1 -1
  148. package/dist/sync/terms.d.ts.map +1 -1
  149. package/dist/sync/terms.js +2 -1
  150. package/dist/sync/terms.js.map +1 -1
  151. package/dist/sync/workspace/index.d.ts +41 -0
  152. package/dist/sync/workspace/index.d.ts.map +1 -0
  153. package/dist/sync/workspace/index.js +124 -0
  154. package/dist/sync/workspace/index.js.map +1 -0
  155. package/dist/utils/frontmatter.d.ts.map +1 -1
  156. package/dist/utils/frontmatter.js +1 -3
  157. package/dist/utils/frontmatter.js.map +1 -1
  158. package/dist/utils/media-body-refs.d.ts +24 -0
  159. package/dist/utils/media-body-refs.d.ts.map +1 -1
  160. package/dist/utils/media-body-refs.js +51 -0
  161. package/dist/utils/media-body-refs.js.map +1 -1
  162. package/dist/utils/media-companion.d.ts +13 -0
  163. package/dist/utils/media-companion.d.ts.map +1 -0
  164. package/dist/utils/media-companion.js +42 -0
  165. package/dist/utils/media-companion.js.map +1 -0
  166. package/dist/utils/media-id.d.ts +46 -0
  167. package/dist/utils/media-id.d.ts.map +1 -0
  168. package/dist/utils/media-id.js +84 -0
  169. package/dist/utils/media-id.js.map +1 -0
  170. package/dist/utils/naming.d.ts.map +1 -1
  171. package/dist/utils/naming.js +3 -2
  172. package/dist/utils/naming.js.map +1 -1
  173. package/dist/utils/ulid.d.ts +31 -0
  174. package/dist/utils/ulid.d.ts.map +1 -0
  175. package/dist/utils/ulid.js +65 -0
  176. package/dist/utils/ulid.js.map +1 -0
  177. package/package.json +1 -1
@@ -0,0 +1,230 @@
1
+ /*
2
+ * Copyright (C) 2026 SPORT-SERVICE RS★R
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import fs from 'node:fs';
23
+ import path from 'node:path';
24
+ import { ApiError } from '../../client/error.js';
25
+ import { createBaseSnapshot, readBaselineFrontmatter } from '../../db/baseline.js';
26
+ import { computeArticleRelativePath, extractDatePrefixFromPath, serializeMarkdown, } from '../../utils/frontmatter.js';
27
+ import { carriesDepthFreeMediaRef, localizeArticleMediaRefs } from '../../utils/media-body-refs.js';
28
+ import { updateConfigSyncedVersion } from '../../utils/config.js';
29
+ import { computeTaxonomyHash } from '../terms.js';
30
+ import { calculateHash } from '../workspace/index.js';
31
+ import { finalizePromotedDraftImages } from './media_stage.js';
32
+ import { transitionContentStatus } from './transport.js';
33
+ /**
34
+ * Computes sync state pending flags and conflict/taxonomy hashes symmetrically.
35
+ */
36
+ export function pendingFlagsFor(params) {
37
+ const { mode, syncState, hasTaxFailures, hasBodyConflict, isTaxonomyConflict, conflictedHash, quarantineRelPath, remoteTaxonomyHash, } = params;
38
+ if (mode === 'create') {
39
+ return {
40
+ conflictPending: 0,
41
+ bodyConflictPending: 0,
42
+ taxonomyConflictPending: 0,
43
+ conflictCopyHash: null,
44
+ conflictCopyPath: null,
45
+ conflictAt: null,
46
+ taxonomyApplyPending: hasTaxFailures ? 1 : 0,
47
+ remoteTaxonomyHash: hasTaxFailures ? null : (remoteTaxonomyHash ?? null),
48
+ };
49
+ }
50
+ if (mode === 'conflict') {
51
+ const isTax = isTaxonomyConflict ? 1 : 0;
52
+ const isBody = hasBodyConflict ? 1 : 0;
53
+ const hasAnyConflict = isTax === 1 || isBody === 1;
54
+ return {
55
+ conflictPending: 1,
56
+ bodyConflictPending: isBody,
57
+ taxonomyConflictPending: isTax,
58
+ conflictCopyHash: hasAnyConflict ? (conflictedHash ?? null) : null,
59
+ conflictCopyPath: hasAnyConflict ? (quarantineRelPath ?? null) : null,
60
+ conflictAt: hasAnyConflict && quarantineRelPath ? Math.floor(Date.now() / 1000) : null,
61
+ taxonomyApplyPending: 0,
62
+ remoteTaxonomyHash: remoteTaxonomyHash ?? null,
63
+ };
64
+ }
65
+ // update mode
66
+ if (hasTaxFailures) {
67
+ return {
68
+ conflictPending: syncState?.conflictPending ?? 0,
69
+ bodyConflictPending: syncState?.bodyConflictPending ?? 0,
70
+ taxonomyConflictPending: syncState?.taxonomyConflictPending ?? 0,
71
+ conflictCopyHash: syncState?.conflictCopyHash ?? null,
72
+ conflictCopyPath: syncState?.conflictCopyPath ?? null,
73
+ conflictAt: syncState?.conflictAt ?? null,
74
+ taxonomyApplyPending: 1,
75
+ remoteTaxonomyHash: remoteTaxonomyHash ?? null,
76
+ };
77
+ }
78
+ return {
79
+ conflictPending: 0,
80
+ bodyConflictPending: 0,
81
+ taxonomyConflictPending: 0,
82
+ conflictCopyHash: null,
83
+ conflictCopyPath: null,
84
+ conflictAt: null,
85
+ taxonomyApplyPending: 0,
86
+ remoteTaxonomyHash: remoteTaxonomyHash ?? null,
87
+ };
88
+ }
89
+ /**
90
+ * Commits article push results: promotes draft media, serializes local markdown,
91
+ * transitions status if needed, updates base snapshots and sync state, and handles file moving.
92
+ */
93
+ export async function commitPostPush(params) {
94
+ const { mode, actualId, originalId, originalRelPath, fullPath, newRev, parsed, rawContent, draftImages, uploadedByAbsPath, candidates, taxFailures, resolvedTaxonomies, options, fetchFn, warnings, syncState, baseSnapshot, createdItemCreatedAt, } = params;
95
+ const hasTaxFailures = taxFailures.length > 0;
96
+ const collection = parsed.frontmatter.collection;
97
+ const currentPrefix = extractDatePrefixFromPath(fullPath);
98
+ let dateInput = null;
99
+ if (mode === 'create') {
100
+ dateInput = parsed.frontmatter.publishedAt || currentPrefix || createdItemCreatedAt || null;
101
+ }
102
+ else {
103
+ const existingSync = options.cache.getSyncState(parsed.frontmatter.id);
104
+ dateInput =
105
+ parsed.frontmatter.publishedAt ||
106
+ currentPrefix ||
107
+ (existingSync?.lastSyncedAt ? new Date(existingSync.lastSyncedAt * 1000) : null);
108
+ }
109
+ const newRelPath = computeArticleRelativePath(parsed.frontmatter.collection, parsed.frontmatter.status, actualId, parsed.frontmatter.title || parsed.frontmatter.slug, dateInput);
110
+ const newFullPath = path.join(options.workspaceRoot, newRelPath);
111
+ const serializedCanonical = serializeMarkdown(parsed.frontmatter, parsed.body, candidates);
112
+ // [P6] Promote uploaded draft images from media/drafts/ into media/ and commit media_state.
113
+ finalizePromotedDraftImages(draftImages, uploadedByAbsPath, options, warnings);
114
+ const serializedContent = options.localMediaRefs
115
+ ? localizeArticleMediaRefs(serializedCanonical, {
116
+ workspaceRoot: options.workspaceRoot,
117
+ articleRelPath: newRelPath,
118
+ fs,
119
+ preferLegacyRef: carriesDepthFreeMediaRef(rawContent),
120
+ })
121
+ : serializedCanonical;
122
+ const newHash = calculateHash(serializedContent);
123
+ // Transition status to published / draft if requested
124
+ let finalRev = newRev;
125
+ if (mode === 'create') {
126
+ if (parsed.frontmatter.status === 'published' && options.allowPublish) {
127
+ finalRev = await transitionContentStatus(collection, actualId, 'published', newRev, parsed.frontmatter.publishedAt, options, fetchFn);
128
+ }
129
+ }
130
+ else {
131
+ const previousStatus = syncState?.status || 'draft';
132
+ if (parsed.frontmatter.status === 'published' && options.allowPublish) {
133
+ finalRev = await transitionContentStatus(collection, actualId, 'published', newRev, parsed.frontmatter.publishedAt, options, fetchFn);
134
+ }
135
+ else if (parsed.frontmatter.status === 'draft' && previousStatus === 'published') {
136
+ finalRev = await transitionContentStatus(collection, actualId, 'draft', newRev, null, options, fetchFn);
137
+ }
138
+ }
139
+ // File write & cleanup
140
+ if (mode === 'create') {
141
+ fs.mkdirSync(path.dirname(newFullPath), { recursive: true });
142
+ fs.writeFileSync(newFullPath, serializedContent, 'utf8');
143
+ if (fullPath !== newFullPath && fs.existsSync(fullPath)) {
144
+ try {
145
+ fs.unlinkSync(fullPath);
146
+ }
147
+ catch (unlinkErr) {
148
+ warnings.push(`Failed to remove provisional file at ${fullPath}: ${unlinkErr.message}.`);
149
+ }
150
+ }
151
+ }
152
+ else {
153
+ if (fullPath !== newFullPath) {
154
+ fs.mkdirSync(path.dirname(newFullPath), { recursive: true });
155
+ fs.writeFileSync(newFullPath, serializedContent, 'utf8');
156
+ if (fs.existsSync(fullPath)) {
157
+ try {
158
+ fs.unlinkSync(fullPath);
159
+ }
160
+ catch (unlinkErr) {
161
+ warnings.push(`Failed to remove old file at ${fullPath} after path transition: ${unlinkErr.message}. Please remove it manually to prevent duplicates.`);
162
+ }
163
+ }
164
+ }
165
+ else {
166
+ fs.writeFileSync(fullPath, serializedContent, 'utf8');
167
+ }
168
+ }
169
+ const baseFm = readBaselineFrontmatter(baseSnapshot);
170
+ // Update Base snapshot
171
+ const savedFrontmatter = { ...parsed.frontmatter };
172
+ if (mode === 'update' && hasTaxFailures && baseFm?.taxonomies) {
173
+ savedFrontmatter.taxonomies = { ...baseFm.taxonomies };
174
+ }
175
+ const calculatedTaxHash = computeTaxonomyHash(parsed.frontmatter.taxonomies?.categories, parsed.frontmatter.taxonomies?.tags);
176
+ const fallbackTaxHash = mode === 'update'
177
+ ? syncState?.remoteTaxonomyHash ||
178
+ (baseFm?.taxonomies
179
+ ? computeTaxonomyHash(baseFm.taxonomies.categories, baseFm.taxonomies.tags)
180
+ : null)
181
+ : null;
182
+ const targetRemoteTaxHash = hasTaxFailures ? fallbackTaxHash : calculatedTaxHash;
183
+ options.cache.saveBaseSnapshot(createBaseSnapshot({
184
+ id: actualId,
185
+ rev: finalRev,
186
+ bodyMarkdown: parsed.body,
187
+ frontmatter: savedFrontmatter,
188
+ hash: newHash,
189
+ }));
190
+ const flags = pendingFlagsFor({
191
+ mode,
192
+ syncState,
193
+ hasTaxFailures,
194
+ remoteTaxonomyHash: targetRemoteTaxHash,
195
+ });
196
+ options.cache.saveSyncState({
197
+ id: actualId,
198
+ localFilePath: newRelPath,
199
+ localHash: newHash,
200
+ remoteRev: finalRev,
201
+ status: parsed.frontmatter.status,
202
+ slug: parsed.frontmatter.slug,
203
+ lastSyncedAt: Math.floor(Date.now() / 1000),
204
+ ...flags,
205
+ });
206
+ if (mode === 'update') {
207
+ updateConfigSyncedVersion(options.workspaceRoot);
208
+ }
209
+ if (hasTaxFailures) {
210
+ throw new ApiError({
211
+ endpoint: taxFailures[0].endpoint,
212
+ code: 'TAXONOMY_UPDATE_FAILED',
213
+ status: taxFailures[0].status || 400,
214
+ message: `Failed to update ${taxFailures.map((f) => f.taxonomy).join(', ')} terms on remote: ${taxFailures.map((f) => f.error).join('; ')}`,
215
+ suggestion: 'Run "emit pull-taxonomies" to update local definitions, verify taxonomy permissions, and retry push.',
216
+ });
217
+ }
218
+ return {
219
+ success: true,
220
+ id: actualId,
221
+ rev: finalRev,
222
+ filePath: newRelPath,
223
+ ...(actualId !== originalId ? { previousId: originalId } : {}),
224
+ ...(originalRelPath !== newRelPath ? { previousFilePath: originalRelPath } : {}),
225
+ ...(Object.keys(resolvedTaxonomies).length > 0 ? { resolvedTaxonomies } : {}),
226
+ conflict: false,
227
+ warnings,
228
+ };
229
+ }
230
+ //# sourceMappingURL=commit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../../src/sync/push/commit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { SyncState } from '../../db/cache.js';
2
+ import type { PreflightError } from '../preflight.js';
3
+ import type { PushOptions } from './types.js';
4
+ export declare class PushValidationError extends Error {
5
+ errors: PreflightError[];
6
+ constructor(message: string, errors: PreflightError[]);
7
+ }
8
+ /**
9
+ * Validates that the target file is not a quarantined rescue copy.
10
+ */
11
+ export declare function assertNotQuarantinedCopy(originalRelPath: string): void;
12
+ /**
13
+ * Guard G15: deletePending protection.
14
+ */
15
+ export declare function checkDeletePendingGuard(syncState: SyncState | null | undefined, options: PushOptions, collection: string, id: string, targetFilePath: string): void;
16
+ /**
17
+ * Guard G16: taxonomy conflict pending protection.
18
+ */
19
+ export declare function checkTaxonomyConflictGuard(syncState: SyncState | null | undefined, options: PushOptions, collection: string, id: string, targetFilePath: string): void;
20
+ /**
21
+ * Guard G17: taxonomy apply pending protection.
22
+ */
23
+ export declare function checkTaxonomyApplyGuard(syncState: SyncState | null | undefined, options: PushOptions, collection: string, id: string, targetFilePath: string): void;
24
+ /**
25
+ * Declarative pipeline: evaluates pre-preflight guards (G15).
26
+ */
27
+ export declare function evaluatePrePreflightGuards(syncState: SyncState | null | undefined, options: PushOptions, collection: string, id: string, targetFilePath: string): void;
28
+ /**
29
+ * Declarative pipeline: evaluates post-preflight guards (G16, G17).
30
+ * T2-1 invariant: preflight (including G6 conflict markers) MUST precede G16.
31
+ */
32
+ export declare function evaluatePostPreflightGuards(syncState: SyncState | null | undefined, options: PushOptions, collection: string, id: string, targetFilePath: string): void;
33
+ //# sourceMappingURL=guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../../src/sync/push/guards.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,qBAAa,mBAAoB,SAAQ,KAAK;IACrC,MAAM,EAAE,cAAc,EAAE,CAAC;IAEhC,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,EAIpD;CACF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAetE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EACvC,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,MAAM,GACrB,IAAI,CAUN;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EACvC,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,MAAM,GACrB,IAAI,CAeN;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EACvC,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,MAAM,GACrB,IAAI,CAcN;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EACvC,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,MAAM,GACrB,IAAI,CAEN;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,EACvC,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,MAAM,GACrB,IAAI,CAGN"}
@@ -0,0 +1,110 @@
1
+ /*
2
+ * Copyright (C) 2026 SPORT-SERVICE RS★R
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { ApiError } from '../../client/error.js';
23
+ import { CONFLICTS_SUBDIR, isQuarantinedRelativePath } from '../workspace/index.js';
24
+ export class PushValidationError extends Error {
25
+ errors;
26
+ constructor(message, errors) {
27
+ super(message);
28
+ this.name = 'PushValidationError';
29
+ this.errors = errors;
30
+ }
31
+ }
32
+ /**
33
+ * Validates that the target file is not a quarantined rescue copy.
34
+ */
35
+ export function assertNotQuarantinedCopy(originalRelPath) {
36
+ if (isQuarantinedRelativePath(originalRelPath)) {
37
+ throw new PushValidationError(`Refusing to push a preserved rescue copy: ${originalRelPath}`, [
38
+ {
39
+ code: 'QUARANTINED_COPY_NOT_PUSHABLE',
40
+ message: `'${originalRelPath}' is a preserved rescue copy under "${CONFLICTS_SUBDIR}/". ` +
41
+ 'Rescue copies hold stale divergent content captured before a pull overwrote it; ' +
42
+ 'pushing one would overwrite the canonical article of the same ULID and recreate duplicate local files.',
43
+ suggestion: 'Merge the valuable lines into the canonical article file (posts/draft/... or posts/published/...), then delete this copy. ' +
44
+ 'To intentionally replace the remote version, copy the rescue file over the canonical path and push that canonical path instead.',
45
+ },
46
+ ]);
47
+ }
48
+ }
49
+ /**
50
+ * Guard G15: deletePending protection.
51
+ */
52
+ export function checkDeletePendingGuard(syncState, options, collection, id, targetFilePath) {
53
+ if (syncState?.deletePending === 1 && !options.revive && !options.force) {
54
+ throw new ApiError({
55
+ endpoint: `/_emdash/api/content/${collection}/${id}`,
56
+ code: 'DELETE_PENDING_ARTICLE',
57
+ status: 409,
58
+ message: `Article ${id} (${targetFilePath}) is marked as delete-pending (previous remote deletion was unconfirmed).`,
59
+ suggestion: `To intentionally revive and push this article to remote, pass --revive (or --force): "emit push ${targetFilePath} --revive"`,
60
+ });
61
+ }
62
+ }
63
+ /**
64
+ * Guard G16: taxonomy conflict pending protection.
65
+ */
66
+ export function checkTaxonomyConflictGuard(syncState, options, collection, id, targetFilePath) {
67
+ const isTaxConflictPending = syncState?.taxonomyConflictPending !== undefined
68
+ ? syncState.taxonomyConflictPending === 1
69
+ : syncState?.conflictPending === 1 && (syncState?.bodyConflictPending ?? 0) === 0;
70
+ if (isTaxConflictPending && !options.resolveTaxonomy && !options.force) {
71
+ throw new ApiError({
72
+ endpoint: `/_emdash/api/content/${collection}/${id}`,
73
+ code: 'TAXONOMY_CONFLICT_PENDING',
74
+ status: 409,
75
+ message: `Article ${id} (${targetFilePath}) has an unresolved taxonomy conflict from a previous sync.`,
76
+ suggestion: `Pass --resolve-taxonomy=union|local|remote (or --force) to explicitly resolve and confirm: "emit push ${targetFilePath} --resolve-taxonomy=union"`,
77
+ });
78
+ }
79
+ }
80
+ /**
81
+ * Guard G17: taxonomy apply pending protection.
82
+ */
83
+ export function checkTaxonomyApplyGuard(syncState, options, collection, id, targetFilePath) {
84
+ if (syncState?.taxonomyApplyPending === 1 &&
85
+ !options.allowUnappliedTaxonomies &&
86
+ !options.force) {
87
+ throw new ApiError({
88
+ endpoint: `/_emdash/api/content/${collection}/${id}`,
89
+ code: 'TAXONOMY_APPLY_PENDING',
90
+ status: 409,
91
+ message: `Article ${id} (${targetFilePath}) has an unconfirmed taxonomy assignment from a previous failed update.`,
92
+ suggestion: `Run "emit pull-taxonomies" to synchronize taxonomy definitions, then re-push (or pass --allow-unapplied-taxonomies / --force).`,
93
+ });
94
+ }
95
+ }
96
+ /**
97
+ * Declarative pipeline: evaluates pre-preflight guards (G15).
98
+ */
99
+ export function evaluatePrePreflightGuards(syncState, options, collection, id, targetFilePath) {
100
+ checkDeletePendingGuard(syncState, options, collection, id, targetFilePath);
101
+ }
102
+ /**
103
+ * Declarative pipeline: evaluates post-preflight guards (G16, G17).
104
+ * T2-1 invariant: preflight (including G6 conflict markers) MUST precede G16.
105
+ */
106
+ export function evaluatePostPreflightGuards(syncState, options, collection, id, targetFilePath) {
107
+ checkTaxonomyConflictGuard(syncState, options, collection, id, targetFilePath);
108
+ checkTaxonomyApplyGuard(syncState, options, collection, id, targetFilePath);
109
+ }
110
+ //# sourceMappingURL=guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guards.js","sourceRoot":"","sources":["../../../src/sync/push/guards.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { PushValidationError } from './guards.js';
2
+ import type { PushOptions, PushResult, ResolvedTaxonomyItem, TaxonomyResolutionStrategy } from './types.js';
3
+ export { PushValidationError, type PushOptions, type PushResult, type TaxonomyResolutionStrategy, type ResolvedTaxonomyItem, };
4
+ /**
5
+ * Pushes a local markdown article to remote EmDash with full preflight guards,
6
+ * two-tier lock lease protection, and automatic 3-way merge on conflict.
7
+ */
8
+ export declare function pushArticle(targetFilePath: string, options: PushOptions): Promise<PushResult>;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sync/push/index.ts"],"names":[],"mappings":"AAiCA,OAAO,EACL,mBAAmB,EAIpB,MAAM,aAAa,CAAC;AAQrB,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,0BAA0B,EAC3B,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,mBAAmB,EACnB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,GAC1B,CAAC;AAEF;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAwYrB"}