@unified-product-graph/core 0.9.0 → 0.9.2
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/CHANGELOG.md +39 -2
- package/dist/index.cjs +90 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -17
- package/dist/index.d.ts +61 -17
- package/dist/index.js +90 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,44 @@ This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
## [0.9.
|
|
10
|
+
## [0.9.2] - 2026-06-09
|
|
11
|
+
|
|
12
|
+
**Journey-model disambiguation (UPG-663).** The four Experience-Design journey types (`user_journey`, `journey_phase`, `journey_step`, `journey_action`) had a coherent concept but broken wiring: there was no deterministic answer to "what are the steps of this journey?". A `journey_phase` is now a temporal band that **spans** steps, not a container that **owns** them, mirroring the marketing precedent `customer_journey_stage_spans_journey_step`. Steps stay owned by `user_journey` (the stable 0.1.0 spine), so each step has exactly one containment parent and the journey renders one canonical step list. Additive plus one edge rename (dual-read via `UPG_EDGE_MIGRATIONS['0.9.2']`). Decision: `2026-06-09-journey-model-disambiguation.md`.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- `journey_action_surfaces_need` and `journey_action_realised_by_feature` edges: `journey_action` previously had zero outbound edges despite carrying `pain_score` / `opportunity_score` "to drive opportunity discovery". Opportunity discovery now routes through `need` (which reaches `opportunity` via `opportunity_addresses_need`), mirroring `journey_step_reveals_need` one level deeper.
|
|
16
|
+
- `JourneyStepProperties.step_order` and `JourneyActionProperties.action_order`: scalar ordering, completing a single `*_order` convention across phase / step / action (matching the existing `phase_order` and `customer_journey_stage.stage_order`). `journey_step_precedes_journey_step` remains the explicit-chain option for branching journeys.
|
|
17
|
+
- `journey-phases-without-canonical-steps` curated anti-pattern (high severity): fires when phases span steps but no journey owns them via `user_journey_contains_journey_step`, so `validate_graph` surfaces a journey with no canonical step spine.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- **`journey_phase_has_step` → `journey_phase_spans_journey_step`** (paired, via `UPG_EDGE_MIGRATIONS['0.9.2']`): the phase-to-step edge becomes non-owning (verb `has_step` to `spans`, classification `hierarchy` to `cross-domain`). `journey_phase` is removed as a containment parent of `journey_step` in the hierarchy; `user_journey` keeps `journey_step` (owned spine) and `journey_phase` (band overlay).
|
|
21
|
+
- `properties/domains/ux-design.ts` JSDoc reconciled to the actual edge names (removed six phantom edges that the spec documented but never shipped).
|
|
22
|
+
- `presentation/labels.ts` alt-label collisions removed: `user_journey` drops `"customer journey"` (collided with `customer_journey_stage`); `journey_step` drops `"touchpoint"` and `"journey phase"` (distinct entity surfaces).
|
|
23
|
+
- `intelligence/domain-guides.ts` UX creation sequence reordered so `journey_step` precedes its child `journey_action`.
|
|
24
|
+
|
|
25
|
+
### Notes
|
|
26
|
+
- `journey_phase` and `journey_action` remain `proposed` (the v0.2 Experience-Design extension over the stable 0.1.0 journey/step spine); not promoted to `stable` in this pass.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## [0.9.1] - 2026-06-09
|
|
31
|
+
|
|
32
|
+
**Cross-product read layer + an OKR-alignment edge + a workspace-resolution fix.** One core spec addition (the `contributes_to` cross-product edge), the read counterpart to 0.8.16's portfolio write tier (server tooling), and a `switch_product` bug fix. From batch-3 dogfooding (portfolio strategy reasoning across the full multi-product workspace). All additive; existing files stay valid.
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- `contributes_to` cross-product edge type in `UPG_CROSS_EDGE_TYPES` (union 7 → 8): the directional OKR rollup / alignment edge, subordinate → superior (product `objective` → company `objective`, product `key_result` → company `key_result`, product `outcome` → company `outcome`). Unlike the symmetric `shares_*` peer edges it is hierarchical, so a portfolio can answer "which company objective is this product serving?" and "which company KRs have no product driving them?". Additive; existing files stay valid. Decision: `2026-06-09-cross-product-okr-alignment-edge.md` (batch-3 #14).
|
|
36
|
+
- (MCP server, not core spec) `portfolio_query` + `portfolio_digest`: read node content and health digests ACROSS products in one call — the multi-product `query` / `get_graph_digest` — without `switch_product`. The read counterpart to the 0.8.16 portfolio write tier. Read-only and parallel-safe: the active product is read from the live store, every other product via a transient read-only load. Tool surface 106 → 108 (batch-3 #13).
|
|
37
|
+
- (SDK) `UPGFileStore.loadReadOnly()`: parse + normalise + index a `.upg` without starting a file watcher or taking a lock, for transient cross-product reads.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
- (MCP server) `switch_product` bare-name resolution now anchors to the workspace `.upg/` directory first and requires a regular file, so a bare product name (e.g. `sanity`) that collides with a sibling source directory (`sanity/`) loads `.upg/sanity.upg` instead of throwing `EISDIR` (batch-3 #12).
|
|
41
|
+
|
|
42
|
+
### Deferred
|
|
43
|
+
- Cross-product **write** (writing nodes/edges into non-active products without `switch_product`) is tracked as batch-4 — the write counterpart to this read layer. Strategic linkage across products is already expressible today via `contributes_to` cross-edges (no switching required); only content propagation into product internals is outstanding.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## [0.9.0] - 2026-06-09
|
|
11
48
|
|
|
12
49
|
**Breaking type rename (with migration) + framework-scoped scoring completion.** Two coordinated spec changes ship in this cut, both additive + deprecate (existing `.upg` files dual-read via `UPG_MIGRATIONS['0.9.0']`): the `theme` → `roadmap_theme` rename (UPG-660, completing the N6 four-way theme-family disambiguation) and the framework-scoped scoring migration for `solution` + `opportunity` (UPG-644, completing UPG-595). Decisions: `2026-06-09-theme-roadmap-theme-rename.md`, `2026-06-05-framework-scoped-scoring-completion.md`.
|
|
13
50
|
|
|
@@ -27,7 +64,7 @@ This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
27
64
|
- `theme` (`ent_080`): retained in the type union and resolvable via the migration map for the 0.9.x dual-read window; `replacement: 'roadmap_theme'`. Loaders retarget old nodes and the four old edge keys automatically.
|
|
28
65
|
- `solution`: `reach`, `impact`, `confidence`, `effort`, `rice_score` (apply `rice-scoring`). `timeline` is unaffected (intrinsic).
|
|
29
66
|
- `opportunity`: `reach`, `frequency`, `pain`, `opportunity_score` (apply `opportunity-sizing`).
|
|
30
|
-
- Native scoring fields are signalled deprecated via `@deprecated` JSDoc (flowing into the generated `UPG_PROPERTY_SCHEMA` descriptions) and stay dual-read for 0.9.x. Removal plus the `migrate_properties` lift onto `framework_exercise` includes-edges lands in 0.9.1, **after** consumers read from the edge (never before: a premature data move silently flattens sort/quadrant surfaces to zero).
|
|
67
|
+
- Native scoring fields are signalled deprecated via `@deprecated` JSDoc (flowing into the generated `UPG_PROPERTY_SCHEMA` descriptions) and stay dual-read for 0.9.x. Removal plus the `migrate_properties` lift onto `framework_exercise` includes-edges lands in a later 0.9.x cut (originally earmarked 0.9.1; 0.9.1 became the batch-3 read layer), **after** consumers read from the edge (never before: a premature data move silently flattens sort/quadrant surfaces to zero).
|
|
31
68
|
- Follow-up (0.9.x): a machine-readable `PropertyDefinition.deprecated` field so the property-registry generator emits it and the public GraphQL generator can mark removed scalars `@deprecated` rather than dropping them silently.
|
|
32
69
|
|
|
33
70
|
---
|
package/dist/index.cjs
CHANGED
|
@@ -1484,8 +1484,24 @@ var UPG_EDGE_CATALOG = {
|
|
|
1484
1484
|
journey_step_realised_by_feature: { forward_verb: "realised_by", reverse_verb: "realises", classification: "cross-domain", source_type: "journey_step", target_type: "feature" },
|
|
1485
1485
|
opportunity_improves_user_journey: { forward_verb: "improves", reverse_verb: "improved_by", classification: "cross-domain", source_type: "opportunity", target_type: "user_journey" },
|
|
1486
1486
|
user_journey_passes_through_journey_phase: { forward_verb: "passes_through", reverse_verb: "is_phase_of", classification: "hierarchy", source_type: "user_journey", target_type: "journey_phase" },
|
|
1487
|
-
|
|
1487
|
+
// (since v0.9.2, UPG-663) A journey_phase is a temporal BAND over the
|
|
1488
|
+
// journey's single step timeline, not a container that owns steps. Steps
|
|
1489
|
+
// belong to the journey via `user_journey_contains_journey_step` (the stable
|
|
1490
|
+
// 0.1.0 spine); a phase merely SPANS a range of them. Mirrors the marketing
|
|
1491
|
+
// precedent `customer_journey_stage_spans_journey_step`. Renamed from the
|
|
1492
|
+
// owning `journey_phase_has_step` (hierarchy) so a step has exactly one
|
|
1493
|
+
// containment parent. See UPG_EDGE_MIGRATIONS['0.9.2'].
|
|
1494
|
+
journey_phase_spans_journey_step: { forward_verb: "spans", reverse_verb: "spanned_by", classification: "cross-domain", source_type: "journey_phase", target_type: "journey_step" },
|
|
1488
1495
|
journey_step_has_action: { forward_verb: "has_action", reverse_verb: "is_action_in", classification: "hierarchy", source_type: "journey_step", target_type: "journey_action" },
|
|
1496
|
+
// (since v0.9.2, UPG-663) journey_action outbound edges. Fixes the
|
|
1497
|
+
// discovery dead-end (D2). The finest blueprint layer carries pain_score /
|
|
1498
|
+
// opportunity_score "to drive opportunity discovery" but previously had zero
|
|
1499
|
+
// outbound edges. Opportunity discovery routes through `need` (mirroring
|
|
1500
|
+
// `journey_step_reveals_need`), which already reaches `opportunity` via the
|
|
1501
|
+
// user chain; the action does not link an opportunity directly. The feature
|
|
1502
|
+
// edge mirrors `journey_step_realised_by_feature` one level deeper.
|
|
1503
|
+
journey_action_surfaces_need: { forward_verb: "surfaces", reverse_verb: "surfaced_in", classification: "cross-domain", source_type: "journey_action", target_type: "need" },
|
|
1504
|
+
journey_action_realised_by_feature: { forward_verb: "realised_by", reverse_verb: "realises", classification: "cross-domain", source_type: "journey_action", target_type: "feature" },
|
|
1489
1505
|
// 2.5 UI System Domain
|
|
1490
1506
|
product_systematised_in_design_system: { forward_verb: "systematised_in", reverse_verb: "systematises", classification: "hierarchy", source_type: "product", target_type: "design_system" },
|
|
1491
1507
|
product_built_with_design_component: { forward_verb: "built_with", reverse_verb: "built_for", classification: "hierarchy", source_type: "product", target_type: "design_component" },
|
|
@@ -2951,7 +2967,8 @@ var UPG_CROSS_EDGE_TYPES = [
|
|
|
2951
2967
|
"depends_on_product",
|
|
2952
2968
|
"cannibalises",
|
|
2953
2969
|
"succeeds",
|
|
2954
|
-
"hosts"
|
|
2970
|
+
"hosts",
|
|
2971
|
+
"contributes_to"
|
|
2955
2972
|
];
|
|
2956
2973
|
|
|
2957
2974
|
// src/registry/entity-type-resolution.ts
|
|
@@ -3242,8 +3259,13 @@ var UPG_VALID_CHILDREN = {
|
|
|
3242
3259
|
// parallel to `observation: ['quote']`. Research-synthesis canon.
|
|
3243
3260
|
// Pairs with `insight_evidenced_by_quote` in the edge catalog.
|
|
3244
3261
|
// ── Design hierarchy ────────────────────────────────────────────────────────
|
|
3262
|
+
// (UPG-663, v0.9.2) A user_journey owns its steps (the stable 0.1.0 spine)
|
|
3263
|
+
// and carries phases as a non-owning band overlay. A journey_phase is NO
|
|
3264
|
+
// LONGER a containment parent of journey_step: it SPANS steps via the
|
|
3265
|
+
// `journey_phase_spans_journey_step` edge (mirroring the marketing
|
|
3266
|
+
// `customer_journey_stage_spans_journey_step` precedent), so each step has
|
|
3267
|
+
// exactly one containment parent and the journey has one canonical step list.
|
|
3245
3268
|
user_journey: ["journey_step", "journey_phase"],
|
|
3246
|
-
journey_phase: ["journey_step"],
|
|
3247
3269
|
journey_step: ["journey_action"],
|
|
3248
3270
|
// v0.5.8 (UPG-528 Part 2d): insights own their evidencing quotes;
|
|
3249
3271
|
// parallel to `observation: ['quote']`. Research-synthesis canon
|
|
@@ -7796,6 +7818,20 @@ function getSplitMigrations(fromVersion, toVersion) {
|
|
|
7796
7818
|
return result;
|
|
7797
7819
|
}
|
|
7798
7820
|
var UPG_EDGE_MIGRATIONS = {
|
|
7821
|
+
"0.9.2": [
|
|
7822
|
+
// (since v0.9.2, UPG-663) Journey-model disambiguation. A journey_phase
|
|
7823
|
+
// is a temporal BAND over the journey's single step timeline, not a
|
|
7824
|
+
// container that owns steps. The owning hierarchy edge
|
|
7825
|
+
// `journey_phase_has_step` is renamed to the non-owning
|
|
7826
|
+
// `journey_phase_spans_journey_step` (mirroring the marketing precedent
|
|
7827
|
+
// `customer_journey_stage_spans_journey_step`). Steps stay owned by the
|
|
7828
|
+
// journey via `user_journey_contains_journey_step` (the stable 0.1.0
|
|
7829
|
+
// spine), so each step keeps a single containment parent and the journey
|
|
7830
|
+
// renders one canonical step list. Endpoints are unchanged
|
|
7831
|
+
// (journey_phase → journey_step); only the edge key and its grammar
|
|
7832
|
+
// (verb has_step → spans, classification hierarchy → cross-domain) change.
|
|
7833
|
+
{ kind: "rename", from: "journey_phase_has_step", to: "journey_phase_spans_journey_step", requires_source_type: "journey_phase", requires_target_type: "journey_step", reason: "Journey-model disambiguation (UPG-663): a phase spans steps, it does not own them. The phase to step edge becomes non-owning (verb has_step to spans), so the step keeps a single containment parent (the journey) and the journey has one canonical step list." }
|
|
7834
|
+
],
|
|
7799
7835
|
"0.9.0": [
|
|
7800
7836
|
// (since v0.9.0, UPG-660) theme → roadmap_theme. The four canonical edges that
|
|
7801
7837
|
// touch the roadmap theme are renamed to the roadmap_theme form. Endpoint guards
|
|
@@ -10294,6 +10330,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10294
10330
|
},
|
|
10295
10331
|
// JourneyActionProperties: Discrete action at a journey step, classified by service layer.
|
|
10296
10332
|
journey_action: {
|
|
10333
|
+
action_order: { type: "number", description: "Display order of this action within its step (0-indexed). The scalar ordering convention shared with `journey_phase.phase_order` and `journey_step.step_order` (UPG-663). Orders the service-blueprint rows within a single moment." },
|
|
10297
10334
|
layer: { type: "string", enum: ["user", "frontstage", "backstage", "support"], description: "Service layer" },
|
|
10298
10335
|
action_description: { type: "string", description: "Plain-language description. Primary content of the action." },
|
|
10299
10336
|
channel: { type: "string", enum: ["in-app", "email", "web", "mobile", "phone", "in-person", "sms", "social", "other"], description: "Channel or surface. Keeps service-blueprint columns consistent across the journey." },
|
|
@@ -10325,7 +10362,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10325
10362
|
system: { type: "string", description: "Performing system or service" },
|
|
10326
10363
|
notes: { type: "string", description: "Free-text notes, observations, or follow-up questions" }
|
|
10327
10364
|
},
|
|
10328
|
-
// JourneyPhaseProperties: Phase within a user journey.
|
|
10365
|
+
// JourneyPhaseProperties: Phase within a user journey. A temporal BAND over the journey's step
|
|
10329
10366
|
journey_phase: {
|
|
10330
10367
|
phase_order: { type: "number", description: "Display order within the journey (0-indexed)" },
|
|
10331
10368
|
label: { type: "string", description: 'Short human-readable name. @example "Discovery", "Onboarding", "Activation"' },
|
|
@@ -10336,8 +10373,9 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10336
10373
|
key_questions: { type: "string[]", description: "Open questions the user asks themselves. Fuel for design and content priorities." },
|
|
10337
10374
|
timeframe: { type: "string", description: 'Typical time window. @example "first 30 seconds", "days 1\u20137", "onboarding week"' }
|
|
10338
10375
|
},
|
|
10339
|
-
// JourneyStepProperties: Single step within a user journey.
|
|
10376
|
+
// JourneyStepProperties: Single step within a user journey. A user-moment on the journey's single
|
|
10340
10377
|
journey_step: {
|
|
10378
|
+
step_order: { type: "number", description: "Display order within the journey's step timeline (0-indexed). The scalar ordering convention shared with `journey_phase.phase_order` and `journey_action.action_order` (UPG-663). For branching journeys, the explicit `journey_step_precedes_journey_step` edge captures the chain." },
|
|
10341
10379
|
touchpoint: { type: "string", description: "Interaction touchpoint" },
|
|
10342
10380
|
channel: { type: "string", description: 'Channel (e.g. "web", "email", "in-store")' },
|
|
10343
10381
|
emotion_score: {
|
|
@@ -18260,8 +18298,13 @@ var STANDARD_LABELS = {
|
|
|
18260
18298
|
interview_guide: { alt_labels: ["discussion guide", "interview script", "moderator guide"] },
|
|
18261
18299
|
survey_response: { alt_labels: ["survey answer", "questionnaire response"] },
|
|
18262
18300
|
// Design layer
|
|
18263
|
-
|
|
18264
|
-
|
|
18301
|
+
// (UPG-663) alt_labels must not collide with other entity types' canonical
|
|
18302
|
+
// names or alt_labels, or the string->type resolver is ambiguous.
|
|
18303
|
+
// Dropped 'customer journey' (collides with customer_journey_stage),
|
|
18304
|
+
// 'touchpoint' and 'journey phase' (both distinct entity surfaces: a
|
|
18305
|
+
// touchpoint is the journey_step.touchpoint property, a phase is journey_phase).
|
|
18306
|
+
user_journey: { alt_labels: ["journey map", "experience map", "journey"] },
|
|
18307
|
+
journey_step: { alt_labels: ["journey moment", "journey stage"] },
|
|
18265
18308
|
design_component: { alt_labels: ["component", "ui component", "design element"] },
|
|
18266
18309
|
design_token: { alt_labels: ["token", "style token", "css variable"] },
|
|
18267
18310
|
wireframe: { alt_labels: ["wireflow", "lo-fi mockup", "skeleton"] },
|
|
@@ -20326,7 +20369,11 @@ var PRODUCT_SPEC_GUIDE = {
|
|
|
20326
20369
|
var UX_DESIGN_GUIDE = {
|
|
20327
20370
|
domain_id: "ux_design",
|
|
20328
20371
|
anchor_entity: "user_journey",
|
|
20329
|
-
|
|
20372
|
+
// (UPG-663) creation order follows containment: a journey_action is a child
|
|
20373
|
+
// of a journey_step, so the step must precede the action. The journey is the
|
|
20374
|
+
// anchor; phases are the band overlay; steps are the timeline; actions
|
|
20375
|
+
// decompose a step into service-blueprint rows.
|
|
20376
|
+
creation_sequence: ["user_journey", "journey_phase", "journey_step", "journey_action", "screen", "screen_state", "user_flow", "wireframe", "prototype", "design_question", "design_concept"],
|
|
20330
20377
|
patterns: [
|
|
20331
20378
|
{
|
|
20332
20379
|
name: "Journey to Screen Flow",
|
|
@@ -23623,6 +23670,40 @@ var UPG_ANTI_PATTERNS = [
|
|
|
23623
23670
|
stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature"],
|
|
23624
23671
|
severity: "medium",
|
|
23625
23672
|
source: { kind: "fundamental" }
|
|
23673
|
+
},
|
|
23674
|
+
// ── Experience-design layer ─────────────────────────────────────────────
|
|
23675
|
+
{
|
|
23676
|
+
id: "journey-phases-without-canonical-steps",
|
|
23677
|
+
name: "Journey phases without a step spine",
|
|
23678
|
+
description: 'The graph has journey phases spanning steps (`journey_phase_spans_journey_step`), but no journey owns its steps via `user_journey_contains_journey_step`. A phase is a band over a step timeline, not a container. When the timeline itself is missing there is no canonical answer to "what are the steps of this journey?". The phase overlay points at steps the journey does not own.',
|
|
23679
|
+
structured_condition: {
|
|
23680
|
+
operator: "and",
|
|
23681
|
+
checks: [
|
|
23682
|
+
{
|
|
23683
|
+
check: {
|
|
23684
|
+
type: "relationship",
|
|
23685
|
+
source_type: "journey_phase",
|
|
23686
|
+
edge_type: "journey_phase_spans_journey_step",
|
|
23687
|
+
target_type: "journey_step",
|
|
23688
|
+
comparison: "exists"
|
|
23689
|
+
}
|
|
23690
|
+
},
|
|
23691
|
+
{
|
|
23692
|
+
check: {
|
|
23693
|
+
type: "relationship",
|
|
23694
|
+
source_type: "user_journey",
|
|
23695
|
+
edge_type: "user_journey_contains_journey_step",
|
|
23696
|
+
target_type: "journey_step",
|
|
23697
|
+
comparison: "not_exists"
|
|
23698
|
+
}
|
|
23699
|
+
}
|
|
23700
|
+
]
|
|
23701
|
+
},
|
|
23702
|
+
why_it_matters: "Steps owned by no journey render a different step list per consumer: the phase overlay sees them, a journey-direct walk does not. The journey has no deterministic step spine to traverse, score, or map to screens.",
|
|
23703
|
+
remediation: "Own every step under its journey with `user_journey_contains_journey_step`, then let phases span ranges of that single timeline via `journey_phase_spans_journey_step`. The phase is a non-owning band overlay, not the step container.",
|
|
23704
|
+
stages: ["concept", "validation", "build", "beta", "launch", "growth"],
|
|
23705
|
+
severity: "high",
|
|
23706
|
+
source: { kind: "fundamental" }
|
|
23626
23707
|
}
|
|
23627
23708
|
];
|
|
23628
23709
|
function getAntiPatternById(id) {
|
|
@@ -26145,7 +26226,7 @@ function isCanonical(text) {
|
|
|
26145
26226
|
}
|
|
26146
26227
|
|
|
26147
26228
|
// src/index.ts
|
|
26148
|
-
var UPG_VERSION = "0.9.
|
|
26229
|
+
var UPG_VERSION = "0.9.2";
|
|
26149
26230
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
26150
26231
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
26151
26232
|
var UPG_TYPES = getTypes();
|