dotdog 0.3.0 → 0.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/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ ## 0.3.1
4
+
5
+ - Fix npm packaging: homepage, bugs, engines, repository fields
6
+ - Trim keywords to 8 specific terms
7
+ - Ship correct README, LICENSE, and CHANGELOG in package
8
+ - CLI help text uses colons, no em dashes
9
+
10
+ ## 0.3.0
11
+
12
+ - `dotdog analyze` — deep project analysis: score, gaps, entity audit
13
+ - `dotdog generate` — generate missing spec files from SPEC.dog
14
+ - `dotdog simulate` — run simulation scenarios
15
+ - `.dag` v1.2: provable token savings, typed nodes and edges
16
+ - VS Code extension: syntax highlighting for .dog files
17
+ - GitHub Pages and llms.txt for AI agent discoverability
18
+ - `dotdog serve` MCP server: getEntity, traverse, search, schema, summary
19
+ - Path traversal guard, traverse depth cap, serve hardening
20
+
21
+ ## 0.2.0
22
+
23
+ - `dotdog compile` — compile .dog files to .dag graph
24
+ - `dotdog visualize` — Mermaid graph output with --save flag
25
+ - MCP server: expose .dag graph to AI agents over stdio
26
+ - `dotdog staleness` — detect drift between spec and reality
27
+ - `dotdog init` — scaffold new spec genome projects
28
+ - `dotdog list` — list all projects and .dog file counts
29
+
30
+ ## 0.1.0
31
+
32
+ - `.dog` file format v1.0
33
+ - `.dag` file format v1.0
34
+ - `dotdog validate` — validate spec completeness
35
+ - `dotdog parse` — parse .dog files
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 specdog
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,76 +1,130 @@
1
- # spec-platform
1
+ # dotdog
2
2
 
3
- Monorepo for the Spec Platform — a knowledge graph system where specs ARE the database and LLMs ARE the query engine.
3
+ [![npm version](https://img.shields.io/npm/v/dotdog)](https://www.npmjs.com/package/dotdog)
4
+ [![npm downloads](https://img.shields.io/npm/dm/dotdog)](https://www.npmjs.com/package/dotdog)
5
+ [![License: MIT](https://img.shields.io/npm/l/dotdog)](https://github.com/specdog/dotdog/blob/main/LICENSE)
6
+ [![CI](https://github.com/specdog/dotdog/actions/workflows/test.yml/badge.svg)](https://github.com/specdog/dotdog/actions)
4
7
 
5
- ## The Flywheel
8
+ > **Feed the dog. Ship with specs.** Write .dog specs. Dog checks them. AI agents fetch them.
6
9
 
7
- ```
8
- spec → validate → app → data → better spec → better app → ...
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install -g dotdog
9
14
  ```
10
15
 
11
- The spec describes the platform. The platform validates the spec. The validation report improves the spec. Each cycle adds granularity.
16
+ Requires Node.js >= 20.
12
17
 
13
- ## Structure
18
+ ## Quick Start
14
19
 
20
+ ```bash
21
+ dotdog init my-project # scaffold a spec genome
22
+ dotdog validate # score completeness (0-100%)
23
+ dotdog analyze # deep analysis : gaps, suggestions, entity audit
15
24
  ```
16
- spec-platform/
17
- ├── packages/
18
- │ ├── spec-engine/ # Core types and ontology (shared by everything)
19
- │ ├── spec-mcp/ # MCP Server — AI agents query specs via stdio
20
- │ └── spec-cli/ # CLI — spec validate, init, simulate, list
21
- ├── projects/ # Spec genomes (dogfooding)
22
- │ └── spec-platform/
23
- │ └── specs/
24
- │ ├── SPEC.dog # Product spec screens, flows, stories
25
- │ ├── constitution.dog # Immutable rules
26
- │ └── data-model.dog # Graph ontology nodes, edges, tasks, predictions, vectors
27
- ├── templates/ # Spec genome templates for new projects
28
- └── package.json # Bun workspace root
25
+
26
+ ## Commands
27
+
28
+ | Command | Description |
29
+ |---------|-------------|
30
+ | `dotdog validate [dir]` | Score spec completeness. Checks file existence, entity descriptions, section counts. |
31
+ | `dotdog analyze [dir]` | Deep analysis. Detects domain, stack, gaps with severity, entity quality audit. |
32
+ | `dotdog parse <file>` | Parse a `.dog` file into sections. |
33
+ | `dotdog compile [dir]` | Compile `.dog` files into a `.dag` graph (JSON). |
34
+ | `dotdog visualize [dir]` | Output Mermaid graph from `.dag`. `--save` writes `.md` for GitHub rendering. |
35
+ | `dotdog serve [dir]` | Start MCP server over stdio. AI agents query specs without hallucination. |
36
+ | `dotdog staleness [dir]` | Detect drift between spec and reality. Compares plan.dog tasks against code. |
37
+ | `dotdog generate [dir]` | Generate missing spec files from SPEC.dog (data-model, COPY, INDEX). |
38
+ | `dotdog simulate <scenario>` | Run a simulation scenario. Reads SPEC.dog scenarios, checks pre/postconditions. |
39
+ | `dotdog init <project>` | Scaffold a new spec genome project with templates. |
40
+ | `dotdog list` | List all projects and their `.dog` file counts. |
41
+
42
+ ## File Formats
43
+
44
+ ### `.dog` : Human-Written Spec Genome
45
+
46
+ Markdown prose + YAML structured blocks. Free and open source. Define entities, relationships, events, predictions, and copy in a single format that both humans and parsers understand.
47
+
48
+ ```markdown
49
+ ### Entity: User
50
+
51
+ A person who uses the app.
52
+
53
+ ` ``yaml
54
+ entity: User
55
+ type: entity
56
+ properties:
57
+ id:
58
+ type: string
59
+ required: true
60
+ email:
61
+ type: string
62
+ required: true
63
+ states: [active, suspended]
64
+ lifecycle: active → suspended
65
+ ` ``
29
66
  ```
30
67
 
31
- ## Quick Start
68
+ ### `.dag` : Machine-Compiled Graph
32
69
 
33
- ```bash
34
- bun install
35
- cd projects/spec-platform/specs
70
+ JSON graph compiled from `.dog` files. Nodes, edges, properties, and states in a deterministic structure. 85% token savings vs raw `.dog` files for AI agents.
36
71
 
37
- # Validate our own spec (dogfood)
38
- bun ../../../packages/spec-cli/src/index.ts validate ../..
72
+ ## MCP Server : AI Agent Integration
39
73
 
40
- # List projects
41
- bun ../../../packages/spec-cli/src/index.ts list
42
- ```
74
+ `dotdog serve` exposes specs to any MCP-compatible AI agent over stdio. Six tools:
43
75
 
44
- ## $0 Stack
76
+ | Tool | Description |
77
+ |------|-------------|
78
+ | `getEntity` | Exact entity with properties, states, lifecycle, and connected edges |
79
+ | `traverse` | BFS subgraph from any starting node to any depth |
80
+ | `search` | Find entities by name or type |
81
+ | `schema` | Property definitions only : zero prose, agent-optimized |
82
+ | `summary` | Node count, edge count, file count, compile time |
83
+ | `listProjects` | Array of project names |
45
84
 
46
- | Component | Technology | Cost |
47
- |-----------|-----------|------|
48
- | Runtime | Bun | $0 |
49
- | Database | bun:sqlite (embedded) | $0 |
50
- | Types | TypeScript (strict) | $0 |
51
- | CLI | Commander.js + chalk | $0 |
52
- | MCP Server | @modelcontextprotocol/sdk (stdio) | $0 |
53
- | Embeddings | all-MiniLM-L6-v2 (local) | $0 |
54
- | Hosting | None needed (local-first) | $0 |
85
+ Agent workflow: `listProjects` `getEntity` `traverse` graph.
55
86
 
56
- ## The Spec Graph
87
+ ## Dogfood
57
88
 
58
- The spec is not a document. It's a knowledge graph.
89
+ dotdog validates its own specs. Every PR:
90
+
91
+ ```
92
+ dotdog validate → find gaps → fix spec → PR → merge → tag → CI publish
93
+ ```
59
94
 
60
- - **Nodes**: entities, tasks, predictions, screens, constraints, user stories
61
- - **Edges**: contains, depends_on, implements, references, calls, precedes
62
- - **Vectors**: every section embedded for semantic search, contradiction detection, staleness checks
63
- - **Predictions**: forecasts with triggers, timeframes, confidence, and actual outcome tracking
95
+ Eat your own dogfood. The tool is the project.
64
96
 
65
- LLMs traverse the graph at query time. They don't read prose and guess — they get exact typed values.
97
+ ## VS Code Extension
66
98
 
67
- ## Score
99
+ Syntax highlighting for `.dog` files. Install:
68
100
 
101
+ ```bash
102
+ cp -r extensions/vscode ~/.vscode/extensions/dotdog
69
103
  ```
70
- spec validate → 43% complete
71
104
 
72
- SPEC.dog
73
- ✓ constitution.dog
74
- data-model.dog
75
- COPY.dog, DESIGN-SYSTEM.dog, plan.dog, INDEX.dog
105
+ ## Format Specifications
106
+
107
+ - [`.dog` format spec](spec/format-spec.dog) : language definition, EBNF grammar, validation rules
108
+ - [`.dag` format spec](spec/format-spec-dag.dog) : graph definition, MCP API, token efficiency
109
+
110
+ ## Links
111
+
112
+ - **GitHub:** [specdog/dotdog](https://github.com/specdog/dotdog)
113
+ - **npm:** [dotdog](https://www.npmjs.com/package/dotdog)
114
+ - **Docs:** [GitHub Pages](https://specdog.github.io/dotdog)
115
+ - **llms.txt:** [llms.txt](llms.txt) : structured for AI agent discovery
116
+ - **AGENTS.md:** [AGENTS.md](AGENTS.md) : instructions for AI coding agents
117
+
118
+ ## Spec-Driven Development
119
+
120
+ dotdog is built for SDD. Write your spec first. Validate it. Compile it. Let AI agents query it. The spec is the source of truth.
121
+
122
+ ```
123
+ spec → validate → compile → serve → AI agent queries
76
124
  ```
125
+
126
+ No more specs that rot in a wiki. No more agents guessing from prose. One source. Zero ambiguity.
127
+
128
+ ## License
129
+
130
+ MIT
package/dist/cli.js CHANGED
@@ -2535,7 +2535,7 @@ var source_default = chalk;
2535
2535
 
2536
2536
  // src/cli.ts
2537
2537
  import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2, mkdirSync, writeFileSync } from "fs";
2538
- import { join as join2 } from "path";
2538
+ import { join as join2, resolve as resolve2 } from "path";
2539
2539
  import { homedir as homedir2 } from "os";
2540
2540
  import { createHash } from "crypto";
2541
2541
 
@@ -2897,13 +2897,21 @@ function parseInlineObject(value) {
2897
2897
  }
2898
2898
  // src/serve.ts
2899
2899
  import { existsSync, readdirSync, readFileSync } from "fs";
2900
- import { join } from "path";
2900
+ import { join, resolve } from "path";
2901
2901
  import { homedir } from "os";
2902
2902
  import * as readline from "readline";
2903
2903
  function resolvePath(p) {
2904
2904
  if (p.startsWith("~"))
2905
2905
  p = join(homedir(), p.slice(1));
2906
- return p.startsWith("/") ? p : join(process.cwd(), p);
2906
+ const resolved = p.startsWith("/") ? p : join(process.cwd(), p);
2907
+ if (!p.startsWith("/") && !p.startsWith("~")) {
2908
+ const rel = resolve(process.cwd(), p);
2909
+ if (!rel.startsWith(process.cwd() + "/") && rel !== process.cwd()) {
2910
+ throw new Error(`Path traversal blocked: ${p}`);
2911
+ }
2912
+ return rel;
2913
+ }
2914
+ return resolved;
2907
2915
  }
2908
2916
  function serve(dir = ".") {
2909
2917
  const root = resolvePath(dir);
@@ -2978,7 +2986,7 @@ function serve(dir = ".") {
2978
2986
  const dag = dagCache.get(args.project || [...dagCache.keys()][0] || "");
2979
2987
  if (!dag)
2980
2988
  return { jsonrpc: "2.0", id, error: { code: 404, message: "Project not found" } };
2981
- const depth = args.depth || 1;
2989
+ const depth = Math.min(Math.max(1, args.depth || 1), 20);
2982
2990
  const visited = new Set;
2983
2991
  const subgraph = { nodes: [], edges: [] };
2984
2992
  const queue = [{ id: args.from, depth: 0 }];
@@ -3060,7 +3068,15 @@ function serve(dir = ".") {
3060
3068
  function resolvePath2(p) {
3061
3069
  if (p.startsWith("~"))
3062
3070
  p = join2(homedir2(), p.slice(1));
3063
- return p.startsWith("/") ? p : join2(process.cwd(), p);
3071
+ const resolved = p.startsWith("/") ? p : join2(process.cwd(), p);
3072
+ if (!p.startsWith("/") && !p.startsWith("~")) {
3073
+ const rel = resolve2(process.cwd(), p);
3074
+ if (!rel.startsWith(process.cwd() + "/") && rel !== process.cwd()) {
3075
+ throw new Error(`Path traversal blocked: ${p}`);
3076
+ }
3077
+ return rel;
3078
+ }
3079
+ return resolved;
3064
3080
  }
3065
3081
  function parseSections2(markdown) {
3066
3082
  const lines = markdown.split(`
@@ -3095,9 +3111,10 @@ function parseSections2(markdown) {
3095
3111
  }
3096
3112
  var program2 = new Command;
3097
3113
  var pkg = JSON.parse(readFileSync2(new URL("../package.json", import.meta.url), "utf-8"));
3098
- program2.name("spec").alias("dotdog").description("The spec dog validate, analyze, generate, simulate .dog files").version(pkg.version);
3114
+ program2.name("spec").alias("dotdog").description("CLI for structured software specs : validate .dog, compile .dag, query via MCP").version(pkg.version);
3099
3115
  program2.command("validate [dir]").action((d = ".") => {
3100
- const dirs = [join2(d, "projects"), join2(d, "specs")];
3116
+ const dir = resolvePath2(d);
3117
+ const dirs = [join2(dir, "projects"), join2(dir, "specs")];
3101
3118
  let found = false;
3102
3119
  for (const dd of dirs) {
3103
3120
  if (!existsSync2(dd))
@@ -3110,7 +3127,7 @@ program2.command("validate [dir]").action((d = ".") => {
3110
3127
  const missing = ["SPEC.dog", "constitution.dog", "data-model.dog"].filter((f) => !files.includes(f));
3111
3128
  const optional = ["COPY.dog", "plan.dog", "DESIGN-SYSTEM.dog", "INDEX.dog"].filter((f) => !files.includes(f));
3112
3129
  console.log(source_default.bold(`
3113
- ${p} ${files.length} .dog files, ${100 - Math.round((missing.length * 3 + optional.length) / 20 * 100)}% complete`));
3130
+ ${p} : ${files.length} .dog files, ${100 - Math.round((missing.length * 3 + optional.length) / 20 * 100)}% complete`));
3114
3131
  for (const f of files)
3115
3132
  console.log(source_default.gray(` ${f}`));
3116
3133
  if (missing.length)
@@ -3177,7 +3194,7 @@ ${d}/`));
3177
3194
  for (const p of projects) {
3178
3195
  const sp = join2(dd, p, "specs");
3179
3196
  const n = existsSync2(sp) ? readdirSync2(sp).filter((f) => f.endsWith(".dog")).length : 0;
3180
- console.log(` ${source_default.cyan(p)} ${n} .dog files`);
3197
+ console.log(` ${source_default.cyan(p)} : ${n} .dog files`);
3181
3198
  }
3182
3199
  }
3183
3200
  });
@@ -3286,7 +3303,7 @@ program2.command("visualize [dir]").option("-s, --save").action((d = ".", opts)
3286
3303
  out += "```\n";
3287
3304
  if (opts.save) {
3288
3305
  const outFile = join2(dd, p, "..", `${p}.md`);
3289
- writeFileSync(outFile, `# ${p} Spec Graph
3306
+ writeFileSync(outFile, `# ${p} : Spec Graph
3290
3307
 
3291
3308
  ${out}`);
3292
3309
  console.log(source_default.green(` ✓ ${outFile}`));
@@ -3295,8 +3312,8 @@ ${out}`);
3295
3312
  }
3296
3313
  }
3297
3314
  });
3298
- program2.command("serve [dir]").description("MCP server expose .dag graph to AI agents over stdio").action((d = ".") => serve(d));
3299
- program2.command("analyze [dir]").description("Analyze a spec project score, gaps, suggestions").option("-p, --project <name>").action((d = ".", opts) => {
3315
+ program2.command("serve [dir]").description("MCP server : expose .dag graph to AI agents over stdio").action((d = ".") => serve(resolvePath2(d)));
3316
+ program2.command("analyze [dir]").description("Analyze a spec project : score, gaps, suggestions").option("-p, --project <name>").action((d = ".", opts) => {
3300
3317
  const dir = resolvePath2(d);
3301
3318
  const dirs = [join2(dir, "projects"), join2(dir, "specs"), dir];
3302
3319
  console.log(source_default.bold(`
@@ -3344,7 +3361,7 @@ Spec Analysis
3344
3361
  console.log(` ${files.length} files | ${score}% complete`);
3345
3362
  for (const a of analyses) {
3346
3363
  const detail = a.entities > 0 ? ` (${a.entities} entities, ${a.rels} rels)` : "";
3347
- console.log(source_default.gray(` ${a.file} ${a.sections} sections, ${(a.size / 1024).toFixed(1)}KB${detail}`));
3364
+ console.log(source_default.gray(` ${a.file} : ${a.sections} sections, ${(a.size / 1024).toFixed(1)}KB${detail}`));
3348
3365
  }
3349
3366
  const gaps = [];
3350
3367
  for (const f of missingReq)
@@ -3495,7 +3512,7 @@ program2.command("simulate <scenario>").description("Run a simulation scenario (
3495
3512
  console.log(source_default.bold(`
3496
3513
  Simulation: ${scenario} (project: ${opts.project})
3497
3514
  `));
3498
- console.log(source_default.gray("Simulation engine reads SPEC.dog scenarios, walks through steps, checks pre/postconditions."));
3515
+ console.log(source_default.gray("Simulation engine : reads SPEC.dog scenarios, walks through steps, checks pre/postconditions."));
3499
3516
  console.log(source_default.gray("Full engine coming in a future release."));
3500
3517
  });
3501
3518
  program2.command("staleness [dir]").action((d = ".") => {
@@ -3556,6 +3573,13 @@ program2.command("staleness [dir]").action((d = ".") => {
3556
3573
  }
3557
3574
  }
3558
3575
  });
3576
+ program2.command("woof").action(() => {
3577
+ console.log(" / \\__");
3578
+ console.log(" ( @\\___");
3579
+ console.log(" / O");
3580
+ console.log(" / (_____/");
3581
+ console.log("/_____/ U");
3582
+ });
3559
3583
  program2.parse();
3560
3584
  export {
3561
3585
  parseToJSON,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dotdog",
3
- "version": "0.3.0",
4
- "description": "The spec dog structured, AI-queryable software specifications. Write .dog specs, compile to .dag graphs, query via MCP. Built for humans and AI agents.",
3
+ "version": "0.3.1",
4
+ "description": "CLI tool for structured software specifications. Validate .dog files, compile .dag graphs, query via MCP.",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",
7
7
  "bin": {
@@ -15,26 +15,28 @@
15
15
  "LICENSE"
16
16
  ],
17
17
  "keywords": [
18
- "spec",
19
18
  "specification",
20
- "ai",
21
- "agent",
22
- "mcp",
23
- "documentation",
24
19
  "cli",
25
- "spec-driven-development",
20
+ "mcp",
26
21
  "graph",
27
- "markdown",
28
- "yaml",
29
- "dotdog",
30
22
  "dag",
31
- "dog"
23
+ "yaml",
24
+ "markdown",
25
+ "spec-driven-development"
32
26
  ],
33
27
  "license": "MIT",
34
28
  "author": "specdog",
29
+ "homepage": "https://github.com/specdog/dotdog#readme",
30
+ "bugs": {
31
+ "url": "https://github.com/specdog/dotdog/issues"
32
+ },
35
33
  "repository": {
36
34
  "type": "git",
37
- "url": "git+https://github.com/specdog/dotdog.git"
35
+ "url": "https://github.com/specdog/dotdog.git",
36
+ "directory": "packages/dotdog"
37
+ },
38
+ "engines": {
39
+ "node": ">=20"
38
40
  },
39
41
  "dependencies": {
40
42
  "commander": "^15.0.0",