sysprom 1.4.0 → 1.5.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.
- package/dist/src/cli/commands/init.d.ts +1 -1
- package/dist/src/operations/index.d.ts +1 -0
- package/dist/src/operations/index.js +2 -0
- package/dist/src/operations/sync.d.ts +945 -0
- package/dist/src/operations/sync.js +123 -0
- package/dist/src/sync.d.ts +26 -0
- package/dist/src/sync.js +81 -0
- package/package.json +1 -1
|
@@ -7,9 +7,9 @@ declare const optsSchema: z.ZodObject<{
|
|
|
7
7
|
title: z.ZodOptional<z.ZodString>;
|
|
8
8
|
scope: z.ZodOptional<z.ZodString>;
|
|
9
9
|
format: z.ZodOptional<z.ZodEnum<{
|
|
10
|
-
dir: "dir";
|
|
11
10
|
json: "json";
|
|
12
11
|
md: "md";
|
|
12
|
+
dir: "dir";
|
|
13
13
|
}>>;
|
|
14
14
|
}, z.core.$strict>;
|
|
15
15
|
export declare const initCommand: CommandDef<typeof argsSchema, typeof optsSchema>;
|
|
@@ -32,6 +32,7 @@ export { graphOp } from "./graph.js";
|
|
|
32
32
|
export { renameOp } from "./rename.js";
|
|
33
33
|
export { jsonToMarkdownOp } from "./json-to-markdown.js";
|
|
34
34
|
export { markdownToJsonOp } from "./markdown-to-json.js";
|
|
35
|
+
export { syncDocumentsOp, type BidirectionalSyncResult, type ConflictStrategy, } from "./sync.js";
|
|
35
36
|
export { speckitImportOp } from "./speckit-import.js";
|
|
36
37
|
export { speckitExportOp } from "./speckit-export.js";
|
|
37
38
|
export { speckitSyncOp, type SyncResult } from "./speckit-sync.js";
|
|
@@ -38,6 +38,8 @@ export { renameOp } from "./rename.js";
|
|
|
38
38
|
// Conversion operations
|
|
39
39
|
export { jsonToMarkdownOp } from "./json-to-markdown.js";
|
|
40
40
|
export { markdownToJsonOp } from "./markdown-to-json.js";
|
|
41
|
+
// Synchronisation operations
|
|
42
|
+
export { syncDocumentsOp, } from "./sync.js";
|
|
41
43
|
// Spec-Kit interoperability operations
|
|
42
44
|
export { speckitImportOp } from "./speckit-import.js";
|
|
43
45
|
export { speckitExportOp } from "./speckit-export.js";
|
|
@@ -0,0 +1,945 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { SysProMDocument } from "../schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Conflict resolution strategy when both documents have diverged.
|
|
5
|
+
* - 'json': prefer the JSON document as source of truth
|
|
6
|
+
* - 'md': prefer the Markdown-parsed document as source of truth
|
|
7
|
+
* - 'interactive': (not yet supported) prompt user per-conflict
|
|
8
|
+
* - 'report': return summary without resolving
|
|
9
|
+
*/
|
|
10
|
+
export declare const ConflictStrategy: z.ZodEnum<{
|
|
11
|
+
json: "json";
|
|
12
|
+
md: "md";
|
|
13
|
+
interactive: "interactive";
|
|
14
|
+
report: "report";
|
|
15
|
+
}>;
|
|
16
|
+
/** Type for conflict resolution strategies. */
|
|
17
|
+
export type ConflictStrategy = z.infer<typeof ConflictStrategy>;
|
|
18
|
+
/**
|
|
19
|
+
* Result of synchronisation between two documents.
|
|
20
|
+
* @property synced The resolved document after applying sync strategy
|
|
21
|
+
* @property jsonChanged True if JSON side was newer/modified
|
|
22
|
+
* @property mdChanged True if MD side was newer/modified
|
|
23
|
+
* @property conflict True if both sides diverged
|
|
24
|
+
* @property strategy The strategy applied to resolve any conflicts
|
|
25
|
+
* @property changedNodes IDs of nodes that differ between JSON and MD
|
|
26
|
+
*/
|
|
27
|
+
export interface BidirectionalSyncResult {
|
|
28
|
+
synced: SysProMDocument;
|
|
29
|
+
jsonChanged: boolean;
|
|
30
|
+
mdChanged: boolean;
|
|
31
|
+
conflict: boolean;
|
|
32
|
+
strategy: ConflictStrategy;
|
|
33
|
+
changedNodes: string[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Synchronise two SysProM document representations.
|
|
37
|
+
* Implements bidirectional sync with configurable conflict resolution.
|
|
38
|
+
* @throws {Error} If conflict resolution is impossible (both changed with 'report' strategy)
|
|
39
|
+
*/
|
|
40
|
+
export declare const syncDocumentsOp: import("./define-operation.js").DefinedOperation<z.ZodObject<{
|
|
41
|
+
jsonDoc: z.ZodObject<{
|
|
42
|
+
$schema: z.ZodOptional<z.ZodString>;
|
|
43
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
44
|
+
title: z.ZodOptional<z.ZodString>;
|
|
45
|
+
doc_type: z.ZodOptional<z.ZodString>;
|
|
46
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
47
|
+
status: z.ZodOptional<z.ZodString>;
|
|
48
|
+
version: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodInt]>>;
|
|
49
|
+
}, z.core.$loose> & {
|
|
50
|
+
is(value: unknown): value is {
|
|
51
|
+
[x: string]: unknown;
|
|
52
|
+
title?: string | undefined;
|
|
53
|
+
doc_type?: string | undefined;
|
|
54
|
+
scope?: string | undefined;
|
|
55
|
+
status?: string | undefined;
|
|
56
|
+
version?: string | number | undefined;
|
|
57
|
+
};
|
|
58
|
+
}>;
|
|
59
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
60
|
+
id: z.ZodString;
|
|
61
|
+
type: z.ZodEnum<{
|
|
62
|
+
intent: "intent";
|
|
63
|
+
concept: "concept";
|
|
64
|
+
capability: "capability";
|
|
65
|
+
element: "element";
|
|
66
|
+
realisation: "realisation";
|
|
67
|
+
invariant: "invariant";
|
|
68
|
+
principle: "principle";
|
|
69
|
+
policy: "policy";
|
|
70
|
+
protocol: "protocol";
|
|
71
|
+
stage: "stage";
|
|
72
|
+
role: "role";
|
|
73
|
+
gate: "gate";
|
|
74
|
+
mode: "mode";
|
|
75
|
+
artefact: "artefact";
|
|
76
|
+
artefact_flow: "artefact_flow";
|
|
77
|
+
decision: "decision";
|
|
78
|
+
change: "change";
|
|
79
|
+
view: "view";
|
|
80
|
+
milestone: "milestone";
|
|
81
|
+
version: "version";
|
|
82
|
+
}> & {
|
|
83
|
+
is(value: unknown): value is "intent" | "concept" | "capability" | "element" | "realisation" | "invariant" | "principle" | "policy" | "protocol" | "stage" | "role" | "gate" | "mode" | "artefact" | "artefact_flow" | "decision" | "change" | "view" | "milestone" | "version";
|
|
84
|
+
};
|
|
85
|
+
name: z.ZodString;
|
|
86
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
87
|
+
is(value: unknown): value is string | string[];
|
|
88
|
+
}>;
|
|
89
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
90
|
+
deprecated: "deprecated";
|
|
91
|
+
proposed: "proposed";
|
|
92
|
+
accepted: "accepted";
|
|
93
|
+
active: "active";
|
|
94
|
+
implemented: "implemented";
|
|
95
|
+
adopted: "adopted";
|
|
96
|
+
defined: "defined";
|
|
97
|
+
introduced: "introduced";
|
|
98
|
+
in_progress: "in_progress";
|
|
99
|
+
complete: "complete";
|
|
100
|
+
consolidated: "consolidated";
|
|
101
|
+
experimental: "experimental";
|
|
102
|
+
retired: "retired";
|
|
103
|
+
superseded: "superseded";
|
|
104
|
+
abandoned: "abandoned";
|
|
105
|
+
deferred: "deferred";
|
|
106
|
+
}> & {
|
|
107
|
+
is(value: unknown): value is "deprecated" | "proposed" | "accepted" | "active" | "implemented" | "adopted" | "defined" | "introduced" | "in_progress" | "complete" | "consolidated" | "experimental" | "retired" | "superseded" | "abandoned" | "deferred";
|
|
108
|
+
}>;
|
|
109
|
+
lifecycle: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
|
|
110
|
+
context: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
111
|
+
is(value: unknown): value is string | string[];
|
|
112
|
+
}>;
|
|
113
|
+
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
114
|
+
id: z.ZodString;
|
|
115
|
+
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
116
|
+
is(value: unknown): value is string | string[];
|
|
117
|
+
};
|
|
118
|
+
}, z.core.$loose> & {
|
|
119
|
+
is(value: unknown): value is {
|
|
120
|
+
[x: string]: unknown;
|
|
121
|
+
id: string;
|
|
122
|
+
description: string | string[];
|
|
123
|
+
};
|
|
124
|
+
}>>;
|
|
125
|
+
selected: z.ZodOptional<z.ZodString>;
|
|
126
|
+
rationale: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
127
|
+
is(value: unknown): value is string | string[];
|
|
128
|
+
}>;
|
|
129
|
+
scope: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
130
|
+
operations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
131
|
+
type: z.ZodEnum<{
|
|
132
|
+
link: "link";
|
|
133
|
+
add: "add";
|
|
134
|
+
update: "update";
|
|
135
|
+
remove: "remove";
|
|
136
|
+
}>;
|
|
137
|
+
target: z.ZodOptional<z.ZodString>;
|
|
138
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
139
|
+
is(value: unknown): value is string | string[];
|
|
140
|
+
}>;
|
|
141
|
+
}, z.core.$loose> & {
|
|
142
|
+
is(value: unknown): value is {
|
|
143
|
+
[x: string]: unknown;
|
|
144
|
+
type: "link" | "add" | "update" | "remove";
|
|
145
|
+
target?: string | undefined;
|
|
146
|
+
description?: string | string[] | undefined;
|
|
147
|
+
};
|
|
148
|
+
}>>;
|
|
149
|
+
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
150
|
+
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
151
|
+
is(value: unknown): value is string | string[];
|
|
152
|
+
};
|
|
153
|
+
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
154
|
+
}, z.core.$loose> & {
|
|
155
|
+
is(value: unknown): value is {
|
|
156
|
+
[x: string]: unknown;
|
|
157
|
+
description: string | string[];
|
|
158
|
+
done?: boolean | undefined;
|
|
159
|
+
};
|
|
160
|
+
}>>;
|
|
161
|
+
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
162
|
+
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
163
|
+
input: z.ZodOptional<z.ZodString>;
|
|
164
|
+
output: z.ZodOptional<z.ZodString>;
|
|
165
|
+
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
166
|
+
role: z.ZodEnum<{
|
|
167
|
+
output: "output";
|
|
168
|
+
input: "input";
|
|
169
|
+
context: "context";
|
|
170
|
+
evidence: "evidence";
|
|
171
|
+
source: "source";
|
|
172
|
+
standard: "standard";
|
|
173
|
+
prior_art: "prior_art";
|
|
174
|
+
}> & {
|
|
175
|
+
is(value: unknown): value is "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
176
|
+
};
|
|
177
|
+
identifier: z.ZodString;
|
|
178
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
179
|
+
is(value: unknown): value is string | string[];
|
|
180
|
+
}>;
|
|
181
|
+
node_id: z.ZodOptional<z.ZodString>;
|
|
182
|
+
internalised: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
183
|
+
is(value: unknown): value is string | string[];
|
|
184
|
+
}>;
|
|
185
|
+
}, z.core.$strip> & {
|
|
186
|
+
is(value: unknown): value is {
|
|
187
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
188
|
+
identifier: string;
|
|
189
|
+
description?: string | string[] | undefined;
|
|
190
|
+
node_id?: string | undefined;
|
|
191
|
+
internalised?: string | string[] | undefined;
|
|
192
|
+
};
|
|
193
|
+
}>>;
|
|
194
|
+
readonly subsystem: z.ZodOptional<z.ZodObject</*elided*/ any, z.core.$strip>>;
|
|
195
|
+
}, z.core.$loose>>;
|
|
196
|
+
relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
197
|
+
from: z.ZodString;
|
|
198
|
+
to: z.ZodString;
|
|
199
|
+
type: z.ZodEnum<{
|
|
200
|
+
refines: "refines";
|
|
201
|
+
realises: "realises";
|
|
202
|
+
implements: "implements";
|
|
203
|
+
depends_on: "depends_on";
|
|
204
|
+
constrained_by: "constrained_by";
|
|
205
|
+
affects: "affects";
|
|
206
|
+
supersedes: "supersedes";
|
|
207
|
+
must_preserve: "must_preserve";
|
|
208
|
+
performs: "performs";
|
|
209
|
+
part_of: "part_of";
|
|
210
|
+
precedes: "precedes";
|
|
211
|
+
must_follow: "must_follow";
|
|
212
|
+
blocks: "blocks";
|
|
213
|
+
routes_to: "routes_to";
|
|
214
|
+
governed_by: "governed_by";
|
|
215
|
+
modifies: "modifies";
|
|
216
|
+
triggered_by: "triggered_by";
|
|
217
|
+
applies_to: "applies_to";
|
|
218
|
+
produces: "produces";
|
|
219
|
+
consumes: "consumes";
|
|
220
|
+
transforms_into: "transforms_into";
|
|
221
|
+
selects: "selects";
|
|
222
|
+
requires: "requires";
|
|
223
|
+
disables: "disables";
|
|
224
|
+
}> & {
|
|
225
|
+
is(value: unknown): value is "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
226
|
+
};
|
|
227
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
228
|
+
is(value: unknown): value is string | string[];
|
|
229
|
+
}>;
|
|
230
|
+
}, z.core.$loose> & {
|
|
231
|
+
is(value: unknown): value is {
|
|
232
|
+
[x: string]: unknown;
|
|
233
|
+
from: string;
|
|
234
|
+
to: string;
|
|
235
|
+
type: "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
236
|
+
description?: string | string[] | undefined;
|
|
237
|
+
};
|
|
238
|
+
}>>;
|
|
239
|
+
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
240
|
+
role: z.ZodEnum<{
|
|
241
|
+
output: "output";
|
|
242
|
+
input: "input";
|
|
243
|
+
context: "context";
|
|
244
|
+
evidence: "evidence";
|
|
245
|
+
source: "source";
|
|
246
|
+
standard: "standard";
|
|
247
|
+
prior_art: "prior_art";
|
|
248
|
+
}> & {
|
|
249
|
+
is(value: unknown): value is "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
250
|
+
};
|
|
251
|
+
identifier: z.ZodString;
|
|
252
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
253
|
+
is(value: unknown): value is string | string[];
|
|
254
|
+
}>;
|
|
255
|
+
node_id: z.ZodOptional<z.ZodString>;
|
|
256
|
+
internalised: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
257
|
+
is(value: unknown): value is string | string[];
|
|
258
|
+
}>;
|
|
259
|
+
}, z.core.$strip> & {
|
|
260
|
+
is(value: unknown): value is {
|
|
261
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
262
|
+
identifier: string;
|
|
263
|
+
description?: string | string[] | undefined;
|
|
264
|
+
node_id?: string | undefined;
|
|
265
|
+
internalised?: string | string[] | undefined;
|
|
266
|
+
};
|
|
267
|
+
}>>;
|
|
268
|
+
}, z.core.$strip> & {
|
|
269
|
+
is(value: unknown): value is {
|
|
270
|
+
nodes: {
|
|
271
|
+
[x: string]: unknown;
|
|
272
|
+
id: string;
|
|
273
|
+
type: "intent" | "concept" | "capability" | "element" | "realisation" | "invariant" | "principle" | "policy" | "protocol" | "stage" | "role" | "gate" | "mode" | "artefact" | "artefact_flow" | "decision" | "change" | "view" | "milestone" | "version";
|
|
274
|
+
name: string;
|
|
275
|
+
description?: string | string[] | undefined;
|
|
276
|
+
status?: "deprecated" | "proposed" | "accepted" | "active" | "implemented" | "adopted" | "defined" | "introduced" | "in_progress" | "complete" | "consolidated" | "experimental" | "retired" | "superseded" | "abandoned" | "deferred" | undefined;
|
|
277
|
+
lifecycle?: Record<string, string | boolean> | undefined;
|
|
278
|
+
context?: string | string[] | undefined;
|
|
279
|
+
options?: {
|
|
280
|
+
[x: string]: unknown;
|
|
281
|
+
id: string;
|
|
282
|
+
description: string | string[];
|
|
283
|
+
}[] | undefined;
|
|
284
|
+
selected?: string | undefined;
|
|
285
|
+
rationale?: string | string[] | undefined;
|
|
286
|
+
scope?: string[] | undefined;
|
|
287
|
+
operations?: {
|
|
288
|
+
[x: string]: unknown;
|
|
289
|
+
type: "link" | "add" | "update" | "remove";
|
|
290
|
+
target?: string | undefined;
|
|
291
|
+
description?: string | string[] | undefined;
|
|
292
|
+
}[] | undefined;
|
|
293
|
+
plan?: {
|
|
294
|
+
[x: string]: unknown;
|
|
295
|
+
description: string | string[];
|
|
296
|
+
done?: boolean | undefined;
|
|
297
|
+
}[] | undefined;
|
|
298
|
+
propagation?: Record<string, boolean> | undefined;
|
|
299
|
+
includes?: string[] | undefined;
|
|
300
|
+
input?: string | undefined;
|
|
301
|
+
output?: string | undefined;
|
|
302
|
+
external_references?: {
|
|
303
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
304
|
+
identifier: string;
|
|
305
|
+
description?: string | string[] | undefined;
|
|
306
|
+
node_id?: string | undefined;
|
|
307
|
+
internalised?: string | string[] | undefined;
|
|
308
|
+
}[] | undefined;
|
|
309
|
+
subsystem?: /*elided*/ any | undefined;
|
|
310
|
+
}[];
|
|
311
|
+
$schema?: string | undefined;
|
|
312
|
+
metadata?: {
|
|
313
|
+
[x: string]: unknown;
|
|
314
|
+
title?: string | undefined;
|
|
315
|
+
doc_type?: string | undefined;
|
|
316
|
+
scope?: string | undefined;
|
|
317
|
+
status?: string | undefined;
|
|
318
|
+
version?: string | number | undefined;
|
|
319
|
+
} | undefined;
|
|
320
|
+
relationships?: {
|
|
321
|
+
[x: string]: unknown;
|
|
322
|
+
from: string;
|
|
323
|
+
to: string;
|
|
324
|
+
type: "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
325
|
+
description?: string | string[] | undefined;
|
|
326
|
+
}[] | undefined;
|
|
327
|
+
external_references?: {
|
|
328
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
329
|
+
identifier: string;
|
|
330
|
+
description?: string | string[] | undefined;
|
|
331
|
+
node_id?: string | undefined;
|
|
332
|
+
internalised?: string | string[] | undefined;
|
|
333
|
+
}[] | undefined;
|
|
334
|
+
};
|
|
335
|
+
};
|
|
336
|
+
mdDoc: z.ZodObject<{
|
|
337
|
+
$schema: z.ZodOptional<z.ZodString>;
|
|
338
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
339
|
+
title: z.ZodOptional<z.ZodString>;
|
|
340
|
+
doc_type: z.ZodOptional<z.ZodString>;
|
|
341
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
342
|
+
status: z.ZodOptional<z.ZodString>;
|
|
343
|
+
version: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodInt]>>;
|
|
344
|
+
}, z.core.$loose> & {
|
|
345
|
+
is(value: unknown): value is {
|
|
346
|
+
[x: string]: unknown;
|
|
347
|
+
title?: string | undefined;
|
|
348
|
+
doc_type?: string | undefined;
|
|
349
|
+
scope?: string | undefined;
|
|
350
|
+
status?: string | undefined;
|
|
351
|
+
version?: string | number | undefined;
|
|
352
|
+
};
|
|
353
|
+
}>;
|
|
354
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
355
|
+
id: z.ZodString;
|
|
356
|
+
type: z.ZodEnum<{
|
|
357
|
+
intent: "intent";
|
|
358
|
+
concept: "concept";
|
|
359
|
+
capability: "capability";
|
|
360
|
+
element: "element";
|
|
361
|
+
realisation: "realisation";
|
|
362
|
+
invariant: "invariant";
|
|
363
|
+
principle: "principle";
|
|
364
|
+
policy: "policy";
|
|
365
|
+
protocol: "protocol";
|
|
366
|
+
stage: "stage";
|
|
367
|
+
role: "role";
|
|
368
|
+
gate: "gate";
|
|
369
|
+
mode: "mode";
|
|
370
|
+
artefact: "artefact";
|
|
371
|
+
artefact_flow: "artefact_flow";
|
|
372
|
+
decision: "decision";
|
|
373
|
+
change: "change";
|
|
374
|
+
view: "view";
|
|
375
|
+
milestone: "milestone";
|
|
376
|
+
version: "version";
|
|
377
|
+
}> & {
|
|
378
|
+
is(value: unknown): value is "intent" | "concept" | "capability" | "element" | "realisation" | "invariant" | "principle" | "policy" | "protocol" | "stage" | "role" | "gate" | "mode" | "artefact" | "artefact_flow" | "decision" | "change" | "view" | "milestone" | "version";
|
|
379
|
+
};
|
|
380
|
+
name: z.ZodString;
|
|
381
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
382
|
+
is(value: unknown): value is string | string[];
|
|
383
|
+
}>;
|
|
384
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
385
|
+
deprecated: "deprecated";
|
|
386
|
+
proposed: "proposed";
|
|
387
|
+
accepted: "accepted";
|
|
388
|
+
active: "active";
|
|
389
|
+
implemented: "implemented";
|
|
390
|
+
adopted: "adopted";
|
|
391
|
+
defined: "defined";
|
|
392
|
+
introduced: "introduced";
|
|
393
|
+
in_progress: "in_progress";
|
|
394
|
+
complete: "complete";
|
|
395
|
+
consolidated: "consolidated";
|
|
396
|
+
experimental: "experimental";
|
|
397
|
+
retired: "retired";
|
|
398
|
+
superseded: "superseded";
|
|
399
|
+
abandoned: "abandoned";
|
|
400
|
+
deferred: "deferred";
|
|
401
|
+
}> & {
|
|
402
|
+
is(value: unknown): value is "deprecated" | "proposed" | "accepted" | "active" | "implemented" | "adopted" | "defined" | "introduced" | "in_progress" | "complete" | "consolidated" | "experimental" | "retired" | "superseded" | "abandoned" | "deferred";
|
|
403
|
+
}>;
|
|
404
|
+
lifecycle: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
|
|
405
|
+
context: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
406
|
+
is(value: unknown): value is string | string[];
|
|
407
|
+
}>;
|
|
408
|
+
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
409
|
+
id: z.ZodString;
|
|
410
|
+
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
411
|
+
is(value: unknown): value is string | string[];
|
|
412
|
+
};
|
|
413
|
+
}, z.core.$loose> & {
|
|
414
|
+
is(value: unknown): value is {
|
|
415
|
+
[x: string]: unknown;
|
|
416
|
+
id: string;
|
|
417
|
+
description: string | string[];
|
|
418
|
+
};
|
|
419
|
+
}>>;
|
|
420
|
+
selected: z.ZodOptional<z.ZodString>;
|
|
421
|
+
rationale: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
422
|
+
is(value: unknown): value is string | string[];
|
|
423
|
+
}>;
|
|
424
|
+
scope: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
425
|
+
operations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
426
|
+
type: z.ZodEnum<{
|
|
427
|
+
link: "link";
|
|
428
|
+
add: "add";
|
|
429
|
+
update: "update";
|
|
430
|
+
remove: "remove";
|
|
431
|
+
}>;
|
|
432
|
+
target: z.ZodOptional<z.ZodString>;
|
|
433
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
434
|
+
is(value: unknown): value is string | string[];
|
|
435
|
+
}>;
|
|
436
|
+
}, z.core.$loose> & {
|
|
437
|
+
is(value: unknown): value is {
|
|
438
|
+
[x: string]: unknown;
|
|
439
|
+
type: "link" | "add" | "update" | "remove";
|
|
440
|
+
target?: string | undefined;
|
|
441
|
+
description?: string | string[] | undefined;
|
|
442
|
+
};
|
|
443
|
+
}>>;
|
|
444
|
+
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
445
|
+
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
446
|
+
is(value: unknown): value is string | string[];
|
|
447
|
+
};
|
|
448
|
+
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
449
|
+
}, z.core.$loose> & {
|
|
450
|
+
is(value: unknown): value is {
|
|
451
|
+
[x: string]: unknown;
|
|
452
|
+
description: string | string[];
|
|
453
|
+
done?: boolean | undefined;
|
|
454
|
+
};
|
|
455
|
+
}>>;
|
|
456
|
+
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
457
|
+
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
458
|
+
input: z.ZodOptional<z.ZodString>;
|
|
459
|
+
output: z.ZodOptional<z.ZodString>;
|
|
460
|
+
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
461
|
+
role: z.ZodEnum<{
|
|
462
|
+
output: "output";
|
|
463
|
+
input: "input";
|
|
464
|
+
context: "context";
|
|
465
|
+
evidence: "evidence";
|
|
466
|
+
source: "source";
|
|
467
|
+
standard: "standard";
|
|
468
|
+
prior_art: "prior_art";
|
|
469
|
+
}> & {
|
|
470
|
+
is(value: unknown): value is "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
471
|
+
};
|
|
472
|
+
identifier: z.ZodString;
|
|
473
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
474
|
+
is(value: unknown): value is string | string[];
|
|
475
|
+
}>;
|
|
476
|
+
node_id: z.ZodOptional<z.ZodString>;
|
|
477
|
+
internalised: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
478
|
+
is(value: unknown): value is string | string[];
|
|
479
|
+
}>;
|
|
480
|
+
}, z.core.$strip> & {
|
|
481
|
+
is(value: unknown): value is {
|
|
482
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
483
|
+
identifier: string;
|
|
484
|
+
description?: string | string[] | undefined;
|
|
485
|
+
node_id?: string | undefined;
|
|
486
|
+
internalised?: string | string[] | undefined;
|
|
487
|
+
};
|
|
488
|
+
}>>;
|
|
489
|
+
readonly subsystem: z.ZodOptional<z.ZodObject</*elided*/ any, z.core.$strip>>;
|
|
490
|
+
}, z.core.$loose>>;
|
|
491
|
+
relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
492
|
+
from: z.ZodString;
|
|
493
|
+
to: z.ZodString;
|
|
494
|
+
type: z.ZodEnum<{
|
|
495
|
+
refines: "refines";
|
|
496
|
+
realises: "realises";
|
|
497
|
+
implements: "implements";
|
|
498
|
+
depends_on: "depends_on";
|
|
499
|
+
constrained_by: "constrained_by";
|
|
500
|
+
affects: "affects";
|
|
501
|
+
supersedes: "supersedes";
|
|
502
|
+
must_preserve: "must_preserve";
|
|
503
|
+
performs: "performs";
|
|
504
|
+
part_of: "part_of";
|
|
505
|
+
precedes: "precedes";
|
|
506
|
+
must_follow: "must_follow";
|
|
507
|
+
blocks: "blocks";
|
|
508
|
+
routes_to: "routes_to";
|
|
509
|
+
governed_by: "governed_by";
|
|
510
|
+
modifies: "modifies";
|
|
511
|
+
triggered_by: "triggered_by";
|
|
512
|
+
applies_to: "applies_to";
|
|
513
|
+
produces: "produces";
|
|
514
|
+
consumes: "consumes";
|
|
515
|
+
transforms_into: "transforms_into";
|
|
516
|
+
selects: "selects";
|
|
517
|
+
requires: "requires";
|
|
518
|
+
disables: "disables";
|
|
519
|
+
}> & {
|
|
520
|
+
is(value: unknown): value is "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
521
|
+
};
|
|
522
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
523
|
+
is(value: unknown): value is string | string[];
|
|
524
|
+
}>;
|
|
525
|
+
}, z.core.$loose> & {
|
|
526
|
+
is(value: unknown): value is {
|
|
527
|
+
[x: string]: unknown;
|
|
528
|
+
from: string;
|
|
529
|
+
to: string;
|
|
530
|
+
type: "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
531
|
+
description?: string | string[] | undefined;
|
|
532
|
+
};
|
|
533
|
+
}>>;
|
|
534
|
+
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
535
|
+
role: z.ZodEnum<{
|
|
536
|
+
output: "output";
|
|
537
|
+
input: "input";
|
|
538
|
+
context: "context";
|
|
539
|
+
evidence: "evidence";
|
|
540
|
+
source: "source";
|
|
541
|
+
standard: "standard";
|
|
542
|
+
prior_art: "prior_art";
|
|
543
|
+
}> & {
|
|
544
|
+
is(value: unknown): value is "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
545
|
+
};
|
|
546
|
+
identifier: z.ZodString;
|
|
547
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
548
|
+
is(value: unknown): value is string | string[];
|
|
549
|
+
}>;
|
|
550
|
+
node_id: z.ZodOptional<z.ZodString>;
|
|
551
|
+
internalised: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
552
|
+
is(value: unknown): value is string | string[];
|
|
553
|
+
}>;
|
|
554
|
+
}, z.core.$strip> & {
|
|
555
|
+
is(value: unknown): value is {
|
|
556
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
557
|
+
identifier: string;
|
|
558
|
+
description?: string | string[] | undefined;
|
|
559
|
+
node_id?: string | undefined;
|
|
560
|
+
internalised?: string | string[] | undefined;
|
|
561
|
+
};
|
|
562
|
+
}>>;
|
|
563
|
+
}, z.core.$strip> & {
|
|
564
|
+
is(value: unknown): value is {
|
|
565
|
+
nodes: {
|
|
566
|
+
[x: string]: unknown;
|
|
567
|
+
id: string;
|
|
568
|
+
type: "intent" | "concept" | "capability" | "element" | "realisation" | "invariant" | "principle" | "policy" | "protocol" | "stage" | "role" | "gate" | "mode" | "artefact" | "artefact_flow" | "decision" | "change" | "view" | "milestone" | "version";
|
|
569
|
+
name: string;
|
|
570
|
+
description?: string | string[] | undefined;
|
|
571
|
+
status?: "deprecated" | "proposed" | "accepted" | "active" | "implemented" | "adopted" | "defined" | "introduced" | "in_progress" | "complete" | "consolidated" | "experimental" | "retired" | "superseded" | "abandoned" | "deferred" | undefined;
|
|
572
|
+
lifecycle?: Record<string, string | boolean> | undefined;
|
|
573
|
+
context?: string | string[] | undefined;
|
|
574
|
+
options?: {
|
|
575
|
+
[x: string]: unknown;
|
|
576
|
+
id: string;
|
|
577
|
+
description: string | string[];
|
|
578
|
+
}[] | undefined;
|
|
579
|
+
selected?: string | undefined;
|
|
580
|
+
rationale?: string | string[] | undefined;
|
|
581
|
+
scope?: string[] | undefined;
|
|
582
|
+
operations?: {
|
|
583
|
+
[x: string]: unknown;
|
|
584
|
+
type: "link" | "add" | "update" | "remove";
|
|
585
|
+
target?: string | undefined;
|
|
586
|
+
description?: string | string[] | undefined;
|
|
587
|
+
}[] | undefined;
|
|
588
|
+
plan?: {
|
|
589
|
+
[x: string]: unknown;
|
|
590
|
+
description: string | string[];
|
|
591
|
+
done?: boolean | undefined;
|
|
592
|
+
}[] | undefined;
|
|
593
|
+
propagation?: Record<string, boolean> | undefined;
|
|
594
|
+
includes?: string[] | undefined;
|
|
595
|
+
input?: string | undefined;
|
|
596
|
+
output?: string | undefined;
|
|
597
|
+
external_references?: {
|
|
598
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
599
|
+
identifier: string;
|
|
600
|
+
description?: string | string[] | undefined;
|
|
601
|
+
node_id?: string | undefined;
|
|
602
|
+
internalised?: string | string[] | undefined;
|
|
603
|
+
}[] | undefined;
|
|
604
|
+
subsystem?: /*elided*/ any | undefined;
|
|
605
|
+
}[];
|
|
606
|
+
$schema?: string | undefined;
|
|
607
|
+
metadata?: {
|
|
608
|
+
[x: string]: unknown;
|
|
609
|
+
title?: string | undefined;
|
|
610
|
+
doc_type?: string | undefined;
|
|
611
|
+
scope?: string | undefined;
|
|
612
|
+
status?: string | undefined;
|
|
613
|
+
version?: string | number | undefined;
|
|
614
|
+
} | undefined;
|
|
615
|
+
relationships?: {
|
|
616
|
+
[x: string]: unknown;
|
|
617
|
+
from: string;
|
|
618
|
+
to: string;
|
|
619
|
+
type: "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
620
|
+
description?: string | string[] | undefined;
|
|
621
|
+
}[] | undefined;
|
|
622
|
+
external_references?: {
|
|
623
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
624
|
+
identifier: string;
|
|
625
|
+
description?: string | string[] | undefined;
|
|
626
|
+
node_id?: string | undefined;
|
|
627
|
+
internalised?: string | string[] | undefined;
|
|
628
|
+
}[] | undefined;
|
|
629
|
+
};
|
|
630
|
+
};
|
|
631
|
+
jsonChanged: z.ZodBoolean;
|
|
632
|
+
mdChanged: z.ZodBoolean;
|
|
633
|
+
strategy: z.ZodOptional<z.ZodEnum<{
|
|
634
|
+
json: "json";
|
|
635
|
+
md: "md";
|
|
636
|
+
interactive: "interactive";
|
|
637
|
+
report: "report";
|
|
638
|
+
}>>;
|
|
639
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
640
|
+
synced: z.ZodObject<{
|
|
641
|
+
$schema: z.ZodOptional<z.ZodString>;
|
|
642
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
643
|
+
title: z.ZodOptional<z.ZodString>;
|
|
644
|
+
doc_type: z.ZodOptional<z.ZodString>;
|
|
645
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
646
|
+
status: z.ZodOptional<z.ZodString>;
|
|
647
|
+
version: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodInt]>>;
|
|
648
|
+
}, z.core.$loose> & {
|
|
649
|
+
is(value: unknown): value is {
|
|
650
|
+
[x: string]: unknown;
|
|
651
|
+
title?: string | undefined;
|
|
652
|
+
doc_type?: string | undefined;
|
|
653
|
+
scope?: string | undefined;
|
|
654
|
+
status?: string | undefined;
|
|
655
|
+
version?: string | number | undefined;
|
|
656
|
+
};
|
|
657
|
+
}>;
|
|
658
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
659
|
+
id: z.ZodString;
|
|
660
|
+
type: z.ZodEnum<{
|
|
661
|
+
intent: "intent";
|
|
662
|
+
concept: "concept";
|
|
663
|
+
capability: "capability";
|
|
664
|
+
element: "element";
|
|
665
|
+
realisation: "realisation";
|
|
666
|
+
invariant: "invariant";
|
|
667
|
+
principle: "principle";
|
|
668
|
+
policy: "policy";
|
|
669
|
+
protocol: "protocol";
|
|
670
|
+
stage: "stage";
|
|
671
|
+
role: "role";
|
|
672
|
+
gate: "gate";
|
|
673
|
+
mode: "mode";
|
|
674
|
+
artefact: "artefact";
|
|
675
|
+
artefact_flow: "artefact_flow";
|
|
676
|
+
decision: "decision";
|
|
677
|
+
change: "change";
|
|
678
|
+
view: "view";
|
|
679
|
+
milestone: "milestone";
|
|
680
|
+
version: "version";
|
|
681
|
+
}> & {
|
|
682
|
+
is(value: unknown): value is "intent" | "concept" | "capability" | "element" | "realisation" | "invariant" | "principle" | "policy" | "protocol" | "stage" | "role" | "gate" | "mode" | "artefact" | "artefact_flow" | "decision" | "change" | "view" | "milestone" | "version";
|
|
683
|
+
};
|
|
684
|
+
name: z.ZodString;
|
|
685
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
686
|
+
is(value: unknown): value is string | string[];
|
|
687
|
+
}>;
|
|
688
|
+
status: z.ZodOptional<z.ZodEnum<{
|
|
689
|
+
deprecated: "deprecated";
|
|
690
|
+
proposed: "proposed";
|
|
691
|
+
accepted: "accepted";
|
|
692
|
+
active: "active";
|
|
693
|
+
implemented: "implemented";
|
|
694
|
+
adopted: "adopted";
|
|
695
|
+
defined: "defined";
|
|
696
|
+
introduced: "introduced";
|
|
697
|
+
in_progress: "in_progress";
|
|
698
|
+
complete: "complete";
|
|
699
|
+
consolidated: "consolidated";
|
|
700
|
+
experimental: "experimental";
|
|
701
|
+
retired: "retired";
|
|
702
|
+
superseded: "superseded";
|
|
703
|
+
abandoned: "abandoned";
|
|
704
|
+
deferred: "deferred";
|
|
705
|
+
}> & {
|
|
706
|
+
is(value: unknown): value is "deprecated" | "proposed" | "accepted" | "active" | "implemented" | "adopted" | "defined" | "introduced" | "in_progress" | "complete" | "consolidated" | "experimental" | "retired" | "superseded" | "abandoned" | "deferred";
|
|
707
|
+
}>;
|
|
708
|
+
lifecycle: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
|
|
709
|
+
context: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
710
|
+
is(value: unknown): value is string | string[];
|
|
711
|
+
}>;
|
|
712
|
+
options: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
713
|
+
id: z.ZodString;
|
|
714
|
+
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
715
|
+
is(value: unknown): value is string | string[];
|
|
716
|
+
};
|
|
717
|
+
}, z.core.$loose> & {
|
|
718
|
+
is(value: unknown): value is {
|
|
719
|
+
[x: string]: unknown;
|
|
720
|
+
id: string;
|
|
721
|
+
description: string | string[];
|
|
722
|
+
};
|
|
723
|
+
}>>;
|
|
724
|
+
selected: z.ZodOptional<z.ZodString>;
|
|
725
|
+
rationale: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
726
|
+
is(value: unknown): value is string | string[];
|
|
727
|
+
}>;
|
|
728
|
+
scope: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
729
|
+
operations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
730
|
+
type: z.ZodEnum<{
|
|
731
|
+
link: "link";
|
|
732
|
+
add: "add";
|
|
733
|
+
update: "update";
|
|
734
|
+
remove: "remove";
|
|
735
|
+
}>;
|
|
736
|
+
target: z.ZodOptional<z.ZodString>;
|
|
737
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
738
|
+
is(value: unknown): value is string | string[];
|
|
739
|
+
}>;
|
|
740
|
+
}, z.core.$loose> & {
|
|
741
|
+
is(value: unknown): value is {
|
|
742
|
+
[x: string]: unknown;
|
|
743
|
+
type: "link" | "add" | "update" | "remove";
|
|
744
|
+
target?: string | undefined;
|
|
745
|
+
description?: string | string[] | undefined;
|
|
746
|
+
};
|
|
747
|
+
}>>;
|
|
748
|
+
plan: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
749
|
+
description: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
750
|
+
is(value: unknown): value is string | string[];
|
|
751
|
+
};
|
|
752
|
+
done: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
753
|
+
}, z.core.$loose> & {
|
|
754
|
+
is(value: unknown): value is {
|
|
755
|
+
[x: string]: unknown;
|
|
756
|
+
description: string | string[];
|
|
757
|
+
done?: boolean | undefined;
|
|
758
|
+
};
|
|
759
|
+
}>>;
|
|
760
|
+
propagation: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
761
|
+
includes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
762
|
+
input: z.ZodOptional<z.ZodString>;
|
|
763
|
+
output: z.ZodOptional<z.ZodString>;
|
|
764
|
+
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
765
|
+
role: z.ZodEnum<{
|
|
766
|
+
output: "output";
|
|
767
|
+
input: "input";
|
|
768
|
+
context: "context";
|
|
769
|
+
evidence: "evidence";
|
|
770
|
+
source: "source";
|
|
771
|
+
standard: "standard";
|
|
772
|
+
prior_art: "prior_art";
|
|
773
|
+
}> & {
|
|
774
|
+
is(value: unknown): value is "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
775
|
+
};
|
|
776
|
+
identifier: z.ZodString;
|
|
777
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
778
|
+
is(value: unknown): value is string | string[];
|
|
779
|
+
}>;
|
|
780
|
+
node_id: z.ZodOptional<z.ZodString>;
|
|
781
|
+
internalised: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
782
|
+
is(value: unknown): value is string | string[];
|
|
783
|
+
}>;
|
|
784
|
+
}, z.core.$strip> & {
|
|
785
|
+
is(value: unknown): value is {
|
|
786
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
787
|
+
identifier: string;
|
|
788
|
+
description?: string | string[] | undefined;
|
|
789
|
+
node_id?: string | undefined;
|
|
790
|
+
internalised?: string | string[] | undefined;
|
|
791
|
+
};
|
|
792
|
+
}>>;
|
|
793
|
+
readonly subsystem: z.ZodOptional<z.ZodObject</*elided*/ any, z.core.$strip>>;
|
|
794
|
+
}, z.core.$loose>>;
|
|
795
|
+
relationships: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
796
|
+
from: z.ZodString;
|
|
797
|
+
to: z.ZodString;
|
|
798
|
+
type: z.ZodEnum<{
|
|
799
|
+
refines: "refines";
|
|
800
|
+
realises: "realises";
|
|
801
|
+
implements: "implements";
|
|
802
|
+
depends_on: "depends_on";
|
|
803
|
+
constrained_by: "constrained_by";
|
|
804
|
+
affects: "affects";
|
|
805
|
+
supersedes: "supersedes";
|
|
806
|
+
must_preserve: "must_preserve";
|
|
807
|
+
performs: "performs";
|
|
808
|
+
part_of: "part_of";
|
|
809
|
+
precedes: "precedes";
|
|
810
|
+
must_follow: "must_follow";
|
|
811
|
+
blocks: "blocks";
|
|
812
|
+
routes_to: "routes_to";
|
|
813
|
+
governed_by: "governed_by";
|
|
814
|
+
modifies: "modifies";
|
|
815
|
+
triggered_by: "triggered_by";
|
|
816
|
+
applies_to: "applies_to";
|
|
817
|
+
produces: "produces";
|
|
818
|
+
consumes: "consumes";
|
|
819
|
+
transforms_into: "transforms_into";
|
|
820
|
+
selects: "selects";
|
|
821
|
+
requires: "requires";
|
|
822
|
+
disables: "disables";
|
|
823
|
+
}> & {
|
|
824
|
+
is(value: unknown): value is "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
825
|
+
};
|
|
826
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
827
|
+
is(value: unknown): value is string | string[];
|
|
828
|
+
}>;
|
|
829
|
+
}, z.core.$loose> & {
|
|
830
|
+
is(value: unknown): value is {
|
|
831
|
+
[x: string]: unknown;
|
|
832
|
+
from: string;
|
|
833
|
+
to: string;
|
|
834
|
+
type: "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
835
|
+
description?: string | string[] | undefined;
|
|
836
|
+
};
|
|
837
|
+
}>>;
|
|
838
|
+
external_references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
839
|
+
role: z.ZodEnum<{
|
|
840
|
+
output: "output";
|
|
841
|
+
input: "input";
|
|
842
|
+
context: "context";
|
|
843
|
+
evidence: "evidence";
|
|
844
|
+
source: "source";
|
|
845
|
+
standard: "standard";
|
|
846
|
+
prior_art: "prior_art";
|
|
847
|
+
}> & {
|
|
848
|
+
is(value: unknown): value is "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
849
|
+
};
|
|
850
|
+
identifier: z.ZodString;
|
|
851
|
+
description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
852
|
+
is(value: unknown): value is string | string[];
|
|
853
|
+
}>;
|
|
854
|
+
node_id: z.ZodOptional<z.ZodString>;
|
|
855
|
+
internalised: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]> & {
|
|
856
|
+
is(value: unknown): value is string | string[];
|
|
857
|
+
}>;
|
|
858
|
+
}, z.core.$strip> & {
|
|
859
|
+
is(value: unknown): value is {
|
|
860
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
861
|
+
identifier: string;
|
|
862
|
+
description?: string | string[] | undefined;
|
|
863
|
+
node_id?: string | undefined;
|
|
864
|
+
internalised?: string | string[] | undefined;
|
|
865
|
+
};
|
|
866
|
+
}>>;
|
|
867
|
+
}, z.core.$strip> & {
|
|
868
|
+
is(value: unknown): value is {
|
|
869
|
+
nodes: {
|
|
870
|
+
[x: string]: unknown;
|
|
871
|
+
id: string;
|
|
872
|
+
type: "intent" | "concept" | "capability" | "element" | "realisation" | "invariant" | "principle" | "policy" | "protocol" | "stage" | "role" | "gate" | "mode" | "artefact" | "artefact_flow" | "decision" | "change" | "view" | "milestone" | "version";
|
|
873
|
+
name: string;
|
|
874
|
+
description?: string | string[] | undefined;
|
|
875
|
+
status?: "deprecated" | "proposed" | "accepted" | "active" | "implemented" | "adopted" | "defined" | "introduced" | "in_progress" | "complete" | "consolidated" | "experimental" | "retired" | "superseded" | "abandoned" | "deferred" | undefined;
|
|
876
|
+
lifecycle?: Record<string, string | boolean> | undefined;
|
|
877
|
+
context?: string | string[] | undefined;
|
|
878
|
+
options?: {
|
|
879
|
+
[x: string]: unknown;
|
|
880
|
+
id: string;
|
|
881
|
+
description: string | string[];
|
|
882
|
+
}[] | undefined;
|
|
883
|
+
selected?: string | undefined;
|
|
884
|
+
rationale?: string | string[] | undefined;
|
|
885
|
+
scope?: string[] | undefined;
|
|
886
|
+
operations?: {
|
|
887
|
+
[x: string]: unknown;
|
|
888
|
+
type: "link" | "add" | "update" | "remove";
|
|
889
|
+
target?: string | undefined;
|
|
890
|
+
description?: string | string[] | undefined;
|
|
891
|
+
}[] | undefined;
|
|
892
|
+
plan?: {
|
|
893
|
+
[x: string]: unknown;
|
|
894
|
+
description: string | string[];
|
|
895
|
+
done?: boolean | undefined;
|
|
896
|
+
}[] | undefined;
|
|
897
|
+
propagation?: Record<string, boolean> | undefined;
|
|
898
|
+
includes?: string[] | undefined;
|
|
899
|
+
input?: string | undefined;
|
|
900
|
+
output?: string | undefined;
|
|
901
|
+
external_references?: {
|
|
902
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
903
|
+
identifier: string;
|
|
904
|
+
description?: string | string[] | undefined;
|
|
905
|
+
node_id?: string | undefined;
|
|
906
|
+
internalised?: string | string[] | undefined;
|
|
907
|
+
}[] | undefined;
|
|
908
|
+
subsystem?: /*elided*/ any | undefined;
|
|
909
|
+
}[];
|
|
910
|
+
$schema?: string | undefined;
|
|
911
|
+
metadata?: {
|
|
912
|
+
[x: string]: unknown;
|
|
913
|
+
title?: string | undefined;
|
|
914
|
+
doc_type?: string | undefined;
|
|
915
|
+
scope?: string | undefined;
|
|
916
|
+
status?: string | undefined;
|
|
917
|
+
version?: string | number | undefined;
|
|
918
|
+
} | undefined;
|
|
919
|
+
relationships?: {
|
|
920
|
+
[x: string]: unknown;
|
|
921
|
+
from: string;
|
|
922
|
+
to: string;
|
|
923
|
+
type: "refines" | "realises" | "implements" | "depends_on" | "constrained_by" | "affects" | "supersedes" | "must_preserve" | "performs" | "part_of" | "precedes" | "must_follow" | "blocks" | "routes_to" | "governed_by" | "modifies" | "triggered_by" | "applies_to" | "produces" | "consumes" | "transforms_into" | "selects" | "requires" | "disables";
|
|
924
|
+
description?: string | string[] | undefined;
|
|
925
|
+
}[] | undefined;
|
|
926
|
+
external_references?: {
|
|
927
|
+
role: "output" | "input" | "context" | "evidence" | "source" | "standard" | "prior_art";
|
|
928
|
+
identifier: string;
|
|
929
|
+
description?: string | string[] | undefined;
|
|
930
|
+
node_id?: string | undefined;
|
|
931
|
+
internalised?: string | string[] | undefined;
|
|
932
|
+
}[] | undefined;
|
|
933
|
+
};
|
|
934
|
+
};
|
|
935
|
+
jsonChanged: z.ZodBoolean;
|
|
936
|
+
mdChanged: z.ZodBoolean;
|
|
937
|
+
conflict: z.ZodBoolean;
|
|
938
|
+
strategy: z.ZodEnum<{
|
|
939
|
+
json: "json";
|
|
940
|
+
md: "md";
|
|
941
|
+
interactive: "interactive";
|
|
942
|
+
report: "report";
|
|
943
|
+
}>;
|
|
944
|
+
changedNodes: z.ZodArray<z.ZodString>;
|
|
945
|
+
}, z.core.$strip>>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
import { defineOperation } from "./define-operation.js";
|
|
3
|
+
import { SysProMDocument } from "../schema.js";
|
|
4
|
+
/**
|
|
5
|
+
* Conflict resolution strategy when both documents have diverged.
|
|
6
|
+
* - 'json': prefer the JSON document as source of truth
|
|
7
|
+
* - 'md': prefer the Markdown-parsed document as source of truth
|
|
8
|
+
* - 'interactive': (not yet supported) prompt user per-conflict
|
|
9
|
+
* - 'report': return summary without resolving
|
|
10
|
+
*/
|
|
11
|
+
export const ConflictStrategy = z.enum(["json", "md", "interactive", "report"]);
|
|
12
|
+
const BidirectionalSyncResultSchema = z.object({
|
|
13
|
+
synced: SysProMDocument,
|
|
14
|
+
jsonChanged: z.boolean(),
|
|
15
|
+
mdChanged: z.boolean(),
|
|
16
|
+
conflict: z.boolean(),
|
|
17
|
+
strategy: ConflictStrategy,
|
|
18
|
+
changedNodes: z.array(z.string()),
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Synchronise two SysProM document representations.
|
|
22
|
+
* Implements bidirectional sync with configurable conflict resolution.
|
|
23
|
+
* @throws {Error} If conflict resolution is impossible (both changed with 'report' strategy)
|
|
24
|
+
*/
|
|
25
|
+
export const syncDocumentsOp = defineOperation({
|
|
26
|
+
name: "syncDocuments",
|
|
27
|
+
description: "Synchronise two SysProM document representations (JSON and Markdown-parsed) with conflict resolution strategies.",
|
|
28
|
+
input: z.object({
|
|
29
|
+
jsonDoc: SysProMDocument,
|
|
30
|
+
mdDoc: SysProMDocument,
|
|
31
|
+
jsonChanged: z.boolean(),
|
|
32
|
+
mdChanged: z.boolean(),
|
|
33
|
+
strategy: ConflictStrategy.optional(),
|
|
34
|
+
}),
|
|
35
|
+
output: BidirectionalSyncResultSchema,
|
|
36
|
+
fn(params) {
|
|
37
|
+
const { jsonDoc, mdDoc, jsonChanged, mdChanged, strategy = "json", } = params;
|
|
38
|
+
// Identify which nodes differ
|
|
39
|
+
const jsonNodeMap = new Map(jsonDoc.nodes.map((n) => [n.id, n]));
|
|
40
|
+
const mdNodeMap = new Map(mdDoc.nodes.map((n) => [n.id, n]));
|
|
41
|
+
const changedNodes = [];
|
|
42
|
+
for (const node of jsonDoc.nodes) {
|
|
43
|
+
const mdNode = mdNodeMap.get(node.id);
|
|
44
|
+
if (!mdNode || JSON.stringify(node) !== JSON.stringify(mdNode)) {
|
|
45
|
+
changedNodes.push(node.id);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const node of mdDoc.nodes) {
|
|
49
|
+
if (!jsonNodeMap.has(node.id)) {
|
|
50
|
+
changedNodes.push(node.id);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Determine sync strategy and result
|
|
54
|
+
if (!jsonChanged && !mdChanged) {
|
|
55
|
+
// No changes, return either document
|
|
56
|
+
return {
|
|
57
|
+
synced: jsonDoc,
|
|
58
|
+
jsonChanged: false,
|
|
59
|
+
mdChanged: false,
|
|
60
|
+
conflict: false,
|
|
61
|
+
strategy: strategy,
|
|
62
|
+
changedNodes: [],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (jsonChanged && !mdChanged) {
|
|
66
|
+
// JSON is the modified source, return it as-is
|
|
67
|
+
return {
|
|
68
|
+
synced: jsonDoc,
|
|
69
|
+
jsonChanged: true,
|
|
70
|
+
mdChanged: false,
|
|
71
|
+
conflict: false,
|
|
72
|
+
strategy: strategy,
|
|
73
|
+
changedNodes,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (!jsonChanged && mdChanged) {
|
|
77
|
+
// MD is the modified source, return it
|
|
78
|
+
return {
|
|
79
|
+
synced: mdDoc,
|
|
80
|
+
jsonChanged: false,
|
|
81
|
+
mdChanged: true,
|
|
82
|
+
conflict: false,
|
|
83
|
+
strategy: strategy,
|
|
84
|
+
changedNodes,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Both have changed — apply conflict strategy
|
|
88
|
+
switch (strategy) {
|
|
89
|
+
case "json": {
|
|
90
|
+
return {
|
|
91
|
+
synced: jsonDoc,
|
|
92
|
+
jsonChanged: true,
|
|
93
|
+
mdChanged: true,
|
|
94
|
+
conflict: true,
|
|
95
|
+
strategy: "json",
|
|
96
|
+
changedNodes,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
case "md": {
|
|
100
|
+
return {
|
|
101
|
+
synced: mdDoc,
|
|
102
|
+
jsonChanged: true,
|
|
103
|
+
mdChanged: true,
|
|
104
|
+
conflict: true,
|
|
105
|
+
strategy: "md",
|
|
106
|
+
changedNodes,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
case "report": {
|
|
110
|
+
const nodeCountStr = String(changedNodes.length);
|
|
111
|
+
throw new Error(`Conflict detected: both JSON and Markdown have diverged (${nodeCountStr} nodes differ). Use --prefer-json or --prefer-md to resolve.`);
|
|
112
|
+
}
|
|
113
|
+
case "interactive": {
|
|
114
|
+
throw new Error("Interactive conflict resolution not yet implemented");
|
|
115
|
+
}
|
|
116
|
+
default: {
|
|
117
|
+
// TypeScript exhaustiveness check
|
|
118
|
+
const _exhaustive = strategy;
|
|
119
|
+
return _exhaustive;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result of detecting changes between JSON and Markdown representations.
|
|
3
|
+
* @property jsonChanged True if JSON has changed since MD was created
|
|
4
|
+
* @property mdChanged True if Markdown has changed since JSON was created
|
|
5
|
+
* @property conflict True if both sides have diverged (both changed)
|
|
6
|
+
*/
|
|
7
|
+
export interface DetectionResult {
|
|
8
|
+
jsonChanged: boolean;
|
|
9
|
+
mdChanged: boolean;
|
|
10
|
+
conflict: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Detect whether JSON and/or Markdown have changed.
|
|
14
|
+
* Strategy:
|
|
15
|
+
* 1. Parse both JSON and Markdown to document objects
|
|
16
|
+
* 2. If documents are identical → no change
|
|
17
|
+
* 3. If documents differ:
|
|
18
|
+
* - Use file modification times to determine which was edited more recently
|
|
19
|
+
* - The newer file is considered the "changed" one
|
|
20
|
+
* - If modification times are very close (< 100ms), treat as conflict
|
|
21
|
+
*
|
|
22
|
+
* @param jsonPath Path to JSON file
|
|
23
|
+
* @param mdPath Path to Markdown file (single or multi-doc)
|
|
24
|
+
* @returns Detection result with jsonChanged, mdChanged, and conflict flags
|
|
25
|
+
*/
|
|
26
|
+
export declare function detectChanges(jsonPath: string, mdPath: string): DetectionResult;
|
package/dist/src/sync.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { markdownToJson } from "./md-to-json.js";
|
|
4
|
+
import { SysProMDocument } from "./schema.js";
|
|
5
|
+
/**
|
|
6
|
+
* Compute a normalised hash of a document for comparison.
|
|
7
|
+
* Uses canonical JSON representation.
|
|
8
|
+
* @param doc The SysProM document
|
|
9
|
+
* @returns SHA256 hash of the canonicalised document
|
|
10
|
+
*/
|
|
11
|
+
function normaliseHash(doc) {
|
|
12
|
+
const sorted = JSON.stringify(doc, Object.keys(doc).sort());
|
|
13
|
+
return createHash("sha256").update(sorted).digest("hex");
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Detect whether JSON and/or Markdown have changed.
|
|
17
|
+
* Strategy:
|
|
18
|
+
* 1. Parse both JSON and Markdown to document objects
|
|
19
|
+
* 2. If documents are identical → no change
|
|
20
|
+
* 3. If documents differ:
|
|
21
|
+
* - Use file modification times to determine which was edited more recently
|
|
22
|
+
* - The newer file is considered the "changed" one
|
|
23
|
+
* - If modification times are very close (< 100ms), treat as conflict
|
|
24
|
+
*
|
|
25
|
+
* @param jsonPath Path to JSON file
|
|
26
|
+
* @param mdPath Path to Markdown file (single or multi-doc)
|
|
27
|
+
* @returns Detection result with jsonChanged, mdChanged, and conflict flags
|
|
28
|
+
*/
|
|
29
|
+
export function detectChanges(jsonPath, mdPath) {
|
|
30
|
+
// Read files
|
|
31
|
+
const jsonContent = readFileSync(jsonPath, "utf8");
|
|
32
|
+
const mdContent = readFileSync(mdPath, "utf8");
|
|
33
|
+
// Parse JSON
|
|
34
|
+
const jsonDoc = JSON.parse(jsonContent);
|
|
35
|
+
if (!SysProMDocument.is(jsonDoc)) {
|
|
36
|
+
throw new Error("JSON file is not a valid SysProM document");
|
|
37
|
+
}
|
|
38
|
+
// Parse Markdown to document
|
|
39
|
+
const mdDoc = markdownToJson(mdPath);
|
|
40
|
+
// Compare parsed documents
|
|
41
|
+
const jsonHash = normaliseHash(jsonDoc);
|
|
42
|
+
const mdHash = normaliseHash(mdDoc);
|
|
43
|
+
// If both parse to identical documents, no changes on either side
|
|
44
|
+
if (jsonHash === mdHash) {
|
|
45
|
+
return {
|
|
46
|
+
jsonChanged: false,
|
|
47
|
+
mdChanged: false,
|
|
48
|
+
conflict: false,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Parsed documents differ. Use file modification times to determine which changed.
|
|
52
|
+
// The file that was modified more recently is the one that diverged.
|
|
53
|
+
const jsonStats = statSync(jsonPath);
|
|
54
|
+
const mdStats = statSync(mdPath);
|
|
55
|
+
const timeDiff = Math.abs(jsonStats.mtimeMs - mdStats.mtimeMs);
|
|
56
|
+
// If modification times are very close (within 100ms), treat as simultaneous edit (conflict)
|
|
57
|
+
if (timeDiff < 100) {
|
|
58
|
+
return {
|
|
59
|
+
jsonChanged: true,
|
|
60
|
+
mdChanged: true,
|
|
61
|
+
conflict: true,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Otherwise, determine which file is newer
|
|
65
|
+
if (jsonStats.mtimeMs > mdStats.mtimeMs) {
|
|
66
|
+
// JSON is newer → JSON was modified after MD
|
|
67
|
+
return {
|
|
68
|
+
jsonChanged: true,
|
|
69
|
+
mdChanged: false,
|
|
70
|
+
conflict: false,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// MD is newer → MD was modified after JSON
|
|
75
|
+
return {
|
|
76
|
+
jsonChanged: false,
|
|
77
|
+
mdChanged: true,
|
|
78
|
+
conflict: false,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|