Skip to content

Commit 02398a3

Browse files
committed
chore(ai): add diagram of preferred semver flow
1 parent 48a80ee commit 02398a3

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# preferred_semver.rs Decision Tree
2+
3+
```mermaid
4+
flowchart TD
5+
Start["visit(dependency)"] --> InvalidLocal{"has invalid<br/>local instance?"}
6+
7+
%% ── Invalid local ──
8+
InvalidLocal -->|Y| ForEachInvalid["for each instance"]
9+
ForEachInvalid --> IsLocalInvalid{"is_local?"}
10+
IsLocalInvalid -->|Y| S_InvalidLocalVersion["⚠️ InvalidLocalVersion"]
11+
IsLocalInvalid -->|N| E_DependsOnInvalid["❌ DependsOnInvalidLocalPackage"]
12+
13+
%% ── Valid local ──
14+
InvalidLocal -->|N| HasLocal{"has local<br/>instance?"}
15+
HasLocal -->|Y| ForEachLocal["for each instance"]
16+
ForEachLocal --> IsLocalValid{"is_local?"}
17+
IsLocalValid -->|Y| V_IsLocalAndValid["✅ IsLocalAndValid"]
18+
IsLocalValid -->|N| IsLink{"is link<br/>specifier?"}
19+
20+
IsLink -->|Y| LinkResolves{"link resolves to<br/>local package?"}
21+
LinkResolves -->|Y| V_SatisfiesLocal_Link["✅ SatisfiesLocal"]
22+
LinkResolves -->|N| F_DiffersToLocal_Link["🔧 DiffersToLocal"]
23+
24+
IsLink -->|N| IsWorkspace{"is workspace<br/>protocol?"}
25+
IsWorkspace -->|Y| StrictMode{"strict mode?"}
26+
StrictMode -->|N| V_SatisfiesLocal_WS["✅ SatisfiesLocal"]
27+
StrictMode -->|Y| LocalVersionCheck
28+
IsWorkspace -->|N| LocalVersionCheck
29+
30+
LocalVersionCheck{"same version<br/>as local?"}
31+
LocalVersionCheck -->|N| F_DiffersToLocal["🔧 DiffersToLocal"]
32+
LocalVersionCheck -->|Y| LocalSemverGroup{"semver group prefers<br/>range ≠ Exact?"}
33+
34+
LocalSemverGroup -->|N| LocalAlreadyEquals{"already equals<br/>local?"}
35+
LocalAlreadyEquals -->|Y| V_IsIdenticalToLocal["✅ IsIdenticalToLocal"]
36+
LocalAlreadyEquals -->|N| F_DiffersToLocal2["🔧 DiffersToLocal"]
37+
38+
LocalSemverGroup -->|Y| LocalMatchesPreferred{"actual range =<br/>preferred range?"}
39+
LocalMatchesPreferred -->|Y| LocalPrefSatisfies{"preferred range<br/>satisfies local?"}
40+
LocalPrefSatisfies -->|Y| V_SatisfiesLocal_SG["✅ SatisfiesLocal"]
41+
LocalPrefSatisfies -->|N| C_MatchConflictsLocal["💥 MatchConflictsWithLocal"]
42+
43+
LocalMatchesPreferred -->|N| LocalPrefSatisfies2{"preferred range<br/>satisfies local?"}
44+
LocalPrefSatisfies2 -->|Y| F_SemverRangeMismatch_Local["🔧 SemverRangeMismatch"]
45+
LocalPrefSatisfies2 -->|N| C_MismatchConflictsLocal["💥 MismatchConflictsWithLocal"]
46+
47+
%% ── Catalog ──
48+
HasLocal -->|N| HasCatalog{"any instance uses<br/>catalog: protocol?"}
49+
HasCatalog -->|Y| ForEachCatalog["for each instance"]
50+
ForEachCatalog --> IsCatalog{"is catalog:?"}
51+
IsCatalog -->|Y| V_IsCatalog["✅ IsCatalog"]
52+
IsCatalog -->|N| F_DiffersToCatalog["🔧 DiffersToCatalog"]
53+
54+
%% ── Registry updates ──
55+
HasCatalog -->|N| HasUpdates{"eligible registry<br/>updates?"}
56+
HasUpdates -->|Y| ForEachUpdate["for each instance"]
57+
ForEachUpdate --> F_DiffersToNpmRegistry["🔧 DiffersToNpmRegistry"]
58+
59+
%% ── Highest/Lowest semver ──
60+
HasUpdates -->|N| HasHighest{"has highest/lowest<br/>semver specifier?"}
61+
HasHighest -->|Y| ForEachHighest["for each instance"]
62+
ForEachHighest --> SameVersion{"same version<br/>as highest?"}
63+
64+
SameVersion -->|N| F_DiffersToHighest["🔧 DiffersToHighestOrLowestSemver<br/>(with preferred range applied)"]
65+
66+
SameVersion -->|Y| HighestSemverGroup{"semver group prefers<br/>range ≠ highest range?"}
67+
68+
HighestSemverGroup -->|Y| HighestMatchesPref{"actual range =<br/>preferred range?"}
69+
70+
HighestMatchesPref -->|Y| HighestPrefSatisfies{"preferred range<br/>satisfies highest?"}
71+
HighestPrefSatisfies -->|Y| V_SatisfiesHighest["✅ SatisfiesHighestOrLowestSemver"]
72+
HighestPrefSatisfies -->|N| C_MatchConflictsHighest["💥 MatchConflictsWithHighestOrLowestSemver"]
73+
74+
HighestMatchesPref -->|N| HighestPrefSatisfies2{"preferred range<br/>satisfies highest?"}
75+
HighestPrefSatisfies2 -->|Y| F_SemverRangeMismatch_Highest["🔧 SemverRangeMismatch"]
76+
HighestPrefSatisfies2 -->|N| C_MismatchConflictsHighest["💥 MismatchConflictsWithHighestOrLowestSemver"]
77+
78+
HighestSemverGroup -->|N| HasPrefMismatch{"has preferred range<br/>AND actual ≠ preferred?"}
79+
80+
HasPrefMismatch -->|Y| PrefSatisfiesHighest3{"preferred range<br/>satisfies highest?"}
81+
PrefSatisfiesHighest3 -->|Y| F_SemverRangeMismatch_Adj["🔧 SemverRangeMismatch"]
82+
PrefSatisfiesHighest3 -->|N| C_MismatchConflictsHighest2["💥 MismatchConflictsWithHighestOrLowestSemver"]
83+
84+
HasPrefMismatch -->|N| HighestAlreadyEquals{"already equals<br/>highest?"}
85+
HighestAlreadyEquals -->|Y| V_IsHighest["✅ IsHighestOrLowestSemver"]
86+
HighestAlreadyEquals -->|N| F_DiffersToHighest2["🔧 DiffersToHighestOrLowestSemver"]
87+
88+
%% ── No semver ──
89+
HasHighest -->|N| AllIdentical{"every specifier<br/>identical?"}
90+
AllIdentical -->|Y| V_NonSemverIdentical["✅ IsNonSemverButIdentical"]
91+
AllIdentical -->|N| E_NonSemverMismatch["❌ NonSemverMismatch"]
92+
93+
%% ── Styling ──
94+
classDef valid fill:#d4edda,stroke:#28a745,color:#000
95+
classDef fixable fill:#fff3cd,stroke:#ffc107,color:#000
96+
classDef conflict fill:#f8d7da,stroke:#dc3545,color:#000
97+
classDef suspect fill:#e2e3e5,stroke:#6c757d,color:#000
98+
classDef unfixable fill:#f8d7da,stroke:#dc3545,color:#000
99+
100+
class V_IsLocalAndValid,V_SatisfiesLocal_Link,V_SatisfiesLocal_WS,V_IsIdenticalToLocal,V_SatisfiesLocal_SG,V_IsCatalog,V_SatisfiesHighest,V_IsHighest,V_NonSemverIdentical valid
101+
class F_DiffersToLocal_Link,F_DiffersToLocal,F_DiffersToLocal2,F_SemverRangeMismatch_Local,F_DiffersToCatalog,F_DiffersToNpmRegistry,F_DiffersToHighest,F_SemverRangeMismatch_Highest,F_SemverRangeMismatch_Adj,F_DiffersToHighest2 fixable
102+
class C_MatchConflictsLocal,C_MismatchConflictsLocal,C_MatchConflictsHighest,C_MismatchConflictsHighest,C_MismatchConflictsHighest2 conflict
103+
class S_InvalidLocalVersion suspect
104+
class E_DependsOnInvalid,E_NonSemverMismatch unfixable
105+
```
106+
107+
## Legend
108+
109+
| Icon | Category | Meaning |
110+
| ---- | --------- | ---------------------------------------------- |
111+
|| Valid | No action needed |
112+
| 🔧 | Fixable | Can be auto-fixed |
113+
| 💥 | Conflict | Semver group and version goal are incompatible |
114+
| ⚠️ | Suspect | Questionable but not fixable |
115+
|| Unfixable | Error that cannot be auto-fixed |
116+
117+
## Branch Priority
118+
119+
The top-level branches are evaluated in order — first match wins:
120+
121+
1. **Invalid local** — local package has missing/invalid `.version`
122+
2. **Valid local** — dependency is developed in this monorepo
123+
3. **Catalog** — any instance uses `catalog:` protocol
124+
4. **Registry updates** — npm registry has eligible updates
125+
5. **Highest/lowest semver** — compare against highest (or lowest) version
126+
6. **No semver** — none of the above apply

0 commit comments

Comments
 (0)