@shahmarasy/prodo 0.1.3 → 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/agents.js +4 -2
- package/dist/artifacts.d.ts +1 -0
- package/dist/artifacts.js +265 -31
- 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/cli.js +80 -3
- 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/init-tui.d.ts +3 -0
- package/dist/init-tui.js +28 -1
- package/dist/init.d.ts +1 -0
- package/dist/init.js +9 -3
- package/dist/normalize.js +55 -7
- 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 +3 -2
- package/dist/settings.d.ts +1 -0
- package/dist/settings.js +2 -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/dist/templates.d.ts +1 -1
- package/dist/templates.js +2 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +13 -0
- package/dist/validator.js +0 -4
- package/dist/workflow-commands.js +2 -1
- package/package.json +74 -45
- package/presets/fintech/preset.json +48 -1
- package/presets/fintech/prompts/prd.md +99 -2
- package/presets/marketplace/preset.json +51 -1
- package/presets/marketplace/prompts/prd.md +140 -2
- package/presets/saas/preset.json +53 -1
- package/presets/saas/prompts/prd.md +150 -2
- 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 -56
- 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 -319
- package/src/{init-tui.ts → cli/init-tui.ts} +208 -179
- package/src/{init.ts → cli/init.ts} +398 -391
- 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 -777
- 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/core/normalize.ts +145 -0
- 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 -34
- 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 -450
- 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 -50
- package/src/{validate.ts → core/validate.ts} +252 -246
- package/src/{validator.ts → core/validator.ts} +92 -96
- package/src/{version.ts → core/version.ts} +24 -24
- package/src/{workflow-commands.ts → core/workflow-commands.ts} +32 -31
- 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 -87
- 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
- package/templates/commands/prodo-fix.md +46 -0
- package/templates/commands/prodo-normalize.md +118 -23
- package/templates/commands/prodo-prd.md +138 -17
- package/templates/commands/prodo-stories.md +153 -17
- package/templates/commands/prodo-techspec.md +167 -17
- package/templates/commands/prodo-validate.md +184 -26
- package/templates/commands/prodo-wireframe.md +188 -17
- package/templates/commands/prodo-workflow.md +200 -17
- package/src/normalize.ts +0 -89
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { UserError } from "../core/errors";
|
|
2
|
+
import type { Skill, SkillContext, SkillManifest } from "./types";
|
|
3
|
+
|
|
4
|
+
export type SkillEngine = {
|
|
5
|
+
register(skill: Skill): void;
|
|
6
|
+
getSkill(name: string): Skill | undefined;
|
|
7
|
+
listSkills(): SkillManifest[];
|
|
8
|
+
execute(name: string, context: SkillContext, inputs: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function validateInputs(skill: Skill, inputs: Record<string, unknown>): void {
|
|
12
|
+
for (const input of skill.manifest.inputs) {
|
|
13
|
+
if (input.required && !(input.name in inputs)) {
|
|
14
|
+
throw new UserError(
|
|
15
|
+
`Skill "${skill.manifest.name}" requires input "${input.name}" (${input.description})`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function createSkillEngine(): SkillEngine {
|
|
22
|
+
const skills = new Map<string, Skill>();
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
register(skill: Skill): void {
|
|
26
|
+
skills.set(skill.manifest.name, skill);
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
getSkill(name: string): Skill | undefined {
|
|
30
|
+
return skills.get(name);
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
listSkills(): SkillManifest[] {
|
|
34
|
+
return Array.from(skills.values()).map((s) => s.manifest);
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async execute(
|
|
38
|
+
name: string,
|
|
39
|
+
context: SkillContext,
|
|
40
|
+
inputs: Record<string, unknown>
|
|
41
|
+
): Promise<Record<string, unknown>> {
|
|
42
|
+
const skill = skills.get(name);
|
|
43
|
+
if (!skill) {
|
|
44
|
+
const available = Array.from(skills.keys()).join(", ");
|
|
45
|
+
throw new UserError(`Unknown skill: "${name}". Available: ${available}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
validateInputs(skill, inputs);
|
|
49
|
+
return skill.execute(context, inputs);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let globalEngine: SkillEngine | null = null;
|
|
55
|
+
|
|
56
|
+
export function getGlobalSkillEngine(): SkillEngine {
|
|
57
|
+
if (!globalEngine) {
|
|
58
|
+
globalEngine = createSkillEngine();
|
|
59
|
+
loadBuiltinSkills(globalEngine);
|
|
60
|
+
}
|
|
61
|
+
return globalEngine;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function resetGlobalSkillEngine(): void {
|
|
65
|
+
globalEngine = null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function loadBuiltinSkills(engine: SkillEngine): void {
|
|
69
|
+
// Lazy-load to avoid circular dependencies
|
|
70
|
+
try {
|
|
71
|
+
const { normalizeSkill } = require("./normalize-skill") as { normalizeSkill: Skill };
|
|
72
|
+
engine.register(normalizeSkill);
|
|
73
|
+
} catch { /* skill not available */ }
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const { validateSkill } = require("./validate-skill") as { validateSkill: Skill };
|
|
77
|
+
engine.register(validateSkill);
|
|
78
|
+
} catch { /* skill not available */ }
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
const { fixSkill } = require("./fix-skill") as { fixSkill: Skill };
|
|
82
|
+
engine.register(fixSkill);
|
|
83
|
+
} catch { /* skill not available */ }
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const { generateArtifactSkill } = require("./generate-artifact-skill") as { generateArtifactSkill: Skill };
|
|
87
|
+
engine.register(generateArtifactSkill);
|
|
88
|
+
} catch { /* skill not available */ }
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const { generatePipelineSkill } = require("./generate-pipeline-skill") as { generatePipelineSkill: Skill };
|
|
92
|
+
engine.register(generatePipelineSkill);
|
|
93
|
+
} catch { /* skill not available */ }
|
|
94
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { runFix } from "../core/fix";
|
|
2
|
+
import type { Skill } from "./types";
|
|
3
|
+
|
|
4
|
+
export const fixSkill: Skill = {
|
|
5
|
+
manifest: {
|
|
6
|
+
name: "fix",
|
|
7
|
+
description: "Auto-regenerate artifacts that failed validation with backup and rollback",
|
|
8
|
+
category: "validation",
|
|
9
|
+
inputs: [
|
|
10
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
11
|
+
{ name: "agent", type: "string", required: false, description: "Agent profile name" },
|
|
12
|
+
{ name: "strict", type: "boolean", required: false, description: "Treat warnings as errors" },
|
|
13
|
+
{ name: "dryRun", type: "boolean", required: false, description: "Preview without applying" }
|
|
14
|
+
],
|
|
15
|
+
outputs: [
|
|
16
|
+
{ name: "applied", type: "string", description: "Whether fix was applied" },
|
|
17
|
+
{ name: "finalPass", type: "string", description: "Whether validation passed after fix" },
|
|
18
|
+
{ name: "reportPath", type: "path", description: "Path to validation report" }
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
async execute(context, inputs): Promise<Record<string, unknown>> {
|
|
23
|
+
const cwd = (inputs.cwd as string) ?? context.cwd;
|
|
24
|
+
const result = await runFix({
|
|
25
|
+
cwd,
|
|
26
|
+
agent: (inputs.agent as string) ?? 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
|
+
import { generateArtifact } from "../core/artifacts";
|
|
2
|
+
import type { Skill } from "./types";
|
|
3
|
+
|
|
4
|
+
export const generateArtifactSkill: Skill = {
|
|
5
|
+
manifest: {
|
|
6
|
+
name: "generate-artifact",
|
|
7
|
+
description: "Generate a single artifact (PRD, workflow, wireframe, stories, techspec)",
|
|
8
|
+
category: "artifact",
|
|
9
|
+
inputs: [
|
|
10
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
11
|
+
{ name: "artifactType", type: "string", required: true, description: "Artifact type to generate" },
|
|
12
|
+
{ name: "from", type: "path", required: false, description: "Override path to normalized-brief.json" },
|
|
13
|
+
{ name: "out", type: "path", required: false, description: "Override output path" }
|
|
14
|
+
],
|
|
15
|
+
outputs: [
|
|
16
|
+
{ name: "filePath", type: "path", description: "Path to generated artifact" }
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
async execute(context, inputs): Promise<Record<string, unknown>> {
|
|
21
|
+
const cwd = (inputs.cwd as string) ?? context.cwd;
|
|
22
|
+
const filePath = await generateArtifact({
|
|
23
|
+
artifactType: inputs.artifactType as string,
|
|
24
|
+
cwd,
|
|
25
|
+
normalizedBriefOverride: inputs.from as string | undefined,
|
|
26
|
+
outPath: inputs.out as string | undefined,
|
|
27
|
+
agent: context.agent
|
|
28
|
+
});
|
|
29
|
+
context.log(`${(inputs.artifactType as string).toUpperCase()} generated: ${filePath}`);
|
|
30
|
+
return { filePath };
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { listArtifactTypes } from "../core/artifact-registry";
|
|
2
|
+
import { generateArtifact } from "../core/artifacts";
|
|
3
|
+
import { runNormalize } from "../core/normalize";
|
|
4
|
+
import { runValidate } from "../core/validate";
|
|
5
|
+
import type { Skill } from "./types";
|
|
6
|
+
|
|
7
|
+
export const generatePipelineSkill: Skill = {
|
|
8
|
+
manifest: {
|
|
9
|
+
name: "generate-pipeline",
|
|
10
|
+
description: "Run end-to-end pipeline: normalize → generate all artifacts → validate",
|
|
11
|
+
category: "core",
|
|
12
|
+
inputs: [
|
|
13
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
14
|
+
{ name: "strict", type: "boolean", required: false, description: "Treat warnings as errors" }
|
|
15
|
+
],
|
|
16
|
+
outputs: [
|
|
17
|
+
{ name: "pass", type: "string", description: "Whether validation passed" },
|
|
18
|
+
{ name: "reportPath", type: "path", description: "Path to validation report" },
|
|
19
|
+
{ name: "artifactCount", type: "string", description: "Number of artifacts generated" }
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
async execute(context, inputs): Promise<Record<string, unknown>> {
|
|
24
|
+
const cwd = (inputs.cwd as string) ?? context.cwd;
|
|
25
|
+
|
|
26
|
+
const normalizedPath = await runNormalize({ cwd });
|
|
27
|
+
context.log(`Normalized brief: ${normalizedPath}`);
|
|
28
|
+
|
|
29
|
+
const artifactTypes = await listArtifactTypes(cwd);
|
|
30
|
+
for (const type of artifactTypes) {
|
|
31
|
+
const file = await generateArtifact({
|
|
32
|
+
artifactType: type,
|
|
33
|
+
cwd,
|
|
34
|
+
normalizedBriefOverride: normalizedPath,
|
|
35
|
+
agent: context.agent
|
|
36
|
+
});
|
|
37
|
+
context.log(`${type.toUpperCase()} generated: ${file}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const result = await runValidate(cwd, { strict: Boolean(inputs.strict) });
|
|
41
|
+
context.log(`Validation ${result.pass ? "passed" : "failed"}: ${result.reportPath}`);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
pass: result.pass,
|
|
45
|
+
reportPath: result.reportPath,
|
|
46
|
+
artifactCount: artifactTypes.length
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { runNormalize } from "../core/normalize";
|
|
2
|
+
import type { Skill } from "./types";
|
|
3
|
+
|
|
4
|
+
export const normalizeSkill: Skill = {
|
|
5
|
+
manifest: {
|
|
6
|
+
name: "normalize",
|
|
7
|
+
description: "Normalize a product brief into structured JSON with contracts and confidence scores",
|
|
8
|
+
category: "core",
|
|
9
|
+
inputs: [
|
|
10
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
11
|
+
{ name: "brief", type: "path", required: false, description: "Override path to brief.md" },
|
|
12
|
+
{ name: "out", type: "path", required: false, description: "Override output path" }
|
|
13
|
+
],
|
|
14
|
+
outputs: [
|
|
15
|
+
{ name: "normalizedBriefPath", type: "path", description: "Path to normalized-brief.json" }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
async execute(context, inputs): Promise<Record<string, unknown>> {
|
|
20
|
+
const cwd = (inputs.cwd as string) ?? context.cwd;
|
|
21
|
+
const outPath = await runNormalize({
|
|
22
|
+
cwd,
|
|
23
|
+
brief: inputs.brief as string | undefined,
|
|
24
|
+
out: inputs.out as string | undefined
|
|
25
|
+
});
|
|
26
|
+
context.log(`Normalized brief written to: ${outPath}`);
|
|
27
|
+
return { normalizedBriefPath: outPath };
|
|
28
|
+
}
|
|
29
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type SkillInput = {
|
|
2
|
+
name: string;
|
|
3
|
+
type: "path" | "string" | "boolean" | "json";
|
|
4
|
+
required: boolean;
|
|
5
|
+
description: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type SkillOutput = {
|
|
9
|
+
name: string;
|
|
10
|
+
type: "path" | "string" | "json";
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type SkillManifest = {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
category: "core" | "artifact" | "validation" | "custom";
|
|
18
|
+
inputs: SkillInput[];
|
|
19
|
+
outputs: SkillOutput[];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type SkillContext = {
|
|
23
|
+
cwd: string;
|
|
24
|
+
log: (message: string) => void;
|
|
25
|
+
agent?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type SkillFunction = (
|
|
29
|
+
context: SkillContext,
|
|
30
|
+
inputs: Record<string, unknown>
|
|
31
|
+
) => Promise<Record<string, unknown>>;
|
|
32
|
+
|
|
33
|
+
export type Skill = {
|
|
34
|
+
manifest: SkillManifest;
|
|
35
|
+
execute: SkillFunction;
|
|
36
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { runValidate } from "../core/validate";
|
|
2
|
+
import type { Skill } from "./types";
|
|
3
|
+
|
|
4
|
+
export const validateSkill: Skill = {
|
|
5
|
+
manifest: {
|
|
6
|
+
name: "validate",
|
|
7
|
+
description: "Run cross-artifact validation and generate a report",
|
|
8
|
+
category: "validation",
|
|
9
|
+
inputs: [
|
|
10
|
+
{ name: "cwd", type: "path", required: true, description: "Project working directory" },
|
|
11
|
+
{ name: "strict", type: "boolean", required: false, description: "Treat warnings as errors" },
|
|
12
|
+
{ name: "report", type: "path", required: false, description: "Override report output path" }
|
|
13
|
+
],
|
|
14
|
+
outputs: [
|
|
15
|
+
{ name: "pass", type: "string", description: "Whether validation passed" },
|
|
16
|
+
{ name: "reportPath", type: "path", description: "Path to validation report" }
|
|
17
|
+
]
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
async execute(context, inputs): Promise<Record<string, unknown>> {
|
|
21
|
+
const cwd = (inputs.cwd as string) ?? context.cwd;
|
|
22
|
+
const result = await runValidate(cwd, {
|
|
23
|
+
strict: Boolean(inputs.strict),
|
|
24
|
+
report: inputs.report as string | undefined
|
|
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
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Fix failing artifacts using latest validation report and brief-aligned regeneration.
|
|
3
|
+
agent-role: "Recovery Engineer"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## User Input
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
$ARGUMENTS
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Execution Policy
|
|
13
|
+
|
|
14
|
+
- Execute-first, diagnose-second.
|
|
15
|
+
- Do not run shell commands or CLI commands from inside the agent.
|
|
16
|
+
- Never invoke `prodo-fix`, `prodo fix`, or any `prodo ...` command in shell.
|
|
17
|
+
- Input files are read-only; never modify `brief.md`.
|
|
18
|
+
- Write outputs only under `product-docs/` and `.prodo/`.
|
|
19
|
+
- Do not print full artifact bodies in chat.
|
|
20
|
+
|
|
21
|
+
## Execution
|
|
22
|
+
|
|
23
|
+
1. Minimum prerequisites only:
|
|
24
|
+
- `.prodo/` exists
|
|
25
|
+
- `brief.md` exists
|
|
26
|
+
- `.prodo/briefs/normalized-brief.json` exists (refresh if stale)
|
|
27
|
+
- Validation report exists in `product-docs/reports/`
|
|
28
|
+
|
|
29
|
+
2. Execute fix process immediately:
|
|
30
|
+
- Read latest validation report.
|
|
31
|
+
- Identify failing artifact types and regenerate only impacted chain.
|
|
32
|
+
- Use normalized brief + active templates for regeneration.
|
|
33
|
+
|
|
34
|
+
3. Verify result:
|
|
35
|
+
- Re-run validation.
|
|
36
|
+
- Confirm report status is PASS.
|
|
37
|
+
- Confirm `brief.md` remained unchanged.
|
|
38
|
+
|
|
39
|
+
4. Diagnose only on failure:
|
|
40
|
+
- Inspect internal hooks/scripts only after fix attempt fails.
|
|
41
|
+
- Return concise root cause + next repair action.
|
|
42
|
+
|
|
43
|
+
## Handoff
|
|
44
|
+
|
|
45
|
+
If pass: suggest next command `/prodo-validate`.
|
|
46
|
+
If fail: suggest highest-priority artifact command to regenerate manually.
|
|
@@ -1,31 +1,126 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: >
|
|
3
|
+
Transform product brief into normalized, standardized JSON schema for downstream artifact generation.
|
|
4
|
+
Validates structure, enriches metadata, and ensures semantic consistency across all product definitions.
|
|
5
|
+
agent-role: "Data Processor & Validator"
|
|
6
|
+
agent-profile: |
|
|
7
|
+
**Character**: Meticulous Data Architect
|
|
8
|
+
- **Personality**: Precise, methodical, quality-focused
|
|
9
|
+
- **Specialization**: Schema validation, data normalization, integrity auditing
|
|
10
|
+
- **Decision Style**: Rule-based, deterministic (no guessing)
|
|
11
|
+
- **Tolerance**: Zero tolerance for data corruption or inconsistency
|
|
12
|
+
|
|
13
|
+
agent-skills: |
|
|
14
|
+
✓ **Core Skills**:
|
|
15
|
+
- JSON schema validation & transformation
|
|
16
|
+
- Data normalization & standardization
|
|
17
|
+
- Metadata enrichment (timestamps, hashing, versioning)
|
|
18
|
+
- Deterministic output generation
|
|
19
|
+
- Integrity verification & audit trail
|
|
20
|
+
|
|
21
|
+
✓ **Performance Metrics**:
|
|
22
|
+
- Speed: Fast (one-pass processing)
|
|
23
|
+
- Accuracy: 100% deterministic
|
|
24
|
+
- Safety: Immutable input protection
|
|
25
|
+
- Reliability: No side effects
|
|
26
|
+
|
|
27
|
+
✓ **Problem-Solving Approach**:
|
|
28
|
+
- Fail-fast on validation errors
|
|
29
|
+
- Detect corruption early
|
|
30
|
+
- Auto-correct when possible
|
|
31
|
+
- Provide clear diagnostics on failure
|
|
32
|
+
|
|
33
|
+
agent-decision-strategy: |
|
|
34
|
+
**Decision Tree**:
|
|
35
|
+
1. Prerequisites valid? → Continue | Fail-fast
|
|
36
|
+
2. Input corrupted? → Report error | Auto-correct if safe
|
|
37
|
+
3. Output format invalid? → Rewrite as pure JSON | Report conversion
|
|
38
|
+
4. Integrity compromised? → Report issue with remediation | Block output
|
|
39
|
+
|
|
40
|
+
**When to Escalate**:
|
|
41
|
+
- Input file missing or unreadable → User must provide
|
|
42
|
+
- Normalization logic ambiguous → Recommend upstream clarification
|
|
43
|
+
- Multiple corruption patterns detected → Suggest expert review
|
|
44
|
+
|
|
45
|
+
agent-efficiency-tips: |
|
|
46
|
+
⚡ **For Maximum Efficiency**:
|
|
47
|
+
- Run FIRST in pipeline (all others depend on this)
|
|
48
|
+
- Cache results: normalized-brief.json rarely changes
|
|
49
|
+
- Single pass: read once, validate, write
|
|
50
|
+
- No re-processing: output is deterministic
|
|
51
|
+
- Early validation: catch brief issues immediately
|
|
3
52
|
---
|
|
4
53
|
|
|
5
|
-
##
|
|
54
|
+
## Context
|
|
55
|
+
|
|
56
|
+
**Purpose**: Convert unstructured or semi-structured product brief into a machine-readable normalized format.
|
|
57
|
+
|
|
58
|
+
**Upstream Dependencies**: `brief.md` must exist in project root.
|
|
59
|
+
|
|
60
|
+
**Downstream Impact**: All artifact generation commands (PRD, stories, techspec, workflow, wireframe) depend on normalized-brief.json for consistency.
|
|
61
|
+
|
|
62
|
+
**User Input**
|
|
6
63
|
|
|
7
64
|
```text
|
|
8
65
|
$ARGUMENTS
|
|
9
66
|
```
|
|
10
67
|
|
|
11
|
-
Execution
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
- Never
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
68
|
+
## Execution Policy
|
|
69
|
+
|
|
70
|
+
**Safety & Integrity**:
|
|
71
|
+
- Execute-first, diagnose-second (fail fast on validation errors).
|
|
72
|
+
- Do not execute shell/CLI commands from inside the agent.
|
|
73
|
+
- Never invoke `prodo-normalize`, `prodo normalize`, or `prodo ...` commands recursively in shell.
|
|
74
|
+
- **Input files are read-only**: Never modify, rewrite, or transform `brief.md`. Treat it as immutable source of truth.
|
|
75
|
+
- Never print full normalized JSON to chat; return only status + file path.
|
|
76
|
+
|
|
77
|
+
**Output Quality**:
|
|
78
|
+
- Write `.prodo/briefs/normalized-brief.json` with validated strict JSON format.
|
|
79
|
+
- Normalized output must be deterministic (same input always produces identical output).
|
|
80
|
+
- Include metadata: normalized timestamp, schema version, input hash for audit trail.
|
|
81
|
+
|
|
82
|
+
## Execution Steps
|
|
83
|
+
|
|
84
|
+
1. **Verify Minimal Prerequisites**
|
|
85
|
+
- Confirm `.prodo/` directory exists (initialized by `prodo init`).
|
|
86
|
+
- Confirm `brief.md` exists and is readable.
|
|
87
|
+
- Check no corrupt `.prodo/briefs/` state exists.
|
|
88
|
+
|
|
89
|
+
2. **Parse and Normalize `brief.md`**
|
|
90
|
+
- Read `brief.md` without modification.
|
|
91
|
+
- Extract and validate core product attributes (name, description, goals, target audience, scope, constraints).
|
|
92
|
+
- Normalize field types: trim whitespace, standardize arrays, convert dates to ISO-8601.
|
|
93
|
+
- Enrich with derived metadata (section count, complexity score, validation flags).
|
|
94
|
+
|
|
95
|
+
3. **Validate Normalized Format**
|
|
96
|
+
- Confirm `.prodo/briefs/normalized-brief.json` was created.
|
|
97
|
+
- Verify strict JSON compliance:
|
|
98
|
+
- First non-space character must be `{`.
|
|
99
|
+
- No markdown fences (no \`\`\`json or \`\`\`).
|
|
100
|
+
- File must parse successfully as a valid JSON object.
|
|
101
|
+
- No trailing commas, unquoted keys, or comments.
|
|
102
|
+
- If format is invalid, rewrite file as pure JSON object only (auto-correct).
|
|
103
|
+
|
|
104
|
+
4. **Audit & Verify Integrity**
|
|
105
|
+
- Confirm original `brief.md` was not modified (compare timestamps or file hash).
|
|
106
|
+
- Verify normalized output contains no executable code or shell injections.
|
|
107
|
+
- Log schema version and normalized metadata.
|
|
108
|
+
|
|
109
|
+
5. **Safety Constraints**
|
|
110
|
+
- Do not create manual fallback files under `.prodo/` outside expected outputs.
|
|
111
|
+
- Do not write to `.prodo/templates/`, `.prodo/config/`, or other reserved directories.
|
|
112
|
+
- Do not modify or create `.gitignore` or hidden system files.
|
|
113
|
+
|
|
114
|
+
6. **Diagnosis & Error Handling**
|
|
115
|
+
- If `brief.md` is missing: report clear error with recovery instructions.
|
|
116
|
+
- If `brief.md` syntax is invalid: report line numbers and invalid fields.
|
|
117
|
+
- If normalization fails: include schema mismatch details and sample valid structure.
|
|
118
|
+
- If `.prodo/briefs/` cannot be written: report file system permissions issue.
|
|
119
|
+
|
|
120
|
+
## Success Criteria
|
|
121
|
+
|
|
122
|
+
- ✅ `.prodo/briefs/normalized-brief.json` exists and is valid JSON.
|
|
123
|
+
- ✅ Original `brief.md` remains unchanged.
|
|
124
|
+
- ✅ Normalized file includes schema version and timestamp.
|
|
125
|
+
- ✅ All required product attributes are present and validated.
|
|
126
|
+
- ✅ Ready for downstream artifact generation.
|