@deskwork/core 0.45.1 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/config.d.ts +14 -4
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +43 -12
  4. package/dist/config.js.map +1 -1
  5. package/dist/content-index.d.ts +25 -0
  6. package/dist/content-index.d.ts.map +1 -1
  7. package/dist/content-index.js +142 -15
  8. package/dist/content-index.js.map +1 -1
  9. package/dist/doctor/index.d.ts +3 -0
  10. package/dist/doctor/index.d.ts.map +1 -1
  11. package/dist/doctor/index.js +3 -0
  12. package/dist/doctor/index.js.map +1 -1
  13. package/dist/doctor/legacy-config.d.ts +98 -0
  14. package/dist/doctor/legacy-config.d.ts.map +1 -0
  15. package/dist/doctor/legacy-config.js +174 -0
  16. package/dist/doctor/legacy-config.js.map +1 -0
  17. package/dist/doctor/project-scope-gate.d.ts +12 -21
  18. package/dist/doctor/project-scope-gate.d.ts.map +1 -1
  19. package/dist/doctor/project-scope-gate.js +13 -25
  20. package/dist/doctor/project-scope-gate.js.map +1 -1
  21. package/dist/doctor/repair.d.ts +11 -0
  22. package/dist/doctor/repair.d.ts.map +1 -1
  23. package/dist/doctor/repair.js +10 -89
  24. package/dist/doctor/repair.js.map +1 -1
  25. package/dist/doctor/rules/duplicate-id.d.ts +7 -2
  26. package/dist/doctor/rules/duplicate-id.d.ts.map +1 -1
  27. package/dist/doctor/rules/duplicate-id.js +8 -5
  28. package/dist/doctor/rules/duplicate-id.js.map +1 -1
  29. package/dist/doctor/rules/duplicate-id.ts +8 -5
  30. package/dist/doctor/rules/legacy-top-level-id-migration.d.ts.map +1 -1
  31. package/dist/doctor/rules/legacy-top-level-id-migration.js +11 -8
  32. package/dist/doctor/rules/legacy-top-level-id-migration.js.map +1 -1
  33. package/dist/doctor/rules/legacy-top-level-id-migration.ts +10 -11
  34. package/dist/doctor/rules/sites-to-lanes-migration.d.ts +39 -0
  35. package/dist/doctor/rules/sites-to-lanes-migration.d.ts.map +1 -0
  36. package/dist/doctor/rules/sites-to-lanes-migration.js +395 -0
  37. package/dist/doctor/rules/sites-to-lanes-migration.js.map +1 -0
  38. package/dist/doctor/rules/sites-to-lanes-migration.ts +449 -0
  39. package/dist/doctor/rules/workflow-stale.d.ts.map +1 -1
  40. package/dist/doctor/rules/workflow-stale.js +5 -2
  41. package/dist/doctor/rules/workflow-stale.js.map +1 -1
  42. package/dist/doctor/rules/workflow-stale.ts +5 -1
  43. package/dist/doctor/runner.d.ts +15 -1
  44. package/dist/doctor/runner.d.ts.map +1 -1
  45. package/dist/doctor/runner.js +48 -41
  46. package/dist/doctor/runner.js.map +1 -1
  47. package/dist/doctor/sites-migration-backfill.d.ts +71 -0
  48. package/dist/doctor/sites-migration-backfill.d.ts.map +1 -0
  49. package/dist/doctor/sites-migration-backfill.js +164 -0
  50. package/dist/doctor/sites-migration-backfill.js.map +1 -0
  51. package/dist/doctor/validate.d.ts.map +1 -1
  52. package/dist/doctor/validate.js +34 -73
  53. package/dist/doctor/validate.js.map +1 -1
  54. package/dist/entry/resolve-artifact.d.ts +80 -0
  55. package/dist/entry/resolve-artifact.d.ts.map +1 -0
  56. package/dist/entry/resolve-artifact.js +102 -0
  57. package/dist/entry/resolve-artifact.js.map +1 -0
  58. package/dist/entry/shortform-path.d.ts +34 -0
  59. package/dist/entry/shortform-path.d.ts.map +1 -0
  60. package/dist/entry/shortform-path.js +50 -0
  61. package/dist/entry/shortform-path.js.map +1 -0
  62. package/dist/index.d.ts +1 -2
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +1 -2
  65. package/dist/index.js.map +1 -1
  66. package/dist/iterate/iterate.d.ts.map +1 -1
  67. package/dist/iterate/iterate.js +21 -26
  68. package/dist/iterate/iterate.js.map +1 -1
  69. package/dist/lanes/bootstrap.d.ts +11 -7
  70. package/dist/lanes/bootstrap.d.ts.map +1 -1
  71. package/dist/lanes/bootstrap.js +42 -17
  72. package/dist/lanes/bootstrap.js.map +1 -1
  73. package/dist/lanes/index.d.ts +1 -0
  74. package/dist/lanes/index.d.ts.map +1 -1
  75. package/dist/lanes/index.js +6 -0
  76. package/dist/lanes/index.js.map +1 -1
  77. package/dist/lanes/loader.d.ts +33 -6
  78. package/dist/lanes/loader.d.ts.map +1 -1
  79. package/dist/lanes/loader.js +44 -11
  80. package/dist/lanes/loader.js.map +1 -1
  81. package/dist/lanes/operations/create.d.ts +11 -2
  82. package/dist/lanes/operations/create.d.ts.map +1 -1
  83. package/dist/lanes/operations/create.js +15 -4
  84. package/dist/lanes/operations/create.js.map +1 -1
  85. package/dist/lanes/operations/list.d.ts +3 -2
  86. package/dist/lanes/operations/list.d.ts.map +1 -1
  87. package/dist/lanes/operations/list.js +3 -2
  88. package/dist/lanes/operations/list.js.map +1 -1
  89. package/dist/lanes/operations/move.d.ts +29 -25
  90. package/dist/lanes/operations/move.d.ts.map +1 -1
  91. package/dist/lanes/operations/move.js +45 -242
  92. package/dist/lanes/operations/move.js.map +1 -1
  93. package/dist/lanes/operations/update.d.ts +15 -5
  94. package/dist/lanes/operations/update.d.ts.map +1 -1
  95. package/dist/lanes/operations/update.js +32 -12
  96. package/dist/lanes/operations/update.js.map +1 -1
  97. package/dist/lanes/scaffold-path.d.ts +88 -0
  98. package/dist/lanes/scaffold-path.d.ts.map +1 -0
  99. package/dist/lanes/scaffold-path.js +122 -0
  100. package/dist/lanes/scaffold-path.js.map +1 -0
  101. package/dist/lanes/types.d.ts +54 -31
  102. package/dist/lanes/types.d.ts.map +1 -1
  103. package/dist/lanes/types.js +60 -21
  104. package/dist/lanes/types.js.map +1 -1
  105. package/dist/outline-split.d.ts +2 -3
  106. package/dist/outline-split.d.ts.map +1 -1
  107. package/dist/outline-split.js +2 -3
  108. package/dist/outline-split.js.map +1 -1
  109. package/dist/paths.d.ts +14 -87
  110. package/dist/paths.d.ts.map +1 -1
  111. package/dist/paths.js +21 -131
  112. package/dist/paths.js.map +1 -1
  113. package/dist/remark-strip-outline.mjs +2 -3
  114. package/dist/rename-slug.d.ts +3 -3
  115. package/dist/rename-slug.d.ts.map +1 -1
  116. package/dist/rename-slug.js +137 -44
  117. package/dist/rename-slug.js.map +1 -1
  118. package/dist/review/handlers.d.ts +3 -3
  119. package/dist/review/handlers.d.ts.map +1 -1
  120. package/dist/review/handlers.js +18 -14
  121. package/dist/review/handlers.js.map +1 -1
  122. package/dist/review/report.d.ts +13 -2
  123. package/dist/review/report.d.ts.map +1 -1
  124. package/dist/review/report.js +48 -18
  125. package/dist/review/report.js.map +1 -1
  126. package/dist/review/start-handlers.d.ts +4 -4
  127. package/dist/review/start-handlers.d.ts.map +1 -1
  128. package/dist/review/start-handlers.js +25 -25
  129. package/dist/review/start-handlers.js.map +1 -1
  130. package/dist/review/workflow-paths.d.ts +24 -26
  131. package/dist/review/workflow-paths.d.ts.map +1 -1
  132. package/dist/review/workflow-paths.js +70 -60
  133. package/dist/review/workflow-paths.js.map +1 -1
  134. package/dist/schema/draft-annotation.d.ts +8 -8
  135. package/dist/schema/entry.d.ts +6 -6
  136. package/dist/schema/journal-events.d.ts +56 -42
  137. package/dist/schema/journal-events.d.ts.map +1 -1
  138. package/dist/schema/journal-events.js +23 -9
  139. package/dist/schema/journal-events.js.map +1 -1
  140. package/dist/sidecar/read.d.ts +8 -0
  141. package/dist/sidecar/read.d.ts.map +1 -1
  142. package/dist/sidecar/read.js +36 -9
  143. package/dist/sidecar/read.js.map +1 -1
  144. package/dist/sidecar/write.d.ts +14 -0
  145. package/dist/sidecar/write.d.ts.map +1 -1
  146. package/dist/sidecar/write.js +25 -0
  147. package/dist/sidecar/write.js.map +1 -1
  148. package/package.json +9 -9
  149. package/dist/body-state.d.ts +0 -27
  150. package/dist/body-state.d.ts.map +0 -1
  151. package/dist/body-state.js +0 -62
  152. package/dist/body-state.js.map +0 -1
  153. package/dist/scaffold.d.ts +0 -67
  154. package/dist/scaffold.d.ts.map +0 -1
  155. package/dist/scaffold.js +0 -122
  156. package/dist/scaffold.js.map +0 -1
@@ -0,0 +1,122 @@
1
+ /**
2
+ * add-time artifactPath composition (Phase 39c-2b, sub-task b).
3
+ *
4
+ * `deskwork add --lane X [--kind markdown] [--layout L]` creates a NEW
5
+ * entry that has no `artifactPath` yet. This module composes that path
6
+ * from the lane's add-time `scaffoldDefaults` (the directory), the
7
+ * requested layout (the on-disk file shape), and the entry's slug, then
8
+ * the caller stamps the result onto the new entry's sidecar — from which
9
+ * point it is authoritative (resolution never recomputes it).
10
+ *
11
+ * MARKDOWN ONLY (operator decision): `deskwork add` supports only
12
+ * markdown entries right now — deskwork has no non-markdown materializer,
13
+ * so a non-markdown entry can't be created. {@link composeAddArtifactPath} therefore throws loudly
14
+ * for any non-markdown kind rather than composing a path that nothing
15
+ * can fulfill. The `ArtifactKind` TYPE still carries the other kinds for
16
+ * graphical-entries; only the add path gates to markdown.
17
+ *
18
+ * Per the sites→lanes retirement design (§ "add-time path composition"):
19
+ *
20
+ * directory ← lane.scaffoldDefaults['markdown'] (FAILS LOUDLY if absent)
21
+ * layout ← --layout flag, else DEFAULT_SCAFFOLD_LAYOUT (index)
22
+ * relativePath ← layoutToContentRelativePath(layout, slug)
23
+ * artifactPath ← posixJoin(directory, relativePath)
24
+ *
25
+ * POSIX join (AUDIT-40): `artifactPath` is persisted and string-compared
26
+ * against the forward-slash paths the rest of the system stores, so the
27
+ * join uses `node:path/posix` (never `node:path.join`, which yields
28
+ * backslashes on Windows).
29
+ *
30
+ * No fallback: a lane that does not declare a `scaffoldDefaults['markdown']`
31
+ * entry is an actionable operator error, not a silent default directory
32
+ * (per the project no-fallbacks rule). The thrown message names the lane
33
+ * id and how to fix it.
34
+ */
35
+ import { posix } from 'node:path';
36
+ /**
37
+ * The default layout used by `deskwork add` when `--layout` is omitted.
38
+ * `index` reproduces the legacy `{slug}/index.md` template default
39
+ * byte-for-byte — chosen for zero-behavior-change at the sites→lanes
40
+ * cutover.
41
+ *
42
+ * Per design Decision #12 this is a single GLOBAL default. (The
43
+ * superseding per-kind Decision #16 was retired alongside the multi-kind
44
+ * machinery when `add` was gated to markdown-only — a global default is
45
+ * correct again now that only one kind is supported.)
46
+ */
47
+ export const DEFAULT_SCAFFOLD_LAYOUT = 'index';
48
+ /**
49
+ * Map a {@link ScaffoldLayout} + slug to the directory-relative path for
50
+ * a MARKDOWN artifact (the only kind `deskwork add` scaffolds).
51
+ */
52
+ export function layoutToContentRelativePath(layout, slug) {
53
+ switch (layout) {
54
+ case 'index':
55
+ return `${slug}/index.md`;
56
+ case 'readme':
57
+ return `${slug}/README.md`;
58
+ case 'flat':
59
+ return `${slug}.md`;
60
+ }
61
+ }
62
+ /**
63
+ * Compose the project-relative `artifactPath` for a NEW markdown entry
64
+ * being scaffolded into a lane.
65
+ *
66
+ * @param lane - The resolved lane config the entry belongs to.
67
+ * @param kind - The entry's artifact kind. ONLY `markdown` is supported;
68
+ * any other kind throws (see module docblock — file creation for
69
+ * non-markdown kinds is not implemented).
70
+ * @param slug - The entry's slug (one or more `/`-separated kebab-case
71
+ * segments).
72
+ * @param layout - The on-disk file shape. When omitted, defaults to
73
+ * {@link DEFAULT_SCAFFOLD_LAYOUT} (`index`).
74
+ * @returns The project-root-relative path to stamp onto the entry's
75
+ * sidecar (e.g. `src/content/blog/my-post/index.md`), joined with
76
+ * forward slashes (AUDIT-40).
77
+ * @throws When `kind` is not `markdown`; or when the lane declares no
78
+ * `scaffoldDefaults['markdown']` entry.
79
+ */
80
+ export function composeAddArtifactPath(lane, kind, slug, layout) {
81
+ if (kind !== 'markdown') {
82
+ throw new Error(`deskwork add currently supports only markdown entries; artifact kind ` +
83
+ `"${kind}" is not yet supported because file creation for ` +
84
+ `non-markdown kinds is not implemented. Use --kind markdown (the ` +
85
+ `default), or omit --kind.`);
86
+ }
87
+ const directory = lane.scaffoldDefaults?.['markdown'];
88
+ if (directory === undefined) {
89
+ const declared = lane.scaffoldDefaults
90
+ ? Object.keys(lane.scaffoldDefaults).sort().join(', ') || '(none)'
91
+ : '(none)';
92
+ throw new Error(`Lane "${lane.id}" has no scaffoldDefaults entry for artifact kind ` +
93
+ `"markdown", so \`deskwork add\` cannot choose where to place the ` +
94
+ `new file. Add a default directory for markdown to the lane — e.g. ` +
95
+ `\`deskwork lane <project-root> update ${lane.id} ` +
96
+ `--scaffold-default markdown=<dir>\`. ` +
97
+ `Kinds the lane currently defines: ${declared}.`);
98
+ }
99
+ const effectiveLayout = layout ?? DEFAULT_SCAFFOLD_LAYOUT;
100
+ const relativePath = layoutToContentRelativePath(effectiveLayout, slug);
101
+ // AUDIT-40: POSIX join — persisted paths are forward-slash, compared
102
+ // string-wise against the rest of the system's stored paths.
103
+ return posix.join(directory, relativePath);
104
+ }
105
+ /**
106
+ * Narrow a raw `--layout` flag value to a {@link ScaffoldLayout}.
107
+ * Returns `undefined` for unrecognized values so the CLI caller can
108
+ * raise its own argument-shaped error (with the legal list and exit 2).
109
+ */
110
+ export function parseScaffoldLayout(value) {
111
+ if (value === 'index' || value === 'readme' || value === 'flat') {
112
+ return value;
113
+ }
114
+ return undefined;
115
+ }
116
+ /** The legal `--layout` values, for error messages. */
117
+ export const SCAFFOLD_LAYOUTS = [
118
+ 'index',
119
+ 'readme',
120
+ 'flat',
121
+ ];
122
+ //# sourceMappingURL=scaffold-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold-path.js","sourceRoot":"","sources":["../../src/lanes/scaffold-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAYlC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAmB,OAAO,CAAC;AAE/D;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAsB,EACtB,IAAY;IAEZ,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,GAAG,IAAI,WAAW,CAAC;QAC5B,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,YAAY,CAAC;QAC7B,KAAK,MAAM;YACT,OAAO,GAAG,IAAI,KAAK,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAgB,EAChB,IAAkB,EAClB,IAAY,EACZ,MAAuB;IAEvB,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,uEAAuE;YACrE,IAAI,IAAI,mDAAmD;YAC3D,kEAAkE;YAClE,2BAA2B,CAC9B,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC,UAAU,CAAC,CAAC;IACtD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB;YACpC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ;YAClE,CAAC,CAAC,QAAQ,CAAC;QACb,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,CAAC,EAAE,oDAAoD;YAClE,mEAAmE;YACnE,oEAAoE;YACpE,yCAAyC,IAAI,CAAC,EAAE,GAAG;YACnD,uCAAuC;YACvC,qCAAqC,QAAQ,GAAG,CACnD,CAAC;IACJ,CAAC;IACD,MAAM,eAAe,GAAG,MAAM,IAAI,uBAAuB,CAAC;IAC1D,MAAM,YAAY,GAAG,2BAA2B,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IACxE,qEAAqE;IACrE,6DAA6D;IAC7D,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QAChE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,gBAAgB,GAA8B;IACzD,OAAO;IACP,QAAQ;IACR,MAAM;CACP,CAAC"}
@@ -3,11 +3,14 @@
3
3
  * pipeline template.
4
4
  *
5
5
  * Lanes are the graphical-entries unit of parallel-pipeline tracking
6
- * (PRD § Lanes). A project hosts one or more lanes; each lane has its
7
- * own content directory, its own pipeline template, and its own stage
8
- * vocabulary derived from that template. Entries live inside a single
9
- * lane; the entry's sidecar carries `lane: <laneId>` to identify
10
- * membership.
6
+ * (PRD § Lanes). A project hosts one or more lanes; each lane has a
7
+ * pipeline template and a stage vocabulary derived from that template.
8
+ * A lane is a LOGICAL grouping identified by `id` — it carries NO
9
+ * location of its own. Per the sites→lanes retirement (Phase 39),
10
+ * location is a property of the ENTRY (`entry.artifactPath`), never the
11
+ * lane. A lane "spans" whatever directories/filesystems its entries
12
+ * happen to live in — emergent from the entries, not declared on the
13
+ * lane. Entries carry `lane: <laneId>` to identify membership.
11
14
  *
12
15
  * Plugin defaults: there are none. Lanes are project-owned; every lane
13
16
  * config lives under `<projectRoot>/.deskwork/lanes/<id>.json`. The
@@ -25,10 +28,19 @@
25
28
  * - `pipelineTemplate` is a non-empty string referencing a
26
29
  * PipelineTemplate id; the loader cross-validates that the
27
30
  * referenced template resolves via `loadPipelineTemplate`.
28
- * - `contentDir` is a non-empty path; relative paths are resolved
29
- * against the project root by callers, absolute paths are taken
30
- * verbatim. Doctor may normalize later; the schema enforces
31
- * non-empty only.
31
+ * - `host` (optional) present only when this lane publishes its
32
+ * content tree as a website. A lane without a host is fully valid
33
+ * (the collection model is renderer-independent). Where the host
34
+ * reads land (studio URL formatting) is a downstream concern; the
35
+ * schema only records the optional string.
36
+ * - `scaffoldDefaults` (optional) — a PARTIAL map from `ArtifactKind`
37
+ * to the directory where `/deskwork:add` drops a NEW file of that
38
+ * kind. Partial by construction: a lane defines defaults only for
39
+ * the kinds its pipeline actually scaffolds (e.g. a single-kind
40
+ * map `{ markdown: 'src/content/blog' }` validates). It is a
41
+ * convenience default used solely at add-time — NEVER identity,
42
+ * NEVER resolution. Unknown keys are rejected because the key
43
+ * schema is the `ArtifactKind` enum.
32
44
  *
33
45
  * The on-disk JSON additionally permits a top-level `"$rationale"`
34
46
  * string field as the JSON-with-comments workaround (matching the
@@ -68,25 +80,51 @@ import { z } from 'zod';
68
80
  * boundary.
69
81
  */
70
82
  export declare const LANE_ID_REGEX: RegExp;
83
+ /**
84
+ * The four artifact kinds the lane-aware entry model recognizes:
85
+ * - `markdown` — a single `.md` file (the legacy editorial
86
+ * artifact shape).
87
+ * - `html-mockup` — a directory containing `index.html` plus
88
+ * optional sibling assets (mockups / design
89
+ * specs / standalone HTML deliverables).
90
+ * - `single-file-html` — a loose `.html` file (not inside an
91
+ * html-mockup directory).
92
+ * - `image` — a raster or vector image file (.png /
93
+ * .jpg / .jpeg / .gif / .webp / .svg).
94
+ *
95
+ * Detection: see `./detection.ts` (`detectArtifactKind`).
96
+ *
97
+ * Declared ABOVE `LaneConfigSchema` so the schema's `scaffoldDefaults`
98
+ * record can key off this enum (a `z.record` over the enum is partial
99
+ * by construction — see the `scaffoldDefaults` field docblock).
100
+ */
101
+ export declare const ArtifactKindSchema: z.ZodEnum<["markdown", "html-mockup", "single-file-html", "image"]>;
102
+ export type ArtifactKind = z.infer<typeof ArtifactKindSchema>;
71
103
  export declare const LaneConfigSchema: z.ZodObject<{
72
104
  id: z.ZodString;
73
105
  name: z.ZodString;
74
106
  pipelineTemplate: z.ZodString;
75
- contentDir: z.ZodString;
107
+ host: z.ZodOptional<z.ZodString>;
108
+ redirectsPath: z.ZodOptional<z.ZodString>;
109
+ scaffoldDefaults: z.ZodOptional<z.ZodRecord<z.ZodEnum<["markdown", "html-mockup", "single-file-html", "image"]>, z.ZodString>>;
76
110
  archivedAt: z.ZodOptional<z.ZodString>;
77
111
  $rationale: z.ZodOptional<z.ZodString>;
78
112
  }, "strict", z.ZodTypeAny, {
79
113
  id: string;
80
- contentDir: string;
81
114
  name: string;
82
115
  pipelineTemplate: string;
116
+ host?: string | undefined;
117
+ redirectsPath?: string | undefined;
118
+ scaffoldDefaults?: Partial<Record<"markdown" | "html-mockup" | "single-file-html" | "image", string>> | undefined;
83
119
  archivedAt?: string | undefined;
84
120
  $rationale?: string | undefined;
85
121
  }, {
86
122
  id: string;
87
- contentDir: string;
88
123
  name: string;
89
124
  pipelineTemplate: string;
125
+ host?: string | undefined;
126
+ redirectsPath?: string | undefined;
127
+ scaffoldDefaults?: Partial<Record<"markdown" | "html-mockup" | "single-file-html" | "image", string>> | undefined;
90
128
  archivedAt?: string | undefined;
91
129
  $rationale?: string | undefined;
92
130
  }>;
@@ -96,25 +134,10 @@ export declare const LaneConfigSchema: z.ZodObject<{
96
134
  * inferred type tracks it without manual duplication.
97
135
  *
98
136
  * The schema is `.strict()`, so the inferred type lists exactly the
99
- * declared keys: `id`, `name`, `pipelineTemplate`, `contentDir`,
100
- * `archivedAt` (optional), `$rationale` (optional). Unknown top-level
101
- * keys fail parse at the schema layer (AUDIT-20260530-08 fix).
137
+ * declared keys: `id`, `name`, `pipelineTemplate`, `host` (optional),
138
+ * `scaffoldDefaults` (optional), `archivedAt` (optional), `$rationale`
139
+ * (optional). Unknown top-level keys including the retired
140
+ * `contentDir` — fail parse at the schema layer (AUDIT-20260530-08 fix).
102
141
  */
103
142
  export type LaneConfig = z.infer<typeof LaneConfigSchema>;
104
- /**
105
- * The four artifact kinds the lane-aware entry model recognizes:
106
- * - `markdown` — a single `.md` file (the legacy editorial
107
- * artifact shape).
108
- * - `html-mockup` — a directory containing `index.html` plus
109
- * optional sibling assets (mockups / design
110
- * specs / standalone HTML deliverables).
111
- * - `single-file-html` — a loose `.html` file (not inside an
112
- * html-mockup directory).
113
- * - `image` — a raster or vector image file (.png /
114
- * .jpg / .jpeg / .gif / .webp / .svg).
115
- *
116
- * Detection: see `./detection.ts` (`detectArtifactKind`).
117
- */
118
- export declare const ArtifactKindSchema: z.ZodEnum<["markdown", "html-mockup", "single-file-html", "image"]>;
119
- export type ArtifactKind = z.infer<typeof ArtifactKindSchema>;
120
143
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lanes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,QAAyB,CAAC;AAEpD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;EAclB,CAAC;AAEZ;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,qEAK7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lanes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,QAAyB,CAAC;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,qEAK7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqClB,CAAC;AAEZ;;;;;;;;;;GAUG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
@@ -3,11 +3,14 @@
3
3
  * pipeline template.
4
4
  *
5
5
  * Lanes are the graphical-entries unit of parallel-pipeline tracking
6
- * (PRD § Lanes). A project hosts one or more lanes; each lane has its
7
- * own content directory, its own pipeline template, and its own stage
8
- * vocabulary derived from that template. Entries live inside a single
9
- * lane; the entry's sidecar carries `lane: <laneId>` to identify
10
- * membership.
6
+ * (PRD § Lanes). A project hosts one or more lanes; each lane has a
7
+ * pipeline template and a stage vocabulary derived from that template.
8
+ * A lane is a LOGICAL grouping identified by `id` — it carries NO
9
+ * location of its own. Per the sites→lanes retirement (Phase 39),
10
+ * location is a property of the ENTRY (`entry.artifactPath`), never the
11
+ * lane. A lane "spans" whatever directories/filesystems its entries
12
+ * happen to live in — emergent from the entries, not declared on the
13
+ * lane. Entries carry `lane: <laneId>` to identify membership.
11
14
  *
12
15
  * Plugin defaults: there are none. Lanes are project-owned; every lane
13
16
  * config lives under `<projectRoot>/.deskwork/lanes/<id>.json`. The
@@ -25,10 +28,19 @@
25
28
  * - `pipelineTemplate` is a non-empty string referencing a
26
29
  * PipelineTemplate id; the loader cross-validates that the
27
30
  * referenced template resolves via `loadPipelineTemplate`.
28
- * - `contentDir` is a non-empty path; relative paths are resolved
29
- * against the project root by callers, absolute paths are taken
30
- * verbatim. Doctor may normalize later; the schema enforces
31
- * non-empty only.
31
+ * - `host` (optional) present only when this lane publishes its
32
+ * content tree as a website. A lane without a host is fully valid
33
+ * (the collection model is renderer-independent). Where the host
34
+ * reads land (studio URL formatting) is a downstream concern; the
35
+ * schema only records the optional string.
36
+ * - `scaffoldDefaults` (optional) — a PARTIAL map from `ArtifactKind`
37
+ * to the directory where `/deskwork:add` drops a NEW file of that
38
+ * kind. Partial by construction: a lane defines defaults only for
39
+ * the kinds its pipeline actually scaffolds (e.g. a single-kind
40
+ * map `{ markdown: 'src/content/blog' }` validates). It is a
41
+ * convenience default used solely at add-time — NEVER identity,
42
+ * NEVER resolution. Unknown keys are rejected because the key
43
+ * schema is the `ArtifactKind` enum.
32
44
  *
33
45
  * The on-disk JSON additionally permits a top-level `"$rationale"`
34
46
  * string field as the JSON-with-comments workaround (matching the
@@ -68,18 +80,6 @@ import { z } from 'zod';
68
80
  * boundary.
69
81
  */
70
82
  export const LANE_ID_REGEX = /^[a-z0-9][a-z0-9-]*$/;
71
- export const LaneConfigSchema = z.object({
72
- id: z.string().regex(LANE_ID_REGEX, 'lane id must be kebab-case [a-z0-9-], starting with [a-z0-9]'),
73
- name: z.string().min(1, 'name must be a non-empty string'),
74
- pipelineTemplate: z.string().min(1, 'pipelineTemplate must be a non-empty string'),
75
- contentDir: z.string().min(1, 'contentDir must be a non-empty string'),
76
- archivedAt: z.string().datetime().optional(),
77
- // Sole explicitly-declared "extra" key — the comments-in-JSON
78
- // workaround that mirrors PipelineTemplateSchema (AUDIT-20260530-02).
79
- // Declared so `.strict()` admits it; anything else at the top level
80
- // is rejected.
81
- $rationale: z.string().optional(),
82
- }).strict();
83
83
  /**
84
84
  * The four artifact kinds the lane-aware entry model recognizes:
85
85
  * - `markdown` — a single `.md` file (the legacy editorial
@@ -93,6 +93,10 @@ export const LaneConfigSchema = z.object({
93
93
  * .jpg / .jpeg / .gif / .webp / .svg).
94
94
  *
95
95
  * Detection: see `./detection.ts` (`detectArtifactKind`).
96
+ *
97
+ * Declared ABOVE `LaneConfigSchema` so the schema's `scaffoldDefaults`
98
+ * record can key off this enum (a `z.record` over the enum is partial
99
+ * by construction — see the `scaffoldDefaults` field docblock).
96
100
  */
97
101
  export const ArtifactKindSchema = z.enum([
98
102
  'markdown',
@@ -100,4 +104,39 @@ export const ArtifactKindSchema = z.enum([
100
104
  'single-file-html',
101
105
  'image',
102
106
  ]);
107
+ export const LaneConfigSchema = z.object({
108
+ id: z.string().regex(LANE_ID_REGEX, 'lane id must be kebab-case [a-z0-9-], starting with [a-z0-9]'),
109
+ name: z.string().min(1, 'name must be a non-empty string'),
110
+ pipelineTemplate: z.string().min(1, 'pipelineTemplate must be a non-empty string'),
111
+ // NOTE: a lane carries NO location. `contentDir` was removed in
112
+ // Phase 39c (sites→lanes retirement) — location is an ENTRY property
113
+ // (`entry.artifactPath`). A lane's only location-adjacent field is the
114
+ // optional add-time `scaffoldDefaults` below, which is never identity
115
+ // and never used for resolution. Because the schema is `.strict()`, a
116
+ // legacy on-disk lane carrying `contentDir` now FAILS parse with an
117
+ // unknown-key error; the doctor migration cleans it.
118
+ // Optional — present only when this lane publishes to a website.
119
+ host: z.string().min(1, 'host must be a non-empty string when present').optional(),
120
+ // Optional — website-publishing metadata, a sibling of `host`. Path
121
+ // (relative to the project root, or absolute) to a Netlify-style
122
+ // `_redirects` file; `rename-slug` appends a 301 block here when the
123
+ // lane is configured to publish to a website. Only meaningful when the
124
+ // lane publishes a website — a lane without it is fully valid and the
125
+ // redirect-append step is simply skipped. Re-homed from the retired
126
+ // `SiteConfig.redirectsPath` in Phase 39c (sites→lanes retirement,
127
+ // spec Decision #23 — mirrors how `host` re-homed under Decision #2).
128
+ redirectsPath: z.string().min(1, 'redirectsPath must be a non-empty string when present').optional(),
129
+ // Optional, PARTIAL-by-construction map from ArtifactKind → scaffold
130
+ // directory. A single-kind map validates; unknown keys are rejected
131
+ // because the key schema is the ArtifactKind enum. Used solely at
132
+ // add-time to choose where a NEW file lands — never identity, never
133
+ // resolution.
134
+ scaffoldDefaults: z.record(ArtifactKindSchema, z.string().min(1)).optional(),
135
+ archivedAt: z.string().datetime().optional(),
136
+ // Sole explicitly-declared "extra" key — the comments-in-JSON
137
+ // workaround that mirrors PipelineTemplateSchema (AUDIT-20260530-02).
138
+ // Declared so `.strict()` admits it; anything else at the top level
139
+ // is rejected.
140
+ $rationale: z.string().optional(),
141
+ }).strict();
103
142
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lanes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAEpD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAClB,aAAa,EACb,8DAA8D,CAC/D;IACD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,iCAAiC,CAAC;IAC1D,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,6CAA6C,CAAC;IAClF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,uCAAuC,CAAC;IACtE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC5C,8DAA8D;IAC9D,sEAAsE;IACtE,oEAAoE;IACpE,eAAe;IACf,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC,MAAM,EAAE,CAAC;AAcZ;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC;IACvC,UAAU;IACV,aAAa;IACb,kBAAkB;IAClB,OAAO;CACR,CAAC,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lanes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;GAYG;AACH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,sBAAsB,CAAC;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC;IACvC,UAAU;IACV,aAAa;IACb,kBAAkB;IAClB,OAAO;CACR,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAClB,aAAa,EACb,8DAA8D,CAC/D;IACD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,iCAAiC,CAAC;IAC1D,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,6CAA6C,CAAC;IAClF,gEAAgE;IAChE,qEAAqE;IACrE,uEAAuE;IACvE,sEAAsE;IACtE,sEAAsE;IACtE,oEAAoE;IACpE,qDAAqD;IACrD,iEAAiE;IACjE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,8CAA8C,CAAC,CAAC,QAAQ,EAAE;IAClF,oEAAoE;IACpE,iEAAiE;IACjE,qEAAqE;IACrE,uEAAuE;IACvE,sEAAsE;IACtE,oEAAoE;IACpE,mEAAmE;IACnE,sEAAsE;IACtE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,uDAAuD,CAAC,CAAC,QAAQ,EAAE;IACpG,qEAAqE;IACrE,oEAAoE;IACpE,kEAAkE;IAClE,oEAAoE;IACpE,cAAc;IACd,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5E,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC5C,8DAA8D;IAC9D,sEAAsE;IACtE,oEAAoE;IACpE,eAAe;IACf,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC,MAAM,EAAE,CAAC"}
@@ -17,9 +17,8 @@ export interface SplitOutline {
17
17
  * prepended to `body`; anything after is appended. Rejoin via
18
18
  * `joinOutline`.
19
19
  *
20
- * This mirrors the line-wise logic in `scripts/lib/editorial/
21
- * body-state.ts` (kept separate so the browser-side bundle
22
- * doesn't have to drag in the server's fs/path imports).
20
+ * Kept as a standalone line-wise helper so the browser-side bundle
21
+ * doesn't have to drag in the server's fs/path imports.
23
22
  */
24
23
  export declare function splitOutline(md: string): SplitOutline;
25
24
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"outline-split.d.ts","sourceRoot":"","sources":["../src/outline-split.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAgBrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAoBjE"}
1
+ {"version":3,"file":"outline-split.d.ts","sourceRoot":"","sources":["../src/outline-split.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,OAAO,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAgBrD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAoBjE"}
@@ -26,9 +26,8 @@
26
26
  * prepended to `body`; anything after is appended. Rejoin via
27
27
  * `joinOutline`.
28
28
  *
29
- * This mirrors the line-wise logic in `scripts/lib/editorial/
30
- * body-state.ts` (kept separate so the browser-side bundle
31
- * doesn't have to drag in the server's fs/path imports).
29
+ * Kept as a standalone line-wise helper so the browser-side bundle
30
+ * doesn't have to drag in the server's fs/path imports.
32
31
  */
33
32
  export function splitOutline(md) {
34
33
  const lines = md.split('\n');
@@ -1 +1 @@
1
- {"version":3,"file":"outline-split.js","sourceRoot":"","sources":["../src/outline-split.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAeH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC;IAC/E,CAAC;IACD,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,MAAM,GAAG,CAAC,CAAC;YACX,MAAM;QACR,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAChF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,IAAY;IACvD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,2DAA2D;QAC3D,wDAAwD;QACxD,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACxD,OAAO,GAAG,IAAI,GAAG,eAAe,KAAK,cAAc,IAAI,CAAC;IAC1D,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,2DAA2D;IAC3D,2DAA2D;IAC3D,uCAAuC;IACvC,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QAC7D,MAAM,CAAC,GAAG,EAAE,CAAC;IACf,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"outline-split.js","sourceRoot":"","sources":["../src/outline-split.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAeH;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC;IAC/E,CAAC;IACD,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,MAAM,GAAG,CAAC,CAAC;YACX,MAAM;QACR,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAChF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,IAAY;IACvD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAChB,2DAA2D;QAC3D,wDAAwD;QACxD,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACxD,OAAO,GAAG,IAAI,GAAG,eAAe,KAAK,cAAc,IAAI,CAAC;IAC1D,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,2DAA2D;IAC3D,2DAA2D;IAC3D,uCAAuC;IACvC,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QAC7D,MAAM,CAAC,GAAG,EAAE,CAAC;IACf,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClE,CAAC"}
package/dist/paths.d.ts CHANGED
@@ -26,7 +26,6 @@
26
26
  */
27
27
  import type { DeskworkConfig } from './config.ts';
28
28
  import type { ContentIndex } from './content-index.ts';
29
- import type { Platform } from './types.ts';
30
29
  /**
31
30
  * Resolve a user-supplied site argument to a configured site slug.
32
31
  *
@@ -34,26 +33,22 @@ import type { Platform } from './types.ts';
34
33
  * An unknown value throws with the list of configured sites.
35
34
  */
36
35
  export declare function resolveSite(config: DeskworkConfig, site: string | null | undefined): string;
37
- /** Absolute path to the site's editorial calendar file. */
38
- export declare function resolveCalendarPath(projectRoot: string, config: DeskworkConfig, site?: string | null): string;
39
- /** Absolute path to the site's channels file, or undefined when the site declares none. */
40
- export declare function resolveChannelsPath(projectRoot: string, config: DeskworkConfig, site?: string | null): string | undefined;
41
- /** Absolute path to the site's blog content directory. */
42
- export declare function resolveContentDir(projectRoot: string, config: DeskworkConfig, site?: string | null): string;
43
- /**
44
- * Bare public hostname for the site (no protocol). Returns `undefined` for
45
- * collections that aren't published as a website (no `host` configured).
46
- * Callers needing a non-undefined value for display should fall back to the
47
- * site slug; callers needing a real URL should throw if undefined.
48
- */
49
- export declare function resolveSiteHost(config: DeskworkConfig, site?: string | null): string | undefined;
50
36
  /**
51
- * Canonical public base URL for the site, with trailing slash. Throws when
52
- * the collection has no `host` configured (i.e. is not published as a
53
- * website) callers that need a URL must guarantee the collection is a
54
- * website-rendered one before calling.
37
+ * Absolute path to the project's editorial calendar file.
38
+ *
39
+ * Phase 39c (sites→lanes retirement) the calendar is a single,
40
+ * project-level derived projection from sidecars (spec §"Calendar"). The
41
+ * legacy per-site `calendarPath` is retired; there is one calendar at
42
+ * `.deskwork/calendar.md`. The `config`/`site` parameters are retained so
43
+ * call sites (and the CLI-verb resolution path, scoped to 39c-2b) need
44
+ * not change in lockstep — the de-parameterization is internal. Both are
45
+ * intentionally ignored. Closes #234 (divergence), #357 (read-side
46
+ * validator), #223 (regen flip-flop) per spec §"Inherited calendar-surface
47
+ * cluster".
55
48
  */
56
- export declare function resolveSiteBaseUrl(config: DeskworkConfig, site?: string | null): string;
49
+ export declare function resolveCalendarPath(projectRoot: string, _config: DeskworkConfig, _site?: string | null): string;
50
+ /** Absolute path to the site's blog content directory. */
51
+ export declare function resolveContentDir(projectRoot: string, config: DeskworkConfig, site?: string | null): string;
57
52
  /**
58
53
  * Absolute path to the blog post markdown for a given slug.
59
54
  *
@@ -112,72 +107,4 @@ export declare function resolveBlogPostDir(projectRoot: string, config: Deskwork
112
107
  export declare function findEntryFile(projectRoot: string, config: DeskworkConfig, site: string | null | undefined, entryId: string, index?: ContentIndex, legacyEntryForFallback?: {
113
108
  slug: string;
114
109
  }): string | undefined;
115
- /**
116
- * Resolve the markdown file backing a calendar entry, preferring the
117
- * UUID frontmatter binding (refactor-proof) and falling back to the
118
- * site's slug-template only when no binding exists.
119
- *
120
- * Equivalent to the studio's `resolveLongformFilePath` but exposed as a
121
- * top-level helper from `paths.ts` so CLI commands can use it without
122
- * pulling in `review/` infrastructure. Always returns an absolute path
123
- * (the slug-template fallback is unconditional); callers should
124
- * `existsSync` if they need an existence guarantee.
125
- *
126
- * Precedence:
127
- * 1. Content index — when `entryId` is supplied (and non-empty), look
128
- * up the file whose frontmatter `deskwork.id:` matches. Refactor-
129
- * proof: the binding follows the file regardless of slug rename or
130
- * directory relocation.
131
- * 2. Slug-template fallback — when the index has no record (entry's
132
- * file isn't bound to frontmatter yet, e.g. pre-doctor / pre-ingest
133
- * state) or no `entryId` was supplied, fall back to
134
- * `resolveBlogFilePath(slug)`.
135
- *
136
- * @param projectRoot Absolute path to the deskwork project root.
137
- * @param config Loaded deskwork config.
138
- * @param site Site slug (or null/undefined for the default site).
139
- * @param slug Calendar entry slug — used both as the legacy fallback
140
- * template input and as a hint for the slug-template fallback.
141
- * @param entryId Calendar entry's stable UUID. When omitted or empty,
142
- * resolution falls straight through to the slug template.
143
- * @param index Pre-built content index. When omitted, this function
144
- * builds one. Pass the per-request memoized index when
145
- * calling from the studio; let the CLI build per call.
146
- */
147
- export declare function resolveEntryFilePath(projectRoot: string, config: DeskworkConfig, site: string | null | undefined, slug: string, entryId?: string, index?: ContentIndex): string;
148
- /**
149
- * Resolve the markdown file path for a shortform draft.
150
- *
151
- * <contentDir>/<entry-dir>/scrapbook/shortform/<platform>[-<channel>].md
152
- *
153
- * Platform is the lowercase Platform value. Channel (if present) is appended
154
- * as `-<channel>`. Channel must validate against the kebab-case regex —
155
- * deskwork stores channels as kebab-case strings throughout.
156
- *
157
- * The entry directory is resolved through `findEntryFile` (id-driven,
158
- * refactor-proof) with slug-template fallback for legacy entries created
159
- * pre-doctor. The slug-template fallback is intentional migration logic so
160
- * pre-bind entries keep working.
161
- *
162
- * Forward-compatibility: every reference to the shortform file location
163
- * goes through this function. Phase 20 (sandbox migration) redirects this
164
- * single function; everything downstream (handlers, CLI, studio) works
165
- * unchanged.
166
- *
167
- * @param projectRoot Absolute path to the deskwork project root.
168
- * @param config Loaded deskwork config.
169
- * @param site Site slug (or null/undefined for the default site).
170
- * @param entry Calendar entry — `id` preferred, `slug` used both as the
171
- * legacy fallback and to identify the entry directory.
172
- * @param platform Which distribution platform.
173
- * @param channel Optional sub-channel (e.g. `synthdiy` for r/synthdiy).
174
- * Must be kebab-case.
175
- * @param index Optional pre-built content index (per-request memoization).
176
- * @returns absolute file path, or undefined when neither the index nor the
177
- * slug-template fallback resolves the entry's directory.
178
- */
179
- export declare function resolveShortformFilePath(projectRoot: string, config: DeskworkConfig, site: string, entry: {
180
- id?: string;
181
- slug: string;
182
- }, platform: Platform, channel?: string, index?: ContentIndex): string | undefined;
183
110
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC9B,MAAM,CAYR;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,cAAc,EACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACpB,MAAM,CAER;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,MAAM,CAER;AAUD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAOR;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,IAAI,EAAE,MAAM,GACX,MAAM,CAER;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,YAAY,EACpB,sBAAsB,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GACxC,MAAM,GAAG,SAAS,CAepB"}