sdd-tool 1.2.5 → 1.2.6

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/dist/cli/index.js CHANGED
@@ -1627,12 +1627,16 @@ var startCommand = {
1627
1627
 
1628
1628
  1. \uBA3C\uC800 \uD504\uB85C\uC81D\uD2B8 \uAD6C\uC870\uB97C \uBD84\uC11D\uD558\uC138\uC694:
1629
1629
  - .sdd/ \uB514\uB809\uD1A0\uB9AC \uC874\uC7AC \uC5EC\uBD80 \uD655\uC778
1630
+ - .sdd/specs/ \uB514\uB809\uD1A0\uB9AC \uB0B4 \uC2A4\uD399 \uD30C\uC77C \uC874\uC7AC \uC5EC\uBD80 \uD655\uC778
1631
+ - src/ \uB610\uB294 lib/ \uB4F1 \uAE30\uC874 \uCF54\uB4DC \uC874\uC7AC \uC5EC\uBD80 \uD655\uC778 (\uBE0C\uB77C\uC6B4\uD544\uB4DC \uD310\uBCC4)
1630
1632
  - .git/ \uB514\uB809\uD1A0\uB9AC \uC874\uC7AC \uC5EC\uBD80 \uD655\uC778
1631
1633
  - .git/hooks/ \uB514\uB809\uD1A0\uB9AC\uC758 SDD \uD6C5 \uC124\uCE58 \uC5EC\uBD80 \uD655\uC778
1632
1634
  - .github/workflows/ \uB514\uB809\uD1A0\uB9AC\uC758 SDD \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC874\uC7AC \uC5EC\uBD80 \uD655\uC778
1633
1635
 
1634
1636
  2. \uBD84\uC11D \uACB0\uACFC\uC5D0 \uB530\uB77C \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC548\uB0B4\uD558\uC138\uC694:
1635
1637
  - SDD \uBBF8\uCD08\uAE30\uD654: \`sdd init\` \uC2E4\uD589 \uAD8C\uC7A5
1638
+ - **\uAE30\uC874 \uCF54\uB4DC\uAC00 \uC788\uACE0 \uC2A4\uD399\uC774 \uC5C6\uC74C (\uBE0C\uB77C\uC6B4\uD544\uB4DC)**: \`/sdd.reverse\` \uC2E4\uD589 \uAD8C\uC7A5
1639
+ - \uC2A4\uD399 \uC5C6\uC74C (\uADF8\uB9B0\uD544\uB4DC): \`/sdd.new\` \uC2E4\uD589 \uAD8C\uC7A5
1636
1640
  - Git Hooks \uBBF8\uC124\uCE58: Git \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC124\uC815 \uAD8C\uC7A5
1637
1641
  - CI/CD \uBBF8\uC124\uC815: GitHub Actions \uC124\uC815 \uAD8C\uC7A5
1638
1642
 
@@ -1696,7 +1700,23 @@ sdd start --workflow validate
1696
1700
  \uD504\uB85C\uC81D\uD2B8\uAC00 \uCD08\uAE30\uD654\uB418\uC9C0 \uC54A\uC740 \uACBD\uC6B0:
1697
1701
  1. \`sdd init\`\uC73C\uB85C \uD504\uB85C\uC81D\uD2B8\uB97C \uCD08\uAE30\uD654\uD558\uC138\uC694 (Git/CI-CD \uC124\uC815 \uD3EC\uD568)
1698
1702
  2. \`/sdd.constitution\`\uC73C\uB85C \uD504\uB85C\uC81D\uD2B8 \uC6D0\uCE59\uC744 \uC815\uC758\uD558\uC138\uC694
1699
- 3. \`/sdd.new\`\uB85C \uCCAB \uAE30\uB2A5 \uBA85\uC138\uB97C \uC791\uC131\uD558\uC138\uC694
1703
+ 3. \uB2E4\uC74C \uB2E8\uACC4 \uC120\uD0DD:
1704
+ - **\uADF8\uB9B0\uD544\uB4DC** (\uC0C8 \uD504\uB85C\uC81D\uD2B8): \`/sdd.new\`\uB85C \uCCAB \uAE30\uB2A5 \uBA85\uC138\uB97C \uC791\uC131\uD558\uC138\uC694
1705
+ - **\uBE0C\uB77C\uC6B4\uD544\uB4DC** (\uAE30\uC874 \uCF54\uB4DC): \`/sdd.reverse\`\uB85C \uAE30\uC874 \uCF54\uB4DC\uC5D0\uC11C \uC2A4\uD399\uC744 \uCD94\uCD9C\uD558\uC138\uC694
1706
+
1707
+ ## \uBE0C\uB77C\uC6B4\uD544\uB4DC \uD504\uB85C\uC81D\uD2B8 (\uAE30\uC874 \uCF54\uB4DC\uBCA0\uC774\uC2A4)
1708
+
1709
+ \uAE30\uC874 \uCF54\uB4DC\uAC00 \uC788\uB294 \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C SDD\uB97C \uB3C4\uC785\uD560 \uB54C:
1710
+
1711
+ 1. **\uC2A4\uD399 \uC5ED\uCD94\uCD9C**: \`/sdd.reverse scan\`\uC73C\uB85C \uD504\uB85C\uC81D\uD2B8 \uAD6C\uC870 \uBD84\uC11D
1712
+ 2. **\uC2A4\uD399 \uCD94\uCD9C**: \`/sdd.reverse extract\`\uB85C \uCF54\uB4DC\uC5D0\uC11C \uC2A4\uD399 \uCD08\uC548 \uC0DD\uC131
1713
+ 3. **\uB9AC\uBDF0 \uBC0F \uD655\uC815**: \`/sdd.reverse review\` \u2192 \`/sdd.reverse finalize\`
1714
+ 4. \uC774\uD6C4 \uC0C8 \uAE30\uB2A5\uC740 \`/sdd.new\`\uB85C \uC791\uC131
1715
+
1716
+ **\uBE0C\uB77C\uC6B4\uD544\uB4DC \uD310\uBCC4 \uAE30\uC900**:
1717
+ - src/, lib/, app/ \uB4F1 \uC18C\uC2A4 \uB514\uB809\uD1A0\uB9AC\uAC00 \uC874\uC7AC
1718
+ - .sdd/specs/ \uC5D0 \uC2A4\uD399 \uD30C\uC77C\uC774 \uC5C6\uAC70\uB098 \uC801\uC74C
1719
+ - package.json, requirements.txt \uB4F1 \uD504\uB85C\uC81D\uD2B8 \uC124\uC815 \uD30C\uC77C \uC874\uC7AC
1700
1720
 
1701
1721
  ## Git \uC6CC\uD06C\uD50C\uB85C\uC6B0 \uC0C1\uC138
1702
1722
 
@@ -2549,75 +2569,121 @@ var reverseCommand = {
2549
2569
  \uAE30\uC874 \uCF54\uB4DC\uB97C \uBD84\uC11D\uD558\uC5EC SDD \uC2A4\uD399 \uCD08\uC548\uC744 \uC790\uB3D9 \uC0DD\uC131\uD569\uB2C8\uB2E4.
2550
2570
  \uB9AC\uBDF0\uC640 \uC2B9\uC778 \uACFC\uC815\uC744 \uD1B5\uD574 \uC815\uC2DD \uC2A4\uD399\uC73C\uB85C \uD655\uC815\uD569\uB2C8\uB2E4.
2551
2571
 
2572
+ ## \uC911\uC694 \uC9C0\uC2DC\uC0AC\uD56D
2573
+
2574
+ **\uBC18\uB4DC\uC2DC CLI \uBA85\uB839\uC5B4\uB97C \uC0AC\uC6A9\uD558\uC138\uC694!**
2575
+ - \uC2A4\uD399 \uD30C\uC77C\uC744 \uC9C1\uC811 \uC791\uC131\uD558\uC9C0 \uB9C8\uC138\uC694
2576
+ - \`sdd reverse <subcommand>\` CLI\uB97C \uC2E4\uD589\uD558\uC138\uC694
2577
+ - \uCD08\uC548\uC740 \`.sdd/.reverse-drafts/\`\uC5D0 \uC800\uC7A5\uB429\uB2C8\uB2E4 (\uC9C1\uC811 \uAC74\uB4DC\uB9AC\uC9C0 \uB9C8\uC138\uC694)
2578
+ - \`.sdd/specs/\`\uC5D0\uB294 finalize \uD6C4\uC5D0\uB9CC \uD30C\uC77C\uC774 \uC0DD\uC131\uB429\uB2C8\uB2E4
2579
+
2552
2580
  ## \uD558\uC704 \uBA85\uB839\uC5B4
2553
2581
 
2554
2582
  \`\`\`
2555
- /sdd.reverse scan [path] # \uD504\uB85C\uC81D\uD2B8 \uAD6C\uC870 \uC2A4\uCE94
2556
- /sdd.reverse extract [path] # \uCF54\uB4DC\uC5D0\uC11C \uC2A4\uD399 \uCD94\uCD9C
2557
- /sdd.reverse review [spec-id] # \uCD94\uCD9C\uB41C \uC2A4\uD399 \uB9AC\uBDF0
2558
- /sdd.reverse finalize [spec-id] # \uC2B9\uC778\uB41C \uC2A4\uD399 \uD655\uC815
2583
+ /sdd.reverse scan [path] # \uD504\uB85C\uC81D\uD2B8 \uAD6C\uC870 \uC2A4\uCE94 (CLI \uC2E4\uD589)
2584
+ /sdd.reverse extract [path] # \uCF54\uB4DC\uC5D0\uC11C \uC2A4\uD399 \uCD94\uCD9C (CLI \uC2E4\uD589)
2585
+ /sdd.reverse review [spec-id] # \uCD94\uCD9C\uB41C \uC2A4\uD399 \uB9AC\uBDF0 (CLI \uC2E4\uD589)
2586
+ /sdd.reverse finalize [spec-id] # \uC2B9\uC778\uB41C \uC2A4\uD399 \uD655\uC815 (CLI \uC2E4\uD589)
2559
2587
  \`\`\`
2560
2588
 
2561
2589
  ## \uC6CC\uD06C\uD50C\uB85C\uC6B0
2562
2590
 
2563
2591
  \`\`\`
2564
- scan \u2192 extract \u2192 review \u2192 finalize
2592
+ scan (+ \uB3C4\uBA54\uC778 \uC790\uB3D9 \uC0DD\uC131) \u2192 extract \u2192 review \u2192 finalize
2565
2593
  \`\`\`
2566
2594
 
2567
- ### 1. Scan (\uC2A4\uCE94)
2595
+ **\uAC01 \uB2E8\uACC4\uB294 \uC21C\uCC28\uC801\uC73C\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4. \uC774\uC804 \uB2E8\uACC4\uB97C \uAC74\uB108\uB6F0\uC9C0 \uB9C8\uC138\uC694!**
2596
+
2597
+ ### 1. Scan (\uC2A4\uCE94 + \uB3C4\uBA54\uC778 \uC0DD\uC131)
2568
2598
 
2569
- \uD504\uB85C\uC81D\uD2B8\uB97C \uBD84\uC11D\uD558\uC5EC \uB514\uB809\uD1A0\uB9AC \uAD6C\uC870, \uC5B8\uC5B4 \uBD84\uD3EC, \uB3C4\uBA54\uC778\uC744 \uCD94\uC815\uD569\uB2C8\uB2E4.
2599
+ **Claude \uC9C0\uC2DC:** \`sdd reverse scan\` CLI \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD558\uC138\uC694.
2570
2600
 
2571
2601
  \`\`\`bash
2572
- sdd reverse scan
2573
- sdd reverse scan src/
2602
+ sdd reverse scan # \uC2A4\uCE94 + \uB3C4\uBA54\uC778 \uC790\uB3D9 \uC0DD\uC131
2603
+ sdd reverse scan src/ # \uD2B9\uC815 \uACBD\uB85C \uC2A4\uCE94
2604
+ sdd reverse scan --no-create-domains # \uB3C4\uBA54\uC778 \uC0DD\uC131 \uC5C6\uC774 \uC2A4\uCE94\uB9CC
2574
2605
  \`\`\`
2575
2606
 
2607
+ **\uC218\uD589 \uC791\uC5C5:**
2608
+ - \uD504\uB85C\uC81D\uD2B8 \uAD6C\uC870 \uBD84\uC11D (src/, lib/, packages/ \uB4F1)
2609
+ - \uC5B8\uC5B4 \uBD84\uD3EC \uD655\uC778
2610
+ - \uB3C4\uBA54\uC778 \uC790\uB3D9 \uC0DD\uC131 (.sdd/domains.yml\uC5D0 \uCD94\uAC00)
2611
+ - \uC2A4\uCE94 \uBA54\uD0C0\uB370\uC774\uD130 \uC800\uC7A5 (.sdd/.reverse-meta.json)
2612
+
2613
+ **\uC644\uB8CC \uD6C4 \uC548\uB0B4:** "\uC2A4\uCE94\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \`/sdd.reverse extract\`\uB85C \uCF54\uB4DC\uC5D0\uC11C \uC2A4\uD399\uC744 \uCD94\uCD9C\uD558\uC138\uC694."
2614
+
2576
2615
  ### 2. Extract (\uCD94\uCD9C)
2577
2616
 
2578
- \uC2A4\uCE94 \uACB0\uACFC\uB97C \uAE30\uBC18\uC73C\uB85C \uCF54\uB4DC\uC5D0\uC11C \uC2A4\uD399 \uCD08\uC548\uC744 \uCD94\uCD9C\uD569\uB2C8\uB2E4.
2617
+ **Claude \uC9C0\uC2DC:** \`sdd reverse extract\` CLI \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD558\uC138\uC694.
2618
+ **\uC8FC\uC758:** \uC2A4\uD399 \uD30C\uC77C\uC744 \uC9C1\uC811 \uC791\uC131\uD558\uC9C0 \uB9C8\uC138\uC694! CLI\uAC00 \`.sdd/.reverse-drafts/\`\uC5D0 \uCD08\uC548\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.
2579
2619
 
2580
2620
  \`\`\`bash
2581
- sdd reverse extract
2582
- sdd reverse extract --domain auth
2583
- sdd reverse extract --depth deep
2621
+ sdd reverse extract # \uC804\uCCB4 \uCD94\uCD9C
2622
+ sdd reverse extract --domain auth # \uD2B9\uC815 \uB3C4\uBA54\uC778\uB9CC
2623
+ sdd reverse extract --depth deep # \uAE4A\uC740 \uBD84\uC11D
2584
2624
  \`\`\`
2585
2625
 
2586
- **\uC635\uC158:**
2587
- - \`--domain <name>\`: \uD2B9\uC815 \uB3C4\uBA54\uC778\uB9CC \uCD94\uCD9C
2588
- - \`--depth <level>\`: \uBD84\uC11D \uAE4A\uC774 (shallow, medium, deep)
2589
- - \`--min-confidence <n>\`: \uCD5C\uC18C \uC2E0\uB8B0\uB3C4 \uD544\uD130
2626
+ **\uC218\uD589 \uC791\uC5C5:**
2627
+ - \uCF54\uB4DC \uC2EC\uBCFC \uBD84\uC11D
2628
+ - \uC2A4\uD399 \uCD08\uC548 \uC0DD\uC131 \u2192 \`.sdd/.reverse-drafts/<domain>/<name>.json\`
2629
+ - \uC0C1\uD0DC: \`pending\` (\uC544\uC9C1 \uC2B9\uC778\uB418\uC9C0 \uC54A\uC74C)
2630
+
2631
+ **\uC644\uB8CC \uD6C4 \uC548\uB0B4:** "\uCD94\uCD9C\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \`/sdd.reverse review\`\uB85C \uC2A4\uD399\uC744 \uB9AC\uBDF0\uD558\uC138\uC694."
2590
2632
 
2591
2633
  ### 3. Review (\uB9AC\uBDF0)
2592
2634
 
2593
- \uCD94\uCD9C\uB41C \uC2A4\uD399 \uCD08\uC548\uC744 \uB9AC\uBDF0\uD558\uACE0 \uC2B9\uC778/\uAC70\uBD80\uD569\uB2C8\uB2E4.
2635
+ **Claude \uC9C0\uC2DC:** \`sdd reverse review\` CLI \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD558\uC138\uC694.
2594
2636
 
2595
2637
  \`\`\`bash
2596
- sdd reverse review # \uB9AC\uBDF0 \uB300\uAE30 \uBAA9\uB85D
2597
- sdd reverse review auth/login # \uD2B9\uC815 \uC2A4\uD399 \uC0C1\uC138
2638
+ sdd reverse review # \uB9AC\uBDF0 \uB300\uAE30 \uBAA9\uB85D \uD655\uC778
2639
+ sdd reverse review auth/login # \uD2B9\uC815 \uC2A4\uD399 \uC0C1\uC138 \uBCF4\uAE30
2640
+ sdd reverse review auth/login --approve # \uC2A4\uD399 \uC2B9\uC778
2641
+ sdd reverse review auth/login --reject # \uC2A4\uD399 \uAC70\uBD80
2598
2642
  \`\`\`
2599
2643
 
2644
+ **\uC218\uD589 \uC791\uC5C5:**
2645
+ - \uCD94\uCD9C\uB41C \uCD08\uC548 \uAC80\uD1A0
2646
+ - \`--approve\`\uB85C \uC2B9\uC778, \`--reject\`\uB85C \uAC70\uBD80
2647
+
2648
+ **\uC644\uB8CC \uD6C4 \uC548\uB0B4:** "\uB9AC\uBDF0\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \`/sdd.reverse finalize\`\uB85C \uC2B9\uC778\uB41C \uC2A4\uD399\uC744 \uD655\uC815\uD558\uC138\uC694."
2649
+
2600
2650
  ### 4. Finalize (\uD655\uC815)
2601
2651
 
2602
- \uC2B9\uC778\uB41C \uC2A4\uD399\uC744 \uC815\uC2DD SDD \uC2A4\uD399\uC73C\uB85C \uBCC0\uD658\uD569\uB2C8\uB2E4.
2652
+ **Claude \uC9C0\uC2DC:** \`sdd reverse finalize\` CLI \uBA85\uB839\uC5B4\uB97C \uC2E4\uD589\uD558\uC138\uC694.
2653
+ **\uC8FC\uC758:** finalize \uD6C4\uC5D0\uB9CC \`.sdd/specs/\`\uC5D0 \uC2A4\uD399\uC774 \uC0DD\uC131\uB429\uB2C8\uB2E4!
2603
2654
 
2604
2655
  \`\`\`bash
2605
- sdd reverse finalize --all # \uBAA8\uB4E0 \uC2B9\uC778 \uC2A4\uD399 \uD655\uC815
2606
- sdd reverse finalize auth/login # \uD2B9\uC815 \uC2A4\uD399 \uD655\uC815
2656
+ sdd reverse finalize --all # \uBAA8\uB4E0 \uC2B9\uC778 \uC2A4\uD399 \uD655\uC815
2657
+ sdd reverse finalize auth/login # \uD2B9\uC815 \uC2A4\uD399 \uD655\uC815
2658
+ sdd reverse finalize -d auth # \uD2B9\uC815 \uB3C4\uBA54\uC778 \uD655\uC815
2607
2659
  \`\`\`
2608
2660
 
2661
+ **\uC218\uD589 \uC791\uC5C5:**
2662
+ - \`.sdd/.reverse-drafts/\`\uC5D0\uC11C \uC2B9\uC778\uB41C \uC2A4\uD399 \uC77D\uAE30
2663
+ - \`.sdd/specs/<feature-id>/spec.md\` \uC0DD\uC131
2664
+ - \uCD08\uC548 \uD30C\uC77C \uC0AD\uC81C
2665
+
2666
+ **\uC644\uB8CC \uD6C4 \uC548\uB0B4:** "\uC2A4\uD399 \uD655\uC815\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \`/sdd.validate\`\uB85C \uC2A4\uD399\uC744 \uAC80\uC99D\uD558\uAC70\uB098 \`/sdd.new\`\uB85C \uC0C8 \uAE30\uB2A5\uC744 \uCD94\uAC00\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
2667
+
2609
2668
  ## \uCD9C\uB825 \uD30C\uC77C
2610
2669
 
2611
- | \uD30C\uC77C | \uC124\uBA85 |
2612
- |------|------|
2613
- | \`.sdd/.reverse-meta.json\` | \uC2A4\uCE94 \uACB0\uACFC \uBA54\uD0C0\uB370\uC774\uD130 |
2614
- | \`.sdd/.reverse-drafts/\` | \uC2A4\uD399 \uCD08\uC548 \uB514\uB809\uD1A0\uB9AC |
2615
- | \`.sdd/specs/\` | \uD655\uC815\uB41C \uC2A4\uD399 \uB514\uB809\uD1A0\uB9AC |
2670
+ **\uC8FC\uC758:** CLI\uAC00 \uC0DD\uC131\uD558\uB294 \uD30C\uC77C \uD615\uC2DD\uC744 \uC815\uD655\uD788 \uB530\uB974\uC138\uC694!
2671
+
2672
+ | \uD30C\uC77C | \uC124\uBA85 | \uC0DD\uC131 \uC2DC\uC810 |
2673
+ |------|------|----------|
2674
+ | \`.sdd/domains.yml\` | \uB3C4\uBA54\uC778 \uC124\uC815 (YAML \uD615\uC2DD, JSON \uC544\uB2D8!) | scan |
2675
+ | \`.sdd/domains/<domain>/domain.md\` | \uB3C4\uBA54\uC778\uBCC4 \uBB38\uC11C | scan |
2676
+ | \`.sdd/.reverse-meta.json\` | \uC2A4\uCE94/\uCD94\uCD9C \uBA54\uD0C0\uB370\uC774\uD130 | scan, extract |
2677
+ | \`.sdd/.reverse-drafts/\` | \uC2A4\uD399 \uCD08\uC548 \uB514\uB809\uD1A0\uB9AC | extract |
2678
+ | \`.sdd/specs/<feature-id>/spec.md\` | \uD655\uC815\uB41C \uC2A4\uD399 | finalize |
2679
+
2680
+ **\uD30C\uC77C\uC744 \uC9C1\uC811 \uC0DD\uC131\uD558\uC9C0 \uB9C8\uC138\uC694!** \uBAA8\uB4E0 \uD30C\uC77C\uC740 CLI \uBA85\uB839\uC5B4\uB85C \uC0DD\uC131\uB429\uB2C8\uB2E4.
2616
2681
 
2617
2682
  ## \uB2E4\uC74C \uB2E8\uACC4
2618
2683
 
2619
2684
  - \uD655\uC815 \uD6C4: \`/sdd.validate\`\uB85C \uC2A4\uD399 \uAC80\uC99D
2620
- - \uB3C4\uBA54\uC778 \uC815\uB9AC: \`/sdd.domain\`\uC73C\uB85C \uB3C4\uBA54\uC778 \uAD6C\uC870\uD654
2685
+ - \uB3C4\uBA54\uC778 \uC218\uC815: \`/sdd.domain\`\uC73C\uB85C \uB3C4\uBA54\uC778 \uC0C1\uC138 \uC870\uC815 (\uC774\uB984 \uBCC0\uACBD, \uC758\uC874\uC131 \uCD94\uAC00 \uB4F1)
2686
+ - \uC0C8 \uAE30\uB2A5: \`/sdd.new\`\uB85C \uC0C8 \uC2A4\uD399 \uC791\uC131
2621
2687
  `
2622
2688
  };
2623
2689
 
@@ -21392,6 +21458,68 @@ async function loadReviewList(sddPath) {
21392
21458
  return failure(new Error(`\uB9AC\uBDF0 \uBAA9\uB85D \uB85C\uB4DC \uC2E4\uD328: ${error2}`));
21393
21459
  }
21394
21460
  }
21461
+ async function approveSpec(sddPath, specId, comment) {
21462
+ const loadResult = await loadReviewList(sddPath);
21463
+ if (!loadResult.success) {
21464
+ return failure(loadResult.error);
21465
+ }
21466
+ const item = loadResult.data.find((i) => i.specId === specId);
21467
+ if (!item) {
21468
+ return failure(new Error(`\uC2A4\uD399\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${specId}`));
21469
+ }
21470
+ item.status = "approved";
21471
+ item.spec.metadata.status = "approved";
21472
+ item.reviewedAt = /* @__PURE__ */ new Date();
21473
+ if (comment) {
21474
+ item.comments.push({
21475
+ type: "info",
21476
+ message: comment,
21477
+ createdAt: /* @__PURE__ */ new Date()
21478
+ });
21479
+ }
21480
+ const saveResult = await saveReviewItem(sddPath, item);
21481
+ if (!saveResult.success) {
21482
+ return failure(saveResult.error);
21483
+ }
21484
+ return success(item);
21485
+ }
21486
+ async function rejectSpec(sddPath, specId, reason) {
21487
+ const loadResult = await loadReviewList(sddPath);
21488
+ if (!loadResult.success) {
21489
+ return failure(loadResult.error);
21490
+ }
21491
+ const item = loadResult.data.find((i) => i.specId === specId);
21492
+ if (!item) {
21493
+ return failure(new Error(`\uC2A4\uD399\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${specId}`));
21494
+ }
21495
+ item.status = "rejected";
21496
+ item.spec.metadata.status = "rejected";
21497
+ item.reviewedAt = /* @__PURE__ */ new Date();
21498
+ item.comments.push({
21499
+ type: "error",
21500
+ message: reason,
21501
+ createdAt: /* @__PURE__ */ new Date()
21502
+ });
21503
+ const saveResult = await saveReviewItem(sddPath, item);
21504
+ if (!saveResult.success) {
21505
+ return failure(saveResult.error);
21506
+ }
21507
+ return success(item);
21508
+ }
21509
+ async function saveReviewItem(sddPath, item) {
21510
+ const [domain, name] = item.specId.split("/");
21511
+ const specDir = path51.join(sddPath, ".reverse-drafts", domain);
21512
+ try {
21513
+ await ensureDir(specDir);
21514
+ const jsonPath = path51.join(specDir, `${name}.json`);
21515
+ await fs33.writeFile(jsonPath, formatSpecAsJson(item.spec), "utf-8");
21516
+ const mdPath = path51.join(specDir, `${name}.md`);
21517
+ await fs33.writeFile(mdPath, formatSpecAsMarkdown(item.spec), "utf-8");
21518
+ return success(void 0);
21519
+ } catch (error2) {
21520
+ return failure(new Error(`\uB9AC\uBDF0 \uD56D\uBAA9 \uC800\uC7A5 \uC2E4\uD328: ${error2}`));
21521
+ }
21522
+ }
21395
21523
  function calculateReviewSummary(items) {
21396
21524
  return {
21397
21525
  total: items.length,
@@ -22559,6 +22687,38 @@ async function handleScan(targetPath, options) {
22559
22687
  error(`\uACB0\uACFC \uC800\uC7A5 \uC2E4\uD328: ${error2}`);
22560
22688
  }
22561
22689
  }
22690
+ const shouldCreateDomains = options.createDomains !== false;
22691
+ if (shouldCreateDomains && result.summary.suggestedDomains.length > 0) {
22692
+ const domainService = createDomainService(sddRoot);
22693
+ const existingDomainsResult = await domainService.list();
22694
+ const existingDomainIds = existingDomainsResult.success ? existingDomainsResult.data.map((d) => d.id) : [];
22695
+ let createdCount = 0;
22696
+ let skippedCount = 0;
22697
+ for (const suggested of result.summary.suggestedDomains) {
22698
+ if (existingDomainIds.includes(suggested.name)) {
22699
+ skippedCount++;
22700
+ continue;
22701
+ }
22702
+ const createResult = await domainService.create(suggested.name, {
22703
+ description: `${suggested.name} \uB3C4\uBA54\uC778 (reverse scan\uC73C\uB85C \uC790\uB3D9 \uC0DD\uC131)`,
22704
+ path: suggested.path
22705
+ });
22706
+ if (createResult.success) {
22707
+ createdCount++;
22708
+ }
22709
+ }
22710
+ if (!options.quiet && (createdCount > 0 || skippedCount > 0)) {
22711
+ console.log("");
22712
+ console.log(chalk10.bold("\u{1F4C1} \uB3C4\uBA54\uC778 \uC790\uB3D9 \uC0DD\uC131:"));
22713
+ if (createdCount > 0) {
22714
+ console.log(chalk10.green(` \u2705 ${createdCount}\uAC1C \uB3C4\uBA54\uC778 \uC0DD\uC131\uB428`));
22715
+ }
22716
+ if (skippedCount > 0) {
22717
+ console.log(chalk10.dim(` \u23ED\uFE0F ${skippedCount}\uAC1C \uB3C4\uBA54\uC778 \uC774\uBBF8 \uC874\uC7AC (\uAC74\uB108\uB700)`));
22718
+ }
22719
+ console.log("");
22720
+ }
22721
+ }
22562
22722
  if (!options.skipSerenaCheck) {
22563
22723
  const serenaCheck = await ensureSerenaAvailable("scan", { skipSerenaCheck: true, quiet: true });
22564
22724
  if (!serenaCheck.success && !options.quiet) {
@@ -22566,6 +22726,11 @@ async function handleScan(targetPath, options) {
22566
22726
  console.log(chalk10.dim(" docs/guide/serena-setup.md \uCC38\uC870\n"));
22567
22727
  }
22568
22728
  }
22729
+ if (!options.quiet && !options.json) {
22730
+ console.log(chalk10.bold("\u{1F4A1} \uB2E4\uC74C \uB2E8\uACC4:"));
22731
+ console.log(" sdd reverse extract # \uCF54\uB4DC\uC5D0\uC11C \uC2A4\uD399 \uCD94\uCD9C");
22732
+ console.log("");
22733
+ }
22569
22734
  }
22570
22735
  async function handleExtract(targetPath, options) {
22571
22736
  const sddRoot = await findSddRoot();
@@ -22670,6 +22835,29 @@ async function handleReview(specId, options) {
22670
22835
  error(`\uC2A4\uD399\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${specId}`);
22671
22836
  process.exit(ExitCode.GENERAL_ERROR);
22672
22837
  }
22838
+ if (options.approve) {
22839
+ const result = await approveSpec(sddPath, item.specId);
22840
+ if (result.success) {
22841
+ success2(`\uC2B9\uC778\uB428: ${item.specId}`);
22842
+ console.log("");
22843
+ console.log(chalk10.bold("\u{1F4A1} \uB2E4\uC74C \uB2E8\uACC4:"));
22844
+ console.log(" sdd reverse finalize --all # \uC2B9\uC778\uB41C \uC2A4\uD399 \uD655\uC815");
22845
+ } else {
22846
+ error(result.error.message);
22847
+ process.exit(ExitCode.GENERAL_ERROR);
22848
+ }
22849
+ return;
22850
+ }
22851
+ if (options.reject) {
22852
+ const result = await rejectSpec(sddPath, item.specId);
22853
+ if (result.success) {
22854
+ success2(`\uAC70\uBD80\uB428: ${item.specId}`);
22855
+ } else {
22856
+ error(result.error.message);
22857
+ process.exit(ExitCode.GENERAL_ERROR);
22858
+ }
22859
+ return;
22860
+ }
22673
22861
  console.log(formatSpecDetail(item));
22674
22862
  console.log(chalk10.bold("\u{1F4A1} \uC791\uC5C5:"));
22675
22863
  console.log(` sdd reverse review ${specId} --approve # \uC2B9\uC778`);
@@ -22791,9 +22979,9 @@ function registerReverseCommand(program2) {
22791
22979
  showReverseHelp();
22792
22980
  }
22793
22981
  });
22794
- reverse.command("scan [path]").description("\uD504\uB85C\uC81D\uD2B8 \uAD6C\uC870 \uC2A4\uCE94").option("-d, --depth <n>", "\uBD84\uC11D \uAE4A\uC774", parseInt).option("-i, --include <pattern>", "\uD3EC\uD568 \uD328\uD134 (glob)").option("-e, --exclude <pattern>", "\uC81C\uC678 \uD328\uD134 (glob)").option("-l, --language <lang>", "\uD2B9\uC815 \uC5B8\uC5B4\uB9CC").option("-o, --output <file>", "\uACB0\uACFC \uC800\uC7A5 \uD30C\uC77C").option("-q, --quiet", "\uC870\uC6A9\uD55C \uBAA8\uB4DC").option("--skip-serena-check", "Serena \uCCB4\uD06C \uAC74\uB108\uB6F0\uAE30 (\uAC1C\uBC1C\uC6A9)").action(handleScan);
22982
+ reverse.command("scan [path]").description("\uD504\uB85C\uC81D\uD2B8 \uAD6C\uC870 \uC2A4\uCE94 \uBC0F \uB3C4\uBA54\uC778 \uC790\uB3D9 \uC0DD\uC131").option("-d, --depth <n>", "\uBD84\uC11D \uAE4A\uC774", parseInt).option("-i, --include <pattern>", "\uD3EC\uD568 \uD328\uD134 (glob)").option("-e, --exclude <pattern>", "\uC81C\uC678 \uD328\uD134 (glob)").option("-l, --language <lang>", "\uD2B9\uC815 \uC5B8\uC5B4\uB9CC").option("-o, --output <file>", "\uACB0\uACFC \uC800\uC7A5 \uD30C\uC77C").option("-q, --quiet", "\uC870\uC6A9\uD55C \uBAA8\uB4DC").option("--json", "JSON \uD615\uC2DD \uCD9C\uB825").option("--compare", "\uC774\uC804 \uC2A4\uCE94\uACFC \uBE44\uAD50").option("--no-create-domains", "\uB3C4\uBA54\uC778 \uC790\uB3D9 \uC0DD\uC131 \uBE44\uD65C\uC131\uD654").option("--skip-serena-check", "Serena \uCCB4\uD06C \uAC74\uB108\uB6F0\uAE30 (\uAC1C\uBC1C\uC6A9)").action(handleScan);
22795
22983
  reverse.command("extract [path]").description("\uCF54\uB4DC\uC5D0\uC11C \uC2A4\uD399 \uCD94\uCD9C").option("--depth <level>", "\uCD94\uCD9C \uAE4A\uC774: shallow, medium, deep", "medium").option("--ai", "AI \uAE30\uBC18 \uC758\uB3C4 \uCD94\uB860 \uD65C\uC131\uD654").option("-d, --domain <name>", "\uB3C4\uBA54\uC778 \uC9C0\uC815").option("-o, --output <dir>", "\uCD9C\uB825 \uB514\uB809\uD1A0\uB9AC").option("-q, --quiet", "\uC870\uC6A9\uD55C \uBAA8\uB4DC").option("--skip-serena-check", "Serena \uCCB4\uD06C \uAC74\uB108\uB6F0\uAE30 (\uAC1C\uBC1C\uC6A9)").action(handleExtract);
22796
- reverse.command("review [spec]").description("\uCD94\uCD9C\uB41C \uC2A4\uD399 \uB9AC\uBDF0").option("-a, --all", "\uBAA8\uB4E0 \uC2A4\uD399 \uB9AC\uBDF0").option("-q, --quiet", "\uC870\uC6A9\uD55C \uBAA8\uB4DC").action(handleReview);
22984
+ reverse.command("review [spec]").description("\uCD94\uCD9C\uB41C \uC2A4\uD399 \uB9AC\uBDF0").option("-a, --all", "\uBAA8\uB4E0 \uC2A4\uD399 \uB9AC\uBDF0").option("--approve", "\uC2A4\uD399 \uC2B9\uC778").option("--reject", "\uC2A4\uD399 \uAC70\uBD80").option("-q, --quiet", "\uC870\uC6A9\uD55C \uBAA8\uB4DC").action(handleReview);
22797
22985
  reverse.command("finalize [spec]").description("\uC2B9\uC778\uB41C \uC2A4\uD399 \uC815\uC2DD \uBCC0\uD658").option("-a, --all", "\uBAA8\uB4E0 \uC2B9\uC778 \uC2A4\uD399 \uD655\uC815").option("-d, --domain <name>", "\uD2B9\uC815 \uB3C4\uBA54\uC778 \uD655\uC815").option("-q, --quiet", "\uC870\uC6A9\uD55C \uBAA8\uB4DC").action(handleFinalize);
22798
22986
  }
22799
22987