@shahmarasy/prodo 0.1.4 → 0.1.5
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/README.md +201 -97
- package/bin/prodo.cjs +6 -6
- package/dist/agents/agent-registry.d.ts +13 -0
- package/dist/agents/agent-registry.js +79 -0
- package/dist/agents/anthropic/index.d.ts +9 -0
- package/dist/agents/anthropic/index.js +55 -0
- package/dist/agents/base.d.ts +25 -0
- package/dist/agents/base.js +71 -0
- package/dist/agents/google/index.d.ts +9 -0
- package/dist/agents/google/index.js +53 -0
- package/dist/agents/mock/index.d.ts +11 -0
- package/dist/agents/mock/index.js +26 -0
- package/dist/agents/openai/index.d.ts +9 -0
- package/dist/agents/openai/index.js +57 -0
- package/dist/agents/system-prompts.d.ts +3 -0
- package/dist/agents/system-prompts.js +32 -0
- package/dist/cli/agent-command-installer.d.ts +4 -0
- package/dist/cli/agent-command-installer.js +148 -0
- package/dist/cli/agent-ids.d.ts +15 -0
- package/dist/cli/agent-ids.js +49 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.js +144 -0
- package/dist/cli/fix-tui.d.ts +4 -0
- package/dist/cli/fix-tui.js +79 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.js +465 -0
- package/dist/cli/init-tui.d.ts +23 -0
- package/dist/cli/init-tui.js +176 -0
- package/dist/cli/init.d.ts +11 -0
- package/dist/cli/init.js +334 -0
- package/dist/cli/normalize-interactive.d.ts +8 -0
- package/dist/cli/normalize-interactive.js +167 -0
- package/dist/cli/preset-loader.d.ts +4 -0
- package/dist/cli/preset-loader.js +210 -0
- package/dist/core/artifact-registry.d.ts +11 -0
- package/dist/core/artifact-registry.js +49 -0
- package/dist/core/artifacts.d.ts +10 -0
- package/dist/core/artifacts.js +892 -0
- package/dist/core/clean.d.ts +10 -0
- package/dist/core/clean.js +74 -0
- package/dist/core/consistency.d.ts +8 -0
- package/dist/core/consistency.js +328 -0
- package/dist/core/constants.d.ts +7 -0
- package/dist/core/constants.js +64 -0
- package/dist/core/errors.d.ts +3 -0
- package/dist/core/errors.js +10 -0
- package/dist/core/fix.d.ts +31 -0
- package/dist/core/fix.js +188 -0
- package/dist/core/hook-executor.d.ts +1 -0
- package/dist/core/hook-executor.js +175 -0
- package/dist/core/markdown.d.ts +16 -0
- package/dist/core/markdown.js +81 -0
- package/dist/core/normalize.d.ts +8 -0
- package/dist/core/normalize.js +125 -0
- package/dist/core/normalized-brief.d.ts +48 -0
- package/dist/core/normalized-brief.js +182 -0
- package/dist/core/output-index.d.ts +13 -0
- package/dist/core/output-index.js +55 -0
- package/dist/core/paths.d.ts +17 -0
- package/dist/core/paths.js +80 -0
- package/dist/core/project-config.d.ts +14 -0
- package/dist/core/project-config.js +69 -0
- package/dist/core/registry.d.ts +13 -0
- package/dist/core/registry.js +115 -0
- package/dist/core/settings.d.ts +7 -0
- package/dist/core/settings.js +35 -0
- package/dist/core/template-engine.d.ts +3 -0
- package/dist/core/template-engine.js +43 -0
- package/dist/core/template-resolver.d.ts +15 -0
- package/dist/core/template-resolver.js +46 -0
- package/dist/core/templates.d.ts +33 -0
- package/dist/core/templates.js +440 -0
- package/dist/core/terminology.d.ts +21 -0
- package/dist/core/terminology.js +143 -0
- package/dist/core/tracing.d.ts +21 -0
- package/dist/core/tracing.js +74 -0
- package/dist/core/types.d.ts +35 -0
- package/dist/core/types.js +5 -0
- package/dist/core/utils.d.ts +7 -0
- package/dist/core/utils.js +66 -0
- package/dist/core/validate.d.ts +10 -0
- package/dist/core/validate.js +226 -0
- package/dist/core/validator.d.ts +5 -0
- package/dist/core/validator.js +76 -0
- package/dist/core/version.d.ts +1 -0
- package/dist/core/version.js +30 -0
- package/dist/core/workflow-commands.d.ts +7 -0
- package/dist/core/workflow-commands.js +29 -0
- package/dist/i18n/en.json +45 -0
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/index.js +63 -0
- package/dist/i18n/tr.json +45 -0
- package/dist/providers/index.d.ts +2 -1
- package/dist/providers/index.js +20 -6
- package/dist/providers/mock-provider.d.ts +1 -1
- package/dist/providers/mock-provider.js +7 -6
- package/dist/providers/openai-provider.d.ts +1 -1
- package/dist/providers/openai-provider.js +1 -1
- package/dist/skills/engine.d.ts +10 -0
- package/dist/skills/engine.js +75 -0
- package/dist/skills/fix-skill.d.ts +2 -0
- package/dist/skills/fix-skill.js +38 -0
- package/dist/skills/generate-artifact-skill.d.ts +2 -0
- package/dist/skills/generate-artifact-skill.js +32 -0
- package/dist/skills/generate-pipeline-skill.d.ts +2 -0
- package/dist/skills/generate-pipeline-skill.js +45 -0
- package/dist/skills/normalize-skill.d.ts +2 -0
- package/dist/skills/normalize-skill.js +29 -0
- package/dist/skills/types.d.ts +28 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/validate-skill.d.ts +2 -0
- package/dist/skills/validate-skill.js +29 -0
- package/package.json +74 -45
- package/src/agents/agent-registry.ts +93 -0
- package/src/agents/anthropic/index.ts +86 -0
- package/src/agents/anthropic/manifest.json +7 -0
- package/src/agents/base.ts +77 -0
- package/src/agents/google/index.ts +79 -0
- package/src/agents/google/manifest.json +7 -0
- package/src/agents/mock/index.ts +32 -0
- package/src/agents/mock/manifest.json +7 -0
- package/src/agents/openai/index.ts +83 -0
- package/src/agents/openai/manifest.json +7 -0
- package/src/agents/system-prompts.ts +35 -0
- package/src/{agent-command-installer.ts → cli/agent-command-installer.ts} +164 -164
- package/src/{agents.ts → cli/agent-ids.ts} +58 -58
- package/src/{doctor.ts → cli/doctor.ts} +157 -137
- package/src/cli/fix-tui.ts +111 -0
- package/src/{cli.ts → cli/index.ts} +459 -410
- package/src/{init-tui.ts → cli/init-tui.ts} +208 -208
- package/src/{init.ts → cli/init.ts} +398 -398
- package/src/cli/normalize-interactive.ts +241 -0
- package/src/{preset-loader.ts → cli/preset-loader.ts} +237 -237
- package/src/{artifact-registry.ts → core/artifact-registry.ts} +69 -69
- package/src/{artifacts.ts → core/artifacts.ts} +1081 -1072
- package/src/core/clean.ts +88 -0
- package/src/{consistency.ts → core/consistency.ts} +374 -303
- package/src/{constants.ts → core/constants.ts} +72 -72
- package/src/{errors.ts → core/errors.ts} +7 -7
- package/src/core/fix.ts +253 -0
- package/src/{hook-executor.ts → core/hook-executor.ts} +196 -196
- package/src/{markdown.ts → core/markdown.ts} +93 -73
- package/src/{normalize.ts → core/normalize.ts} +145 -137
- package/src/{normalized-brief.ts → core/normalized-brief.ts} +227 -206
- package/src/{output-index.ts → core/output-index.ts} +59 -59
- package/src/{paths.ts → core/paths.ts} +75 -71
- package/src/{project-config.ts → core/project-config.ts} +78 -78
- package/src/{registry.ts → core/registry.ts} +119 -119
- package/src/{settings.ts → core/settings.ts} +35 -35
- package/src/core/template-engine.ts +45 -0
- package/src/{template-resolver.ts → core/template-resolver.ts} +54 -54
- package/src/{templates.ts → core/templates.ts} +452 -452
- package/src/core/terminology.ts +177 -0
- package/src/core/tracing.ts +110 -0
- package/src/{types.ts → core/types.ts} +46 -46
- package/src/{utils.ts → core/utils.ts} +64 -64
- package/src/{validate.ts → core/validate.ts} +252 -246
- package/src/{validator.ts → core/validator.ts} +92 -92
- package/src/{version.ts → core/version.ts} +24 -24
- package/src/{workflow-commands.ts → core/workflow-commands.ts} +32 -32
- package/src/i18n/en.json +45 -0
- package/src/i18n/index.ts +58 -0
- package/src/i18n/tr.json +45 -0
- package/src/providers/index.ts +29 -12
- package/src/providers/mock-provider.ts +200 -199
- package/src/providers/openai-provider.ts +88 -88
- package/src/skills/engine.ts +94 -0
- package/src/skills/fix-skill.ts +38 -0
- package/src/skills/generate-artifact-skill.ts +32 -0
- package/src/skills/generate-pipeline-skill.ts +49 -0
- package/src/skills/normalize-skill.ts +29 -0
- package/src/skills/types.ts +36 -0
- package/src/skills/validate-skill.ts +29 -0
|
@@ -0,0 +1,63 @@
|
|
|
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.t = t;
|
|
7
|
+
exports.loadTranslations = loadTranslations;
|
|
8
|
+
exports.availableLanguages = availableLanguages;
|
|
9
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const cache = new Map();
|
|
12
|
+
function loadJson(lang) {
|
|
13
|
+
if (cache.has(lang))
|
|
14
|
+
return cache.get(lang);
|
|
15
|
+
const filePath = node_path_1.default.resolve(__dirname, `${lang}.json`);
|
|
16
|
+
try {
|
|
17
|
+
const raw = node_fs_1.default.readFileSync(filePath, "utf8");
|
|
18
|
+
const parsed = JSON.parse(raw);
|
|
19
|
+
cache.set(lang, parsed);
|
|
20
|
+
return parsed;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
cache.set(lang, {});
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function normalizeLang(lang) {
|
|
28
|
+
if (!lang)
|
|
29
|
+
return "en";
|
|
30
|
+
const code = lang.toLowerCase().trim();
|
|
31
|
+
if (code.startsWith("tr"))
|
|
32
|
+
return "tr";
|
|
33
|
+
if (code.startsWith("en"))
|
|
34
|
+
return "en";
|
|
35
|
+
return code;
|
|
36
|
+
}
|
|
37
|
+
function t(key, lang) {
|
|
38
|
+
const normalized = normalizeLang(lang);
|
|
39
|
+
const translations = loadJson(normalized);
|
|
40
|
+
if (key in translations)
|
|
41
|
+
return translations[key];
|
|
42
|
+
if (normalized !== "en") {
|
|
43
|
+
const fallback = loadJson("en");
|
|
44
|
+
if (key in fallback)
|
|
45
|
+
return fallback[key];
|
|
46
|
+
}
|
|
47
|
+
return key;
|
|
48
|
+
}
|
|
49
|
+
function loadTranslations(lang) {
|
|
50
|
+
return { ...loadJson(normalizeLang(lang)) };
|
|
51
|
+
}
|
|
52
|
+
function availableLanguages() {
|
|
53
|
+
const dir = node_path_1.default.resolve(__dirname);
|
|
54
|
+
try {
|
|
55
|
+
return node_fs_1.default.readdirSync(dir)
|
|
56
|
+
.filter((f) => f.endsWith(".json"))
|
|
57
|
+
.map((f) => f.replace(".json", ""))
|
|
58
|
+
.sort();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return ["en"];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"user_action": "Kullanıcı işlemi",
|
|
3
|
+
"main_flow": "Ana Akış",
|
|
4
|
+
"user": "Kullanıcı",
|
|
5
|
+
"success": "Başarı",
|
|
6
|
+
"error": "Hata",
|
|
7
|
+
"flow_focus": "Akış Odağı",
|
|
8
|
+
"initial_version": "İlk sürüm",
|
|
9
|
+
"fix_revision": "Doğrulama sonrası düzeltme revizyonu",
|
|
10
|
+
"primary_user": "Birincil kullanıcı",
|
|
11
|
+
"back": "Geri",
|
|
12
|
+
"next": "Devam",
|
|
13
|
+
"save": "Kaydet",
|
|
14
|
+
"content": "İçerik",
|
|
15
|
+
"primary_info_area": "Birincil bilgi alanı",
|
|
16
|
+
"status_indicator": "Durum göstergesi",
|
|
17
|
+
"form": "Form",
|
|
18
|
+
"field": "Alan",
|
|
19
|
+
"description": "Açıklama",
|
|
20
|
+
"contract": "Kontrat",
|
|
21
|
+
"actor": "Aktör",
|
|
22
|
+
"detailed_input_area": "Detaylı Giriş Alanı",
|
|
23
|
+
"upload_area": "Dosya Alanı",
|
|
24
|
+
"low_fidelity_wireframe": "Düşük sadakatli wireframe.",
|
|
25
|
+
"confirmation_text": "Onay metni",
|
|
26
|
+
"header_and_navigation": "Başlık ve gezinme",
|
|
27
|
+
"content_section": "İçerik bölümü",
|
|
28
|
+
"form_section": "Form bölümü",
|
|
29
|
+
"text_input": "Metin alanı",
|
|
30
|
+
"to_be_refined": "Detay daha sonra netleştirilecek.",
|
|
31
|
+
"note": "Not",
|
|
32
|
+
"requirement_item": "Gereksinim maddesi",
|
|
33
|
+
"contract_coverage": "Kontrat kapsamı",
|
|
34
|
+
"screen": "Ekran",
|
|
35
|
+
"for_artifact": "için",
|
|
36
|
+
"fix_proposal": "Düzeltme Önerisi",
|
|
37
|
+
"fix_complete": "Düzeltme tamamlandı — doğrulama geçti.",
|
|
38
|
+
"fix_still_failing": "Düzeltme uygulandı ama doğrulama hâlâ başarısız.",
|
|
39
|
+
"fix_cancelled": "Düzeltme iptal edildi.",
|
|
40
|
+
"no_issues": "Engel teşkil eden sorun bulunamadı. Düzeltilecek bir şey yok.",
|
|
41
|
+
"issues_found": "Bulunan sorunlar",
|
|
42
|
+
"artifacts_to_regenerate": "Yeniden oluşturulacak artefaktlar",
|
|
43
|
+
"general": "Genel",
|
|
44
|
+
"suggestion_prefix": "→"
|
|
45
|
+
}
|
package/dist/providers/index.js
CHANGED
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getGlobalRegistry = void 0;
|
|
3
4
|
exports.createProvider = createProvider;
|
|
4
|
-
const
|
|
5
|
-
|
|
5
|
+
const agent_registry_1 = require("../agents/agent-registry");
|
|
6
|
+
let cachedProvider = null;
|
|
7
|
+
let cachedAgentName = null;
|
|
6
8
|
function createProvider() {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
const agentName = process.env.PRODO_AGENT ??
|
|
10
|
+
process.env.PRODO_LLM_PROVIDER ??
|
|
11
|
+
"mock";
|
|
12
|
+
if (cachedProvider && cachedAgentName === agentName) {
|
|
13
|
+
return cachedProvider;
|
|
10
14
|
}
|
|
11
|
-
|
|
15
|
+
const registry = (0, agent_registry_1.getGlobalRegistry)();
|
|
16
|
+
const agent = registry.get(agentName);
|
|
17
|
+
if (!agent) {
|
|
18
|
+
const available = registry.list().map((a) => a.name).join(", ");
|
|
19
|
+
throw new Error(`Unknown agent: "${agentName}". Available: ${available}`);
|
|
20
|
+
}
|
|
21
|
+
cachedProvider = registry.toProvider(agent);
|
|
22
|
+
cachedAgentName = agentName;
|
|
23
|
+
return cachedProvider;
|
|
12
24
|
}
|
|
25
|
+
var agent_registry_2 = require("../agents/agent-registry");
|
|
26
|
+
Object.defineProperty(exports, "getGlobalRegistry", { enumerable: true, get: function () { return agent_registry_2.getGlobalRegistry; } });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LLMProvider, ProviderSchemaHint } from "../types";
|
|
1
|
+
import type { LLMProvider, ProviderSchemaHint } from "../core/types";
|
|
2
2
|
export declare class MockProvider implements LLMProvider {
|
|
3
3
|
generate(_prompt: string, inputContext: Record<string, unknown>, schemaHint: ProviderSchemaHint): Promise<{
|
|
4
4
|
body: string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MockProvider = void 0;
|
|
4
|
+
const i18n_1 = require("../i18n");
|
|
4
5
|
function asStringArray(value) {
|
|
5
6
|
if (!Array.isArray(value))
|
|
6
7
|
return [];
|
|
@@ -107,18 +108,18 @@ function buildArtifactBody(schemaHint, inputContext) {
|
|
|
107
108
|
const lang = typeof inputContext.outputLanguage === "string" ? inputContext.outputLanguage.toLowerCase() : "en";
|
|
108
109
|
const items = normalizeSectionItems(inputContext);
|
|
109
110
|
const coverage = coverageItems(schemaHint, inputContext);
|
|
110
|
-
const localizedItems = lang === "tr" ? items.map((_, index) =>
|
|
111
|
+
const localizedItems = lang === "tr" ? items.map((_, index) => `${(0, i18n_1.t)("requirement_item", lang)} ${index + 1}`) : items;
|
|
111
112
|
const localizedCoverage = lang === "tr"
|
|
112
113
|
? coverage.map((item, index) => ({
|
|
113
114
|
id: item.id,
|
|
114
|
-
text:
|
|
115
|
+
text: `${(0, i18n_1.t)("contract_coverage", lang)} ${index + 1}`
|
|
115
116
|
}))
|
|
116
117
|
: coverage;
|
|
117
|
-
const fallback =
|
|
118
|
+
const fallback = (0, i18n_1.t)("to_be_refined", lang);
|
|
118
119
|
const sections = schemaHint.requiredHeadings.map((heading) => headingBlock(heading, localizedItems, fallback, localizedCoverage));
|
|
119
120
|
const title = lang === "tr"
|
|
120
|
-
? `# ${productName}
|
|
121
|
-
: `# ${schemaHint.artifactType.toUpperCase()}
|
|
121
|
+
? `# ${productName} ${(0, i18n_1.t)("for_artifact", lang)} ${schemaHint.artifactType.toUpperCase()}`
|
|
122
|
+
: `# ${schemaHint.artifactType.toUpperCase()} ${(0, i18n_1.t)("for_artifact", lang)} ${productName}`;
|
|
122
123
|
if (schemaHint.artifactType === "workflow") {
|
|
123
124
|
return `${title}\n\n${sections.join("\n")}\n\n\`\`\`mermaid
|
|
124
125
|
flowchart TD
|
|
@@ -127,7 +128,7 @@ flowchart TD
|
|
|
127
128
|
C --> D[Done]
|
|
128
129
|
\`\`\``.trim();
|
|
129
130
|
}
|
|
130
|
-
return `${title}\n\n${sections.join("\n")}\n\n${
|
|
131
|
+
return `${title}\n\n${sections.join("\n")}\n\n${(0, i18n_1.t)("note", lang)}: ${fallback}`.trim();
|
|
131
132
|
}
|
|
132
133
|
function semanticIssuesWithMock(inputContext) {
|
|
133
134
|
const pair = inputContext.pair;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Skill, SkillContext, SkillManifest } from "./types";
|
|
2
|
+
export type SkillEngine = {
|
|
3
|
+
register(skill: Skill): void;
|
|
4
|
+
getSkill(name: string): Skill | undefined;
|
|
5
|
+
listSkills(): SkillManifest[];
|
|
6
|
+
execute(name: string, context: SkillContext, inputs: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
export declare function createSkillEngine(): SkillEngine;
|
|
9
|
+
export declare function getGlobalSkillEngine(): SkillEngine;
|
|
10
|
+
export declare function resetGlobalSkillEngine(): void;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSkillEngine = createSkillEngine;
|
|
4
|
+
exports.getGlobalSkillEngine = getGlobalSkillEngine;
|
|
5
|
+
exports.resetGlobalSkillEngine = resetGlobalSkillEngine;
|
|
6
|
+
const errors_1 = require("../core/errors");
|
|
7
|
+
function validateInputs(skill, inputs) {
|
|
8
|
+
for (const input of skill.manifest.inputs) {
|
|
9
|
+
if (input.required && !(input.name in inputs)) {
|
|
10
|
+
throw new errors_1.UserError(`Skill "${skill.manifest.name}" requires input "${input.name}" (${input.description})`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function createSkillEngine() {
|
|
15
|
+
const skills = new Map();
|
|
16
|
+
return {
|
|
17
|
+
register(skill) {
|
|
18
|
+
skills.set(skill.manifest.name, skill);
|
|
19
|
+
},
|
|
20
|
+
getSkill(name) {
|
|
21
|
+
return skills.get(name);
|
|
22
|
+
},
|
|
23
|
+
listSkills() {
|
|
24
|
+
return Array.from(skills.values()).map((s) => s.manifest);
|
|
25
|
+
},
|
|
26
|
+
async execute(name, context, inputs) {
|
|
27
|
+
const skill = skills.get(name);
|
|
28
|
+
if (!skill) {
|
|
29
|
+
const available = Array.from(skills.keys()).join(", ");
|
|
30
|
+
throw new errors_1.UserError(`Unknown skill: "${name}". Available: ${available}`);
|
|
31
|
+
}
|
|
32
|
+
validateInputs(skill, inputs);
|
|
33
|
+
return skill.execute(context, inputs);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
let globalEngine = null;
|
|
38
|
+
function getGlobalSkillEngine() {
|
|
39
|
+
if (!globalEngine) {
|
|
40
|
+
globalEngine = createSkillEngine();
|
|
41
|
+
loadBuiltinSkills(globalEngine);
|
|
42
|
+
}
|
|
43
|
+
return globalEngine;
|
|
44
|
+
}
|
|
45
|
+
function resetGlobalSkillEngine() {
|
|
46
|
+
globalEngine = null;
|
|
47
|
+
}
|
|
48
|
+
function loadBuiltinSkills(engine) {
|
|
49
|
+
// Lazy-load to avoid circular dependencies
|
|
50
|
+
try {
|
|
51
|
+
const { normalizeSkill } = require("./normalize-skill");
|
|
52
|
+
engine.register(normalizeSkill);
|
|
53
|
+
}
|
|
54
|
+
catch { /* skill not available */ }
|
|
55
|
+
try {
|
|
56
|
+
const { validateSkill } = require("./validate-skill");
|
|
57
|
+
engine.register(validateSkill);
|
|
58
|
+
}
|
|
59
|
+
catch { /* skill not available */ }
|
|
60
|
+
try {
|
|
61
|
+
const { fixSkill } = require("./fix-skill");
|
|
62
|
+
engine.register(fixSkill);
|
|
63
|
+
}
|
|
64
|
+
catch { /* skill not available */ }
|
|
65
|
+
try {
|
|
66
|
+
const { generateArtifactSkill } = require("./generate-artifact-skill");
|
|
67
|
+
engine.register(generateArtifactSkill);
|
|
68
|
+
}
|
|
69
|
+
catch { /* skill not available */ }
|
|
70
|
+
try {
|
|
71
|
+
const { generatePipelineSkill } = require("./generate-pipeline-skill");
|
|
72
|
+
engine.register(generatePipelineSkill);
|
|
73
|
+
}
|
|
74
|
+
catch { /* skill not available */ }
|
|
75
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fixSkill = void 0;
|
|
4
|
+
const fix_1 = require("../core/fix");
|
|
5
|
+
exports.fixSkill = {
|
|
6
|
+
manifest: {
|
|
7
|
+
name: "fix",
|
|
8
|
+
description: "Auto-regenerate artifacts that failed validation with backup and rollback",
|
|
9
|
+
category: "validation",
|
|
10
|
+
inputs: [
|
|
11
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
12
|
+
{ name: "agent", type: "string", required: false, description: "Agent profile name" },
|
|
13
|
+
{ name: "strict", type: "boolean", required: false, description: "Treat warnings as errors" },
|
|
14
|
+
{ name: "dryRun", type: "boolean", required: false, description: "Preview without applying" }
|
|
15
|
+
],
|
|
16
|
+
outputs: [
|
|
17
|
+
{ name: "applied", type: "string", description: "Whether fix was applied" },
|
|
18
|
+
{ name: "finalPass", type: "string", description: "Whether validation passed after fix" },
|
|
19
|
+
{ name: "reportPath", type: "path", description: "Path to validation report" }
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
async execute(context, inputs) {
|
|
23
|
+
const cwd = inputs.cwd ?? context.cwd;
|
|
24
|
+
const result = await (0, fix_1.runFix)({
|
|
25
|
+
cwd,
|
|
26
|
+
agent: inputs.agent ?? context.agent,
|
|
27
|
+
strict: Boolean(inputs.strict),
|
|
28
|
+
dryRun: Boolean(inputs.dryRun),
|
|
29
|
+
log: context.log
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
applied: result.applied,
|
|
33
|
+
finalPass: result.finalPass,
|
|
34
|
+
reportPath: result.reportPath,
|
|
35
|
+
targetCount: result.proposal.targets.length
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateArtifactSkill = void 0;
|
|
4
|
+
const artifacts_1 = require("../core/artifacts");
|
|
5
|
+
exports.generateArtifactSkill = {
|
|
6
|
+
manifest: {
|
|
7
|
+
name: "generate-artifact",
|
|
8
|
+
description: "Generate a single artifact (PRD, workflow, wireframe, stories, techspec)",
|
|
9
|
+
category: "artifact",
|
|
10
|
+
inputs: [
|
|
11
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
12
|
+
{ name: "artifactType", type: "string", required: true, description: "Artifact type to generate" },
|
|
13
|
+
{ name: "from", type: "path", required: false, description: "Override path to normalized-brief.json" },
|
|
14
|
+
{ name: "out", type: "path", required: false, description: "Override output path" }
|
|
15
|
+
],
|
|
16
|
+
outputs: [
|
|
17
|
+
{ name: "filePath", type: "path", description: "Path to generated artifact" }
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
async execute(context, inputs) {
|
|
21
|
+
const cwd = inputs.cwd ?? context.cwd;
|
|
22
|
+
const filePath = await (0, artifacts_1.generateArtifact)({
|
|
23
|
+
artifactType: inputs.artifactType,
|
|
24
|
+
cwd,
|
|
25
|
+
normalizedBriefOverride: inputs.from,
|
|
26
|
+
outPath: inputs.out,
|
|
27
|
+
agent: context.agent
|
|
28
|
+
});
|
|
29
|
+
context.log(`${inputs.artifactType.toUpperCase()} generated: ${filePath}`);
|
|
30
|
+
return { filePath };
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generatePipelineSkill = void 0;
|
|
4
|
+
const artifact_registry_1 = require("../core/artifact-registry");
|
|
5
|
+
const artifacts_1 = require("../core/artifacts");
|
|
6
|
+
const normalize_1 = require("../core/normalize");
|
|
7
|
+
const validate_1 = require("../core/validate");
|
|
8
|
+
exports.generatePipelineSkill = {
|
|
9
|
+
manifest: {
|
|
10
|
+
name: "generate-pipeline",
|
|
11
|
+
description: "Run end-to-end pipeline: normalize → generate all artifacts → validate",
|
|
12
|
+
category: "core",
|
|
13
|
+
inputs: [
|
|
14
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
15
|
+
{ name: "strict", type: "boolean", required: false, description: "Treat warnings as errors" }
|
|
16
|
+
],
|
|
17
|
+
outputs: [
|
|
18
|
+
{ name: "pass", type: "string", description: "Whether validation passed" },
|
|
19
|
+
{ name: "reportPath", type: "path", description: "Path to validation report" },
|
|
20
|
+
{ name: "artifactCount", type: "string", description: "Number of artifacts generated" }
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
async execute(context, inputs) {
|
|
24
|
+
const cwd = inputs.cwd ?? context.cwd;
|
|
25
|
+
const normalizedPath = await (0, normalize_1.runNormalize)({ cwd });
|
|
26
|
+
context.log(`Normalized brief: ${normalizedPath}`);
|
|
27
|
+
const artifactTypes = await (0, artifact_registry_1.listArtifactTypes)(cwd);
|
|
28
|
+
for (const type of artifactTypes) {
|
|
29
|
+
const file = await (0, artifacts_1.generateArtifact)({
|
|
30
|
+
artifactType: type,
|
|
31
|
+
cwd,
|
|
32
|
+
normalizedBriefOverride: normalizedPath,
|
|
33
|
+
agent: context.agent
|
|
34
|
+
});
|
|
35
|
+
context.log(`${type.toUpperCase()} generated: ${file}`);
|
|
36
|
+
}
|
|
37
|
+
const result = await (0, validate_1.runValidate)(cwd, { strict: Boolean(inputs.strict) });
|
|
38
|
+
context.log(`Validation ${result.pass ? "passed" : "failed"}: ${result.reportPath}`);
|
|
39
|
+
return {
|
|
40
|
+
pass: result.pass,
|
|
41
|
+
reportPath: result.reportPath,
|
|
42
|
+
artifactCount: artifactTypes.length
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeSkill = void 0;
|
|
4
|
+
const normalize_1 = require("../core/normalize");
|
|
5
|
+
exports.normalizeSkill = {
|
|
6
|
+
manifest: {
|
|
7
|
+
name: "normalize",
|
|
8
|
+
description: "Normalize a product brief into structured JSON with contracts and confidence scores",
|
|
9
|
+
category: "core",
|
|
10
|
+
inputs: [
|
|
11
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
12
|
+
{ name: "brief", type: "path", required: false, description: "Override path to brief.md" },
|
|
13
|
+
{ name: "out", type: "path", required: false, description: "Override output path" }
|
|
14
|
+
],
|
|
15
|
+
outputs: [
|
|
16
|
+
{ name: "normalizedBriefPath", type: "path", description: "Path to normalized-brief.json" }
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
async execute(context, inputs) {
|
|
20
|
+
const cwd = inputs.cwd ?? context.cwd;
|
|
21
|
+
const outPath = await (0, normalize_1.runNormalize)({
|
|
22
|
+
cwd,
|
|
23
|
+
brief: inputs.brief,
|
|
24
|
+
out: inputs.out
|
|
25
|
+
});
|
|
26
|
+
context.log(`Normalized brief written to: ${outPath}`);
|
|
27
|
+
return { normalizedBriefPath: outPath };
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type SkillInput = {
|
|
2
|
+
name: string;
|
|
3
|
+
type: "path" | "string" | "boolean" | "json";
|
|
4
|
+
required: boolean;
|
|
5
|
+
description: string;
|
|
6
|
+
};
|
|
7
|
+
export type SkillOutput = {
|
|
8
|
+
name: string;
|
|
9
|
+
type: "path" | "string" | "json";
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
export type SkillManifest = {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
category: "core" | "artifact" | "validation" | "custom";
|
|
16
|
+
inputs: SkillInput[];
|
|
17
|
+
outputs: SkillOutput[];
|
|
18
|
+
};
|
|
19
|
+
export type SkillContext = {
|
|
20
|
+
cwd: string;
|
|
21
|
+
log: (message: string) => void;
|
|
22
|
+
agent?: string;
|
|
23
|
+
};
|
|
24
|
+
export type SkillFunction = (context: SkillContext, inputs: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
25
|
+
export type Skill = {
|
|
26
|
+
manifest: SkillManifest;
|
|
27
|
+
execute: SkillFunction;
|
|
28
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateSkill = void 0;
|
|
4
|
+
const validate_1 = require("../core/validate");
|
|
5
|
+
exports.validateSkill = {
|
|
6
|
+
manifest: {
|
|
7
|
+
name: "validate",
|
|
8
|
+
description: "Run cross-artifact validation and generate a report",
|
|
9
|
+
category: "validation",
|
|
10
|
+
inputs: [
|
|
11
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
12
|
+
{ name: "strict", type: "boolean", required: false, description: "Treat warnings as errors" },
|
|
13
|
+
{ name: "report", type: "path", required: false, description: "Override report output path" }
|
|
14
|
+
],
|
|
15
|
+
outputs: [
|
|
16
|
+
{ name: "pass", type: "string", description: "Whether validation passed" },
|
|
17
|
+
{ name: "reportPath", type: "path", description: "Path to validation report" }
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
async execute(context, inputs) {
|
|
21
|
+
const cwd = inputs.cwd ?? context.cwd;
|
|
22
|
+
const result = await (0, validate_1.runValidate)(cwd, {
|
|
23
|
+
strict: Boolean(inputs.strict),
|
|
24
|
+
report: inputs.report
|
|
25
|
+
});
|
|
26
|
+
context.log(`Validation ${result.pass ? "passed" : "failed"}: ${result.reportPath}`);
|
|
27
|
+
return { pass: result.pass, reportPath: result.reportPath, issueCount: result.issues.length };
|
|
28
|
+
}
|
|
29
|
+
};
|
package/package.json
CHANGED
|
@@ -1,45 +1,74 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@shahmarasy/prodo",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "CLI-first, prompt-powered product artifact kit",
|
|
5
|
-
"main": "dist/cli.js",
|
|
6
|
-
"types": "dist/cli.d.ts",
|
|
7
|
-
"bin": {
|
|
8
|
-
"prodo": "bin/prodo.cjs"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"bin/",
|
|
12
|
-
"dist/",
|
|
13
|
-
"templates/",
|
|
14
|
-
"presets/",
|
|
15
|
-
"src/",
|
|
16
|
-
"README.md"
|
|
17
|
-
],
|
|
18
|
-
"publishConfig": {
|
|
19
|
-
"access": "public"
|
|
20
|
-
},
|
|
21
|
-
"engines": {
|
|
22
|
-
"node": ">=20"
|
|
23
|
-
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "tsc -p tsconfig.json",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@shahmarasy/prodo",
|
|
3
|
+
"version": "0.1.5",
|
|
4
|
+
"description": "CLI-first, prompt-powered product artifact kit",
|
|
5
|
+
"main": "dist/cli/index.js",
|
|
6
|
+
"types": "dist/cli/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"prodo": "bin/prodo.cjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"dist/",
|
|
13
|
+
"templates/",
|
|
14
|
+
"presets/",
|
|
15
|
+
"src/",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build:ts": "tsc -p tsconfig.json",
|
|
26
|
+
"build:i18n": "node -e \"const fs=require('fs');const p=require('path');['en','tr'].forEach(l=>{const s=p.join('src','i18n',l+'.json');const d=p.join('dist','i18n',l+'.json');fs.copyFileSync(s,d)})\"",
|
|
27
|
+
"build": "npm run build:ts && npm run build:i18n",
|
|
28
|
+
"test": "npm run build && node --test tests/*.test.cjs",
|
|
29
|
+
"verify:release": "npm run build && node scripts/verify-release-build.cjs"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"product-management",
|
|
33
|
+
"prd",
|
|
34
|
+
"ai-agents",
|
|
35
|
+
"codex",
|
|
36
|
+
"claude",
|
|
37
|
+
"gemini",
|
|
38
|
+
"document-generation",
|
|
39
|
+
"cli"
|
|
40
|
+
],
|
|
41
|
+
"author": "Shahmarasy",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@clack/prompts": "^1.1.0",
|
|
45
|
+
"ajv": "^8.18.0",
|
|
46
|
+
"ajv-formats": "^3.0.1",
|
|
47
|
+
"commander": "^14.0.3",
|
|
48
|
+
"gray-matter": "^4.0.3",
|
|
49
|
+
"js-yaml": "^4.1.1",
|
|
50
|
+
"nunjucks": "^3.2.4"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"openai": ">=4.0.0",
|
|
54
|
+
"@anthropic-ai/sdk": ">=0.20.0",
|
|
55
|
+
"@google/generative-ai": ">=0.1.0"
|
|
56
|
+
},
|
|
57
|
+
"peerDependenciesMeta": {
|
|
58
|
+
"openai": {
|
|
59
|
+
"optional": true
|
|
60
|
+
},
|
|
61
|
+
"@anthropic-ai/sdk": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"@google/generative-ai": {
|
|
65
|
+
"optional": true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/js-yaml": "^4.0.9",
|
|
70
|
+
"@types/node": "^25.5.0",
|
|
71
|
+
"@types/nunjucks": "^3.2.6",
|
|
72
|
+
"typescript": "^5.9.3"
|
|
73
|
+
}
|
|
74
|
+
}
|