@webex/common-timers 3.12.0-mobius-socket.3 → 3.12.0-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,243 @@
1
+ ---
2
+ type: Architecture
3
+ title: '@webex/common-timers architecture'
4
+ description: Repository-wide boundaries, resources, interactions, dependencies, and cross-cutting architecture.
5
+ tags: [architecture]
6
+ ---
7
+ <!-- sdd-generated-metadata
8
+ doc_kind: standing-doc
9
+ generated_from: architecture@0.3.0
10
+ generated_by: claude-code
11
+ approved_by: pending
12
+ updated_at: 2026-09-28T05:34:36Z
13
+ validation_status: pass
14
+ -->
15
+
16
+ # @webex/common-timers architecture
17
+
18
+ Canonical architecture for the `@webex/common-timers` package. This document owns the facts that span
19
+ the package as a whole — what it is, what it publishes, what it depends on, and the platform and
20
+ release boundaries it sits inside. Behavior belongs to the owning module specification and is linked,
21
+ not repeated.
22
+
23
+ Related context: [specification registry](specs/README.md) ·
24
+ [repository agent instructions](../AGENTS.md)
25
+
26
+ ## Applicability
27
+
28
+ | Condition ID | Status | Evidence or reason | Owned section |
29
+ | ------------------------------------ | ---------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
30
+ | `repo.owns_datastore` | N/A | No migrations, ORM configuration, schema file, or connection string exists | Repository data and schema |
31
+ | `repo.holds_client_state` | N/A | No store or shared state model; the only state is one private field per `Timer` instance | Client state model |
32
+ | `repo.components_interact` | N/A | The package is a single module with a single source file; there is no second component to interact with | Dependency and interaction topology |
33
+ | `repo.domain_data_across_components` | N/A | No domain entities exist; callbacks and durations are opaque values the package never inspects | Object and data ownership |
34
+ | `repo.caches_data` | N/A | No cache client, memoization, or bounded store | Caching catalog |
35
+ | `repo.observability_convention` | N/A | No logger, metric, trace, or audit call; the package emits nothing observable | Observability patterns |
36
+ | `repo.deploys_to_infra` | N/A | No container, manifest, or cloud configuration; the package is published to a registry, not deployed | Runtime and infrastructure |
37
+ | `repo.shared_base_libs` | Applicable | Build, lint, and test behavior are inherited from workspace-internal `@webex/*-legacy` packages | Shared and base libraries |
38
+ | `repo.is_monorepo` | N/A | The documented scope is one package; workspace-wide package mapping is owned outside it | Package map and dependencies |
39
+ | `repo.multi_platform` | Applicable | The `unref` capability check, the `process` browser shim, and the browserify transform encode a Node/browser split | Platform matrix |
40
+ | `repo.published_package` | Applicable | `package.json` declares `main`, `devMain`, and `deploy:npm` | Release and versioning |
41
+ | `repo.embedded_in_host` | N/A | Consumed as a dependency; no mount contract, plugin manifest, or widget registration | Host integration and theming |
42
+ | `repo.exposes_commands_or_artifacts` | N/A | No CLI, generator, or repository-owned command surface; the published build output is covered by Release and versioning | Commands and generated artifacts |
43
+ | `repo.cross_repo_deps_material` | N/A | The package declares no runtime dependencies, so nothing external can affect its behavior or delivery | Cross-repository topology |
44
+ | `repo.security_arch_warranted` | N/A | No identity, token, secret, encryption, or trust boundary; the posture is recorded under Cross-cutting architecture | Security architecture |
45
+
46
+ ## Design overview
47
+
48
+ `@webex/common-timers` exists to solve one problem for every other package in the Webex JS SDK: a
49
+ pending timer must never be the reason a Node process refuses to exit.
50
+
51
+ Node's `setTimeout` and `setInterval` return a `Timeout` object that counts toward process liveness
52
+ until it fires or is cleared. An SDK that schedules retries, heartbeats, and batch flushes therefore
53
+ keeps a host CLI or test run alive long after the caller's work is done. Node's answer is
54
+ `Timeout.unref()`, and this package's answer is to make calling it unforgettable: the SDK imports
55
+ `safeSetTimeout` and `safeSetInterval` instead of the globals, and the `unref` call is built in.
56
+
57
+ That decision shapes everything else. Because browsers return a plain number with no `unref` method,
58
+ the wrappers feature-detect the method on the returned handle rather than branching on the platform —
59
+ so one module, one build, and no bundler shim serve both targets, at the cost of a
60
+ `number | NodeJS.Timeout` return type that every consumer has to accept.
61
+
62
+ A third export, `Timer`, sits on top. It is the one abstraction the free functions cannot express: a
63
+ deadline a caller can push back repeatedly and then retire, with a guarded `init → running → done`
64
+ lifecycle that throws rather than silently ignoring an invalid call. It arms itself through
65
+ `safeSetTimeout`, so a managed timer inherits the same process-exit safety.
66
+
67
+ The package is 117 lines in one file with zero runtime dependencies. Its architectural weight is
68
+ entirely in what it promises to the eleven workspace packages that consume it, not in its internal
69
+ structure.
70
+
71
+ ## Resource inventory and responsibilities
72
+
73
+ | Resource | Kind | Responsibility | Owner | Source | Detailed specification |
74
+ | ---------------------- | ------- | --------------------------------------------------------------------------------------------------------- | -------------------------- | -------------- | ---------------------- |
75
+ | `@webex/common-timers` | Package | Publish the SDK's timer vocabulary to npm and to the surrounding workspace | Cisco Webex for Developers | `package.json` | `src/docs/README.md` |
76
+ | `src` | Module | The timer primitives themselves: both scheduling wrappers, the `unref` capability check, and the `Timer` lifecycle | Cisco Webex for Developers | `src/index.ts` | [`src/docs/README.md`](../src/docs/README.md) |
77
+
78
+ ## Interaction and execution flows
79
+
80
+ The package has no internal interactions to diagram — one module, one file. The architecturally
81
+ meaningful flow is the one that crosses its boundary: a consuming SDK package calls in, the module
82
+ calls the host runtime, and the host calls the consumer's callback back directly.
83
+
84
+ ```mermaid
85
+ flowchart LR
86
+ Consumer[Consuming SDK package] -->|import| Entry["src/index.ts"]
87
+ Entry -->|setTimeout / setInterval| Host[Host timer API]
88
+ Entry -->|unref when supported| Host
89
+ Host -.->|callback on the event loop| Consumer
90
+ Consumer -->|clearTimeout / clearInterval| Host
91
+ ```
92
+
93
+ | From | To | Interaction or transport | Purpose | Failure or compatibility behavior |
94
+ | --------------------- | --------------------- | -------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
95
+ | Consuming SDK package | `src` | Static import, synchronous call | Schedule deferred or repeating work, or bound a request with a resettable deadline | `Timer` throws synchronously on an invalid lifecycle call; the free functions have no rejected path |
96
+ | `src` | Host timer API | Direct call to the runtime global | Create the timer and release it from process liveness | Platform errors propagate unchanged. A missing `unref` is skipped silently, leaving the platform default |
97
+ | Host timer API | Consuming SDK package | Event-loop callback | Deliver the scheduled callback | A Node process may exit before the delay elapses, in which case the callback is never invoked at all |
98
+ | Consuming SDK package | Host timer API | Direct call to the runtime global | Cancel a timer using the returned handle | The package exports no clear function; cancellation uses the platform's own `clearTimeout` / `clearInterval` |
99
+
100
+ ## Dependency topology
101
+
102
+ | Dependency | Type | Used by | Purpose | Version, failure, or fallback policy |
103
+ | --------------------------------------- | -------- | ------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
104
+ | Host timer API | External | `src` | `setTimeout`, `setInterval`, and `clearTimeout` — the primitives being wrapped | No fallback and no polyfill. Whatever the runtime throws propagates to the caller unchanged |
105
+ | `Timeout.unref()` (Node-only extension) | External | `src` | Release a pending timer from process liveness | Feature-detected on the handle. Absent in browsers, where the branch is skipped and the platform default applies |
106
+ | `@webex/babel-config-legacy` | Internal | build | Transpilation configuration | `workspace:*`; development only, never shipped in the published artifact |
107
+ | `@webex/eslint-config-legacy` | Internal | lint | Lint rules | `workspace:*`; development only |
108
+ | `@webex/jest-config-legacy` | Internal | test | Unit-test configuration | `workspace:*`; development only |
109
+ | `@webex/legacy-tools` | Internal | build | The `webex-legacy-tools` build and test runner | `workspace:*`; development only |
110
+
111
+ There are **no runtime dependencies**: `package.json` declares only `devDependencies`. That removes
112
+ every cycle, ordering constraint, and third-party single point of failure from this package — the
113
+ only thing it can depend on at runtime is the host itself. Exact versions live in
114
+ [`package.json`](../package.json).
115
+
116
+ ## Public and consumer surfaces
117
+
118
+ | Surface | Type | Owner | Consumers | Compatibility policy | Source |
119
+ | ---------------------- | ---- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
120
+ | `common-timers-sdk` | SDK | `src` | Declared by `internal-plugin-mercury`, `internal-plugin-metrics`, `internal-plugin-device`, `internal-plugin-encryption`, `internal-plugin-avatar`, `internal-plugin-dss`, `internal-plugin-ai-assistant`, `internal-plugin-scheduler`, `webex-core`, and `calling`; additionally imported, without being declared, by `plugin-meetings` | Published npm surface: `safeSetTimeout`, `safeSetInterval`, and `Timer`. Stable under the workspace's shared semantic version; the wrapper signatures track the platform's own | `package.json` |
121
+
122
+ `common-timers-sdk` is the package's only contract. Its canonical native source is the package entry
123
+ point declared by `main` and `devMain` in [`package.json`](../package.json); per-export detail,
124
+ including the parameter and return types, lives in the owning module specification's `Public surface`
125
+ and `Export stability` sections at [`src/docs/README.md`](../src/docs/README.md). This page indexes
126
+ the contract; it does not restate the declarations.
127
+
128
+ The declared and importing consumer sets differ in both directions, which matters for impact
129
+ analysis: `internal-plugin-scheduler` declares the dependency without importing it, and
130
+ `plugin-meetings` imports it without declaring it. A dependency-graph query over `package.json`
131
+ files alone therefore both over- and under-states the blast radius of a surface change. The module
132
+ specification records the per-export breakdown.
133
+
134
+ The package consumes one external contract, `host-timer-api` — the runtime's own
135
+ `setTimeout`/`setInterval`/`clearTimeout` plus the Node `Timeout.unref()` extension. It is external
136
+ and unversioned by this repository; its consumption is recorded in the module spec's `Dependencies`.
137
+
138
+ ## Cross-cutting architecture
139
+
140
+ ### Security
141
+
142
+ - **Trust boundaries and identity flow:** none. The package has no identity, no authentication, and
143
+ no trust boundary. It never reads configuration, never touches the network, and never inspects the
144
+ callback or duration a caller passes it.
145
+ - **Sensitive surfaces and data classes:** none. No data of any classification transits the package;
146
+ arguments are forwarded to the host scheduler and never stored, logged, or serialized.
147
+ - **Encryption and secret boundaries:** not applicable. Nothing is persisted or transmitted.
148
+
149
+ The security-relevant property of this package is a liveness one, not a confidentiality one: because
150
+ every timer is unref-ed, the package can cause scheduled work to be silently dropped at process exit.
151
+ Consumers that require a callback to run before shutdown must hold the process open themselves.
152
+
153
+ ### Observability and operations
154
+
155
+ - **Logging and correlation:** none. The package emits no log line, and deliberately takes no logger
156
+ dependency — a timer primitive called from ten packages would produce noise with no correlation
157
+ context of its own. Consumers log around their own timer usage.
158
+ - **Metrics, traces, and audit signals:** none emitted or consumed.
159
+ - **Ownership and operational entry points:** the package is maintained by Cisco Webex for Developers
160
+ as part of the Webex JS SDK workspace; it has no dashboard, alert, or runbook of its own because it
161
+ has no runtime deployment. Failures surface inside the consuming package.
162
+
163
+ ### Quality attributes
164
+
165
+ The measurable expectations that fit a dependency-free utility package of this size:
166
+
167
+ | Attribute | Expectation | Evidence |
168
+ | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
169
+ | Footprint | Zero runtime dependencies; the published artifact is one transpiled module | `package.json` |
170
+ | Platform compatibility | The same build runs on Node `>=18` and in a browser, with no conditional export or bundler shim | `package.json`, `src/index.ts`, `process` |
171
+ | Process-exit safety | No timer created through this package extends process lifetime | `src/index.ts` |
172
+ | Lifecycle correctness | Every invalid `Timer` transition is rejected rather than ignored; all six rejection branches are covered by unit tests | `test/unit/spec/index.ts` |
173
+ | Process-exit verification | **Not verified by test.** No assertion covers the `unref` contract on either platform branch | `src/index.ts` (code reading only) |
174
+ | Test verification | 13 unit cases in one suite, all passing. No coverage threshold gates the package — coverage collection is disabled in its jest config | `test/unit/spec/index.ts`, `jest.config.js` |
175
+
176
+ Process-exit safety is the attribute that most needs proving and is the one still unproven: the
177
+ `unref` calls in `src/index.ts` carry no test, so removing them would not turn the suite red. The
178
+ attribute is supported by code reading alone. Lifecycle correctness, by contrast, is thoroughly
179
+ covered. Per-requirement evidence and the full list of coverage gaps are recorded in the module
180
+ specification's `Verification` section.
181
+
182
+ ## Shared and base libraries
183
+
184
+ Every build, lint, and test behavior in this package is inherited. The package contributes three
185
+ two-line configuration files that do nothing but re-export the shared configuration.
186
+
187
+ | Library | Inherited responsibility | Consumers | Version floor | Compatibility rule |
188
+ | ----------------------------- | -------------------------------------------------------------------------------- | --------------------------- | ------------- | ------------------------------------------------------------------------------------------ |
189
+ | `@webex/babel-config-legacy` | Transpilation targets and plugins, re-exported verbatim by `babel.config.js` | Build | `workspace:*` | Pinned to the workspace; a change to the shared config changes this package's output |
190
+ | `@webex/eslint-config-legacy` | All lint rules, extended by `.eslintrc.js` with `root: true` and nothing else | `test:style` | `workspace:*` | Pinned to the workspace; this package adds no local rule or override |
191
+ | `@webex/jest-config-legacy` | Unit-test runner configuration, re-exported verbatim by `jest.config.js` | `test:unit` | `workspace:*` | Pinned to the workspace. It sets `collectCoverage: false`, which is why no gate applies here |
192
+ | `@webex/legacy-tools` | The `webex-legacy-tools` build and test CLI invoked by the package scripts | `build:src`, `test:unit` | `workspace:*` | Pinned to the workspace; command flags are owned there, not here |
193
+
194
+ The practical consequence for a contributor: there is no package-local knob. Changing how this
195
+ package builds, lints, or tests means changing the shared workspace configuration.
196
+
197
+ ## Platform matrix
198
+
199
+ The package targets Node and the browser from one source file and one build. The split is a single
200
+ runtime capability check, not a build-time branch.
201
+
202
+ | Platform | Shared versus platform-specific boundary | Entry or build | Support and compatibility constraints |
203
+ | -------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
204
+ | Node | Fully shared. The handle is a `Timeout` object exposing `unref`, so the capability check succeeds and the timer is released from process liveness | `dist/index.js` via `main`, built by `build:src` | Requires Node `>=18` per `engines`. Scheduled callbacks may be dropped at process exit — that is the intended behavior |
205
+ | Browser | Fully shared. The handle is a number with no `unref`, so the check fails and the platform default applies | Same module; the browserify transform resolves the `process` shim to `{browser: true}` | No separate bundle, no `browser` field in `package.json`, and no polyfill. Behavior degrades to plain `setTimeout`/`setInterval` |
206
+
207
+ Because the two platforms return different handle types, the exported return type is the union
208
+ `number | NodeJS.Timeout`. That union is the visible cost of the single-build decision, and it is
209
+ part of the published contract rather than an implementation detail.
210
+
211
+ ## Release and versioning
212
+
213
+ | Artifact | Publish target | Versioning rule | Deprecation window | Changelog or migration obligation |
214
+ | ---------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
215
+ | `@webex/common-timers` | npm | Published by `deploy:npm`. Version numbers are assigned by the workspace release pipeline, not declared in this package's `package.json` | Governed by the workspace release process; the package declares none of its own | Changelog generation is owned at the workspace root. This package ships no `CHANGELOG.md` |
216
+
217
+ The published artifact is `dist/index.js`, produced by `build:src`. In-workspace consumers resolve
218
+ `devMain` (`src/index.ts`) instead, so a change to the source is visible to sibling packages without
219
+ a publish. A breaking change to any of the three exports is a breaking change for eleven workspace
220
+ packages plus external npm consumers; the module specification's `Export stability` section records
221
+ what specifically is promised, including that the `Timer` rejection message wording is asserted by
222
+ the unit suite.
223
+
224
+ ## Domain language
225
+
226
+ | Term | Repository-specific meaning | Authoritative source |
227
+ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
228
+ | unref | Asking a Node timer handle to stop counting toward process liveness, so a pending timer cannot prevent the process from exiting | `src/index.ts` |
229
+ | safe | In `safeSetTimeout` / `safeSetInterval`, specifically "safe against wedging a process open" — it implies nothing about error handling or types | `README.md` |
230
+ | handle | The value the host scheduler returns: a `Timeout` object in Node, a number in a browser. The package returns it unchanged after unref-ing it | `src/index.ts` |
231
+ | arm | Move a `Timer` from `init` to `running` by scheduling its callback. Only `start()` arms a timer | `src/index.ts` |
232
+ | reset | Clear a running timer and re-arm it for the **full** original timeout. It is an idle deadline, not a pause or a resume | `src/index.ts` |
233
+ | done | The terminal `Timer` state, reached by either expiry or cancellation. It is not recoverable and the two causes are indistinguishable | `src/index.ts` |
234
+
235
+ ## References and maintenance
236
+
237
+ - Decisions: [adr/](adr/)
238
+ - Instantiated specifications and routing: [specs/README.md](specs/README.md)
239
+ - Module specification: [`src/docs/README.md`](../src/docs/README.md)
240
+ - Getting started: [getting-started.md](getting-started.md)
241
+ - Update this document in the same change that alters the package's published surface, its
242
+ dependency posture, its platform support, or its release boundary. A change confined to timer
243
+ behavior belongs in the module specification instead.
@@ -0,0 +1,121 @@
1
+ ---
2
+ type: Getting Started
3
+ title: Getting started
4
+ description: Local setup, build, run, and test routing for @webex/common-timers.
5
+ tags: [onboarding]
6
+ ---
7
+ <!-- sdd-generated-metadata
8
+ doc_kind: standing-doc
9
+ generated_from: getting-started@0.3.0
10
+ generated_by: claude-code
11
+ approved_by: pending
12
+ updated_at: 2026-09-28T05:34:36Z
13
+ validation_status: pass
14
+ -->
15
+
16
+ # Getting started
17
+
18
+ Onboarding for **`@webex/common-timers`**. The package is one of many in the Webex JS SDK yarn
19
+ workspace, so every command below is run from the workspace root and targets this package by name.
20
+
21
+ ## Prerequisites
22
+
23
+ | Tool or access | Version or requirement |
24
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
25
+ | Node.js | `package.json` declares the package floor as `>=18`. The surrounding workspace pins a newer Node through its own `.nvmrc` and contributor instructions, so match the workspace when working in-tree |
26
+ | Yarn | The workspace ships its own Yarn release and resolves it automatically; do not install Yarn separately |
27
+ | Registry, VPN, or account access | N/A. The package has no runtime dependencies and resolves nothing from a private registry |
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ yarn install
33
+ ```
34
+
35
+ Run `yarn install` once at the Webex JS SDK workspace root. It installs every package in the
36
+ workspace, including this one; there is no package-local install step.
37
+
38
+ Cloning the workspace is owned at the workspace root, not by this package, so no clone command is
39
+ recorded here — follow the root repository's own instructions to obtain a checkout first.
40
+
41
+ ## Build
42
+
43
+ ```bash
44
+ yarn workspace @webex/common-timers build:src
45
+ ```
46
+
47
+ This runs `webex-legacy-tools build` over `src/` and writes the transpiled module plus type
48
+ declarations and source maps to `dist/`, which is what `main` points at for published consumers.
49
+ `yarn workspace @webex/common-timers build` is an alias for the same thing.
50
+
51
+ ## Run
52
+
53
+ ```bash
54
+ # N/A — this package has no runnable entry point.
55
+ yarn workspace @webex/common-timers test:unit
56
+ ```
57
+
58
+ There is nothing to start. The package is a library with no CLI, server, or runtime entry point —
59
+ `package.json` declares no `bin` and no `start` script. The closest thing to running it is executing
60
+ its unit suite, or importing it from a sibling workspace package, which resolves `devMain`
61
+ (`src/index.ts`) directly without a build.
62
+
63
+ ## Tests
64
+
65
+ ```bash
66
+ yarn workspace @webex/common-timers test:unit
67
+ ```
68
+
69
+ The package declares exactly one test tier. `package.json` also declares an aggregate `test` script,
70
+ but it chains `test:integration` and `test:browser`, neither of which this package defines — so
71
+ `yarn workspace @webex/common-timers test` cannot succeed. Use the individual commands.
72
+
73
+ | Tier | Command | Test location | Framework | External dependencies |
74
+ | ---- | -------------------------------------------------- | ------------------------- | --------- | --------------------- |
75
+ | Unit | `yarn workspace @webex/common-timers test:unit` | `test/unit/spec/index.ts` | jest | None |
76
+
77
+ Lint runs separately:
78
+
79
+ ```bash
80
+ yarn workspace @webex/common-timers test:style
81
+ ```
82
+
83
+ - Coverage or quality gate: N/A. The resolved `jest.config.js` sets `collectCoverage: false` and
84
+ declares no threshold, and the package has no `test:coverage` script for the workspace CI coverage
85
+ job to pick up. Verified with the package owner during onboarding.
86
+ - Enforcement source: `jest.config.js`, which re-exports the shared `@webex/jest-config-legacy`
87
+ configuration
88
+ - Test environment or QA dependencies: none. The suite runs entirely in-process against sinon fake
89
+ timers
90
+
91
+ ## Configuration and secrets
92
+
93
+ - Required configuration: none. The package reads no environment variable, config file, or remote
94
+ setting.
95
+ - Secret source: N/A — the package handles no credentials.
96
+ - Package or artifact access: N/A — no runtime dependencies and no private registry.
97
+ - Required neighboring repositories or workspace layout: the package must be built and tested from
98
+ inside the Webex JS SDK workspace, because its build, lint, and test configuration are all
99
+ `workspace:*` dependencies (`@webex/legacy-tools`, `@webex/jest-config-legacy`,
100
+ `@webex/eslint-config-legacy`, `@webex/babel-config-legacy`).
101
+ - Platform, simulator, device, or SDK setup: N/A.
102
+ - Never commit credentials or copy production secrets into a local config.
103
+
104
+ ## First-run verification
105
+
106
+ 1. Run `yarn install` at the workspace root.
107
+ 2. Run `yarn workspace @webex/common-timers test:unit`.
108
+ 3. Run `yarn workspace @webex/common-timers build:src` and confirm `dist/index.js` exists.
109
+
110
+ Expected result: the unit suite reports **13 passed, 13 total** from the single suite at
111
+ `test/unit/spec/index.ts`, covering `safeSetTimeout` callback delivery, `safeSetInterval` repetition,
112
+ and the three `Timer` methods with all six rejected transitions. The `unref` contract is not
113
+ asserted anywhere; see the module spec's `Verification` section. The build writes `dist/`.
114
+
115
+ ## Next steps
116
+
117
+ - [Repository architecture](architecture.md)
118
+ - [Specification registry](specs/README.md)
119
+ - [Module specification](../src/docs/README.md) — the behavior contract, state machine, and known
120
+ test gaps
121
+ - [Documentation index](index.md)
package/docs/index.md ADDED
@@ -0,0 +1,50 @@
1
+ ---
2
+ okf_version: '0.1'
3
+ ---
4
+ <!-- sdd-generated-metadata
5
+ doc_kind: standing-doc
6
+ generated_from: docs-index@0.3.0
7
+ generated_by: claude-code
8
+ approved_by: pending
9
+ updated_at: 2026-09-28T05:34:36Z
10
+ validation_status: pass
11
+ -->
12
+
13
+ # @webex/common-timers documentation
14
+
15
+ Doc map for developers and agents working on the timer primitives the Webex JS SDK schedules all of
16
+ its deferred work through.
17
+
18
+ ## Start here
19
+
20
+ - [Getting started](getting-started.md) — prerequisites, build, and the test router
21
+ - [Repository architecture](architecture.md) — what the package publishes, what it depends on, and
22
+ the platform and release boundaries it sits inside
23
+
24
+ There is no service specification and no API specification for this package: it is a published
25
+ library with no deployable runtime and no HTTP surface. Both omissions are recorded in
26
+ `.sdd/manifest.json` under `layout.artifact_decisions`.
27
+
28
+ ## Decisions
29
+
30
+ - [adr/](adr/) — architectural decision records. None are registered yet; the decisions that shape
31
+ the current design are recorded in the module specification's `Key design trade-off` section.
32
+
33
+ ## Specifications and contracts
34
+
35
+ - [architecture.md](architecture.md) — canonical package-wide architecture and the contract index
36
+ - [specs/README.md](specs/README.md) — module and specification registry
37
+ - [`src/docs/README.md`](../src/docs/README.md) — the owning specification beside the module's code:
38
+ public surface, requirements, state machine, failure modes, and verification
39
+ - [adr/](adr/) — concrete architectural decisions; the blank ADR template stays under `.sdd/`
40
+
41
+ The package's one contract, `common-timers-sdk`, is a published npm package surface. Its native
42
+ source is the entry point declared by `main` and `devMain` in [`package.json`](../package.json), and
43
+ the exact declarations live in [`src/index.ts`](../src/index.ts). The architecture page indexes that
44
+ contract and the module specification details it; neither copies the declarations into Markdown.
45
+
46
+ ## Related repository resources
47
+
48
+ - [`README.md`](../README.md) — the package's npm-facing readme, covering install and basic usage
49
+ - Contribution guidelines, changelog generation, and the release pipeline are owned at the Webex JS
50
+ SDK workspace root, not in this package
@@ -0,0 +1,86 @@
1
+ ---
2
+ type: Reference
3
+ title: Specification registry
4
+ description: Canonical specification registry and change-routing guide.
5
+ tags: [specifications, registry]
6
+ ---
7
+ <!-- sdd-generated-metadata
8
+ doc_kind: standing-doc
9
+ generated_from: spec-index@0.3.0
10
+ generated_by: claude-code
11
+ approved_by: pending
12
+ updated_at: 2026-09-28T05:34:36Z
13
+ validation_status: pass
14
+ -->
15
+
16
+ # Specification registry
17
+
18
+ Use this page to find the canonical architecture for `@webex/common-timers` and every instantiated
19
+ module specification plus native contract. Technical facts stay in one owning document; this page is
20
+ navigation, ownership, status, and change/test routing only.
21
+
22
+ Start with the [repository architecture](../architecture.md). There is no service specification: the
23
+ package is a published library, not a deployable service.
24
+
25
+ ## Document roles
26
+
27
+ | Document | Canonical ownership |
28
+ | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
29
+ | [Repository architecture](../architecture.md) | Package boundaries, resource inventory, interactions, dependency topology, and cross-cutting architecture |
30
+ | Service specification | N/A — not generated. The package has no deployable runtime, so no service or operating contract exists |
31
+ | Module specifications | Stable behavior and design at each module's `docs/README.md`, routed by `.sdd/manifest.json` |
32
+ | [ADR](../adr/) | A durable decision, its deciders, rationale, consequences, and supersession lineage. None are registered yet |
33
+
34
+ ## Instantiated specification registry
35
+
36
+ | Resource | Role | Canonical path | Owner | Status | Last verified |
37
+ | ---------------------- | ------------ | ---------------------- | -------------------------- | ------ | ------------- |
38
+ | `@webex/common-timers` | Architecture | `docs/architecture.md` | Cisco Webex for Developers | Active | 2026-09-28 |
39
+ | `src` | Module | `src/docs/README.md` | Cisco Webex for Developers | Active | 2026-09-28 |
40
+ | `common-timers-sdk` | Contract | `package.json` | Cisco Webex for Developers | Active | 2026-09-28 |
41
+
42
+ ### Module registry
43
+
44
+ One row per module in `.sdd/manifest.json`, which stays authoritative; this table is its
45
+ human-readable mirror and the reconciliation surface for `check_spec_index.py`.
46
+
47
+ | Module | Responsibility | Manifest coverage state | Start here |
48
+ | --- | --- | --- | --- |
49
+ | `src/` | Timer primitives that never hold a Node process open: unref-ing wrappers over `setTimeout` and `setInterval`, plus the guarded `Timer` lifecycle | Partial | `src/docs/README.md` |
50
+
51
+ Generator-side field measurement for `src` is complete: 100% (14 of 14 mandatory fields) assessed
52
+ 2026-09-24, with critical field coverage at 9 of 9. The score, date, and evidence summary are
53
+ recorded in the module specification's `Coverage score` metadata row and in `.sdd/manifest.json`.
54
+
55
+ Two gates still hold promotion open. This module has no characterization baseline, and the `unref`
56
+ requirements (`MOD-002`, `MOD-004`, `MOD-012`) together with the re-entrancy requirement (`MOD-009`)
57
+ have no automated evidence; the sole test file, `test/unit/spec/index.ts`, is pre-existing and covers
58
+ the `Timer` lifecycle rather than the `unref` contract. Independent validation (validator `codex`,
59
+ 2026-09-24) returned blocked across two runs, raising three findings in total — consumer-inventory
60
+ drift, an onboarding command with no manifest entry, and evidence-column anchors that were not
61
+ repository file paths. All three were repaired and the third run returned pass-with-warnings. A later
62
+ run assessed a test suite that has since been withdrawn from this change, so that result is stale.
63
+ `src` stays `Partial` until the missing assertions and a characterization baseline exist and a fresh
64
+ validation covers them.
65
+
66
+ ## Change and verification routing
67
+
68
+ | Change affects | Load and update | Verification route |
69
+ | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
70
+ | Package boundaries, dependency posture, platform support, or release | `docs/architecture.md`, and a new ADR under `docs/adr/` when the decision is durable | `yarn workspace @webex/common-timers build:src` plus the affected module spec |
71
+ | Timer behavior, the `Timer` lifecycle, or a thrown message | `src/docs/README.md` — `Requirements`, `State machine`, `Caller-visible failure modes`, `Verification` | `yarn workspace @webex/common-timers test:unit` |
72
+ | The exported surface or its types | `src/docs/README.md` — `Public surface` and `Export stability` — plus the architecture contract index | `yarn workspace @webex/common-timers build:src` and every dependent package's unit suite |
73
+ | Build, lint, or test configuration | `docs/getting-started.md` and the architecture `Shared and base libraries` section | `yarn workspace @webex/common-timers test:style` and `test:unit` |
74
+
75
+ ## Module and contract registration
76
+
77
+ The module specification is generated at the exact `modules[].canonical_spec` path recorded in
78
+ `.sdd/manifest.json` — `src/docs/README.md`. Every module and submodule is registered in the Module
79
+ registry above in manifest tree order; `src` has no submodules.
80
+
81
+ `common-timers-sdk` is the package's only contract: a published SDK/package surface whose canonical
82
+ native source is the entry point declared by `main` and `devMain` in `package.json`, with the exact
83
+ declarations in `src/index.ts`. Published package surfaces retain their ecosystem-native API source
84
+ and do not require OpenAPI, and the package serves no HTTP routes, so `api-specs/openapi.yaml` is
85
+ omitted. The module also consumes one external contract, `host-timer-api`, the host runtime's timer
86
+ API. This page provides navigation and ownership rather than a copied contract.
package/package.json CHANGED
@@ -32,12 +32,12 @@
32
32
  "@webex/eslint-config-legacy": "0.0.0",
33
33
  "@webex/jest-config-legacy": "0.0.0",
34
34
  "@webex/legacy-tools": "0.0.0",
35
- "@webex/test-helper-chai": "3.12.0-mobius-socket.3",
36
- "@webex/test-helper-mocha": "3.12.0-mobius-socket.3",
37
- "@webex/test-helper-mock-webex": "3.12.0-mobius-socket.3",
38
- "@webex/test-helper-test-users": "3.12.0-mobius-socket.3",
35
+ "@webex/test-helper-chai": "3.12.0-next.9",
36
+ "@webex/test-helper-mocha": "3.12.0-next.9",
37
+ "@webex/test-helper-mock-webex": "3.12.0-next.9",
38
+ "@webex/test-helper-test-users": "3.12.0-next.9",
39
39
  "eslint": "^8.24.0",
40
40
  "prettier": "^2.7.1"
41
41
  },
42
- "version": "3.12.0-mobius-socket.3"
42
+ "version": "3.12.0-next.10"
43
43
  }