scoutline 0.23.0 → 0.24.1
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/README.md +49 -1
- package/dist/capabilities/investigation.d.ts +134 -0
- package/dist/capabilities/investigation.d.ts.map +1 -0
- package/dist/capabilities/investigation.js +278 -0
- package/dist/capabilities/investigation.js.map +1 -0
- package/dist/commands/archive.d.ts +18 -1
- package/dist/commands/archive.d.ts.map +1 -1
- package/dist/commands/archive.js +23 -12
- package/dist/commands/archive.js.map +1 -1
- package/dist/commands/investigate.d.ts +232 -0
- package/dist/commands/investigate.d.ts.map +1 -0
- package/dist/commands/investigate.js +838 -0
- package/dist/commands/investigate.js.map +1 -0
- package/dist/commands/search.d.ts +16 -0
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +10 -2
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/vision.d.ts.map +1 -1
- package/dist/commands/vision.js +15 -2
- package/dist/commands/vision.js.map +1 -1
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +379 -10
- package/dist/index.js.map +1 -1
- package/dist/lib/context-file.d.ts +21 -0
- package/dist/lib/context-file.d.ts.map +1 -1
- package/dist/lib/context-file.js +84 -6
- package/dist/lib/context-file.js.map +1 -1
- package/dist/lib/equals-form.d.ts +34 -0
- package/dist/lib/equals-form.d.ts.map +1 -0
- package/dist/lib/equals-form.js +49 -0
- package/dist/lib/equals-form.js.map +1 -0
- package/dist/lib/investigate-claims.d.ts +98 -0
- package/dist/lib/investigate-claims.d.ts.map +1 -0
- package/dist/lib/investigate-claims.js +166 -0
- package/dist/lib/investigate-claims.js.map +1 -0
- package/dist/lib/investigate-extract.d.ts +58 -0
- package/dist/lib/investigate-extract.d.ts.map +1 -0
- package/dist/lib/investigate-extract.js +126 -0
- package/dist/lib/investigate-extract.js.map +1 -0
- package/dist/lib/investigate-planner.d.ts +60 -0
- package/dist/lib/investigate-planner.d.ts.map +1 -0
- package/dist/lib/investigate-planner.js +125 -0
- package/dist/lib/investigate-planner.js.map +1 -0
- package/dist/lib/journal.d.ts.map +1 -1
- package/dist/lib/journal.js +10 -9
- package/dist/lib/journal.js.map +1 -1
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +4 -1
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/types.d.ts +45 -1
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/providers/zai/adapter.d.ts.map +1 -1
- package/dist/providers/zai/adapter.js +245 -3
- package/dist/providers/zai/adapter.js.map +1 -1
- package/dist/providers/zai/layout-parsing.d.ts +76 -0
- package/dist/providers/zai/layout-parsing.d.ts.map +1 -0
- package/dist/providers/zai/layout-parsing.js +151 -0
- package/dist/providers/zai/layout-parsing.js.map +1 -0
- package/dist/providers/zai/media.d.ts +19 -0
- package/dist/providers/zai/media.d.ts.map +1 -1
- package/dist/providers/zai/media.js +61 -0
- package/dist/providers/zai/media.js.map +1 -1
- package/package.json +1 -1
- package/skills/scoutline/SKILL.md +71 -1
|
@@ -27,6 +27,27 @@ export declare const MAX_TERMS = 12;
|
|
|
27
27
|
* `STOPWORD_SET`; the frozen array is the shipped constant.
|
|
28
28
|
*/
|
|
29
29
|
export declare const STOPWORDS: readonly string[];
|
|
30
|
+
/** D2.3: term length bounds. Exported: `investigate-planner` shares them. */
|
|
31
|
+
export declare const MIN_TERM_CHARS = 4;
|
|
32
|
+
export declare const MAX_TERM_CHARS = 40;
|
|
33
|
+
/**
|
|
34
|
+
* True for pure-ASCII tokens — callers use this to apply the
|
|
35
|
+
* MIN_TERM_CHARS floor to ASCII only (single non-ASCII chars are
|
|
36
|
+
* meaningful word units; issue #271).
|
|
37
|
+
*/
|
|
38
|
+
export declare function isAsciiToken(token: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Tokenize lowercased text into term tokens: word-like units with
|
|
41
|
+
* ASCII punctuation never inside a non-ASCII token. `keepApostrophe`
|
|
42
|
+
* selects claims' grammar ("don't" stays one token) and
|
|
43
|
+
* `keepUnderscore` journal recall's (snake_case identifiers stay
|
|
44
|
+
* whole tokens) — both on the ASCII path only.
|
|
45
|
+
* Segments longer than MAX_TERM_CHARS are dropped here (not by
|
|
46
|
+
* callers): the "en" segmenter splits long unspaced CJK runs into
|
|
47
|
+
* dictionary chunks (東東×…), so a caller-side length check could
|
|
48
|
+
* admit sub-cap chunks of an over-long word.
|
|
49
|
+
*/
|
|
50
|
+
export declare function tokenizeTerms(text: string, keepApostrophe?: boolean, keepUnderscore?: boolean): string[];
|
|
30
51
|
export interface ParsedContextText {
|
|
31
52
|
/** In document order, deduped exact-trim (case-sensitive). */
|
|
32
53
|
readonly headings: readonly string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-file.d.ts","sourceRoot":"","sources":["../../src/lib/context-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,SAAU,CAAC;AAEzC,wEAAwE;AACxE,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,wCAAwC;AACxC,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EAQrC,CAAC;
|
|
1
|
+
{"version":3,"file":"context-file.d.ts","sourceRoot":"","sources":["../../src/lib/context-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,SAAU,CAAC;AAEzC,wEAAwE;AACxE,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,wCAAwC;AACxC,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EAQrC,CAAC;AAkBH,6EAA6E;AAC7E,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,cAAc,KAAK,CAAC;AAkCjC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,cAAc,UAAQ,EACtB,cAAc,UAAQ,GACrB,MAAM,EAAE,CAsBV;AAKD,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAOD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAqChE;AA+DD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAEhE;AAED,gEAAgE;AAChE,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK1C;AAMD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAW/E;AAED,gCAAgC;AAChC,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;CAAE,CAAC;AAE7B,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C;;;;OAIG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CACnC;AAED,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,iBAAiB,EACvB,EAAE,EAAE,eAAe,GAClB,OAAO,CAAC,oBAAoB,CAAC,CAe/B"}
|
package/dist/lib/context-file.js
CHANGED
|
@@ -49,11 +49,80 @@ const HEADING_PATTERN = /^(#{1,6})\s+(.+)$/;
|
|
|
49
49
|
const MAX_QUESTION_CHARS = 200;
|
|
50
50
|
/** D2.4: headings longer than this are dropped from sub-queries. */
|
|
51
51
|
const MAX_SUBQUERY_HEADING_CHARS = 60;
|
|
52
|
-
/** D2.3: term length bounds. */
|
|
53
|
-
const MIN_TERM_CHARS = 4;
|
|
54
|
-
const MAX_TERM_CHARS = 40;
|
|
52
|
+
/** D2.3: term length bounds. Exported: `investigate-planner` shares them. */
|
|
53
|
+
export const MIN_TERM_CHARS = 4;
|
|
54
|
+
export const MAX_TERM_CHARS = 40;
|
|
55
55
|
/** D2.5: the appended bias segment fits within this many chars. */
|
|
56
56
|
const MAX_BIAS_APPEND_CHARS = 240;
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Issue #271: Unicode word segmentation at the shared term seam.
|
|
59
|
+
//
|
|
60
|
+
// Pure-ASCII input keeps the legacy split verbatim (byte-identical A/B —
|
|
61
|
+
// the segmenter would fuse ASCII punctuation into words like "3.14").
|
|
62
|
+
// Input containing non-ASCII goes through `Intl.Segmenter` (fixed "en"
|
|
63
|
+
// locale, granularity "word" — locale-independent for determinism; en/ja
|
|
64
|
+
// agree on CJK corpus). Non-ASCII word-like segments are kept WHOLE: a
|
|
65
|
+
// CJK word is a meaningful unit, so the 4-char ASCII minimum never
|
|
66
|
+
// applies to them (single CJK chars pass); the 40-char cap still does.
|
|
67
|
+
// Length bounds themselves are applied by the CALLERS, not here.
|
|
68
|
+
//
|
|
69
|
+
// OUT OF SCOPE (documented): negation cues stay English literals —
|
|
70
|
+
// non-Latin contradiction detection is not attempted.
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
/** The legacy ASCII split class (kept verbatim for the A/B pin). */
|
|
73
|
+
const ASCII_SPLIT = /[^a-z0-9]+/;
|
|
74
|
+
/** Claims' apostrophe-keeping variant of the legacy split. */
|
|
75
|
+
const ASCII_SPLIT_APOSTROPHE = /[^a-z0-9']+/;
|
|
76
|
+
/** Journal recall's underscore-keeping variant (identifiers stay whole). */
|
|
77
|
+
const ASCII_SPLIT_UNDERSCORE = /[^a-z0-9_]+/;
|
|
78
|
+
const SEGMENTER = new Intl.Segmenter("en", { granularity: "word" });
|
|
79
|
+
function isAscii(text) {
|
|
80
|
+
return /^[\x00-\x7f]*$/.test(text);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* True for pure-ASCII tokens — callers use this to apply the
|
|
84
|
+
* MIN_TERM_CHARS floor to ASCII only (single non-ASCII chars are
|
|
85
|
+
* meaningful word units; issue #271).
|
|
86
|
+
*/
|
|
87
|
+
export function isAsciiToken(token) {
|
|
88
|
+
return isAscii(token);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Tokenize lowercased text into term tokens: word-like units with
|
|
92
|
+
* ASCII punctuation never inside a non-ASCII token. `keepApostrophe`
|
|
93
|
+
* selects claims' grammar ("don't" stays one token) and
|
|
94
|
+
* `keepUnderscore` journal recall's (snake_case identifiers stay
|
|
95
|
+
* whole tokens) — both on the ASCII path only.
|
|
96
|
+
* Segments longer than MAX_TERM_CHARS are dropped here (not by
|
|
97
|
+
* callers): the "en" segmenter splits long unspaced CJK runs into
|
|
98
|
+
* dictionary chunks (東東×…), so a caller-side length check could
|
|
99
|
+
* admit sub-cap chunks of an over-long word.
|
|
100
|
+
*/
|
|
101
|
+
export function tokenizeTerms(text, keepApostrophe = false, keepUnderscore = false) {
|
|
102
|
+
// ponytail: keepApostrophe (claims) and keepUnderscore (journal) are
|
|
103
|
+
// caller-exclusive today; a stacking caller adds the combined class.
|
|
104
|
+
const split = keepUnderscore
|
|
105
|
+
? ASCII_SPLIT_UNDERSCORE
|
|
106
|
+
: keepApostrophe
|
|
107
|
+
? ASCII_SPLIT_APOSTROPHE
|
|
108
|
+
: ASCII_SPLIT;
|
|
109
|
+
const lower = text.toLowerCase();
|
|
110
|
+
if (isAscii(lower)) {
|
|
111
|
+
return lower.split(split).filter((t) => t.length > 0);
|
|
112
|
+
}
|
|
113
|
+
const tokens = [];
|
|
114
|
+
for (const { segment, isWordLike } of SEGMENTER.segment(lower)) {
|
|
115
|
+
if (!isWordLike)
|
|
116
|
+
continue;
|
|
117
|
+
if (isAscii(segment)) {
|
|
118
|
+
tokens.push(...segment.split(split).filter((t) => t.length > 0));
|
|
119
|
+
}
|
|
120
|
+
else if (segment.length <= MAX_TERM_CHARS) {
|
|
121
|
+
tokens.push(segment);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return tokens;
|
|
125
|
+
}
|
|
57
126
|
/** D3 (G3): NUL byte anywhere in this prefix marks the source binary. */
|
|
58
127
|
const BINARY_SNIFF_BYTES = 8192;
|
|
59
128
|
/**
|
|
@@ -102,13 +171,22 @@ export function parseContextText(text) {
|
|
|
102
171
|
subQueries: deriveSubQueriesFromStream(stream),
|
|
103
172
|
};
|
|
104
173
|
}
|
|
105
|
-
/**
|
|
174
|
+
/**
|
|
175
|
+
* D2.3: lowercase tokens from the stream, stopword/length filtered,
|
|
176
|
+
* capped. Issue #271: tokens come from the shared Unicode tokenizer —
|
|
177
|
+
* non-ASCII segments are meaningful single units, so the ASCII
|
|
178
|
+
* MIN_TERM_CHARS floor never applies to them (single CJK chars pass);
|
|
179
|
+
* the MAX_TERM_CHARS cap applies to every token.
|
|
180
|
+
*/
|
|
106
181
|
function deriveTerms(stream) {
|
|
107
182
|
const terms = [];
|
|
108
183
|
const seen = new Set();
|
|
109
184
|
for (const item of stream) {
|
|
110
|
-
for (const token of item.value
|
|
111
|
-
if (token
|
|
185
|
+
for (const token of tokenizeTerms(item.value)) {
|
|
186
|
+
if (isAscii(token) && token.length < MIN_TERM_CHARS) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (token.length > MAX_TERM_CHARS) {
|
|
112
190
|
continue;
|
|
113
191
|
}
|
|
114
192
|
if (STOPWORD_SET.has(token) || seen.has(token)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-file.js","sourceRoot":"","sources":["../../src/lib/context-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEzD,sEAAsE;AACtE,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,UAAU;AAEpD,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,wCAAwC;AACxC,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC;AAE5B;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAsB,MAAM,CAAC,MAAM,CAAC;IACxD,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAClE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM;IACrE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;IAClE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAC7D,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO;IAClE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ;IAChE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO;CAC9D,CAAC,CAAC;AAEH,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAE5C,uEAAuE;AACvE,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B,oEAAoE;AACpE,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAEtC,
|
|
1
|
+
{"version":3,"file":"context-file.js","sourceRoot":"","sources":["../../src/lib/context-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central `--flag=value` normalization (#263).
|
|
3
|
+
*
|
|
4
|
+
* `parseArgs` (index.ts) has no equals-form handling: a `--flag=value`
|
|
5
|
+
* token landed as a boolean flag under a garbage key (`flags["flag=value"]`)
|
|
6
|
+
* and was silently dropped — the accept-and-drop class, but at the parser
|
|
7
|
+
* layer. Two commands (archive, investigate) guarded locally with
|
|
8
|
+
* per-command rejections; this seam replaces both: `--flag=value` is
|
|
9
|
+
* EQUIVALENT to `--flag value` on every command.
|
|
10
|
+
*
|
|
11
|
+
* `main()` runs this over the full argv BEFORE extractGlobalOptions, the
|
|
12
|
+
* strict-flag gate, and every handler's parse, so all downstream token
|
|
13
|
+
* walks (parseArgs, findUnknownStrictFlag, isCommandHelpInvocation,
|
|
14
|
+
* collectLongFlagValues, isDryRunBatchInvocation) observe space-form
|
|
15
|
+
* tokens only. parseArchiveArgs applies it directly because it is
|
|
16
|
+
* exported and callable with raw argv (the tests do).
|
|
17
|
+
*
|
|
18
|
+
* Semantics (deliberate rulings):
|
|
19
|
+
* - Splits on the FIRST '=' only, and only in `--`-prefixed tokens
|
|
20
|
+
* with a non-empty key: `--header=K:V=W` → `--header` `K:V=W` (a
|
|
21
|
+
* value's internal '='s are never split); `--=x` and bare `--` pass
|
|
22
|
+
* through untouched (a `=` at index 2 means an empty key).
|
|
23
|
+
* - `--flag=` → `--flag` `` — parseArgs treats the empty follower as
|
|
24
|
+
* no value, so the equals form with an empty value is the VALUELESS
|
|
25
|
+
* flag, exactly like the space form `--flag ""`.
|
|
26
|
+
* - `--no-cache=1` → `--no-cache` `1`: the no-branch consumes nothing,
|
|
27
|
+
* so `1` becomes a positional — identical to the space form.
|
|
28
|
+
* - Short flags (`-O=json`) and non-flag tokens (`a=b`) are untouched:
|
|
29
|
+
* the contract is the long-flag equals form ≡ space form, nothing
|
|
30
|
+
* more. Under SCOUTLINE_STRICT_FLAGS a `-O=json` token still rejects
|
|
31
|
+
* as unknown, same as before.
|
|
32
|
+
*/
|
|
33
|
+
export declare function normalizeEqualsFormFlags(args: readonly string[]): string[];
|
|
34
|
+
//# sourceMappingURL=equals-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equals-form.d.ts","sourceRoot":"","sources":["../../src/lib/equals-form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAe1E"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central `--flag=value` normalization (#263).
|
|
3
|
+
*
|
|
4
|
+
* `parseArgs` (index.ts) has no equals-form handling: a `--flag=value`
|
|
5
|
+
* token landed as a boolean flag under a garbage key (`flags["flag=value"]`)
|
|
6
|
+
* and was silently dropped — the accept-and-drop class, but at the parser
|
|
7
|
+
* layer. Two commands (archive, investigate) guarded locally with
|
|
8
|
+
* per-command rejections; this seam replaces both: `--flag=value` is
|
|
9
|
+
* EQUIVALENT to `--flag value` on every command.
|
|
10
|
+
*
|
|
11
|
+
* `main()` runs this over the full argv BEFORE extractGlobalOptions, the
|
|
12
|
+
* strict-flag gate, and every handler's parse, so all downstream token
|
|
13
|
+
* walks (parseArgs, findUnknownStrictFlag, isCommandHelpInvocation,
|
|
14
|
+
* collectLongFlagValues, isDryRunBatchInvocation) observe space-form
|
|
15
|
+
* tokens only. parseArchiveArgs applies it directly because it is
|
|
16
|
+
* exported and callable with raw argv (the tests do).
|
|
17
|
+
*
|
|
18
|
+
* Semantics (deliberate rulings):
|
|
19
|
+
* - Splits on the FIRST '=' only, and only in `--`-prefixed tokens
|
|
20
|
+
* with a non-empty key: `--header=K:V=W` → `--header` `K:V=W` (a
|
|
21
|
+
* value's internal '='s are never split); `--=x` and bare `--` pass
|
|
22
|
+
* through untouched (a `=` at index 2 means an empty key).
|
|
23
|
+
* - `--flag=` → `--flag` `` — parseArgs treats the empty follower as
|
|
24
|
+
* no value, so the equals form with an empty value is the VALUELESS
|
|
25
|
+
* flag, exactly like the space form `--flag ""`.
|
|
26
|
+
* - `--no-cache=1` → `--no-cache` `1`: the no-branch consumes nothing,
|
|
27
|
+
* so `1` becomes a positional — identical to the space form.
|
|
28
|
+
* - Short flags (`-O=json`) and non-flag tokens (`a=b`) are untouched:
|
|
29
|
+
* the contract is the long-flag equals form ≡ space form, nothing
|
|
30
|
+
* more. Under SCOUTLINE_STRICT_FLAGS a `-O=json` token still rejects
|
|
31
|
+
* as unknown, same as before.
|
|
32
|
+
*/
|
|
33
|
+
export function normalizeEqualsFormFlags(args) {
|
|
34
|
+
const out = [];
|
|
35
|
+
for (const arg of args) {
|
|
36
|
+
if (arg.startsWith("--")) {
|
|
37
|
+
const eq = arg.indexOf("=");
|
|
38
|
+
// eq > 2 ⇒ non-empty key between "--" and "=" (also excludes the
|
|
39
|
+
// -1 no-equals case and the `--=` empty-key case).
|
|
40
|
+
if (eq > 2) {
|
|
41
|
+
out.push(arg.slice(0, eq), arg.slice(eq + 1));
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
out.push(arg);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=equals-form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equals-form.js","sourceRoot":"","sources":["../../src/lib/equals-form.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAuB;IAC9D,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC5B,iEAAiE;YACjE,mDAAmD;YACnD,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;gBACX,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC9C,SAAS;YACX,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic claim splitting + claim↔evidence matching for
|
|
3
|
+
* `investigate --verify` (investigate-verify lane, Ticket T1; DESIGN
|
|
4
|
+
* D2, PRD AC-2/AC-4/AC-5).
|
|
5
|
+
*
|
|
6
|
+
* splitClaims: the extract grammar's terminator rules — the SHARED
|
|
7
|
+
* splitWindows seam (lib/investigate-extract.ts, issue #276): `[.!?]`
|
|
8
|
+
* followed by a space (or end of input), the unconditional
|
|
9
|
+
* ideographic set 。!?, or a newline; the terminator char belongs
|
|
10
|
+
* to the window, the separator run (spaces/tabs) to neither. The
|
|
11
|
+
* splitter is PURE: the ≤ 8 claim cap is the CALLER's fail-loud
|
|
12
|
+
* validation (commands/investigate.ts, T3) — a 9-sentence statement
|
|
13
|
+
* returns 9 claims here, never a throw, never a truncation.
|
|
14
|
+
*
|
|
15
|
+
* matchClaimsToEvidence: zero-model, deterministic. Per claim —
|
|
16
|
+
* terms = normalizeTerms over the claim's stopword-filtered tokens
|
|
17
|
+
* (reused from lib/investigate-extract.ts, imports only); a passage
|
|
18
|
+
* matches when any term appears whole-word case-folded in
|
|
19
|
+
* passage.quote; the negation-cue scan runs over MATCHING passages
|
|
20
|
+
* only; evidence pointers land in first-encounter order (source
|
|
21
|
+
* order, then passage order); negationCues counts cue-bearing
|
|
22
|
+
* matching passages.
|
|
23
|
+
*
|
|
24
|
+
* Byte-stable: no clocks, no randomness, no locale-dependent casing
|
|
25
|
+
* beyond toLowerCase.
|
|
26
|
+
*/
|
|
27
|
+
import type { EvidenceSource } from "../capabilities/investigation.js";
|
|
28
|
+
/**
|
|
29
|
+
* The verify-mode claim cap (PRD AC-1: > 8 sentence-claims is a
|
|
30
|
+
* fail-loud VALIDATION_ERROR, the R1 pipe-cap precedent — fail, never
|
|
31
|
+
* truncate). Exported so the command's error message names the cap
|
|
32
|
+
* from the single source of truth.
|
|
33
|
+
*/
|
|
34
|
+
export declare const MAX_VERIFY_CLAIMS = 8;
|
|
35
|
+
/**
|
|
36
|
+
* Split a statement into sentence-claims: extract-grammar windows,
|
|
37
|
+
* whitespace-only sentences dropped, quotes trimmed. Deterministic —
|
|
38
|
+
* the same statement yields the identical claim array byte-stably.
|
|
39
|
+
* `|` needs no handling: claims split on sentences, never pipes.
|
|
40
|
+
*/
|
|
41
|
+
export declare function splitClaims(statement: string): string[];
|
|
42
|
+
/**
|
|
43
|
+
* The negation-cue list behind `contradicted`. FROZEN and versioned:
|
|
44
|
+
* additions change verdicts and are release-visible (the parent-owned
|
|
45
|
+
* CHANGELOG bullet names them). Every cue is a LITERAL whole-word
|
|
46
|
+
* string (fix-round m1: the parenthesized inflection grammar is gone —
|
|
47
|
+
* variants spell out; a missing-absence family covers "without",
|
|
48
|
+
* "lacks", "untrue", "false", "absent", "rarely", "seldom").
|
|
49
|
+
*
|
|
50
|
+
* DISCLOSED as hint-grade: `contradicted` means "a term-matching
|
|
51
|
+
* passage carries a negation cue", NOT semantic contradiction —
|
|
52
|
+
* semantic judgment stays with the calling agent (agent-synthesis
|
|
53
|
+
* contract); the per-claim cue count exists for exactly that
|
|
54
|
+
* re-judgment.
|
|
55
|
+
*/
|
|
56
|
+
export declare const NEGATION_CUES: readonly string[];
|
|
57
|
+
/** The deterministic verdict vocabulary (PRD AC-5). */
|
|
58
|
+
export type ClaimVerdict = "corroborated" | "contradicted" | "unresolved";
|
|
59
|
+
/** One evidence pointer into the pack's own sources array. */
|
|
60
|
+
export interface ClaimEvidencePointer {
|
|
61
|
+
readonly sourceIndex: number;
|
|
62
|
+
readonly passageIndex: number;
|
|
63
|
+
}
|
|
64
|
+
/** One claim row: text, verdict, cue count, evidence pointers. */
|
|
65
|
+
export interface ClaimRow {
|
|
66
|
+
readonly text: string;
|
|
67
|
+
readonly verdict: ClaimVerdict;
|
|
68
|
+
/** Number of cue-bearing MATCHING passages (agent re-judgment input). */
|
|
69
|
+
readonly negationCues: number;
|
|
70
|
+
readonly evidence: readonly ClaimEvidencePointer[];
|
|
71
|
+
}
|
|
72
|
+
/** The additive verify block (PRD AC-6): statement + per-claim rows. */
|
|
73
|
+
export interface VerifyBlock {
|
|
74
|
+
readonly statement: string;
|
|
75
|
+
readonly claims: readonly ClaimRow[];
|
|
76
|
+
}
|
|
77
|
+
export interface MatchClaimsArgs {
|
|
78
|
+
readonly statement: string;
|
|
79
|
+
readonly claims: readonly string[];
|
|
80
|
+
readonly sources: readonly EvidenceSource[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Claim terms: lowercase tokens via the shared Unicode tokenizer
|
|
84
|
+
* (issue #271, apostrophe grammar — ASCII behavior byte-identical),
|
|
85
|
+
* stopword-filtered, normalizeTerms-dedupe.
|
|
86
|
+
*/
|
|
87
|
+
/** Exported for the #271 term-derivation pin (pure; test-observable). */
|
|
88
|
+
export declare function claimTerms(claim: string): string[];
|
|
89
|
+
/**
|
|
90
|
+
* Match claims to evidence: per claim, every (source, passage) whose
|
|
91
|
+
* quote contains ≥ 1 claim term whole-word case-folded becomes an
|
|
92
|
+
* evidence pointer in first-encounter order; the cue scan runs over
|
|
93
|
+
* matching passages only; the verdict follows PRD-5 (corroborated =
|
|
94
|
+
* matches + 0 cues; contradicted = ≥ 1 cue-bearing match; unresolved
|
|
95
|
+
* = no matches).
|
|
96
|
+
*/
|
|
97
|
+
export declare function matchClaimsToEvidence({ statement, claims, sources }: MatchClaimsArgs): VerifyBlock;
|
|
98
|
+
//# sourceMappingURL=investigate-claims.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"investigate-claims.d.ts","sourceRoot":"","sources":["../../src/lib/investigate-claims.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAQvE;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAMnC;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CASvD;AAMD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAgCzC,CAAC;AAQH,uDAAuD;AACvD,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,cAAc,GAAG,YAAY,CAAC;AAE1E,8DAA8D;AAC9D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,kEAAkE;AAClE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACpD;AAED,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;CAC7C;AAwBD;;;;GAIG;AACH,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAGlD;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,eAAe,GAAG,WAAW,CAqBlG"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic claim splitting + claim↔evidence matching for
|
|
3
|
+
* `investigate --verify` (investigate-verify lane, Ticket T1; DESIGN
|
|
4
|
+
* D2, PRD AC-2/AC-4/AC-5).
|
|
5
|
+
*
|
|
6
|
+
* splitClaims: the extract grammar's terminator rules — the SHARED
|
|
7
|
+
* splitWindows seam (lib/investigate-extract.ts, issue #276): `[.!?]`
|
|
8
|
+
* followed by a space (or end of input), the unconditional
|
|
9
|
+
* ideographic set 。!?, or a newline; the terminator char belongs
|
|
10
|
+
* to the window, the separator run (spaces/tabs) to neither. The
|
|
11
|
+
* splitter is PURE: the ≤ 8 claim cap is the CALLER's fail-loud
|
|
12
|
+
* validation (commands/investigate.ts, T3) — a 9-sentence statement
|
|
13
|
+
* returns 9 claims here, never a throw, never a truncation.
|
|
14
|
+
*
|
|
15
|
+
* matchClaimsToEvidence: zero-model, deterministic. Per claim —
|
|
16
|
+
* terms = normalizeTerms over the claim's stopword-filtered tokens
|
|
17
|
+
* (reused from lib/investigate-extract.ts, imports only); a passage
|
|
18
|
+
* matches when any term appears whole-word case-folded in
|
|
19
|
+
* passage.quote; the negation-cue scan runs over MATCHING passages
|
|
20
|
+
* only; evidence pointers land in first-encounter order (source
|
|
21
|
+
* order, then passage order); negationCues counts cue-bearing
|
|
22
|
+
* matching passages.
|
|
23
|
+
*
|
|
24
|
+
* Byte-stable: no clocks, no randomness, no locale-dependent casing
|
|
25
|
+
* beyond toLowerCase.
|
|
26
|
+
*/
|
|
27
|
+
import { STOPWORDS, tokenizeTerms } from "./context-file.js";
|
|
28
|
+
import { normalizeTerms, splitWindows } from "./investigate-extract.js";
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Claim splitting (extract-grammar terminators)
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
const STOPWORD_SET = new Set(STOPWORDS);
|
|
33
|
+
/**
|
|
34
|
+
* The verify-mode claim cap (PRD AC-1: > 8 sentence-claims is a
|
|
35
|
+
* fail-loud VALIDATION_ERROR, the R1 pipe-cap precedent — fail, never
|
|
36
|
+
* truncate). Exported so the command's error message names the cap
|
|
37
|
+
* from the single source of truth.
|
|
38
|
+
*/
|
|
39
|
+
export const MAX_VERIFY_CLAIMS = 8;
|
|
40
|
+
// splitWindows and its Window shape live in lib/investigate-extract.ts
|
|
41
|
+
// (issue #276: the terminator grammar is ONE shared seam — the ideographic
|
|
42
|
+
// set extends both extract and claims from the single definition).
|
|
43
|
+
/**
|
|
44
|
+
* Split a statement into sentence-claims: extract-grammar windows,
|
|
45
|
+
* whitespace-only sentences dropped, quotes trimmed. Deterministic —
|
|
46
|
+
* the same statement yields the identical claim array byte-stably.
|
|
47
|
+
* `|` needs no handling: claims split on sentences, never pipes.
|
|
48
|
+
*/
|
|
49
|
+
export function splitClaims(statement) {
|
|
50
|
+
const claims = [];
|
|
51
|
+
for (const window of splitWindows(statement)) {
|
|
52
|
+
const claim = statement.slice(window.start, window.end).trim();
|
|
53
|
+
if (claim.length > 0) {
|
|
54
|
+
claims.push(claim);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return claims;
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Negation cues (frozen, versioned contract — PRD AC-5)
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
/**
|
|
63
|
+
* The negation-cue list behind `contradicted`. FROZEN and versioned:
|
|
64
|
+
* additions change verdicts and are release-visible (the parent-owned
|
|
65
|
+
* CHANGELOG bullet names them). Every cue is a LITERAL whole-word
|
|
66
|
+
* string (fix-round m1: the parenthesized inflection grammar is gone —
|
|
67
|
+
* variants spell out; a missing-absence family covers "without",
|
|
68
|
+
* "lacks", "untrue", "false", "absent", "rarely", "seldom").
|
|
69
|
+
*
|
|
70
|
+
* DISCLOSED as hint-grade: `contradicted` means "a term-matching
|
|
71
|
+
* passage carries a negation cue", NOT semantic contradiction —
|
|
72
|
+
* semantic judgment stays with the calling agent (agent-synthesis
|
|
73
|
+
* contract); the per-claim cue count exists for exactly that
|
|
74
|
+
* re-judgment.
|
|
75
|
+
*/
|
|
76
|
+
export const NEGATION_CUES = Object.freeze([
|
|
77
|
+
"not",
|
|
78
|
+
"no",
|
|
79
|
+
"never",
|
|
80
|
+
"none",
|
|
81
|
+
"cannot",
|
|
82
|
+
"can't",
|
|
83
|
+
"isn't",
|
|
84
|
+
"aren't",
|
|
85
|
+
"wasn't",
|
|
86
|
+
"weren't",
|
|
87
|
+
"doesn't",
|
|
88
|
+
"don't",
|
|
89
|
+
"didn't",
|
|
90
|
+
"won't",
|
|
91
|
+
"wouldn't",
|
|
92
|
+
"fail to",
|
|
93
|
+
"fails to",
|
|
94
|
+
"failed to",
|
|
95
|
+
"denies",
|
|
96
|
+
"denied",
|
|
97
|
+
"refutes",
|
|
98
|
+
"refuted",
|
|
99
|
+
"disputes",
|
|
100
|
+
"disputed",
|
|
101
|
+
"without",
|
|
102
|
+
"lacks",
|
|
103
|
+
"untrue",
|
|
104
|
+
"false",
|
|
105
|
+
"absent",
|
|
106
|
+
"rarely",
|
|
107
|
+
"seldom",
|
|
108
|
+
]);
|
|
109
|
+
const CUE_LITERALS = NEGATION_CUES;
|
|
110
|
+
function escapeRegExp(s) {
|
|
111
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Whole-word containment. ASCII terms keep the boundary guard
|
|
115
|
+
* (`[^\p{L}\p{N}_]` on both sides). Non-ASCII terms match as
|
|
116
|
+
* substrings: unspaced scripts (CJK) have no word separators, so the
|
|
117
|
+
* boundary class can never fire between letters (issue #271).
|
|
118
|
+
*/
|
|
119
|
+
function containsWholeWord(content, term) {
|
|
120
|
+
const asciiTerm = /^[\x00-\x7f]*$/.test(term);
|
|
121
|
+
const body = escapeRegExp(term);
|
|
122
|
+
const re = new RegExp(asciiTerm
|
|
123
|
+
? `(^|[^\\p{L}\\p{N}_])${body}(?:[^\\p{L}\\p{N}_]|$)`
|
|
124
|
+
: body, "iu");
|
|
125
|
+
return re.test(content);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Claim terms: lowercase tokens via the shared Unicode tokenizer
|
|
129
|
+
* (issue #271, apostrophe grammar — ASCII behavior byte-identical),
|
|
130
|
+
* stopword-filtered, normalizeTerms-dedupe.
|
|
131
|
+
*/
|
|
132
|
+
/** Exported for the #271 term-derivation pin (pure; test-observable). */
|
|
133
|
+
export function claimTerms(claim) {
|
|
134
|
+
const tokens = tokenizeTerms(claim, true).filter((t) => !STOPWORD_SET.has(t));
|
|
135
|
+
return normalizeTerms(tokens);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Match claims to evidence: per claim, every (source, passage) whose
|
|
139
|
+
* quote contains ≥ 1 claim term whole-word case-folded becomes an
|
|
140
|
+
* evidence pointer in first-encounter order; the cue scan runs over
|
|
141
|
+
* matching passages only; the verdict follows PRD-5 (corroborated =
|
|
142
|
+
* matches + 0 cues; contradicted = ≥ 1 cue-bearing match; unresolved
|
|
143
|
+
* = no matches).
|
|
144
|
+
*/
|
|
145
|
+
export function matchClaimsToEvidence({ statement, claims, sources }) {
|
|
146
|
+
const rows = claims.map((text) => {
|
|
147
|
+
const terms = claimTerms(text);
|
|
148
|
+
const evidence = [];
|
|
149
|
+
let cueBearers = 0;
|
|
150
|
+
sources.forEach((source, sourceIndex) => {
|
|
151
|
+
source.passages.forEach((passage, passageIndex) => {
|
|
152
|
+
const matched = terms.some((term) => containsWholeWord(passage.quote, term));
|
|
153
|
+
if (!matched)
|
|
154
|
+
return;
|
|
155
|
+
evidence.push({ sourceIndex, passageIndex });
|
|
156
|
+
const carriesCue = CUE_LITERALS.some((cue) => containsWholeWord(passage.quote.toLowerCase(), cue));
|
|
157
|
+
if (carriesCue)
|
|
158
|
+
cueBearers += 1;
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
const verdict = evidence.length === 0 ? "unresolved" : cueBearers > 0 ? "contradicted" : "corroborated";
|
|
162
|
+
return { text, verdict, negationCues: cueBearers, evidence };
|
|
163
|
+
});
|
|
164
|
+
return { statement, claims: rows };
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=investigate-claims.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"investigate-claims.js","sourceRoot":"","sources":["../../src/lib/investigate-claims.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic passage extraction for the investigate pipeline
|
|
3
|
+
* (T3, docs/plans/investigate-pipeline DESIGN D4, PRD AC-5).
|
|
4
|
+
*
|
|
5
|
+
* Splits content into sentence windows with character-index tracking,
|
|
6
|
+
* keeps the windows containing >= 1 term as a whole word (case-folded),
|
|
7
|
+
* dedupes by exact quote equality, caps at 5 first-encounter passages.
|
|
8
|
+
*
|
|
9
|
+
* Boundary-char ownership: the terminator that ended a window
|
|
10
|
+
* (`.`/`!`/`?`/`\n`) belongs to the window; the separator run
|
|
11
|
+
* (spaces/tabs after a terminator) belongs to neither window. The
|
|
12
|
+
* round-trip pin — content.slice(...charRange) === quote for every
|
|
13
|
+
* passage — holds byte-exactly under this rule, and is invariant to
|
|
14
|
+
* it (any slicing convention preserves the pin).
|
|
15
|
+
*
|
|
16
|
+
* Byte-stable: no clocks, no randomness, no locale-dependent casing
|
|
17
|
+
* beyond toLowerCase. Self-contained: no imports.
|
|
18
|
+
*/
|
|
19
|
+
export interface Passage {
|
|
20
|
+
quote: string;
|
|
21
|
+
charRange: [number, number];
|
|
22
|
+
}
|
|
23
|
+
export interface ExtractPassagesArgs {
|
|
24
|
+
content: string;
|
|
25
|
+
terms: string[];
|
|
26
|
+
}
|
|
27
|
+
/** Normalize the term set: trim, case-fold, drop empties, dedupe. */
|
|
28
|
+
export declare function normalizeTerms(terms: string[]): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Ideographic sentence terminators (issue #276): the ideographic full
|
|
31
|
+
* stop 。 (U+3002) and the fullwidth !?. They terminate UNCONDITIONALLY
|
|
32
|
+
* — no space lookahead — because unspaced scripts never satisfy the
|
|
33
|
+
* ASCII rule's lookahead. Clause commas (,、) are deliberately NOT
|
|
34
|
+
* terminators: they separate clauses inside a sentence, not sentences.
|
|
35
|
+
* Exported: investigate-claims.ts's splitClaims shares this grammar.
|
|
36
|
+
*/
|
|
37
|
+
export declare const IDEOGRAPHIC_TERMINATORS: Set<string>;
|
|
38
|
+
/** A window is [start, end) with the terminator char owned by the window. */
|
|
39
|
+
export interface Window {
|
|
40
|
+
start: number;
|
|
41
|
+
end: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Split content into sentence windows on `[.!?]` terminators followed
|
|
45
|
+
* by a space (the literal `[.!?] +` grammar), the unconditional
|
|
46
|
+
* ideographic set (issue #276, see {@link IDEOGRAPHIC_TERMINATORS}),
|
|
47
|
+
* plus newline boundaries, tracking exact offsets into the original
|
|
48
|
+
* content. Newlines terminate but never separate: "here.\n" ends at
|
|
49
|
+
* the `\n`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function splitWindows(content: string): Window[];
|
|
52
|
+
/**
|
|
53
|
+
* Extract passages: sentence windows of `content` containing >= 1 of
|
|
54
|
+
* `terms` as a whole word (case-folded), deduped by exact quote,
|
|
55
|
+
* capped at 5 first-encounter. Empty term set -> [] (valid).
|
|
56
|
+
*/
|
|
57
|
+
export declare function extractPassages({ content, terms }: ExtractPassagesArgs): Passage[];
|
|
58
|
+
//# sourceMappingURL=investigate-extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"investigate-extract.d.ts","sourceRoot":"","sources":["../../src/lib/investigate-extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAID,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CASxD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,aAA2B,CAAC;AAEhE,6EAA6E;AAC7E,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoCtD;AAwBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,mBAAmB,GAAG,OAAO,EAAE,CAqBlF"}
|