@popoverai/dotrequirements 0.33.0 → 0.34.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/cli.js +13 -1
- package/dist/cloud.d.ts +5 -1
- package/dist/cloud.js +6 -2
- package/dist/commands/board/index.d.ts +13 -0
- package/dist/commands/board/index.js +96 -0
- package/dist/commands/branch-merge.d.ts +78 -0
- package/dist/commands/branch-merge.js +129 -0
- package/dist/commands/diff.js +15 -5
- package/dist/commands/mockup/index.d.ts +11 -0
- package/dist/commands/mockup/index.js +82 -0
- package/dist/commands/scores/index.d.ts +50 -0
- package/dist/commands/scores/index.js +190 -0
- package/dist/commands/solution/ask.d.ts +9 -0
- package/dist/commands/solution/ask.js +27 -0
- package/dist/commands/solution/author.d.ts +19 -0
- package/dist/commands/solution/author.js +202 -0
- package/dist/commands/solution/branch.d.ts +103 -0
- package/dist/commands/solution/branch.js +341 -0
- package/dist/commands/solution/brief.d.ts +81 -0
- package/dist/commands/solution/brief.js +47 -0
- package/dist/commands/solution/checkout.d.ts +27 -0
- package/dist/commands/solution/checkout.js +66 -0
- package/dist/commands/solution/client.d.ts +16 -0
- package/dist/commands/solution/client.js +46 -0
- package/dist/commands/solution/contract.d.ts +9 -0
- package/dist/commands/solution/contract.js +23 -0
- package/dist/commands/solution/create.d.ts +14 -0
- package/dist/commands/solution/create.js +52 -0
- package/dist/commands/solution/demo-script.d.ts +28 -0
- package/dist/commands/solution/demo-script.js +43 -0
- package/dist/commands/solution/image.d.ts +60 -0
- package/dist/commands/solution/image.js +148 -0
- package/dist/commands/solution/index.d.ts +12 -0
- package/dist/commands/solution/index.js +281 -0
- package/dist/commands/solution/look-up.d.ts +9 -0
- package/dist/commands/solution/look-up.js +69 -0
- package/dist/commands/solution/next.d.ts +12 -0
- package/dist/commands/solution/next.js +48 -0
- package/dist/commands/solution/plan-file.d.ts +22 -0
- package/dist/commands/solution/plan-file.js +33 -0
- package/dist/commands/solution/preview-screenshot.d.ts +21 -0
- package/dist/commands/solution/preview-screenshot.js +56 -0
- package/dist/commands/solution/pull-request.d.ts +25 -0
- package/dist/commands/solution/pull-request.js +117 -0
- package/dist/commands/solution/pushing.d.ts +66 -0
- package/dist/commands/solution/pushing.js +185 -0
- package/dist/commands/solution/rehearse.d.ts +10 -0
- package/dist/commands/solution/rehearse.js +24 -0
- package/dist/commands/solution/request.d.ts +3 -0
- package/dist/commands/solution/request.js +13 -0
- package/dist/commands/solution/review.d.ts +27 -0
- package/dist/commands/solution/review.js +104 -0
- package/dist/commands/solution/run-file.d.ts +42 -0
- package/dist/commands/solution/run-file.js +63 -0
- package/dist/commands/solution/share.d.ts +62 -0
- package/dist/commands/solution/share.js +346 -0
- package/dist/commands/solution/stall.d.ts +14 -0
- package/dist/commands/solution/stall.js +41 -0
- package/dist/commands/solution/start.d.ts +11 -0
- package/dist/commands/solution/start.js +20 -0
- package/dist/commands/solution/status.d.ts +39 -0
- package/dist/commands/solution/status.js +145 -0
- package/dist/commands/solution/summary.d.ts +13 -0
- package/dist/commands/solution/summary.js +5 -0
- package/dist/commands/solution/things.d.ts +118 -0
- package/dist/commands/solution/things.js +78 -0
- package/dist/commands/solution/thread.d.ts +13 -0
- package/dist/commands/solution/thread.js +53 -0
- package/dist/commands/solution/upload.d.ts +24 -0
- package/dist/commands/solution/upload.js +27 -0
- package/dist/commands/solution/video.d.ts +88 -0
- package/dist/commands/solution/video.js +364 -0
- package/dist/commands/solution/working-folder.d.ts +44 -0
- package/dist/commands/solution/working-folder.js +64 -0
- package/dist/commands/sync.d.ts +2 -1
- package/dist/commands/sync.js +21 -5
- package/dist/convex.d.ts +54 -0
- package/dist/convex.js +64 -0
- package/dist/push/core.js +7 -2
- package/dist/rehearsal/derive.d.ts +23 -0
- package/dist/rehearsal/derive.js +112 -0
- package/dist/rehearsal/driver.d.ts +44 -0
- package/dist/rehearsal/driver.js +337 -0
- package/dist/rehearsal/earlier.d.ts +25 -0
- package/dist/rehearsal/earlier.js +138 -0
- package/dist/rehearsal/index.d.ts +5 -0
- package/dist/rehearsal/index.js +4 -0
- package/dist/rehearsal/live.d.ts +72 -0
- package/dist/rehearsal/live.js +301 -0
- package/dist/rehearsal/report.d.ts +4 -0
- package/dist/rehearsal/report.js +69 -0
- package/dist/rehearsal/types.d.ts +377 -0
- package/dist/rehearsal/types.js +8 -0
- package/dist/requirements/index.d.ts +6 -0
- package/dist/requirements/index.js +24 -0
- package/dist/schema/browser.d.ts +1 -1
- package/dist/schema/browser.js +3 -1
- package/dist/schema/file-writer.d.ts +5 -0
- package/dist/schema/file-writer.js +4 -0
- package/dist/schema/parser.d.ts +11 -2
- package/dist/schema/parser.js +11 -7
- package/dist/schema/schemas.d.ts +40 -0
- package/dist/schema/schemas.js +4 -0
- package/dist/sync/execute.d.ts +10 -1
- package/dist/sync/execute.js +69 -5
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.js +1 -1
- package/dist/sync/publish.d.ts +7 -0
- package/dist/sync/segment.js +4 -1
- package/dist/sync/snapshot.d.ts +23 -1
- package/dist/sync/snapshot.js +75 -3
- package/dist/sync/solution-documents.d.ts +64 -0
- package/dist/sync/solution-documents.js +97 -0
- package/dist/sync/types.d.ts +18 -0
- package/package.json +3 -2
package/dist/schema/schemas.d.ts
CHANGED
|
@@ -86,6 +86,8 @@ export declare const MetadataSchema: z.ZodObject<{
|
|
|
86
86
|
id: z.ZodOptional<z.ZodString>;
|
|
87
87
|
title: z.ZodOptional<z.ZodString>;
|
|
88
88
|
defaultPrefix: z.ZodOptional<z.ZodString>;
|
|
89
|
+
solution: z.ZodOptional<z.ZodString>;
|
|
90
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
89
91
|
attachments: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
90
92
|
url: z.ZodString;
|
|
91
93
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -112,6 +114,8 @@ export declare const MetadataSchema: z.ZodObject<{
|
|
|
112
114
|
id?: string | undefined;
|
|
113
115
|
title?: string | undefined;
|
|
114
116
|
defaultPrefix?: string | undefined;
|
|
117
|
+
solution?: string | undefined;
|
|
118
|
+
outcome?: string | undefined;
|
|
115
119
|
attachments?: {
|
|
116
120
|
url: string;
|
|
117
121
|
title?: string | undefined;
|
|
@@ -120,6 +124,8 @@ export declare const MetadataSchema: z.ZodObject<{
|
|
|
120
124
|
id?: string | undefined;
|
|
121
125
|
title?: string | undefined;
|
|
122
126
|
defaultPrefix?: string | undefined;
|
|
127
|
+
solution?: string | undefined;
|
|
128
|
+
outcome?: string | undefined;
|
|
123
129
|
attachments?: {
|
|
124
130
|
url: string;
|
|
125
131
|
title?: string | undefined;
|
|
@@ -133,6 +139,8 @@ export declare const MetadataSchema: z.ZodObject<{
|
|
|
133
139
|
id?: string | undefined;
|
|
134
140
|
title?: string | undefined;
|
|
135
141
|
defaultPrefix?: string | undefined;
|
|
142
|
+
solution?: string | undefined;
|
|
143
|
+
outcome?: string | undefined;
|
|
136
144
|
attachments?: {
|
|
137
145
|
url: string;
|
|
138
146
|
title?: string | undefined;
|
|
@@ -146,6 +154,8 @@ export declare const MetadataSchema: z.ZodObject<{
|
|
|
146
154
|
id?: string | undefined;
|
|
147
155
|
title?: string | undefined;
|
|
148
156
|
defaultPrefix?: string | undefined;
|
|
157
|
+
solution?: string | undefined;
|
|
158
|
+
outcome?: string | undefined;
|
|
149
159
|
attachments?: {
|
|
150
160
|
url: string;
|
|
151
161
|
title?: string | undefined;
|
|
@@ -213,6 +223,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
213
223
|
id: z.ZodOptional<z.ZodString>;
|
|
214
224
|
title: z.ZodOptional<z.ZodString>;
|
|
215
225
|
defaultPrefix: z.ZodOptional<z.ZodString>;
|
|
226
|
+
solution: z.ZodOptional<z.ZodString>;
|
|
227
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
216
228
|
attachments: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
217
229
|
url: z.ZodString;
|
|
218
230
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -239,6 +251,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
239
251
|
id?: string | undefined;
|
|
240
252
|
title?: string | undefined;
|
|
241
253
|
defaultPrefix?: string | undefined;
|
|
254
|
+
solution?: string | undefined;
|
|
255
|
+
outcome?: string | undefined;
|
|
242
256
|
attachments?: {
|
|
243
257
|
url: string;
|
|
244
258
|
title?: string | undefined;
|
|
@@ -247,6 +261,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
247
261
|
id?: string | undefined;
|
|
248
262
|
title?: string | undefined;
|
|
249
263
|
defaultPrefix?: string | undefined;
|
|
264
|
+
solution?: string | undefined;
|
|
265
|
+
outcome?: string | undefined;
|
|
250
266
|
attachments?: {
|
|
251
267
|
url: string;
|
|
252
268
|
title?: string | undefined;
|
|
@@ -260,6 +276,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
260
276
|
id?: string | undefined;
|
|
261
277
|
title?: string | undefined;
|
|
262
278
|
defaultPrefix?: string | undefined;
|
|
279
|
+
solution?: string | undefined;
|
|
280
|
+
outcome?: string | undefined;
|
|
263
281
|
attachments?: {
|
|
264
282
|
url: string;
|
|
265
283
|
title?: string | undefined;
|
|
@@ -273,6 +291,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
273
291
|
id?: string | undefined;
|
|
274
292
|
title?: string | undefined;
|
|
275
293
|
defaultPrefix?: string | undefined;
|
|
294
|
+
solution?: string | undefined;
|
|
295
|
+
outcome?: string | undefined;
|
|
276
296
|
attachments?: {
|
|
277
297
|
url: string;
|
|
278
298
|
title?: string | undefined;
|
|
@@ -288,6 +308,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
288
308
|
id: z.ZodOptional<z.ZodString>;
|
|
289
309
|
title: z.ZodOptional<z.ZodString>;
|
|
290
310
|
defaultPrefix: z.ZodOptional<z.ZodString>;
|
|
311
|
+
solution: z.ZodOptional<z.ZodString>;
|
|
312
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
291
313
|
attachments: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
292
314
|
url: z.ZodString;
|
|
293
315
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -314,6 +336,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
314
336
|
id?: string | undefined;
|
|
315
337
|
title?: string | undefined;
|
|
316
338
|
defaultPrefix?: string | undefined;
|
|
339
|
+
solution?: string | undefined;
|
|
340
|
+
outcome?: string | undefined;
|
|
317
341
|
attachments?: {
|
|
318
342
|
url: string;
|
|
319
343
|
title?: string | undefined;
|
|
@@ -322,6 +346,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
322
346
|
id?: string | undefined;
|
|
323
347
|
title?: string | undefined;
|
|
324
348
|
defaultPrefix?: string | undefined;
|
|
349
|
+
solution?: string | undefined;
|
|
350
|
+
outcome?: string | undefined;
|
|
325
351
|
attachments?: {
|
|
326
352
|
url: string;
|
|
327
353
|
title?: string | undefined;
|
|
@@ -335,6 +361,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
335
361
|
id?: string | undefined;
|
|
336
362
|
title?: string | undefined;
|
|
337
363
|
defaultPrefix?: string | undefined;
|
|
364
|
+
solution?: string | undefined;
|
|
365
|
+
outcome?: string | undefined;
|
|
338
366
|
attachments?: {
|
|
339
367
|
url: string;
|
|
340
368
|
title?: string | undefined;
|
|
@@ -348,6 +376,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
348
376
|
id?: string | undefined;
|
|
349
377
|
title?: string | undefined;
|
|
350
378
|
defaultPrefix?: string | undefined;
|
|
379
|
+
solution?: string | undefined;
|
|
380
|
+
outcome?: string | undefined;
|
|
351
381
|
attachments?: {
|
|
352
382
|
url: string;
|
|
353
383
|
title?: string | undefined;
|
|
@@ -363,6 +393,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
363
393
|
id: z.ZodOptional<z.ZodString>;
|
|
364
394
|
title: z.ZodOptional<z.ZodString>;
|
|
365
395
|
defaultPrefix: z.ZodOptional<z.ZodString>;
|
|
396
|
+
solution: z.ZodOptional<z.ZodString>;
|
|
397
|
+
outcome: z.ZodOptional<z.ZodString>;
|
|
366
398
|
attachments: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
367
399
|
url: z.ZodString;
|
|
368
400
|
title: z.ZodOptional<z.ZodString>;
|
|
@@ -389,6 +421,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
389
421
|
id?: string | undefined;
|
|
390
422
|
title?: string | undefined;
|
|
391
423
|
defaultPrefix?: string | undefined;
|
|
424
|
+
solution?: string | undefined;
|
|
425
|
+
outcome?: string | undefined;
|
|
392
426
|
attachments?: {
|
|
393
427
|
url: string;
|
|
394
428
|
title?: string | undefined;
|
|
@@ -397,6 +431,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
397
431
|
id?: string | undefined;
|
|
398
432
|
title?: string | undefined;
|
|
399
433
|
defaultPrefix?: string | undefined;
|
|
434
|
+
solution?: string | undefined;
|
|
435
|
+
outcome?: string | undefined;
|
|
400
436
|
attachments?: {
|
|
401
437
|
url: string;
|
|
402
438
|
title?: string | undefined;
|
|
@@ -410,6 +446,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
410
446
|
id?: string | undefined;
|
|
411
447
|
title?: string | undefined;
|
|
412
448
|
defaultPrefix?: string | undefined;
|
|
449
|
+
solution?: string | undefined;
|
|
450
|
+
outcome?: string | undefined;
|
|
413
451
|
attachments?: {
|
|
414
452
|
url: string;
|
|
415
453
|
title?: string | undefined;
|
|
@@ -423,6 +461,8 @@ export declare const RequirementsFileSchema: z.ZodObject<{
|
|
|
423
461
|
id?: string | undefined;
|
|
424
462
|
title?: string | undefined;
|
|
425
463
|
defaultPrefix?: string | undefined;
|
|
464
|
+
solution?: string | undefined;
|
|
465
|
+
outcome?: string | undefined;
|
|
426
466
|
attachments?: {
|
|
427
467
|
url: string;
|
|
428
468
|
title?: string | undefined;
|
package/dist/schema/schemas.js
CHANGED
|
@@ -147,6 +147,10 @@ export const MetadataSchema = z.object({
|
|
|
147
147
|
id: z.string().optional(), // Cloud document link - filled by push when creating
|
|
148
148
|
title: z.string().optional(), // Legacy fallback — the body's leading H1 is the title
|
|
149
149
|
defaultPrefix: z.string().optional(), // Editor hint for new requirement keys
|
|
150
|
+
// SOLDOC-5: the solution (by id) and the outcome (by name) this document
|
|
151
|
+
// belongs to. Written by the sync; the truth once present.
|
|
152
|
+
solution: z.string().optional(),
|
|
153
|
+
outcome: z.string().optional(),
|
|
150
154
|
// ATTACH-10: links attached to the document (a Miro board, a reference
|
|
151
155
|
// page). Round-trips through sync — the cloud stores them as document
|
|
152
156
|
// metadata, the file carries them here.
|
package/dist/sync/execute.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { PlannedAction, SyncMode } from "./plan.js";
|
|
11
11
|
import type { CloudAuth } from "./snapshot.js";
|
|
12
|
+
import { type SolutionForSync } from "./solution-documents.js";
|
|
12
13
|
import type { CloudSnapshot, DocumentComparison } from "./types.js";
|
|
13
14
|
export interface SyncOutcome {
|
|
14
15
|
cloudCreated: number;
|
|
@@ -59,6 +60,8 @@ export interface SyncOutcome {
|
|
|
59
60
|
name: string;
|
|
60
61
|
warning: string;
|
|
61
62
|
}>;
|
|
63
|
+
/** SOLDOC-5.1/5.2: a file whose path and frontmatter disagree about where it belongs. Optional so an outcome built before the field existed still reads. */
|
|
64
|
+
belongingWarnings?: string[];
|
|
62
65
|
/** SYNC-CLI-EDIT-3.1: files whose notation the cloud changed on storing —
|
|
63
66
|
* list markers, emphasis characters, spacing. Counted so the sync can say
|
|
64
67
|
* the reformatting happened and why, instead of leaving Jaime to discover
|
|
@@ -85,5 +88,11 @@ export interface SyncOutcome {
|
|
|
85
88
|
* writes require a project slug in `auth`; a read-only share run has none and
|
|
86
89
|
* its plan carries no cloud-writing actions.
|
|
87
90
|
*/
|
|
88
|
-
export declare function executePlan(plan: PlannedAction[], cloud: CloudSnapshot, auth: CloudAuth, workspaceRoot: string, mode: SyncMode
|
|
91
|
+
export declare function executePlan(plan: PlannedAction[], cloud: CloudSnapshot, auth: CloudAuth, workspaceRoot: string, mode: SyncMode,
|
|
92
|
+
/**
|
|
93
|
+
* The project's solutions, as `projectSolutions` read them; null (the
|
|
94
|
+
* default) when the project's team doesn't have solutions
|
|
95
|
+
* (SOLACCESS-2.2), so no file is placed as a solution's.
|
|
96
|
+
*/
|
|
97
|
+
solutions?: SolutionForSync[] | null): Promise<SyncOutcome>;
|
|
89
98
|
//# sourceMappingURL=execute.d.ts.map
|
package/dist/sync/execute.js
CHANGED
|
@@ -16,8 +16,9 @@ import { parseFilesForPushIndividually, WEB_APP_URL } from "../push/core.js";
|
|
|
16
16
|
import { composeMarkdownWithTitle, splitLeadingH1, writeRequirementsFile, } from "../schema/index.js";
|
|
17
17
|
import { commandErrorMessage } from "../utils/command-error.js";
|
|
18
18
|
import { cloudAttachmentRemovals, resolveAttachments } from "./attachments.js";
|
|
19
|
-
import { resolveLocalPath } from "./local-files.js";
|
|
19
|
+
import { resolveLocalPath, sanitizeFileName } from "./local-files.js";
|
|
20
20
|
import { publishToCloud } from "./publish.js";
|
|
21
|
+
import { requirementsDocByName, resolveBelonging, solutionDirOf, solutionDocumentPath, } from "./solution-documents.js";
|
|
21
22
|
function emptyOutcome() {
|
|
22
23
|
return {
|
|
23
24
|
cloudCreated: 0,
|
|
@@ -35,6 +36,7 @@ function emptyOutcome() {
|
|
|
35
36
|
writeBackWarnings: [],
|
|
36
37
|
importWarnings: [],
|
|
37
38
|
publishWarnings: [],
|
|
39
|
+
belongingWarnings: [],
|
|
38
40
|
normalized: [],
|
|
39
41
|
renames: [],
|
|
40
42
|
inferredPrefixes: [],
|
|
@@ -45,7 +47,13 @@ function emptyOutcome() {
|
|
|
45
47
|
* writes require a project slug in `auth`; a read-only share run has none and
|
|
46
48
|
* its plan carries no cloud-writing actions.
|
|
47
49
|
*/
|
|
48
|
-
export async function executePlan(plan, cloud, auth, workspaceRoot, mode
|
|
50
|
+
export async function executePlan(plan, cloud, auth, workspaceRoot, mode,
|
|
51
|
+
/**
|
|
52
|
+
* The project's solutions, as `projectSolutions` read them; null (the
|
|
53
|
+
* default) when the project's team doesn't have solutions
|
|
54
|
+
* (SOLACCESS-2.2), so no file is placed as a solution's.
|
|
55
|
+
*/
|
|
56
|
+
solutions = null) {
|
|
49
57
|
const outcome = emptyOutcome();
|
|
50
58
|
const client = new ConvexHttpClient(convexUrl());
|
|
51
59
|
const cloudById = new Map(cloud.documents.map((d) => [d.documentId, d]));
|
|
@@ -64,7 +72,7 @@ export async function executePlan(plan, cloud, auth, workspaceRoot, mode) {
|
|
|
64
72
|
outcome.invalid.push(doc);
|
|
65
73
|
break;
|
|
66
74
|
case "cloud_write":
|
|
67
|
-
await cloudWrite(auth, doc, cloudById, outcome, mode);
|
|
75
|
+
await cloudWrite(auth, doc, cloudById, outcome, mode, solutions);
|
|
68
76
|
break;
|
|
69
77
|
case "cloud_delete":
|
|
70
78
|
await cloudDelete(client, auth, doc, outcome);
|
|
@@ -161,7 +169,7 @@ async function syncResidualAttachments(client, auth, doc, action, outcome, mode)
|
|
|
161
169
|
outcome.attachmentWrites++;
|
|
162
170
|
}
|
|
163
171
|
}
|
|
164
|
-
async function cloudWrite(auth, doc, cloudById, outcome, mode) {
|
|
172
|
+
async function cloudWrite(auth, doc, cloudById, outcome, mode, solutions) {
|
|
165
173
|
if (!auth.projectSlug || !doc.filePath) {
|
|
166
174
|
throw new Error("Cannot write to the cloud without project credentials.");
|
|
167
175
|
}
|
|
@@ -170,6 +178,24 @@ async function cloudWrite(auth, doc, cloudById, outcome, mode) {
|
|
|
170
178
|
if (!parsed)
|
|
171
179
|
throw new Error(`Could not parse ${path.basename(doc.filePath)}`);
|
|
172
180
|
const meta = parsed.metadata.document;
|
|
181
|
+
// SOLDOC-3/4/5: what the file's name and place say about it. A file in a
|
|
182
|
+
// solution directory with no frontmatter declares its belonging by its
|
|
183
|
+
// path; one with frontmatter keeps that, and a disagreeing path is reported.
|
|
184
|
+
// SOLACCESS-2.2: without solutions, a file is placed as it was before them.
|
|
185
|
+
const withSolutions = solutions !== null;
|
|
186
|
+
const resolved = withSolutions
|
|
187
|
+
? resolveBelonging(doc.filePath, { solution: meta?.solution, outcome: meta?.outcome }, solutionDirOf(doc.filePath), solutions)
|
|
188
|
+
: { belonging: undefined, warning: undefined };
|
|
189
|
+
if (resolved.warning) {
|
|
190
|
+
outcome.belongingWarnings = [
|
|
191
|
+
...(outcome.belongingWarnings ?? []),
|
|
192
|
+
resolved.warning,
|
|
193
|
+
];
|
|
194
|
+
}
|
|
195
|
+
const belonging = resolved.belonging;
|
|
196
|
+
const isRequirementsDoc = withSolutions
|
|
197
|
+
? requirementsDocByName(doc.filePath)
|
|
198
|
+
: undefined;
|
|
173
199
|
// SYNC-TITLE-1.1: a legacy file whose title lives only in frontmatter (no body
|
|
174
200
|
// H1) must reach the cloud self-describing. Materialize the title as the body's
|
|
175
201
|
// leading H1 BEFORE the push — so the cloud row carries the H1 on first write
|
|
@@ -214,6 +240,8 @@ async function cloudWrite(auth, doc, cloudById, outcome, mode) {
|
|
|
214
240
|
: []
|
|
215
241
|
: undefined,
|
|
216
242
|
runMarker: parsed.metadata.ctsRun,
|
|
243
|
+
solution: belonging,
|
|
244
|
+
isRequirementsDoc,
|
|
217
245
|
});
|
|
218
246
|
const documentId = saveResult.documentId;
|
|
219
247
|
// ATTACH-10.3.1.0: the publish above is the push that removes cloud
|
|
@@ -319,6 +347,9 @@ async function cloudWrite(auth, doc, cloudById, outcome, mode) {
|
|
|
319
347
|
// the title.
|
|
320
348
|
writeRequirementsFile(doc.filePath, {
|
|
321
349
|
documentId,
|
|
350
|
+
// SOLDOC-4.1: the belonging the path declared is written into the
|
|
351
|
+
// frontmatter, where it is the truth from now on.
|
|
352
|
+
belonging,
|
|
322
353
|
// The prefix just pushed is the file's own (or the one inferred from
|
|
323
354
|
// its first key, DOC-HEADER-11.4, which the write-back materializes).
|
|
324
355
|
defaultPrefix: meta?.defaultPrefix
|
|
@@ -365,8 +396,9 @@ function localWrite(doc, cloudById, usedPaths, requirementsDir, outcome, mode) {
|
|
|
365
396
|
throw new Error(`No cloud content for ${doc.title}`);
|
|
366
397
|
if (!fs.existsSync(requirementsDir))
|
|
367
398
|
fs.mkdirSync(requirementsDir, { recursive: true });
|
|
368
|
-
const filePath =
|
|
399
|
+
const filePath = placeCloudDocument(cloudDoc, doc.filePath, usedPaths, requirementsDir);
|
|
369
400
|
usedPaths.add(filePath);
|
|
401
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
370
402
|
// DOC-HEADER-11.6/11.7: a cloud document with no prefix means "nothing to
|
|
371
403
|
// impose" under an additive sync and "no prefix" under cloud-wins authority
|
|
372
404
|
// — so a prefix Jaime wrote is only ever removed by the mode they ran to
|
|
@@ -390,10 +422,42 @@ function localWrite(doc, cloudById, usedPaths, requirementsDir, outcome, mode) {
|
|
|
390
422
|
defaultPrefix,
|
|
391
423
|
attachments,
|
|
392
424
|
version: cloudDoc.version,
|
|
425
|
+
belonging: cloudDoc.solution
|
|
426
|
+
? {
|
|
427
|
+
solutionId: cloudDoc.solution.solutionId,
|
|
428
|
+
outcome: cloudDoc.solution.outcome,
|
|
429
|
+
}
|
|
430
|
+
: undefined,
|
|
393
431
|
}, cloudDoc.body);
|
|
394
432
|
if (changed)
|
|
395
433
|
outcome.localWritten++;
|
|
396
434
|
}
|
|
435
|
+
/**
|
|
436
|
+
* SOLDOC-6: where a pulled document lands. A file it is already linked to
|
|
437
|
+
* keeps its path (SYNC-DISCOVERY-2.0); a document that belongs to a solution
|
|
438
|
+
* lands in that solution's directory, named for its outcome; a document
|
|
439
|
+
* that is not a requirements document and belongs to no solution has no
|
|
440
|
+
* place, and the pull says so rather than guessing.
|
|
441
|
+
*/
|
|
442
|
+
function placeCloudDocument(cloudDoc, existingPath, usedPaths, requirementsDir) {
|
|
443
|
+
if (existingPath)
|
|
444
|
+
return existingPath;
|
|
445
|
+
const isRequirementsDoc = cloudDoc.isRequirementsDoc !== false;
|
|
446
|
+
if (cloudDoc.solution) {
|
|
447
|
+
// SOLDOC-9: the solution's own directory name; a backend from before it
|
|
448
|
+
// was sent leaves it out, and the title's slug stands in.
|
|
449
|
+
const candidate = solutionDocumentPath(requirementsDir, cloudDoc.solution.directory ??
|
|
450
|
+
sanitizeFileName(cloudDoc.solution.title ?? cloudDoc.solution.solutionId), cloudDoc.solution.outcome, isRequirementsDoc);
|
|
451
|
+
if (usedPaths.has(candidate) || fs.existsSync(candidate)) {
|
|
452
|
+
throw new Error(`"${cloudDoc.title}" belongs at ${path.relative(path.dirname(requirementsDir), candidate)}, but another file is already there.`);
|
|
453
|
+
}
|
|
454
|
+
return candidate;
|
|
455
|
+
}
|
|
456
|
+
if (!isRequirementsDoc) {
|
|
457
|
+
throw new Error(`"${cloudDoc.title}" is not a requirements document and belongs to no solution, so the pull has nowhere to put it.`);
|
|
458
|
+
}
|
|
459
|
+
return resolveLocalPath(cloudDoc, existingPath, usedPaths, requirementsDir);
|
|
460
|
+
}
|
|
397
461
|
function localDelete(doc, outcome) {
|
|
398
462
|
if (!doc.filePath)
|
|
399
463
|
return;
|
package/dist/sync/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { ComparisonResult, DocumentComparison } from "./types.js";
|
|
|
6
6
|
export { compareSnapshots, duplicateIdAbortMessage, duplicateLocalDocumentIds, } from "./compare.js";
|
|
7
7
|
export { displayName, formatUnitDetail, formatVerdictLine, resolutionHint, scopeToken, } from "./render.js";
|
|
8
8
|
export { segmentBody } from "./segment.js";
|
|
9
|
-
export { acquireCloudSnapshot, acquireLocalSnapshot, type CloudAuth, readLocalDocument, } from "./snapshot.js";
|
|
9
|
+
export { acquireCloudSnapshot, acquireLocalSnapshot, type CloudAuth, foreignDocumentNotes, projectSolutions, readLocalDocument, } from "./snapshot.js";
|
|
10
10
|
export type { CloudDocument, CloudSnapshot, ComparisonResult, DocumentComparison, LocalDocument, LocalSnapshot, UnitDetail, Verdict, } from "./types.js";
|
|
11
11
|
export { verdictLabel } from "./types.js";
|
|
12
12
|
/**
|
package/dist/sync/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import * as path from "node:path";
|
|
|
6
6
|
export { compareSnapshots, duplicateIdAbortMessage, duplicateLocalDocumentIds, } from "./compare.js";
|
|
7
7
|
export { displayName, formatUnitDetail, formatVerdictLine, resolutionHint, scopeToken, } from "./render.js";
|
|
8
8
|
export { segmentBody } from "./segment.js";
|
|
9
|
-
export { acquireCloudSnapshot, acquireLocalSnapshot, readLocalDocument, } from "./snapshot.js";
|
|
9
|
+
export { acquireCloudSnapshot, acquireLocalSnapshot, foreignDocumentNotes, projectSolutions, readLocalDocument, } from "./snapshot.js";
|
|
10
10
|
export { verdictLabel } from "./types.js";
|
|
11
11
|
/**
|
|
12
12
|
* Does a document match one scope token? A token may name a local file (path or
|
package/dist/sync/publish.d.ts
CHANGED
|
@@ -32,6 +32,13 @@ export interface PublishParams {
|
|
|
32
32
|
title?: string;
|
|
33
33
|
}>;
|
|
34
34
|
runMarker?: string;
|
|
35
|
+
/** SOLDOC-4/5: the belonging the file declares. */
|
|
36
|
+
solution?: {
|
|
37
|
+
solutionId: string;
|
|
38
|
+
outcome: string;
|
|
39
|
+
};
|
|
40
|
+
/** SOLDOC-3: what the file's name says; undefined where the rule doesn't reach. */
|
|
41
|
+
isRequirementsDoc?: boolean;
|
|
35
42
|
}
|
|
36
43
|
/**
|
|
37
44
|
* What the server reports back: the document, any run-marker complaint, and any
|
package/dist/sync/segment.js
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
* normalized text (prose has no stable id, so a reworded passage reads as a
|
|
7
7
|
* removal-plus-addition — a conflict, per DIFF-4.3).
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
// From the fs-free modules, not the schema index, so the backend can bundle
|
|
10
|
+
// the comparator for merging a solution's branch (BRANCH-7).
|
|
11
|
+
import { getAllRequirements, parseRequirementBlock, splitRequirementFenceContent, } from "../schema/parser-core.js";
|
|
12
|
+
import { canonicalRequirementKey, canonicalRequirementPath, } from "../schema/schemas.js";
|
|
10
13
|
/** Matches a fenced dotrequirements block; group 1 is its inner content. */
|
|
11
14
|
const FENCE = /```dotrequirements\n([\s\S]*?)```/gm;
|
|
12
15
|
/**
|
package/dist/sync/snapshot.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* the comparator stays a pure function (compare.ts). The local half reads the
|
|
4
4
|
* workspace; the cloud half is one export query.
|
|
5
5
|
*/
|
|
6
|
+
import type { SolutionForSync } from "./solution-documents.js";
|
|
6
7
|
import type { CloudSnapshot, LocalDocument, LocalSnapshot } from "./types.js";
|
|
7
8
|
/**
|
|
8
9
|
* Read and classify one requirements file into a LocalDocument. A file whose
|
|
@@ -15,7 +16,21 @@ export declare function readLocalDocument(filePath: string): LocalDocument;
|
|
|
15
16
|
* Build the local snapshot from the workspace, or from an explicit set of file
|
|
16
17
|
* paths (scope). Files are always read fresh from disk.
|
|
17
18
|
*/
|
|
18
|
-
export declare function acquireLocalSnapshot(workspaceRoot: string, filePaths?: string[]
|
|
19
|
+
export declare function acquireLocalSnapshot(workspaceRoot: string, filePaths?: string[], options?: {
|
|
20
|
+
solutions?: boolean;
|
|
21
|
+
}): Promise<LocalSnapshot>;
|
|
22
|
+
/**
|
|
23
|
+
* The project's solutions as the sync places files by them (SOLDOC-4), or
|
|
24
|
+
* null when the project's team doesn't have solutions, so the sync behaves
|
|
25
|
+
* as it did before solutions (SOLACCESS-2.2). Whether it has them is the
|
|
26
|
+
* export's answer — the one the cloud side was read with — so the local
|
|
27
|
+
* side can't follow a different one. A share run places nothing, so it
|
|
28
|
+
* needs no list. A failure to fetch the list fails the sync, as does a
|
|
29
|
+
* switch flipped between the two reads: guessing would leave solution
|
|
30
|
+
* documents out of the repo's side, and a repo-wins sync would delete them
|
|
31
|
+
* from the cloud.
|
|
32
|
+
*/
|
|
33
|
+
export declare function projectSolutions(auth: CloudAuth, cloud: CloudSnapshot): Promise<SolutionForSync[] | null>;
|
|
19
34
|
export interface CloudAuth {
|
|
20
35
|
/** projectSlug + projectSecret for full access, or a bare share token. */
|
|
21
36
|
projectSlug?: string;
|
|
@@ -27,4 +42,11 @@ export interface CloudAuth {
|
|
|
27
42
|
* names the project) — the read-only path never writes back.
|
|
28
43
|
*/
|
|
29
44
|
export declare function acquireCloudSnapshot(auth: CloudAuth): Promise<CloudSnapshot>;
|
|
45
|
+
/**
|
|
46
|
+
* SYNC-FAIL-5: of the ids the workspace's files carry, the ones that name
|
|
47
|
+
* another project's document, each with the words a push of that file gets,
|
|
48
|
+
* so `dotreq diff` says what `dotreq sync` will. A backend that can't answer
|
|
49
|
+
* leaves the diff as it was rather than failing it.
|
|
50
|
+
*/
|
|
51
|
+
export declare function foreignDocumentNotes(auth: CloudAuth, documentIds: string[]): Promise<Map<string, string>>;
|
|
30
52
|
//# sourceMappingURL=snapshot.d.ts.map
|
package/dist/sync/snapshot.js
CHANGED
|
@@ -8,7 +8,7 @@ import { ConvexHttpClient } from "convex/browser";
|
|
|
8
8
|
import YAML from "yaml";
|
|
9
9
|
import { convexUrl } from "../cloud.js";
|
|
10
10
|
import { api } from "../convex.js";
|
|
11
|
-
import { findRequirementsFiles } from "../requirements/index.js";
|
|
11
|
+
import { findRequirementsFiles, findSyncedFiles, } from "../requirements/index.js";
|
|
12
12
|
import { splitLeadingH1, validateMetadata } from "../schema/index.js";
|
|
13
13
|
import { parseRequirementBlocksFromMarkdown, splitFrontmatter, stripFrontmatterBlock, } from "../schema/parser-core.js";
|
|
14
14
|
/**
|
|
@@ -33,6 +33,8 @@ export function readLocalDocument(filePath) {
|
|
|
33
33
|
let title;
|
|
34
34
|
let defaultPrefix;
|
|
35
35
|
let attachments;
|
|
36
|
+
let solution;
|
|
37
|
+
let outcome;
|
|
36
38
|
let frontmatterError;
|
|
37
39
|
const split = splitFrontmatter(raw);
|
|
38
40
|
if (split) {
|
|
@@ -57,6 +59,11 @@ export function readLocalDocument(filePath) {
|
|
|
57
59
|
title = d.title;
|
|
58
60
|
if (typeof d.defaultPrefix === "string")
|
|
59
61
|
defaultPrefix = d.defaultPrefix;
|
|
62
|
+
// SOLDOC-5: the belonging, read like the id — before validation.
|
|
63
|
+
if (typeof d.solution === "string")
|
|
64
|
+
solution = d.solution;
|
|
65
|
+
if (typeof d.outcome === "string")
|
|
66
|
+
outcome = d.outcome;
|
|
60
67
|
// ATTACH-10.1: attachments from frontmatter. Shape-filtered here for
|
|
61
68
|
// the same reason as the fields above; a malformed entry is caught by
|
|
62
69
|
// validateMetadata below and flags the file rather than half-syncing.
|
|
@@ -108,6 +115,8 @@ export function readLocalDocument(filePath) {
|
|
|
108
115
|
title: derivedTitle,
|
|
109
116
|
defaultPrefix,
|
|
110
117
|
attachments,
|
|
118
|
+
solution,
|
|
119
|
+
outcome,
|
|
111
120
|
body,
|
|
112
121
|
};
|
|
113
122
|
}
|
|
@@ -115,10 +124,44 @@ export function readLocalDocument(filePath) {
|
|
|
115
124
|
* Build the local snapshot from the workspace, or from an explicit set of file
|
|
116
125
|
* paths (scope). Files are always read fresh from disk.
|
|
117
126
|
*/
|
|
118
|
-
export async function acquireLocalSnapshot(workspaceRoot, filePaths) {
|
|
119
|
-
|
|
127
|
+
export async function acquireLocalSnapshot(workspaceRoot, filePaths, options = {}) {
|
|
128
|
+
// SOLACCESS-2.2: a project whose team doesn't have solutions syncs the
|
|
129
|
+
// files it always did — solution directories' Markdown is left alone.
|
|
130
|
+
const paths = filePaths ??
|
|
131
|
+
(options.solutions === false
|
|
132
|
+
? await findRequirementsFiles(workspaceRoot)
|
|
133
|
+
: await findSyncedFiles(workspaceRoot));
|
|
120
134
|
return { documents: paths.map(readLocalDocument) };
|
|
121
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* The project's solutions as the sync places files by them (SOLDOC-4), or
|
|
138
|
+
* null when the project's team doesn't have solutions, so the sync behaves
|
|
139
|
+
* as it did before solutions (SOLACCESS-2.2). Whether it has them is the
|
|
140
|
+
* export's answer — the one the cloud side was read with — so the local
|
|
141
|
+
* side can't follow a different one. A share run places nothing, so it
|
|
142
|
+
* needs no list. A failure to fetch the list fails the sync, as does a
|
|
143
|
+
* switch flipped between the two reads: guessing would leave solution
|
|
144
|
+
* documents out of the repo's side, and a repo-wins sync would delete them
|
|
145
|
+
* from the cloud.
|
|
146
|
+
*/
|
|
147
|
+
export async function projectSolutions(auth, cloud) {
|
|
148
|
+
if (cloud.solutions !== true)
|
|
149
|
+
return null;
|
|
150
|
+
if (!auth.projectSlug)
|
|
151
|
+
return [];
|
|
152
|
+
const client = new ConvexHttpClient(convexUrl());
|
|
153
|
+
const answer = await client.query(api.solutions.queries.forSync, {
|
|
154
|
+
projectAuth: {
|
|
155
|
+
projectSlug: auth.projectSlug,
|
|
156
|
+
projectSecret: auth.projectSecret,
|
|
157
|
+
},
|
|
158
|
+
project: auth.projectSlug,
|
|
159
|
+
});
|
|
160
|
+
if (!Array.isArray(answer)) {
|
|
161
|
+
throw new Error("The project's solutions were switched off while syncing. Run the sync again.");
|
|
162
|
+
}
|
|
163
|
+
return answer;
|
|
164
|
+
}
|
|
122
165
|
/**
|
|
123
166
|
* Build the cloud snapshot with one export query: the project's own, with a
|
|
124
167
|
* project secret, or the share endpoint, with a bare share token (the token
|
|
@@ -140,6 +183,7 @@ export async function acquireCloudSnapshot(auth) {
|
|
|
140
183
|
return {
|
|
141
184
|
projectName: result.projectName,
|
|
142
185
|
projectSlug: result.projectSlug,
|
|
186
|
+
solutions: result.solutions === true,
|
|
143
187
|
documents: result.documents.map((d) => ({
|
|
144
188
|
documentId: d.documentId,
|
|
145
189
|
title: d.title,
|
|
@@ -148,7 +192,35 @@ export async function acquireCloudSnapshot(auth) {
|
|
|
148
192
|
body: d.markdownContent,
|
|
149
193
|
version: d.version,
|
|
150
194
|
updatedAt: d.updatedAt,
|
|
195
|
+
solution: d.solution,
|
|
196
|
+
isRequirementsDoc: d.isRequirementsDoc,
|
|
151
197
|
})),
|
|
152
198
|
};
|
|
153
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* SYNC-FAIL-5: of the ids the workspace's files carry, the ones that name
|
|
202
|
+
* another project's document, each with the words a push of that file gets,
|
|
203
|
+
* so `dotreq diff` says what `dotreq sync` will. A backend that can't answer
|
|
204
|
+
* leaves the diff as it was rather than failing it.
|
|
205
|
+
*/
|
|
206
|
+
export async function foreignDocumentNotes(auth, documentIds) {
|
|
207
|
+
// A share token only syncs down, so it pushes nothing to warn about.
|
|
208
|
+
if (documentIds.length === 0 || !auth.projectSlug)
|
|
209
|
+
return new Map();
|
|
210
|
+
const client = new ConvexHttpClient(convexUrl());
|
|
211
|
+
try {
|
|
212
|
+
const foreign = (await client.query(api.documents.queries.foreignDocumentIds, {
|
|
213
|
+
projectAuth: {
|
|
214
|
+
projectSlug: auth.projectSlug,
|
|
215
|
+
projectSecret: auth.projectSecret,
|
|
216
|
+
},
|
|
217
|
+
project: auth.projectSlug,
|
|
218
|
+
documentIds,
|
|
219
|
+
}));
|
|
220
|
+
return new Map(foreign.map((f) => [f.documentId, f.message]));
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return new Map();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
154
226
|
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a solution's documents live, the sync's half (SOLDOC; the decision
|
|
3
|
+
* is in docs/working/four-areas-prototype.md, "Where a solution's documents
|
|
4
|
+
* live"). A document that belongs to a solution and is not a requirements
|
|
5
|
+
* document lives in a solution directory, `.requirements/solutions/<solution>/`,
|
|
6
|
+
* named for its outcome; the `.requirements.md` name is what makes a file a
|
|
7
|
+
* requirements document, wherever it sits. A new file declares its belonging
|
|
8
|
+
* by its path; once the frontmatter carries it, the frontmatter is the truth.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SOLUTIONS_DIR = "solutions";
|
|
11
|
+
/** What a file's place in the workspace says about it, before any frontmatter. */
|
|
12
|
+
export interface PathClaim {
|
|
13
|
+
/** The solution directory's name and the file's stem, as slugs. */
|
|
14
|
+
solutionSlug: string;
|
|
15
|
+
outcomeSlug: string;
|
|
16
|
+
}
|
|
17
|
+
/** The solution directory a file sits directly in, if any (SOLDOC-8.1). */
|
|
18
|
+
export declare function solutionDirOf(filePath: string): PathClaim | undefined;
|
|
19
|
+
/** `pitch` for `pitch.md` and for `pitch.requirements.md`. */
|
|
20
|
+
export declare function stemOf(fileName: string): string;
|
|
21
|
+
/** SOLDOC-3: the name, never the content. Undefined for a file the rule doesn't reach. */
|
|
22
|
+
export declare function requirementsDocByName(filePath: string): boolean | undefined;
|
|
23
|
+
export interface SolutionForSync {
|
|
24
|
+
solutionId: string;
|
|
25
|
+
title: string;
|
|
26
|
+
/**
|
|
27
|
+
* The solution's directory name, which no other solution in the project
|
|
28
|
+
* has (SOLDOC-9). A backend from before it was sent leaves it out, and the
|
|
29
|
+
* title's slug stands in.
|
|
30
|
+
*/
|
|
31
|
+
directory?: string;
|
|
32
|
+
outcomes: string[];
|
|
33
|
+
}
|
|
34
|
+
/** The directory a solution's documents live in, by name. */
|
|
35
|
+
export declare function directoryOf(solution: SolutionForSync): string;
|
|
36
|
+
export interface Belonging {
|
|
37
|
+
solutionId: string;
|
|
38
|
+
outcome: string;
|
|
39
|
+
}
|
|
40
|
+
export type Resolved = {
|
|
41
|
+
belonging: Belonging;
|
|
42
|
+
warning?: string;
|
|
43
|
+
} | {
|
|
44
|
+
belonging: undefined;
|
|
45
|
+
warning?: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* What a pushed file belongs to (SOLDOC-4, SOLDOC-5): the frontmatter's
|
|
49
|
+
* belonging when it has one, else what its path claims, resolved against
|
|
50
|
+
* the project's solutions. A frontmatter that disagrees with the path is
|
|
51
|
+
* kept and reported; a path that resolves to nothing refuses the push.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveBelonging(filePath: string, frontmatter: {
|
|
54
|
+
solution?: string;
|
|
55
|
+
outcome?: string;
|
|
56
|
+
}, claim: PathClaim | undefined, solutions: SolutionForSync[] | undefined): Resolved;
|
|
57
|
+
/**
|
|
58
|
+
* SOLDOC-6, SOLDOC-9: where a pulled document that belongs to a solution
|
|
59
|
+
* lands when it has no file yet: in the solution's own directory, named for
|
|
60
|
+
* its outcome, with the `.requirements.md` name when it is a requirements
|
|
61
|
+
* document.
|
|
62
|
+
*/
|
|
63
|
+
export declare function solutionDocumentPath(requirementsDir: string, solutionDirectory: string, outcome: string, isRequirementsDoc: boolean): string;
|
|
64
|
+
//# sourceMappingURL=solution-documents.d.ts.map
|