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