@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.
- package/CHANGELOG.md +410 -0
- package/LICENSE +21 -0
- package/README.md +168 -0
- package/bridge/mcp-server.cjs +14171 -0
- package/package.json +98 -0
- package/src/adapters/capabilities.ts +178 -0
- package/src/adapters/claude-code.ts +110 -0
- package/src/adapters/cline.ts +98 -0
- package/src/adapters/codex.ts +173 -0
- package/src/adapters/copilot.ts +106 -0
- package/src/adapters/cursor.ts +97 -0
- package/src/adapters/degradation.ts +95 -0
- package/src/adapters/index.ts +324 -0
- package/src/adapters/kiro-frontmatter.ts +139 -0
- package/src/adapters/kiro-inclusion.ts +86 -0
- package/src/adapters/kiro.ts +412 -0
- package/src/adapters/qdeveloper.ts +115 -0
- package/src/adapters/types.ts +81 -0
- package/src/adapters/windsurf.ts +96 -0
- package/src/admin.ts +283 -0
- package/src/asset-conventions.ts +118 -0
- package/src/attribution-backfill.ts +319 -0
- package/src/attribution-report.ts +95 -0
- package/src/attribution.ts +239 -0
- package/src/backends/github.ts +194 -0
- package/src/backends/http.ts +122 -0
- package/src/backends/index.ts +39 -0
- package/src/backends/local.ts +47 -0
- package/src/backends/s3.ts +157 -0
- package/src/backends/types.ts +59 -0
- package/src/base-cache.ts +270 -0
- package/src/browse-ui.ts +3754 -0
- package/src/browse.ts +1038 -0
- package/src/build.ts +1108 -0
- package/src/catalog.ts +204 -0
- package/src/cli-deprecated.ts +29 -0
- package/src/cli.ts +773 -0
- package/src/collection-admin.ts +287 -0
- package/src/collection-builder.ts +464 -0
- package/src/collections.ts +116 -0
- package/src/compatibility.ts +105 -0
- package/src/config.ts +743 -0
- package/src/eval/rubrics/kiro-progressive-steering.ts +841 -0
- package/src/eval.ts +1169 -0
- package/src/file-writer.ts +61 -0
- package/src/format-registry.ts +141 -0
- package/src/guild/auto-updater.ts +163 -0
- package/src/guild/backend-resolver.ts +49 -0
- package/src/guild/cli.ts +592 -0
- package/src/guild/collection-expander.ts +47 -0
- package/src/guild/global-cache.ts +247 -0
- package/src/guild/hook-generator.ts +100 -0
- package/src/guild/manifest.ts +154 -0
- package/src/guild/path-utils.ts +12 -0
- package/src/guild/sync.ts +622 -0
- package/src/guild/version-resolver.ts +42 -0
- package/src/help/metadata.ts +445 -0
- package/src/help/renderer.ts +265 -0
- package/src/help/typo-suggester.ts +25 -0
- package/src/hooks/expression.ts +493 -0
- package/src/hooks/pipeline.ts +141 -0
- package/src/import.ts +773 -0
- package/src/importers/claude-code.ts +134 -0
- package/src/importers/cline.ts +103 -0
- package/src/importers/codex.ts +140 -0
- package/src/importers/copilot.ts +103 -0
- package/src/importers/cursor.ts +105 -0
- package/src/importers/index.ts +390 -0
- package/src/importers/kiro.ts +110 -0
- package/src/importers/qdeveloper.ts +103 -0
- package/src/importers/types.ts +54 -0
- package/src/importers/windsurf.ts +104 -0
- package/src/install.ts +1005 -0
- package/src/manifest-admin.ts +306 -0
- package/src/mcp-bridge.ts +240 -0
- package/src/mutation/delta.ts +50 -0
- package/src/mutation/history.ts +66 -0
- package/src/mutation/operators.ts +524 -0
- package/src/mutation/runner.ts +332 -0
- package/src/new.ts +106 -0
- package/src/outcomes/collision.ts +127 -0
- package/src/outcomes/normalize.ts +208 -0
- package/src/outcomes/registry.ts +173 -0
- package/src/parser.ts +446 -0
- package/src/provenance-backfill-cli.ts +319 -0
- package/src/provenance-backfill.ts +520 -0
- package/src/publish.ts +354 -0
- package/src/reconcile-orchestrator.ts +502 -0
- package/src/reconcile-report-renderer.ts +176 -0
- package/src/resolve-body.ts +15 -0
- package/src/rosetta/builtins/compatibility-profiles.ts +297 -0
- package/src/rosetta/builtins/contracts.ts +1033 -0
- package/src/rosetta/builtins/pretty-printers/claude-code-native.ts +122 -0
- package/src/rosetta/builtins/pretty-printers/cline-native.ts +50 -0
- package/src/rosetta/builtins/pretty-printers/codex-native.ts +127 -0
- package/src/rosetta/builtins/pretty-printers/copilot-native.ts +50 -0
- package/src/rosetta/builtins/pretty-printers/cursor-native.ts +50 -0
- package/src/rosetta/builtins/pretty-printers/index.ts +81 -0
- package/src/rosetta/builtins/pretty-printers/kiro-native.ts +166 -0
- package/src/rosetta/builtins/pretty-printers/kiro-power.ts +108 -0
- package/src/rosetta/builtins/pretty-printers/kiro-skill.ts +88 -0
- package/src/rosetta/builtins/pretty-printers/qdeveloper-native.ts +51 -0
- package/src/rosetta/builtins/pretty-printers/superpowers.ts +97 -0
- package/src/rosetta/builtins/pretty-printers/windsurf-native.ts +50 -0
- package/src/rosetta/builtins/sources/claude-code-native.ts +348 -0
- package/src/rosetta/builtins/sources/cline-native.ts +176 -0
- package/src/rosetta/builtins/sources/codex-native.ts +343 -0
- package/src/rosetta/builtins/sources/copilot-native.ts +178 -0
- package/src/rosetta/builtins/sources/cursor-native.ts +176 -0
- package/src/rosetta/builtins/sources/index.ts +95 -0
- package/src/rosetta/builtins/sources/kiro-native.ts +462 -0
- package/src/rosetta/builtins/sources/kiro-power.ts +285 -0
- package/src/rosetta/builtins/sources/kiro-skill.ts +230 -0
- package/src/rosetta/builtins/sources/qdeveloper-native.ts +181 -0
- package/src/rosetta/builtins/sources/superpowers.ts +240 -0
- package/src/rosetta/builtins/sources/windsurf-native.ts +176 -0
- package/src/rosetta/builtins/targets/claude-code.ts +181 -0
- package/src/rosetta/builtins/targets/cline.ts +87 -0
- package/src/rosetta/builtins/targets/codex.ts +226 -0
- package/src/rosetta/builtins/targets/copilot.ts +103 -0
- package/src/rosetta/builtins/targets/cursor.ts +87 -0
- package/src/rosetta/builtins/targets/index.ts +60 -0
- package/src/rosetta/builtins/targets/kiro.ts +278 -0
- package/src/rosetta/builtins/targets/qdeveloper.ts +103 -0
- package/src/rosetta/builtins/targets/windsurf.ts +87 -0
- package/src/rosetta/canonical.ts +729 -0
- package/src/rosetta/compatibility.ts +432 -0
- package/src/rosetta/contracts.ts +329 -0
- package/src/rosetta/detector.ts +724 -0
- package/src/rosetta/diagnostics.ts +630 -0
- package/src/rosetta/engine-bootstrap.ts +103 -0
- package/src/rosetta/engine.ts +744 -0
- package/src/rosetta/index.ts +381 -0
- package/src/rosetta/inspection.ts +530 -0
- package/src/rosetta/plan.ts +448 -0
- package/src/rosetta/provenance-digest.ts +369 -0
- package/src/rosetta/reconcile.ts +812 -0
- package/src/rosetta/redaction.ts +467 -0
- package/src/rosetta/registry.ts +712 -0
- package/src/rosetta/renderers.ts +571 -0
- package/src/rosetta/request-guard.ts +335 -0
- package/src/rosetta/resolution.ts +419 -0
- package/src/rosetta/source-accounting.ts +233 -0
- package/src/rosetta/templates.ts +129 -0
- package/src/rosetta-cli.ts +717 -0
- package/src/rosetta-docs-generator.ts +793 -0
- package/src/rosetta-profiles-cli.ts +367 -0
- package/src/schemas.ts +1712 -0
- package/src/spec-coordination.ts +1141 -0
- package/src/temper.ts +747 -0
- package/src/template-bundle-loader.ts +312 -0
- package/src/template-engine.ts +53 -0
- package/src/translation-application-policy.ts +496 -0
- package/src/translation-orchestrator.ts +1013 -0
- package/src/translation-plan-applier.ts +473 -0
- package/src/tutorial.ts +305 -0
- package/src/validate.ts +1093 -0
- package/src/versioning.ts +553 -0
- package/src/wizard.ts +660 -0
- package/src/workspace.ts +237 -0
- package/templates/eval-contexts/claude-code.md.njk +6 -0
- package/templates/eval-contexts/cline.md.njk +6 -0
- package/templates/eval-contexts/copilot.md.njk +6 -0
- package/templates/eval-contexts/cursor.md.njk +6 -0
- package/templates/eval-contexts/kiro.md.njk +10 -0
- package/templates/eval-contexts/qdeveloper.md.njk +6 -0
- package/templates/eval-contexts/windsurf.md.njk +6 -0
- package/templates/harness-adapters/_base/attribution-footer.md.njk +17 -0
- package/templates/harness-adapters/_base/base.md.njk +16 -0
- package/templates/harness-adapters/claude-code/claude.md.njk +1 -0
- package/templates/harness-adapters/claude-code/mcp.json.njk +1 -0
- package/templates/harness-adapters/claude-code/settings.json.njk +1 -0
- package/templates/harness-adapters/claude-code/skill-library-index.md.njk +13 -0
- package/templates/harness-adapters/claude-code/skill.md.njk +19 -0
- package/templates/harness-adapters/cline/hook.sh.njk +4 -0
- package/templates/harness-adapters/cline/mcp.json.njk +1 -0
- package/templates/harness-adapters/cline/rule.md.njk +1 -0
- package/templates/harness-adapters/codex/agents-md.md.njk +6 -0
- package/templates/harness-adapters/codex/agents-pointer.md.njk +16 -0
- package/templates/harness-adapters/codex/skill.md.njk +27 -0
- package/templates/harness-adapters/copilot/agents.md.njk +1 -0
- package/templates/harness-adapters/copilot/instructions.md.njk +1 -0
- package/templates/harness-adapters/copilot/scoped.md.njk +6 -0
- package/templates/harness-adapters/cursor/mcp.json.njk +1 -0
- package/templates/harness-adapters/cursor/rule.md.njk +6 -0
- package/templates/harness-adapters/kiro/hook.json.njk +1 -0
- package/templates/harness-adapters/kiro/mcp.json.njk +1 -0
- package/templates/harness-adapters/kiro/power-steering.md.njk +3 -0
- package/templates/harness-adapters/kiro/power.md.njk +12 -0
- package/templates/harness-adapters/kiro/steering.md.njk +16 -0
- package/templates/harness-adapters/qdeveloper/agent.md.njk +1 -0
- package/templates/harness-adapters/qdeveloper/mcp.json.njk +1 -0
- package/templates/harness-adapters/qdeveloper/rule.md.njk +1 -0
- package/templates/harness-adapters/windsurf/mcp.json.njk +1 -0
- package/templates/harness-adapters/windsurf/rule.md.njk +1 -0
- package/templates/harness-adapters/windsurf/workflow.md.njk +1 -0
- package/templates/knowledge/hooks.yaml.njk +4 -0
- package/templates/knowledge/knowledge.md.njk +53 -0
- package/templates/knowledge/mcp-servers.yaml.njk +2 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Importer — Compatibility Facade
|
|
3
|
+
*
|
|
4
|
+
* Preserves the public `parseClaudeCode` interface while delegating pure parsing
|
|
5
|
+
* to the Rosetta Stone claude-code-native source translator. Handles multi-file
|
|
6
|
+
* grouping (CLAUDE.md, settings.json, mcp.json) deterministically.
|
|
7
|
+
*
|
|
8
|
+
* For supplementary files (settings.json, mcp.json) that lack a primary CLAUDE.md,
|
|
9
|
+
* a synthetic primary document is injected so the translator can produce a valid
|
|
10
|
+
* candidate with extracted hooks/MCP servers.
|
|
11
|
+
*
|
|
12
|
+
* Requirements: 14.2, 14.10, 14.11
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { readFile } from "node:fs/promises";
|
|
16
|
+
import { basename } from "node:path";
|
|
17
|
+
import { translateClaudeCodeNative } from "../rosetta/builtins/sources/claude-code-native";
|
|
18
|
+
import type { SourceTranslatorContext } from "../rosetta/registry";
|
|
19
|
+
import type {
|
|
20
|
+
FormatIdentifier,
|
|
21
|
+
NormalizedRelativePath,
|
|
22
|
+
SourceDocument,
|
|
23
|
+
} from "../schemas";
|
|
24
|
+
import type { ImportedFile, ImportParser } from "./types";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Derives a kebab-case artifact name from a file path.
|
|
28
|
+
*/
|
|
29
|
+
function deriveArtifactName(filePath: string): string {
|
|
30
|
+
const base = basename(filePath);
|
|
31
|
+
const name = base.replace(/\.[^.]+$/, "");
|
|
32
|
+
return name
|
|
33
|
+
.toLowerCase()
|
|
34
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
35
|
+
.replace(/^-|-$/g, "");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Claude Code import parser.
|
|
40
|
+
* Handles CLAUDE.md, .claude/settings.json, and .claude/mcp.json.
|
|
41
|
+
* Delegates pure parsing to the Rosetta Stone claude-code-native source translator.
|
|
42
|
+
*/
|
|
43
|
+
export const parseClaudeCode: ImportParser = async (
|
|
44
|
+
filePath: string,
|
|
45
|
+
): Promise<ImportedFile> => {
|
|
46
|
+
const raw = await readFile(filePath, "utf-8");
|
|
47
|
+
const base = basename(filePath);
|
|
48
|
+
|
|
49
|
+
// Derive artifact name based on file type
|
|
50
|
+
let artifactName: string;
|
|
51
|
+
if (base.endsWith("settings.json")) {
|
|
52
|
+
artifactName = "claude-settings";
|
|
53
|
+
} else if (base.endsWith("mcp.json")) {
|
|
54
|
+
artifactName = "claude-mcp";
|
|
55
|
+
} else {
|
|
56
|
+
artifactName = deriveArtifactName(filePath);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Build SourceDocument set for Rosetta Stone.
|
|
60
|
+
// For supplementary files (settings.json, mcp.json) we inject a synthetic
|
|
61
|
+
// CLAUDE.md so the translator can produce a candidate.
|
|
62
|
+
const documents: SourceDocument[] = [];
|
|
63
|
+
|
|
64
|
+
if (base.endsWith("settings.json") || base.endsWith("mcp.json")) {
|
|
65
|
+
// Inject a minimal synthetic CLAUDE.md as the primary document
|
|
66
|
+
documents.push({
|
|
67
|
+
path: "CLAUDE.md" as NormalizedRelativePath,
|
|
68
|
+
content: "",
|
|
69
|
+
executable: false,
|
|
70
|
+
});
|
|
71
|
+
documents.push({
|
|
72
|
+
path: base as NormalizedRelativePath,
|
|
73
|
+
content: raw,
|
|
74
|
+
executable: false,
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
documents.push({
|
|
78
|
+
path: base as NormalizedRelativePath,
|
|
79
|
+
content: raw,
|
|
80
|
+
executable: false,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Build translator context with the artifact name hint
|
|
85
|
+
const context: SourceTranslatorContext = {
|
|
86
|
+
format: {
|
|
87
|
+
id: "claude-code" as FormatIdentifier,
|
|
88
|
+
} as SourceTranslatorContext["format"],
|
|
89
|
+
canonicalSchemaVersion: "1.0.0",
|
|
90
|
+
options: {},
|
|
91
|
+
callerContext: { artifactNameHint: artifactName },
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Delegate to Rosetta Stone
|
|
95
|
+
const output = translateClaudeCodeNative(documents, context);
|
|
96
|
+
|
|
97
|
+
// Map SourceTranslationOutput back to ImportedFile shape
|
|
98
|
+
if (output.candidate) {
|
|
99
|
+
const candidate = output.candidate as Record<string, unknown>;
|
|
100
|
+
const frontmatter = (candidate.frontmatter ?? {}) as Record<
|
|
101
|
+
string,
|
|
102
|
+
unknown
|
|
103
|
+
>;
|
|
104
|
+
const {
|
|
105
|
+
name: _n,
|
|
106
|
+
type: _t,
|
|
107
|
+
harnesses: _h,
|
|
108
|
+
...restFrontmatter
|
|
109
|
+
} = frontmatter;
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
sourcePath: filePath,
|
|
113
|
+
artifactName,
|
|
114
|
+
body: (candidate.body as string) ?? "",
|
|
115
|
+
frontmatter: restFrontmatter,
|
|
116
|
+
hooks: (candidate.hooks as ImportedFile["hooks"]) ?? [],
|
|
117
|
+
mcpServers: (candidate.mcpServers as ImportedFile["mcpServers"]) ?? [],
|
|
118
|
+
extraFields: (candidate.extraFields as Record<string, unknown>) ?? {},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Fallback: if translation produced no candidate, return minimal result
|
|
123
|
+
return {
|
|
124
|
+
sourcePath: filePath,
|
|
125
|
+
artifactName,
|
|
126
|
+
body: "",
|
|
127
|
+
frontmatter: {},
|
|
128
|
+
hooks: [],
|
|
129
|
+
mcpServers: [],
|
|
130
|
+
extraFields: {},
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export default parseClaudeCode;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cline Importer — Compatibility Facade
|
|
3
|
+
*
|
|
4
|
+
* Preserves the public `parseCline` interface while delegating pure parsing
|
|
5
|
+
* to the Rosetta Stone cline-native source translator.
|
|
6
|
+
*
|
|
7
|
+
* Requirements: 14.2, 14.10, 14.11
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
|
+
import { basename } from "node:path";
|
|
12
|
+
import { translateClineNative } from "../rosetta/builtins/sources/cline-native";
|
|
13
|
+
import type { SourceTranslatorContext } from "../rosetta/registry";
|
|
14
|
+
import type {
|
|
15
|
+
FormatIdentifier,
|
|
16
|
+
NormalizedRelativePath,
|
|
17
|
+
SourceDocument,
|
|
18
|
+
} from "../schemas";
|
|
19
|
+
import type { ImportedFile, ImportParser } from "./types";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Derives a kebab-case artifact name from a file path.
|
|
23
|
+
*/
|
|
24
|
+
function deriveArtifactName(filePath: string): string {
|
|
25
|
+
const base = basename(filePath);
|
|
26
|
+
const name = base.replace(/\.md$/, "");
|
|
27
|
+
return name
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
30
|
+
.replace(/^-|-$/g, "");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Cline import parser.
|
|
35
|
+
* Handles .clinerules/*.md files.
|
|
36
|
+
* Delegates pure parsing to the Rosetta Stone cline-native source translator.
|
|
37
|
+
*/
|
|
38
|
+
export const parseCline: ImportParser = async (
|
|
39
|
+
filePath: string,
|
|
40
|
+
): Promise<ImportedFile> => {
|
|
41
|
+
const raw = await readFile(filePath, "utf-8");
|
|
42
|
+
const artifactName = deriveArtifactName(filePath);
|
|
43
|
+
|
|
44
|
+
// Build SourceDocument for Rosetta Stone
|
|
45
|
+
const documents: SourceDocument[] = [
|
|
46
|
+
{
|
|
47
|
+
path: basename(filePath) as NormalizedRelativePath,
|
|
48
|
+
content: raw,
|
|
49
|
+
executable: false,
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
// Build translator context
|
|
54
|
+
const context: SourceTranslatorContext = {
|
|
55
|
+
format: {
|
|
56
|
+
id: "cline" as FormatIdentifier,
|
|
57
|
+
} as SourceTranslatorContext["format"],
|
|
58
|
+
canonicalSchemaVersion: "1.0.0",
|
|
59
|
+
options: {},
|
|
60
|
+
callerContext: { artifactNameHint: artifactName },
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Delegate to Rosetta Stone
|
|
64
|
+
const output = translateClineNative(documents, context);
|
|
65
|
+
|
|
66
|
+
// Map SourceTranslationOutput back to ImportedFile shape
|
|
67
|
+
if (output.candidate) {
|
|
68
|
+
const candidate = output.candidate as Record<string, unknown>;
|
|
69
|
+
const frontmatter = (candidate.frontmatter ?? {}) as Record<
|
|
70
|
+
string,
|
|
71
|
+
unknown
|
|
72
|
+
>;
|
|
73
|
+
const {
|
|
74
|
+
name: _n,
|
|
75
|
+
type: _t,
|
|
76
|
+
harnesses: _h,
|
|
77
|
+
...restFrontmatter
|
|
78
|
+
} = frontmatter;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
sourcePath: filePath,
|
|
82
|
+
artifactName,
|
|
83
|
+
body: (candidate.body as string) ?? "",
|
|
84
|
+
frontmatter: restFrontmatter,
|
|
85
|
+
hooks: (candidate.hooks as ImportedFile["hooks"]) ?? [],
|
|
86
|
+
mcpServers: (candidate.mcpServers as ImportedFile["mcpServers"]) ?? [],
|
|
87
|
+
extraFields: (candidate.extraFields as Record<string, unknown>) ?? {},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Fallback: if translation produced no candidate, return minimal result
|
|
92
|
+
return {
|
|
93
|
+
sourcePath: filePath,
|
|
94
|
+
artifactName,
|
|
95
|
+
body: raw.trim(),
|
|
96
|
+
frontmatter: {},
|
|
97
|
+
hooks: [],
|
|
98
|
+
mcpServers: [],
|
|
99
|
+
extraFields: {},
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default parseCline;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Importer — Compatibility Facade
|
|
3
|
+
*
|
|
4
|
+
* Preserves the public `parseCodex` interface while delegating pure parsing
|
|
5
|
+
* to the Rosetta Stone codex-native source translator. Handles multi-file
|
|
6
|
+
* grouping (AGENTS.md, SKILL.md files, config.toml) deterministically.
|
|
7
|
+
*
|
|
8
|
+
* For config.toml files (which are supplementary and lack a primary markdown
|
|
9
|
+
* document), a synthetic AGENTS.md is injected so the translator can produce
|
|
10
|
+
* a valid candidate with MCP servers extracted.
|
|
11
|
+
*
|
|
12
|
+
* Requirements: 14.2, 14.10, 14.11
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { readFile } from "node:fs/promises";
|
|
16
|
+
import { basename } from "node:path";
|
|
17
|
+
import { translateCodexNative } from "../rosetta/builtins/sources/codex-native";
|
|
18
|
+
import type { SourceTranslatorContext } from "../rosetta/registry";
|
|
19
|
+
import type {
|
|
20
|
+
FormatIdentifier,
|
|
21
|
+
NormalizedRelativePath,
|
|
22
|
+
SourceDocument,
|
|
23
|
+
} from "../schemas";
|
|
24
|
+
import type { ImportedFile, ImportParser } from "./types";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Derives a kebab-case artifact name from a file path.
|
|
28
|
+
* For SKILL.md files, prefers the parent directory name.
|
|
29
|
+
*/
|
|
30
|
+
function deriveArtifactName(filePath: string): string {
|
|
31
|
+
const parts = filePath.split("/");
|
|
32
|
+
const base = basename(filePath);
|
|
33
|
+
let name = base.replace(/\.[^.]+$/, "");
|
|
34
|
+
// `.codex/skills/<name>/SKILL.md` → use the skill directory name
|
|
35
|
+
if (name.toLowerCase() === "skill" && parts.length >= 2) {
|
|
36
|
+
name = parts[parts.length - 2];
|
|
37
|
+
}
|
|
38
|
+
// `AGENTS.md` → use a stable, descriptive name
|
|
39
|
+
if (name.toLowerCase() === "agents") {
|
|
40
|
+
name = "codex-agents";
|
|
41
|
+
}
|
|
42
|
+
// `config.toml` → use "codex-mcp" as the artifact name
|
|
43
|
+
if (base === "config.toml") {
|
|
44
|
+
return "codex-mcp";
|
|
45
|
+
}
|
|
46
|
+
return name
|
|
47
|
+
.toLowerCase()
|
|
48
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
49
|
+
.replace(/^-|-$/g, "");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Codex import parser.
|
|
54
|
+
* Handles AGENTS.md, SKILL.md files under .codex/skills and .agents/skills,
|
|
55
|
+
* and `.codex/config.toml`.
|
|
56
|
+
* Delegates pure parsing to the Rosetta Stone codex-native source translator.
|
|
57
|
+
*/
|
|
58
|
+
export const parseCodex: ImportParser = async (
|
|
59
|
+
filePath: string,
|
|
60
|
+
): Promise<ImportedFile> => {
|
|
61
|
+
const raw = await readFile(filePath, "utf-8");
|
|
62
|
+
const artifactName = deriveArtifactName(filePath);
|
|
63
|
+
const base = basename(filePath);
|
|
64
|
+
|
|
65
|
+
// Build SourceDocument set for Rosetta Stone.
|
|
66
|
+
// For config.toml (supplementary file), we inject a synthetic primary
|
|
67
|
+
// document so the translator can produce a candidate with MCP servers.
|
|
68
|
+
const documents: SourceDocument[] = [];
|
|
69
|
+
|
|
70
|
+
if (base === "config.toml") {
|
|
71
|
+
// Inject a minimal synthetic AGENTS.md as the primary document
|
|
72
|
+
documents.push({
|
|
73
|
+
path: "AGENTS.md" as NormalizedRelativePath,
|
|
74
|
+
content: "",
|
|
75
|
+
executable: false,
|
|
76
|
+
});
|
|
77
|
+
documents.push({
|
|
78
|
+
path: base as NormalizedRelativePath,
|
|
79
|
+
content: raw,
|
|
80
|
+
executable: false,
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
documents.push({
|
|
84
|
+
path: base as NormalizedRelativePath,
|
|
85
|
+
content: raw,
|
|
86
|
+
executable: false,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Build translator context
|
|
91
|
+
const context: SourceTranslatorContext = {
|
|
92
|
+
format: {
|
|
93
|
+
id: "codex" as FormatIdentifier,
|
|
94
|
+
} as SourceTranslatorContext["format"],
|
|
95
|
+
canonicalSchemaVersion: "1.0.0",
|
|
96
|
+
options: {},
|
|
97
|
+
callerContext: { artifactNameHint: artifactName },
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// Delegate to Rosetta Stone
|
|
101
|
+
const output = translateCodexNative(documents, context);
|
|
102
|
+
|
|
103
|
+
// Map SourceTranslationOutput back to ImportedFile shape
|
|
104
|
+
if (output.candidate) {
|
|
105
|
+
const candidate = output.candidate as Record<string, unknown>;
|
|
106
|
+
const frontmatter = (candidate.frontmatter ?? {}) as Record<
|
|
107
|
+
string,
|
|
108
|
+
unknown
|
|
109
|
+
>;
|
|
110
|
+
const {
|
|
111
|
+
name: _n,
|
|
112
|
+
type: _t,
|
|
113
|
+
harnesses: _h,
|
|
114
|
+
...restFrontmatter
|
|
115
|
+
} = frontmatter;
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
sourcePath: filePath,
|
|
119
|
+
artifactName,
|
|
120
|
+
body: (candidate.body as string) ?? "",
|
|
121
|
+
frontmatter: restFrontmatter,
|
|
122
|
+
hooks: (candidate.hooks as ImportedFile["hooks"]) ?? [],
|
|
123
|
+
mcpServers: (candidate.mcpServers as ImportedFile["mcpServers"]) ?? [],
|
|
124
|
+
extraFields: (candidate.extraFields as Record<string, unknown>) ?? {},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Fallback: if translation produced no candidate, return minimal result
|
|
129
|
+
return {
|
|
130
|
+
sourcePath: filePath,
|
|
131
|
+
artifactName,
|
|
132
|
+
body: "",
|
|
133
|
+
frontmatter: {},
|
|
134
|
+
hooks: [],
|
|
135
|
+
mcpServers: [],
|
|
136
|
+
extraFields: {},
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export default parseCodex;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copilot Importer — Compatibility Facade
|
|
3
|
+
*
|
|
4
|
+
* Preserves the public `parseCopilot` interface while delegating pure parsing
|
|
5
|
+
* to the Rosetta Stone copilot-native source translator.
|
|
6
|
+
*
|
|
7
|
+
* Requirements: 14.2, 14.10, 14.11
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
|
+
import { basename } from "node:path";
|
|
12
|
+
import { translateCopilotNative } from "../rosetta/builtins/sources/copilot-native";
|
|
13
|
+
import type { SourceTranslatorContext } from "../rosetta/registry";
|
|
14
|
+
import type {
|
|
15
|
+
FormatIdentifier,
|
|
16
|
+
NormalizedRelativePath,
|
|
17
|
+
SourceDocument,
|
|
18
|
+
} from "../schemas";
|
|
19
|
+
import type { ImportedFile, ImportParser } from "./types";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Derives a kebab-case artifact name from a file path.
|
|
23
|
+
*/
|
|
24
|
+
function deriveArtifactName(filePath: string): string {
|
|
25
|
+
const base = basename(filePath);
|
|
26
|
+
const name = base.replace(/\.instructions\.md$/, "").replace(/\.md$/, "");
|
|
27
|
+
return name
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
30
|
+
.replace(/^-|-$/g, "");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Copilot import parser.
|
|
35
|
+
* Handles .github/copilot-instructions.md and .github/instructions/*.instructions.md.
|
|
36
|
+
* Delegates pure parsing to the Rosetta Stone copilot-native source translator.
|
|
37
|
+
*/
|
|
38
|
+
export const parseCopilot: ImportParser = async (
|
|
39
|
+
filePath: string,
|
|
40
|
+
): Promise<ImportedFile> => {
|
|
41
|
+
const raw = await readFile(filePath, "utf-8");
|
|
42
|
+
const artifactName = deriveArtifactName(filePath);
|
|
43
|
+
|
|
44
|
+
// Build SourceDocument for Rosetta Stone
|
|
45
|
+
const documents: SourceDocument[] = [
|
|
46
|
+
{
|
|
47
|
+
path: basename(filePath) as NormalizedRelativePath,
|
|
48
|
+
content: raw,
|
|
49
|
+
executable: false,
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
// Build translator context
|
|
54
|
+
const context: SourceTranslatorContext = {
|
|
55
|
+
format: {
|
|
56
|
+
id: "copilot" as FormatIdentifier,
|
|
57
|
+
} as SourceTranslatorContext["format"],
|
|
58
|
+
canonicalSchemaVersion: "1.0.0",
|
|
59
|
+
options: {},
|
|
60
|
+
callerContext: { artifactNameHint: artifactName },
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Delegate to Rosetta Stone
|
|
64
|
+
const output = translateCopilotNative(documents, context);
|
|
65
|
+
|
|
66
|
+
// Map SourceTranslationOutput back to ImportedFile shape
|
|
67
|
+
if (output.candidate) {
|
|
68
|
+
const candidate = output.candidate as Record<string, unknown>;
|
|
69
|
+
const frontmatter = (candidate.frontmatter ?? {}) as Record<
|
|
70
|
+
string,
|
|
71
|
+
unknown
|
|
72
|
+
>;
|
|
73
|
+
const {
|
|
74
|
+
name: _n,
|
|
75
|
+
type: _t,
|
|
76
|
+
harnesses: _h,
|
|
77
|
+
...restFrontmatter
|
|
78
|
+
} = frontmatter;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
sourcePath: filePath,
|
|
82
|
+
artifactName,
|
|
83
|
+
body: (candidate.body as string) ?? "",
|
|
84
|
+
frontmatter: restFrontmatter,
|
|
85
|
+
hooks: (candidate.hooks as ImportedFile["hooks"]) ?? [],
|
|
86
|
+
mcpServers: (candidate.mcpServers as ImportedFile["mcpServers"]) ?? [],
|
|
87
|
+
extraFields: (candidate.extraFields as Record<string, unknown>) ?? {},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Fallback: if translation produced no candidate, return minimal result
|
|
92
|
+
return {
|
|
93
|
+
sourcePath: filePath,
|
|
94
|
+
artifactName,
|
|
95
|
+
body: raw.trim(),
|
|
96
|
+
frontmatter: {},
|
|
97
|
+
hooks: [],
|
|
98
|
+
mcpServers: [],
|
|
99
|
+
extraFields: {},
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export default parseCopilot;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor Importer — Compatibility Facade
|
|
3
|
+
*
|
|
4
|
+
* Preserves the public `parseCursor` interface while delegating pure parsing
|
|
5
|
+
* to the Rosetta Stone cursor-native source translator.
|
|
6
|
+
*
|
|
7
|
+
* Requirements: 14.2, 14.10, 14.11
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
|
+
import { basename } from "node:path";
|
|
12
|
+
import { translateCursorNative } from "../rosetta/builtins/sources/cursor-native";
|
|
13
|
+
import type { SourceTranslatorContext } from "../rosetta/registry";
|
|
14
|
+
import type {
|
|
15
|
+
FormatIdentifier,
|
|
16
|
+
NormalizedRelativePath,
|
|
17
|
+
SourceDocument,
|
|
18
|
+
} from "../schemas";
|
|
19
|
+
import type { ImportedFile, ImportParser } from "./types";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Derives a kebab-case artifact name from a file path.
|
|
23
|
+
*/
|
|
24
|
+
function deriveArtifactName(filePath: string): string {
|
|
25
|
+
const base = basename(filePath);
|
|
26
|
+
if (base === ".cursorrules") return "cursorrules";
|
|
27
|
+
const name = base.replace(/\.md$/, "");
|
|
28
|
+
return name
|
|
29
|
+
.toLowerCase()
|
|
30
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
31
|
+
.replace(/^-|-$/g, "");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Cursor import parser.
|
|
36
|
+
* Handles .cursor/rules/*.md and .cursorrules.
|
|
37
|
+
* Delegates pure parsing to the Rosetta Stone cursor-native source translator.
|
|
38
|
+
*/
|
|
39
|
+
export const parseCursor: ImportParser = async (
|
|
40
|
+
filePath: string,
|
|
41
|
+
): Promise<ImportedFile> => {
|
|
42
|
+
const raw = await readFile(filePath, "utf-8");
|
|
43
|
+
const artifactName = deriveArtifactName(filePath);
|
|
44
|
+
|
|
45
|
+
// Build SourceDocument for Rosetta Stone
|
|
46
|
+
const documents: SourceDocument[] = [
|
|
47
|
+
{
|
|
48
|
+
path: basename(filePath) as NormalizedRelativePath,
|
|
49
|
+
content: raw,
|
|
50
|
+
executable: false,
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
// Build translator context
|
|
55
|
+
const context: SourceTranslatorContext = {
|
|
56
|
+
format: {
|
|
57
|
+
id: "cursor" as FormatIdentifier,
|
|
58
|
+
} as SourceTranslatorContext["format"],
|
|
59
|
+
canonicalSchemaVersion: "1.0.0",
|
|
60
|
+
options: {},
|
|
61
|
+
callerContext: { artifactNameHint: artifactName },
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Delegate to Rosetta Stone
|
|
65
|
+
const output = translateCursorNative(documents, context);
|
|
66
|
+
|
|
67
|
+
// Map SourceTranslationOutput back to ImportedFile shape
|
|
68
|
+
if (output.candidate) {
|
|
69
|
+
const candidate = output.candidate as Record<string, unknown>;
|
|
70
|
+
const frontmatter = (candidate.frontmatter ?? {}) as Record<
|
|
71
|
+
string,
|
|
72
|
+
unknown
|
|
73
|
+
>;
|
|
74
|
+
// Remove fields that are managed by the import orchestrator
|
|
75
|
+
const {
|
|
76
|
+
name: _n,
|
|
77
|
+
type: _t,
|
|
78
|
+
harnesses: _h,
|
|
79
|
+
...restFrontmatter
|
|
80
|
+
} = frontmatter;
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
sourcePath: filePath,
|
|
84
|
+
artifactName,
|
|
85
|
+
body: (candidate.body as string) ?? "",
|
|
86
|
+
frontmatter: restFrontmatter,
|
|
87
|
+
hooks: (candidate.hooks as ImportedFile["hooks"]) ?? [],
|
|
88
|
+
mcpServers: (candidate.mcpServers as ImportedFile["mcpServers"]) ?? [],
|
|
89
|
+
extraFields: (candidate.extraFields as Record<string, unknown>) ?? {},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Fallback: if translation produced no candidate, return minimal result
|
|
94
|
+
return {
|
|
95
|
+
sourcePath: filePath,
|
|
96
|
+
artifactName,
|
|
97
|
+
body: raw.trim(),
|
|
98
|
+
frontmatter: {},
|
|
99
|
+
hooks: [],
|
|
100
|
+
mcpServers: [],
|
|
101
|
+
extraFields: {},
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export default parseCursor;
|