@dezkareid/osddt 0.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,2 +1,40 @@
1
1
  # osddt
2
- Other spec drivent development tool but for monorepo
2
+ Other spec driven development tool but for monorepo
3
+
4
+ ## CLI Commands
5
+
6
+ | Command | Description |
7
+ | ------------------------------ | ------------------------------------------------------------- |
8
+ | `@dezkareid/osddt setup` | Generate agent command files for Claude and Gemini |
9
+ | `@dezkareid/osddt meta-info` | Output current branch and date as JSON |
10
+ | `@dezkareid/osddt done <feature-name>` | Move `working-on/<feature>` to `done/<feature>` |
11
+
12
+ ## Command Templates
13
+
14
+ Run `npx @dezkareid/osddt setup` once to generate the agent command files.
15
+
16
+ `osddt.research` and `osddt.start` are **peer entry points** — use whichever fits your situation. Both lead to `osddt.spec`. Use `osddt.continue` to resume an in-progress feature from a new session.
17
+
18
+ ```
19
+ osddt.continue ──────────────────────────────────────────────────────────────────────────────┐
20
+
21
+ osddt.research ──┐ │
22
+ ├──► osddt.spec → osddt.plan → osddt.tasks → osddt.implement → osddt.done ◄─┘
23
+ osddt.start ──┘
24
+ ```
25
+
26
+ | Template | Description |
27
+ | ------------------ | ------------------------------------------------------------------ |
28
+ | `osddt.continue` | Detect the current workflow phase and prompt the next command |
29
+ | `osddt.research` | Research a topic and write a research file to inform the spec |
30
+ | `osddt.start` | Start a new feature by creating a branch and working-on folder |
31
+ | `osddt.spec` | Analyze requirements and write a feature specification |
32
+ | `osddt.plan` | Create a technical implementation plan from a specification |
33
+ | `osddt.tasks` | Generate actionable tasks from an implementation plan |
34
+ | `osddt.implement` | Execute tasks from the task list one by one |
35
+ | `osddt.done` | Mark a feature as done and move it from working-on to done |
36
+
37
+ Generated files are placed in:
38
+
39
+ - `.claude/commands/osddt.<name>.md` (Claude Code)
40
+ - `.gemini/commands/osddt.<name>.toml` (Gemini CLI)
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function doneCommand(): Command;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function metaInfoCommand(): Command;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function setupCommand(): Command;
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,533 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import path from 'path';
4
+ import fs from 'fs-extra';
5
+ import select from '@inquirer/select';
6
+ import checkbox from '@inquirer/checkbox';
7
+ import { execSync } from 'child_process';
8
+
9
+ const REPO_PREAMBLE = `## Context
10
+
11
+ Before proceeding, run the following command and parse the JSON output to get the current branch and date:
12
+
13
+ \`\`\`
14
+ npx @dezkareid/osddt meta-info
15
+ \`\`\`
16
+
17
+ ## Repository Configuration
18
+
19
+ Before proceeding, read the \`.osddtrc\` file in the root of the repository to determine the project path.
20
+
21
+ \`\`\`json
22
+ // .osddtrc example
23
+ { "repoType": "monorepo" | "single" }
24
+ \`\`\`
25
+
26
+ - If \`repoType\` is \`"single"\`: the project path is the repository root.
27
+ - If \`repoType\` is \`"monorepo"\`: ask the user which package to work on (e.g. \`packages/my-package\`), then use \`<repo-root>/<package>\` as the project path.
28
+
29
+ ## Working Directory
30
+
31
+ All generated files live under \`<project-path>/working-on/<feature-name>/\`. The \`<feature-name>\` is derived from the arguments provided. Create the directory if it does not exist.
32
+
33
+ > All file paths in the instructions below are relative to \`<project-path>/working-on/<feature-name>/\`.
34
+
35
+ `;
36
+ const FEATURE_NAME_RULES = `### Feature Name Constraints
37
+
38
+ When deriving a feature name from a description:
39
+
40
+ - Use only lowercase letters, digits, and hyphens (\`a-z\`, \`0-9\`, \`-\`)
41
+ - Replace spaces and special characters with hyphens
42
+ - Remove consecutive hyphens (e.g. \`--\` → \`-\`)
43
+ - Remove leading and trailing hyphens
44
+ - **Maximum length: 30 characters** — if the derived name exceeds 30 characters, truncate at the last hyphen boundary before or at the 30th character
45
+ - If the input is already a valid branch name (no spaces, kebab-case or slash-separated), apply the 30-character limit to the last segment only (after the last \`/\`)
46
+ - Reject (and ask the user to provide a shorter name) if no valid name can be derived after truncation
47
+
48
+ **Examples:**
49
+
50
+ | Input | Derived feature name |
51
+ | ----------------------------------------------------- | ---------------------------- |
52
+ | \`Add user authentication\` | \`add-user-authentication\` |
53
+ | \`Implement real-time notifications for dashboard\` | \`implement-real-time\` |
54
+ | \`feat/add-user-authentication\` | \`add-user-authentication\` |
55
+ | \`feat/implement-real-time-notifications-for-dashboard\` | \`implement-real-time\` |
56
+ `;
57
+ const WORKING_DIR_STEP = `Check whether the working directory \`<project-path>/working-on/<feature-name>\` already exists:
58
+ - If it **does not exist**, create it:
59
+ \`\`\`
60
+ mkdir -p <project-path>/working-on/<feature-name>
61
+ \`\`\`
62
+ - If it **already exists**, warn the user and ask whether to:
63
+ - **Resume** — continue into the existing folder (proceed to the next step without recreating it)
64
+ - **Abort** — stop and do nothing`;
65
+ const COMMAND_DEFINITIONS = [
66
+ {
67
+ name: 'osddt.continue',
68
+ description: 'Detect the current workflow phase and prompt the next command to run',
69
+ body: (args) => `${REPO_PREAMBLE}## Instructions
70
+
71
+ Check the working directory \`<project-path>/working-on/<feature-name>\` for the files listed below **in order** to determine the current phase. Use the first matching condition:
72
+
73
+ | Condition | Current phase | Run next |
74
+ | --------- | ------------- | -------- |
75
+ | \`osddt.tasks.md\` exists **and** has at least one unchecked task (\`- [ ]\`) | Implementing | \`/osddt.implement ${args}\` |
76
+ | \`osddt.tasks.md\` exists **and** all tasks are checked (\`- [x]\`) | Ready to close | \`/osddt.done ${args}\` |
77
+ | \`osddt.plan.md\` exists | Planning done | \`/osddt.tasks ${args}\` |
78
+ | \`osddt.spec.md\` exists | Spec done | \`/osddt.plan ${args}\` |
79
+ | \`osddt.research.md\` exists | Research done | \`/osddt.spec ${args}\` |
80
+ | None of the above | Not started | \`/osddt.spec ${args}\` (or \`/osddt.research ${args}\` if research is needed first) |
81
+
82
+ Report which file was found, which phase that corresponds to, and the exact command the user should run next.
83
+
84
+ ## Arguments
85
+
86
+ ${args}
87
+ `,
88
+ },
89
+ {
90
+ name: 'osddt.research',
91
+ description: 'Research a topic and write a research file to inform the feature specification',
92
+ body: (args) => `${REPO_PREAMBLE}## Instructions
93
+
94
+ The argument provided is: ${args}
95
+
96
+ Determine the feature name using the following logic:
97
+
98
+ 1. If ${args} looks like a branch name (e.g. \`feat/my-feature\`, \`my-feature-branch\` — no spaces, kebab-case or slash-separated), derive the feature name from the last segment (after the last \`/\`, or the full value if no \`/\` is present).
99
+ 2. Otherwise treat ${args} as a human-readable topic description and convert it to a feature name.
100
+
101
+ Apply the constraints below before using the name:
102
+
103
+ ${FEATURE_NAME_RULES}
104
+
105
+ Once the feature name is determined:
106
+
107
+ 3. ${WORKING_DIR_STEP}
108
+
109
+ 4. Research the topic thoroughly:
110
+ - Explore the existing codebase for relevant patterns, conventions, and prior art
111
+ - Identify related files, modules, and dependencies
112
+ - Note any constraints, risks, or open questions
113
+
114
+ 5. Write the findings to \`osddt.research.md\` in the working directory using the following format:
115
+
116
+ ## Research Format
117
+
118
+ The research file should include:
119
+ - **Topic**: What was researched and why
120
+ - **Codebase Findings**: Relevant existing code, patterns, and conventions found
121
+ - **External References**: Libraries, APIs, or documentation consulted
122
+ - **Key Insights**: Important discoveries that should inform the specification
123
+ - **Constraints & Risks**: Known limitations or risks uncovered during research
124
+ - **Open Questions**: Ambiguities that the specification phase should resolve
125
+
126
+ ## Arguments
127
+
128
+ ${args}
129
+
130
+ ## Next Step
131
+
132
+ Run the following command to write the feature specification:
133
+
134
+ \`\`\`
135
+ /osddt.spec ${args}
136
+ \`\`\`
137
+ `,
138
+ },
139
+ {
140
+ name: 'osddt.start',
141
+ description: 'Start a new feature by creating a branch and working-on folder',
142
+ body: (args) => `${REPO_PREAMBLE}## Instructions
143
+
144
+ The argument provided is: ${args}
145
+
146
+ Determine the branch name using the following logic:
147
+
148
+ 1. If ${args} looks like a branch name (e.g. \`feat/my-feature\`, \`fix/some-bug\`, \`my-feature-branch\` — no spaces, kebab-case or slash-separated), use it as-is.
149
+ 2. Otherwise treat ${args} as a human-readable feature description, convert it to a feature name, and use the format \`feat/<derived-name>\` as the branch name.
150
+
151
+ Apply the constraints below to the feature name (the segment after the last \`/\`) before using it:
152
+
153
+ ${FEATURE_NAME_RULES}
154
+
155
+ Once the branch name is determined:
156
+
157
+ 3. Check whether the branch already exists locally or remotely:
158
+ - If it **does not exist**, create and switch to it:
159
+ \`\`\`
160
+ git checkout -b <branch-name>
161
+ \`\`\`
162
+ - If it **already exists**, warn the user and ask whether to:
163
+ - **Resume** — switch to the existing branch (\`git checkout <branch-name>\`) and continue
164
+ - **Abort** — stop and do nothing
165
+
166
+ 4. ${WORKING_DIR_STEP}
167
+
168
+ Where \`<feature-name>\` is the last segment of the branch name (after the last \`/\`, or the full branch name if no \`/\` is present).
169
+
170
+ 5. Report the branch name and working directory that were created or resumed.
171
+
172
+ ## Arguments
173
+
174
+ ${args}
175
+
176
+ ## Next Step
177
+
178
+ Run the following command to write the feature specification:
179
+
180
+ \`\`\`
181
+ /osddt.spec ${args}
182
+ \`\`\`
183
+ `,
184
+ },
185
+ {
186
+ name: 'osddt.spec',
187
+ description: 'Analyze requirements and write a feature specification',
188
+ body: (args) => `## Instructions
189
+
190
+ 1. Check whether \`osddt.research.md\` exists in the working directory.
191
+ - If it exists, read it and use its findings (key insights, constraints, open questions, codebase findings) as additional context when writing the specification.
192
+ - If it does not exist, proceed using only the requirements provided in ${args}.
193
+ 2. Analyze the requirements provided in ${args}
194
+ 3. Identify the core problem being solved
195
+ 4. Define the scope, constraints, and acceptance criteria
196
+ 5. Write the specification to \`osddt.spec.md\` in the working directory
197
+
198
+ ## Specification Format
199
+
200
+ The spec should include:
201
+ - **Overview**: What and why
202
+ - **Requirements**: Functional and non-functional
203
+ - **Scope**: What is in and out of scope
204
+ - **Acceptance Criteria**: Clear, testable criteria
205
+ - **Open Questions**: Any ambiguities to resolve
206
+
207
+ > If \`osddt.research.md\` was found, add a **Research Summary** section that briefly references the key insights and constraints it identified.
208
+
209
+ ## Arguments
210
+
211
+ ${args}
212
+
213
+ ## Next Step
214
+
215
+ Run the following command to create the implementation plan:
216
+
217
+ \`\`\`
218
+ /osddt.plan ${args}
219
+ \`\`\`
220
+ `,
221
+ },
222
+ {
223
+ name: 'osddt.plan',
224
+ description: 'Create a technical implementation plan from a specification',
225
+ body: (args) => `## Instructions
226
+
227
+ 1. Read \`osddt.spec.md\` from the working directory
228
+ 2. Break down the implementation into logical phases and steps
229
+ 3. Identify technical decisions, dependencies, and risks
230
+ 4. Write the plan to \`osddt.plan.md\` in the working directory
231
+
232
+ ## Plan Format
233
+
234
+ The plan should include:
235
+ - **Architecture Overview**: High-level design decisions
236
+ - **Implementation Phases**: Ordered phases with goals
237
+ - **Technical Dependencies**: Libraries, APIs, services needed
238
+ - **Risks & Mitigations**: Known risks and how to address them
239
+ - **Out of Scope**: Explicitly what will not be built
240
+
241
+ ## Arguments
242
+
243
+ ${args}
244
+
245
+ ## Next Step
246
+
247
+ Run the following command to generate the task list:
248
+
249
+ \`\`\`
250
+ /osddt.tasks ${args}
251
+ \`\`\`
252
+ `,
253
+ },
254
+ {
255
+ name: 'osddt.tasks',
256
+ description: 'Generate actionable tasks from an implementation plan',
257
+ body: (args) => `## Instructions
258
+
259
+ 1. Read \`osddt.plan.md\` from the working directory
260
+ 2. Break each phase into discrete, executable tasks
261
+ 3. Estimate complexity (S/M/L) for each task
262
+ 4. Write the task list to \`osddt.tasks.md\` in the working directory
263
+
264
+ ## Tasks Format
265
+
266
+ The task list should include:
267
+ - **Checklist** of tasks grouped by phase
268
+ - Each task should be: \`- [ ] [S/M/L] Description of task\`
269
+ - **Dependencies**: Note which tasks must complete before others
270
+ - **Definition of Done**: Clear completion criteria per phase
271
+
272
+ ## Arguments
273
+
274
+ ${args}
275
+
276
+ ## Next Step
277
+
278
+ Run the following command to start implementing tasks:
279
+
280
+ \`\`\`
281
+ /osddt.implement ${args}
282
+ \`\`\`
283
+ `,
284
+ },
285
+ {
286
+ name: 'osddt.implement',
287
+ description: 'Execute tasks from the task list one by one',
288
+ body: (args) => `## Instructions
289
+
290
+ 1. Read \`osddt.tasks.md\` from the working directory
291
+ 2. Find the next unchecked task (\`- [ ]\`)
292
+ 3. Implement that task following the spec (\`osddt.spec.md\`) and plan (\`osddt.plan.md\`) in the working directory
293
+ 4. Mark the task as complete (\`- [x]\`) in \`osddt.tasks.md\`
294
+ 5. Report what was done and any issues encountered
295
+
296
+ ## Guidelines
297
+
298
+ - Implement one task at a time
299
+ - Follow the existing code style and conventions
300
+ - Write tests for new functionality when applicable
301
+ - Ask for clarification if requirements are ambiguous
302
+
303
+ ## Arguments
304
+
305
+ ${args}
306
+
307
+ ## Next Step
308
+
309
+ Once all tasks are checked off, run the following command to mark the feature as done:
310
+
311
+ \`\`\`
312
+ /osddt.done ${args}
313
+ \`\`\`
314
+ `,
315
+ },
316
+ {
317
+ name: 'osddt.done',
318
+ description: 'Mark a feature as done and move it from working-on to done',
319
+ body: (args) => `## Instructions
320
+
321
+ 1. Confirm all tasks in \`osddt.tasks.md\` are checked off (\`- [x]\`)
322
+ 2. Run the following command to move the feature folder from \`working-on\` to \`done\`:
323
+
324
+ \`\`\`
325
+ npx @dezkareid/osddt done ${args}
326
+ \`\`\`
327
+
328
+ The command will automatically prefix the destination folder name with today's date in \`YYYY-MM-DD\` format.
329
+ For example, \`working-on/feature-a\` will be moved to \`done/YYYY-MM-DD-feature-a\`.
330
+
331
+ 3. Report the result of the command, including the full destination path
332
+
333
+ ## Arguments
334
+
335
+ ${args}
336
+ `,
337
+ },
338
+ ];
339
+
340
+ const CLAUDE_COMMANDS_DIR = '.claude/commands';
341
+ function formatClaudeCommand(description, body) {
342
+ return `---
343
+ description: "${description}"
344
+ ---
345
+
346
+ ${body}`;
347
+ }
348
+ function getClaudeTemplates(cwd) {
349
+ const dir = path.join(cwd, CLAUDE_COMMANDS_DIR);
350
+ return COMMAND_DEFINITIONS.map((cmd) => ({
351
+ filePath: path.join(dir, `${cmd.name}.md`),
352
+ content: formatClaudeCommand(cmd.description, cmd.body('$ARGUMENTS')),
353
+ }));
354
+ }
355
+
356
+ const GEMINI_COMMANDS_DIR = '.gemini/commands';
357
+ function formatGeminiCommand(description, body) {
358
+ return `description = "${description}"
359
+
360
+ prompt = """
361
+ ${body}"""
362
+ `;
363
+ }
364
+ function getGeminiTemplates(cwd) {
365
+ const dir = path.join(cwd, GEMINI_COMMANDS_DIR);
366
+ return COMMAND_DEFINITIONS.map((cmd) => ({
367
+ filePath: path.join(dir, `${cmd.name}.toml`),
368
+ content: formatGeminiCommand(cmd.description, cmd.body('{{args}}')),
369
+ }));
370
+ }
371
+
372
+ async function askRepoType() {
373
+ return select({
374
+ message: 'What type of repository is this?',
375
+ choices: [
376
+ {
377
+ name: 'Single repo',
378
+ value: 'single',
379
+ description: 'A standalone project with one package',
380
+ },
381
+ {
382
+ name: 'Monorepo',
383
+ value: 'monorepo',
384
+ description: 'A repository containing multiple packages',
385
+ },
386
+ ],
387
+ });
388
+ }
389
+ async function askAgents() {
390
+ return checkbox({
391
+ message: 'Which AI assistant tools do you want to set up?',
392
+ choices: [
393
+ {
394
+ name: 'Claude Code',
395
+ value: 'claude',
396
+ checked: true,
397
+ },
398
+ {
399
+ name: 'Gemini CLI',
400
+ value: 'gemini',
401
+ checked: true,
402
+ },
403
+ ],
404
+ validate(choices) {
405
+ if (choices.length === 0) {
406
+ return 'You must select at least one agent.';
407
+ }
408
+ return true;
409
+ },
410
+ });
411
+ }
412
+
413
+ async function writeCommandFile(file) {
414
+ await fs.ensureDir(path.dirname(file.filePath));
415
+ await fs.writeFile(file.filePath, file.content, 'utf-8');
416
+ console.log(` Created: ${file.filePath}`);
417
+ }
418
+ async function writeConfig(cwd, config) {
419
+ const configPath = path.join(cwd, '.osddtrc');
420
+ await fs.writeJson(configPath, config, { spaces: 2 });
421
+ console.log(`\nSaved config: ${configPath}`);
422
+ }
423
+ async function runSetup(cwd) {
424
+ const agents = await askAgents();
425
+ console.log('');
426
+ const repoType = await askRepoType();
427
+ console.log('');
428
+ console.log('Setting up OSDDT command files...\n');
429
+ if (agents.includes('claude')) {
430
+ const claudeFiles = getClaudeTemplates(cwd);
431
+ console.log('Claude Code commands (.claude/commands/):');
432
+ for (const file of claudeFiles) {
433
+ await writeCommandFile(file);
434
+ }
435
+ console.log('');
436
+ }
437
+ if (agents.includes('gemini')) {
438
+ const geminiFiles = getGeminiTemplates(cwd);
439
+ console.log('Gemini CLI commands (.gemini/commands/):');
440
+ for (const file of geminiFiles) {
441
+ await writeCommandFile(file);
442
+ }
443
+ console.log('');
444
+ }
445
+ await writeConfig(cwd, { repoType });
446
+ console.log('\nSetup complete!');
447
+ console.log('Commands created: osddt.spec, osddt.plan, osddt.tasks, osddt.implement');
448
+ }
449
+ function setupCommand() {
450
+ const cmd = new Command('setup');
451
+ cmd
452
+ .description('Create OSDDT command files for Claude and Gemini CLI agents')
453
+ .option('-d, --dir <directory>', 'target directory', process.cwd())
454
+ .action(async (options) => {
455
+ const targetDir = path.resolve(options.dir);
456
+ await runSetup(targetDir);
457
+ });
458
+ return cmd;
459
+ }
460
+
461
+ function getCurrentBranch() {
462
+ try {
463
+ return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' }).trim();
464
+ }
465
+ catch {
466
+ return 'unknown';
467
+ }
468
+ }
469
+ function getCurrentDate() {
470
+ return new Date().toISOString().split('T')[0];
471
+ }
472
+ function metaInfoCommand() {
473
+ const cmd = new Command('meta-info');
474
+ cmd
475
+ .description('Output project meta information as JSON (branch, date)')
476
+ .action(() => {
477
+ const info = {
478
+ branch: getCurrentBranch(),
479
+ date: getCurrentDate(),
480
+ };
481
+ console.log(JSON.stringify(info));
482
+ });
483
+ return cmd;
484
+ }
485
+
486
+ function todayPrefix() {
487
+ const now = new Date();
488
+ const yyyy = now.getFullYear();
489
+ const mm = String(now.getMonth() + 1).padStart(2, '0');
490
+ const dd = String(now.getDate()).padStart(2, '0');
491
+ return `${yyyy}-${mm}-${dd}`;
492
+ }
493
+ async function runDone(featureName, cwd) {
494
+ const configPath = path.join(cwd, '.osddtrc');
495
+ if (!(await fs.pathExists(configPath))) {
496
+ console.error('Error: .osddtrc not found. Run `osddt setup` first.');
497
+ process.exit(1);
498
+ }
499
+ await fs.readJson(configPath);
500
+ const projectPath = cwd;
501
+ const src = path.join(projectPath, 'working-on', featureName);
502
+ const destName = `${todayPrefix()}-${featureName}`;
503
+ const dest = path.join(projectPath, 'done', destName);
504
+ if (!(await fs.pathExists(src))) {
505
+ console.error(`Error: working-on/${featureName} does not exist.`);
506
+ process.exit(1);
507
+ }
508
+ await fs.ensureDir(path.dirname(dest));
509
+ await fs.move(src, dest);
510
+ console.log(`Moved: working-on/${featureName} → done/${destName}`);
511
+ }
512
+ function doneCommand() {
513
+ const cmd = new Command('done');
514
+ cmd
515
+ .description('Move a feature from working-on/<feature-name> to done/<feature-name>')
516
+ .argument('<feature-name>', 'name of the feature to mark as done')
517
+ .option('-d, --dir <directory>', 'project directory', process.cwd())
518
+ .action(async (featureName, options) => {
519
+ const targetDir = path.resolve(options.dir);
520
+ await runDone(featureName, targetDir);
521
+ });
522
+ return cmd;
523
+ }
524
+
525
+ const program = new Command();
526
+ program
527
+ .name('osddt')
528
+ .description('Spec-Driven Development tooling for monorepos and single-package repos')
529
+ .version('0.0.0');
530
+ program.addCommand(setupCommand());
531
+ program.addCommand(metaInfoCommand());
532
+ program.addCommand(doneCommand());
533
+ program.parse(process.argv);
@@ -0,0 +1,6 @@
1
+ interface CommandFile {
2
+ filePath: string;
3
+ content: string;
4
+ }
5
+ export declare function getClaudeTemplates(cwd: string): CommandFile[];
6
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ interface CommandFile {
2
+ filePath: string;
3
+ content: string;
4
+ }
5
+ export declare function getGeminiTemplates(cwd: string): CommandFile[];
6
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ export declare const REPO_PREAMBLE = "## Context\n\nBefore proceeding, run the following command and parse the JSON output to get the current branch and date:\n\n```\nnpx @dezkareid/osddt meta-info\n```\n\n## Repository Configuration\n\nBefore proceeding, read the `.osddtrc` file in the root of the repository to determine the project path.\n\n```json\n// .osddtrc example\n{ \"repoType\": \"monorepo\" | \"single\" }\n```\n\n- If `repoType` is `\"single\"`: the project path is the repository root.\n- If `repoType` is `\"monorepo\"`: ask the user which package to work on (e.g. `packages/my-package`), then use `<repo-root>/<package>` as the project path.\n\n## Working Directory\n\nAll generated files live under `<project-path>/working-on/<feature-name>/`. The `<feature-name>` is derived from the arguments provided. Create the directory if it does not exist.\n\n> All file paths in the instructions below are relative to `<project-path>/working-on/<feature-name>/`.\n\n";
2
+ export declare const FEATURE_NAME_RULES = "### Feature Name Constraints\n\nWhen deriving a feature name from a description:\n\n- Use only lowercase letters, digits, and hyphens (`a-z`, `0-9`, `-`)\n- Replace spaces and special characters with hyphens\n- Remove consecutive hyphens (e.g. `--` \u2192 `-`)\n- Remove leading and trailing hyphens\n- **Maximum length: 30 characters** \u2014 if the derived name exceeds 30 characters, truncate at the last hyphen boundary before or at the 30th character\n- If the input is already a valid branch name (no spaces, kebab-case or slash-separated), apply the 30-character limit to the last segment only (after the last `/`)\n- Reject (and ask the user to provide a shorter name) if no valid name can be derived after truncation\n\n**Examples:**\n\n| Input | Derived feature name |\n| ----------------------------------------------------- | ---------------------------- |\n| `Add user authentication` | `add-user-authentication` |\n| `Implement real-time notifications for dashboard` | `implement-real-time` |\n| `feat/add-user-authentication` | `add-user-authentication` |\n| `feat/implement-real-time-notifications-for-dashboard` | `implement-real-time` |\n";
3
+ export declare const WORKING_DIR_STEP = "Check whether the working directory `<project-path>/working-on/<feature-name>` already exists:\n - If it **does not exist**, create it:\n ```\n mkdir -p <project-path>/working-on/<feature-name>\n ```\n - If it **already exists**, warn the user and ask whether to:\n - **Resume** \u2014 continue into the existing folder (proceed to the next step without recreating it)\n - **Abort** \u2014 stop and do nothing";
4
+ export type ArgPlaceholder = '$ARGUMENTS' | '{{args}}';
5
+ export interface CommandDefinition {
6
+ name: string;
7
+ description: string;
8
+ body: (args: ArgPlaceholder) => string;
9
+ }
10
+ export declare const COMMAND_DEFINITIONS: CommandDefinition[];
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export type RepoType = 'monorepo' | 'single';
2
+ export type AgentType = 'claude' | 'gemini';
3
+ export declare function askRepoType(): Promise<RepoType>;
4
+ export declare function askAgents(): Promise<AgentType[]>;
package/package.json CHANGED
@@ -1,10 +1,57 @@
1
1
  {
2
2
  "name": "@dezkareid/osddt",
3
- "version": "0.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Package for Spec-Driven Development workflow",
5
5
  "keywords": [
6
- "setup",
7
- "package",
8
- "npm"
9
- ]
10
- }
6
+ "spec-driven",
7
+ "cli"
8
+ ],
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "publishConfig": {
14
+ "access": "public",
15
+ "provenance": true
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/dezkareid/osddt.git"
20
+ },
21
+ "author": "Joel Humberto Gomez Paredes <elmaildeldezkareid@gmail.com>",
22
+ "license": "ISC",
23
+ "bugs": {
24
+ "url": "https://github.com/dezkareid/osddt/issues"
25
+ },
26
+ "homepage": "https://github.com/dezkareid/osddt#readme",
27
+ "type": "module",
28
+ "bin": {
29
+ "osddt": "./dist/index.js"
30
+ },
31
+ "main": "./dist/index.js",
32
+ "dependencies": {
33
+ "@inquirer/checkbox": "5.0.7",
34
+ "@inquirer/select": "5.0.7",
35
+ "commander": "12.0.0",
36
+ "fs-extra": "11.2.0",
37
+ "tslib": "2.8.1"
38
+ },
39
+ "devDependencies": {
40
+ "@rollup/plugin-typescript": "12.1.4",
41
+ "@types/fs-extra": "11.0.4",
42
+ "@types/node": "25.0.10",
43
+ "eslint": "9.39.2",
44
+ "prettier": "3.8.1",
45
+ "rollup": "4.56.0",
46
+ "typescript": "5.9.3",
47
+ "vitest": "4.0.18"
48
+ },
49
+ "scripts": {
50
+ "build": "rollup -c",
51
+ "dev": "rollup -c --watch",
52
+ "test": "vitest run",
53
+ "test:watch": "vitest",
54
+ "lint": "eslint src",
55
+ "format": "prettier --write src"
56
+ }
57
+ }
package/AGENTS.md DELETED
@@ -1,32 +0,0 @@
1
- # Agent Instructions: dezkareid monorepo
2
-
3
- This file provides critical context and dependency information for AI agents working in this project.
4
-
5
- ## Critical Dependency Versions
6
-
7
- The following versions are established across the project's packages and should be respected when adding new dependencies or troubleshooting.
8
-
9
- ### Core Languages & Runtimes
10
- - **TypeScript**: `5.9.3`
11
-
12
- ### Build & Bundling Tools
13
- - **Rollup**: `4.56.0`
14
-
15
- ### Testing Frameworks
16
- - **Vitest**: `4.0.18`
17
-
18
- ### Linting & Formatting
19
- - **ESLint**: `9.39.2`
20
- - **Prettier**: `3.8.1`
21
-
22
- ### Type Definitions
23
- - **@types/node**: `25.0.10`
24
- - **@types/fs-extra**: `11.0.4`
25
-
26
- ### Key Libraries
27
- - **Commander**: `12.0.0` (for CLI tools)
28
- - **fs-extra**: `11.2.0`
29
- - **globby**: `14.0.1`
30
-
31
- ## Project Structure & Conventions
32
- - **Package Manager**: `npm` is the required package manager.