dotdog 0.8.0 → 0.8.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.
Files changed (2) hide show
  1. package/dist/cli.js +48 -12
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -3421,7 +3421,7 @@ function serve(dir = ".") {
3421
3421
  project: P(dag),
3422
3422
  nodes: N(dag).length,
3423
3423
  edges: E(dag).length,
3424
- version: dag.v || dag.version || "",
3424
+ version: dag.v || dag.version || (Array.isArray(dag) ? `${dag[0]}` : "unknown"),
3425
3425
  order: dag.o || [],
3426
3426
  cycles: dag.cy !== undefined ? dag.cy : null,
3427
3427
  savings: tk.sv || tk.savings_pct || 0,
@@ -3464,6 +3464,18 @@ function serve(dir = ".") {
3464
3464
  }
3465
3465
 
3466
3466
  // src/cli.ts
3467
+ function normalizeDag(dag) {
3468
+ if (Array.isArray(dag)) {
3469
+ const v3Nodes = (dag[2] || []).map((n, i) => {
3470
+ const props = n[2] || [];
3471
+ const states = n[3] || [];
3472
+ const edges = n[4] || [];
3473
+ return [i, n[0], n[1] === "p" ? "prediction" : "entity", "", props, states, edges];
3474
+ });
3475
+ return { v: dag[0], p: dag[1], n: v3Nodes, tk: dag[3] };
3476
+ }
3477
+ return dag;
3478
+ }
3467
3479
  function resolvePath2(p) {
3468
3480
  if (p.startsWith("~"))
3469
3481
  p = join3(homedir2(), p.slice(1));
@@ -3645,7 +3657,7 @@ ${s.length} sections`));
3645
3657
  for (const sec of s)
3646
3658
  console.log(` ${sec.heading.padEnd(30)} ${sec.content.length} chars`);
3647
3659
  });
3648
- program2.command("compile [dir]").option("-o, --output <file>").action((d = ".", opts) => {
3660
+ program2.command("compile [dir]").option("-o, --output <file>").option("--v3", "Ultra-compact v3 format (53% smaller than v2)").action((d = ".", opts) => {
3649
3661
  const dir = resolvePath2(d);
3650
3662
  const dirs = [join3(dir, "projects"), join3(dir, "specs"), dir];
3651
3663
  let found = false;
@@ -3795,16 +3807,36 @@ program2.command("compile [dir]").option("-o, --output <file>").action((d = ".",
3795
3807
  }
3796
3808
  v2nodes.push(entry);
3797
3809
  }
3798
- const dag = { v: 2, p, n: v2nodes };
3799
- const dagJson = JSON.stringify(dag);
3800
- const dagTokens = Math.round(Buffer.byteLength(dagJson, "utf-8") / 4);
3810
+ const outPath = opts.output || join3(pd, `${p}.dag`);
3811
+ const v2dag = { v: 2, p, n: v2nodes };
3812
+ const v2Json = JSON.stringify(v2dag);
3813
+ const dagTokens = Math.round(Buffer.byteLength(v2Json, "utf-8") / 4);
3801
3814
  const allSavingsPct = sourceTokens > 0 ? Math.round((1 - dagTokens / sourceTokens) * 1000) / 10 : 0;
3802
3815
  const contentSavingsPct = contentTokens > 0 ? Math.round((1 - dagTokens / contentTokens) * 1000) / 10 : 0;
3803
3816
  const savingsTokens = sourceTokens - dagTokens;
3804
- const outPath = opts.output || join3(pd, `${p}.dag`);
3805
3817
  const tokens = { m: "chars/4", st: sourceTokens, ct: contentTokens, dt: dagTokens, sv: allSavingsPct, cs: contentSavingsPct, saved: savingsTokens };
3806
- const report = { ...dag, tk: tokens };
3807
- writeFileSync2(outPath, JSON.stringify(report, null, 2));
3818
+ const v3dag = [3, p, v2nodes.map((n) => {
3819
+ const nd2 = nodes[n[0]];
3820
+ const tc = nd2.g === "prediction" ? "p" : "e";
3821
+ const st = nd2.s && nd2.s.length ? nd2.s : null;
3822
+ const ed = n[6] && n[6].length ? n[6] : null;
3823
+ const entry = [nd2.i, tc, n[4].length ? n[4] : null, st, ed];
3824
+ if (nd2.g === "prediction") {
3825
+ const f = [];
3826
+ if (nd2.cf != null)
3827
+ f.push(nd2.cf);
3828
+ if (nd2.tf)
3829
+ f.push(nd2.tf);
3830
+ if (f.length)
3831
+ entry.push(f);
3832
+ }
3833
+ return entry;
3834
+ }), tokens];
3835
+ const dag = opts.v3 ? v3dag : v2dag;
3836
+ const dagJson = JSON.stringify(dag);
3837
+ const report = opts.v3 ? [...dag, tokens] : { ...dag, tk: tokens };
3838
+ writeFileSync2(outPath, JSON.stringify(report, null, 2) + `
3839
+ `);
3808
3840
  console.log(source_default.green(` ✓ ${outPath}`));
3809
3841
  console.log(source_default.gray(` ${nodes.length} nodes, ${edges.length} edges, ${files.length} files`));
3810
3842
  console.log(source_default.gray(` ${sourceTokens} → ${dagTokens} tokens (${allSavingsPct}% savings, ${contentSavingsPct}% content-only, ${savingsTokens} saved)`));
@@ -3869,7 +3901,8 @@ program2.command("visualize [dir]").option("-s, --save").action((d = ".", opts)
3869
3901
  if (!existsSync3(dagFile))
3870
3902
  continue;
3871
3903
  const dag = JSON.parse(readFileSync3(dagFile, "utf-8"));
3872
- const nodes = dag.n || dag.nodes || [];
3904
+ const d2 = normalizeDag(dag);
3905
+ const nodes = d2.n || dag.nodes || [];
3873
3906
  const isV22 = (n) => Array.isArray(n) && typeof n[0] === "number";
3874
3907
  const nodeName2 = (n) => isV22(n) ? nodes[n[0]] ? nodes[n[0]][1] || String(n[0]) : String(n[0]) : n.i || n.id || "";
3875
3908
  const slug = (s) => s.replace(/\s+/g, "_").replace(/^[^a-zA-Z]+/, "n_");
@@ -4209,7 +4242,8 @@ program2.command("simulate <scenario>").description("Walk through a scenario, ch
4209
4242
  let entities = [], relationships = [];
4210
4243
  if (existsSync3(dagFile)) {
4211
4244
  const dag = JSON.parse(readFileSync3(dagFile, "utf-8"));
4212
- const simNodes = dag.n || dag.nodes || [];
4245
+ const d2 = normalizeDag(dag);
4246
+ const simNodes = d2.n || dag.nodes || [];
4213
4247
  const isV22 = (n) => Array.isArray(n) && typeof n[0] === "number";
4214
4248
  entities = simNodes.map((n) => (isV22(n) ? n[1] || String(n[0]) : n.i || n.id || "").toLowerCase());
4215
4249
  if (dag.e || dag.edges) {
@@ -4380,7 +4414,8 @@ program2.command("verify [dir]").description("Verify spec-code alignment. --init
4380
4414
  if (opts.init) {
4381
4415
  const entities = [];
4382
4416
  const props = new Map;
4383
- for (const node of dag.n || []) {
4417
+ const d3 = normalizeDag(dag);
4418
+ for (const node of d3.n || []) {
4384
4419
  const name = node[1] || String(node[0]);
4385
4420
  entities.push(name);
4386
4421
  if (node[4])
@@ -4730,7 +4765,8 @@ program2.command("badge [dir]").description("Generate dotdog-badge.svg (shields.
4730
4765
  console.log(source_default.red(` No .dag for ${p}. Run dotdog compile first.`));
4731
4766
  continue;
4732
4767
  }
4733
- const dag = JSON.parse(readFileSync3(dagFile, "utf-8"));
4768
+ const rawDag = JSON.parse(readFileSync3(dagFile, "utf-8"));
4769
+ const dag = normalizeDag(rawDag);
4734
4770
  const saved = dag.tk && dag.tk.saved ? dag.tk.saved : 0;
4735
4771
  const fmt = saved >= 1000 ? `${(saved / 1000).toFixed(1)}K` : `${saved}`;
4736
4772
  const label = "dotdog";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotdog",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
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",