@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,108 @@
1
+ /**
2
+ * Rosetta Stone — Kiro Power Pretty-Printer
3
+ *
4
+ * Renders a canonical KnowledgeArtifact back into the kiro-power source format:
5
+ * - `POWER.md` with YAML frontmatter (name, description, keywords, globs, alwaysApply)
6
+ * - `steering/*.md` from workflows
7
+ *
8
+ * CONSTRAINTS:
9
+ * - NO filesystem, process, clock, random, Git, or network imports
10
+ * - Pure function only
11
+ *
12
+ * Requirements: 5.4, 12.4, 16.2
13
+ */
14
+
15
+ import type {
16
+ NormalizedRelativePath,
17
+ SourceDocument,
18
+ TranslationDiagnostic,
19
+ } from "../../../schemas";
20
+ import { renderDeterministicYaml } from "../../canonical";
21
+ import { codePointCompare } from "../../contracts";
22
+ import type {
23
+ SourcePrintOutput,
24
+ SourceTranslatorContext,
25
+ } from "../../registry";
26
+
27
+ // ═══════════════════════════════════════════════════════════════════════════════
28
+ // Pretty-Printer
29
+ // ═══════════════════════════════════════════════════════════════════════════════
30
+
31
+ /**
32
+ * Pretty-print a canonical KnowledgeArtifact into kiro-power source format.
33
+ *
34
+ * Produces:
35
+ * - `POWER.md` with frontmatter: name, description, keywords, globs (from file_patterns),
36
+ * alwaysApply (from inclusion)
37
+ * - `steering/*.md` from workflows
38
+ */
39
+ export function prettyPrintKiroPower(
40
+ artifact: Record<string, unknown>,
41
+ _context: SourceTranslatorContext,
42
+ ): SourcePrintOutput {
43
+ const diagnostics: TranslationDiagnostic[] = [];
44
+ const documents: SourceDocument[] = [];
45
+
46
+ const fm = (artifact.frontmatter ?? {}) as Record<string, unknown>;
47
+ const body = (artifact.body as string) ?? "";
48
+ const workflows =
49
+ (artifact.workflows as Array<{
50
+ name: string;
51
+ filename: string;
52
+ content: string;
53
+ }>) ?? [];
54
+
55
+ // Build POWER.md frontmatter
56
+ const powerFm: Record<string, unknown> = {};
57
+
58
+ if (fm.name) powerFm.name = fm.name;
59
+ if (fm.description) powerFm.description = fm.description;
60
+ if (Array.isArray(fm.keywords) && fm.keywords.length > 0) {
61
+ powerFm.keywords = fm.keywords;
62
+ }
63
+
64
+ // Map file_patterns → globs
65
+ if (Array.isArray(fm.file_patterns) && fm.file_patterns.length > 0) {
66
+ powerFm.globs = fm.file_patterns;
67
+ }
68
+
69
+ // Map inclusion → alwaysApply
70
+ if (fm.inclusion === "always") {
71
+ powerFm.alwaysApply = true;
72
+ } else if (fm.inclusion && fm.inclusion !== "manual") {
73
+ powerFm.inclusion = fm.inclusion;
74
+ }
75
+
76
+ // Render POWER.md
77
+ const POWER_KEY_ORDER = [
78
+ "name",
79
+ "description",
80
+ "keywords",
81
+ "globs",
82
+ "alwaysApply",
83
+ "inclusion",
84
+ ];
85
+ const frontmatterYaml = renderDeterministicYaml(powerFm, POWER_KEY_ORDER);
86
+ const powerContent = `---\n${frontmatterYaml}---\n${body}\n`;
87
+
88
+ documents.push({
89
+ path: "POWER.md" as NormalizedRelativePath,
90
+ content: powerContent,
91
+ executable: false,
92
+ });
93
+
94
+ // Render steering/*.md from workflows
95
+ const sortedWorkflows = [...workflows].sort((a, b) =>
96
+ codePointCompare(a.filename, b.filename),
97
+ );
98
+
99
+ for (const wf of sortedWorkflows) {
100
+ documents.push({
101
+ path: `steering/${wf.filename}` as NormalizedRelativePath,
102
+ content: `${wf.content}\n`,
103
+ executable: false,
104
+ });
105
+ }
106
+
107
+ return { documents, diagnostics };
108
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Rosetta Stone — Kiro Skill Pretty-Printer
3
+ *
4
+ * Renders a canonical KnowledgeArtifact back into the kiro-skill source format:
5
+ * - `SKILL.md` with YAML frontmatter (name, description, keywords)
6
+ * - `references/*.md` from workflows
7
+ *
8
+ * CONSTRAINTS:
9
+ * - NO filesystem, process, clock, random, Git, or network imports
10
+ * - Pure function only
11
+ *
12
+ * Requirements: 5.4, 12.4, 16.2
13
+ */
14
+
15
+ import type {
16
+ NormalizedRelativePath,
17
+ SourceDocument,
18
+ TranslationDiagnostic,
19
+ } from "../../../schemas";
20
+ import { renderDeterministicYaml } from "../../canonical";
21
+ import { codePointCompare } from "../../contracts";
22
+ import type {
23
+ SourcePrintOutput,
24
+ SourceTranslatorContext,
25
+ } from "../../registry";
26
+
27
+ // ═══════════════════════════════════════════════════════════════════════════════
28
+ // Pretty-Printer
29
+ // ═══════════════════════════════════════════════════════════════════════════════
30
+
31
+ /**
32
+ * Pretty-print a canonical KnowledgeArtifact into kiro-skill source format.
33
+ *
34
+ * Produces:
35
+ * - `SKILL.md` with frontmatter: name, description, keywords
36
+ * - `references/*.md` from workflows
37
+ */
38
+ export function prettyPrintKiroSkill(
39
+ artifact: Record<string, unknown>,
40
+ _context: SourceTranslatorContext,
41
+ ): SourcePrintOutput {
42
+ const diagnostics: TranslationDiagnostic[] = [];
43
+ const documents: SourceDocument[] = [];
44
+
45
+ const fm = (artifact.frontmatter ?? {}) as Record<string, unknown>;
46
+ const body = (artifact.body as string) ?? "";
47
+ const workflows =
48
+ (artifact.workflows as Array<{
49
+ name: string;
50
+ filename: string;
51
+ content: string;
52
+ }>) ?? [];
53
+
54
+ // Build SKILL.md frontmatter
55
+ const skillFm: Record<string, unknown> = {};
56
+
57
+ if (fm.name) skillFm.name = fm.name;
58
+ if (fm.description) skillFm.description = fm.description;
59
+ if (Array.isArray(fm.keywords) && fm.keywords.length > 0) {
60
+ skillFm.keywords = fm.keywords;
61
+ }
62
+
63
+ // Render SKILL.md
64
+ const SKILL_KEY_ORDER = ["name", "description", "keywords"];
65
+ const frontmatterYaml = renderDeterministicYaml(skillFm, SKILL_KEY_ORDER);
66
+ const skillContent = `---\n${frontmatterYaml}---\n${body}\n`;
67
+
68
+ documents.push({
69
+ path: "SKILL.md" as NormalizedRelativePath,
70
+ content: skillContent,
71
+ executable: false,
72
+ });
73
+
74
+ // Render references/*.md from workflows
75
+ const sortedWorkflows = [...workflows].sort((a, b) =>
76
+ codePointCompare(a.filename, b.filename),
77
+ );
78
+
79
+ for (const wf of sortedWorkflows) {
80
+ documents.push({
81
+ path: `references/${wf.filename}` as NormalizedRelativePath,
82
+ content: `${wf.content}\n`,
83
+ executable: false,
84
+ });
85
+ }
86
+
87
+ return { documents, diagnostics };
88
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Rosetta Stone — Q Developer Native Pretty-Printer
3
+ *
4
+ * Renders a canonical KnowledgeArtifact back into Q Developer native format:
5
+ * - `.qdeveloper/rules/<name>.md` with body content
6
+ *
7
+ * CONSTRAINTS:
8
+ * - NO filesystem, process, clock, random, Git, or network imports
9
+ * - Pure function only
10
+ *
11
+ * Requirements: 5.4, 12.4, 16.2
12
+ */
13
+
14
+ import type {
15
+ NormalizedRelativePath,
16
+ SourceDocument,
17
+ TranslationDiagnostic,
18
+ } from "../../../schemas";
19
+ import type {
20
+ SourcePrintOutput,
21
+ SourceTranslatorContext,
22
+ } from "../../registry";
23
+
24
+ // ═══════════════════════════════════════════════════════════════════════════════
25
+ // Pretty-Printer
26
+ // ═══════════════════════════════════════════════════════════════════════════════
27
+
28
+ /**
29
+ * Pretty-print a canonical KnowledgeArtifact into Q Developer native format.
30
+ *
31
+ * Produces:
32
+ * - `.qdeveloper/rules/<name>.md` with the artifact body
33
+ */
34
+ export function prettyPrintQDeveloperNative(
35
+ artifact: Record<string, unknown>,
36
+ _context: SourceTranslatorContext,
37
+ ): SourcePrintOutput {
38
+ const diagnostics: TranslationDiagnostic[] = [];
39
+ const documents: SourceDocument[] = [];
40
+
41
+ const body = (artifact.body as string) ?? "";
42
+ const name = (artifact.name as string) ?? "rule";
43
+
44
+ documents.push({
45
+ path: `.qdeveloper/rules/${name}.md` as NormalizedRelativePath,
46
+ content: `${body}\n`,
47
+ executable: false,
48
+ });
49
+
50
+ return { documents, diagnostics };
51
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Rosetta Stone — Superpowers Pretty-Printer
3
+ *
4
+ * Renders a canonical KnowledgeArtifact back into the superpowers source format:
5
+ * - `SKILL.md` with YAML frontmatter (name, description, requires from depends)
6
+ * - Companion `.md` files from workflows
7
+ *
8
+ * CONSTRAINTS:
9
+ * - NO filesystem, process, clock, random, Git, or network imports
10
+ * - Pure function only
11
+ *
12
+ * Requirements: 5.4, 12.4, 16.2
13
+ */
14
+
15
+ import type {
16
+ NormalizedRelativePath,
17
+ SourceDocument,
18
+ TranslationDiagnostic,
19
+ } from "../../../schemas";
20
+ import { renderDeterministicYaml } from "../../canonical";
21
+ import { codePointCompare } from "../../contracts";
22
+ import type {
23
+ SourcePrintOutput,
24
+ SourceTranslatorContext,
25
+ } from "../../registry";
26
+
27
+ // ═══════════════════════════════════════════════════════════════════════════════
28
+ // Pretty-Printer
29
+ // ═══════════════════════════════════════════════════════════════════════════════
30
+
31
+ /**
32
+ * Pretty-print a canonical KnowledgeArtifact into superpowers source format.
33
+ *
34
+ * Produces:
35
+ * - `SKILL.md` with frontmatter: name, description, requires (from depends)
36
+ * - Companion `.md` files from workflows
37
+ */
38
+ export function prettyPrintSuperpowers(
39
+ artifact: Record<string, unknown>,
40
+ _context: SourceTranslatorContext,
41
+ ): SourcePrintOutput {
42
+ const diagnostics: TranslationDiagnostic[] = [];
43
+ const documents: SourceDocument[] = [];
44
+
45
+ const fm = (artifact.frontmatter ?? {}) as Record<string, unknown>;
46
+ const body = (artifact.body as string) ?? "";
47
+ const workflows =
48
+ (artifact.workflows as Array<{
49
+ name: string;
50
+ filename: string;
51
+ content: string;
52
+ }>) ?? [];
53
+
54
+ // Build SKILL.md frontmatter
55
+ const skillFm: Record<string, unknown> = {};
56
+
57
+ if (fm.name) skillFm.name = fm.name;
58
+ if (fm.description) skillFm.description = fm.description;
59
+
60
+ // Map depends → requires
61
+ if (Array.isArray(fm.depends) && fm.depends.length > 0) {
62
+ skillFm.requires = fm.depends;
63
+ }
64
+
65
+ if (Array.isArray(fm.keywords) && fm.keywords.length > 0) {
66
+ skillFm.keywords = fm.keywords;
67
+ }
68
+
69
+ // Render SKILL.md
70
+ const SUPERPOWERS_KEY_ORDER = ["name", "description", "requires", "keywords"];
71
+ const frontmatterYaml = renderDeterministicYaml(
72
+ skillFm,
73
+ SUPERPOWERS_KEY_ORDER,
74
+ );
75
+ const skillContent = `---\n${frontmatterYaml}---\n${body}\n`;
76
+
77
+ documents.push({
78
+ path: "SKILL.md" as NormalizedRelativePath,
79
+ content: skillContent,
80
+ executable: false,
81
+ });
82
+
83
+ // Render companion .md files from workflows
84
+ const sortedWorkflows = [...workflows].sort((a, b) =>
85
+ codePointCompare(a.filename, b.filename),
86
+ );
87
+
88
+ for (const wf of sortedWorkflows) {
89
+ documents.push({
90
+ path: wf.filename as NormalizedRelativePath,
91
+ content: `${wf.content}\n`,
92
+ executable: false,
93
+ });
94
+ }
95
+
96
+ return { documents, diagnostics };
97
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Rosetta Stone — Windsurf Native Pretty-Printer
3
+ *
4
+ * Renders a canonical KnowledgeArtifact back into Windsurf native format:
5
+ * - `.windsurfrules` with body content
6
+ *
7
+ * CONSTRAINTS:
8
+ * - NO filesystem, process, clock, random, Git, or network imports
9
+ * - Pure function only
10
+ *
11
+ * Requirements: 5.4, 12.4, 16.2
12
+ */
13
+
14
+ import type {
15
+ NormalizedRelativePath,
16
+ SourceDocument,
17
+ TranslationDiagnostic,
18
+ } from "../../../schemas";
19
+ import type {
20
+ SourcePrintOutput,
21
+ SourceTranslatorContext,
22
+ } from "../../registry";
23
+
24
+ // ═══════════════════════════════════════════════════════════════════════════════
25
+ // Pretty-Printer
26
+ // ═══════════════════════════════════════════════════════════════════════════════
27
+
28
+ /**
29
+ * Pretty-print a canonical KnowledgeArtifact into Windsurf native format.
30
+ *
31
+ * Produces:
32
+ * - `.windsurfrules` with the artifact body
33
+ */
34
+ export function prettyPrintWindsurfNative(
35
+ artifact: Record<string, unknown>,
36
+ _context: SourceTranslatorContext,
37
+ ): SourcePrintOutput {
38
+ const diagnostics: TranslationDiagnostic[] = [];
39
+ const documents: SourceDocument[] = [];
40
+
41
+ const body = (artifact.body as string) ?? "";
42
+
43
+ documents.push({
44
+ path: ".windsurfrules" as NormalizedRelativePath,
45
+ content: `${body}\n`,
46
+ executable: false,
47
+ });
48
+
49
+ return { documents, diagnostics };
50
+ }