thinkpool-pair 0.7.330 → 0.7.331
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/package.json +1 -1
- package/terminal-name.mjs +17 -5
package/package.json
CHANGED
package/terminal-name.mjs
CHANGED
|
@@ -17,6 +17,7 @@ const ANY_HEADING = /^(?:#{1,6}\s+|(?:context|background|constraints?|inputs?|ou
|
|
|
17
17
|
const NOISE = /^(?:context|background|for reference|here(?:'s| is)|note|current(?:ly)?|example|environment|room now|constraints?|acceptance|success criteria)\b/i
|
|
18
18
|
const EXPLANATION = /^(?:because|cause|since|so that|this is because)\b/i
|
|
19
19
|
const CONSTRAINT = /^(?:users? can still|keep|must|never|should|without)\b/i
|
|
20
|
+
const DEPENDENT_FRAGMENT = /^(?:after|before|by|during|for|from|in|instead(?: of)?|on|through|until|with|without)\b/i
|
|
20
21
|
const INFORMATION_REQUEST = /^(?:which|what|who|where|when|why|how)\b/i
|
|
21
22
|
const NEGATIVE_PREFERENCE = /^(?:(?:i|we)\s+)?(?:do not|don't|dont|would not|wouldn't|won't|wont)\s+(?:(?:want|wanna|need)(?:\s+to)?|use|include|choose)\b|^(?:(?:i|we)\s+)?(?:want|wanna|need)(?:\s+to)?\s+avoid\b/i
|
|
22
23
|
const ISSUE = /\b(?:broken|buggy|crash(?:es|ed|ing)?|duplicate|error|fail(?:s|ed|ing|ure)?|flash(?:es|ed|ing)?|missing|no animation|not working|out of (?:scrollable )?view|stuck|wrong)\b/i
|
|
@@ -29,6 +30,7 @@ const ACTIONS = Object.freeze([
|
|
|
29
30
|
{ title: 'Harden', score: 98, re: /\b(?:harden|hardens|hardened|hardening)\b/i },
|
|
30
31
|
{ title: 'Snap', score: 96, re: /\b(?:snap|snaps|snapped|snapping)\b/i },
|
|
31
32
|
{ title: 'Improve', score: 94, re: /\b(?:improve|improves|improved|improving|optimi[sz](?:e|es|ed|ing)|\bbetter\b)\b/i },
|
|
33
|
+
{ title: 'Rework', score: 93, re: /\b(?:rework|reworks|reworked|reworking)\b/i },
|
|
32
34
|
{ title: 'Implement', score: 92, re: /\b(?:implement|implements|implemented|implementing)\b/i },
|
|
33
35
|
{ title: 'Build', score: 90, re: /\b(?:build|builds|built|building|create|creates|created|creating)\b/i },
|
|
34
36
|
{ title: 'Add', score: 88, re: /\b(?:add|adds|added|adding|wire|wires|wired|wiring)\b/i },
|
|
@@ -136,7 +138,11 @@ const bestIntentClause = (text) => {
|
|
|
136
138
|
if (EXPLANATION.test(clause)) score -= 34
|
|
137
139
|
if (CONSTRAINT.test(clause)) score -= 45
|
|
138
140
|
if (NEGATIVE_PREFERENCE.test(clause)) score -= 70
|
|
139
|
-
|
|
141
|
+
// A short dependent tail such as "From ground up" or "On mobile" adds
|
|
142
|
+
// scope to the preceding request; it is not a standalone task. Recency is
|
|
143
|
+
// deliberately not a signal here: the title should represent the main
|
|
144
|
+
// theme, not whichever sentence happened to come last.
|
|
145
|
+
if (!action && !REQUEST.test(clause) && !INFORMATION_REQUEST.test(clause) && DEPENDENT_FRAGMENT.test(clause)) score -= 24
|
|
140
146
|
if (!best || score > best.score) best = { clause, score }
|
|
141
147
|
}
|
|
142
148
|
return best?.clause || clauses[0] || null
|
|
@@ -175,13 +181,18 @@ const titleWord = (word) => {
|
|
|
175
181
|
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
|
176
182
|
}
|
|
177
183
|
|
|
178
|
-
const contentWords = (value) => {
|
|
184
|
+
const contentWords = (value, excludedFamilies = []) => {
|
|
179
185
|
const words = String(value || '').match(/[\p{L}\p{N}][\p{L}\p{N}+#.'-]*/gu) || []
|
|
180
186
|
const seen = new Set()
|
|
181
187
|
const result = []
|
|
182
188
|
for (let word of words) {
|
|
183
189
|
const lower = word.toLowerCase()
|
|
184
190
|
if (SKIP.has(lower) || /^https?$/i.test(word)) continue
|
|
191
|
+
// ACTIONS intentionally folds synonyms into one title verb (review/test/verify
|
|
192
|
+
// all become Audit). Once that verb is chosen, words from the same family are
|
|
193
|
+
// not objects. Keeping them spent the title budget on "Audit Reviews Audits"
|
|
194
|
+
// before the extractor reached the actual scope.
|
|
195
|
+
if (excludedFamilies.some((family) => family.test(word))) continue
|
|
185
196
|
if (lower === 'flashes' || lower === 'flashing') word = 'flash'
|
|
186
197
|
if (lower === 'failing' || lower === 'failed' || lower === 'fails') word = 'failure'
|
|
187
198
|
const key = word.toLowerCase().replace(/(?:s|ed|ing)$/i, '')
|
|
@@ -227,12 +238,13 @@ const taskTitle = (value) => {
|
|
|
227
238
|
const before = body.slice(0, action.index)
|
|
228
239
|
objectText = body.slice(action.index + action.match.length)
|
|
229
240
|
const weakLead = bestAction(before)
|
|
230
|
-
if (weakLead?.score <= 76) domain = contentWords(before.slice(weakLead.index + weakLead.match.length)).slice(0, 3)
|
|
241
|
+
if (weakLead?.score <= 76) domain = contentWords(before.slice(weakLead.index + weakLead.match.length), [weakLead.re]).slice(0, 3)
|
|
231
242
|
objectText = objectText.split(/\s*,?\s+(?:and|then)\s+(?:(?:also)\s+)?(?=(?:add|build|create|implement|remove|replace|update|wire)\b)/i, 1)[0]
|
|
232
243
|
objectText = objectText.replace(/\b(?:and|then)\s+(?:audit|check|debug|investigate|review|test|verify)\b/gi, ' ')
|
|
233
244
|
}
|
|
234
|
-
|
|
235
|
-
|
|
245
|
+
const excludedObjectFamilies = action ? [action.re] : []
|
|
246
|
+
let object = contentWords(objectText, excludedObjectFamilies)
|
|
247
|
+
if (!object.length) object = contentWords(body, excludedObjectFamilies)
|
|
236
248
|
if (informationRequest) {
|
|
237
249
|
const available = object.findIndex((word) => /^available$/i.test(word))
|
|
238
250
|
if (available > 0) object = [object[available], ...object.slice(0, available), ...object.slice(available + 1)]
|