Skip to content

Commit b57e0b6

Browse files
committed
agents and deps with failing tests
1 parent dab6c0f commit b57e0b6

7 files changed

Lines changed: 85 additions & 26 deletions

File tree

AGENTS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ on [Ash Framework](https://www.ash-hq.org/) + [AshNeo4j](https://github.com/diff
1919
2. Read `CLAUDE.md` — dependency usage rules (Ash, Elixir, OTP, AshNeo4j, Spark).
2020
3. Consult the skill at `.claude/skills/diffo-framework/` for Ash ecosystem patterns.
2121

22+
## Updating dependencies
23+
24+
When updating a dependency (e.g. bumping `ash_neo4j`, `ash`, `spark` in `mix.exs`), always
25+
run `mix usage_rules.sync` immediately after `mix deps.get`. Dependencies publish their own
26+
usage rules; syncing pulls those changes into `CLAUDE.md` so you are working from the
27+
up-to-date guidance before touching any code.
28+
2229
## Project structure
2330

2431
```

lib/diffo/provider/components/instance/extension/characteristic.ex

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ defmodule Diffo.Provider.Instance.Characteristic do
77
require Logger
88

99
alias Diffo.Provider
10-
alias Diffo.Provider.Instance
1110
alias Diffo.Type.Value
11+
alias AshNeo4j.Resource.Info, as: Neo4jInfo
12+
alias AshNeo4j.Neo4jHelper
1213

1314
@doc """
1415
Struct for a Characteristic
@@ -66,10 +67,35 @@ defmodule Diffo.Provider.Instance.Characteristic do
6667
def relate_instance(result, changeset)
6768
when is_struct(result) and is_struct(changeset, Ash.Changeset) do
6869
characteristics = Ash.Changeset.get_argument(changeset, :characteristics)
70+
relate_to_instance(result, characteristics)
71+
end
6972

70-
Provider.relate_instance_characteristics(%Instance{id: result.id}, %{
71-
characteristics: characteristics
72-
})
73+
# Directly create HAS edges in Neo4j rather than going through manage_relationship.
74+
# manage_relationship on a has_many triggers accessing_from updates on each
75+
# Characteristic, which break because Ash.Resource.Info.reverse_relationship
76+
# finds no path back to the concrete resource (ShelfInstance etc.) — Characteristic's
77+
# belongs_to :instance targets the generic Diffo.Provider.Instance, not the
78+
# domain-specific subtype.
79+
defp relate_to_instance(result, nil), do: {:ok, result}
80+
defp relate_to_instance(result, []), do: {:ok, result}
81+
82+
defp relate_to_instance(result, char_ids) do
83+
instance_label_pair = Neo4jInfo.label_pair(result.__struct__)
84+
char_label = Neo4jInfo.label(Diffo.Provider.Characteristic)
85+
86+
Enum.reduce_while(char_ids, {:ok, result}, fn char_id, acc ->
87+
case Neo4jHelper.relate_nodes(
88+
instance_label_pair,
89+
%{uuid: result.id},
90+
char_label,
91+
%{uuid: char_id},
92+
:HAS,
93+
:outgoing
94+
) do
95+
{:ok, _} -> {:cont, acc}
96+
{:error, error} -> {:halt, {:error, error}}
97+
end
98+
end)
7399
end
74100

75101
@doc """

lib/diffo/provider/components/instance/extension/feature.ex

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ defmodule Diffo.Provider.Instance.Feature do
77
require Logger
88

99
alias Diffo.Provider
10-
alias Diffo.Provider.Instance
1110
alias Diffo.Type.Value
11+
alias AshNeo4j.Resource.Info, as: Neo4jInfo
12+
alias AshNeo4j.Neo4jHelper
1213

1314
@doc """
1415
Struct for a Feature
@@ -94,7 +95,33 @@ defmodule Diffo.Provider.Instance.Feature do
9495
def relate_instance(result, changeset)
9596
when is_struct(result) and is_struct(changeset, Ash.Changeset) do
9697
features = Ash.Changeset.get_argument(changeset, :features)
97-
Provider.relate_instance_features(%Instance{id: result.id}, %{features: features})
98+
relate_to_instance(result, features)
99+
end
100+
101+
# Directly create HAS edges rather than going through manage_relationship,
102+
# for the same reason as Characteristic: the accessing_from path breaks because
103+
# Feature's belongs_to :instance targets Diffo.Provider.Instance, not the
104+
# domain-specific concrete resource (ShelfInstance etc.).
105+
defp relate_to_instance(result, nil), do: {:ok, result}
106+
defp relate_to_instance(result, []), do: {:ok, result}
107+
108+
defp relate_to_instance(result, feature_ids) do
109+
instance_label_pair = Neo4jInfo.label_pair(result.__struct__)
110+
feature_label = Neo4jInfo.label(Diffo.Provider.Feature)
111+
112+
Enum.reduce_while(feature_ids, {:ok, result}, fn feature_id, acc ->
113+
case Neo4jHelper.relate_nodes(
114+
instance_label_pair,
115+
%{uuid: result.id},
116+
feature_label,
117+
%{uuid: feature_id},
118+
:HAS,
119+
:outgoing
120+
) do
121+
{:ok, _} -> {:cont, acc}
122+
{:error, error} -> {:halt, {:error, error}}
123+
end
124+
end)
98125
end
99126

100127
defimpl String.Chars do

lib/diffo/provider/components/instance/extension/specification.ex

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ defmodule Diffo.Provider.Instance.Specification do
77
require Logger
88

99
alias Diffo.Provider
10-
alias Diffo.Provider.Instance
1110

1211
@doc """
1312
Struct for a Specification
@@ -48,7 +47,13 @@ defmodule Diffo.Provider.Instance.Specification do
4847
def relate_instance(result, changeset)
4948
when is_struct(result) and is_struct(changeset, Ash.Changeset) do
5049
specified_by = Ash.Changeset.get_argument(changeset, :specified_by)
51-
Provider.respecify_instance(%Instance{id: result.id}, %{specified_by: specified_by})
50+
51+
# Clear specification_id so manage_relationship sees nil→id (add only, no spurious remove).
52+
# action_helper pre-sets specification_id before calling us, which would make
53+
# Ash treat old==new and generate an empty-argument remove that fails.
54+
%{result | specification_id: nil}
55+
|> Ash.Changeset.for_update(:specify, %{specified_by: specified_by})
56+
|> Ash.update()
5257
end
5358

5459
defimpl String.Chars do

lib/diffo/provider/components/party_ref.ex

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,11 @@ defmodule Diffo.Provider.PartyRef do
5151

5252
create :create do
5353
description "creates a party ref, relating an instance, place or source party to a party"
54-
accept [:role]
55-
56-
argument :instance_id, :uuid
57-
argument :place_id, :string
58-
argument :source_party_id, :string
59-
argument :party_id, :string
60-
61-
change manage_relationship(:instance_id, :instance, type: :append_and_remove)
62-
change manage_relationship(:place_id, :place, type: :append_and_remove)
63-
change manage_relationship(:source_party_id, :source_party, type: :append_and_remove)
64-
change manage_relationship(:party_id, :party, type: :append_and_remove)
54+
# IDs accepted directly as attributes so AshNeo4j's create_from_attributes path
55+
# builds graph edges using the single labels in the relate DSL (:Instance, :Party, :Place).
56+
# manage_relationship would fail: it looks up the generic Diffo.Provider.Instance/Party
57+
# by label_pair, which doesn't match domain-specific subtypes (ShelfInstance, Person, etc.).
58+
accept [:role, :instance_id, :place_id, :source_party_id, :party_id]
6559
end
6660

6761
read :list do

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ defmodule Diffo.MixProject do
124124
{:ash_outstanding, "~> 0.2.3"},
125125
{:ash_jason, "~> 3.0"},
126126
{:ash_state_machine, "~> 0.2.12"},
127-
{:ash_neo4j, ash_neo4j_version("~> 0.5")},
127+
{:ash_neo4j, ash_neo4j_version("~> 0.6")},
128128
{:bolty, ">= 0.0.12"},
129129
{:ash, ash_version("~> 3.0 and >= 3.24.2")},
130130
{:uuid, "~> 1.1"},

0 commit comments

Comments
 (0)