@shahmarasy/prodo 0.1.6 → 0.1.7

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.
@@ -1,4 +1,4 @@
1
1
  export declare const AI_ALIASES: Record<string, "codex" | "gemini-cli" | "claude-cli">;
2
2
  export type SupportedAi = "codex" | "gemini-cli" | "claude-cli";
3
3
  export declare function resolveAi(ai?: string): SupportedAi | undefined;
4
- export declare function installAgentCommands(projectRoot: string, ai: SupportedAi): Promise<string[]>;
4
+ export declare function installAgentCommands(projectRoot: string, ai: SupportedAi, lang?: string): Promise<string[]>;
@@ -110,13 +110,119 @@ async function loadCommandTemplateNames(commandTemplatesDir) {
110
110
  .map((name) => name.replace(/\.md$/, ""))
111
111
  .sort();
112
112
  }
113
- async function installAgentCommands(projectRoot, ai) {
113
+ function generateClaudeMd(projectRoot, lang) {
114
+ const projectName = node_path_1.default.basename(projectRoot) || "Product";
115
+ return `# Prodo — Product Artifact Workspace
116
+
117
+ This project uses **Prodo** to generate product documentation from a brief.
118
+
119
+ ## Project Structure
120
+
121
+ - \`brief.md\` — Product brief (INPUT — read-only during generation)
122
+ - \`product-docs/\` — Generated artifacts (OUTPUT)
123
+ - \`.prodo/\` — Internal scaffold (templates, schemas, prompts, state)
124
+
125
+ ## Workflow
126
+
127
+ Run commands in this sequence:
128
+
129
+ 1. \`/prodo-normalize\` — Parse brief into structured JSON
130
+ 2. \`/prodo-prd\` — Generate Product Requirements Document
131
+ 3. \`/prodo-workflow\` — Generate workflow diagrams (Markdown + Mermaid)
132
+ 4. \`/prodo-wireframe\` — Generate wireframes (Markdown + HTML)
133
+ 5. \`/prodo-stories\` — Generate user stories with Gherkin scenarios
134
+ 6. \`/prodo-techspec\` — Generate technical specification
135
+ 7. \`/prodo-validate\` — Cross-artifact validation (7 gates)
136
+
137
+ ## Rules
138
+
139
+ - **Never modify \`brief.md\` during command execution** — it is read-only input
140
+ - **All artifacts must include contract tags** like \`[G1]\`, \`[F2]\`, \`[C1]\` for traceability
141
+ - **Output language is \`${lang}\`** — do not mix languages in generated content
142
+ - **Follow templates strictly** — each artifact has a template in \`.prodo/templates/\`
143
+ - **Validate after generation** — run \`/prodo-validate\` to check consistency
144
+ `;
145
+ }
146
+ function generateArtifactRules(lang) {
147
+ return `# Artifact Format Rules
148
+
149
+ ## Contract Tags
150
+ Every artifact must reference brief requirements using tags:
151
+ - \`[G1]\`, \`[G2]\` — Goal references
152
+ - \`[F1]\`, \`[F2]\` — Feature references
153
+ - \`[C1]\`, \`[C2]\` — Constraint references
154
+
155
+ Tags must appear inline where the requirement is addressed.
156
+
157
+ ## Frontmatter
158
+ Every generated artifact must include YAML frontmatter:
159
+ \`\`\`yaml
160
+ artifact_type: prd | workflow | wireframe | stories | techspec
161
+ version: <timestamp>
162
+ source_brief: <path to normalized-brief.json>
163
+ generated_at: <ISO timestamp>
164
+ status: draft
165
+ contract_coverage:
166
+ goals: [G1, G2]
167
+ core_features: [F1, F2]
168
+ constraints: [C1]
169
+ \`\`\`
170
+
171
+ ## Paired Outputs
172
+ - **Workflow**: Produces \`.md\` (narrative) + \`.mmd\` (Mermaid diagram)
173
+ - **Wireframe**: Produces \`.md\` (description) + \`.html\` (low-fidelity prototype)
174
+
175
+ ## Language
176
+ Output language: **${lang}**. Do not mix languages. Required heading names stay in English.
177
+ `;
178
+ }
179
+ function generateBriefRules() {
180
+ return `# Brief Writing Rules
181
+
182
+ ## Structure
183
+ The brief (\`brief.md\`) should contain these sections:
184
+
185
+ - **Product Name** — Clear, specific product name
186
+ - **Problem** — Core problem the product solves (be specific)
187
+ - **Audience** — Target users (list distinct personas)
188
+ - **Goals** — Measurable objectives (not vague aspirations)
189
+ - **Core Features** — One capability per bullet point
190
+ - **Constraints** — Technical, business, or regulatory limits
191
+ - **Assumptions** — Open questions or working assumptions
192
+
193
+ ## Tips
194
+ - Be specific: "Reduce checkout abandonment by 30%" not "Improve UX"
195
+ - Use consistent terminology throughout
196
+ - Each feature should be distinct and independently describable
197
+ - Constraints should be concrete: "Node.js 20+", "GDPR compliant"
198
+ `;
199
+ }
200
+ async function installAgentCommands(projectRoot, ai, lang) {
114
201
  const cfg = AGENT_CONFIG[ai];
115
202
  const target = node_path_1.default.join(projectRoot, cfg.baseDir);
116
203
  const commandTemplatesDir = node_path_1.default.join(projectRoot, ".prodo", "commands");
117
204
  const commandNames = await loadCommandTemplateNames(commandTemplatesDir);
118
205
  await (0, utils_1.ensureDir)(target);
119
206
  const written = [];
207
+ if (ai === "claude-cli") {
208
+ const claudeMdPath = node_path_1.default.join(projectRoot, "CLAUDE.md");
209
+ if (!(await (0, utils_1.fileExists)(claudeMdPath))) {
210
+ await promises_1.default.writeFile(claudeMdPath, generateClaudeMd(projectRoot, lang ?? "en"), "utf8");
211
+ written.push(claudeMdPath);
212
+ }
213
+ const rulesDir = node_path_1.default.join(projectRoot, ".claude", "rules");
214
+ await (0, utils_1.ensureDir)(rulesDir);
215
+ const artifactRulesPath = node_path_1.default.join(rulesDir, "artifact-format.md");
216
+ if (!(await (0, utils_1.fileExists)(artifactRulesPath))) {
217
+ await promises_1.default.writeFile(artifactRulesPath, generateArtifactRules(lang ?? "en"), "utf8");
218
+ written.push(artifactRulesPath);
219
+ }
220
+ const briefRulesPath = node_path_1.default.join(rulesDir, "brief-rules.md");
221
+ if (!(await (0, utils_1.fileExists)(briefRulesPath))) {
222
+ await promises_1.default.writeFile(briefRulesPath, generateBriefRules(), "utf8");
223
+ written.push(briefRulesPath);
224
+ }
225
+ }
120
226
  for (const commandName of commandNames) {
121
227
  const templatePath = node_path_1.default.join(commandTemplatesDir, `${commandName}.md`);
122
228
  if (!(await (0, utils_1.fileExists)(templatePath))) {
package/dist/cli/init.js CHANGED
@@ -312,7 +312,7 @@ async function runInit(cwd, options) {
312
312
  await rollbackFiles(backup);
313
313
  throw error;
314
314
  }
315
- const installedAgentFiles = options?.ai ? await (0, agent_command_installer_1.installAgentCommands)(cwd, options.ai) : [];
315
+ const installedAgentFiles = options?.ai ? await (0, agent_command_installer_1.installAgentCommands)(cwd, options.ai, options?.lang) : [];
316
316
  const manifest = {
317
317
  schema_version: "1.0",
318
318
  generated_at: new Date().toISOString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shahmarasy/prodo",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
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",
@@ -122,7 +122,97 @@ async function loadCommandTemplateNames(commandTemplatesDir: string): Promise<st
122
122
  .sort();
123
123
  }
124
124
 
125
- export async function installAgentCommands(projectRoot: string, ai: SupportedAi): Promise<string[]> {
125
+ function generateClaudeMd(projectRoot: string, lang: string): string {
126
+ const projectName = path.basename(projectRoot) || "Product";
127
+ return `# Prodo — Product Artifact Workspace
128
+
129
+ This project uses **Prodo** to generate product documentation from a brief.
130
+
131
+ ## Project Structure
132
+
133
+ - \`brief.md\` — Product brief (INPUT — read-only during generation)
134
+ - \`product-docs/\` — Generated artifacts (OUTPUT)
135
+ - \`.prodo/\` — Internal scaffold (templates, schemas, prompts, state)
136
+
137
+ ## Workflow
138
+
139
+ Run commands in this sequence:
140
+
141
+ 1. \`/prodo-normalize\` — Parse brief into structured JSON
142
+ 2. \`/prodo-prd\` — Generate Product Requirements Document
143
+ 3. \`/prodo-workflow\` — Generate workflow diagrams (Markdown + Mermaid)
144
+ 4. \`/prodo-wireframe\` — Generate wireframes (Markdown + HTML)
145
+ 5. \`/prodo-stories\` — Generate user stories with Gherkin scenarios
146
+ 6. \`/prodo-techspec\` — Generate technical specification
147
+ 7. \`/prodo-validate\` — Cross-artifact validation (7 gates)
148
+
149
+ ## Rules
150
+
151
+ - **Never modify \`brief.md\` during command execution** — it is read-only input
152
+ - **All artifacts must include contract tags** like \`[G1]\`, \`[F2]\`, \`[C1]\` for traceability
153
+ - **Output language is \`${lang}\`** — do not mix languages in generated content
154
+ - **Follow templates strictly** — each artifact has a template in \`.prodo/templates/\`
155
+ - **Validate after generation** — run \`/prodo-validate\` to check consistency
156
+ `;
157
+ }
158
+
159
+ function generateArtifactRules(lang: string): string {
160
+ return `# Artifact Format Rules
161
+
162
+ ## Contract Tags
163
+ Every artifact must reference brief requirements using tags:
164
+ - \`[G1]\`, \`[G2]\` — Goal references
165
+ - \`[F1]\`, \`[F2]\` — Feature references
166
+ - \`[C1]\`, \`[C2]\` — Constraint references
167
+
168
+ Tags must appear inline where the requirement is addressed.
169
+
170
+ ## Frontmatter
171
+ Every generated artifact must include YAML frontmatter:
172
+ \`\`\`yaml
173
+ artifact_type: prd | workflow | wireframe | stories | techspec
174
+ version: <timestamp>
175
+ source_brief: <path to normalized-brief.json>
176
+ generated_at: <ISO timestamp>
177
+ status: draft
178
+ contract_coverage:
179
+ goals: [G1, G2]
180
+ core_features: [F1, F2]
181
+ constraints: [C1]
182
+ \`\`\`
183
+
184
+ ## Paired Outputs
185
+ - **Workflow**: Produces \`.md\` (narrative) + \`.mmd\` (Mermaid diagram)
186
+ - **Wireframe**: Produces \`.md\` (description) + \`.html\` (low-fidelity prototype)
187
+
188
+ ## Language
189
+ Output language: **${lang}**. Do not mix languages. Required heading names stay in English.
190
+ `;
191
+ }
192
+
193
+ function generateBriefRules(): string {
194
+ return `# Brief Writing Rules
195
+
196
+ ## Structure
197
+ The brief (\`brief.md\`) should contain these sections:
198
+
199
+ - **Product Name** — Clear, specific product name
200
+ - **Problem** — Core problem the product solves (be specific)
201
+ - **Audience** — Target users (list distinct personas)
202
+ - **Goals** — Measurable objectives (not vague aspirations)
203
+ - **Core Features** — One capability per bullet point
204
+ - **Constraints** — Technical, business, or regulatory limits
205
+ - **Assumptions** — Open questions or working assumptions
206
+
207
+ ## Tips
208
+ - Be specific: "Reduce checkout abandonment by 30%" not "Improve UX"
209
+ - Use consistent terminology throughout
210
+ - Each feature should be distinct and independently describable
211
+ - Constraints should be concrete: "Node.js 20+", "GDPR compliant"
212
+ `;
213
+ }
214
+
215
+ export async function installAgentCommands(projectRoot: string, ai: SupportedAi, lang?: string): Promise<string[]> {
126
216
  const cfg = AGENT_CONFIG[ai];
127
217
  const target = path.join(projectRoot, cfg.baseDir);
128
218
  const commandTemplatesDir = path.join(projectRoot, ".prodo", "commands");
@@ -130,6 +220,30 @@ export async function installAgentCommands(projectRoot: string, ai: SupportedAi)
130
220
  await ensureDir(target);
131
221
 
132
222
  const written: string[] = [];
223
+
224
+ if (ai === "claude-cli") {
225
+ const claudeMdPath = path.join(projectRoot, "CLAUDE.md");
226
+ if (!(await fileExists(claudeMdPath))) {
227
+ await fs.writeFile(claudeMdPath, generateClaudeMd(projectRoot, lang ?? "en"), "utf8");
228
+ written.push(claudeMdPath);
229
+ }
230
+
231
+ const rulesDir = path.join(projectRoot, ".claude", "rules");
232
+ await ensureDir(rulesDir);
233
+
234
+ const artifactRulesPath = path.join(rulesDir, "artifact-format.md");
235
+ if (!(await fileExists(artifactRulesPath))) {
236
+ await fs.writeFile(artifactRulesPath, generateArtifactRules(lang ?? "en"), "utf8");
237
+ written.push(artifactRulesPath);
238
+ }
239
+
240
+ const briefRulesPath = path.join(rulesDir, "brief-rules.md");
241
+ if (!(await fileExists(briefRulesPath))) {
242
+ await fs.writeFile(briefRulesPath, generateBriefRules(), "utf8");
243
+ written.push(briefRulesPath);
244
+ }
245
+ }
246
+
133
247
  for (const commandName of commandNames) {
134
248
  const templatePath = path.join(commandTemplatesDir, `${commandName}.md`);
135
249
  if (!(await fileExists(templatePath))) {
package/src/cli/init.ts CHANGED
@@ -376,7 +376,7 @@ export async function runInit(
376
376
  throw error;
377
377
  }
378
378
 
379
- const installedAgentFiles = options?.ai ? await installAgentCommands(cwd, options.ai) : [];
379
+ const installedAgentFiles = options?.ai ? await installAgentCommands(cwd, options.ai, options?.lang) : [];
380
380
  const manifest: ScaffoldManifest = {
381
381
  schema_version: "1.0",
382
382
  generated_at: new Date().toISOString(),