@dzhechkov/memory 0.2.6 → 0.2.7
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/dreaming.d.ts +4 -1
- package/dist/dreaming.d.ts.map +1 -1
- package/dist/dreaming.js +74 -10
- package/dist/dreaming.js.map +1 -1
- package/package.json +1 -1
- package/src/dreaming.ts +88 -9
package/dist/dreaming.d.ts
CHANGED
|
@@ -55,7 +55,10 @@ export declare function isNoiseInsight(text: string): boolean;
|
|
|
55
55
|
* NOISE GATE (a real-store audit found ~85 of 91 records were junk):
|
|
56
56
|
* - Tool invocations are NOT harvested — a `tool_use` is telemetry, not a learning.
|
|
57
57
|
* - System wrappers arriving as user messages ({@link isSystemWrapper}) are skipped.
|
|
58
|
-
* -
|
|
58
|
+
* - Verdict classification only fires on checkpoint-like messages (≤ 200 chars,
|
|
59
|
+
* ≤ 100 for failed) and only on ANCHORED standalone words/phrases, never bare
|
|
60
|
+
* substrings — "в stop hook" and "не изобретать заново" are live-store
|
|
61
|
+
* misfires that bare substrings produced.
|
|
59
62
|
*/
|
|
60
63
|
export declare function harvestDreamPatterns(options: DreamOptions): DreamPattern[];
|
|
61
64
|
/** Convert a DreamPattern to a MemoryRecord for storage via any MemoryBackend. */
|
package/dist/dreaming.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dreaming.d.ts","sourceRoot":"","sources":["../src/dreaming.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,qDAAqD;AACrD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,QAAQ,CAAC;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD;
|
|
1
|
+
{"version":3,"file":"dreaming.d.ts","sourceRoot":"","sources":["../src/dreaming.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,qDAAqD;AACrD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,QAAQ,CAAC;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD;AAyGD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOpD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,YAAY,EAAE,CAyE1E;AAaD,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,YAAY,CAWxE"}
|
package/dist/dreaming.js
CHANGED
|
@@ -61,14 +61,73 @@ const EXCELLENT_RESPONSES = new Set([
|
|
|
61
61
|
]);
|
|
62
62
|
/**
|
|
63
63
|
* Only messages this short are considered checkpoint-like for the
|
|
64
|
-
* needs_work/failed
|
|
64
|
+
* needs_work/failed verdict checks. Longer messages routinely QUOTE words
|
|
65
65
|
* like 'stop' or 'переделай' without meaning them as verdicts.
|
|
66
66
|
*/
|
|
67
67
|
const CHECKPOINT_MAX_LENGTH = 200;
|
|
68
|
+
/**
|
|
69
|
+
* A `failed@0.0` verdict poisons the reward store, so it demands the tightest
|
|
70
|
+
* gate: real rejections ("стоп", "stop — wrong direction") are terse. Anything
|
|
71
|
+
* longer than this is an instruction that happens to contain a rejection word.
|
|
72
|
+
*/
|
|
73
|
+
const FAILED_MAX_LENGTH = 100;
|
|
68
74
|
/** Normalize a checkpoint response: trim, lowercase, strip trailing punctuation. */
|
|
69
75
|
function normalizeCheckpointText(text) {
|
|
70
76
|
return text.trim().toLowerCase().replace(/[\s.!…]+$/u, '');
|
|
71
77
|
}
|
|
78
|
+
/** Escape a literal string for embedding in a RegExp source. */
|
|
79
|
+
function escapeRegExp(literal) {
|
|
80
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Unicode-aware "standalone word" boundary, as lookarounds.
|
|
84
|
+
*
|
|
85
|
+
* CRITICAL: JS `\b` is ASCII-only — `\bпеределай\b` NEVER matches Cyrillic
|
|
86
|
+
* text because Cyrillic letters are non-word characters for `\b` (both sides
|
|
87
|
+
* of the "boundary" are non-word, so there is no boundary). Every RU/EN
|
|
88
|
+
* keyword must go through these lookarounds instead; no raw `\b` anywhere.
|
|
89
|
+
*
|
|
90
|
+
* The hyphen is treated as a joiner so glued/compound forms do not match:
|
|
91
|
+
* "напеределай", "stopwatch", "restop", "стоп-кран", "wrong-таки".
|
|
92
|
+
*/
|
|
93
|
+
const WORD_BEFORE = '(?<![\\p{L}\\p{N}-])';
|
|
94
|
+
const WORD_AFTER = '(?![\\p{L}\\p{N}-])';
|
|
95
|
+
/** True when `word` occurs in `text` as a standalone word (Unicode-aware). */
|
|
96
|
+
function hasStandaloneWord(text, word) {
|
|
97
|
+
const re = new RegExp(`${WORD_BEFORE}${escapeRegExp(word)}${WORD_AFTER}`, 'iu');
|
|
98
|
+
return re.test(text);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* failed@0.0 — only when rejection is the ESSENCE of the message: the
|
|
102
|
+
* normalized text STARTS with a standalone rejection anchor. Mid-sentence
|
|
103
|
+
* mentions ("можешь добавить в stop hook…", "wrong-таки было") must NOT fire —
|
|
104
|
+
* a real misfire from the live store classified a normal instruction about a
|
|
105
|
+
* "stop hook" as failed@0.0.
|
|
106
|
+
*
|
|
107
|
+
* Documented choice: "стоп машина" starts with standalone "стоп" and DOES
|
|
108
|
+
* classify as failed — leading "стоп" as a word is accepted as a halt order.
|
|
109
|
+
*
|
|
110
|
+
* Applied to the normalized (trimmed, lowercased, punctuation-stripped) text.
|
|
111
|
+
*/
|
|
112
|
+
const FAILED_LEADING_RE = new RegExp(`^(?:стоп|stop|wrong|(?:это\\s+|вс[её]\\s+)?неправильно)${WORD_AFTER}`, 'u');
|
|
113
|
+
/**
|
|
114
|
+
* needs_work@0.3 — only ANCHORED imperative rework phrases, never bare
|
|
115
|
+
* keywords. Standalone-word matches anywhere in the message.
|
|
116
|
+
*/
|
|
117
|
+
const NEEDS_WORK_WORDS = [
|
|
118
|
+
'переделай',
|
|
119
|
+
'переделать',
|
|
120
|
+
'redo',
|
|
121
|
+
'rework',
|
|
122
|
+
'start over',
|
|
123
|
+
];
|
|
124
|
+
/**
|
|
125
|
+
* 'заново' fires ONLY inside imperative collocations ("сделай всё заново",
|
|
126
|
+
* "начни заново"). Bare 'заново' — and especially the idiom "не изобретать
|
|
127
|
+
* заново" (don't reinvent the wheel; a real misfire from the live store) —
|
|
128
|
+
* must NOT fire.
|
|
129
|
+
*/
|
|
130
|
+
const ZANOVO_IMPERATIVE_RE = new RegExp(`${WORD_BEFORE}(?:сделай|сделать|начни|начать|давай|начн[её]м)\\s+(?:вс[её]\\s+)?заново${WORD_AFTER}`, 'iu');
|
|
72
131
|
/**
|
|
73
132
|
* True for insights matching the LEGACY noise this harvester used to emit,
|
|
74
133
|
* so a prune step can retro-clean existing stores:
|
|
@@ -98,7 +157,10 @@ export function isNoiseInsight(text) {
|
|
|
98
157
|
* NOISE GATE (a real-store audit found ~85 of 91 records were junk):
|
|
99
158
|
* - Tool invocations are NOT harvested — a `tool_use` is telemetry, not a learning.
|
|
100
159
|
* - System wrappers arriving as user messages ({@link isSystemWrapper}) are skipped.
|
|
101
|
-
* -
|
|
160
|
+
* - Verdict classification only fires on checkpoint-like messages (≤ 200 chars,
|
|
161
|
+
* ≤ 100 for failed) and only on ANCHORED standalone words/phrases, never bare
|
|
162
|
+
* substrings — "в stop hook" and "не изобретать заново" are live-store
|
|
163
|
+
* misfires that bare substrings produced.
|
|
102
164
|
*/
|
|
103
165
|
export function harvestDreamPatterns(options) {
|
|
104
166
|
const { sessionsDir, since } = options;
|
|
@@ -135,17 +197,19 @@ export function harvestDreamPatterns(options) {
|
|
|
135
197
|
score = 1.0;
|
|
136
198
|
}
|
|
137
199
|
else if (trimmed.length <= CHECKPOINT_MAX_LENGTH) {
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
score = 0.3;
|
|
144
|
-
}
|
|
145
|
-
else if (text.includes('стоп') || text.includes('stop') || text.includes('wrong')) {
|
|
200
|
+
// Anchored verdicts only on checkpoint-like (short) messages.
|
|
201
|
+
// PRECISION over recall: a missed downgrade costs nothing (the
|
|
202
|
+
// 'good' outcome is not recorded), a false failed@0.0 poisons the
|
|
203
|
+
// reward store. When in doubt, do not classify.
|
|
204
|
+
if (trimmed.length <= FAILED_MAX_LENGTH && FAILED_LEADING_RE.test(normalized)) {
|
|
146
205
|
outcome = 'failed';
|
|
147
206
|
score = 0.0;
|
|
148
207
|
}
|
|
208
|
+
else if (NEEDS_WORK_WORDS.some((word) => hasStandaloneWord(trimmed, word)) ||
|
|
209
|
+
ZANOVO_IMPERATIVE_RE.test(trimmed)) {
|
|
210
|
+
outcome = 'needs_work';
|
|
211
|
+
score = 0.3;
|
|
212
|
+
}
|
|
149
213
|
}
|
|
150
214
|
if (outcome !== 'good') {
|
|
151
215
|
patterns.push({
|
package/dist/dreaming.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dreaming.js","sourceRoot":"","sources":["../src/dreaming.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAsBjC;;;;GAIG;AACH,MAAM,uBAAuB,GAAsB;IACjD,oBAAoB;IACpB,kBAAkB;IAClB,uBAAuB;IACvB,eAAe;IACf,aAAa;IACb,cAAc;IACd,sBAAsB;IACtB,sBAAsB;CACvB,CAAC;AAEF,0EAA0E;AAC1E,MAAM,uBAAuB,GAAG,mCAAmC,CAAC;AAEpE;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACpC,OAAO,CACL,uBAAuB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAClE,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,CACtC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IACvD,IAAI;IACJ,IAAI;IACJ,MAAM;IACN,WAAW;IACX,IAAI;IACJ,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,SAAS;IACT,MAAM;IACN,MAAM;IACN,eAAe;CAChB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC,oFAAoF;AACpF,SAAS,uBAAuB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,uCAAuC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACpE,MAAM,UAAU,GAAG,mBAAmB,CAAC;IACvC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAChC,OAAO,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"dreaming.js","sourceRoot":"","sources":["../src/dreaming.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/dreaming.ts
CHANGED
|
@@ -89,16 +89,88 @@ const EXCELLENT_RESPONSES: ReadonlySet<string> = new Set([
|
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
91
|
* Only messages this short are considered checkpoint-like for the
|
|
92
|
-
* needs_work/failed
|
|
92
|
+
* needs_work/failed verdict checks. Longer messages routinely QUOTE words
|
|
93
93
|
* like 'stop' or 'переделай' without meaning them as verdicts.
|
|
94
94
|
*/
|
|
95
95
|
const CHECKPOINT_MAX_LENGTH = 200;
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* A `failed@0.0` verdict poisons the reward store, so it demands the tightest
|
|
99
|
+
* gate: real rejections ("стоп", "stop — wrong direction") are terse. Anything
|
|
100
|
+
* longer than this is an instruction that happens to contain a rejection word.
|
|
101
|
+
*/
|
|
102
|
+
const FAILED_MAX_LENGTH = 100;
|
|
103
|
+
|
|
97
104
|
/** Normalize a checkpoint response: trim, lowercase, strip trailing punctuation. */
|
|
98
105
|
function normalizeCheckpointText(text: string): string {
|
|
99
106
|
return text.trim().toLowerCase().replace(/[\s.!…]+$/u, '');
|
|
100
107
|
}
|
|
101
108
|
|
|
109
|
+
/** Escape a literal string for embedding in a RegExp source. */
|
|
110
|
+
function escapeRegExp(literal: string): string {
|
|
111
|
+
return literal.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Unicode-aware "standalone word" boundary, as lookarounds.
|
|
116
|
+
*
|
|
117
|
+
* CRITICAL: JS `\b` is ASCII-only — `\bпеределай\b` NEVER matches Cyrillic
|
|
118
|
+
* text because Cyrillic letters are non-word characters for `\b` (both sides
|
|
119
|
+
* of the "boundary" are non-word, so there is no boundary). Every RU/EN
|
|
120
|
+
* keyword must go through these lookarounds instead; no raw `\b` anywhere.
|
|
121
|
+
*
|
|
122
|
+
* The hyphen is treated as a joiner so glued/compound forms do not match:
|
|
123
|
+
* "напеределай", "stopwatch", "restop", "стоп-кран", "wrong-таки".
|
|
124
|
+
*/
|
|
125
|
+
const WORD_BEFORE = '(?<![\\p{L}\\p{N}-])';
|
|
126
|
+
const WORD_AFTER = '(?![\\p{L}\\p{N}-])';
|
|
127
|
+
|
|
128
|
+
/** True when `word` occurs in `text` as a standalone word (Unicode-aware). */
|
|
129
|
+
function hasStandaloneWord(text: string, word: string): boolean {
|
|
130
|
+
const re = new RegExp(`${WORD_BEFORE}${escapeRegExp(word)}${WORD_AFTER}`, 'iu');
|
|
131
|
+
return re.test(text);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* failed@0.0 — only when rejection is the ESSENCE of the message: the
|
|
136
|
+
* normalized text STARTS with a standalone rejection anchor. Mid-sentence
|
|
137
|
+
* mentions ("можешь добавить в stop hook…", "wrong-таки было") must NOT fire —
|
|
138
|
+
* a real misfire from the live store classified a normal instruction about a
|
|
139
|
+
* "stop hook" as failed@0.0.
|
|
140
|
+
*
|
|
141
|
+
* Documented choice: "стоп машина" starts with standalone "стоп" and DOES
|
|
142
|
+
* classify as failed — leading "стоп" as a word is accepted as a halt order.
|
|
143
|
+
*
|
|
144
|
+
* Applied to the normalized (trimmed, lowercased, punctuation-stripped) text.
|
|
145
|
+
*/
|
|
146
|
+
const FAILED_LEADING_RE = new RegExp(
|
|
147
|
+
`^(?:стоп|stop|wrong|(?:это\\s+|вс[её]\\s+)?неправильно)${WORD_AFTER}`,
|
|
148
|
+
'u',
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* needs_work@0.3 — only ANCHORED imperative rework phrases, never bare
|
|
153
|
+
* keywords. Standalone-word matches anywhere in the message.
|
|
154
|
+
*/
|
|
155
|
+
const NEEDS_WORK_WORDS: readonly string[] = [
|
|
156
|
+
'переделай',
|
|
157
|
+
'переделать',
|
|
158
|
+
'redo',
|
|
159
|
+
'rework',
|
|
160
|
+
'start over',
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 'заново' fires ONLY inside imperative collocations ("сделай всё заново",
|
|
165
|
+
* "начни заново"). Bare 'заново' — and especially the idiom "не изобретать
|
|
166
|
+
* заново" (don't reinvent the wheel; a real misfire from the live store) —
|
|
167
|
+
* must NOT fire.
|
|
168
|
+
*/
|
|
169
|
+
const ZANOVO_IMPERATIVE_RE = new RegExp(
|
|
170
|
+
`${WORD_BEFORE}(?:сделай|сделать|начни|начать|давай|начн[её]м)\\s+(?:вс[её]\\s+)?заново${WORD_AFTER}`,
|
|
171
|
+
'iu',
|
|
172
|
+
);
|
|
173
|
+
|
|
102
174
|
/**
|
|
103
175
|
* True for insights matching the LEGACY noise this harvester used to emit,
|
|
104
176
|
* so a prune step can retro-clean existing stores:
|
|
@@ -128,7 +200,10 @@ export function isNoiseInsight(text: string): boolean {
|
|
|
128
200
|
* NOISE GATE (a real-store audit found ~85 of 91 records were junk):
|
|
129
201
|
* - Tool invocations are NOT harvested — a `tool_use` is telemetry, not a learning.
|
|
130
202
|
* - System wrappers arriving as user messages ({@link isSystemWrapper}) are skipped.
|
|
131
|
-
* -
|
|
203
|
+
* - Verdict classification only fires on checkpoint-like messages (≤ 200 chars,
|
|
204
|
+
* ≤ 100 for failed) and only on ANCHORED standalone words/phrases, never bare
|
|
205
|
+
* substrings — "в stop hook" and "не изобретать заново" are live-store
|
|
206
|
+
* misfires that bare substrings produced.
|
|
132
207
|
*/
|
|
133
208
|
export function harvestDreamPatterns(options: DreamOptions): DreamPattern[] {
|
|
134
209
|
const { sessionsDir, since } = options;
|
|
@@ -169,15 +244,19 @@ export function harvestDreamPatterns(options: DreamOptions): DreamPattern[] {
|
|
|
169
244
|
outcome = 'excellent';
|
|
170
245
|
score = 1.0;
|
|
171
246
|
} else if (trimmed.length <= CHECKPOINT_MAX_LENGTH) {
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
score = 0.3;
|
|
178
|
-
} else if (text.includes('стоп') || text.includes('stop') || text.includes('wrong')) {
|
|
247
|
+
// Anchored verdicts only on checkpoint-like (short) messages.
|
|
248
|
+
// PRECISION over recall: a missed downgrade costs nothing (the
|
|
249
|
+
// 'good' outcome is not recorded), a false failed@0.0 poisons the
|
|
250
|
+
// reward store. When in doubt, do not classify.
|
|
251
|
+
if (trimmed.length <= FAILED_MAX_LENGTH && FAILED_LEADING_RE.test(normalized)) {
|
|
179
252
|
outcome = 'failed';
|
|
180
253
|
score = 0.0;
|
|
254
|
+
} else if (
|
|
255
|
+
NEEDS_WORK_WORDS.some((word) => hasStandaloneWord(trimmed, word)) ||
|
|
256
|
+
ZANOVO_IMPERATIVE_RE.test(trimmed)
|
|
257
|
+
) {
|
|
258
|
+
outcome = 'needs_work';
|
|
259
|
+
score = 0.3;
|
|
181
260
|
}
|
|
182
261
|
}
|
|
183
262
|
|