Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
541da80
feat(serenity): dynamic AI resource allocation — allocator core + tra…
byteclimber Jul 3, 2026
7522589
test(serenity): close patch-coverage gaps (bodyText guard, realSleep …
byteclimber Jul 3, 2026
721508c
fix(serenity): tighten metered-405 classifier + distinct transient er…
byteclimber Jul 3, 2026
0eafe0d
refactor(serenity): narrow releaseAiSurplus catch + freeze DIMS (LLMO…
byteclimber Jul 3, 2026
a10f788
feat(serenity): flag-gated carve — skip flat re-grant under dynamic a…
byteclimber Jul 3, 2026
6d0aef1
test(serenity): assert pre-poll runs under dynamic allocation + clari…
byteclimber Jul 3, 2026
ee6077f
feat(serenity): dynamic AI allocation — global kill-switch + fail-fas…
byteclimber Jul 6, 2026
89f7a0d
fix(serenity): address MysticatBot review — redact error messages, de…
byteclimber Jul 6, 2026
a718ad6
test(serenity): cover release-path pool-exhausted branch — 100% patch…
byteclimber Jul 7, 2026
31a5a85
Merge remote-tracking branch 'origin/main' into feat/dynamic-alloc-co…
byteclimber Jul 8, 2026
05bbc72
docs(serenity): document deliberate scope decisions — release infra, …
byteclimber Jul 9, 2026
23f0d32
fix(serenity): size model-set changes on signed net delta + wire rele…
byteclimber Jul 9, 2026
710315a
fix(serenity): releaseAiSurplus must never emit an all-zero transfer …
byteclimber Jul 13, 2026
bb307b4
refactor(serenity): rename allocator ids to parent/sub-workspace, fai…
byteclimber Jul 13, 2026
7a068a4
test(serenity): flag-ON metered integration test for dynamic allocati…
byteclimber Jul 13, 2026
e299803
fix(serenity): close Rainer's 2026-07-13 review — fail-loud guard, lo…
byteclimber Jul 13, 2026
e6d83ff
Merge remote-tracking branch 'origin/main' into feat/dynamic-alloc-co…
byteclimber Jul 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 13 additions & 32 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"@adobe/spacecat-shared-ticket-client": "^1.0.4",
"@adobe/spacecat-shared-tier-client": "1.5.1",
"@adobe/spacecat-shared-tokowaka-client": "1.20.0",
"@adobe/spacecat-shared-user-manager-client": "1.3.1",
"@adobe/spacecat-shared-user-manager-client": "1.5.0",
"@adobe/spacecat-shared-utils": "1.124.1",
"@adobe/spacecat-shared-vault-secrets": "1.3.5",
"@aws-sdk/client-cloudfront": "3.1045.0",
Expand Down
28 changes: 27 additions & 1 deletion src/controllers/serenity.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import {
} from '../support/serenity/handlers/tags.js';
import { ensureSubworkspace, decommissionBrandWorkspace } from '../support/serenity/workspace-lifecycle.js';
import { isSerenityActiveForOrg } from '../support/serenity/serenity-active.js';
import { isDynamicAllocationEnabled } from '../support/serenity/dynamic-allocation-active.js';
import { MAX_TOPICS_ON_CREATE } from '../support/serenity/brand-provisioning.js';
import { marketForGeoTargetId } from '../support/serenity/locations.js';
import { brandNeedles, classifyBrandedTag } from '../support/serenity/branded-classifier.js';
Expand Down Expand Up @@ -420,6 +421,11 @@ function SerenityController(context, log, env) {
return createSerenityTransport({ env: ctx.env || env, imsToken });
}

// Global dynamic-allocation kill-switch for this request (env/Vault boolean, default OFF). Read
// per request off ctx.env, mirroring buildTransport's env resolution. When OFF the metered
// handlers front through a no-op guard (byte-for-byte pre-PR behavior).
const dynamicAllocationEnabled = (ctx) => isDynamicAllocationEnabled(ctx?.env || env);

/** Loads the Brand model instance (for subworkspace-mode write/lifecycle flows). */
async function loadBrand(ctx, brandUuid) {
const Brand = ctx?.dataAccess?.Brand;
Expand Down Expand Up @@ -501,6 +507,10 @@ function SerenityController(context, log, env) {
ctx.data || {},
log,
classifyPromptType,
{
dynamicAllocation: dynamicAllocationEnabled(ctx),
parentWorkspaceId: auth.parentWorkspaceId ?? '',
},
)
: await handleCreatePrompts(
transport,
Expand Down Expand Up @@ -689,6 +699,9 @@ function SerenityController(context, log, env) {
// in depth: this options bag flows into markets-subworkspace.js and
// shouldn't carry access to unrelated tables).
dataAccess: { BrandSemrushProject: ctx.dataAccess.BrandSemrushProject },
// Dynamic-allocation kill-switch. The JIT top-up units pool is the org parent passed
// positionally above (auth.parentWorkspaceId) — not duplicated in this options bag.
dynamicAllocation: dynamicAllocationEnabled(ctx),
},
);
// Mirror this market as a SpaceCat Site (+ brand_sites link) keyed on the
Expand Down Expand Up @@ -982,7 +995,16 @@ function SerenityController(context, log, env) {
}
const transport = buildTransport(ctx, imsToken);
const result = auth.mode === 'subworkspace'
? await handleUpdateModelsSubworkspace(transport, auth.workspaceId, ctx.data || {}, log)
? await handleUpdateModelsSubworkspace(
transport,
/** @type {string} */ (auth.workspaceId),
ctx.data || {},
log,
{
dynamicAllocation: dynamicAllocationEnabled(ctx),
parentWorkspaceId: auth.parentWorkspaceId ?? '',
},
)
: await handleUpdateModels(
transport,
ctx.dataAccess,
Expand Down Expand Up @@ -1072,6 +1094,7 @@ function SerenityController(context, log, env) {
log,
{},
brandPointerReloader(ctx, auth.brandUuid),
{ dynamicAllocation: dynamicAllocationEnabled(ctx) },
);
let bareSucceeded = true;
if (typeof brand.setStatus === 'function') {
Expand Down Expand Up @@ -1166,6 +1189,7 @@ function SerenityController(context, log, env) {
log,
{},
brandPointerReloader(ctx, auth.brandUuid),
{ dynamicAllocation: dynamicAllocationEnabled(ctx) },
);
const results = [];
for (const m of markets) {
Expand Down Expand Up @@ -1214,6 +1238,8 @@ function SerenityController(context, log, env) {
// Narrowed to the one model the mapping-row helpers touch — see
// the single-market create call site for the same rationale.
dataAccess: { BrandSemrushProject: ctx.dataAccess.BrandSemrushProject },
// JIT units pool = the org parent passed positionally above; not duplicated here.
dynamicAllocation: dynamicAllocationEnabled(ctx),
},
);
} catch (e) {
Expand Down
Loading
Loading