@ai-matrx/content-ir 0.18.5 → 0.18.6
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/CHANGELOG.md +58 -3
- package/README.md +3 -1
- package/dist/index.cjs +50 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +50 -14
- package/dist/index.js.map +1 -1
- package/dist/source.cjs +50 -14
- package/dist/source.cjs.map +1 -1
- package/dist/source.js +50 -14
- package/dist/source.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,18 +1,72 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.18.
|
|
3
|
+
## 0.18.6
|
|
4
4
|
|
|
5
5
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
-
`git diff npm/content-ir-core/v0.18.
|
|
6
|
+
`git diff npm/content-ir-core/v0.18.5..npm/content-ir-core/v0.18.6 -- apps/shared/content-ir-core`).
|
|
7
7
|
No source changes intended and no consumer action required.
|
|
8
8
|
|
|
9
|
+
## 0.19.0
|
|
10
|
+
|
|
11
|
+
**Carries: RC-B3 fix round (verify-RC-B3 § 0.18.3) and RC-B3r R3 — builder:
|
|
12
|
+
the RC-B3 standard lane.** (aidream 1174edb640 — RC-B10, the print lane —
|
|
13
|
+
shipped in 0.18.3, and 094594d3a1 — the escaped-bracket rule, "Unreleased"
|
|
14
|
+
below — shipped in 0.18.4; both under generic "no source changes" notes.)
|
|
15
|
+
|
|
16
|
+
**`/source` streaming: settled means settled** (F3/F4). Found with the
|
|
17
|
+
verifier's generator (realistic model fragments, every prefix, with and
|
|
18
|
+
without a final newline), now permanent in `__tests__/source-attack.test.ts`
|
|
19
|
+
(`LLM-fragment documents…`; 12,000 documents in `SOURCE_ATTACK=long`) plus 27
|
|
20
|
+
pinned reproducers. `tokenizeSource(prefix, { streaming: true })` now also
|
|
21
|
+
holds back, as prose or as an open island:
|
|
22
|
+
- lines a box-drawing tree still forming at the end may claim as its root
|
|
23
|
+
label (the renderer's walk-back), the open last line included;
|
|
24
|
+
- a paragraph cut short by a block that may still dissolve (a `$$` pair
|
|
25
|
+
closing on the open line, an unbalanced JSON head, any opener still
|
|
26
|
+
arriving on the open line) — and a footnote before one;
|
|
27
|
+
- everything inline on the open last line, and a block island ending there;
|
|
28
|
+
- a nested-fence closer found only by the strict-CommonMark retry, a tilde
|
|
29
|
+
fence whose inner block may still grow past it, braces that balance on
|
|
30
|
+
the open last line;
|
|
31
|
+
- a code span that a blank-so-far or `>`-only open line may still close
|
|
32
|
+
(`pendingCodeSpanStart`, `source/code-ranges.ts`).
|
|
33
|
+
The two lone-HTML-tag holdbacks (M-N6/N7) collapsed into the open-tail block
|
|
34
|
+
rule. Each holdback turns the attack suite red on its own when removed
|
|
35
|
+
(planted mutations on a scratch copy). The H2 exception is unchanged.
|
|
36
|
+
|
|
37
|
+
**`/source` one-shot: a mid-line reasoning mention that never closes is prose**
|
|
38
|
+
(RC-B3r R3). `grep -c '<thinking>' log.txt > count.txt` no longer opens an
|
|
39
|
+
`xml_region` to the end of the text (the renderer shows prose). While a stream
|
|
40
|
+
is still arriving it stays an open region (its closer may yet come).
|
|
41
|
+
|
|
42
|
+
**`isSingleDollarMath` refuses shell and template variable chains** (F5):
|
|
43
|
+
`$USER$HOSTNAME`, `A=$A$B`, `df$col$sub`, `$name.$ext`, `PS1='$USER@$HOST'`,
|
|
44
|
+
`${a}${b}` stay text; `$n$th`, `$x_i$s` stay math. Measured read-only with
|
|
45
|
+
matrx-frontend `scripts/measure-single-dollar-rule.ts` over 85,325 assistant
|
|
46
|
+
messages and 4,317 notes: 0 spans gained, 3 lost (2 shell-variable-chain, 1
|
|
47
|
+
template-literal), each an intended false positive; notes unchanged. New
|
|
48
|
+
export `singleDollarAfter(text, close)` — the `after` argument the rule now
|
|
49
|
+
reads (the following name, `\n` marking the end of text). Shared vectors grew
|
|
50
|
+
(`__tests__/fixtures/single-dollar-vectors.json`, including the trailing-space
|
|
51
|
+
guard case `echo $HOME $PATH`).
|
|
52
|
+
- Consumer action: callers of `isSingleDollarMath` pass
|
|
53
|
+
`singleDollarAfter(text, close)` instead of `text[close + 1]` (a one-character
|
|
54
|
+
`after` still works; it just cannot see a variable chain).
|
|
55
|
+
|
|
56
|
+
## 0.18.5
|
|
57
|
+
|
|
58
|
+
Automatic republish. Despite the generated note, this version DID carry source
|
|
59
|
+
changes: the first half of the 0.19.0 work above (aidream edb3ec222d streaming
|
|
60
|
+
holds, 3a1dae805c + 9a6c8db0b2 variable-chain guard, 60d3f61803
|
|
61
|
+
`singleDollarAfter`). 0.19.0 supersedes it.
|
|
62
|
+
|
|
9
63
|
## 0.18.4
|
|
10
64
|
|
|
11
65
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
12
66
|
`git diff npm/content-ir-core/v0.18.3..npm/content-ir-core/v0.18.4 -- apps/shared/content-ir-core`).
|
|
13
67
|
No source changes intended and no consumer action required.
|
|
14
68
|
|
|
15
|
-
##
|
|
69
|
+
## Shipped in 0.18.4 (listed here before the release)
|
|
16
70
|
|
|
17
71
|
**`/source`: THE escaped-bracket rule** (verify-RC-B4 R3-2). `\[ … \]` is a
|
|
18
72
|
display-math island only when its content is real TeX — a command, `^ { } =
|
|
@@ -897,3 +951,4 @@ unchanged. Two things are worth doing at your next working session:
|
|
|
897
951
|
- Promoted the existing verified Content IR twin into an independently installable public package.
|
|
898
952
|
- Added ESM and declaration builds, package linting, packed-artifact analysis, and an isolated consumer canary.
|
|
899
953
|
- Preserved all parser, session, normalization, schema conversion, and structural-validation behavior with the existing shared fixtures and fingerprint vectors.
|
|
954
|
+
|
package/README.md
CHANGED
|
@@ -48,7 +48,9 @@ The package has no browser, React runtime, application store, database client, r
|
|
|
48
48
|
`tokenizeSource(text)` reads stored text; `tokenizeSource(prefix, { streaming: true })`
|
|
49
49
|
reads a message still arriving. In streaming mode anything the next bytes could
|
|
50
50
|
still change is held back as plain prose (an open last line, an unclosed code
|
|
51
|
-
span, a `$$` that can still pair, a footnote whose continuation is undecided,
|
|
51
|
+
span, a `$$` that can still pair, a footnote whose continuation is undecided,
|
|
52
|
+
lines a box-drawing tree still forming below may claim as its root label, a
|
|
53
|
+
paragraph cut short by a block that may still dissolve, …),
|
|
52
54
|
so **an island reported `complete` is the island the finished text has** — with
|
|
53
55
|
ONE documented exception:
|
|
54
56
|
|
package/dist/index.cjs
CHANGED
|
@@ -6214,10 +6214,13 @@ var Tokenizer = class {
|
|
|
6214
6214
|
/**
|
|
6215
6215
|
* Streaming: an open block that may still turn back into prose — a `$$`
|
|
6216
6216
|
* pair whose closer is on the open last line (prose after it makes it
|
|
6217
|
-
* inline),
|
|
6217
|
+
* inline), a JSON head whose braces have not balanced (it may never parse),
|
|
6218
|
+
* or any opener that is itself still arriving on the open last line.
|
|
6218
6219
|
*/
|
|
6219
6220
|
mayDissolve(block) {
|
|
6220
|
-
|
|
6221
|
+
if (!this.streaming || block.complete) return false;
|
|
6222
|
+
if (block.type === "math_block" || block.type === "json") return true;
|
|
6223
|
+
return this.isOpenTail(this.lineOf(block.start));
|
|
6221
6224
|
}
|
|
6222
6225
|
/** Streaming: paragraph ends where an undecided, dissolvable block cut them short. */
|
|
6223
6226
|
undecidedBreaks = /* @__PURE__ */ new Set();
|
|
@@ -6238,6 +6241,12 @@ var Tokenizer = class {
|
|
|
6238
6241
|
}
|
|
6239
6242
|
return lo;
|
|
6240
6243
|
}
|
|
6244
|
+
/** How many whitespace characters open the text at `from` (up to `to`). */
|
|
6245
|
+
leadingSpace(from, to) {
|
|
6246
|
+
let k = from;
|
|
6247
|
+
while (k < to && /\s/.test(this.text[k])) k++;
|
|
6248
|
+
return k - from;
|
|
6249
|
+
}
|
|
6241
6250
|
isBlank(from, to) {
|
|
6242
6251
|
return !NOT_WHITESPACE.test(this.text.slice(from, to));
|
|
6243
6252
|
}
|
|
@@ -6262,6 +6271,10 @@ var Tokenizer = class {
|
|
|
6262
6271
|
break;
|
|
6263
6272
|
}
|
|
6264
6273
|
const island = this.detectBlock(pos, li, true);
|
|
6274
|
+
if (island && pos + this.leadingSpace(pos, this.contentEnds[li]) >= this.provisionalFrom) {
|
|
6275
|
+
this.push({ kind: "prose", start: pos, end: this.n, island: null, inlines: [] });
|
|
6276
|
+
break;
|
|
6277
|
+
}
|
|
6265
6278
|
if (island) {
|
|
6266
6279
|
this.push({ kind: "island", start: island.start, end: island.end, island, inlines: [] });
|
|
6267
6280
|
pos = island.end;
|
|
@@ -6322,36 +6335,55 @@ var Tokenizer = class {
|
|
|
6322
6335
|
* region…) is never a tree line nor a root label, so it stops the walk.
|
|
6323
6336
|
*/
|
|
6324
6337
|
treeRootHoldFrom() {
|
|
6325
|
-
const
|
|
6338
|
+
const claimFrom = (k2) => {
|
|
6339
|
+
const lineStart = this.lineStarts[k2];
|
|
6340
|
+
const lineEnd = this.contentEnds[k2];
|
|
6341
|
+
let pos = lineStart;
|
|
6326
6342
|
for (; ; ) {
|
|
6327
|
-
const block = this.blockAt(
|
|
6328
|
-
if (!block || block.kind !== "island" || block.island
|
|
6329
|
-
|
|
6330
|
-
if (
|
|
6331
|
-
|
|
6343
|
+
const block = this.blockAt(pos);
|
|
6344
|
+
if (!block || block.kind !== "island" || !block.island) return pos;
|
|
6345
|
+
if (block.island.fromParagraph === true || this.mayDissolve(block.island)) return pos;
|
|
6346
|
+
if (block.start < lineStart) {
|
|
6347
|
+
const opened = this.lineOf(block.start);
|
|
6348
|
+
if (this.lineStarts[opened] !== block.start && claimFrom(opened) !== -1) return pos;
|
|
6349
|
+
if (block.end >= lineEnd) return -1;
|
|
6350
|
+
pos = block.end;
|
|
6351
|
+
continue;
|
|
6352
|
+
}
|
|
6353
|
+
if (block.end >= lineEnd) return -1;
|
|
6354
|
+
pos = block.end;
|
|
6332
6355
|
}
|
|
6333
6356
|
};
|
|
6334
6357
|
let k = this.lineCount - 1;
|
|
6335
6358
|
let start = this.lineCount;
|
|
6359
|
+
let startPos = this.n;
|
|
6336
6360
|
if (k >= 0 && this.isOpenTail(k)) {
|
|
6337
|
-
|
|
6361
|
+
const at = claimFrom(k);
|
|
6362
|
+
if (at === -1) return this.n;
|
|
6338
6363
|
start = k;
|
|
6364
|
+
startPos = at;
|
|
6339
6365
|
k--;
|
|
6340
6366
|
}
|
|
6341
|
-
for (; k >= 0
|
|
6367
|
+
for (; k >= 0; k--) {
|
|
6342
6368
|
this.tick(1);
|
|
6369
|
+
const at = claimFrom(k);
|
|
6370
|
+
if (at === -1) break;
|
|
6343
6371
|
if (this.lineIsBlank(k)) continue;
|
|
6344
6372
|
if (!TREE_GLYPHS.test(this.lineText(k))) break;
|
|
6345
6373
|
start = k;
|
|
6374
|
+
startPos = at;
|
|
6346
6375
|
}
|
|
6347
|
-
let
|
|
6348
|
-
for (let j = start - 1; j >= 0
|
|
6376
|
+
let rootPos = startPos;
|
|
6377
|
+
for (let j = start - 1; j >= 0; j--) {
|
|
6378
|
+
const at = claimFrom(j);
|
|
6379
|
+
if (at === -1) break;
|
|
6349
6380
|
const trimmed = this.lineText(j).trim();
|
|
6350
6381
|
this.tick(trimmed.length + 1);
|
|
6351
6382
|
if (!trimmed || isSplitterTreeLine(trimmed) || /^#{1,6}\s/.test(trimmed)) break;
|
|
6352
|
-
|
|
6383
|
+
rootPos = at;
|
|
6384
|
+
if (at > this.lineStarts[j]) break;
|
|
6353
6385
|
}
|
|
6354
|
-
return
|
|
6386
|
+
return rootPos;
|
|
6355
6387
|
}
|
|
6356
6388
|
/** The block (so far) containing offset `pos`, or null. */
|
|
6357
6389
|
blockAt(pos) {
|
|
@@ -7121,6 +7153,10 @@ var Tokenizer = class {
|
|
|
7121
7153
|
const closer = `</${name}>`;
|
|
7122
7154
|
const close = this.next(closer, tagEnd);
|
|
7123
7155
|
const blockType = isAttr ? "xml_attr" : "xml_region";
|
|
7156
|
+
if (close === -1 && isThinking && !this.streaming) {
|
|
7157
|
+
i = tagEnd;
|
|
7158
|
+
continue;
|
|
7159
|
+
}
|
|
7124
7160
|
if (close === -1) return stop(this.island(blockType, i, this.n, false, { tag: name }));
|
|
7125
7161
|
const end = close + closer.length;
|
|
7126
7162
|
if (end > pe) return stop(this.spill(blockType, i, end, pe, { tag: name }));
|