@unified-product-graph/core 0.17.3 → 0.17.5
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/README.md +1 -1
- package/dist/index.cjs +120 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +175 -4
- package/dist/index.d.ts +175 -4
- package/dist/index.js +117 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
The TypeScript core for the **Unified Product Graph (UPG)**, an open specification that gives product tools a shared vocabulary for entities, edges, and frameworks.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
319 entity types across 37 domains. 1024 typed edges. 46 canonical framework definitions, with more added as each is reviewed.
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
COVERAGE_ANTI_PATTERNS: () => COVERAGE_ANTI_PATTERNS,
|
|
40
40
|
DEFAULT_ENTITY_EMOJI: () => DEFAULT_ENTITY_EMOJI,
|
|
41
41
|
DEFERRED_PROPOSED_BY_CONTRACT: () => DEFERRED_PROPOSED_BY_CONTRACT,
|
|
42
|
+
DEFER_EDGE_PROPERTY_SCHEMA: () => DEFER_EDGE_PROPERTY_SCHEMA,
|
|
42
43
|
DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK: () => DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
|
|
43
44
|
ENGINEERING_PLATFORM_PLAYBOOK: () => ENGINEERING_PLATFORM_PLAYBOOK,
|
|
44
45
|
ENTITY_EMOJI: () => ENTITY_EMOJI,
|
|
@@ -70,6 +71,7 @@ __export(index_exports, {
|
|
|
70
71
|
UPG_CROSS_EDGE_TYPES: () => UPG_CROSS_EDGE_TYPES,
|
|
71
72
|
UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES: () => UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES,
|
|
72
73
|
UPG_CROSS_ONLY_EDGE_TYPES: () => UPG_CROSS_ONLY_EDGE_TYPES,
|
|
74
|
+
UPG_DELIBERATE_ONLY_EDGE_TYPES: () => UPG_DELIBERATE_ONLY_EDGE_TYPES,
|
|
73
75
|
UPG_DEPRECATED_TYPES: () => UPG_DEPRECATED_TYPES,
|
|
74
76
|
UPG_DOMAINS: () => UPG_DOMAINS,
|
|
75
77
|
UPG_DOMAIN_ACTIVATION: () => UPG_DOMAIN_ACTIVATION,
|
|
@@ -201,6 +203,7 @@ __export(index_exports, {
|
|
|
201
203
|
isCanonicalProductStage: () => isCanonicalProductStage,
|
|
202
204
|
isContainmentFreeType: () => isContainmentFreeType,
|
|
203
205
|
isCrossProductEligible: () => isCrossProductEligible,
|
|
206
|
+
isDeliberateOnlyEdge: () => isDeliberateOnlyEdge,
|
|
204
207
|
isDeprecatedType: () => isDeprecatedType,
|
|
205
208
|
isDomainGuideStep: () => isDomainGuideStep,
|
|
206
209
|
isEntitySequenceStep: () => isEntitySequenceStep,
|
|
@@ -267,7 +270,8 @@ var UPG_DOMAINS = [
|
|
|
267
270
|
"strategic_pillar",
|
|
268
271
|
"assumption",
|
|
269
272
|
"decision",
|
|
270
|
-
"constraint"
|
|
273
|
+
"constraint",
|
|
274
|
+
"strategic_question"
|
|
271
275
|
]
|
|
272
276
|
},
|
|
273
277
|
{
|
|
@@ -786,6 +790,10 @@ var UPG_ENTITY_META = [
|
|
|
786
790
|
{ name: "assumption", type_id: "ent_014", maturity: "stable", since: "0.1.0" },
|
|
787
791
|
{ name: "decision", type_id: "ent_015", maturity: "stable", since: "0.1.0" },
|
|
788
792
|
{ name: "constraint", type_id: "ent_348", maturity: "stable", since: "0.4.3" },
|
|
793
|
+
// (0.17.4) Strategy-domain sibling of research_question / design_question,
|
|
794
|
+
// completing the domain-question triad. An open coordination/ownership question
|
|
795
|
+
// a plan is exposed to (distinct from `assumption`, which the plan is built on).
|
|
796
|
+
{ name: "strategic_question", type_id: "ent_357", maturity: "proposed", since: "0.17.4" },
|
|
789
797
|
// ── User ──
|
|
790
798
|
{ name: "persona", type_id: "ent_016", maturity: "stable", since: "0.1.0" },
|
|
791
799
|
{ name: "job", type_id: "ent_017", maturity: "stable", since: "0.1.0" },
|
|
@@ -1260,6 +1268,12 @@ var CLASSIFICATION_EDGE_PROPERTY_SCHEMA = {
|
|
|
1260
1268
|
description: "Optional. A source URL, or a competitor_signal / evidence node id backing the classification. Mirrors feature_rivals_competitor_feature.evidence (free text or a node id)."
|
|
1261
1269
|
}
|
|
1262
1270
|
};
|
|
1271
|
+
var DEFER_EDGE_PROPERTY_SCHEMA = {
|
|
1272
|
+
deferred_to: {
|
|
1273
|
+
type: "string",
|
|
1274
|
+
description: 'Target period the parked work is deferred to. Freeform, mirroring strategic_theme.time_horizon. @example "Q4 2026", "FY27", "next release".'
|
|
1275
|
+
}
|
|
1276
|
+
};
|
|
1263
1277
|
var UPG_EDGE_CATALOG = {
|
|
1264
1278
|
// ── Part 1: Core Narrative Spine (Ring 1) ──────────────────────────────────
|
|
1265
1279
|
// 1.1 User Domain
|
|
@@ -2290,6 +2304,11 @@ var UPG_EDGE_CATALOG = {
|
|
|
2290
2304
|
document_describes_positioning: { forward_verb: "describes", reverse_verb: "described_by", classification: "semantic", source_type: "document", target_type: "positioning" },
|
|
2291
2305
|
document_describes_decision: { forward_verb: "describes", reverse_verb: "described_by", classification: "semantic", source_type: "document", target_type: "decision" },
|
|
2292
2306
|
document_contains_insight: { forward_verb: "contains", reverse_verb: "contained_in", classification: "semantic", source_type: "document", target_type: "insight" },
|
|
2307
|
+
// Research-provenance containment (0.17.5): a synthesis document is walkable
|
|
2308
|
+
// to the evidence it sourced. Within-graph containment (the document and the
|
|
2309
|
+
// evidence co-reside), so NOT cross_product_eligible.
|
|
2310
|
+
document_contains_quote: { forward_verb: "contains", reverse_verb: "contained_in", classification: "semantic", source_type: "document", target_type: "quote" },
|
|
2311
|
+
document_contains_observation: { forward_verb: "contains", reverse_verb: "contained_in", classification: "semantic", source_type: "document", target_type: "observation" },
|
|
2293
2312
|
// 5.3 Customer Education & Training Domain
|
|
2294
2313
|
product_educates_via_education_program: { forward_verb: "educates_via", reverse_verb: "educates", classification: "hierarchy", source_type: "product", target_type: "education_program" },
|
|
2295
2314
|
education_program_teaches_via_tutorial: { forward_verb: "teaches_via", reverse_verb: "teaches", classification: "hierarchy", source_type: "education_program", target_type: "tutorial" },
|
|
@@ -3334,7 +3353,45 @@ var UPG_EDGE_CATALOG = {
|
|
|
3334
3353
|
// Operating-lifecycle cross-edges (0.11.6): a product's journey phase realises a canonical
|
|
3335
3354
|
// operating stage (the cross-surface join key); a stage is measured by a rollup metric (loop close).
|
|
3336
3355
|
journey_phase_realises_operating_stage: { forward_verb: "realises", reverse_verb: "realised_by", classification: "cross-domain", source_type: "journey_phase", target_type: "operating_stage", cross_product_eligible: true },
|
|
3337
|
-
operating_stage_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "cross-domain", source_type: "operating_stage", target_type: "metric" }
|
|
3356
|
+
operating_stage_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "cross-domain", source_type: "operating_stage", target_type: "metric" },
|
|
3357
|
+
// ── OKR planning coverage (0.17.4) ──────────────────────────────────────────
|
|
3358
|
+
// Reconciling the strategy graph against a live planning doc surfaced texture
|
|
3359
|
+
// the objective — the node every OKR doc organises itself around — could not
|
|
3360
|
+
// reach: cross-team dependencies and deferred (out-of-scope) work.
|
|
3361
|
+
// objective ↔ dependency. Every OKR in the source doc carries a dependency
|
|
3362
|
+
// table ("which other team's work this depends on"). `dependency` (team_org)
|
|
3363
|
+
// already carries dependency_type / criticality / target_date; it was
|
|
3364
|
+
// reachable only from `team`. An objective DEPENDS ON a dependency; the
|
|
3365
|
+
// dependency BLOCKS the objective (explicit mirror, not left implicit).
|
|
3366
|
+
// Cross-domain, not hierarchy: a dependency is parented under its owning team,
|
|
3367
|
+
// so an objective references it laterally rather than containing it. Both are
|
|
3368
|
+
// cross_product_eligible — a Studio objective can depend on a dependency owned
|
|
3369
|
+
// by another team's graph within the portfolio (0.17.3 locked predicate).
|
|
3370
|
+
objective_depends_on_dependency: { forward_verb: "depends_on", reverse_verb: "dependency_of", classification: "cross-domain", source_type: "objective", target_type: "dependency", cross_product_eligible: true },
|
|
3371
|
+
dependency_blocks_objective: { forward_verb: "blocks", reverse_verb: "blocked_by", classification: "cross-domain", source_type: "dependency", target_type: "objective", cross_product_eligible: true },
|
|
3372
|
+
// objective / initiative → strategic_question. A planning doc's "Risks & Open
|
|
3373
|
+
// Questions" section names unresolved coordination questions the plan is
|
|
3374
|
+
// exposed to (who owns a capability across teams after a reorg). The
|
|
3375
|
+
// strategy-domain sibling of research_question / design_question. The question
|
|
3376
|
+
// is raised under (contained by) the objective or initiative that surfaces it,
|
|
3377
|
+
// so hierarchy — mirroring initiative_assumes_assumption. Within-graph: the
|
|
3378
|
+
// question node is authored alongside its objective, so NOT
|
|
3379
|
+
// cross_product_eligible (the cross-team nature lives in the question text, not
|
|
3380
|
+
// in a cross-graph edge).
|
|
3381
|
+
objective_raises_strategic_question: { forward_verb: "raises", reverse_verb: "raised_by", classification: "hierarchy", source_type: "objective", target_type: "strategic_question" },
|
|
3382
|
+
initiative_raises_strategic_question: { forward_verb: "raises", reverse_verb: "raised_by", classification: "hierarchy", source_type: "initiative", target_type: "strategic_question" },
|
|
3383
|
+
// objective → feature / capability (the defer / out-of-scope edge). Every OKR
|
|
3384
|
+
// in the source doc carries an explicit "Out of scope" list, load-bearing for
|
|
3385
|
+
// keeping a quarter from silently expanding (localization deferred to Q4,
|
|
3386
|
+
// another team's feature work parked). Modelled as an edge to the real feature
|
|
3387
|
+
// or capability parked for later, not a scalar exclusion string, so the parked
|
|
3388
|
+
// work stays queryable and connected. The `deferred_to` edge property carries
|
|
3389
|
+
// the temporal target. feature is product_spec (cross-domain); capability is
|
|
3390
|
+
// intra-strategy (semantic). Both cross_product_eligible: deferring another
|
|
3391
|
+
// product's feature or capability, authored in a different graph within the
|
|
3392
|
+
// portfolio, fits the 0.17.3 locked predicate.
|
|
3393
|
+
objective_defers_feature: { forward_verb: "defers", reverse_verb: "deferred_by", classification: "cross-domain", source_type: "objective", target_type: "feature", carries_properties: true, property_schema: DEFER_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true, deliberate_only: true },
|
|
3394
|
+
objective_defers_capability: { forward_verb: "defers", reverse_verb: "deferred_by", classification: "semantic", source_type: "objective", target_type: "capability", carries_properties: true, property_schema: DEFER_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true, deliberate_only: true }
|
|
3338
3395
|
};
|
|
3339
3396
|
var UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES = Object.keys(UPG_EDGE_CATALOG).filter(
|
|
3340
3397
|
(k) => UPG_EDGE_CATALOG[k].cross_product_eligible === true
|
|
@@ -3343,6 +3400,13 @@ function isCrossProductEligible(type) {
|
|
|
3343
3400
|
const def = UPG_EDGE_CATALOG[type];
|
|
3344
3401
|
return def?.cross_product_eligible === true;
|
|
3345
3402
|
}
|
|
3403
|
+
var UPG_DELIBERATE_ONLY_EDGE_TYPES = Object.keys(UPG_EDGE_CATALOG).filter(
|
|
3404
|
+
(k) => UPG_EDGE_CATALOG[k].deliberate_only === true
|
|
3405
|
+
);
|
|
3406
|
+
function isDeliberateOnlyEdge(type) {
|
|
3407
|
+
const def = UPG_EDGE_CATALOG[type];
|
|
3408
|
+
return def?.deliberate_only === true;
|
|
3409
|
+
}
|
|
3346
3410
|
var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
3347
3411
|
// Universal semantic verbs
|
|
3348
3412
|
"node_informs_node",
|
|
@@ -3710,7 +3774,9 @@ var UPG_VALID_CHILDREN = {
|
|
|
3710
3774
|
// where self-nesting genuinely lives, not on `experiment`).
|
|
3711
3775
|
experiment_run: ["learning", "evidence", "metric", "experiment_run"],
|
|
3712
3776
|
// ── OKR hierarchy ──────────────────────────────────────────────────────────
|
|
3713
|
-
|
|
3777
|
+
// strategic_question (0.17.4): an open coordination question raised under an
|
|
3778
|
+
// objective (objective_raises_strategic_question, hierarchy).
|
|
3779
|
+
objective: ["key_result", "metric", "strategic_question"],
|
|
3714
3780
|
key_result: ["metric"],
|
|
3715
3781
|
// ── Strategic cascade: vision → mission → strategic_pillar → strategic_theme →
|
|
3716
3782
|
// { initiative, objective } ───────────────────────────────────────────────
|
|
@@ -3735,7 +3801,7 @@ var UPG_VALID_CHILDREN = {
|
|
|
3735
3801
|
// catalog (hierarchy, strategic_theme → objective, reverse_verb: rolls_up_to;
|
|
3736
3802
|
// renamed from objective_rolls_up_to_strategic_theme in UPG-676).
|
|
3737
3803
|
strategic_theme: ["initiative", "objective"],
|
|
3738
|
-
initiative: ["assumption"],
|
|
3804
|
+
initiative: ["assumption", "strategic_question"],
|
|
3739
3805
|
// v0.5.2 (UPG-528): capability decomposes into sub-capabilities (Wardley
|
|
3740
3806
|
// value-chain spine) and is realised by user-facing features. Pairs with
|
|
3741
3807
|
// `capability_depends_on_capability` and `capability_implemented_by_feature`
|
|
@@ -4808,6 +4874,15 @@ var ASSUMPTION_LIFECYCLE = {
|
|
|
4808
4874
|
}
|
|
4809
4875
|
]
|
|
4810
4876
|
};
|
|
4877
|
+
var STRATEGIC_QUESTION_LIFECYCLE = {
|
|
4878
|
+
entity_type: "strategic_question",
|
|
4879
|
+
initial_phase: "open",
|
|
4880
|
+
terminal_phases: ["resolved"],
|
|
4881
|
+
phases: [
|
|
4882
|
+
{ id: "open", label: "Open", description: "The question has been raised but not yet answered. The plan is exposed to it.", transitions_to: ["resolved"] },
|
|
4883
|
+
{ id: "resolved", label: "Resolved", description: "The question has been answered; the resolution is captured. The plan is no longer exposed to it. May reopen if the answer unravels.", transitions_to: ["open"] }
|
|
4884
|
+
]
|
|
4885
|
+
};
|
|
4811
4886
|
var OUTCOME_LIFECYCLE = {
|
|
4812
4887
|
entity_type: "outcome",
|
|
4813
4888
|
initial_phase: "identified",
|
|
@@ -6485,6 +6560,7 @@ var UPG_LIFECYCLES = [
|
|
|
6485
6560
|
INITIATIVE_LIFECYCLE,
|
|
6486
6561
|
STRATEGIC_PILLAR_LIFECYCLE,
|
|
6487
6562
|
ASSUMPTION_LIFECYCLE,
|
|
6563
|
+
STRATEGIC_QUESTION_LIFECYCLE,
|
|
6488
6564
|
FEATURE_AREA_LIFECYCLE,
|
|
6489
6565
|
FEATURE_LIFECYCLE,
|
|
6490
6566
|
EPIC_LIFECYCLE,
|
|
@@ -12279,7 +12355,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12279
12355
|
session_ref: { type: "string", description: "Capturing session reference. Convenience field; the canonical relationship to study/session is an edge per P14. Retained as a lightweight context anchor for AI inference." },
|
|
12280
12356
|
is_highlighted: { type: "boolean", description: "Flagged as a highlight. Absorbed from the deprecated Highlight entity." },
|
|
12281
12357
|
highlight_tag: { type: "string", description: 'Free-form highlight type tag. @example "pain", "delight", "behaviour", "moment of clarity"' },
|
|
12282
|
-
sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Structured sentiment. Tools like Dovetail and EnjoyHQ converge on these four values. More precise than `highlight_tag` for aggregation." }
|
|
12358
|
+
sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Structured sentiment. Tools like Dovetail and EnjoyHQ converge on these four values. More precise than `highlight_tag` for aggregation." },
|
|
12359
|
+
source_url: { type: "string", description: "Stable deep-link to the exact moment this observation was captured in the originating recording or transcript. A per-moment locator, not a study-level link. Distinct from `session_ref`, which holds an opaque session ID.", modifier: "volatile" }
|
|
12283
12360
|
},
|
|
12284
12361
|
// OnCallRotationProperties: On-call rotation.
|
|
12285
12362
|
on_call_rotation: {
|
|
@@ -12323,7 +12400,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12323
12400
|
participant: {
|
|
12324
12401
|
alias: { type: "string", description: 'Anonymous alias for privacy (e.g. "P01")' },
|
|
12325
12402
|
recruit_source: { type: "string", description: "How the participant was recruited" },
|
|
12326
|
-
consent_status: { type: "string", enum: ["pending", "given", "withdrawn"], description: "Current consent status for data usage" }
|
|
12403
|
+
consent_status: { type: "string", enum: ["pending", "given", "withdrawn"], description: "Current consent status for data usage" },
|
|
12404
|
+
source_url: { type: "string", description: "Stable deep-link to the exact moment this participant appears in the originating recording or transcript. A per-moment locator, not a study-level link.", modifier: "volatile" }
|
|
12327
12405
|
},
|
|
12328
12406
|
// PartnerProgramProperties: Partner program.
|
|
12329
12407
|
partner_program: {
|
|
@@ -12546,7 +12624,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12546
12624
|
// QuoteProperties: Verbatim quote from a participant.
|
|
12547
12625
|
quote: {
|
|
12548
12626
|
text: { type: "string", description: "Quoted text" },
|
|
12549
|
-
timestamp: { type: "string", description: "When said (ISO timestamp or session offset)" }
|
|
12627
|
+
timestamp: { type: "string", description: "When said (ISO timestamp or session offset)" },
|
|
12628
|
+
source_url: { type: "string", description: "Stable deep-link to the exact moment this quote was spoken in the originating recording or transcript. A per-moment locator, not a study-level link.", modifier: "volatile" }
|
|
12550
12629
|
},
|
|
12551
12630
|
// QuoteDocumentProperties: Quote document.
|
|
12552
12631
|
quote_document: {
|
|
@@ -12961,6 +13040,15 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12961
13040
|
time_horizon: { type: "string", description: 'Standing / multi-year horizon, often open-ended (a pillar is durable). @example "3 years", "2026-2028", "ongoing"' },
|
|
12962
13041
|
success_indicator: { type: "string", description: "How the business knows this durable pillar is on track. Narrative, not a metric edge. A strategic_theme deliberately has no success_indicator: it is measured through its child objectives, not on its own." }
|
|
12963
13042
|
},
|
|
13043
|
+
// StrategicQuestionProperties: StrategicQuestion entity. An open coordination or
|
|
13044
|
+
// ownership question a plan is exposed to (strategy sibling of research_question /
|
|
13045
|
+
// design_question). `status` is the node lifecycle (open -> resolved).
|
|
13046
|
+
strategic_question: {
|
|
13047
|
+
question: { type: "string", description: "The question itself. Primary content." },
|
|
13048
|
+
context: { type: "string", description: "Context that surfaced the question: the reorg, the boundary, the unowned area." },
|
|
13049
|
+
resolution: { type: "string", description: "The answer, captured when the question moves to `resolved`." },
|
|
13050
|
+
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Importance to resolve relative to other open questions." }
|
|
13051
|
+
},
|
|
12964
13052
|
// StrategicThemeProperties: StrategicTheme entity. A time-bound thrust WITHIN a
|
|
12965
13053
|
// strategic_pillar (distinct cascade level, UPG-692 T3.3) — measured through its
|
|
12966
13054
|
// child objectives, so it carries no success_indicator of its own.
|
|
@@ -19989,6 +20077,7 @@ var ENTITY_EMOJI = {
|
|
|
19989
20077
|
stakeholder: "\u{1F9D1}\u200D\u{1F4BC}",
|
|
19990
20078
|
status_report: "\u{1F4C4}",
|
|
19991
20079
|
strategic_pillar: "\u{1F3DB}\uFE0F",
|
|
20080
|
+
strategic_question: "\u2754",
|
|
19992
20081
|
strategic_theme: "\u{1F9F5}",
|
|
19993
20082
|
subscription: "\u{1F502}",
|
|
19994
20083
|
success_milestone: "\u{1F389}",
|
|
@@ -20546,6 +20635,7 @@ var STANDARD_LABELS = {
|
|
|
20546
20635
|
value_stream: { alt_labels: ["value chain", "stream"] },
|
|
20547
20636
|
strategic_pillar: { alt_labels: ["pillar", "foundation"] },
|
|
20548
20637
|
assumption: { alt_labels: ["belief", "working assumption", "premise"] },
|
|
20638
|
+
strategic_question: { alt_labels: ["open question", "coordination question", "ownership question"] },
|
|
20549
20639
|
// User layer
|
|
20550
20640
|
job_step: { alt_labels: ["job stage", "job phase", "job map step"] },
|
|
20551
20641
|
switching_cost: { alt_labels: ["lock-in", "migration cost", "switching barrier"] },
|
|
@@ -22975,7 +23065,13 @@ var USER_RESEARCH_GUIDE = {
|
|
|
22975
23065
|
anti_patterns: [
|
|
22976
23066
|
{ description: "Insights without evidence: every insight must trace back to observations and quotes" },
|
|
22977
23067
|
{ description: "Orphan quotes: quotes should belong to observations, not float independently" },
|
|
22978
|
-
{ description: "Research studies without questions: always define what you want to learn before starting" }
|
|
23068
|
+
{ description: "Research studies without questions: always define what you want to learn before starting" },
|
|
23069
|
+
{
|
|
23070
|
+
name: "Study conflation",
|
|
23071
|
+
affected_entity: "research_study",
|
|
23072
|
+
description: "Do not merge multiple research rounds with different stated goals into one `research_study` (or one participant pool) just because they were synthesized into the same downstream document. If two rounds have different research questions, they are different `research_study` nodes, even if an analyst wrote them up together.",
|
|
23073
|
+
remediation: "Verify against the *original* recording or session metadata, not the synthesis doc's grouping."
|
|
23074
|
+
}
|
|
22979
23075
|
]
|
|
22980
23076
|
};
|
|
22981
23077
|
var MARKET_INTELLIGENCE_GUIDE = {
|
|
@@ -23090,7 +23186,7 @@ var STRATEGY_GUIDE = {
|
|
|
23090
23186
|
// entries are later additions appended in chronological-introduction
|
|
23091
23187
|
// order. Placement reflects the order in which they would naturally be
|
|
23092
23188
|
// authored after the canonical strategy spine.
|
|
23093
|
-
creation_sequence: ["product", "vision", "mission", "outcome", "objective", "key_result", "metric", "metric_quality_assessment", "strategic_theme", "strategic_pillar", "initiative", "capability", "value_stream", "assumption", "decision", "constraint"],
|
|
23189
|
+
creation_sequence: ["product", "vision", "mission", "outcome", "objective", "key_result", "metric", "metric_quality_assessment", "strategic_theme", "strategic_pillar", "initiative", "capability", "value_stream", "assumption", "strategic_question", "decision", "constraint"],
|
|
23094
23190
|
patterns: [
|
|
23095
23191
|
{
|
|
23096
23192
|
name: "Strategic Cascade",
|
|
@@ -23108,13 +23204,16 @@ var STRATEGY_GUIDE = {
|
|
|
23108
23204
|
required_bridges: [
|
|
23109
23205
|
{ edge_type: "outcome_reveals_opportunity", target_domain: "discovery", when: "Outcomes should connect to the opportunities that deliver them" },
|
|
23110
23206
|
{ edge_type: "outcome_delivered_by_feature", target_domain: "product_spec", when: "Strategic outcomes should decompose into shipped features" },
|
|
23111
|
-
{ edge_type: "assumption_becomes_hypothesis", target_domain: "validation", when: "Risky assumptions should become testable hypotheses" }
|
|
23207
|
+
{ edge_type: "assumption_becomes_hypothesis", target_domain: "validation", when: "Risky assumptions should become testable hypotheses" },
|
|
23208
|
+
{ edge_type: "objective_depends_on_dependency", target_domain: "team_org", when: "An objective that hinges on cross-team work should name the dependency it is exposed to" },
|
|
23209
|
+
{ edge_type: "objective_defers_feature", target_domain: "product_spec", when: "Work an objective explicitly puts out of scope for now should point at the deferred feature with a deferred_to period, not silently vanish from the quarter" }
|
|
23112
23210
|
],
|
|
23113
23211
|
anti_patterns: [
|
|
23114
23212
|
{ description: "Outcomes without metrics. Measurement is the signal an outcome happened." },
|
|
23115
23213
|
{ description: "Objectives without key results: an objective without measurement is a wish" },
|
|
23116
23214
|
{ description: "Too many strategic themes: focus beats breadth, aim for 2-4 active themes" },
|
|
23117
|
-
{ description: "Constraints without an origin: a qualitative guardrail lives on a constraint, so set constraint_origin to say where it comes from. internal marks a self-imposed principle or operating tenet the team commits to; external marks a limit, requirement, or ceiling imposed from outside (a regulation, a budget cap, a platform bound)." }
|
|
23215
|
+
{ description: "Constraints without an origin: a qualitative guardrail lives on a constraint, so set constraint_origin to say where it comes from. internal marks a self-imposed principle or operating tenet the team commits to; external marks a limit, requirement, or ceiling imposed from outside (a regulation, a budget cap, a platform bound)." },
|
|
23216
|
+
{ description: "Overloading assumption for open questions: an assumption is a premise the plan is built on and resolves by being tested (assumption_becomes_hypothesis). An unresolved coordination or ownership question the plan is exposed to (who owns a capability across teams, where a boundary falls after a reorg) is a strategic_question, raised under the objective or initiative it hangs off. Do not force one into the other." }
|
|
23118
23217
|
]
|
|
23119
23218
|
};
|
|
23120
23219
|
var PRODUCT_SPEC_GUIDE = {
|
|
@@ -27167,6 +27266,10 @@ var UPG_REGIONS = [
|
|
|
27167
27266
|
type: "assumption",
|
|
27168
27267
|
role: "leaf"
|
|
27169
27268
|
},
|
|
27269
|
+
{
|
|
27270
|
+
type: "strategic_question",
|
|
27271
|
+
role: "leaf"
|
|
27272
|
+
},
|
|
27170
27273
|
{
|
|
27171
27274
|
type: "constraint",
|
|
27172
27275
|
role: "leaf"
|
|
@@ -27192,6 +27295,8 @@ var UPG_REGIONS = [
|
|
|
27192
27295
|
"strategic_pillar_decided_via_decision",
|
|
27193
27296
|
"strategic_theme_pursues_initiative",
|
|
27194
27297
|
"initiative_assumes_assumption",
|
|
27298
|
+
"objective_raises_strategic_question",
|
|
27299
|
+
"initiative_raises_strategic_question",
|
|
27195
27300
|
"initiative_drives_outcome",
|
|
27196
27301
|
"objective_achieved_through_key_result",
|
|
27197
27302
|
"objective_measured_by_metric",
|
|
@@ -29876,7 +29981,7 @@ function isCanonical(text) {
|
|
|
29876
29981
|
}
|
|
29877
29982
|
|
|
29878
29983
|
// src/index.ts
|
|
29879
|
-
var UPG_VERSION = "0.17.
|
|
29984
|
+
var UPG_VERSION = "0.17.5";
|
|
29880
29985
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
29881
29986
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
29882
29987
|
var UPG_TYPES = getTypes();
|
|
@@ -29950,6 +30055,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
29950
30055
|
COVERAGE_ANTI_PATTERNS,
|
|
29951
30056
|
DEFAULT_ENTITY_EMOJI,
|
|
29952
30057
|
DEFERRED_PROPOSED_BY_CONTRACT,
|
|
30058
|
+
DEFER_EDGE_PROPERTY_SCHEMA,
|
|
29953
30059
|
DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
|
|
29954
30060
|
ENGINEERING_PLATFORM_PLAYBOOK,
|
|
29955
30061
|
ENTITY_EMOJI,
|
|
@@ -29981,6 +30087,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
29981
30087
|
UPG_CROSS_EDGE_TYPES,
|
|
29982
30088
|
UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES,
|
|
29983
30089
|
UPG_CROSS_ONLY_EDGE_TYPES,
|
|
30090
|
+
UPG_DELIBERATE_ONLY_EDGE_TYPES,
|
|
29984
30091
|
UPG_DEPRECATED_TYPES,
|
|
29985
30092
|
UPG_DOMAINS,
|
|
29986
30093
|
UPG_DOMAIN_ACTIVATION,
|
|
@@ -30112,6 +30219,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
30112
30219
|
isCanonicalProductStage,
|
|
30113
30220
|
isContainmentFreeType,
|
|
30114
30221
|
isCrossProductEligible,
|
|
30222
|
+
isDeliberateOnlyEdge,
|
|
30115
30223
|
isDeprecatedType,
|
|
30116
30224
|
isDomainGuideStep,
|
|
30117
30225
|
isEntitySequenceStep,
|