@company-semantics/contracts 89.1.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 +7 -5
- package/src/api/generated-spec-hash.ts +2 -2
- package/src/api/generated.ts +323 -2
- package/src/generated/openapi-routes.ts +4 -0
- 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
|
@@ -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
|
+
});
|
|
@@ -21,6 +21,13 @@
|
|
|
21
21
|
* - A candidate patch changes exactly one thing: bringing a line into review never
|
|
22
22
|
* also commits a treatment, and a patch can never hide a line.
|
|
23
23
|
* - The set response's discovery block is required and null before any completed run.
|
|
24
|
+
* - Index-first discovery (control ADR index-first-operating-knowledge-discovery): an
|
|
25
|
+
* item's operating-knowledge family, canonical path and attention evidence are
|
|
26
|
+
* REQUIRED nullable keys; a family needs a known document type; evidence and a path
|
|
27
|
+
* exist only on a line T1 attended and never on a withheld line.
|
|
28
|
+
* - The discovery block's enumeration fields are all present or all absent, and the
|
|
29
|
+
* run's completeness is the combination of its roots' — a truncated run never
|
|
30
|
+
* claims `complete`.
|
|
24
31
|
*/
|
|
25
32
|
|
|
26
33
|
import { describe, expect, it } from "vitest";
|
|
@@ -59,6 +66,8 @@ function candidateItem(overrides: Record<string, unknown> = {}) {
|
|
|
59
66
|
sourceClass: "board_deck",
|
|
60
67
|
documentType: null,
|
|
61
68
|
documentTypeConfidence: null,
|
|
69
|
+
operatingKnowledgeFamily: null,
|
|
70
|
+
canonicalPath: null,
|
|
62
71
|
periodLabel: "Q3 2026",
|
|
63
72
|
seriesRole: "current",
|
|
64
73
|
relevance: 0.92,
|
|
@@ -74,6 +83,7 @@ function candidateItem(overrides: Record<string, unknown> = {}) {
|
|
|
74
83
|
relevanceReasons: [],
|
|
75
84
|
targetAudience: "org_wide",
|
|
76
85
|
attention: { t1: null, t2: null },
|
|
86
|
+
attentionEvidence: null,
|
|
77
87
|
included: true,
|
|
78
88
|
treatmentUnresolved: false,
|
|
79
89
|
matchReason: "A board deck for the current quarter.",
|
|
@@ -143,6 +153,9 @@ function candidateSet(overrides: Record<string, unknown> = {}) {
|
|
|
143
153
|
filesDropped: 240,
|
|
144
154
|
coveragePercent: 87,
|
|
145
155
|
scanOutcome: "complete",
|
|
156
|
+
enumerationCompleteness: null,
|
|
157
|
+
rootCoverage: null,
|
|
158
|
+
stageCounters: null,
|
|
146
159
|
},
|
|
147
160
|
...overrides,
|
|
148
161
|
};
|
|
@@ -575,6 +588,111 @@ describe("candidate relevance", () => {
|
|
|
575
588
|
});
|
|
576
589
|
});
|
|
577
590
|
|
|
591
|
+
describe("index-first discovery item fields", () => {
|
|
592
|
+
const evidence = [
|
|
593
|
+
{
|
|
594
|
+
kind: "path_terms",
|
|
595
|
+
values: ["playbook"],
|
|
596
|
+
source: { producer: "lexicon", version: "3" },
|
|
597
|
+
},
|
|
598
|
+
];
|
|
599
|
+
|
|
600
|
+
it("an item carries its operating-knowledge family, canonical path and attention evidence", () => {
|
|
601
|
+
const parsed = SourceSyncCandidateItemSchema.safeParse(
|
|
602
|
+
candidateItem({
|
|
603
|
+
documentType: "process_playbook",
|
|
604
|
+
documentTypeConfidence: 0.88,
|
|
605
|
+
operatingKnowledgeFamily: "practices",
|
|
606
|
+
canonicalPath: "Product/How we work",
|
|
607
|
+
attention: { t1: "exploit", t2: null },
|
|
608
|
+
attentionEvidence: evidence,
|
|
609
|
+
}),
|
|
610
|
+
);
|
|
611
|
+
expect(parsed.success).toBe(true);
|
|
612
|
+
expect(parsed.data?.operatingKnowledgeFamily).toBe("practices");
|
|
613
|
+
expect(parsed.data?.canonicalPath).toBe("Product/How we work");
|
|
614
|
+
expect(parsed.data?.attentionEvidence).toEqual(evidence);
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
it("an item from before index-first discovery has no family, no path and no evidence", () => {
|
|
618
|
+
const parsed = SourceSyncCandidateItemSchema.safeParse(candidateItem());
|
|
619
|
+
expect(parsed.success).toBe(true);
|
|
620
|
+
expect(parsed.data?.operatingKnowledgeFamily).toBeNull();
|
|
621
|
+
expect(parsed.data?.canonicalPath).toBeNull();
|
|
622
|
+
expect(parsed.data?.attentionEvidence).toBeNull();
|
|
623
|
+
for (const key of [
|
|
624
|
+
"operatingKnowledgeFamily",
|
|
625
|
+
"canonicalPath",
|
|
626
|
+
"attentionEvidence",
|
|
627
|
+
]) {
|
|
628
|
+
const item: Record<string, unknown> = candidateItem();
|
|
629
|
+
delete item[key];
|
|
630
|
+
expect(SourceSyncCandidateItemSchema.safeParse(item).success).toBe(false);
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
it("an operating-knowledge family needs a known document type", () => {
|
|
635
|
+
for (const [documentType, documentTypeConfidence] of [
|
|
636
|
+
[null, null],
|
|
637
|
+
["unknown", null],
|
|
638
|
+
] as const) {
|
|
639
|
+
const parsed = SourceSyncCandidateItemSchema.safeParse(
|
|
640
|
+
candidateItem({
|
|
641
|
+
documentType,
|
|
642
|
+
documentTypeConfidence,
|
|
643
|
+
operatingKnowledgeFamily: "practices",
|
|
644
|
+
}),
|
|
645
|
+
);
|
|
646
|
+
expect(parsed.success).toBe(false);
|
|
647
|
+
expect(parsed.error?.issues[0]?.message).toBe(
|
|
648
|
+
"an operating-knowledge family needs a known document type",
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
it("a withheld line carries no attention evidence and no path", () => {
|
|
654
|
+
for (const claim of [
|
|
655
|
+
{ attentionEvidence: evidence },
|
|
656
|
+
{ canonicalPath: "Finance/Board" },
|
|
657
|
+
]) {
|
|
658
|
+
const parsed = SourceSyncCandidateItemSchema.safeParse(
|
|
659
|
+
candidateItem({
|
|
660
|
+
withheld: true,
|
|
661
|
+
attention: { t1: "exploit", t2: null },
|
|
662
|
+
...claim,
|
|
663
|
+
}),
|
|
664
|
+
);
|
|
665
|
+
expect(parsed.success).toBe(false);
|
|
666
|
+
expect(parsed.error?.issues[0]?.message).toBe(
|
|
667
|
+
"a withheld line carries no attention evidence and no path",
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
it("attention evidence exists only on a line T1 attended", () => {
|
|
673
|
+
const parsed = SourceSyncCandidateItemSchema.safeParse(
|
|
674
|
+
candidateItem({
|
|
675
|
+
attention: { t1: null, t2: "explore" },
|
|
676
|
+
attentionEvidence: evidence,
|
|
677
|
+
}),
|
|
678
|
+
);
|
|
679
|
+
expect(parsed.success).toBe(false);
|
|
680
|
+
expect(parsed.error?.issues[0]?.message).toBe(
|
|
681
|
+
"attention evidence exists only on a line T1 attended",
|
|
682
|
+
);
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
it("a canonical path exists only on a line T1 attended", () => {
|
|
686
|
+
const parsed = SourceSyncCandidateItemSchema.safeParse(
|
|
687
|
+
candidateItem({ canonicalPath: "Product/How we work" }),
|
|
688
|
+
);
|
|
689
|
+
expect(parsed.success).toBe(false);
|
|
690
|
+
expect(parsed.error?.issues[0]?.message).toBe(
|
|
691
|
+
"a canonical path exists only on a line T1 attended",
|
|
692
|
+
);
|
|
693
|
+
});
|
|
694
|
+
});
|
|
695
|
+
|
|
578
696
|
describe("SourceSyncCandidateItemPatchSchema", () => {
|
|
579
697
|
it("bring into review is a patch of visibility alone", () => {
|
|
580
698
|
expect(
|
|
@@ -631,6 +749,111 @@ describe("SourceSyncCandidateSetResponseSchema discovery", () => {
|
|
|
631
749
|
).toBe(false);
|
|
632
750
|
}
|
|
633
751
|
});
|
|
752
|
+
|
|
753
|
+
const rootEntry = (status: string, rootId: string | null = null) => ({
|
|
754
|
+
rootKind: rootId === null ? "user" : "shared_drive",
|
|
755
|
+
rootId,
|
|
756
|
+
status,
|
|
757
|
+
enumeratedCount: 3,
|
|
758
|
+
observedOldestModifiedTime: "2024-01-01T00:00:00Z",
|
|
759
|
+
observedNewestModifiedTime: "2026-09-01T00:00:00Z",
|
|
760
|
+
skippedRanges: [],
|
|
761
|
+
});
|
|
762
|
+
const stageCounters = {
|
|
763
|
+
filesEnumerated: 100000,
|
|
764
|
+
filesMetadataEligible: 60000,
|
|
765
|
+
filesT0Scored: 60000,
|
|
766
|
+
filesT1Attended: 400,
|
|
767
|
+
filesPeeked: 120,
|
|
768
|
+
filesClassified: 300,
|
|
769
|
+
filesShown: 12,
|
|
770
|
+
filesRetained: 40,
|
|
771
|
+
};
|
|
772
|
+
const withEnumeration = (enumeration: Record<string, unknown>) =>
|
|
773
|
+
candidateSet({
|
|
774
|
+
discovery: { ...candidateSet().discovery, ...enumeration },
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
it("a discovery block from before index-first discovery has no enumeration fields", () => {
|
|
778
|
+
const parsed =
|
|
779
|
+
SourceSyncCandidateSetResponseSchema.safeParse(candidateSet());
|
|
780
|
+
expect(parsed.success).toBe(true);
|
|
781
|
+
expect(parsed.data?.discovery?.enumerationCompleteness).toBeNull();
|
|
782
|
+
expect(parsed.data?.discovery?.rootCoverage).toBeNull();
|
|
783
|
+
expect(parsed.data?.discovery?.stageCounters).toBeNull();
|
|
784
|
+
for (const key of [
|
|
785
|
+
"enumerationCompleteness",
|
|
786
|
+
"rootCoverage",
|
|
787
|
+
"stageCounters",
|
|
788
|
+
]) {
|
|
789
|
+
const discovery: Record<string, unknown> = {
|
|
790
|
+
...candidateSet().discovery,
|
|
791
|
+
};
|
|
792
|
+
delete discovery[key];
|
|
793
|
+
expect(
|
|
794
|
+
SourceSyncCandidateSetResponseSchema.safeParse(
|
|
795
|
+
candidateSet({ discovery }),
|
|
796
|
+
).success,
|
|
797
|
+
).toBe(false);
|
|
798
|
+
}
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
it("enumeration fields are all present or all absent", () => {
|
|
802
|
+
expect(
|
|
803
|
+
SourceSyncCandidateSetResponseSchema.safeParse(
|
|
804
|
+
withEnumeration({
|
|
805
|
+
enumerationCompleteness: "complete",
|
|
806
|
+
rootCoverage: [rootEntry("complete")],
|
|
807
|
+
stageCounters,
|
|
808
|
+
}),
|
|
809
|
+
).success,
|
|
810
|
+
).toBe(true);
|
|
811
|
+
for (const partial of [
|
|
812
|
+
{ enumerationCompleteness: "complete" },
|
|
813
|
+
{ enumerationCompleteness: "complete", stageCounters },
|
|
814
|
+
{ rootCoverage: [rootEntry("complete")], stageCounters },
|
|
815
|
+
]) {
|
|
816
|
+
const parsed = SourceSyncCandidateSetResponseSchema.safeParse(
|
|
817
|
+
withEnumeration(partial),
|
|
818
|
+
);
|
|
819
|
+
expect(parsed.success).toBe(false);
|
|
820
|
+
expect(parsed.error?.issues[0]?.message).toBe(
|
|
821
|
+
"enumeration fields are all present or all absent",
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
it("enumeration completeness is the combination of its roots", () => {
|
|
827
|
+
const rootCoverage = [
|
|
828
|
+
rootEntry("complete"),
|
|
829
|
+
rootEntry("local_budget_truncated", "0AbCdEfGhIjK"),
|
|
830
|
+
];
|
|
831
|
+
const claimsComplete = SourceSyncCandidateSetResponseSchema.safeParse(
|
|
832
|
+
withEnumeration({
|
|
833
|
+
enumerationCompleteness: "complete",
|
|
834
|
+
rootCoverage,
|
|
835
|
+
stageCounters,
|
|
836
|
+
}),
|
|
837
|
+
);
|
|
838
|
+
expect(claimsComplete.success).toBe(false);
|
|
839
|
+
expect(claimsComplete.error?.issues[0]?.message).toBe(
|
|
840
|
+
"enumeration completeness is the combination of its roots",
|
|
841
|
+
);
|
|
842
|
+
const truncated = SourceSyncCandidateSetResponseSchema.safeParse(
|
|
843
|
+
withEnumeration({
|
|
844
|
+
enumerationCompleteness: "local_budget_truncated",
|
|
845
|
+
rootCoverage,
|
|
846
|
+
stageCounters,
|
|
847
|
+
}),
|
|
848
|
+
);
|
|
849
|
+
expect(truncated.success).toBe(true);
|
|
850
|
+
expect(truncated.data?.discovery?.stageCounters?.filesEnumerated).toBe(
|
|
851
|
+
100000,
|
|
852
|
+
);
|
|
853
|
+
expect(truncated.data?.discovery?.enumerationCompleteness).not.toBe(
|
|
854
|
+
"complete",
|
|
855
|
+
);
|
|
856
|
+
});
|
|
634
857
|
});
|
|
635
858
|
|
|
636
859
|
describe("SourceSyncDiscoveryRunResponseSchema", () => {
|
|
@@ -6,18 +6,31 @@
|
|
|
6
6
|
* order.
|
|
7
7
|
*
|
|
8
8
|
* INVARIANTS TESTED:
|
|
9
|
-
* - Each of the twenty-
|
|
10
|
-
* relevance) has exactly the members this release
|
|
9
|
+
* - Each of the twenty-five closed sets (eleven Source Sync, thirteen discovery
|
|
10
|
+
* relevance, one attention evidence) has exactly the members this release
|
|
11
|
+
* fixes
|
|
11
12
|
* - `decoy` is a source class; `unknown` is a sharing breadth
|
|
13
|
+
* - OPERATING_KNOWLEDGE_FAMILIES names exactly the five families
|
|
12
14
|
* - No member string appears in two sets
|
|
13
15
|
* - The four relevance reason code sets are pairwise disjoint
|
|
14
|
-
* - DOCUMENT_TYPES has exactly its
|
|
16
|
+
* - DOCUMENT_TYPES has exactly its forty members, the ten operating-knowledge
|
|
17
|
+
* types immediately before `unknown`, `unknown` last; it sits
|
|
15
18
|
* OUTSIDE the disjointness table and shares a word with another set only
|
|
16
19
|
* where pinned (a structural name on a separate axis)
|
|
20
|
+
* - ENUMERATION_COMPLETENESS and ENUMERATION_ROOT_KINDS sit OUTSIDE the
|
|
21
|
+
* disjointness table: `complete` is also a scan outcome and `domain` a
|
|
22
|
+
* sharing breadth (same word, separate axis), pinned exactly
|
|
17
23
|
*/
|
|
18
24
|
|
|
19
25
|
import { describe, it, expect } from "vitest";
|
|
20
26
|
|
|
27
|
+
import { ATTENTION_SIGNAL_KINDS } from "../attention-evidence";
|
|
28
|
+
|
|
29
|
+
import {
|
|
30
|
+
ENUMERATION_COMPLETENESS,
|
|
31
|
+
ENUMERATION_ROOT_KINDS,
|
|
32
|
+
} from "../enumeration";
|
|
33
|
+
|
|
21
34
|
import {
|
|
22
35
|
ATTENTION_LANES,
|
|
23
36
|
CANDIDATE_MACHINE_STATES,
|
|
@@ -37,6 +50,7 @@ import {
|
|
|
37
50
|
import {
|
|
38
51
|
AUDIENCE_FITS,
|
|
39
52
|
DOCUMENT_TYPES,
|
|
53
|
+
OPERATING_KNOWLEDGE_FAMILIES,
|
|
40
54
|
SHARING_BREADTHS,
|
|
41
55
|
SOURCE_CLASSES,
|
|
42
56
|
SOURCE_SENSITIVITY_CLASSES,
|
|
@@ -126,6 +140,17 @@ const VOCABULARIES = [
|
|
|
126
140
|
tuple: SOURCE_SYNC_SCOPE_APPROVER_KINDS,
|
|
127
141
|
members: ["org_admin", "unit_head"],
|
|
128
142
|
},
|
|
143
|
+
{
|
|
144
|
+
name: "OPERATING_KNOWLEDGE_FAMILIES",
|
|
145
|
+
tuple: OPERATING_KNOWLEDGE_FAMILIES,
|
|
146
|
+
members: [
|
|
147
|
+
"direction",
|
|
148
|
+
"operating_model",
|
|
149
|
+
"practices",
|
|
150
|
+
"identity_market",
|
|
151
|
+
"decisions_learning",
|
|
152
|
+
],
|
|
153
|
+
},
|
|
129
154
|
{
|
|
130
155
|
name: "SOURCE_RELEVANCE_TIERS",
|
|
131
156
|
tuple: SOURCE_RELEVANCE_TIERS,
|
|
@@ -240,6 +265,18 @@ const VOCABULARIES = [
|
|
|
240
265
|
tuple: SCAN_OUTCOMES,
|
|
241
266
|
members: ["complete", "budget_exhausted", "file_ceiling", "stopped"],
|
|
242
267
|
},
|
|
268
|
+
{
|
|
269
|
+
name: "ATTENTION_SIGNAL_KINDS",
|
|
270
|
+
tuple: ATTENTION_SIGNAL_KINDS,
|
|
271
|
+
members: [
|
|
272
|
+
"tree_prior",
|
|
273
|
+
"path_terms",
|
|
274
|
+
"content_match",
|
|
275
|
+
"breadth",
|
|
276
|
+
"recency",
|
|
277
|
+
"mime_prior",
|
|
278
|
+
],
|
|
279
|
+
},
|
|
243
280
|
] as const satisfies readonly {
|
|
244
281
|
name: string;
|
|
245
282
|
tuple: readonly string[];
|
|
@@ -274,6 +311,16 @@ describe("Source Sync closed sets", () => {
|
|
|
274
311
|
expect(SHARING_BREADTHS).toContain("unknown");
|
|
275
312
|
});
|
|
276
313
|
|
|
314
|
+
it("names the five operating-knowledge families", () => {
|
|
315
|
+
expect([...OPERATING_KNOWLEDGE_FAMILIES]).toEqual([
|
|
316
|
+
"direction",
|
|
317
|
+
"operating_model",
|
|
318
|
+
"practices",
|
|
319
|
+
"identity_market",
|
|
320
|
+
"decisions_learning",
|
|
321
|
+
]);
|
|
322
|
+
});
|
|
323
|
+
|
|
277
324
|
it("no member appears in two sets", () => {
|
|
278
325
|
const all = VOCABULARIES.flatMap(({ tuple }) => [...tuple]);
|
|
279
326
|
expect(new Set(all).size).toBe(all.length);
|
|
@@ -295,7 +342,7 @@ describe("Source Sync closed sets", () => {
|
|
|
295
342
|
});
|
|
296
343
|
|
|
297
344
|
describe("document types", () => {
|
|
298
|
-
it("has exactly the
|
|
345
|
+
it("has exactly the forty document types, in order", () => {
|
|
299
346
|
expect([...DOCUMENT_TYPES]).toEqual([
|
|
300
347
|
"board_deck",
|
|
301
348
|
"board_minutes",
|
|
@@ -326,9 +373,34 @@ describe("document types", () => {
|
|
|
326
373
|
"coursework",
|
|
327
374
|
"empty_template",
|
|
328
375
|
"image_or_screenshot",
|
|
376
|
+
"team_charter",
|
|
377
|
+
"process_playbook",
|
|
378
|
+
"policy_handbook",
|
|
379
|
+
"onboarding_guide",
|
|
380
|
+
"values_culture",
|
|
381
|
+
"positioning_messaging",
|
|
382
|
+
"decision_log",
|
|
383
|
+
"postmortem",
|
|
384
|
+
"metrics_definition",
|
|
385
|
+
"operating_cadence",
|
|
329
386
|
"unknown",
|
|
330
387
|
]);
|
|
331
|
-
expect(new Set(DOCUMENT_TYPES).size).toBe(
|
|
388
|
+
expect(new Set(DOCUMENT_TYPES).size).toBe(40);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it("the ten operating-knowledge document types sit before unknown", () => {
|
|
392
|
+
expect(DOCUMENT_TYPES.slice(29, 39)).toEqual([
|
|
393
|
+
"team_charter",
|
|
394
|
+
"process_playbook",
|
|
395
|
+
"policy_handbook",
|
|
396
|
+
"onboarding_guide",
|
|
397
|
+
"values_culture",
|
|
398
|
+
"positioning_messaging",
|
|
399
|
+
"decision_log",
|
|
400
|
+
"postmortem",
|
|
401
|
+
"metrics_definition",
|
|
402
|
+
"operating_cadence",
|
|
403
|
+
]);
|
|
332
404
|
});
|
|
333
405
|
|
|
334
406
|
it("unknown is the last document type", () => {
|
|
@@ -349,3 +421,30 @@ describe("document types", () => {
|
|
|
349
421
|
]);
|
|
350
422
|
});
|
|
351
423
|
});
|
|
424
|
+
|
|
425
|
+
describe("enumeration vocabulary", () => {
|
|
426
|
+
it("enumeration vocabularies share a member with another set only where pinned", () => {
|
|
427
|
+
const others = new Set<string>(
|
|
428
|
+
VOCABULARIES.flatMap(({ tuple }) => [...tuple]),
|
|
429
|
+
);
|
|
430
|
+
// SCAN_OUTCOMES
|
|
431
|
+
expect(ENUMERATION_COMPLETENESS.filter((m) => others.has(m))).toEqual([
|
|
432
|
+
"complete",
|
|
433
|
+
]);
|
|
434
|
+
// SHARING_BREADTHS
|
|
435
|
+
expect(ENUMERATION_ROOT_KINDS.filter((m) => others.has(m))).toEqual([
|
|
436
|
+
"domain",
|
|
437
|
+
]);
|
|
438
|
+
expect([...ENUMERATION_COMPLETENESS]).toEqual([
|
|
439
|
+
"complete",
|
|
440
|
+
"local_budget_truncated",
|
|
441
|
+
"provider_incomplete",
|
|
442
|
+
"both",
|
|
443
|
+
]);
|
|
444
|
+
expect([...ENUMERATION_ROOT_KINDS]).toEqual([
|
|
445
|
+
"user",
|
|
446
|
+
"shared_drive",
|
|
447
|
+
"domain",
|
|
448
|
+
]);
|
|
449
|
+
});
|
|
450
|
+
});
|