@dezkareid/osddt 1.2.0 → 1.3.1

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/AGENTS.md CHANGED
@@ -103,7 +103,7 @@ osddt/
103
103
  ├── src/
104
104
  │ ├── index.ts # CLI entry point — wires Commander program and registers all commands
105
105
  │ ├── commands/
106
- │ │ ├── setup.ts # `osddt setup` — prompts for agents & repo type, writes command files and .osddtrc
106
+ │ │ ├── setup.ts # `osddt setup` — prompts for agents & repo type (or reads --agents/--repo-type flags), writes command files and .osddtrc
107
107
  │ │ ├── meta-info.ts # `osddt meta-info` — outputs { branch, date } as JSON (consumed by generated templates)
108
108
  │ │ └── done.ts # `osddt done <feature>` — moves working-on/<feature> → done/YYYY-MM-DD-<feature>
109
109
  │ ├── templates/
@@ -125,7 +125,7 @@ osddt/
125
125
  #### Key relationships
126
126
 
127
127
  - **`shared.ts` is the single source of truth** for all command template content. Both `claude.ts` and `gemini.ts` import `COMMAND_DEFINITIONS` from it and only differ in file format (Markdown vs TOML) and argument placeholder (`$ARGUMENTS` vs `{{args}}`).
128
- - **`setup.ts`** orchestrates the interactive setup: calls `askAgents()` → `askRepoType()` → writes selected agent files → writes `.osddtrc`.
128
+ - **`setup.ts`** orchestrates setup: reads `--agents`/`--repo-type` flags when provided (non-interactive), otherwise calls `askAgents()` → `askRepoType()` → writes selected agent files → writes `.osddtrc`.
129
129
  - **`meta-info.ts`** is referenced inside the generated templates so agents can fetch live branch/date at invocation time (not baked in at build time).
130
130
  - **Test files** (`.spec.ts`) live next to the source file they cover. Template tests are pure (no mocks); command tests mock `fs-extra` and `child_process`.
131
131
 
@@ -133,11 +133,22 @@ osddt/
133
133
 
134
134
  All commands available via `npx @dezkareid/osddt <command>`:
135
135
 
136
- | Command | Description |
137
- | ------------------------------ | ------------------------------------------------------------- |
138
- | `@dezkareid/osddt setup` | Generate agent command files for Claude and Gemini |
139
- | `@dezkareid/osddt meta-info` | Output current branch and date as JSON |
140
- | `@dezkareid/osddt done <feature-name>` | Move `working-on/<feature>` to `done/<feature>` |
136
+ | Command | Description |
137
+ | -------------------------------------------------------------------- | ------------------------------------------------------------- |
138
+ | `@dezkareid/osddt setup` | Generate agent command files for Claude and Gemini |
139
+ | `@dezkareid/osddt setup --agents <list> --repo-type <type>` | Non-interactive setup (for CI/scripted environments) |
140
+ | `@dezkareid/osddt meta-info` | Output current branch and date as JSON |
141
+ | `@dezkareid/osddt done <feature-name> --dir <project-path>` | Move `working-on/<feature>` to `done/<feature>` |
142
+
143
+ #### `osddt setup` options
144
+
145
+ | Flag | Values | Description |
146
+ | ---- | ------ | ----------- |
147
+ | `--agents <list>` | `claude`, `gemini` (comma-separated) | Skip the agents prompt and use the provided value(s) |
148
+ | `--repo-type <type>` | `single`, `monorepo` | Skip the repo type prompt and use the provided value |
149
+ | `-d, --dir <directory>` | any path | Target directory (defaults to current working directory) |
150
+
151
+ Both flags are optional. Providing neither runs the fully interactive mode. Providing both skips all prompts.
141
152
 
142
153
  ### Command Templates
143
154
 
@@ -152,7 +163,7 @@ Templates are generated by `npx @dezkareid/osddt setup` and placed in each agent
152
163
  | `osddt.plan` | Create a technical implementation plan from a specification |
153
164
  | `osddt.tasks` | Generate actionable tasks from an implementation plan |
154
165
  | `osddt.implement` | Execute tasks from the task list one by one |
155
- | `osddt.done` | Mark a feature as done and move it from working-on to done |
166
+ | `osddt.done` | Resolve project path, verify tasks, and move the feature to done |
156
167
 
157
168
  #### Template Workflow
158
169
 
@@ -203,6 +214,17 @@ osddt.start ──┘
203
214
  2. Checks for an existing `working-on/<feature-name>/` folder — offers **Resume** or **Abort** if found, otherwise creates it.
204
215
  3. Researches the topic (codebase exploration, external references) and writes `osddt.research.md`.
205
216
 
217
+ #### osddt.done behaviour
218
+
219
+ - **Input**: A feature name or branch name identifying the feature to close.
220
+ - **Actions performed by the agent**:
221
+ 1. Reads `.osddtrc` to resolve the project path (single vs monorepo). For monorepos, asks the user which package.
222
+ 2. Derives the feature name from the input (same rules as other commands — last segment of a branch name or kebab-cased slug, subject to the 30-character limit). Must match the folder under `working-on/`.
223
+ 3. Confirms all tasks in `osddt.tasks.md` are checked off (`- [x]`).
224
+ 4. Runs `npx @dezkareid/osddt done <feature-name> --dir <project-path>` to move the folder.
225
+
226
+ Note: the `osddt done` CLI command does **not** read `.osddtrc` — project path resolution is the agent's responsibility, handled in step 1 above.
227
+
206
228
  ### Template Data Convention
207
229
 
208
230
  When a template needs dynamic information (e.g. current branch, date, repo config), **do not pass it as a build-time argument**. Instead:
package/README.md CHANGED
@@ -3,11 +3,30 @@ Other spec driven development tool but for monorepo
3
3
 
4
4
  ## CLI Commands
5
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>` |
6
+ | Command | Description |
7
+ | -------------------------------------------------------------------- | ------------------------------------------------------------- |
8
+ | `@dezkareid/osddt setup` | Generate agent command files for Claude and Gemini |
9
+ | `@dezkareid/osddt setup --agents <list> --repo-type <type>` | Non-interactive setup (for CI/scripted environments) |
10
+ | `@dezkareid/osddt meta-info` | Output current branch and date as JSON |
11
+ | `@dezkareid/osddt done <feature-name> --dir <project-path>` | Move `working-on/<feature>` to `done/<feature>` |
12
+
13
+ ### `osddt setup` options
14
+
15
+ | Flag | Values | Description |
16
+ | ---- | ------ | ----------- |
17
+ | `--agents <list>` | `claude`, `gemini` (comma-separated) | Skip the agents prompt and use the provided value(s) |
18
+ | `--repo-type <type>` | `single`, `monorepo` | Skip the repo type prompt and use the provided value |
19
+ | `-d, --dir <directory>` | any path | Target directory (defaults to current working directory) |
20
+
21
+ Both flags are optional. Providing neither runs the fully interactive mode. Providing both skips all prompts.
22
+
23
+ ```bash
24
+ # Interactive (default)
25
+ npx @dezkareid/osddt setup
26
+
27
+ # Non-interactive (CI-friendly)
28
+ npx @dezkareid/osddt setup --agents claude,gemini --repo-type single
29
+ ```
11
30
 
12
31
  ## Command Templates
13
32
 
@@ -32,9 +51,31 @@ osddt.start ──┘
32
51
  | `osddt.plan` | Create a technical implementation plan from a specification |
33
52
  | `osddt.tasks` | Generate actionable tasks from an implementation plan |
34
53
  | `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 |
54
+ | `osddt.done` | Resolve project path, verify tasks, and move the feature to done |
36
55
 
37
56
  Generated files are placed in:
38
57
 
39
58
  - `.claude/commands/osddt.<name>.md` (Claude Code)
40
59
  - `.gemini/commands/osddt.<name>.toml` (Gemini CLI)
60
+
61
+ ## Development
62
+
63
+ ### Running Tests
64
+
65
+ ```bash
66
+ # Run the full test suite once
67
+ pnpm test
68
+
69
+ # Run in watch mode during development
70
+ pnpm run test:watch
71
+ ```
72
+
73
+ ### Local Setup
74
+
75
+ After making changes to the source, rebuild and regenerate the agent command files in the repository:
76
+
77
+ ```bash
78
+ pnpm run setup-local
79
+ ```
80
+
81
+ This runs `pnpm run build` followed by `npx osddt setup`, prompting you to select which agents to configure and the repo type.
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js CHANGED
@@ -224,13 +224,13 @@ Run the following command to create the implementation plan:
224
224
  description: 'Create a technical implementation plan from a specification',
225
225
  body: (args) => `## Instructions
226
226
 
227
- 1. Read \`osddt.spec.md\` from the working directory
228
- 2. Check whether \`osddt.plan.md\` already exists in the working directory:
227
+ 1. Check whether \`osddt.plan.md\` already exists in the working directory:
229
228
  - If it **does not exist**, proceed to generate it.
230
229
  - If it **already exists**, ask the user whether to:
231
230
  - **Regenerate** — discard the existing file and create a fresh plan from scratch
232
231
  - **Update** — read the existing file and apply targeted changes based on ${args}
233
232
  - **Do nothing** — stop here and leave the file as-is
233
+ 2. Read \`osddt.spec.md\` from the working directory
234
234
  3. Break down the implementation into logical phases and steps
235
235
  4. Identify technical decisions, dependencies, and risks
236
236
  5. Write the plan to \`osddt.plan.md\` in the working directory
@@ -262,13 +262,13 @@ Run the following command to generate the task list:
262
262
  description: 'Generate actionable tasks from an implementation plan',
263
263
  body: (args) => `## Instructions
264
264
 
265
- 1. Read \`osddt.plan.md\` from the working directory
266
- 2. Check whether \`osddt.tasks.md\` already exists in the working directory:
265
+ 1. Check whether \`osddt.tasks.md\` already exists in the working directory:
267
266
  - If it **does not exist**, proceed to generate it.
268
267
  - If it **already exists**, ask the user whether to:
269
268
  - **Regenerate** — discard the existing file and create a fresh task list from scratch
270
269
  - **Update** — read the existing file and apply targeted changes based on ${args}
271
270
  - **Do nothing** — stop here and leave the file as-is
271
+ 2. Read \`osddt.plan.md\` from the working directory
272
272
  3. Break each phase into discrete, executable tasks
273
273
  4. Estimate complexity (S/M/L) for each task
274
274
  5. Write the task list to \`osddt.tasks.md\` in the working directory
@@ -301,10 +301,6 @@ Run the following command to start implementing tasks:
301
301
 
302
302
  1. Check whether \`osddt.tasks.md\` exists in the working directory:
303
303
  - If it **does not exist**, stop and ask the user to run \`/osddt.tasks ${args}\` first.
304
- - If it **already exists**, ask the user whether to:
305
- - **Continue** — find the next unchecked task and implement it (default)
306
- - **Update tasks** — edit \`osddt.tasks.md\` before implementing (e.g. to add, remove, or reorder tasks)
307
- - **Do nothing** — stop here without making any changes
308
304
  2. Read \`osddt.tasks.md\` from the working directory
309
305
  3. Find the next unchecked task (\`- [ ]\`)
310
306
  4. Implement that task following the spec (\`osddt.spec.md\`) and plan (\`osddt.plan.md\`) in the working directory
@@ -336,17 +332,22 @@ Once all tasks are checked off, run the following command to mark the feature as
336
332
  description: 'Mark a feature as done and move it from working-on to done',
337
333
  body: (args) => `## Instructions
338
334
 
339
- 1. Confirm all tasks in \`osddt.tasks.md\` are checked off (\`- [x]\`)
340
- 2. Run the following command to move the feature folder from \`working-on\` to \`done\`:
335
+ 1. Resolve the project path:
336
+ - Read \`.osddtrc\` from the repository root.
337
+ - If \`repoType\` is \`"single"\`: the project path is the repository root.
338
+ - 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.
339
+ 2. Derive the feature name from ${args} using the same rules as the other commands (last segment of a branch name, or a kebab-cased slug — subject to the 30-character limit). This must match the folder name under \`working-on/\`.
340
+ 3. Confirm all tasks in \`osddt.tasks.md\` are checked off (\`- [x]\`)
341
+ 4. Run the following command to move the feature folder from \`working-on\` to \`done\`:
341
342
 
342
343
  \`\`\`
343
- npx @dezkareid/osddt done ${args}
344
+ npx @dezkareid/osddt done <feature-name> --dir <project-path>
344
345
  \`\`\`
345
346
 
346
347
  The command will automatically prefix the destination folder name with today's date in \`YYYY-MM-DD\` format.
347
348
  For example, \`working-on/feature-a\` will be moved to \`done/YYYY-MM-DD-feature-a\`.
348
349
 
349
- 3. Report the result of the command, including the full destination path
350
+ 5. Report the result of the command, including the full destination path
350
351
 
351
352
  ## Arguments
352
353
 
@@ -428,6 +429,28 @@ async function askAgents() {
428
429
  });
429
430
  }
430
431
 
432
+ const VALID_AGENTS = ['claude', 'gemini'];
433
+ const VALID_REPO_TYPES = ['single', 'monorepo'];
434
+ function parseAgents(raw) {
435
+ const values = raw.split(',').map((s) => s.trim());
436
+ if (values.length === 0) {
437
+ console.error('Error: --agents requires at least one value.');
438
+ process.exit(1);
439
+ }
440
+ const invalid = values.filter((v) => !VALID_AGENTS.includes(v));
441
+ if (invalid.length > 0) {
442
+ console.error(`Error: Invalid agent(s): ${invalid.join(', ')}. Valid values: ${VALID_AGENTS.join(', ')}.`);
443
+ process.exit(1);
444
+ }
445
+ return values;
446
+ }
447
+ function parseRepoType(raw) {
448
+ if (!VALID_REPO_TYPES.includes(raw)) {
449
+ console.error(`Error: Invalid repo type: "${raw}". Valid values: ${VALID_REPO_TYPES.join(', ')}.`);
450
+ process.exit(1);
451
+ }
452
+ return raw;
453
+ }
431
454
  async function writeCommandFile(file) {
432
455
  await fs.ensureDir(path.dirname(file.filePath));
433
456
  await fs.writeFile(file.filePath, file.content, 'utf-8');
@@ -438,11 +461,13 @@ async function writeConfig(cwd, config) {
438
461
  await fs.writeJson(configPath, config, { spaces: 2 });
439
462
  console.log(`\nSaved config: ${configPath}`);
440
463
  }
441
- async function runSetup(cwd) {
442
- const agents = await askAgents();
443
- console.log('');
444
- const repoType = await askRepoType();
445
- console.log('');
464
+ async function runSetup(cwd, rawAgents, rawRepoType) {
465
+ const agents = rawAgents !== undefined ? parseAgents(rawAgents) : await askAgents();
466
+ if (rawAgents === undefined)
467
+ console.log('');
468
+ const repoType = rawRepoType !== undefined ? parseRepoType(rawRepoType) : await askRepoType();
469
+ if (rawRepoType === undefined)
470
+ console.log('');
446
471
  console.log('Setting up OSDDT command files...\n');
447
472
  if (agents.includes('claude')) {
448
473
  const claudeFiles = getClaudeTemplates(cwd);
@@ -469,9 +494,11 @@ function setupCommand() {
469
494
  cmd
470
495
  .description('Create OSDDT command files for Claude and Gemini CLI agents')
471
496
  .option('-d, --dir <directory>', 'target directory', process.cwd())
497
+ .option('--agents <list>', 'comma-separated agents to set up (claude, gemini)')
498
+ .option('--repo-type <type>', 'repository type (single, monorepo)')
472
499
  .action(async (options) => {
473
500
  const targetDir = path.resolve(options.dir);
474
- await runSetup(targetDir);
501
+ await runSetup(targetDir, options.agents, options.repoType);
475
502
  });
476
503
  return cmd;
477
504
  }
@@ -509,16 +536,9 @@ function todayPrefix() {
509
536
  return `${yyyy}-${mm}-${dd}`;
510
537
  }
511
538
  async function runDone(featureName, cwd) {
512
- const configPath = path.join(cwd, '.osddtrc');
513
- if (!(await fs.pathExists(configPath))) {
514
- console.error('Error: .osddtrc not found. Run `osddt setup` first.');
515
- process.exit(1);
516
- }
517
- await fs.readJson(configPath);
518
- const projectPath = cwd;
519
- const src = path.join(projectPath, 'working-on', featureName);
539
+ const src = path.join(cwd, 'working-on', featureName);
520
540
  const destName = `${todayPrefix()}-${featureName}`;
521
- const dest = path.join(projectPath, 'done', destName);
541
+ const dest = path.join(cwd, 'done', destName);
522
542
  if (!(await fs.pathExists(src))) {
523
543
  console.error(`Error: working-on/${featureName} does not exist.`);
524
544
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dezkareid/osddt",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "Package for Spec-Driven Development workflow",
5
5
  "keywords": [
6
6
  "spec-driven",
@@ -56,6 +56,6 @@
56
56
  "test:watch": "vitest",
57
57
  "lint": "eslint src",
58
58
  "format": "prettier --write src",
59
- "setup-local": "pnpm run build && npx osddt setup"
59
+ "setup-local": "pnpm run build && npx osddt setup --agents claude --repo-type single"
60
60
  }
61
61
  }