artifact-graph 0.9.1 → 0.9.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
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.2
4
+
5
+ ### Fixed
6
+
7
+ - Scenario explicit relation field recognition is tightened to whole-line field syntax matching:
8
+ plain prose mentions of `关联功能` / `关联决策` / `关联实体` no longer produce edges or
9
+ spurious `FORMAT_ERROR` diagnostics.
10
+ - An invalid explicit relation reference is no longer reported twice across the scan and
11
+ validation stages: `validateGraph` now returns exactly one `FORMAT_ERROR` carrying the file,
12
+ line number, node, invalid value, and the expected rule.
13
+ - Behavior tightening: Markdown list-item forms such as `- **关联决策**: ADR-0001` are no longer
14
+ recognized as explicit relation fields (0.9.1 misidentified them via substring matching);
15
+ standard line-start field syntax is unaffected.
16
+
3
17
  ## 0.9.1
4
18
 
5
19
  ### Fixed
package/dist/cli.js CHANGED
@@ -5072,6 +5072,7 @@ function validateScenarioPrdLinks(graph, schema = DEFAULT_SCHEMA) {
5072
5072
  }
5073
5073
  pushDuplicateIssues(issues, scenarioUid, validRefs, "feature");
5074
5074
  for (const ref of refs) {
5075
+ if (ref.valid === false) continue;
5075
5076
  if (!featurePattern.test(ref.target)) {
5076
5077
  issues.push(issue("FORMAT_ERROR", `scenario ${scenarioUid} has invalid feature reference ${ref.target}`, ref.path, ref.line, { node: scenarioUid }));
5077
5078
  }
@@ -6826,13 +6827,15 @@ function decisionFrontmatterEdges(path, decisionCode, value, targetType, kind) {
6826
6827
  return [edge(toUid("decision", decisionCode), toUid(targetType, code), kind, "frontmatter", path, 1)];
6827
6828
  });
6828
6829
  }
6830
+ function matchExplicitRelationFieldLine(line, label) {
6831
+ const escaped = escapeRegExp(label);
6832
+ const match = new RegExp(`^\\s*(?:\\*\\*${escaped}\\*\\*|${escaped})[:\uFF1A]\\s*(.*?)\\s*$`).exec(line);
6833
+ return match?.[1] ?? null;
6834
+ }
6829
6835
  function markdownRelationOccurrences(path, scenario, block, label, targetType, schema = DEFAULT_SCHEMA) {
6830
6836
  const result = [];
6831
6837
  block.forEach((line, index) => {
6832
- if (!line.includes(label)) {
6833
- return;
6834
- }
6835
- const relationText = line.split(/[::]/).slice(1).join(":").trim();
6838
+ const relationText = matchExplicitRelationFieldLine(line, label);
6836
6839
  if (!relationText) {
6837
6840
  return;
6838
6841
  }
@@ -6865,7 +6868,8 @@ function relationOccurrences(node, field, targetType) {
6865
6868
  target,
6866
6869
  path: typeof record.path === "string" ? record.path : node.path,
6867
6870
  line: typeof record.line === "number" ? record.line : node.line,
6868
- raw: typeof record.raw === "string" ? record.raw : void 0
6871
+ raw: typeof record.raw === "string" ? record.raw : void 0,
6872
+ valid: typeof record.valid === "boolean" ? record.valid : void 0
6869
6873
  }];
6870
6874
  });
6871
6875
  }
package/dist/index.cjs CHANGED
@@ -5050,6 +5050,7 @@ function validateScenarioPrdLinks(graph, schema = DEFAULT_SCHEMA) {
5050
5050
  }
5051
5051
  pushDuplicateIssues(issues, scenarioUid, validRefs, "feature");
5052
5052
  for (const ref of refs) {
5053
+ if (ref.valid === false) continue;
5053
5054
  if (!featurePattern.test(ref.target)) {
5054
5055
  issues.push(issue("FORMAT_ERROR", `scenario ${scenarioUid} has invalid feature reference ${ref.target}`, ref.path, ref.line, { node: scenarioUid }));
5055
5056
  }
@@ -6804,13 +6805,15 @@ function decisionFrontmatterEdges(path, decisionCode, value, targetType, kind) {
6804
6805
  return [edge(toUid("decision", decisionCode), toUid(targetType, code), kind, "frontmatter", path, 1)];
6805
6806
  });
6806
6807
  }
6808
+ function matchExplicitRelationFieldLine(line, label) {
6809
+ const escaped = escapeRegExp(label);
6810
+ const match = new RegExp(`^\\s*(?:\\*\\*${escaped}\\*\\*|${escaped})[:\uFF1A]\\s*(.*?)\\s*$`).exec(line);
6811
+ return match?.[1] ?? null;
6812
+ }
6807
6813
  function markdownRelationOccurrences(path, scenario, block, label, targetType, schema = DEFAULT_SCHEMA) {
6808
6814
  const result = [];
6809
6815
  block.forEach((line, index) => {
6810
- if (!line.includes(label)) {
6811
- return;
6812
- }
6813
- const relationText = line.split(/[::]/).slice(1).join(":").trim();
6816
+ const relationText = matchExplicitRelationFieldLine(line, label);
6814
6817
  if (!relationText) {
6815
6818
  return;
6816
6819
  }
@@ -6843,7 +6846,8 @@ function relationOccurrences(node, field, targetType) {
6843
6846
  target,
6844
6847
  path: typeof record.path === "string" ? record.path : node.path,
6845
6848
  line: typeof record.line === "number" ? record.line : node.line,
6846
- raw: typeof record.raw === "string" ? record.raw : void 0
6849
+ raw: typeof record.raw === "string" ? record.raw : void 0,
6850
+ valid: typeof record.valid === "boolean" ? record.valid : void 0
6847
6851
  }];
6848
6852
  });
6849
6853
  }
package/dist/index.js CHANGED
@@ -4940,6 +4940,7 @@ function validateScenarioPrdLinks(graph, schema = DEFAULT_SCHEMA) {
4940
4940
  }
4941
4941
  pushDuplicateIssues(issues, scenarioUid, validRefs, "feature");
4942
4942
  for (const ref of refs) {
4943
+ if (ref.valid === false) continue;
4943
4944
  if (!featurePattern.test(ref.target)) {
4944
4945
  issues.push(issue("FORMAT_ERROR", `scenario ${scenarioUid} has invalid feature reference ${ref.target}`, ref.path, ref.line, { node: scenarioUid }));
4945
4946
  }
@@ -6694,13 +6695,15 @@ function decisionFrontmatterEdges(path, decisionCode, value, targetType, kind) {
6694
6695
  return [edge(toUid("decision", decisionCode), toUid(targetType, code), kind, "frontmatter", path, 1)];
6695
6696
  });
6696
6697
  }
6698
+ function matchExplicitRelationFieldLine(line, label) {
6699
+ const escaped = escapeRegExp(label);
6700
+ const match = new RegExp(`^\\s*(?:\\*\\*${escaped}\\*\\*|${escaped})[:\uFF1A]\\s*(.*?)\\s*$`).exec(line);
6701
+ return match?.[1] ?? null;
6702
+ }
6697
6703
  function markdownRelationOccurrences(path, scenario, block, label, targetType, schema = DEFAULT_SCHEMA) {
6698
6704
  const result = [];
6699
6705
  block.forEach((line, index) => {
6700
- if (!line.includes(label)) {
6701
- return;
6702
- }
6703
- const relationText = line.split(/[::]/).slice(1).join(":").trim();
6706
+ const relationText = matchExplicitRelationFieldLine(line, label);
6704
6707
  if (!relationText) {
6705
6708
  return;
6706
6709
  }
@@ -6733,7 +6736,8 @@ function relationOccurrences(node, field, targetType) {
6733
6736
  target,
6734
6737
  path: typeof record.path === "string" ? record.path : node.path,
6735
6738
  line: typeof record.line === "number" ? record.line : node.line,
6736
- raw: typeof record.raw === "string" ? record.raw : void 0
6739
+ raw: typeof record.raw === "string" ? record.raw : void 0,
6740
+ valid: typeof record.valid === "boolean" ? record.valid : void 0
6737
6741
  }];
6738
6742
  });
6739
6743
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "artifact-graph",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Git-native Markdown artifact graph scanner and validator",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",