dotdog 0.5.0 → 0.5.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 +122 -11
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2751,7 +2751,7 @@ function parseBlocks(lines, start, end) {
2751
2751
  let i = start;
2752
2752
  while (i < end) {
2753
2753
  const line = lines[i];
2754
- const entityMatch = line.match(/^###\s+Entity:\s*(.+)/);
2754
+ const entityMatch = line.match(/^#{3,5}\s+Entity:\s*(.+)/);
2755
2755
  if (entityMatch) {
2756
2756
  const result = parseStructuredBlock(lines, i, end, "entity", entityMatch[1]);
2757
2757
  if (result) {
@@ -2760,7 +2760,7 @@ function parseBlocks(lines, start, end) {
2760
2760
  continue;
2761
2761
  }
2762
2762
  }
2763
- const relMatch = line.match(/^###\s+Relationship:\s*(.+)/);
2763
+ const relMatch = line.match(/^#{3,5}\s+Relationship:\s*(.+)/);
2764
2764
  if (relMatch) {
2765
2765
  const result = parseStructuredBlock(lines, i, end, "relationship", relMatch[1]);
2766
2766
  if (result) {
@@ -2769,7 +2769,7 @@ function parseBlocks(lines, start, end) {
2769
2769
  continue;
2770
2770
  }
2771
2771
  }
2772
- const eventMatch = line.match(/^###\s+Event:\s*(.+)/);
2772
+ const eventMatch = line.match(/^#{3,5}\s+Event:\s*(.+)/);
2773
2773
  if (eventMatch) {
2774
2774
  const result = parseStructuredBlock(lines, i, end, "event", eventMatch[1]);
2775
2775
  if (result) {
@@ -2778,7 +2778,7 @@ function parseBlocks(lines, start, end) {
2778
2778
  continue;
2779
2779
  }
2780
2780
  }
2781
- const predMatch = line.match(/^###\s+Prediction:\s*(.+)/);
2781
+ const predMatch = line.match(/^#{3,5}\s+Prediction:\s*(.+)/);
2782
2782
  if (predMatch) {
2783
2783
  const result = parseStructuredBlock(lines, i, end, "prediction", predMatch[1]);
2784
2784
  if (result) {
@@ -2787,6 +2787,83 @@ function parseBlocks(lines, start, end) {
2787
2787
  continue;
2788
2788
  }
2789
2789
  }
2790
+ if (lines[i].startsWith("```")) {
2791
+ let yamlEnd = i + 1;
2792
+ while (yamlEnd < end && !lines[yamlEnd].startsWith("```"))
2793
+ yamlEnd++;
2794
+ if (yamlEnd < end) {
2795
+ const yamlContent = lines.slice(i + 1, yamlEnd);
2796
+ const yaml = parseSimpleYAML(yamlContent);
2797
+ if (yaml.prediction) {
2798
+ blocks.push({
2799
+ kind: "prediction",
2800
+ statement: yaml.prediction || "",
2801
+ description: yaml.description || "",
2802
+ trigger: yaml.trigger || "",
2803
+ timeframe: yaml.timeframe || "",
2804
+ confidence: yaml.confidence || 0,
2805
+ measurement: yaml.measurement || "",
2806
+ status: yaml.status || "pending",
2807
+ yaml,
2808
+ lineStart: i + 1,
2809
+ lineEnd: yamlEnd
2810
+ });
2811
+ i = yamlEnd + 1;
2812
+ continue;
2813
+ }
2814
+ if (yaml.entity) {
2815
+ blocks.push({
2816
+ kind: "entity",
2817
+ name: yaml.entity || "",
2818
+ description: yaml.description || "",
2819
+ type: yaml.type || "node",
2820
+ properties: {},
2821
+ states: Array.isArray(yaml.states) ? yaml.states : [],
2822
+ lifecycle: [],
2823
+ yaml,
2824
+ lineStart: i + 1,
2825
+ lineEnd: yamlEnd
2826
+ });
2827
+ i = yamlEnd + 1;
2828
+ continue;
2829
+ }
2830
+ if (yaml.relationship || yaml.verb) {
2831
+ blocks.push({
2832
+ kind: "relationship",
2833
+ source: yaml.source || "",
2834
+ target: yaml.target || "",
2835
+ verb: yaml.verb || "connects",
2836
+ description: yaml.description || "",
2837
+ cardinality: yaml.cardinality || "N:M",
2838
+ required: false,
2839
+ cascade: "none",
2840
+ invariants: [],
2841
+ yaml,
2842
+ lineStart: i + 1,
2843
+ lineEnd: yamlEnd
2844
+ });
2845
+ i = yamlEnd + 1;
2846
+ continue;
2847
+ }
2848
+ if (yaml.event) {
2849
+ blocks.push({
2850
+ kind: "event",
2851
+ name: yaml.event || "",
2852
+ trigger: yaml.trigger || "",
2853
+ payload: {},
2854
+ preconditions: [],
2855
+ postconditions: [],
2856
+ sideEffects: [],
2857
+ probability: null,
2858
+ yaml,
2859
+ lineStart: i + 1,
2860
+ lineEnd: yamlEnd
2861
+ });
2862
+ i = yamlEnd + 1;
2863
+ continue;
2864
+ }
2865
+ }
2866
+ }
2790
2867
  if (/^\|.+\|/.test(line) && i + 1 < end && /^\|[-| ]+\|/.test(lines[i + 1])) {
2791
2868
  const table = parseTable(lines, i, end);
2792
2869
  if (table) {
@@ -2795,8 +2872,31 @@ function parseBlocks(lines, start, end) {
2795
2872
  continue;
2796
2873
  }
2797
2874
  }
2875
+ if (lines[i].startsWith("```")) {
2876
+ let yamlEnd = i + 1;
2877
+ while (yamlEnd < end && !lines[yamlEnd].startsWith("```"))
2878
+ yamlEnd++;
2879
+ if (yamlEnd < end && yamlEnd > i + 1) {
2880
+ const yamlContent = lines.slice(i + 1, yamlEnd);
2881
+ const yaml = parseSimpleYAML(yamlContent);
2882
+ const key = yaml.prediction ? "prediction" : yaml.entity ? "entity" : yaml.event ? "event" : yaml.relationship || yaml.verb ? "relationship" : null;
2883
+ if (key) {
2884
+ if (key === "prediction") {
2885
+ blocks.push({ kind: "prediction", statement: yaml.prediction || "", description: yaml.description || "", trigger: yaml.trigger || "", timeframe: yaml.timeframe || "", confidence: yaml.confidence || 0, measurement: yaml.measurement || "", status: yaml.status || "pending", yaml, lineStart: i + 1, lineEnd: yamlEnd });
2886
+ } else if (key === "entity") {
2887
+ blocks.push({ kind: "entity", name: yaml.entity || "", description: yaml.description || "", type: yaml.type || "node", properties: {}, states: Array.isArray(yaml.states) ? yaml.states : [], lifecycle: [], yaml, lineStart: i + 1, lineEnd: yamlEnd });
2888
+ } else if (key === "event") {
2889
+ blocks.push({ kind: "event", name: yaml.event || "", trigger: yaml.trigger || "", payload: {}, preconditions: [], postconditions: [], sideEffects: [], probability: null, yaml, lineStart: i + 1, lineEnd: yamlEnd });
2890
+ } else if (key === "relationship") {
2891
+ blocks.push({ kind: "relationship", source: yaml.source || "", target: yaml.target || "", verb: yaml.verb || "connects", description: yaml.description || "", cardinality: yaml.cardinality || "N:M", required: false, cascade: "none", invariants: [], yaml, lineStart: i + 1, lineEnd: yamlEnd });
2892
+ }
2893
+ i = yamlEnd + 1;
2894
+ continue;
2895
+ }
2896
+ }
2897
+ }
2798
2898
  const proseStart = i;
2799
- while (i < end && !isBlockStart(lines[i])) {
2899
+ while (i < end && !isBlockStart(lines[i]) && !lines[i].startsWith("```")) {
2800
2900
  i++;
2801
2901
  }
2802
2902
  const proseLines = lines.slice(proseStart, i).filter((l) => l.trim() !== "" || i === proseStart + 1);
@@ -2813,7 +2913,7 @@ function parseBlocks(lines, start, end) {
2813
2913
  return blocks;
2814
2914
  }
2815
2915
  function isBlockStart(line) {
2816
- return /^###\s+(Entity|Relationship|Event|Prediction):/.test(line) || /^\|.+\|/.test(line);
2916
+ return /^#{3,5}\s+(Entity|Relationship|Event|Prediction):/.test(line) || /^\|.+\|/.test(line);
2817
2917
  }
2818
2918
  function parseStructuredBlock(lines, start, end, kind, headerRest) {
2819
2919
  let i = start + 1;
@@ -3390,7 +3490,7 @@ program2.command("validate [dir]").action((d = ".") => {
3390
3490
  const missing = ["SPEC.dog", "constitution.dog", "data-model.dog"].filter((f) => !files.includes(f));
3391
3491
  const optional = ["COPY.dog", "plan.dog", "DESIGN-SYSTEM.dog", "INDEX.dog"].filter((f) => !files.includes(f));
3392
3492
  console.log(source_default.bold(`
3393
- ${p} : ${files.length} .dog files, ${100 - Math.round((missing.length * 3 + optional.length) / 20 * 100)}% complete`));
3493
+ ${p} : ${files.length} .dog files, ${Math.max(0, 100 - Math.round(missing.length * 3 / 20 * 100))}% complete`));
3394
3494
  for (const f of files)
3395
3495
  console.log(source_default.gray(` ${f}`));
3396
3496
  if (missing.length) {
@@ -3398,7 +3498,7 @@ program2.command("validate [dir]").action((d = ".") => {
3398
3498
  hasErrors = true;
3399
3499
  }
3400
3500
  if (optional.length)
3401
- console.log(source_default.yellow(` Missing optional: ${optional.join(", ")}`));
3501
+ console.log(source_default.gray(` Optional: ${optional.join(", ")} — not required for 100%`));
3402
3502
  }
3403
3503
  }
3404
3504
  if (!found)
@@ -3832,7 +3932,7 @@ Spec Analysis
3832
3932
  for (const f of missingReq)
3833
3933
  gaps.push(`\uD83D\uDD34 ${f}: Missing required file`);
3834
3934
  for (const f of missingOpt)
3835
- gaps.push(`\uD83D\uDFE1 ${f}: Missing optional file`);
3935
+ gaps.push(`ℹ️ ${f}: Optional file not present`);
3836
3936
  const entityNames = new Set(allEntities.map((e) => e.name));
3837
3937
  for (const e of allEntities) {
3838
3938
  if (!e.description || e.description.length < 10)
@@ -4469,8 +4569,19 @@ program2.command("resolve <name>").description("Mark a prediction as correct, wr
4469
4569
  if (block.kind === "prediction") {
4470
4570
  const b = block;
4471
4571
  if ((b.statement || b.name || "").toLowerCase().includes(name.toLowerCase())) {
4472
- const searchFor = `### Prediction: ${b.statement || b.name}`;
4473
- const headingIdx = content.indexOf(searchFor);
4572
+ let headingIdx = -1;
4573
+ const stmt = b.statement || b.name || "";
4574
+ for (const prefix of ["###", "####", "#####"]) {
4575
+ for (const fmt of [`${prefix} Prediction: ${stmt}`, `${prefix} ${stmt}`]) {
4576
+ const idx = content.indexOf(fmt);
4577
+ if (idx >= 0) {
4578
+ headingIdx = idx;
4579
+ break;
4580
+ }
4581
+ }
4582
+ if (headingIdx >= 0)
4583
+ break;
4584
+ }
4474
4585
  if (headingIdx >= 0) {
4475
4586
  const blockStart = content.indexOf("```yaml", headingIdx);
4476
4587
  const blockEnd = content.indexOf("```", blockStart + 7);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dotdog",
3
- "version": "0.5.0",
3
+ "version": "0.5.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",