lean-spec 0.1.1 → 0.1.2

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/CHANGELOG.md CHANGED
@@ -7,6 +7,45 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.1.2] - 2025-11-10
11
+
12
+ ### Changed
13
+
14
+ **BREAKING: Command and directory naming migration**
15
+ - **Command name**: `lspec` → `lean-spec` (full name for clarity and consistency)
16
+ - **Config directory**: `.lspec/` → `.lean-spec/` (matches package and command name)
17
+ - **Binary**: Only `lean-spec` command available (removed `lspec` alias)
18
+
19
+ **Benefits:**
20
+ - ✅ Consistency: Package name, command, and config directory all use `lean-spec`
21
+ - ✅ Clarity: `npx lean-spec` works immediately (matches npm package name)
22
+ - ✅ Simplicity: Single command to remember, no abbreviations
23
+
24
+ **Migration Guide for Existing Users:**
25
+
26
+ 1. **Uninstall old version:**
27
+ ```bash
28
+ npm uninstall -g lean-spec
29
+ ```
30
+
31
+ 2. **Install new version:**
32
+ ```bash
33
+ npm install -g lean-spec
34
+ ```
35
+
36
+ 3. **Update existing projects:**
37
+ ```bash
38
+ # Rename config directory
39
+ mv .lspec .lean-spec
40
+ ```
41
+
42
+ 4. **Update commands:**
43
+ - Old: `lspec init` → New: `lean-spec init`
44
+ - Old: `lspec board` → New: `lean-spec board`
45
+ - Old: `npx lspec` → New: `npx lean-spec`
46
+
47
+ **All documentation, examples, and specs updated to reflect new naming.**
48
+
10
49
  ## [0.1.1] - 2025-11-07
11
50
 
12
51
  ### Changed
@@ -88,5 +127,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
127
  - Gray-matter for frontmatter parsing
89
128
  - Dayjs for date handling
90
129
 
130
+ [0.1.2]: https://github.com/codervisor/lean-spec/releases/tag/v0.1.2
91
131
  [0.1.1]: https://github.com/codervisor/lean-spec/releases/tag/v0.1.1
92
132
  [0.1.0]: https://github.com/codervisor/lean-spec/releases/tag/v0.1.0
package/README.md CHANGED
@@ -31,7 +31,7 @@ Specs under 300 lines. Intent-focused. Machine-readable. Adapts to your workflow
31
31
  <p align="center">
32
32
  <a href="#quick-start-5-minutes"><strong>Quick Start (5 Minutes) →</strong></a> •
33
33
  <a href="https://www.lean-spec.dev"><strong>Documentation</strong></a> •
34
- <a href="https://www.lean-spec.dev/docs/examples"><strong>Examples</strong></a>
34
+ <a href="https://www.lean-spec.dev/docs/guide/ai-executable-patterns"><strong>Examples</strong></a>
35
35
  </p>
36
36
 
37
37
  ---
@@ -98,7 +98,7 @@ priority: high
98
98
  # Unified Dashboard
99
99
 
100
100
  ## Overview
101
- Combine `lspec board` and `lspec stats` into a single, comprehensive
101
+ Combine `lean-spec board` and `lean-spec stats` into a single, comprehensive
102
102
  project health view. Give users instant insight into project status,
103
103
  bottlenecks, and team velocity.
104
104
 
@@ -136,9 +136,10 @@ LeanSpec isn't arbitrary rules—it's derived from fundamental constraints of wo
136
136
  ### 🧠 Context Economy
137
137
  **Specs <300 lines → Fit in working memory**
138
138
 
139
- - **Physics**: AI context windows are bounded (~20K effective tokens)
140
- - **Biology**: Human working memory is limited (7±2 items)
139
+ - **Physics**: AI performance degrades with longer context (quality drops beyond 50K tokens despite 200K limits)
140
+ - **Biology**: Human working memory is limited (7±2 items, 5-10 min attention)
141
141
  - **Economics**: Large contexts cost more time and money
142
+ - **Reality**: Attention is the scarce resource, not storage
142
143
  - **Result**: Keep specs under 300 lines, split complex features
143
144
 
144
145
  ### ✂️ Signal-to-Noise Maximization
@@ -177,7 +178,7 @@ LeanSpec isn't arbitrary rules—it's derived from fundamental constraints of wo
177
178
 
178
179
  **These aren't preferences—they're constraints.** Physics (context windows), biology (working memory), and economics (token costs) dictate what works.
179
180
 
180
- 📖 [Deep dive: First Principles Guide →](https://www.lean-spec.dev/docs/guide/first-principles)
181
+ 📖 [Deep dive: First Principles Guide →](https://www.lean-spec.dev/docs/guide/understanding#the-five-first-principles)
181
182
 
182
183
  ---
183
184
 
@@ -199,7 +200,7 @@ MCP-native specs. Works with any tool that supports Model Context Protocol.
199
200
  Track progress without leaving the terminal:
200
201
 
201
202
  ```bash
202
- $ lspec board
203
+ $ lean-spec board
203
204
 
204
205
  📋 Spec Kanban Board
205
206
 
@@ -219,7 +220,7 @@ $ lspec board
219
220
  ```
220
221
 
221
222
  ```bash
222
- $ lspec stats
223
+ $ lean-spec stats
223
224
 
224
225
  📊 Project Stats
225
226
 
@@ -271,7 +272,7 @@ Custom fields fully supported. Adapts to your workflow as you grow.
271
272
  ```bash
272
273
  npm install -g lean-spec
273
274
  cd your-project
274
- lspec init
275
+ lean-spec init
275
276
  ```
276
277
 
277
278
  ### 2. Work with Your AI Tool
@@ -281,7 +282,7 @@ lspec init
281
282
  ```
282
283
  👤 You: "Create a spec for user authentication with OAuth2."
283
284
 
284
- 🤖 AI: [runs lspec create user-authentication]
285
+ 🤖 AI: [runs lean-spec create user-authentication]
285
286
  "I've created specs/001-user-authentication/README.md.
286
287
  Here's the spec..."
287
288
 
@@ -295,19 +296,19 @@ lspec init
295
296
 
296
297
  ```bash
297
298
  # Check project status
298
- lspec board
299
+ lean-spec board
299
300
 
300
301
  # View spec with AI-friendly output
301
- lspec view user-authentication --json
302
+ lean-spec view user-authentication --json
302
303
 
303
304
  # Update status as you progress
304
- lspec update user-authentication --status in-progress
305
+ lean-spec update user-authentication --status in-progress
305
306
  ```
306
307
 
307
308
  **The workflow:**
308
- 1. ✅ Ask AI to create spec (it uses `lspec create`)
309
+ 1. ✅ Ask AI to create spec (it uses `lean-spec create`)
309
310
  2. ✅ AI reads spec and implements (spec fits in context)
310
- 3. ✅ Track with `lspec board` / `lspec stats`
311
+ 3. ✅ Track with `lean-spec board` / `lean-spec stats`
311
312
  4. ✅ Update status as work progresses
312
313
 
313
314
  **Why this works:**
@@ -317,9 +318,9 @@ lspec update user-authentication --status in-progress
317
318
  - You drive, AI executes
318
319
 
319
320
  **Next steps:**
320
- - 📘 [Full CLI Reference](https://www.lean-spec.dev/docs/cli-reference) - All commands
321
- - 🎨 [Choose a Template](https://www.lean-spec.dev/docs/templates) - Minimal, standard, or enterprise
322
- - 🤖 [AI Agent Setup](AGENTS.md) - Configure Cursor, Claude, Aider
321
+ - 📘 [Full CLI Reference](https://www.lean-spec.dev/docs/reference/cli) - All commands
322
+ - 🎨 [Choose a Template](https://www.lean-spec.dev/docs/guide/templates) - Minimal, standard, or enterprise
323
+ - 🤖 [AI Agent Setup](AGENTS.md) - Configure AI coding tools
323
324
 
324
325
  ---
325
326
 
@@ -387,24 +388,24 @@ We dogfood our own methodology. Specs that fit in AI context enable the velocity
387
388
  ## Learn More
388
389
 
389
390
  ### 📚 Documentation
390
- - [Getting Started Guide](https://www.lean-spec.dev/docs/getting-started) - Complete setup walkthrough
391
- - [First Principles](https://www.lean-spec.dev/docs/guide/first-principles) - The philosophy behind LeanSpec
392
- - [CLI Reference](https://www.lean-spec.dev/docs/cli-reference) - All commands with examples
391
+ - [Getting Started Guide](https://www.lean-spec.dev/docs/guide/getting-started) - Complete setup walkthrough
392
+ - [First Principles](https://www.lean-spec.dev/docs/guide/understanding#the-five-first-principles) - The philosophy behind LeanSpec
393
+ - [CLI Reference](https://www.lean-spec.dev/docs/reference/cli) - All commands with examples
393
394
 
394
395
  ### 🛠️ Integrations
395
396
  - [AI Agent Configuration](AGENTS.md) - Cursor, Copilot, Aider setup
396
397
  - [MCP Server](docs/MCP-SERVER.md) - Claude Desktop integration
397
- - [VS Code Extension](https://www.lean-spec.dev/docs/tools/vscode) - Enhanced editor support
398
+ - [VS Code Extension](https://www.lean-spec.dev/docs/roadmap#vs-code-extension) - Enhanced editor support (planned)
398
399
 
399
400
  ### 🎓 Guides
400
401
  - [Custom Fields](https://www.lean-spec.dev/docs/guide/custom-fields) - Adapt to your workflow
401
- - [Sub-Specs](https://www.lean-spec.dev/docs/guide/sub-specs) - Manage complex features
402
- - [Folder Structure](https://www.lean-spec.dev/docs/guide/folder-structure) - Organize your specs
402
+ - [Templates](https://www.lean-spec.dev/docs/guide/templates) - Choose the right structure
403
+ - [Frontmatter](https://www.lean-spec.dev/docs/guide/frontmatter) - Metadata and organization
403
404
 
404
405
  ### 🤝 Community
405
406
  - [GitHub Issues](https://github.com/codervisor/lean-spec/issues) - Report bugs or request features
406
407
  - [Contributing Guide](CONTRIBUTING.md) - Join the project
407
- - [Examples](https://www.lean-spec.dev/docs/examples) - Real-world usage patterns
408
+ - [AI-Executable Patterns](https://www.lean-spec.dev/docs/guide/ai-executable-patterns) - Real-world usage patterns
408
409
 
409
410
  ---
410
411
 
@@ -39,7 +39,7 @@ var DEFAULT_CONFIG = {
39
39
  }
40
40
  };
41
41
  async function loadConfig(cwd = process.cwd()) {
42
- const configPath = path.join(cwd, ".lspec", "config.json");
42
+ const configPath = path.join(cwd, ".lean-spec", "config.json");
43
43
  try {
44
44
  const content = await fs.readFile(configPath, "utf-8");
45
45
  const userConfig = JSON.parse(content);
@@ -51,7 +51,7 @@ async function loadConfig(cwd = process.cwd()) {
51
51
  }
52
52
  }
53
53
  async function saveConfig(config, cwd = process.cwd()) {
54
- const configDir = path.join(cwd, ".lspec");
54
+ const configDir = path.join(cwd, ".lean-spec");
55
55
  const configPath = path.join(configDir, "config.json");
56
56
  await fs.mkdir(configDir, { recursive: true });
57
57
  await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
@@ -616,14 +616,14 @@ async function checkSpecs(options = {}) {
616
616
  console.log("");
617
617
  }
618
618
  console.log(chalk3.cyan("Tip: Use date prefix to prevent conflicts:"));
619
- console.log(chalk3.gray(' Edit .lspec/config.json \u2192 structure.prefix: "{YYYYMMDD}-"'));
619
+ console.log(chalk3.gray(' Edit .lean-spec/config.json \u2192 structure.prefix: "{YYYYMMDD}-"'));
620
620
  console.log("");
621
621
  console.log(chalk3.cyan("Or rename folders manually to resolve."));
622
622
  console.log("");
623
623
  } else {
624
624
  console.log("");
625
625
  console.log(chalk3.yellow(`\u26A0\uFE0F Conflict warning: ${conflicts.length} sequence conflict(s) detected`));
626
- console.log(chalk3.gray("Run: lspec check"));
626
+ console.log(chalk3.gray("Run: lean-spec check"));
627
627
  console.log("");
628
628
  }
629
629
  }
@@ -677,7 +677,7 @@ async function createSpec(name, options = {}) {
677
677
  }
678
678
  }
679
679
  await fs5.mkdir(specDir, { recursive: true });
680
- const templatesDir = path6.join(cwd, ".lspec", "templates");
680
+ const templatesDir = path6.join(cwd, ".lean-spec", "templates");
681
681
  let templateName;
682
682
  if (options.template) {
683
683
  if (config.templates?.[options.template]) {
@@ -1351,7 +1351,7 @@ import * as path11 from "path";
1351
1351
  import chalk9 from "chalk";
1352
1352
  async function listTemplates(cwd = process.cwd()) {
1353
1353
  const config = await loadConfig(cwd);
1354
- const templatesDir = path11.join(cwd, ".lspec", "templates");
1354
+ const templatesDir = path11.join(cwd, ".lean-spec", "templates");
1355
1355
  console.log("");
1356
1356
  console.log(chalk9.green("=== Project Templates ==="));
1357
1357
  console.log("");
@@ -1397,7 +1397,7 @@ async function showTemplate(templateName, cwd = process.cwd()) {
1397
1397
  console.error(chalk9.gray(`Available: ${Object.keys(config.templates || {}).join(", ")}`));
1398
1398
  process.exit(1);
1399
1399
  }
1400
- const templatesDir = path11.join(cwd, ".lspec", "templates");
1400
+ const templatesDir = path11.join(cwd, ".lean-spec", "templates");
1401
1401
  const templateFile = config.templates[templateName];
1402
1402
  const templatePath = path11.join(templatesDir, templateFile);
1403
1403
  try {
@@ -1415,7 +1415,7 @@ async function showTemplate(templateName, cwd = process.cwd()) {
1415
1415
  }
1416
1416
  async function addTemplate(name, file, cwd = process.cwd()) {
1417
1417
  const config = await loadConfig(cwd);
1418
- const templatesDir = path11.join(cwd, ".lspec", "templates");
1418
+ const templatesDir = path11.join(cwd, ".lean-spec", "templates");
1419
1419
  const templatePath = path11.join(templatesDir, file);
1420
1420
  try {
1421
1421
  await fs8.access(templatePath);
@@ -1453,11 +1453,11 @@ async function removeTemplate(name, cwd = process.cwd()) {
1453
1453
  delete config.templates[name];
1454
1454
  await saveConfig(config, cwd);
1455
1455
  console.log(chalk9.green(`\u2713 Removed template: ${name}`));
1456
- console.log(chalk9.gray(` Note: Template file ${file} still exists in .lspec/templates/`));
1456
+ console.log(chalk9.gray(` Note: Template file ${file} still exists in .lean-spec/templates/`));
1457
1457
  }
1458
1458
  async function copyTemplate(source, target, cwd = process.cwd()) {
1459
1459
  const config = await loadConfig(cwd);
1460
- const templatesDir = path11.join(cwd, ".lspec", "templates");
1460
+ const templatesDir = path11.join(cwd, ".lean-spec", "templates");
1461
1461
  let sourceFile;
1462
1462
  if (config.templates?.[source]) {
1463
1463
  sourceFile = config.templates[source];
@@ -1523,7 +1523,56 @@ async function handleExistingFiles(action, existingFiles, templateDir, cwd, vari
1523
1523
  } catch {
1524
1524
  continue;
1525
1525
  }
1526
- if (action === "merge" && file === "AGENTS.md") {
1526
+ if (action === "merge-ai" && file === "AGENTS.md") {
1527
+ const existing = await fs9.readFile(filePath, "utf-8");
1528
+ let template = await fs9.readFile(templateFilePath, "utf-8");
1529
+ for (const [key, value] of Object.entries(variables)) {
1530
+ template = template.replace(new RegExp(`\\{${key}\\}`, "g"), value);
1531
+ }
1532
+ const promptPath = path12.join(cwd, ".lean-spec", "MERGE-AGENTS-PROMPT.md");
1533
+ const aiPrompt = `# AI Prompt: Consolidate AGENTS.md
1534
+
1535
+ ## Task
1536
+ Consolidate the existing AGENTS.md with LeanSpec instructions into a single, coherent document.
1537
+
1538
+ ## Instructions
1539
+ 1. Read both documents below
1540
+ 2. Merge them intelligently:
1541
+ - Preserve ALL existing project-specific information (workflows, SOPs, architecture, conventions)
1542
+ - Integrate LeanSpec sections where they fit naturally
1543
+ - Remove redundancy and ensure coherent flow
1544
+ - Keep the tone and style consistent
1545
+ 3. Replace the existing AGENTS.md with the consolidated version
1546
+
1547
+ ## Existing AGENTS.md
1548
+ \`\`\`markdown
1549
+ ${existing}
1550
+ \`\`\`
1551
+
1552
+ ## LeanSpec Instructions to Integrate
1553
+ \`\`\`markdown
1554
+ ${template}
1555
+ \`\`\`
1556
+
1557
+ ## Output
1558
+ Create a single consolidated AGENTS.md that:
1559
+ - Keeps all existing project context and workflows
1560
+ - Adds LeanSpec commands and principles where appropriate
1561
+ - Maintains clear structure and readability
1562
+ - Removes any duplicate or conflicting guidance
1563
+ `;
1564
+ await fs9.mkdir(path12.dirname(promptPath), { recursive: true });
1565
+ await fs9.writeFile(promptPath, aiPrompt, "utf-8");
1566
+ console.log(chalk10.green(`\u2713 Created AI consolidation prompt`));
1567
+ console.log(chalk10.cyan(` \u2192 ${promptPath}`));
1568
+ console.log("");
1569
+ console.log(chalk10.yellow("\u{1F4DD} Next steps:"));
1570
+ console.log(chalk10.gray(" 1. Open .lean-spec/MERGE-AGENTS-PROMPT.md"));
1571
+ console.log(chalk10.gray(" 2. Send it to your AI coding assistant (GitHub Copilot, Cursor, etc.)"));
1572
+ console.log(chalk10.gray(" 3. Let AI create the consolidated AGENTS.md"));
1573
+ console.log(chalk10.gray(" 4. Review and commit the result"));
1574
+ console.log("");
1575
+ } else if (action === "merge-append" && file === "AGENTS.md") {
1527
1576
  const existing = await fs9.readFile(filePath, "utf-8");
1528
1577
  let template = await fs9.readFile(templateFilePath, "utf-8");
1529
1578
  for (const [key, value] of Object.entries(variables)) {
@@ -1537,8 +1586,9 @@ async function handleExistingFiles(action, existingFiles, templateDir, cwd, vari
1537
1586
 
1538
1587
  ${template.split("\n").slice(1).join("\n")}`;
1539
1588
  await fs9.writeFile(filePath, merged, "utf-8");
1540
- console.log(chalk10.green(`\u2713 Merged LeanSpec section into ${file}`));
1541
- } else if (action === "backup") {
1589
+ console.log(chalk10.green(`\u2713 Appended LeanSpec section to ${file}`));
1590
+ console.log(chalk10.yellow(" \u26A0 Note: May be verbose. Consider consolidating later."));
1591
+ } else if (action === "overwrite") {
1542
1592
  const backupPath = `${filePath}.backup`;
1543
1593
  await fs9.rename(filePath, backupPath);
1544
1594
  console.log(chalk10.yellow(`\u2713 Backed up ${file} \u2192 ${file}.backup`));
@@ -1548,6 +1598,7 @@ ${template.split("\n").slice(1).join("\n")}`;
1548
1598
  }
1549
1599
  await fs9.writeFile(filePath, content, "utf-8");
1550
1600
  console.log(chalk10.green(`\u2713 Created new ${file}`));
1601
+ console.log(chalk10.gray(` \u{1F4A1} Your original content is preserved in ${file}.backup`));
1551
1602
  }
1552
1603
  }
1553
1604
  }
@@ -1594,9 +1645,9 @@ var TEMPLATES_DIR = path13.join(__dirname2, "..", "templates");
1594
1645
  async function initProject() {
1595
1646
  const cwd = process.cwd();
1596
1647
  try {
1597
- await fs10.access(path13.join(cwd, ".lspec", "config.json"));
1598
- console.log(chalk11.yellow("LeanSpec already initialized in this directory."));
1599
- console.log(chalk11.gray("To reinitialize, delete .lspec/ directory first."));
1648
+ await fs10.access(path13.join(cwd, ".lean-spec", "config.json"));
1649
+ console.log(chalk11.yellow("\u26A0 LeanSpec already initialized in this directory."));
1650
+ console.log(chalk11.gray("To reinitialize, delete .lean-spec/ directory first."));
1600
1651
  return;
1601
1652
  } catch {
1602
1653
  }
@@ -1615,12 +1666,13 @@ async function initProject() {
1615
1666
  name: "Choose template",
1616
1667
  value: "template",
1617
1668
  description: "Pick from: minimal, standard, enterprise"
1618
- },
1619
- {
1620
- name: "Customize everything",
1621
- value: "custom",
1622
- description: "Full control over structure and settings"
1623
1669
  }
1670
+ // TODO: Re-enable when custom setup mode is implemented
1671
+ // {
1672
+ // name: 'Customize everything',
1673
+ // value: 'custom',
1674
+ // description: 'Full control over structure and settings',
1675
+ // },
1624
1676
  ]
1625
1677
  });
1626
1678
  let templateName = "standard";
@@ -1637,8 +1689,6 @@ async function initProject() {
1637
1689
  }
1638
1690
  ]
1639
1691
  });
1640
- } else if (setupMode === "custom") {
1641
- console.log(chalk11.yellow("Full customization coming soon. Using standard for now."));
1642
1692
  }
1643
1693
  const templateDir = path13.join(TEMPLATES_DIR, templateName);
1644
1694
  const templateConfigPath = path13.join(templateDir, "config.json");
@@ -1650,31 +1700,34 @@ async function initProject() {
1650
1700
  console.error(chalk11.red(`Error: Template not found: ${templateName}`));
1651
1701
  process.exit(1);
1652
1702
  }
1653
- const patternChoice = await select({
1654
- message: "Select folder pattern:",
1655
- choices: [
1656
- {
1657
- name: "Simple: 001-my-spec/",
1658
- value: "simple",
1659
- description: "Global sequential numbering (recommended)"
1660
- },
1661
- {
1662
- name: "Date-grouped: 20251105/001-my-spec/",
1663
- value: "date-grouped",
1664
- description: "Group specs by creation date (good for teams)"
1665
- },
1666
- {
1667
- name: "Flat with date: 20251105-001-my-spec/",
1668
- value: "date-prefix",
1669
- description: "Date prefix with global numbering"
1670
- },
1671
- {
1672
- name: "Custom pattern",
1673
- value: "custom",
1674
- description: "Enter your own pattern"
1675
- }
1676
- ]
1677
- });
1703
+ let patternChoice = "simple";
1704
+ if (setupMode !== "quick") {
1705
+ patternChoice = await select({
1706
+ message: "Select folder pattern:",
1707
+ choices: [
1708
+ {
1709
+ name: "Simple: 001-my-spec/",
1710
+ value: "simple",
1711
+ description: "Global sequential numbering (recommended)"
1712
+ },
1713
+ {
1714
+ name: "Date-grouped: 20251105/001-my-spec/",
1715
+ value: "date-grouped",
1716
+ description: "Group specs by creation date (good for teams)"
1717
+ },
1718
+ {
1719
+ name: "Flat with date: 20251105-001-my-spec/",
1720
+ value: "date-prefix",
1721
+ description: "Date prefix with global numbering"
1722
+ },
1723
+ {
1724
+ name: "Custom pattern",
1725
+ value: "custom",
1726
+ description: "Enter your own pattern"
1727
+ }
1728
+ ]
1729
+ });
1730
+ }
1678
1731
  if (patternChoice === "simple") {
1679
1732
  templateConfig.structure.pattern = "flat";
1680
1733
  templateConfig.structure.prefix = "";
@@ -1688,13 +1741,13 @@ async function initProject() {
1688
1741
  } else if (patternChoice === "custom") {
1689
1742
  console.log("");
1690
1743
  console.log(chalk11.yellow("\u26A0 Custom pattern input is not yet implemented."));
1691
- console.log(chalk11.gray(" You can manually edit .lspec/config.json after initialization."));
1744
+ console.log(chalk11.gray(" You can manually edit .lean-spec/config.json after initialization."));
1692
1745
  console.log(chalk11.gray(" Using simple pattern for now."));
1693
1746
  console.log("");
1694
1747
  templateConfig.structure.pattern = "flat";
1695
1748
  templateConfig.structure.prefix = "";
1696
1749
  }
1697
- const templatesDir = path13.join(cwd, ".lspec", "templates");
1750
+ const templatesDir = path13.join(cwd, ".lean-spec", "templates");
1698
1751
  try {
1699
1752
  await fs10.mkdir(templatesDir, { recursive: true });
1700
1753
  } catch (error) {
@@ -1705,7 +1758,7 @@ async function initProject() {
1705
1758
  const targetSpecPath = path13.join(templatesDir, "spec-template.md");
1706
1759
  try {
1707
1760
  await fs10.copyFile(templateSpecPath, targetSpecPath);
1708
- console.log(chalk11.green("\u2713 Created .lspec/templates/spec-template.md"));
1761
+ console.log(chalk11.green("\u2713 Created .lean-spec/templates/spec-template.md"));
1709
1762
  } catch (error) {
1710
1763
  console.error(chalk11.red("Error copying template:"), error);
1711
1764
  process.exit(1);
@@ -1715,29 +1768,34 @@ async function initProject() {
1715
1768
  default: "spec-template.md"
1716
1769
  };
1717
1770
  await saveConfig(templateConfig, cwd);
1718
- console.log(chalk11.green("\u2713 Created .lspec/config.json"));
1771
+ console.log(chalk11.green("\u2713 Created .lean-spec/config.json"));
1719
1772
  const existingFiles = await detectExistingSystemPrompts(cwd);
1720
1773
  let skipFiles = [];
1721
1774
  if (existingFiles.length > 0) {
1722
1775
  console.log("");
1723
1776
  console.log(chalk11.yellow(`Found existing: ${existingFiles.join(", ")}`));
1724
1777
  const action = await select({
1725
- message: "How would you like to proceed?",
1778
+ message: "How would you like to handle existing AGENTS.md?",
1726
1779
  choices: [
1727
1780
  {
1728
- name: "Merge - Add LeanSpec section to existing files",
1729
- value: "merge",
1730
- description: "Appends LeanSpec guidance to your existing AGENTS.md"
1781
+ name: "AI-Assisted Merge (recommended)",
1782
+ value: "merge-ai",
1783
+ description: "Creates prompt for AI to intelligently consolidate both files"
1731
1784
  },
1732
1785
  {
1733
- name: "Backup - Save existing and create new",
1734
- value: "backup",
1735
- description: "Renames existing files to .backup and creates fresh ones"
1786
+ name: "Simple Append",
1787
+ value: "merge-append",
1788
+ description: "Quickly appends LeanSpec section (may be verbose)"
1736
1789
  },
1737
1790
  {
1738
- name: "Skip - Keep existing files as-is",
1791
+ name: "Replace with LeanSpec",
1792
+ value: "overwrite",
1793
+ description: "Backs up existing, creates fresh AGENTS.md from template"
1794
+ },
1795
+ {
1796
+ name: "Keep Existing Only",
1739
1797
  value: "skip",
1740
- description: "Only adds .lspec config and specs/ directory"
1798
+ description: "Skips AGENTS.md, only adds .lean-spec config and specs/"
1741
1799
  }
1742
1800
  ]
1743
1801
  });
@@ -3035,7 +3093,7 @@ function renderColumn(title, emoji, specs, expanded, colorFn) {
3035
3093
  }
3036
3094
  console.log("");
3037
3095
  } else if (!expanded && specs.length > 0) {
3038
- console.log(` ${chalk15.dim("(collapsed, use --show-complete to expand)")}`);
3096
+ console.log(` ${chalk15.dim("(collapsed, use --complete to expand)")}`);
3039
3097
  console.log("");
3040
3098
  } else {
3041
3099
  console.log(` ${chalk15.dim("(empty)")}`);
@@ -3701,26 +3759,28 @@ async function depsCommand(specPath, options) {
3701
3759
  console.log("");
3702
3760
  console.log(chalk18.green(`\u{1F4E6} Dependencies for ${chalk18.cyan(sanitizeUserInput(spec.path))}`));
3703
3761
  console.log("");
3704
- console.log(chalk18.bold("Depends On:"));
3762
+ const hasAnyRelationships = dependsOn.length > 0 || blocks.length > 0 || relatedSpecs.length > 0;
3763
+ if (!hasAnyRelationships) {
3764
+ console.log(chalk18.gray(" No dependencies or relationships"));
3765
+ console.log("");
3766
+ return;
3767
+ }
3705
3768
  if (dependsOn.length > 0) {
3769
+ console.log(chalk18.bold("Depends On:"));
3706
3770
  for (const dep of dependsOn) {
3707
3771
  const status = getStatusIndicator(dep.frontmatter.status);
3708
3772
  console.log(` \u2192 ${sanitizeUserInput(dep.path)} ${status}`);
3709
3773
  }
3710
- } else {
3711
- console.log(chalk18.gray(" (none)"));
3774
+ console.log("");
3712
3775
  }
3713
- console.log("");
3714
- console.log(chalk18.bold("Blocks:"));
3715
3776
  if (blocks.length > 0) {
3777
+ console.log(chalk18.bold("Required By:"));
3716
3778
  for (const blocked of blocks) {
3717
3779
  const status = getStatusIndicator(blocked.frontmatter.status);
3718
3780
  console.log(` \u2190 ${sanitizeUserInput(blocked.path)} ${status}`);
3719
3781
  }
3720
- } else {
3721
- console.log(chalk18.gray(" (none)"));
3782
+ console.log("");
3722
3783
  }
3723
- console.log("");
3724
3784
  if (relatedSpecs.length > 0) {
3725
3785
  console.log(chalk18.bold("Related Specs:"));
3726
3786
  for (const rel of relatedSpecs) {
@@ -3744,8 +3804,8 @@ function findDependencies(spec, specMap) {
3744
3804
  if (dep) {
3745
3805
  deps.push(dep);
3746
3806
  } else {
3747
- for (const [path20, s] of specMap.entries()) {
3748
- if (path20.includes(depPath)) {
3807
+ for (const [path19, s] of specMap.entries()) {
3808
+ if (path19.includes(depPath)) {
3749
3809
  deps.push(s);
3750
3810
  break;
3751
3811
  }
@@ -3777,8 +3837,8 @@ function findRelated(spec, specMap) {
3777
3837
  if (rel) {
3778
3838
  related.push(rel);
3779
3839
  } else {
3780
- for (const [path20, s] of specMap.entries()) {
3781
- if (path20.includes(relPath)) {
3840
+ for (const [path19, s] of specMap.entries()) {
3841
+ if (path19.includes(relPath)) {
3782
3842
  related.push(s);
3783
3843
  break;
3784
3844
  }
@@ -4432,7 +4492,6 @@ async function mcpCommand() {
4432
4492
  }
4433
4493
 
4434
4494
  // src/mcp-server.ts
4435
- import * as path19 from "path";
4436
4495
  function formatErrorMessage(prefix, error) {
4437
4496
  const errorMsg = error instanceof Error ? error.message : String(error);
4438
4497
  return `${prefix}: ${errorMsg}`;
@@ -4496,20 +4555,22 @@ async function searchSpecsData(query, options) {
4496
4555
  return results;
4497
4556
  }
4498
4557
  async function readSpecData(specPath) {
4499
- const config = await loadConfig();
4500
4558
  const cwd = process.cwd();
4501
- const specsDir = path19.join(cwd, config.specsDir);
4502
- const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
4503
- if (!resolvedPath) {
4504
- throw new Error(`Spec not found: ${specPath}`);
4505
- }
4506
- const specInfo = await getSpec(resolvedPath);
4507
- if (!specInfo) {
4559
+ const specContent = await readSpecContent(specPath, cwd);
4560
+ if (!specContent) {
4508
4561
  throw new Error(`Spec not found: ${specPath}`);
4509
4562
  }
4510
4563
  return {
4511
- spec: specToData(specInfo),
4512
- content: specInfo.content || ""
4564
+ spec: {
4565
+ name: specContent.name,
4566
+ path: specContent.path,
4567
+ status: specContent.frontmatter.status,
4568
+ created: String(specContent.frontmatter.created),
4569
+ priority: specContent.frontmatter.priority,
4570
+ tags: specContent.frontmatter.tags,
4571
+ assignee: specContent.frontmatter.assignee
4572
+ },
4573
+ content: specContent.content
4513
4574
  };
4514
4575
  }
4515
4576
  async function getStatsData() {
@@ -4665,7 +4726,7 @@ async function createMcpServer() {
4665
4726
  title: "View Spec",
4666
4727
  description: "Read the complete content of a specification. Use this to understand spec details, review design decisions, or check implementation status. Returns metadata and full content.",
4667
4728
  inputSchema: {
4668
- specPath: z.string().describe('The spec to view. Can be: spec name (e.g., "unified-dashboard"), sequence number (e.g., "045" or "45"), or full folder name (e.g., "045-unified-dashboard").'),
4729
+ specPath: z.string().describe('The spec to view. Can be: spec name (e.g., "unified-dashboard"), sequence number (e.g., "045" or "45"), full folder name (e.g., "045-unified-dashboard"), or sub-spec file (e.g., "045/DESIGN.md" or "unified-dashboard/TESTING.md").'),
4669
4730
  raw: z.boolean().optional().describe("Output raw markdown instead of formatted"),
4670
4731
  json: z.boolean().optional().describe("Output as JSON instead of formatted")
4671
4732
  },
@@ -5365,4 +5426,4 @@ export {
5365
5426
  createMcpServer,
5366
5427
  mcpCommand
5367
5428
  };
5368
- //# sourceMappingURL=chunk-GLXYUS7F.js.map
5429
+ //# sourceMappingURL=chunk-OXTU3PN4.js.map