@willcgage/module-schematic 0.61.0 → 0.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -43,6 +43,19 @@ interface SchematicEndplate {
43
43
  y: number;
44
44
  heading: number;
45
45
  };
46
+ /** Whether that pose was AUTHORED — placed or typed by the owner — rather
47
+ * than a derived one that found its way into the doc (#182).
48
+ *
49
+ * Authorship used to be inferred from `pose` merely existing, so a derived
50
+ * pose written back silently PINNED the plate: it stopped following the
51
+ * module and went stale the moment the length changed (FMN-0068 ended up with
52
+ * endplate B at x=48 on a 47.9″ board). A pose is only an override when the
53
+ * owner meant it.
54
+ *
55
+ * Absent on A/B = derived residue, ignored. Absent on a placed branch
56
+ * endplate (one with `at`) = still authored — placing it IS the gesture, and
57
+ * docs predate this flag. */
58
+ poseAuthored?: boolean;
46
59
  /** Free-moN endplate FACE width across the track, inches — the physical size
47
60
  * of the standard interface at this end. Free-moN spec: 12″ minimum, 24″
48
61
  * recommended. Absent = the recommended default (modules may differ end to
package/dist/index.d.ts CHANGED
@@ -43,6 +43,19 @@ interface SchematicEndplate {
43
43
  y: number;
44
44
  heading: number;
45
45
  };
46
+ /** Whether that pose was AUTHORED — placed or typed by the owner — rather
47
+ * than a derived one that found its way into the doc (#182).
48
+ *
49
+ * Authorship used to be inferred from `pose` merely existing, so a derived
50
+ * pose written back silently PINNED the plate: it stopped following the
51
+ * module and went stale the moment the length changed (FMN-0068 ended up with
52
+ * endplate B at x=48 on a 47.9″ board). A pose is only an override when the
53
+ * owner meant it.
54
+ *
55
+ * Absent on A/B = derived residue, ignored. Absent on a placed branch
56
+ * endplate (one with `at`) = still authored — placing it IS the gesture, and
57
+ * docs predate this flag. */
58
+ poseAuthored?: boolean;
46
59
  /** Free-moN endplate FACE width across the track, inches — the physical size
47
60
  * of the standard interface at this end. Free-moN spec: 12″ minimum, 24″
48
61
  * recommended. Absent = the recommended default (modules may differ end to
package/dist/index.js CHANGED
@@ -667,7 +667,7 @@ function buildTransition(state) {
667
667
  }
668
668
  function withPoses(endplates, overrides) {
669
669
  return endplates.map(
670
- (e) => overrides[e.id] ? { ...e, pose: overrides[e.id] } : e
670
+ (e) => overrides[e.id] ? { ...e, pose: overrides[e.id], poseAuthored: true } : e
671
671
  );
672
672
  }
673
673
  function withWidths(endplates, widths, offsets = {}) {
@@ -2031,10 +2031,26 @@ function trackMeetsEndplateIssues(path, pose, opts) {
2031
2031
  function poseNeedsManual(geometryType) {
2032
2032
  return geometryType === "wye" || geometryType === "other";
2033
2033
  }
2034
+ function isAxialPose(p) {
2035
+ const h = norm360(p.heading);
2036
+ return Math.abs(p.y) < 1e-6 && (Math.abs(h) < 1e-6 || Math.abs(h - 180) < 1e-6);
2037
+ }
2034
2038
  function poseOverridesFromDoc(doc) {
2035
2039
  const out = {};
2036
2040
  for (const e of doc.endplates ?? []) {
2037
- if (e.id && e.pose && typeof e.pose.x === "number" && typeof e.pose.y === "number" && typeof e.pose.heading === "number") {
2041
+ if (e.id && e.pose && typeof e.pose.x === "number" && typeof e.pose.y === "number" && typeof e.pose.heading === "number" && // Only an AUTHORED pose overrides derivation (#182) — but docs written
2042
+ // before the flag existed have to keep working, so authorship is inferred
2043
+ // for the two cases that can only BE authored:
2044
+ // · a placed branch endplate (`at`) — dropping it on the board is the
2045
+ // gesture, and it has no derivable position at all;
2046
+ // · an OFF-AXIS pose on A/B — a hand-placed plate is off-axis by
2047
+ // definition (that's why it needed hand placing, e.g. a wye's B).
2048
+ // What's left is an axial A/B pose, which is exactly the shape plain
2049
+ // derivation produces — residue. Honouring it silently pins the plate so
2050
+ // it stops following the module and goes stale (FMN-0068's B sat at 48 on
2051
+ // a 47.9″ board). Anything saved from now on carries the flag, so this
2052
+ // guesswork only ever applies to old docs.
2053
+ (e.poseAuthored === true || !!e.at || !isAxialPose(e.pose))) {
2038
2054
  out[e.id] = { x: e.pose.x, y: e.pose.y, heading: e.pose.heading };
2039
2055
  }
2040
2056
  }