@dezkareid/osddt 1.1.0 → 1.3.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/AGENTS.md ADDED
@@ -0,0 +1,249 @@
1
+ # Agent Instructions: Other Spec-Driven Development Tooling (OSDDT)
2
+
3
+ This project is a command line utility for spec-driven development. It is intended to be used in monorepos or single package repos.
4
+
5
+ ## Overview
6
+
7
+ ### Agents Support
8
+ Each agent has its own conventions for:
9
+
10
+ - **Command file formats** (Markdown, TOML, etc.)
11
+ - **Directory structures** (`.claude/commands/`, `.windsurf/workflows/`, etc.)
12
+ - **Command invocation patterns** (slash commands, CLI tools, etc.)
13
+ - **Argument passing conventions** (`$ARGUMENTS`, `{{args}}`, etc.)
14
+
15
+ | Agent | Directory | Format | CLI Tool | Description |
16
+ | -------------------------- | ---------------------- | -------- | --------------- | --------------------------- |
17
+ | **Claude Code** | `.claude/commands/` | Markdown | `claude` | Anthropic's Claude Code CLI |
18
+ | **Gemini CLI** | `.gemini/commands/` | TOML | `gemini` | Google's Gemini CLI |
19
+
20
+
21
+ ### Command File Formats
22
+
23
+ #### Markdown Format
24
+
25
+ Used by: Claude, Cursor, opencode, Windsurf, Amazon Q Developer, Amp, SHAI, IBM Bob
26
+
27
+ **Standard format:**
28
+
29
+ ```markdown
30
+ ---
31
+ description: "Command description"
32
+ ---
33
+
34
+ Command content with {SCRIPT} and $ARGUMENTS placeholders.
35
+ ```
36
+
37
+ #### TOML Format
38
+
39
+ Used by: Gemini
40
+
41
+ ```toml
42
+ description = "Command description"
43
+
44
+ prompt = """
45
+ Command content with {SCRIPT} and {{args}} placeholders.
46
+ """
47
+ ```
48
+
49
+ ### Directory Conventions
50
+
51
+ - **CLI agents**: Usually `.<agent-name>/commands/`
52
+
53
+ ### Argument Patterns
54
+
55
+ Different agents use different argument placeholders:
56
+
57
+ - **Markdown/prompt-based**: `$ARGUMENTS`
58
+ - **TOML-based**: `{{args}}`
59
+
60
+ ## Development
61
+
62
+ ### Commit Rules
63
+
64
+ Always use Conventional Commits format for commit messages.
65
+
66
+ Never commit directly to `main` or `master`. If the current branch is one of them, propose creating a new branch before committing.
67
+
68
+ ### Critical Dependency Versions
69
+
70
+ The following versions are established across the project's packages and should be respected when adding new dependencies or troubleshooting.
71
+
72
+ Always prefer use exact versions for dependencies. Do not use `^` or `~`.
73
+
74
+ #### Core Languages & Runtimes
75
+ - **TypeScript**: `5.9.3`
76
+
77
+ #### Build & Bundling Tools
78
+ - **Rollup**: `4.56.0`
79
+
80
+ #### Testing Frameworks
81
+ - **Vitest**: `4.0.18`
82
+
83
+ #### Linting & Formatting
84
+ - **ESLint**: `9.39.2`
85
+ - **Prettier**: `3.8.1`
86
+
87
+ #### Type Definitions
88
+ - **@types/node**: `25.0.10`
89
+ - **@types/fs-extra**: `11.0.4`
90
+
91
+ #### Key Libraries
92
+ - **Commander**: `12.0.0` (for CLI tools)
93
+ - **fs-extra**: `11.2.0`
94
+ - **globby**: `14.0.1`
95
+
96
+ ### Project Structure & Conventions
97
+ - **Package Manager**: `pnpm` is the required package manager.
98
+
99
+ ### Codebase Structure
100
+
101
+ ```
102
+ osddt/
103
+ ├── src/
104
+ │ ├── index.ts # CLI entry point — wires Commander program and registers all commands
105
+ │ ├── commands/
106
+ │ │ ├── setup.ts # `osddt setup` — prompts for agents & repo type (or reads --agents/--repo-type flags), writes command files and .osddtrc
107
+ │ │ ├── meta-info.ts # `osddt meta-info` — outputs { branch, date } as JSON (consumed by generated templates)
108
+ │ │ └── done.ts # `osddt done <feature>` — moves working-on/<feature> → done/YYYY-MM-DD-<feature>
109
+ │ ├── templates/
110
+ │ │ ├── shared.ts # REPO_PREAMBLE, FEATURE_NAME_RULES, WORKING_DIR_STEP, and COMMAND_DEFINITIONS array
111
+ │ │ ├── claude.ts # Formats COMMAND_DEFINITIONS as Markdown (.claude/commands/osddt.<name>.md)
112
+ │ │ └── gemini.ts # Formats COMMAND_DEFINITIONS as TOML (.gemini/commands/osddt.<name>.toml)
113
+ │ └── utils/
114
+ │ └── prompt.ts # Inquirer prompts: askAgents() (checkbox) and askRepoType() (select)
115
+ ├── dist/ # Compiled output (single ESM bundle, gitignored)
116
+ ├── rollup.config.js # Bundles src/index.ts → dist/index.js (ESM, shebang injected)
117
+ ├── tsconfig.json # TypeScript config
118
+ ├── vitest.config.ts # Vitest config
119
+ ├── package.json # Package name: @dezkareid/osddt, bin: osddt → dist/index.js
120
+ ├── .osddtrc # Runtime config written by setup (repoType: "single" | "monorepo")
121
+ ├── AGENTS.md / CLAUDE.md / GEMINI.md # Agent-specific instructions (kept in sync)
122
+ └── README.md # Public-facing documentation
123
+ ```
124
+
125
+ #### Key relationships
126
+
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 setup: reads `--agents`/`--repo-type` flags when provided (non-interactive), otherwise calls `askAgents()` → `askRepoType()` → writes selected agent files → writes `.osddtrc`.
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
+ - **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
+
132
+ ### CLI Commands
133
+
134
+ All commands available via `npx @dezkareid/osddt <command>`:
135
+
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>` | 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.
152
+
153
+ ### Command Templates
154
+
155
+ Templates are generated by `npx @dezkareid/osddt setup` and placed in each agent's commands directory. Each template corresponds to a step in the spec-driven workflow.
156
+
157
+ | Template | Description |
158
+ | ------------------ | ------------------------------------------------------------------ |
159
+ | `osddt.continue` | Detect the current workflow phase and prompt the next command |
160
+ | `osddt.research` | Research a topic and write a research file to inform the spec |
161
+ | `osddt.start` | Start a new feature by creating a branch and working-on folder |
162
+ | `osddt.spec` | Analyze requirements and write a feature specification |
163
+ | `osddt.plan` | Create a technical implementation plan from a specification |
164
+ | `osddt.tasks` | Generate actionable tasks from an implementation plan |
165
+ | `osddt.implement` | Execute tasks from the task list one by one |
166
+ | `osddt.done` | Mark a feature as done and move it from working-on to done |
167
+
168
+ #### Template Workflow
169
+
170
+ `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.
171
+
172
+ ```
173
+ osddt.continue ──────────────────────────────────────────────────────────────────────────────┐
174
+
175
+ osddt.research ──┐ │
176
+ ├──► osddt.spec → osddt.plan → osddt.tasks → osddt.implement → osddt.done ◄─┘
177
+ osddt.start ──┘
178
+ ```
179
+
180
+ - Use **`osddt.continue`** at the start of a new session to detect the current phase and get the exact command to run next. It inspects the `working-on/<feature-name>/` folder for phase files and reports which one was found.
181
+ - Use **`osddt.research`** when you want to explore the codebase and gather findings before writing the spec. It creates the `working-on/<feature-name>/` folder and writes `osddt.research.md`.
182
+ - Use **`osddt.start`** when you are ready to begin implementation directly. It creates the git branch and the `working-on/<feature-name>/` folder.
183
+ - Both `osddt.research` and `osddt.start` check whether the working directory already exists and ask to **Resume** or **Abort** if it does.
184
+
185
+ #### Generated File Locations
186
+
187
+ | Agent | Directory | File pattern |
188
+ | ----------- | ------------------- | -------------------------- |
189
+ | Claude Code | `.claude/commands/` | `osddt.<name>.md` |
190
+ | Gemini CLI | `.gemini/commands/` | `osddt.<name>.toml` |
191
+
192
+ #### osddt.continue behaviour
193
+
194
+ - **Input**: A feature name or branch name to locate the working directory.
195
+ - **Actions performed by the agent**:
196
+ 1. Runs `npx @dezkareid/osddt meta-info` and reads `.osddtrc` to resolve the project path.
197
+ 2. Checks the `working-on/<feature-name>/` folder for the following phase files **in order**: `osddt.tasks.md` (with unchecked tasks), `osddt.tasks.md` (all checked), `osddt.plan.md`, `osddt.spec.md`, `osddt.research.md`.
198
+ 3. Reports the file found, the current phase, and the **exact command** the user should run next.
199
+
200
+ #### osddt.start behaviour
201
+
202
+ - **Input**: Either a human-readable feature description (e.g. `"Add user authentication"`) or an existing branch name (e.g. `feat/add-user-auth`).
203
+ - **Branch name resolution**: input is used as-is if it looks like a branch name; otherwise a name is derived (lowercased, hyphens, prefixed with `feat/`), subject to the 30-character feature name limit.
204
+ - **Actions performed by the agent**:
205
+ 1. Checks for an existing branch — offers **Resume** (`git checkout`) or **Abort** if found, otherwise runs `git checkout -b <branch-name>`.
206
+ 2. Reads `.osddtrc` to resolve the project path (single vs monorepo).
207
+ 3. Checks for an existing `working-on/<feature-name>/` folder — offers **Resume** or **Abort** if found, otherwise creates it.
208
+
209
+ #### osddt.research behaviour
210
+
211
+ - **Input**: Either a human-readable topic description or a branch/feature name.
212
+ - **Actions performed by the agent**:
213
+ 1. Derives the feature name (subject to the 30-character limit).
214
+ 2. Checks for an existing `working-on/<feature-name>/` folder — offers **Resume** or **Abort** if found, otherwise creates it.
215
+ 3. Researches the topic (codebase exploration, external references) and writes `osddt.research.md`.
216
+
217
+ ### Template Data Convention
218
+
219
+ When a template needs dynamic information (e.g. current branch, date, repo config), **do not pass it as a build-time argument**. Instead:
220
+
221
+ 1. Create an `npx @dezkareid/osddt <command>` that outputs the data (preferably as JSON).
222
+ 2. Reference that command in the template body, instructing the agent to run it at invocation time.
223
+
224
+ This keeps generated files deterministic and ensures agents always get live values.
225
+
226
+ ## Testing
227
+
228
+ ### Approach
229
+
230
+ Tests are written using **Vitest** and follow **BDD (Behaviour-Driven Development)** conventions:
231
+
232
+ - Test files live next to the source files they cover, using the `.spec.ts` suffix.
233
+ - Tests are structured with `describe` blocks that express the context ("given …") and `it` blocks that express the expected behaviour ("should …").
234
+ - Side effects (filesystem, child processes, `process.exit`) are isolated with `vi.mock` / `vi.spyOn` so tests remain fast and deterministic.
235
+ - Pure functions (template generators) are tested without mocks.
236
+
237
+ ### Running Tests
238
+
239
+ ```bash
240
+ # Run the full test suite once
241
+ pnpm test
242
+
243
+ # Run in watch mode during development
244
+ pnpm run test:watch
245
+ ```
246
+
247
+ ## Documentation
248
+
249
+ When a command in templates or npx commands are added/updated/removed/renamed/deprecated, ask to update the AGENTS.md and README.md files.
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>` | 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
 
@@ -38,3 +57,25 @@ 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,10 +224,16 @@ 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. 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
227
+ 1. Check whether \`osddt.plan.md\` already exists in the working directory:
228
+ - If it **does not exist**, proceed to generate it.
229
+ - If it **already exists**, ask the user whether to:
230
+ - **Regenerate** — discard the existing file and create a fresh plan from scratch
231
+ - **Update** — read the existing file and apply targeted changes based on ${args}
232
+ - **Do nothing** — stop here and leave the file as-is
233
+ 2. Read \`osddt.spec.md\` from the working directory
234
+ 3. Break down the implementation into logical phases and steps
235
+ 4. Identify technical decisions, dependencies, and risks
236
+ 5. Write the plan to \`osddt.plan.md\` in the working directory
231
237
 
232
238
  ## Plan Format
233
239
 
@@ -256,10 +262,16 @@ Run the following command to generate the task list:
256
262
  description: 'Generate actionable tasks from an implementation plan',
257
263
  body: (args) => `## Instructions
258
264
 
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
265
+ 1. Check whether \`osddt.tasks.md\` already exists in the working directory:
266
+ - If it **does not exist**, proceed to generate it.
267
+ - If it **already exists**, ask the user whether to:
268
+ - **Regenerate** — discard the existing file and create a fresh task list from scratch
269
+ - **Update** — read the existing file and apply targeted changes based on ${args}
270
+ - **Do nothing** — stop here and leave the file as-is
271
+ 2. Read \`osddt.plan.md\` from the working directory
272
+ 3. Break each phase into discrete, executable tasks
273
+ 4. Estimate complexity (S/M/L) for each task
274
+ 5. Write the task list to \`osddt.tasks.md\` in the working directory
263
275
 
264
276
  ## Tasks Format
265
277
 
@@ -287,11 +299,13 @@ Run the following command to start implementing tasks:
287
299
  description: 'Execute tasks from the task list one by one',
288
300
  body: (args) => `## Instructions
289
301
 
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
302
+ 1. Check whether \`osddt.tasks.md\` exists in the working directory:
303
+ - If it **does not exist**, stop and ask the user to run \`/osddt.tasks ${args}\` first.
304
+ 2. Read \`osddt.tasks.md\` from the working directory
305
+ 3. Find the next unchecked task (\`- [ ]\`)
306
+ 4. Implement that task following the spec (\`osddt.spec.md\`) and plan (\`osddt.plan.md\`) in the working directory
307
+ 5. Mark the task as complete (\`- [x]\`) in \`osddt.tasks.md\`
308
+ 6. Report what was done and any issues encountered
295
309
 
296
310
  ## Guidelines
297
311
 
@@ -410,6 +424,28 @@ async function askAgents() {
410
424
  });
411
425
  }
412
426
 
427
+ const VALID_AGENTS = ['claude', 'gemini'];
428
+ const VALID_REPO_TYPES = ['single', 'monorepo'];
429
+ function parseAgents(raw) {
430
+ const values = raw.split(',').map((s) => s.trim());
431
+ if (values.length === 0) {
432
+ console.error('Error: --agents requires at least one value.');
433
+ process.exit(1);
434
+ }
435
+ const invalid = values.filter((v) => !VALID_AGENTS.includes(v));
436
+ if (invalid.length > 0) {
437
+ console.error(`Error: Invalid agent(s): ${invalid.join(', ')}. Valid values: ${VALID_AGENTS.join(', ')}.`);
438
+ process.exit(1);
439
+ }
440
+ return values;
441
+ }
442
+ function parseRepoType(raw) {
443
+ if (!VALID_REPO_TYPES.includes(raw)) {
444
+ console.error(`Error: Invalid repo type: "${raw}". Valid values: ${VALID_REPO_TYPES.join(', ')}.`);
445
+ process.exit(1);
446
+ }
447
+ return raw;
448
+ }
413
449
  async function writeCommandFile(file) {
414
450
  await fs.ensureDir(path.dirname(file.filePath));
415
451
  await fs.writeFile(file.filePath, file.content, 'utf-8');
@@ -420,11 +456,13 @@ async function writeConfig(cwd, config) {
420
456
  await fs.writeJson(configPath, config, { spaces: 2 });
421
457
  console.log(`\nSaved config: ${configPath}`);
422
458
  }
423
- async function runSetup(cwd) {
424
- const agents = await askAgents();
425
- console.log('');
426
- const repoType = await askRepoType();
427
- console.log('');
459
+ async function runSetup(cwd, rawAgents, rawRepoType) {
460
+ const agents = rawAgents !== undefined ? parseAgents(rawAgents) : await askAgents();
461
+ if (rawAgents === undefined)
462
+ console.log('');
463
+ const repoType = rawRepoType !== undefined ? parseRepoType(rawRepoType) : await askRepoType();
464
+ if (rawRepoType === undefined)
465
+ console.log('');
428
466
  console.log('Setting up OSDDT command files...\n');
429
467
  if (agents.includes('claude')) {
430
468
  const claudeFiles = getClaudeTemplates(cwd);
@@ -451,9 +489,11 @@ function setupCommand() {
451
489
  cmd
452
490
  .description('Create OSDDT command files for Claude and Gemini CLI agents')
453
491
  .option('-d, --dir <directory>', 'target directory', process.cwd())
492
+ .option('--agents <list>', 'comma-separated agents to set up (claude, gemini)')
493
+ .option('--repo-type <type>', 'repository type (single, monorepo)')
454
494
  .action(async (options) => {
455
495
  const targetDir = path.resolve(options.dir);
456
- await runSetup(targetDir);
496
+ await runSetup(targetDir, options.agents, options.repoType);
457
497
  });
458
498
  return cmd;
459
499
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dezkareid/osddt",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Package for Spec-Driven Development workflow",
5
5
  "keywords": [
6
6
  "spec-driven",
@@ -8,7 +8,10 @@
8
8
  ],
9
9
  "files": [
10
10
  "dist",
11
- "README.md"
11
+ "README.md",
12
+ "AGENTS.md",
13
+ "GEMINI.md",
14
+ "CLAUDE.md"
12
15
  ],
13
16
  "publishConfig": {
14
17
  "access": "public",
@@ -52,6 +55,7 @@
52
55
  "test": "vitest run",
53
56
  "test:watch": "vitest",
54
57
  "lint": "eslint src",
55
- "format": "prettier --write src"
58
+ "format": "prettier --write src",
59
+ "setup-local": "pnpm run build && npx osddt setup --agents claude --repo-type single"
56
60
  }
57
61
  }