@unified-product-graph/core 0.9.11 → 0.9.13
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 -0
- package/dist/index.cjs +289 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +177 -18
- package/dist/index.d.ts +177 -18
- package/dist/index.js +288 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -489,6 +489,12 @@ var UPG_DOMAINS = [
|
|
|
489
489
|
label: "Workspace",
|
|
490
490
|
description: "Spatial thinking spaces for arranging entities, debating decisions, and committing to the graph. Workspaces are transient canvases that sit alongside all other domains, letting you compose and explore relationships before they become permanent graph structure. A framework exercise is a structured workspace: one run of a framework (MoSCoW, RICE, Kano, \u2026) applied to a chosen set of entities, with each entity's result recorded on the exercise-to-entity edge rather than the entity itself.",
|
|
491
491
|
types: ["workspace", "framework_exercise"]
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
id: "foundations",
|
|
495
|
+
label: "Foundations",
|
|
496
|
+
description: "The shared specifications and foundational primitives a product organisation stewards or implements everywhere. Specifications are governed specs (query languages, protocols, data formats, encodings) like GROQ or Portable Text; primitives are the compositional units those specs define (a block, a reference, a query value). Both are registry-hostable canonicals that products implement, expose, or conform to. Distinct from a product feature: a specification has no single owner, no P&L, and no buyer; it is the rulebook many products point at.",
|
|
497
|
+
types: ["specification", "primitive"]
|
|
492
498
|
}
|
|
493
499
|
];
|
|
494
500
|
var UPG_ENTITY_TO_DOMAIN = Object.freeze(
|
|
@@ -508,6 +514,9 @@ function getDomainIdForType(entityType) {
|
|
|
508
514
|
|
|
509
515
|
// src/registry/entity-meta.ts
|
|
510
516
|
var UPG_ENTITY_META = [
|
|
517
|
+
// Foundations (0.9.12): shared specifications + the primitives they define.
|
|
518
|
+
{ name: "specification", type_id: "ent_352", maturity: "proposed", since: "0.9.12" },
|
|
519
|
+
{ name: "primitive", type_id: "ent_353", maturity: "proposed", since: "0.9.12" },
|
|
511
520
|
// ── Strategic ──
|
|
512
521
|
{ name: "product", type_id: "ent_001", maturity: "stable", since: "0.1.0" },
|
|
513
522
|
{ name: "outcome", type_id: "ent_002", maturity: "stable", since: "0.1.0" },
|
|
@@ -2926,7 +2935,16 @@ var UPG_EDGE_CATALOG = {
|
|
|
2926
2935
|
data_quality_rule_governs_data_source: { forward_verb: "governs", reverse_verb: "governed_by", classification: "semantic", source_type: "data_quality_rule", target_type: "data_source" },
|
|
2927
2936
|
// press_release → launch (marketing → go_to_market). A press release had 0
|
|
2928
2937
|
// outbound; it could not name the launch it announces.
|
|
2929
|
-
press_release_announces_launch: { forward_verb: "announces", reverse_verb: "announced_by", classification: "cross-domain", source_type: "press_release", target_type: "launch" }
|
|
2938
|
+
press_release_announces_launch: { forward_verb: "announces", reverse_verb: "announced_by", classification: "cross-domain", source_type: "press_release", target_type: "launch" },
|
|
2939
|
+
// ── Foundations (0.9.12): registry-internal relationships between canonical
|
|
2940
|
+
// specifications and primitives. Product-to-foundation links (implements,
|
|
2941
|
+
// exposes, conforms_to) are portfolio cross-edges, not catalog edges.
|
|
2942
|
+
specification_extends_specification: { forward_verb: "extends", reverse_verb: "extended_by", classification: "hierarchy", source_type: "specification", target_type: "specification" },
|
|
2943
|
+
specification_competes_with_specification: { forward_verb: "competes_with", reverse_verb: "competes_with", classification: "semantic", source_type: "specification", target_type: "specification" },
|
|
2944
|
+
primitive_defined_by_specification: { forward_verb: "defined_by", reverse_verb: "defines", classification: "semantic", source_type: "primitive", target_type: "specification" },
|
|
2945
|
+
primitive_composes_primitive: { forward_verb: "composes", reverse_verb: "composed_by", classification: "hierarchy", source_type: "primitive", target_type: "primitive" },
|
|
2946
|
+
// Stewardship: a registry specification is governed by a (registry-hostable) organization (0.9.13).
|
|
2947
|
+
specification_governed_by_organization: { forward_verb: "governed_by", reverse_verb: "governs", classification: "semantic", source_type: "specification", target_type: "organization" }
|
|
2930
2948
|
};
|
|
2931
2949
|
var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
2932
2950
|
// Universal semantic verbs
|
|
@@ -2993,7 +3011,14 @@ var UPG_CROSS_EDGE_TYPES = [
|
|
|
2993
3011
|
"instance_of",
|
|
2994
3012
|
"area_serves_persona",
|
|
2995
3013
|
"area_targets_market_segment",
|
|
2996
|
-
"rolls_up_to"
|
|
3014
|
+
"rolls_up_to",
|
|
3015
|
+
"product_implements_specification",
|
|
3016
|
+
"product_exposes_specification",
|
|
3017
|
+
"feature_conforms_to_specification",
|
|
3018
|
+
"api_contract_speaks_specification",
|
|
3019
|
+
"product_exposes_primitive",
|
|
3020
|
+
"feature_manipulates_primitive",
|
|
3021
|
+
"primitive_stored_as_data_type"
|
|
2997
3022
|
];
|
|
2998
3023
|
var REGISTRY_PRODUCT_ID = "registry";
|
|
2999
3024
|
|
|
@@ -3057,6 +3082,13 @@ function resolveEntityType(rawType) {
|
|
|
3057
3082
|
|
|
3058
3083
|
// src/grammar/hierarchy.ts
|
|
3059
3084
|
var UPG_VALID_CHILDREN = {
|
|
3085
|
+
// ── Foundations (0.9.12): registry canonicals that self-nest. A
|
|
3086
|
+
// specification extends a specification (a dialect of a parent spec); a
|
|
3087
|
+
// primitive composes primitives (a block contains spans). These back the
|
|
3088
|
+
// hierarchy-classified specification_extends_specification /
|
|
3089
|
+
// primitive_composes_primitive catalog edges.
|
|
3090
|
+
specification: ["specification"],
|
|
3091
|
+
primitive: ["primitive"],
|
|
3060
3092
|
// ── Product (root) ─────────────────────────────────────────────────────────
|
|
3061
3093
|
product: [
|
|
3062
3094
|
// Strategy
|
|
@@ -5977,9 +6009,42 @@ var FRAMEWORK_EXERCISE_LIFECYCLE = {
|
|
|
5977
6009
|
}
|
|
5978
6010
|
]
|
|
5979
6011
|
};
|
|
6012
|
+
var SPECIFICATION_LIFECYCLE = {
|
|
6013
|
+
entity_type: "specification",
|
|
6014
|
+
initial_phase: "draft",
|
|
6015
|
+
terminal_phases: ["superseded"],
|
|
6016
|
+
phases: [
|
|
6017
|
+
{
|
|
6018
|
+
id: "draft",
|
|
6019
|
+
label: "Draft",
|
|
6020
|
+
description: "Being authored. Not yet adopted as the canonical specification.",
|
|
6021
|
+
transitions_to: ["active", "superseded"]
|
|
6022
|
+
},
|
|
6023
|
+
{
|
|
6024
|
+
id: "active",
|
|
6025
|
+
label: "Active",
|
|
6026
|
+
description: "In force. The current authoritative version products implement and conform to.",
|
|
6027
|
+
transitions_to: ["deprecated", "superseded"]
|
|
6028
|
+
},
|
|
6029
|
+
{
|
|
6030
|
+
id: "deprecated",
|
|
6031
|
+
label: "Deprecated",
|
|
6032
|
+
description: "Still valid but no longer recommended; a successor exists or is imminent.",
|
|
6033
|
+
transitions_to: ["superseded"]
|
|
6034
|
+
},
|
|
6035
|
+
{
|
|
6036
|
+
id: "superseded",
|
|
6037
|
+
label: "Superseded",
|
|
6038
|
+
description: "Replaced by a newer specification. Retained for historical reference.",
|
|
6039
|
+
transitions_to: []
|
|
6040
|
+
}
|
|
6041
|
+
]
|
|
6042
|
+
};
|
|
5980
6043
|
var UPG_LIFECYCLES = [
|
|
5981
6044
|
// Product (root)
|
|
5982
6045
|
PRODUCT_LIFECYCLE,
|
|
6046
|
+
// Foundations (0.9.12)
|
|
6047
|
+
SPECIFICATION_LIFECYCLE,
|
|
5983
6048
|
// Discovery & Validation
|
|
5984
6049
|
RESEARCH_STUDY_LIFECYCLE,
|
|
5985
6050
|
NEED_LIFECYCLE,
|
|
@@ -6087,6 +6152,9 @@ function getLifecycleForType(entityType) {
|
|
|
6087
6152
|
return UPG_LIFECYCLES.find((l) => l.entity_type === entityType);
|
|
6088
6153
|
}
|
|
6089
6154
|
var UPG_LIFECYCLE_FREE_TYPES = /* @__PURE__ */ new Set([
|
|
6155
|
+
// ── Foundations (1 of 2): a primitive either exists or is deprecated; no
|
|
6156
|
+
// phase ladder (like metric). `specification` carries a lifecycle. ──
|
|
6157
|
+
"primitive",
|
|
6090
6158
|
// ── User (5): personas and JTBD atoms are reference data ──────────────────
|
|
6091
6159
|
"persona",
|
|
6092
6160
|
"job",
|
|
@@ -7158,6 +7226,50 @@ function getDeprecatedTypes() {
|
|
|
7158
7226
|
return deprecated;
|
|
7159
7227
|
}
|
|
7160
7228
|
var UPG_PROPERTY_MIGRATIONS = {
|
|
7229
|
+
// ── v0.9.12: technical-domain enum widening + data_flow orientation split ──
|
|
7230
|
+
//
|
|
7231
|
+
// Real authoring outgrew four engineering-domain enums. 0.9.12 widens them
|
|
7232
|
+
// (see properties/domains/engineering.ts) and adds a data_flow `orientation`
|
|
7233
|
+
// axis distinct from `direction` (cardinality). These rules dual-read the
|
|
7234
|
+
// legacy values so graphs authored before 0.9.12 stay valid on load:
|
|
7235
|
+
// - data_flow.direction inbound/outbound/internal -> properties.orientation,
|
|
7236
|
+
// and direction resets to unidirectional (all three were one-way).
|
|
7237
|
+
// - integration_pattern.pattern_type "data sync" -> data_sync,
|
|
7238
|
+
// backend_client -> client_library.
|
|
7239
|
+
// - service.service_type backend -> api (use the new `cli` for CLI tools).
|
|
7240
|
+
// - api_contract.protocol HTTP -> REST, HTTP/SSE -> the new SSE value.
|
|
7241
|
+
"0.9.12": [
|
|
7242
|
+
{
|
|
7243
|
+
kind: "remap_property_value",
|
|
7244
|
+
type: "data_flow",
|
|
7245
|
+
property: "direction",
|
|
7246
|
+
value_map: { inbound: "inbound", outbound: "outbound", internal: "internal" },
|
|
7247
|
+
to_property: "orientation",
|
|
7248
|
+
reset_value: "unidirectional",
|
|
7249
|
+
reason: "data_flow.direction conflated cardinality with orientation; the orientation values move to the new `orientation` property and direction resets to `unidirectional` (0.9.12)."
|
|
7250
|
+
},
|
|
7251
|
+
{
|
|
7252
|
+
kind: "remap_property_value",
|
|
7253
|
+
type: "integration_pattern",
|
|
7254
|
+
property: "pattern_type",
|
|
7255
|
+
value_map: { "data sync": "data_sync", backend_client: "client_library" },
|
|
7256
|
+
reason: 'integration_pattern.pattern_type widened in 0.9.12; legacy "data sync" snake-cases to data_sync and backend_client collapses to client_library.'
|
|
7257
|
+
},
|
|
7258
|
+
{
|
|
7259
|
+
kind: "remap_property_value",
|
|
7260
|
+
type: "service",
|
|
7261
|
+
property: "service_type",
|
|
7262
|
+
value_map: { backend: "api" },
|
|
7263
|
+
reason: "service.service_type `backend` is too generic to canonise; normalised to `api` in 0.9.12 (use `cli` for command-line tools)."
|
|
7264
|
+
},
|
|
7265
|
+
{
|
|
7266
|
+
kind: "remap_property_value",
|
|
7267
|
+
type: "api_contract",
|
|
7268
|
+
property: "protocol",
|
|
7269
|
+
value_map: { HTTP: "REST", "HTTP/SSE": "SSE" },
|
|
7270
|
+
reason: "api_contract.protocol normalised in 0.9.12: HTTP maps to REST and HTTP/SSE maps to the new SSE value."
|
|
7271
|
+
}
|
|
7272
|
+
],
|
|
7161
7273
|
// ── v0.8.0: UPG-574 deprecated-property removal pass ───────────────────
|
|
7162
7274
|
//
|
|
7163
7275
|
// The seven properties tagged `@deprecated since v0.4.0` that survived the
|
|
@@ -7651,6 +7763,25 @@ function migrateNodeProperties(node, fromVersion, toVersion) {
|
|
|
7651
7763
|
}
|
|
7652
7764
|
break;
|
|
7653
7765
|
}
|
|
7766
|
+
case "remap_property_value": {
|
|
7767
|
+
const props = workingNode.properties;
|
|
7768
|
+
if (!props || !(m.property in props)) break;
|
|
7769
|
+
const oldValue = props[m.property];
|
|
7770
|
+
if (typeof oldValue !== "string" || !(oldValue in m.value_map)) break;
|
|
7771
|
+
const mapped = m.value_map[oldValue];
|
|
7772
|
+
const nextProps = { ...props };
|
|
7773
|
+
if (m.to_property) {
|
|
7774
|
+
nextProps[m.to_property] = mapped;
|
|
7775
|
+
nextProps[m.property] = m.reset_value ?? mapped;
|
|
7776
|
+
changes.push({ kind: "remapped_property_value", property: m.property, to_property: m.to_property, value_changed: true });
|
|
7777
|
+
} else {
|
|
7778
|
+
nextProps[m.property] = mapped;
|
|
7779
|
+
changes.push({ kind: "remapped_property_value", property: m.property, value_changed: mapped !== oldValue });
|
|
7780
|
+
}
|
|
7781
|
+
workingNode.properties = nextProps;
|
|
7782
|
+
mutated = true;
|
|
7783
|
+
break;
|
|
7784
|
+
}
|
|
7654
7785
|
}
|
|
7655
7786
|
}
|
|
7656
7787
|
}
|
|
@@ -9104,7 +9235,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9104
9235
|
// ApiContractProperties: API contract.
|
|
9105
9236
|
api_contract: {
|
|
9106
9237
|
spec_url: { type: "string", description: "URL of the specification document" },
|
|
9107
|
-
protocol: { type: "string", enum: ["REST", "GraphQL", "gRPC", "AsyncAPI", "SOAP", "WebSocket", "MQTT", "other"], description: "Communication protocol" },
|
|
9238
|
+
protocol: { type: "string", enum: ["REST", "GraphQL", "gRPC", "AsyncAPI", "SOAP", "WebSocket", "MQTT", "SSE", "other"], description: "Communication protocol. `SSE` (server-sent events) added in 0.9.12." },
|
|
9108
9239
|
version: { type: "string", description: "API version" },
|
|
9109
9240
|
owner: { type: "string", description: "Maintaining person or team." }
|
|
9110
9241
|
},
|
|
@@ -9585,7 +9716,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9585
9716
|
data_flow: {
|
|
9586
9717
|
trigger: { type: "string", description: "What triggers the flow" },
|
|
9587
9718
|
data_type: { type: "string", description: "Type of data transferred" },
|
|
9588
|
-
direction: { type: "string", enum: ["unidirectional", "bidirectional"], description: "Direction" },
|
|
9719
|
+
direction: { type: "string", enum: ["unidirectional", "bidirectional"], description: "Direction (cardinality of the link)." },
|
|
9720
|
+
orientation: { type: "string", enum: ["inbound", "outbound", "internal"], description: "Flow orientation relative to the system or component, a separate axis from `direction` (which is cardinality). A flow can be `unidirectional` AND `inbound`. Added in 0.9.12 to split the orientation axis that authors were conflating into `direction` (inbound/outbound/internal values)." },
|
|
9589
9721
|
protocol: { type: "string", enum: ["rest", "graphql", "grpc", "event", "webhook", "file"], description: "Communication protocol" }
|
|
9590
9722
|
},
|
|
9591
9723
|
// DataLineageProperties: DataLineage entity.
|
|
@@ -10341,7 +10473,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10341
10473
|
},
|
|
10342
10474
|
// IntegrationPatternProperties: Integration pattern between systems.
|
|
10343
10475
|
integration_pattern: {
|
|
10344
|
-
pattern_type: { type: "string", enum: ["api", "event", "file", "database", "webhook"], description: "Type" },
|
|
10476
|
+
pattern_type: { type: "string", enum: ["api", "event", "file", "database", "webhook", "adapter", "client_library", "host_embedding", "pipes_and_filters", "data_sync"], description: "Type. `adapter`, `client_library`, `host_embedding`, `pipes_and_filters`, `data_sync` added in 0.9.12." },
|
|
10345
10477
|
protocol: { type: "string", description: "Communication protocol" }
|
|
10346
10478
|
},
|
|
10347
10479
|
// InteractionSpecProperties: Interaction specification.
|
|
@@ -11046,6 +11178,12 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11046
11178
|
tier_order: { type: "number", description: "Display ordering (1 = first tier shown)" },
|
|
11047
11179
|
is_highlighted: { type: "boolean", description: "Highlighted as recommended / most popular" }
|
|
11048
11180
|
},
|
|
11181
|
+
// PrimitiveProperties: A foundational compositional unit a specification defines: the noun products
|
|
11182
|
+
primitive: {
|
|
11183
|
+
primitive_kind: { type: "string", enum: ["data_type", "object", "block", "unit"], description: "The shape of the thing products pass around." },
|
|
11184
|
+
defined_by: { type: "string", description: "The `specification/<slug>` this primitive comes from; nullable for spec-less internal primitives. Mirrors the `primitive_defined_by_specification` edge for quick lookup." },
|
|
11185
|
+
since: { type: "string", description: "Year or version the primitive was introduced." }
|
|
11186
|
+
},
|
|
11049
11187
|
// PrivacyPolicyProperties: Privacy policy.
|
|
11050
11188
|
privacy_policy: {
|
|
11051
11189
|
version: { type: "string", description: "Version identifier of the policy" },
|
|
@@ -11416,7 +11554,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11416
11554
|
},
|
|
11417
11555
|
// ServiceProperties: Service or microservice.
|
|
11418
11556
|
service: {
|
|
11419
|
-
service_type: { type: "string", enum: ["web", "api", "worker", "db", "queue", "library", "mobile", "docs", "lambda"], description: "Functional classification. Expanded from Backstage's component type vocabulary." },
|
|
11557
|
+
service_type: { type: "string", enum: ["web", "api", "worker", "db", "queue", "library", "mobile", "docs", "lambda", "cli"], description: "Functional classification. Expanded from Backstage's component type vocabulary. `cli` added in 0.9.12." },
|
|
11420
11558
|
tech_stack: { type: "string[]", description: 'Technologies used (e.g. ["TypeScript", "Postgres", "Redis"])' },
|
|
11421
11559
|
owner: { type: "string", description: "Owning person or team. Backstage marks this required; strongly recommended." },
|
|
11422
11560
|
lifecycle: { type: "string", enum: ["experimental", "production", "deprecated"], description: 'Service maturity. Answers "how mature is it?". `experimental` = early-stage. `production` = battle-tested. `deprecated` = being phased out.' },
|
|
@@ -11538,6 +11676,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11538
11676
|
},
|
|
11539
11677
|
rice_score: { type: "number", description: "Computed: (reach \xD7 impact \xD7 confidence) / effort. @deprecated 0.9.0:computed by the `rice-scoring` framework on its application edge, not stored on the entity. Removed in 0.9.1." }
|
|
11540
11678
|
},
|
|
11679
|
+
// SpecificationProperties: A governed specification: a query language, protocol, data format, encoding,
|
|
11680
|
+
specification: {
|
|
11681
|
+
kind: { type: "string", enum: ["language", "protocol", "data_format", "encoding", "interface_contract", "object_model"], description: "What the artifact fundamentally is, independent of how it is governed." },
|
|
11682
|
+
language_flavor: { type: "string", enum: ["query", "programming", "markup", "styling", "schema", "template"], description: "Set only when `kind` is `language`: the kind of language." },
|
|
11683
|
+
governance: { type: "string", enum: ["open_spec_stewarded", "open_standard_consortium", "proprietary_open", "internal_primitive", "de_facto"], description: "How the specification is governed (its ratification status, and whether it counts as a `standard`). `open_standard_consortium` is a formal standard (W3C, IETF, ISO); `de_facto` and `internal_primitive` never became one." },
|
|
11684
|
+
steward: { type: "string", description: "The governing body or organisation (may later become an `organization` ref)." },
|
|
11685
|
+
openness: { type: "string", enum: ["open", "proprietary"], description: "Whether the specification itself is open or proprietary." },
|
|
11686
|
+
spec_url: { type: "string", description: "URL of the published specification." },
|
|
11687
|
+
current_version: { type: "string", description: "Latest published version string." },
|
|
11688
|
+
since: { type: "string", description: "Year or version the specification was introduced." },
|
|
11689
|
+
conformance: { type: "string", description: "How conformance is tested (test suite, certification program). Optional." }
|
|
11690
|
+
},
|
|
11541
11691
|
// StakeholderProperties: Stakeholder entity.
|
|
11542
11692
|
stakeholder: {
|
|
11543
11693
|
stakeholder_type: { type: "string", enum: ["internal", "external", "investor", "regulator"], description: "Relationship of the stakeholder to the organisation" },
|
|
@@ -19523,6 +19673,30 @@ var OPERATIONS_QUALITY_PLAYBOOK = {
|
|
|
19523
19673
|
)
|
|
19524
19674
|
]
|
|
19525
19675
|
};
|
|
19676
|
+
var FOUNDATIONS_PLAYBOOK = {
|
|
19677
|
+
id: "playbook:foundations",
|
|
19678
|
+
name: "Foundations",
|
|
19679
|
+
version: "0.9.12",
|
|
19680
|
+
description: "Register the specifications your products implement and expose, and the primitives those specs define, as canonical entities instead of scattered per-product features.",
|
|
19681
|
+
region: "foundations",
|
|
19682
|
+
is_canonical: true,
|
|
19683
|
+
related_framework_ids: [],
|
|
19684
|
+
target_anchor_entity: "specification",
|
|
19685
|
+
creation_sequence: [
|
|
19686
|
+
seqStep(
|
|
19687
|
+
1,
|
|
19688
|
+
"Specifications",
|
|
19689
|
+
["specification"],
|
|
19690
|
+
"Define each governed spec your products implement, expose, or conform to (a query language, protocol, or format) as one canonical specification, not a per-product feature."
|
|
19691
|
+
),
|
|
19692
|
+
seqStep(
|
|
19693
|
+
2,
|
|
19694
|
+
"Primitives",
|
|
19695
|
+
["primitive"],
|
|
19696
|
+
"Define the compositional units those specs define (a block, a reference, a query value) as primitives, each linked to its specification."
|
|
19697
|
+
)
|
|
19698
|
+
]
|
|
19699
|
+
};
|
|
19526
19700
|
var UPG_PLAYBOOKS = [
|
|
19527
19701
|
// Region 1 - strategy_outcomes
|
|
19528
19702
|
STRATEGY_OUTCOMES_PLAYBOOK,
|
|
@@ -19545,7 +19719,9 @@ var UPG_PLAYBOOKS = [
|
|
|
19545
19719
|
// Region 9 - analytics_data
|
|
19546
19720
|
ANALYTICS_DATA_PLAYBOOK,
|
|
19547
19721
|
// Region 10 - operations_quality
|
|
19548
|
-
OPERATIONS_QUALITY_PLAYBOOK
|
|
19722
|
+
OPERATIONS_QUALITY_PLAYBOOK,
|
|
19723
|
+
// Region 11 - foundations
|
|
19724
|
+
FOUNDATIONS_PLAYBOOK
|
|
19549
19725
|
];
|
|
19550
19726
|
|
|
19551
19727
|
// src/step-sequence.ts
|
|
@@ -20287,7 +20463,7 @@ var UPG_DOMAIN_RINGS = [
|
|
|
20287
20463
|
id: "build",
|
|
20288
20464
|
label: "Build",
|
|
20289
20465
|
description: "How do we construct it?",
|
|
20290
|
-
domain_ids: ["engineering", "ai", "automation", "data_analytics", "testing", "devops", "security", "accessibility"]
|
|
20466
|
+
domain_ids: ["engineering", "foundations", "ai", "automation", "data_analytics", "testing", "devops", "security", "accessibility"]
|
|
20291
20467
|
},
|
|
20292
20468
|
{
|
|
20293
20469
|
id: "grow",
|
|
@@ -21202,10 +21378,30 @@ var WORKSPACE_GUIDE = {
|
|
|
21202
21378
|
{ description: "Workspace content is transient by default: promote discoveries to the graph, do not leave them in the workspace" }
|
|
21203
21379
|
]
|
|
21204
21380
|
};
|
|
21381
|
+
var FOUNDATIONS_GUIDE = {
|
|
21382
|
+
domain_id: "foundations",
|
|
21383
|
+
anchor_entity: "specification",
|
|
21384
|
+
creation_sequence: ["specification", "primitive"],
|
|
21385
|
+
patterns: [
|
|
21386
|
+
{
|
|
21387
|
+
name: "Specification defines primitives",
|
|
21388
|
+
description: "A specification governs one or more primitives; each primitive is defined_by the spec and may compose other primitives",
|
|
21389
|
+
entity_types: ["specification", "primitive"],
|
|
21390
|
+
edge_chain: ["primitive_defined_by_specification", "primitive_composes_primitive"]
|
|
21391
|
+
}
|
|
21392
|
+
],
|
|
21393
|
+
required_bridges: [],
|
|
21394
|
+
anti_patterns: [
|
|
21395
|
+
{ description: "A specification scattered as duplicate features across products instead of one canonical with instance_of links" },
|
|
21396
|
+
{ description: "Modelling a governed spec as a product: it has no single owner, P&L, or buyer; it is the rulebook products point at" }
|
|
21397
|
+
]
|
|
21398
|
+
};
|
|
21205
21399
|
var UPG_DOMAIN_GUIDES = [
|
|
21206
21400
|
// Nucleus
|
|
21207
21401
|
PORTFOLIO_GUIDE,
|
|
21208
21402
|
WORKSPACE_GUIDE,
|
|
21403
|
+
// Foundations (0.9.12)
|
|
21404
|
+
FOUNDATIONS_GUIDE,
|
|
21209
21405
|
// Ring 1: Understand
|
|
21210
21406
|
USER_GUIDE,
|
|
21211
21407
|
USER_RESEARCH_GUIDE,
|
|
@@ -23984,6 +24180,47 @@ var UPG_ANTI_PATTERNS = [
|
|
|
23984
24180
|
stages: ["beta", "launch", "growth", "mature"],
|
|
23985
24181
|
severity: "medium",
|
|
23986
24182
|
source: { kind: "practitioner", attribution: "Marty Cagan, Inspired (product discovery)" }
|
|
24183
|
+
},
|
|
24184
|
+
// ── Foundations layer (0.9.13): portfolio-scoped, registry-aware ──────────
|
|
24185
|
+
// These read the shared registry + cross-product edges, so they are evaluated
|
|
24186
|
+
// by portfolio_validate, not the single-graph evaluator. They carry no
|
|
24187
|
+
// structured_condition (the detector is cross-product, not a single-graph
|
|
24188
|
+
// IntelligenceCondition).
|
|
24189
|
+
{
|
|
24190
|
+
id: "specification-without-implementer",
|
|
24191
|
+
since: "0.9.13",
|
|
24192
|
+
scope: "portfolio",
|
|
24193
|
+
name: "Specification without implementer",
|
|
24194
|
+
description: "A specification in the shared registry has no product, feature, or api_contract implementing or conforming to it anywhere in the portfolio. A specification nobody implements is a document, not a contract: it states an intent the portfolio never honours.",
|
|
24195
|
+
why_it_matters: "An unimplemented specification carries authority it has not earned. Teams cite it as a standard while no surface actually conforms, so conformance claims cannot be trusted or traced.",
|
|
24196
|
+
remediation: "Link at least one product, feature, or api_contract to the specification via `product_implements_specification`, `product_exposes_specification`, `feature_conforms_to_specification`, or `api_contract_speaks_specification`; or retire the specification from the registry.",
|
|
24197
|
+
stages: ["validation", "build", "beta", "launch", "growth", "mature"],
|
|
24198
|
+
severity: "medium",
|
|
24199
|
+
source: { kind: "fundamental" }
|
|
24200
|
+
},
|
|
24201
|
+
{
|
|
24202
|
+
id: "primitive-scattered-without-canonical",
|
|
24203
|
+
since: "0.9.13",
|
|
24204
|
+
scope: "portfolio",
|
|
24205
|
+
name: "Primitive scattered without a canonical",
|
|
24206
|
+
description: "The same primitive concept appears as a product-local node in two or more products, but no canonical primitive in the shared registry unifies them. Each product redefines the building block on its own terms, so the portfolio carries several drifting copies of one shared idea instead of a single authoritative definition.",
|
|
24207
|
+
why_it_matters: "Scattered primitives drift apart in name, shape, and meaning. Cross-product reasoning breaks because the same concept reads as several unrelated entities, and a change to the shared building block has no single place to land.",
|
|
24208
|
+
remediation: "Define the shared primitive once in the registry with `define_canonical_entity`, then link each product copy via `register_instance` so the building block has one authoritative definition.",
|
|
24209
|
+
stages: ["build", "beta", "launch", "growth", "mature"],
|
|
24210
|
+
severity: "medium",
|
|
24211
|
+
source: { kind: "fundamental" }
|
|
24212
|
+
},
|
|
24213
|
+
{
|
|
24214
|
+
id: "product-reimplements-specification",
|
|
24215
|
+
since: "0.9.13",
|
|
24216
|
+
scope: "portfolio",
|
|
24217
|
+
name: "Specification reimplemented across products",
|
|
24218
|
+
description: "Two or more products independently implement the same registry specification rather than one depending on a shared implementation. Parallel implementations of a single contract multiply the surface that must stay in sync and usually signal a missing shared library or service.",
|
|
24219
|
+
why_it_matters: "Every independent reimplementation of a specification is another place a conformance bug can hide and another copy that drifts from the contract. The cost of a spec change scales with the number of reimplementers.",
|
|
24220
|
+
remediation: "Consolidate onto one implementation that the others depend on (`depends_on_product` / `hosts`), or confirm the duplication is deliberate and record why. Capture the stewarding organization with `create_registry_edge` so the contract has an owner.",
|
|
24221
|
+
stages: ["build", "beta", "launch", "growth", "mature"],
|
|
24222
|
+
severity: "low",
|
|
24223
|
+
source: { kind: "fundamental" }
|
|
23987
24224
|
}
|
|
23988
24225
|
];
|
|
23989
24226
|
function getAntiPatternById(id) {
|
|
@@ -24007,6 +24244,7 @@ function evaluateAntiPatterns(inputs, options) {
|
|
|
24007
24244
|
const idFilter = options?.anti_pattern_ids ? new Set(options.anti_pattern_ids) : void 0;
|
|
24008
24245
|
const fires = [];
|
|
24009
24246
|
for (const ap of UPG_ANTI_PATTERNS) {
|
|
24247
|
+
if (ap.scope === "portfolio" || !ap.structured_condition) continue;
|
|
24010
24248
|
if (severityFilter && ap.severity !== severityFilter) continue;
|
|
24011
24249
|
if (idFilter && !idFilter.has(ap.id)) continue;
|
|
24012
24250
|
if (inputs.productStage && !ap.stages.includes(inputs.productStage)) {
|
|
@@ -24167,6 +24405,7 @@ function buildViolation(ap) {
|
|
|
24167
24405
|
}
|
|
24168
24406
|
function collectTargetEntities(cond) {
|
|
24169
24407
|
const types = /* @__PURE__ */ new Set();
|
|
24408
|
+
if (!cond) return [];
|
|
24170
24409
|
walk(cond);
|
|
24171
24410
|
return [...types].sort();
|
|
24172
24411
|
function walk(c) {
|
|
@@ -26498,6 +26737,45 @@ var UPG_REGIONS = [
|
|
|
26498
26737
|
crosses_into: "users_needs"
|
|
26499
26738
|
}
|
|
26500
26739
|
]
|
|
26740
|
+
},
|
|
26741
|
+
{
|
|
26742
|
+
id: "foundations",
|
|
26743
|
+
label: "Foundations",
|
|
26744
|
+
order: 11,
|
|
26745
|
+
shape: "polymorphic-target",
|
|
26746
|
+
mental_model: "Shared specs and primitives that many products implement, expose, and conform to.",
|
|
26747
|
+
operators: [
|
|
26748
|
+
"platform architect",
|
|
26749
|
+
"standards author",
|
|
26750
|
+
"staff engineer",
|
|
26751
|
+
"API designer"
|
|
26752
|
+
],
|
|
26753
|
+
composes_atomic_domains: [
|
|
26754
|
+
"foundations"
|
|
26755
|
+
],
|
|
26756
|
+
entities: [
|
|
26757
|
+
{
|
|
26758
|
+
type: "specification",
|
|
26759
|
+
role: "anchor"
|
|
26760
|
+
},
|
|
26761
|
+
{
|
|
26762
|
+
type: "primitive",
|
|
26763
|
+
role: "container"
|
|
26764
|
+
}
|
|
26765
|
+
],
|
|
26766
|
+
anchor: {
|
|
26767
|
+
type: "specification",
|
|
26768
|
+
rationale: "The specification is the rulebook many products point at: they implement, expose, and conform to it, and primitives are defined by it. It is the high-inbound canonical of the Foundations region.",
|
|
26769
|
+
outbound_cross_edge_count: 0,
|
|
26770
|
+
inbound_cross_edge_count: 6
|
|
26771
|
+
},
|
|
26772
|
+
intra_edges: [
|
|
26773
|
+
"specification_extends_specification",
|
|
26774
|
+
"specification_competes_with_specification",
|
|
26775
|
+
"primitive_defined_by_specification",
|
|
26776
|
+
"primitive_composes_primitive"
|
|
26777
|
+
],
|
|
26778
|
+
boundary_edges: []
|
|
26501
26779
|
}
|
|
26502
26780
|
];
|
|
26503
26781
|
var UPG_REGION_MAP = Object.fromEntries(UPG_REGIONS.map((r) => [r.id, r]));
|
|
@@ -27004,7 +27282,7 @@ function isCanonical(text) {
|
|
|
27004
27282
|
}
|
|
27005
27283
|
|
|
27006
27284
|
// src/index.ts
|
|
27007
|
-
var UPG_VERSION = "0.9.
|
|
27285
|
+
var UPG_VERSION = "0.9.13";
|
|
27008
27286
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
27009
27287
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
27010
27288
|
var UPG_TYPES = getTypes();
|
|
@@ -27076,6 +27354,7 @@ export {
|
|
|
27076
27354
|
DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
|
|
27077
27355
|
ENGINEERING_PLATFORM_PLAYBOOK,
|
|
27078
27356
|
EXPERIENCE_DESIGN_BRAND_PLAYBOOK,
|
|
27357
|
+
FOUNDATIONS_PLAYBOOK,
|
|
27079
27358
|
LEGACY_PRODUCT_STAGES,
|
|
27080
27359
|
MARKDOWN_FORMAT_VERSION,
|
|
27081
27360
|
MARKET_COMPETITIVE_PLAYBOOK,
|