@unified-product-graph/core 0.12.3 → 0.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -8642,6 +8642,288 @@ var UPG_SCALAR_TO_EDGE_MIGRATIONS = {
8642
8642
  drop_scalar: true,
8643
8643
  reason: "P14 shadow: the subscription_subscribes_to_pricing_tier edge already exists. Backfill the plan as a pricing_tier edge, then drop the name string."
8644
8644
  }
8645
+ ],
8646
+ "0.12.4": [
8647
+ // ── Bucket B — actor-as-string (ADDITIVE: add the ownership edge, KEEP the display string) ──
8648
+ // Per the scalar-vs-edge ADR display-cache rule (2026-06-16) and T3.1 (reuse the
8649
+ // polymorphic node_owned_by_* family; do NOT mint typed actor edges). `drop_scalar`
8650
+ // is FALSE for every entry: the string stays as a human-readable display-cache, and
8651
+ // the edge makes "everything owned by X" queryable across instances. OPT-IN — consumers
8652
+ // run promote_scalars_to_edges when they want the edges; nothing is forced on upgrade.
8653
+ // person-vs-team is the field-level call (ratified 2026-06-16): org units + durable
8654
+ // platform/components → team (9); work items, authored artifacts, and DRIs → person.
8655
+ // Two single-string participant fields (threat_model.participants, ceremony.participants)
8656
+ // are intentionally NOT here: a free-text name list cannot be promoted to one edge
8657
+ // without guessing — they are re-doc'd as display-cache only.
8658
+ // ── owned by a team (org units + durable platform/components) ──
8659
+ {
8660
+ from_type: "feature_area",
8661
+ scalar_property: "owner",
8662
+ target_type: "team",
8663
+ edge_type: "node_owned_by_team",
8664
+ drop_scalar: false,
8665
+ reason: 'P14 actor: a feature area is owned by a team; link node_owned_by_team so "everything this team owns" is queryable. Display string kept as a cache.'
8666
+ },
8667
+ {
8668
+ from_type: "bounded_context",
8669
+ scalar_property: "team_owner",
8670
+ target_type: "team",
8671
+ edge_type: "node_owned_by_team",
8672
+ drop_scalar: false,
8673
+ reason: "P14 actor: the owning team is a first-class entity; link node_owned_by_team. Display string kept as a cache."
8674
+ },
8675
+ {
8676
+ from_type: "service",
8677
+ scalar_property: "owner",
8678
+ target_type: "team",
8679
+ edge_type: "node_owned_by_team",
8680
+ drop_scalar: false,
8681
+ reason: "P14 actor: Backstage-style service ownership rolls up by team; link node_owned_by_team. Display string kept as a cache."
8682
+ },
8683
+ {
8684
+ from_type: "product_area",
8685
+ scalar_property: "owner",
8686
+ target_type: "team",
8687
+ edge_type: "node_owned_by_team",
8688
+ drop_scalar: false,
8689
+ reason: "P14 actor: a product area is an org unit owned by a team; link node_owned_by_team. Display string kept as a cache."
8690
+ },
8691
+ {
8692
+ from_type: "api_contract",
8693
+ scalar_property: "owner",
8694
+ target_type: "team",
8695
+ edge_type: "node_owned_by_team",
8696
+ drop_scalar: false,
8697
+ reason: "P14 actor: an API contract is a service-interface component owned by the team that owns the service (Backstage); link node_owned_by_team. Display string kept as a cache."
8698
+ },
8699
+ {
8700
+ from_type: "database_schema",
8701
+ scalar_property: "owner",
8702
+ target_type: "team",
8703
+ edge_type: "node_owned_by_team",
8704
+ drop_scalar: false,
8705
+ reason: "P14 actor: a database schema is a data component owned by the team responsible for it; link node_owned_by_team. Display string kept as a cache."
8706
+ },
8707
+ {
8708
+ from_type: "design_system",
8709
+ scalar_property: "maintainer",
8710
+ target_type: "team",
8711
+ edge_type: "node_owned_by_team",
8712
+ drop_scalar: false,
8713
+ reason: "P14 actor: a design system is a shared platform maintained by a team; link node_owned_by_team. Display string kept as a cache."
8714
+ },
8715
+ {
8716
+ from_type: "service_level_agreement",
8717
+ scalar_property: "owner",
8718
+ target_type: "team",
8719
+ edge_type: "node_owned_by_team",
8720
+ drop_scalar: false,
8721
+ reason: "P14 actor: an SLA is a service-provider-side commitment owned by a team; link node_owned_by_team. Display string kept as a cache."
8722
+ },
8723
+ {
8724
+ from_type: "key_activity",
8725
+ scalar_property: "operational_owner",
8726
+ target_type: "team",
8727
+ edge_type: "node_owned_by_team",
8728
+ drop_scalar: false,
8729
+ reason: "P14 actor: the operationally accountable owner of a recurring activity is a team; link node_owned_by_team. Display string kept as a cache."
8730
+ },
8731
+ // ── owned by a person (DRIs, work items, authored artifacts; the string is a name, handle, or email) ──
8732
+ {
8733
+ from_type: "strategic_theme",
8734
+ scalar_property: "owner",
8735
+ target_type: "person",
8736
+ edge_type: "node_owned_by_person",
8737
+ drop_scalar: false,
8738
+ reason: "P14 actor: the theme owner is a first-class person; link node_owned_by_person so cross-theme ownership is queryable. Display string kept."
8739
+ },
8740
+ {
8741
+ from_type: "initiative",
8742
+ scalar_property: "owner",
8743
+ target_type: "person",
8744
+ edge_type: "node_owned_by_person",
8745
+ drop_scalar: false,
8746
+ reason: "P14 actor: the initiative owner is a first-class person; link node_owned_by_person. Display string kept."
8747
+ },
8748
+ {
8749
+ from_type: "strategic_pillar",
8750
+ scalar_property: "owner",
8751
+ target_type: "person",
8752
+ edge_type: "node_owned_by_person",
8753
+ drop_scalar: false,
8754
+ reason: "P14 actor: the pillar owner is a first-class person; link node_owned_by_person. Display string kept."
8755
+ },
8756
+ {
8757
+ from_type: "metric",
8758
+ scalar_property: "owner",
8759
+ target_type: "person",
8760
+ edge_type: "node_owned_by_person",
8761
+ drop_scalar: false,
8762
+ reason: 'P14 actor: the metric owner is a first-class person ("every metric this person owns"); link node_owned_by_person. Display string kept.'
8763
+ },
8764
+ {
8765
+ from_type: "data_domain",
8766
+ scalar_property: "steward",
8767
+ target_type: "person",
8768
+ edge_type: "node_owned_by_person",
8769
+ drop_scalar: false,
8770
+ reason: "P14 actor: the data steward is a first-class person; link node_owned_by_person. Display string kept."
8771
+ },
8772
+ {
8773
+ from_type: "partnership",
8774
+ scalar_property: "owner",
8775
+ target_type: "person",
8776
+ edge_type: "node_owned_by_person",
8777
+ drop_scalar: false,
8778
+ reason: "P14 actor: the partnership owner is a first-class person; link node_owned_by_person. Display string kept."
8779
+ },
8780
+ {
8781
+ from_type: "key_resource",
8782
+ scalar_property: "owner",
8783
+ target_type: "person",
8784
+ edge_type: "node_owned_by_person",
8785
+ drop_scalar: false,
8786
+ reason: "P14 actor: the resource owner is a first-class person; link node_owned_by_person. Display string kept."
8787
+ },
8788
+ {
8789
+ from_type: "document",
8790
+ scalar_property: "author",
8791
+ target_type: "person",
8792
+ edge_type: "node_owned_by_person",
8793
+ drop_scalar: false,
8794
+ reason: 'P14 actor: the author is a first-class person ("every document by this author"); link node_owned_by_person. Display string kept.'
8795
+ },
8796
+ {
8797
+ from_type: "outcome",
8798
+ scalar_property: "owner",
8799
+ target_type: "person",
8800
+ edge_type: "node_owned_by_person",
8801
+ drop_scalar: false,
8802
+ reason: "P14 actor: the outcome owner is a first-class person; link node_owned_by_person. Display string kept."
8803
+ },
8804
+ {
8805
+ from_type: "feature",
8806
+ scalar_property: "owner",
8807
+ target_type: "person",
8808
+ edge_type: "node_owned_by_person",
8809
+ drop_scalar: false,
8810
+ reason: "P14 actor: the feature owner is a first-class person; link node_owned_by_person. Display string kept."
8811
+ },
8812
+ {
8813
+ from_type: "epic",
8814
+ scalar_property: "owner",
8815
+ target_type: "person",
8816
+ edge_type: "node_owned_by_person",
8817
+ drop_scalar: false,
8818
+ reason: "P14 actor: the epic owner is a first-class person; link node_owned_by_person. Display string kept."
8819
+ },
8820
+ {
8821
+ from_type: "release",
8822
+ scalar_property: "owner",
8823
+ target_type: "person",
8824
+ edge_type: "node_owned_by_person",
8825
+ drop_scalar: false,
8826
+ reason: "P14 actor: the release owner is a first-class person; link node_owned_by_person. Display string kept."
8827
+ },
8828
+ {
8829
+ from_type: "task",
8830
+ scalar_property: "assignee",
8831
+ target_type: "person",
8832
+ edge_type: "node_owned_by_person",
8833
+ drop_scalar: false,
8834
+ reason: 'P14 actor: the assignee is a first-class person ("every task assigned to this person"); link node_owned_by_person. Display string kept.'
8835
+ },
8836
+ {
8837
+ from_type: "bug",
8838
+ scalar_property: "assignee",
8839
+ target_type: "person",
8840
+ edge_type: "node_owned_by_person",
8841
+ drop_scalar: false,
8842
+ reason: "P14 actor: the assignee is a first-class person; link node_owned_by_person. Display string kept."
8843
+ },
8844
+ {
8845
+ from_type: "roadmap",
8846
+ scalar_property: "owner",
8847
+ target_type: "person",
8848
+ edge_type: "node_owned_by_person",
8849
+ drop_scalar: false,
8850
+ reason: "P14 actor: the roadmap owner is a first-class person; link node_owned_by_person. Display string kept."
8851
+ },
8852
+ {
8853
+ from_type: "journey_step",
8854
+ scalar_property: "owner",
8855
+ target_type: "person",
8856
+ edge_type: "node_owned_by_person",
8857
+ drop_scalar: false,
8858
+ reason: "P14 actor: the journey-step owner is a first-class person; link node_owned_by_person. Display string kept."
8859
+ },
8860
+ {
8861
+ from_type: "design_concept",
8862
+ scalar_property: "owner",
8863
+ target_type: "person",
8864
+ edge_type: "node_owned_by_person",
8865
+ drop_scalar: false,
8866
+ reason: "P14 actor: the design-concept owner is a first-class person; link node_owned_by_person. Display string kept."
8867
+ },
8868
+ {
8869
+ from_type: "technical_debt_item",
8870
+ scalar_property: "owner",
8871
+ target_type: "person",
8872
+ edge_type: "node_owned_by_person",
8873
+ drop_scalar: false,
8874
+ reason: "P14 actor: the debt-item owner is a first-class person; link node_owned_by_person. Display string kept."
8875
+ },
8876
+ {
8877
+ from_type: "feature_flag",
8878
+ scalar_property: "owner",
8879
+ target_type: "person",
8880
+ edge_type: "node_owned_by_person",
8881
+ drop_scalar: false,
8882
+ reason: "P14 actor: the flag owner is a first-class person; link node_owned_by_person. Display string kept."
8883
+ },
8884
+ {
8885
+ from_type: "deployment",
8886
+ scalar_property: "deployer",
8887
+ target_type: "person",
8888
+ edge_type: "node_owned_by_person",
8889
+ drop_scalar: false,
8890
+ reason: 'P14 actor: the deployer is a first-class person ("every deployment by this person"); link node_owned_by_person. Display string kept.'
8891
+ },
8892
+ {
8893
+ from_type: "investigation",
8894
+ scalar_property: "lead_investigator",
8895
+ target_type: "person",
8896
+ edge_type: "node_owned_by_person",
8897
+ drop_scalar: false,
8898
+ reason: "P14 actor: the lead investigator is a first-class person; link node_owned_by_person. Display string kept."
8899
+ },
8900
+ {
8901
+ from_type: "department",
8902
+ scalar_property: "leader",
8903
+ target_type: "person",
8904
+ edge_type: "node_owned_by_person",
8905
+ drop_scalar: false,
8906
+ reason: "P14 actor: the department leader is a first-class person; link node_owned_by_person. Display string kept."
8907
+ },
8908
+ // ── owned by people (multi: string[] of names) ──
8909
+ {
8910
+ from_type: "decision",
8911
+ scalar_property: "decision_makers",
8912
+ target_type: "person",
8913
+ edge_type: "node_owned_by_person",
8914
+ multi: true,
8915
+ drop_scalar: false,
8916
+ reason: "P14 actor: each decision-maker is a first-class person; one node_owned_by_person edge per name. Display list kept as a cache."
8917
+ },
8918
+ {
8919
+ from_type: "review_gate",
8920
+ scalar_property: "required_approvers",
8921
+ target_type: "person",
8922
+ edge_type: "node_owned_by_person",
8923
+ multi: true,
8924
+ drop_scalar: false,
8925
+ reason: "P14 actor: each required approver is a first-class person; one node_owned_by_person edge per name. Display list kept as a cache."
8926
+ }
8645
8927
  ]
8646
8928
  };
8647
8929
  function getScalarToEdgeMigrations(fromVersion, toVersion) {
@@ -9893,7 +10175,7 @@ var UPG_PROPERTY_SCHEMA = {
9893
10175
  spec_url: { type: "string", description: "URL of the specification document" },
9894
10176
  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." },
9895
10177
  version: { type: "string", description: "API version" },
9896
- owner: { type: "string", description: "Maintaining person or team." }
10178
+ owner: { type: "string", description: "Maintaining person or team. Promote to a `node_owned_by_team` edge if ownership must be queryable." }
9897
10179
  },
9898
10180
  // ApiEcosystemProperties: API ecosystem.
9899
10181
  api_ecosystem: {
@@ -9974,7 +10256,7 @@ var UPG_PROPERTY_SCHEMA = {
9974
10256
  },
9975
10257
  // BoundedContextProperties: DDD bounded context.
9976
10258
  bounded_context: {
9977
- team_owner: { type: "string", description: "Owning team" },
10259
+ team_owner: { type: "string", description: "Owning team. Promote to a `node_owned_by_team` edge if ownership must be queryable." },
9978
10260
  tech_stack: { type: "string[]", description: "Technologies used within this context" },
9979
10261
  ubiquitous_language: { type: "string", description: "Key terms and their definitions" }
9980
10262
  },
@@ -10063,7 +10345,7 @@ var UPG_PROPERTY_SCHEMA = {
10063
10345
  steps_to_reproduce: { type: "string", description: "Step-by-step reproduction" },
10064
10346
  environment: { type: "string", description: 'Observed environment (e.g. "prod", "staging", "iOS 17.4")' },
10065
10347
  priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Urgency relative to other work. Independent of `bug_severity` (a critical bug can have low priority if rare)." },
10066
- assignee: { type: "string", description: "Assigned person" },
10348
+ assignee: { type: "string", description: "Assigned person. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
10067
10349
  due_date: { type: "string", description: "ISO date due. Often tied to a release gate or SLA." },
10068
10350
  labels: { type: "string[]", description: "Free-form classification tags. Applied uniformly across work item types." }
10069
10351
  },
@@ -10103,7 +10385,7 @@ var UPG_PROPERTY_SCHEMA = {
10103
10385
  ceremony_type: { type: "string", enum: ["standup", "planning", "review", "retro", "sync", "demo", "other"], description: "Kind of recurring meeting" },
10104
10386
  cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "How often the ceremony occurs. Uses the shared `Cadence` scale." },
10105
10387
  duration_minutes: { type: "number", description: "Typical duration of the meeting in minutes" },
10106
- participants: { type: "string", description: "People or roles who attend" }
10388
+ participants: { type: "string", description: "People or roles who attend. Promote individuals to `node_owned_by_person` edges if participation must be queryable." }
10107
10389
  },
10108
10390
  // CertificationProperties: Certification.
10109
10391
  certification: {
@@ -10433,7 +10715,7 @@ var UPG_PROPERTY_SCHEMA = {
10433
10715
  },
10434
10716
  // DataDomainProperties: DataDomain. A coarse-grained grouping of related data assets (sources,
10435
10717
  data_domain: {
10436
- steward: { type: "string", description: "Accountable person or team" },
10718
+ steward: { type: "string", description: "Accountable person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
10437
10719
  domain_type: { type: "string", enum: ["master", "operational", "analytical", "reference"], description: "Domain contents classification. `master` = canonical entity data (customers, products). `operational` = live transactional data. `analytical` = warehouse / BI data. `reference` = slow-changing lookup data." },
10438
10720
  sensitivity: { type: "string", enum: ["public", "internal", "confidential", "restricted"], description: "Sensitivity band applied across the domain" }
10439
10721
  },
@@ -10499,7 +10781,7 @@ var UPG_PROPERTY_SCHEMA = {
10499
10781
  db_type: { type: "string", enum: ["postgres", "mysql", "mongodb", "redis", "other"], description: "Engine" },
10500
10782
  schema_version: { type: "string", description: "Current schema version" },
10501
10783
  migration_status: { type: "string", enum: ["current", "pending", "failed"], description: "Pending-migration status" },
10502
- owner: { type: "string", description: "Owning person or team responsible for design and migrations." },
10784
+ owner: { type: "string", description: "Owning person or team responsible for design and migrations. Promote to a `node_owned_by_team` edge if ownership must be queryable." },
10503
10785
  table_count: { type: "number", description: "Tables or collections in this schema. Useful for migration scope estimation." }
10504
10786
  },
10505
10787
  // DealProperties: Deal.
@@ -10517,7 +10799,7 @@ var UPG_PROPERTY_SCHEMA = {
10517
10799
  date: { type: "string", description: "ISO date the decision was made or last meaningfully updated." },
10518
10800
  decision_outcome: { type: "string", description: "Outcome text. What was decided. Separate from `rationale` (which explains why)." },
10519
10801
  consequences: { type: "string", description: `Known positive and negative consequences. Mirrors MADR's "Consequences" section.` },
10520
- decision_makers: { type: "string[]", description: `People who made the decision. Mirrors MADR's "Deciders" field.` },
10802
+ decision_makers: { type: "string[]", description: 'People who made the decision. Mirrors MADR\'s "Deciders" field. Promote to `node_owned_by_person` edges (one per name) if ownership must be queryable.' },
10521
10803
  decision_drivers: { type: "string[]", description: `Forces, constraints, and goals that shaped the decision. Mirrors MADR's "Decision Drivers" section. @example ["must work offline", "team has no Go expertise", "cost < $500/mo"]` }
10522
10804
  },
10523
10805
  // DeliverableProperties: Deliverable.
@@ -10538,7 +10820,7 @@ var UPG_PROPERTY_SCHEMA = {
10538
10820
  headcount: { type: "number", description: "Total number of people in the department" },
10539
10821
  budget: { type: "number", description: "Annual budget allocated to the department" },
10540
10822
  department_mission: { type: "string", description: "Charter / purpose statement for the department" },
10541
- leader: { type: "string", description: "Department leader (person or role reference)" },
10823
+ leader: { type: "string", description: "Department leader (person or role reference). Promote to a `node_owned_by_person` edge if ownership must be queryable." },
10542
10824
  fiscal_year: { type: "string", description: "Fiscal year the headcount / budget numbers apply to" }
10543
10825
  },
10544
10826
  // DependencyProperties: Dependency entity.
@@ -10556,7 +10838,7 @@ var UPG_PROPERTY_SCHEMA = {
10556
10838
  deploy_status: { type: "string", enum: ["success", "failure", "rolling"], description: "Current status" },
10557
10839
  sha: { type: "string", description: "Git SHA of the deployed commit" },
10558
10840
  duration_seconds: { type: "number", description: "Wall-clock duration in seconds. Tracks deployment speed trends." },
10559
- deployer: { type: "string", description: "Triggering person or system." }
10841
+ deployer: { type: "string", description: "Triggering person or system. Promote to a `node_owned_by_person` edge if ownership must be queryable." }
10560
10842
  },
10561
10843
  // DesignComponentProperties: Design system component.
10562
10844
  design_component: {
@@ -10573,7 +10855,7 @@ var UPG_PROPERTY_SCHEMA = {
10573
10855
  rationale: { type: "string", description: "Selection or rejection rationale" },
10574
10856
  concept_status: { type: "string", enum: ["exploring", "validated", "selected", "rejected"], description: "Current selection status" },
10575
10857
  maturity: { type: "string", enum: ["sketch", "refined", "final"], description: "Development stage, from rough idea to presentation-ready" },
10576
- owner: { type: "string", description: "Shepherding designer or researcher" }
10858
+ owner: { type: "string", description: "Shepherding designer or researcher. Promote to a `node_owned_by_person` edge if ownership must be queryable." }
10577
10859
  },
10578
10860
  // DesignGuidelineProperties: Design guideline.
10579
10861
  design_guideline: {
@@ -10624,7 +10906,7 @@ var UPG_PROPERTY_SCHEMA = {
10624
10906
  design_system: {
10625
10907
  version: { type: "string", description: "Current version" },
10626
10908
  repo_path: { type: "string", description: "Code repository or package path" },
10627
- maintainer: { type: "string", description: "Maintaining person or team" },
10909
+ maintainer: { type: "string", description: "Maintaining person or team. Promote to a `node_owned_by_team` edge if ownership must be queryable." },
10628
10910
  license: { type: "string", description: "Open-source license, if public" },
10629
10911
  homepage_url: { type: "string", description: "Documentation homepage. Public-facing entry point." }
10630
10912
  },
@@ -10687,7 +10969,7 @@ var UPG_PROPERTY_SCHEMA = {
10687
10969
  source_url: { type: "string", description: "Canonical retrievable URL" },
10688
10970
  platform: { type: "string", enum: ["markdown", "notion", "figma", "google_docs", "confluence", "github", "linear", "other"], description: "Hosting platform" },
10689
10971
  document_type: { type: "string", enum: ["vision", "plan", "decision", "research", "spec", "audit", "session", "feedback", "case-study", "narrative", "bug-report", "archive-collection", "rfc", "runbook", "guide", "onboarding", "brief", "report", "reference"], description: "Purpose classification" },
10690
- author: { type: "string", description: "Author (free-form: name, email, or handle)" },
10972
+ author: { type: "string", description: "Author (free-form: name, email, or handle). Promote to a `node_owned_by_person` edge if ownership must be queryable." },
10691
10973
  last_updated: { type: "string", description: "ISO 8601 last-meaningful-update" },
10692
10974
  word_count: { type: "number", description: "Approximate word count. Useful for planning, indexing, summarisation." },
10693
10975
  content_summary: { type: "string", description: "1\u20133 sentence summary. Drives previews, search snippets, embedding context." },
@@ -10725,7 +11007,7 @@ var UPG_PROPERTY_SCHEMA = {
10725
11007
  epic: {
10726
11008
  estimate: { type: "string", description: 'Rough size estimate (e.g. "3 sprints", "L", "13 points")' },
10727
11009
  priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Task-level priority" },
10728
- owner: { type: "string", description: "Responsible person or team" },
11010
+ owner: { type: "string", description: "Responsible person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
10729
11011
  start_date: { type: "string", description: "ISO date work begins" },
10730
11012
  target_date: { type: "string", description: "ISO date work completes" }
10731
11013
  },
@@ -10905,7 +11187,7 @@ var UPG_PROPERTY_SCHEMA = {
10905
11187
  // FeatureProperties: A discrete, user-facing capability of the product.
10906
11188
  feature: {
10907
11189
  priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Task-level priority" },
10908
- owner: { type: "string", description: "Responsible person or team" },
11190
+ owner: { type: "string", description: "Responsible person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
10909
11191
  start_date: { type: "string", description: "ISO date work begins" },
10910
11192
  target_date: { type: "string", description: "ISO date work completes" },
10911
11193
  health: { type: "string", enum: ["on_track", "at_risk", "off_track"], description: "Delivery health" }
@@ -10915,7 +11197,7 @@ var UPG_PROPERTY_SCHEMA = {
10915
11197
  scope_summary: { type: "string", description: "One-line scope description. Disambiguates from sibling areas at a glance." },
10916
11198
  owning_team: { type: "string", description: "Team identifier or slug. Free-form display. Canonical relationship is the `team_owns_feature_area` edge." },
10917
11199
  feature_count: { type: "number", description: "Approximate feature count under this area. Snapshot; `feature_area_contains_feature` edges are the source of truth.", modifier: "derived" },
10918
- owner: { type: "string", description: "Area owner (handle or email)" },
11200
+ owner: { type: "string", description: "Area owner (handle or email). Promote to a `node_owned_by_team` edge if ownership must be queryable." },
10919
11201
  priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Importance to the product overall" },
10920
11202
  maturity: { type: "string", enum: ["nascent", "growing", "mature", "legacy"], description: "Maturity. `nascent` = newly-formed grouping. `mature` = established surface. `legacy` = being phased out for a successor." },
10921
11203
  area_status: { type: "string", enum: ["active", "planned", "deprecated"], description: "Status in the product structure" }
@@ -10926,7 +11208,7 @@ var UPG_PROPERTY_SCHEMA = {
10926
11208
  flag_status: { type: "string", enum: ["on", "off", "rollout"], description: "Activation state. `on` = enabled for all. `off` = disabled for all. `rollout` = partial via targeting_rules." },
10927
11209
  rollout_pct: { type: "number", description: "Percentage enabled (0\u2013100). Meaningful when `flag_status === 'rollout'`." },
10928
11210
  targeting_rules: { type: "string", description: "Human-readable targeting rules. Full rule evaluation happens in the flag service." },
10929
- owner: { type: "string", description: "Owning person or team responsible for the flag's lifecycle." },
11211
+ owner: { type: "string", description: "Owning person or team responsible for the flag's lifecycle. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
10930
11212
  flag_type: { type: "string", enum: ["temporary", "permanent", "experiment"], description: "Lifecycle classification. `temporary` = should be removed after rollout (kill switch, gradual rollout). `permanent` = long-lived feature gate (entitlement flag). `experiment` = A/B test with a defined end condition." },
10931
11213
  expiry_date: { type: "string", description: "ISO date after which this flag should be cleaned up. A temporary flag without an `expiry_date` is a code smell." },
10932
11214
  created_date: { type: "string", description: "Creation date. Useful for flag age and stale-flag detection." }
@@ -11165,7 +11447,7 @@ var UPG_PROPERTY_SCHEMA = {
11165
11447
  start_date: { type: "string", description: 'ISO start date. @example "2026-04-01"' },
11166
11448
  end_date: { type: "string", description: 'ISO end date. @example "2026-09-30"' },
11167
11449
  budget: { type: "number", description: "Budget allocated (base currency units)" },
11168
- owner: { type: "string", description: "Owning person or team" }
11450
+ owner: { type: "string", description: "Owning person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." }
11169
11451
  },
11170
11452
  // InsightProperties: Unified insight, synthesised from evidence and observations.
11171
11453
  insight: {
@@ -11234,7 +11516,7 @@ var UPG_PROPERTY_SCHEMA = {
11234
11516
  findings: { type: "string", description: "Findings discovered so far" },
11235
11517
  started_at: { type: "string", description: "ISO timestamp the investigation began" },
11236
11518
  resolved_at: { type: "string", description: "ISO timestamp the investigation was concluded. Pairs with `status === 'resolved' | 'abandoned'`." },
11237
- lead_investigator: { type: "string", description: "Lead investigator (email or handle). Distinct from the team owning the affected service." },
11519
+ lead_investigator: { type: "string", description: "Lead investigator (email or handle). Distinct from the team owning the affected service. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
11238
11520
  session_id: { type: "string", description: "Originating session" },
11239
11521
  category: { type: "string", enum: ["performance", "security", "data_quality", "reliability", "cost", "compliance", "other"], description: "Kind of issue under investigation. Distinct from `RootCauseProperties.cause_category`, which captures *why something went wrong*." }
11240
11522
  },
@@ -11364,7 +11646,7 @@ var UPG_PROPERTY_SCHEMA = {
11364
11646
  required: ["value", "label"]
11365
11647
  },
11366
11648
  thought: { type: "string", description: "What the user is thinking" },
11367
- owner: { type: "string", description: "Responsible owner" }
11649
+ owner: { type: "string", description: "Responsible owner. Promote to a `node_owned_by_person` edge if ownership must be queryable." }
11368
11650
  },
11369
11651
  // KeyActivityProperties: KeyActivity.
11370
11652
  key_activity: {
@@ -11373,7 +11655,7 @@ var UPG_PROPERTY_SCHEMA = {
11373
11655
  frequency_count: { type: "number", description: "Exact count of runs in the period. Pairs with `frequency_period`." },
11374
11656
  frequency_period: { type: "string", description: "Recurrence period (ISO-8601 `Duration`, e.g. `'P7D'`)" },
11375
11657
  frequency_rating: { type: "string", enum: ["constant", "regular", "occasional", "rare", "other"], description: "Qualitative tier. Use when an exact rate is unknown." },
11376
- operational_owner: { type: "string", description: "Operationally accountable team or individual" },
11658
+ operational_owner: { type: "string", description: "Operationally accountable team or individual. Promote to a `node_owned_by_team` edge if ownership must be queryable." },
11377
11659
  capacity_constraint: { type: "string", description: "Bottleneck or scaling constraint" },
11378
11660
  automation_level: { type: "string", enum: ["manual", "assisted", "automated"], description: "How much runs without human intervention" }
11379
11661
  },
@@ -11381,7 +11663,7 @@ var UPG_PROPERTY_SCHEMA = {
11381
11663
  key_resource: {
11382
11664
  resource_type: { type: "string", enum: ["physical", "intellectual", "human", "financial"], description: "Category" },
11383
11665
  criticality: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Criticality to the business model" },
11384
- owner: { type: "string", description: "Accountable person or team" },
11666
+ owner: { type: "string", description: "Accountable person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
11385
11667
  scarcity_risk: {
11386
11668
  type: "assessment",
11387
11669
  scale_id: "severity_5",
@@ -11570,7 +11852,7 @@ var UPG_PROPERTY_SCHEMA = {
11570
11852
  range_min: { type: "number", description: "Minimum expected or baseline value" },
11571
11853
  range_max: { type: "number", description: "Maximum expected or ceiling value" },
11572
11854
  cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "Measurement cadence. Canonical `Cadence` since v0.4.0. `'realtime'` migrates to `'continuous'`; all other values 1:1." },
11573
- owner: { type: "string", description: "Person or team responsible for tracking this metric" },
11855
+ owner: { type: "string", description: "Person or team responsible for tracking this metric. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
11574
11856
  metric_health: { type: "string", enum: ["healthy", "at_risk", "unhealthy", "unknown"], description: "Universal health rollup. Orthogonal to lifecycle and `guardrail_status`. Applies to every metric regardless of `designation`. `healthy` = trending well against target / inside safe range. `at_risk` = drifting, approaching breach or target shortfall. `unhealthy` = missed target or breached; action needed. `unknown` = no current reading or not yet measured. For guardrails specifically, `guardrail_status` remains the breach-specific signal (`safe`/`warning`/`breached`)." },
11575
11857
  guardrail_threshold_min: { type: "number", description: "Lower bound for guardrail safety (below this = breach)" },
11576
11858
  guardrail_threshold_max: { type: "number", description: "Upper bound for guardrail safety (above this = breach)" },
@@ -11757,7 +12039,7 @@ var UPG_PROPERTY_SCHEMA = {
11757
12039
  // OutcomeProperties: A measurable change in user or business state the product drives.
11758
12040
  outcome: {
11759
12041
  timeline: { type: "string", description: 'Target timeframe (e.g. "Q2 2026", "12 months")' },
11760
- owner: { type: "string", description: "Accountable person or team" },
12042
+ owner: { type: "string", description: "Accountable person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
11761
12043
  success_criteria: { type: "string", description: 'What "achieved" looks like, concretely. Pairs with `measurement_method`. @example "30-day retention above 40% for new signups"' },
11762
12044
  measurement_method: { type: "string", enum: ["quantitative", "qualitative", "mixed"], description: "Assessment approach. `quantitative` = metrics drive the call. `qualitative` = observation / interviews. `mixed` = both, weighted case-by-case." },
11763
12045
  current_state: { type: "string", description: "Baseline or latest read" },
@@ -11816,7 +12098,7 @@ var UPG_PROPERTY_SCHEMA = {
11816
12098
  },
11817
12099
  required: ["value", "label"]
11818
12100
  },
11819
- owner: { type: "string", description: "Internal owner" },
12101
+ owner: { type: "string", description: "Internal owner. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
11820
12102
  start_date: { type: "string", description: "Date the partnership became effective (ISO 8601)" }
11821
12103
  },
11822
12104
  // PaywallProperties: Paywall.
@@ -11944,7 +12226,7 @@ var UPG_PROPERTY_SCHEMA = {
11944
12226
  product_area: {
11945
12227
  strategic_priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Strategic priority assigned to this area" },
11946
12228
  description: { type: "string", description: "Narrative description of what this area covers" },
11947
- owner: { type: "string", description: "Person or team that owns this area" }
12229
+ owner: { type: "string", description: "Person or team that owns this area. Promote to a `node_owned_by_team` edge if ownership must be queryable." }
11948
12230
  },
11949
12231
  // ProgramProperties: Program.
11950
12232
  program: {
@@ -12055,7 +12337,7 @@ var UPG_PROPERTY_SCHEMA = {
12055
12337
  release_date: { type: "string", description: "Scheduled or actual release date (ISO)" },
12056
12338
  version: { type: "string", description: 'Semver or named version (e.g. "v2.1.0", "Beta 3")' },
12057
12339
  start_date: { type: "string", description: "ISO date work begins" },
12058
- owner: { type: "string", description: "Responsible person or team" }
12340
+ owner: { type: "string", description: "Responsible person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." }
12059
12341
  },
12060
12342
  // ReleaseStrategyProperties: Release strategy.
12061
12343
  release_strategy: {
@@ -12116,7 +12398,7 @@ var UPG_PROPERTY_SCHEMA = {
12116
12398
  // ReviewGateProperties: Review gate.
12117
12399
  review_gate: {
12118
12400
  gate_type: { type: "string", enum: ["human_review", "automated_check", "approval"], description: "Kind of review required at this gate" },
12119
- required_approvers: { type: "string[]", description: "People or roles that must approve" },
12401
+ required_approvers: { type: "string[]", description: "People or roles that must approve. Promote to `node_owned_by_person` edges (one per name) if ownership must be queryable." },
12120
12402
  gate_status: { type: "string", enum: ["pending", "approved", "rejected", "bypassed"], description: "Current approval status of the gate" }
12121
12403
  },
12122
12404
  // RiskProperties: Risk.
@@ -12156,7 +12438,7 @@ var UPG_PROPERTY_SCHEMA = {
12156
12438
  roadmap: {
12157
12439
  roadmap_type: { type: "string", enum: ["now_next_later", "quarterly", "release_based", "theme_based"], description: "Structure" },
12158
12440
  timeframe: { type: "string", description: "Covered timeframe" },
12159
- owner: { type: "string", description: "Owning person or team" }
12441
+ owner: { type: "string", description: "Owning person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." }
12160
12442
  },
12161
12443
  // RoadmapItemProperties: Roadmap item.
12162
12444
  roadmap_item: {
@@ -12296,7 +12578,7 @@ var UPG_PROPERTY_SCHEMA = {
12296
12578
  service: {
12297
12579
  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." },
12298
12580
  tech_stack: { type: "string[]", description: 'Technologies used (e.g. ["TypeScript", "Postgres", "Redis"])' },
12299
- owner: { type: "string", description: "Owning person or team. Backstage marks this required; strongly recommended." },
12581
+ owner: { type: "string", description: "Owning person or team. Backstage marks this required; strongly recommended. Promote to a `node_owned_by_team` edge if ownership must be queryable." },
12300
12582
  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.' },
12301
12583
  tags: { type: "string[]", description: 'Free-form filter tags (e.g. ["payments", "critical-path", "team-alpha"]).' },
12302
12584
  links: { type: "object[]", description: "Named URLs for documentation, dashboards, runbooks." }
@@ -12317,7 +12599,7 @@ var UPG_PROPERTY_SCHEMA = {
12317
12599
  agreement_term: { type: "string", description: 'Effective term of the agreement (e.g. "12 months", "auto-renewing annual")' },
12318
12600
  effective_date: { type: "string", description: "ISO date effective" },
12319
12601
  expiry_date: { type: "string", description: "ISO date expires. Pairs with `agreement_term` for renewal logic." },
12320
- owner: { type: "string", description: "Party accountable on the service provider side" },
12602
+ owner: { type: "string", description: "Party accountable on the service provider side. Promote to a `node_owned_by_team` edge if ownership must be queryable." },
12321
12603
  consequence_of_breach: { type: "string", description: "What happens if the SLA is breached (credits, penalties, escalation path)" }
12322
12604
  },
12323
12605
  // ServiceLevelIndicatorProperties: Service Level Indicator.
@@ -12464,7 +12746,7 @@ var UPG_PROPERTY_SCHEMA = {
12464
12746
  },
12465
12747
  // StrategicPillarProperties: StrategicPillar entity. Durable multi-year direction the product commits to.
12466
12748
  strategic_pillar: {
12467
- owner: { type: "string", description: "Owning person or team" },
12749
+ owner: { type: "string", description: "Owning person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
12468
12750
  description: { type: "string", description: "Narrative of the pillar's intent" },
12469
12751
  scope: { type: "string", description: "What this pillar covers" },
12470
12752
  time_horizon: { type: "string", description: 'Planning horizon. Typically multi-year. @example "3 years", "2026-2028"' },
@@ -12472,7 +12754,7 @@ var UPG_PROPERTY_SCHEMA = {
12472
12754
  },
12473
12755
  // StrategicThemeProperties: StrategicTheme entity.
12474
12756
  strategic_theme: {
12475
- owner: { type: "string", description: "Owning person or team" },
12757
+ owner: { type: "string", description: "Owning person or team. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
12476
12758
  time_horizon: { type: "string", description: 'Planning horizon. @example "Q1 2026", "FY26"' },
12477
12759
  description: { type: "string", description: "Short narrative of what the theme is about" },
12478
12760
  scope: { type: "string", description: "What the theme explicitly includes or excludes" }
@@ -12565,7 +12847,7 @@ var UPG_PROPERTY_SCHEMA = {
12565
12847
  },
12566
12848
  // TaskProperties: Task: a discrete unit of work, smaller than a story.
12567
12849
  task: {
12568
- assignee: { type: "string", description: "Assigned person" },
12850
+ assignee: { type: "string", description: "Assigned person. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
12569
12851
  effort: { type: "string", description: 'Effort estimate (e.g. "2h", "1d", "3 points"). Use a consistent unit within your team.' },
12570
12852
  priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Relative importance against other tasks" },
12571
12853
  due_date: { type: "string", description: "ISO date due. Typically bounded by the containing story's due date." },
@@ -12611,7 +12893,7 @@ var UPG_PROPERTY_SCHEMA = {
12611
12893
  },
12612
12894
  required: ["value", "label"]
12613
12895
  },
12614
- owner: { type: "string", description: "Owning person or team responsible for paydown." },
12896
+ owner: { type: "string", description: "Owning person or team responsible for paydown. Promote to a `node_owned_by_person` edge if ownership must be queryable." },
12615
12897
  affected_area: { type: "string", description: 'Codebase location, service, or module. @example "apps/graph/src/canvas/", "UserService", "auth module"' },
12616
12898
  interest: { type: "string", description: 'Ongoing cost of leaving it unresolved (the "interest" in the financial metaphor). @example "~2h/sprint of workarounds", "blocks type-safe refactor of checkout"' },
12617
12899
  intentionality: { type: "string", enum: ["deliberate", "inadvertent"], description: "Origin of the debt. `deliberate` = conscious decision to ship something imperfect (prudent or reckless). `inadvertent` = discovered after the fact. Based on Fowler's Technical Debt Quadrant." }
@@ -12719,7 +13001,7 @@ var UPG_PROPERTY_SCHEMA = {
12719
13001
  methodology: { type: "string", enum: ["stride", "dread", "pasta", "attack_tree", "other"], description: 'Methodology. `stride` = Spoofing, Tampering, Repudiation, Information Disclosure, DoS, Elevation of Privilege (OWASP standard). `dread` = Damage, Reproducibility, Exploitability, Affected users, Discoverability (numeric scoring). `pasta` = Process for Attack Simulation and Threat Analysis (7-stage). `attack_tree` = hierarchical tree of attack paths. @example "stride" is the most widely used methodology for web applications' },
12720
13002
  scope: { type: "string", description: 'What system, feature, or data flow is being analysed. @example "user authentication", "payment processing", "admin API"' },
12721
13003
  last_reviewed: { type: "string", description: 'ISO date last reviewed. Models become stale as systems evolve. @example "2026-03-01"' },
12722
- participants: { type: "string", description: 'Participants in the exercise. @example "Alice Chen (security lead), Bob Park (backend engineer), Carol Liu (architect)"' },
13004
+ participants: { type: "string", description: 'Participants in the exercise. @example "Alice Chen (security lead), Bob Park (backend engineer), Carol Liu (architect)". Promote individuals to `node_owned_by_person` edges if participation must be queryable.' },
12723
13005
  threat_count: { type: "number", description: "Threats identified. Key metric for scope and completeness. @example 12" }
12724
13006
  },
12725
13007
  // TouchpointProperties: Customer touchpoint.
@@ -29146,7 +29428,7 @@ function isCanonical(text) {
29146
29428
  }
29147
29429
 
29148
29430
  // src/index.ts
29149
- var UPG_VERSION = "0.12.3";
29431
+ var UPG_VERSION = "0.12.4";
29150
29432
  var UPG_FORMAT_VERSION = "0.4.0";
29151
29433
  var MARKDOWN_FORMAT_VERSION = "0.1";
29152
29434
  var UPG_TYPES = getTypes();