slopless 0.2.23 → 0.2.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/rules/semantic-thinness/patterns/abstract-metaphor-claim.json +83 -1
  2. package/dist/rules/semantic-thinness/patterns/deictic-summary.json +31 -2
  3. package/dist/rules/semantic-thinness/patterns/empty-quantification.json +33 -0
  4. package/dist/rules/semantic-thinness/patterns/empty-scene-transition.json +2 -1
  5. package/dist/rules/semantic-thinness/private/concrete-guards.js +2 -0
  6. package/dist/rules/semantic-thinness/private/pattern-data-e.js +2 -0
  7. package/dist/rules/semantic-thinness/private/pattern-matcher.js +28 -7
  8. package/dist/rules/syntactic-patterns/closers/affirmation-closers.js +13 -3
  9. package/dist/rules/syntactic-patterns/contrast/contrastive-aphorism.js +2 -0
  10. package/dist/rules/syntactic-patterns/contrast/negation-reframe.js +1 -1
  11. package/dist/rules/syntactic-patterns/contrast/private/action-reframe-vocabulary.js +47 -0
  12. package/dist/rules/syntactic-patterns/contrast/private/audience-replacement.js +267 -0
  13. package/dist/rules/syntactic-patterns/contrast/private/copular-reframe.js +79 -0
  14. package/dist/rules/syntactic-patterns/contrast/private/evidence-limitation-pair.js +307 -0
  15. package/dist/rules/syntactic-patterns/contrast/private/inline-semicolon-reframe.js +50 -0
  16. package/dist/rules/syntactic-patterns/contrast/private/inline-short-negation.js +1 -0
  17. package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-matcher.js +78 -73
  18. package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-parts.js +99 -31
  19. package/dist/rules/syntactic-patterns/contrast/private/negation-vocabulary.js +27 -0
  20. package/dist/rules/syntactic-patterns/contrast/private/negative-consequence.js +301 -0
  21. package/dist/rules/syntactic-patterns/contrast/private/negative-slop-frames.js +155 -39
  22. package/dist/rules/syntactic-patterns/contrast/private/policy-object.js +55 -0
  23. package/dist/rules/syntactic-patterns/contrast/private/reframe-classification.js +214 -0
  24. package/dist/rules/syntactic-patterns/contrast/private/sequence-reframes.js +9 -0
  25. package/dist/rules/syntactic-patterns/contrast/private/temporal-reframe.js +318 -0
  26. package/dist/rules/syntactic-patterns/lead-ins/generic-signposting.js +96 -102
  27. package/dist/rules/syntactic-patterns/lead-ins/private/component-assignment-frame.js +239 -0
  28. package/dist/rules/syntactic-patterns/lead-ins/private/discourse-evaluation.js +150 -4
  29. package/dist/rules/syntactic-patterns/lead-ins/private/evaluative-colon-frame.js +166 -0
  30. package/dist/rules/syntactic-patterns/lead-ins/private/reaction-frame.js +29 -0
  31. package/dist/rules/syntactic-patterns/lead-ins/private/relative-discourse-frame.js +119 -0
  32. package/package.json +1 -1
@@ -0,0 +1,301 @@
1
+ import { wordTokens } from "../../../../shared/text/tokens.js";
2
+ const OMISSION_VERBS = new Set(["drop", "leave", "omit", "remove", "skip"]);
3
+ const INFORMATION_ARTIFACTS = new Set([
4
+ "attribute",
5
+ "catalog",
6
+ "content",
7
+ "description",
8
+ "document",
9
+ "evidence",
10
+ "feed",
11
+ "field",
12
+ "listing",
13
+ "metadata",
14
+ "page",
15
+ "profile",
16
+ "record",
17
+ "report"
18
+ ]);
19
+ const CONSEQUENCE_VERBS = new Set([
20
+ "fail",
21
+ "fails",
22
+ "failed",
23
+ "lose",
24
+ "loses",
25
+ "lost",
26
+ "miss",
27
+ "misses",
28
+ "missed"
29
+ ]);
30
+ const NEGATIVE_AUXILIARIES = new Set([
31
+ "aren't",
32
+ "cannot",
33
+ "can't",
34
+ "didn't",
35
+ "doesn't",
36
+ "don't",
37
+ "hadn't",
38
+ "hasn't",
39
+ "haven't",
40
+ "isn't",
41
+ "not",
42
+ "wasn't",
43
+ "weren't",
44
+ "won't",
45
+ "wouldn't"
46
+ ]);
47
+ const ABSTRACT_OUTCOMES = new Set([
48
+ "comparison",
49
+ "consideration",
50
+ "decision",
51
+ "discoverability",
52
+ "distribution",
53
+ "market",
54
+ "ranking",
55
+ "recommendation",
56
+ "results",
57
+ "selection",
58
+ "visibility"
59
+ ]);
60
+ const ENTRY_VERBS = new Set([
61
+ "appear",
62
+ "appears",
63
+ "compare",
64
+ "compares",
65
+ "enter",
66
+ "enters",
67
+ "include",
68
+ "includes",
69
+ "qualify",
70
+ "qualifies",
71
+ "rank",
72
+ "ranks",
73
+ "reach",
74
+ "reaches",
75
+ "recommend",
76
+ "recommends",
77
+ "select",
78
+ "selects"
79
+ ]);
80
+ const INFORMATION_VERBS = new Set([
81
+ "describe",
82
+ "described",
83
+ "describes",
84
+ "explain",
85
+ "explained",
86
+ "explains",
87
+ "include",
88
+ "included",
89
+ "includes",
90
+ "list",
91
+ "listed",
92
+ "lists",
93
+ "mention",
94
+ "mentioned",
95
+ "mentions",
96
+ "say",
97
+ "said",
98
+ "says",
99
+ "show",
100
+ "showed",
101
+ "shown",
102
+ "shows",
103
+ "state",
104
+ "stated",
105
+ "states"
106
+ ]);
107
+ const SELECTION_PREDICATES = new Map([
108
+ ["appeared", "appear"],
109
+ ["compared", "compare"],
110
+ ["considered", "consider"],
111
+ ["included", "include"],
112
+ ["qualified", "qualify"],
113
+ ["ranked", "rank"],
114
+ ["reached", "reach"],
115
+ ["recommended", "recommend"],
116
+ ["rejected", "reject"],
117
+ ["selected", "select"],
118
+ ["shown", "show"]
119
+ ]);
120
+ const CAUSAL_CONNECTORS = new Set([
121
+ "after",
122
+ "because",
123
+ "if",
124
+ "since",
125
+ "therefore",
126
+ "until",
127
+ "when",
128
+ "while"
129
+ ]);
130
+ const TECHNICAL_OR_SAFETY_WORDS = new Set([
131
+ "backup",
132
+ "bytes",
133
+ "checksum",
134
+ "citation",
135
+ "citations",
136
+ "code",
137
+ "database",
138
+ "debug",
139
+ "debugging",
140
+ "disk",
141
+ "error",
142
+ "measurement",
143
+ "measurements",
144
+ "parser",
145
+ "pressure",
146
+ "psi",
147
+ "records",
148
+ "schema",
149
+ "semicolon",
150
+ "stack",
151
+ "tank",
152
+ "trace",
153
+ "valve",
154
+ "voltage"
155
+ ]);
156
+ function words(text) {
157
+ return wordTokens(text).map((token) => token.normalized);
158
+ }
159
+ function hasQuotedText(text) {
160
+ return [...text].some((character) => character === '"' ||
161
+ character === "\u201c" ||
162
+ character === "\u201d" ||
163
+ character === "`");
164
+ }
165
+ function hasDigit(word) {
166
+ return [...word].some((character) => character >= "0" && character <= "9");
167
+ }
168
+ function hasDash(text) {
169
+ for (let index = 0; index < text.length; index += 1) {
170
+ const character = text[index];
171
+ if (character === "\u2013" || character === "\u2014") {
172
+ return true;
173
+ }
174
+ if (character === "-" &&
175
+ (text[index - 1]?.trim() === "" || text[index + 1]?.trim() === "")) {
176
+ return true;
177
+ }
178
+ }
179
+ return false;
180
+ }
181
+ function hasRejectedContext(text, sentenceWords) {
182
+ return (hasQuotedText(text) ||
183
+ sentenceWords.some((word) => CAUSAL_CONNECTORS.has(word) ||
184
+ TECHNICAL_OR_SAFETY_WORDS.has(word) ||
185
+ hasDigit(word)));
186
+ }
187
+ function containsAny(sentenceWords, candidates) {
188
+ return sentenceWords.some((word) => candidates.has(word));
189
+ }
190
+ function omissionConsequence(first, second) {
191
+ const firstWords = words(first);
192
+ const secondWords = words(second);
193
+ const comma = first.indexOf(",");
194
+ const startsWithOmission = OMISSION_VERBS.has(firstWords[0] ?? "") &&
195
+ containsAny(words(first.slice(0, comma < 0 ? first.length : comma)), INFORMATION_ARTIFACTS);
196
+ const namesMissingInformation = firstWords.some((word, index) => word === "no" &&
197
+ firstWords
198
+ .slice(index + 1, index + 4)
199
+ .some((candidate) => INFORMATION_ARTIFACTS.has(candidate)));
200
+ if (firstWords.length > 32 ||
201
+ secondWords.length > 16 ||
202
+ (!startsWithOmission && !namesMissingInformation) ||
203
+ hasRejectedContext(first, firstWords) ||
204
+ hasRejectedContext(second, secondWords)) {
205
+ return false;
206
+ }
207
+ const consequenceStart = firstWords.findIndex((word, index) => index > 0 && CONSEQUENCE_VERBS.has(word));
208
+ const hasNegativeConsequence = consequenceStart > 0 &&
209
+ firstWords
210
+ .slice(Math.max(0, consequenceStart - 3), consequenceStart)
211
+ .some((word) => NEGATIVE_AUXILIARIES.has(word));
212
+ const neverIndex = secondWords.indexOf("never");
213
+ const entryVerb = neverIndex < 0
214
+ ? undefined
215
+ : secondWords.slice(neverIndex + 1).find((word) => ENTRY_VERBS.has(word));
216
+ const combined = [...firstWords, ...secondWords];
217
+ return (hasNegativeConsequence &&
218
+ neverIndex > 0 &&
219
+ entryVerb !== undefined &&
220
+ containsAny(combined, ABSTRACT_OUTCOMES));
221
+ }
222
+ function selectionOccurrences(sentenceWords) {
223
+ const occurrences = [];
224
+ sentenceWords.forEach((word, index) => {
225
+ const canonical = SELECTION_PREDICATES.get(word);
226
+ if (canonical !== undefined) {
227
+ occurrences.push({ canonical, index });
228
+ }
229
+ });
230
+ return occurrences;
231
+ }
232
+ function hasNegativeMarkerBefore(sentenceWords, index, marker) {
233
+ const previous = sentenceWords[index - 1];
234
+ if (previous === marker) {
235
+ return true;
236
+ }
237
+ const clauseStart = sentenceWords.lastIndexOf(marker, index - 1);
238
+ return clauseStart >= 0 && index - clauseStart <= 3;
239
+ }
240
+ function inlineSelectionClaim(text, allowStackedNever) {
241
+ const sentenceWords = words(text);
242
+ if (sentenceWords.length > 14 || hasRejectedContext(text, sentenceWords)) {
243
+ return false;
244
+ }
245
+ const occurrences = selectionOccurrences(sentenceWords);
246
+ if (occurrences.length < 2) {
247
+ return false;
248
+ }
249
+ const repeatedAcrossNegation = occurrences.some((firstOccurrence, index) => occurrences
250
+ .slice(index + 1)
251
+ .some((secondOccurrence) => firstOccurrence.canonical === secondOccurrence.canonical &&
252
+ hasNegativeMarkerBefore(sentenceWords, firstOccurrence.index, "not") &&
253
+ hasNegativeMarkerBefore(sentenceWords, secondOccurrence.index, "never")));
254
+ const stackedNeverPredicates = occurrences.filter((occurrence) => hasNegativeMarkerBefore(sentenceWords, occurrence.index, "never")).length >= 2;
255
+ return ((hasDash(text) && repeatedAcrossNegation) ||
256
+ (allowStackedNever && stackedNeverPredicates));
257
+ }
258
+ function artifactInformationClaim(text) {
259
+ const sentenceWords = words(text);
260
+ if (sentenceWords.length > 18 || hasRejectedContext(text, sentenceWords)) {
261
+ return false;
262
+ }
263
+ const neverIndex = sentenceWords.indexOf("never");
264
+ if (neverIndex < 1 || neverIndex > 5) {
265
+ return false;
266
+ }
267
+ const subject = sentenceWords.slice(0, neverIndex);
268
+ return (containsAny(subject, INFORMATION_ARTIFACTS) &&
269
+ INFORMATION_VERBS.has(sentenceWords[neverIndex + 1] ?? "") &&
270
+ sentenceWords.length > neverIndex + 2);
271
+ }
272
+ function shortOutcomeFragment(text) {
273
+ const sentenceWords = words(text);
274
+ return (sentenceWords.length > 0 &&
275
+ sentenceWords.length <= 3 &&
276
+ !hasRejectedContext(text, sentenceWords) &&
277
+ !sentenceWords.includes("never"));
278
+ }
279
+ function artifactSelectionSequence(first, second, third) {
280
+ if (!artifactInformationClaim(first)) {
281
+ return undefined;
282
+ }
283
+ if (inlineSelectionClaim(second, true)) {
284
+ return `${first} ${second}`;
285
+ }
286
+ return third !== undefined &&
287
+ shortOutcomeFragment(second) &&
288
+ inlineSelectionClaim(third, true)
289
+ ? `${first} ${second} ${third}`
290
+ : undefined;
291
+ }
292
+ export function matchNegativeConsequence(first, second, third) {
293
+ if (second.length === 0) {
294
+ return inlineSelectionClaim(first, false) ? first : undefined;
295
+ }
296
+ if (omissionConsequence(first, second)) {
297
+ return `${first} ${second}`;
298
+ }
299
+ return artifactSelectionSequence(first, second, third);
300
+ }
301
+ //# sourceMappingURL=negative-consequence.js.map
@@ -1,31 +1,56 @@
1
- import { DO_NEGATIONS, EXPLICIT_DO_AUXILIARIES, FACTUAL_NEGATION_CONNECTORS, PRONOUN_REFRAME_STARTS, hasAnyWord, skipOptionalAdverbs, startsWithAny, startsWithSubjectOrPronoun, startsWithWords, stripLeadingPairPivot, validSubject, words } from "./negation-reframe-parts.js";
2
- const GENERIC_ACTION_VERBS = new Set([
3
- "asked",
4
- "built",
5
- "called",
6
- "crossed",
7
- "found",
8
- "gave",
9
- "left",
10
- "looked",
11
- "made",
12
- "moved",
13
- "opened",
14
- "pointed",
15
- "raised",
16
- "reached",
17
- "pulled",
18
- "kept",
1
+ import { hasFactualConnectorAfterNegation } from "./negation-context-gates.js";
2
+ import { hasAbstractPolicyDirectObject } from "./policy-object.js";
3
+ import { negatedProgressiveNeverPayoff } from "./copular-reframe.js";
4
+ import { GENERIC_ACTION_VERBS } from "./action-reframe-vocabulary.js";
5
+ export { shouldReportCopularReframe } from "./reframe-classification.js";
6
+ export { progressiveVerbMirror, pronounCopularReframe, sameSubjectCopularReframe, startsWithNegatedPronounCopula } from "./copular-reframe.js";
7
+ export { matchSequenceReframe } from "./sequence-reframes.js";
8
+ import { ACTION_NEGATIONS, EXPLICIT_DO_AUXILIARIES, FACTUAL_NEGATION_CONNECTORS, PRONOUN_REFRAME_STARTS, findCopularNegation, pronounCopulaStart, skipOptionalAdverbs, startsWithAny, startsWithSubjectOrPronoun, startsWithWords, stripLeadingPairPivot, validSubject, words } from "./negation-reframe-parts.js";
9
+ const NEGATED_ACTION_REFRAME_VERBS = new Set([
10
+ "avoid",
11
+ "change",
12
+ "create",
13
+ "end",
14
+ "erase",
15
+ "fix",
16
+ "guarantee",
17
+ "make",
18
+ "mean",
19
+ "remove",
20
+ "replace",
21
+ "require",
22
+ "skip",
23
+ "solve"
24
+ ]);
25
+ const REPLACEMENT_SUBJECT_PRONOUNS = new Set(["he", "she"]);
26
+ const EMBEDDED_CLAUSE_VERBS = new Set([
27
+ "believed",
28
+ "explained",
29
+ "reckoned",
30
+ "reported",
19
31
  "said",
20
- "sat",
21
- "shifted",
22
- "stood",
23
- "started",
24
- "stopped",
25
- "took",
26
- "turned",
27
- "walked",
28
- "went"
32
+ "thought"
33
+ ]);
34
+ const PRONOUN_PAYOFF_VERBS = new Set([
35
+ "becomes",
36
+ "creates",
37
+ "depends",
38
+ "exposes",
39
+ "lands",
40
+ "means",
41
+ "moves",
42
+ "needs",
43
+ "points",
44
+ "requires",
45
+ "reveals",
46
+ "shifts",
47
+ "shows",
48
+ "turns"
49
+ ]);
50
+ const PRONOUN_SUBJECTS = new Set(["it", "this", "that", "they", "we", "you"]);
51
+ const ACTION_REPLACEMENT_CONNECTORS = new Set([
52
+ ...FACTUAL_NEGATION_CONNECTORS,
53
+ "after"
29
54
  ]);
30
55
  function startsWithPassiveCopula(tokens) {
31
56
  const tokenWords = words(tokens);
@@ -36,6 +61,13 @@ function startsWithPassiveCopula(tokens) {
36
61
  }
37
62
  function noLongerCopularReframe(aTokens, bTokens) {
38
63
  const tokenWords = words(aTokens);
64
+ const contractedStart = pronounCopulaStart(aTokens);
65
+ if (contractedStart !== undefined &&
66
+ tokenWords[contractedStart.predicateStart] === "no" &&
67
+ tokenWords[contractedStart.predicateStart + 1] === "longer") {
68
+ return (startsWithSubjectOrPronoun(bTokens, contractedStart.subject) &&
69
+ !startsWithPassiveCopula(bTokens));
70
+ }
39
71
  for (let index = 0; index < tokenWords.length - 2; index += 1) {
40
72
  const current = tokenWords[index];
41
73
  const subject = tokenWords.slice(0, index);
@@ -65,23 +97,48 @@ function fragmentDefinitionReframe(aTokens, bTokens) {
65
97
  }
66
98
  function negatedActionSubject(tokens) {
67
99
  const tokenWords = words(tokens);
100
+ const copularNegation = findCopularNegation(tokens);
101
+ if (copularNegation !== undefined &&
102
+ validSubject(copularNegation.subject) &&
103
+ tokenWords[copularNegation.negatedPredicateStart]?.endsWith("ing") === true) {
104
+ return copularNegation.subject;
105
+ }
68
106
  for (let index = 0; index < tokenWords.length; index += 1) {
69
107
  const current = tokenWords[index];
70
108
  const next = tokenWords[index + 1];
71
109
  const subject = tokenWords.slice(0, index);
72
- if (!validSubject(subject)) {
110
+ if (!validSubject(subject) ||
111
+ subject.some((word) => EMBEDDED_CLAUSE_VERBS.has(word))) {
73
112
  continue;
74
113
  }
75
- if (DO_NEGATIONS.has(current ?? "")) {
76
- return subject;
114
+ if (ACTION_NEGATIONS.has(current ?? "")) {
115
+ return tokenWords[index + 1] !== undefined &&
116
+ !tokenWords.slice(index + 1).includes("and")
117
+ ? subject
118
+ : undefined;
77
119
  }
78
120
  if (EXPLICIT_DO_AUXILIARIES.has(current ?? "") && next === "not") {
79
- return subject;
121
+ return tokenWords[index + 2] !== undefined &&
122
+ !tokenWords.slice(index + 2).includes("and")
123
+ ? subject
124
+ : undefined;
80
125
  }
81
126
  }
82
127
  return undefined;
83
128
  }
84
- function negativeActionReplacement(aTokens, bTokens) {
129
+ function constrainedSetSubjectLength(tokens, subject) {
130
+ if (startsWithWords(tokens, subject)) {
131
+ return subject.length;
132
+ }
133
+ if (startsWithSubjectOrPronoun(tokens, subject)) {
134
+ return 1;
135
+ }
136
+ return subject.length > 1 &&
137
+ REPLACEMENT_SUBJECT_PRONOUNS.has(tokens[0]?.normalized ?? "")
138
+ ? 1
139
+ : undefined;
140
+ }
141
+ export function negatedActionReplacement(aTokens, bTokens) {
85
142
  const tokenWords = words(aTokens);
86
143
  const subject = negatedActionSubject(aTokens);
87
144
  if (subject === undefined) {
@@ -89,13 +146,34 @@ function negativeActionReplacement(aTokens, bTokens) {
89
146
  }
90
147
  const bContentTokens = stripLeadingPairPivot(bTokens);
91
148
  const bWords = words(bContentTokens);
92
- const verbIndex = skipOptionalAdverbs(bWords, subject.length);
93
- const verb = bWords[verbIndex];
149
+ const subjectLength = constrainedSetSubjectLength(bContentTokens, subject);
150
+ const genericVerbIndex = subjectLength === undefined
151
+ ? undefined
152
+ : skipOptionalAdverbs(bWords, subjectLength);
94
153
  return (tokenWords.length <= 14 &&
95
- !hasAnyWord(tokenWords, FACTUAL_NEGATION_CONNECTORS) &&
96
- startsWithSubjectOrPronoun(bContentTokens, subject) &&
97
- verb !== undefined &&
98
- GENERIC_ACTION_VERBS.has(verb));
154
+ !tokenWords.some((word) => FACTUAL_NEGATION_CONNECTORS.has(word)) &&
155
+ !bWords.some((word) => ACTION_REPLACEMENT_CONNECTORS.has(word)) &&
156
+ ((genericVerbIndex !== undefined &&
157
+ GENERIC_ACTION_VERBS.has(bWords[genericVerbIndex] ?? "")) ||
158
+ negatedActionSetReplacement(aTokens, bTokens)));
159
+ }
160
+ export function negatedActionSetReplacement(aTokens, bTokens) {
161
+ const tokenWords = words(aTokens);
162
+ const subject = negatedActionSubject(aTokens);
163
+ if (subject === undefined) {
164
+ return false;
165
+ }
166
+ const bContentTokens = stripLeadingPairPivot(bTokens);
167
+ const bWords = words(bContentTokens);
168
+ const subjectLength = constrainedSetSubjectLength(bContentTokens, subject);
169
+ const verbIndex = subjectLength === undefined
170
+ ? undefined
171
+ : skipOptionalAdverbs(bWords, subjectLength);
172
+ return (tokenWords.length <= 14 &&
173
+ !tokenWords.some((word) => FACTUAL_NEGATION_CONNECTORS.has(word)) &&
174
+ !bWords.some((word) => ACTION_REPLACEMENT_CONNECTORS.has(word)) &&
175
+ verbIndex !== undefined &&
176
+ hasAbstractPolicyDirectObject(bWords, verbIndex));
99
177
  }
100
178
  function notBecauseReframe(aTokens, bTokens) {
101
179
  return (startsWithWords(aTokens, ["not", "because"]) &&
@@ -130,10 +208,48 @@ export function hasNegativeSlopPairSignal(tokens) {
130
208
  hasTrailingProblemFrame(tokenWords) ||
131
209
  hasLeadingProblemFrame(tokenWords));
132
210
  }
211
+ export function negatedActionPronounPayoff(aTokens, bTokens) {
212
+ const aWords = words(aTokens);
213
+ const bWords = words(stripLeadingPairPivot(bTokens));
214
+ const pronounStart = PRONOUN_SUBJECTS.has(bWords[0] ?? "") ? 1 : undefined;
215
+ if (pronounStart === undefined) {
216
+ return false;
217
+ }
218
+ const payoffVerbIndex = skipOptionalAdverbs(bWords, pronounStart);
219
+ if (!PRONOUN_PAYOFF_VERBS.has(bWords[payoffVerbIndex] ?? "")) {
220
+ return false;
221
+ }
222
+ for (let index = 0; index < aWords.length; index += 1) {
223
+ if (hasNegatedReframeVerb(aTokens, aWords, index)) {
224
+ return true;
225
+ }
226
+ }
227
+ return false;
228
+ }
229
+ function hasNegatedReframeVerb(tokens, tokenWords, index) {
230
+ const current = tokenWords[index];
231
+ const next = tokenWords[index + 1];
232
+ const subject = tokenWords.slice(0, index);
233
+ if (!validSubject(subject)) {
234
+ return false;
235
+ }
236
+ const negationIndex = ACTION_NEGATIONS.has(current ?? "")
237
+ ? index
238
+ : EXPLICIT_DO_AUXILIARIES.has(current ?? "") && next === "not"
239
+ ? index + 1
240
+ : undefined;
241
+ if (negationIndex === undefined ||
242
+ hasFactualConnectorAfterNegation(tokens, negationIndex)) {
243
+ return false;
244
+ }
245
+ const verbIndex = skipOptionalAdverbs(tokenWords, negationIndex + 1);
246
+ return NEGATED_ACTION_REFRAME_VERBS.has(tokenWords[verbIndex] ?? "");
247
+ }
133
248
  export function negativeSlopReframe(aTokens, bTokens) {
134
249
  return (noLongerCopularReframe(aTokens, bTokens) ||
250
+ negatedProgressiveNeverPayoff(aTokens, bTokens) ||
135
251
  fragmentDefinitionReframe(aTokens, bTokens) ||
136
- negativeActionReplacement(aTokens, bTokens) ||
252
+ negatedActionReplacement(aTokens, bTokens) ||
137
253
  notBecauseReframe(aTokens, bTokens) ||
138
254
  notProblemReframe(aTokens, bTokens));
139
255
  }
@@ -0,0 +1,55 @@
1
+ const ABSTRACT_POLICY_OBJECTS = new Set([
2
+ "condition",
3
+ "criterion",
4
+ "policy",
5
+ "principle",
6
+ "requirement",
7
+ "rule",
8
+ "standard",
9
+ "threshold"
10
+ ]);
11
+ const DIRECT_OBJECT_DETERMINERS = new Set([
12
+ "a",
13
+ "an",
14
+ "one",
15
+ "that",
16
+ "the",
17
+ "this"
18
+ ]);
19
+ const POLICY_OBJECT_MODIFIERS = new Set([
20
+ "access",
21
+ "approval",
22
+ "business",
23
+ "content",
24
+ "deployment",
25
+ "editorial",
26
+ "governance",
27
+ "launch",
28
+ "operating",
29
+ "pricing",
30
+ "quality",
31
+ "release",
32
+ "review",
33
+ "safety",
34
+ "security",
35
+ "service",
36
+ "spending",
37
+ "technical",
38
+ "testing",
39
+ "usage"
40
+ ]);
41
+ export function hasAbstractPolicyDirectObject(tokenWords, verbIndex) {
42
+ if (!["set", "sets"].includes(tokenWords[verbIndex] ?? "")) {
43
+ return false;
44
+ }
45
+ const objectTokens = tokenWords.slice(verbIndex + 1);
46
+ const directObject = DIRECT_OBJECT_DETERMINERS.has(objectTokens[0] ?? "")
47
+ ? objectTokens.slice(1)
48
+ : objectTokens;
49
+ const [first, second] = directObject;
50
+ return ((directObject.length === 1 && ABSTRACT_POLICY_OBJECTS.has(first ?? "")) ||
51
+ (directObject.length === 2 &&
52
+ POLICY_OBJECT_MODIFIERS.has(first ?? "") &&
53
+ ABSTRACT_POLICY_OBJECTS.has(second ?? "")));
54
+ }
55
+ //# sourceMappingURL=policy-object.js.map