@shahmarasy/prodo 0.1.5 → 0.1.6

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 (67) hide show
  1. package/dist/agents/system-prompts.js +12 -12
  2. package/dist/cli/agent-command-installer.js +18 -18
  3. package/dist/cli/doctor.js +2 -2
  4. package/dist/cli/index.js +32 -30
  5. package/dist/cli/init-tui.d.ts +2 -2
  6. package/dist/cli/init-tui.js +43 -36
  7. package/dist/cli/init.d.ts +1 -0
  8. package/dist/cli/init.js +2 -1
  9. package/dist/core/artifacts.js +72 -72
  10. package/dist/core/settings.d.ts +1 -0
  11. package/dist/core/settings.js +10 -2
  12. package/dist/core/templates.js +248 -248
  13. package/dist/i18n/en.json +45 -45
  14. package/dist/i18n/tr.json +45 -45
  15. package/dist/providers/mock-provider.js +5 -5
  16. package/dist/providers/openai-provider.js +12 -12
  17. package/dist/skill-engine/context.d.ts +7 -0
  18. package/dist/skill-engine/context.js +76 -0
  19. package/dist/skill-engine/discovery.d.ts +2 -0
  20. package/dist/skill-engine/discovery.js +52 -0
  21. package/dist/skill-engine/graph.d.ts +4 -0
  22. package/dist/skill-engine/graph.js +114 -0
  23. package/dist/skill-engine/index.d.ts +11 -0
  24. package/dist/skill-engine/index.js +49 -0
  25. package/dist/skill-engine/pipeline.d.ts +9 -0
  26. package/dist/skill-engine/pipeline.js +84 -0
  27. package/dist/skill-engine/registry.d.ts +12 -0
  28. package/dist/skill-engine/registry.js +74 -0
  29. package/dist/skill-engine/types.d.ts +66 -0
  30. package/dist/skill-engine/types.js +2 -0
  31. package/dist/skill-engine/validator.d.ts +4 -0
  32. package/dist/skill-engine/validator.js +90 -0
  33. package/dist/skills/fix.d.ts +2 -0
  34. package/dist/skills/fix.js +41 -0
  35. package/dist/skills/generate-artifact.d.ts +2 -0
  36. package/dist/skills/generate-artifact.js +42 -0
  37. package/dist/skills/normalize.d.ts +2 -0
  38. package/dist/skills/normalize.js +29 -0
  39. package/dist/skills/register-core.d.ts +2 -0
  40. package/dist/skills/register-core.js +21 -0
  41. package/dist/skills/validate.d.ts +2 -0
  42. package/dist/skills/validate.js +37 -0
  43. package/package.json +4 -6
  44. package/src/cli/doctor.ts +2 -2
  45. package/src/cli/index.ts +35 -31
  46. package/src/cli/init-tui.ts +220 -208
  47. package/src/cli/init.ts +3 -2
  48. package/src/core/settings.ts +41 -35
  49. package/src/skill-engine/context.ts +90 -0
  50. package/src/skill-engine/discovery.ts +57 -0
  51. package/src/skill-engine/graph.ts +136 -0
  52. package/src/skill-engine/index.ts +55 -0
  53. package/src/skill-engine/pipeline.ts +112 -0
  54. package/src/skill-engine/registry.ts +75 -0
  55. package/src/skill-engine/types.ts +81 -0
  56. package/src/skill-engine/validator.ts +135 -0
  57. package/src/skills/fix.ts +45 -0
  58. package/src/skills/generate-artifact.ts +48 -0
  59. package/src/skills/{normalize-skill.ts → normalize.ts} +15 -12
  60. package/src/skills/register-core.ts +27 -0
  61. package/src/skills/validate.ts +40 -0
  62. package/src/skills/engine.ts +0 -94
  63. package/src/skills/fix-skill.ts +0 -38
  64. package/src/skills/generate-artifact-skill.ts +0 -32
  65. package/src/skills/generate-pipeline-skill.ts +0 -49
  66. package/src/skills/types.ts +0 -36
  67. package/src/skills/validate-skill.ts +0 -29
@@ -0,0 +1,66 @@
1
+ import type { ValidationIssue } from "../core/types";
2
+ export type SkillInputType = "string" | "path" | "boolean" | "json" | "number";
3
+ export type SkillInput = {
4
+ name: string;
5
+ type: SkillInputType;
6
+ required: boolean;
7
+ description?: string;
8
+ default?: unknown;
9
+ };
10
+ export type SkillOutput = {
11
+ name: string;
12
+ type: SkillInputType;
13
+ description?: string;
14
+ };
15
+ export type SkillManifest = {
16
+ name: string;
17
+ version: string;
18
+ description: string;
19
+ category: "core" | "artifact" | "validation" | "custom";
20
+ depends_on: string[];
21
+ inputs: SkillInput[];
22
+ outputs: SkillOutput[];
23
+ tags?: string[];
24
+ };
25
+ export type PipelineState = {
26
+ cwd: string;
27
+ normalizedBriefPath?: string;
28
+ generatedArtifacts: Map<string, string>;
29
+ validationResult?: {
30
+ pass: boolean;
31
+ reportPath: string;
32
+ issues: ValidationIssue[];
33
+ };
34
+ custom: Record<string, unknown>;
35
+ startedAt: string;
36
+ completedSkills: string[];
37
+ };
38
+ export type ProgressCallback = (step: number, total: number, message: string) => void;
39
+ export type SkillContext = {
40
+ state: PipelineState;
41
+ progress: ProgressCallback;
42
+ log: (message: string) => void;
43
+ agent?: string;
44
+ };
45
+ export type SkillExecuteFn = (context: SkillContext, inputs: Record<string, unknown>) => Promise<Record<string, unknown>>;
46
+ export type Skill = {
47
+ manifest: SkillManifest;
48
+ execute: SkillExecuteFn;
49
+ };
50
+ export type SkillError = {
51
+ skillName: string;
52
+ phase: "input_validation" | "execution" | "output_validation";
53
+ message: string;
54
+ inputContext?: Record<string, unknown>;
55
+ stack?: string;
56
+ recoveryHints: string[];
57
+ };
58
+ export type ExecutionTier = {
59
+ tier: number;
60
+ skills: string[];
61
+ };
62
+ export type PipelineOptions = {
63
+ log?: (message: string) => void;
64
+ progress?: ProgressCallback;
65
+ agent?: string;
66
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import type { SkillError, SkillManifest } from "./types";
2
+ export declare function validateInputs(manifest: SkillManifest, inputs: Record<string, unknown>): SkillError | null;
3
+ export declare function validateInputPaths(manifest: SkillManifest, inputs: Record<string, unknown>): Promise<SkillError | null>;
4
+ export declare function validateOutputs(manifest: SkillManifest, outputs: Record<string, unknown>): SkillError | null;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateInputs = validateInputs;
4
+ exports.validateInputPaths = validateInputPaths;
5
+ exports.validateOutputs = validateOutputs;
6
+ const utils_1 = require("../core/utils");
7
+ function makeError(skillName, phase, message, hints = []) {
8
+ return {
9
+ skillName,
10
+ phase,
11
+ message,
12
+ recoveryHints: hints
13
+ };
14
+ }
15
+ function checkType(value, expectedType, fieldName) {
16
+ switch (expectedType) {
17
+ case "string":
18
+ if (typeof value !== "string")
19
+ return `"${fieldName}" must be a string, got ${typeof value}`;
20
+ return null;
21
+ case "path":
22
+ if (typeof value !== "string")
23
+ return `"${fieldName}" must be a path (string), got ${typeof value}`;
24
+ return null;
25
+ case "boolean":
26
+ if (typeof value !== "boolean")
27
+ return `"${fieldName}" must be a boolean, got ${typeof value}`;
28
+ return null;
29
+ case "number":
30
+ if (typeof value !== "number" || !Number.isFinite(value)) {
31
+ return `"${fieldName}" must be a finite number, got ${typeof value}`;
32
+ }
33
+ return null;
34
+ case "json":
35
+ if (typeof value === "string") {
36
+ try {
37
+ JSON.parse(value);
38
+ }
39
+ catch {
40
+ return `"${fieldName}" must be valid JSON string`;
41
+ }
42
+ }
43
+ return null;
44
+ default:
45
+ return null;
46
+ }
47
+ }
48
+ function validateInputs(manifest, inputs) {
49
+ for (const input of manifest.inputs) {
50
+ const value = inputs[input.name];
51
+ if (input.required && (value === undefined || value === null)) {
52
+ if (input.default !== undefined)
53
+ continue;
54
+ return makeError(manifest.name, "input_validation", `Required input "${input.name}" is missing`, [`Provide "${input.name}" (${input.type}): ${input.description ?? ""}`]);
55
+ }
56
+ if (value === undefined || value === null)
57
+ continue;
58
+ const typeError = checkType(value, input.type, input.name);
59
+ if (typeError) {
60
+ return makeError(manifest.name, "input_validation", typeError, [`Expected type: ${input.type}`]);
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+ async function validateInputPaths(manifest, inputs) {
66
+ for (const input of manifest.inputs) {
67
+ if (input.type !== "path")
68
+ continue;
69
+ const value = inputs[input.name];
70
+ if (typeof value !== "string")
71
+ continue;
72
+ if (input.required && !(await (0, utils_1.fileExists)(value))) {
73
+ return makeError(manifest.name, "input_validation", `Path "${input.name}" does not exist: ${value}`, [`Ensure the file or directory exists: ${value}`]);
74
+ }
75
+ }
76
+ return null;
77
+ }
78
+ function validateOutputs(manifest, outputs) {
79
+ for (const output of manifest.outputs) {
80
+ const value = outputs[output.name];
81
+ if (value === undefined || value === null) {
82
+ return makeError(manifest.name, "output_validation", `Expected output "${output.name}" was not produced`, [`Skill "${manifest.name}" should return "${output.name}" (${output.type})`]);
83
+ }
84
+ const typeError = checkType(value, output.type, output.name);
85
+ if (typeError) {
86
+ return makeError(manifest.name, "output_validation", typeError, [`Skill "${manifest.name}" returned wrong type for "${output.name}"`]);
87
+ }
88
+ }
89
+ return null;
90
+ }
@@ -0,0 +1,2 @@
1
+ import type { Skill } from "../skill-engine/types";
2
+ export declare const fixSkill: Skill;
@@ -0,0 +1,41 @@
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
+ version: "2.0.0",
9
+ description: "Auto-regenerate failing artifacts with backup, proposal, and validation",
10
+ category: "validation",
11
+ depends_on: [],
12
+ inputs: [
13
+ { name: "cwd", type: "path", required: true, description: "Project working directory" }
14
+ ],
15
+ outputs: [
16
+ { name: "validationResult", type: "json", description: "Final validation result after fix" }
17
+ ],
18
+ tags: ["fix", "repair", "validation"]
19
+ },
20
+ async execute(context, inputs) {
21
+ const cwd = inputs.cwd ?? context.state.cwd;
22
+ context.progress(1, 3, "Running fix pipeline...");
23
+ const result = await (0, fix_1.runFix)({
24
+ cwd,
25
+ agent: context.agent,
26
+ log: context.log
27
+ });
28
+ context.progress(3, 3, result.finalPass ? "Fix complete." : "Fix applied, issues remain.");
29
+ context.state.validationResult = result.finalPass
30
+ ? { pass: true, reportPath: result.reportPath, issues: [] }
31
+ : undefined;
32
+ return {
33
+ validationResult: {
34
+ pass: result.finalPass,
35
+ reportPath: result.reportPath,
36
+ applied: result.applied,
37
+ targetCount: result.proposal.targets.length
38
+ }
39
+ };
40
+ }
41
+ };
@@ -0,0 +1,2 @@
1
+ import type { Skill } from "../skill-engine/types";
2
+ export declare function createArtifactSkill(artifactType: string, upstream?: string[]): Skill;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createArtifactSkill = createArtifactSkill;
4
+ const artifacts_1 = require("../core/artifacts");
5
+ const constants_1 = require("../core/constants");
6
+ function createArtifactSkill(artifactType, upstream) {
7
+ const resolvedUpstream = upstream ?? (0, constants_1.defaultUpstreamByArtifact)(artifactType);
8
+ const depends_on = ["normalize", ...resolvedUpstream];
9
+ const manifest = {
10
+ name: artifactType,
11
+ version: "2.0.0",
12
+ description: `Generate ${artifactType} artifact from normalized brief`,
13
+ category: "artifact",
14
+ depends_on,
15
+ inputs: [
16
+ { name: "cwd", type: "path", required: true, description: "Project working directory" },
17
+ { name: "normalizedBriefPath", type: "path", required: false, description: "Path to normalized brief" }
18
+ ],
19
+ outputs: [
20
+ { name: "artifactPath", type: "path", description: `Path to generated ${artifactType}` }
21
+ ],
22
+ tags: ["artifact", artifactType]
23
+ };
24
+ return {
25
+ manifest,
26
+ async execute(context, inputs) {
27
+ const cwd = inputs.cwd ?? context.state.cwd;
28
+ const normalizedBriefOverride = inputs.normalizedBriefPath ?? context.state.normalizedBriefPath;
29
+ context.progress(1, 2, `Generating ${artifactType}...`);
30
+ const filePath = await (0, artifacts_1.generateArtifact)({
31
+ artifactType,
32
+ cwd,
33
+ normalizedBriefOverride,
34
+ agent: context.agent
35
+ });
36
+ context.progress(2, 2, `${artifactType} generated.`);
37
+ context.log(`${artifactType.toUpperCase()} generated: ${filePath}`);
38
+ context.state.generatedArtifacts.set(artifactType, filePath);
39
+ return { artifactPath: filePath };
40
+ }
41
+ };
42
+ }
@@ -0,0 +1,2 @@
1
+ import type { Skill } from "../skill-engine/types";
2
+ export declare const normalizeSkill: Skill;
@@ -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
+ version: "2.0.0",
9
+ description: "Normalize a product brief into structured JSON with contracts and confidence scores",
10
+ category: "core",
11
+ depends_on: [],
12
+ inputs: [
13
+ { name: "cwd", type: "path", required: true, description: "Project working directory" }
14
+ ],
15
+ outputs: [
16
+ { name: "normalizedBriefPath", type: "path", description: "Path to normalized-brief.json" }
17
+ ],
18
+ tags: ["brief", "normalization"]
19
+ },
20
+ async execute(context, inputs) {
21
+ const cwd = inputs.cwd ?? context.state.cwd;
22
+ context.progress(1, 2, "Normalizing brief...");
23
+ const outPath = await (0, normalize_1.runNormalize)({ cwd });
24
+ context.progress(2, 2, "Brief normalized.");
25
+ context.log(`Normalized brief written to: ${outPath}`);
26
+ context.state.normalizedBriefPath = outPath;
27
+ return { normalizedBriefPath: outPath };
28
+ }
29
+ };
@@ -0,0 +1,2 @@
1
+ import type { SkillRegistry } from "../skill-engine/registry";
2
+ export declare function registerCoreSkills(registry: SkillRegistry, cwd: string): Promise<void>;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerCoreSkills = registerCoreSkills;
4
+ const artifact_registry_1 = require("../core/artifact-registry");
5
+ const generate_artifact_1 = require("./generate-artifact");
6
+ const fix_1 = require("./fix");
7
+ const normalize_1 = require("./normalize");
8
+ const validate_1 = require("./validate");
9
+ async function registerCoreSkills(registry, cwd) {
10
+ registry.register(normalize_1.normalizeSkill);
11
+ const definitions = await (0, artifact_registry_1.listArtifactDefinitions)(cwd);
12
+ const artifactNames = [];
13
+ for (const def of definitions) {
14
+ const skill = (0, generate_artifact_1.createArtifactSkill)(def.name, def.upstream);
15
+ registry.register(skill);
16
+ artifactNames.push(def.name);
17
+ }
18
+ const validateSkill = (0, validate_1.createValidateSkill)(artifactNames);
19
+ registry.register(validateSkill);
20
+ registry.register(fix_1.fixSkill);
21
+ }
@@ -0,0 +1,2 @@
1
+ import type { Skill } from "../skill-engine/types";
2
+ export declare function createValidateSkill(artifactTypes: string[]): Skill;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createValidateSkill = createValidateSkill;
4
+ const validate_1 = require("../core/validate");
5
+ function createValidateSkill(artifactTypes) {
6
+ return {
7
+ manifest: {
8
+ name: "validate",
9
+ version: "2.0.0",
10
+ description: "Run 7-gate cross-artifact validation and generate report",
11
+ category: "validation",
12
+ depends_on: [...artifactTypes],
13
+ inputs: [
14
+ { name: "cwd", type: "path", required: true, description: "Project working directory" }
15
+ ],
16
+ outputs: [
17
+ { name: "validationResult", type: "json", description: "Validation result with pass/fail and issues" }
18
+ ],
19
+ tags: ["validation", "consistency"]
20
+ },
21
+ async execute(context, inputs) {
22
+ const cwd = inputs.cwd ?? context.state.cwd;
23
+ context.progress(1, 2, "Validating artifacts...");
24
+ const result = await (0, validate_1.runValidate)(cwd, {});
25
+ context.progress(2, 2, `Validation ${result.pass ? "passed" : "failed"}.`);
26
+ context.log(`Validation ${result.pass ? "passed" : "failed"}: ${result.reportPath}`);
27
+ context.state.validationResult = result;
28
+ return {
29
+ validationResult: {
30
+ pass: result.pass,
31
+ reportPath: result.reportPath,
32
+ issueCount: result.issues.length
33
+ }
34
+ };
35
+ }
36
+ };
37
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shahmarasy/prodo",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "CLI-first, prompt-powered product artifact kit",
5
5
  "main": "dist/cli/index.js",
6
6
  "types": "dist/cli/index.d.ts",
@@ -22,11 +22,9 @@
22
22
  "node": ">=20"
23
23
  },
24
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"
25
+ "build": "node scripts/build.cjs",
26
+ "test": "node scripts/test.cjs",
27
+ "verify:release": "node scripts/build.cjs"
30
28
  },
31
29
  "keywords": [
32
30
  "product-management",
package/src/cli/doctor.ts CHANGED
@@ -137,8 +137,8 @@ export async function runDoctor(cwd: string, out: (line: string) => void): Promi
137
137
  out("");
138
138
  out(renderLogo(width));
139
139
  out("");
140
- out(center(color("Prodo — Product Artifact Toolkit", "\u001B[1;37m"), width));
141
- out(center(color("Crafted by Codex, guided by Shahmarasy intelligence", "\u001B[2;37m"), width));
140
+ out(center(color("Prodo — AI-Powered Product Owner", "\u001B[1;37m"), width));
141
+ out(center(color("Built by Shahmarasy · Works with Claude, Codex, and Gemini", "\u001B[2;37m"), width));
142
142
  out("");
143
143
  out("Checking environment...");
144
144
  out("");
package/src/cli/index.ts CHANGED
@@ -120,7 +120,7 @@ export async function runCli(options: RunOptions = {}): Promise<number> {
120
120
 
121
121
  program
122
122
  .command("init [target]")
123
- .option("--ai <name>", "agent integration: codex | gemini-cli | claude-cli")
123
+ .option("--ai <name>", "agent: codex | gemini-cli | claude-cli")
124
124
  .option("--lang <code>", "document language (e.g. en, tr)")
125
125
  .option("--author <name>", "document author name")
126
126
  .option("--preset <name>", "preset to install during initialization")
@@ -165,15 +165,14 @@ export async function runCli(options: RunOptions = {}): Promise<number> {
165
165
  });
166
166
  out(`Initialized Prodo scaffold at ${path.join(projectRoot, ".prodo")}`);
167
167
  if (selectedAi) {
168
- out(`Agent command set installed for ${selectedAi}.`);
168
+ const label = selectedAi === "claude-cli" ? "Claude Code"
169
+ : selectedAi === "codex" ? "Codex" : "Gemini CLI";
170
+ out(`Agent commands installed for ${label}.`);
169
171
  out(`Installed ${result.installedAgentFiles.length} command files.`);
170
- out("Agent workflow: edit brief.md, then run slash commands in your agent.");
172
+ out(`Next: edit brief.md, open in ${label}, run /prodo-normalize`);
171
173
  } else {
172
- out("No agent selected. Use `prodo generate` for end-to-end generation.");
174
+ out("Next: edit brief.md, then run `prodo generate`.");
173
175
  }
174
- out(`Settings file: ${result.settingsPath}`);
175
- out(`Author: ${selected.author}`);
176
- out("Next: edit brief.md.");
177
176
  });
178
177
 
179
178
  program
@@ -196,28 +195,30 @@ export async function runCli(options: RunOptions = {}): Promise<number> {
196
195
  return;
197
196
  }
198
197
  await withBriefReadOnlyGuard(cwd, async () => {
199
- await runHookPhase(cwd, "before_normalize", out);
200
- const normalizedPath = await runNormalize({ cwd });
201
- out(`Normalized brief written to: ${normalizedPath}`);
202
- await runHookPhase(cwd, "after_normalize", out);
198
+ const { createEngine, createPipelineState } = await import("../skill-engine");
199
+ const engine = await createEngine(cwd, out);
200
+ const state = createPipelineState(cwd);
201
+ const pipelineSkills = ["normalize", ...artifactTypes, "validate"];
203
202
 
204
- for (const type of artifactTypes) {
205
- await runArtifactCommand(type, { from: normalizedPath, agent: opts.agent }, cwd, out, {
206
- suggestValidate: false
207
- });
208
- }
203
+ await runHookPhase(cwd, "before_normalize", out);
209
204
 
210
- await runHookPhase(cwd, "before_validate", out);
211
- const result = await runValidate(cwd, {
212
- strict: Boolean(opts.strict),
213
- report: opts.report
205
+ const finalState = await engine.runPipeline(pipelineSkills, state, {
206
+ log: (msg) => {
207
+ out(msg);
208
+ },
209
+ agent: opts.agent
214
210
  });
215
- out(`Validation report written to: ${result.reportPath}`);
216
- if (!result.pass) {
211
+
212
+ await runHookPhase(cwd, "after_validate", out);
213
+
214
+ if (finalState.validationResult && !finalState.validationResult.pass) {
215
+ out(`Validation report written to: ${finalState.validationResult.reportPath}`);
217
216
  throw new UserError("Validation failed. Review report and fix issues.");
218
217
  }
218
+ if (finalState.validationResult) {
219
+ out(`Validation report written to: ${finalState.validationResult.reportPath}`);
220
+ }
219
221
  out("Generation pipeline completed. Validation passed.");
220
- await runHookPhase(cwd, "after_validate", out);
221
222
  });
222
223
  });
223
224
 
@@ -388,35 +389,38 @@ export async function runCli(options: RunOptions = {}): Promise<number> {
388
389
  });
389
390
 
390
391
  program
391
- .command("skills", { hidden: true })
392
- .description("Advanced: manage and run skills")
392
+ .command("skills")
393
+ .description("Manage and run skills")
393
394
  .argument("[action]", "list or run", "list")
394
395
  .argument("[name]", "skill name (for run)")
395
396
  .option("--input <json>", "JSON input for skill execution")
396
397
  .action(async (action: string, name: string | undefined, opts: { input?: string }) => {
397
- const { getGlobalSkillEngine } = await import("../skills/engine");
398
- const engine = getGlobalSkillEngine();
398
+ const { createEngine, createHydratedState } = await import("../skill-engine");
399
+ const engine = await createEngine(cwd, out);
400
+ const registry = engine.getRegistry();
399
401
 
400
402
  if (action === "list") {
401
- const manifests = engine.listSkills();
403
+ const manifests = registry.listManifests();
402
404
  if (manifests.length === 0) {
403
405
  out("No skills registered.");
404
406
  return;
405
407
  }
406
408
  out("Available skills:\n");
407
409
  for (const m of manifests) {
408
- out(` ${m.name.padEnd(25)} [${m.category}] ${m.description}`);
410
+ const deps = m.depends_on.length > 0 ? ` (deps: ${m.depends_on.join(", ")})` : "";
411
+ out(` ${m.name.padEnd(25)} [${m.category}] v${m.version} ${m.description}${deps}`);
409
412
  }
410
413
  return;
411
414
  }
412
415
 
413
416
  if (action === "run") {
414
417
  if (!name) throw new UserError("Skill name is required. Usage: prodo skills run <name>");
418
+ const state = await createHydratedState(cwd);
415
419
  const inputs = opts.input ? JSON.parse(opts.input) as Record<string, unknown> : {};
416
420
  inputs.cwd = inputs.cwd ?? cwd;
417
- const result = await engine.execute(name, { cwd, log: out }, inputs);
421
+ const result = await engine.runSkill(name, state, { log: out });
418
422
  out(`\nSkill "${name}" completed.`);
419
- out(JSON.stringify(result, null, 2));
423
+ out(`Completed skills: ${result.completedSkills.join(" ")}`);
420
424
  return;
421
425
  }
422
426