mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-19 09:45:07 +00:00
Post-Phase-3 cleanup batch #1. Bundles two small v1.x-roadmap deferrals (#4 and #7 in docs/v1x-roadmap.md) into one D-day. No new user-facing feature; pins existing behaviour into tests + finally wires the ADR-documented activeSpawns field on /health. (1) AUTH_MISSING tuple test (v1.x #7, D45 P3 deferral) New engine-level test in Suite D40 asserts that an AUTH_MISSING hop produces a fallbackDetail tuple with trigger_type: 'auth_missing' AND that the engine does NOT advance past it (HARD_TRIGGER_CODES[AUTH_MISSING]=false). Pre-D56 the behaviour was implicit through neighbouring tests; D56 makes it explicit so a future refactor that moves the tuple-push past the auth_missing branch fails this test directly. Authority: ADR 0004 § Decision (hard-trigger table) + Amendment 5 (tuple shape). (2) /health activeSpawns integration (v1.x #4, ADR 0002 Amendment 6 forward note) handleHealth now surfaces providers.status.<name>.activeSpawns (sourced from D38 getActiveSpawnCount(name) — already imported at server.mjs:39). The field is computed BEFORE healthCheck() is awaited so it remains present even when healthCheck() throws — getActiveSpawnCount is a cheap in-memory counter read. New Suite 21c-extra test pins the field presence + numeric + non-negative for every enabled provider in the fixture. Authority: ADR 0002 Amendment 6 § "Forward note — exposing the counter via HTTP" — names the path providers.status.<name>.activeSpawns and pins it as the Phase 1 deferral that becomes due once management endpoints exist (which they now do, post-Phase-3). Test count: 601 → 603 (+2 D56 tests; 603/603 pass locally). Release-kit: under Unreleased per phase_rolling_mode (Phase 3 closed at v0.3.0; Phase 4 entries also land here once Phase 4 opens — D56 is a cleanup-D-day that ships under v0.3.x, not a Phase 4 deliverable). Co-authored-by: dtzp555 <dtzp555@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+10
-1
@@ -4,7 +4,16 @@ All notable changes to OLP land here. Per `CLAUDE.md` release_kit overlay, this
|
||||
|
||||
## Unreleased
|
||||
|
||||
(empty — Phase 4 entries land here once Phase 4 opens)
|
||||
### D56 — v1.x cleanup batch #1: AUTH_MISSING tuple test + `/health` activeSpawns (post-Phase-3)
|
||||
|
||||
Post-Phase-3 cleanup batch. Resolves two small v1.x-roadmap deferrals into one D-day. No new user-facing feature; pins existing behaviour into tests + finally wires the ADR-documented `activeSpawns` field on `/health`.
|
||||
|
||||
- **AUTH_MISSING tuple test** (v1.x roadmap #7 / D45 reviewer P3 deferral). New engine-level test in Suite D40 asserts that an `AUTH_MISSING` hop produces a `fallbackDetail` tuple with `trigger_type: 'auth_missing'` AND that the engine does NOT advance past the AUTH_MISSING hop (per ADR 0004 § Decision — `HARD_TRIGGER_CODES[AUTH_MISSING]=false`). Pre-D56 the behaviour was implicit through other engine-path tests; this commit makes it explicit so a future refactor that moves the tuple-push past the auth_missing branch fails this test directly.
|
||||
- **`/health` activeSpawns integration** (v1.x roadmap #4 / ADR 0002 Amendment 6 forward note). `handleHealth` now surfaces `providers.status.<name>.activeSpawns` (sourced from D38 `getActiveSpawnCount(name)`). The field is set BEFORE `healthCheck()` is awaited so it remains accessible even when `healthCheck()` throws (cheap in-memory counter read). New Suite 21c-extra test pins the field presence + non-negative value for every enabled provider. With no requests in flight: 0; under saturation: equals `hints.maxConcurrent`.
|
||||
- **Test count:** 601 → 603 (+2 D56 tests).
|
||||
- **Authority:** `docs/v1x-roadmap.md` #4 + #7; ADR 0002 Amendment 6 (concurrency observability forward note); ADR 0004 Amendment 5 (X-OLP-Fallback-Detail tuple shape the new test asserts).
|
||||
|
||||
|
||||
|
||||
## v0.3.0 — 2026-05-25
|
||||
|
||||
|
||||
+9
-2
@@ -577,10 +577,17 @@ async function handleHealth(req, res) {
|
||||
const available = listAllProviderNames().length;
|
||||
const providerStatuses = {};
|
||||
for (const [name, provider] of loadedProviders) {
|
||||
// D56 / v1.x roadmap #4 (ADR 0002 Amendment 6 forward note): surface
|
||||
// per-provider active spawn count for capacity-planning observability.
|
||||
// D38 shipped getActiveSpawnCount; this is the /health integration.
|
||||
// The field is set BEFORE healthCheck() in case healthCheck throws —
|
||||
// activeSpawns is cheap (in-memory counter read) and useful even
|
||||
// when healthCheck fails.
|
||||
const activeSpawns = getActiveSpawnCount(name);
|
||||
try {
|
||||
providerStatuses[name] = await provider.healthCheck();
|
||||
providerStatuses[name] = { ...(await provider.healthCheck()), activeSpawns };
|
||||
} catch (e) {
|
||||
providerStatuses[name] = { ok: false, error: e.message };
|
||||
providerStatuses[name] = { ok: false, error: e.message, activeSpawns };
|
||||
}
|
||||
}
|
||||
sendJSON(res, 200, {
|
||||
|
||||
@@ -6247,6 +6247,30 @@ describe('D40 — X-OLP-Fallback-Detail header (issue #7)', () => {
|
||||
assert.equal(result.fallbackDetail[0].code, 'SPAWN_FAILED');
|
||||
});
|
||||
|
||||
it('engine: AUTH_MISSING terminates chain, fallbackDetail tuple records trigger_type:"auth_missing" (D56, v1.x roadmap #7)', async () => {
|
||||
// v1.x roadmap #7 (D40 follow-up): explicit pin that the AUTH_MISSING
|
||||
// path produces a fallbackDetail tuple with trigger_type:"auth_missing"
|
||||
// BEFORE the engine's early-return at engine.mjs:486. Was implicit via
|
||||
// other engine-path tests; D56 makes it explicit so any future refactor
|
||||
// that moves the tuple-push past the auth_missing branch fails this.
|
||||
const err = new ProviderError('No OAuth token found', 'AUTH_MISSING');
|
||||
const chain = [
|
||||
{ provider: 'anthropic', model: 'claude-sonnet-4-6' },
|
||||
{ provider: 'openai', model: 'gpt-5.5' }, // present to verify AUTH_MISSING does NOT advance
|
||||
];
|
||||
const hopFn = async () => { throw err; };
|
||||
const result = await executeWithFallback(chain, makeIR({ model: 'claude-sonnet-4-6' }), hopFn);
|
||||
// AUTH_MISSING is HARD_TRIGGER_CODES[AUTH_MISSING]=false (engine.mjs L52);
|
||||
// chain stops at hop 0 instead of advancing to openai.
|
||||
assert.equal(result.chunks, null, 'AUTH_MISSING terminates chain');
|
||||
assert.equal(result.fallbackHops, 0, 'AUTH_MISSING does NOT advance — stays at hop 0');
|
||||
assert.equal(result.fallbackDetail.length, 1, 'fallbackDetail has exactly 1 tuple (the AUTH_MISSING hop)');
|
||||
assert.equal(result.fallbackDetail[0].code, 'AUTH_MISSING');
|
||||
assert.equal(result.fallbackDetail[0].trigger_type, 'auth_missing');
|
||||
assert.equal(result.fallbackDetail[0].provider, 'anthropic');
|
||||
assert.equal(result.fallbackDetail[0].hop, 0);
|
||||
});
|
||||
|
||||
it('engine: non-ProviderError exception → tuple code is "UNKNOWN"', async () => {
|
||||
const err = new Error('Something unexpected'); // no .code field
|
||||
const chain = [{ provider: 'anthropic', model: 'claude-sonnet-4-6' }];
|
||||
@@ -10522,6 +10546,29 @@ describe('Suite 21 — D46 owner-vs-guest gating (ADR 0007 §§ 7.1, 7.2)', () =
|
||||
assert.ok('status' in body.providers, 'owner /health providers.status must be present');
|
||||
});
|
||||
|
||||
it('21c-extra: owner /health each provider status carries activeSpawns field (D56, v1.x #4 / ADR 0002 Amendment 6)', async () => {
|
||||
// ADR 0002 Amendment 6 forward note: when surfaced on /health, the
|
||||
// per-provider concurrency counter lives at providers.status.<name>.
|
||||
// activeSpawns. D56 wires it. With no requests in flight, the value
|
||||
// is 0; under saturation it equals hints.maxConcurrent.
|
||||
const { plaintext_token } = createKey({ name: '21c-extra', owner_tier: 'owner', providers_enabled: '*', olpHome: TMP });
|
||||
const r = await fetch({
|
||||
port, method: 'GET', path: '/health',
|
||||
headers: { Authorization: `Bearer ${plaintext_token}` },
|
||||
});
|
||||
assert.equal(r.status, 200);
|
||||
const body = JSON.parse(r.body);
|
||||
// At least one provider must be enabled in the fixture
|
||||
const statusEntries = Object.entries(body.providers.status);
|
||||
assert.ok(statusEntries.length >= 1, 'fixture has at least one enabled provider');
|
||||
for (const [name, status] of statusEntries) {
|
||||
assert.ok('activeSpawns' in status,
|
||||
`providers.status.${name}.activeSpawns MUST be present (ADR 0002 Amendment 6)`);
|
||||
assert.equal(typeof status.activeSpawns, 'number');
|
||||
assert.ok(status.activeSpawns >= 0, 'activeSpawns >= 0');
|
||||
}
|
||||
});
|
||||
|
||||
it('21d: owner_only_endpoints config opt-out — empty list → guest gets full payload', async () => {
|
||||
__setAuthConfig({
|
||||
allow_anonymous: true,
|
||||
|
||||
Reference in New Issue
Block a user