Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ SPDX-License-Identifier: Apache-2.0

## Unreleased

## 0.4.0

Add runtime contract and evidence hardening behind explicit subpaths. The root
import remains unchanged.

- Add `@workit/core/contracts` for declared cancellable and shielded task
composition. This is a compile-time intent contract; it does not prove that
arbitrary task bodies observe `ctx.signal`.
- Add `@workit/core/fault` for bounded in-process lifecycle fault scenarios
over the real WorkIt scope engine. This is not OS fault injection, process
crash recovery, network chaos testing, or deterministic scheduler replay.
- Add declared agent tool capability checks to `@workit/core/ai`, including a
typed `AgentCapabilityError` and denial events before denied tool bodies run.
- Extend `@workit/core/ledger` with caller-owned SQLite and Postgres receipt
ledger adapters. These adapters define a receipt storage contract; they do
not make WorkIt a database framework.
- Add executable evidence for typed cancellation contracts, bounded fault
scenarios, agent authority, SQL receipt ledgers, and resource audit visibility.
- Extend package-consumer coverage for the new subpaths across ESM, CommonJS,
strict TypeScript, framework fixtures, and browser/worker unsupported-runtime
checks.
- Keep the root `@workit/core` import and bundle budget unchanged.

## 0.3.0

Add the `@workit/core/time-policy` planning subpath for declared async time
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ cite the software release you used:
title = {WorkIt: A TypeScript Structured Concurrency Runtime for Node.js Server Runtimes},
year = {2026},
url = {https://github.com/WorkRuntime/workit},
version = {0.3.0},
version = {0.4.0},
license = {Apache-2.0}
}
```
Expand Down Expand Up @@ -95,7 +95,9 @@ Stable consumer paths for this release line:
@workit/core/ai
@workit/core/analysis
@workit/core/channel
@workit/core/contracts
@workit/core/diagnostics
@workit/core/fault
@workit/core/ledger
@workit/core/observability
@workit/core/otel
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "workit",
"version": "0.3.0",
"version": "0.4.0",
"private": true,
"description": "WorkIt monorepo.",
"type": "module",
Expand Down
54 changes: 49 additions & 5 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Rules:
| Worker-thread hard boundary | `@workit/core/worker` |
| Diagnostics and snapshots | `@workit/core/diagnostics` |
| OpenTelemetry bridge | `@workit/core/otel` |
| Agent helper contracts | `@workit/core/ai` |
| Agent helper and declared tool authority contracts | `@workit/core/ai` |

### Task Functions And Invocation

Expand Down Expand Up @@ -286,11 +286,13 @@ ownership helpers live behind explicit subpaths.
| Need | Subpath | Boundary |
|---|---|---|
| Build lifecycle receipts from scope events and snapshots | `@workit/core/replay` | audit evidence, not deterministic scheduler replay |
| Persist receipts in caller-owned stores | `@workit/core/ledger` | memory and file receipt ledgers, not a database framework |
| Persist receipts in caller-owned stores | `@workit/core/ledger` | memory, file, and caller-owned SQL receipt ledgers, not a database framework |
| Verify receipts and caller-provided protocol specs | `@workit/core/analysis` | bounded verification over supplied evidence, not whole-program analysis |
| Record explicit terminal activity boundaries | `@workit/core/activity` | completed activity replay, not in-flight workflow recovery |
| Compose lazy, shared, and scope-owned resources | `@workit/core/resources` | cleanup ownership through WorkIt scopes, not automatic resource detection |
| Plan declared retry, hedge, timeout, deadline, series, and parallel time bounds | `@workit/core/time-policy` | conservative planning over declared policies, not wall-clock execution proof |
| Declare cancellable and shielded task intent | `@workit/core/contracts` | compile-time composition contract, not proof of task-body cooperation |
| Run bounded lifecycle fault scenarios | `@workit/core/fault` | in-process evidence harness, not OS/process/network fault injection |

### Time Policy Planning

Expand Down Expand Up @@ -321,6 +323,48 @@ The planner does not execute JavaScript, inspect provider latency, or guarantee
operating-system timer precision. Runtime cancellation still depends on task
bodies and providers observing `ctx.signal`.

### Typed Cancellation Contracts

`@workit/core/contracts` adds typed composition boundaries for codebases that
want task cancellation intent to be explicit at review time.

```ts
import { cancellable, shielded, typedGroup } from "@workit/core/contracts";

const value = await typedGroup(async (task) => {
const child = task(cancellable(async (ctx) => {
ctx.signal.throwIfAborted();
return "value";
}));
const flush = task.shielded(shielded(async () => undefined, { timeout: "250ms" }));
await flush;
return await child;
});
```

This is a TypeScript contract over declared task intent. It does not prove that
an arbitrary task body checks `ctx.signal` or that a provider stops after the
signal is aborted.

### Bounded Fault Evidence

`@workit/core/fault` runs explicit lifecycle scenarios through the real WorkIt
scope engine and returns receipts plus verifier output.

```ts
import { cleanupHang, runFaultScenario } from "@workit/core/fault";

const report = await runFaultScenario(cleanupHang({ cleanupTimeout: "10ms" }));

if (report.status !== "pass") {
throw new Error(JSON.stringify(report.findings));
}
```

The harness is for in-process lifecycle evidence such as cancellation storms,
cleanup timeouts, provider timeouts, and retry exhaustion. It is not an OS
chaos tool, process supervisor, distributed fault injector, or security sandbox.

## Common Use Cases

These are short entry points. The full narrative and benchmark discussion live
Expand Down Expand Up @@ -485,9 +529,9 @@ thresholds, not exact milliseconds.

| Evidence | Current result |
|---|---:|
| Unit tests | 319 passing |
| Unit tests | 354 passing |
| Coverage gate | 100% statements, branches, functions, lines |
| Evidence proof files | 17 passing |
| Evidence proof files | 22 passing |
| Runtime dependencies | 0 |
| Article benchmark suite | 19/19 passing |
| Core group import | 14,175 B minified / 4,835 B gzip |
Expand Down Expand Up @@ -666,7 +710,7 @@ cite the software release you used:
title = {WorkIt: A TypeScript Structured Concurrency Runtime for Node.js Server Runtimes},
year = {2026},
url = {https://github.com/WorkRuntime/workit},
version = {0.3.0},
version = {0.4.0},
license = {Apache-2.0}
}
```
Expand Down
66 changes: 58 additions & 8 deletions packages/core/evidence/claims.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,13 @@
},
{
"id": "LIFE-011",
"title": "resource ownership can be audited across cleanup paths",
"title": "resource cleanup audit records success, failure, and timeout paths",
"class": "lifecycle",
"status": "proven",
"proof": "tests/evidence/lifecycle/resource-audit.mjs",
"command": "npm run test:evidence",
"expectedInvariant": "explicit resource audit instrumentation records acquired/released/pending resources while WorkIt emits cleanup timeout and failure events",
"limitations": "Resource audit entries are explicit caller instrumentation; WorkIt supplies cleanup failure and timeout events through the scope event surface."
"expectedInvariant": "resource audit instrumentation records acquired/released/pending resources while WorkIt emits cleanup timeout and failure events",
"limitations": "Successful resource acquisition and release entries are explicit audit instrumentation in the evidence harness. WorkIt's current first-class event surface exposes cleanup failures and timeouts, not every successful cleanup start/completion."
},
{
"id": "CORR-001",
Expand Down Expand Up @@ -137,6 +137,26 @@
"expectedInvariant": "unbounded retry counts are rejected at the policy boundary",
"limitations": "The cap prevents accidental huge retry policies; application-level retry budgets may be stricter."
},
{
"id": "CORR-006",
"title": "agent authority denies undeclared capability before tool execution",
"class": "correctness",
"status": "proven",
"proof": "tests/evidence/correctness/agent-authority.mjs",
"command": "npm run test:evidence",
"expectedInvariant": "denied declared tool capability emits agent:tool_denied and the tool body is never called",
"limitations": "This is declared tool policy inside runAgent, not operating-system, filesystem, network, or CPU sandboxing."
},
{
"id": "CORR-007",
"title": "receipt analysis detects leaked owned work",
"class": "correctness",
"status": "proven",
"proof": "tests/evidence/correctness/analysis-verifiers.mjs",
"command": "npm run test:evidence",
"expectedInvariant": "a non-terminal receipt with pending tasks fails analysis with leaked_tasks",
"limitations": "The verifier analyzes receipt evidence supplied to it; it does not observe work that was never captured."
},
{
"id": "CORR-009",
"title": "time-policy planner computes retry upper bounds",
Expand All @@ -158,14 +178,14 @@
"limitations": "Deadline feasibility is computed from the supplied clock and policy; applications remain responsible for accurate external deadlines."
},
{
"id": "CORR-007",
"title": "receipt analysis detects leaked owned work",
"id": "CORR-011",
"title": "fault injection harness records lifecycle evidence through real scopes",
"class": "correctness",
"status": "proven",
"proof": "tests/evidence/correctness/analysis-verifiers.mjs",
"proof": "tests/evidence/correctness/fault-injection.mjs",
"command": "npm run test:evidence",
"expectedInvariant": "a non-terminal receipt with pending tasks fails analysis with leaked_tasks",
"limitations": "The verifier analyzes receipt evidence supplied to it; it does not observe work that was never captured."
"expectedInvariant": "bounded cancellation, cleanup timeout, provider timeout, and retry exhaustion scenarios return passing reports with WorkIt receipts",
"limitations": "This is bounded in-process fault injection through explicit scenarios; it is not deterministic replay, SIGKILL recovery, or an operating-system fault injector."
},
{
"id": "CORR-012",
Expand Down Expand Up @@ -227,6 +247,16 @@
"expectedInvariant": "generated nested policies match the recursive model for upper bounds, attempts, parallel work, truncation limits, and typed timeout/deadline warnings",
"limitations": "This is a bounded executable proof over generated nested policy trees. It is not a theorem over arbitrary TypeScript programs, wall-clock scheduling, provider latency, or completed mechanized proof."
},
{
"id": "CORR-023",
"title": "typed cancellation contracts reject undeclared task composition",
"class": "correctness",
"status": "proven",
"proof": "tests/evidence/correctness/typed-cancellation-contracts.mjs",
"command": "npm run test:evidence",
"expectedInvariant": "tsc accepts declared cancellable/shielded composition and rejects plain or misrouted tasks",
"limitations": "This proves an optional compile-time intent contract at the contracts subpath. It does not prove that arbitrary task bodies observe ctx.signal or change the root WorkIt API."
},
{
"id": "SEC-001",
"title": "worker offload rejects remote and executable URL schemes",
Expand Down Expand Up @@ -287,6 +317,26 @@
"expectedInvariant": "a receipt appended by one ledger instance is readable from a new ledger instance",
"limitations": "This proof covers WorkIt's file-backed receipt ledger, not database durability or distributed queue semantics."
},
{
"id": "REL-006",
"title": "SQL receipt ledger adapters preserve idempotency and conflict detection",
"class": "release",
"status": "proven",
"proof": "tests/evidence/release/sql-receipt-ledger.mjs",
"command": "npm run test:evidence",
"expectedInvariant": "SQLite and Postgres ledger ports return the same record for identical appends and reject conflicting receipt content",
"limitations": "The adapters use caller-owned database clients and validate their SQL identifier input; deployment-level durability, replication, backup, and transaction policy remain database responsibilities."
},
{
"id": "REL-007",
"title": "SQLite receipt ledger persists through a real file-backed database",
"class": "release",
"status": "proven",
"proof": "tests/evidence/release/sql-ledger-integration.mjs",
"command": "npm run test:evidence",
"expectedInvariant": "a receipt appended through node:sqlite is readable after database close and reopen, while conflicting content is rejected",
"limitations": "This proof uses node:sqlite when the active Node runtime provides it. Postgres remains an environment-gated integration path because WorkIt does not take a runtime pg dependency."
},
{
"id": "PERF-001",
"title": "article benchmark suite has expected executable coverage",
Expand Down
15 changes: 14 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@workit/core",
"version": "0.3.0",
"version": "0.4.0",
"description": "Structured concurrency runtime for TypeScript: owned async work, cancellation, budgets, retries, timeouts, worker offload, scopes.",
"keywords": [
"structured-concurrency",
Expand Down Expand Up @@ -82,6 +82,11 @@
"import": "./dist/channel/index.js",
"require": "./dist-cjs/channel/index.cjs"
},
"./contracts": {
"types": "./dist/contracts/index.d.ts",
"import": "./dist/contracts/index.js",
"require": "./dist-cjs/contracts/index.cjs"
},
"./observability": {
"types": "./dist/observability/index.d.ts",
"import": "./dist/observability/index.js",
Expand All @@ -92,6 +97,14 @@
"import": "./dist/diagnostics/index.js",
"require": "./dist-cjs/diagnostics/index.cjs"
},
"./fault": {
"types": "./dist/fault/index.d.ts",
"node": {
"import": "./dist/fault/index.js",
"require": "./dist-cjs/fault/index.cjs"
},
"default": "./dist/runtime/unsupported.js"
},
"./ledger": {
"types": "./dist/ledger/index.d.ts",
"node": {
Expand Down
2 changes: 2 additions & 0 deletions packages/core/scripts/build-cjs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ const ENTRIES = [
{ entry: "dist/ai/index.js", outfile: "dist-cjs/ai/index.cjs" },
{ entry: "dist/analysis/index.js", outfile: "dist-cjs/analysis/index.cjs" },
{ entry: "dist/channel/index.js", outfile: "dist-cjs/channel/index.cjs" },
{ entry: "dist/contracts/index.js", outfile: "dist-cjs/contracts/index.cjs" },
{ entry: "dist/diagnostics/index.js", outfile: "dist-cjs/diagnostics/index.cjs" },
{ entry: "dist/fault/index.js", outfile: "dist-cjs/fault/index.cjs" },
{ entry: "dist/ledger/index.js", outfile: "dist-cjs/ledger/index.cjs" },
{ entry: "dist/observability/index.js", outfile: "dist-cjs/observability/index.cjs" },
{ entry: "dist/otel/index.js", outfile: "dist-cjs/otel/index.cjs" },
Expand Down
Loading