From ce3a6c0d2155a42032628ccc5b97c1cef063bef6 Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Wed, 28 Jan 2026 10:29:47 +0100 Subject: [PATCH 01/12] feat(reporting): add GitHub PR markdown renderer with trends and diff detail names - extend `DiffSummary` to include added/removed node/edge names and serialize them - humanize diff node/edge identifiers when building summaries - add `TrendPoint`/`TrendSummary` and include trends in `Report` - introduce `GitHubReportRenderer` for rich GitHub PR comment output - add comprehensive tests for GitHub renderer output and table alignment --- pacta/reporting/builder.py | 51 ++++ pacta/reporting/renderers/github.py | 302 ++++++++++++++++++++++++ pacta/reporting/types.py | 84 +++++++ tests/reporting/test_github_renderer.py | 293 +++++++++++++++++++++++ 4 files changed, 730 insertions(+) create mode 100644 pacta/reporting/renderers/github.py create mode 100644 tests/reporting/test_github_renderer.py diff --git a/pacta/reporting/builder.py b/pacta/reporting/builder.py index 8a4c135..7f61d43 100644 --- a/pacta/reporting/builder.py +++ b/pacta/reporting/builder.py @@ -1,3 +1,5 @@ +import json +import re from collections import Counter from collections.abc import Mapping, Sequence from dataclasses import replace @@ -189,11 +191,20 @@ def _normalize_diff(self, diff: Any | None) -> DiffSummary | None: if isinstance(diff, DiffSummary): return diff + # Extract detail names from SnapshotDiff.details if available + details = get_field(diff, "details", default={}) or {} + nodes_detail = details.get("nodes", {}) if isinstance(details, dict) else {} + edges_detail = details.get("edges", {}) if isinstance(details, dict) else {} + return DiffSummary( nodes_added=int(get_field(diff, "nodes_added", default=get_field(diff, "nodesAdded", default=0))), nodes_removed=int(get_field(diff, "nodes_removed", default=get_field(diff, "nodesRemoved", default=0))), edges_added=int(get_field(diff, "edges_added", default=get_field(diff, "edgesAdded", default=0))), edges_removed=int(get_field(diff, "edges_removed", default=get_field(diff, "edgesRemoved", default=0))), + added_node_names=tuple(_humanize_node(n) for n in nodes_detail.get("added", ())), + removed_node_names=tuple(_humanize_node(n) for n in nodes_detail.get("removed", ())), + added_edge_names=tuple(_humanize_edge(e) for e in edges_detail.get("added", ())), + removed_edge_names=tuple(_humanize_edge(e) for e in edges_detail.get("removed", ())), ) def _build_summary(self, violations: Sequence[Violation], engine_errors: Sequence[EngineError]) -> Summary: @@ -213,3 +224,43 @@ def _build_summary(self, violations: Sequence[Violation], engine_errors: Sequenc by_rule=dict(sorted(by_rule.items(), key=lambda kv: kv[0])), engine_errors=len(engine_errors), ) + + +# --- Diff key humanization --- + +_NODE_ID_RE = re.compile(r"^[a-z]+://[^:]+::(.+)$") + + +def _humanize_node(key: str) -> str: + """Turn 'python://code-root::src.domain.user' into 'src.domain.user'.""" + m = _NODE_ID_RE.match(key) + return m.group(1) if m else key + + +def _humanize_edge(key: str) -> str: + """Turn an edge key into 'src.fqname → dst.fqname'. + + Edge keys come in two forms: + 1) 'from_id->to_id:kind' (structured key) + 2) JSON blob from dumps_deterministic(e.to_dict()) + """ + # Form 1: structured key + if "->" in key and not key.startswith("{"): + arrow_idx = key.index("->") + from_part = key[:arrow_idx] + rest = key[arrow_idx + 2 :] + to_part = rest.split(":")[0] if ":" in rest else rest + return f"{_humanize_node(from_part)} → {_humanize_node(to_part)}" + + # Form 2: JSON blob — extract src/dst fqnames + try: + data = json.loads(key) + src = data.get("src", {}) + dst = data.get("dst", {}) + src_name = src.get("fqname", str(src)) + dst_name = dst.get("fqname", str(dst)) + return f"{src_name} → {dst_name}" + except (json.JSONDecodeError, TypeError, AttributeError): + pass + + return key diff --git a/pacta/reporting/renderers/github.py b/pacta/reporting/renderers/github.py new file mode 100644 index 0000000..a902743 --- /dev/null +++ b/pacta/reporting/renderers/github.py @@ -0,0 +1,302 @@ +from pacta.reporting.types import Report, Violation +from pacta.rules.explain import explain_violation + + +class GitHubReportRenderer: + """ + Rich Markdown output for GitHub PR comments. + + Renders a descriptive architecture report including structural changes, + violation details with suggestions, and architecture trends. + """ + + def __init__(self, *, max_detail_items: int = 10) -> None: + self._max_items = max_detail_items + + def render(self, report: Report) -> str: + lines: list[str] = [] + + lines.append(self._render_header(report)) + lines.append(self._render_structural_changes(report)) + lines.append(self._render_violations_summary(report)) + lines.append(self._render_new_violations(report)) + lines.append(self._render_existing_violations(report)) + lines.append(self._render_fixed_violations(report)) + lines.append(self._render_trends(report)) + lines.append(self._render_footer(report)) + + # Filter empty sections and join + return "\n".join(s for s in lines if s) + "\n" + + def _render_header(self, report: Report) -> str: + lines: list[str] = [] + + lines.append("## Architecture Report") + + parts: list[str] = [] + if report.run.branch: + parts.append(f"**Branch:** `{report.run.branch}`") + if report.run.commit: + short_commit = report.run.commit[:7] + parts.append(f"**Commit:** `{short_commit}`") + if report.run.baseline_ref: + parts.append(f"**Baseline:** `{report.run.baseline_ref}`") + + if parts: + lines.append(" | ".join(parts)) + lines.append("") + + return "\n".join(lines) + + def _render_structural_changes(self, report: Report) -> str: + if report.diff is None: + return "" + + d = report.diff + if d.nodes_added == 0 and d.nodes_removed == 0 and d.edges_added == 0 and d.edges_removed == 0: + return "" + + lines: list[str] = [] + lines.append("### Structural Changes") + lines.append("") + lines.append( + _aligned_table( + headers=["", "Added", "Removed"], + rows=[ + ["Modules/Classes", f"+{d.nodes_added}", f"-{d.nodes_removed}"], + ["Dependencies", f"+{d.edges_added}", f"-{d.edges_removed}"], + ], + ) + ) + lines.append("") + + if d.added_node_names: + items = d.added_node_names[: self._max_items] + names = ", ".join(f"`{n}`" for n in items) + overflow = len(d.added_node_names) - self._max_items + suffix = f" (+{overflow} more)" if overflow > 0 else "" + lines.append(f"**New modules:** {names}{suffix}") + + if d.removed_node_names: + items = d.removed_node_names[: self._max_items] + names = ", ".join(f"`{n}`" for n in items) + overflow = len(d.removed_node_names) - self._max_items + suffix = f" (+{overflow} more)" if overflow > 0 else "" + lines.append(f"**Removed modules:** {names}{suffix}") + + if d.added_edge_names: + items = d.added_edge_names[: self._max_items] + names = ", ".join(f"`{n}`" for n in items) + overflow = len(d.added_edge_names) - self._max_items + suffix = f" (+{overflow} more)" if overflow > 0 else "" + lines.append(f"**New dependencies:** {names}{suffix}") + + if d.removed_edge_names: + items = d.removed_edge_names[: self._max_items] + names = ", ".join(f"`{n}`" for n in items) + overflow = len(d.removed_edge_names) - self._max_items + suffix = f" (+{overflow} more)" if overflow > 0 else "" + lines.append(f"**Removed dependencies:** {names}{suffix}") + + if d.added_node_names or d.removed_node_names or d.added_edge_names or d.removed_edge_names: + lines.append("") + + return "\n".join(lines) + + def _render_violations_summary(self, report: Report) -> str: + s = report.summary + if s.total_violations == 0: + return "" + + has_baseline = report.run.baseline_ref is not None + + if has_baseline: + # Show status-based summary (new/existing/fixed) + rows: list[list[str]] = [] + for status in ("new", "existing", "fixed", "unknown"): + count = s.by_status.get(status, 0) + if count > 0: + label = {"new": "New", "existing": "Existing", "fixed": "Fixed", "unknown": "Unknown"}[status] + rows.append([label, str(count)]) + + lines: list[str] = [] + lines.append("### Violations Summary") + lines.append("") + lines.append(_aligned_table(headers=["Status", "Count"], rows=rows)) + else: + # No baseline: show severity-based summary + rows = [] + for sev in ("error", "warning", "info"): + count = s.by_severity.get(sev, 0) + if count > 0: + rows.append([sev.capitalize(), str(count)]) + + lines = [] + lines.append(f"### Violations ({s.total_violations} total)") + lines.append("") + lines.append(_aligned_table(headers=["Severity", "Count"], rows=rows)) + + lines.append("") + return "\n".join(lines) + + def _render_new_violations(self, report: Report) -> str: + has_baseline = report.run.baseline_ref is not None + + if has_baseline: + # With baseline: show only new violations + target = [v for v in report.violations if v.status == "new"] + if not target: + return "" + heading = "### New Violations (action required)" + else: + # Without baseline: show all violations + target = list(report.violations) + if not target: + return "" + heading = "### Violation Details" + + lines: list[str] = [] + lines.append(heading) + lines.append("") + + for v in target: + lines.extend(self._render_violation_block(v)) + lines.append("") + + return "\n".join(lines) + + def _render_existing_violations(self, report: Report) -> str: + has_baseline = report.run.baseline_ref is not None + if not has_baseline: + return "" + + existing = [v for v in report.violations if v.status == "existing"] + if not existing: + return "" + + lines: list[str] = [] + lines.append(f"### Existing Violations ({len(existing)})") + lines.append("") + lines.append("
") + lines.append("Click to expand") + lines.append("") + + for v in existing: + lines.extend(self._render_violation_block(v)) + lines.append("") + + lines.append("
") + lines.append("") + return "\n".join(lines) + + def _render_fixed_violations(self, report: Report) -> str: + fixed = [v for v in report.violations if v.status == "fixed"] + if not fixed: + return "" + + lines: list[str] = [] + lines.append("### Fixed Violations") + lines.append("") + + for v in fixed: + lines.append(f"- ~~`{v.rule.id}` — {v.rule.name}~~ (resolved)") + + lines.append("") + return "\n".join(lines) + + def _render_violation_block(self, v: Violation) -> list[str]: + lines: list[str] = [] + + sev = v.rule.severity.value.upper() if hasattr(v.rule.severity, "value") else str(v.rule.severity).upper() + + lines.append(f"> **{sev}** `{v.rule.id}` — {v.rule.name}") + + loc = "" + if v.location is not None: + loc = f"`{v.location.file}:{v.location.line}`" + + explanation = explain_violation(v) + if loc: + lines.append(f"> {loc} — {explanation}") + else: + lines.append(f"> {explanation}") + + if v.suggestion: + lines.append(f"> *{v.suggestion}*") + + return lines + + def _render_trends(self, report: Report) -> str: + if report.trends is None or not report.trends.points: + return "" + + t = report.trends + last_point = t.points[-1] + + metrics = [ + ("Violations", last_point.violations, t.violation_change), + ("Modules", last_point.nodes, t.node_change), + ("Dependencies", last_point.edges, t.edge_change), + ("Density", last_point.density, t.density_change), + ] + + rows: list[list[str]] = [] + for name, current, change in metrics: + trend = _trend_label(name, change) + current_str = f"{current:.2f}" if name == "Density" else f"{current:.0f}" + change_str = f"{change:+.2f}" if name == "Density" else f"{change:+.0f}" + rows.append([name, trend, current_str, change_str]) + + lines: list[str] = [] + lines.append(f"### Architecture Trends (last {len(t.points)} snapshots)") + lines.append("") + lines.append( + _aligned_table( + headers=["Metric", "Trend", "Current", "Change"], + rows=rows, + ) + ) + lines.append("") + return "\n".join(lines) + + def _render_footer(self, report: Report) -> str: + lines: list[str] = [] + lines.append("---") + lines.append(f"*Generated by [Pacta](https://github.com/akhundMurad/pacta) v{report.version}*") + return "\n".join(lines) + + +def _trend_label(metric_name: str, change: float) -> str: + if change < 0: + direction = "Improving" if metric_name == "Violations" else "Decreasing" + return f"↓ {direction}" + elif change > 0: + direction = "Worsening" if metric_name == "Violations" else "Growing" + return f"↑ {direction}" + else: + return "→ Stable" + + +def _aligned_table(headers: list[str], rows: list[list[str]]) -> str: + """Render a Markdown table with columns padded to equal width.""" + col_count = len(headers) + widths = [len(h) for h in headers] + for row in rows: + for i, cell in enumerate(row): + if i < col_count: + widths[i] = max(widths[i], len(cell)) + + def _fmt_row(cells: list[str]) -> str: + parts = [] + for i, cell in enumerate(cells): + parts.append(f" {cell:<{widths[i]}} ") + return "|" + "|".join(parts) + "|" + + lines = [ + _fmt_row(headers), + "|" + "|".join("-" * (w + 2) for w in widths) + "|", + ] + for row in rows: + lines.append(_fmt_row(row)) + + return "\n".join(lines) diff --git a/pacta/reporting/types.py b/pacta/reporting/types.py index 4e48dfe..9133d66 100644 --- a/pacta/reporting/types.py +++ b/pacta/reporting/types.py @@ -324,12 +324,21 @@ class DiffSummary: edges_added: int edges_removed: int + added_node_names: tuple[str, ...] = () + removed_node_names: tuple[str, ...] = () + added_edge_names: tuple[str, ...] = () + removed_edge_names: tuple[str, ...] = () + def to_dict(self) -> dict[str, Any]: return { "nodes_added": self.nodes_added, "nodes_removed": self.nodes_removed, "edges_added": self.edges_added, "edges_removed": self.edges_removed, + "added_node_names": list(self.added_node_names), + "removed_node_names": list(self.removed_node_names), + "added_edge_names": list(self.added_edge_names), + "removed_edge_names": list(self.removed_edge_names), } @staticmethod @@ -339,6 +348,77 @@ def from_dict(data: Mapping[str, Any]) -> "DiffSummary": nodes_removed=data["nodes_removed"], edges_added=data["edges_added"], edges_removed=data["edges_removed"], + added_node_names=tuple(data.get("added_node_names", ())), + removed_node_names=tuple(data.get("removed_node_names", ())), + added_edge_names=tuple(data.get("added_edge_names", ())), + removed_edge_names=tuple(data.get("removed_edge_names", ())), + ) + + +# Architecture trends + + +@dataclass(frozen=True, slots=True) +class TrendPoint: + """ + A single data point in the architecture trend timeline. + """ + + label: str + violations: float + nodes: float + edges: float + density: float + + def to_dict(self) -> dict[str, Any]: + return { + "label": self.label, + "violations": self.violations, + "nodes": self.nodes, + "edges": self.edges, + "density": self.density, + } + + @staticmethod + def from_dict(data: Mapping[str, Any]) -> "TrendPoint": + return TrendPoint( + label=data["label"], + violations=float(data["violations"]), + nodes=float(data["nodes"]), + edges=float(data["edges"]), + density=float(data["density"]), + ) + + +@dataclass(frozen=True, slots=True) +class TrendSummary: + """ + Architecture metric trends over recent snapshots. + """ + + points: tuple[TrendPoint, ...] + violation_change: float + node_change: float + edge_change: float + density_change: float + + def to_dict(self) -> dict[str, Any]: + return { + "points": [p.to_dict() for p in self.points], + "violation_change": self.violation_change, + "node_change": self.node_change, + "edge_change": self.edge_change, + "density_change": self.density_change, + } + + @staticmethod + def from_dict(data: Mapping[str, Any]) -> "TrendSummary": + return TrendSummary( + points=tuple(TrendPoint.from_dict(p) for p in data.get("points", ())), + violation_change=float(data["violation_change"]), + node_change=float(data["node_change"]), + edge_change=float(data["edge_change"]), + density_change=float(data["density_change"]), ) @@ -361,6 +441,7 @@ class Report: engine_errors: tuple[EngineError, ...] = () diff: DiffSummary | None = None + trends: TrendSummary | None = None def to_dict(self) -> dict[str, Any]: return { @@ -371,11 +452,13 @@ def to_dict(self) -> dict[str, Any]: "violations": [v.to_dict() for v in self.violations], "engine_errors": [e.to_dict() for e in self.engine_errors], "diff": None if self.diff is None else self.diff.to_dict(), + "trends": None if self.trends is None else self.trends.to_dict(), } @staticmethod def from_dict(data: Mapping[str, Any]) -> "Report": diff = data.get("diff") + trends = data.get("trends") return Report( tool=data["tool"], @@ -385,4 +468,5 @@ def from_dict(data: Mapping[str, Any]) -> "Report": violations=tuple(Violation.from_dict(v) for v in data.get("violations", ())), engine_errors=tuple(EngineError.from_dict(e) for e in data.get("engine_errors", ())), diff=None if diff is None else DiffSummary.from_dict(diff), + trends=None if trends is None else TrendSummary.from_dict(trends), ) diff --git a/tests/reporting/test_github_renderer.py b/tests/reporting/test_github_renderer.py new file mode 100644 index 0000000..a918a47 --- /dev/null +++ b/tests/reporting/test_github_renderer.py @@ -0,0 +1,293 @@ +from pacta.reporting.renderers.github import GitHubReportRenderer +from pacta.reporting.types import ( + DiffSummary, + Report, + ReportLocation, + RuleRef, + RunInfo, + Severity, + Summary, + TrendPoint, + TrendSummary, + Violation, +) + + +def _make_run(**overrides): + defaults = dict( + repo_root="/tmp/repo", + commit="abc1234def", + branch="feature/billing", + model_file="architecture.yml", + rules_files=("rules.pacta.yml",), + baseline_ref="baseline", + mode="full", + created_at="2025-01-22T12:00:00+00:00", + tool_version="0.0.5", + metadata={}, + ) + defaults.update(overrides) + return RunInfo(**defaults) + + +def _make_violation( + *, + rule_id="no-domain-infra", + name="Domain cannot depend on Infra", + severity=Severity.ERROR, + status="new", + file="src/domain/service.py", + line=12, + suggestion="Use dependency injection", +): + return Violation( + rule=RuleRef(id=rule_id, name=name, severity=severity), + message="Forbidden dependency", + status=status, + location=ReportLocation(file=file, line=line, column=1), + context={ + "target": "dependency", + "dep_type": "import", + "src_fqname": "app.domain.BillingService", + "dst_fqname": "app.infra.PostgresClient", + "src_layer": "domain", + "dst_layer": "infra", + }, + violation_key="key1", + suggestion=suggestion, + ) + + +def _make_report(*, violations=(), diff=None, trends=None, baseline_ref="baseline"): + all_v = list(violations) + by_sev = {} + by_status = {} + by_rule = {} + for v in all_v: + sev = v.rule.severity.value + by_sev[sev] = by_sev.get(sev, 0) + 1 + by_status[v.status] = by_status.get(v.status, 0) + 1 + by_rule[v.rule.id] = by_rule.get(v.rule.id, 0) + 1 + + return Report( + tool="pacta", + version="0.0.5", + run=_make_run(baseline_ref=baseline_ref), + summary=Summary( + total_violations=len(all_v), + by_severity=by_sev, + by_status=by_status, + by_rule=by_rule, + engine_errors=0, + ), + violations=tuple(all_v), + engine_errors=(), + diff=diff, + trends=trends, + ) + + +class TestGitHubRendererHeader: + def test_header_includes_branch_and_commit(self): + report = _make_report() + out = GitHubReportRenderer().render(report) + assert "## Architecture Report" in out + assert "`feature/billing`" in out + assert "`abc1234`" in out + assert "`baseline`" in out + + def test_no_branch_or_commit(self): + report = Report( + tool="pacta", + version="0.0.5", + run=_make_run(branch=None, commit=None, baseline_ref=None), + summary=Summary(total_violations=0, by_severity={}, by_status={}, by_rule={}, engine_errors=0), + violations=(), + engine_errors=(), + ) + out = GitHubReportRenderer().render(report) + assert "## Architecture Report" in out + assert "Branch" not in out + + +class TestGitHubRendererStructuralChanges: + def test_diff_table_rendered(self): + diff = DiffSummary( + nodes_added=3, + nodes_removed=1, + edges_added=5, + edges_removed=2, + added_node_names=("app.billing.InvoiceService", "app.billing.TaxCalc"), + removed_node_names=("app.legacy.OldBilling",), + ) + report = _make_report(diff=diff) + out = GitHubReportRenderer().render(report) + assert "### Structural Changes" in out + assert "+3" in out + assert "-1" in out + assert "`app.billing.InvoiceService`" in out + assert "**Removed modules:**" in out + + def test_no_diff_section_when_empty(self): + report = _make_report() + out = GitHubReportRenderer().render(report) + assert "### Structural Changes" not in out + + +class TestGitHubRendererViolations: + def test_new_violations_with_baseline(self): + v = _make_violation(status="new") + report = _make_report(violations=[v], baseline_ref="baseline") + out = GitHubReportRenderer().render(report) + assert "### New Violations (action required)" in out + assert "`no-domain-infra`" in out + assert "src/domain/service.py:12" in out + assert "Use dependency injection" in out + + def test_all_violations_shown_without_baseline(self): + v = _make_violation(status="unknown") + report = _make_report(violations=[v], baseline_ref=None) + out = GitHubReportRenderer().render(report) + assert "### Violation Details" in out + assert "`no-domain-infra`" in out + assert "src/domain/service.py:12" in out + + def test_severity_summary_without_baseline(self): + v1 = _make_violation(status="unknown", severity=Severity.WARNING) + v2 = _make_violation(status="unknown", severity=Severity.INFO, rule_id="other", name="Other") + report = _make_report(violations=[v1, v2], baseline_ref=None) + out = GitHubReportRenderer().render(report) + assert "### Violations (2 total)" in out + assert "Warning" in out + assert "Info" in out + + def test_status_summary_with_baseline(self): + new_v = _make_violation(status="new") + existing_v = _make_violation(status="existing", rule_id="other-rule", name="Other") + report = _make_report(violations=[new_v, existing_v], baseline_ref="baseline") + out = GitHubReportRenderer().render(report) + assert "### Violations Summary" in out + assert "New" in out + assert "Existing" in out + + def test_existing_violations_collapsible(self): + v = _make_violation(status="existing") + report = _make_report(violations=[v], baseline_ref="baseline") + out = GitHubReportRenderer().render(report) + assert "
" in out + assert "Existing Violations" in out + + def test_fixed_violations_section(self): + v = _make_violation(status="fixed", rule_id="no-circular", name="No circular deps") + report = _make_report(violations=[v]) + out = GitHubReportRenderer().render(report) + assert "### Fixed Violations" in out + assert "~~`no-circular`" in out + assert "(resolved)" in out + + def test_no_violations_no_summary(self): + report = _make_report() + out = GitHubReportRenderer().render(report) + assert "### Violations" not in out + + +class TestGitHubRendererTrends: + def test_trends_table_rendered(self): + trends = TrendSummary( + points=( + TrendPoint(label="Jan 20", violations=5, nodes=40, edges=67, density=1.68), + TrendPoint(label="Jan 22", violations=3, nodes=42, edges=67, density=1.60), + ), + violation_change=-2, + node_change=2, + edge_change=0, + density_change=-0.08, + ) + report = _make_report(trends=trends) + out = GitHubReportRenderer().render(report) + assert "### Architecture Trends (last 2 snapshots)" in out + assert "Violations" in out + assert "Improving" in out + assert "-2" in out + + def test_no_trends_when_none(self): + report = _make_report() + out = GitHubReportRenderer().render(report) + assert "### Architecture Trends" not in out + + +class TestGitHubRendererTableAlignment: + def test_tables_have_aligned_columns(self): + trends = TrendSummary( + points=(TrendPoint(label="Jan 22", violations=3, nodes=42, edges=67, density=1.60),), + violation_change=0, + node_change=0, + edge_change=0, + density_change=0, + ) + report = _make_report(trends=trends) + out = GitHubReportRenderer().render(report) + # All rows in a table should have the same length + for line in out.split("\n"): + if line.startswith("|") and "---" not in line: + # Each cell should be padded + assert " " in line, f"Table row not padded: {line}" + + +class TestGitHubRendererFooter: + def test_footer_includes_version(self): + report = _make_report() + out = GitHubReportRenderer().render(report) + assert "Pacta" in out + assert "v0.0.5" in out + + +class TestGitHubRendererFullOutput: + def test_full_report_with_baseline(self): + diff = DiffSummary( + nodes_added=3, + nodes_removed=1, + edges_added=5, + edges_removed=2, + added_node_names=("app.billing.InvoiceService",), + removed_node_names=("app.legacy.OldBilling",), + ) + trends = TrendSummary( + points=( + TrendPoint(label="Jan 20", violations=5, nodes=40, edges=67, density=1.68), + TrendPoint(label="Jan 22", violations=3, nodes=42, edges=67, density=1.60), + ), + violation_change=-2, + node_change=2, + edge_change=0, + density_change=-0.08, + ) + new_v = _make_violation(status="new") + fixed_v = _make_violation(status="fixed", rule_id="no-circular", name="No circular deps") + + report = _make_report(violations=[new_v, fixed_v], diff=diff, trends=trends) + out = GitHubReportRenderer().render(report) + + assert "## Architecture Report" in out + assert "### Structural Changes" in out + assert "### Violations Summary" in out + assert "### New Violations" in out + assert "### Fixed Violations" in out + assert "### Architecture Trends" in out + assert "Generated by" in out + + def test_full_report_without_baseline(self): + v1 = _make_violation(status="unknown", severity=Severity.WARNING) + v2 = _make_violation(status="unknown", severity=Severity.INFO, rule_id="other", name="Other") + report = _make_report(violations=[v1, v2], baseline_ref=None) + out = GitHubReportRenderer().render(report) + + assert "## Architecture Report" in out + assert "### Violations (2 total)" in out + assert "### Violation Details" in out + assert "`no-domain-infra`" in out + assert "`other`" in out + assert "Generated by" in out + # No baseline-specific sections + assert "### Violations Summary" not in out + assert "### New Violations" not in out From 37eb36877b0f5951b35461946c13adc2022788f7 Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Wed, 28 Jan 2026 10:29:58 +0100 Subject: [PATCH 02/12] feat(cli): add GitHub report format with snapshot-based trends summary --- pacta/cli/_trends.py | 75 ++++++++++++++++++++++++++++++++++++++++++++ pacta/cli/check.py | 7 ++++- pacta/cli/main.py | 4 +-- pacta/cli/scan.py | 7 ++++- 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 pacta/cli/_trends.py diff --git a/pacta/cli/_trends.py b/pacta/cli/_trends.py new file mode 100644 index 0000000..2e46501 --- /dev/null +++ b/pacta/cli/_trends.py @@ -0,0 +1,75 @@ +from __future__ import annotations + +from dataclasses import replace +from datetime import datetime + +from pacta.reporting.types import Report, TrendPoint, TrendSummary +from pacta.snapshot.store import FsSnapshotStore + + +def attach_trends( + report: Report, + *, + repo_root: str, + last: int = 5, +) -> Report: + """ + Load recent snapshots and attach a TrendSummary to the report. + + Returns the report unchanged if no history is available. + """ + try: + store = FsSnapshotStore(repo_root=repo_root) + objects = store.list_objects() + except Exception: + return report + + if len(objects) < 2: + return report + + # Take the most recent N entries (list_objects returns newest-first) + entries = objects[:last] + # Reverse to chronological order (oldest first) + entries = list(reversed(entries)) + + points: list[TrendPoint] = [] + for _, snapshot in entries: + meta = snapshot.meta + node_count = float(len(snapshot.nodes)) + edge_count = float(len(snapshot.edges)) + violation_count = float(len(snapshot.violations)) + density = round(edge_count / node_count, 2) if node_count > 0 else 0.0 + + label = _format_label(meta.created_at) + points.append( + TrendPoint( + label=label, + violations=violation_count, + nodes=node_count, + edges=edge_count, + density=density, + ) + ) + + first = points[0] + last_pt = points[-1] + + trends = TrendSummary( + points=tuple(points), + violation_change=last_pt.violations - first.violations, + node_change=last_pt.nodes - first.nodes, + edge_change=last_pt.edges - first.edges, + density_change=round(last_pt.density - first.density, 2), + ) + + return replace(report, trends=trends) + + +def _format_label(created_at: str | None) -> str: + if not created_at or "T" not in created_at: + return created_at or "unknown" + try: + dt = datetime.fromisoformat(created_at.replace("Z", "+00:00")) + return dt.strftime("%b %d") + except ValueError: + return created_at.split("T")[0] diff --git a/pacta/cli/check.py b/pacta/cli/check.py index 2fbf381..a4c8285 100644 --- a/pacta/cli/check.py +++ b/pacta/cli/check.py @@ -1,9 +1,11 @@ from pathlib import Path from pacta.cli._io import default_model_file, default_rules_files, ensure_repo_root +from pacta.cli._trends import attach_trends from pacta.cli.exitcodes import exit_code_from_report_dict from pacta.core.config import EngineConfig from pacta.core.engine import DefaultPactaEngine +from pacta.reporting.renderers.github import GitHubReportRenderer from pacta.reporting.renderers.json import JsonReportRenderer from pacta.reporting.renderers.text import TextReportRenderer from pacta.snapshot.store import FsSnapshotStore @@ -70,7 +72,10 @@ def run( store.save(result.snapshot, refs=[save_ref]) # Render report - if fmt == "json": + if fmt == "github": + report = attach_trends(result.report, repo_root=repo_root) + out = GitHubReportRenderer().render(report) + elif fmt == "json": out = JsonReportRenderer().render(result.report) else: out = TextReportRenderer(verbosity=verbosity).render(result.report) # type: ignore[arg-type] diff --git a/pacta/cli/main.py b/pacta/cli/main.py index 81d0bde..e20f996 100644 --- a/pacta/cli/main.py +++ b/pacta/cli/main.py @@ -14,7 +14,7 @@ def build_parser() -> argparse.ArgumentParser: # scan scan_p = sub.add_parser("scan", help="Scan repository and evaluate rules.") scan_p.add_argument("path", nargs="?", default=".", help="Repository root (default: .)") - scan_p.add_argument("--format", choices=["text", "json"], default="text", help="Output format.") + scan_p.add_argument("--format", choices=["text", "json", "github"], default="text", help="Output format.") scan_p.add_argument("--rules", action="append", default=None, help="Rules file path (repeatable).") scan_p.add_argument("--model", default=None, help="Architecture model file (architecture.yaml).") scan_p.add_argument("--baseline", default=None, help="Baseline snapshot ref (e.g. baseline).") @@ -30,7 +30,7 @@ def build_parser() -> argparse.ArgumentParser: check_p = sub.add_parser("check", help="Evaluate rules against a snapshot.") check_p.add_argument("path", nargs="?", default=".", help="Repository root (default: .)") check_p.add_argument("--ref", default="latest", help="Snapshot ref to check (default: latest).") - check_p.add_argument("--format", choices=["text", "json"], default="text", help="Output format.") + check_p.add_argument("--format", choices=["text", "json", "github"], default="text", help="Output format.") check_p.add_argument("--rules", action="append", default=None, help="Rules file path (repeatable).") check_p.add_argument("--model", default=None, help="Architecture model file (architecture.yaml).") check_p.add_argument("--baseline", default=None, help="Baseline snapshot ref.") diff --git a/pacta/cli/scan.py b/pacta/cli/scan.py index f1c7292..97b9e53 100644 --- a/pacta/cli/scan.py +++ b/pacta/cli/scan.py @@ -1,6 +1,8 @@ from pacta.cli._engine_adapter import run_engine_scan from pacta.cli._io import default_model_file, default_rules_files, ensure_repo_root +from pacta.cli._trends import attach_trends from pacta.cli.exitcodes import exit_code_from_report_dict +from pacta.reporting.renderers.github import GitHubReportRenderer from pacta.reporting.renderers.json import JsonReportRenderer from pacta.reporting.renderers.text import TextReportRenderer @@ -32,7 +34,10 @@ def run( tool_version=tool_version, ) - if fmt == "json": + if fmt == "github": + report = attach_trends(report, repo_root=repo_root) + out = GitHubReportRenderer().render(report) + elif fmt == "json": out = JsonReportRenderer().render(report) else: out = TextReportRenderer(verbosity=verbosity).render(report) # type: ignore[arg-type] From f6eac327be67ada02bd969d240d905715eb8b5eb Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Wed, 28 Jan 2026 10:30:13 +0100 Subject: [PATCH 03/12] feat(action): add composite GitHub Action for Pacta architecture review --- action.yml | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 action.yml diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..8ec4be2 --- /dev/null +++ b/action.yml @@ -0,0 +1,103 @@ +name: 'Pacta Architecture Review' +description: 'Run architecture checks and post a rich PR comment describing architectural changes' +branding: + icon: 'layers' + color: 'blue' + +inputs: + model: + description: 'Path to architecture.yml' + required: false + default: 'architecture.yml' + rules: + description: 'Path to rules.pacta.yml' + required: false + default: 'rules.pacta.yml' + baseline: + description: 'Baseline ref name (omit to skip baseline comparison)' + required: false + default: '' + python-version: + description: 'Python version to use' + required: false + default: '3.11' + fail-on-violations: + description: 'Fail the check if new violations are found' + required: false + default: 'true' + pacta-version: + description: 'Pacta version to install (default: latest)' + required: false + default: 'pacta' + +runs: + using: 'composite' + steps: + - uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + + - name: Install Pacta + shell: bash + run: pip install ${{ inputs.pacta-version }} + + - name: Run Architecture Check + id: pacta + shell: bash + run: | + ARGS="--model ${{ inputs.model }} --rules ${{ inputs.rules }}" + if [ -n "${{ inputs.baseline }}" ]; then + ARGS="$ARGS --baseline ${{ inputs.baseline }}" + fi + + # Generate GitHub Markdown comment + pacta scan . $ARGS --format github > "$RUNNER_TEMP/pacta-comment.md" || true + + # Generate JSON for machine-readable results + pacta scan . $ARGS --format json > "$RUNNER_TEMP/pacta-results.json" || true + + # Extract new violation count + NEW=$(jq '.summary.by_status.new // 0' "$RUNNER_TEMP/pacta-results.json" 2>/dev/null || echo 0) + echo "new_violations=$NEW" >> "$GITHUB_OUTPUT" + + - name: Post or Update PR Comment + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const commentPath = '${{ runner.temp }}/pacta-comment.md'; + const body = fs.readFileSync(commentPath, 'utf8'); + const marker = ''; + const fullBody = marker + '\n' + body; + + // Find existing comment to update (idempotent) + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + const existing = comments.find(c => c.body.startsWith(marker)); + + if (existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body: fullBody, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: fullBody, + }); + } + + - name: Fail on New Violations + if: inputs.fail-on-violations == 'true' && steps.pacta.outputs.new_violations != '0' + shell: bash + run: | + echo "::error::Pacta found ${{ steps.pacta.outputs.new_violations }} new architectural violation(s)" + exit 1 From 654c20455a05e20f47f72243fb18cb357ba4435d Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Wed, 28 Jan 2026 10:30:21 +0100 Subject: [PATCH 04/12] docs: add GitHub Action integration guide and document github output format --- docs/ci-integration.md | 42 ++++++++++++++++++++++++++++++++++++++++++ docs/cli.md | 4 ++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/ci-integration.md b/docs/ci-integration.md index 097ef4e..4ec0a03 100644 --- a/docs/ci-integration.md +++ b/docs/ci-integration.md @@ -88,6 +88,48 @@ jobs: !!! note "Persisting baselines" The baseline is stored in `.pacta/snapshots/`. Commit this directory to your repository, or use GitHub Actions cache/artifacts to persist it between runs. +### Pacta GitHub Action (Recommended) + +The simplest way to get rich architectural PR comments. Uses `--format github` to generate a descriptive Markdown comment with structural changes, violation details, and architecture trends: + +```yaml +name: Architecture Check + +on: + pull_request: + branches: [main] + +jobs: + architecture: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: actions/checkout@v4 + - uses: akhundMurad/pacta@main + with: + model: architecture.yml + rules: rules.pacta.yml + baseline: baseline +``` + +The action will: + +- Run `pacta scan` with `--format github` to produce a rich Markdown report +- Post (or update) a PR comment with structural changes, new/fixed violations, and architecture trends +- Fail the check if new violations are introduced (configurable via `fail-on-violations: false`) + +**Action Inputs:** + +| Input | Default | Description | +|-------|---------|-------------| +| `model` | `architecture.yml` | Path to architecture model | +| `rules` | `rules.pacta.yml` | Path to rules file | +| `baseline` | *(none)* | Baseline ref for incremental checks | +| `python-version` | `3.11` | Python version | +| `fail-on-violations` | `true` | Fail if new violations found | +| `pacta-version` | `pacta` | Pacta package specifier | + ### JSON Output for PR Comments Generate JSON output and post results as a PR comment: diff --git a/docs/cli.md b/docs/cli.md index 11911a9..abacb10 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -20,7 +20,7 @@ pacta scan [PATH] [OPTIONS] |--------|---------|-------------| | `--model FILE` | `architecture.yml` | Architecture model file | | `--rules FILE` | `rules.pacta.yml` | Rules file (repeatable) | -| `--format {text,json}` | `text` | Output format | +| `--format {text,json,github}` | `text` | Output format (`github` produces Markdown for PR comments) | | `--baseline REF` | - | Compare against baseline snapshot | | `--save-ref REF` | - | Save snapshot under this ref | | `--mode {full,changed_only}` | `full` | Evaluation mode | @@ -84,7 +84,7 @@ pacta check [PATH] [OPTIONS] | `--ref REF` | `latest` | Snapshot ref to check | | `--model FILE` | `architecture.yml` | Architecture model file | | `--rules FILE` | `rules.pacta.yml` | Rules file (repeatable) | -| `--format {text,json}` | `text` | Output format | +| `--format {text,json,github}` | `text` | Output format (`github` produces Markdown for PR comments) | | `--baseline REF` | - | Compare against baseline snapshot | | `--save-ref REF` | - | Also save result under this ref | | `-q, --quiet` | - | Summary only | From 9fabb42426b6ccb72d13afd5e23e6040f1ecf83c Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Thu, 29 Jan 2026 00:06:24 +0100 Subject: [PATCH 05/12] chore(cli): remove unused __future__ annotations import from _trends.py --- pacta/cli/_trends.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pacta/cli/_trends.py b/pacta/cli/_trends.py index 2e46501..672aef0 100644 --- a/pacta/cli/_trends.py +++ b/pacta/cli/_trends.py @@ -1,5 +1,3 @@ -from __future__ import annotations - from dataclasses import replace from datetime import datetime From e64ee199d040418dfaa39e2c9cadb42facb44383 Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Thu, 29 Jan 2026 00:21:48 +0100 Subject: [PATCH 06/12] ci: add workflow to test action and support local pacta install option --- .github/workflows/test-action.yml | 28 ++++++++++++++++++++++++++++ action.yml | 9 +++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/test-action.yml diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml new file mode 100644 index 0000000..865fd36 --- /dev/null +++ b/.github/workflows/test-action.yml @@ -0,0 +1,28 @@ +name: Test Pacta Composite Action + +on: + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + issues: write + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check jq + run: jq --version + + - name: Run action (default inputs) + uses: ./ + with: + model: architecture.yml + rules: rules.pacta.yml + fail-on-violations: "false" + pacta-version: "local" diff --git a/action.yml b/action.yml index 8ec4be2..e7e4044 100644 --- a/action.yml +++ b/action.yml @@ -26,7 +26,7 @@ inputs: required: false default: 'true' pacta-version: - description: 'Pacta version to install (default: latest)' + description: 'Pacta version to install (PyPI spec, default: pacta)' required: false default: 'pacta' @@ -39,7 +39,12 @@ runs: - name: Install Pacta shell: bash - run: pip install ${{ inputs.pacta-version }} + run: | + if [ "${{ inputs.pacta-version }}" = "local" ]; then + pip install . + else + pip install "${{ inputs.pacta-version }}" + fi - name: Run Architecture Check id: pacta From 2f933de79d9235db26b5c1d20708cfb374a587b7 Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Thu, 29 Jan 2026 00:29:29 +0100 Subject: [PATCH 07/12] feat(action): add target_dir input to control scan root Update workflow example and use target_dir in pacta scan commands instead of hardcoded `.` --- .github/workflows/test-action.yml | 5 +++-- action.yml | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml index 865fd36..94d6509 100644 --- a/.github/workflows/test-action.yml +++ b/.github/workflows/test-action.yml @@ -22,7 +22,8 @@ jobs: - name: Run action (default inputs) uses: ./ with: - model: architecture.yml - rules: rules.pacta.yml + target_dir: 'examples/hexagonal-app/' + model: examples/hexagonal-app/architecture.yml + rules: examples/hexagonal-app/rules.pacta.yml fail-on-violations: "false" pacta-version: "local" diff --git a/action.yml b/action.yml index e7e4044..9643af4 100644 --- a/action.yml +++ b/action.yml @@ -5,6 +5,10 @@ branding: color: 'blue' inputs: + target_dir: + description: 'Repository root (default: .)' + required: false + default: '.' model: description: 'Path to architecture.yml' required: false @@ -56,10 +60,10 @@ runs: fi # Generate GitHub Markdown comment - pacta scan . $ARGS --format github > "$RUNNER_TEMP/pacta-comment.md" || true + pacta scan ${{ inputs.target_dir }} $ARGS --format github > "$RUNNER_TEMP/pacta-comment.md" || true # Generate JSON for machine-readable results - pacta scan . $ARGS --format json > "$RUNNER_TEMP/pacta-results.json" || true + pacta scan ${{ inputs.target_dir }} $ARGS --format json > "$RUNNER_TEMP/pacta-results.json" || true # Extract new violation count NEW=$(jq '.summary.by_status.new // 0' "$RUNNER_TEMP/pacta-results.json" 2>/dev/null || echo 0) From e709c4f93404d078dfa94df5813ac47b0a76ec96 Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Thu, 29 Jan 2026 00:37:22 +0100 Subject: [PATCH 08/12] chore(ci): update test-action workflow to use simple-layered-app example --- .github/workflows/test-action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml index 94d6509..4d90e69 100644 --- a/.github/workflows/test-action.yml +++ b/.github/workflows/test-action.yml @@ -22,8 +22,8 @@ jobs: - name: Run action (default inputs) uses: ./ with: - target_dir: 'examples/hexagonal-app/' - model: examples/hexagonal-app/architecture.yml - rules: examples/hexagonal-app/rules.pacta.yml + target_dir: 'examples/simple-layered-app/' + model: examples/simple-layered-app/architecture.yml + rules: examples/simple-layered-app/rules.pacta.yml fail-on-violations: "false" pacta-version: "local" From 2fb3f114371e6c1d3b4cc91a0cbd74c3c4a105bd Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Thu, 29 Jan 2026 00:42:20 +0100 Subject: [PATCH 09/12] chore(examples): track pacta snapshots for simple-layered-app --- .gitignore | 1 - .../.pacta/snapshots/objects/0ea5fad2.json | 579 +++++++++++ .../.pacta/snapshots/objects/10dfb35a.json | 829 ++++++++++++++++ .../.pacta/snapshots/objects/14ec11dd.json | 853 +++++++++++++++++ .../.pacta/snapshots/objects/2722c4bc.json | 897 ++++++++++++++++++ .../.pacta/snapshots/objects/5a624473.json | 733 ++++++++++++++ .../.pacta/snapshots/objects/660c26b5.json | 729 ++++++++++++++ .../.pacta/snapshots/objects/a2ad2dcf.json | 819 ++++++++++++++++ .../.pacta/snapshots/objects/ac29788f.json | 529 +++++++++++ .../.pacta/snapshots/objects/afd35017.json | 467 +++++++++ .../.pacta/snapshots/objects/b4228f1d.json | 753 +++++++++++++++ .../.pacta/snapshots/objects/ba00988a.json | 621 ++++++++++++ .../.pacta/snapshots/objects/c8ec26a4.json | 645 +++++++++++++ .../.pacta/snapshots/objects/cc292fef.json | 613 ++++++++++++ .../.pacta/snapshots/refs/latest | 1 + 15 files changed, 9068 insertions(+), 1 deletion(-) create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/0ea5fad2.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/10dfb35a.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/14ec11dd.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/2722c4bc.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/5a624473.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/660c26b5.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/a2ad2dcf.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/ac29788f.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/afd35017.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/b4228f1d.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/ba00988a.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/c8ec26a4.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/cc292fef.json create mode 100644 examples/simple-layered-app/.pacta/snapshots/refs/latest diff --git a/.gitignore b/.gitignore index f450e08..5222dc6 100644 --- a/.gitignore +++ b/.gitignore @@ -194,6 +194,5 @@ pyrightconfig.json # End of https://www.toptal.com/developers/gitignore/api/python,visualstudiocode -.pacta/ .vscode/ uv.toml diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/0ea5fad2.json b/examples/simple-layered-app/.pacta/snapshots/objects/0ea5fad2.json new file mode 100644 index 0000000..e1f3c3f --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/0ea5fad2.json @@ -0,0 +1,579 @@ +{ + "_hash": "0ea5fad25d41e124a103f4352b35e1d32295cceaf6214ea03e9d7229c56331f3", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "feature", + "commit": "000000eabc", + "created_at": "2025-01-15T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule3", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule4", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule5", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule6", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule7", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule8", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/10dfb35a.json b/examples/simple-layered-app/.pacta/snapshots/objects/10dfb35a.json new file mode 100644 index 0000000..4d61f19 --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/10dfb35a.json @@ -0,0 +1,829 @@ +{ + "_hash": "10dfb35a1360c351c93d2a29b2e18d7fe8c46cd2ca7a4e9144e3ed29aa5b5675", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod19", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod20", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod19", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "0000046abc", + "created_at": "2025-03-12T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod14", + "path": "src/mod14.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod15", + "path": "src/mod15.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod16", + "path": "src/mod16.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod17", + "path": "src/mod17.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod18", + "path": "src/mod18.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod19", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod19", + "path": "src/mod19.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/14ec11dd.json b/examples/simple-layered-app/.pacta/snapshots/objects/14ec11dd.json new file mode 100644 index 0000000..ff60ebe --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/14ec11dd.json @@ -0,0 +1,853 @@ +{ + "_hash": "14ec11ddc60b477efa20977e3976e587a63fb6574292ead510ea4ade2e47bb74", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod20", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod21", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod19", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod20", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod19", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "000004dabc", + "created_at": "2025-03-19T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod14", + "path": "src/mod14.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod15", + "path": "src/mod15.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod16", + "path": "src/mod16.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod17", + "path": "src/mod17.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod18", + "path": "src/mod18.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod19", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod19", + "path": "src/mod19.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod20", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod20", + "path": "src/mod20.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/2722c4bc.json b/examples/simple-layered-app/.pacta/snapshots/objects/2722c4bc.json new file mode 100644 index 0000000..dd6c302 --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/2722c4bc.json @@ -0,0 +1,897 @@ +{ + "_hash": "2722c4bc17489075df143f0e0668a94ee8936739f2d15eeb0fbe8c0bd1143afe", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.application.order_service", + "name": "OrderService" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.application.order_service", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "application", + "loc": { + "end": null, + "file": "src/ui/order_controller.py", + "start": { + "column": 1, + "line": 3 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.ui.order_controller", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "ui" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.application.user_service", + "name": "UserService" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.application.user_service", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "application", + "loc": { + "end": null, + "file": "src/ui/user_controller.py", + "start": { + "column": 1, + "line": 3 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.ui.user_controller", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "ui" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.domain.order", + "name": "Order" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.domain.order", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "domain", + "loc": { + "end": null, + "file": "src/application/order_service.py", + "start": { + "column": 1, + "line": 3 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.application.order_service", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "application" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.domain.order", + "name": "Order" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.domain.order", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "domain", + "loc": { + "end": null, + "file": "src/infra/order_repository.py", + "start": { + "column": 1, + "line": 3 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.infra.order_repository", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "infra" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.domain.user", + "name": "User" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.domain.user", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "domain", + "loc": { + "end": null, + "file": "src/application/user_service.py", + "start": { + "column": 1, + "line": 3 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.application.user_service", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "application" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.domain.user", + "name": "User" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.domain.user", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "domain", + "loc": { + "end": null, + "file": "src/infra/database.py", + "start": { + "column": 1, + "line": 5 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.infra.database", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "infra" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.domain.user", + "name": "User" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.domain.user", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "domain", + "loc": { + "end": null, + "file": "src/infra/user_repository.py", + "start": { + "column": 1, + "line": 5 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.infra.user_repository", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "infra" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.infra.database", + "name": "Database" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.infra.database", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "infra", + "loc": { + "end": null, + "file": "src/ui/user_controller.py", + "start": { + "column": 1, + "line": 7 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.ui.user_controller", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "ui" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.infra.order_repository", + "name": "OrderRepository" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.infra.order_repository", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "infra", + "loc": { + "end": null, + "file": "src/application/order_service.py", + "start": { + "column": 1, + "line": 4 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.application.order_service", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "application" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.infra.user_repository", + "name": "UserRepository" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.infra.user_repository", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "infra", + "loc": { + "end": null, + "file": "src/application/user_service.py", + "start": { + "column": 1, + "line": 4 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.application.user_service", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "application" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "src.ui.order_controller", + "name": "OrderController" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "src.ui.order_controller", + "language": "python" + }, + "dst_container": "main-app", + "dst_context": null, + "dst_layer": "ui", + "loc": { + "end": null, + "file": "src/application/order_service.py", + "start": { + "column": 1, + "line": 5 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.application.order_service", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "application" + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": { + "kind": "from", + "level": 0, + "module": "typing", + "name": "List" + }, + "dst": { + "code_root": "simple-layered-app", + "fqname": "typing", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": { + "end": null, + "file": "src/domain/order.py", + "start": { + "column": 1, + "line": 3 + } + }, + "src": { + "code_root": "simple-layered-app", + "fqname": "src.domain.order", + "language": "python" + }, + "src_container": "main-app", + "src_context": null, + "src_layer": "domain" + } + ], + "meta": { + "branch": "feature/github-action", + "commit": "f9bac778c137f6ca128aa5bfb3a6a2ca2efb2e68", + "created_at": "2026-01-28T09:27:30.470256+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": { + "end": null, + "file": "src/__init__.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "src", + "path": "src/__init__.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.application", + "language": "python" + }, + "kind": "module", + "layer": "application", + "loc": { + "end": null, + "file": "src/application/__init__.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "application", + "path": "src/application/__init__.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.application.order_service", + "language": "python" + }, + "kind": "module", + "layer": "application", + "loc": { + "end": null, + "file": "src/application/order_service.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "order_service", + "path": "src/application/order_service.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.application.user_service", + "language": "python" + }, + "kind": "module", + "layer": "application", + "loc": { + "end": null, + "file": "src/application/user_service.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "user_service", + "path": "src/application/user_service.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.domain", + "language": "python" + }, + "kind": "module", + "layer": "domain", + "loc": { + "end": null, + "file": "src/domain/__init__.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "domain", + "path": "src/domain/__init__.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.domain.order", + "language": "python" + }, + "kind": "module", + "layer": "domain", + "loc": { + "end": null, + "file": "src/domain/order.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "order", + "path": "src/domain/order.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.domain.user", + "language": "python" + }, + "kind": "module", + "layer": "domain", + "loc": { + "end": null, + "file": "src/domain/user.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "user", + "path": "src/domain/user.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.infra", + "language": "python" + }, + "kind": "module", + "layer": "infra", + "loc": { + "end": null, + "file": "src/infra/__init__.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "infra", + "path": "src/infra/__init__.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.infra.database", + "language": "python" + }, + "kind": "module", + "layer": "infra", + "loc": { + "end": null, + "file": "src/infra/database.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "database", + "path": "src/infra/database.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.infra.order_repository", + "language": "python" + }, + "kind": "module", + "layer": "infra", + "loc": { + "end": null, + "file": "src/infra/order_repository.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "order_repository", + "path": "src/infra/order_repository.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.infra.user_repository", + "language": "python" + }, + "kind": "module", + "layer": "infra", + "loc": { + "end": null, + "file": "src/infra/user_repository.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "user_repository", + "path": "src/infra/user_repository.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.ui", + "language": "python" + }, + "kind": "module", + "layer": "ui", + "loc": { + "end": null, + "file": "src/ui/__init__.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "ui", + "path": "src/ui/__init__.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.ui.order_controller", + "language": "python" + }, + "kind": "module", + "layer": "ui", + "loc": { + "end": null, + "file": "src/ui/order_controller.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "order_controller", + "path": "src/ui/order_controller.py", + "tags": [] + }, + { + "attributes": {}, + "container": "main-app", + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "src.ui.user_controller", + "language": "python" + }, + "kind": "module", + "layer": "ui", + "loc": { + "end": null, + "file": "src/ui/user_controller.py", + "start": { + "column": 1, + "line": 1 + } + }, + "name": "user_controller", + "path": "src/ui/user_controller.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "simple-layered-app", + "fqname": "typing", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "typing", + "path": null, + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": { + "dep_type": "import", + "dst_container": "main-app", + "dst_context": null, + "dst_fqname": "src.infra.database", + "dst_id": "python://simple-layered-app::src.infra.database", + "dst_layer": "infra", + "src_container": "main-app", + "src_context": null, + "src_fqname": "src.ui.user_controller", + "src_id": "python://simple-layered-app::src.ui.user_controller", + "src_layer": "ui", + "target": "dependency" + }, + "location": { + "column": 1, + "end_column": null, + "end_line": null, + "file": "src/ui/user_controller.py", + "line": 7 + }, + "message": "UI layer should not directly depend on Infrastructure layer", + "rule": { + "description": null, + "id": "no_ui_to_infra", + "name": "UI should not directly access Infrastructure", + "severity": "warning" + }, + "status": "unknown", + "suggestion": "Access infrastructure through application services instead", + "violation_key": "394469e3be36ac776a8eaa14ce1171dda428f0a9" + }, + { + "context": { + "dep_type": "import", + "dst_container": "main-app", + "dst_context": null, + "dst_fqname": "src.domain.user", + "dst_id": "python://simple-layered-app::src.domain.user", + "dst_layer": "domain", + "src_container": "main-app", + "src_context": null, + "src_fqname": "src.infra.database", + "src_id": "python://simple-layered-app::src.infra.database", + "src_layer": "infra", + "target": "dependency" + }, + "location": { + "column": 1, + "end_column": null, + "end_line": null, + "file": "src/infra/database.py", + "line": 5 + }, + "message": "Infrastructure implementing domain interfaces (tracked for visibility)", + "rule": { + "description": null, + "id": "infra_can_use_domain", + "name": "Infrastructure implementing domain interfaces", + "severity": "info" + }, + "status": "unknown", + "suggestion": null, + "violation_key": "daf7ebe686b02da8204c737b607bbb360fc3bd72" + }, + { + "context": { + "dep_type": "import", + "dst_container": "main-app", + "dst_context": null, + "dst_fqname": "src.domain.order", + "dst_id": "python://simple-layered-app::src.domain.order", + "dst_layer": "domain", + "src_container": "main-app", + "src_context": null, + "src_fqname": "src.infra.order_repository", + "src_id": "python://simple-layered-app::src.infra.order_repository", + "src_layer": "infra", + "target": "dependency" + }, + "location": { + "column": 1, + "end_column": null, + "end_line": null, + "file": "src/infra/order_repository.py", + "line": 3 + }, + "message": "Infrastructure implementing domain interfaces (tracked for visibility)", + "rule": { + "description": null, + "id": "infra_can_use_domain", + "name": "Infrastructure implementing domain interfaces", + "severity": "info" + }, + "status": "unknown", + "suggestion": null, + "violation_key": "3ecb956f2c2073332cffa8cca46ac7ce3b8ff2c2" + }, + { + "context": { + "dep_type": "import", + "dst_container": "main-app", + "dst_context": null, + "dst_fqname": "src.domain.user", + "dst_id": "python://simple-layered-app::src.domain.user", + "dst_layer": "domain", + "src_container": "main-app", + "src_context": null, + "src_fqname": "src.infra.user_repository", + "src_id": "python://simple-layered-app::src.infra.user_repository", + "src_layer": "infra", + "target": "dependency" + }, + "location": { + "column": 1, + "end_column": null, + "end_line": null, + "file": "src/infra/user_repository.py", + "line": 5 + }, + "message": "Infrastructure implementing domain interfaces (tracked for visibility)", + "rule": { + "description": null, + "id": "infra_can_use_domain", + "name": "Infrastructure implementing domain interfaces", + "severity": "info" + }, + "status": "unknown", + "suggestion": null, + "violation_key": "bcc98abe10c4f666d584ee25a722b0843c0d1c08" + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/5a624473.json b/examples/simple-layered-app/.pacta/snapshots/objects/5a624473.json new file mode 100644 index 0000000..eaaaf5b --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/5a624473.json @@ -0,0 +1,733 @@ +{ + "_hash": "5a624473c58600a4f3aaaee777060ae6ce2d72c81b6fd9397bd235d5e970f73c", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "feature", + "commit": "000002aabc", + "created_at": "2025-02-12T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod14", + "path": "src/mod14.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod15", + "path": "src/mod15.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule3", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule4", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule5", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/660c26b5.json b/examples/simple-layered-app/.pacta/snapshots/objects/660c26b5.json new file mode 100644 index 0000000..8a3f35f --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/660c26b5.json @@ -0,0 +1,729 @@ +{ + "_hash": "660c26b5904c58e57014ccaca9c206bf3336fadfc81fc7dddd33332dd9cf77da", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "0000031abc", + "created_at": "2025-02-19T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod14", + "path": "src/mod14.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod15", + "path": "src/mod15.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod16", + "path": "src/mod16.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/a2ad2dcf.json b/examples/simple-layered-app/.pacta/snapshots/objects/a2ad2dcf.json new file mode 100644 index 0000000..8c2c25f --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/a2ad2dcf.json @@ -0,0 +1,819 @@ +{ + "_hash": "a2ad2dcf8eb39f8fb1a32294ea424758bf448a969cbfa31087f5c1140d43d5ba", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod19", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "hotfix", + "commit": "000003fabc", + "created_at": "2025-03-05T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod14", + "path": "src/mod14.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod15", + "path": "src/mod15.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod16", + "path": "src/mod16.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod17", + "path": "src/mod17.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod18", + "path": "src/mod18.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule3", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/ac29788f.json b/examples/simple-layered-app/.pacta/snapshots/objects/ac29788f.json new file mode 100644 index 0000000..0777115 --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/ac29788f.json @@ -0,0 +1,529 @@ +{ + "_hash": "ac29788fcd05ac474493d2e493a95511bbf375c77677877633ecd2b0df4b74de", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "0000007abc", + "created_at": "2025-01-08T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule3", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule4", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule5", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule6", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/afd35017.json b/examples/simple-layered-app/.pacta/snapshots/objects/afd35017.json new file mode 100644 index 0000000..756275f --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/afd35017.json @@ -0,0 +1,467 @@ +{ + "_hash": "afd3501728b0dcdb5b071c87cf7d4878602553345b2f4aef2570e38c00a8ed95", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "0000000abc", + "created_at": "2025-01-01T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule3", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule4", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule5", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule6", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule7", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/b4228f1d.json b/examples/simple-layered-app/.pacta/snapshots/objects/b4228f1d.json new file mode 100644 index 0000000..139c12d --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/b4228f1d.json @@ -0,0 +1,753 @@ +{ + "_hash": "b4228f1d453172925b22b791d3283578d0381b00a98da6faeb102235dcc37559", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod18", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "0000038abc", + "created_at": "2025-02-26T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod14", + "path": "src/mod14.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod15", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod15", + "path": "src/mod15.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod16", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod16", + "path": "src/mod16.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod17", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod17", + "path": "src/mod17.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/ba00988a.json b/examples/simple-layered-app/.pacta/snapshots/objects/ba00988a.json new file mode 100644 index 0000000..39ab36b --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/ba00988a.json @@ -0,0 +1,621 @@ +{ + "_hash": "ba00988a9e84530e6b2e1483ab9c588f0b9e8bc767a697ba49655adc0f6c600f", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "000001cabc", + "created_at": "2025-01-29T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule3", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule4", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/c8ec26a4.json b/examples/simple-layered-app/.pacta/snapshots/objects/c8ec26a4.json new file mode 100644 index 0000000..3e7e340 --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/c8ec26a4.json @@ -0,0 +1,645 @@ +{ + "_hash": "c8ec26a4e9c151cd778ba16ca5e3462d24ae0637fd20cd3b077fd0f972341306", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "0000023abc", + "created_at": "2025-02-05T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod14", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod14", + "path": "src/mod14.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule3", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/cc292fef.json b/examples/simple-layered-app/.pacta/snapshots/objects/cc292fef.json new file mode 100644 index 0000000..e6957e5 --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/objects/cc292fef.json @@ -0,0 +1,613 @@ +{ + "_hash": "cc292fefc18a2576e6f581fab2fa224d367d6e37058b41144cb39b9694e07a03", + "edges": [ + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + }, + { + "confidence": 1.0, + "dep_type": "import", + "details": {}, + "dst": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "dst_container": null, + "dst_context": null, + "dst_layer": null, + "loc": null, + "src": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "src_container": null, + "src_context": null, + "src_layer": null + } + ], + "meta": { + "branch": "main", + "commit": "0000015abc", + "created_at": "2025-01-22T12:00:00+00:00", + "extra": {}, + "model_version": null, + "repo_root": "examples/simple-layered-app", + "tool_version": null + }, + "nodes": [ + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod0", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod0", + "path": "src/mod0.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod1", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod1", + "path": "src/mod1.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod10", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod10", + "path": "src/mod10.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod11", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod11", + "path": "src/mod11.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod12", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod12", + "path": "src/mod12.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod13", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod13", + "path": "src/mod13.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod2", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod2", + "path": "src/mod2.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod3", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod3", + "path": "src/mod3.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod4", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod4", + "path": "src/mod4.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod5", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod5", + "path": "src/mod5.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod6", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod6", + "path": "src/mod6.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod7", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod7", + "path": "src/mod7.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod8", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod8", + "path": "src/mod8.py", + "tags": [] + }, + { + "attributes": {}, + "container": null, + "context": null, + "id": { + "code_root": "demo", + "fqname": "mod9", + "language": "python" + }, + "kind": "module", + "layer": null, + "loc": null, + "name": "module_mod9", + "path": "src/mod9.py", + "tags": [] + } + ], + "schema_version": 1, + "violations": [ + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule0", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule1", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule2", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule3", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule4", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + }, + { + "context": {}, + "location": null, + "message": "Architecture violation", + "rule": { + "description": null, + "id": "rule5", + "name": "Test Rule", + "severity": "error" + }, + "status": "unknown", + "suggestion": null, + "violation_key": null + } + ] +} diff --git a/examples/simple-layered-app/.pacta/snapshots/refs/latest b/examples/simple-layered-app/.pacta/snapshots/refs/latest new file mode 100644 index 0000000..e7a05a4 --- /dev/null +++ b/examples/simple-layered-app/.pacta/snapshots/refs/latest @@ -0,0 +1 @@ +2722c4bc From 1ce7a308290055b9884115fa7c5ef23913bb3cb7 Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Thu, 29 Jan 2026 00:46:26 +0100 Subject: [PATCH 10/12] chore(gitignore): remove test-action GitHub workflow - simplify Pacta install to always use pacta-version input --- .github/workflows/test-action.yml | 29 ----------------------------- .gitignore | 1 + action.yml | 7 +------ 3 files changed, 2 insertions(+), 35 deletions(-) delete mode 100644 .github/workflows/test-action.yml diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml deleted file mode 100644 index 4d90e69..0000000 --- a/.github/workflows/test-action.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Test Pacta Composite Action - -on: - pull_request: - branches: [main] - workflow_dispatch: - -permissions: - contents: read - pull-requests: write - issues: write - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Check jq - run: jq --version - - - name: Run action (default inputs) - uses: ./ - with: - target_dir: 'examples/simple-layered-app/' - model: examples/simple-layered-app/architecture.yml - rules: examples/simple-layered-app/rules.pacta.yml - fail-on-violations: "false" - pacta-version: "local" diff --git a/.gitignore b/.gitignore index 5222dc6..f450e08 100644 --- a/.gitignore +++ b/.gitignore @@ -194,5 +194,6 @@ pyrightconfig.json # End of https://www.toptal.com/developers/gitignore/api/python,visualstudiocode +.pacta/ .vscode/ uv.toml diff --git a/action.yml b/action.yml index 9643af4..029751f 100644 --- a/action.yml +++ b/action.yml @@ -43,12 +43,7 @@ runs: - name: Install Pacta shell: bash - run: | - if [ "${{ inputs.pacta-version }}" = "local" ]; then - pip install . - else - pip install "${{ inputs.pacta-version }}" - fi + run: pip install "${{ inputs.pacta-version }}" - name: Run Architecture Check id: pacta From 2121915c9d3c34ab5a42700d8654f1d3e9189f1f Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Thu, 29 Jan 2026 00:48:36 +0100 Subject: [PATCH 11/12] chore(examples/simple-layered-app): remove pacta snapshot objects and latest ref --- .../.pacta/snapshots/objects/0ea5fad2.json | 579 ----------- .../.pacta/snapshots/objects/10dfb35a.json | 829 ---------------- .../.pacta/snapshots/objects/14ec11dd.json | 853 ----------------- .../.pacta/snapshots/objects/2722c4bc.json | 897 ------------------ .../.pacta/snapshots/objects/5a624473.json | 733 -------------- .../.pacta/snapshots/objects/660c26b5.json | 729 -------------- .../.pacta/snapshots/objects/a2ad2dcf.json | 819 ---------------- .../.pacta/snapshots/objects/ac29788f.json | 529 ----------- .../.pacta/snapshots/objects/afd35017.json | 467 --------- .../.pacta/snapshots/objects/b4228f1d.json | 753 --------------- .../.pacta/snapshots/objects/ba00988a.json | 621 ------------ .../.pacta/snapshots/objects/c8ec26a4.json | 645 ------------- .../.pacta/snapshots/objects/cc292fef.json | 613 ------------ .../.pacta/snapshots/refs/latest | 1 - 14 files changed, 9068 deletions(-) delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/0ea5fad2.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/10dfb35a.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/14ec11dd.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/2722c4bc.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/5a624473.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/660c26b5.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/a2ad2dcf.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/ac29788f.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/afd35017.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/b4228f1d.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/ba00988a.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/c8ec26a4.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/objects/cc292fef.json delete mode 100644 examples/simple-layered-app/.pacta/snapshots/refs/latest diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/0ea5fad2.json b/examples/simple-layered-app/.pacta/snapshots/objects/0ea5fad2.json deleted file mode 100644 index e1f3c3f..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/0ea5fad2.json +++ /dev/null @@ -1,579 +0,0 @@ -{ - "_hash": "0ea5fad25d41e124a103f4352b35e1d32295cceaf6214ea03e9d7229c56331f3", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "feature", - "commit": "000000eabc", - "created_at": "2025-01-15T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule3", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule4", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule5", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule6", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule7", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule8", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/10dfb35a.json b/examples/simple-layered-app/.pacta/snapshots/objects/10dfb35a.json deleted file mode 100644 index 4d61f19..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/10dfb35a.json +++ /dev/null @@ -1,829 +0,0 @@ -{ - "_hash": "10dfb35a1360c351c93d2a29b2e18d7fe8c46cd2ca7a4e9144e3ed29aa5b5675", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod19", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod20", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod19", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "0000046abc", - "created_at": "2025-03-12T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod14", - "path": "src/mod14.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod15", - "path": "src/mod15.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod16", - "path": "src/mod16.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod17", - "path": "src/mod17.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod18", - "path": "src/mod18.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod19", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod19", - "path": "src/mod19.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/14ec11dd.json b/examples/simple-layered-app/.pacta/snapshots/objects/14ec11dd.json deleted file mode 100644 index ff60ebe..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/14ec11dd.json +++ /dev/null @@ -1,853 +0,0 @@ -{ - "_hash": "14ec11ddc60b477efa20977e3976e587a63fb6574292ead510ea4ade2e47bb74", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod20", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod21", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod19", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod20", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod19", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "000004dabc", - "created_at": "2025-03-19T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod14", - "path": "src/mod14.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod15", - "path": "src/mod15.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod16", - "path": "src/mod16.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod17", - "path": "src/mod17.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod18", - "path": "src/mod18.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod19", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod19", - "path": "src/mod19.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod20", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod20", - "path": "src/mod20.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/2722c4bc.json b/examples/simple-layered-app/.pacta/snapshots/objects/2722c4bc.json deleted file mode 100644 index dd6c302..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/2722c4bc.json +++ /dev/null @@ -1,897 +0,0 @@ -{ - "_hash": "2722c4bc17489075df143f0e0668a94ee8936739f2d15eeb0fbe8c0bd1143afe", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.application.order_service", - "name": "OrderService" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.application.order_service", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "application", - "loc": { - "end": null, - "file": "src/ui/order_controller.py", - "start": { - "column": 1, - "line": 3 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.ui.order_controller", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "ui" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.application.user_service", - "name": "UserService" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.application.user_service", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "application", - "loc": { - "end": null, - "file": "src/ui/user_controller.py", - "start": { - "column": 1, - "line": 3 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.ui.user_controller", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "ui" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.domain.order", - "name": "Order" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.domain.order", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "domain", - "loc": { - "end": null, - "file": "src/application/order_service.py", - "start": { - "column": 1, - "line": 3 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.application.order_service", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "application" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.domain.order", - "name": "Order" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.domain.order", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "domain", - "loc": { - "end": null, - "file": "src/infra/order_repository.py", - "start": { - "column": 1, - "line": 3 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.infra.order_repository", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "infra" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.domain.user", - "name": "User" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.domain.user", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "domain", - "loc": { - "end": null, - "file": "src/application/user_service.py", - "start": { - "column": 1, - "line": 3 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.application.user_service", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "application" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.domain.user", - "name": "User" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.domain.user", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "domain", - "loc": { - "end": null, - "file": "src/infra/database.py", - "start": { - "column": 1, - "line": 5 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.infra.database", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "infra" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.domain.user", - "name": "User" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.domain.user", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "domain", - "loc": { - "end": null, - "file": "src/infra/user_repository.py", - "start": { - "column": 1, - "line": 5 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.infra.user_repository", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "infra" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.infra.database", - "name": "Database" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.infra.database", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "infra", - "loc": { - "end": null, - "file": "src/ui/user_controller.py", - "start": { - "column": 1, - "line": 7 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.ui.user_controller", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "ui" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.infra.order_repository", - "name": "OrderRepository" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.infra.order_repository", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "infra", - "loc": { - "end": null, - "file": "src/application/order_service.py", - "start": { - "column": 1, - "line": 4 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.application.order_service", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "application" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.infra.user_repository", - "name": "UserRepository" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.infra.user_repository", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "infra", - "loc": { - "end": null, - "file": "src/application/user_service.py", - "start": { - "column": 1, - "line": 4 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.application.user_service", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "application" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "src.ui.order_controller", - "name": "OrderController" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "src.ui.order_controller", - "language": "python" - }, - "dst_container": "main-app", - "dst_context": null, - "dst_layer": "ui", - "loc": { - "end": null, - "file": "src/application/order_service.py", - "start": { - "column": 1, - "line": 5 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.application.order_service", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "application" - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": { - "kind": "from", - "level": 0, - "module": "typing", - "name": "List" - }, - "dst": { - "code_root": "simple-layered-app", - "fqname": "typing", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": { - "end": null, - "file": "src/domain/order.py", - "start": { - "column": 1, - "line": 3 - } - }, - "src": { - "code_root": "simple-layered-app", - "fqname": "src.domain.order", - "language": "python" - }, - "src_container": "main-app", - "src_context": null, - "src_layer": "domain" - } - ], - "meta": { - "branch": "feature/github-action", - "commit": "f9bac778c137f6ca128aa5bfb3a6a2ca2efb2e68", - "created_at": "2026-01-28T09:27:30.470256+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": { - "end": null, - "file": "src/__init__.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "src", - "path": "src/__init__.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.application", - "language": "python" - }, - "kind": "module", - "layer": "application", - "loc": { - "end": null, - "file": "src/application/__init__.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "application", - "path": "src/application/__init__.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.application.order_service", - "language": "python" - }, - "kind": "module", - "layer": "application", - "loc": { - "end": null, - "file": "src/application/order_service.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "order_service", - "path": "src/application/order_service.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.application.user_service", - "language": "python" - }, - "kind": "module", - "layer": "application", - "loc": { - "end": null, - "file": "src/application/user_service.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "user_service", - "path": "src/application/user_service.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.domain", - "language": "python" - }, - "kind": "module", - "layer": "domain", - "loc": { - "end": null, - "file": "src/domain/__init__.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "domain", - "path": "src/domain/__init__.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.domain.order", - "language": "python" - }, - "kind": "module", - "layer": "domain", - "loc": { - "end": null, - "file": "src/domain/order.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "order", - "path": "src/domain/order.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.domain.user", - "language": "python" - }, - "kind": "module", - "layer": "domain", - "loc": { - "end": null, - "file": "src/domain/user.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "user", - "path": "src/domain/user.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.infra", - "language": "python" - }, - "kind": "module", - "layer": "infra", - "loc": { - "end": null, - "file": "src/infra/__init__.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "infra", - "path": "src/infra/__init__.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.infra.database", - "language": "python" - }, - "kind": "module", - "layer": "infra", - "loc": { - "end": null, - "file": "src/infra/database.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "database", - "path": "src/infra/database.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.infra.order_repository", - "language": "python" - }, - "kind": "module", - "layer": "infra", - "loc": { - "end": null, - "file": "src/infra/order_repository.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "order_repository", - "path": "src/infra/order_repository.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.infra.user_repository", - "language": "python" - }, - "kind": "module", - "layer": "infra", - "loc": { - "end": null, - "file": "src/infra/user_repository.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "user_repository", - "path": "src/infra/user_repository.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.ui", - "language": "python" - }, - "kind": "module", - "layer": "ui", - "loc": { - "end": null, - "file": "src/ui/__init__.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "ui", - "path": "src/ui/__init__.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.ui.order_controller", - "language": "python" - }, - "kind": "module", - "layer": "ui", - "loc": { - "end": null, - "file": "src/ui/order_controller.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "order_controller", - "path": "src/ui/order_controller.py", - "tags": [] - }, - { - "attributes": {}, - "container": "main-app", - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "src.ui.user_controller", - "language": "python" - }, - "kind": "module", - "layer": "ui", - "loc": { - "end": null, - "file": "src/ui/user_controller.py", - "start": { - "column": 1, - "line": 1 - } - }, - "name": "user_controller", - "path": "src/ui/user_controller.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "simple-layered-app", - "fqname": "typing", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "typing", - "path": null, - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": { - "dep_type": "import", - "dst_container": "main-app", - "dst_context": null, - "dst_fqname": "src.infra.database", - "dst_id": "python://simple-layered-app::src.infra.database", - "dst_layer": "infra", - "src_container": "main-app", - "src_context": null, - "src_fqname": "src.ui.user_controller", - "src_id": "python://simple-layered-app::src.ui.user_controller", - "src_layer": "ui", - "target": "dependency" - }, - "location": { - "column": 1, - "end_column": null, - "end_line": null, - "file": "src/ui/user_controller.py", - "line": 7 - }, - "message": "UI layer should not directly depend on Infrastructure layer", - "rule": { - "description": null, - "id": "no_ui_to_infra", - "name": "UI should not directly access Infrastructure", - "severity": "warning" - }, - "status": "unknown", - "suggestion": "Access infrastructure through application services instead", - "violation_key": "394469e3be36ac776a8eaa14ce1171dda428f0a9" - }, - { - "context": { - "dep_type": "import", - "dst_container": "main-app", - "dst_context": null, - "dst_fqname": "src.domain.user", - "dst_id": "python://simple-layered-app::src.domain.user", - "dst_layer": "domain", - "src_container": "main-app", - "src_context": null, - "src_fqname": "src.infra.database", - "src_id": "python://simple-layered-app::src.infra.database", - "src_layer": "infra", - "target": "dependency" - }, - "location": { - "column": 1, - "end_column": null, - "end_line": null, - "file": "src/infra/database.py", - "line": 5 - }, - "message": "Infrastructure implementing domain interfaces (tracked for visibility)", - "rule": { - "description": null, - "id": "infra_can_use_domain", - "name": "Infrastructure implementing domain interfaces", - "severity": "info" - }, - "status": "unknown", - "suggestion": null, - "violation_key": "daf7ebe686b02da8204c737b607bbb360fc3bd72" - }, - { - "context": { - "dep_type": "import", - "dst_container": "main-app", - "dst_context": null, - "dst_fqname": "src.domain.order", - "dst_id": "python://simple-layered-app::src.domain.order", - "dst_layer": "domain", - "src_container": "main-app", - "src_context": null, - "src_fqname": "src.infra.order_repository", - "src_id": "python://simple-layered-app::src.infra.order_repository", - "src_layer": "infra", - "target": "dependency" - }, - "location": { - "column": 1, - "end_column": null, - "end_line": null, - "file": "src/infra/order_repository.py", - "line": 3 - }, - "message": "Infrastructure implementing domain interfaces (tracked for visibility)", - "rule": { - "description": null, - "id": "infra_can_use_domain", - "name": "Infrastructure implementing domain interfaces", - "severity": "info" - }, - "status": "unknown", - "suggestion": null, - "violation_key": "3ecb956f2c2073332cffa8cca46ac7ce3b8ff2c2" - }, - { - "context": { - "dep_type": "import", - "dst_container": "main-app", - "dst_context": null, - "dst_fqname": "src.domain.user", - "dst_id": "python://simple-layered-app::src.domain.user", - "dst_layer": "domain", - "src_container": "main-app", - "src_context": null, - "src_fqname": "src.infra.user_repository", - "src_id": "python://simple-layered-app::src.infra.user_repository", - "src_layer": "infra", - "target": "dependency" - }, - "location": { - "column": 1, - "end_column": null, - "end_line": null, - "file": "src/infra/user_repository.py", - "line": 5 - }, - "message": "Infrastructure implementing domain interfaces (tracked for visibility)", - "rule": { - "description": null, - "id": "infra_can_use_domain", - "name": "Infrastructure implementing domain interfaces", - "severity": "info" - }, - "status": "unknown", - "suggestion": null, - "violation_key": "bcc98abe10c4f666d584ee25a722b0843c0d1c08" - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/5a624473.json b/examples/simple-layered-app/.pacta/snapshots/objects/5a624473.json deleted file mode 100644 index eaaaf5b..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/5a624473.json +++ /dev/null @@ -1,733 +0,0 @@ -{ - "_hash": "5a624473c58600a4f3aaaee777060ae6ce2d72c81b6fd9397bd235d5e970f73c", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "feature", - "commit": "000002aabc", - "created_at": "2025-02-12T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod14", - "path": "src/mod14.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod15", - "path": "src/mod15.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule3", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule4", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule5", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/660c26b5.json b/examples/simple-layered-app/.pacta/snapshots/objects/660c26b5.json deleted file mode 100644 index 8a3f35f..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/660c26b5.json +++ /dev/null @@ -1,729 +0,0 @@ -{ - "_hash": "660c26b5904c58e57014ccaca9c206bf3336fadfc81fc7dddd33332dd9cf77da", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "0000031abc", - "created_at": "2025-02-19T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod14", - "path": "src/mod14.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod15", - "path": "src/mod15.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod16", - "path": "src/mod16.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/a2ad2dcf.json b/examples/simple-layered-app/.pacta/snapshots/objects/a2ad2dcf.json deleted file mode 100644 index 8c2c25f..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/a2ad2dcf.json +++ /dev/null @@ -1,819 +0,0 @@ -{ - "_hash": "a2ad2dcf8eb39f8fb1a32294ea424758bf448a969cbfa31087f5c1140d43d5ba", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod19", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "hotfix", - "commit": "000003fabc", - "created_at": "2025-03-05T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod14", - "path": "src/mod14.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod15", - "path": "src/mod15.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod16", - "path": "src/mod16.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod17", - "path": "src/mod17.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod18", - "path": "src/mod18.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule3", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/ac29788f.json b/examples/simple-layered-app/.pacta/snapshots/objects/ac29788f.json deleted file mode 100644 index 0777115..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/ac29788f.json +++ /dev/null @@ -1,529 +0,0 @@ -{ - "_hash": "ac29788fcd05ac474493d2e493a95511bbf375c77677877633ecd2b0df4b74de", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "0000007abc", - "created_at": "2025-01-08T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule3", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule4", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule5", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule6", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/afd35017.json b/examples/simple-layered-app/.pacta/snapshots/objects/afd35017.json deleted file mode 100644 index 756275f..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/afd35017.json +++ /dev/null @@ -1,467 +0,0 @@ -{ - "_hash": "afd3501728b0dcdb5b071c87cf7d4878602553345b2f4aef2570e38c00a8ed95", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "0000000abc", - "created_at": "2025-01-01T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule3", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule4", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule5", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule6", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule7", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/b4228f1d.json b/examples/simple-layered-app/.pacta/snapshots/objects/b4228f1d.json deleted file mode 100644 index 139c12d..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/b4228f1d.json +++ /dev/null @@ -1,753 +0,0 @@ -{ - "_hash": "b4228f1d453172925b22b791d3283578d0381b00a98da6faeb102235dcc37559", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod18", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "0000038abc", - "created_at": "2025-02-26T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod14", - "path": "src/mod14.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod15", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod15", - "path": "src/mod15.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod16", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod16", - "path": "src/mod16.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod17", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod17", - "path": "src/mod17.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/ba00988a.json b/examples/simple-layered-app/.pacta/snapshots/objects/ba00988a.json deleted file mode 100644 index 39ab36b..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/ba00988a.json +++ /dev/null @@ -1,621 +0,0 @@ -{ - "_hash": "ba00988a9e84530e6b2e1483ab9c588f0b9e8bc767a697ba49655adc0f6c600f", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "000001cabc", - "created_at": "2025-01-29T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule3", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule4", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/c8ec26a4.json b/examples/simple-layered-app/.pacta/snapshots/objects/c8ec26a4.json deleted file mode 100644 index 3e7e340..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/c8ec26a4.json +++ /dev/null @@ -1,645 +0,0 @@ -{ - "_hash": "c8ec26a4e9c151cd778ba16ca5e3462d24ae0637fd20cd3b077fd0f972341306", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "0000023abc", - "created_at": "2025-02-05T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod14", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod14", - "path": "src/mod14.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule3", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/objects/cc292fef.json b/examples/simple-layered-app/.pacta/snapshots/objects/cc292fef.json deleted file mode 100644 index e6957e5..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/objects/cc292fef.json +++ /dev/null @@ -1,613 +0,0 @@ -{ - "_hash": "cc292fefc18a2576e6f581fab2fa224d367d6e37058b41144cb39b9694e07a03", - "edges": [ - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - }, - { - "confidence": 1.0, - "dep_type": "import", - "details": {}, - "dst": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "dst_container": null, - "dst_context": null, - "dst_layer": null, - "loc": null, - "src": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "src_container": null, - "src_context": null, - "src_layer": null - } - ], - "meta": { - "branch": "main", - "commit": "0000015abc", - "created_at": "2025-01-22T12:00:00+00:00", - "extra": {}, - "model_version": null, - "repo_root": "examples/simple-layered-app", - "tool_version": null - }, - "nodes": [ - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod0", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod0", - "path": "src/mod0.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod1", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod1", - "path": "src/mod1.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod10", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod10", - "path": "src/mod10.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod11", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod11", - "path": "src/mod11.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod12", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod12", - "path": "src/mod12.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod13", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod13", - "path": "src/mod13.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod2", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod2", - "path": "src/mod2.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod3", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod3", - "path": "src/mod3.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod4", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod4", - "path": "src/mod4.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod5", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod5", - "path": "src/mod5.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod6", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod6", - "path": "src/mod6.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod7", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod7", - "path": "src/mod7.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod8", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod8", - "path": "src/mod8.py", - "tags": [] - }, - { - "attributes": {}, - "container": null, - "context": null, - "id": { - "code_root": "demo", - "fqname": "mod9", - "language": "python" - }, - "kind": "module", - "layer": null, - "loc": null, - "name": "module_mod9", - "path": "src/mod9.py", - "tags": [] - } - ], - "schema_version": 1, - "violations": [ - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule0", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule1", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule2", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule3", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule4", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - }, - { - "context": {}, - "location": null, - "message": "Architecture violation", - "rule": { - "description": null, - "id": "rule5", - "name": "Test Rule", - "severity": "error" - }, - "status": "unknown", - "suggestion": null, - "violation_key": null - } - ] -} diff --git a/examples/simple-layered-app/.pacta/snapshots/refs/latest b/examples/simple-layered-app/.pacta/snapshots/refs/latest deleted file mode 100644 index e7a05a4..0000000 --- a/examples/simple-layered-app/.pacta/snapshots/refs/latest +++ /dev/null @@ -1 +0,0 @@ -2722c4bc From 52b1b01a504dfebbdce08dc85e4b5ceeb3f89e8c Mon Sep 17 00:00:00 2001 From: Murad Akhundov Date: Thu, 29 Jan 2026 01:04:06 +0100 Subject: [PATCH 12/12] docs(ci-integration): add GitHub Action comment example and document target_dir input --- assets/github-action-example.png | Bin 0 -> 150754 bytes docs/ci-integration.md | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 assets/github-action-example.png diff --git a/assets/github-action-example.png b/assets/github-action-example.png new file mode 100644 index 0000000000000000000000000000000000000000..87e4cea8b7c433e9f4fe0afb095e17b046196594 GIT binary patch literal 150754 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

!5*3cL4 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 Sqz$iue^TP|V#T5ce*X{o5ZfjI literal 0 HcmV?d00001 diff --git a/docs/ci-integration.md b/docs/ci-integration.md index 4ec0a03..ca6167f 100644 --- a/docs/ci-integration.md +++ b/docs/ci-integration.md @@ -119,10 +119,15 @@ The action will: - Post (or update) a PR comment with structural changes, new/fixed violations, and architecture trends - Fail the check if new violations are introduced (configurable via `fail-on-violations: false`) +**Example comment:** + +![Github Action output example](https://raw.githubusercontent.com/akhundMurad/pacta/main/assets/github-action-example.png) + **Action Inputs:** | Input | Default | Description | |-------|---------|-------------| +| `target_dir` | `.` | Repository root | | `model` | `architecture.yml` | Path to architecture model | | `rules` | `rules.pacta.yml` | Path to rules file | | `baseline` | *(none)* | Baseline ref for incremental checks |