@validation-os/core 0.15.6 → 0.16.1
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/{chunk-HMAHBGOJ.js → chunk-TCKAMOAK.js} +412 -11
- package/dist/chunk-TCKAMOAK.js.map +1 -0
- package/dist/derivation/index.d.ts +2 -2
- package/dist/derivation/index.js +25 -1
- package/dist/{index-DMPfDeEw.d.ts → index-DhQyc0Gj.d.ts} +335 -24
- package/dist/index.d.ts +29 -12
- package/dist/index.js +58 -25
- package/dist/index.js.map +1 -1
- package/dist/{provider-biEHIhDh.d.ts → provider-BAip4ABo.d.ts} +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/{types-B845UmLh.d.ts → types-DZIQEO4D.d.ts} +42 -7
- package/package.json +1 -1
- package/dist/chunk-HMAHBGOJ.js.map +0 -1
|
@@ -7,8 +7,12 @@ var derivation_exports = {};
|
|
|
7
7
|
__export(derivation_exports, {
|
|
8
8
|
COMMITMENT_FOUND: () => COMMITMENT_FOUND,
|
|
9
9
|
COMPLETENESS_SLOTS: () => COMPLETENESS_SLOTS,
|
|
10
|
+
CONFIDENCE_FLOOR_BY_STAGE: () => CONFIDENCE_FLOOR_BY_STAGE,
|
|
11
|
+
DEFAULT_QUESTION_TYPE: () => DEFAULT_QUESTION_TYPE,
|
|
12
|
+
INFERABLE_QUESTION_TYPES: () => INFERABLE_QUESTION_TYPES,
|
|
10
13
|
KILL_LANE_THRESHOLD: () => KILL_LANE_THRESHOLD,
|
|
11
14
|
MAX_STRENGTH: () => MAX_STRENGTH,
|
|
15
|
+
RISK_THRESHOLD_BY_STAGE: () => RISK_THRESHOLD_BY_STAGE,
|
|
12
16
|
RUNG_ANCHOR: () => RUNG_ANCHOR,
|
|
13
17
|
W0: () => W0,
|
|
14
18
|
W0_BY_RUNG: () => W0_BY_RUNG,
|
|
@@ -17,23 +21,31 @@ __export(derivation_exports, {
|
|
|
17
21
|
assumptionCompleteness: () => assumptionCompleteness,
|
|
18
22
|
beliefRisk: () => beliefRisk,
|
|
19
23
|
beliefTestMeters: () => beliefTestMeters,
|
|
24
|
+
ceilingAnchor: () => ceilingAnchor,
|
|
20
25
|
classifyStage: () => classifyStage,
|
|
21
26
|
commitmentFactor: () => commitmentFactor,
|
|
22
27
|
completenessSlotPresence: () => completenessSlotPresence,
|
|
23
28
|
confidence: () => confidence,
|
|
24
29
|
confidenceAttribution: () => confidenceAttribution,
|
|
30
|
+
confidenceFloorForStage: () => confidenceFloorForStage,
|
|
25
31
|
confidenceTrajectory: () => confidenceTrajectory,
|
|
26
32
|
deriveBeliefStage: () => deriveBeliefStage,
|
|
27
33
|
derivedImpacts: () => derivedImpacts,
|
|
28
34
|
emptyTestMeter: () => emptyTestMeter,
|
|
29
35
|
experimentConfidence: () => experimentConfidence,
|
|
30
36
|
experimentProgress: () => experimentProgress,
|
|
37
|
+
hasClearedThreshold: () => hasClearedThreshold,
|
|
38
|
+
inferQuestionType: () => inferQuestionType,
|
|
31
39
|
isConcluded: () => isConcluded,
|
|
40
|
+
isNonEvidence: () => isNonEvidence,
|
|
41
|
+
migrateRegister: () => migrateRegister,
|
|
32
42
|
missingCompletenessSlots: () => missingCompletenessSlots,
|
|
43
|
+
needsReview: () => needsReview,
|
|
33
44
|
portfolioProgress: () => portfolioProgress,
|
|
34
45
|
rankNextMoves: () => rankNextMoves,
|
|
35
46
|
readingStrength: () => readingStrength,
|
|
36
47
|
risk: () => risk,
|
|
48
|
+
riskThresholdForStage: () => riskThresholdForStage,
|
|
37
49
|
round2: () => round2,
|
|
38
50
|
scoreAndDedupe: () => scoreAndDedupe,
|
|
39
51
|
sign: () => sign,
|
|
@@ -47,14 +59,114 @@ function round2(n) {
|
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
// src/derivation/rung.ts
|
|
62
|
+
var Z = { Low: 0, Typical: 0, High: 0 };
|
|
63
|
+
function band(low, typical, high) {
|
|
64
|
+
return { Low: low, Typical: typical, High: high };
|
|
65
|
+
}
|
|
50
66
|
var RUNG_ANCHOR = {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
67
|
+
Existence: {
|
|
68
|
+
Talk: band(10, 20, 30),
|
|
69
|
+
"Desk research": band(15, 15, 15),
|
|
70
|
+
"Signed up": Z,
|
|
71
|
+
"Observed usage": band(20, 35, 50),
|
|
72
|
+
"Signed intent": Z,
|
|
73
|
+
"Paying users": Z
|
|
74
|
+
},
|
|
75
|
+
Prevalence: {
|
|
76
|
+
Talk: Z,
|
|
77
|
+
"Desk research": band(15, 15, 15),
|
|
78
|
+
"Signed up": Z,
|
|
79
|
+
"Observed usage": band(25, 40, 50),
|
|
80
|
+
"Signed intent": Z,
|
|
81
|
+
"Paying users": Z
|
|
82
|
+
},
|
|
83
|
+
CausalEffect: {
|
|
84
|
+
Talk: Z,
|
|
85
|
+
"Desk research": Z,
|
|
86
|
+
"Signed up": Z,
|
|
87
|
+
"Observed usage": band(30, 50, 70),
|
|
88
|
+
"Signed intent": band(30, 50, 70),
|
|
89
|
+
"Paying users": band(50, 70, 90)
|
|
90
|
+
},
|
|
91
|
+
WillingnessToPay: {
|
|
92
|
+
Talk: Z,
|
|
93
|
+
"Desk research": Z,
|
|
94
|
+
"Signed up": band(30, 50, 70),
|
|
95
|
+
"Observed usage": Z,
|
|
96
|
+
"Signed intent": band(50, 70, 85),
|
|
97
|
+
"Paying users": band(75, 88, 99)
|
|
98
|
+
},
|
|
99
|
+
ValueUtility: {
|
|
100
|
+
Talk: band(10, 20, 30),
|
|
101
|
+
"Desk research": Z,
|
|
102
|
+
"Signed up": Z,
|
|
103
|
+
"Observed usage": band(30, 50, 70),
|
|
104
|
+
"Signed intent": Z,
|
|
105
|
+
"Paying users": Z
|
|
106
|
+
},
|
|
107
|
+
Regulatory: {
|
|
108
|
+
Talk: Z,
|
|
109
|
+
"Desk research": band(30, 50, 70),
|
|
110
|
+
"Signed up": Z,
|
|
111
|
+
"Observed usage": Z,
|
|
112
|
+
"Signed intent": Z,
|
|
113
|
+
"Paying users": Z
|
|
114
|
+
},
|
|
115
|
+
Feasibility: {
|
|
116
|
+
Talk: Z,
|
|
117
|
+
"Desk research": band(15, 15, 15),
|
|
118
|
+
"Signed up": Z,
|
|
119
|
+
"Observed usage": band(30, 50, 70),
|
|
120
|
+
"Signed intent": Z,
|
|
121
|
+
"Paying users": Z
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
function isNonEvidence(questionType, rung) {
|
|
125
|
+
const anchors = RUNG_ANCHOR[questionType]?.[rung];
|
|
126
|
+
if (!anchors) return false;
|
|
127
|
+
return anchors.Low === 0 && anchors.Typical === 0 && anchors.High === 0;
|
|
128
|
+
}
|
|
129
|
+
function ceilingAnchor(questionType, rung) {
|
|
130
|
+
return RUNG_ANCHOR[questionType]?.[rung]?.High ?? 0;
|
|
131
|
+
}
|
|
132
|
+
var RISK_THRESHOLD_BY_STAGE = {
|
|
133
|
+
Discovery: 30,
|
|
134
|
+
// two-way door — act on weak evidence
|
|
135
|
+
Validation: 15,
|
|
136
|
+
// becoming one-way — need more before committing
|
|
137
|
+
Scale: 10,
|
|
138
|
+
// one-way door — strong evidence before scaling
|
|
139
|
+
Maturity: 5
|
|
140
|
+
// defensive, often regulatory — strongest evidence
|
|
141
|
+
};
|
|
142
|
+
var CONFIDENCE_FLOOR_BY_STAGE = {
|
|
143
|
+
Discovery: 10,
|
|
144
|
+
// any signal counts for a two-way door
|
|
145
|
+
Validation: 25,
|
|
146
|
+
// need a real reading, not just vibes
|
|
147
|
+
Scale: 40,
|
|
148
|
+
// need solid evidence before scaling
|
|
149
|
+
Maturity: 60
|
|
150
|
+
// need strong evidence for a one-way door
|
|
57
151
|
};
|
|
152
|
+
function riskThresholdForStage(stage) {
|
|
153
|
+
if (stage && stage in RISK_THRESHOLD_BY_STAGE) {
|
|
154
|
+
return RISK_THRESHOLD_BY_STAGE[stage];
|
|
155
|
+
}
|
|
156
|
+
return RISK_THRESHOLD_BY_STAGE.Maturity;
|
|
157
|
+
}
|
|
158
|
+
function confidenceFloorForStage(stage) {
|
|
159
|
+
if (stage && stage in CONFIDENCE_FLOOR_BY_STAGE) {
|
|
160
|
+
return CONFIDENCE_FLOOR_BY_STAGE[stage];
|
|
161
|
+
}
|
|
162
|
+
return CONFIDENCE_FLOOR_BY_STAGE.Maturity;
|
|
163
|
+
}
|
|
164
|
+
function hasClearedThreshold(risk2, stage, confidence2) {
|
|
165
|
+
const riskCleared = risk2 <= riskThresholdForStage(stage);
|
|
166
|
+
if (confidence2 === void 0) return riskCleared;
|
|
167
|
+
const confCleared = confidence2 >= confidenceFloorForStage(stage);
|
|
168
|
+
return riskCleared && confCleared;
|
|
169
|
+
}
|
|
58
170
|
|
|
59
171
|
// src/derivation/completeness.ts
|
|
60
172
|
var COMPLETENESS_SLOTS = [
|
|
@@ -62,7 +174,8 @@ var COMPLETENESS_SLOTS = [
|
|
|
62
174
|
"Lens",
|
|
63
175
|
"Impact",
|
|
64
176
|
"Scoring justification",
|
|
65
|
-
"Dependencies traced"
|
|
177
|
+
"Dependencies traced",
|
|
178
|
+
"Question Type"
|
|
66
179
|
];
|
|
67
180
|
function hasText(value) {
|
|
68
181
|
return typeof value === "string" && value.trim().length > 0;
|
|
@@ -79,7 +192,8 @@ function completenessSlotPresence(record) {
|
|
|
79
192
|
Lens: hasText(record.Lens),
|
|
80
193
|
Impact: hasNumber(record.Impact),
|
|
81
194
|
"Scoring justification": hasText(record["Scoring justification"]),
|
|
82
|
-
"Dependencies traced": hasAny(record.dependsOnIds) || hasAny(record.enablesIds)
|
|
195
|
+
"Dependencies traced": hasAny(record.dependsOnIds) || hasAny(record.enablesIds),
|
|
196
|
+
"Question Type": hasText(record["Question Type"])
|
|
83
197
|
};
|
|
84
198
|
}
|
|
85
199
|
function missingCompletenessSlots(record) {
|
|
@@ -107,8 +221,271 @@ function isConcluded(result) {
|
|
|
107
221
|
function readingStrength(input) {
|
|
108
222
|
const s = sign(input.result);
|
|
109
223
|
if (s === 0) return 0;
|
|
110
|
-
const
|
|
111
|
-
return (RUNG_ANCHOR[input.rung]?.[
|
|
224
|
+
const band2 = input.magnitudeBand ?? "Typical";
|
|
225
|
+
return (RUNG_ANCHOR[input.questionType]?.[input.rung]?.[band2] ?? 0) * s;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// src/derivation/question-type.ts
|
|
229
|
+
var DEFAULT_QUESTION_TYPE = "Existence";
|
|
230
|
+
var RULES = [
|
|
231
|
+
{
|
|
232
|
+
type: "Regulatory",
|
|
233
|
+
patterns: [
|
|
234
|
+
/\bregulat(?:or|ion)\s+(?:prohibits|rul(?:es|ed)\s+against)\b/,
|
|
235
|
+
/\bregulator\b.*\bagainst\b/,
|
|
236
|
+
/\bcompliance\s+audit\s+fails?\b/,
|
|
237
|
+
/\bprohibits?\b.*\bscoring\b/,
|
|
238
|
+
// Positive bar patterns (the register's rightIf text):
|
|
239
|
+
/\bregulat(?:or|ion)s?\s+(?:approve|accept|confirm|permit)\b/,
|
|
240
|
+
/\bfca\b.*\bconfirm\b/,
|
|
241
|
+
/\blegal\s+opinion\b.*\bstate/i,
|
|
242
|
+
/\bnon[-\s]?compliant\b.*\boutputs?\b/,
|
|
243
|
+
/\bconduct\s+layer\b.*\b(?:safe|within|comply)\b/,
|
|
244
|
+
/\bconsumer\s+duty\b/,
|
|
245
|
+
/\bguardrails?\b.*\b(?:regulat|comply|within)\b/,
|
|
246
|
+
/\beducation\b.*\bguidance\b.*\bwithin\b/
|
|
247
|
+
]
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
type: "WillingnessToPay",
|
|
251
|
+
patterns: [
|
|
252
|
+
/\b(?:don't|do not|won't|will not)\s+pay\b/,
|
|
253
|
+
/\bfake[-\s]?door\s+(?:signup\s+)?rate\s+below\b/,
|
|
254
|
+
/\bfake[-\s]?door\b.*\brate\b/,
|
|
255
|
+
/\bdon't\s+sign\s+up\b/,
|
|
256
|
+
/\bno\s+(?:buyer|user)s?\s+(?:sign|pay|commit)\b/,
|
|
257
|
+
/\bsigns?\s+(?:an\s+)?loi\b/,
|
|
258
|
+
/\bput(?:s|ting)?\s+down\s+(?:a\s+)?deposit\b/,
|
|
259
|
+
/\bdon't\s+commit\b/,
|
|
260
|
+
/\boffered\s+users?\s+pay\b/,
|
|
261
|
+
/\bpay(?:ing)?\s+(?:rate|share)?\s*(?:is\s+)?below\b/,
|
|
262
|
+
/\bfewer\s+than\s+\d+\s+of\s+\d+\s+offered\s+users?\s+pay\b/,
|
|
263
|
+
// Positive bar patterns:
|
|
264
|
+
/\bsign\s+(?:a\s+)?(?:design[-\s]?partner|pilot)\s+agreement\b/,
|
|
265
|
+
/\bsigned\s+intent\b/i,
|
|
266
|
+
/\bcommit(?:s|ting)?\s+(?:before|to\s+pay|to\s+a)\b/,
|
|
267
|
+
/\badopt\s*(?:and\s*)?pay\b/,
|
|
268
|
+
/\bpay\s+for\b.*\b(?:layer|harness|governed)\b/,
|
|
269
|
+
/\bagree\s+(?:in\s+writing|to\s+ingest|to\s+sign)\b/,
|
|
270
|
+
/\b(?:design|pilot)\s+partner\b.*\bagreement\b/
|
|
271
|
+
]
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
type: "ValueUtility",
|
|
275
|
+
patterns: [
|
|
276
|
+
/\bstop\s+using\s+(?:it|the)\b/,
|
|
277
|
+
/\bdrop[-\s]?off\s+exceeds\b/,
|
|
278
|
+
/\bsustained\s+usage\s+falls?\s+below\b/,
|
|
279
|
+
/\bretention\s+(?:drops?|falls?)\s+below\b/,
|
|
280
|
+
/\bweek-\d+\s+retention\s+drops?\s+below\b/,
|
|
281
|
+
/\bdisuse\b/,
|
|
282
|
+
// Positive bar patterns:
|
|
283
|
+
/\bengage\s+(?:turn[-\s]by[-\s]turn|with|positively)\b/i,
|
|
284
|
+
/\bengage(?:s|ment)?\s+with\b/i,
|
|
285
|
+
/\breact\s+positively\b/i,
|
|
286
|
+
/\bcomfortable\s+with\b.*\b(?:bank|storing|context)\b/i,
|
|
287
|
+
/\bchoose\s+(?:voice|as\s+their\s+primary)\b/i,
|
|
288
|
+
/\bsustained\s+(?:retention|usage|engagement)\b/i,
|
|
289
|
+
/\bcome\s+back\b.*\bsession/i,
|
|
290
|
+
/\bprefer\b.*\b(?:modality|interface|experience)\b/i
|
|
291
|
+
]
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
type: "CausalEffect",
|
|
295
|
+
patterns: [
|
|
296
|
+
/\btreatment\s+group(?:'s)?\s+doesn'?t\s+differ\s+from\s+control\b/,
|
|
297
|
+
/\bno\s+causal\s+effect\s+of\b/,
|
|
298
|
+
/\bvariant\s+doesn'?t\s+outperform\s+control\b/,
|
|
299
|
+
/\bdiffer\s+from\s+control\b/,
|
|
300
|
+
/\boutperform\s+control\b/,
|
|
301
|
+
/\btreatment\s+vs\.?\s+control\b/,
|
|
302
|
+
// Positive bar patterns:
|
|
303
|
+
/\bbeats?\s+(?:a\s+)?\w+[-\s]only\s+(?:model|baseline|control)\b/i,
|
|
304
|
+
/\brelative\s+lift\b/i,
|
|
305
|
+
/\breplicated\s+in\b.*\bcohort/i,
|
|
306
|
+
/\bwins?\s+≥?\s*\d+\s*[×x]\b/i,
|
|
307
|
+
/\bframing\s+wins\b/i
|
|
308
|
+
]
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
type: "Prevalence",
|
|
312
|
+
patterns: [
|
|
313
|
+
/\brate\s+is\s+below\b/,
|
|
314
|
+
/\bfewer\s+than\s+\d+\s+of\s+\d+\s+(?:interviewed|surveyed|of)\b/,
|
|
315
|
+
/\bfewer\s+than\s+\d+%\s+of\s+\w+\s+hit\b/,
|
|
316
|
+
/\bthe\s+(?:rate|share|proportion)\s+is\s+below\b/,
|
|
317
|
+
/\b(?:in\s+)?surveyed\s+teams\b/,
|
|
318
|
+
/\bshare\s+(?:of\s+\w+\s+)?(?:is\s+)?below\b/,
|
|
319
|
+
/\bproportion\s+is\s+below\b/,
|
|
320
|
+
// Positive bar patterns:
|
|
321
|
+
/\b[≥>]\s*\d+%\s+of\b/i,
|
|
322
|
+
/\b[≥>]\s*\d+\s+of\b/i,
|
|
323
|
+
/\bnamed\b.*\b(?:as|in)\s+a\s+top[-\s]\d\b/i,
|
|
324
|
+
/\b[≥>]\s*\d+\s+(?:of\s+\d+\s+)?(?:institutions?|consumers?|users?|buyers?|banks?|teams?)\b/i
|
|
325
|
+
]
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
type: "Feasibility",
|
|
329
|
+
patterns: [
|
|
330
|
+
/\bcan'?t\s+complete\s+the\s+flow\b/,
|
|
331
|
+
/\bsystem\s+can'?t\s+(?:do|ingest|handle|build)\b/,
|
|
332
|
+
/\bcan'?t\s+be\s+built\b/,
|
|
333
|
+
/\bcan'?t\s+ingest\b/,
|
|
334
|
+
/\bprototype\s+can'?t\s+be\s+built\b/,
|
|
335
|
+
/\bcan'?t\s+\w+\s+(?:unaided|without\s+(?:help|regressions))\b/,
|
|
336
|
+
// Positive bar patterns:
|
|
337
|
+
/\bcomplete\s+the\s+(?:flow|setup|wizard)\b.*\b(?:unaided|without\s+help)\b/i,
|
|
338
|
+
/\bingest\b.*\b(?:rows?|records?)\b.*\b(?:under|in)\s+\d+/i,
|
|
339
|
+
/\b(?:can|able\s+to)\s+(?:build|ship|deliver)\b.*\b(?:without|no)\s+(?:regress|break)/i
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
type: "Existence",
|
|
344
|
+
patterns: [
|
|
345
|
+
/\bno\s+one\s+(?:we\s+interview\s+)?(?:describes|reports|mentions)\b/,
|
|
346
|
+
/\bno\s+interviewee(?:s)?\s+(?:describe|report|mention)s?\b/,
|
|
347
|
+
/\bcan'?t\s+describe\s+the\s+mechanism\b/,
|
|
348
|
+
/\bno\s+one\s+reports\s+caring\b/,
|
|
349
|
+
/\bno\s+one\s+describes\b/,
|
|
350
|
+
// Positive bar patterns:
|
|
351
|
+
/\bindependently\s+states?\b.*\b(?:needs?|wants?|values?|sees)\b/i,
|
|
352
|
+
/\bindependently\s+(?:report|state|confirm)s?\b/i,
|
|
353
|
+
/\bsay\s+they'?d\s+(?:be\s+)?(?:comfortable|prefer)\b/i,
|
|
354
|
+
/\b(?:credible|independent)\b.*\b(?:states?|reports?|confirms?)\b/i
|
|
355
|
+
]
|
|
356
|
+
}
|
|
357
|
+
];
|
|
358
|
+
function normalize(s) {
|
|
359
|
+
return s.toLowerCase().replace(/\s+/g, " ").trim();
|
|
360
|
+
}
|
|
361
|
+
function inferQuestionType(description, wrongIfBar) {
|
|
362
|
+
const bar = normalize(wrongIfBar ?? "");
|
|
363
|
+
const desc = normalize(description ?? "");
|
|
364
|
+
const hay = bar.length > 0 ? `${bar} ${desc}` : desc;
|
|
365
|
+
for (const rule of RULES) {
|
|
366
|
+
for (const re of rule.patterns) {
|
|
367
|
+
if (re.test(hay)) return rule.type;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return DEFAULT_QUESTION_TYPE;
|
|
371
|
+
}
|
|
372
|
+
var INFERABLE_QUESTION_TYPES = [
|
|
373
|
+
"Existence",
|
|
374
|
+
"Prevalence",
|
|
375
|
+
"CausalEffect",
|
|
376
|
+
"WillingnessToPay",
|
|
377
|
+
"ValueUtility",
|
|
378
|
+
"Regulatory",
|
|
379
|
+
"Feasibility"
|
|
380
|
+
];
|
|
381
|
+
function needsReview(description, wrongIfBar, inferred) {
|
|
382
|
+
if (wrongIfBar == null || wrongIfBar.trim() === "") return true;
|
|
383
|
+
const bar = normalize(wrongIfBar);
|
|
384
|
+
for (const rule of RULES) {
|
|
385
|
+
if (rule.type === inferred) {
|
|
386
|
+
for (const re of rule.patterns) {
|
|
387
|
+
if (re.test(bar)) return false;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/derivation/migrate.ts
|
|
395
|
+
function migrateRegister(assumptions, readings) {
|
|
396
|
+
const questionTypeById = /* @__PURE__ */ new Map();
|
|
397
|
+
const reviewNeededById = /* @__PURE__ */ new Set();
|
|
398
|
+
for (const a of assumptions) {
|
|
399
|
+
const existing = a["Question Type"];
|
|
400
|
+
let qt;
|
|
401
|
+
let review = false;
|
|
402
|
+
if (existing && ["Existence", "Prevalence", "CausalEffect", "WillingnessToPay", "ValueUtility", "Regulatory", "Feasibility"].includes(existing)) {
|
|
403
|
+
qt = existing;
|
|
404
|
+
} else {
|
|
405
|
+
qt = inferQuestionType(a.Description ?? "", a.wrongIfBar ?? "");
|
|
406
|
+
review = needsReview(a.Description ?? "", a.wrongIfBar ?? "", qt);
|
|
407
|
+
if (review) reviewNeededById.add(a.id);
|
|
408
|
+
}
|
|
409
|
+
questionTypeById.set(a.id, qt);
|
|
410
|
+
}
|
|
411
|
+
const migratedReadings = [];
|
|
412
|
+
let nonEvidenceFlagCount = 0;
|
|
413
|
+
for (const r of readings) {
|
|
414
|
+
const questionType = questionTypeById.get(r.assumptionId) ?? "Existence";
|
|
415
|
+
const band2 = r.magnitudeBand ?? "Typical";
|
|
416
|
+
const newStrength = readingStrength({
|
|
417
|
+
questionType,
|
|
418
|
+
rung: r.Rung,
|
|
419
|
+
result: r.Result,
|
|
420
|
+
magnitudeBand: band2
|
|
421
|
+
});
|
|
422
|
+
const oldStrength = r.derived?.strength ?? 0;
|
|
423
|
+
const nonEvidence = isNonEvidence(questionType, r.Rung);
|
|
424
|
+
if (nonEvidence) nonEvidenceFlagCount += 1;
|
|
425
|
+
migratedReadings.push({
|
|
426
|
+
id: r.id,
|
|
427
|
+
assumptionId: r.assumptionId,
|
|
428
|
+
Rung: r.Rung,
|
|
429
|
+
newStrength,
|
|
430
|
+
oldStrength,
|
|
431
|
+
nonEvidence
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
const inputsByAssumption = /* @__PURE__ */ new Map();
|
|
435
|
+
for (const a of assumptions) inputsByAssumption.set(a.id, []);
|
|
436
|
+
for (const r of readings) {
|
|
437
|
+
const questionType = questionTypeById.get(r.assumptionId) ?? "Existence";
|
|
438
|
+
inputsByAssumption.get(r.assumptionId)?.push({
|
|
439
|
+
id: r.id,
|
|
440
|
+
source: r.Source,
|
|
441
|
+
rung: r.Rung,
|
|
442
|
+
result: r.Result,
|
|
443
|
+
questionType,
|
|
444
|
+
representativeness: r.Representativeness,
|
|
445
|
+
credibility: r.Credibility,
|
|
446
|
+
date: r.Date,
|
|
447
|
+
magnitudeBand: r.magnitudeBand ?? void 0,
|
|
448
|
+
experimentId: r.experimentId
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
const migratedAssumptions = assumptions.map((a) => {
|
|
452
|
+
const questionType = questionTypeById.get(a.id) ?? "Existence";
|
|
453
|
+
const oldConfidence = a.derived?.confidence ?? 0;
|
|
454
|
+
const newConfidence = confidence(inputsByAssumption.get(a.id) ?? []);
|
|
455
|
+
const stage = a.Stage ?? null;
|
|
456
|
+
return {
|
|
457
|
+
...a,
|
|
458
|
+
"Question Type": questionType,
|
|
459
|
+
questionTypeReviewNeeded: reviewNeededById.has(a.id),
|
|
460
|
+
newConfidence,
|
|
461
|
+
oldConfidence,
|
|
462
|
+
confidenceDelta: Math.round((newConfidence - oldConfidence) * 100) / 100,
|
|
463
|
+
riskThreshold: riskThresholdForStage(stage)
|
|
464
|
+
};
|
|
465
|
+
});
|
|
466
|
+
const confidenceDeltas = migratedAssumptions.map((a) => ({
|
|
467
|
+
id: a.id,
|
|
468
|
+
delta: a.confidenceDelta,
|
|
469
|
+
oldConfidence: a.oldConfidence,
|
|
470
|
+
newConfidence: a.newConfidence
|
|
471
|
+
})).sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));
|
|
472
|
+
const oldRanked = [...assumptions].map((a) => ({ id: a.id, c: a.derived?.confidence ?? 0 })).sort((a, b) => b.c - a.c || a.id.localeCompare(b.id));
|
|
473
|
+
const newRanked = [...migratedAssumptions].map((a) => ({ id: a.id, c: a.newConfidence })).sort((a, b) => b.c - a.c || a.id.localeCompare(b.id));
|
|
474
|
+
const oldRank = new Map(oldRanked.map((r, i) => [r.id, i + 1]));
|
|
475
|
+
const newRank = new Map(newRanked.map((r, i) => [r.id, i + 1]));
|
|
476
|
+
const rankingShifts = migratedAssumptions.map((a) => {
|
|
477
|
+
const o = oldRank.get(a.id) ?? 0;
|
|
478
|
+
const n = newRank.get(a.id) ?? 0;
|
|
479
|
+
return { id: a.id, oldRank: o, newRank: n, shift: n - o };
|
|
480
|
+
}).filter((r) => r.oldRank > 0 && r.newRank > 0).sort((a, b) => Math.abs(b.shift) - Math.abs(a.shift));
|
|
481
|
+
return {
|
|
482
|
+
assumptions: migratedAssumptions,
|
|
483
|
+
readings: migratedReadings,
|
|
484
|
+
nonEvidenceFlagCount,
|
|
485
|
+
reviewQueueCount: reviewNeededById.size,
|
|
486
|
+
confidenceDeltas,
|
|
487
|
+
rankingShifts
|
|
488
|
+
};
|
|
112
489
|
}
|
|
113
490
|
|
|
114
491
|
// src/derivation/source-quality.ts
|
|
@@ -131,6 +508,16 @@ var TESTING_RUNGS = [
|
|
|
131
508
|
"Observed usage"
|
|
132
509
|
];
|
|
133
510
|
var MARKET_RUNG_VALUES = ["Signed intent", "Paying users"];
|
|
511
|
+
var STAGES = ["Discovery", "Validation", "Scale", "Maturity"];
|
|
512
|
+
var QUESTION_TYPES = [
|
|
513
|
+
"Existence",
|
|
514
|
+
"Prevalence",
|
|
515
|
+
"CausalEffect",
|
|
516
|
+
"WillingnessToPay",
|
|
517
|
+
"ValueUtility",
|
|
518
|
+
"Regulatory",
|
|
519
|
+
"Feasibility"
|
|
520
|
+
];
|
|
134
521
|
|
|
135
522
|
// src/derivation/confidence.ts
|
|
136
523
|
var MARKET_RUNG_SET = new Set(MARKET_RUNG_VALUES);
|
|
@@ -615,6 +1002,8 @@ export {
|
|
|
615
1002
|
REGISTERS,
|
|
616
1003
|
TESTING_RUNGS,
|
|
617
1004
|
MARKET_RUNG_VALUES,
|
|
1005
|
+
STAGES,
|
|
1006
|
+
QUESTION_TYPES,
|
|
618
1007
|
COMPLETENESS_SLOTS,
|
|
619
1008
|
completenessSlotPresence,
|
|
620
1009
|
missingCompletenessSlots,
|
|
@@ -622,9 +1011,21 @@ export {
|
|
|
622
1011
|
assumptionComplete,
|
|
623
1012
|
round2,
|
|
624
1013
|
RUNG_ANCHOR,
|
|
1014
|
+
isNonEvidence,
|
|
1015
|
+
ceilingAnchor,
|
|
1016
|
+
RISK_THRESHOLD_BY_STAGE,
|
|
1017
|
+
CONFIDENCE_FLOOR_BY_STAGE,
|
|
1018
|
+
riskThresholdForStage,
|
|
1019
|
+
confidenceFloorForStage,
|
|
1020
|
+
hasClearedThreshold,
|
|
625
1021
|
sign,
|
|
626
1022
|
isConcluded,
|
|
627
1023
|
readingStrength,
|
|
1024
|
+
DEFAULT_QUESTION_TYPE,
|
|
1025
|
+
inferQuestionType,
|
|
1026
|
+
INFERABLE_QUESTION_TYPES,
|
|
1027
|
+
needsReview,
|
|
1028
|
+
migrateRegister,
|
|
628
1029
|
sourceQuality,
|
|
629
1030
|
W0_BY_RUNG,
|
|
630
1031
|
w0ForRung,
|
|
@@ -651,4 +1052,4 @@ export {
|
|
|
651
1052
|
assembleJourney,
|
|
652
1053
|
derivation_exports
|
|
653
1054
|
};
|
|
654
|
-
//# sourceMappingURL=chunk-
|
|
1055
|
+
//# sourceMappingURL=chunk-TCKAMOAK.js.map
|