Skip to content

chore: merge main into main-convert - #423

Merged
JosephSamirL merged 48 commits into
main-convertfrom
sync/merge-main-into-main-convert
Jul 27, 2026
Merged

chore: merge main into main-convert#423
JosephSamirL merged 48 commits into
main-convertfrom
sync/merge-main-into-main-convert

Conversation

@abbaseya

Copy link
Copy Markdown
Collaborator

Summary

Merges the latest main into main-convert to bring the branch up to date.

main-convert is a protected branch (direct pushes are rejected), so this merge is delivered via this PR.

Conflict resolution

All 26 conflicts were release-please–managed files and were resolved in favor of main (theirs), which carries the authoritative published versions:

  • .release-please-manifest.json
  • packages/*/package.json (version bumps, e.g. 3.13.14.0.0)
  • packages/*/CHANGELOG.md

Non-conflicting source/demo/test changes were auto-merged. Verified: no leftover conflict markers, 0 unmerged paths.

🤖 Generated with Claude Code

abbaseya and others added 30 commits June 5, 2026 20:36
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Releases created by release-please use the default GITHUB_TOKEN, and
GitHub does not fire `on: release` workflows for events created with
that token — so publish-package.yml never auto-ran and every npm
publish had to be dispatched manually.

workflow_dispatch is an explicit exception to that rule, so the
release job now dispatches the existing publish-package.yml (the
single publishing path) once per released tag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(ci): auto-dispatch npm publish when release-please creates releases
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Releases created by release-please use the default GITHUB_TOKEN, and
GitHub does not fire `on: release` workflows for events created with
that token — so publish-package.yml never auto-ran and every npm
publish had to be dispatched manually.

workflow_dispatch is an explicit exception to that rule, so the
release job now dispatches the existing publish-package.yml (the
single publishing path) once per released tag.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…face signatures

Beads: ai-driven-product-dev-p5at
Agent: sdk-js
Foundation only — no algorithm/behavior change. Build+lint green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beads: ai-driven-product-dev-n7x9
18 Mocha/Chai tests, spec-derived expected numbers as independent oracle.
AC2/AC4/AC5 coverage. Fail cleanly (methods not implemented yet).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beads: ai-driven-product-dev-n7x9
getBucketRanges/selectBucketAnchored/getBucketForVisitorAnchored per normative
spec. Packed path frozen. 28/28 bucketing tests pass (18 anchored + 10 packed),
TS2420 self-resolved on default yarn test:mocha.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beads: ai-driven-product-dev-pm33
9 Mocha/Chai tests: AC1 gate branching, AC4 stops/ta:0, AC8 guard precedence,
AC9 no schema drift. 4 fail (gate not implemented), 5 pass (packed-path + invariant locks).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beads: ai-driven-product-dev-pm33
Number(experience.version) > 8 -> anchored (via _buildVariationAllocations +
getBucketForVisitorAnchored); else packed unchanged (_buildPackedBuckets extracted
verbatim). Guard/hash/seed/event payloads untouched. 37/37 data suite pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… + runner

Beads: ai-driven-product-dev-jnz9
59 vectors (all spec categories: incident-flip, raise-superset, per-sliver,
lower-eject, stopped-arm, ta:0, NaN, boundary, v8===v9 coincidence). Expected
values computed then frozen; every spec-given band matched. Runner 60 passing.
Full monorepo suite green (480 Mocha + 36 Playwright). Cross-SDK contract for the
5 sibling SDKs; fixture at packages/bucketing/tests/cross-sdk-bucketing-vectors.json.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d test files

Beads: ai-driven-product-dev-kz6x
Review R1 (conf 95): header comments claimed methods/gate not-yet-implemented (RED);
now shipped + passing. Rewrote to describe shipped behavior for sibling-SDK porters;
fixed stale data-manager.ts:620-637 -> :685 gate ref. Comment-only. Suites unchanged
(bucketing 28, data 97).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…SonarCloud S2871

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ent stamp is 11) + browser golden-vector test

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erience version

Introduces an anchored bucketing layout chosen per experience by experience.version: experiences at version > 11 bucket via the anchored layout, while version <= 11, missing, or non-numeric keep the existing packed walk unchanged. Anchored ranges stay fixed to each variation's position, so raising traffic allocation grows every arm in place instead of relocating ranges and re-bucketing already-assigned visitors. Adds public API to @convertcom/js-sdk-bucketing (getBucketRanges, selectBucketAnchored, getBucketForVisitorAnchored) and a VariationAllocation type in @convertcom/js-sdk-types. Hash, seed, stored-decision guard, forced-variation path, and event payloads are unchanged.

BREAKING CHANGE: bucketing layout is now selected by experience.version; experiences at version > 11 use the new anchored layout instead of the packed cumulative walk.
Pure exported helper parsePreviewParam(value) -> {experienceId,variationId}|null,
dot-separated numeric ids, exported from js-sdk public entry. 12-row case-table test.

Beads: ai-driven-product-dev-hooy

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ygiene (AC1,AC2)

Add debugToken?:string to ConfigBase; ApiManager appends debug_token=<value> and forces
_conv_low_cache=1 to the config-fetch URL when set (proper &-joined query). Token never
sent to track endpoint nor logged. Config-matrix + hygiene tests (6) + api suite (16) green.

Beads: ai-driven-product-dev-m568

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…emo (AC3-fetch,AC8)

ApiManager.getConfigByExperience(id) fetches /config/<sdkKey>?exp=<id>&_conv_low_cache=1
(+debug_token when configured), memoized process-wide in a module-level Map keyed
sdkKey:experienceId, 60s TTL (live Date.now), in-flight promise cached to collapse
concurrent calls to one fetch. 7 tests + 23 api suite green.

Beads: ai-driven-product-dev-e0aw

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ger (AC4,AC7)

Pure DataManager.getPreviewDecision(experience, variationId) resolves the variation
directly from the passed experience.variations (not shared config), returns a
BucketedVariation-shaped decision bypassing rules/env/status/traffic/stored/hash, with
no putData and no enqueue. Unknown variation -> null. 7 tests + 104 data suite green.

Beads: ai-driven-product-dev-rr3l

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…isolation (AC3,AC5,AC6,AC7)

Add enableStorage flag (gates putData in DataManager fresh-bucketing branch). Context.setPreview
resolves via shared config or getConfigByExperience, validates variation, stores per-context
_preview. Preview context: runExperience forces getPreviewDecision for the target key, all run*
run with enableTracking/enableStorage false + BUCKETING fires suppressed, trackConversion
short-circuits. Zero /track (fetch+beacon) and zero store writes; concurrent non-preview context
unaffected. Fixed latent getData() {}-vs-null bug. Node 4 preview tests + 159 js-sdk suite +
Playwright browser gate (zero-trace on real transport) all green.

Beads: ai-driven-product-dev-t5ir

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dit R1 fix)

Thread enableStorage through matchRulesByField -> selectLocations and gate its putData
(data-manager.ts) so a preview context running a location-targeted non-target experience
writes nothing. Guard Context runCustomSegments/setDefaultSegments/updateVisitorProperties
on _preview (no visitor-state persistence on a preview context). Fix JSDoc @returns parse
error in parse-preview-param.ts. 4 new storage tests + browser store-write spy green; js-sdk
163 + data 104 + segments 7 + experience 12 suites green.

Beads: ai-driven-product-dev-y5gj

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…review (decision-audit R2)

selectLocations obtained the visitor's stored locations array by reference from getData
(live _bucketedVisitors on the memory path) and push/spliced it in place BEFORE the
enableStorage-gated putData -- mutating shared visitor state on a preview context. Now
operates on a copy when enableStorage is false (zero change to the normal persist path).
Regression test (seed locations, run under preview, assert array unchanged) + 9 preview
tests + 164 js-sdk + 104 data (incl golden-vector) + browser gate all green.

Beads: ai-driven-product-dev-ehrh

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…stale RED comments

getConfigByExperience now evicts its cache entry on fetch rejection (guarded against
clobbering a newer entry) so a transient failure no longer blocks preview retry for 60s;
regression test added. Removed stale RED-phase comments + now-false 'as any' casts from
committed preview tests (methods exist on impl+interface). 8 config + 24 api + 104 data +
9 context-preview + 164 js-sdk + browser gate 39 all green.

Beads: ai-driven-product-dev-4qqt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pired preview-config cache entries

Adds localeCompare comparators to the two bare string .sort() calls flagged
by SonarCloud rule S2871 in api-manager-config-by-experience.tests.ts, and
sweeps expired entries from the process-wide configByExperienceCache map on
every getConfigByExperience() call so resolved-but-expired entries for
distinct experienceIds don't accumulate unbounded in long-running servers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(bucketing): anchored layout (contract v12) — JS SDK reference impl
abbaseya and others added 18 commits July 8, 2026 13:46
Beads: ai-driven-product-dev-xypk
Agent: sdk-js
Files: 1 changed

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nRuleType literal

Beads: ai-driven-product-dev-rv02
Agent: sdk-js
Files: 3 changed

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…owser gate

Beads: ai-driven-product-dev-hpul
Agent: sdk-js
RED: data-unit 4 pass / 5 fail (seam missing); integration 2 pass / 4 fail
Files: 3 test files

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ted_into_experience_key seam

Beads: ai-driven-product-dev-hpul
Agent: sdk-js
GREEN: data-unit 9/9, full data pkg 90/90, integration 5/6 (AC3 = test-timing bug, fix next)
RuleManager untouched (AC7). package.json build-churn deliberately excluded.
Files: packages/data/src/data-manager.ts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cross-instance read

Beads: ai-driven-product-dev-hpul
Agent: sdk-js
Integration now 6/6. Test-timing bug (async DataStore flush), seam unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bit-identical

Beads: ai-driven-product-dev-uosk
Agent: sdk-js
Rules suite 47/47 (38 existing + 9 new). All 8 rows assert RuleManager.isRuleMatched({})=false (Compatibility contract). RuleManager src untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
qs-02: Experiment preview (debug token + preview links)
feat(rules): mutual-exclusion audience rule (bucketed_into_experience_key) — qs-03
…ument how to test

Reads the ?convert_preview={experienceId}.{variationId} param at each demo's
context-creation seam via the already-public parsePreviewParam helper, and
awaits context.setPreview() before the experience renders. Adds a "Testing
preview links" section to each demo README with a concrete example URL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…arity)

runExperiences() now returns the forced preview decision for the previewed experience (replace-in-place, else append), matching runExperience() and the PHP/Android/Python/iOS SDKs; other experiences still decide normally and zero-trace holds. Extends the debug-token AC2 hygiene test to the preview ?exp= fetch seam, and corrects a stale test comment that claimed the (now passing) zero-trace storage regression locks must fail.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L42GvyvKc4t8AXG7nnhq3f
…rams

Cross-SDK release-review parity fixes (JS oracle): URL-encode environment/exp/debug_token in both config-fetch builders; suppress LOCATION_ACTIVATED/DEACTIVATED events while a preview is active via a preview-scoped suppressEvents flag (location matching still runs; normal enableTracking:false runs still fire events).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat: Full Stack v12 — safe traffic ramp-up, variation preview & experiment exclusion
…efresh lockfile so release QA passes on the major bump
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	.release-please-manifest.json
#	packages/api/CHANGELOG.md
#	packages/api/package.json
#	packages/bucketing/CHANGELOG.md
#	packages/bucketing/package.json
#	packages/cloudflare/CHANGELOG.md
#	packages/cloudflare/package.json
#	packages/data/CHANGELOG.md
#	packages/data/package.json
#	packages/enums/CHANGELOG.md
#	packages/enums/package.json
#	packages/event/CHANGELOG.md
#	packages/event/package.json
#	packages/experience/CHANGELOG.md
#	packages/experience/package.json
#	packages/js-sdk/CHANGELOG.md
#	packages/js-sdk/package.json
#	packages/logger/CHANGELOG.md
#	packages/logger/package.json
#	packages/rules/CHANGELOG.md
#	packages/rules/package.json
#	packages/segments/CHANGELOG.md
#	packages/segments/package.json
#	packages/types/CHANGELOG.md
#	packages/types/package.json
#	packages/utils/CHANGELOG.md
#	packages/utils/package.json
@abbaseya
abbaseya requested a review from JosephSamirL July 24, 2026 17:29
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@sonarqubecloud

Copy link
Copy Markdown

@abbaseya abbaseya self-assigned this Jul 24, 2026
@abbaseya
abbaseya requested review from a team and removed request for JosephSamirL July 24, 2026 17:42
@JosephSamirL
JosephSamirL merged commit 97bb34a into main-convert Jul 27, 2026
6 checks passed
@JosephSamirL
JosephSamirL deleted the sync/merge-main-into-main-convert branch July 27, 2026 07:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants