@tangle-network/agent-app 0.44.15 → 0.44.17
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/work-product/index.d.ts +332 -127
- package/dist/work-product/index.js +262 -63
- package/dist/work-product/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -81,8 +81,10 @@ interface WorkProductService {
|
|
|
81
81
|
/** Re-open a `changes_requested` row as the next draft: version bumps +1
|
|
82
82
|
* and the correction turn accumulates into the same scope row. */
|
|
83
83
|
reopen(id: string): Promise<WorkProductOutcome<WorkProductRecord>>;
|
|
84
|
-
/** Merge evidence entries by id
|
|
85
|
-
*
|
|
84
|
+
/** Merge evidence entries by id AND by what they assert (target + source +
|
|
85
|
+
* claim), so re-stating a fact already recorded replaces it under whatever
|
|
86
|
+
* id this batch minted rather than appending a near-copy. Legal only while
|
|
87
|
+
* `draft`/`blocked`. */
|
|
86
88
|
upsertEvidence(id: string, entries: readonly EvidenceEntry[]): Promise<WorkProductOutcome<WorkProductRecord>>;
|
|
87
89
|
/** Merge exception entries by id, then reconcile the blocked flag: any
|
|
88
90
|
* unresolved blocking entry parks `draft`→`blocked`; resolving the last
|
|
@@ -186,6 +188,295 @@ declare function finalizeWorkProductProvenance(store: WorkProductStorePort, inpu
|
|
|
186
188
|
*/
|
|
187
189
|
declare function workProductTrustInputs<D extends string = string>(records: readonly WorkProductRecord[], verdictsFor: (record: WorkProductRecord) => readonly JudgeVerdict<D>[] | undefined): TrustItem<D>[];
|
|
188
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Claim support and target correctness — is this citation attached to the RIGHT
|
|
193
|
+
* place, and does the text it names actually say what the entry claims?
|
|
194
|
+
*
|
|
195
|
+
* Three checks live here, each answering a different half of "is this evidence
|
|
196
|
+
* row honest": {@link verifyClaimSupport} (claim ↔ cited text),
|
|
197
|
+
* {@link verifyTargetLabel} (target ↔ cited line), and
|
|
198
|
+
* {@link verifyArtifactAgreement} (claim ↔ the artifact field it decorates).
|
|
199
|
+
* They share the numeric canonicalization below, which is why they share a
|
|
200
|
+
* file — a second copy of "what counts as the same figure" is how two gates
|
|
201
|
+
* drift into disagreeing about the same row.
|
|
202
|
+
*
|
|
203
|
+
* ── Check one: claim support ────────────────────────────────────────────────
|
|
204
|
+
*
|
|
205
|
+
* The two gates before this one answer different questions. `sourceContainsQuote`
|
|
206
|
+
* asks whether the quote is really in the document; `findSourceLine` /
|
|
207
|
+
* `sliceSourceSpan` make the platform produce the quote so it cannot be typed
|
|
208
|
+
* wrong. Both are about the TEXT's provenance. Neither one looks at `claim`.
|
|
209
|
+
*
|
|
210
|
+
* Production row `7256ef49` is what that gap costs. Four evidence entries, all
|
|
211
|
+
* `quoteBasis:'span'`, every quote a genuine slice of the document it named —
|
|
212
|
+
* and every one landing on the employer/payer line about 200 characters above
|
|
213
|
+
* the figure:
|
|
214
|
+
*
|
|
215
|
+
* claim 128450.00 -> "tics LLC EIN 84-2213907\nEmployee: Dana"
|
|
216
|
+
* claim 812.44 -> "nt Savings Bank TIN 22-5510983\nRecip"
|
|
217
|
+
* claim 2204.18 -> "ndex Fund Trust TIN 47-3320115\nRec"
|
|
218
|
+
* claim 1955.02 -> "pient: Dana R. Whitfield\n------------"
|
|
219
|
+
*
|
|
220
|
+
* That is strictly worse than a fabricated quote. A fabricated quote fails the
|
|
221
|
+
* verbatim gate; this one passes every gate, is real text from the right
|
|
222
|
+
* document, and reads to a reviewer as an authoritative citation while
|
|
223
|
+
* supporting nothing. `locator.find` (the platform locating a value the model
|
|
224
|
+
* names) prevents the model from ADDRESSING the wrong line, and it is the right
|
|
225
|
+
* primary fix. This module is the independent check underneath it: whatever
|
|
226
|
+
* anchoring form produced the text, the text has to contain the figure.
|
|
227
|
+
*
|
|
228
|
+
* That also settles what a raw `locator.span` is worth. Hand-computed offsets
|
|
229
|
+
* stay accepted, but only when they independently verify — which is exactly
|
|
230
|
+
* "the slice contains the claimed value".
|
|
231
|
+
*
|
|
232
|
+
* ── The rule, and why it is drawn here ──────────────────────────────────────
|
|
233
|
+
*
|
|
234
|
+
* Strict on figures, silent on everything else. An unsatisfiable gate does not
|
|
235
|
+
* stop a bad submit, it SELECTS for one — that is the measured mechanism behind
|
|
236
|
+
* the 38 fabricated quotes on row `a68b1943`, where a coverage gate demanded
|
|
237
|
+
* document lineage for computed values and got thirteen invented citations
|
|
238
|
+
* forty seconds later. So the rule fires only where an honest citation can
|
|
239
|
+
* always satisfy it:
|
|
240
|
+
*
|
|
241
|
+
* - The claim IS a value (`"128450.00"`, `"$30,000"`, `"3"`) — the anchored
|
|
242
|
+
* text MUST contain that value. No latitude. This is the shape every tax
|
|
243
|
+
* figure takes and the shape row `7256ef49` failed.
|
|
244
|
+
* - The claim is prose naming figures (`"indemnity capped at $5,000,000"`) —
|
|
245
|
+
* at least one of its currency-shaped figures must occur. Not all of them:
|
|
246
|
+
* a claim may legitimately narrate a computation over several lines while
|
|
247
|
+
* anchoring to the one line under discussion, and refusing that would make
|
|
248
|
+
* an honest citation unrepresentable for the sake of a stricter-sounding
|
|
249
|
+
* rule. One is enough to keep the anchor tethered to the claim's subject.
|
|
250
|
+
* - The claim carries no figure at all (`"Married Filing Jointly"`,
|
|
251
|
+
* `"Dana R. Whitfield"`, `"2025-04-15"`) — nothing to check, and the entry
|
|
252
|
+
* passes. A filing status has no number to find, and inventing a
|
|
253
|
+
* word-overlap score here would re-open the hole the verbatim gate closes.
|
|
254
|
+
* - The entry has no anchored text at all — nothing to check. A computed
|
|
255
|
+
* value cites its computation, not a document.
|
|
256
|
+
*
|
|
257
|
+
* A bare year, a form number and a box number are deliberately NOT figures:
|
|
258
|
+
* `2025`, `1040` and `Box 1` have no thousands separator, no cent pair and no
|
|
259
|
+
* currency symbol, so prose mentioning them does not trip the rule.
|
|
260
|
+
*
|
|
261
|
+
* ── Matching is value-wise, never substring ─────────────────────────────────
|
|
262
|
+
*
|
|
263
|
+
* `text.includes(claim)` would be the obvious implementation and it is wrong in
|
|
264
|
+
* the direction that matters: it passes `"450.00"` against `"128,450.00"`, so a
|
|
265
|
+
* claim citing the wrong figure survives whenever its digits happen to be a tail
|
|
266
|
+
* of a real one. Both sides are tokenized into numbers and compared as VALUES,
|
|
267
|
+
* so `450` and `128450` are simply different.
|
|
268
|
+
*/
|
|
269
|
+
/**
|
|
270
|
+
* Reduce a numeric token to the form both sides are compared in: no currency,
|
|
271
|
+
* no grouping, no trailing zeros in the fraction, no leading zeros.
|
|
272
|
+
*
|
|
273
|
+
* Sign and accounting parentheses are stripped rather than preserved, so
|
|
274
|
+
* `(1,234.00)`, `-1,234.00` and `1,234.00` all reduce to `1234`. A document
|
|
275
|
+
* renders the same deduction all three ways depending on the form and the
|
|
276
|
+
* extractor, and the sign is a property of the TARGET LINE's semantics, not of
|
|
277
|
+
* the document's typography. Comparing magnitudes keeps those honest citations
|
|
278
|
+
* working, and it concedes nothing to fabrication: the digits still have to be
|
|
279
|
+
* the document's digits.
|
|
280
|
+
*
|
|
281
|
+
* Returns `null` for anything that is not a plain number.
|
|
282
|
+
*/
|
|
283
|
+
declare function canonicalizeValue(token: string): string | null;
|
|
284
|
+
/** Every distinct value appearing in `text`, canonicalized. */
|
|
285
|
+
declare function valuesInText(text: string): string[];
|
|
286
|
+
/**
|
|
287
|
+
* The values a claim asserts, canonicalized — empty when the claim asserts no
|
|
288
|
+
* figure, which is the "nothing to check" case.
|
|
289
|
+
*
|
|
290
|
+
* A claim that is ENTIRELY one value yields that value (strict path). Otherwise
|
|
291
|
+
* only currency-shaped figures inside the prose count, so an assertion that
|
|
292
|
+
* merely mentions a year or a form number yields nothing.
|
|
293
|
+
*/
|
|
294
|
+
declare function claimValues(claim: string): string[];
|
|
295
|
+
type ClaimSupport =
|
|
296
|
+
/** No figure to check: a non-numeric claim, or no anchored text. */
|
|
297
|
+
{
|
|
298
|
+
status: 'not_applicable';
|
|
299
|
+
} | {
|
|
300
|
+
status: 'supported';
|
|
301
|
+
matched: string;
|
|
302
|
+
} | {
|
|
303
|
+
status: 'unsupported';
|
|
304
|
+
claimed: string[];
|
|
305
|
+
present: string[];
|
|
306
|
+
};
|
|
307
|
+
/**
|
|
308
|
+
* Does `quote` carry the figure `claim` asserts?
|
|
309
|
+
*
|
|
310
|
+
* `supported` requires ONE claimed value to occur, which is exact for the
|
|
311
|
+
* single-value claim (there is only one) and deliberate latitude for prose (see
|
|
312
|
+
* the rule note at the top of the file).
|
|
313
|
+
*/
|
|
314
|
+
declare function verifyClaimSupport(quote: string, claim: string): ClaimSupport;
|
|
315
|
+
/**
|
|
316
|
+
* The sentence a model can act on without re-reading the document: what it
|
|
317
|
+
* claimed, what the line it cited actually says, what figures that line does
|
|
318
|
+
* carry, and the two ways out — cite the value, or drop the locator because the
|
|
319
|
+
* figure was computed. Naming both keeps the gate satisfiable, which is the
|
|
320
|
+
* property that stops it manufacturing the citation it screens for.
|
|
321
|
+
*/
|
|
322
|
+
declare function claimSupportErrorDetail(failure: Extract<ClaimSupport, {
|
|
323
|
+
status: 'unsupported';
|
|
324
|
+
}>, quote: string): string;
|
|
325
|
+
/**
|
|
326
|
+
* Does the cited line belong to the target the entry attaches it to?
|
|
327
|
+
*
|
|
328
|
+
* `verifyClaimSupport` asks whether the anchored text carries the claimed
|
|
329
|
+
* figure. It is blind, BY CONSTRUCTION, to whether that figure belongs on that
|
|
330
|
+
* line. Production row `95105c8a` is what the blindness costs — two entries,
|
|
331
|
+
* both anchored to a real line of the right document, both carrying the figure
|
|
332
|
+
* they claim, and both attached to the wrong form line:
|
|
333
|
+
*
|
|
334
|
+
* f1040.line_3b claim 1955.02 -> "Box 1b Qualified dividends ..... 1,955.02"
|
|
335
|
+
* f1040.line_3a claim 2204.18 -> "Box 1a Total ordinary dividends . 2,204.18"
|
|
336
|
+
*
|
|
337
|
+
* Form 1040 line 3a is QUALIFIED dividends and line 3b is ORDINARY, so each
|
|
338
|
+
* citation points a reviewer at the other one's line. `quote_verification`,
|
|
339
|
+
* `claim_support` and `evidence_coverage` were all green on that row. A
|
|
340
|
+
* citation that points at the wrong line is a wrong citation even when every
|
|
341
|
+
* character of it is real, and it is the failure a reviewer is least able to
|
|
342
|
+
* catch by eye, because it looks exactly like a good one.
|
|
343
|
+
*
|
|
344
|
+
* ── Why the domain supplies LABELS and the shell supplies the COMPARISON ────
|
|
345
|
+
*
|
|
346
|
+
* The shell cannot know that line 3a means qualified dividends; that is tax
|
|
347
|
+
* vocabulary and baking it here would violate the one rule this package is
|
|
348
|
+
* built on. So the product declares which targets are CONFUSABLE with each
|
|
349
|
+
* other and what each one's line looks like in a source document — a
|
|
350
|
+
* {@link ConfusableTargetGroup} — and the shell does the comparing.
|
|
351
|
+
*
|
|
352
|
+
* ── Why a group of labels, and not a per-target expectation ─────────────────
|
|
353
|
+
*
|
|
354
|
+
* The obvious shape is a per-target expectation read POSITIVELY: "a citation
|
|
355
|
+
* for line_3a must contain 'Qualified'". It is stricter, it is easier to
|
|
356
|
+
* explain, and it is the wrong shape, because it refuses honest work. A
|
|
357
|
+
* consolidated broker statement writing "Qual. div. income", a payer writing
|
|
358
|
+
* "Dividends that are qualified", an OCR layer dropping a word — each one turns
|
|
359
|
+
* a correct citation into a refusal. And this codebase has already measured
|
|
360
|
+
* what refusing honest work does: a coverage gate that demanded document
|
|
361
|
+
* lineage for computed values produced 38 fabricated quotes on row `a68b1943`,
|
|
362
|
+
* because a gate a model cannot satisfy honestly is a gate it satisfies
|
|
363
|
+
* dishonestly. An unsatisfiable rule does not stop bad work; it SELECTS for
|
|
364
|
+
* invented work.
|
|
365
|
+
*
|
|
366
|
+
* So the same labels are read NEGATIVELY and COMPARATIVELY. An entry is
|
|
367
|
+
* refused only when the cited line positively identifies a SIBLING target and
|
|
368
|
+
* says nothing that identifies its own:
|
|
369
|
+
*
|
|
370
|
+
* - the line carries one of the target's own labels → `identified`, pass
|
|
371
|
+
* - the line carries no label from the group at all → `not_applicable`, pass
|
|
372
|
+
* - the line carries a sibling's label and none of its own → `crossed`, refuse
|
|
373
|
+
*
|
|
374
|
+
* Silence therefore always passes. An unusually-labelled document costs
|
|
375
|
+
* nothing, a target the product never grouped costs nothing, and the only way
|
|
376
|
+
* to fail is for the document itself to say the line belongs to a different
|
|
377
|
+
* target — which is not a phrasing accident, it is the crossed pair. The rule
|
|
378
|
+
* is satisfiable by the honest citation in every case, and unsatisfiable only
|
|
379
|
+
* by the wrong one.
|
|
380
|
+
*
|
|
381
|
+
* Matching is punctuation- and case-insensitive: a label is a semantic marker
|
|
382
|
+
* for which LINE this is, not a quotation. (`sourceContainsQuote` stays exact —
|
|
383
|
+
* different question, different tolerance.)
|
|
384
|
+
*/
|
|
385
|
+
/** One set of targets whose source lines are mistakable for each other, with
|
|
386
|
+
* the phrases that tell them apart. Every string is product vocabulary; the
|
|
387
|
+
* shell reads none of them as meaning anything. */
|
|
388
|
+
interface ConfusableTargetGroup {
|
|
389
|
+
/** Named in the refusal so the model is told which distinction it missed
|
|
390
|
+
* ("Form 1099-DIV boxes 1a/1b"). */
|
|
391
|
+
note?: string;
|
|
392
|
+
/** Target → phrases that identify THAT target's line in a source document.
|
|
393
|
+
* Targets must be spelled the way evidence targets are spelled after the
|
|
394
|
+
* product's `normalizeTarget`, so one canonical name is written once. */
|
|
395
|
+
labels: Record<string, readonly string[]>;
|
|
396
|
+
}
|
|
397
|
+
type TargetLabelVerdict =
|
|
398
|
+
/** No group covers this target, or the line says nothing either way. */
|
|
399
|
+
{
|
|
400
|
+
status: 'not_applicable';
|
|
401
|
+
}
|
|
402
|
+
/** The cited line carries one of this target's own labels. */
|
|
403
|
+
| {
|
|
404
|
+
status: 'identified';
|
|
405
|
+
label: string;
|
|
406
|
+
}
|
|
407
|
+
/** The cited line identifies a DIFFERENT target in the same group. */
|
|
408
|
+
| {
|
|
409
|
+
status: 'crossed';
|
|
410
|
+
rival: string;
|
|
411
|
+
rivalLabel: string;
|
|
412
|
+
expected: readonly string[];
|
|
413
|
+
note?: string;
|
|
414
|
+
};
|
|
415
|
+
declare function verifyTargetLabel(quote: string, target: string, groups: readonly ConfusableTargetGroup[]): TargetLabelVerdict;
|
|
416
|
+
/** The sentence a model can act on: which line it actually cited, which target
|
|
417
|
+
* that line belongs to, and what its own target's line looks like. */
|
|
418
|
+
declare function targetLabelErrorDetail(failure: Extract<TargetLabelVerdict, {
|
|
419
|
+
status: 'crossed';
|
|
420
|
+
}>, target: string, quote: string): string;
|
|
421
|
+
/**
|
|
422
|
+
* Does the entry agree with the artifact it is evidence FOR?
|
|
423
|
+
*
|
|
424
|
+
* The two checks above compare evidence to the SOURCE. This one compares it to
|
|
425
|
+
* the DELIVERABLE, and it needs no product vocabulary at all: when the artifact
|
|
426
|
+
* states a value for a target and an evidence entry attached to that target
|
|
427
|
+
* asserts a different one, the work product contradicts itself, and a reviewer
|
|
428
|
+
* clicking that line is shown a figure the package does not report there.
|
|
429
|
+
*
|
|
430
|
+
* ── The rule, and the honest citation it must not refuse ────────────────────
|
|
431
|
+
*
|
|
432
|
+
* "Claim must equal the field" is the tempting rule and it is unsatisfiable for
|
|
433
|
+
* every aggregated or derived line. Measured on production row `a68b1943`:
|
|
434
|
+
* line 1a is 189,750.00 and its two evidence rows cite $128,450.00 and
|
|
435
|
+
* $61,300.00 — one per W-2, which is exactly the lineage a reviewer wants.
|
|
436
|
+
* Line 8 is a Schedule C net profit of 11,056.56 evidenced by gross receipts of
|
|
437
|
+
* 14,750.00 and four expense lines. Refusing those would delete correct work
|
|
438
|
+
* and, on this codebase's measured history, buy invented citations in its place.
|
|
439
|
+
*
|
|
440
|
+
* So the refusal is narrower and it is a CONTRADICTION rather than an
|
|
441
|
+
* inequality: the claim asserts a figure that the artifact itself assigns to a
|
|
442
|
+
* DIFFERENT target. On row `95105c8a` that is precisely the crossed pair —
|
|
443
|
+
* `line_3a` is 1955.02 in the artifact and its evidence claims 2204.18, which
|
|
444
|
+
* the same artifact reports on `line_3b`. There is no honest reading of that:
|
|
445
|
+
* the package cannot simultaneously say the number belongs on 3b and offer it
|
|
446
|
+
* as the support for 3a.
|
|
447
|
+
*
|
|
448
|
+
* A component that appears nowhere else in the field map (128,450.00 of a
|
|
449
|
+
* 189,750.00 total) is not a contradiction and is not refused. A claim
|
|
450
|
+
* narrating a computation passes as soon as one of its figures is the target's
|
|
451
|
+
* own value, which is what a narration of line 9 does by definition.
|
|
452
|
+
*/
|
|
453
|
+
/** Canonical target → canonical value, for the artifact fields that state a
|
|
454
|
+
* figure. Non-numeric fields are dropped: a filing status or a name has no
|
|
455
|
+
* numeric contradiction to detect, and inventing a string comparison here
|
|
456
|
+
* would re-open the fuzzy-matching hole the quote gate closes. */
|
|
457
|
+
declare function indexArtifactValues(fields: Readonly<Record<string, unknown>> | undefined, normalizeTarget?: (target: string) => string): Map<string, string>;
|
|
458
|
+
type ArtifactAgreement =
|
|
459
|
+
/** The artifact states no figure for this target, or the claim asserts none. */
|
|
460
|
+
{
|
|
461
|
+
status: 'not_applicable';
|
|
462
|
+
} | {
|
|
463
|
+
status: 'agrees';
|
|
464
|
+
value: string;
|
|
465
|
+
}
|
|
466
|
+
/** The claim asserts a figure the artifact reports on a different target. */
|
|
467
|
+
| {
|
|
468
|
+
status: 'contradicts';
|
|
469
|
+
claimed: string;
|
|
470
|
+
expected: string;
|
|
471
|
+
belongsTo: string;
|
|
472
|
+
};
|
|
473
|
+
declare function verifyArtifactAgreement(target: string, claim: string, fieldValues: ReadonlyMap<string, string>): ArtifactAgreement;
|
|
474
|
+
/** The sentence a model can act on: both numbers, both lines, and the two ways
|
|
475
|
+
* out — move the citation, or correct the artifact. */
|
|
476
|
+
declare function artifactAgreementErrorDetail(failure: Extract<ArtifactAgreement, {
|
|
477
|
+
status: 'contradicts';
|
|
478
|
+
}>, target: string): string;
|
|
479
|
+
|
|
189
480
|
/**
|
|
190
481
|
* The agent-facing work-product side channel — three registry `customTools`
|
|
191
482
|
* built on `/tools`' `defineAppTool`, dispatched through `dispatchAppTool`'s
|
|
@@ -221,6 +512,17 @@ declare const QUOTE_VERIFICATION_CHECK = "quote_verification";
|
|
|
221
512
|
* production row `7256ef49` passed that one on all four entries while
|
|
222
513
|
* supporting none of them. */
|
|
223
514
|
declare const CLAIM_SUPPORT_CHECK = "claim_support";
|
|
515
|
+
/** Platform check: how many citations anchor to a line that belongs to the
|
|
516
|
+
* TARGET they are attached to, rather than to a sibling target's line.
|
|
517
|
+
* Recorded when the product declares `confusableTargets`; `claim_support`
|
|
518
|
+
* passes a crossed pair by construction, because the figure really is on the
|
|
519
|
+
* line — the wrong one. */
|
|
520
|
+
declare const TARGET_CORRECTNESS_CHECK = "target_correctness";
|
|
521
|
+
/** Platform check: how many evidence claims agree with the artifact field they
|
|
522
|
+
* decorate. A package whose evidence reports one figure on a line and whose
|
|
523
|
+
* artifact reports another contradicts itself; every other gate on this row
|
|
524
|
+
* reads only one of the two halves. */
|
|
525
|
+
declare const ARTIFACT_AGREEMENT_CHECK = "artifact_agreement";
|
|
224
526
|
/** Domain seams for the three work-product tools — every domain word is a
|
|
225
527
|
* parameter; the shell bakes none. */
|
|
226
528
|
interface WorkProductToolConfig {
|
|
@@ -275,6 +577,33 @@ interface WorkProductToolConfig {
|
|
|
275
577
|
* product whose claims are figures the source states in a form no numeric
|
|
276
578
|
* comparison can reach. */
|
|
277
579
|
verifyClaimSupport?: boolean;
|
|
580
|
+
/** Fold an evidence `target` (and every `materialTargets` name) to the
|
|
581
|
+
* product's ONE canonical spelling.
|
|
582
|
+
*
|
|
583
|
+
* Without it a target namespace forks and every check that joins evidence
|
|
584
|
+
* to the artifact by name silently half-works. Measured on production row
|
|
585
|
+
* `95105c8a`: the same seven form lines arrived as `line_3a` and
|
|
586
|
+
* `f1040.line_3a` in one turn, so coverage, deduplication and artifact
|
|
587
|
+
* agreement each saw two unrelated targets where the return has one line.
|
|
588
|
+
*
|
|
589
|
+
* Pure and total — it runs on every ingested entry and on the coverage
|
|
590
|
+
* target list, so a target it does not recognize must come back unchanged
|
|
591
|
+
* rather than throw. */
|
|
592
|
+
normalizeTarget?: (target: string) => string;
|
|
593
|
+
/** Targets whose SOURCE LINES are mistakable for each other, with the
|
|
594
|
+
* phrases that tell them apart — the product's vocabulary, compared by the
|
|
595
|
+
* shell. Omit and no target-correctness check runs.
|
|
596
|
+
*
|
|
597
|
+
* Read negatively: an entry is refused only when the line it cites carries
|
|
598
|
+
* a sibling target's label and none of its own, so an unusually-labelled
|
|
599
|
+
* document never costs an honest citation. See `./claim-support` for why
|
|
600
|
+
* the positive form ("the line must say X") is the wrong shape. */
|
|
601
|
+
confusableTargets?: readonly ConfusableTargetGroup[];
|
|
602
|
+
/** Refuse an evidence claim that asserts a figure the artifact reports on a
|
|
603
|
+
* DIFFERENT target. ON by default and domain-free — it compares the package
|
|
604
|
+
* to itself. Set `false` only for a product whose evidence claims are not
|
|
605
|
+
* the artifact's own figures. */
|
|
606
|
+
verifyArtifactAgreement?: boolean;
|
|
278
607
|
/** Per-turn provenance closure the ROUTE supplies (profileHash + runId are
|
|
279
608
|
* known at dispatch; trusted, never read from model args). */
|
|
280
609
|
provenance: (ctx: AppToolContext) => WorkProductProvenanceBase;
|
|
@@ -429,130 +758,6 @@ declare function sliceSourceSpan(sourceText: string, span: {
|
|
|
429
758
|
end: number;
|
|
430
759
|
}): SourceSpanResult;
|
|
431
760
|
|
|
432
|
-
/**
|
|
433
|
-
* Claim support — does the anchored text actually say what the entry claims?
|
|
434
|
-
*
|
|
435
|
-
* The two gates before this one answer different questions. `sourceContainsQuote`
|
|
436
|
-
* asks whether the quote is really in the document; `findSourceLine` /
|
|
437
|
-
* `sliceSourceSpan` make the platform produce the quote so it cannot be typed
|
|
438
|
-
* wrong. Both are about the TEXT's provenance. Neither one looks at `claim`.
|
|
439
|
-
*
|
|
440
|
-
* Production row `7256ef49` is what that gap costs. Four evidence entries, all
|
|
441
|
-
* `quoteBasis:'span'`, every quote a genuine slice of the document it named —
|
|
442
|
-
* and every one landing on the employer/payer line about 200 characters above
|
|
443
|
-
* the figure:
|
|
444
|
-
*
|
|
445
|
-
* claim 128450.00 -> "tics LLC EIN 84-2213907\nEmployee: Dana"
|
|
446
|
-
* claim 812.44 -> "nt Savings Bank TIN 22-5510983\nRecip"
|
|
447
|
-
* claim 2204.18 -> "ndex Fund Trust TIN 47-3320115\nRec"
|
|
448
|
-
* claim 1955.02 -> "pient: Dana R. Whitfield\n------------"
|
|
449
|
-
*
|
|
450
|
-
* That is strictly worse than a fabricated quote. A fabricated quote fails the
|
|
451
|
-
* verbatim gate; this one passes every gate, is real text from the right
|
|
452
|
-
* document, and reads to a reviewer as an authoritative citation while
|
|
453
|
-
* supporting nothing. `locator.find` (the platform locating a value the model
|
|
454
|
-
* names) prevents the model from ADDRESSING the wrong line, and it is the right
|
|
455
|
-
* primary fix. This module is the independent check underneath it: whatever
|
|
456
|
-
* anchoring form produced the text, the text has to contain the figure.
|
|
457
|
-
*
|
|
458
|
-
* That also settles what a raw `locator.span` is worth. Hand-computed offsets
|
|
459
|
-
* stay accepted, but only when they independently verify — which is exactly
|
|
460
|
-
* "the slice contains the claimed value".
|
|
461
|
-
*
|
|
462
|
-
* ── The rule, and why it is drawn here ──────────────────────────────────────
|
|
463
|
-
*
|
|
464
|
-
* Strict on figures, silent on everything else. An unsatisfiable gate does not
|
|
465
|
-
* stop a bad submit, it SELECTS for one — that is the measured mechanism behind
|
|
466
|
-
* the 38 fabricated quotes on row `a68b1943`, where a coverage gate demanded
|
|
467
|
-
* document lineage for computed values and got thirteen invented citations
|
|
468
|
-
* forty seconds later. So the rule fires only where an honest citation can
|
|
469
|
-
* always satisfy it:
|
|
470
|
-
*
|
|
471
|
-
* - The claim IS a value (`"128450.00"`, `"$30,000"`, `"3"`) — the anchored
|
|
472
|
-
* text MUST contain that value. No latitude. This is the shape every tax
|
|
473
|
-
* figure takes and the shape row `7256ef49` failed.
|
|
474
|
-
* - The claim is prose naming figures (`"indemnity capped at $5,000,000"`) —
|
|
475
|
-
* at least one of its currency-shaped figures must occur. Not all of them:
|
|
476
|
-
* a claim may legitimately narrate a computation over several lines while
|
|
477
|
-
* anchoring to the one line under discussion, and refusing that would make
|
|
478
|
-
* an honest citation unrepresentable for the sake of a stricter-sounding
|
|
479
|
-
* rule. One is enough to keep the anchor tethered to the claim's subject.
|
|
480
|
-
* - The claim carries no figure at all (`"Married Filing Jointly"`,
|
|
481
|
-
* `"Dana R. Whitfield"`, `"2025-04-15"`) — nothing to check, and the entry
|
|
482
|
-
* passes. A filing status has no number to find, and inventing a
|
|
483
|
-
* word-overlap score here would re-open the hole the verbatim gate closes.
|
|
484
|
-
* - The entry has no anchored text at all — nothing to check. A computed
|
|
485
|
-
* value cites its computation, not a document.
|
|
486
|
-
*
|
|
487
|
-
* A bare year, a form number and a box number are deliberately NOT figures:
|
|
488
|
-
* `2025`, `1040` and `Box 1` have no thousands separator, no cent pair and no
|
|
489
|
-
* currency symbol, so prose mentioning them does not trip the rule.
|
|
490
|
-
*
|
|
491
|
-
* ── Matching is value-wise, never substring ─────────────────────────────────
|
|
492
|
-
*
|
|
493
|
-
* `text.includes(claim)` would be the obvious implementation and it is wrong in
|
|
494
|
-
* the direction that matters: it passes `"450.00"` against `"128,450.00"`, so a
|
|
495
|
-
* claim citing the wrong figure survives whenever its digits happen to be a tail
|
|
496
|
-
* of a real one. Both sides are tokenized into numbers and compared as VALUES,
|
|
497
|
-
* so `450` and `128450` are simply different.
|
|
498
|
-
*/
|
|
499
|
-
/**
|
|
500
|
-
* Reduce a numeric token to the form both sides are compared in: no currency,
|
|
501
|
-
* no grouping, no trailing zeros in the fraction, no leading zeros.
|
|
502
|
-
*
|
|
503
|
-
* Sign and accounting parentheses are stripped rather than preserved, so
|
|
504
|
-
* `(1,234.00)`, `-1,234.00` and `1,234.00` all reduce to `1234`. A document
|
|
505
|
-
* renders the same deduction all three ways depending on the form and the
|
|
506
|
-
* extractor, and the sign is a property of the TARGET LINE's semantics, not of
|
|
507
|
-
* the document's typography. Comparing magnitudes keeps those honest citations
|
|
508
|
-
* working, and it concedes nothing to fabrication: the digits still have to be
|
|
509
|
-
* the document's digits.
|
|
510
|
-
*
|
|
511
|
-
* Returns `null` for anything that is not a plain number.
|
|
512
|
-
*/
|
|
513
|
-
declare function canonicalizeValue(token: string): string | null;
|
|
514
|
-
/** Every distinct value appearing in `text`, canonicalized. */
|
|
515
|
-
declare function valuesInText(text: string): string[];
|
|
516
|
-
/**
|
|
517
|
-
* The values a claim asserts, canonicalized — empty when the claim asserts no
|
|
518
|
-
* figure, which is the "nothing to check" case.
|
|
519
|
-
*
|
|
520
|
-
* A claim that is ENTIRELY one value yields that value (strict path). Otherwise
|
|
521
|
-
* only currency-shaped figures inside the prose count, so an assertion that
|
|
522
|
-
* merely mentions a year or a form number yields nothing.
|
|
523
|
-
*/
|
|
524
|
-
declare function claimValues(claim: string): string[];
|
|
525
|
-
type ClaimSupport =
|
|
526
|
-
/** No figure to check: a non-numeric claim, or no anchored text. */
|
|
527
|
-
{
|
|
528
|
-
status: 'not_applicable';
|
|
529
|
-
} | {
|
|
530
|
-
status: 'supported';
|
|
531
|
-
matched: string;
|
|
532
|
-
} | {
|
|
533
|
-
status: 'unsupported';
|
|
534
|
-
claimed: string[];
|
|
535
|
-
present: string[];
|
|
536
|
-
};
|
|
537
|
-
/**
|
|
538
|
-
* Does `quote` carry the figure `claim` asserts?
|
|
539
|
-
*
|
|
540
|
-
* `supported` requires ONE claimed value to occur, which is exact for the
|
|
541
|
-
* single-value claim (there is only one) and deliberate latitude for prose (see
|
|
542
|
-
* the rule note at the top of the file).
|
|
543
|
-
*/
|
|
544
|
-
declare function verifyClaimSupport(quote: string, claim: string): ClaimSupport;
|
|
545
|
-
/**
|
|
546
|
-
* The sentence a model can act on without re-reading the document: what it
|
|
547
|
-
* claimed, what the line it cited actually says, what figures that line does
|
|
548
|
-
* carry, and the two ways out — cite the value, or drop the locator because the
|
|
549
|
-
* figure was computed. Naming both keeps the gate satisfiable, which is the
|
|
550
|
-
* property that stops it manufacturing the citation it screens for.
|
|
551
|
-
*/
|
|
552
|
-
declare function claimSupportErrorDetail(failure: Extract<ClaimSupport, {
|
|
553
|
-
status: 'unsupported';
|
|
554
|
-
}>, quote: string): string;
|
|
555
|
-
|
|
556
761
|
/**
|
|
557
762
|
* Framework-neutral work-product review endpoints — the
|
|
558
763
|
* `createInteractionAnswerRoute` factory pattern: web-standard
|
|
@@ -642,4 +847,4 @@ interface WorkProductRoutes {
|
|
|
642
847
|
/** Create the work-product review endpoints over the store port and product seams */
|
|
643
848
|
declare function createWorkProductRoutes(options: WorkProductRoutesOptions): WorkProductRoutes;
|
|
644
849
|
|
|
645
|
-
export { CLAIM_SUPPORT_CHECK, type ClaimSupport, type CreateWorkProductInput, EVIDENCE_COVERAGE_CHECK, EvidenceEntry, ExceptionEntry, type FinalizeWorkProductProvenanceInput, type InMemoryWorkProductStore, MAX_WORK_PRODUCT_BATCH, QUOTE_VERIFICATION_CHECK, QualityCheck, type SourceFindFailure, type SourceFindResult, type SourceSpanFailure, type SourceSpanResult, type SubmitWorkProductInput, TrustItem, WorkProductArtifact, WorkProductAuditEvent, type WorkProductAuthorizeArgs, type WorkProductOutcome, WorkProductPersistedPart, WorkProductProvenance, type WorkProductProvenanceBase, WorkProductRecord, type WorkProductRouteAuthorization, type WorkProductRoutes, type WorkProductRoutesOptions, type WorkProductService, type WorkProductServiceOptions, WorkProductStatus, WorkProductStorePort, type WorkProductToolConfig, type WorkProductVerdictBody, type WorkProductVerdictInput, buildWorkProductTools, canTransitionWorkProduct, canonicalizeValue, claimSupportErrorDetail, claimValues, createInMemoryWorkProductStore, createWorkProductRoutes, createWorkProductService, finalizeWorkProductProvenance, findSourceLine, isWorkProductTerminal, normalizeQuoteText, sliceSourceSpan, sourceContainsQuote, stampProvenance, validateWorkProductVerdictBody, valuesInText, verifyClaimSupport, workProductTrustInputs };
|
|
850
|
+
export { ARTIFACT_AGREEMENT_CHECK, type ArtifactAgreement, CLAIM_SUPPORT_CHECK, type ClaimSupport, type ConfusableTargetGroup, type CreateWorkProductInput, EVIDENCE_COVERAGE_CHECK, EvidenceEntry, ExceptionEntry, type FinalizeWorkProductProvenanceInput, type InMemoryWorkProductStore, MAX_WORK_PRODUCT_BATCH, QUOTE_VERIFICATION_CHECK, QualityCheck, type SourceFindFailure, type SourceFindResult, type SourceSpanFailure, type SourceSpanResult, type SubmitWorkProductInput, TARGET_CORRECTNESS_CHECK, type TargetLabelVerdict, TrustItem, WorkProductArtifact, WorkProductAuditEvent, type WorkProductAuthorizeArgs, type WorkProductOutcome, WorkProductPersistedPart, WorkProductProvenance, type WorkProductProvenanceBase, WorkProductRecord, type WorkProductRouteAuthorization, type WorkProductRoutes, type WorkProductRoutesOptions, type WorkProductService, type WorkProductServiceOptions, WorkProductStatus, WorkProductStorePort, type WorkProductToolConfig, type WorkProductVerdictBody, type WorkProductVerdictInput, artifactAgreementErrorDetail, buildWorkProductTools, canTransitionWorkProduct, canonicalizeValue, claimSupportErrorDetail, claimValues, createInMemoryWorkProductStore, createWorkProductRoutes, createWorkProductService, finalizeWorkProductProvenance, findSourceLine, indexArtifactValues, isWorkProductTerminal, normalizeQuoteText, sliceSourceSpan, sourceContainsQuote, stampProvenance, targetLabelErrorDetail, validateWorkProductVerdictBody, valuesInText, verifyArtifactAgreement, verifyClaimSupport, verifyTargetLabel, workProductTrustInputs };
|