gutterpress 0.0.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 (230) hide show
  1. package/README.md +422 -0
  2. package/dist/CGATS21_CRPC1-g0e3k7kr.icc +0 -0
  3. package/dist/api/index.d.ts +76 -0
  4. package/dist/api/index.js +272 -0
  5. package/dist/assets/preview/scripts/pagedjs-bridge.d.ts +1 -0
  6. package/dist/assets/preview/scripts/pagedjs-interface.d.ts +1 -0
  7. package/dist/assets/preview/scripts/preview-shell.d.ts +1 -0
  8. package/dist/audit-1jrwwacz.js +66 -0
  9. package/dist/build-5s92kgpc.js +77 -0
  10. package/dist/chapter-01-6fn9pvd0.md +31 -0
  11. package/dist/chapter-01-7jwqg1ct.md +20 -0
  12. package/dist/chapter-01-jj8ftn4c.md +29 -0
  13. package/dist/chapter-01-rkpyvjna.md +26 -0
  14. package/dist/checks/asset/approved-fonts.d.ts +3 -0
  15. package/dist/checks/asset/extensions.d.ts +41 -0
  16. package/dist/checks/asset/font-license.d.ts +3 -0
  17. package/dist/checks/asset/image-alpha.d.ts +3 -0
  18. package/dist/checks/asset/image-color-space.d.ts +3 -0
  19. package/dist/checks/asset/image-file-size.d.ts +3 -0
  20. package/dist/checks/asset/image-resolution.d.ts +3 -0
  21. package/dist/checks/asset/image-tac.d.ts +3 -0
  22. package/dist/checks/asset/index.d.ts +7 -0
  23. package/dist/checks/formatter.d.ts +3 -0
  24. package/dist/checks/heuristic/index.d.ts +4 -0
  25. package/dist/checks/heuristic/layer-count.d.ts +3 -0
  26. package/dist/checks/heuristic/placement-variance.d.ts +3 -0
  27. package/dist/checks/heuristic/section-density.d.ts +3 -0
  28. package/dist/checks/heuristic/text-density.d.ts +3 -0
  29. package/dist/checks/pdf/bleed.d.ts +3 -0
  30. package/dist/checks/pdf/bookmarks.d.ts +3 -0
  31. package/dist/checks/pdf/color-spaces.d.ts +3 -0
  32. package/dist/checks/pdf/cross-refs.d.ts +3 -0
  33. package/dist/checks/pdf/embedded-fonts.d.ts +3 -0
  34. package/dist/checks/pdf/image-resolution.d.ts +3 -0
  35. package/dist/checks/pdf/index.d.ts +15 -0
  36. package/dist/checks/pdf/ink-coverage.d.ts +3 -0
  37. package/dist/checks/pdf/page-labels.d.ts +3 -0
  38. package/dist/checks/pdf/page-size.d.ts +3 -0
  39. package/dist/checks/pdf/pdfx-markers.d.ts +3 -0
  40. package/dist/checks/pdf/pdfx-metadata.d.ts +3 -0
  41. package/dist/checks/pdf/pdfx-structure.d.ts +6 -0
  42. package/dist/checks/pdf/qpdf-structure.d.ts +3 -0
  43. package/dist/checks/pdf/rasterized-pages.d.ts +3 -0
  44. package/dist/checks/pdf/toc-links.d.ts +3 -0
  45. package/dist/checks/pdf/transparency.d.ts +3 -0
  46. package/dist/checks/policy.d.ts +61 -0
  47. package/dist/checks/register-builtins.d.ts +17 -0
  48. package/dist/checks/registry.d.ts +40 -0
  49. package/dist/checks/runner.d.ts +25 -0
  50. package/dist/checks/source/accessibility-alt-text.d.ts +3 -0
  51. package/dist/checks/source/accessibility-heading-order.d.ts +3 -0
  52. package/dist/checks/source/config-file.d.ts +8 -0
  53. package/dist/checks/source/htmlhint.d.ts +3 -0
  54. package/dist/checks/source/index.d.ts +6 -0
  55. package/dist/checks/source/local-refs.d.ts +3 -0
  56. package/dist/checks/source/markdownlint.d.ts +3 -0
  57. package/dist/checks/source/stylelint.d.ts +3 -0
  58. package/dist/checks/tool-check.d.ts +23 -0
  59. package/dist/checks/types.d.ts +52 -0
  60. package/dist/cli-1tyj4bk3.js +124 -0
  61. package/dist/cli-37x76zdn.js +4 -0
  62. package/dist/cli-506tg37g.js +26 -0
  63. package/dist/cli-5bxx0c4y.js +464 -0
  64. package/dist/cli-7ykx7pp0.js +12378 -0
  65. package/dist/cli-h7phg3ka.js +746 -0
  66. package/dist/cli-hvqjs342.js +284 -0
  67. package/dist/cli-yja077f6.js +92 -0
  68. package/dist/cli.js +157 -0
  69. package/dist/constants.d.ts +17 -0
  70. package/dist/doctor-25zjt8dz.js +57 -0
  71. package/dist/favicon-wkbm9cjn.ico +0 -0
  72. package/dist/git-http-yrb4ag6z.js +17 -0
  73. package/dist/index-1tyj4bk3.js +124 -0
  74. package/dist/index-37x76zdn.js +4 -0
  75. package/dist/index-3h3fef7r.js +15218 -0
  76. package/dist/index-5bxx0c4y.js +464 -0
  77. package/dist/index-yja077f6.js +92 -0
  78. package/dist/index.d.ts +32 -0
  79. package/dist/index.js +310 -0
  80. package/dist/lib/app-heartbeat.d.ts +102 -0
  81. package/dist/lib/asset-inline.d.ts +73 -0
  82. package/dist/lib/browser-pool.d.ts +17 -0
  83. package/dist/lib/build-error.d.ts +52 -0
  84. package/dist/lib/build-fingerprint.d.ts +15 -0
  85. package/dist/lib/build-preflight.d.ts +43 -0
  86. package/dist/lib/build-runner.d.ts +161 -0
  87. package/dist/lib/build-staging.d.ts +64 -0
  88. package/dist/lib/chromium.d.ts +20 -0
  89. package/dist/lib/cli-args.d.ts +45 -0
  90. package/dist/lib/desktop.d.ts +14 -0
  91. package/dist/lib/diagnostics.d.ts +64 -0
  92. package/dist/lib/embedded-assets.d.ts +29 -0
  93. package/dist/lib/exec.d.ts +84 -0
  94. package/dist/lib/fetch-timeout.d.ts +41 -0
  95. package/dist/lib/ghostscript.d.ts +48 -0
  96. package/dist/lib/host-policy.d.ts +75 -0
  97. package/dist/lib/image-inspect.d.ts +32 -0
  98. package/dist/lib/install-hints.d.ts +21 -0
  99. package/dist/lib/lint-runner.d.ts +10 -0
  100. package/dist/lib/manifest-config.d.ts +31 -0
  101. package/dist/lib/manifest-doc.d.ts +25 -0
  102. package/dist/lib/manifest.d.ts +41 -0
  103. package/dist/lib/markdown/assemble.d.ts +78 -0
  104. package/dist/lib/markdown/chapter-id.d.ts +24 -0
  105. package/dist/lib/markdown/images.d.ts +34 -0
  106. package/dist/lib/markdown/index.d.ts +78 -0
  107. package/dist/lib/markdown/markdown-it-paged.d.ts +30 -0
  108. package/dist/lib/markdown/plugins.d.ts +69 -0
  109. package/dist/lib/markdown/renderer.d.ts +111 -0
  110. package/dist/lib/npm-plugin-installer.d.ts +33 -0
  111. package/dist/lib/open-path.d.ts +5 -0
  112. package/dist/lib/output-paths.d.ts +23 -0
  113. package/dist/lib/pagedjs-marker.d.ts +42 -0
  114. package/dist/lib/pagedjs.d.ts +26 -0
  115. package/dist/lib/pagination.d.ts +169 -0
  116. package/dist/lib/pdf-inspect.d.ts +123 -0
  117. package/dist/lib/pdf-parse.d.ts +57 -0
  118. package/dist/lib/plugin-manager.d.ts +108 -0
  119. package/dist/lib/plugin-vendor.d.ts +107 -0
  120. package/dist/lib/presets.d.ts +45 -0
  121. package/dist/lib/printsafe.d.ts +17 -0
  122. package/dist/lib/project-scaffold.d.ts +116 -0
  123. package/dist/lib/project-source.d.ts +140 -0
  124. package/dist/lib/project-templates.d.ts +49 -0
  125. package/dist/lib/publish/butler.d.ts +10 -0
  126. package/dist/lib/publish/command-runner.d.ts +18 -0
  127. package/dist/lib/publish/connect.d.ts +23 -0
  128. package/dist/lib/publish/manifest-publish.d.ts +9 -0
  129. package/dist/lib/publish/providers/azure-swa.d.ts +3 -0
  130. package/dist/lib/publish/providers/drivethrurpg.d.ts +10 -0
  131. package/dist/lib/publish/providers/guided.d.ts +3 -0
  132. package/dist/lib/publish/providers/itch.d.ts +5 -0
  133. package/dist/lib/publish/providers/kdp.d.ts +9 -0
  134. package/dist/lib/publish/providers/shopify.d.ts +5 -0
  135. package/dist/lib/publish/registry.d.ts +5 -0
  136. package/dist/lib/publish/run-publish.d.ts +30 -0
  137. package/dist/lib/publish/selections.d.ts +25 -0
  138. package/dist/lib/publish/types.d.ts +258 -0
  139. package/dist/lib/remote-auth/clone.d.ts +87 -0
  140. package/dist/lib/remote-auth/conflict-resolution.d.ts +29 -0
  141. package/dist/lib/remote-auth/diagnose.d.ts +77 -0
  142. package/dist/lib/remote-auth/generic-auth.d.ts +97 -0
  143. package/dist/lib/remote-auth/git-http.d.ts +85 -0
  144. package/dist/lib/remote-auth/github-auth.d.ts +69 -0
  145. package/dist/lib/remote-auth/github-repos.d.ts +64 -0
  146. package/dist/lib/remote-auth/operation-log.d.ts +66 -0
  147. package/dist/lib/remote-auth/recovery/abort-interrupted-operation.d.ts +103 -0
  148. package/dist/lib/remote-auth/recovery/backup.d.ts +113 -0
  149. package/dist/lib/remote-auth/recovery/classify.d.ts +109 -0
  150. package/dist/lib/remote-auth/recovery/context.d.ts +47 -0
  151. package/dist/lib/remote-auth/recovery/dispatch.d.ts +33 -0
  152. package/dist/lib/remote-auth/recovery/failsafe.d.ts +33 -0
  153. package/dist/lib/remote-auth/recovery/inspect.d.ts +74 -0
  154. package/dist/lib/remote-auth/recovery/manual-guidance.d.ts +28 -0
  155. package/dist/lib/remote-auth/recovery/outcome-mapping.d.ts +58 -0
  156. package/dist/lib/remote-auth/recovery/policy.d.ts +47 -0
  157. package/dist/lib/remote-auth/recovery/recover-auth.d.ts +42 -0
  158. package/dist/lib/remote-auth/recovery/recover-binary-conflict.d.ts +37 -0
  159. package/dist/lib/remote-auth/recovery/recover-corrupt-index.d.ts +40 -0
  160. package/dist/lib/remote-auth/recovery/recover-detached-head.d.ts +70 -0
  161. package/dist/lib/remote-auth/recovery/recover-interrupted-cherry-pick.d.ts +23 -0
  162. package/dist/lib/remote-auth/recovery/recover-interrupted-merge.d.ts +28 -0
  163. package/dist/lib/remote-auth/recovery/recover-interrupted-rebase.d.ts +39 -0
  164. package/dist/lib/remote-auth/recovery/recover-merge-conflict.d.ts +34 -0
  165. package/dist/lib/remote-auth/recovery/recover-missing-git-dir.d.ts +37 -0
  166. package/dist/lib/remote-auth/recovery/recover-missing-objects.d.ts +56 -0
  167. package/dist/lib/remote-auth/recovery/recover-network.d.ts +34 -0
  168. package/dist/lib/remote-auth/recovery/recover-non-fast-forward.d.ts +27 -0
  169. package/dist/lib/remote-auth/recovery/recover-stale-lock.d.ts +76 -0
  170. package/dist/lib/remote-auth/recovery/recover-unrelated-histories.d.ts +44 -0
  171. package/dist/lib/remote-auth/recovery/recover-wrong-remote.d.ts +35 -0
  172. package/dist/lib/remote-auth/recovery/types.d.ts +235 -0
  173. package/dist/lib/remote-auth/resolution-plan.d.ts +64 -0
  174. package/dist/lib/remote-auth/sync-messages.d.ts +26 -0
  175. package/dist/lib/remote-auth/sync-types.d.ts +225 -0
  176. package/dist/lib/remote-auth/sync.d.ts +45 -0
  177. package/dist/lib/remote-auth/test-access.d.ts +47 -0
  178. package/dist/lib/remote-auth/test-support/git-http-server.d.ts +71 -0
  179. package/dist/lib/remote-auth/token-store.d.ts +95 -0
  180. package/dist/lib/remote-auth/transport.d.ts +105 -0
  181. package/dist/lib/slug.d.ts +28 -0
  182. package/dist/lib/snippets.d.ts +39 -0
  183. package/dist/lib/source-provider.d.ts +244 -0
  184. package/dist/lib/static-serve.d.ts +54 -0
  185. package/dist/lib/style-resolver.d.ts +30 -0
  186. package/dist/lib/theme-import.d.ts +70 -0
  187. package/dist/lib/theme-manager.d.ts +128 -0
  188. package/dist/lib/tool-probe.d.ts +37 -0
  189. package/dist/lib/validation-exec.d.ts +47 -0
  190. package/dist/lib/validation-profile.d.ts +18 -0
  191. package/dist/lib/version.d.ts +9 -0
  192. package/dist/lint-f63nxjfj.js +65 -0
  193. package/dist/manifest-n1gh3qw5.yaml +9 -0
  194. package/dist/manifest-ryyg71nf.yaml +9 -0
  195. package/dist/manifest.schema-rn1dpdpn.json +564 -0
  196. package/dist/new-7b08a42h.js +105 -0
  197. package/dist/paged.polyfill-n95pbxfn.js +33288 -0
  198. package/dist/pagedjs-bridge-vn4hk9fx.js +111 -0
  199. package/dist/pagedjs-interface-80g3xa8p.js +498 -0
  200. package/dist/platform.d.ts +100 -0
  201. package/dist/plugin-wf2cbmwc.js +129 -0
  202. package/dist/preflight-tg4mpz1h.js +222 -0
  203. package/dist/preview/file-watcher.d.ts +174 -0
  204. package/dist/preview/http-server.d.ts +45 -0
  205. package/dist/preview/lifecycle.d.ts +67 -0
  206. package/dist/preview/server-context.d.ts +36 -0
  207. package/dist/preview-h2bwbb2x.js +102 -0
  208. package/dist/preview-shell-rghtfmc8.js +155 -0
  209. package/dist/project-source-0tg0r6vm.js +17 -0
  210. package/dist/publish-ztaet53r.js +233 -0
  211. package/dist/render.d.ts +20 -0
  212. package/dist/render.js +682 -0
  213. package/dist/repair-jkp4n3j8.js +171 -0
  214. package/dist/schema/manifest.types.d.ts +218 -0
  215. package/dist/server.d.ts +34 -0
  216. package/dist/source-provider-hp96b5jf.js +46 -0
  217. package/dist/test-helpers/testkit.d.ts +91 -0
  218. package/dist/theme-0yzvthe8.css +65 -0
  219. package/dist/theme-570zmh2t.css +58 -0
  220. package/dist/theme-6a2fngc8.json +6 -0
  221. package/dist/theme-cd6efzjw.json +6 -0
  222. package/dist/theme-nya4nqh6.css +70 -0
  223. package/dist/theme-tqfypc1w.json +6 -0
  224. package/dist/theme-xt0hjb1b.json +6 -0
  225. package/dist/theme-zz2ktzqs.css +60 -0
  226. package/dist/types.d.ts +31 -0
  227. package/dist/utils/file-utils.d.ts +53 -0
  228. package/dist/utils/logger.d.ts +59 -0
  229. package/dist/validate-k2drs19j.js +99 -0
  230. package/package.json +102 -0
@@ -0,0 +1,161 @@
1
+ import { resolveConfig } from "./manifest";
2
+ import { BuildError } from "./build-error";
3
+ import { type Gates } from "./build-preflight";
4
+ import { type PdfRenderer, type PdfRenderInput } from "./pagination";
5
+ export type { PdfRenderer, PdfRenderInput };
6
+ export type BuildFormat = "html" | "pdf" | "pdfx";
7
+ export type PdfxFlavor = "x1a" | "x3";
8
+ export { BuildError };
9
+ export interface BuildRunnerOptions {
10
+ inputDir: string;
11
+ format: BuildFormat;
12
+ outDir?: string;
13
+ pdfFileOverride?: string | null;
14
+ title?: string;
15
+ pdfxFlavor?: PdfxFlavor;
16
+ iccPath?: string;
17
+ manifestPath?: string;
18
+ stripAnnotations?: boolean;
19
+ skipLint?: boolean;
20
+ skipPreValidate?: boolean;
21
+ skipPostValidate?: boolean;
22
+ /**
23
+ * Optional PDF renderer override. When provided, the build uses it instead of
24
+ * launching Chromium via puppeteer, and the Chromium preflight is skipped.
25
+ * The Electron desktop injects one backed by `webContents.printToPDF`.
26
+ */
27
+ pdfRenderer?: PdfRenderer;
28
+ /**
29
+ * Keep the pooled headless browser alive after the build returns. A one-shot
30
+ * CLI build leaves this false so the process can exit; a long-lived
31
+ * preview/watch server sets it true so the browser stays warm across rebuilds
32
+ * (every rebuild then skips the ~1–2s Chromium launch). The server owns
33
+ * `closeBrowser()` on shutdown.
34
+ */
35
+ keepBrowserAlive?: boolean;
36
+ rawArgs: Record<string, unknown>;
37
+ }
38
+ export interface BuildRunnerResult {
39
+ outDir: string;
40
+ /**
41
+ * The published `book.html`, or `null` for a one-file delivery (`--out x.pdf`,
42
+ * a desktop export) where only the PDF is delivered and everything else is
43
+ * discarded with the work dir. Returning a work-dir path here would hand the
44
+ * caller a filename that is already deleted by the time they see it.
45
+ */
46
+ htmlPath: string | null;
47
+ pdfPath: string | null;
48
+ /** As {@link htmlPath}: `null` when nothing but the artifact was published. */
49
+ fingerprintPath: string | null;
50
+ }
51
+ export interface SplitOutPath {
52
+ outDir?: string;
53
+ pdfFileOverride: string | null;
54
+ }
55
+ /**
56
+ * Split --out into outDir + optional pdfFileOverride.
57
+ * - For pdf/pdfx, accept "*.pdf" forms (file path) and split into dirname + path.
58
+ * - For html or any non-.pdf string, treat as a directory.
59
+ */
60
+ export declare function splitOutPath(outArg: string | undefined, format: BuildFormat): SplitOutPath;
61
+ /**
62
+ * Everything the build stages + output strategies need, resolved once up front:
63
+ * the requested format, absolute input/output dirs, the manifest dir (for
64
+ * plugin + ICC resolution), the merged config, and the lint/validate gates.
65
+ * Assembled by {@link resolveBuildContext}; consumed by {@link runQualityGates},
66
+ * {@link renderBook}, and the {@link OutputStrategy} implementations.
67
+ */
68
+ /**
69
+ * Where a finished build is delivered. The build itself always writes to a
70
+ * scratch `workDir`; this says what happens to it afterwards.
71
+ *
72
+ * The distinction is structural, not a flag: `rm` appears in exactly one branch
73
+ * of {@link publishBuild}, the `project` one, whose path is always computed by
74
+ * `resolveOutputDir` from the manifest. A caller-supplied path is a different
75
+ * variant that reaches different code, so no `--out` value can be deleted —
76
+ * there is no code path that would do it.
77
+ */
78
+ export type PublishTarget =
79
+ /** gutterpress's own `dist/<slug>/`. Replaced wholesale, so stale files vanish. */
80
+ {
81
+ kind: "project";
82
+ dir: string;
83
+ }
84
+ /** `--out <dir>`: the user's directory. Files are added; nothing is removed. */
85
+ | {
86
+ kind: "directory";
87
+ dir: string;
88
+ }
89
+ /** `--out <file.pdf>` / the desktop's Save dialog: ONE file, nothing else. */
90
+ | {
91
+ kind: "file";
92
+ file: string;
93
+ };
94
+ export interface BuildContext {
95
+ opts: BuildRunnerOptions;
96
+ format: BuildFormat;
97
+ inputDir: string;
98
+ outDir: string;
99
+ manifestDir: string;
100
+ config: ReturnType<typeof resolveConfig>;
101
+ gates: Gates;
102
+ /**
103
+ * Where the build actually writes. A build assembles a COMPLETE output tree
104
+ * here and only then replaces `outDir` with it, so a build is atomic (a crash
105
+ * leaves the previous output untouched) and stale files cannot survive — the
106
+ * work dir starts empty, so whatever is not rebuilt simply is not there.
107
+ *
108
+ * It is a sibling of `outDir` rather than an OS temp dir so the final publish
109
+ * is a same-filesystem `rename`.
110
+ */
111
+ workDir: string;
112
+ /** What to do with `workDir` once the build succeeds. */
113
+ target: PublishTarget;
114
+ }
115
+ /**
116
+ * Stage 1 — load the manifest, merge CLI overrides into the resolved config,
117
+ * pick the output dir, and compute the lint/validate gates. Pure planning: no
118
+ * filesystem writes, no browser, no logging beyond computeGates' own
119
+ * flags-ignored notice. Everything downstream reads from the returned context.
120
+ */
121
+ export declare function resolveBuildContext(opts: BuildRunnerOptions): Promise<BuildContext>;
122
+ /**
123
+ * Stage 3 — load configured plugins, render the markdown chapters to
124
+ * `outDir/book.html`, and copy user asset directories. Returns the path to the
125
+ * rendered book.html both output strategies then paginate. This is the shared
126
+ * pre-format work; the per-format tails live in the strategies.
127
+ *
128
+ * ARCH finding #4: markdown-it-paged computes typed, line-numbered
129
+ * author-mistake warnings (`env.layoutWarnings`) that every real render path
130
+ * used to discard silently. `renderChaptersToFile`'s `onChapterWarnings`
131
+ * threads them back out here so a final artifact never omits a marker
132
+ * mistake without at least telling the author about it in the build log.
133
+ * Exported (not just for the pipeline) so this stage is unit-testable
134
+ * without driving the full `runBuild` pagination/PDF machinery.
135
+ */
136
+ export declare function renderBook(ctx: BuildContext): Promise<string>;
137
+ /**
138
+ * Resolve the effective ICC profile for a PDF/X build (extracted from the pdfx
139
+ * branch so it is unit-testable in isolation). Relative paths are tried against
140
+ * the manifest dir first, then cwd. As a convenience the unspecified default
141
+ * profile (`CGATS21_CRPC1.icc`, no explicit `--icc`) falls back to the embedded
142
+ * copy shipped in the binary. Throws BuildError(exitCode 2) if nothing resolves.
143
+ */
144
+ export declare function resolveIccProfile(icc: string, manifestDir: string, explicitIccPath: string | undefined): Promise<string>;
145
+ /**
146
+ * Orchestrate a build: resolve the context, mkdir the output, preflight tools
147
+ * (non-html), pre-warm the browser when this build will paginate in Chromium,
148
+ * run the quality gates, render the book, then hand off to the per-format output
149
+ * strategy for pagination + finalize. The heavy lifting lives in the named
150
+ * stages + strategies above (plus ./build-preflight, ./build-staging, and
151
+ * ./pagination); this reads as the pipeline it is.
152
+ *
153
+ * Everything from the prewarm decision onward runs inside a try/finally that
154
+ * closes the pooled browser (unless `keepBrowserAlive` is set) — finding #50:
155
+ * previously the close only happened on the success tail (inside
156
+ * `finalizeBuild`), so a prewarmed Chromium leaked whenever a quality gate,
157
+ * the render, or pagination itself threw. `closeBrowser()` is a no-op if
158
+ * nothing was launched (including the injected-renderer path, which never
159
+ * uses the pool), so it is safe to call unconditionally here.
160
+ */
161
+ export declare function runBuild(opts: BuildRunnerOptions): Promise<BuildRunnerResult>;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * HTML string-rewriting for the shippable artifact: turns the raw
3
+ * serialized-paginated DOM that pagination produces into the static desktop HTML
4
+ * (or the runtime-pagination fallback). Pure string/fs transforms — no browser.
5
+ *
6
+ * The former `stagePaginationInput` is GONE. It copied `book.html` plus every
7
+ * asset directory into a temp dir purely so relative URLs would resolve against
8
+ * some root, which cost a second full copy of every asset per build and made the
9
+ * staged tree a second place assets could go missing. `book.html` is now
10
+ * self-contained (CSS and fonts inlined by `lib/asset-inline.ts`), so the
11
+ * pagination pass serves `outDir` directly with in-memory overlays for the
12
+ * engine — see `createStaticFileServer`'s `overlays` in `./pagination.ts`.
13
+ */
14
+ /**
15
+ * Remove the Paged.js pagination ENGINE from an already-paginated, serialized
16
+ * document so the browser renders the static pages as-is and never re-paginates.
17
+ * Strips (a) the polyfill `<script src>` and (b) the inline break-inside handler.
18
+ * Navigation toolbar scripts are NOT touched — they only scroll between pages
19
+ * that already exist, which is not DOM-pagination.
20
+ */
21
+ export declare function stripPaginationRuntime(html: string): string;
22
+ /**
23
+ * Rewrite the build's ephemeral pagination origin back to document-relative
24
+ * URLs.
25
+ *
26
+ * Paged.js absolutizes every non-`data:` CSS `url()` against the sheet's origin
27
+ * (`replaceUrls`, paged.polyfill.js), so the serialized document comes back
28
+ * pointing at `http://127.0.0.1:<port>/…` — a port that dies with the build.
29
+ * Left alone, a shipped `book.html` references a dead origin for every
30
+ * content-addressed image.
31
+ *
32
+ * The leading slash is stripped along with the origin ON PURPOSE: `book.html`
33
+ * sits at the artifact root, so `assets/x.png` is correct and `/assets/x.png`
34
+ * would break any deployment under a subpath (GitHub Pages project sites).
35
+ */
36
+ export declare function stripPaginationOrigin(html: string): string;
37
+ /**
38
+ * Inject the navigation-only toolbar scripts (page nav, zoom, view modes) into
39
+ * the static document head. These read the pre-rendered `.pagedjs_page`
40
+ * elements; they do not paginate.
41
+ */
42
+ export declare function injectNavigationScripts(html: string): string;
43
+ /**
44
+ * Turn a raw serialized paginated document into the shippable static desktop
45
+ * `book.html`: copy the navigation toolbar scripts, strip the pagination engine
46
+ * and the build's ephemeral origin, wire the nav scripts, and write the file.
47
+ * Shared by the HTML format and the PDF unification path.
48
+ */
49
+ export declare function finalizeStaticBook(rawSerializedHtml: string, htmlFile: string, outDir: string): Promise<void>;
50
+ /**
51
+ * Fallback for `--format html` when no headless browser is available: ship the
52
+ * Paged.js polyfill + nav scripts so the BROWSER paginates at load time (the
53
+ * pre-SSG behavior). Slower at runtime and not pre-paginated, but it works with
54
+ * no Chromium at build.
55
+ */
56
+ export declare function shipRuntimePaginatedHtml(htmlFile: string, outDir: string): Promise<void>;
57
+ /**
58
+ * Create a unique scratch directory under the OS temp dir. Now used ONLY for
59
+ * PDF/X intermediates (`raw.pdf`, Ghostscript work files) — never for staging
60
+ * assets. Must not be resolved against `process.cwd()`: `runBuild` is exported
61
+ * and called by the desktop host, so writing scratch dirs into the caller's
62
+ * directory is a hidden side effect. Callers remove it in a `finally`.
63
+ */
64
+ export declare function createStageRoot(): Promise<string>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Returns the path to a system Chrome/Chromium binary, or undefined if none found.
3
+ *
4
+ * Resolution order:
5
+ * 1. CHROMIUM_PATH / PUPPETEER_EXECUTABLE_PATH env vars
6
+ * 2. Hard-coded standard install paths (Chrome / Edge / Brave / Chromium
7
+ * on Linux, macOS, Windows)
8
+ * 3. PATH probe via `which` / `where.exe` for common binary names
9
+ * (catches Scoop, Chocolatey, Homebrew, portable installs, and any
10
+ * Chromium variant the user added to PATH manually)
11
+ *
12
+ * Prefer requireChromiumExecutable() for build paths that cannot continue
13
+ * without it — it surfaces a multi-line install-instructions error.
14
+ */
15
+ export declare function resolveChromiumExecutable(): Promise<string | undefined>;
16
+ /**
17
+ * Like resolveChromiumExecutable() but throws with actionable install instructions
18
+ * when no Chrome/Chromium is found on the system.
19
+ */
20
+ export declare function requireChromiumExecutable(): Promise<string>;
@@ -0,0 +1,45 @@
1
+ import type { BuildFormat, PdfxFlavor } from "./build-runner.ts";
2
+ export { EXIT_CODES } from "./build-error.ts";
3
+ /** A recoverable "bad CLI usage" error carrying the process exit code. */
4
+ export declare class UsageError extends Error {
5
+ exitCode: number;
6
+ constructor(message: string, exitCode?: number);
7
+ }
8
+ interface CliArgumentDefinition {
9
+ type?: "boolean" | "string" | "enum" | "positional";
10
+ alias?: string | readonly string[];
11
+ }
12
+ type CliArgumentDefinitions = Readonly<Record<string, CliArgumentDefinition>>;
13
+ /**
14
+ * Reject option names citty would otherwise retain and silently ignore, and
15
+ * reject value-taking options whose value is absent.
16
+ *
17
+ * This scans raw argv rather than the parsed object so a positional name used
18
+ * as an option (for example, `build --input`) cannot masquerade as a declared
19
+ * flag. Citty parses in non-strict mode and turns a valueless string option
20
+ * into `""`; catching that from raw argv is the only way to distinguish an
21
+ * omitted option from a typo. A dash-prefixed token is still a legitimate
22
+ * string value unless it names an option declared by this command.
23
+ */
24
+ export declare function rejectUnknownFlags(rawArgs: readonly string[], declared: CliArgumentDefinitions, commandName: string): void;
25
+ /**
26
+ * Reject CLI positionals beyond the ones a command declares (UX finding M46).
27
+ *
28
+ * Citty's parser keeps every raw positional token in `args._` even after
29
+ * `type: "positional"` args have claimed their share — it shifts values off a
30
+ * COPY of `_` for each declared positional arg, but never trims the original
31
+ * array. So a command with one declared positional silently drops a second
32
+ * one instead of erroring, e.g. `gutterpress build a b` builds `a` and never
33
+ * mentions `b`. Call this near the top of a command's `run()`, passing
34
+ * `(args as { _: unknown[] })._` and how many positionals the command itself
35
+ * declares, to turn that into a named `UsageError` instead.
36
+ */
37
+ export declare function rejectExtraPositionals(positionals: unknown[] | undefined, expectedCount: number, commandName: string): void;
38
+ /** Parse `--format`, falling back to the caller-supplied default. */
39
+ export declare function parseFormat(raw: unknown, opts: {
40
+ default: BuildFormat;
41
+ }): BuildFormat;
42
+ /** Parse `--pdfx-flavor`, which is only valid alongside `--format pdfx`. */
43
+ export declare function parsePdfxFlavor(raw: unknown, format: BuildFormat): PdfxFlavor | undefined;
44
+ /** Parse `--port`, defaulting to {@link NETWORK.DEFAULT_PORT} (0 = OS-assigned). */
45
+ export declare function resolvePort(raw: unknown): number;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Output filename constants for the build pipeline.
3
+ *
4
+ * Historically this file also emitted "desktop chrome" (toolbar + folder
5
+ * picker + GH clone modal) into the build output so the directory was a
6
+ * self-hostable site. That chrome was removed 2026-05-18 when the desktop
7
+ * was extracted into packages/desktop (Electron + SvelteKit). The CLI build
8
+ * now produces a "naked" book.html with Paged.js polyfill and the
9
+ * pagedjs-interface/bridge scripts injected — no toolbar.
10
+ *
11
+ * Power users who want a hosted UI launch the desktop app or write their
12
+ * own iframe wrapper around book.html.
13
+ */
14
+ export declare const BOOK_HTML_FILENAME = "book.html";
@@ -0,0 +1,64 @@
1
+ /**
2
+ * System diagnostics — surfaces tool availability + versions for the
3
+ * desktop's Help/About dialog and the `gutterpress doctor` CLI command.
4
+ *
5
+ * Reuses `resolveChromiumExecutable`, `findTool`, and `isToolAvailable` for
6
+ * tool detection. Install-hint copy lives in `./install-hints.ts` — the
7
+ * single source of truth also consumed by build-runner.ts's preflight and
8
+ * chromium.ts's `requireChromiumExecutable` — not duplicated here. Probes
9
+ * are run in parallel; total wall time is dominated by the slowest
10
+ * `--version` invocation (~50-200ms per tool that's present, ~5ms per tool
11
+ * that's missing).
12
+ */
13
+ export interface ToolStatus {
14
+ /**
15
+ * Stable machine id for this tool, independent of the human-readable
16
+ * `name`/`bin` display strings (e.g. "chromium", "gs", "qpdf"). Consumers
17
+ * that need to single out a specific tool (the desktop's doctor route
18
+ * excludes the bundled-Chromium entry from the "external tools" list) MUST
19
+ * match on this field, not on `bin`/`name` — those are presentation text
20
+ * and can be reworded without notice (UX L10).
21
+ */
22
+ id: string;
23
+ name: string;
24
+ /** The canonical CLI/binary name being probed (gs, qpdf, etc). */
25
+ bin: string;
26
+ /** True if the binary is resolvable on PATH or via fixed-path scan. */
27
+ found: boolean;
28
+ /** Absolute path on disk if found. */
29
+ path?: string;
30
+ /** First line of `<bin> --version` output if found and the call succeeded. */
31
+ version?: string;
32
+ /**
33
+ * What features depend on this tool.
34
+ * "required" — the feature breaks without it
35
+ * "optional" — the feature degrades / skips gracefully
36
+ */
37
+ usedBy: Array<{
38
+ feature: string;
39
+ severity: "required" | "optional";
40
+ }>;
41
+ /** Multi-line, per-platform install hint. Always present. */
42
+ installHint: string;
43
+ }
44
+ export interface SystemDiagnostics {
45
+ /** Gutterpress lib version */
46
+ libVersion: string;
47
+ platform: {
48
+ os: string;
49
+ arch: string;
50
+ release: string;
51
+ node: string;
52
+ };
53
+ tools: ToolStatus[];
54
+ /** Existing CLI config/credential directory; reporting it never relocates data. */
55
+ configDir: string;
56
+ /** Path to the docs page with deeper info. */
57
+ docsUrl: string;
58
+ }
59
+ /**
60
+ * Probe every external tool the lib could spawn and return a structured
61
+ * report. Safe to call repeatedly; the slowest path is ~200ms when every
62
+ * tool is present (one `--version` per tool, in parallel).
63
+ */
64
+ export declare function getSystemDiagnostics(): Promise<SystemDiagnostics>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Embedded preview assets (favicon, manifest schema, paged.js polyfill,
3
+ * iframe interface + cross-origin bridge).
4
+ *
5
+ * `with { type: "file" }` imports are the canonical embedding mechanism for
6
+ * assets that must be accessible in all three runtime contexts:
7
+ *
8
+ * - bun build --compile (standalone binary):
9
+ * Bun embeds the file at a bunfs path and the import returns that absolute
10
+ * bunfs path as a string. All modules are merged into one root file in
11
+ * bunfs, so new URL("../assets/...", import.meta.url) does NOT work here
12
+ * because import.meta.url points to the bundle root, not the source file.
13
+ * with { type: "file" } correctly gives the embedded absolute path.
14
+ *
15
+ * - bun run src/cli.ts (development):
16
+ * The import returns the real absolute disk path to the asset file.
17
+ *
18
+ * - Node.js via dist/ (Electron in-process):
19
+ * bun build --target node copies assets alongside the output JS with
20
+ * hashed filenames and rewrites imports to relative strings like
21
+ * "./favicon-abc123.ico". We resolve these relative to __libdir so
22
+ * readFile always gets an absolute path regardless of CWD.
23
+ *
24
+ * On first use we copy everything into a per-process temp directory and return
25
+ * that path, letting call sites use plain readFile/cp without caring about
26
+ * the source format.
27
+ */
28
+ export declare function getAssetsDir(): Promise<string>;
29
+ export declare function getAssetPath(relPath: string): Promise<string>;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Join `dir` onto the front of `existingPath` using `sep` (defaults to the
3
+ * current platform's `node:path` delimiter — `:` on POSIX, `;` on Windows).
4
+ * A pure function so the delimiter behavior is unit-testable without
5
+ * needing to actually run on every OS — see exec.test.ts.
6
+ */
7
+ export declare function buildEnhancedPath(dir: string, existingPath: string, sep?: string): string;
8
+ /** Gutterpress's own node_modules/.bin so locally installed tools are found. */
9
+ export declare const localBin: string;
10
+ /**
11
+ * PATH with `localBin` prepended, correctly delimiter-joined. Single source
12
+ * of truth for every spawn in the lib — `run` and `execCapture` below use
13
+ * it, and tool-probe.ts's `isToolAvailable`/`findTool` get it for free by
14
+ * calling `execCapture` instead of keeping their own copy (previously a
15
+ * literal `:` here corrupted PATH on Windows while tool-probe.ts's copy of
16
+ * the same logic used `delimiter` correctly — see docs/reviews
17
+ * 2026-07-10-architecture-critical-review.md, finding #3).
18
+ */
19
+ export declare const enhancedPath: string;
20
+ /**
21
+ * Spawn a child process, inherit stdio, reject on non-zero exit.
22
+ */
23
+ export declare function run(cmd: string, args: string[], opts?: {
24
+ cwd?: string;
25
+ }): Promise<void>;
26
+ /**
27
+ * After the child's 'exit', stdio data can still be in flight — buffered in
28
+ * the pipes, or written by a grandchild that inherited them (the SWA CLI
29
+ * spawns StaticSitesClient). Settling on 'exit' truncates that output, so we
30
+ * settle on 'close' (stdio flushed) — but a detached grandchild can hold the
31
+ * pipes open forever, so 'exit' arms this grace and we settle with whatever
32
+ * has arrived when it expires. The grace is an IDLE window, re-armed on every
33
+ * post-exit chunk: a grandchild actively streaming (StaticSitesClient still
34
+ * printing the deployment URL) is never cut mid-stream, while a silent
35
+ * daemon holding the pipe still settles one grace-width after exit.
36
+ */
37
+ export declare const EXIT_FLUSH_GRACE_MS = 2000;
38
+ export interface SpawnCaptureOptions {
39
+ cwd?: string;
40
+ /** Full child environment — callers compose it (no ambient default here). */
41
+ env?: NodeJS.ProcessEnv;
42
+ /** Kill budget in ms. 0/undefined = no timer. */
43
+ timeoutMs?: number;
44
+ /** "total" (default): one-shot deadline. "idle": re-armed on every chunk,
45
+ * so only complete output silence kills the child. */
46
+ timeoutMode?: "total" | "idle";
47
+ /** Raw chunk tap, called per stream as data arrives. */
48
+ onChunk?: (stream: "stdout" | "stderr", text: string) => void;
49
+ /** Keep only the trailing N chars of each captured stream (unbounded when
50
+ * unset) — bounds memory for hours-long progress streams. */
51
+ captureLimit?: number;
52
+ /** Override {@link EXIT_FLUSH_GRACE_MS} (tests). */
53
+ exitGraceMs?: number;
54
+ }
55
+ /**
56
+ * The lib's single "spawn, buffer stdout/stderr, settle" core. Resolves with
57
+ * the exit code/signal for ANY exit (callers decide whether non-zero is an
58
+ * error); rejects only on spawn error or timeout kill. Every timer is cleared
59
+ * on settle and `unref()`d so a pending call can never keep the process alive
60
+ * on its own. `execCapture` below and publish's `defaultCommandRunner` are
61
+ * thin adapters over this — do not grow parallel spawn loops elsewhere
62
+ * (previously four copies existed with different bug profiles — see
63
+ * docs/reviews 2026-07-10-architecture-critical-review.md, finding #16).
64
+ */
65
+ export declare function spawnCapture(cmd: string, args: string[], opts?: SpawnCaptureOptions): Promise<{
66
+ code: number | null;
67
+ signal: NodeJS.Signals | null;
68
+ stdout: string;
69
+ stderr: string;
70
+ }>;
71
+ /**
72
+ * Spawn and capture stdout/stderr. Rejects on non-zero exit, on spawn
73
+ * error, or — when `timeoutMs` is given — if the child hasn't exited in
74
+ * time (it is then SIGKILLed). A thin adapter over {@link spawnCapture};
75
+ * build-fingerprint.ts, diagnostics.ts, and tool-probe.ts all call this
76
+ * instead of keeping their own copies.
77
+ */
78
+ export declare function execCapture(cmd: string, args: string[], opts?: {
79
+ timeoutMs?: number;
80
+ cwd?: string;
81
+ }): Promise<{
82
+ stdout: string;
83
+ stderr: string;
84
+ }>;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared network deadline + author-friendly error mapping for the CLI's
3
+ * direct `fetch` call sites (GitHub auth/API, the butler download). ONE copy
4
+ * of the policy, so a fix here reaches every site (the old per-site clones
5
+ * let the dropped-timeout bug below survive in two of three copies):
6
+ *
7
+ * - The deadline is a TOTAL budget (`AbortSignal.timeout` keeps ticking
8
+ * through any body read done inside `run`), COMPOSED with the caller's
9
+ * cancellation signal via `AbortSignal.any` — the old
10
+ * `signal ?? AbortSignal.timeout(...)` pattern silently DROPPED the
11
+ * timeout whenever a caller passed a signal.
12
+ * - A caller abort ("AbortError") is rethrown untouched, so cancellation
13
+ * keeps its site-specific handling.
14
+ * - A fired deadline ("TimeoutError") maps to `timeoutMessage`.
15
+ * - Every other failure (DNS, TLS, socket reset) maps to `offlineMessage`,
16
+ * with the underlying error attached as `cause`.
17
+ *
18
+ * (The isomorphic-git transport has its own idle/total timer design —
19
+ * remote-auth/git-http.ts — because that client accepts no AbortSignal.)
20
+ */
21
+ /** An operation error that already has its final classification and message. */
22
+ export declare class FetchPassthroughError extends Error {
23
+ }
24
+ /** An author-friendly HTTP status error that should not be remapped. */
25
+ export declare class FriendlyHttpError extends FetchPassthroughError {
26
+ }
27
+ /** A timeout, DNS, TLS, or socket failure that an optional download may skip. */
28
+ export declare class FetchUnavailableError extends Error {
29
+ }
30
+ export interface FetchTimeoutOptions {
31
+ /** TOTAL deadline in ms, covering everything `run` does with the signal. */
32
+ timeoutMs: number;
33
+ /** Optional caller cancellation, composed with the deadline. */
34
+ signal?: AbortSignal;
35
+ /** Message when the deadline fires. Defaults to the offline mapping. */
36
+ timeoutMessage?: string;
37
+ /** Message for network-level failures (string, or built from the cause). */
38
+ offlineMessage: string | ((cause: unknown) => string);
39
+ }
40
+ /** Run one fetch-shaped operation under the policy described in the header. */
41
+ export declare function withFetchTimeout<T>(options: FetchTimeoutOptions, run: (signal: AbortSignal) => Promise<T>): Promise<T>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Resolve the Ghostscript command on every supported platform.
3
+ *
4
+ * Resolution order is explicit override, platform-specific PATH names, then
5
+ * conventional versioned Windows installer directories. The optional
6
+ * arguments make the Windows branch testable on non-Windows CI; production
7
+ * callers always use the current platform and environment.
8
+ */
9
+ export declare function resolveGhostscript(targetPlatform?: NodeJS.Platform, env?: NodeJS.ProcessEnv): Promise<string | undefined>;
10
+ /**
11
+ * Strip all annotations from a PDF using qpdf.
12
+ *
13
+ * Chromium embeds internal link annotations (from HTML `id` attributes)
14
+ * that are not permitted in PDF/X output. Removing them before Ghostscript
15
+ * prevents the "Annotation not TrapNet or PrinterMark" warning and keeps
16
+ * the output in strict PDF/X compliance.
17
+ */
18
+ export declare function stripAnnotations(pdfPath: string, stagingDir: string): Promise<void>;
19
+ type PdfxFlavor = "x1a" | "x3";
20
+ /**
21
+ * Generate the PostScript definition file for PDF/X output intent + GCR.
22
+ */
23
+ export declare function makePdfxDefPs(params: {
24
+ iccPath: string;
25
+ pdfx: PdfxFlavor;
26
+ title: string;
27
+ maxTac?: number;
28
+ }): string;
29
+ /**
30
+ * Stamp the Creator metadata field on an existing PDF.
31
+ *
32
+ * Uses pdf-lib (pure JS, MIT) rather than Ghostscript, so the plain-PDF build
33
+ * path needs no system tool at all — gs is now required only for PDF/X CMYK
34
+ * conversion (ADR 0002). `updateMetadata: false` keeps pdf-lib from rewriting
35
+ * the ModDate/Producer so the only change is the /Creator field.
36
+ */
37
+ export declare function stampCreator(pdfPath: string): Promise<void>;
38
+ /**
39
+ * Convert an RGB PDF to CMYK PDF/X using Ghostscript.
40
+ */
41
+ export declare function convertToPdfxCmyk(inputPdf: string, outPdf: string, config: {
42
+ iccPath: string;
43
+ pdfx: PdfxFlavor;
44
+ title?: string;
45
+ maxTac?: number;
46
+ stagingDir: string;
47
+ }): Promise<void>;
48
+ export {};
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Host-timer POLICY (pure) extracted from the source-provider abstraction.
3
+ *
4
+ * These helpers are the testable core of the desktop host's automatic-snapshot
5
+ * and automatic-sync timers: they turn a persisted, possibly-partial user
6
+ * settings object into a concrete debounce/cadence delay (ms) — or `null` when
7
+ * the feature is switched off. The timers themselves live in the Electron main
8
+ * process (CLAUDE.md §8); this module owns ONLY the clamping/default policy so
9
+ * both the CLI and the desktop resolve delays identically.
10
+ *
11
+ * Nothing here touches Git, the filesystem, or `isomorphic-git` — it is the
12
+ * host-facing cadence policy, deliberately separate from `source-provider.ts`'s
13
+ * SourceProvider operations.
14
+ */
15
+ /** User-facing auto-snapshot policy (mirrors the desktop's settings group). */
16
+ export interface AutoSnapshotPolicy {
17
+ /** Master switch — automatic snapshots default ON. */
18
+ autoSnapshot: boolean;
19
+ /** Minutes of quiet after the last edit before a snapshot fires. */
20
+ autoSnapshotMinutes: number;
21
+ }
22
+ /** Cadence bounds: never below 5 minutes (commit-per-keystroke guard), never
23
+ * above a day (a longer value means the user effectively wants it off). */
24
+ export declare const AUTO_SNAPSHOT_MIN_MINUTES = 5;
25
+ export declare const AUTO_SNAPSHOT_MAX_MINUTES: number;
26
+ export declare const AUTO_SNAPSHOT_DEFAULT_MINUTES = 10;
27
+ /** User-facing auto-sync policy (mirrors the desktop's settings group). */
28
+ export interface AutoSyncPolicy {
29
+ /** Master switch — automatic sync defaults ON when a remote is configured. */
30
+ autoSync: boolean;
31
+ /** Periodic safety cadence in minutes (clamped, like the snapshot cadence). */
32
+ autoSyncMinutes: number;
33
+ }
34
+ /**
35
+ * Cadence bounds for the periodic safety sync. The floor (1 min) is lower than
36
+ * the snapshot floor because a network round-trip is cheaper than a full tree
37
+ * walk, and the transparent-sync plan targets ~2 min as the default cadence.
38
+ * The ceiling matches the snapshot ceiling (one day = effectively paused).
39
+ */
40
+ export declare const AUTO_SYNC_MIN_MINUTES = 1;
41
+ export declare const AUTO_SYNC_MAX_MINUTES: number;
42
+ export declare const AUTO_SYNC_DEFAULT_MINUTES = 2;
43
+ /**
44
+ * Resolve the debounce delay (ms) for the host's auto-snapshot timer, or
45
+ * `null` when automatic snapshots are disabled. Pure — the testable core of
46
+ * the trigger policy (the timer itself lives in the Electron main process).
47
+ *
48
+ * Defensive about persisted settings: a missing policy means "defaults"
49
+ * (enabled, 10 min); a non-finite/absurd minutes value falls back to the
50
+ * default and is then clamped into [5, 1440].
51
+ */
52
+ export declare function autoSnapshotDelayMs(policy: Partial<AutoSnapshotPolicy> | undefined): number | null;
53
+ /**
54
+ * Resolve the periodic-safety-sync interval (ms) for the host's auto-sync
55
+ * orchestrator, or `null` when auto-sync is disabled. Pure — the testable core
56
+ * of the trigger policy (the timer and the actual `syncProject` call live in
57
+ * the Electron main process, per CLAUDE.md §8).
58
+ *
59
+ * Modelled exactly on `autoSnapshotDelayMs`: a missing or partial policy means
60
+ * "defaults" (enabled, 2 min); a non-finite/absurd minutes value falls back to
61
+ * the default and is then clamped into [AUTO_SYNC_MIN_MINUTES,
62
+ * AUTO_SYNC_MAX_MINUTES].
63
+ *
64
+ * Note: the host orchestrator ALSO debounces on file-change triggers; this
65
+ * cadence governs only the periodic safety timer (§4.2 "Periodic safety").
66
+ */
67
+ export declare function autoSyncDelayMs(policy: Partial<AutoSyncPolicy> | undefined): number | null;
68
+ /**
69
+ * True when a changed path is internal Git state (any `.git` segment). The
70
+ * host's project watcher and auto-snapshot triggers must IGNORE these: the
71
+ * automatic snapshot itself writes under `.git`, and treating that as a
72
+ * content change would re-trigger preview reloads / re-arm the timer forever.
73
+ * Accepts absolute paths, relative paths, or bare basenames.
74
+ */
75
+ export declare function isGitInternalPath(p: string): boolean;