@thinkingsage/kanon 0.8.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 (199) hide show
  1. package/CHANGELOG.md +410 -0
  2. package/LICENSE +21 -0
  3. package/README.md +168 -0
  4. package/bridge/mcp-server.cjs +14171 -0
  5. package/package.json +98 -0
  6. package/src/adapters/capabilities.ts +178 -0
  7. package/src/adapters/claude-code.ts +110 -0
  8. package/src/adapters/cline.ts +98 -0
  9. package/src/adapters/codex.ts +173 -0
  10. package/src/adapters/copilot.ts +106 -0
  11. package/src/adapters/cursor.ts +97 -0
  12. package/src/adapters/degradation.ts +95 -0
  13. package/src/adapters/index.ts +324 -0
  14. package/src/adapters/kiro-frontmatter.ts +139 -0
  15. package/src/adapters/kiro-inclusion.ts +86 -0
  16. package/src/adapters/kiro.ts +412 -0
  17. package/src/adapters/qdeveloper.ts +115 -0
  18. package/src/adapters/types.ts +81 -0
  19. package/src/adapters/windsurf.ts +96 -0
  20. package/src/admin.ts +283 -0
  21. package/src/asset-conventions.ts +118 -0
  22. package/src/attribution-backfill.ts +319 -0
  23. package/src/attribution-report.ts +95 -0
  24. package/src/attribution.ts +239 -0
  25. package/src/backends/github.ts +194 -0
  26. package/src/backends/http.ts +122 -0
  27. package/src/backends/index.ts +39 -0
  28. package/src/backends/local.ts +47 -0
  29. package/src/backends/s3.ts +157 -0
  30. package/src/backends/types.ts +59 -0
  31. package/src/base-cache.ts +270 -0
  32. package/src/browse-ui.ts +3754 -0
  33. package/src/browse.ts +1038 -0
  34. package/src/build.ts +1108 -0
  35. package/src/catalog.ts +204 -0
  36. package/src/cli-deprecated.ts +29 -0
  37. package/src/cli.ts +773 -0
  38. package/src/collection-admin.ts +287 -0
  39. package/src/collection-builder.ts +464 -0
  40. package/src/collections.ts +116 -0
  41. package/src/compatibility.ts +105 -0
  42. package/src/config.ts +743 -0
  43. package/src/eval/rubrics/kiro-progressive-steering.ts +841 -0
  44. package/src/eval.ts +1169 -0
  45. package/src/file-writer.ts +61 -0
  46. package/src/format-registry.ts +141 -0
  47. package/src/guild/auto-updater.ts +163 -0
  48. package/src/guild/backend-resolver.ts +49 -0
  49. package/src/guild/cli.ts +592 -0
  50. package/src/guild/collection-expander.ts +47 -0
  51. package/src/guild/global-cache.ts +247 -0
  52. package/src/guild/hook-generator.ts +100 -0
  53. package/src/guild/manifest.ts +154 -0
  54. package/src/guild/path-utils.ts +12 -0
  55. package/src/guild/sync.ts +622 -0
  56. package/src/guild/version-resolver.ts +42 -0
  57. package/src/help/metadata.ts +445 -0
  58. package/src/help/renderer.ts +265 -0
  59. package/src/help/typo-suggester.ts +25 -0
  60. package/src/hooks/expression.ts +493 -0
  61. package/src/hooks/pipeline.ts +141 -0
  62. package/src/import.ts +773 -0
  63. package/src/importers/claude-code.ts +134 -0
  64. package/src/importers/cline.ts +103 -0
  65. package/src/importers/codex.ts +140 -0
  66. package/src/importers/copilot.ts +103 -0
  67. package/src/importers/cursor.ts +105 -0
  68. package/src/importers/index.ts +390 -0
  69. package/src/importers/kiro.ts +110 -0
  70. package/src/importers/qdeveloper.ts +103 -0
  71. package/src/importers/types.ts +54 -0
  72. package/src/importers/windsurf.ts +104 -0
  73. package/src/install.ts +1005 -0
  74. package/src/manifest-admin.ts +306 -0
  75. package/src/mcp-bridge.ts +240 -0
  76. package/src/mutation/delta.ts +50 -0
  77. package/src/mutation/history.ts +66 -0
  78. package/src/mutation/operators.ts +524 -0
  79. package/src/mutation/runner.ts +332 -0
  80. package/src/new.ts +106 -0
  81. package/src/outcomes/collision.ts +127 -0
  82. package/src/outcomes/normalize.ts +208 -0
  83. package/src/outcomes/registry.ts +173 -0
  84. package/src/parser.ts +446 -0
  85. package/src/provenance-backfill-cli.ts +319 -0
  86. package/src/provenance-backfill.ts +520 -0
  87. package/src/publish.ts +354 -0
  88. package/src/reconcile-orchestrator.ts +502 -0
  89. package/src/reconcile-report-renderer.ts +176 -0
  90. package/src/resolve-body.ts +15 -0
  91. package/src/rosetta/builtins/compatibility-profiles.ts +297 -0
  92. package/src/rosetta/builtins/contracts.ts +1033 -0
  93. package/src/rosetta/builtins/pretty-printers/claude-code-native.ts +122 -0
  94. package/src/rosetta/builtins/pretty-printers/cline-native.ts +50 -0
  95. package/src/rosetta/builtins/pretty-printers/codex-native.ts +127 -0
  96. package/src/rosetta/builtins/pretty-printers/copilot-native.ts +50 -0
  97. package/src/rosetta/builtins/pretty-printers/cursor-native.ts +50 -0
  98. package/src/rosetta/builtins/pretty-printers/index.ts +81 -0
  99. package/src/rosetta/builtins/pretty-printers/kiro-native.ts +166 -0
  100. package/src/rosetta/builtins/pretty-printers/kiro-power.ts +108 -0
  101. package/src/rosetta/builtins/pretty-printers/kiro-skill.ts +88 -0
  102. package/src/rosetta/builtins/pretty-printers/qdeveloper-native.ts +51 -0
  103. package/src/rosetta/builtins/pretty-printers/superpowers.ts +97 -0
  104. package/src/rosetta/builtins/pretty-printers/windsurf-native.ts +50 -0
  105. package/src/rosetta/builtins/sources/claude-code-native.ts +348 -0
  106. package/src/rosetta/builtins/sources/cline-native.ts +176 -0
  107. package/src/rosetta/builtins/sources/codex-native.ts +343 -0
  108. package/src/rosetta/builtins/sources/copilot-native.ts +178 -0
  109. package/src/rosetta/builtins/sources/cursor-native.ts +176 -0
  110. package/src/rosetta/builtins/sources/index.ts +95 -0
  111. package/src/rosetta/builtins/sources/kiro-native.ts +462 -0
  112. package/src/rosetta/builtins/sources/kiro-power.ts +285 -0
  113. package/src/rosetta/builtins/sources/kiro-skill.ts +230 -0
  114. package/src/rosetta/builtins/sources/qdeveloper-native.ts +181 -0
  115. package/src/rosetta/builtins/sources/superpowers.ts +240 -0
  116. package/src/rosetta/builtins/sources/windsurf-native.ts +176 -0
  117. package/src/rosetta/builtins/targets/claude-code.ts +181 -0
  118. package/src/rosetta/builtins/targets/cline.ts +87 -0
  119. package/src/rosetta/builtins/targets/codex.ts +226 -0
  120. package/src/rosetta/builtins/targets/copilot.ts +103 -0
  121. package/src/rosetta/builtins/targets/cursor.ts +87 -0
  122. package/src/rosetta/builtins/targets/index.ts +60 -0
  123. package/src/rosetta/builtins/targets/kiro.ts +278 -0
  124. package/src/rosetta/builtins/targets/qdeveloper.ts +103 -0
  125. package/src/rosetta/builtins/targets/windsurf.ts +87 -0
  126. package/src/rosetta/canonical.ts +729 -0
  127. package/src/rosetta/compatibility.ts +432 -0
  128. package/src/rosetta/contracts.ts +329 -0
  129. package/src/rosetta/detector.ts +724 -0
  130. package/src/rosetta/diagnostics.ts +630 -0
  131. package/src/rosetta/engine-bootstrap.ts +103 -0
  132. package/src/rosetta/engine.ts +744 -0
  133. package/src/rosetta/index.ts +381 -0
  134. package/src/rosetta/inspection.ts +530 -0
  135. package/src/rosetta/plan.ts +448 -0
  136. package/src/rosetta/provenance-digest.ts +369 -0
  137. package/src/rosetta/reconcile.ts +812 -0
  138. package/src/rosetta/redaction.ts +467 -0
  139. package/src/rosetta/registry.ts +712 -0
  140. package/src/rosetta/renderers.ts +571 -0
  141. package/src/rosetta/request-guard.ts +335 -0
  142. package/src/rosetta/resolution.ts +419 -0
  143. package/src/rosetta/source-accounting.ts +233 -0
  144. package/src/rosetta/templates.ts +129 -0
  145. package/src/rosetta-cli.ts +717 -0
  146. package/src/rosetta-docs-generator.ts +793 -0
  147. package/src/rosetta-profiles-cli.ts +367 -0
  148. package/src/schemas.ts +1712 -0
  149. package/src/spec-coordination.ts +1141 -0
  150. package/src/temper.ts +747 -0
  151. package/src/template-bundle-loader.ts +312 -0
  152. package/src/template-engine.ts +53 -0
  153. package/src/translation-application-policy.ts +496 -0
  154. package/src/translation-orchestrator.ts +1013 -0
  155. package/src/translation-plan-applier.ts +473 -0
  156. package/src/tutorial.ts +305 -0
  157. package/src/validate.ts +1093 -0
  158. package/src/versioning.ts +553 -0
  159. package/src/wizard.ts +660 -0
  160. package/src/workspace.ts +237 -0
  161. package/templates/eval-contexts/claude-code.md.njk +6 -0
  162. package/templates/eval-contexts/cline.md.njk +6 -0
  163. package/templates/eval-contexts/copilot.md.njk +6 -0
  164. package/templates/eval-contexts/cursor.md.njk +6 -0
  165. package/templates/eval-contexts/kiro.md.njk +10 -0
  166. package/templates/eval-contexts/qdeveloper.md.njk +6 -0
  167. package/templates/eval-contexts/windsurf.md.njk +6 -0
  168. package/templates/harness-adapters/_base/attribution-footer.md.njk +17 -0
  169. package/templates/harness-adapters/_base/base.md.njk +16 -0
  170. package/templates/harness-adapters/claude-code/claude.md.njk +1 -0
  171. package/templates/harness-adapters/claude-code/mcp.json.njk +1 -0
  172. package/templates/harness-adapters/claude-code/settings.json.njk +1 -0
  173. package/templates/harness-adapters/claude-code/skill-library-index.md.njk +13 -0
  174. package/templates/harness-adapters/claude-code/skill.md.njk +19 -0
  175. package/templates/harness-adapters/cline/hook.sh.njk +4 -0
  176. package/templates/harness-adapters/cline/mcp.json.njk +1 -0
  177. package/templates/harness-adapters/cline/rule.md.njk +1 -0
  178. package/templates/harness-adapters/codex/agents-md.md.njk +6 -0
  179. package/templates/harness-adapters/codex/agents-pointer.md.njk +16 -0
  180. package/templates/harness-adapters/codex/skill.md.njk +27 -0
  181. package/templates/harness-adapters/copilot/agents.md.njk +1 -0
  182. package/templates/harness-adapters/copilot/instructions.md.njk +1 -0
  183. package/templates/harness-adapters/copilot/scoped.md.njk +6 -0
  184. package/templates/harness-adapters/cursor/mcp.json.njk +1 -0
  185. package/templates/harness-adapters/cursor/rule.md.njk +6 -0
  186. package/templates/harness-adapters/kiro/hook.json.njk +1 -0
  187. package/templates/harness-adapters/kiro/mcp.json.njk +1 -0
  188. package/templates/harness-adapters/kiro/power-steering.md.njk +3 -0
  189. package/templates/harness-adapters/kiro/power.md.njk +12 -0
  190. package/templates/harness-adapters/kiro/steering.md.njk +16 -0
  191. package/templates/harness-adapters/qdeveloper/agent.md.njk +1 -0
  192. package/templates/harness-adapters/qdeveloper/mcp.json.njk +1 -0
  193. package/templates/harness-adapters/qdeveloper/rule.md.njk +1 -0
  194. package/templates/harness-adapters/windsurf/mcp.json.njk +1 -0
  195. package/templates/harness-adapters/windsurf/rule.md.njk +1 -0
  196. package/templates/harness-adapters/windsurf/workflow.md.njk +1 -0
  197. package/templates/knowledge/hooks.yaml.njk +4 -0
  198. package/templates/knowledge/knowledge.md.njk +53 -0
  199. package/templates/knowledge/mcp-servers.yaml.njk +2 -0
@@ -0,0 +1,793 @@
1
+ /**
2
+ * Rosetta Stone — Documentation Generator
3
+ *
4
+ * Bun script that generates reference documentation from the frozen registry
5
+ * and schema types. Outputs checked-in Markdown files to `docs/rosetta/`.
6
+ *
7
+ * Run: `bun run src/rosetta-docs-generator.ts`
8
+ *
9
+ * CONSTRAINTS:
10
+ * - Reads from BUILTIN_FORMAT_CONTRACTS and schema types
11
+ * - Does NOT hardcode format data — all content is derived from the registry
12
+ * - Output is deterministic and stable across runs
13
+ *
14
+ * Requirements: 17.2, 17.3, 17.4, 17.7, 17.8
15
+ */
16
+
17
+ import { mkdirSync, writeFileSync } from "node:fs";
18
+ import { join } from "node:path";
19
+
20
+ import {
21
+ BUILTIN_FORMAT_CONTRACTS,
22
+ SELECTION_ALIASES,
23
+ } from "./rosetta/builtins/contracts";
24
+ import type { DiagnosticCodeMetadata } from "./rosetta/diagnostics";
25
+ import { DIAGNOSTIC_CODE_REGISTRY } from "./rosetta/diagnostics";
26
+ import type {
27
+ FormatContract,
28
+ RosettaCompatibilityEntry,
29
+ RosettaCompatibilityProfile,
30
+ } from "./schemas";
31
+ import { AcquisitionProfileSchema, TranslationProfileSchema } from "./schemas";
32
+
33
+ // ═══════════════════════════════════════════════════════════════════════════════
34
+ // Configuration
35
+ // ═══════════════════════════════════════════════════════════════════════════════
36
+
37
+ const OUTPUT_DIR = join(import.meta.dir, "..", "docs", "rosetta");
38
+
39
+ // ═══════════════════════════════════════════════════════════════════════════════
40
+ // Helpers
41
+ // ═══════════════════════════════════════════════════════════════════════════════
42
+
43
+ function ensureOutputDir(): void {
44
+ mkdirSync(OUTPUT_DIR, { recursive: true });
45
+ }
46
+
47
+ function writeDoc(filename: string, content: string): void {
48
+ writeFileSync(join(OUTPUT_DIR, filename), content);
49
+ console.log(` Generated: docs/rosetta/${filename}`);
50
+ }
51
+
52
+ function escapeCell(value: string): string {
53
+ return value.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\n/g, " ");
54
+ }
55
+
56
+ // ═══════════════════════════════════════════════════════════════════════════════
57
+ // Format Reference
58
+ // ═══════════════════════════════════════════════════════════════════════════════
59
+
60
+ export function generateFormatReference(): string {
61
+ const lines: string[] = [
62
+ "# Format Reference",
63
+ "",
64
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
65
+ "",
66
+ "## Registered Formats",
67
+ "",
68
+ "| ID | Direction | Harness | Aliases | Default Variant | Lifecycle | Contract Version |",
69
+ "|---|---|---|---|---|---|---|",
70
+ ];
71
+
72
+ for (const contract of BUILTIN_FORMAT_CONTRACTS) {
73
+ const aliases =
74
+ contract.aliases.length > 0 ? contract.aliases.join(", ") : "—";
75
+ const harness = contract.harness ?? "none";
76
+ const defaultVariant = contract.defaultVariant ?? "—";
77
+ const lifecycle = contract.lifecycle.status;
78
+ lines.push(
79
+ `| \`${contract.id}\` | ${contract.direction} | ${harness} | ${aliases} | ${escapeCell(String(defaultVariant))} | ${lifecycle} | ${contract.contractVersion} |`,
80
+ );
81
+ }
82
+
83
+ lines.push("");
84
+ lines.push("## Selection Aliases");
85
+ lines.push("");
86
+ lines.push("| ID | Status | Description | Replacement |");
87
+ lines.push("|---|---|---|---|");
88
+
89
+ for (const [id, meta] of Object.entries(SELECTION_ALIASES)) {
90
+ lines.push(
91
+ `| \`${id}\` | ${meta.status} | ${escapeCell(meta.description)} | ${escapeCell(meta.replacement)} |`,
92
+ );
93
+ }
94
+
95
+ lines.push("");
96
+ return lines.join("\n");
97
+ }
98
+
99
+ // ═══════════════════════════════════════════════════════════════════════════════
100
+ // Variant Reference
101
+ // ═══════════════════════════════════════════════════════════════════════════════
102
+
103
+ export function generateVariantReference(): string {
104
+ const lines: string[] = [
105
+ "# Variant Reference",
106
+ "",
107
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
108
+ "",
109
+ ];
110
+
111
+ for (const contract of BUILTIN_FORMAT_CONTRACTS) {
112
+ const variants = Object.entries(contract.variants);
113
+ if (variants.length === 0) continue;
114
+
115
+ lines.push(`## ${contract.id}`);
116
+ lines.push("");
117
+ lines.push(`Default variant: \`${contract.defaultVariant ?? "none"}\``);
118
+ lines.push("");
119
+ lines.push(
120
+ "| Variant | Description | Path Conventions | Option Overrides |",
121
+ );
122
+ lines.push("|---|---|---|---|");
123
+
124
+ for (const [variantId, variant] of variants) {
125
+ const paths =
126
+ variant.pathConventions?.map((p) => `\`${p.pattern}\``).join(", ") ??
127
+ "—";
128
+ const overrides =
129
+ Object.keys(variant.optionOverrides ?? {}).length > 0
130
+ ? JSON.stringify(variant.optionOverrides)
131
+ : "—";
132
+ lines.push(
133
+ `| \`${variantId}\` | ${escapeCell(variant.description ?? "—")} | ${paths} | ${escapeCell(overrides)} |`,
134
+ );
135
+ }
136
+
137
+ lines.push("");
138
+ }
139
+
140
+ return lines.join("\n");
141
+ }
142
+
143
+ // ═══════════════════════════════════════════════════════════════════════════════
144
+ // Detection Reference
145
+ // ═══════════════════════════════════════════════════════════════════════════════
146
+
147
+ export function generateDetectionReference(): string {
148
+ const lines: string[] = [
149
+ "# Detection Reference",
150
+ "",
151
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
152
+ "",
153
+ ];
154
+
155
+ const sourceFormats = BUILTIN_FORMAT_CONTRACTS.filter(
156
+ (c) => c.direction === "source" || c.direction === "bidirectional",
157
+ );
158
+
159
+ for (const contract of sourceFormats) {
160
+ lines.push(`## ${contract.id}`);
161
+ lines.push("");
162
+ lines.push(`Threshold: ${contract.detection.threshold}`);
163
+ lines.push("");
164
+ lines.push(
165
+ "| Rule ID | Kind | Pattern | Weight | Required | Evidence Label |",
166
+ );
167
+ lines.push("|---|---|---|---|---|---|");
168
+
169
+ for (const rule of contract.detection.rules) {
170
+ lines.push(
171
+ `| \`${rule.id}\` | ${rule.kind} | \`${escapeCell(rule.pattern)}\` | ${rule.weight} | ${rule.required ? "yes" : "no"} | ${escapeCell(rule.evidenceLabel)} |`,
172
+ );
173
+ }
174
+
175
+ lines.push("");
176
+ }
177
+
178
+ return lines.join("\n");
179
+ }
180
+
181
+ // ═══════════════════════════════════════════════════════════════════════════════
182
+ // Lifecycle Reference
183
+ // ═══════════════════════════════════════════════════════════════════════════════
184
+
185
+ export function generateLifecycleReference(): string {
186
+ const lines: string[] = [
187
+ "# Lifecycle Reference",
188
+ "",
189
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
190
+ "",
191
+ ];
192
+
193
+ const byStatus: Record<string, FormatContract[]> = {};
194
+ for (const contract of BUILTIN_FORMAT_CONTRACTS) {
195
+ const status = contract.lifecycle.status;
196
+ if (!byStatus[status]) byStatus[status] = [];
197
+ byStatus[status].push(contract);
198
+ }
199
+
200
+ const statusOrder = ["active", "experimental", "deprecated", "retired"];
201
+ for (const status of statusOrder) {
202
+ const contracts = byStatus[status];
203
+ if (!contracts || contracts.length === 0) continue;
204
+
205
+ lines.push(
206
+ `## ${status.charAt(0).toUpperCase() + status.slice(1)} Formats`,
207
+ );
208
+ lines.push("");
209
+ lines.push("| Format | Introduced In | Deprecated In | Replacement |");
210
+ lines.push("|---|---|---|---|");
211
+
212
+ for (const contract of contracts) {
213
+ const lc = contract.lifecycle;
214
+ const introduced = lc.introducedIn ?? "—";
215
+ const deprecated =
216
+ "deprecatedIn" in lc ? ((lc.deprecatedIn as string) ?? "—") : "—";
217
+ const replacement =
218
+ "replacement" in lc ? ((lc.replacement as string) ?? "—") : "—";
219
+ lines.push(
220
+ `| \`${contract.id}\` | ${introduced} | ${deprecated} | ${replacement} |`,
221
+ );
222
+ }
223
+
224
+ lines.push("");
225
+ }
226
+
227
+ return lines.join("\n");
228
+ }
229
+
230
+ // ═══════════════════════════════════════════════════════════════════════════════
231
+ // Compatibility Reference
232
+ // ═══════════════════════════════════════════════════════════════════════════════
233
+
234
+ export function generateCompatibilityReference(): string {
235
+ const lines: string[] = [
236
+ "# Compatibility Reference",
237
+ "",
238
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
239
+ "",
240
+ ];
241
+
242
+ for (const contract of BUILTIN_FORMAT_CONTRACTS) {
243
+ lines.push(`## ${contract.id}`);
244
+ lines.push("");
245
+ lines.push(`Harness: ${contract.harness ?? "none"}`);
246
+ lines.push("");
247
+ lines.push("| Capability | Support | Degradation Action |");
248
+ lines.push("|---|---|---|");
249
+
250
+ const profile = contract.compatibility as RosettaCompatibilityProfile;
251
+ const capabilities = Object.keys(profile).sort();
252
+ for (const cap of capabilities) {
253
+ const entry = (profile as Record<string, RosettaCompatibilityEntry>)[cap];
254
+ const degradation = entry.degradation ?? "—";
255
+ lines.push(`| ${cap} | ${entry.support} | ${degradation} |`);
256
+ }
257
+
258
+ lines.push("");
259
+ }
260
+
261
+ return lines.join("\n");
262
+ }
263
+
264
+ // ═══════════════════════════════════════════════════════════════════════════════
265
+ // Profile Field Reference
266
+ // ═══════════════════════════════════════════════════════════════════════════════
267
+
268
+ export interface ZodFieldInfo {
269
+ name: string;
270
+ type: string;
271
+ default: string;
272
+ optional: boolean;
273
+ }
274
+
275
+ function getZodInnerType(def: {
276
+ type?: string;
277
+ innerType?: { _zod?: { def?: { type?: string } } };
278
+ }): string {
279
+ const inner = def.innerType?._zod?.def;
280
+ return inner?.type ?? "unknown";
281
+ }
282
+
283
+ export function extractZodFields(schema: {
284
+ shape: Record<string, unknown>;
285
+ }): ZodFieldInfo[] {
286
+ const fields: ZodFieldInfo[] = [];
287
+
288
+ const shape = schema.shape;
289
+ for (const [name, fieldSchema] of Object.entries(shape)) {
290
+ let type = "unknown";
291
+ let defaultValue = "—";
292
+ let optional = false;
293
+
294
+ // Zod 4 internal structure: _zod.def.type
295
+ const s = fieldSchema as {
296
+ _zod?: {
297
+ def?: {
298
+ type?: string;
299
+ defaultValue?: unknown;
300
+ innerType?: { _zod?: { def?: { type?: string } } };
301
+ };
302
+ };
303
+ };
304
+ const def = s?._zod?.def;
305
+ if (def) {
306
+ if (def.type === "default") {
307
+ const raw = def.defaultValue;
308
+ defaultValue = JSON.stringify(raw);
309
+ type = getZodInnerType(def);
310
+ } else if (def.type === "optional") {
311
+ optional = true;
312
+ type = getZodInnerType(def);
313
+ } else {
314
+ type = def.type ?? "unknown";
315
+ }
316
+ }
317
+
318
+ fields.push({ name, type, default: defaultValue, optional });
319
+ }
320
+
321
+ return fields;
322
+ }
323
+
324
+ export function generateProfileFieldReference(): string {
325
+ const lines: string[] = [
326
+ "# Profile Field Reference",
327
+ "",
328
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
329
+ "",
330
+ "## Acquisition Profile Fields",
331
+ "",
332
+ "| Field | Type | Default | Required | Description |",
333
+ "|---|---|---|---|---|",
334
+ ];
335
+
336
+ const acquisitionFields = extractZodFields(AcquisitionProfileSchema);
337
+ for (const field of acquisitionFields) {
338
+ const required = !field.optional && field.default === "—" ? "yes" : "no";
339
+ lines.push(
340
+ `| \`${field.name}\` | ${field.type} | ${field.default} | ${required} | — |`,
341
+ );
342
+ }
343
+
344
+ lines.push("");
345
+ lines.push("## Translation Profile Fields");
346
+ lines.push("");
347
+ lines.push("| Field | Type | Default | Required | Description |");
348
+ lines.push("|---|---|---|---|---|");
349
+
350
+ const translationFields = extractZodFields(TranslationProfileSchema);
351
+ for (const field of translationFields) {
352
+ const required = !field.optional && field.default === "—" ? "yes" : "no";
353
+ lines.push(
354
+ `| \`${field.name}\` | ${field.type} | ${field.default} | ${required} | — |`,
355
+ );
356
+ }
357
+
358
+ lines.push("");
359
+ lines.push("## Profile Precedence Order");
360
+ lines.push("");
361
+ lines.push("Option resolution follows this precedence (highest wins):");
362
+ lines.push("");
363
+ lines.push("1. Explicit CLI flag (`--variant`, `--strict`, etc.)");
364
+ lines.push("2. Named translation profile from `kanon.config.yaml`");
365
+ lines.push("3. Canonical `harness-config` in the artifact");
366
+ lines.push("4. Format contract default");
367
+ lines.push("");
368
+ lines.push("## Security Constraints");
369
+ lines.push("");
370
+ lines.push(
371
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: literal ${ENV_VAR} in documentation output
372
+ "- `credentialReference` in acquisition profiles accepts `${ENV_VAR}` references only",
373
+ );
374
+ lines.push("- Literal credentials are rejected during profile validation");
375
+ lines.push(
376
+ "- Sensitive values are never logged or included in diagnostic payloads",
377
+ );
378
+ lines.push("");
379
+
380
+ return lines.join("\n");
381
+ }
382
+
383
+ // ═══════════════════════════════════════════════════════════════════════════════
384
+ // Normalization Reference
385
+ // ═══════════════════════════════════════════════════════════════════════════════
386
+
387
+ export function generateNormalizationReference(): string {
388
+ const lines: string[] = [
389
+ "# Normalization Reference",
390
+ "",
391
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
392
+ "",
393
+ ];
394
+
395
+ for (const contract of BUILTIN_FORMAT_CONTRACTS) {
396
+ if (contract.normalizationRules.length === 0) continue;
397
+
398
+ lines.push(`## ${contract.id}`);
399
+ lines.push("");
400
+ lines.push("| Rule ID | Description | Scope |");
401
+ lines.push("|---|---|---|");
402
+
403
+ for (const rule of contract.normalizationRules) {
404
+ lines.push(
405
+ `| \`${rule.id}\` | ${escapeCell(rule.description)} | ${rule.scope} |`,
406
+ );
407
+ }
408
+
409
+ lines.push("");
410
+ }
411
+
412
+ return lines.join("\n");
413
+ }
414
+
415
+ // ═══════════════════════════════════════════════════════════════════════════════
416
+ // Security Reference
417
+ // ═══════════════════════════════════════════════════════════════════════════════
418
+
419
+ export function generateSecurityReference(): string {
420
+ const lines: string[] = [
421
+ "# Security Reference",
422
+ "",
423
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
424
+ "",
425
+ "## Sensitive Value Policies",
426
+ "",
427
+ "| Format | Policy | Allowed Reference Patterns |",
428
+ "|---|---|---|",
429
+ ];
430
+
431
+ for (const contract of BUILTIN_FORMAT_CONTRACTS) {
432
+ const policy = contract.security.sensitiveValuePolicy;
433
+ const patterns =
434
+ contract.security.allowedReferencePatterns.length > 0
435
+ ? contract.security.allowedReferencePatterns
436
+ .map((p) => `\`${p}\``)
437
+ .join(", ")
438
+ : "—";
439
+ lines.push(`| \`${contract.id}\` | ${policy} | ${patterns} |`);
440
+ }
441
+
442
+ lines.push("");
443
+ lines.push("## Policy Descriptions");
444
+ lines.push("");
445
+ lines.push(
446
+ "- **reject**: Sensitive values are rejected entirely. No credentials allowed in content.",
447
+ );
448
+ lines.push(
449
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: literal ${ENV_VAR} in documentation output
450
+ "- **reference-only**: Only `${ENV_VAR}` style references are permitted. Raw secrets are rejected.",
451
+ );
452
+ lines.push(
453
+ "- **preserve**: Sensitive values pass through unchanged (not currently used by built-ins).",
454
+ );
455
+ lines.push("");
456
+
457
+ return lines.join("\n");
458
+ }
459
+
460
+ // ═══════════════════════════════════════════════════════════════════════════════
461
+ // CLI Examples
462
+ // ═══════════════════════════════════════════════════════════════════════════════
463
+
464
+ export function generateCliExamples(): string {
465
+ const lines: string[] = [
466
+ "# CLI Examples",
467
+ "",
468
+ "> Auto-generated executable examples for the `kanon rosetta` commands.",
469
+ "",
470
+ "## List Formats",
471
+ "",
472
+ "List all registered format contracts:",
473
+ "",
474
+ "```bash",
475
+ "kanon rosetta formats",
476
+ "```",
477
+ "",
478
+ "List formats as JSON:",
479
+ "",
480
+ "```bash",
481
+ "kanon rosetta formats --json",
482
+ "```",
483
+ "",
484
+ "## Detect Format",
485
+ "",
486
+ "Detect the source format of an artifact directory:",
487
+ "",
488
+ "```bash",
489
+ "kanon rosetta detect ./path/to/artifact",
490
+ "```",
491
+ "",
492
+ "Detect with JSON output:",
493
+ "",
494
+ "```bash",
495
+ "kanon rosetta detect ./path/to/artifact --json",
496
+ "```",
497
+ "",
498
+ "## Explicit Selection",
499
+ "",
500
+ "Validate that a specific format is detected (explicit selection has precedence):",
501
+ "",
502
+ "```bash",
503
+ "kanon rosetta detect ./path/to/artifact --format kiro-power",
504
+ "```",
505
+ "",
506
+ "## Inspect Translation",
507
+ "",
508
+ "Inspect an inbound translation plan (source to canonical) as JSON:",
509
+ "",
510
+ "```bash",
511
+ "kanon rosetta inspect ./path/to/artifact --from kiro-power --json",
512
+ "```",
513
+ "",
514
+ "Inspect an outbound translation (canonical to target):",
515
+ "",
516
+ "```bash",
517
+ "kanon rosetta inspect ./path/to/artifact --to cursor --json",
518
+ "```",
519
+ "",
520
+ "## Dry Run",
521
+ "",
522
+ "Preview a translation without writing files:",
523
+ "",
524
+ "```bash",
525
+ "kanon rosetta translate ./path/to/artifact --from kiro-power --dry-run",
526
+ "```",
527
+ "",
528
+ "## Strict Mode with JSON Output",
529
+ "",
530
+ "Translate with strict mode (promote compatibility diagnostics to errors) and JSON output:",
531
+ "",
532
+ "```bash",
533
+ "kanon rosetta translate ./path/to/artifact --from kanon-canonical --to cursor --strict --json",
534
+ "```",
535
+ "",
536
+ "## Inbound Translation",
537
+ "",
538
+ "Translate from a source format into canonical:",
539
+ "",
540
+ "```bash",
541
+ "kanon rosetta translate ./path/to/artifact --from kiro-power",
542
+ "```",
543
+ "",
544
+ "Translate from a harness-native format:",
545
+ "",
546
+ "```bash",
547
+ "kanon rosetta translate ./path/to/artifact --from claude-code",
548
+ "```",
549
+ "",
550
+ "## Outbound Translation",
551
+ "",
552
+ "Translate from canonical to a target format:",
553
+ "",
554
+ "```bash",
555
+ "kanon rosetta translate ./knowledge/my-artifact --to kiro",
556
+ "```",
557
+ "",
558
+ "Translate with an explicit variant:",
559
+ "",
560
+ "```bash",
561
+ "kanon rosetta translate ./knowledge/my-artifact --to kiro --variant power",
562
+ "```",
563
+ "",
564
+ "## Transcode (Source-to-Target)",
565
+ "",
566
+ "Translate directly between formats (source to canonical to target):",
567
+ "",
568
+ "```bash",
569
+ "kanon rosetta translate ./path/to/artifact --from kiro-power --to cursor",
570
+ "```",
571
+ "",
572
+ "## Using Profiles",
573
+ "",
574
+ "Translate using a named profile from `kanon.config.yaml`:",
575
+ "",
576
+ "```bash",
577
+ "kanon rosetta translate ./path/to/artifact --profile upstream-kiro",
578
+ "```",
579
+ "",
580
+ ];
581
+
582
+ return lines.join("\n");
583
+ }
584
+
585
+ // ═══════════════════════════════════════════════════════════════════════════════
586
+ // Degradation Reference (combined with compatibility)
587
+ // ═══════════════════════════════════════════════════════════════════════════════
588
+
589
+ export function generateDegradationReference(): string {
590
+ const lines: string[] = [
591
+ "# Degradation Reference",
592
+ "",
593
+ "> Auto-generated from the frozen Rosetta Stone registry. Do not edit manually.",
594
+ "",
595
+ "This document lists the degradation actions declared by each format contract",
596
+ "for capabilities with `partial` or `none` support levels.",
597
+ "",
598
+ ];
599
+
600
+ for (const contract of BUILTIN_FORMAT_CONTRACTS) {
601
+ const profile = contract.compatibility as RosettaCompatibilityProfile;
602
+ const degradedCaps: Array<{
603
+ cap: string;
604
+ entry: RosettaCompatibilityEntry;
605
+ }> = [];
606
+
607
+ for (const [cap, entry] of Object.entries(profile) as Array<
608
+ [string, RosettaCompatibilityEntry]
609
+ >) {
610
+ if (entry.support !== "full") {
611
+ degradedCaps.push({ cap, entry });
612
+ }
613
+ }
614
+
615
+ if (degradedCaps.length === 0) continue;
616
+
617
+ lines.push(`## ${contract.id}`);
618
+ lines.push("");
619
+ lines.push("| Capability | Support | Degradation Action |");
620
+ lines.push("|---|---|---|");
621
+
622
+ for (const { cap, entry } of degradedCaps.sort((a, b) =>
623
+ a.cap.localeCompare(b.cap),
624
+ )) {
625
+ const action = entry.degradation ?? "—";
626
+ lines.push(`| ${cap} | ${entry.support} | ${action} |`);
627
+ }
628
+
629
+ lines.push("");
630
+ }
631
+
632
+ return lines.join("\n");
633
+ }
634
+
635
+ // ═══════════════════════════════════════════════════════════════════════════════
636
+ // Diagnostic Conventions (generated from DIAGNOSTIC_CODE_REGISTRY)
637
+ // ═══════════════════════════════════════════════════════════════════════════════
638
+
639
+ export function generateDiagnosticConventions(): string {
640
+ const lines: string[] = [
641
+ "# Diagnostic Conventions",
642
+ "",
643
+ "> Auto-generated RS_* code reference from the frozen diagnostic registry.",
644
+ "> See also the hand-written guidance in this file for naming, severity,",
645
+ "> phase ordering, blocking metadata, and safe construction rules.",
646
+ "",
647
+ "## Registered Diagnostic Codes",
648
+ "",
649
+ "| Code | Phase | Severity | Blocking | Description |",
650
+ "|---|---|---|---|---|",
651
+ ];
652
+
653
+ const entries = Object.values(
654
+ DIAGNOSTIC_CODE_REGISTRY,
655
+ ) as DiagnosticCodeMetadata[];
656
+ const sorted = [...entries].sort((a, b) => a.code.localeCompare(b.code));
657
+
658
+ for (const entry of sorted) {
659
+ lines.push(
660
+ `| \`${entry.code}\` | ${entry.phase} | ${entry.defaultSeverity} | ${entry.blocking ? "Yes" : "No"} | ${escapeCell(entry.messageTemplate)} |`,
661
+ );
662
+ }
663
+
664
+ lines.push("");
665
+ lines.push("## Code Naming Convention");
666
+ lines.push("");
667
+ lines.push(
668
+ "All codes use the `RS_` prefix followed by a category and optional detail:",
669
+ );
670
+ lines.push("");
671
+ lines.push("```");
672
+ lines.push("RS_<CATEGORY>_<DETAIL>");
673
+ lines.push("```");
674
+ lines.push("");
675
+ lines.push("## Severity Rules");
676
+ lines.push("");
677
+ lines.push("| Severity | Meaning | Blocks Application |");
678
+ lines.push("|---|---|---|");
679
+ lines.push("| `info` | Informational note | Never |");
680
+ lines.push(
681
+ "| `warning` | Potential issue, review recommended | Only in strict mode |",
682
+ );
683
+ lines.push(
684
+ "| `error` | Translation cannot proceed safely | Always (if blocking) |",
685
+ );
686
+ lines.push("");
687
+ lines.push("## Phase Order");
688
+ lines.push("");
689
+ lines.push(
690
+ "Diagnostics sort by phase (lower = earlier), then severity, then code:",
691
+ );
692
+ lines.push("");
693
+ lines.push("1. request");
694
+ lines.push("2. registry");
695
+ lines.push("3. detection");
696
+ lines.push("4. source-validation");
697
+ lines.push("5. source-translation");
698
+ lines.push("6. canonical-validation");
699
+ lines.push("7. compatibility");
700
+ lines.push("8. target-translation");
701
+ lines.push("9. plan-validation");
702
+ lines.push("10. redaction");
703
+ lines.push("");
704
+ lines.push("## Safe Construction");
705
+ lines.push("");
706
+ lines.push(
707
+ "Use `createDiagnostic` from `./rosetta` — never embed raw content,",
708
+ );
709
+ lines.push("stack traces, or credential-like values in diagnostic messages.");
710
+ lines.push("Use `convertInternalError` for unexpected exceptions.");
711
+ lines.push("");
712
+
713
+ return lines.join("\n");
714
+ }
715
+
716
+ // ═══════════════════════════════════════════════════════════════════════════════
717
+ // Generated Document Manifest
718
+ // ═══════════════════════════════════════════════════════════════════════════════
719
+
720
+ /**
721
+ * Manifest of every deterministically generated reference document mapped to
722
+ * the pure generator function that produces its content. Tests use this to
723
+ * snapshot output, verify determinism, and compare against checked-in files
724
+ * without triggering any filesystem writes.
725
+ */
726
+ export const GENERATED_DOC_MANIFEST: ReadonlyArray<
727
+ readonly [filename: string, generate: () => string]
728
+ > = [
729
+ ["format-reference.md", generateFormatReference],
730
+ ["variant-reference.md", generateVariantReference],
731
+ ["detection-reference.md", generateDetectionReference],
732
+ ["lifecycle-reference.md", generateLifecycleReference],
733
+ ["compatibility-reference.md", generateCompatibilityReference],
734
+ ["degradation-reference.md", generateDegradationReference],
735
+ ["profile-field-reference.md", generateProfileFieldReference],
736
+ ["normalization-reference.md", generateNormalizationReference],
737
+ ["security-reference.md", generateSecurityReference],
738
+ ["cli-examples.md", generateCliExamples],
739
+ ["diagnostic-conventions.md", generateDiagnosticConventions],
740
+ ];
741
+
742
+ /**
743
+ * Hand-written guidance documents (produced by task 17.2). The generator does
744
+ * not regenerate these; it verifies they are present. Tests assert each file
745
+ * exists in the output directory.
746
+ */
747
+ export const GUIDANCE_DOC_FILES: readonly string[] = [
748
+ "architecture-guide.md",
749
+ "migration-guide.md",
750
+ "extension-guide.md",
751
+ "testing-guide.md",
752
+ "path-boundaries.md",
753
+ "redaction-guide.md",
754
+ "inert-content.md",
755
+ ];
756
+
757
+ /** Absolute path to the generated documentation output directory. */
758
+ export const DOCS_OUTPUT_DIR = OUTPUT_DIR;
759
+
760
+ // ═══════════════════════════════════════════════════════════════════════════════
761
+ // Main
762
+ // ═══════════════════════════════════════════════════════════════════════════════
763
+
764
+ function main(): void {
765
+ console.log("Rosetta Stone Documentation Generator");
766
+ console.log("======================================");
767
+ console.log("");
768
+
769
+ ensureOutputDir();
770
+
771
+ console.log("Generating reference documentation...");
772
+ console.log("");
773
+
774
+ for (const [filename, generate] of GENERATED_DOC_MANIFEST) {
775
+ writeDoc(filename, generate());
776
+ }
777
+
778
+ console.log("");
779
+ console.log("Guidance documents (hand-written, verified present):");
780
+ for (const file of GUIDANCE_DOC_FILES) {
781
+ console.log(` Present: docs/rosetta/${file}`);
782
+ }
783
+
784
+ console.log("");
785
+ console.log(
786
+ `Done. Generated ${GENERATED_DOC_MANIFEST.length} files, ${GUIDANCE_DOC_FILES.length} guidance files in docs/rosetta/`,
787
+ );
788
+ }
789
+
790
+ // Only run generation when executed directly (not when imported by tests).
791
+ if (import.meta.main !== false) {
792
+ main();
793
+ }