@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,278 @@
1
+ /**
2
+ * Rosetta Stone — Kiro Target Translator
3
+ *
4
+ * Wraps the existing kiro adapter logic with resolved variants, body overrides,
5
+ * template bundles, effective compatibility actions, structured diagnostics,
6
+ * and deterministic TranslationPlan output.
7
+ *
8
+ * CONSTRAINTS:
9
+ * - NO filesystem, process, clock, random, Git, or network imports
10
+ * - Pure function only
11
+ *
12
+ * Requirements: 6.1, 6.5, 6.6, 7.3, 7.5, 13.8
13
+ */
14
+
15
+ import type {
16
+ DegradationRecord,
17
+ KnowledgeArtifact,
18
+ OutputFile,
19
+ TranslationDiagnostic,
20
+ } from "../../../schemas";
21
+ import {
22
+ evaluateCompatibility,
23
+ identifyUsedCapabilities,
24
+ resolveEffectiveProfile,
25
+ } from "../../compatibility";
26
+ import { createPlan } from "../../plan";
27
+ import type {
28
+ TargetTranslationOutput,
29
+ TargetTranslatorContext,
30
+ } from "../../registry";
31
+
32
+ // ═══════════════════════════════════════════════════════════════════════════════
33
+ // Kiro Target Translator
34
+ // ═══════════════════════════════════════════════════════════════════════════════
35
+
36
+ function allocateHookPath(baseName: string, usedPaths: Set<string>): string {
37
+ const normalizedBaseName = `${baseName}.kiro.hook`;
38
+ let candidate = normalizedBaseName;
39
+ let suffix = 1;
40
+
41
+ while (usedPaths.has(candidate)) {
42
+ candidate = `${baseName}-${suffix}.kiro.hook`;
43
+ suffix += 1;
44
+ }
45
+
46
+ usedPaths.add(candidate);
47
+ return candidate;
48
+ }
49
+
50
+ /**
51
+ * Translate a canonical KnowledgeArtifact into Kiro harness-native output.
52
+ *
53
+ * Handles both `steering` and `power` variants:
54
+ * - steering: produces a steering .md file plus hooks and MCP config
55
+ * - power: produces POWER.md, steering files, workflows, hooks, and MCP config
56
+ *
57
+ * Uses the template bundle for all rendering and applies body overrides
58
+ * when available for the "kiro" harness.
59
+ */
60
+ export function translateKiroTarget(
61
+ artifact: Record<string, unknown>,
62
+ context: TargetTranslatorContext,
63
+ ): TargetTranslationOutput {
64
+ const diagnostics: TranslationDiagnostic[] = [];
65
+ const degradations: DegradationRecord[] = [];
66
+
67
+ const art = artifact as unknown as KnowledgeArtifact;
68
+ const { format, variant, canonicalSchemaVersion, templates } = context;
69
+
70
+ // Resolve body override for kiro harness
71
+ const body = art.bodyOverrides?.kiro ?? art.body;
72
+
73
+ // Evaluate compatibility
74
+ const variantContract = format.variants[variant];
75
+ const effectiveProfile = resolveEffectiveProfile(format, variantContract);
76
+ const usedCapabilities = identifyUsedCapabilities(art);
77
+ const evaluation = evaluateCompatibility(
78
+ effectiveProfile,
79
+ usedCapabilities,
80
+ art,
81
+ );
82
+ diagnostics.push(...evaluation.diagnostics);
83
+ degradations.push(...evaluation.degradations);
84
+
85
+ // Resolve harness-config for kiro
86
+ const harnessConfig = (art.frontmatter as Record<string, unknown>)[
87
+ "harness-config"
88
+ ] as Record<string, unknown> | undefined;
89
+ const kiroConfig = (harnessConfig?.kiro ?? {}) as Record<string, unknown>;
90
+
91
+ // Render output files
92
+ const outputFiles: OutputFile[] = [];
93
+ const usedHookPaths = new Set<string>();
94
+
95
+ if (variant === "power") {
96
+ // Generate POWER.md
97
+ const powerContent = templates.render("kiro/power.md.njk", {
98
+ artifact: art,
99
+ harnessConfig: kiroConfig,
100
+ body,
101
+ });
102
+ outputFiles.push({
103
+ relativePath: "POWER.md",
104
+ content: powerContent,
105
+ executable: false,
106
+ });
107
+
108
+ // Workflow files under steering/
109
+ for (const wf of art.workflows) {
110
+ outputFiles.push({
111
+ relativePath: `steering/${wf.filename}`,
112
+ content: wf.content,
113
+ executable: false,
114
+ });
115
+ }
116
+
117
+ // Main steering .md file (unless suppressed)
118
+ const emitMainSteering = kiroConfig["main-steering"] !== false;
119
+ if (emitMainSteering) {
120
+ const steeringContent = templates.render("kiro/power-steering.md.njk", {
121
+ artifact: art,
122
+ harnessConfig: kiroConfig,
123
+ body,
124
+ });
125
+ outputFiles.push({
126
+ relativePath: `steering/${art.name}.md`,
127
+ content: steeringContent,
128
+ executable: false,
129
+ });
130
+ }
131
+ } else {
132
+ // steering variant (default)
133
+ const steeringContent = templates.render("kiro/steering.md.njk", {
134
+ artifact: art,
135
+ harnessConfig: kiroConfig,
136
+ body,
137
+ inclusion: "manual",
138
+ fileMatchPattern: undefined,
139
+ auditComment: `<!-- forge:kiro-inclusion: manual -->`,
140
+ });
141
+ outputFiles.push({
142
+ relativePath: `${art.name}.md`,
143
+ content: steeringContent,
144
+ executable: false,
145
+ });
146
+ }
147
+
148
+ // Generate hook files
149
+ for (const hook of art.hooks) {
150
+ const kiroHook = buildKiroHookData(hook);
151
+ const hookContent = templates.render("kiro/hook.json.njk", {
152
+ hook: kiroHook,
153
+ });
154
+ const hookName = hook.name.toLowerCase().replace(/\s+/g, "-");
155
+ outputFiles.push({
156
+ relativePath: allocateHookPath(hookName, usedHookPaths),
157
+ content: hookContent,
158
+ executable: false,
159
+ });
160
+ }
161
+
162
+ // Handle spec-hooks from harness-config (Kiro-specific extension)
163
+ const specHooks = kiroConfig["spec-hooks"] as
164
+ | Array<Record<string, unknown>>
165
+ | undefined;
166
+ if (specHooks && Array.isArray(specHooks)) {
167
+ for (const specHook of specHooks) {
168
+ const hookContent = templates.render("kiro/hook.json.njk", {
169
+ hook: specHook,
170
+ });
171
+ const hookName = String(specHook.name || "spec-hook")
172
+ .toLowerCase()
173
+ .replace(/\s+/g, "-");
174
+ outputFiles.push({
175
+ relativePath: `${hookName}.kiro.hook`,
176
+ content: hookContent,
177
+ executable: false,
178
+ });
179
+ }
180
+ }
181
+
182
+ // Generate mcp.json
183
+ if (art.mcpServers.length > 0) {
184
+ const mcpConfig = buildMcpConfigData(art.mcpServers);
185
+ const mcpContent = templates.render("kiro/mcp.json.njk", {
186
+ mcpConfig,
187
+ });
188
+ outputFiles.push({
189
+ relativePath: "mcp.json",
190
+ content: mcpContent,
191
+ executable: false,
192
+ });
193
+ }
194
+
195
+ // Build plan deterministically
196
+ const plan = createPlan(format.id, canonicalSchemaVersion, outputFiles, {
197
+ variant,
198
+ });
199
+
200
+ return { plan, diagnostics, degradations };
201
+ }
202
+
203
+ // ═══════════════════════════════════════════════════════════════════════════════
204
+ // Internal Helpers
205
+ // ═══════════════════════════════════════════════════════════════════════════════
206
+
207
+ /** Kiro event mapping from canonical events. */
208
+ const KIRO_EVENT_MAP: Record<string, string> = {
209
+ file_edited: "fileEdited",
210
+ file_created: "fileCreated",
211
+ file_deleted: "fileDeleted",
212
+ agent_stop: "agentStop",
213
+ prompt_submit: "promptSubmit",
214
+ pre_tool_use: "preToolUse",
215
+ post_tool_use: "postToolUse",
216
+ pre_task: "preTaskExecution",
217
+ post_task: "postTaskExecution",
218
+ user_triggered: "userTriggered",
219
+ };
220
+
221
+ /**
222
+ * Build Kiro hook data structure for template rendering.
223
+ */
224
+ function buildKiroHookData(
225
+ hook: KnowledgeArtifact["hooks"][number],
226
+ ): Record<string, unknown> {
227
+ const kiroEvent = KIRO_EVENT_MAP[hook.event] ?? hook.event;
228
+ const when: Record<string, unknown> = { type: kiroEvent };
229
+ if (hook.condition?.file_patterns?.length) {
230
+ when.patterns = hook.condition.file_patterns;
231
+ }
232
+ if (hook.condition?.tool_types?.length) {
233
+ when.toolTypes = hook.condition.tool_types;
234
+ }
235
+
236
+ let then: Record<string, unknown>;
237
+ if (hook.action.type === "ask_agent") {
238
+ then = { type: "askAgent", prompt: hook.action.prompt };
239
+ } else {
240
+ then = { type: "runCommand", command: hook.action.command };
241
+ }
242
+
243
+ return {
244
+ name: hook.name,
245
+ version: "1.0.0",
246
+ description: hook.description || "",
247
+ when,
248
+ then,
249
+ };
250
+ }
251
+
252
+ /**
253
+ * Build MCP config data structure for template rendering.
254
+ */
255
+ function buildMcpConfigData(
256
+ servers: KnowledgeArtifact["mcpServers"],
257
+ ): Record<string, unknown> {
258
+ const mcpServers: Record<string, unknown> = {};
259
+ for (const server of servers) {
260
+ if ("command" in server) {
261
+ mcpServers[server.name] = {
262
+ command: server.command,
263
+ args: server.args,
264
+ env: server.env,
265
+ ...(server.timeout ? { timeout: server.timeout } : {}),
266
+ };
267
+ } else {
268
+ mcpServers[server.name] = {
269
+ url: server.url,
270
+ ...(server.env && Object.keys(server.env).length > 0
271
+ ? { env: server.env }
272
+ : {}),
273
+ ...(server.timeout ? { timeout: server.timeout } : {}),
274
+ };
275
+ }
276
+ }
277
+ return { mcpServers };
278
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Rosetta Stone — Q Developer Target Translator
3
+ *
4
+ * Translates a canonical KnowledgeArtifact into Amazon Q Developer's native
5
+ * output format (.qdeveloper/rules/<name>.md or agent files).
6
+ *
7
+ * CONSTRAINTS:
8
+ * - NO filesystem, process, clock, random, Git, or network imports
9
+ * - Pure function only
10
+ *
11
+ * Requirements: 6.1, 6.5, 6.6, 12.2, 12.5, 13.8
12
+ */
13
+
14
+ import type {
15
+ DegradationRecord,
16
+ KnowledgeArtifact,
17
+ OutputFile,
18
+ TranslationDiagnostic,
19
+ } from "../../../schemas";
20
+ import {
21
+ evaluateCompatibility,
22
+ identifyUsedCapabilities,
23
+ resolveEffectiveProfile,
24
+ } from "../../compatibility";
25
+ import { codePointCompare } from "../../contracts";
26
+ import { createPlan } from "../../plan";
27
+ import type {
28
+ TargetTranslationOutput,
29
+ TargetTranslatorContext,
30
+ } from "../../registry";
31
+
32
+ // ═══════════════════════════════════════════════════════════════════════════════
33
+ // Q Developer Target Translator
34
+ // ═══════════════════════════════════════════════════════════════════════════════
35
+
36
+ /**
37
+ * Translate a canonical artifact into Q Developer-native output files.
38
+ *
39
+ * Supports variants:
40
+ * - "rule" (default): .qdeveloper/rules/<artifact-name>.md
41
+ * - "agent": .qdeveloper/agents/<artifact-name>.md
42
+ */
43
+ export function translateQDeveloperTarget(
44
+ artifact: Record<string, unknown>,
45
+ context: TargetTranslatorContext,
46
+ ): TargetTranslationOutput {
47
+ const diagnostics: TranslationDiagnostic[] = [];
48
+ const degradations: DegradationRecord[] = [];
49
+
50
+ const art = artifact as unknown as KnowledgeArtifact;
51
+ const { format, variant, canonicalSchemaVersion, templates } = context;
52
+
53
+ // Resolve body override for qdeveloper harness
54
+ const body = art.bodyOverrides?.qdeveloper ?? art.body;
55
+
56
+ // Evaluate compatibility
57
+ const variantContract = format.variants[variant];
58
+ const effectiveProfile = resolveEffectiveProfile(format, variantContract);
59
+ const usedCapabilities = identifyUsedCapabilities(art);
60
+ const evaluation = evaluateCompatibility(
61
+ effectiveProfile,
62
+ usedCapabilities,
63
+ art,
64
+ );
65
+ diagnostics.push(...evaluation.diagnostics);
66
+ degradations.push(...evaluation.degradations);
67
+
68
+ // Render output files
69
+ const outputFiles: OutputFile[] = [];
70
+
71
+ if (variant === "agent") {
72
+ // Agent variant: .qdeveloper/agents/<name>.md
73
+ const content = templates.render("qdeveloper/agent.md.njk", {
74
+ artifact: art,
75
+ body,
76
+ });
77
+ outputFiles.push({
78
+ relativePath: `.qdeveloper/agents/${art.name}.md`,
79
+ content,
80
+ executable: false,
81
+ });
82
+ } else {
83
+ // Default "rule" variant: .qdeveloper/rules/<name>.md
84
+ const content = templates.render("qdeveloper/rule.md.njk", {
85
+ artifact: art,
86
+ body,
87
+ });
88
+ outputFiles.push({
89
+ relativePath: `.qdeveloper/rules/${art.name}.md`,
90
+ content,
91
+ executable: false,
92
+ });
93
+ }
94
+
95
+ // Sort output files deterministically by path
96
+ outputFiles.sort((a, b) => codePointCompare(a.relativePath, b.relativePath));
97
+
98
+ const plan = createPlan(format.id, canonicalSchemaVersion, outputFiles, {
99
+ variant,
100
+ });
101
+
102
+ return { plan, diagnostics, degradations };
103
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Rosetta Stone — Windsurf Target Translator
3
+ *
4
+ * Translates a canonical KnowledgeArtifact into Windsurf's native output
5
+ * format (.windsurf/rules/<name>.md).
6
+ *
7
+ * CONSTRAINTS:
8
+ * - NO filesystem, process, clock, random, Git, or network imports
9
+ * - Pure function only
10
+ *
11
+ * Requirements: 6.1, 6.5, 6.6, 12.2, 12.5, 13.8
12
+ */
13
+
14
+ import type {
15
+ DegradationRecord,
16
+ KnowledgeArtifact,
17
+ OutputFile,
18
+ TranslationDiagnostic,
19
+ } from "../../../schemas";
20
+ import {
21
+ evaluateCompatibility,
22
+ identifyUsedCapabilities,
23
+ resolveEffectiveProfile,
24
+ } from "../../compatibility";
25
+ import { codePointCompare } from "../../contracts";
26
+ import { createPlan } from "../../plan";
27
+ import type {
28
+ TargetTranslationOutput,
29
+ TargetTranslatorContext,
30
+ } from "../../registry";
31
+
32
+ // ═══════════════════════════════════════════════════════════════════════════════
33
+ // Windsurf Target Translator
34
+ // ═══════════════════════════════════════════════════════════════════════════════
35
+
36
+ /**
37
+ * Translate a canonical artifact into Windsurf-native output files.
38
+ *
39
+ * Produces .windsurf/rules/<artifact-name>.md
40
+ */
41
+ export function translateWindsurfTarget(
42
+ artifact: Record<string, unknown>,
43
+ context: TargetTranslatorContext,
44
+ ): TargetTranslationOutput {
45
+ const diagnostics: TranslationDiagnostic[] = [];
46
+ const degradations: DegradationRecord[] = [];
47
+
48
+ const art = artifact as unknown as KnowledgeArtifact;
49
+ const { format, variant, canonicalSchemaVersion, templates } = context;
50
+
51
+ // Resolve body override for windsurf harness
52
+ const body = art.bodyOverrides?.windsurf ?? art.body;
53
+
54
+ // Evaluate compatibility
55
+ const variantContract = format.variants[variant];
56
+ const effectiveProfile = resolveEffectiveProfile(format, variantContract);
57
+ const usedCapabilities = identifyUsedCapabilities(art);
58
+ const evaluation = evaluateCompatibility(
59
+ effectiveProfile,
60
+ usedCapabilities,
61
+ art,
62
+ );
63
+ diagnostics.push(...evaluation.diagnostics);
64
+ degradations.push(...evaluation.degradations);
65
+
66
+ // Render output files
67
+ const outputFiles: OutputFile[] = [];
68
+
69
+ const content = templates.render("windsurf/rule.md.njk", {
70
+ artifact: art,
71
+ body,
72
+ });
73
+ outputFiles.push({
74
+ relativePath: `.windsurf/rules/${art.name}.md`,
75
+ content,
76
+ executable: false,
77
+ });
78
+
79
+ // Sort output files deterministically by path
80
+ outputFiles.sort((a, b) => codePointCompare(a.relativePath, b.relativePath));
81
+
82
+ const plan = createPlan(format.id, canonicalSchemaVersion, outputFiles, {
83
+ variant,
84
+ });
85
+
86
+ return { plan, diagnostics, degradations };
87
+ }