@shahmarasy/prodo 0.1.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 (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/bin/prodo.cjs +6 -0
  4. package/dist/agent-command-installer.d.ts +4 -0
  5. package/dist/agent-command-installer.js +158 -0
  6. package/dist/agents.d.ts +15 -0
  7. package/dist/agents.js +47 -0
  8. package/dist/artifact-registry.d.ts +11 -0
  9. package/dist/artifact-registry.js +49 -0
  10. package/dist/artifacts.d.ts +9 -0
  11. package/dist/artifacts.js +514 -0
  12. package/dist/cli.d.ts +9 -0
  13. package/dist/cli.js +305 -0
  14. package/dist/consistency.d.ts +8 -0
  15. package/dist/consistency.js +268 -0
  16. package/dist/constants.d.ts +7 -0
  17. package/dist/constants.js +64 -0
  18. package/dist/doctor.d.ts +1 -0
  19. package/dist/doctor.js +123 -0
  20. package/dist/errors.d.ts +3 -0
  21. package/dist/errors.js +10 -0
  22. package/dist/hook-executor.d.ts +1 -0
  23. package/dist/hook-executor.js +175 -0
  24. package/dist/init-tui.d.ts +21 -0
  25. package/dist/init-tui.js +161 -0
  26. package/dist/init.d.ts +10 -0
  27. package/dist/init.js +307 -0
  28. package/dist/markdown.d.ts +11 -0
  29. package/dist/markdown.js +66 -0
  30. package/dist/normalize.d.ts +7 -0
  31. package/dist/normalize.js +73 -0
  32. package/dist/normalized-brief.d.ts +39 -0
  33. package/dist/normalized-brief.js +170 -0
  34. package/dist/output-index.d.ts +13 -0
  35. package/dist/output-index.js +55 -0
  36. package/dist/paths.d.ts +16 -0
  37. package/dist/paths.js +76 -0
  38. package/dist/preset-loader.d.ts +4 -0
  39. package/dist/preset-loader.js +210 -0
  40. package/dist/project-config.d.ts +14 -0
  41. package/dist/project-config.js +69 -0
  42. package/dist/providers/index.d.ts +2 -0
  43. package/dist/providers/index.js +12 -0
  44. package/dist/providers/mock-provider.d.ts +7 -0
  45. package/dist/providers/mock-provider.js +168 -0
  46. package/dist/providers/openai-provider.d.ts +11 -0
  47. package/dist/providers/openai-provider.js +69 -0
  48. package/dist/registry.d.ts +13 -0
  49. package/dist/registry.js +115 -0
  50. package/dist/settings.d.ts +6 -0
  51. package/dist/settings.js +34 -0
  52. package/dist/template-resolver.d.ts +11 -0
  53. package/dist/template-resolver.js +28 -0
  54. package/dist/templates.d.ts +33 -0
  55. package/dist/templates.js +428 -0
  56. package/dist/types.d.ts +35 -0
  57. package/dist/types.js +5 -0
  58. package/dist/utils.d.ts +6 -0
  59. package/dist/utils.js +53 -0
  60. package/dist/validate.d.ts +9 -0
  61. package/dist/validate.js +226 -0
  62. package/dist/validator.d.ts +5 -0
  63. package/dist/validator.js +80 -0
  64. package/dist/version.d.ts +1 -0
  65. package/dist/version.js +30 -0
  66. package/dist/workflow-commands.d.ts +7 -0
  67. package/dist/workflow-commands.js +28 -0
  68. package/package.json +45 -0
  69. package/presets/fintech/preset.json +1 -0
  70. package/presets/fintech/prompts/prd.md +3 -0
  71. package/presets/marketplace/preset.json +1 -0
  72. package/presets/marketplace/prompts/prd.md +3 -0
  73. package/presets/saas/preset.json +1 -0
  74. package/presets/saas/prompts/prd.md +3 -0
  75. package/src/agent-command-installer.ts +174 -0
  76. package/src/agents.ts +56 -0
  77. package/src/artifact-registry.ts +69 -0
  78. package/src/artifacts.ts +606 -0
  79. package/src/cli.ts +322 -0
  80. package/src/consistency.ts +303 -0
  81. package/src/constants.ts +72 -0
  82. package/src/doctor.ts +137 -0
  83. package/src/errors.ts +7 -0
  84. package/src/hook-executor.ts +196 -0
  85. package/src/init-tui.ts +193 -0
  86. package/src/init.ts +375 -0
  87. package/src/markdown.ts +73 -0
  88. package/src/normalize.ts +89 -0
  89. package/src/normalized-brief.ts +206 -0
  90. package/src/output-index.ts +59 -0
  91. package/src/paths.ts +72 -0
  92. package/src/preset-loader.ts +237 -0
  93. package/src/project-config.ts +78 -0
  94. package/src/providers/index.ts +12 -0
  95. package/src/providers/mock-provider.ts +188 -0
  96. package/src/providers/openai-provider.ts +87 -0
  97. package/src/registry.ts +119 -0
  98. package/src/settings.ts +34 -0
  99. package/src/template-resolver.ts +33 -0
  100. package/src/templates.ts +440 -0
  101. package/src/types.ts +46 -0
  102. package/src/utils.ts +50 -0
  103. package/src/validate.ts +246 -0
  104. package/src/validator.ts +96 -0
  105. package/src/version.ts +24 -0
  106. package/src/workflow-commands.ts +31 -0
  107. package/templates/artifacts/prd.md +219 -0
  108. package/templates/artifacts/stories.md +49 -0
  109. package/templates/artifacts/techspec.md +42 -0
  110. package/templates/artifacts/wireframe.html +260 -0
  111. package/templates/artifacts/wireframe.md +22 -0
  112. package/templates/artifacts/workflow.md +22 -0
  113. package/templates/artifacts/workflow.mmd +6 -0
  114. package/templates/commands/prodo-normalize.md +24 -0
  115. package/templates/commands/prodo-prd.md +24 -0
  116. package/templates/commands/prodo-stories.md +24 -0
  117. package/templates/commands/prodo-techspec.md +24 -0
  118. package/templates/commands/prodo-validate.md +24 -0
  119. package/templates/commands/prodo-wireframe.md +24 -0
  120. package/templates/commands/prodo-workflow.md +24 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Bahman Shahmarasy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ <div align="center">
2
+ <h1>Prodo</h1>
3
+ <h3><em>Product Artifact Toolkit</em></h3>
4
+ </div>
5
+
6
+ <p align="center">
7
+ <strong>Build consistent product documentation from a stable brief with a CLI-first workflow.</strong>
8
+ </p>
9
+
10
+ ---
11
+
12
+ ## Table of Contents
13
+
14
+ - [What is Prodo?](#what-is-prodo)
15
+ - [Install](#install)
16
+ - [Quick Start](#quick-start)
17
+ - [Core Workflow](#core-workflow)
18
+ - [Supported Agents](#supported-agents)
19
+ - [CLI Reference](#cli-reference)
20
+ - [Output Structure](#output-structure)
21
+ - [Validation Model](#validation-model)
22
+ - [Development](#development)
23
+ - [License](#license)
24
+
25
+ ## What is Prodo?
26
+
27
+ Prodo is a CLI-first toolkit for product-document pipelines.
28
+
29
+ It helps teams move from a raw brief to structured artifacts such as:
30
+
31
+ - PRD
32
+ - Workflow (Markdown explanation + Mermaid)
33
+ - Wireframe (Markdown explanation + HTML)
34
+ - Stories
35
+ - Tech Spec
36
+
37
+ Prodo is designed to keep input stable, outputs deterministic, and cross-artifact consistency measurable.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ npm i -g @shahmarasy/prodo
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ```bash
48
+ # 1) Initialize in your project
49
+ prodo init . --ai codex --lang tr
50
+
51
+ # 2) Edit brief
52
+ # brief.md
53
+
54
+ # 3) Check environment (optional)
55
+ prodo doctor
56
+ ```
57
+
58
+ ## Core Workflow
59
+
60
+ After initialization, Prodo installs agent-native command files.
61
+
62
+ Recommended flow inside your AI agent:
63
+
64
+ 1. Normalize the brief
65
+ 2. Produce artifacts in sequence
66
+ 3. Validate consistency
67
+
68
+ Prodo keeps:
69
+
70
+ - `brief.md` as input
71
+ - `.prodo/` as internal runtime state
72
+ - `product-docs/` as user-facing outputs
73
+
74
+ ## Supported Agents
75
+
76
+ `prodo init --ai <name>` supports:
77
+
78
+ - `codex`
79
+ - `gemini-cli`
80
+ - `claude-cli`
81
+
82
+ Agent command files are installed to native locations:
83
+
84
+ - Codex: `.agents/skills/`
85
+ - Gemini CLI: `.gemini/commands/`
86
+ - Claude CLI: `.claude/commands/`
87
+
88
+ ## Agent Commands
89
+
90
+ Prodo agent command set:
91
+
92
+ - `/prodo-normalize`
93
+ - `/prodo-prd`
94
+ - `/prodo-workflow`
95
+ - `/prodo-wireframe`
96
+ - `/prodo-stories`
97
+ - `/prodo-techspec`
98
+ - `/prodo-validate`
99
+
100
+ Codex skills mode equivalents:
101
+
102
+ - `$prodo-normalize`
103
+ - `$prodo-prd`
104
+ - `$prodo-workflow`
105
+ - `$prodo-wireframe`
106
+ - `$prodo-stories`
107
+ - `$prodo-techspec`
108
+ - `$prodo-validate`
109
+
110
+ ## CLI Reference
111
+
112
+ Primary commands:
113
+
114
+ - `prodo init [target] [--ai <name>] [--lang <code>] [--preset <name>]`
115
+ - `prodo doctor` (alias: `prodo check`)
116
+
117
+ Version:
118
+
119
+ - `prodo --version`
120
+ - `prodo -v`
121
+
122
+ ## Output Structure
123
+
124
+ Project-level:
125
+
126
+ - `brief.md` (input, read-only during execution)
127
+ - `product-docs/` (all generated product documents)
128
+ - `.prodo/` (internal runtime state: prompts, schemas, templates, index, context)
129
+
130
+ Paired artifact behavior:
131
+
132
+ - Workflow: `*.md` + `*.mmd`
133
+ - Wireframe: `*.md` + `*.html`
134
+
135
+ ## Validation Model
136
+
137
+ Validation reports include gate-based checks:
138
+
139
+ - Schema pass
140
+ - Tag coverage pass
141
+ - Contract relevance pass
142
+ - Semantic consistency pass
143
+
144
+ All applicable gates must pass for final success.
145
+
146
+ ## Development
147
+
148
+ ```bash
149
+ npm install
150
+ npm run build
151
+ npm test
152
+ npm run verify:release
153
+ ```
154
+
155
+ ## License
156
+
157
+ MIT
package/bin/prodo.cjs ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ require("../dist/cli").runCli().then((code) => {
4
+ process.exitCode = code;
5
+ });
6
+
@@ -0,0 +1,4 @@
1
+ export declare const AI_ALIASES: Record<string, "codex" | "gemini-cli" | "claude-cli">;
2
+ export type SupportedAi = "codex" | "gemini-cli" | "claude-cli";
3
+ export declare function resolveAi(ai?: string): SupportedAi | undefined;
4
+ export declare function installAgentCommands(projectRoot: string, ai: SupportedAi): Promise<string[]>;
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AI_ALIASES = void 0;
7
+ exports.resolveAi = resolveAi;
8
+ exports.installAgentCommands = installAgentCommands;
9
+ const promises_1 = __importDefault(require("node:fs/promises"));
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const js_yaml_1 = __importDefault(require("js-yaml"));
12
+ const errors_1 = require("./errors");
13
+ const utils_1 = require("./utils");
14
+ exports.AI_ALIASES = {
15
+ codex: "codex",
16
+ gemini: "gemini-cli",
17
+ "gemmini-cli": "gemini-cli",
18
+ "gemmini": "gemini-cli",
19
+ "gemini-cli": "gemini-cli",
20
+ claude: "claude-cli",
21
+ "claude-cli": "claude-cli"
22
+ };
23
+ const AGENT_CONFIG = {
24
+ "claude-cli": {
25
+ baseDir: ".claude/commands",
26
+ format: "markdown",
27
+ extension: ".md",
28
+ argsPlaceholder: "$ARGUMENTS"
29
+ },
30
+ "gemini-cli": {
31
+ baseDir: ".gemini/commands",
32
+ format: "toml",
33
+ extension: ".toml",
34
+ argsPlaceholder: "{{args}}"
35
+ },
36
+ codex: {
37
+ baseDir: ".agents/skills",
38
+ format: "skill",
39
+ extension: "/SKILL.md",
40
+ argsPlaceholder: "$ARGUMENTS"
41
+ }
42
+ };
43
+ function parseFrontmatter(content) {
44
+ if (!content.startsWith("---"))
45
+ return { frontmatter: {}, body: content };
46
+ const end = content.indexOf("\n---", 4);
47
+ if (end === -1)
48
+ return { frontmatter: {}, body: content };
49
+ const fmRaw = content.slice(3, end).trim();
50
+ const body = content.slice(end + 4).trimStart();
51
+ const frontmatter = js_yaml_1.default.load(fmRaw) ?? {};
52
+ return { frontmatter, body };
53
+ }
54
+ function renderFrontmatter(frontmatter) {
55
+ if (Object.keys(frontmatter).length === 0)
56
+ return "";
57
+ return `---\n${js_yaml_1.default.dump(frontmatter)}---\n`;
58
+ }
59
+ function resolveScriptBlock(frontmatter, argsPlaceholder) {
60
+ const run = frontmatter.run;
61
+ const runAction = typeof run?.action === "string" ? run.action.trim() : "";
62
+ const runMode = typeof run?.mode === "string" ? run.mode.trim() : "";
63
+ if (runAction) {
64
+ const modeSuffix = runMode ? ` (${runMode})` : "";
65
+ return `- Internal action: ${runAction}${modeSuffix}`;
66
+ }
67
+ const runCommand = typeof run?.command === "string" ? run.command.replace("{ARGS}", argsPlaceholder) : "";
68
+ if (runCommand) {
69
+ return `- Command: ${runCommand}`;
70
+ }
71
+ const scripts = frontmatter.scripts;
72
+ const sh = typeof scripts?.sh === "string" ? scripts.sh.replace("{ARGS}", argsPlaceholder) : "";
73
+ const ps = typeof scripts?.ps === "string" ? scripts.ps.replace("{ARGS}", argsPlaceholder) : "";
74
+ return [`- Bash: ${sh}`, `- PowerShell: ${ps}`].filter((line) => line.length > 8).join("\n");
75
+ }
76
+ function toTomlPrompt(body, frontmatter, argsPlaceholder) {
77
+ const description = String(frontmatter.description ?? "Prodo command");
78
+ const scriptsBlock = resolveScriptBlock(frontmatter, argsPlaceholder);
79
+ const promptBody = body.replaceAll("$ARGUMENTS", argsPlaceholder);
80
+ return `description = "${description.replace(/"/g, '\\"')}"
81
+
82
+ prompt = """
83
+ ${promptBody}
84
+
85
+ Script options:
86
+ ${scriptsBlock}
87
+ """`;
88
+ }
89
+ function toSkill(name, body, frontmatter) {
90
+ const description = String(frontmatter.description ?? "Prodo workflow command");
91
+ return `---
92
+ name: ${name}
93
+ description: ${description}
94
+ compatibility: Requires Prodo project scaffold (.prodo)
95
+ metadata:
96
+ author: prodo
97
+ source: .prodo/commands/${name}.md
98
+ ---
99
+
100
+ ${body}`;
101
+ }
102
+ function resolveAi(ai) {
103
+ if (!ai)
104
+ return undefined;
105
+ const normalized = exports.AI_ALIASES[ai.trim().toLowerCase()];
106
+ if (!normalized) {
107
+ throw new errors_1.UserError("Unsupported --ai value. Use: codex | gemini-cli | claude-cli");
108
+ }
109
+ return normalized;
110
+ }
111
+ async function loadCommandTemplateNames(commandTemplatesDir) {
112
+ if (!(await (0, utils_1.fileExists)(commandTemplatesDir))) {
113
+ throw new errors_1.UserError(`Missing command templates directory: ${commandTemplatesDir}`);
114
+ }
115
+ const entries = await promises_1.default.readdir(commandTemplatesDir, { withFileTypes: true });
116
+ return entries
117
+ .filter((entry) => entry.isFile())
118
+ .map((entry) => entry.name)
119
+ .filter((name) => name.endsWith(".md") && name.startsWith("prodo-"))
120
+ .map((name) => name.replace(/\.md$/, ""))
121
+ .sort();
122
+ }
123
+ async function installAgentCommands(projectRoot, ai) {
124
+ const cfg = AGENT_CONFIG[ai];
125
+ const target = node_path_1.default.join(projectRoot, cfg.baseDir);
126
+ const commandTemplatesDir = node_path_1.default.join(projectRoot, ".prodo", "commands");
127
+ const commandNames = await loadCommandTemplateNames(commandTemplatesDir);
128
+ await (0, utils_1.ensureDir)(target);
129
+ const written = [];
130
+ for (const commandName of commandNames) {
131
+ const templatePath = node_path_1.default.join(commandTemplatesDir, `${commandName}.md`);
132
+ if (!(await (0, utils_1.fileExists)(templatePath))) {
133
+ throw new errors_1.UserError(`Missing command template: ${templatePath}`);
134
+ }
135
+ const raw = await promises_1.default.readFile(templatePath, "utf8");
136
+ const parsed = parseFrontmatter(raw);
137
+ if (cfg.format === "skill") {
138
+ const skillDir = node_path_1.default.join(target, commandName);
139
+ await (0, utils_1.ensureDir)(skillDir);
140
+ const outPath = node_path_1.default.join(skillDir, "SKILL.md");
141
+ const content = toSkill(commandName, parsed.body.replaceAll("$ARGUMENTS", cfg.argsPlaceholder), parsed.frontmatter);
142
+ await promises_1.default.writeFile(outPath, content, "utf8");
143
+ written.push(outPath);
144
+ continue;
145
+ }
146
+ if (cfg.format === "toml") {
147
+ const outPath = node_path_1.default.join(target, `${commandName}${cfg.extension}`);
148
+ await promises_1.default.writeFile(outPath, toTomlPrompt(parsed.body, parsed.frontmatter, cfg.argsPlaceholder), "utf8");
149
+ written.push(outPath);
150
+ continue;
151
+ }
152
+ const outPath = node_path_1.default.join(target, `${commandName}${cfg.extension}`);
153
+ const replacedBody = parsed.body.replaceAll("$ARGUMENTS", cfg.argsPlaceholder);
154
+ await promises_1.default.writeFile(outPath, `${renderFrontmatter(parsed.frontmatter)}\n${replacedBody}`, "utf8");
155
+ written.push(outPath);
156
+ }
157
+ return written;
158
+ }
@@ -0,0 +1,15 @@
1
+ export declare const AGENT_IDS: readonly ["codex", "gemini-cli", "claude-cli"];
2
+ export type AgentId = (typeof AGENT_IDS)[number];
3
+ export declare function isSupportedAgent(agent?: string): agent is AgentId;
4
+ export declare function resolveAgent(agent?: string): AgentId | undefined;
5
+ export type CommandSetItem = {
6
+ command: string;
7
+ purpose: string;
8
+ };
9
+ export type AgentCommandSet = {
10
+ agent: string;
11
+ description?: string;
12
+ recommended_sequence?: CommandSetItem[];
13
+ artifact_shortcuts?: Record<string, string>;
14
+ };
15
+ export declare function loadAgentCommandSet(_cwd: string, agent: AgentId): Promise<AgentCommandSet>;
package/dist/agents.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AGENT_IDS = void 0;
4
+ exports.isSupportedAgent = isSupportedAgent;
5
+ exports.resolveAgent = resolveAgent;
6
+ exports.loadAgentCommandSet = loadAgentCommandSet;
7
+ const errors_1 = require("./errors");
8
+ exports.AGENT_IDS = ["codex", "gemini-cli", "claude-cli"];
9
+ function isSupportedAgent(agent) {
10
+ if (!agent)
11
+ return false;
12
+ return exports.AGENT_IDS.includes(agent);
13
+ }
14
+ function resolveAgent(agent) {
15
+ if (!agent)
16
+ return undefined;
17
+ if (!isSupportedAgent(agent)) {
18
+ throw new errors_1.UserError(`Unsupported agent: ${agent}. Supported: ${exports.AGENT_IDS.join(", ")}`);
19
+ }
20
+ return agent;
21
+ }
22
+ async function loadAgentCommandSet(_cwd, agent) {
23
+ const prefix = `prodo-${agent}`;
24
+ return {
25
+ agent,
26
+ description: "Agent-specific command set for Prodo artifact pipeline.",
27
+ recommended_sequence: [
28
+ { command: "prodo init . --ai <agent> --lang <en|tr>", purpose: "Initialize Prodo scaffold and agent commands." },
29
+ { command: `${prefix} normalize`, purpose: "Normalize start brief into normalized brief JSON." },
30
+ { command: `${prefix} prd`, purpose: "Generate PRD artifact." },
31
+ { command: `${prefix} workflow`, purpose: "Generate workflow artifact." },
32
+ { command: `${prefix} wireframe`, purpose: "Generate wireframe artifact." },
33
+ { command: `${prefix} stories`, purpose: "Generate stories artifact." },
34
+ { command: `${prefix} techspec`, purpose: "Generate techspec artifact." },
35
+ { command: `${prefix} validate`, purpose: "Run validation report." }
36
+ ],
37
+ artifact_shortcuts: {
38
+ normalize: `${prefix} normalize`,
39
+ prd: `${prefix} prd`,
40
+ workflow: `${prefix} workflow`,
41
+ wireframe: `${prefix} wireframe`,
42
+ stories: `${prefix} stories`,
43
+ techspec: `${prefix} techspec`,
44
+ validate: `${prefix} validate`
45
+ }
46
+ };
47
+ }
@@ -0,0 +1,11 @@
1
+ import type { ArtifactType, ContractCoverage } from "./types";
2
+ export type ArtifactDefinition = {
3
+ name: ArtifactType;
4
+ output_dir: string;
5
+ required_headings: string[];
6
+ upstream: ArtifactType[];
7
+ required_contracts: Array<keyof ContractCoverage>;
8
+ };
9
+ export declare function listArtifactDefinitions(cwd: string): Promise<ArtifactDefinition[]>;
10
+ export declare function listArtifactTypes(cwd: string): Promise<ArtifactType[]>;
11
+ export declare function getArtifactDefinition(cwd: string, artifactType: string): Promise<ArtifactDefinition>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listArtifactDefinitions = listArtifactDefinitions;
4
+ exports.listArtifactTypes = listArtifactTypes;
5
+ exports.getArtifactDefinition = getArtifactDefinition;
6
+ const constants_1 = require("./constants");
7
+ const project_config_1 = require("./project-config");
8
+ const types_1 = require("./types");
9
+ function normalizeName(name) {
10
+ return name.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-");
11
+ }
12
+ function toDefinition(partial) {
13
+ const name = normalizeName(partial.name);
14
+ const outputDir = partial.output_dir?.trim() || (0, constants_1.defaultOutputDir)(name);
15
+ const requiredHeadings = partial.required_headings?.length ? partial.required_headings : (0, constants_1.defaultRequiredHeadings)(name);
16
+ const upstream = (partial.upstream?.length ? partial.upstream : (0, constants_1.defaultUpstreamByArtifact)(name)).map(normalizeName);
17
+ const requiredContracts = partial.required_contracts?.length
18
+ ? partial.required_contracts
19
+ : (0, constants_1.defaultRequiredContractsByArtifact)(name);
20
+ return {
21
+ name,
22
+ output_dir: outputDir,
23
+ required_headings: requiredHeadings,
24
+ upstream,
25
+ required_contracts: requiredContracts
26
+ };
27
+ }
28
+ async function listArtifactDefinitions(cwd) {
29
+ const config = await (0, project_config_1.readProjectConfig)(cwd);
30
+ const base = types_1.ARTIFACT_TYPES.map((name) => toDefinition({ name }));
31
+ const byName = new Map(base.map((item) => [item.name, item]));
32
+ for (const extra of config.artifacts ?? []) {
33
+ const merged = toDefinition(extra);
34
+ byName.set(merged.name, merged);
35
+ }
36
+ return Array.from(byName.values());
37
+ }
38
+ async function listArtifactTypes(cwd) {
39
+ const defs = await listArtifactDefinitions(cwd);
40
+ return defs.map((item) => item.name);
41
+ }
42
+ async function getArtifactDefinition(cwd, artifactType) {
43
+ const normalized = normalizeName(artifactType);
44
+ const defs = await listArtifactDefinitions(cwd);
45
+ const found = defs.find((item) => item.name === normalized);
46
+ if (found)
47
+ return found;
48
+ return toDefinition({ name: normalized });
49
+ }
@@ -0,0 +1,9 @@
1
+ import type { ArtifactType } from "./types";
2
+ export type GenerateOptions = {
3
+ artifactType: ArtifactType;
4
+ cwd: string;
5
+ normalizedBriefOverride?: string;
6
+ outPath?: string;
7
+ agent?: string;
8
+ };
9
+ export declare function generateArtifact(options: GenerateOptions): Promise<string>;