Skip to content

Release/v2.2.2#14

Merged
magmacomputing merged 5 commits intomainfrom
release/v2.2.2
Apr 18, 2026
Merged

Release/v2.2.2#14
magmacomputing merged 5 commits intomainfrom
release/v2.2.2

Conversation

@magmacomputing
Copy link
Copy Markdown
Owner

@magmacomputing magmacomputing commented Apr 18, 2026

Emergency Patch to correct some missed library functionality

Summary by CodeRabbit

  • Bug Fixes

    • Fixed build configuration to prevent unintended code elimination and ensure critical utilities are accessible
    • Fixed documentation build to resolve browser compatibility issues
    • Improved utility function transpilation reliability
  • Documentation

    • Redesigned landing page with enhanced hero section and feature showcase
    • Added dedicated Documentation section with quick links
    • Updated ticker plugin guidance and examples
  • Tests

    • Added distribution testing capability for built artifacts

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 18, 2026

Warning

Rate limit exceeded

@magmacomputing has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 11 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 5 minutes and 11 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 180b2ef6-94fd-4e00-84f7-11c89523652c

📥 Commits

Reviewing files that changed from the base of the PR and between c9eb673 and 6fc111a.

📒 Files selected for processing (11)
  • packages/library/src/common/reflection.library.ts
  • packages/library/src/common/serialize.library.ts
  • packages/library/src/common/symbol.library.ts
  • packages/library/vitest.config.ts
  • packages/tempo/README.md
  • packages/tempo/index.md
  • packages/tempo/package.json
  • packages/tempo/rollup.config.js
  • packages/tempo/src/tempo.register.ts
  • packages/tempo/vitest.config.ts
  • packages/tempo/vitest.workspace.ts
📝 Walkthrough

Walkthrough

Release v2.2.2 introducing dist-based testing infrastructure, refactoring term registries to persist globally across module reloads, enhancing prototype chain traversal in reflection utilities, and redesigning documentation with updated Vue markup and hero sections.

Changes

Cohort / File(s) Summary
Version Bump
package.json, packages/library/package.json, packages/tempo/package.json
Updated package versions from 2.2.1 to 2.2.2; tempo package updated library dependency to 2.2.2.
Build & Test Infrastructure
package.json, packages/tempo/rollup.config.js, packages/library/vitest.config.ts, packages/tempo/vitest.config.ts, vitest.workspace.ts
Added test:dist script with cross-env for environment-gated testing; refactored Rollup to dynamically discover dist/ entries; updated Vitest configs to conditionally resolve aliases to dist/ when TEST_DIST=true; expanded workspace test globs and added polyfill setup files.
Global Registry Persistence
packages/tempo/src/tempo.symbol.ts, packages/tempo/src/tempo.register.ts, packages/tempo/src/tempo.class.ts, packages/tempo/src/plugin/term/standard.index.ts
Added four new global symbols ($installed, $terms, $extends, $modules) to enable registries to persist on globalThis across module reloads; removed Tempo.#terms clearing in init(); registered term-extension callback on registry reset.
Reflection & Plugin Utilities
packages/library/src/common/reflection.library.ts, packages/tempo/src/plugin/plugin.util.ts
Enhanced ownAccessors to traverse prototype and constructor chains up to 50 levels; tightened type annotations in findTermPlugin and registerTerm callbacks.
Documentation & Metadata
packages/tempo/README.md, packages/tempo/index.md, packages/tempo/doc/tempo.ticker.md, packages/tempo/CHANGELOG.md, packages/tempo/.npmignore, packages/tempo/.vitepress/config.ts, packages/library/src/common/pledge.class.ts
Redesigned README header with logo/typography table layout and new Documentation section; refactored index.md hero section and ticker demo to use new Tempo() with fmt.weekTime and timezone tracking; updated VitePress build target and module aliases; added npmignore for tempo package; updated JSDoc example in pledge.ts; added v2.2.2 CHANGELOG entry.
Package Configuration
packages/tempo/package.json
Updated files list to publish only dist/, removing doc/ and .vitepress/dist/; changed test script to plain vitest run; added test:dist script.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Feature/monorepo transition #6: Both PRs modify Tempo's module/registry and term/plugin initialization code (symbols, global-backed registries, and term handling across reloads).
  • Optimize/granular bundling #8: Both PRs modify build/test plumbing (packages/tempo/rollup.config.js and Vitest alias/config) to change how entry points and module aliases are resolved for distribution builds.
  • Feat/modular features #11: Both PRs make overlapping changes to packages/library/src/common/reflection.library.ts accessor logic and related tempo registration/config files.

Poem

🐰 A rabbit hops through registry halls,
Where terms persist through globalThis walls,
Prototypes traced through fifty deep chains,
Dist builds tested, no loose threads remain,
hop

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Release/v2.2.2' is generic and does not clearly convey what was actually changed in the pull request. While it indicates a version bump, it does not summarize the substantive changes such as library functionality corrections, build configuration updates, or test infrastructure improvements. Consider using a more descriptive title like 'Release v2.2.2: Fix library reflection utilities and build configuration' to better communicate the main changes to reviewers scanning the history.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch release/v2.2.2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (3)
packages/tempo/.npmignore (1)

1-11: Redundant with files whitelist in package.json.

packages/tempo/package.json already sets "files": ["dist/"], which is a whitelist and takes precedence — npm will only publish dist/ (plus always-included files like package.json, README.md, LICENSE) regardless of .npmignore. The .npmignore here is effectively dead configuration. Consider removing it to avoid drift (e.g., someone later adds an entry to files and forgets to update .npmignore, or vice versa).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/tempo/.npmignore` around lines 1 - 11, The .npmignore file is
redundant because package.json already uses the "files": ["dist/"] whitelist
which controls published contents; remove packages/tempo/.npmignore to avoid
configuration drift and rely on the "files" field in package.json (keep
README.md, LICENSE, package.json as they are always included).
packages/tempo/src/tempo.register.ts (1)

15-23: Minor inconsistency in how registry slots are shared across reloads.

  • _terms / _extends (Lines 15-16): store the raw array on globalThis; each module load wraps it in a fresh secureRef. ✅ Shared data, local proxy.
  • modules (Line 21): stores the secureRef proxy itself on globalThis. On a subsequent module load, the first load's proxy (with its captured closures) is reused, not a fresh wrapper.
  • installed (Line 22): stores the raw Set. ✅ Shared data.

The modules slot is the odd one out — it retains the first-ever module's proxy state across reloads, which can keep the first module alive via closure references and diverges from the pattern used by terms/extends. Consider storing the raw record on globalThis and wrapping locally, consistent with _terms/_extends:

♻️ Suggested alignment
-const _terms = (globalThis as any)[sym.$terms] ??= [] as TermPlugin[];
-const _extends = (globalThis as any)[sym.$extends] ??= [] as Extension[];
+const _terms    = ((globalThis as any)[sym.$terms]    ??= [] as TermPlugin[]);
+const _extends  = ((globalThis as any)[sym.$extends]  ??= [] as Extension[]);
+const _modules  = ((globalThis as any)[sym.$modules]  ??= {} as Record<string, any>);
 
 const _REGISTRY = {
 	terms: secureRef(_terms),
 	extends: secureRef(_extends),
-	modules: (globalThis as any)[sym.$modules] ??= secureRef({} as Record<string, any>),
+	modules: secureRef(_modules),
 	installed: (globalThis as any)[sym.$installed] ??= new Set()
 }

Side benefit: registryReset can drop the internal.modules[lib.$Target] ?? internal.modules fallback on Line 76 since the unwrap becomes uniform.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/tempo/src/tempo.register.ts` around lines 15 - 23, The registry
stores a secureRef for modules on globalThis while storing raw arrays for _terms
and _extends, causing the first module load's proxy closures to persist; change
the modules slot to store the raw record on globalThis (like _terms/_extends)
and then wrap it locally with secureRef when building _REGISTRY so that
secureRef({}) is not reused across reloads; update references to symbols _terms,
_extends, modules, secureRef and _REGISTRY and adjust registryReset (and the
internal.modules lookup / fallback such as the lib.$Target usage) to assume the
unwrap is uniform after this change.
packages/tempo/rollup.config.js (1)

13-36: Robustness of dynamic entry discovery.

Two minor concerns with the new dist-driven input generation:

  1. Hard failure when dist/ is absent. fs.readdirSync('dist', ...) throws synchronously at config load time. The build script runs tsc -b first so this is fine in the happy path, but rollup -c in isolation (e.g. debugging build:bundle after clean) now produces an opaque ENOENT. A guarded early return with a clear message would help:

    💡 Guard example
    -// Generate a map of entry points from all files in dist (after tsc has run)
    -const entryPoints = Object.fromEntries(
    -	getFiles('dist').map(file => [
    -		path.relative('dist', file).replace(/\.js$/, ''),
    -		file
    -	])
    -);
    +// Generate a map of entry points from all files in dist (after tsc has run)
    +if (!fs.existsSync('dist')) {
    +	throw new Error('rollup: dist/ not found — run `tsc -b` (or `npm run build`) first.');
    +}
    +const entryPoints = Object.fromEntries(
    +	getFiles('dist').map(file => [
    +		path.relative('dist', file).replace(/\.js$/, ''),
    +		file
    +	])
    +);
  2. CWD-relative paths. Both getFiles('dist') and path.resolve('../library/dist/common.index.js') depend on process.cwd() being packages/tempo. That holds when invoked through workspace scripts but silently breaks when invoked from the monorepo root directly. Anchoring against import.meta.url (this is an ESM config — import path from 'node:path') would make it cwd-independent:

    import { fileURLToPath } from 'node:url';
    const here = path.dirname(fileURLToPath(import.meta.url));
    // ...getFiles(path.join(here, 'dist')) and path.resolve(here, '../library/dist/common.index.js')

Neither blocks the release; both reduce future friction.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/tempo/rollup.config.js` around lines 13 - 36, The dynamic entry
discovery in getFiles and entryPoints can fail when the dist directory is
missing and is cwd-dependent; update getFiles (and its call site that builds
entryPoints) to first compute a repo-local base directory using import.meta.url
(via fileURLToPath and path.dirname) and use path.join(here, 'dist') instead of
a raw 'dist', and add a guarded check that the dist directory exists
(fs.existsSync or try/catch around fs.readdirSync) that returns an empty map or
throws a clear, descriptive error instead of letting ENOENT bubble; also resolve
the forced inclusion path (entryPoints['lib/common.index']) against the same
here (e.g., path.resolve(here, '../library/dist/common.index.js')) so all paths
are independent of process.cwd().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/library/src/common/reflection.library.ts`:
- Around line 102-112: The constructor-chain loop in reflection.library.ts is
terminating against Function and Object constructors, which lets
Function.prototype and Object.prototype be iterated and leak keys like
'__proto__' and 'arguments'; update the loop termination in the code that walks
the constructor chain (the variable named "constructor" and the while condition
that currently checks "constructor !== Object && constructor !== Function &&
++depth < limit") to mirror the instance-chain logic by stopping at the
prototype objects themselves (e.g., check "constructor !== Function.prototype &&
constructor !== Object.prototype") and ensure the loop also respects null, so
that Object.getPrototypeOf(constructor) will terminate without collecting
descriptors from Function.prototype/Object.prototype. This change prevents
collection of prototype-only accessors such as '__proto__' and 'arguments'.

In `@packages/tempo/.vitepress/config.ts`:
- Around line 77-91: The VitePress alias configuration (the alias entries
referencing ../dist/... and the `@magmacomputing/tempo` replacements) creates an
implicit dependency on compiled artifacts, so update the package scripts that
run VitePress (the docs:dev and docs:build scripts in packages/tempo
package.json) to run build:library and build:tempo (or a new predocs script)
before docs:api and the VitePress step, or alternatively add clear instructions
to CONTRIBUTING/README about requiring build:library and build:tempo prior to
running docs:dev/docs:build; adjust the scripts so the dist artifacts exist
before vitepress starts to avoid unresolved import errors.

In `@packages/tempo/index.md`:
- Around line 23-49: The onMounted handler awaits dynamic imports then creates a
recurring Tempo.ticker but onUnmounted may have already fired, causing a leaked
timer; fix by adding a local cancellation flag (e.g., let cancelled = false) or
an isMounted boolean: set it true at the start of onMounted and false in
onUnmounted, then after the Promise.all and before calling Tempo.ticker(...)
check the flag and skip creating the ticker if cancelled; additionally, if a
ticker is created ensure onUnmounted always stops it (ticker?.stop()) and nulled
to avoid any dangling references.

In `@packages/tempo/package.json`:
- Around line 150-151: The change removed the workspace-based Vitest invocation
(vitest.workspace.ts) and consolidated tests into the local vitest.config.ts,
altering test suites from two isolated runs ("Tempo: Full" vs "Tempo: Core") to
a single pooled run; confirm this behavioral change is intentional and, if you
want to preserve previous suite separation, revert to invoking the workspace
config or recreate equivalent exclusion/inclusion patterns in vitest.config.ts
(look for the "test" script and vitest.workspace.ts / vitest.config.ts
references), and also add cross-env to this package's devDependencies so the
"test:dist" script (which uses cross-env) works when the package is installed
standalone (update package.json devDependencies to include "cross-env").

In `@packages/tempo/README.md`:
- Around line 4-10: Inline style attributes on the HTML table/header (elements:
<td>, <img src="./img/logo.svg">, <h1>, <p>) will be stripped by GitHub/npm
renderers; remove reliance on inline styles in the README and instead use
GitHub-supported markup or assets: replace the styled <h1 style=...> with a
plain Markdown heading (e.g. "# Tempo") or use <h1 align="left">, convert the
styled <p> to a normal paragraph without inline CSS, keep the image but if you
need the exact visual banner create a pre-rendered banner image and reference it
via the existing <img src="./img/logo.svg">, or move style rules into the
VitePress site stylesheet for docs-only styling.

In `@packages/tempo/src/plugin/term/standard.index.ts`:
- Around line 7-11: The resetHooks Set accumulates callbacks because each import
registers a new function reference; modify the registry reset handling so after
invoking each hook from resetHooks() you clear the Set to prevent accumulation —
i.e., in the reset routine that currently calls resetHooks().forEach(hook =>
hook()), add a call to resetHooks().clear() immediately after; this touches the
reset logic that invokes resetHooks and ensures repeated imports/HMR do not grow
the hook Set while preserving existing behavior of onRegistryReset and
Tempo.extend re-extension.

---

Nitpick comments:
In `@packages/tempo/.npmignore`:
- Around line 1-11: The .npmignore file is redundant because package.json
already uses the "files": ["dist/"] whitelist which controls published contents;
remove packages/tempo/.npmignore to avoid configuration drift and rely on the
"files" field in package.json (keep README.md, LICENSE, package.json as they are
always included).

In `@packages/tempo/rollup.config.js`:
- Around line 13-36: The dynamic entry discovery in getFiles and entryPoints can
fail when the dist directory is missing and is cwd-dependent; update getFiles
(and its call site that builds entryPoints) to first compute a repo-local base
directory using import.meta.url (via fileURLToPath and path.dirname) and use
path.join(here, 'dist') instead of a raw 'dist', and add a guarded check that
the dist directory exists (fs.existsSync or try/catch around fs.readdirSync)
that returns an empty map or throws a clear, descriptive error instead of
letting ENOENT bubble; also resolve the forced inclusion path
(entryPoints['lib/common.index']) against the same here (e.g.,
path.resolve(here, '../library/dist/common.index.js')) so all paths are
independent of process.cwd().

In `@packages/tempo/src/tempo.register.ts`:
- Around line 15-23: The registry stores a secureRef for modules on globalThis
while storing raw arrays for _terms and _extends, causing the first module
load's proxy closures to persist; change the modules slot to store the raw
record on globalThis (like _terms/_extends) and then wrap it locally with
secureRef when building _REGISTRY so that secureRef({}) is not reused across
reloads; update references to symbols _terms, _extends, modules, secureRef and
_REGISTRY and adjust registryReset (and the internal.modules lookup / fallback
such as the lib.$Target usage) to assume the unwrap is uniform after this
change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0f014d5e-5020-42b0-8d84-556d2ffec95a

📥 Commits

Reviewing files that changed from the base of the PR and between c46e90e and c9eb673.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (20)
  • package.json
  • packages/library/package.json
  • packages/library/src/common/pledge.class.ts
  • packages/library/src/common/reflection.library.ts
  • packages/library/vitest.config.ts
  • packages/tempo/.npmignore
  • packages/tempo/.vitepress/config.ts
  • packages/tempo/CHANGELOG.md
  • packages/tempo/README.md
  • packages/tempo/doc/tempo.ticker.md
  • packages/tempo/index.md
  • packages/tempo/package.json
  • packages/tempo/rollup.config.js
  • packages/tempo/src/plugin/plugin.util.ts
  • packages/tempo/src/plugin/term/standard.index.ts
  • packages/tempo/src/tempo.class.ts
  • packages/tempo/src/tempo.register.ts
  • packages/tempo/src/tempo.symbol.ts
  • packages/tempo/vitest.config.ts
  • vitest.workspace.ts
💤 Files with no reviewable changes (1)
  • packages/tempo/src/tempo.class.ts

Comment thread packages/library/src/common/reflection.library.ts
Comment thread packages/tempo/.vitepress/config.ts
Comment thread packages/tempo/index.md
Comment on lines +150 to +151
"test": "vitest run",
"test:dist": "cross-env TEST_DIST=true vitest run",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the split config previously excluded these tests and find any that rely on isolation
rg -nP --type=ts -C2 "core\.test|lazy\.test" packages/tempo/test 2>/dev/null | head -60
# Check whether cross-env is declared in tempo package devDependencies
cat packages/tempo/package.json | jq '.devDependencies."cross-env" // "NOT DECLARED"'

Repository: magmacomputing/magma

Length of output: 78


🏁 Script executed:

#!/bin/bash
# Check if vitest.workspace.ts exists
find . -name "vitest.workspace.ts" -type f

# Look for any test files with .core.test or .lazy.test patterns anywhere in repo
find . -name "*.core.test.ts" -o -name "*.lazy.test.ts" 2>/dev/null

# Check the current vitest.config.ts in packages/tempo
cat packages/tempo/vitest.config.ts

Repository: magmacomputing/magma

Length of output: 4682


🏁 Script executed:

#!/bin/bash
# Read the workspace config to see what it was doing
cat vitest.workspace.ts

Repository: magmacomputing/magma

Length of output: 1198


Confirm intentional test execution changes and add missing dependency.

The removal of --workspace ../../vitest.workspace.ts changes test execution behavior significantly. Previously, the workspace config ran tests in two separate suites: "Tempo: Full" (excluding *.core.test.ts and *.lazy.test.ts) and "Tempo: Core" (including only those). The new local vitest.config.ts runs all tests together via a single pool with pool: 'forks' for process isolation. While fork isolation mitigates shared-state risks, this differs from the intentional suite separation. Confirm this behavioral change is intentional and that no unexpected test interactions occur.

Additionally, test:dist uses cross-env but it is not declared in packages/tempo/devDependencies. This dependency exists only at the root, so the script will fail if the package is installed or tested standalone. Add cross-env to this package's devDependencies.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/tempo/package.json` around lines 150 - 151, The change removed the
workspace-based Vitest invocation (vitest.workspace.ts) and consolidated tests
into the local vitest.config.ts, altering test suites from two isolated runs
("Tempo: Full" vs "Tempo: Core") to a single pooled run; confirm this behavioral
change is intentional and, if you want to preserve previous suite separation,
revert to invoking the workspace config or recreate equivalent
exclusion/inclusion patterns in vitest.config.ts (look for the "test" script and
vitest.workspace.ts / vitest.config.ts references), and also add cross-env to
this package's devDependencies so the "test:dist" script (which uses cross-env)
works when the package is installed standalone (update package.json
devDependencies to include "cross-env").

Comment thread packages/tempo/README.md Outdated
Comment thread packages/tempo/src/plugin/term/standard.index.ts
@magmacomputing magmacomputing merged commit ce81a2c into main Apr 18, 2026
1 check passed
@magmacomputing magmacomputing deleted the release/v2.2.2 branch April 18, 2026 08:19
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.

1 participant