slopless 0.2.24 → 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.
- package/dist/rules/semantic-thinness/patterns/abstract-metaphor-claim.json +83 -1
- package/dist/rules/semantic-thinness/patterns/deictic-summary.json +31 -2
- package/dist/rules/semantic-thinness/patterns/empty-scene-transition.json +2 -1
- package/dist/rules/semantic-thinness/private/concrete-guards.js +2 -0
- package/dist/rules/semantic-thinness/private/pattern-matcher.js +22 -6
- package/dist/rules/syntactic-patterns/contrast/contrastive-aphorism.js +2 -0
- package/dist/rules/syntactic-patterns/contrast/negation-reframe.js +1 -1
- package/dist/rules/syntactic-patterns/contrast/private/action-reframe-vocabulary.js +47 -0
- package/dist/rules/syntactic-patterns/contrast/private/audience-replacement.js +267 -0
- package/dist/rules/syntactic-patterns/contrast/private/copular-reframe.js +39 -1
- package/dist/rules/syntactic-patterns/contrast/private/evidence-limitation-pair.js +307 -0
- package/dist/rules/syntactic-patterns/contrast/private/inline-semicolon-reframe.js +50 -0
- package/dist/rules/syntactic-patterns/contrast/private/inline-short-negation.js +1 -0
- package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-matcher.js +64 -7
- package/dist/rules/syntactic-patterns/contrast/private/negation-reframe-parts.js +37 -25
- package/dist/rules/syntactic-patterns/contrast/private/negation-vocabulary.js +27 -0
- package/dist/rules/syntactic-patterns/contrast/private/negative-consequence.js +301 -0
- package/dist/rules/syntactic-patterns/contrast/private/negative-slop-frames.js +51 -38
- package/dist/rules/syntactic-patterns/contrast/private/reframe-classification.js +21 -0
- package/dist/rules/syntactic-patterns/contrast/private/sequence-reframes.js +9 -0
- package/dist/rules/syntactic-patterns/contrast/private/temporal-reframe.js +318 -0
- package/dist/rules/syntactic-patterns/lead-ins/generic-signposting.js +85 -22
- package/dist/rules/syntactic-patterns/lead-ins/private/component-assignment-frame.js +239 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/discourse-evaluation.js +1 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/evaluative-colon-frame.js +166 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/reaction-frame.js +29 -0
- package/dist/rules/syntactic-patterns/lead-ins/private/relative-discourse-frame.js +119 -0
- package/package.json +1 -1
|
@@ -17,7 +17,39 @@
|
|
|
17
17
|
"{abstractSubject} {linkingVerb} {infrastructureNoun} with {abstractObject}.",
|
|
18
18
|
"{abstractSubject} behaves like a {filterNoun}.",
|
|
19
19
|
"{artifactSubject} adds another {layerNoun} to {diagnosisObject}.",
|
|
20
|
-
"{artifactSubject} add another {layerNoun} to {diagnosisObject}."
|
|
20
|
+
"{artifactSubject} add another {layerNoun} to {diagnosisObject}.",
|
|
21
|
+
{
|
|
22
|
+
"text": "{identityArtifact} {linkingVerb} the {artifactRole}.",
|
|
23
|
+
"matchMode": "full"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"text": "the {identityArtifact} {linkingVerb} the {artifactRole}.",
|
|
27
|
+
"matchMode": "full"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"text": "{identityArtifact} {linkingVerb} the {artifactRole} now.",
|
|
31
|
+
"matchMode": "full"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"text": "the {identityArtifact} {linkingVerb} the {artifactRole} now.",
|
|
35
|
+
"matchMode": "full"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"text": "{audiencePreposition} the {automatedAudience}, the {identityArtifact} {linkingVerb} the {artifactRole}.",
|
|
39
|
+
"matchMode": "full"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"text": "{audiencePreposition} the {automatedAudience}, {identityArtifact} {linkingVerb} the {artifactRole}.",
|
|
43
|
+
"matchMode": "full"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"text": "{audiencePreposition} the {automatedAudience} {audienceActivity}, the {identityArtifact} {linkingVerb} the {artifactRole}.",
|
|
47
|
+
"matchMode": "full"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"text": "{audiencePreposition} the {automatedAudience} {audienceActivity}, {identityArtifact} {linkingVerb} the {artifactRole}.",
|
|
51
|
+
"matchMode": "full"
|
|
52
|
+
}
|
|
21
53
|
],
|
|
22
54
|
"slots": {
|
|
23
55
|
"abstractSubject": [
|
|
@@ -87,6 +119,56 @@
|
|
|
87
119
|
"the report",
|
|
88
120
|
"visibility"
|
|
89
121
|
],
|
|
122
|
+
"identityArtifact": [
|
|
123
|
+
"feed",
|
|
124
|
+
"page",
|
|
125
|
+
"prompt",
|
|
126
|
+
"dashboard",
|
|
127
|
+
"database",
|
|
128
|
+
"index",
|
|
129
|
+
"schema",
|
|
130
|
+
"metadata",
|
|
131
|
+
"report",
|
|
132
|
+
"spreadsheet",
|
|
133
|
+
"interface",
|
|
134
|
+
"pipeline",
|
|
135
|
+
"model",
|
|
136
|
+
"content"
|
|
137
|
+
],
|
|
138
|
+
"artifactRole": [
|
|
139
|
+
"product",
|
|
140
|
+
"strategy",
|
|
141
|
+
"decision",
|
|
142
|
+
"answer",
|
|
143
|
+
"business",
|
|
144
|
+
"brand",
|
|
145
|
+
"storefront",
|
|
146
|
+
"market",
|
|
147
|
+
"distribution",
|
|
148
|
+
"experience",
|
|
149
|
+
"work",
|
|
150
|
+
"source of truth"
|
|
151
|
+
],
|
|
152
|
+
"audiencePreposition": ["for", "to"],
|
|
153
|
+
"automatedAudience": [
|
|
154
|
+
"agent",
|
|
155
|
+
"ai assistant",
|
|
156
|
+
"algorithm",
|
|
157
|
+
"assistant",
|
|
158
|
+
"crawler",
|
|
159
|
+
"machine",
|
|
160
|
+
"model",
|
|
161
|
+
"ranking system",
|
|
162
|
+
"recommendation engine",
|
|
163
|
+
"search agent"
|
|
164
|
+
],
|
|
165
|
+
"audienceActivity": [
|
|
166
|
+
"choosing the product",
|
|
167
|
+
"doing the shopping",
|
|
168
|
+
"making the decision",
|
|
169
|
+
"ranking the results",
|
|
170
|
+
"reading the page"
|
|
171
|
+
],
|
|
90
172
|
"abstractObject": [
|
|
91
173
|
"consequences",
|
|
92
174
|
"diagnosis",
|
|
@@ -5,8 +5,26 @@
|
|
|
5
5
|
"matchMode": "contains",
|
|
6
6
|
"maxTokens": 80,
|
|
7
7
|
"templates": [
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
{
|
|
9
|
+
"text": "{deicticCopula} the {summaryNoun}.",
|
|
10
|
+
"matchMode": "full"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"text": "{deicticCopula} the {evaluativeAdjective} {summaryNoun}.",
|
|
14
|
+
"matchMode": "full"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"text": "{deicticSubject} {linkingVerb} the {summaryNoun}.",
|
|
18
|
+
"matchMode": "full"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"text": "{deicticSubject} {linkingVerb} the {summaryNoun}.",
|
|
22
|
+
"matchMode": "connector"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"text": "{deicticSubject} {linkingVerb} the {evaluativeAdjective} {summaryNoun}.",
|
|
26
|
+
"matchMode": "full"
|
|
27
|
+
},
|
|
10
28
|
"{deicticSubject} {linkingVerb} the {summaryNoun} that {thinPredicate}.",
|
|
11
29
|
"{deicticSubject} {linkingVerb} the {summaryNoun} {genericAudience} {reactionVerb}.",
|
|
12
30
|
"{deicticSubject} {summaryVerb} the {summaryNoun}.",
|
|
@@ -14,6 +32,7 @@
|
|
|
14
32
|
"{deicticSubject} {meaningVerb} {summaryNoun}.",
|
|
15
33
|
"{deicticSubject} {explanationVerb} {summaryNoun}.",
|
|
16
34
|
"{deicticSubject} {explanationVerb} the {summaryNoun}.",
|
|
35
|
+
"{deicticSubject} {speechVerb} {deicticSubject} {linkingVerb} the {summaryNoun}.",
|
|
17
36
|
"{deicticSubject} {meaningVerb} {abstractSubject} {linkingVerb} {weakJudgment}.",
|
|
18
37
|
"{deicticSubject} {explanationVerb} why {abstractSubject} {abstractVerb}.",
|
|
19
38
|
"{deicticSubject} {explanationVerb} how {abstractSubject} {abstractVerb}.",
|
|
@@ -30,6 +49,14 @@
|
|
|
30
49
|
"{deicticSubject} {linkingVerb} the reason {abstractSubject} {importanceVerb}."
|
|
31
50
|
],
|
|
32
51
|
"slots": {
|
|
52
|
+
"deicticCopula": [
|
|
53
|
+
"that is",
|
|
54
|
+
"this is",
|
|
55
|
+
"it is",
|
|
56
|
+
"that's",
|
|
57
|
+
"this's",
|
|
58
|
+
"it's"
|
|
59
|
+
],
|
|
33
60
|
"deicticSubject": ["that", "this", "it"],
|
|
34
61
|
"linkingVerb": ["is", "was"],
|
|
35
62
|
"evaluativeAdjective": [
|
|
@@ -51,6 +78,7 @@
|
|
|
51
78
|
],
|
|
52
79
|
"summaryNoun": [
|
|
53
80
|
"part",
|
|
81
|
+
"piece",
|
|
54
82
|
"promise",
|
|
55
83
|
"truth",
|
|
56
84
|
"lesson",
|
|
@@ -99,6 +127,7 @@
|
|
|
99
127
|
],
|
|
100
128
|
"meaningVerb": ["means", "meant", "does not mean", "doesn't mean"],
|
|
101
129
|
"explanationVerb": ["shows", "showed", "explains", "explained", "proves"],
|
|
130
|
+
"speechVerb": ["says", "said", "tells", "told"],
|
|
102
131
|
"weakJudgment": [
|
|
103
132
|
"useless",
|
|
104
133
|
"useful",
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
"id": "empty-scene-transition",
|
|
3
3
|
"class": "transition-change",
|
|
4
4
|
"purpose": "Catch generic transition lines that declare change, passage, or motion without naming what changed or why.",
|
|
5
|
-
"matchMode": "
|
|
5
|
+
"matchMode": "full",
|
|
6
6
|
"templates": [
|
|
7
7
|
"{genericSubject} {changeVerb}.",
|
|
8
8
|
"{genericSubject} {changeVerb} {weakModifier}.",
|
|
9
9
|
"{genericSubject} {changeVerb} {genericObject}.",
|
|
10
|
+
"{weakModifier}, {genericSubject} {changeVerb}.",
|
|
10
11
|
"{genericSubject} {passageVerb}."
|
|
11
12
|
],
|
|
12
13
|
"slots": {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const CONCRETE_EXPLANATION_TOKENS = new Set([
|
|
2
2
|
"api",
|
|
3
3
|
"archive",
|
|
4
|
+
"assigned",
|
|
4
5
|
"auditor",
|
|
5
6
|
"billing",
|
|
6
7
|
"bids",
|
|
@@ -20,6 +21,7 @@ const CONCRETE_EXPLANATION_TOKENS = new Set([
|
|
|
20
21
|
"invoice",
|
|
21
22
|
"key",
|
|
22
23
|
"ledger",
|
|
24
|
+
"lists",
|
|
23
25
|
"masonry",
|
|
24
26
|
"mark",
|
|
25
27
|
"meter",
|
|
@@ -16,6 +16,7 @@ const REJECT_TOKENS = new Set([
|
|
|
16
16
|
]);
|
|
17
17
|
const BROAD_PATTERN_IDS = new Set([
|
|
18
18
|
"abstract-agency-personification",
|
|
19
|
+
"abstract-metaphor-claim",
|
|
19
20
|
"abstract-personification-line",
|
|
20
21
|
"body-emotion-shorthand",
|
|
21
22
|
"deictic-summary",
|
|
@@ -59,15 +60,16 @@ function readSlotName(template, start) {
|
|
|
59
60
|
return [name, index];
|
|
60
61
|
}
|
|
61
62
|
function compileTemplate(template) {
|
|
63
|
+
const text = typeof template === "string" ? template : template.text;
|
|
62
64
|
const parts = [];
|
|
63
65
|
let literal = "";
|
|
64
66
|
let index = 0;
|
|
65
|
-
while (index <
|
|
66
|
-
const character =
|
|
67
|
+
while (index < text.length) {
|
|
68
|
+
const character = text[index];
|
|
67
69
|
if (character === "{") {
|
|
68
70
|
flushLiteral(parts, literal);
|
|
69
71
|
literal = "";
|
|
70
|
-
const [name, nextIndex] = readSlotName(
|
|
72
|
+
const [name, nextIndex] = readSlotName(text, index);
|
|
71
73
|
parts.push({ kind: "slot", name });
|
|
72
74
|
index = nextIndex;
|
|
73
75
|
continue;
|
|
@@ -76,7 +78,16 @@ function compileTemplate(template) {
|
|
|
76
78
|
index += 1;
|
|
77
79
|
}
|
|
78
80
|
flushLiteral(parts, literal);
|
|
79
|
-
|
|
81
|
+
const matchMode = typeof template !== "string" &&
|
|
82
|
+
(template.matchMode === "contains" ||
|
|
83
|
+
template.matchMode === "connector" ||
|
|
84
|
+
template.matchMode === "full" ||
|
|
85
|
+
template.matchMode === "suffix")
|
|
86
|
+
? template.matchMode
|
|
87
|
+
: undefined;
|
|
88
|
+
return matchMode === undefined
|
|
89
|
+
? { parts, signal: text }
|
|
90
|
+
: { matchMode, parts, signal: text };
|
|
80
91
|
}
|
|
81
92
|
function compileSlotValues(slots) {
|
|
82
93
|
const compiled = {};
|
|
@@ -138,6 +149,7 @@ function matchPart(source, pattern, part, tokenIndex) {
|
|
|
138
149
|
.map((tokens) => tokenIndex + tokens.length);
|
|
139
150
|
}
|
|
140
151
|
function templateMatches(source, pattern, template, start) {
|
|
152
|
+
const matchMode = template.matchMode ?? pattern.matchMode;
|
|
141
153
|
let positions = [start];
|
|
142
154
|
for (const part of template.parts) {
|
|
143
155
|
positions = positions.flatMap((position) => matchPart(source, pattern, part, position));
|
|
@@ -145,13 +157,17 @@ function templateMatches(source, pattern, template, start) {
|
|
|
145
157
|
return false;
|
|
146
158
|
}
|
|
147
159
|
}
|
|
148
|
-
if (
|
|
160
|
+
if (matchMode === "contains") {
|
|
149
161
|
return positions.length > 0;
|
|
150
162
|
}
|
|
163
|
+
if (matchMode === "connector") {
|
|
164
|
+
return positions.some((position) => ["and", "but", "so", "yet"].includes(source[position]?.normalized ?? ""));
|
|
165
|
+
}
|
|
151
166
|
return positions.includes(source.length);
|
|
152
167
|
}
|
|
153
168
|
function templateMatchesPattern(source, pattern, template) {
|
|
154
|
-
|
|
169
|
+
const matchMode = template.matchMode ?? pattern.matchMode;
|
|
170
|
+
if (matchMode === "full" || matchMode === "connector") {
|
|
155
171
|
return templateMatches(source, pattern, template, 0);
|
|
156
172
|
}
|
|
157
173
|
for (let start = 0; start < source.length; start += 1) {
|
|
@@ -2,6 +2,7 @@ import { defineTextlintRule } from "../../../adapters/textlint/rule.js";
|
|
|
2
2
|
import { sentenceUnits } from "../../../adapters/textlint/units.js";
|
|
3
3
|
import { cleanSentence, startsWithWords, tokens, trimTerminalPunctuation } from "../../../shared/matchers/prose-patterns.js";
|
|
4
4
|
import { pairHasAbstractSubjectOrObject } from "./private/abstract-pair-gates.js";
|
|
5
|
+
import { matchEvidenceLimitationPair } from "./private/evidence-limitation-pair.js";
|
|
5
6
|
import { matchSameSentenceContrast } from "./private/same-sentence-contrast.js";
|
|
6
7
|
import { matchSingleSentenceAphorism } from "./private/single-sentence-aphorism.js";
|
|
7
8
|
const PREFIXES = ["and ", "but ", "so ", "because "];
|
|
@@ -104,6 +105,7 @@ const rule = defineTextlintRule({
|
|
|
104
105
|
matchLessMorePair(current.text, next.text) ??
|
|
105
106
|
matchGivesYouPair(current.text, next.text) ??
|
|
106
107
|
matchGetsOneAnotherPair(current.text, next.text) ??
|
|
108
|
+
matchEvidenceLimitationPair(current.text, next.text) ??
|
|
107
109
|
matchEvaluativeContrastPair(current.text, next.text);
|
|
108
110
|
if (signal !== undefined) {
|
|
109
111
|
detections.push({
|
|
@@ -21,7 +21,7 @@ const rule = defineTextlintRule({
|
|
|
21
21
|
family: "syntactic-patterns",
|
|
22
22
|
id: RULE_ID
|
|
23
23
|
},
|
|
24
|
-
formatMessage: (report) => `Negation reframe found: "${report.evidence}". Rewrite
|
|
24
|
+
formatMessage: (report) => `Negation reframe found: "${report.evidence}". Rewrite the staged negation as a direct claim.`,
|
|
25
25
|
reportPolicy: { kind: "one-to-one" },
|
|
26
26
|
units: (document) => [
|
|
27
27
|
...allParagraphUnits(document),
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const GENERIC_ACTION_VERBS = new Set([
|
|
2
|
+
"asked",
|
|
3
|
+
"built",
|
|
4
|
+
"called",
|
|
5
|
+
"checked",
|
|
6
|
+
"checks",
|
|
7
|
+
"compare",
|
|
8
|
+
"compared",
|
|
9
|
+
"compares",
|
|
10
|
+
"crossed",
|
|
11
|
+
"decided",
|
|
12
|
+
"decides",
|
|
13
|
+
"followed",
|
|
14
|
+
"follows",
|
|
15
|
+
"found",
|
|
16
|
+
"gave",
|
|
17
|
+
"kept",
|
|
18
|
+
"left",
|
|
19
|
+
"looked",
|
|
20
|
+
"made",
|
|
21
|
+
"moved",
|
|
22
|
+
"opened",
|
|
23
|
+
"pointed",
|
|
24
|
+
"pulled",
|
|
25
|
+
"raised",
|
|
26
|
+
"rank",
|
|
27
|
+
"ranked",
|
|
28
|
+
"ranks",
|
|
29
|
+
"read",
|
|
30
|
+
"reads",
|
|
31
|
+
"reached",
|
|
32
|
+
"reasoned",
|
|
33
|
+
"reasons",
|
|
34
|
+
"returned",
|
|
35
|
+
"returns",
|
|
36
|
+
"said",
|
|
37
|
+
"sat",
|
|
38
|
+
"shifted",
|
|
39
|
+
"started",
|
|
40
|
+
"stood",
|
|
41
|
+
"stopped",
|
|
42
|
+
"took",
|
|
43
|
+
"turned",
|
|
44
|
+
"walked",
|
|
45
|
+
"went"
|
|
46
|
+
]);
|
|
47
|
+
//# sourceMappingURL=action-reframe-vocabulary.js.map
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { wordTokens } from "../../../../shared/text/tokens.js";
|
|
2
|
+
const HUMAN_AUDIENCES = new Set([
|
|
3
|
+
"buyers",
|
|
4
|
+
"customers",
|
|
5
|
+
"people",
|
|
6
|
+
"readers",
|
|
7
|
+
"researchers",
|
|
8
|
+
"shoppers",
|
|
9
|
+
"users",
|
|
10
|
+
"visitors"
|
|
11
|
+
]);
|
|
12
|
+
const MACHINE_ACTORS = new Set([
|
|
13
|
+
"agent",
|
|
14
|
+
"agents",
|
|
15
|
+
"ai",
|
|
16
|
+
"algorithm",
|
|
17
|
+
"algorithms",
|
|
18
|
+
"assistant",
|
|
19
|
+
"assistants",
|
|
20
|
+
"bot",
|
|
21
|
+
"bots",
|
|
22
|
+
"crawler",
|
|
23
|
+
"crawlers",
|
|
24
|
+
"machine",
|
|
25
|
+
"machines",
|
|
26
|
+
"model",
|
|
27
|
+
"models",
|
|
28
|
+
"system",
|
|
29
|
+
"systems"
|
|
30
|
+
]);
|
|
31
|
+
const PREDICATES = new Map([
|
|
32
|
+
["buy", "buy"],
|
|
33
|
+
["buys", "buy"],
|
|
34
|
+
["bought", "buy"],
|
|
35
|
+
["choose", "choose"],
|
|
36
|
+
["chooses", "choose"],
|
|
37
|
+
["chose", "choose"],
|
|
38
|
+
["compare", "compare"],
|
|
39
|
+
["compares", "compare"],
|
|
40
|
+
["compared", "compare"],
|
|
41
|
+
["evaluate", "evaluate"],
|
|
42
|
+
["evaluates", "evaluate"],
|
|
43
|
+
["evaluated", "evaluate"],
|
|
44
|
+
["find", "find"],
|
|
45
|
+
["finds", "find"],
|
|
46
|
+
["found", "find"],
|
|
47
|
+
["inspect", "inspect"],
|
|
48
|
+
["inspects", "inspect"],
|
|
49
|
+
["inspected", "inspect"],
|
|
50
|
+
["purchase", "purchase"],
|
|
51
|
+
["purchases", "purchase"],
|
|
52
|
+
["purchased", "purchase"],
|
|
53
|
+
["read", "read"],
|
|
54
|
+
["reads", "read"],
|
|
55
|
+
["review", "review"],
|
|
56
|
+
["reviews", "review"],
|
|
57
|
+
["reviewed", "review"],
|
|
58
|
+
["search", "search"],
|
|
59
|
+
["searches", "search"],
|
|
60
|
+
["searched", "search"],
|
|
61
|
+
["select", "select"],
|
|
62
|
+
["selects", "select"],
|
|
63
|
+
["selected", "select"],
|
|
64
|
+
["scan", "scan"],
|
|
65
|
+
["scans", "scan"],
|
|
66
|
+
["scanned", "scan"]
|
|
67
|
+
]);
|
|
68
|
+
const CAUSAL_CONNECTORS = new Set([
|
|
69
|
+
"after",
|
|
70
|
+
"because",
|
|
71
|
+
"if",
|
|
72
|
+
"since",
|
|
73
|
+
"therefore",
|
|
74
|
+
"until",
|
|
75
|
+
"when",
|
|
76
|
+
"while"
|
|
77
|
+
]);
|
|
78
|
+
const OBJECT_FILLERS = new Set([
|
|
79
|
+
"a",
|
|
80
|
+
"an",
|
|
81
|
+
"and",
|
|
82
|
+
"at",
|
|
83
|
+
"for",
|
|
84
|
+
"from",
|
|
85
|
+
"in",
|
|
86
|
+
"its",
|
|
87
|
+
"my",
|
|
88
|
+
"of",
|
|
89
|
+
"on",
|
|
90
|
+
"our",
|
|
91
|
+
"the",
|
|
92
|
+
"their",
|
|
93
|
+
"to",
|
|
94
|
+
"your"
|
|
95
|
+
]);
|
|
96
|
+
const OBJECT_PRONOUNS = new Set([
|
|
97
|
+
"he",
|
|
98
|
+
"her",
|
|
99
|
+
"him",
|
|
100
|
+
"it",
|
|
101
|
+
"me",
|
|
102
|
+
"she",
|
|
103
|
+
"them",
|
|
104
|
+
"they",
|
|
105
|
+
"us",
|
|
106
|
+
"we",
|
|
107
|
+
"you"
|
|
108
|
+
]);
|
|
109
|
+
const ARTIFACT_SURFACES = new Set([
|
|
110
|
+
"catalog",
|
|
111
|
+
"dashboard",
|
|
112
|
+
"database",
|
|
113
|
+
"feed",
|
|
114
|
+
"index",
|
|
115
|
+
"listing",
|
|
116
|
+
"page",
|
|
117
|
+
"report",
|
|
118
|
+
"site"
|
|
119
|
+
]);
|
|
120
|
+
function words(text) {
|
|
121
|
+
return wordTokens(text).map((token) => token.normalized);
|
|
122
|
+
}
|
|
123
|
+
function hasQuote(text) {
|
|
124
|
+
return [...text].some((character) => character === '"' ||
|
|
125
|
+
character === "\u201c" ||
|
|
126
|
+
character === "\u201d" ||
|
|
127
|
+
character === "`");
|
|
128
|
+
}
|
|
129
|
+
function hasDigit(word) {
|
|
130
|
+
return [...word].some((character) => character >= "0" && character <= "9");
|
|
131
|
+
}
|
|
132
|
+
function hasRejectedSurface(text, sentenceWords) {
|
|
133
|
+
return (hasQuote(text) ||
|
|
134
|
+
sentenceWords.some((word) => CAUSAL_CONNECTORS.has(word) || hasDigit(word)));
|
|
135
|
+
}
|
|
136
|
+
function stripTimeMarker(sentenceWords) {
|
|
137
|
+
const suffixes = [
|
|
138
|
+
["anymore"],
|
|
139
|
+
["now"],
|
|
140
|
+
["any", "longer"],
|
|
141
|
+
["these", "days"]
|
|
142
|
+
];
|
|
143
|
+
for (const suffix of suffixes) {
|
|
144
|
+
const start = sentenceWords.length - suffix.length;
|
|
145
|
+
if (start > 0 &&
|
|
146
|
+
suffix.every((word, index) => sentenceWords[start + index] === word)) {
|
|
147
|
+
return sentenceWords.slice(0, start);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
function humanAudienceEnd(sentenceWords) {
|
|
153
|
+
const first = sentenceWords[0];
|
|
154
|
+
if (first === "nobody") {
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
if (first === "no" && sentenceWords[1] === "one") {
|
|
158
|
+
return 2;
|
|
159
|
+
}
|
|
160
|
+
const headIndex = first === "the" || first === "most" || first === "many" ? 1 : 0;
|
|
161
|
+
return HUMAN_AUDIENCES.has(sentenceWords[headIndex] ?? "")
|
|
162
|
+
? headIndex + 1
|
|
163
|
+
: undefined;
|
|
164
|
+
}
|
|
165
|
+
function firstClaim(sentenceWords) {
|
|
166
|
+
const originalSubjectEnd = humanAudienceEnd(sentenceWords);
|
|
167
|
+
const withoutTime = stripTimeMarker(sentenceWords) ??
|
|
168
|
+
(originalSubjectEnd !== undefined &&
|
|
169
|
+
sentenceWords[originalSubjectEnd] === "no" &&
|
|
170
|
+
sentenceWords[originalSubjectEnd + 1] === "longer"
|
|
171
|
+
? sentenceWords
|
|
172
|
+
: undefined);
|
|
173
|
+
if (withoutTime === undefined) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
const subjectEnd = humanAudienceEnd(withoutTime);
|
|
177
|
+
if (subjectEnd === undefined) {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
let predicateIndex = subjectEnd;
|
|
181
|
+
const subjectStart = withoutTime[0];
|
|
182
|
+
if (subjectStart !== "nobody" && subjectStart !== "no") {
|
|
183
|
+
if (withoutTime[predicateIndex] === "don't" ||
|
|
184
|
+
withoutTime[predicateIndex] === "doesn't" ||
|
|
185
|
+
withoutTime[predicateIndex] === "didn't") {
|
|
186
|
+
predicateIndex += 1;
|
|
187
|
+
}
|
|
188
|
+
else if (withoutTime[predicateIndex] === "do" &&
|
|
189
|
+
withoutTime[predicateIndex + 1] === "not") {
|
|
190
|
+
predicateIndex += 2;
|
|
191
|
+
}
|
|
192
|
+
else if (withoutTime[predicateIndex] === "no" &&
|
|
193
|
+
withoutTime[predicateIndex + 1] === "longer") {
|
|
194
|
+
predicateIndex += 2;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const predicate = PREDICATES.get(withoutTime[predicateIndex] ?? "");
|
|
201
|
+
const object = withoutTime.slice(predicateIndex + 1);
|
|
202
|
+
return predicate !== undefined && object.length > 0
|
|
203
|
+
? { object, predicate }
|
|
204
|
+
: undefined;
|
|
205
|
+
}
|
|
206
|
+
function machineActorEnd(sentenceWords) {
|
|
207
|
+
let index = sentenceWords[0] === "a" ||
|
|
208
|
+
sentenceWords[0] === "an" ||
|
|
209
|
+
sentenceWords[0] === "the"
|
|
210
|
+
? 1
|
|
211
|
+
: 0;
|
|
212
|
+
const actorStart = index;
|
|
213
|
+
while (index < actorStart + 2 &&
|
|
214
|
+
MACHINE_ACTORS.has(sentenceWords[index] ?? "")) {
|
|
215
|
+
index += 1;
|
|
216
|
+
}
|
|
217
|
+
return index > actorStart ? index : undefined;
|
|
218
|
+
}
|
|
219
|
+
function secondClaim(sentenceWords) {
|
|
220
|
+
const actorEnd = machineActorEnd(sentenceWords);
|
|
221
|
+
if (actorEnd === undefined) {
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
const predicate = PREDICATES.get(sentenceWords[actorEnd] ?? "");
|
|
225
|
+
const object = sentenceWords.slice(actorEnd + 1);
|
|
226
|
+
return predicate !== undefined && object.length > 0
|
|
227
|
+
? { object, predicate }
|
|
228
|
+
: undefined;
|
|
229
|
+
}
|
|
230
|
+
function contentWords(object) {
|
|
231
|
+
return new Set(object.filter((word) => !OBJECT_FILLERS.has(word) && !OBJECT_PRONOUNS.has(word)));
|
|
232
|
+
}
|
|
233
|
+
function sharesContent(firstObject, secondObject) {
|
|
234
|
+
if (secondObject.length === 0 ||
|
|
235
|
+
secondObject.every((word) => OBJECT_PRONOUNS.has(word))) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
const firstContent = contentWords(firstObject);
|
|
239
|
+
const secondContent = contentWords(secondObject);
|
|
240
|
+
const sameContent = firstContent.size === secondContent.size &&
|
|
241
|
+
[...firstContent].every((word) => secondContent.has(word));
|
|
242
|
+
const firstCore = [...firstContent].filter((word) => !ARTIFACT_SURFACES.has(word));
|
|
243
|
+
const secondCore = [...secondContent].filter((word) => !ARTIFACT_SURFACES.has(word));
|
|
244
|
+
return (sameContent ||
|
|
245
|
+
(firstCore.length > 0 &&
|
|
246
|
+
firstCore.length === secondCore.length &&
|
|
247
|
+
firstCore.every((word) => secondCore.includes(word))));
|
|
248
|
+
}
|
|
249
|
+
export function matchAudienceReplacement(first, second) {
|
|
250
|
+
const firstWords = words(first);
|
|
251
|
+
const secondWords = words(second);
|
|
252
|
+
if (firstWords.length > 24 ||
|
|
253
|
+
secondWords.length > 20 ||
|
|
254
|
+
hasRejectedSurface(first, firstWords) ||
|
|
255
|
+
hasRejectedSurface(second, secondWords)) {
|
|
256
|
+
return undefined;
|
|
257
|
+
}
|
|
258
|
+
const humanClaim = firstClaim(firstWords);
|
|
259
|
+
const machineClaim = secondClaim(secondWords);
|
|
260
|
+
if (humanClaim === undefined ||
|
|
261
|
+
machineClaim?.predicate !== humanClaim.predicate ||
|
|
262
|
+
!sharesContent(humanClaim.object, machineClaim.object)) {
|
|
263
|
+
return undefined;
|
|
264
|
+
}
|
|
265
|
+
return `${first} ${second}`;
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=audience-replacement.js.map
|
|
@@ -1,4 +1,27 @@
|
|
|
1
|
-
import { NEGATION_WORDS, findCopularNegation, pronounCopulaStart, skipOptionalAdverbs, startsWithPronounCopula, startsWithWords, startsWithSubjectCopula, validSubject, words } from "./negation-reframe-parts.js";
|
|
1
|
+
import { FACTUAL_NEGATION_CONNECTORS, NEGATION_WORDS, findCopularNegation, pronounCopulaStart, skipOptionalAdverbs, startsWithPronounCopula, startsWithWords, startsWithSubjectCopula, validSubject, words } from "./negation-reframe-parts.js";
|
|
2
|
+
const AGENTIC_SYSTEM_SUBJECTS = new Set([
|
|
3
|
+
"agent",
|
|
4
|
+
"assistant",
|
|
5
|
+
"engine",
|
|
6
|
+
"model",
|
|
7
|
+
"system",
|
|
8
|
+
"tool"
|
|
9
|
+
]);
|
|
10
|
+
const PAYOFF_VERBS = new Set([
|
|
11
|
+
"compared",
|
|
12
|
+
"considered",
|
|
13
|
+
"encountered",
|
|
14
|
+
"entered",
|
|
15
|
+
"evaluated",
|
|
16
|
+
"found",
|
|
17
|
+
"met",
|
|
18
|
+
"qualified",
|
|
19
|
+
"ranked",
|
|
20
|
+
"reached",
|
|
21
|
+
"reviewed",
|
|
22
|
+
"selected",
|
|
23
|
+
"seen"
|
|
24
|
+
]);
|
|
2
25
|
export function sameSubjectCopularReframe(aTokens, bTokens) {
|
|
3
26
|
const negation = findCopularNegation(aTokens);
|
|
4
27
|
if (negation === undefined || !validSubject(negation.subject)) {
|
|
@@ -38,4 +61,19 @@ export function startsWithNegatedPronounCopula(tokens) {
|
|
|
38
61
|
const predicateIndex = skipOptionalAdverbs(tokenWords, start.predicateStart);
|
|
39
62
|
return NEGATION_WORDS.has(tokenWords[predicateIndex] ?? "");
|
|
40
63
|
}
|
|
64
|
+
export function negatedProgressiveNeverPayoff(first, second) {
|
|
65
|
+
const negation = findCopularNegation(first);
|
|
66
|
+
if (negation === undefined ||
|
|
67
|
+
!AGENTIC_SYSTEM_SUBJECTS.has(negation.subject.at(-1) ?? "") ||
|
|
68
|
+
words(first)[negation.negatedPredicateStart]?.endsWith("ing") !== true) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const secondWords = words(second);
|
|
72
|
+
const neverIndex = secondWords.slice(1, 4).indexOf("never") + 1;
|
|
73
|
+
return (["it", "they"].includes(secondWords[0] ?? "") &&
|
|
74
|
+
neverIndex > 0 &&
|
|
75
|
+
PAYOFF_VERBS.has(secondWords[neverIndex + 1] ?? "") &&
|
|
76
|
+
!secondWords.some((word) => FACTUAL_NEGATION_CONNECTORS.has(word)) &&
|
|
77
|
+
secondWords.length <= 10);
|
|
78
|
+
}
|
|
41
79
|
//# sourceMappingURL=copular-reframe.js.map
|