@unified-product-graph/core 0.32.0 → 0.32.1

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.d.cts CHANGED
@@ -12601,7 +12601,10 @@ interface EmptyCell {
12601
12601
  }
12602
12602
  /** ClassificationAxis: a dimension along which subjects are classified.
12603
12603
  *
12604
- * Top-level taxonomy axis hosted by a `competitive_analysis`. Common shapes:
12604
+ * A top-level taxonomy axis, hosted by either a `competitive_analysis` (via
12605
+ * `competitive_analysis_dimensioned_by_classification_axis`) or a `product` (via
12606
+ * `product_dimensioned_by_classification_axis`, added at 0.32.0 so a product can
12607
+ * carry its own label taxonomy without inventing a `tag` entity). Common shapes:
12605
12608
  * "CMS Architecture", "Editing Paradigm", "Database × Workload Type",
12606
12609
  * "IDE × Language Ecosystem".
12607
12610
  *
@@ -14519,6 +14522,36 @@ interface ChangelogProperties {
14519
14522
  * cooldown). Concretely dated (`starts_on` / `ends_on`), which is the deliberate
14520
14523
  * contrast with the freeform `strategic_theme.time_horizon` label a theme carries.
14521
14524
  *
14525
+ * @remarks
14526
+ * THE ACTIVE CYCLE IS THE ONE WHOSE STATUS IS `active`. There is no `is_active`
14527
+ * property and there will not be one: the lifecycle already holds that fact, and
14528
+ * a boolean beside it would be a second source of truth for one thing, which is
14529
+ * a pair that drifts rather than a pair that agrees.
14530
+ *
14531
+ * INVARIANT, documented and deliberately UNENFORCED: at most one `active` cycle
14532
+ * per parent per `cadence_kind`. No check ships for it. The near-miss is real
14533
+ * rather than hypothetical, which is the reason: a portfolio legitimately runs
14534
+ * two products' iterations concurrently, so the rule holds per parent and a
14535
+ * checker would need a graded corpus to tell a violation from that arrangement.
14536
+ * Under the labeled-fixture doctrine a check without such a corpus is one nobody
14537
+ * can defend, so the rule lives here, where an implementer meets it, instead of
14538
+ * in a validator that would be wrong about real graphs.
14539
+ *
14540
+ * ROLLING A CYCLE FORWARD: set cycle N to `closed`, and RE-POINT the unfinished
14541
+ * work's `planning_cycle_schedules_work_item` edges at N+1. A rolled item ends
14542
+ * with ONE edge, not two. The edge means IS SCHEDULED IN, present tense, so a
14543
+ * second edge would assert the item is in both cycles at once.
14544
+ *
14545
+ * The rejected alternative was keeping both edges plus a `rolled_from` edge
14546
+ * property. It builds the deferred scheduling-provenance layer through a side
14547
+ * door, and the corpus shows what it would actually record: six issues
14548
+ * auto-rolled across five cycles with zero completions, which is five edges per
14549
+ * issue documenting that nothing happened.
14550
+ *
14551
+ * Whether the HISTORY of past scheduling is retained is deliberately still open,
14552
+ * deferred alongside the same question for canvas keys rather than answered
14553
+ * twice in two places with two different answers.
14554
+ *
14522
14555
  * @example
14523
14556
  * const properties: PlanningCycleProperties = {
14524
14557
  * cadence_kind: 'iteration',
@@ -20408,8 +20441,8 @@ interface WorkspaceProperties {
20408
20441
  /**
20409
20442
  * Opaque canvas furniture: the parts of a canvas with no graph referent.
20410
20443
  * Preserved verbatim on round-trip and never interpreted. Tool extension keys
20411
- * are namespaced `<tool>:<key>` with a colon, and no consumer interprets a key
20412
- * it does not own.
20444
+ * are namespaced `<tool>:<key>` with a colon (the rule since 0.31.0), and no
20445
+ * consumer interprets a key it does not own.
20413
20446
  *
20414
20447
  * @remarks
20415
20448
  * The cut here is UPG principle P14 applied literally. Anything that is a
@@ -20534,7 +20567,9 @@ interface WorkspaceCanvas {
20534
20567
  * type that forces every conforming consumer to work around it is describing
20535
20568
  * the wrong thing, so the type now says what the doc always did.
20536
20569
  *
20537
- * THE RULE FOR THESE KEYS (0.31.0):
20570
+ * THE RULE FOR THESE KEYS (0.31.0; the one-release read tolerance for the old
20571
+ * underscore form was retired at 0.32.0, which is a different fact about a
20572
+ * different release and is why the two dates are both correct):
20538
20573
  * - Syntax is `<tool>:<key>`, with a COLON. An underscore key is indistinguishable
20539
20574
  * from an ordinary property name, so it cannot be reliably matched, which is
20540
20575
  * exactly what makes a future migration miss half of what it targets.
@@ -20921,6 +20956,29 @@ interface FrameworkExerciseProperties {
20921
20956
  * to. The genus type; whether it is also a ratified `standard` is carried by
20922
20957
  * `governance`, not the type.
20923
20958
  *
20959
+ * @remarks
20960
+ * CONFORMANCE HAS NO TYPED EDGE TODAY, and this paragraph exists because the
20961
+ * sentence above reads as though it does. "Products implement, expose, or
20962
+ * conform to" names three relationships, and the catalog carries none of them:
20963
+ * everything pointing at `specification` comes from `primitive`,
20964
+ * `operating_lifecycle`, another `specification`, or `organization`. Nothing
20965
+ * comes from `product` or `feature`.
20966
+ *
20967
+ * The cost was measured rather than predicted. A published entity doc, written
20968
+ * by someone reading this very summary, cited
20969
+ * `product_implements_specification`, `product_exposes_specification` and
20970
+ * `feature_conforms_to_specification`. All three are plausible, all three follow
20971
+ * this sentence's own verbs, and none of them has ever existed. The reader did
20972
+ * nothing wrong; the type promised a relationship and the catalog did not
20973
+ * deliver one.
20974
+ *
20975
+ * So, stated plainly until the gap is closed: the central question this type
20976
+ * invites, WHICH PRODUCTS CONFORM TO THIS SPECIFICATION, is not expressible in
20977
+ * typed form. A claim can ride the universal `node_constrains_node`, which is
20978
+ * honest but unqueryable as conformance. Minting a real edge is a MINOR, filed
20979
+ * for 0.33.0 rather than smuggled into a patch, and when it lands this remark
20980
+ * comes out.
20981
+ *
20924
20982
  * @example
20925
20983
  * const properties: SpecificationProperties = {
20926
20984
  * kind: 'language',
@@ -25480,7 +25538,7 @@ declare function checkHeaderSealText(text: string): UPGHeaderSealReport;
25480
25538
  * it stamps the `upg_version` field of every `.upg` file written by the SDK.
25481
25539
  * The `check:version-lockstep` gate enforces this at release time.
25482
25540
  */
25483
- declare const UPG_VERSION: "0.32.0";
25541
+ declare const UPG_VERSION: "0.32.1";
25484
25542
  /**
25485
25543
  * The `.upg` JSON document format version. Written to the `upg_version` field.
25486
25544
  * Evolves independently from `UPG_VERSION` (the catalogue version).
package/dist/index.d.ts CHANGED
@@ -12601,7 +12601,10 @@ interface EmptyCell {
12601
12601
  }
12602
12602
  /** ClassificationAxis: a dimension along which subjects are classified.
12603
12603
  *
12604
- * Top-level taxonomy axis hosted by a `competitive_analysis`. Common shapes:
12604
+ * A top-level taxonomy axis, hosted by either a `competitive_analysis` (via
12605
+ * `competitive_analysis_dimensioned_by_classification_axis`) or a `product` (via
12606
+ * `product_dimensioned_by_classification_axis`, added at 0.32.0 so a product can
12607
+ * carry its own label taxonomy without inventing a `tag` entity). Common shapes:
12605
12608
  * "CMS Architecture", "Editing Paradigm", "Database × Workload Type",
12606
12609
  * "IDE × Language Ecosystem".
12607
12610
  *
@@ -14519,6 +14522,36 @@ interface ChangelogProperties {
14519
14522
  * cooldown). Concretely dated (`starts_on` / `ends_on`), which is the deliberate
14520
14523
  * contrast with the freeform `strategic_theme.time_horizon` label a theme carries.
14521
14524
  *
14525
+ * @remarks
14526
+ * THE ACTIVE CYCLE IS THE ONE WHOSE STATUS IS `active`. There is no `is_active`
14527
+ * property and there will not be one: the lifecycle already holds that fact, and
14528
+ * a boolean beside it would be a second source of truth for one thing, which is
14529
+ * a pair that drifts rather than a pair that agrees.
14530
+ *
14531
+ * INVARIANT, documented and deliberately UNENFORCED: at most one `active` cycle
14532
+ * per parent per `cadence_kind`. No check ships for it. The near-miss is real
14533
+ * rather than hypothetical, which is the reason: a portfolio legitimately runs
14534
+ * two products' iterations concurrently, so the rule holds per parent and a
14535
+ * checker would need a graded corpus to tell a violation from that arrangement.
14536
+ * Under the labeled-fixture doctrine a check without such a corpus is one nobody
14537
+ * can defend, so the rule lives here, where an implementer meets it, instead of
14538
+ * in a validator that would be wrong about real graphs.
14539
+ *
14540
+ * ROLLING A CYCLE FORWARD: set cycle N to `closed`, and RE-POINT the unfinished
14541
+ * work's `planning_cycle_schedules_work_item` edges at N+1. A rolled item ends
14542
+ * with ONE edge, not two. The edge means IS SCHEDULED IN, present tense, so a
14543
+ * second edge would assert the item is in both cycles at once.
14544
+ *
14545
+ * The rejected alternative was keeping both edges plus a `rolled_from` edge
14546
+ * property. It builds the deferred scheduling-provenance layer through a side
14547
+ * door, and the corpus shows what it would actually record: six issues
14548
+ * auto-rolled across five cycles with zero completions, which is five edges per
14549
+ * issue documenting that nothing happened.
14550
+ *
14551
+ * Whether the HISTORY of past scheduling is retained is deliberately still open,
14552
+ * deferred alongside the same question for canvas keys rather than answered
14553
+ * twice in two places with two different answers.
14554
+ *
14522
14555
  * @example
14523
14556
  * const properties: PlanningCycleProperties = {
14524
14557
  * cadence_kind: 'iteration',
@@ -20408,8 +20441,8 @@ interface WorkspaceProperties {
20408
20441
  /**
20409
20442
  * Opaque canvas furniture: the parts of a canvas with no graph referent.
20410
20443
  * Preserved verbatim on round-trip and never interpreted. Tool extension keys
20411
- * are namespaced `<tool>:<key>` with a colon, and no consumer interprets a key
20412
- * it does not own.
20444
+ * are namespaced `<tool>:<key>` with a colon (the rule since 0.31.0), and no
20445
+ * consumer interprets a key it does not own.
20413
20446
  *
20414
20447
  * @remarks
20415
20448
  * The cut here is UPG principle P14 applied literally. Anything that is a
@@ -20534,7 +20567,9 @@ interface WorkspaceCanvas {
20534
20567
  * type that forces every conforming consumer to work around it is describing
20535
20568
  * the wrong thing, so the type now says what the doc always did.
20536
20569
  *
20537
- * THE RULE FOR THESE KEYS (0.31.0):
20570
+ * THE RULE FOR THESE KEYS (0.31.0; the one-release read tolerance for the old
20571
+ * underscore form was retired at 0.32.0, which is a different fact about a
20572
+ * different release and is why the two dates are both correct):
20538
20573
  * - Syntax is `<tool>:<key>`, with a COLON. An underscore key is indistinguishable
20539
20574
  * from an ordinary property name, so it cannot be reliably matched, which is
20540
20575
  * exactly what makes a future migration miss half of what it targets.
@@ -20921,6 +20956,29 @@ interface FrameworkExerciseProperties {
20921
20956
  * to. The genus type; whether it is also a ratified `standard` is carried by
20922
20957
  * `governance`, not the type.
20923
20958
  *
20959
+ * @remarks
20960
+ * CONFORMANCE HAS NO TYPED EDGE TODAY, and this paragraph exists because the
20961
+ * sentence above reads as though it does. "Products implement, expose, or
20962
+ * conform to" names three relationships, and the catalog carries none of them:
20963
+ * everything pointing at `specification` comes from `primitive`,
20964
+ * `operating_lifecycle`, another `specification`, or `organization`. Nothing
20965
+ * comes from `product` or `feature`.
20966
+ *
20967
+ * The cost was measured rather than predicted. A published entity doc, written
20968
+ * by someone reading this very summary, cited
20969
+ * `product_implements_specification`, `product_exposes_specification` and
20970
+ * `feature_conforms_to_specification`. All three are plausible, all three follow
20971
+ * this sentence's own verbs, and none of them has ever existed. The reader did
20972
+ * nothing wrong; the type promised a relationship and the catalog did not
20973
+ * deliver one.
20974
+ *
20975
+ * So, stated plainly until the gap is closed: the central question this type
20976
+ * invites, WHICH PRODUCTS CONFORM TO THIS SPECIFICATION, is not expressible in
20977
+ * typed form. A claim can ride the universal `node_constrains_node`, which is
20978
+ * honest but unqueryable as conformance. Minting a real edge is a MINOR, filed
20979
+ * for 0.33.0 rather than smuggled into a patch, and when it lands this remark
20980
+ * comes out.
20981
+ *
20924
20982
  * @example
20925
20983
  * const properties: SpecificationProperties = {
20926
20984
  * kind: 'language',
@@ -25480,7 +25538,7 @@ declare function checkHeaderSealText(text: string): UPGHeaderSealReport;
25480
25538
  * it stamps the `upg_version` field of every `.upg` file written by the SDK.
25481
25539
  * The `check:version-lockstep` gate enforces this at release time.
25482
25540
  */
25483
- declare const UPG_VERSION: "0.32.0";
25541
+ declare const UPG_VERSION: "0.32.1";
25484
25542
  /**
25485
25543
  * The `.upg` JSON document format version. Written to the `upg_version` field.
25486
25544
  * Evolves independently from `UPG_VERSION` (the catalogue version).
package/dist/index.js CHANGED
@@ -8281,7 +8281,7 @@ var UPG_PROPERTY_MIGRATIONS = {
8281
8281
  kind: "drop_props",
8282
8282
  type: "bug",
8283
8283
  drop_props: ["labels"],
8284
- reason: "0.32.0: BugProperties.labels duplicated base-node `tags` and had no consumers. Same resolution as task."
8284
+ reason: "0.32.0: BugProperties.labels duplicated base-node `tags` and had no consumers. Freeform labels live in `tags`; grouped labels are classification_axis + node_classified_as_classification_value."
8285
8285
  }
8286
8286
  ],
8287
8287
  // ── v0.21.0: UPG-690 D.1 — collapse residual *_status shadows into status ────
@@ -14362,7 +14362,7 @@ var UPG_PROPERTY_SCHEMA = {
14362
14362
  archived_at: { type: "string", description: "ISO timestamp archived. Pairs with `archived === true`. @deprecated since 0.32.0. Use `UPGBaseNode.archived_at`. Lifted by `UPG_PROPERTY_MIGRATIONS['0.32.0']`." },
14363
14363
  icon: { type: "string", description: "Display icon (emoji or icon name)" },
14364
14364
  retention: { type: "string", enum: ["transient", "durable"], description: "Retention intent. Absent means `transient`.", notes: "A workspace is a free-form thinking space and is transient by default, so the spec makes both intents EXPRESSIBLE and takes no position on which reaches the file. Whether to write a transient canvas at all is a tool decision, and the recommended posture is not to: a scratch canvas nobody named has no business in a shared, git-tracked graph, where it lands in everyone's diff. Writing only `durable` workspaces is what keeps a canonical graph entity comfortable with a transient-by-default object." },
14365
- canvas: { type: "object", description: "Opaque canvas furniture: the parts of a canvas with no graph referent. Preserved verbatim on round-trip and never interpreted. Tool extension keys are namespaced `<tool>:<key>` with a colon, and no consumer interprets a key it does not own.", notes: "The cut here is UPG principle P14 applied literally. Anything that is a REFERENCE TO A GRAPH NODE is an edge, which is why placed entities ride `workspace_arranges_node` and not this bag: a node id held as a scalar inside a blob is a foreign key in disguise, and a deleted node would leave a stale reference nothing can detect. Anything that is pure UI chrome with no graph referent stays here, because minting `annotation` and `frame` entity types would add catalog surface that is meaningless to every consumer outside the tool that drew it. WHY THE COLON, and why the rule is in the summary rather than buried here. An underscore key is indistinguishable from an ordinary property name, so a migration that targets namespaced keys cannot match it and no validator can detect one that should have been namespaced. That undetectability is why enforcement lives in the type and the documentation instead of in a check: a check would report clean on a bag full of underscore keys, which is worse than no check. Two conventions were already coexisting when this was ruled (`entopo_views` in a live writer, `entopo:view_blocks` in the contract test certifying preservation), which is how a cheap rule becomes a migration. PRESERVATION IS NOT PERMISSION TO RENDER. Preserving every byte says nothing about meaning: a field-measured canvas carried `excluded: true` tombstones, and a consumer that preserved them faithfully while rendering every entry showed the user images they had deleted." }
14365
+ canvas: { type: "object", description: "Opaque canvas furniture: the parts of a canvas with no graph referent. Preserved verbatim on round-trip and never interpreted. Tool extension keys are namespaced `<tool>:<key>` with a colon (the rule since 0.31.0), and no consumer interprets a key it does not own.", notes: "The cut here is UPG principle P14 applied literally. Anything that is a REFERENCE TO A GRAPH NODE is an edge, which is why placed entities ride `workspace_arranges_node` and not this bag: a node id held as a scalar inside a blob is a foreign key in disguise, and a deleted node would leave a stale reference nothing can detect. Anything that is pure UI chrome with no graph referent stays here, because minting `annotation` and `frame` entity types would add catalog surface that is meaningless to every consumer outside the tool that drew it. WHY THE COLON, and why the rule is in the summary rather than buried here. An underscore key is indistinguishable from an ordinary property name, so a migration that targets namespaced keys cannot match it and no validator can detect one that should have been namespaced. That undetectability is why enforcement lives in the type and the documentation instead of in a check: a check would report clean on a bag full of underscore keys, which is worse than no check. Two conventions were already coexisting when this was ruled (`entopo_views` in a live writer, `entopo:view_blocks` in the contract test certifying preservation), which is how a cheap rule becomes a migration. PRESERVATION IS NOT PERMISSION TO RENDER. Preserving every byte says nothing about meaning: a field-measured canvas carried `excluded: true` tombstones, and a consumer that preserved them faithfully while rendering every entry showed the user images they had deleted." }
14366
14366
  }
14367
14367
  };
14368
14368
  function getPropertySchema(entityType) {
@@ -32840,7 +32840,7 @@ function checkHeaderSealText(text) {
32840
32840
  }
32841
32841
 
32842
32842
  // src/index.ts
32843
- var UPG_VERSION = "0.32.0";
32843
+ var UPG_VERSION = "0.32.1";
32844
32844
  var UPG_FORMAT_VERSION = "0.4.0";
32845
32845
  var MARKDOWN_FORMAT_VERSION = "0.1";
32846
32846
  var UPG_TYPES = getTypes();