@company-semantics/contracts 89.2.0 → 90.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/api/generated-spec-hash.ts +2 -2
- package/src/api/generated.ts +83 -1
- package/src/source-sync/README.md +95 -5
- package/src/source-sync/__tests__/attention-evidence.test.ts +96 -0
- package/src/source-sync/__tests__/barrel.test.ts +39 -0
- package/src/source-sync/__tests__/enumeration.test.ts +160 -0
- package/src/source-sync/__tests__/schemas.test.ts +223 -0
- package/src/source-sync/__tests__/vocabulary.test.ts +104 -5
- package/src/source-sync/attention-evidence.ts +93 -0
- package/src/source-sync/candidate-item.ts +25 -0
- package/src/source-sync/enumeration.ts +152 -0
- package/src/source-sync/index.ts +35 -1
- package/src/source-sync/relevance.ts +85 -11
- package/src/source-sync/vocabulary.ts +37 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@company-semantics/contracts",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "90.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
"guard:decisions-deprecation:json": "npx tsx scripts/ci/decisions-deprecation-guard.ts --json",
|
|
110
110
|
"guard:quick": "sh scripts/ci/run-guard.sh --quick",
|
|
111
111
|
"ci:local": "pnpm typecheck && pnpm lint:md && pnpm guard:test && pnpm guard",
|
|
112
|
+
"verify": "sh scripts/ci/run-verify.sh",
|
|
112
113
|
"guard": "sh scripts/ci/run-guard.sh",
|
|
113
114
|
"guard:test": "NODE_OPTIONS='--max-old-space-size=4096' vitest run scripts/ci/__tests__",
|
|
114
115
|
"release": "npx tsx scripts/release.ts",
|
|
@@ -183,7 +184,7 @@
|
|
|
183
184
|
}
|
|
184
185
|
},
|
|
185
186
|
"lint-staged": {
|
|
186
|
-
"*.ts": "
|
|
187
|
+
"*.ts": "sh scripts/ci/unless-verified.sh tsc 'tsc -b --noEmit'",
|
|
187
188
|
"*.md": "markdownlint-cli2",
|
|
188
189
|
"package.json": "node -e \"JSON.parse(require('fs').readFileSync('package.json'))\""
|
|
189
190
|
},
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit. Run pnpm generate:spec-hash to regenerate.
|
|
2
|
-
export const SPEC_HASH = '
|
|
3
|
-
export const SPEC_HASH_FULL = '
|
|
2
|
+
export const SPEC_HASH = 'ba43b4881a93' as const;
|
|
3
|
+
export const SPEC_HASH_FULL = 'ba43b4881a9318819726dfe0c0465ecae3802951f7f558fec6786a7171195a91' as const;
|
package/src/api/generated.ts
CHANGED
|
@@ -9328,8 +9328,10 @@ export interface components {
|
|
|
9328
9328
|
/** @enum {string} */
|
|
9329
9329
|
classificationState: "unclassified" | "classified";
|
|
9330
9330
|
sourceClass: ("board_deck" | "board_minutes" | "investor_update" | "financial_brief" | "budget_forecast" | "okr_plan" | "annual_plan" | "all_hands" | "unit_strategy" | "roadmap" | "qbr" | "other" | "decoy") | null;
|
|
9331
|
-
documentType: ("board_deck" | "board_minutes" | "strategy_memo" | "planning_doc" | "okr_doc" | "roadmap" | "operating_review" | "all_hands_deck" | "offsite_notes" | "investor_update" | "pitch_deck" | "product_spec" | "research_analysis" | "general_meeting_notes" | "financial_plan" | "financial_actuals" | "equity_admin_record" | "corporate_formation_record" | "corporate_governance_record" | "government_filing" | "equity_agreement" | "commercial_agreement" | "employment_agreement" | "transaction_record" | "personal_document" | "social_event_material" | "coursework" | "empty_template" | "image_or_screenshot" | "unknown") | null;
|
|
9331
|
+
documentType: ("board_deck" | "board_minutes" | "strategy_memo" | "planning_doc" | "okr_doc" | "roadmap" | "operating_review" | "all_hands_deck" | "offsite_notes" | "investor_update" | "pitch_deck" | "product_spec" | "research_analysis" | "general_meeting_notes" | "financial_plan" | "financial_actuals" | "equity_admin_record" | "corporate_formation_record" | "corporate_governance_record" | "government_filing" | "equity_agreement" | "commercial_agreement" | "employment_agreement" | "transaction_record" | "personal_document" | "social_event_material" | "coursework" | "empty_template" | "image_or_screenshot" | "team_charter" | "process_playbook" | "policy_handbook" | "onboarding_guide" | "values_culture" | "positioning_messaging" | "decision_log" | "postmortem" | "metrics_definition" | "operating_cadence" | "unknown") | null;
|
|
9332
9332
|
documentTypeConfidence: number | null;
|
|
9333
|
+
operatingKnowledgeFamily: ("direction" | "operating_model" | "practices" | "identity_market" | "decisions_learning") | null;
|
|
9334
|
+
canonicalPath: string | null;
|
|
9333
9335
|
periodLabel: string | null;
|
|
9334
9336
|
seriesRole: ("current" | "history") | null;
|
|
9335
9337
|
relevance: number;
|
|
@@ -9375,6 +9377,59 @@ export interface components {
|
|
|
9375
9377
|
t1: ("exploit" | "explore") | null;
|
|
9376
9378
|
t2: ("exploit" | "explore") | null;
|
|
9377
9379
|
};
|
|
9380
|
+
attentionEvidence: ({
|
|
9381
|
+
/** @constant */
|
|
9382
|
+
kind: "tree_prior";
|
|
9383
|
+
score: number;
|
|
9384
|
+
folderId: string;
|
|
9385
|
+
source: {
|
|
9386
|
+
producer: string;
|
|
9387
|
+
version: string;
|
|
9388
|
+
};
|
|
9389
|
+
} | {
|
|
9390
|
+
/** @constant */
|
|
9391
|
+
kind: "path_terms";
|
|
9392
|
+
values: string[];
|
|
9393
|
+
source: {
|
|
9394
|
+
producer: string;
|
|
9395
|
+
version: string;
|
|
9396
|
+
};
|
|
9397
|
+
} | {
|
|
9398
|
+
/** @constant */
|
|
9399
|
+
kind: "content_match";
|
|
9400
|
+
values: string[];
|
|
9401
|
+
strength: number;
|
|
9402
|
+
probeId: string;
|
|
9403
|
+
source: {
|
|
9404
|
+
producer: string;
|
|
9405
|
+
version: string;
|
|
9406
|
+
};
|
|
9407
|
+
} | {
|
|
9408
|
+
/** @constant */
|
|
9409
|
+
kind: "breadth";
|
|
9410
|
+
/** @enum {string} */
|
|
9411
|
+
value: "restricted_few" | "group" | "domain" | "anyone" | "unknown";
|
|
9412
|
+
source: {
|
|
9413
|
+
producer: string;
|
|
9414
|
+
version: string;
|
|
9415
|
+
};
|
|
9416
|
+
} | {
|
|
9417
|
+
/** @constant */
|
|
9418
|
+
kind: "recency";
|
|
9419
|
+
score: number;
|
|
9420
|
+
source: {
|
|
9421
|
+
producer: string;
|
|
9422
|
+
version: string;
|
|
9423
|
+
};
|
|
9424
|
+
} | {
|
|
9425
|
+
/** @constant */
|
|
9426
|
+
kind: "mime_prior";
|
|
9427
|
+
score: number;
|
|
9428
|
+
source: {
|
|
9429
|
+
producer: string;
|
|
9430
|
+
version: string;
|
|
9431
|
+
};
|
|
9432
|
+
})[] | null;
|
|
9378
9433
|
included: boolean;
|
|
9379
9434
|
treatmentUnresolved: boolean;
|
|
9380
9435
|
matchReason: string;
|
|
@@ -9465,6 +9520,33 @@ export interface components {
|
|
|
9465
9520
|
coveragePercent: number;
|
|
9466
9521
|
/** @enum {string} */
|
|
9467
9522
|
scanOutcome: "complete" | "budget_exhausted" | "file_ceiling" | "stopped";
|
|
9523
|
+
enumerationCompleteness: ("complete" | "local_budget_truncated" | "provider_incomplete" | "both") | null;
|
|
9524
|
+
rootCoverage: {
|
|
9525
|
+
/** @enum {string} */
|
|
9526
|
+
rootKind: "user" | "shared_drive" | "domain";
|
|
9527
|
+
rootId: string | null;
|
|
9528
|
+
/** @enum {string} */
|
|
9529
|
+
status: "complete" | "local_budget_truncated" | "provider_incomplete" | "both";
|
|
9530
|
+
enumeratedCount: number;
|
|
9531
|
+
observedOldestModifiedTime: string | null;
|
|
9532
|
+
observedNewestModifiedTime: string | null;
|
|
9533
|
+
skippedRanges: {
|
|
9534
|
+
/** Format: date-time */
|
|
9535
|
+
from: string;
|
|
9536
|
+
/** Format: date-time */
|
|
9537
|
+
to: string;
|
|
9538
|
+
}[];
|
|
9539
|
+
}[] | null;
|
|
9540
|
+
stageCounters: {
|
|
9541
|
+
filesEnumerated: number;
|
|
9542
|
+
filesMetadataEligible: number;
|
|
9543
|
+
filesT0Scored: number;
|
|
9544
|
+
filesT1Attended: number;
|
|
9545
|
+
filesPeeked: number;
|
|
9546
|
+
filesClassified: number;
|
|
9547
|
+
filesShown: number;
|
|
9548
|
+
filesRetained: number;
|
|
9549
|
+
} | null;
|
|
9468
9550
|
} | null;
|
|
9469
9551
|
};
|
|
9470
9552
|
SourceSyncApproveResponse: {
|
|
@@ -165,7 +165,15 @@ product policy in the backend decides what that means.
|
|
|
165
165
|
what a file IS — `corporate_formation_record`, never `irrelevant_doc` —
|
|
166
166
|
never how relevant it is. A medium is not a meaning: `image_or_screenshot`
|
|
167
167
|
is graded on its content. `unknown` is a real answer (the model could not
|
|
168
|
-
tell, or two reads disagreed) and is always last.
|
|
168
|
+
tell, or two reads disagreed) and is always last. There are forty: the ten
|
|
169
|
+
operating-knowledge types (`team_charter` … `operating_cadence`, control ADR
|
|
170
|
+
`index-first-operating-knowledge-discovery`) sit just before `unknown`.
|
|
171
|
+
- **Operating-knowledge family is a derived name.**
|
|
172
|
+
`OPERATING_KNOWLEDGE_FAMILIES` (`direction`, `operating_model`, `practices`,
|
|
173
|
+
`identity_market`, `decisions_learning`) is resolved by backend policy from
|
|
174
|
+
the resolved type, like `sourceClass`, and travels as the item's
|
|
175
|
+
`operatingKnowledgeFamily`, which needs a known type. It is not the backend's
|
|
176
|
+
relevance-policy family, which never travels.
|
|
169
177
|
- **The resolved type travels, nothing else.** The candidate item's
|
|
170
178
|
`documentType` and `documentTypeConfidence` (0..1) carry the RESOLVED type,
|
|
171
179
|
after the backend reconciles the T1 and T2 observations. Both are null on an
|
|
@@ -191,6 +199,63 @@ product policy in the backend decides what that means.
|
|
|
191
199
|
is uncertainty, never irrelevance. `peek_confirms` / `peek_contradicts`
|
|
192
200
|
stay for v1-pinned rows.
|
|
193
201
|
|
|
202
|
+
## Enumeration
|
|
203
|
+
|
|
204
|
+
Doctrine: control ADR `index-first-operating-knowledge-discovery`. Vocabulary:
|
|
205
|
+
ADR `operating-knowledge-discovery-vocabulary`. The sets live in
|
|
206
|
+
`enumeration.ts`.
|
|
207
|
+
|
|
208
|
+
- **A partial enumeration is never presented as an index of the corpus.**
|
|
209
|
+
`ENUMERATION_COMPLETENESS` has four values, never a boolean: `complete`,
|
|
210
|
+
`local_budget_truncated` (our ceiling), `provider_incomplete` (the
|
|
211
|
+
provider's incomplete search) and `both`. Only `complete` may be called a
|
|
212
|
+
full index. Any other value means absence is unknown, not negative evidence
|
|
213
|
+
(INV-SOURCESYNC-PARTIAL-ENUMERATION-IS-UNKNOWN).
|
|
214
|
+
- **Per root, never by name.** `RootCoverage` covers one root
|
|
215
|
+
(`ENUMERATION_ROOT_KINDS`: `user`, `shared_drive`, `domain`). It holds the
|
|
216
|
+
shared drive's provider id (null for the other kinds), the root's status and
|
|
217
|
+
count, the observed modified-time bounds (present exactly when it enumerated
|
|
218
|
+
a file) and the skipped ranges (none when it is complete). It never holds a
|
|
219
|
+
drive, folder or file name.
|
|
220
|
+
- **The run's completeness is the combination of its roots.**
|
|
221
|
+
`combineEnumerationCompleteness` is pure: our ceiling anywhere and the
|
|
222
|
+
provider's incompleteness anywhere make `both`, and the run is `complete`
|
|
223
|
+
only when every root is.
|
|
224
|
+
- **Counters name what they did.** `DiscoveryStageCounters` holds
|
|
225
|
+
`filesEnumerated`, `filesMetadataEligible`, `filesT0Scored`,
|
|
226
|
+
`filesT1Attended`, `filesPeeked`, `filesClassified`, `filesShown` and
|
|
227
|
+
`filesRetained`, and the counts narrow from enumerated to shown. A metadata
|
|
228
|
+
count never reads as a content read: there is no `filesIndexed`.
|
|
229
|
+
- **On the discovery summary, all or none.** `enumerationCompleteness`,
|
|
230
|
+
`rootCoverage` (1..64) and `stageCounters` are required and nullable. Either
|
|
231
|
+
all three are present, or all three are null, which means the run predates
|
|
232
|
+
index-first discovery.
|
|
233
|
+
|
|
234
|
+
## Attention evidence
|
|
235
|
+
|
|
236
|
+
Vocabulary: ADR `operating-knowledge-discovery-vocabulary`. The schemas live
|
|
237
|
+
in `attention-evidence.ts`.
|
|
238
|
+
|
|
239
|
+
- **Why a file got T1 attention.** `AttentionEvidence` is an array of at most
|
|
240
|
+
six signals with at most one per `ATTENTION_SIGNAL_KINDS` kind: `tree_prior`
|
|
241
|
+
(a score and the folder's provider `folderId`), `path_terms` (matched
|
|
242
|
+
product terms), `content_match` (matched plan terms, a strength and the
|
|
243
|
+
`probeId`), `breadth` (a `SHARING_BREADTHS` member, so there is no new
|
|
244
|
+
breadth vocabulary), `recency` and `mime_prior` (a score each).
|
|
245
|
+
- **Every signal has provenance.** Each signal carries
|
|
246
|
+
`source: { producer, version }`
|
|
247
|
+
(INV-SOURCESYNC-ATTENTION-EVIDENCE-HAS-PROVENANCE). `producer` is a
|
|
248
|
+
documented lowercase key, not a closed set. The documented keys are
|
|
249
|
+
`lexicon`, `source-discovery-tree-triage`, `source-discovery-plan` and
|
|
250
|
+
`metadata-scorer`.
|
|
251
|
+
- **Terms are vocabulary, never content.** A term is product or plan
|
|
252
|
+
vocabulary that matched. It is never text read from the file and never a
|
|
253
|
+
slice of its name. A folder is named only by its provider id.
|
|
254
|
+
- **Only after T1 attention, never when withheld.** The item's
|
|
255
|
+
`attentionEvidence` and `canonicalPath` (the Tier-1 path) are null when the
|
|
256
|
+
line never received T1 attention, when it is withheld, and for runs before
|
|
257
|
+
index-first discovery.
|
|
258
|
+
|
|
194
259
|
## Public API
|
|
195
260
|
|
|
196
261
|
- `SOURCE_CLASSES` / `SourceClass` — what kind of document a source is.
|
|
@@ -210,12 +275,34 @@ product policy in the backend decides what that means.
|
|
|
210
275
|
`org_admin` or `unit_head`.
|
|
211
276
|
- `DOCUMENT_TYPES` / `DocumentType` / `KnownDocumentType` — what a source is,
|
|
212
277
|
structurally; `KnownDocumentType` excludes `unknown` (see Document type).
|
|
278
|
+
- `OPERATING_KNOWLEDGE_FAMILIES` / `OperatingKnowledgeFamily` — what kind of
|
|
279
|
+
operating knowledge a line is, resolved by the backend (see Document type).
|
|
280
|
+
- `ENUMERATION_COMPLETENESS` / `EnumerationCompleteness` — how completely a
|
|
281
|
+
run or root was enumerated; only `complete` is a full index (see
|
|
282
|
+
Enumeration).
|
|
283
|
+
- `ENUMERATION_ROOT_KINDS` / `EnumerationRootKind` — `user`, `shared_drive` or
|
|
284
|
+
`domain`.
|
|
285
|
+
- `combineEnumerationCompleteness(statuses)` — the pure fold of per-root
|
|
286
|
+
statuses into one.
|
|
287
|
+
- `EnumerationSkippedRangeSchema` — a modified-time range left unenumerated.
|
|
288
|
+
- `RootCoverageSchema` / `RootCoverage` — how far one root's enumeration got.
|
|
289
|
+
- `DiscoveryStageCountersSchema` / `DiscoveryStageCounters` — what each stage
|
|
290
|
+
did, by count, narrowing from enumerated to shown.
|
|
291
|
+
- `ATTENTION_SIGNAL_KINDS` / `AttentionSignalKind` — the kinds of attention
|
|
292
|
+
signal (see Attention evidence).
|
|
293
|
+
- `AttentionSignalSourceSchema` / `AttentionSignalSource` — a signal's
|
|
294
|
+
producer and version.
|
|
295
|
+
- `AttentionSignalSchema` / `AttentionSignal` — one signal: a discriminated
|
|
296
|
+
union on `kind`.
|
|
297
|
+
- `AttentionEvidenceSchema` / `AttentionEvidence` — why a line got T1
|
|
298
|
+
attention: at most one signal per kind.
|
|
213
299
|
- `SourceSyncDiscoveryRunResponseSchema` / `SourceSyncDiscoveryRunResponse` —
|
|
214
300
|
the discovery run started, and the workflow narrating it.
|
|
215
301
|
- `SourceSyncCandidateItemSchema` / `SourceSyncCandidateItem` — one source
|
|
216
302
|
proposed for one target document, with the server's `included` and the
|
|
217
303
|
resolved `documentType` / `documentTypeConfidence` (null when unclassified
|
|
218
|
-
or v1-pinned)
|
|
304
|
+
or v1-pinned), `operatingKnowledgeFamily`, `canonicalPath` and
|
|
305
|
+
`attentionEvidence` (null before index-first discovery).
|
|
219
306
|
- `SourceSyncCandidateSetResponseSchema` / `SourceSyncCandidateSetResponse` —
|
|
220
307
|
the draft set under review: its revision, items, presented questions,
|
|
221
308
|
distinct-file `totals` and cost estimate.
|
|
@@ -307,7 +394,10 @@ product policy in the backend decides what that means.
|
|
|
307
394
|
|
|
308
395
|
`rules.ts` imports only `zod`, `../api/primitives` and `./vocabulary`.
|
|
309
396
|
`upkeep.ts` and `reach.ts` import only `zod` and `../api/primitives`.
|
|
310
|
-
`candidate-item.ts` imports only `zod`, `../api/primitives`, `./vocabulary
|
|
311
|
-
and `./
|
|
312
|
-
`relevance.ts` imports only `zod`.
|
|
397
|
+
`candidate-item.ts` imports only `zod`, `../api/primitives`, `./vocabulary`,
|
|
398
|
+
`./relevance` and `./attention-evidence`.
|
|
399
|
+
`relevance.ts` imports only `zod` and `./enumeration`.
|
|
400
|
+
`enumeration.ts` imports only `zod` and `../api/primitives` (never
|
|
401
|
+
`./relevance`, so there is no cycle).
|
|
402
|
+
`attention-evidence.ts` imports only `zod` and `./vocabulary`.
|
|
313
403
|
`vocabulary.ts` itself has no imports.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attention evidence tests.
|
|
3
|
+
*
|
|
4
|
+
* INVARIANTS TESTED:
|
|
5
|
+
* - Every attention signal kind is accepted with its provenance; empty evidence
|
|
6
|
+
* is accepted
|
|
7
|
+
* - An attention signal kind appears at most once
|
|
8
|
+
* - A tree prior names its folder by provider id; a content match names its probe
|
|
9
|
+
* - Every signal carries a lowercase producer key and a version
|
|
10
|
+
* - Breadth reuses the sharing breadth vocabulary
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, it, expect } from "vitest";
|
|
14
|
+
|
|
15
|
+
import { AttentionEvidenceSchema } from "../attention-evidence";
|
|
16
|
+
|
|
17
|
+
const source = { producer: "lexicon", version: "3" };
|
|
18
|
+
const everyKind = [
|
|
19
|
+
{
|
|
20
|
+
kind: "tree_prior",
|
|
21
|
+
score: 0.72,
|
|
22
|
+
folderId: "0AbcFolder",
|
|
23
|
+
source: { producer: "source-discovery-tree-triage", version: "1" },
|
|
24
|
+
},
|
|
25
|
+
{ kind: "path_terms", values: ["planning", "qbr"], source },
|
|
26
|
+
{
|
|
27
|
+
kind: "content_match",
|
|
28
|
+
values: ["operating review"],
|
|
29
|
+
strength: 0.8,
|
|
30
|
+
probeId: "practices_1",
|
|
31
|
+
source: { producer: "source-discovery-plan", version: "2" },
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
kind: "breadth",
|
|
35
|
+
value: "domain",
|
|
36
|
+
source: { producer: "metadata-scorer", version: "4" },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
kind: "recency",
|
|
40
|
+
score: 0.31,
|
|
41
|
+
source: { producer: "metadata-scorer", version: "4" },
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
kind: "mime_prior",
|
|
45
|
+
score: 0.6,
|
|
46
|
+
source: { producer: "metadata-scorer", version: "4" },
|
|
47
|
+
},
|
|
48
|
+
] as const;
|
|
49
|
+
|
|
50
|
+
describe("AttentionEvidenceSchema", () => {
|
|
51
|
+
it("accepts one entry of every attention signal kind with its provenance", () => {
|
|
52
|
+
expect(AttentionEvidenceSchema.safeParse(everyKind).success).toBe(true);
|
|
53
|
+
expect(AttentionEvidenceSchema.safeParse([]).success).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("an attention signal kind appears at most once", () => {
|
|
57
|
+
expect(
|
|
58
|
+
AttentionEvidenceSchema.safeParse([everyKind[1], everyKind[1]]).success,
|
|
59
|
+
).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("a tree prior names the folder and a content match names the probe", () => {
|
|
63
|
+
const { folderId: _f, ...noFolder } = everyKind[0];
|
|
64
|
+
const { probeId: _p, ...noProbe } = everyKind[2];
|
|
65
|
+
expect(AttentionEvidenceSchema.safeParse([noFolder]).success).toBe(false);
|
|
66
|
+
expect(AttentionEvidenceSchema.safeParse([noProbe]).success).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("refuses an attention signal without a producer version", () => {
|
|
70
|
+
expect(
|
|
71
|
+
AttentionEvidenceSchema.safeParse([
|
|
72
|
+
{
|
|
73
|
+
kind: "recency",
|
|
74
|
+
score: 0.3,
|
|
75
|
+
source: { producer: "metadata-scorer" },
|
|
76
|
+
},
|
|
77
|
+
]).success,
|
|
78
|
+
).toBe(false);
|
|
79
|
+
expect(
|
|
80
|
+
AttentionEvidenceSchema.safeParse([
|
|
81
|
+
{
|
|
82
|
+
kind: "recency",
|
|
83
|
+
score: 0.3,
|
|
84
|
+
source: { producer: "Has Spaces", version: "1" },
|
|
85
|
+
},
|
|
86
|
+
]).success,
|
|
87
|
+
).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("breadth reuses the sharing breadth vocabulary", () => {
|
|
91
|
+
expect(
|
|
92
|
+
AttentionEvidenceSchema.safeParse([{ ...everyKind[3], value: "public" }])
|
|
93
|
+
.success,
|
|
94
|
+
).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
* the same binding.
|
|
21
21
|
* - `DOCUMENT_TYPES` is reachable from the root as the same binding, and its
|
|
22
22
|
* two types are named by the barrel.
|
|
23
|
+
* - Every index-first discovery name (operating-knowledge families, the
|
|
24
|
+
* enumeration vocabulary, attention evidence) is reachable from the root as
|
|
25
|
+
* the same binding, and its types are named by the barrel.
|
|
23
26
|
* - `ACTION_ITEM_KINDS` at the root carries `sourceSync.approval_pending`.
|
|
24
27
|
* - The root re-exports the domain barrel explicitly.
|
|
25
28
|
*
|
|
@@ -69,7 +72,9 @@ import type {
|
|
|
69
72
|
SourceSyncStandingOrder,
|
|
70
73
|
SourceSyncStandingOrdersResponse,
|
|
71
74
|
} from "../../index";
|
|
75
|
+
import * as attentionEvidence from "../attention-evidence";
|
|
72
76
|
import * as candidateItem from "../candidate-item";
|
|
77
|
+
import * as enumeration from "../enumeration";
|
|
73
78
|
import * as reach from "../reach";
|
|
74
79
|
import * as relevance from "../relevance";
|
|
75
80
|
import * as rules from "../rules";
|
|
@@ -260,6 +265,40 @@ describe("source-sync Release C package surface", () => {
|
|
|
260
265
|
expect([...barrelTypeExports]).toContain("KnownDocumentType");
|
|
261
266
|
});
|
|
262
267
|
|
|
268
|
+
it("every index-first discovery name is reachable from the root as the same binding", () => {
|
|
269
|
+
const root = rootBarrel as Record<string, unknown>;
|
|
270
|
+
for (const [name, module] of [
|
|
271
|
+
["OPERATING_KNOWLEDGE_FAMILIES", vocabulary],
|
|
272
|
+
["ENUMERATION_COMPLETENESS", enumeration],
|
|
273
|
+
["ENUMERATION_ROOT_KINDS", enumeration],
|
|
274
|
+
["combineEnumerationCompleteness", enumeration],
|
|
275
|
+
["EnumerationSkippedRangeSchema", enumeration],
|
|
276
|
+
["RootCoverageSchema", enumeration],
|
|
277
|
+
["DiscoveryStageCountersSchema", enumeration],
|
|
278
|
+
["ATTENTION_SIGNAL_KINDS", attentionEvidence],
|
|
279
|
+
["AttentionSignalSourceSchema", attentionEvidence],
|
|
280
|
+
["AttentionSignalSchema", attentionEvidence],
|
|
281
|
+
["AttentionEvidenceSchema", attentionEvidence],
|
|
282
|
+
] as const) {
|
|
283
|
+
const declared = (module as Record<string, unknown>)[name];
|
|
284
|
+
expect(declared, `${name} is declared`).toBeDefined();
|
|
285
|
+
expect(root[name], `${name} at the root`).toBe(declared);
|
|
286
|
+
}
|
|
287
|
+
for (const type of [
|
|
288
|
+
"OperatingKnowledgeFamily",
|
|
289
|
+
"EnumerationCompleteness",
|
|
290
|
+
"EnumerationRootKind",
|
|
291
|
+
"RootCoverage",
|
|
292
|
+
"DiscoveryStageCounters",
|
|
293
|
+
"AttentionSignalKind",
|
|
294
|
+
"AttentionSignalSource",
|
|
295
|
+
"AttentionSignal",
|
|
296
|
+
"AttentionEvidence",
|
|
297
|
+
]) {
|
|
298
|
+
expect([...barrelTypeExports]).toContain(type);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
|
|
263
302
|
it("exposes sourceSync.approval_pending in ACTION_ITEM_KINDS at the root", () => {
|
|
264
303
|
expect(rootBarrel.ACTION_ITEM_KINDS).toContain(
|
|
265
304
|
"sourceSync.approval_pending",
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Index-first enumeration vocabulary tests.
|
|
3
|
+
*
|
|
4
|
+
* INVARIANTS TESTED:
|
|
5
|
+
* - Root statuses combine so that only every root complete is `complete`, and
|
|
6
|
+
* our ceiling plus the provider's incompleteness is `both`
|
|
7
|
+
* - A complete root skips nothing; a root id names exactly a shared drive
|
|
8
|
+
* - A skipped range never ends before it starts
|
|
9
|
+
* - Observed modified times are present exactly when a root enumerated a file
|
|
10
|
+
* - Stage counters are non-negative and narrow from enumerated to shown
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, it, expect } from "vitest";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
combineEnumerationCompleteness,
|
|
17
|
+
DiscoveryStageCountersSchema,
|
|
18
|
+
EnumerationSkippedRangeSchema,
|
|
19
|
+
RootCoverageSchema,
|
|
20
|
+
} from "../enumeration";
|
|
21
|
+
|
|
22
|
+
function root(overrides: Record<string, unknown> = {}) {
|
|
23
|
+
return {
|
|
24
|
+
rootKind: "user",
|
|
25
|
+
rootId: null,
|
|
26
|
+
status: "complete",
|
|
27
|
+
enumeratedCount: 3,
|
|
28
|
+
observedOldestModifiedTime: "2025-01-01T00:00:00.000Z",
|
|
29
|
+
observedNewestModifiedTime: "2026-09-30T00:00:00.000Z",
|
|
30
|
+
skippedRanges: [],
|
|
31
|
+
...overrides,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function counters(overrides: Record<string, unknown> = {}) {
|
|
36
|
+
return {
|
|
37
|
+
filesEnumerated: 1000,
|
|
38
|
+
filesMetadataEligible: 800,
|
|
39
|
+
filesT0Scored: 600,
|
|
40
|
+
filesT1Attended: 120,
|
|
41
|
+
filesPeeked: 40,
|
|
42
|
+
filesClassified: 200,
|
|
43
|
+
filesShown: 25,
|
|
44
|
+
filesRetained: 30,
|
|
45
|
+
...overrides,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const RANGE = {
|
|
50
|
+
from: "2024-01-01T00:00:00.000Z",
|
|
51
|
+
to: "2024-06-30T00:00:00.000Z",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
describe("enumeration", () => {
|
|
55
|
+
it("combines root statuses into one enumeration completeness", () => {
|
|
56
|
+
expect(combineEnumerationCompleteness(["complete", "complete"])).toBe(
|
|
57
|
+
"complete",
|
|
58
|
+
);
|
|
59
|
+
expect(
|
|
60
|
+
combineEnumerationCompleteness(["complete", "local_budget_truncated"]),
|
|
61
|
+
).toBe("local_budget_truncated");
|
|
62
|
+
expect(
|
|
63
|
+
combineEnumerationCompleteness(["provider_incomplete", "complete"]),
|
|
64
|
+
).toBe("provider_incomplete");
|
|
65
|
+
expect(
|
|
66
|
+
combineEnumerationCompleteness([
|
|
67
|
+
"local_budget_truncated",
|
|
68
|
+
"provider_incomplete",
|
|
69
|
+
]),
|
|
70
|
+
).toBe("both");
|
|
71
|
+
expect(combineEnumerationCompleteness(["both"])).toBe("both");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("a complete root skips nothing", () => {
|
|
75
|
+
expect(RootCoverageSchema.safeParse(root()).success).toBe(true);
|
|
76
|
+
expect(
|
|
77
|
+
RootCoverageSchema.safeParse(root({ skippedRanges: [RANGE] })).success,
|
|
78
|
+
).toBe(false);
|
|
79
|
+
expect(
|
|
80
|
+
RootCoverageSchema.safeParse(
|
|
81
|
+
root({ status: "local_budget_truncated", skippedRanges: [RANGE] }),
|
|
82
|
+
).success,
|
|
83
|
+
).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("a root id names exactly a shared drive", () => {
|
|
87
|
+
expect(
|
|
88
|
+
RootCoverageSchema.safeParse(root({ rootId: "0AbCdEf" })).success,
|
|
89
|
+
).toBe(false);
|
|
90
|
+
expect(
|
|
91
|
+
RootCoverageSchema.safeParse(root({ rootKind: "shared_drive" })).success,
|
|
92
|
+
).toBe(false);
|
|
93
|
+
expect(
|
|
94
|
+
RootCoverageSchema.safeParse(
|
|
95
|
+
root({ rootKind: "shared_drive", rootId: "0AbCdEf" }),
|
|
96
|
+
).success,
|
|
97
|
+
).toBe(true);
|
|
98
|
+
expect(
|
|
99
|
+
RootCoverageSchema.safeParse(root({ rootKind: "domain" })).success,
|
|
100
|
+
).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("refuses a skipped range that ends before it starts", () => {
|
|
104
|
+
expect(EnumerationSkippedRangeSchema.safeParse(RANGE).success).toBe(true);
|
|
105
|
+
expect(
|
|
106
|
+
EnumerationSkippedRangeSchema.safeParse({
|
|
107
|
+
from: RANGE.to,
|
|
108
|
+
to: RANGE.from,
|
|
109
|
+
}).success,
|
|
110
|
+
).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("an empty root has no observed modified times", () => {
|
|
114
|
+
expect(
|
|
115
|
+
RootCoverageSchema.safeParse(root({ enumeratedCount: 0 })).success,
|
|
116
|
+
).toBe(false);
|
|
117
|
+
expect(
|
|
118
|
+
RootCoverageSchema.safeParse(
|
|
119
|
+
root({
|
|
120
|
+
enumeratedCount: 0,
|
|
121
|
+
observedOldestModifiedTime: null,
|
|
122
|
+
observedNewestModifiedTime: null,
|
|
123
|
+
}),
|
|
124
|
+
).success,
|
|
125
|
+
).toBe(true);
|
|
126
|
+
expect(
|
|
127
|
+
RootCoverageSchema.safeParse(root({ observedNewestModifiedTime: null }))
|
|
128
|
+
.success,
|
|
129
|
+
).toBe(false);
|
|
130
|
+
expect(
|
|
131
|
+
RootCoverageSchema.safeParse(
|
|
132
|
+
root({
|
|
133
|
+
observedOldestModifiedTime: "2026-09-30T00:00:00.000Z",
|
|
134
|
+
observedNewestModifiedTime: "2025-01-01T00:00:00.000Z",
|
|
135
|
+
}),
|
|
136
|
+
).success,
|
|
137
|
+
).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("stage counters narrow from enumerated to shown", () => {
|
|
141
|
+
expect(DiscoveryStageCountersSchema.safeParse(counters()).success).toBe(
|
|
142
|
+
true,
|
|
143
|
+
);
|
|
144
|
+
expect(
|
|
145
|
+
DiscoveryStageCountersSchema.safeParse(counters({ filesPeeked: 121 }))
|
|
146
|
+
.success,
|
|
147
|
+
).toBe(false);
|
|
148
|
+
expect(
|
|
149
|
+
DiscoveryStageCountersSchema.safeParse(counters({ filesShown: 31 }))
|
|
150
|
+
.success,
|
|
151
|
+
).toBe(false);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("refuses negative stage counters", () => {
|
|
155
|
+
expect(
|
|
156
|
+
DiscoveryStageCountersSchema.safeParse(counters({ filesEnumerated: -1 }))
|
|
157
|
+
.success,
|
|
158
|
+
).toBe(false);
|
|
159
|
+
});
|
|
160
|
+
});
|