net.anisota.graph.wordlist
Schema Diff
+11 -2
Compatibility Analysis
Backward Compatible
Backward compatible. 2 non-breaking changes.
Non-Breaking Changes (2)
- AddedVertex AddedVertex { vertex_id: "net.anisota.graph.wordlist:body.treatment" }
- AddedEdge AddedEdge { src: "net.anisota.graph.wordlist:body", tgt: "net.anisota.graph.wordlist:body.treatment", kind: "prop", name: Some("treatment") }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "net.anisota.graph.wordlist:body.treatment" }
Additional Notes
- Non-breaking: AddedEdge { src: "net.anisota.graph.wordlist:body", tgt: "net.anisota.graph.wordlist:body.treatment", kind: "prop", name: Some("treatment") }
1
1
{
2
2
"$type": "com.atproto.lexicon.schema",
3
3
"defs": {
4
4
"main": {
5
5
"description": "A named, shareable list of muted words/phrases — Anisota's managed layer on top of Bluesky's flat muted-words preference. Each list is a complete, self-contained record so it can be shared by URL and saved (copied) into another user's PDS, mirroring the net.anisota.spell.custom architecture. Muting is applied client-side by the moderation pipeline: multiple enabled lists combine, a list can be scoped to specific feeds, restricted to a time-of-day/day-of-week window, and softened with a strength percentage (mute only that share of matching posts, deterministically per post). A list can optionally be projected into Bluesky's native mutedWordsPref for parity with other clients.",
6
6
"key": "tid",
7
7
"record": {
8
8
"properties": {
9
9
"createdAt": {
10
10
"description": "When this list was created",
11
11
"format": "datetime",
12
12
"type": "string"
13
13
},
14
14
"description": {
15
15
"description": "Optional description of what this list covers",
16
16
"maxLength": 300,
17
17
"type": "string"
18
18
},
19
19
"enabled": {
20
20
"default": false,
21
21
"description": "Whether this list is currently active. Scheduling and spell effects further gate an enabled list.",
22
22
"type": "boolean"
23
23
},
24
24
"name": {
25
25
"description": "Display name for this word list",
26
26
"maxLength": 64,
27
27
"type": "string"
28
28
},
29
29
"schedule": {
30
30
"description": "Optional active window. Absent means the list applies at all times while enabled.",
31
31
"ref": "#schedule",
32
32
"type": "ref"
33
33
},
34
34
"source": {
35
35
"ref": "#source",
36
36
"type": "ref"
37
37
},
38
38
"strength": {
39
-
"description": "Mute strength percentage: the share of matching posts this list mutes (deterministic per post). Absent means 100 (mute everything it matches).",
39
+
"description": "Mute strength percentage: the share of matching posts this list mutes. Which posts fill that share is decided by match confidence — how many of the list's words hit, whether they landed in the post's own text, a hashtag, or only a quoted post, and how much of the post they account for — so a softened list keeps the squarest matches muted and lets the marginal ones through. Deterministic per post, so a post never flickers. Absent means 100 (mute everything it matches).",
40
40
"maximum": 100,
41
41
"minimum": 0,
42
42
"type": "integer"
43
43
},
44
44
"syncToBluesky": {
45
45
"default": false,
46
46
"description": "Whether this list's words are also projected into Bluesky's native mutedWordsPref (managed entries, removed when the list is disabled or deleted).",
47
47
"type": "boolean"
48
48
},
49
49
"targetFeeds": {
50
50
"description": "Feeds where this list applies: feed generator / list at-uris, or the literal sentinel 'following' for the home timeline. Empty or absent applies everywhere.",
51
51
"items": {
52
52
"maxLength": 512,
53
53
"type": "string"
54
54
},
55
55
"maxLength": 50,
56
56
"type": "array"
57
57
},
58
+
"treatment": {
59
+
"description": "What this list does to a post it mutes, overriding the app-wide muted-words handling: 'hide' removes it from feeds, 'warn' collapses it behind a notice, 'show' leaves it visible and only counts it toward impact. Absent inherits the global setting.",
60
+
"knownValues": [
61
+
"hide",
62
+
"warn",
63
+
"show"
64
+
],
65
+
"type": "string"
66
+
},
58
67
"updatedAt": {
59
68
"description": "When this list was last modified",
60
69
"format": "datetime",
61
70
"type": "string"
62
71
},
63
72
"words": {
64
73
"description": "The muted words/phrases in this list",
65
74
"items": {
66
75
"ref": "#word",
67
76
"type": "ref"
68
77
},
69
78
"maxLength": 500,
70
79
"type": "array"
71
80
}
72
81
},
73
82
"required": [
74
83
"name",
75
84
"words",
76
85
"createdAt"
77
86
],
78
87
"type": "object"
79
88
},
80
89
"type": "record"
81
90
},
82
91
"schedule": {
83
-
"description": "A recurring active window. Days and time window combine: the list applies only on the listed days (absent/empty = every day) and only inside the time window (absent = all day). A window whose end is at or before its start wraps past midnight.",
92
+
"description": "A recurring active window. Days and time window combine: the list applies only on the listed days (absent/empty = every day) and only inside the time window (absent = all day). A window whose end is before its start wraps past midnight; equal start and end means no time bound (all day on the listed days).",
84
93
"properties": {
85
94
"days": {
86
95
"description": "Days of week the list is active (0 = Sunday … 6 = Saturday)",
87
96
"items": {
88
97
"maximum": 6,
89
98
"minimum": 0,
90
99
"type": "integer"
91
100
},
92
101
"maxLength": 7,
93
102
"type": "array"
94
103
},
95
104
"endTime": {
96
105
"description": "Window end as 'HH:MM' local time",
97
106
"maxLength": 5,
98
107
"type": "string"
99
108
},
100
109
"startTime": {
101
110
"description": "Window start as 'HH:MM' local time",
102
111
"maxLength": 5,
103
112
"type": "string"
104
113
}
105
114
},
106
115
"type": "object"
107
116
},
108
117
"source": {
109
118
"description": "Provenance. An 'original' list was created here; a 'learned' list was saved from another user, carrying a backlink to its immediate parent (originalUri/originalDid) and to the top of its lineage (rootUri/rootDid), modelled on net.anisota.spell.custom so save counts can aggregate across re-shares.",
110
119
"properties": {
111
120
"originalDid": {
112
121
"description": "DID of the user this list was saved from.",
113
122
"format": "did",
114
123
"type": "string"
115
124
},
116
125
"originalUri": {
117
126
"description": "AT URI of the list this copy was saved from (its immediate parent).",
118
127
"format": "at-uri",
119
128
"type": "string"
120
129
},
121
130
"rootDid": {
122
131
"description": "DID of the original author at the top of the lineage.",
123
132
"format": "did",
124
133
"type": "string"
125
134
},
126
135
"rootUri": {
127
136
"description": "AT URI of the first author's list — the top of the lineage — propagated to every descendant.",
128
137
"format": "at-uri",
129
138
"type": "string"
130
139
},
131
140
"type": {
132
141
"knownValues": [
133
142
"original",
134
143
"learned"
135
144
],
136
145
"type": "string"
137
146
}
138
147
},
139
148
"type": "object"
140
149
},
141
150
"word": {
142
151
"description": "One muted word or phrase, matching the shape of Bluesky's mutedWord items so a list can be projected into the native preference losslessly.",
143
152
"properties": {
144
153
"actorTarget": {
145
154
"description": "Whose posts to apply this word to. Absent means 'all'.",
146
155
"knownValues": [
147
156
"all",
148
157
"exclude-following"
149
158
],
150
159
"type": "string"
151
160
},
152
161
"targets": {
153
162
"description": "What to match against: post text ('content') and/or hashtags ('tag'). Absent means both.",
154
163
"items": {
155
164
"knownValues": [
156
165
"content",
157
166
"tag"
158
167
],
159
168
"type": "string"
160
169
},
161
170
"type": "array"
162
171
},
163
172
"value": {
164
173
"description": "The word or phrase to mute",
165
174
"maxLength": 100,
166
175
"type": "string"
167
176
}
168
177
},
169
178
"required": [
170
179
"value"
171
180
],
172
181
"type": "object"
173
182
}
174
183
},
175
184
"id": "net.anisota.graph.wordlist",
176
185
"lexicon": 1
177
186
}