@unified-product-graph/core 0.39.0 → 0.41.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/CHANGELOG.md +31 -0
- package/README.md +1 -1
- package/dist/index.cjs +89 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -1
- package/dist/index.d.ts +94 -1
- package/dist/index.js +89 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -6387,6 +6387,76 @@ declare const UPG_EDGE_CATALOG: {
|
|
|
6387
6387
|
target_type: string;
|
|
6388
6388
|
deliberate_only: true;
|
|
6389
6389
|
};
|
|
6390
|
+
project_contains_epic: {
|
|
6391
|
+
forward_verb: string;
|
|
6392
|
+
reverse_verb: string;
|
|
6393
|
+
classification: "hierarchy";
|
|
6394
|
+
source_type: string;
|
|
6395
|
+
target_type: string;
|
|
6396
|
+
};
|
|
6397
|
+
project_contains_feature: {
|
|
6398
|
+
forward_verb: string;
|
|
6399
|
+
reverse_verb: string;
|
|
6400
|
+
classification: "hierarchy";
|
|
6401
|
+
source_type: string;
|
|
6402
|
+
target_type: string;
|
|
6403
|
+
};
|
|
6404
|
+
project_contains_user_story: {
|
|
6405
|
+
forward_verb: string;
|
|
6406
|
+
reverse_verb: string;
|
|
6407
|
+
classification: "hierarchy";
|
|
6408
|
+
source_type: string;
|
|
6409
|
+
target_type: string;
|
|
6410
|
+
};
|
|
6411
|
+
project_contains_task: {
|
|
6412
|
+
forward_verb: string;
|
|
6413
|
+
reverse_verb: string;
|
|
6414
|
+
classification: "hierarchy";
|
|
6415
|
+
source_type: string;
|
|
6416
|
+
target_type: string;
|
|
6417
|
+
};
|
|
6418
|
+
project_contains_bug: {
|
|
6419
|
+
forward_verb: string;
|
|
6420
|
+
reverse_verb: string;
|
|
6421
|
+
classification: "hierarchy";
|
|
6422
|
+
source_type: string;
|
|
6423
|
+
target_type: string;
|
|
6424
|
+
};
|
|
6425
|
+
project_advances_key_result: {
|
|
6426
|
+
forward_verb: string;
|
|
6427
|
+
reverse_verb: string;
|
|
6428
|
+
classification: "cross-domain";
|
|
6429
|
+
source_type: string;
|
|
6430
|
+
target_type: string;
|
|
6431
|
+
};
|
|
6432
|
+
project_drives_outcome: {
|
|
6433
|
+
forward_verb: string;
|
|
6434
|
+
reverse_verb: string;
|
|
6435
|
+
classification: "cross-domain";
|
|
6436
|
+
source_type: string;
|
|
6437
|
+
target_type: string;
|
|
6438
|
+
};
|
|
6439
|
+
project_assumes_assumption: {
|
|
6440
|
+
forward_verb: string;
|
|
6441
|
+
reverse_verb: string;
|
|
6442
|
+
classification: "cross-domain";
|
|
6443
|
+
source_type: string;
|
|
6444
|
+
target_type: string;
|
|
6445
|
+
};
|
|
6446
|
+
constraint_constrains_project: {
|
|
6447
|
+
forward_verb: string;
|
|
6448
|
+
reverse_verb: string;
|
|
6449
|
+
classification: "cross-domain";
|
|
6450
|
+
source_type: string;
|
|
6451
|
+
target_type: string;
|
|
6452
|
+
};
|
|
6453
|
+
strategic_theme_pursues_project: {
|
|
6454
|
+
forward_verb: string;
|
|
6455
|
+
reverse_verb: string;
|
|
6456
|
+
classification: "cross-domain";
|
|
6457
|
+
source_type: string;
|
|
6458
|
+
target_type: string;
|
|
6459
|
+
};
|
|
6390
6460
|
milestone_gates_release: {
|
|
6391
6461
|
forward_verb: string;
|
|
6392
6462
|
reverse_verb: string;
|
|
@@ -11636,6 +11706,29 @@ declare function rotateSlug<T extends Pick<UPGBaseNode, 'slug' | 'aliases'>>(nod
|
|
|
11636
11706
|
* the containment guardrail (persona↔job↔need decompositions,
|
|
11637
11707
|
* product-local reasoning) that must stay in-graph.
|
|
11638
11708
|
*
|
|
11709
|
+
* WILDCARD ENDPOINTS, STATED PLAINLY (0.41.0, field report `7aaa2f7e`). The
|
|
11710
|
+
* mechanism is described on `isCrossCapable` below, but its consequence was
|
|
11711
|
+
* never written down where a reader looks for it, so a reporter reasonably
|
|
11712
|
+
* read a `decision_*_node` edge's absent scope as unfinished work and proposed
|
|
11713
|
+
* declaring it `provisional`. It cannot be declared: scope is DERIVED, never
|
|
11714
|
+
* authored. And `node` is not a type, so it can never be `portfolio_shared`
|
|
11715
|
+
* and never carries the gate on its own. Therefore:
|
|
11716
|
+
*
|
|
11717
|
+
* **An edge with a `node` wildcard endpoint is `resident` unless its OTHER,
|
|
11718
|
+
* concrete endpoint is a portfolio-shared type, or the edge type is curated
|
|
11719
|
+
* into `UPG_CROSS_EDGE_TYPES` by name.**
|
|
11720
|
+
*
|
|
11721
|
+
* That is why `node_owned_by_team` is cross-capable (team is shared) while
|
|
11722
|
+
* `decision_influences_node`, `decision_produces_node`,
|
|
11723
|
+
* `decision_constrained_by_node` and `risk_threatens_node` are resident:
|
|
11724
|
+
* `decision` and `risk` are not in the shared tier. Only three wildcard edges
|
|
11725
|
+
* are cross-capable today, all of them curated BY NAME.
|
|
11726
|
+
*
|
|
11727
|
+
* Widening one is a two-option decision and BOTH amend a ratified list, which
|
|
11728
|
+
* is why it is not a spec-writer's call: curate the edge type by name, or
|
|
11729
|
+
* promote the concrete endpoint type into the portfolio-shared tier, which
|
|
11730
|
+
* moves every other edge touching that type at the same time.
|
|
11731
|
+
*
|
|
11639
11732
|
* The gate (`isCrossCapable`) is DERIVED from `EntityTypeMeta.portfolio_shared`, so
|
|
11640
11733
|
* the guardrail is self-maintaining: a new persona/job/need internal edge is
|
|
11641
11734
|
* auto-rejected with no list to touch. The gate LOGIC itself never changes the
|
|
@@ -27035,7 +27128,7 @@ declare function checkHeaderSealText(text: string): UPGHeaderSealReport;
|
|
|
27035
27128
|
* it stamps the `upg_version` field of every `.upg` file written by the SDK.
|
|
27036
27129
|
* The `check:version-lockstep` gate enforces this at release time.
|
|
27037
27130
|
*/
|
|
27038
|
-
declare const UPG_VERSION: "0.
|
|
27131
|
+
declare const UPG_VERSION: "0.41.0";
|
|
27039
27132
|
/**
|
|
27040
27133
|
* The `.upg` JSON document format version. Written to the `upg_version` field.
|
|
27041
27134
|
* Evolves independently from `UPG_VERSION` (the catalogue version).
|
package/dist/index.d.ts
CHANGED
|
@@ -6387,6 +6387,76 @@ declare const UPG_EDGE_CATALOG: {
|
|
|
6387
6387
|
target_type: string;
|
|
6388
6388
|
deliberate_only: true;
|
|
6389
6389
|
};
|
|
6390
|
+
project_contains_epic: {
|
|
6391
|
+
forward_verb: string;
|
|
6392
|
+
reverse_verb: string;
|
|
6393
|
+
classification: "hierarchy";
|
|
6394
|
+
source_type: string;
|
|
6395
|
+
target_type: string;
|
|
6396
|
+
};
|
|
6397
|
+
project_contains_feature: {
|
|
6398
|
+
forward_verb: string;
|
|
6399
|
+
reverse_verb: string;
|
|
6400
|
+
classification: "hierarchy";
|
|
6401
|
+
source_type: string;
|
|
6402
|
+
target_type: string;
|
|
6403
|
+
};
|
|
6404
|
+
project_contains_user_story: {
|
|
6405
|
+
forward_verb: string;
|
|
6406
|
+
reverse_verb: string;
|
|
6407
|
+
classification: "hierarchy";
|
|
6408
|
+
source_type: string;
|
|
6409
|
+
target_type: string;
|
|
6410
|
+
};
|
|
6411
|
+
project_contains_task: {
|
|
6412
|
+
forward_verb: string;
|
|
6413
|
+
reverse_verb: string;
|
|
6414
|
+
classification: "hierarchy";
|
|
6415
|
+
source_type: string;
|
|
6416
|
+
target_type: string;
|
|
6417
|
+
};
|
|
6418
|
+
project_contains_bug: {
|
|
6419
|
+
forward_verb: string;
|
|
6420
|
+
reverse_verb: string;
|
|
6421
|
+
classification: "hierarchy";
|
|
6422
|
+
source_type: string;
|
|
6423
|
+
target_type: string;
|
|
6424
|
+
};
|
|
6425
|
+
project_advances_key_result: {
|
|
6426
|
+
forward_verb: string;
|
|
6427
|
+
reverse_verb: string;
|
|
6428
|
+
classification: "cross-domain";
|
|
6429
|
+
source_type: string;
|
|
6430
|
+
target_type: string;
|
|
6431
|
+
};
|
|
6432
|
+
project_drives_outcome: {
|
|
6433
|
+
forward_verb: string;
|
|
6434
|
+
reverse_verb: string;
|
|
6435
|
+
classification: "cross-domain";
|
|
6436
|
+
source_type: string;
|
|
6437
|
+
target_type: string;
|
|
6438
|
+
};
|
|
6439
|
+
project_assumes_assumption: {
|
|
6440
|
+
forward_verb: string;
|
|
6441
|
+
reverse_verb: string;
|
|
6442
|
+
classification: "cross-domain";
|
|
6443
|
+
source_type: string;
|
|
6444
|
+
target_type: string;
|
|
6445
|
+
};
|
|
6446
|
+
constraint_constrains_project: {
|
|
6447
|
+
forward_verb: string;
|
|
6448
|
+
reverse_verb: string;
|
|
6449
|
+
classification: "cross-domain";
|
|
6450
|
+
source_type: string;
|
|
6451
|
+
target_type: string;
|
|
6452
|
+
};
|
|
6453
|
+
strategic_theme_pursues_project: {
|
|
6454
|
+
forward_verb: string;
|
|
6455
|
+
reverse_verb: string;
|
|
6456
|
+
classification: "cross-domain";
|
|
6457
|
+
source_type: string;
|
|
6458
|
+
target_type: string;
|
|
6459
|
+
};
|
|
6390
6460
|
milestone_gates_release: {
|
|
6391
6461
|
forward_verb: string;
|
|
6392
6462
|
reverse_verb: string;
|
|
@@ -11636,6 +11706,29 @@ declare function rotateSlug<T extends Pick<UPGBaseNode, 'slug' | 'aliases'>>(nod
|
|
|
11636
11706
|
* the containment guardrail (persona↔job↔need decompositions,
|
|
11637
11707
|
* product-local reasoning) that must stay in-graph.
|
|
11638
11708
|
*
|
|
11709
|
+
* WILDCARD ENDPOINTS, STATED PLAINLY (0.41.0, field report `7aaa2f7e`). The
|
|
11710
|
+
* mechanism is described on `isCrossCapable` below, but its consequence was
|
|
11711
|
+
* never written down where a reader looks for it, so a reporter reasonably
|
|
11712
|
+
* read a `decision_*_node` edge's absent scope as unfinished work and proposed
|
|
11713
|
+
* declaring it `provisional`. It cannot be declared: scope is DERIVED, never
|
|
11714
|
+
* authored. And `node` is not a type, so it can never be `portfolio_shared`
|
|
11715
|
+
* and never carries the gate on its own. Therefore:
|
|
11716
|
+
*
|
|
11717
|
+
* **An edge with a `node` wildcard endpoint is `resident` unless its OTHER,
|
|
11718
|
+
* concrete endpoint is a portfolio-shared type, or the edge type is curated
|
|
11719
|
+
* into `UPG_CROSS_EDGE_TYPES` by name.**
|
|
11720
|
+
*
|
|
11721
|
+
* That is why `node_owned_by_team` is cross-capable (team is shared) while
|
|
11722
|
+
* `decision_influences_node`, `decision_produces_node`,
|
|
11723
|
+
* `decision_constrained_by_node` and `risk_threatens_node` are resident:
|
|
11724
|
+
* `decision` and `risk` are not in the shared tier. Only three wildcard edges
|
|
11725
|
+
* are cross-capable today, all of them curated BY NAME.
|
|
11726
|
+
*
|
|
11727
|
+
* Widening one is a two-option decision and BOTH amend a ratified list, which
|
|
11728
|
+
* is why it is not a spec-writer's call: curate the edge type by name, or
|
|
11729
|
+
* promote the concrete endpoint type into the portfolio-shared tier, which
|
|
11730
|
+
* moves every other edge touching that type at the same time.
|
|
11731
|
+
*
|
|
11639
11732
|
* The gate (`isCrossCapable`) is DERIVED from `EntityTypeMeta.portfolio_shared`, so
|
|
11640
11733
|
* the guardrail is self-maintaining: a new persona/job/need internal edge is
|
|
11641
11734
|
* auto-rejected with no list to touch. The gate LOGIC itself never changes the
|
|
@@ -27035,7 +27128,7 @@ declare function checkHeaderSealText(text: string): UPGHeaderSealReport;
|
|
|
27035
27128
|
* it stamps the `upg_version` field of every `.upg` file written by the SDK.
|
|
27036
27129
|
* The `check:version-lockstep` gate enforces this at release time.
|
|
27037
27130
|
*/
|
|
27038
|
-
declare const UPG_VERSION: "0.
|
|
27131
|
+
declare const UPG_VERSION: "0.41.0";
|
|
27039
27132
|
/**
|
|
27040
27133
|
* The `.upg` JSON document format version. Written to the `upg_version` field.
|
|
27041
27134
|
* Evolves independently from `UPG_VERSION` (the catalogue version).
|
package/dist/index.js
CHANGED
|
@@ -2735,6 +2735,93 @@ var UPG_EDGE_CATALOG = {
|
|
|
2735
2735
|
// arbitrary work. deliberate_only because project membership is authored,
|
|
2736
2736
|
// never inferred from co-occurrence.
|
|
2737
2737
|
project_delivers_work_item: { forward_verb: "delivers", reverse_verb: "delivered_by", classification: "semantic", source_type: "project", target_type: "node", deliberate_only: true },
|
|
2738
|
+
// ── project as a first-class home for work (0.41.0, Captain-ratified) ──────
|
|
2739
|
+
//
|
|
2740
|
+
// Teams model in Linear, where an Initiative holds Projects and a Project
|
|
2741
|
+
// holds Issues; UPG must express that natively or every sync leaves a reader
|
|
2742
|
+
// guessing which node is which. `project_implements_initiative` already
|
|
2743
|
+
// carries the upper relation (read from the project's side). These five carry
|
|
2744
|
+
// the lower one, and the set is exactly what the Linear issue-type map
|
|
2745
|
+
// produces: an issue becomes a feature, bug, task, user_story or epic.
|
|
2746
|
+
//
|
|
2747
|
+
// WHY THESE ARE CONTAINMENT AND `project_delivers_work_item` IS NOT.
|
|
2748
|
+
// 0.33.0 widened `project_delivers_epic` into the polymorphic
|
|
2749
|
+
// `project_delivers_work_item` and ruled, correctly, that it could not be a
|
|
2750
|
+
// `contains` verb: containment obliges a `UPG_VALID_CHILDREN` pair keyed by
|
|
2751
|
+
// CONCRETE type names, which a wildcard endpoint can never supply. That
|
|
2752
|
+
// argument forecloses containment for the wildcard; it does not foreclose
|
|
2753
|
+
// containment for concrete pairs, which is what these are. So this is not a
|
|
2754
|
+
// reversal of that ruling — it is the half the wildcard could not reach.
|
|
2755
|
+
//
|
|
2756
|
+
// A KNOWN SHADOW PAIR, ACCEPTED DELIBERATELY (Captain, 2026-09-04). Both an
|
|
2757
|
+
// authored `project_contains_task` and a `project_delivers_work_item` can
|
|
2758
|
+
// name the same pair. That duplication is real and is taken on purpose, to
|
|
2759
|
+
// avoid a migration on live `project_delivers_work_item` instances. The
|
|
2760
|
+
// precedence is stated so it is never ambiguous: CONTAINMENT IS THE PARENT
|
|
2761
|
+
// AXIS AND WINS; the polymorphic edge stays the reference for targets outside
|
|
2762
|
+
// the concrete set. If a real graph is ever observed holding both for one
|
|
2763
|
+
// pair, that is the signal to retire the polymorphic edge for these five
|
|
2764
|
+
// types and migrate — the option deliberately not taken here.
|
|
2765
|
+
project_contains_epic: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "project", target_type: "epic" },
|
|
2766
|
+
project_contains_feature: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "project", target_type: "feature" },
|
|
2767
|
+
project_contains_user_story: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "project", target_type: "user_story" },
|
|
2768
|
+
project_contains_task: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "project", target_type: "task" },
|
|
2769
|
+
project_contains_bug: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "project", target_type: "bug" },
|
|
2770
|
+
// ── project's strategic reach (0.41.0) ────────────────────────────────────
|
|
2771
|
+
//
|
|
2772
|
+
// The parity half. `initiative` and `project` are two granularities of the
|
|
2773
|
+
// same idea, and teams pick one: Linear-shaped teams put the dated, owned,
|
|
2774
|
+
// key-result-linked bet in a PROJECT, while the standard's `initiative`
|
|
2775
|
+
// carried all the strategic reach and `project` reached milestone,
|
|
2776
|
+
// deliverable and a wildcard. A team choosing the honest name for its
|
|
2777
|
+
// granularity should not lose its connection to strategy.
|
|
2778
|
+
//
|
|
2779
|
+
// Mirrors of initiative's edges on the FORWARD verbs, so a reader moving
|
|
2780
|
+
// between the two granularities is never re-learning the vocabulary. The
|
|
2781
|
+
// mirror is deliberately not total, and the two places it stops are both
|
|
2782
|
+
// correct rather than sloppy:
|
|
2783
|
+
//
|
|
2784
|
+
// REVERSE VERBS. `strategic_theme_pursues_initiative` reverses to
|
|
2785
|
+
// `pursued_under`, which reads as membership in a theme's programme.
|
|
2786
|
+
// `strategic_theme_pursues_project` reverses to `pursued_by`, because a
|
|
2787
|
+
// project is the vehicle doing the pursuing, not a subdivision of the
|
|
2788
|
+
// theme. Same forward verb, different relationship on the way back.
|
|
2789
|
+
//
|
|
2790
|
+
// CLASSIFICATION. Initiative's five are causal / cross-domain / hierarchy
|
|
2791
|
+
// / semantic; all five of these are `cross-domain`. That is domain
|
|
2792
|
+
// arithmetic, not inconsistency: `initiative` sits in `strategy` alongside
|
|
2793
|
+
// its targets, so a `cross-domain` classification there would be T1.7
|
|
2794
|
+
// same-domain debt, while `project` is `program_mgmt` and every target
|
|
2795
|
+
// here is `strategy`, so `cross-domain` is the measured truth and adds
|
|
2796
|
+
// nothing to that debt.
|
|
2797
|
+
//
|
|
2798
|
+
// CROSS-PRODUCT SCOPE, ruled deliberately (2026-09-04, raised by Troi during
|
|
2799
|
+
// the 0.41.0 editorial pass). Three of initiative's carry
|
|
2800
|
+
// `cross_product_eligible: true` and none of these do, which looks at first
|
|
2801
|
+
// like reinstating at the portfolio seam the reach this change removes
|
|
2802
|
+
// elsewhere. It is not: `key_result`, `outcome` and `strategic_theme` are
|
|
2803
|
+
// all `portfolio_shared`, so these edges already resolve `provisional` and
|
|
2804
|
+
// ARE authorable across graphs today, with a warning, not rejected. The
|
|
2805
|
+
// difference is curated (hard-allow, silent) versus provisional (allowed,
|
|
2806
|
+
// warned). Left provisional on purpose: the curated set is a ratified
|
|
2807
|
+
// snapshot that grows on measured need, and no field evidence yet shows
|
|
2808
|
+
// anyone authoring these across graphs. Promote to curated when it appears,
|
|
2809
|
+
// which is a one-flag change per edge.
|
|
2810
|
+
//
|
|
2811
|
+
// Deliberately NOT mirrored: `initiative_enters_market_segment`,
|
|
2812
|
+
// `_realises_value_proposition`, `_unlocks_revenue_stream` and
|
|
2813
|
+
// `_raises_strategic_question`. A delivery-scoped project does not enter a
|
|
2814
|
+
// market or unlock a revenue stream; that reach belongs to the coarser level,
|
|
2815
|
+
// and copying it down would make the two types synonyms rather than
|
|
2816
|
+
// granularities. `capability` needs no edge either: a project reaches it
|
|
2817
|
+
// through the features it now contains (`capability_implemented_by_feature`),
|
|
2818
|
+
// and `decision` already reaches a project through the polymorphic
|
|
2819
|
+
// `decision_influences_node`.
|
|
2820
|
+
project_advances_key_result: { forward_verb: "advances", reverse_verb: "advanced_by", classification: "cross-domain", source_type: "project", target_type: "key_result" },
|
|
2821
|
+
project_drives_outcome: { forward_verb: "drives", reverse_verb: "driven_by", classification: "cross-domain", source_type: "project", target_type: "outcome" },
|
|
2822
|
+
project_assumes_assumption: { forward_verb: "assumes", reverse_verb: "assumed_by", classification: "cross-domain", source_type: "project", target_type: "assumption" },
|
|
2823
|
+
constraint_constrains_project: { forward_verb: "constrains", reverse_verb: "constrained_by", classification: "cross-domain", source_type: "constraint", target_type: "project" },
|
|
2824
|
+
strategic_theme_pursues_project: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "cross-domain", source_type: "strategic_theme", target_type: "project" },
|
|
2738
2825
|
milestone_gates_release: { forward_verb: "gates", reverse_verb: "gated_by", classification: "cross-domain", source_type: "milestone", target_type: "release" },
|
|
2739
2826
|
milestone_triggers_release: { forward_verb: "triggers", reverse_verb: "triggered_by", classification: "cross-domain", source_type: "milestone", target_type: "release" },
|
|
2740
2827
|
deliverable_ships_feature: { forward_verb: "ships", reverse_verb: "shipped_by", classification: "cross-domain", source_type: "deliverable", target_type: "feature" },
|
|
@@ -7727,7 +7814,7 @@ var UPG_VALID_CHILDREN = {
|
|
|
7727
7814
|
subscription: ["invoice"],
|
|
7728
7815
|
// ── Program Management hierarchy ─────────────────────────────────────────────
|
|
7729
7816
|
program: ["project", "risk_register", "change_request", "resource_allocation", "status_report"],
|
|
7730
|
-
project: ["milestone", "deliverable"],
|
|
7817
|
+
project: ["milestone", "deliverable", "epic", "feature", "user_story", "task", "bug"],
|
|
7731
7818
|
risk_register: ["risk"],
|
|
7732
7819
|
// ── Accessibility hierarchy ──────────────────────────────────────────────────
|
|
7733
7820
|
a11y_standard: ["a11y_guideline", "a11y_audit", "a11y_annotation"],
|
|
@@ -33894,7 +33981,7 @@ function checkHeaderSealText(text) {
|
|
|
33894
33981
|
}
|
|
33895
33982
|
|
|
33896
33983
|
// src/index.ts
|
|
33897
|
-
var UPG_VERSION = "0.
|
|
33984
|
+
var UPG_VERSION = "0.41.0";
|
|
33898
33985
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
33899
33986
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
33900
33987
|
var UPG_TYPES = getTypes();
|