@profile-as-code/core 0.1.1 → 0.1.2
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/cite.d.ts +91 -0
- package/dist/cite.d.ts.map +1 -0
- package/dist/cite.js +440 -0
- package/dist/cite.js.map +1 -0
- package/dist/completeness.d.ts +1 -1
- package/dist/completeness.js +1 -1
- package/dist/generated/ai-policy.gen.d.ts +36 -0
- package/dist/generated/ai-policy.gen.d.ts.map +1 -0
- package/dist/generated/ai-policy.gen.js +31 -0
- package/dist/generated/ai-policy.gen.js.map +1 -0
- package/dist/generated/platforms.gen.d.ts +8 -0
- package/dist/generated/platforms.gen.d.ts.map +1 -1
- package/dist/generated/platforms.gen.js +68 -0
- package/dist/generated/platforms.gen.js.map +1 -1
- package/dist/generated/schema.zod.d.ts +20 -0
- package/dist/generated/schema.zod.d.ts.map +1 -1
- package/dist/generated/schema.zod.js +6 -1
- package/dist/generated/schema.zod.js.map +1 -1
- package/dist/geo.d.ts +11 -3
- package/dist/geo.d.ts.map +1 -1
- package/dist/geo.js +21 -8
- package/dist/geo.js.map +1 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js +9 -0
- package/dist/load.js.map +1 -1
- package/dist/normalize.d.ts +57 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +133 -0
- package/dist/normalize.js.map +1 -0
- package/dist/presence.d.ts +94 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +217 -0
- package/dist/presence.js.map +1 -0
- package/dist/registry.d.ts +6 -3
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +8 -4
- package/dist/registry.js.map +1 -1
- package/dist/structured-data.d.ts +4 -3
- package/dist/structured-data.d.ts.map +1 -1
- package/dist/structured-data.js +72 -7
- package/dist/structured-data.js.map +1 -1
- package/dist/types.d.ts +15 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/dist/paste-source.d.ts +0 -14
- package/dist/paste-source.d.ts.map +0 -1
- package/dist/paste-source.js +0 -17
- package/dist/paste-source.js.map +0 -1
package/dist/cite.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cite.ts — the deterministic citation matcher (SPEC §7.4, issue #291).
|
|
3
|
+
*
|
|
4
|
+
* The engine answers ONE question about an answer-engine record: did this saved
|
|
5
|
+
* answer cite this entity? It is a pure function over the SSOT and the answer
|
|
6
|
+
* bytes — no network, no model, no clock (D19) — because the alternative
|
|
7
|
+
* (substring matching) is why GEO reporting overreports, and the only fix is a
|
|
8
|
+
* matcher that says exactly which text it matched, why, and when it refuses to
|
|
9
|
+
* guess.
|
|
10
|
+
*
|
|
11
|
+
* The vocabulary is the workspace's DECLARED data, never world knowledge:
|
|
12
|
+
* name identity.name
|
|
13
|
+
* alias identity.orgName (the one declared alternate name the schema has)
|
|
14
|
+
* handle identity.handle (its final token, '@' stripped) + socialHandles
|
|
15
|
+
* rows with status: claimed
|
|
16
|
+
* hosts the role: identity URL and the sameAs set (structured-data.ts —
|
|
17
|
+
* one derivation, never a second)
|
|
18
|
+
* partial a contiguous multi-token prefix of the name (low confidence)
|
|
19
|
+
*
|
|
20
|
+
* Normalization and word-boundary matching live in `normalize.ts`. It is
|
|
21
|
+
* `cite-check`'s fold, not `geoCheck`'s: `geoCheck` keeps its own case-only
|
|
22
|
+
* comparison so this matcher cannot move a published GEO score (§8).
|
|
23
|
+
*
|
|
24
|
+
* Guards make a text hit NOT a citation (`cited: false`): a shorter term
|
|
25
|
+
* contained in a longer declared one (`longer-name`), a one-word name with no
|
|
26
|
+
* declared disambiguator in its sentence (`ambiguous-term` + `no-qualifier`), and
|
|
27
|
+
* a mention inside a contrast clause (`contrast-context`). `competing:<phrase>`
|
|
28
|
+
* never decides on its own — it only names the longer reading the text carries
|
|
29
|
+
* when the hit is already ambiguous, so ordinary prose cannot become a
|
|
30
|
+
* competitor through an adjacent capital. `confidence: low` is never citable
|
|
31
|
+
* downstream (declared in §7.4).
|
|
32
|
+
*/
|
|
33
|
+
import type { Profile } from "./types.js";
|
|
34
|
+
/** The rung a span was matched by — one kind per ladder rung (SPEC §7.4). */
|
|
35
|
+
export type CiteSpanKind = "citation-url" | "name" | "alias" | "handle" | "partial";
|
|
36
|
+
/** The best surviving rung. `low` is never a citation in a downstream report. */
|
|
37
|
+
export type CiteConfidence = "high" | "medium" | "low";
|
|
38
|
+
/** One citation row of the runner's input contract. */
|
|
39
|
+
export interface CiteCitation {
|
|
40
|
+
url: string;
|
|
41
|
+
title?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* One saved answer (the runner's contract, never produced here). The matcher
|
|
45
|
+
* reads `answer` + `citations`; the rest is carried through for a report.
|
|
46
|
+
*/
|
|
47
|
+
export interface CiteAnswer {
|
|
48
|
+
engine?: string | null;
|
|
49
|
+
askedAt?: string | null;
|
|
50
|
+
question?: string | null;
|
|
51
|
+
answer: string;
|
|
52
|
+
citations: CiteCitation[];
|
|
53
|
+
}
|
|
54
|
+
/** A matched span: a character range in `answer`, or a citation pointer. */
|
|
55
|
+
export interface CiteSpan {
|
|
56
|
+
/** Original offset (inclusive). 0 for a `citation-url` span (not in the text). */
|
|
57
|
+
start: number;
|
|
58
|
+
/** Original offset (exclusive). 0 for a `citation-url` span. */
|
|
59
|
+
end: number;
|
|
60
|
+
kind: CiteSpanKind;
|
|
61
|
+
/** The citation URL — only on `citation-url` spans. */
|
|
62
|
+
url?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Per-answer result. Never aggregated by the engine (SPEC §7.4). */
|
|
65
|
+
export interface CiteMatch {
|
|
66
|
+
cited: boolean;
|
|
67
|
+
confidence: CiteConfidence;
|
|
68
|
+
spans: CiteSpan[];
|
|
69
|
+
reasons: string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The vocabulary the matcher resolved from the workspace. Exposed in `--json`
|
|
73
|
+
* so a report can say WHAT was matched without re-reading the SSOT.
|
|
74
|
+
*/
|
|
75
|
+
export interface CiteVocabulary {
|
|
76
|
+
name: string;
|
|
77
|
+
aliases: string[];
|
|
78
|
+
handles: string[];
|
|
79
|
+
partials: string[];
|
|
80
|
+
hosts: string[];
|
|
81
|
+
}
|
|
82
|
+
/** The public vocabulary of a workspace (the `entity` block of `--json`). */
|
|
83
|
+
export declare function citeVocabulary(profile: Profile): CiteVocabulary;
|
|
84
|
+
/**
|
|
85
|
+
* Match one saved answer against the workspace's declared entity (SPEC §7.4).
|
|
86
|
+
* Pure: the same profile + answer bytes always produce the same result.
|
|
87
|
+
*/
|
|
88
|
+
export declare function citeMatch(profile: Profile, answer: CiteAnswer): CiteMatch;
|
|
89
|
+
/** Exported for tests: the declared host of a URL under the matcher's rule. */
|
|
90
|
+
export declare function citationHost(url: string): string | undefined;
|
|
91
|
+
//# sourceMappingURL=cite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cite.d.ts","sourceRoot":"","sources":["../src/cite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEpF,iFAAiF;AACjF,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEvD,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,4EAA4E;AAC5E,MAAM,WAAW,QAAQ;IACvB,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,YAAY,CAAC;IACnB,uDAAuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,cAAc,CAAC;IAC3B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAsND,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAE/D;AAgFD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,CA0JzE;AAaD,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5D"}
|
package/dist/cite.js
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cite.ts — the deterministic citation matcher (SPEC §7.4, issue #291).
|
|
3
|
+
*
|
|
4
|
+
* The engine answers ONE question about an answer-engine record: did this saved
|
|
5
|
+
* answer cite this entity? It is a pure function over the SSOT and the answer
|
|
6
|
+
* bytes — no network, no model, no clock (D19) — because the alternative
|
|
7
|
+
* (substring matching) is why GEO reporting overreports, and the only fix is a
|
|
8
|
+
* matcher that says exactly which text it matched, why, and when it refuses to
|
|
9
|
+
* guess.
|
|
10
|
+
*
|
|
11
|
+
* The vocabulary is the workspace's DECLARED data, never world knowledge:
|
|
12
|
+
* name identity.name
|
|
13
|
+
* alias identity.orgName (the one declared alternate name the schema has)
|
|
14
|
+
* handle identity.handle (its final token, '@' stripped) + socialHandles
|
|
15
|
+
* rows with status: claimed
|
|
16
|
+
* hosts the role: identity URL and the sameAs set (structured-data.ts —
|
|
17
|
+
* one derivation, never a second)
|
|
18
|
+
* partial a contiguous multi-token prefix of the name (low confidence)
|
|
19
|
+
*
|
|
20
|
+
* Normalization and word-boundary matching live in `normalize.ts`. It is
|
|
21
|
+
* `cite-check`'s fold, not `geoCheck`'s: `geoCheck` keeps its own case-only
|
|
22
|
+
* comparison so this matcher cannot move a published GEO score (§8).
|
|
23
|
+
*
|
|
24
|
+
* Guards make a text hit NOT a citation (`cited: false`): a shorter term
|
|
25
|
+
* contained in a longer declared one (`longer-name`), a one-word name with no
|
|
26
|
+
* declared disambiguator in its sentence (`ambiguous-term` + `no-qualifier`), and
|
|
27
|
+
* a mention inside a contrast clause (`contrast-context`). `competing:<phrase>`
|
|
28
|
+
* never decides on its own — it only names the longer reading the text carries
|
|
29
|
+
* when the hit is already ambiguous, so ordinary prose cannot become a
|
|
30
|
+
* competitor through an adjacent capital. `confidence: low` is never citable
|
|
31
|
+
* downstream (declared in §7.4).
|
|
32
|
+
*/
|
|
33
|
+
import { byteOrder } from "./byte-order.js";
|
|
34
|
+
import { disambiguationQualifiers } from "./geo.js";
|
|
35
|
+
import { findTerm, foldForMatch, normalizeText, termOccursIn } from "./normalize.js";
|
|
36
|
+
import { entityId, sameAsUrls } from "./structured-data.js";
|
|
37
|
+
const RUNG_ORDER = ["name", "alias", "handle", "partial"];
|
|
38
|
+
const RUNG_RANK = {
|
|
39
|
+
"citation-url": 0,
|
|
40
|
+
name: 0,
|
|
41
|
+
alias: 1,
|
|
42
|
+
handle: 2,
|
|
43
|
+
partial: 3,
|
|
44
|
+
};
|
|
45
|
+
const RUNG_REASON = {
|
|
46
|
+
"citation-url": "citation-url",
|
|
47
|
+
name: "exact-name",
|
|
48
|
+
alias: "alias",
|
|
49
|
+
handle: "handle",
|
|
50
|
+
partial: "partial",
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The closed contrast lexicon (§7.4, declared limit): a mention inside a
|
|
54
|
+
* comparison is not an assertion about the entity. EN · ES · PT, matched
|
|
55
|
+
* case- and accent-insensitively as a phrase, only BEFORE the hit.
|
|
56
|
+
*/
|
|
57
|
+
const CONTRAST_MARKERS = [
|
|
58
|
+
"unlike",
|
|
59
|
+
"contrary to",
|
|
60
|
+
"as opposed to",
|
|
61
|
+
"rather than",
|
|
62
|
+
"instead of",
|
|
63
|
+
"versus",
|
|
64
|
+
"vs",
|
|
65
|
+
"compared to",
|
|
66
|
+
"a diferencia de",
|
|
67
|
+
"en contraste con",
|
|
68
|
+
"en lugar de",
|
|
69
|
+
"em vez de",
|
|
70
|
+
"ao contrário de",
|
|
71
|
+
"diferentemente de",
|
|
72
|
+
];
|
|
73
|
+
/** Reason ordering in the output set (SPEC §7.4: a fixed order). */
|
|
74
|
+
const REASON_ORDER = [
|
|
75
|
+
"citation-url",
|
|
76
|
+
"identity-domain",
|
|
77
|
+
"sameAs-domain",
|
|
78
|
+
"url-invalid",
|
|
79
|
+
"exact-name",
|
|
80
|
+
"alias",
|
|
81
|
+
"handle",
|
|
82
|
+
"partial",
|
|
83
|
+
"longer-name",
|
|
84
|
+
"competing",
|
|
85
|
+
"ambiguous-term",
|
|
86
|
+
"no-qualifier",
|
|
87
|
+
"contrast-context",
|
|
88
|
+
];
|
|
89
|
+
/** Host of a URL, lowercased and with a leading `www.` stripped. */
|
|
90
|
+
function hostOf(url) {
|
|
91
|
+
try {
|
|
92
|
+
const host = new URL(url).hostname.toLowerCase();
|
|
93
|
+
return host.startsWith("www.") ? host.slice(4) : host;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** Citation host belongs to a declared host: equal, or a subdomain of it. */
|
|
100
|
+
function sameSite(citationHost, declaredHost) {
|
|
101
|
+
return citationHost === declaredHost || citationHost.endsWith(`.${declaredHost}`);
|
|
102
|
+
}
|
|
103
|
+
/** A declared URL's path, without a trailing slash (`""` for the root). */
|
|
104
|
+
function pathOf(url) {
|
|
105
|
+
try {
|
|
106
|
+
return new URL(url).pathname.replace(/\/+$/, "");
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Does the cited URL point at the declared one? A shared host alone is not
|
|
114
|
+
* enough: `github.com/someone-else` shares `github.com` with a declared
|
|
115
|
+
* `github.com/elenavasquez`, and host-only matching would overreport exactly
|
|
116
|
+
* the way substring matching does. A declared URL on the root claims the whole
|
|
117
|
+
* host; a declared URL with a path claims that path and its descendants.
|
|
118
|
+
*/
|
|
119
|
+
function pathMatches(citationPath, declaredPath) {
|
|
120
|
+
if (declaredPath === "")
|
|
121
|
+
return true;
|
|
122
|
+
return citationPath === declaredPath || citationPath.startsWith(`${declaredPath}/`);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The declared handle inside a free-text `identity.handle` ("X @cluciani_ve"):
|
|
126
|
+
* its final whitespace-separated token, leading `@` stripped, trailing
|
|
127
|
+
* punctuation trimmed. Nothing is parsed beyond that (declared limit).
|
|
128
|
+
*/
|
|
129
|
+
function parseDeclaredHandle(raw) {
|
|
130
|
+
const tokens = raw.trim().split(/\s+/).filter(Boolean);
|
|
131
|
+
const last = tokens[tokens.length - 1];
|
|
132
|
+
if (last === undefined)
|
|
133
|
+
return undefined;
|
|
134
|
+
const cleaned = last.replace(/^@+/, "").replace(/[.,;:)\]}]+$/, "");
|
|
135
|
+
return cleaned.length >= 2 ? cleaned : undefined;
|
|
136
|
+
}
|
|
137
|
+
/** Push `value` unless its normalized form is already present (order preserved). */
|
|
138
|
+
function pushUnique(out, seen, value) {
|
|
139
|
+
const key = normalizeText(value);
|
|
140
|
+
if (key === "" || seen.has(key))
|
|
141
|
+
return;
|
|
142
|
+
seen.add(key);
|
|
143
|
+
out.push(value);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolve the workspace's declared citation vocabulary. One source per fact:
|
|
147
|
+
* `sameAsUrls` and `entityId` are the structured-data set — never re-derived.
|
|
148
|
+
*/
|
|
149
|
+
function buildVocabulary(profile) {
|
|
150
|
+
const identity = profile.identity;
|
|
151
|
+
const name = identity.name.trim();
|
|
152
|
+
const used = new Set([normalizeText(name)]);
|
|
153
|
+
const aliases = [];
|
|
154
|
+
const orgName = identity.orgName?.trim();
|
|
155
|
+
if (orgName !== undefined && orgName !== "")
|
|
156
|
+
pushUnique(aliases, used, orgName);
|
|
157
|
+
const handles = [];
|
|
158
|
+
const handle = identity.handle?.trim();
|
|
159
|
+
if (handle !== undefined && handle !== "") {
|
|
160
|
+
const parsed = parseDeclaredHandle(handle);
|
|
161
|
+
if (parsed !== undefined)
|
|
162
|
+
pushUnique(handles, used, parsed);
|
|
163
|
+
}
|
|
164
|
+
for (const row of profile.socialHandles ?? []) {
|
|
165
|
+
if (row.status !== "claimed")
|
|
166
|
+
continue;
|
|
167
|
+
pushUnique(handles, used, row.handle.trim());
|
|
168
|
+
}
|
|
169
|
+
const partials = [];
|
|
170
|
+
const tokens = name.split(/\s+/).filter(Boolean);
|
|
171
|
+
// EVERY contiguous multi-token prefix shorter than the name (SPEC §7.4):
|
|
172
|
+
// "DA SEO Digital Studio" yields "DA SEO" and "DA SEO Digital". A single-token
|
|
173
|
+
// prefix is deliberately not a rung — it is a common word.
|
|
174
|
+
for (let length = 2; length < tokens.length; length++) {
|
|
175
|
+
pushUnique(partials, used, tokens.slice(0, length).join(" "));
|
|
176
|
+
}
|
|
177
|
+
const targets = [];
|
|
178
|
+
const seenTargets = new Set();
|
|
179
|
+
const addTarget = (url, kind) => {
|
|
180
|
+
if (url === undefined)
|
|
181
|
+
return;
|
|
182
|
+
const host = hostOf(url);
|
|
183
|
+
const path = pathOf(url);
|
|
184
|
+
if (host === undefined || path === undefined)
|
|
185
|
+
return;
|
|
186
|
+
const key = `${host}${path}`;
|
|
187
|
+
if (seenTargets.has(key))
|
|
188
|
+
return;
|
|
189
|
+
seenTargets.add(key);
|
|
190
|
+
targets.push({ host, path, kind });
|
|
191
|
+
};
|
|
192
|
+
// The entity's own page first: a citation of it is still a citation of the
|
|
193
|
+
// entity, and the reason says which authority the target came from.
|
|
194
|
+
addTarget(entityId(identity), "identity");
|
|
195
|
+
for (const url of sameAsUrls(profile))
|
|
196
|
+
addTarget(url, "sameAs");
|
|
197
|
+
const knownTerms = new Set();
|
|
198
|
+
for (const term of [name, ...aliases, ...handles]) {
|
|
199
|
+
const key = normalizeText(term);
|
|
200
|
+
if (key !== "")
|
|
201
|
+
knownTerms.add(key);
|
|
202
|
+
}
|
|
203
|
+
// Qualifiers are declared, never inferred: the location and role titles
|
|
204
|
+
// geoCheck's name-collision already reads (one home) plus the entity's other
|
|
205
|
+
// declared terms.
|
|
206
|
+
const qualifiers = [];
|
|
207
|
+
const seenQualifiers = new Set();
|
|
208
|
+
for (const q of disambiguationQualifiers(profile))
|
|
209
|
+
pushUnique(qualifiers, seenQualifiers, q);
|
|
210
|
+
for (const term of [name, ...aliases, ...handles])
|
|
211
|
+
pushUnique(qualifiers, seenQualifiers, term);
|
|
212
|
+
return {
|
|
213
|
+
public: {
|
|
214
|
+
name,
|
|
215
|
+
aliases,
|
|
216
|
+
handles,
|
|
217
|
+
partials,
|
|
218
|
+
hosts: [...new Set(targets.map((t) => t.host))],
|
|
219
|
+
},
|
|
220
|
+
targets,
|
|
221
|
+
qualifiers,
|
|
222
|
+
knownTerms,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/** The public vocabulary of a workspace (the `entity` block of `--json`). */
|
|
226
|
+
export function citeVocabulary(profile) {
|
|
227
|
+
return buildVocabulary(profile).public;
|
|
228
|
+
}
|
|
229
|
+
/** A sentence's `[start, end)` bounds around one offset, in the original text. */
|
|
230
|
+
function sentenceBounds(text, index) {
|
|
231
|
+
const breaks = new Set([".", "!", "?", ";", "\n", "\u2026"]);
|
|
232
|
+
let start = 0;
|
|
233
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
234
|
+
if (breaks.has(text[i] ?? "")) {
|
|
235
|
+
start = i + 1;
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
let end = text.length;
|
|
240
|
+
for (let i = index; i < text.length; i++) {
|
|
241
|
+
if (breaks.has(text[i] ?? "")) {
|
|
242
|
+
end = i;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return { start, end };
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* The longer capitalised phrase the occurrence sits inside — the text's own
|
|
250
|
+
* competing reading (`DA SEO` → `DA SEO Digital`). Expansion is by adjacent
|
|
251
|
+
* tokens that start with an uppercase letter; it stops at punctuation, so
|
|
252
|
+
* `Pasco, WA` does not expand.
|
|
253
|
+
*/
|
|
254
|
+
function capitalRun(text, start, end) {
|
|
255
|
+
const TOKEN_CHAR = /[\p{L}\p{N}'\u2019-]/u;
|
|
256
|
+
const UPPER = /^\p{Lu}/u;
|
|
257
|
+
let runStart = start;
|
|
258
|
+
let runEnd = end;
|
|
259
|
+
for (;;) {
|
|
260
|
+
if (text[runEnd] !== " ")
|
|
261
|
+
break;
|
|
262
|
+
const first = runEnd + 1;
|
|
263
|
+
if (!UPPER.test(text[first] ?? ""))
|
|
264
|
+
break;
|
|
265
|
+
let tokenEnd = first;
|
|
266
|
+
while (tokenEnd < text.length && TOKEN_CHAR.test(text[tokenEnd] ?? ""))
|
|
267
|
+
tokenEnd++;
|
|
268
|
+
runEnd = tokenEnd;
|
|
269
|
+
}
|
|
270
|
+
for (;;) {
|
|
271
|
+
if (runStart === 0 || text[runStart - 1] !== " ")
|
|
272
|
+
break;
|
|
273
|
+
const tokenEnd = runStart - 1;
|
|
274
|
+
let tokenStart = tokenEnd;
|
|
275
|
+
while (tokenStart > 0 && TOKEN_CHAR.test(text[tokenStart - 1] ?? ""))
|
|
276
|
+
tokenStart--;
|
|
277
|
+
// A capital that only opens a sentence ("Follow daseo") is not a longer
|
|
278
|
+
// proper noun; expanding over it would manufacture a competitor.
|
|
279
|
+
if (isSentenceInitial(text, tokenStart))
|
|
280
|
+
break;
|
|
281
|
+
const token = text.slice(tokenStart, tokenEnd);
|
|
282
|
+
if (token === "" || !UPPER.test(token))
|
|
283
|
+
break;
|
|
284
|
+
runStart = tokenStart;
|
|
285
|
+
}
|
|
286
|
+
return runStart === start && runEnd === end ? undefined : { start: runStart, end: runEnd };
|
|
287
|
+
}
|
|
288
|
+
/** Is the token at `index` the first word of its sentence? */
|
|
289
|
+
function isSentenceInitial(text, index) {
|
|
290
|
+
const breaks = new Set([".", "!", "?", ";", "\n", "\u2026"]);
|
|
291
|
+
let i = index - 1;
|
|
292
|
+
while (i >= 0 && (text[i] === " " || text[i] === '""' || text[i] === "'"))
|
|
293
|
+
i--;
|
|
294
|
+
return i < 0 || breaks.has(text[i] ?? "");
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Match one saved answer against the workspace's declared entity (SPEC §7.4).
|
|
298
|
+
* Pure: the same profile + answer bytes always produce the same result.
|
|
299
|
+
*/
|
|
300
|
+
export function citeMatch(profile, answer) {
|
|
301
|
+
const vocab = buildVocabulary(profile);
|
|
302
|
+
const text = answer.answer;
|
|
303
|
+
const folded = foldForMatch(text);
|
|
304
|
+
const reasons = [];
|
|
305
|
+
// 1. Citation rung: a saved citation on a declared host needs no text match —
|
|
306
|
+
// "cited without naming" is exactly this case.
|
|
307
|
+
const citationSpans = [];
|
|
308
|
+
const seenUrls = new Set();
|
|
309
|
+
for (const citation of answer.citations) {
|
|
310
|
+
const host = hostOf(citation.url);
|
|
311
|
+
const path = pathOf(citation.url);
|
|
312
|
+
if (host === undefined || path === undefined) {
|
|
313
|
+
// A citation the URL parser rejects (a missing scheme is the common case)
|
|
314
|
+
// is NOT a silent "not cited": it is named, and the scheme is never
|
|
315
|
+
// guessed — a dropped citation would change the rate (SPEC §7.4 limit f).
|
|
316
|
+
reasons.push(`url-invalid:${citation.url}`);
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
const declared = vocab.targets.find((target) => sameSite(host, target.host) && pathMatches(path, target.path));
|
|
320
|
+
if (declared === undefined)
|
|
321
|
+
continue;
|
|
322
|
+
if (!seenUrls.has(citation.url)) {
|
|
323
|
+
seenUrls.add(citation.url);
|
|
324
|
+
citationSpans.push({ start: 0, end: 0, kind: "citation-url", url: citation.url });
|
|
325
|
+
}
|
|
326
|
+
reasons.push("citation-url", declared.kind === "identity" ? "identity-domain" : "sameAs-domain");
|
|
327
|
+
}
|
|
328
|
+
// 2. Text rungs: every word-bounded occurrence of every declared term.
|
|
329
|
+
const raw = [];
|
|
330
|
+
const termLists = {
|
|
331
|
+
name: [vocab.public.name],
|
|
332
|
+
alias: vocab.public.aliases,
|
|
333
|
+
handle: vocab.public.handles,
|
|
334
|
+
partial: vocab.public.partials,
|
|
335
|
+
};
|
|
336
|
+
for (const kind of RUNG_ORDER) {
|
|
337
|
+
const list = termLists[kind];
|
|
338
|
+
for (const term of list) {
|
|
339
|
+
for (const occurrence of findTerm(folded, term)) {
|
|
340
|
+
raw.push({
|
|
341
|
+
span: { start: occurrence.start, end: occurrence.end, kind },
|
|
342
|
+
kind: kind,
|
|
343
|
+
term,
|
|
344
|
+
reasons: [RUNG_REASON[kind]],
|
|
345
|
+
cited: true,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// 3. Containment: the longer declared term wins; the shorter keeps its reason
|
|
351
|
+
// but is not a second hit ("DA SEO" inside "DA SEO Digital").
|
|
352
|
+
const ordered = [...raw].sort((a, b) => b.span.end - b.span.start - (a.span.end - a.span.start) ||
|
|
353
|
+
RUNG_RANK[a.kind] - RUNG_RANK[b.kind] ||
|
|
354
|
+
a.span.start - b.span.start ||
|
|
355
|
+
a.span.end - b.span.end);
|
|
356
|
+
const kept = [];
|
|
357
|
+
for (const hit of ordered) {
|
|
358
|
+
const sameSpan = kept.find((k) => k.span.start === hit.span.start && k.span.end === hit.span.end);
|
|
359
|
+
// Same text matched by two rungs: the higher rung already reports it, so the
|
|
360
|
+
// duplicate is dropped without a `longer-name` claim (nothing was shorter).
|
|
361
|
+
if (sameSpan !== undefined)
|
|
362
|
+
continue;
|
|
363
|
+
const container = kept.find((k) => k.span.start <= hit.span.start &&
|
|
364
|
+
k.span.end >= hit.span.end &&
|
|
365
|
+
k.span.end - k.span.start > hit.span.end - hit.span.start);
|
|
366
|
+
if (container !== undefined) {
|
|
367
|
+
reasons.push(`longer-name:${container.term}`);
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
kept.push(hit);
|
|
371
|
+
}
|
|
372
|
+
// 4. Guards — each one says why a hit is NOT a citation.
|
|
373
|
+
for (const hit of kept) {
|
|
374
|
+
const sentence = sentenceBounds(text, hit.span.start);
|
|
375
|
+
const before = foldForMatch(text.slice(sentence.start, hit.span.start));
|
|
376
|
+
const sentenceText = foldForMatch(text.slice(sentence.start, sentence.end));
|
|
377
|
+
const contrast = CONTRAST_MARKERS.find((marker) => termOccursIn(before, marker, 0, before.text.length));
|
|
378
|
+
if (contrast !== undefined) {
|
|
379
|
+
hit.reasons.push("contrast-context");
|
|
380
|
+
hit.cited = false;
|
|
381
|
+
}
|
|
382
|
+
// The one-word guard is the ambiguity decision. `competing` does NOT decide
|
|
383
|
+
// anything on its own: it only NAMES the longer reading the text carries
|
|
384
|
+
// once the hit is already ambiguous, so ordinary prose ("In Ecuador Pasco
|
|
385
|
+
// is a CLI", "… Studio Founder Ana ships") can never be turned into a
|
|
386
|
+
// competitor by an adjacent capital (review F1).
|
|
387
|
+
const singleWord = !/\s/.test(hit.term.trim());
|
|
388
|
+
if (singleWord && hit.kind !== "handle") {
|
|
389
|
+
const qualified = vocab.qualifiers.some((qualifier) => normalizeText(qualifier) !== normalizeText(hit.term) &&
|
|
390
|
+
termOccursIn(sentenceText, qualifier, 0, sentenceText.text.length));
|
|
391
|
+
if (!qualified) {
|
|
392
|
+
hit.reasons.push(`ambiguous-term:${normalizeText(hit.term)}`, "no-qualifier");
|
|
393
|
+
hit.cited = false;
|
|
394
|
+
const run = capitalRun(text, hit.span.start, hit.span.end);
|
|
395
|
+
if (run !== undefined) {
|
|
396
|
+
const phrase = text.slice(run.start, run.end);
|
|
397
|
+
if (!vocab.knownTerms.has(normalizeText(phrase))) {
|
|
398
|
+
hit.reasons.push(`competing:${phrase}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// 5. Project: citations first, then text spans by position; reasons as a set
|
|
405
|
+
// in the fixed contract order.
|
|
406
|
+
const textSpans = [...kept]
|
|
407
|
+
.sort((a, b) => a.span.start - b.span.start ||
|
|
408
|
+
a.span.end - b.span.end ||
|
|
409
|
+
RUNG_RANK[a.kind] - RUNG_RANK[b.kind])
|
|
410
|
+
.map((hit) => hit.span);
|
|
411
|
+
for (const hit of kept)
|
|
412
|
+
reasons.push(...hit.reasons);
|
|
413
|
+
const citedHits = kept.filter((hit) => hit.cited);
|
|
414
|
+
const cited = citationSpans.length > 0 || citedHits.length > 0;
|
|
415
|
+
let confidence = "low";
|
|
416
|
+
if (citationSpans.length > 0 || citedHits.some((hit) => hit.kind === "name"))
|
|
417
|
+
confidence = "high";
|
|
418
|
+
else if (citedHits.some((hit) => hit.kind === "alias" || hit.kind === "handle")) {
|
|
419
|
+
confidence = "medium";
|
|
420
|
+
}
|
|
421
|
+
return {
|
|
422
|
+
cited,
|
|
423
|
+
confidence,
|
|
424
|
+
spans: [...citationSpans, ...textSpans],
|
|
425
|
+
reasons: orderReasons(reasons),
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
/** De-duplicate and order the reason set as the contract declares. */
|
|
429
|
+
function orderReasons(reasons) {
|
|
430
|
+
const rank = (reason) => {
|
|
431
|
+
const index = REASON_ORDER.findIndex((head) => reason === head || reason.startsWith(`${head}:`));
|
|
432
|
+
return index === -1 ? REASON_ORDER.length : index;
|
|
433
|
+
};
|
|
434
|
+
return [...new Set(reasons)].sort((a, b) => rank(a) - rank(b) || byteOrder(a, b));
|
|
435
|
+
}
|
|
436
|
+
/** Exported for tests: the declared host of a URL under the matcher's rule. */
|
|
437
|
+
export function citationHost(url) {
|
|
438
|
+
return hostOf(url);
|
|
439
|
+
}
|
|
440
|
+
//# sourceMappingURL=cite.js.map
|
package/dist/cite.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cite.js","sourceRoot":"","sources":["../src/cite.ts"],"names":[],"mappings":"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"}
|
package/dist/completeness.d.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* evidence claims that carry a source + registry entries (`evidenceItem`)
|
|
15
15
|
* deployment share of trackable units with a ledger record (`ledger`)
|
|
16
16
|
*
|
|
17
|
-
* Policy is parameterized
|
|
17
|
+
* Policy is parameterized: a user says "my target is the
|
|
18
18
|
* GitHub milestone set, not everything" by dropping an item (weight 0) — a
|
|
19
19
|
* parameter, never a code path. No weights are hardcoded outside the catalog.
|
|
20
20
|
*/
|
package/dist/completeness.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* evidence claims that carry a source + registry entries (`evidenceItem`)
|
|
15
15
|
* deployment share of trackable units with a ledger record (`ledger`)
|
|
16
16
|
*
|
|
17
|
-
* Policy is parameterized
|
|
17
|
+
* Policy is parameterized: a user says "my target is the
|
|
18
18
|
* GitHub milestone set, not everything" by dropping an item (weight 0) — a
|
|
19
19
|
* parameter, never a code path. No weights are hardcoded outside the catalog.
|
|
20
20
|
*/
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED by scripts/gen-platforms/gen.mjs from platforms/registry.yaml — DO NOT EDIT BY HAND (#290).
|
|
3
|
+
*
|
|
4
|
+
* The AI crawler policy has exactly one data home: the `ai:` block of
|
|
5
|
+
* `platforms/registry.yaml`, where every entry names the operator's own page
|
|
6
|
+
* and the date it was read. `pasco export ai-policy` renders these rows into
|
|
7
|
+
* robots.txt / llms.txt / AI-POLICY.md; a UA list kept in the CLI would rot
|
|
8
|
+
* without a failing command. Run `pnpm gen:platforms` after editing the
|
|
9
|
+
* registry; CI asserts this file is fresh.
|
|
10
|
+
*/
|
|
11
|
+
/** The two robots.txt groups the policy is expressed as — never one wildcard. */
|
|
12
|
+
export type AiCrawlerFamily = "retrieval" | "training";
|
|
13
|
+
/** One robots.txt token and the evidence behind its classification. */
|
|
14
|
+
export interface AiCrawler {
|
|
15
|
+
/** Registry slug — the entry a reader is pointed at. */
|
|
16
|
+
readonly slug: string;
|
|
17
|
+
/** The robots.txt `User-agent` token, verbatim. */
|
|
18
|
+
readonly ua: string;
|
|
19
|
+
/** retrieval = the output is a citation · training = foundation-model corpus. */
|
|
20
|
+
readonly family: AiCrawlerFamily;
|
|
21
|
+
/** The company/foundation that runs it. */
|
|
22
|
+
readonly operator: string;
|
|
23
|
+
/** That operator's own page documenting the token. */
|
|
24
|
+
readonly source: string;
|
|
25
|
+
/** ISO date `source` was read (the `--check` staleness anchor). */
|
|
26
|
+
readonly as_of: string;
|
|
27
|
+
}
|
|
28
|
+
/** The policy contract version (a consumer refuses a version it does not know). */
|
|
29
|
+
export declare const AI_POLICY_VERSION = 1;
|
|
30
|
+
/** The date the policy was last reviewed (the generated files' dated stamp). */
|
|
31
|
+
export declare const AI_POLICY_AS_OF = "2026-10-27";
|
|
32
|
+
/** The stated position, verbatim from the SPEC §12 M9 floor (gate-checked). */
|
|
33
|
+
export declare const AI_POLICY_STANCE = "**private-first default**: `robots.txt` on published surfaces **blocks** AI-training crawlers (CCBot / vendor AI crawlers) and user data ships **without** an open license; entering corpora or open-licensing data requires the profile owner's explicit opt-in (consent field \u2014 schema work deferred with Q10).";
|
|
34
|
+
/** The crawler rows, in registry order (retrieval first, then training). */
|
|
35
|
+
export declare const AI_CRAWLERS: readonly AiCrawler[];
|
|
36
|
+
//# sourceMappingURL=ai-policy.gen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-policy.gen.d.ts","sourceRoot":"","sources":["../../src/generated/ai-policy.gen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,iFAAiF;AACjF,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,UAAU,CAAC;AAEvD,uEAAuE;AACvE,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC,gFAAgF;AAChF,eAAO,MAAM,eAAe,eAAe,CAAC;AAE5C,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,2TAAsT,CAAC;AAEpV,4EAA4E;AAC5E,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAY3C,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED by scripts/gen-platforms/gen.mjs from platforms/registry.yaml — DO NOT EDIT BY HAND (#290).
|
|
3
|
+
*
|
|
4
|
+
* The AI crawler policy has exactly one data home: the `ai:` block of
|
|
5
|
+
* `platforms/registry.yaml`, where every entry names the operator's own page
|
|
6
|
+
* and the date it was read. `pasco export ai-policy` renders these rows into
|
|
7
|
+
* robots.txt / llms.txt / AI-POLICY.md; a UA list kept in the CLI would rot
|
|
8
|
+
* without a failing command. Run `pnpm gen:platforms` after editing the
|
|
9
|
+
* registry; CI asserts this file is fresh.
|
|
10
|
+
*/
|
|
11
|
+
/** The policy contract version (a consumer refuses a version it does not know). */
|
|
12
|
+
export const AI_POLICY_VERSION = 1;
|
|
13
|
+
/** The date the policy was last reviewed (the generated files' dated stamp). */
|
|
14
|
+
export const AI_POLICY_AS_OF = "2026-10-27";
|
|
15
|
+
/** The stated position, verbatim from the SPEC §12 M9 floor (gate-checked). */
|
|
16
|
+
export const AI_POLICY_STANCE = "**private-first default**: `robots.txt` on published surfaces **blocks** AI-training crawlers (CCBot / vendor AI crawlers) and user data ships **without** an open license; entering corpora or open-licensing data requires the profile owner's explicit opt-in (consent field — schema work deferred with Q10).";
|
|
17
|
+
/** The crawler rows, in registry order (retrieval first, then training). */
|
|
18
|
+
export const AI_CRAWLERS = [
|
|
19
|
+
{ slug: "googlebot", ua: "Googlebot", family: "retrieval", operator: "Google", source: "https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers", as_of: "2026-10-27" },
|
|
20
|
+
{ slug: "oai-searchbot", ua: "OAI-SearchBot", family: "retrieval", operator: "OpenAI", source: "https://developers.openai.com/api/docs/bots", as_of: "2026-10-27" },
|
|
21
|
+
{ slug: "chatgpt-user", ua: "ChatGPT-User", family: "retrieval", operator: "OpenAI", source: "https://developers.openai.com/api/docs/bots", as_of: "2026-10-27" },
|
|
22
|
+
{ slug: "perplexitybot", ua: "PerplexityBot", family: "retrieval", operator: "Perplexity", source: "https://docs.perplexity.ai/docs/resources/perplexity-crawlers", as_of: "2026-10-27" },
|
|
23
|
+
{ slug: "perplexity-user", ua: "Perplexity-User", family: "retrieval", operator: "Perplexity", source: "https://docs.perplexity.ai/docs/resources/perplexity-crawlers", as_of: "2026-10-27" },
|
|
24
|
+
{ slug: "claude-searchbot", ua: "Claude-SearchBot", family: "retrieval", operator: "Anthropic", source: "https://privacy.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler", as_of: "2026-10-27" },
|
|
25
|
+
{ slug: "claude-user", ua: "Claude-User", family: "retrieval", operator: "Anthropic", source: "https://privacy.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler", as_of: "2026-10-27" },
|
|
26
|
+
{ slug: "gptbot", ua: "GPTBot", family: "training", operator: "OpenAI", source: "https://developers.openai.com/api/docs/bots", as_of: "2026-10-27" },
|
|
27
|
+
{ slug: "claudebot", ua: "ClaudeBot", family: "training", operator: "Anthropic", source: "https://privacy.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler", as_of: "2026-10-27" },
|
|
28
|
+
{ slug: "google-extended", ua: "Google-Extended", family: "training", operator: "Google", source: "https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers", as_of: "2026-10-27" },
|
|
29
|
+
{ slug: "ccbot", ua: "CCBot", family: "training", operator: "Common Crawl", source: "https://commoncrawl.org/ccbot", as_of: "2026-10-27" },
|
|
30
|
+
];
|
|
31
|
+
//# sourceMappingURL=ai-policy.gen.js.map
|