diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..2b604fa --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,3 @@ +# Copilot Instructions + +Read and follow the repository guidance in [../AGENTS.md](../AGENTS.md). diff --git a/.github/instructions/ci-cd.instructions.md b/.github/instructions/ci-cd.instructions.md new file mode 100644 index 0000000..27dfffb --- /dev/null +++ b/.github/instructions/ci-cd.instructions.md @@ -0,0 +1,40 @@ +--- +applyTo: '.github/workflows/**,release.config.js,package.json,rollup.config.js,typedoc.json' +name: web-capabilities CI/CD +description: Use when reviewing checks, builds, bundled worker source, documentation generation, package entry points, or semantic-release behavior. +--- + +# CI/CD Instructions + +## Pull-request checks + +- Read `.github/workflows/pull-request-checks.yml` before changing or describing CI. +- Pull requests install with Yarn, then run `yarn test:lint`, `yarn test:prettier`, `yarn test:spelling`, `yarn transpile:validate`, `yarn build`, and `yarn test:coverage`. +- Docs generation and the aggregate `yarn test` command are not current pull-request gates. +- Do not claim a check is CI-enforced unless the workflow invokes it. + +## Build and package outputs + +- Rollup builds ESM and CommonJS JavaScript plus bundled TypeScript declarations from `src/index.ts`. +- At build time, Rollup embeds `*.worker.js` into the bundle as a string (`rollup-plugin-string`). At runtime, the WASM probe creates a `Worker` from a Blob URL. The npm package does not ship a separate worker file on disk. +- Keep `package.json` `main`, `module`, `types`, and `exports` aligned with Rollup outputs. +- The npm package includes only `dist/**/*`. +- The runtime dependency is `bowser`. Review any proposed runtime package as a compatibility and supply-chain change. +- Generated API files belong under `docs/api/`. That directory is gitignored locally; semantic-release can still commit generated docs on release. +- Cleanup must not delete maintained files under `docs/contributing/` or `docs/knowledge-base/`. + +## Release + +- Pushes to `main` install with Yarn, run `yarn build`, and invoke semantic-release. +- Conventional Commits on `main` determine whether semantic-release publishes and which version increment applies. +- The release configuration publishes to the public npm registry and commits configured release assets, including the `docs` directory. +- The current release workflow builds but does not run tests or generate TypeDoc output. Document that gap accurately. +- Treat changes to capability outcomes, probe classification, `src/index.ts`, exported signatures, entry points, declarations, or runtime dependencies as compatibility-sensitive. + +## Failure triage and safety + +- Fix deterministic lint, test, type, documentation, or build failures. Do not rerun them hoping for a different result. +- Retry only failures supported by evidence of transient runner, registry, or network problems. +- Treat a release failure on `main` as a coordinated delivery issue. +- Never expose workflow tokens, npm credentials, or secret values. +- Do not run semantic-release or npm publishing locally unless the user explicitly requests a coordinated release. diff --git a/.github/instructions/code-review.instructions.md b/.github/instructions/code-review.instructions.md new file mode 100644 index 0000000..e118322 --- /dev/null +++ b/.github/instructions/code-review.instructions.md @@ -0,0 +1,29 @@ +--- +applyTo: 'src/**/*.ts,README.md,AGENTS.md,docs/knowledge-base/**/*.md' +name: web-capabilities Code Review +description: Use when reviewing capability checks, browser detection, system info, WASM runtime probing, worker lifecycle, public exports, tests, or architecture guidance. +--- + +# Code Review Instructions + +## Priorities + +1. `CapabilityState` stays correct. Return `UNKNOWN` when signals are missing instead of guessing. +2. Keep `WebCapabilities.supportsWasm()` separate from `WasmRuntimeProbe.check()`. They answer different questions. +3. Preserve probe cleanup: terminate the worker and revoke the Blob URL. +4. Treat probe thresholds, check order, visibility handling, and reason codes as correctness-sensitive. +5. Treat public exports and capability outcomes as compatibility-sensitive. +6. Require tests when behavior changes at browser boundaries or in the WASM probe. + +## Checks + +- Prefer browser APIs and feature detection. Use `BrowserInfo` for version checks instead of new user-agent parsing. +- Do not use the WASM availability helper as a stand-in for the async speed probe, or the other way around. +- Keep the probe's one-result-per-page cache unless a test intentionally resets it. +- Reject invalid worker measurements before classification. +- Return `UNKNOWN` for background-tab and too-short timing cases instead of a false slow or fast result. +- Keep `CpuInfo` deprecated behavior stable for existing callers. +- Register and unregister `SystemInfo` pressure callbacks safely when the API is missing. +- Keep JSDoc complete where ESLint requires it. +- Verify documentation claims against source, tests, and configuration. +- Do not add secrets, private URLs, real user-agent captures, or local absolute paths. diff --git a/.github/instructions/testing.instructions.md b/.github/instructions/testing.instructions.md new file mode 100644 index 0000000..9bd95f5 --- /dev/null +++ b/.github/instructions/testing.instructions.md @@ -0,0 +1,35 @@ +--- +applyTo: 'src/**/*.spec.ts,src/**/*.worker.js' +name: web-capabilities Tests +description: Use when writing or reviewing co-located Jest tests and WASM worker benchmark behavior. +--- + +# Testing Instructions + +## Framework and location + +- Jest runs through `ts-jest` in the environment configured by `jest.config.js`. Check `package.json` and `jest.config.js` instead of pinning tool versions in guidance. +- Keep tests next to source as `src/**/*.spec.ts`. +- Import worker source through the same path the production code uses. `jest.config.js` applies a raw transform to `*.worker.js`. +- Use `yarn test:unit` for focused runtime feedback and `yarn test:coverage` for the pull-request test command. +- Run `yarn transpile:validate` when changing exports, public types, probe result shapes, or worker message contracts. + +## Test patterns + +- Name the top-level `describe` after the class or capability under test. +- Use behavior-focused `it('should ...')` descriptions. +- Reset `WasmRuntimeProbe` cached state in `beforeEach` when testing probe behavior. +- Mock `Worker`, `URL.createObjectURL`, and `URL.revokeObjectURL` when exercising probe orchestration without running the real benchmark. +- Stub browser globals such as `WebAssembly`, `RTCPeerConnection`, codec capabilities, and `document.visibilityState` explicitly for capability tests. +- Assert full result objects or focused fields for `status`, `capability`, `reason`, and `measurements` where classification matters. +- Keep tests independent. Avoid relying on execution order across spec files. + +## Required coverage by change type + +- Capability method changes: `CAPABLE`, `NOT_CAPABLE`, and `UNKNOWN` paths, including missing hardware or API signals. +- Browser helper changes: version comparison helpers and browser or OS identification against controlled parser inputs. +- System info changes: pressure observer support, callback registration, immediate callback when state already exists, and logical core count behavior. +- WASM support changes: disabled runtime, missing worker support, worker start failure, timeout, runtime error, invalid measurements, and cleanup. +- Probe classification changes: fast ratios, slow ratios, uncertain combinations, background tab, divide timing too short, and measurement rounding. +- Public type changes: TypeScript validation plus runtime tests where behavior also changes. +- Regression fixes: the smallest mock or stub setup that fails before the fix and passes after it. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index cb90cc9..5482172 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,28 +1,35 @@ ## Description + ## This change implements... + - [ ] A new feature - [ ] A bug fix - [ ] Other (please specify): ## Is this a breaking change? + - [ ] Yes - [ ] No ## I certify that... + - [ ] All relevant unit and integration tests have passed and/or have been updated according to this change. ## Generative AI (GAI) Usage Disclosure + [Reference: Cisco GAI Coding Guidelines](https://cisco.sharepoint.com/sites/AIML/SitePages/Practice-Guide---GAI-Coding.aspx) - [ ] **Cisco approved GAI tool/IDE was used for coding** - eg: VSCode, Cursor, Windsurf, Codex, Claude code - [ ] **No GAI** - Code was written entirely manually without GAI assistance **If a GAI tool/IDE was used then select the category that best describes GAI usage in this PR:** -- [ ] **Manual Draft with GAI Refinement** - I/we created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code) *(Default)* + +- [ ] **Manual Draft with GAI Refinement** - I/we created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code) _(Default)_ - [ ] **GAI Draft with Manual Customization** - GAI tool was used to create a draft that I/we subsequently customized or modified. - [ ] **GAI Generated Code** - Code was generated entirely by GAI **Additional GAI Usage Details (Optional):** + diff --git a/.github/skills/pr-description/SKILL.md b/.github/skills/pr-description/SKILL.md new file mode 100644 index 0000000..f4a799e --- /dev/null +++ b/.github/skills/pr-description/SKILL.md @@ -0,0 +1,74 @@ +--- +name: pr-description +description: Draft accurate web-capabilities pull-request descriptions from the repository template, committed changes, and observed test evidence. +--- + +# PR Description + +Create a concise, reader-friendly pull-request description that helps reviewers understand why the change matters, what behavior changes, and how it was verified. + +## Sources + +Read these before drafting: + +1. `.github/pull_request_template.md` +2. The complete committed diff against the pull-request base branch +3. All branch commits +4. Test output supplied by the author or produced in the current session +5. Public issues or documentation linked by the author + +Repository files and observed results are authoritative. Do not invent motivation, test evidence, issue links, screenshots, browser compatibility, or release claims. + +## Workflow + +1. Confirm the base branch. Use `main` when no other base is specified. +2. Review the complete branch diff, not only the latest commit. +3. Check `git status`. If uncommitted changes exist, warn the author and exclude them from the pull-request description until committed. +4. Identify effects on capability outcomes, browser detection, system info, WASM checks, runtime probe behavior, public exports, declarations, package formats, runtime dependencies, and release behavior. +5. Ask what manual testing was performed. Request the browser scenario and result when relevant. If no manual testing was needed, ask the author to confirm why. +6. Ask only for facts that cannot be derived, such as a public issue link, screenshots, or the Generative AI disclosure category. +7. Produce the completed repository template without removing headings or policy checkboxes. Do not reproduce private-only links in newly drafted text. + +## Description rules + +- Under `Description`, start with two to four short bullets that explain the developer or user outcome. +- Lead with why the change is useful, then explain what changed to achieve it. +- Use plain language, active voice, and short sentences. Explain an unavoidable technical term the first time it appears. +- Prefer outcomes such as “documentation commands cannot remove contributor guides” over implementation phrases such as “isolate generated output.” +- Describe behavior and developer outcomes instead of listing changed files or repeating the diff. +- Include implementation details only when they help a reviewer evaluate correctness or compatibility. +- State important non-effects directly, such as “This does not change runtime behavior or the public API.” +- Add a short `Testing` subsection under `Description` with only commands and manual checks that actually ran. +- Summarize warnings or partial results in plain language and identify whether they existed before the change. +- When manual testing was not needed, explain why in one sentence. +- Call out capability outcome changes, browser detection changes, probe classification changes, public API impact, declaration changes, package compatibility, dependency changes, migration steps, or semantic-version impact only when supported by the diff. +- Preserve the `This change implements...`, breaking-change, certification, and Generative AI sections. +- Keep checkboxes unchecked when evidence or author input is missing. +- Never mark the test certification checkbox without evidence. +- Never select a Generative AI disclosure category for the author. +- Do not add a dedicated risk section. Fold important compatibility or rollout notes into the description bullets when the diff requires them. +- Use only public links in this public repository. + +## Wording example + +Avoid: + +> Preserve maintained documentation by isolating generated TypeDoc output and extend validation coverage. + +Prefer: + +> Keep generated API documentation separate from contributor guides so documentation commands cannot remove maintained content. Include the new guides in formatting and spell checks. + +For capability or probe changes, prefer: + +> Treat background-tab probe runs as inconclusive (`UNKNOWN`) instead of slow WASM. + +over: + +> Add `BACKGROUND_TAB` handling in `WasmRuntimeProbe.classify()`. + +## Output + +Return one Markdown block that can be pasted into GitHub. + +After the block, list unresolved author questions separately. Do not put `TBD` placeholders in an otherwise final description. diff --git a/.github/workflows/pull-request-checks.yml b/.github/workflows/pull-request-checks.yml index 6373a22..5e66526 100644 --- a/.github/workflows/pull-request-checks.yml +++ b/.github/workflows/pull-request-checks.yml @@ -10,4 +10,8 @@ jobs: node-version: 22 - run: yarn install - run: yarn test:lint + - run: yarn test:prettier + - run: yarn test:spelling + - run: yarn transpile:validate + - run: yarn build - run: yarn test:coverage diff --git a/.gitignore b/.gitignore index dc375bb..a993d3e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules dist .idea/ coverage/ +docs/api/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e854681 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,175 @@ +# AGENTS.md + +## Project Overview + +`@webex/web-capabilities` provides helper functions for browser and system information and for checking whether a browser is likely to support certain features. + +Most checks run synchronously from browser APIs and hardware signals. `WasmRuntimeProbe` adds an optional async check when callers need to know whether WebAssembly runs fast enough, not just whether it is present. + +Start with [README.md](README.md) for usage and [docs/knowledge-base/README.md](docs/knowledge-base/README.md) for a short architecture summary, build outputs, testing, and release behavior. + +## General Guidelines + +- Be direct, analytical, and evidence-based. +- Derive behavior from `src/`, co-located tests, and checked-in configuration. +- Treat `src/index.ts` as the public source export boundary and `package.json` as the authority for package entry points and runtime dependencies. +- Read the knowledge base before broad architecture searches. +- When guidance conflicts, current source and repository configuration win. + +## Agent Rules + +1. Cite repository paths, config keys, tests, or stable public links for factual claims. +2. Use public sources only. Do not add private issue links, documentation hosts, consumer chains, or enterprise-only skills. +3. Never commit secrets, credentials, private keys, certificate material, or decrypted `.env` content. +4. Do not add absolute local paths to committed files. +5. Create commits or push changes only when the user explicitly asks. + +### Committing files + +- Stage explicit paths only. Do not use `git add .` or `git add -A`. +- Stage only files changed for the current task. +- Before committing, inspect `git status` and the staged diff for secrets, keys, certificates, local paths, generated output, or unrelated changes. + +### Knowledge base + +The curated knowledge base under `docs/knowledge-base/` is maintained separately from generated API documentation under `docs/api/`. + +- Read it for capability aggregation, browser and system inputs, WASM probing, worker lifecycle, public exports, and delivery behavior. +- Verify implementation details against source, tests, package metadata, and configuration. +- Ask before adding articles beyond the maintained index and architecture overview. +- Keep public repository content limited to publicly verifiable facts and links. + +## Repository Layout + +| Path | Purpose | +| ---------------------------------- | ------------------------------------------------------------------------- | +| `src/index.ts` | Public source export barrel | +| `src/web-capabilities.ts` | Feature capability checks and primitive browser support helpers | +| `src/browser-info.ts` | Browser, OS, engine, and version helpers via `bowser` | +| `src/cpu-info.ts` | Deprecated CPU helper retained for compatibility | +| `src/system-info.ts` | CPU core count and Compute Pressure API helpers | +| `src/wasm-runtime-probe.ts` | Async WASM runtime benchmark orchestration | +| `src/wasm-runtime-probe.worker.js` | Inlined worker benchmark source embedded by Rollup | +| `src/**/*.spec.ts` | Co-located Jest unit tests | +| `rollup.config.js` | ESM, CommonJS, and declaration builds; embeds worker source at build time | +| `.github/workflows/` | Pull-request checks and main-branch publishing | +| `docs/knowledge-base/` | Maintained architecture guidance | +| `docs/api/` | Generated TypeDoc output (gitignored locally; published on release) | + +## Setup + +Use a Node version that satisfies `package.json` `engines.node` and the Yarn version pinned by `package.json`. GitHub Actions workflows use Node 22. + +```bash +yarn install --frozen-lockfile +yarn prepare +``` + +Do not use npm for dependency installation. `package.json` sets `engines.npm` to `please-use-yarn`. + +## Development Commands + +Run commands from the repository root. + +| Command | Purpose | +| ------------------------- | ----------------------------------------------------------------------------------- | +| `yarn build` | Clean generated output and build ESM, CommonJS, and declaration artifacts | +| `yarn watch` | Run the Rollup build in watch mode | +| `yarn transpile:validate` | Type-check with TypeScript without emitting files | +| `yarn test:unit` | Run Jest unit tests | +| `yarn test:coverage` | Run Jest with coverage | +| `yarn test:lint` | Run ESLint on TypeScript source | +| `yarn test:prettier` | Check source and maintained Markdown formatting | +| `yarn test:spelling` | Spellcheck maintained source and documentation | +| `yarn docs` | Replace generated TypeDoc output under `docs/api/` while preserving maintained docs | +| `yarn fix` | Apply configured Prettier and ESLint fixes | + +`yarn test` runs the build and every `test:*` script. Run `yarn transpile:validate` separately because the aggregate script does not include it. + +## Coding Conventions + +### TypeScript + +- TypeScript strict mode, `noImplicitAny`, `strictNullChecks`, and `noImplicitReturns` are enabled. +- The compiler targets ES2015 and emits ESNext modules for Rollup. +- Prefer feature detection over new user-agent parsing. Use `BrowserInfo` when a check depends on browser version. +- Return `CapabilityState.UNKNOWN` when required signals are missing rather than guessing capability. +- Avoid `any` unless an existing browser boundary requires it and the reason is documented. + +### Formatting, comments, and JSDoc + +- Prettier uses a 100-character print width, single quotes, two-space indentation, and ES5 trailing commas. +- ESLint uses Airbnb, TypeScript, Jest, JSDoc, and Prettier rules. +- JSDoc is required for functions, classes, and methods unless a narrow existing suppression applies. +- Comments explain intent, browser constraints, or counterintuitive behavior. Do not narrate obvious code or change history. +- Keep public API descriptions concise and include required `@param` and `@returns` tags. + +### Capability and runtime boundaries + +- `CapabilityState` values are API outcomes, not product policy. `CAPABLE`, `NOT_CAPABLE`, and `UNKNOWN` must stay semantically stable. +- `WebCapabilities.supportsWasm()` checks whether WASM is available. `WasmRuntimeProbe.check()` is a separate async speed check. +- `WasmRuntimeProbe.check()` caches one promise per page load. Do not add duplicate probes without clearing that cache intentionally in tests. +- Worker lifecycle must terminate the worker and revoke the Blob URL in a `finally` block. +- Benchmark thresholds, classification order, visibility handling, timeout behavior, and unknown or uncertain reasons are correctness-sensitive. + +## Public API and Compatibility + +`src/index.ts` re-exports `WebCapabilities`, `CapabilityState`, `BrowserInfo`, `BrowserName`, `OSName`, `CpuInfo`, `SystemInfo`, `SystemInfoEvents`, pressure-related types, and the WASM runtime probe types. Changes to those exports, method signatures, capability outcomes, probe classification, or package entry points can affect consumers and semantic versioning. + +The package publishes ESM, CommonJS, and bundled declaration entry points from `dist/`. The only runtime dependency is `bowser`. + +See [the architecture overview](docs/knowledge-base/architecture/web-capabilities-overview.md) for package areas, CapabilityState, the WASM probe, builds, tests, and releases. + +## Testing + +- Jest runs through `ts-jest` in the jsdom environment configured by `jest.config.js`. +- Tests are co-located as `src/**/*.spec.ts`. +- `*.worker.js` imports use the raw transform configured in `jest.config.js`. +- Capability tests mock or stub browser globals such as `WebAssembly`, `Worker`, `RTCPeerConnection`, and codec capabilities. +- WASM runtime probe tests reset the cached promise, mock worker construction and responses, and cover disabled, slow, fast, uncertain, unknown, timeout, and cleanup paths. +- Add a regression test for every capability outcome, threshold, worker lifecycle, or public behavior change. +- Run `yarn transpile:validate` for exported type or public API changes in addition to Jest. + +Path-scoped detail lives in [.github/instructions/testing.instructions.md](.github/instructions/testing.instructions.md). + +## Code Review Priorities + +1. Preserve `CapabilityState` semantics and avoid false positives that block or enable features incorrectly. +2. Keep `supportsWasm()` separate from `WasmRuntimeProbe.check()`. +3. Preserve worker termination and Blob URL cleanup in the probe. +4. Treat probe thresholds, check order, visibility handling, and reason codes as correctness-sensitive. +5. Treat exports, declarations, entry points, and capability outcomes as compatibility-sensitive. +6. Add or update tests when browser-boundary or probe behavior changes. + +Path-scoped detail lives in [.github/instructions/code-review.instructions.md](.github/instructions/code-review.instructions.md). + +## CI/CD + +- Pull requests install with Yarn, then run `yarn test:lint`, `yarn test:prettier`, `yarn test:spelling`, `yarn transpile:validate`, `yarn build`, and `yarn test:coverage` in GitHub Actions. +- Docs generation and the aggregate `yarn test` command are not current pull-request gates. +- Pushes to `main` install dependencies, run `yarn build`, and invoke semantic-release. +- semantic-release analyzes Conventional Commits, publishes the public npm package, updates the changelog and package metadata, and commits configured release assets. +- Do not run semantic-release or publish locally unless the user explicitly requests a coordinated release. + +Path-scoped detail lives in [.github/instructions/ci-cd.instructions.md](.github/instructions/ci-cd.instructions.md). + +## Pull Requests + +- Follow [docs/contributing/GIT_CONVENTIONS.md](docs/contributing/GIT_CONVENTIONS.md) for branches and Conventional Commits. +- Use [.github/skills/pr-description/SKILL.md](.github/skills/pr-description/SKILL.md) to draft the existing pull-request template from the complete committed diff and observed test evidence. +- Lead with why the change is useful, use outcome-focused bullets, and prefer plain language over implementation jargon. +- Call out capability outcome, browser detection, worker lifecycle, probe classification, public API, declaration, package-format, or semantic-version impact when applicable. +- Preserve the template headings and leave Generative AI disclosure choices to the author. + +## Security and Public Scope + +- Do not add secrets, tokens, credentials, private keys, certificates, `.env` values, private URLs, or absolute local paths. +- Do not copy private issue, documentation, CI, or consumer information into this public repository. +- Do not add real user-agent strings, browser profiles, or identifying session data to tests or logs. +- Keep dependency and workflow changes deterministic through `yarn.lock` and review package-source changes carefully. + +## Maintaining This Guidance + +Update this guidance when public exports, capability boundaries, scripts, Node or Yarn requirements, tests, build outputs, workflows, or release behavior change. + +If guidance disagrees with current source or configuration, fix the guidance rather than preserving stale assumptions. diff --git a/README.md b/README.md index 763608b..1352732 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,15 @@ import { CpuInfo } from '@webex/web-capabilities'; const logicalCores = CpuInfo.getNumLogicalCores(); if (logicalCores) { - console.log(`Number of logical CPU cores: ${logicalCores}`); + console.log(`Number of logical CPU cores: ${logicalCores}`); } ``` +## Contributing and AI-assisted development + +- Read [AGENTS.md](AGENTS.md) for setup, verified commands, coding conventions, testing boundaries, and AI-agent guidance. +- Follow [docs/contributing/GIT_CONVENTIONS.md](docs/contributing/GIT_CONVENTIONS.md) for branch and commit conventions. +- Start with the [knowledge base](docs/knowledge-base/README.md) for capability detection, WASM probing, package, and release architecture. # Setup diff --git a/cspell.json b/cspell.json index be61343..ab850b8 100644 --- a/cspell.json +++ b/cspell.json @@ -30,6 +30,7 @@ "globby", "gohri", "inferencing", + "jitless", "KHTML", "libauth", "mindmeld", diff --git a/docs/contributing/GIT_CONVENTIONS.md b/docs/contributing/GIT_CONVENTIONS.md new file mode 100644 index 0000000..87e9d0d --- /dev/null +++ b/docs/contributing/GIT_CONVENTIONS.md @@ -0,0 +1,43 @@ +# Branch and Commit Conventions + +Use these rules for branch names and commit messages. Pull-request description guidance lives in [the PR description skill](../../.github/skills/pr-description/SKILL.md). + +## Branch names + +The repository does not currently enforce a branch-name format. Existing remote branches include both `/` and standalone topic patterns. + +- Start new work from the current `main` branch. +- Prefer `/` for contributor branches. +- Keep names lowercase, short, and hyphen-separated. +- Describe the change rather than copying a long issue title. + +Example: + +```text +developer/wasm-probe-thresholds +``` + +## Commit messages + +Commit messages must follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). The local Husky commit-message hook runs commitlint with the conventional configuration, and semantic-release analyzes commits that reach `main`. + +Use this format: + +```text +(): +``` + +Common types: + +- `feat`: new behavior that normally produces a minor release +- `fix`: corrected behavior that normally produces a patch release +- `docs`: documentation-only change +- `refactor`: internal restructuring without a behavior change +- `test`: test-only change +- `chore`, `ci`, or `build`: maintenance and delivery work + +Keep the subject direct and lowercase. Use the body when the reason or tradeoff is not clear from the subject. + +Mark an intentional breaking change with `!` after the type or scope, or add a `BREAKING CHANGE:` footer. Breaking changes can produce a major release. + +semantic-release reads commits merged into `main`. Do not assume the pull-request title alone controls the published version. diff --git a/docs/knowledge-base/README.md b/docs/knowledge-base/README.md new file mode 100644 index 0000000..81ab4d4 --- /dev/null +++ b/docs/knowledge-base/README.md @@ -0,0 +1,15 @@ +# Knowledge Base + +Public, repository-local architecture and onboarding guidance for `@webex/web-capabilities`. Read this index before broad searches about capability checks, browser detection, system signals, WASM runtime probing, package boundaries, or release behavior. + +| Link | What you get | +| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| [architecture/web-capabilities-overview.md](architecture/web-capabilities-overview.md) | Package areas, CapabilityState, WASM probe basics, build and test summary | +| [README.md](../../README.md) | Package usage and development links | +| [src/index.ts](../../src/index.ts) | Authoritative public source exports | + +Generated API documentation belongs under `docs/api/`. That directory is gitignored locally. Cleanup commands must preserve this knowledge base and `docs/contributing/`. + +Keep articles short and verify implementation details against current source, tests, package metadata, and configuration. Use only public links and publicly verifiable relationships. + +New articles belong under `architecture/` or `questions/` and must be linked here. Agents should ask before capturing additional repeatable knowledge. diff --git a/docs/knowledge-base/architecture/web-capabilities-overview.md b/docs/knowledge-base/architecture/web-capabilities-overview.md new file mode 100644 index 0000000..2544bef --- /dev/null +++ b/docs/knowledge-base/architecture/web-capabilities-overview.md @@ -0,0 +1,80 @@ +# web-capabilities Architecture + +## Scope + +`@webex/web-capabilities` is a small browser-side library with helpers for browser or system information and for estimating whether certain features are likely to work in the current environment. + +Consumers read the public exports from `src/index.ts`. This page summarizes the main areas of the package. Method-level detail belongs in source, tests, and generated API docs under `docs/api/`. + +## Main areas + +```mermaid +flowchart LR + app["Application code"] --> exports["src/index.ts"] + exports --> browser["BrowserInfo"] + exports --> system["SystemInfo and CpuInfo"] + exports --> caps["WebCapabilities"] + exports --> probe["WasmRuntimeProbe"] + caps --> state["CapabilityState"] + probe --> state +``` + +| Area | Role | +| ------------------ | -------------------------------------------------------------------------------- | +| `BrowserInfo` | Browser, OS, engine, and version helpers via the `bowser` dependency | +| `SystemInfo` | Logical CPU core count and optional Compute Pressure API helpers | +| `CpuInfo` | Deprecated wrapper around core count; kept for compatibility | +| `WebCapabilities` | Synchronous checks for feature support, codecs, WebRTC APIs, and hardware limits | +| `WasmRuntimeProbe` | Optional async check for whether WASM runs fast enough for heavy effects | + +## CapabilityState + +All capability helpers return `CapabilityState`: + +- `CAPABLE` — enough signal that the requirement is met +- `NOT_CAPABLE` — enough signal that it is not met +- `UNKNOWN` — not enough information to decide + +These are library outcomes. Callers decide how to use them in product logic. + +## Synchronous checks + +`WebCapabilities` inspects browser globals, codec capabilities, core count, and related signals. Examples include background noise removal, virtual background, video codec support, encoded stream transforms, and RTCPeerConnection availability. + +When a required signal is missing, methods return `UNKNOWN` instead of guessing. See `src/web-capabilities.ts` and its tests for the full method list and thresholds. + +## Browser and system helpers + +`BrowserInfo` centralizes user-agent parsing and version comparisons. Use it when a check depends on browser name or version rather than adding new parsing elsewhere. + +`SystemInfo` is the preferred source for core count and CPU pressure events. Prefer it over `CpuInfo` in new code. + +## WASM: present versus fast enough + +Two APIs answer different questions: + +| API | Question | When | +| -------------------------------- | -------------------------------------------- | -------------------------- | +| `WebCapabilities.supportsWasm()` | Is WASM available? | Sync, cheap | +| `WasmRuntimeProbe.check()` | Is WASM fast enough for real-time WASM work? | Async, cached for the page | + +Do not treat one result as a substitute for the other. WASM can be available but too slow in some browser modes. + +The probe runs a short benchmark in a Web Worker. Rollup embeds `wasm-runtime-probe.worker.js` into the published bundle as source text. At runtime the probe starts that worker from a Blob URL, then terminates it and revokes the URL when finished. + +Classification uses timing ratios and fixed thresholds. Order of checks, visibility handling, timeout behavior, and reason codes are correctness-sensitive. See `src/wasm-runtime-probe.ts` and `src/wasm-runtime-probe.spec.ts` before changing them. + +## Build, test, and release + +- Rollup publishes ESM, CommonJS, and TypeScript declarations from `src/index.ts`. +- Jest runs in jsdom; worker source uses a raw transform in tests. +- TypeDoc output goes to `docs/api/` and must not overwrite `docs/knowledge-base/` or `docs/contributing/`. +- Pull-request CI runs lint, Prettier, spelling, TypeScript validation, build, and coverage. Release on `main` builds and runs semantic-release. + +Runtime dependency: `bowser` only. + +## Compatibility notes + +- Keep `supportsWasm()` separate from `WasmRuntimeProbe.check()`. +- Preserve worker termination and Blob URL cleanup in the probe. +- Treat export, threshold, and classification changes as semver-sensitive. diff --git a/package.json b/package.json index 31c6642..87610c4 100644 --- a/package.json +++ b/package.json @@ -14,17 +14,17 @@ "build": "run-s clean compile", "clean": "yarn transpile:clean", "compile": "rollup -c ./rollup.config.js", - "docs": "rimraf ./docs/* && typedoc", + "docs": "rimraf ./docs/api && typedoc", "fix": "run-s fix:*", - "fix:prettier": "prettier \"src/**/*.ts\" --write", + "fix:prettier": "prettier --write \"src/**/*.ts\" \"docs/**/*.md\" \"AGENTS.md\" \"README.md\" \".github/**/*.md\"", "fix:lint": "eslint src --ext .ts --fix", "prepare": "husky install", "release": "semantic-release", "test": "run-s build test:*", "test:coverage": "jest --coverage", "test:lint": "eslint src --ext .ts --max-warnings=0", - "test:prettier": "prettier \"src/**/*.ts\" --list-different", - "test:spelling": "cspell \"{README.md,.github/*.md,src/**/*.ts}\"", + "test:prettier": "prettier --list-different \"src/**/*.ts\" \"docs/**/*.md\" \"AGENTS.md\" \"README.md\" \".github/**/*.md\"", + "test:spelling": "cspell \"src/**/*.ts\" \"docs/**/*.md\" \"AGENTS.md\" \"README.md\" \".github/**/*.md\"", "test:unit": "jest", "transpile": "tsc", "transpile:clean": "rimraf ./dist", diff --git a/typedoc.json b/typedoc.json index 23d69f2..8a0c1cb 100644 --- a/typedoc.json +++ b/typedoc.json @@ -1,5 +1,5 @@ { "entryPoints": ["src"], "githubPages": false, - "out": "docs" + "out": "docs/api" }