axstack 0.52.0 → 0.52.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axstack",
3
- "version": "0.52.0",
3
+ "version": "0.52.1",
4
4
  "description": "Axstack installer and setup CLI: installs owned chat skills and role data, configures supported harness settings, and checks T3 Code capabilities.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -51,7 +51,7 @@ remaining quota in every applicable window. Null or absent reset timing is valid
51
51
  Claude session/weekly/scoped Opus and Codex windows. The adapter omits the missing
52
52
  reset; it never invents a timestamp. Unknown reset timing alone does **not** mean
53
53
  unused or not started: the reported used percentage still governs remaining quota,
54
- same-account eligibility and Astra's reserve, including exhaustion at 100% used.
54
+ same-account eligibility and the primary-pool reserve, including exhaustion at 100% used.
55
55
  For pressure, an untimed window earns zero elapsed-window credit, a conservative
56
56
  lower bound, while its full reported usage is subtracted. `untimedWindows` reports
57
57
  these windows (including relevant Opus scope); n/a session windows are separate.
@@ -65,11 +65,18 @@ A weekly-exhausted account contributes 100% session usage. Different resets stay
65
65
  per account; T3 lists refill events scaled by member count, rather than inventing
66
66
  one pool reset. An n/a session contributes neither a zero nor 100% observation;
67
67
  only accounts with an applicable session enter its mean, and an all-n/a session
68
- is reported as null with status n/a. This script uses that unrounded mean for the reserve check:
69
- Astra is excluded if either applicable Codex window has less than 25% remaining; exactly
70
- 25% is eligible. Opus has no Codex reserve exclusion. Percentages do not establish
71
- absolute tokens or relative subscription sizes. Duplicate identities hold
72
- instead of silently adding capacity from overlapping sources.
68
+ is reported as null with status n/a. For each primary pool, remaining capacity is
69
+ its minimum applicable session/weekly unrounded pooled percentage; n/a is omitted.
70
+ Sol xhigh is eligible **only when both Opus and Astra pools have <30% remaining**.
71
+ Exactly 30% on either pool excludes Sol, even if it is the current default.
72
+ When both are low, choose Sol if its Codex accounts and catalog are eligible.
73
+ Otherwise choose eligible Opus medium/Astra medium, preferring a non-low primary
74
+ over a low primary before pacing or fairness. If only low primaries remain
75
+ available, use those; exhausted accounts never gain capacity. Scoped Opus limits
76
+ still constrain eligibility; an unavailable primary is not evidence of <30%.
77
+ Unknown telemetry or catalogs hold. There is no separate Astra reserve cutoff.
78
+ Percentages do not establish absolute tokens or relative subscription sizes.
79
+ Duplicate identities hold instead of adding capacity from overlapping sources.
73
80
 
74
81
  Pressure is the worse session/weekly mean of elapsed-window percentage minus
75
82
  used percentage, higher meaning more underused capacity. As in T3's pace display,
@@ -105,11 +112,11 @@ that period, not an immutable record of its original model; hard-deleted/pruned
105
112
  records and manual model changes limit fidelity. The source/coverage is reported.
106
113
  A supplied project-only list remains caller-scoped, not global history.
107
114
 
108
- When history is unavailable, similarly pressured eligible models receive fixed
109
- six-hour UTC slots in Opus/Astra/Sol order. The target is stable within a slot;
115
+ When history is unavailable, similarly pressured eligible primaries receive fixed
116
+ six-hour UTC slots in Opus/Astra order. Sol is selected only in the both-low case. The target is stable within a slot;
110
117
  pressure hysteresis still protects a current default outside a fair tie. This
111
118
  prevents indefinite starvation without timer state, a new database, per-tick
112
- rotation, or any claim of equal chat counts. Quota eligibility/reserves always win.
119
+ rotation, or any claim of equal chat counts. Reserve eligibility always wins over fairness and hysteresis.
113
120
 
114
121
  ## Run or enable
115
122
 
@@ -97,9 +97,15 @@ export function decide(settings, snapshots, catalogs, now, history = null) {
97
97
  }
98
98
  const choices = candidates(settings, catalogs, now);
99
99
  result.pools = Object.fromEntries(['claudeAgent', 'codex'].map((d) => [d, pool(all, d, now)]));
100
- const eligible = choices.filter((c) => result.pools[c.driver].eligibleAccounts > 0
101
- && (c.selection.model !== 'gpt-6-astra'
102
- || Math.min(...[result.pools.codex.sessionRemaining, result.pools.codex.weeklyRemaining].filter((v) => v !== null)) >= 25));
100
+ const low = (driver) => Math.min(...[result.pools[driver].sessionRemaining,
101
+ result.pools[driver].weeklyRemaining].filter((v) => v !== null)) < 30;
102
+ const available = choices.filter((c) => result.pools[c.driver].eligibleAccounts > 0);
103
+ const sol = available.filter((c) => c.selection.model === 'gpt-6.1-sol');
104
+ const primaries = available.filter((c) => c.selection.model !== 'gpt-6.1-sol');
105
+ const nonLow = primaries.filter((c) => !low(c.driver));
106
+ // Apply the reserve before pacing, fairness and hysteresis can retain a forbidden default.
107
+ const eligible = low('claudeAgent') && low('codex') && sol.length ? sol
108
+ : nonLow.length ? nonLow : primaries;
103
109
  if (!eligible.length) throw Error('both pools exhausted; no account has both windows available');
104
110
  const best = Math.max(...eligible.map((c) => result.pools[c.driver].score));
105
111
  const tied = eligible.filter((c) => best - result.pools[c.driver].score <= 5);
@@ -118,8 +124,8 @@ export function decide(settings, snapshots, catalogs, now, history = null) {
118
124
  }
119
125
  if (!chosen && current && best - result.pools[current.driver].score < 10) {
120
126
  // Fixed UTC slots prevent starvation without persistent timer state or per-tick rotation.
121
- const rotation = Math.floor(now / (6 * 3600000)) % choices.length;
122
- const target = [...choices.slice(rotation), ...choices.slice(0, rotation)].find((c) => tied.includes(c));
127
+ const rotation = Math.floor(now / (6 * 3600000)) % eligible.length;
128
+ const target = [...eligible.slice(rotation), ...eligible.slice(0, rotation)].find((c) => tied.includes(c));
123
129
  chosen = !counts && tied.includes(current) ? target : current;
124
130
  }
125
131
  if (!chosen) {