@dezkareid/osddt 1.11.14 → 1.12.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.
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function copyEnvCommand(): Command;
package/dist/index.js CHANGED
@@ -254,13 +254,24 @@ ${npxCommand} start-worktree <feature-name> --dir <package-path>
254
254
 
255
255
  4. Parse the command output to extract \`worktreePath\` and \`workingDir\`.
256
256
 
257
- 5. Navigate into the worktree directory to locate the project:
257
+ 5. Copy environment files into the new worktree. Read \`bare-path\` and \`mainBranch\` from \`.osddtrc\` to construct the source path:
258
+ - Single repo (\`repoType: "single"\`):
259
+ \`\`\`
260
+ ${npxCommand} copy-env --source <bare-path>/<mainBranch> --target <worktreePath>
261
+ \`\`\`
262
+ - Monorepo (\`repoType: "monorepo"\`):
263
+ \`\`\`
264
+ ${npxCommand} copy-env --source <bare-path>/<mainBranch>/<package-path> --target <worktreePath>/<package-path>
265
+ \`\`\`
266
+ If the command finds no files, it exits silently — this is not an error.
267
+
268
+ 6. Navigate into the worktree directory to locate the project:
258
269
  - Enter \`<worktreePath>\` — this is the isolated git worktree for this feature.
259
270
  - If \`repoType\` is \`"single"\`: the project root is \`<worktreePath>\`.
260
271
  - If \`repoType\` is \`"monorepo"\`: the project root is \`<worktreePath>/<package-path>\`.
261
272
  - The planning files will live under \`<workingDir>\` (i.e. \`<project-root>/working-on/<feature-name>/\`).
262
273
 
263
- 6. Report the branch name, worktree path, project root, and working directory.
274
+ 7. Report the branch name, worktree path, project root, and working directory.
264
275
 
265
276
  ---
266
277
 
@@ -519,6 +530,17 @@ ${npxCommand} start-worktree <feature-name> --dir <package-path>
519
530
 
520
531
  4. Parse the command output to extract \`worktreePath\` and \`workingDir\`. Navigate into \`<worktreePath>\` to locate the project root.
521
532
 
533
+ 5. Copy environment files into the new worktree. Read \`bare-path\` and \`mainBranch\` from \`.osddtrc\` to construct the source path:
534
+ - Single repo (\`repoType: "single"\`):
535
+ \`\`\`
536
+ ${npxCommand} copy-env --source <bare-path>/<mainBranch> --target <worktreePath>
537
+ \`\`\`
538
+ - Monorepo (\`repoType: "monorepo"\`):
539
+ \`\`\`
540
+ ${npxCommand} copy-env --source <bare-path>/<mainBranch>/<package-path> --target <worktreePath>/<package-path>
541
+ \`\`\`
542
+ If the command finds no files, it exits silently — this is not an error.
543
+
522
544
  #### If \`worktree-repository\` is **absent** — Standard workflow
523
545
 
524
546
  3. Check whether the branch already exists locally or remotely:
@@ -584,56 +606,64 @@ ${args}
584
606
  {
585
607
  name: 'osddt.done',
586
608
  description: 'Mark a feature as done and move it from working-on to done',
587
- body: ({ npxCommand }) => `## Instructions
609
+ body: ({ npxCommand }) => `## Step 1 — Verify tasks
610
+
611
+ Confirm all tasks in \`osddt.tasks.md\` are checked off (\`- [x]\`).
588
612
 
589
- 1. Confirm all tasks in \`osddt.tasks.md\` are checked off (\`- [x]\`)
590
- 2. Run the following command to check whether this feature uses a git worktree:
613
+ ## Step 2 Detect feature type
591
614
 
592
615
  \`\`\`
593
616
  ${npxCommand} worktree-info <feature-name>
594
617
  \`\`\`
595
618
 
596
- 3. Based on the result:
619
+ - **Exit code 1** → standard feature. Follow **[If standard feature]** below.
620
+ - **Exit code 0** → worktree feature. Follow **[If worktree feature]** below.
597
621
 
598
- **If it exits with code 1 (standard feature):** use the project path from \`.osddtrc\`, then run:
599
- \`\`\`
600
- ${npxCommand} done <feature-name> --dir <project-path>
601
- \`\`\`
602
- Skip to step 8.
622
+ ## If standard feature
623
+
624
+ Run the done command using the project path from \`.osddtrc\`:
603
625
 
604
- **If it exits with code 0 (worktree feature):** parse the JSON to get \`worktreePath\` and \`branch\`, derive \`<project-path>\` from \`workingDir\`, then continue below.
626
+ \`\`\`
627
+ ${npxCommand} done <feature-name> --dir <project-path>
628
+ \`\`\`
605
629
 
606
- 4. Check for uncommitted changes inside the worktree:
630
+ Then skip to **[Step 3 Report]**.
607
631
 
608
- \`\`\`
609
- git -C <worktreePath> status --porcelain
610
- \`\`\`
632
+ ## If worktree feature
611
633
 
612
- 5. If there are **uncommitted changes**:
613
- 1. Run \`git -C <worktreePath> diff\` to inspect them.
614
- 2. Derive a concise commit message in **conventional commit** format (e.g. \`feat: add payment gateway integration\`) based on the diff.
615
- 3. Present the proposed message to the user: _"Use this commit message, or provide your own?"_
616
- 4. Once confirmed, commit:
617
- \`\`\`
618
- git -C <worktreePath> add -A
619
- git -C <worktreePath> commit -m "<confirmed-message>"
620
- \`\`\`
634
+ Parse the JSON output to get \`worktreePath\` and \`branch\`. Derive \`<project-path>\` from \`workingDir\`.
621
635
 
622
- 6. Push the branch to remote (covers both first push and subsequent pushes):
636
+ Run the done command to archive the working-on folder:
623
637
 
624
- \`\`\`
625
- git -C <worktreePath> push --set-upstream origin <branch>
626
- \`\`\`
638
+ \`\`\`
639
+ ${npxCommand} done <feature-name> --dir <project-path>
640
+ \`\`\`
627
641
 
628
- 7. Run the done command with the \`--worktree\` flag:
642
+ Then check for uncommitted changes:
643
+
644
+ \`\`\`
645
+ git -C <worktreePath> status --porcelain
646
+ \`\`\`
647
+
648
+ If there are **uncommitted changes**:
649
+ 1. Run \`git -C <worktreePath> diff\` to inspect them.
650
+ 2. Derive a concise commit message in **conventional commit** format (e.g. \`feat: add payment gateway integration\`) based on the diff.
651
+ 3. Present the proposed message to the user: _"Use this commit message, or provide your own?"_
652
+ 4. Once confirmed, commit:
629
653
  \`\`\`
630
- ${npxCommand} done <feature-name> --dir <project-path> --worktree
654
+ git -C <worktreePath> add -A
655
+ git -C <worktreePath> commit -m "<confirmed-message>"
631
656
  \`\`\`
632
657
 
633
- 8. The command will automatically prefix the destination folder name with today's date in \`YYYY-MM-DD\` format.
634
- For example, \`working-on/feature-a\` will be moved to \`done/YYYY-MM-DD-feature-a\`.
658
+ Push the branch to remote:
659
+
660
+ \`\`\`
661
+ git -C <worktreePath> push --set-upstream origin <branch>
662
+ \`\`\`
635
663
 
636
- 9. Report the result of the command, including the full destination path
664
+ ## Step 3 Report
665
+
666
+ Report the result of the command, including the full destination path.
637
667
 
638
668
  ${getCustomContextStep(npxCommand, 'done')}`,
639
669
  },
@@ -1392,6 +1422,76 @@ function worktreeInfoCommand() {
1392
1422
  return cmd;
1393
1423
  }
1394
1424
 
1425
+ function matchesPatterns(filename, patterns) {
1426
+ return patterns.some((pattern) => {
1427
+ // Convert glob pattern to regex: only support leading/trailing * and literal chars
1428
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
1429
+ return new RegExp(`^${escaped}$`).test(filename);
1430
+ });
1431
+ }
1432
+ async function readRc(cwd) {
1433
+ const rcPath = path.join(cwd, '.osddtrc');
1434
+ if (await fs.pathExists(rcPath)) {
1435
+ return await fs.readJson(rcPath);
1436
+ }
1437
+ return {};
1438
+ }
1439
+ async function copyFile(src, dest, force, dryRun) {
1440
+ if (dryRun) {
1441
+ console.log(`[dry-run] Would copy: ${src} → ${dest}`);
1442
+ return;
1443
+ }
1444
+ if ((await fs.pathExists(dest)) && !force) {
1445
+ console.log(`Skipped: ${dest} (already exists)`);
1446
+ return;
1447
+ }
1448
+ await fs.copy(src, dest, { overwrite: true });
1449
+ console.log(`Copied: ${src} → ${dest}`);
1450
+ }
1451
+ async function findMatchedFiles(source, patterns) {
1452
+ if (!(await fs.pathExists(source)))
1453
+ return [];
1454
+ const entries = await fs.readdir(source);
1455
+ return entries.filter(entry => matchesPatterns(entry, patterns));
1456
+ }
1457
+ async function runCopyEnv(options) {
1458
+ const cwd = process.cwd();
1459
+ if (!options.target)
1460
+ return;
1461
+ const rc = await readRc(cwd);
1462
+ const source = options.source ?? rc['copy-env']?.source;
1463
+ if (!source)
1464
+ return;
1465
+ const rawPattern = options.pattern ?? rc['copy-env']?.pattern ?? '.env*';
1466
+ const patterns = rawPattern.split(',').map(p => p.trim()).filter(Boolean);
1467
+ const matched = await findMatchedFiles(source, patterns);
1468
+ if (matched.length === 0)
1469
+ return;
1470
+ await fs.ensureDir(options.target);
1471
+ for (const filename of matched) {
1472
+ await copyFile(path.join(source, filename), path.join(options.target, filename), options.force ?? false, options.dryRun ?? false);
1473
+ }
1474
+ }
1475
+ function copyEnvCommand() {
1476
+ const cmd = new Command('copy-env');
1477
+ cmd
1478
+ .description('Copy environment files from a source directory to a target directory')
1479
+ .option('--source <path>', 'source directory to copy env files from')
1480
+ .option('--target <path>', 'target directory to copy env files into')
1481
+ .option('--pattern <globs>', 'comma-separated glob patterns (default: .env*)')
1482
+ .option('--force', 'overwrite existing files in target')
1483
+ .option('--dry-run', 'print what would be copied without writing')
1484
+ .action(async (options) => {
1485
+ try {
1486
+ await runCopyEnv(options);
1487
+ }
1488
+ catch {
1489
+ // fail silently
1490
+ }
1491
+ });
1492
+ return cmd;
1493
+ }
1494
+
1395
1495
  const __filename$1 = fileURLToPath(import.meta.url);
1396
1496
  const __dirname$1 = path.dirname(__filename$1);
1397
1497
  const pkgPath = path.join(__dirname$1, '..', 'package.json');
@@ -1408,4 +1508,5 @@ program.addCommand(updateCommand());
1408
1508
  program.addCommand(contextCommand());
1409
1509
  program.addCommand(startWorktreeCommand());
1410
1510
  program.addCommand(worktreeInfoCommand());
1511
+ program.addCommand(copyEnvCommand());
1411
1512
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dezkareid/osddt",
3
- "version": "1.11.14",
3
+ "version": "1.12.1",
4
4
  "description": "Package for Spec-Driven Development workflow",
5
5
  "keywords": [
6
6
  "spec-driven",