@company-semantics/contracts 99.3.0 → 100.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 +1 -1
- package/src/api/generated-spec-hash.ts +2 -2
- package/src/api/generated.ts +10 -1
- package/src/source-sync/__tests__/scope-projection.test.ts +24 -0
- package/src/source-sync/index.ts +2 -0
- package/src/source-sync/schemas.ts +10 -0
- package/src/source-sync/vocabulary.ts +10 -0
- package/src/workflows/deferred-route.ts +2 -0
- package/src/workflows/outcome-reasons.ts +5 -0
package/package.json
CHANGED
|
@@ -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 = '7e0143b235a3' as const;
|
|
3
|
+
export const SPEC_HASH_FULL = '7e0143b235a3cc79cc020305bc8e4cf82c7784774cff280504fe70c0e9ee9a81' as const;
|
package/src/api/generated.ts
CHANGED
|
@@ -7469,10 +7469,11 @@ export interface components {
|
|
|
7469
7469
|
/** @enum {string} */
|
|
7470
7470
|
kind: "produced" | "empty" | "partial" | "stopped" | "failed" | "abandoned" | "unknown";
|
|
7471
7471
|
/** @enum {string} */
|
|
7472
|
-
reason: "updates_ready" | "updates_applied" | "stopped_by_user" | "paused_billing" | "run_ceiling_reached" | "pricing_unconfigured" | "synthesis_incomplete" | "approval_mismatch" | "landing_refused" | "standing_order_refused" | "no_connection" | "source_sync_off" | "internal_error" | "abandoned" | "unrecognized_terminal_state";
|
|
7472
|
+
reason: "updates_ready" | "updates_ready_partial" | "updates_applied" | "stopped_by_user" | "paused_billing" | "run_ceiling_reached" | "pricing_unconfigured" | "synthesis_incomplete" | "approval_mismatch" | "landing_refused" | "standing_order_refused" | "no_connection" | "source_sync_off" | "internal_error" | "abandoned" | "unrecognized_terminal_state";
|
|
7473
7473
|
facts: {
|
|
7474
7474
|
scopeCount: number;
|
|
7475
7475
|
violationCount: number;
|
|
7476
|
+
notLandedCount: number;
|
|
7476
7477
|
} | null;
|
|
7477
7478
|
disposition: {
|
|
7478
7479
|
/** @constant */
|
|
@@ -10848,6 +10849,8 @@ export interface components {
|
|
|
10848
10849
|
label: string;
|
|
10849
10850
|
} | null;
|
|
10850
10851
|
approvedAt: string | null;
|
|
10852
|
+
approvable: boolean;
|
|
10853
|
+
blockedReason: "needs_doc_access" | null;
|
|
10851
10854
|
}[];
|
|
10852
10855
|
discovery: {
|
|
10853
10856
|
foundThisRun: number;
|
|
@@ -10912,6 +10915,8 @@ export interface components {
|
|
|
10912
10915
|
label: string;
|
|
10913
10916
|
} | null;
|
|
10914
10917
|
approvedAt: string | null;
|
|
10918
|
+
approvable: boolean;
|
|
10919
|
+
blockedReason: "needs_doc_access" | null;
|
|
10915
10920
|
}[];
|
|
10916
10921
|
/** Format: uuid */
|
|
10917
10922
|
workflowId: string;
|
|
@@ -11039,6 +11044,8 @@ export interface components {
|
|
|
11039
11044
|
label: string;
|
|
11040
11045
|
} | null;
|
|
11041
11046
|
approvedAt: string | null;
|
|
11047
|
+
approvable: boolean;
|
|
11048
|
+
blockedReason: "needs_doc_access" | null;
|
|
11042
11049
|
}[];
|
|
11043
11050
|
};
|
|
11044
11051
|
SourceSyncApplyResponse: {
|
|
@@ -11098,6 +11105,8 @@ export interface components {
|
|
|
11098
11105
|
label: string;
|
|
11099
11106
|
} | null;
|
|
11100
11107
|
approvedAt: string | null;
|
|
11108
|
+
approvable: boolean;
|
|
11109
|
+
blockedReason: "needs_doc_access" | null;
|
|
11101
11110
|
}[];
|
|
11102
11111
|
};
|
|
11103
11112
|
SourceSyncRulesResponse: {
|
|
@@ -34,6 +34,8 @@ function scope(overrides: Record<string, unknown> = {}) {
|
|
|
34
34
|
vacantHead: false,
|
|
35
35
|
approvedBy: null,
|
|
36
36
|
approvedAt: null,
|
|
37
|
+
approvable: true,
|
|
38
|
+
blockedReason: null,
|
|
37
39
|
...overrides,
|
|
38
40
|
};
|
|
39
41
|
}
|
|
@@ -100,6 +102,28 @@ describe("SourceSyncScopeApprovalProjectionSchema", () => {
|
|
|
100
102
|
});
|
|
101
103
|
});
|
|
102
104
|
|
|
105
|
+
describe("approvable and blockedReason", () => {
|
|
106
|
+
it("accepts a visible scope the caller may not approve, with its reason", () => {
|
|
107
|
+
const parsed = SourceSyncScopeApprovalProjectionSchema.safeParse(
|
|
108
|
+
scope({ approvable: false, blockedReason: "needs_doc_access" }),
|
|
109
|
+
);
|
|
110
|
+
expect(parsed.success).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("refuses a reason outside the vocabulary and a missing approvable", () => {
|
|
114
|
+
expect(
|
|
115
|
+
SourceSyncScopeApprovalProjectionSchema.safeParse(
|
|
116
|
+
scope({ approvable: false, blockedReason: "not_admin" }),
|
|
117
|
+
).success,
|
|
118
|
+
).toBe(false);
|
|
119
|
+
const { approvable: _omit, ...withoutApprovable } = scope();
|
|
120
|
+
expect(
|
|
121
|
+
SourceSyncScopeApprovalProjectionSchema.safeParse(withoutApprovable)
|
|
122
|
+
.success,
|
|
123
|
+
).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
103
127
|
describe("scopes is required on every checkpoint response", () => {
|
|
104
128
|
const schemas = [
|
|
105
129
|
["candidate set", SourceSyncCandidateSetResponseSchema],
|
package/src/source-sync/index.ts
CHANGED
|
@@ -31,6 +31,7 @@ export type {
|
|
|
31
31
|
SourceSyncDocDisposition,
|
|
32
32
|
SourceSyncScopeApprovalState,
|
|
33
33
|
SourceSyncScopeApproverKind,
|
|
34
|
+
SourceSyncScopeBlockedReason,
|
|
34
35
|
DocumentType,
|
|
35
36
|
KnownDocumentType,
|
|
36
37
|
OperatingKnowledgeFamily,
|
|
@@ -47,6 +48,7 @@ export {
|
|
|
47
48
|
SOURCE_SYNC_DOC_DISPOSITIONS,
|
|
48
49
|
SOURCE_SYNC_SCOPE_APPROVAL_STATES,
|
|
49
50
|
SOURCE_SYNC_SCOPE_APPROVER_KINDS,
|
|
51
|
+
SOURCE_SYNC_SCOPE_BLOCKED_REASONS,
|
|
50
52
|
DOCUMENT_TYPES,
|
|
51
53
|
OPERATING_KNOWLEDGE_FAMILIES,
|
|
52
54
|
} from "./vocabulary";
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
SOURCE_SYNC_DOC_RISKS,
|
|
27
27
|
SOURCE_SYNC_SCOPE_APPROVAL_STATES,
|
|
28
28
|
SOURCE_SYNC_SCOPE_APPROVER_KINDS,
|
|
29
|
+
SOURCE_SYNC_SCOPE_BLOCKED_REASONS,
|
|
29
30
|
} from "./vocabulary";
|
|
30
31
|
import { CandidateDiscoverySummarySchema } from "./relevance";
|
|
31
32
|
import { SourceSyncCandidateItemSchema } from "./candidate-item";
|
|
@@ -45,6 +46,13 @@ const PersonLabel = z.string().min(1).max(255);
|
|
|
45
46
|
* still a `unit_head` scope, `assignedTo` is null, and the org's admins approve it.
|
|
46
47
|
* - An approved scope reports the routing its approval RECORDED; a later head
|
|
47
48
|
* change does not rewrite it. A pending scope reports its routing as of now.
|
|
49
|
+
* - `approvable` is whether THE CALLER may approve this pending scope now. A scope
|
|
50
|
+
* can be visible but not approvable: approving needs the caller's own upload and
|
|
51
|
+
* edit access on the scope's document, because landing and apply act as the
|
|
52
|
+
* approver. `blockedReason` is non-null exactly when a pending scope is not
|
|
53
|
+
* approvable; an approved scope is never approvable and carries null. At the
|
|
54
|
+
* synthesis checkpoint a pending scope is approvable: apply is decided per
|
|
55
|
+
* document by the edit policy, which approving the candidate set required.
|
|
48
56
|
*/
|
|
49
57
|
export const SourceSyncScopeApprovalProjectionSchema = z.object({
|
|
50
58
|
/** 'company' or 'unit:<uuid>'. */
|
|
@@ -62,6 +70,8 @@ export const SourceSyncScopeApprovalProjectionSchema = z.object({
|
|
|
62
70
|
/** Non-null exactly when a person's approval is recorded. */
|
|
63
71
|
approvedBy: z.object({ label: PersonLabel }).nullable(),
|
|
64
72
|
approvedAt: IsoDateTime.nullable(),
|
|
73
|
+
approvable: z.boolean(),
|
|
74
|
+
blockedReason: z.enum(SOURCE_SYNC_SCOPE_BLOCKED_REASONS).nullable(),
|
|
65
75
|
});
|
|
66
76
|
|
|
67
77
|
/** The discovery run a person started, or that upkeep started on a schedule. */
|
|
@@ -111,6 +111,16 @@ export const SOURCE_SYNC_SCOPE_APPROVER_KINDS = [
|
|
|
111
111
|
export type SourceSyncScopeApproverKind =
|
|
112
112
|
(typeof SOURCE_SYNC_SCOPE_APPROVER_KINDS)[number];
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Why the CALLER may not approve a scope they can see. `needs_doc_access`: the
|
|
116
|
+
* landing and the apply act as the approver, so approving needs the caller's own
|
|
117
|
+
* upload and edit access on the scope's document (an admin holds only metadata
|
|
118
|
+
* access to company.md content).
|
|
119
|
+
*/
|
|
120
|
+
export const SOURCE_SYNC_SCOPE_BLOCKED_REASONS = ["needs_doc_access"] as const;
|
|
121
|
+
export type SourceSyncScopeBlockedReason =
|
|
122
|
+
(typeof SOURCE_SYNC_SCOPE_BLOCKED_REASONS)[number];
|
|
123
|
+
|
|
114
124
|
/**
|
|
115
125
|
* What a source IS — a STRUCTURAL name the model observes, never a relevance verdict
|
|
116
126
|
* (control ADR source-discovery-observation-vs-policy). The set names operating
|
|
@@ -147,6 +147,8 @@ export const SYNTHESIZE_DEFERRED_ROUTE_OF_REASON = {
|
|
|
147
147
|
// prettier-ignore
|
|
148
148
|
updates_ready: { route: "covered", by: "sourceSync.review_ready", fallback: "notice", audience: "creator" },
|
|
149
149
|
// prettier-ignore
|
|
150
|
+
updates_ready_partial: { route: "covered", by: "sourceSync.review_ready", fallback: "notice", audience: "creator" },
|
|
151
|
+
// prettier-ignore
|
|
150
152
|
updates_applied: { route: "covered", by: "sourceSync.docs_updated", fallback: "notice", audience: "creator" },
|
|
151
153
|
stopped_by_user: STOPPED,
|
|
152
154
|
paused_billing: EXPLAINED,
|
|
@@ -120,6 +120,8 @@ export type DiscoverOutcomeFacts = z.infer<typeof DiscoverOutcomeFactsSchema>;
|
|
|
120
120
|
/** Why a synthesis (landing then drafting) run ended the way it did. */
|
|
121
121
|
export const SYNTHESIZE_OUTCOME_KIND_OF_REASON = {
|
|
122
122
|
updates_ready: "produced",
|
|
123
|
+
/** Drafted from what landed; some approved files could not be brought in. */
|
|
124
|
+
updates_ready_partial: "partial",
|
|
123
125
|
updates_applied: "produced",
|
|
124
126
|
stopped_by_user: "stopped",
|
|
125
127
|
paused_billing: "failed",
|
|
@@ -142,6 +144,7 @@ export type SynthesizeOutcomeReason =
|
|
|
142
144
|
/** What each synthesis ending offers. TOTAL; an empty list is explicit. */
|
|
143
145
|
export const SYNTHESIZE_AFFORDANCES_OF_REASON = {
|
|
144
146
|
updates_ready: [],
|
|
147
|
+
updates_ready_partial: [],
|
|
145
148
|
updates_applied: [],
|
|
146
149
|
stopped_by_user: [],
|
|
147
150
|
paused_billing: [OPEN_BILLING],
|
|
@@ -168,6 +171,8 @@ export const SynthesizeOutcomeFactsSchema = z
|
|
|
168
171
|
scopeCount: Count,
|
|
169
172
|
/** Authority or size violations that left the batch incomplete. */
|
|
170
173
|
violationCount: Count,
|
|
174
|
+
/** Approved files to attach that did not land (refused, unreadable, gone). */
|
|
175
|
+
notLandedCount: Count,
|
|
171
176
|
})
|
|
172
177
|
.strict();
|
|
173
178
|
|