synabun 2026.4.26-beta.13 → 2026.4.26-beta.14

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.
@@ -10604,7 +10604,10 @@ async function checkSynabunUpdate() {
10604
10604
  } catch { /* keep prior current if package.json read fails */ }
10605
10605
 
10606
10606
  const curParsed = parseSemver(current);
10607
- const installedChannel = curParsed?.pre ? 'prerelease' : 'stable';
10607
+ // Numeric-only suffix (`2026.4.26-1`) is a post-release iteration, not a
10608
+ // prerelease — keep those on the stable channel. Only true alpha/beta/rc
10609
+ // suffixes flip the channel.
10610
+ const installedChannel = (curParsed?.pre && curParsed.iter == null) ? 'prerelease' : 'stable';
10608
10611
 
10609
10612
  const fetchJsonWithTimeout = async (url, ms = 5000) => {
10610
10613
  const controller = new AbortController();
@@ -10799,25 +10802,36 @@ function parseVersion(raw) {
10799
10802
  }
10800
10803
 
10801
10804
  // Structured semver parse — handles calver bumps and prerelease tags:
10802
- // "2026.4.26" -> { major:2026, minor:4, patch:26, pre:null }
10803
- // "2026.4.20-2" -> { major:2026, minor:4, patch:20, pre:"2" }
10804
- // "2026.4.26-beta.3" -> { major:2026, minor:4, patch:26, pre:"beta.3" }
10805
- // "v1.2.3-rc.1" -> { major:1, minor:2, patch:3, pre:"rc.1" }
10805
+ // "2026.4.26" -> { major:2026, minor:4, patch:26, pre:null, iter:null }
10806
+ // "2026.4.20-2" -> { major:2026, minor:4, patch:20, pre:"2", iter:2 }
10807
+ // "2026.4.26-beta.3" -> { major:2026, minor:4, patch:26, pre:"beta.3", iter:null }
10808
+ // "v1.2.3-rc.1" -> { major:1, minor:2, patch:3, pre:"rc.1", iter:null }
10809
+ //
10810
+ // `iter` is set when the suffix is purely numeric (SynaBun's calver iteration
10811
+ // scheme: `2026.4.26-1` is the FIRST patch published after `2026.4.26`).
10812
+ // Strict semver §9 treats any prerelease suffix as PRE-release (lower than no
10813
+ // suffix). SynaBun publishes calver iterations as `latest` on npm, so we need
10814
+ // to treat numeric-only suffixes as POST-release iterations instead.
10806
10815
  function parseSemver(raw) {
10807
10816
  if (raw == null) return null;
10808
10817
  const s = String(raw).trim().replace(/^v\.?/, '');
10809
10818
  const m = s.match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/);
10810
10819
  if (!m) return null;
10820
+ const pre = m[4] || null;
10821
+ const iter = pre && /^\d+$/.test(pre) ? Number(pre) : null;
10811
10822
  return {
10812
10823
  major: +m[1],
10813
10824
  minor: +m[2],
10814
10825
  patch: +m[3],
10815
- pre: m[4] || null,
10826
+ pre,
10827
+ iter,
10816
10828
  };
10817
10829
  }
10818
10830
 
10819
- // Semver-spec precedence including prerelease handling:
10820
- // 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0
10831
+ // Precedence (mix of semver §11 + SynaBun calver-iteration convention):
10832
+ // 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0 < 1.0.0-1 < 1.0.0-2
10833
+ // Numeric-only suffix = post-release iteration (NEWER than no-suffix release).
10834
+ // Mixed/alpha suffix = prerelease (OLDER than no-suffix release, per semver).
10821
10835
  // Returns negative if a<b, positive if a>b, 0 if equal. Accepts strings or
10822
10836
  // parsed objects.
10823
10837
  function compareSemver(a, b) {
@@ -10829,11 +10843,19 @@ function compareSemver(a, b) {
10829
10843
  if (pa.major !== pb.major) return pa.major - pb.major;
10830
10844
  if (pa.minor !== pb.minor) return pa.minor - pb.minor;
10831
10845
  if (pa.patch !== pb.patch) return pa.patch - pb.patch;
10832
- // Equal x.y.z. Prerelease vs none: a release without prerelease is GREATER.
10846
+ // Equal x.y.z. Order from oldest → newest:
10847
+ // alpha-prerelease < no-suffix release < numeric iteration
10833
10848
  if (!pa.pre && !pb.pre) return 0;
10849
+ // Numeric iterations are POST-release: always newer than no-suffix and
10850
+ // newer than alpha prereleases.
10851
+ if (pa.iter != null && pb.iter == null) return 1;
10852
+ if (pa.iter == null && pb.iter != null) return -1;
10853
+ if (pa.iter != null && pb.iter != null) return pa.iter - pb.iter;
10854
+ // Neither side is a numeric iteration. Standard semver §11: no-suffix is
10855
+ // greater than alpha prerelease.
10834
10856
  if (!pa.pre && pb.pre) return 1;
10835
10857
  if ( pa.pre && !pb.pre) return -1;
10836
- // Both have prerelease — compare identifiers per semver §11.4.
10858
+ // Both have alpha-flavoured prerelease — compare identifiers per semver §11.4.
10837
10859
  const ia = pa.pre.split('.');
10838
10860
  const ib = pb.pre.split('.');
10839
10861
  const len = Math.max(ia.length, ib.length);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synabun",
3
- "version": "2026.4.26-beta.13",
3
+ "version": "2026.4.26-beta.14",
4
4
  "description": "Persistent vector memory for AI assistants",
5
5
  "license": "Apache-2.0",
6
6
  "author": "The SynaBun Authors",