@arnilo/prism 0.2.2 → 0.2.4
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.
- package/CHANGELOG.md +10 -0
- package/README.md +3 -3
- package/dist/agent-session.js +1 -1
- package/dist/cache-telemetry.js +1 -1
- package/dist/contracts-core.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pinned-fetch.js +0 -1
- package/dist/skill-disclosure.js +1 -1
- package/dist/skill-load.js +0 -1
- package/dist/tool-effects.js +1 -1
- package/dist/tool-result-fold.js +2 -2
- package/docs/0.1.0-readiness.md +15 -13
- package/docs/index.md +2 -2
- package/docs/migration.md +8 -0
- package/docs/release-and-install.md +110 -9
- package/package.json +10 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.4] - 2026-08-14
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- **Release 0.2.4 (plan 024)** is the package-documentation-and-compatibility-truth cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.4: delta is the version literal only). Truth remediation, no runtime contract change: (1) **umbrella wording matches manifests** — `@arnilo/prism-providers` states 11 of 14 first-party provider adapters (Azure/Bedrock/Vertex are added separately by `@arnilo/prism-all`; its install list was corrected from 9 to the full 11 — alibaba and ollama were missing) and `@arnilo/prism-all` states 20 direct / 43 transitive packages with the complete omission set (document-reader, OpenAPI tools, NATS, Caveman, Ponytail); membership unchanged in 0.2.x (§0.3.0 owns expansion). (2) **manifest-derived package truth** — dependency-free `scripts/package-truth.mjs` → `scripts/package-truth.json` becomes the single source for counts (50/49/14/9/26), provider membership, umbrella closures, and profile closures; the count/tarball/current-line docs literals were regenerated from it; `scripts/phase24-truth.test.mjs` asserts generator reproducibility, committed-artifact equality, count/closure correctness, and fail-closed behavior on malformed manifests and unmatched workspace globs. (3) **peer-version policy Decision A** — exact `@arnilo/prism: <current>` pins remain through 0.2.x with the atomic-upgrade rule (all `@arnilo/prism-*` packages move at the same version; partial upgrades are unsupported and fail clearly with npm ERESOLVE); the range widens to `^1.0.0` at the 1.x stable release; documented in `docs/release-and-install.md` + `docs/migration.md`. (4) **current-line truth** — `docs/0.1.0-readiness.md` and `docs/index.md` current-line blocks refreshed to the 0.2.x line, with 0.1.7 recorded as the terminal 0.1.x baseline and the 0.1.1/0.1.0 tables demoted to historical record. Release graph stays **50** publishable manifests at exact **0.2.4**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.3: **compatible, no migration** (no persisted-shape change). Exit gate green (core + script gates incl. `phase24-truth` 12 tests, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.4 — version literal only, protected Postgres durable conformance evidence per the release skip manifest, release-evidence manifest with zero blocked surfaces, evidence in `scripts/phase24-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.4 publish handoff` — signed `v0.2.4` tag + npm OIDC).
|
|
7
|
+
|
|
8
|
+
## [0.2.3] - 2026-08-14
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **Release 0.2.3 (plan 023)** is the build-coverage-and-release-evidence-integrity cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.3: delta is the version literal only — no export changes; baselines regenerated with `--update-baseline`, no `--allow-break`; freeze manifest `scripts/phase23-freeze-manifest.json` records per-task evidence tokens). Four tooling/evidence fixes, no runtime contract change: (1) **build serialization** (`build-serialization`, core tooling) — dependency-free `scripts/with-build-lock.mjs` holds one O_EXCL lockfile at `node_modules/.prism-build.lock` (pid + startedAt, read-back verified, stale-PID reclaim via `process.kill(pid, 0)`, 100 ms backoff to env-overridable `PRISM_BUILD_LOCK_TIMEOUT_MS` default 120 s, fail-closed exit 1) around every emit/test leaf (root `build:core`, both `node --test` segments, `test:coverage` leaves, coverage summary, all 43 workspace build/test/`test:postgres` scripts) so concurrent compilers and importers can never observe a partially emitted `dist/` — the 2026-08-12 review defect that 0.1.1's destructive-clean removal did not close; the lock is never held by orchestrator scripts, `PRISM_BUILD_LOCK_HELD=1` prevents accidental nesting, and the direct-`tsc` caveat is documented in `docs/release-and-install.md`. (2) **corrected workspace coverage denominators** (`coverage-denominators`, `scripts/coverage-summary.mjs`) — workspace coverage runs now pass package-local `--test-coverage-include=dist/**` so imported core `dist/` no longer pollutes package rows (`mcp` 45.47→90.25, `rag` 19.70→94.82, `memory` 20.37→72.00, `session-store-nats` 16.04→93.69, `enterprise-postgres` 21.93→43.26; `session-store-postgres` stays 22.89 as the protected durable-leg proof); the 60/70/75 core gate is unchanged; evidence-based per-package line thresholds in `scripts/coverage-thresholds.json` (freeze-run percentages minus 3 pp) with `protectedException` entries for the env-gated durable-leg packages (`session-store-postgres`, `enterprise-postgres`, `memory`, `session-store-nats`) shown separately; the machine-readable `scripts/coverage-summary.json` artifact records per-package lines/branches/functions/denominator files/threshold/pass-fail and the gate exits 1 on any non-protected below-threshold package. (3) **machine-auditable release skip manifest** (`skip-manifest`, `scripts/release-skip-manifest.mjs` → `scripts/release-evidence.json`) — every release surface (core `npm test`, each workspace suite, threat suites, `test:postgres` durable conformance, provider live legs, NATS real legs, the four live canaries) records `pass`/`skip`/`blocked`/`protected` with reason and required env names only (never secrets); the 33 protected/live skips are named; a required surface with absent evidence records `blocked` and `scripts/release.mjs` gate fails closed (`checkReleaseEvidence`) — missing credentials/services can never convert into a green release; the artifact is CI-retained and gitignored. (4) **stabilized quality gates** (`quality-gates`) — `biome.json` migrated to the 2.x canonical `linter.rules.preset: "recommended"` (deprecated key removed) and all 97 lint diagnostics resolved to zero (safe + reviewed `--unsafe` fixes across 108 files, 10 hand-removed dead `_`-renamed variables, 5 justified `biome-ignore` comments for shell-interpolation probes/verbatim fixtures/grep targets); the racy 150 ms MCP bridge timing assertion became a deterministic awaited-outcome barrier with a test-level timeout, and kept load-sensitive guards carry documented `ponytail:` ceilings; `npm run lint` writes machine-readable `scripts/lint-report.sarif` and `npm run sweep:unused` writes `scripts/unused-report.json`, both retained by the release workflow. New regression surface: `scripts/phase23-build-race.test.mjs` (8 lock/stress tests incl. synthetic partial-`dist` sensitivity, stale-lock reclaim, live-lock fail-closed), `scripts/phase23-coverage.test.mjs` (4 tests: include-filter + core-gate greps, thresholds JSON validation, real-artifact denominator proof, sabotaged fail-closed run), `scripts/phase23-skip-manifest.test.mjs` (6 tests: blocked-not-skip, protected-named with the frozen 33-skip floor, live-canary-not-pass, unexplained-skip-rejected, no-secret, wiring), `scripts/phase23-quality-gates.test.mjs` (5 tests: lint clean, preset config, timing quarantine, biome-ignore reasons, machine-readable reports), and `scripts/phase23-security.test.mjs` (3 tests: matrix item 4 concurrent emit+public-entry importer, matrix item 12 coverage denominator + protected rows, gate accounting — built public entrypoints, wired into `security:threat-suites`) plus the packed plain-JS `security23.mjs` consumer in install-smoke. Release graph stays **50** publishable manifests at exact **0.2.3**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.2: **compatible, no migration** (no persisted-shape change). Exit gate green (core + script gates incl. phase21-freeze done-phase + all phase23 suites, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.3, protected Postgres durable conformance evidence, release-evidence manifest with zero blocked surfaces, evidence in `scripts/phase23-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.3 publish handoff` — signed `v0.2.3` tag + npm OIDC).
|
|
12
|
+
|
|
3
13
|
## [0.2.2] - 2026-08-13
|
|
4
14
|
|
|
5
15
|
### Changed
|
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ npm install @arnilo/prism @arnilo/prism-provider-openai # core + one provider
|
|
|
55
55
|
npm install @arnilo/prism-base # core + compaction + validation
|
|
56
56
|
npm install @arnilo/prism-code @arnilo/prism-provider-openai # coding-agent profile
|
|
57
57
|
npm install @arnilo/prism-sdk @arnilo/prism-provider-openai # application profile
|
|
58
|
-
npm install @arnilo/prism-all #
|
|
58
|
+
npm install @arnilo/prism-all # broad umbrella (20 direct / 43 transitive packages)
|
|
59
59
|
npm install @arnilo/prism-server @arnilo/prism-workflows # optional Web API boundary
|
|
60
60
|
npm install @arnilo/prism-supervisor # optional local delegation + A2A 1.0
|
|
61
61
|
npm install @arnilo/prism-web-tools # optional bounded Brave/Exa/Firecrawl research
|
|
@@ -177,12 +177,12 @@ printf '{"id":"1","command":"prompt","params":{"input":"Hi"}}\n' \
|
|
|
177
177
|
| `@arnilo/prism-credentials-node` | encrypted-file and keychain credentials |
|
|
178
178
|
| `@arnilo/prism-session-store-sqlite` | SQLite persistence/checkpoints/leases/owned run feedback |
|
|
179
179
|
| `@arnilo/prism-session-store-postgres` | PostgreSQL persistence/checkpoints/leases/owned run feedback |
|
|
180
|
-
| `@arnilo/prism-providers` | family:
|
|
180
|
+
| `@arnilo/prism-providers` | family: 11 of 14 first-party provider adapters (omits Azure, Bedrock, Vertex, which `prism-all` adds separately), including AI SDK interoperability |
|
|
181
181
|
| `@arnilo/prism-compaction` | family: both compaction strategies |
|
|
182
182
|
| `@arnilo/prism-base` | profile: core + compaction + JSON Schema validation |
|
|
183
183
|
| `@arnilo/prism-code` | profile: base + coding tools/security + MCP |
|
|
184
184
|
| `@arnilo/prism-sdk` | profile: base + workflows + MCP + credentials + OpenTelemetry |
|
|
185
|
-
| `@arnilo/prism-all` |
|
|
185
|
+
| `@arnilo/prism-all` | broad umbrella: 20 first-party packages (43 transitive) across runtime, capability, provider, and persistence — omits document-reader, OpenAPI tools, NATS, Caveman, and Ponytail |
|
|
186
186
|
|
|
187
187
|
## Scripts
|
|
188
188
|
|
package/dist/agent-session.js
CHANGED
|
@@ -500,7 +500,7 @@ export class RuntimeAgentSession {
|
|
|
500
500
|
if (calls.length > 0)
|
|
501
501
|
limits.charge("maxToolRounds");
|
|
502
502
|
const durable = this.activeDurable;
|
|
503
|
-
if (!durable
|
|
503
|
+
if (!durable?.options.interruptBeforeTool || calls.length === 0)
|
|
504
504
|
return;
|
|
505
505
|
// Round-level gate: record one pending decision per uncovered gated call. Ungated
|
|
506
506
|
// and sticky-allowed calls still dispatch; the suspension fires at the next provider
|
package/dist/cache-telemetry.js
CHANGED
|
@@ -17,7 +17,7 @@ function validateTokens(name, value) {
|
|
|
17
17
|
throw new CacheTelemetryError(`${name} must be a non-negative safe integer, got ${value}`);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
function sampleFor(
|
|
20
|
+
function sampleFor(_usage, model) {
|
|
21
21
|
if (model)
|
|
22
22
|
return { provider: model.provider, model: model.model };
|
|
23
23
|
// Provider-only aggregation: no model supplied, attribute to the unknown bucket.
|
package/dist/contracts-core.d.ts
CHANGED
|
@@ -1213,7 +1213,7 @@ export interface ProductionPersistenceStore {
|
|
|
1213
1213
|
readonly expectedVersion?: number;
|
|
1214
1214
|
}): Promise<{
|
|
1215
1215
|
readonly version: number;
|
|
1216
|
-
} |
|
|
1216
|
+
} | undefined>;
|
|
1217
1217
|
/** DB-friendly branch read (mirrors `SessionStore.readBranchPath`): one ancestor-chain
|
|
1218
1218
|
* query instead of `queryEntries({ sessionId })` + in-memory walk. Optional. */
|
|
1219
1219
|
readBranchPath?(query: SessionBranchRead): Promise<PersistencePage<SessionEntry>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -109,5 +109,5 @@ export { createToolParameterValidator, createToolRegistry, dispatchToolCall, fil
|
|
|
109
109
|
export type { ResolvedUseCaseModel, ResolveUseCaseModelInput, UseCaseModelBinding, } from "./use-case-model.js";
|
|
110
110
|
export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
|
|
111
111
|
export declare const name = "prism";
|
|
112
|
-
export declare const version = "0.2.
|
|
112
|
+
export declare const version = "0.2.4";
|
|
113
113
|
export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
|
package/dist/index.js
CHANGED
|
@@ -60,6 +60,6 @@ export { DEFAULT_TOOL_RESULT_FOLD_MAX_SUMMARY_BYTES, DEFAULT_TOOL_RESULT_FOLD_MI
|
|
|
60
60
|
export { createToolParameterValidator, createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
|
|
61
61
|
export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
|
|
62
62
|
export const name = "prism";
|
|
63
|
-
export const version = "0.2.
|
|
63
|
+
export const version = "0.2.4";
|
|
64
64
|
export const description = "Agent harness for AI providers, agents, sessions, and tools.";
|
|
65
65
|
//# sourceMappingURL=index.js.map
|
package/dist/pinned-fetch.js
CHANGED
|
@@ -23,7 +23,6 @@ import { assertSsrfAllowedUrl, MediaContentError } from "./content.js";
|
|
|
23
23
|
/** One DNS-pinned, redirect-free, byte-bounded fetch. See module comment. */
|
|
24
24
|
export async function pinnedFetch(url, init, options) {
|
|
25
25
|
const errorPrefix = options?.errorPrefix ?? "Request";
|
|
26
|
-
const hostnameErrorPrefix = options?.hostnameErrorPrefix ?? errorPrefix;
|
|
27
26
|
if (url.username || url.password)
|
|
28
27
|
throw new MediaContentError("ssrf_denied", `${errorPrefix} URL must not embed credentials`);
|
|
29
28
|
if (url.hash)
|
package/dist/skill-disclosure.js
CHANGED
|
@@ -96,6 +96,6 @@ function truncateUtf8Bytes(text, maxBytes) {
|
|
|
96
96
|
let end = Math.max(0, maxBytes - suffix.length);
|
|
97
97
|
while (end > 0 && (encoded[end] & 0xc0) === 0x80)
|
|
98
98
|
end--;
|
|
99
|
-
return new TextDecoder().decode(encoded.slice(0, end))
|
|
99
|
+
return `${new TextDecoder().decode(encoded.slice(0, end))}…`;
|
|
100
100
|
}
|
|
101
101
|
//# sourceMappingURL=skill-disclosure.js.map
|
package/dist/skill-load.js
CHANGED
|
@@ -64,7 +64,6 @@ export function applyRestoredSkillBodies(skills, bodies) {
|
|
|
64
64
|
validateLoadedSkillBodies(bodies);
|
|
65
65
|
if (bodies.length === 0)
|
|
66
66
|
return skills;
|
|
67
|
-
const byName = new Map(skills.map((skill) => [skill.name, skill]));
|
|
68
67
|
const out = skills.map((skill) => {
|
|
69
68
|
const body = bodies.find((entry) => entry.name === skill.name);
|
|
70
69
|
return body ? { ...skill, instructions: body.instructions } : skill;
|
package/dist/tool-effects.js
CHANGED
|
@@ -130,7 +130,7 @@ export function createMemoryToolEffectStore(options = {}) {
|
|
|
130
130
|
},
|
|
131
131
|
async resolveUnknown(input) {
|
|
132
132
|
const record = current(input);
|
|
133
|
-
if (
|
|
133
|
+
if (record?.status !== "unknown" || record.version !== input.expectedVersion)
|
|
134
134
|
throw conflict();
|
|
135
135
|
const result = input.result === undefined ? undefined : validateResult(input.result, input);
|
|
136
136
|
const resultRef = input.resultRef === undefined ? undefined : validateReference(input.resultRef);
|
package/dist/tool-result-fold.js
CHANGED
|
@@ -56,7 +56,7 @@ async function foldToolResultMessage(message, options, context) {
|
|
|
56
56
|
if (message.role !== "tool")
|
|
57
57
|
return message;
|
|
58
58
|
const block = message.content.find((part) => part.type === "tool_result");
|
|
59
|
-
if (
|
|
59
|
+
if (block?.type !== "tool_result")
|
|
60
60
|
return message;
|
|
61
61
|
const text = toolResultText(block.result, block.error, message.content);
|
|
62
62
|
const folded = await maybeFold({
|
|
@@ -141,7 +141,7 @@ function capSummaryBytes(summary, maxBytes) {
|
|
|
141
141
|
let end = Math.max(0, maxBytes - suffix.length);
|
|
142
142
|
while (end > 0 && (encoded[end] & 0xc0) === 0x80)
|
|
143
143
|
end--;
|
|
144
|
-
return new TextDecoder().decode(encoded.slice(0, end))
|
|
144
|
+
return `${new TextDecoder().decode(encoded.slice(0, end))}…`;
|
|
145
145
|
}
|
|
146
146
|
function inferToolResultTurns(history) {
|
|
147
147
|
const turns = new Array(history.length).fill(1);
|
package/docs/0.1.0-readiness.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0.1.0 / 1.0 Readiness Gates
|
|
2
2
|
|
|
3
|
-
Status: **0.
|
|
3
|
+
Status: **0.2.4** is the current release line (the 0.2.x review-remediation line: fail-closed runtime/sandbox security, provider completion and outbound trust boundaries, concurrent-state/durability integrity, build/coverage/release-evidence integrity, package/documentation/compatibility truth); **0.1.7** was the terminal 0.1.x baseline; **1.0** readiness remains operator-gated, not automatic.
|
|
4
4
|
|
|
5
5
|
This page distills runnable readiness gates into one command-per-gate table.
|
|
6
6
|
The **Last evidence** column records the 0.1.0-tree snapshot (plan 012 Tasks
|
|
@@ -17,22 +17,24 @@ Evidence trail: [`docs/_evidence/review-coverage-2026-07-26-phase-11.md`](./_evi
|
|
|
17
17
|
The per-phase review-coverage evidence archive lives in [`docs/_evidence/`](./_evidence/)
|
|
18
18
|
(plans 067–079, releases 0.0.4–0.0.16; tarball-excluded, kept in-repo for audit).
|
|
19
19
|
Historical release lines (0.0.16 floor → 0.0.27 Phase 10 ACP interop → 0.1.0)
|
|
20
|
-
keep their per-phase evidence in the pages above; this page records the 0.
|
|
21
|
-
snapshot (plan
|
|
20
|
+
keep their per-phase evidence in the pages above; this page records the 0.2.4
|
|
21
|
+
snapshot (plan 024) with the 0.1.x tables below as the historical record.
|
|
22
22
|
|
|
23
|
-
## Current line (0.
|
|
23
|
+
## Current line (0.2.4)
|
|
24
24
|
|
|
25
25
|
| Item | Status |
|
|
26
26
|
|---|---|
|
|
27
|
-
| Published graph | **
|
|
28
|
-
|
|
|
29
|
-
| Upgrade path | `docs/migration.md` `0.
|
|
30
|
-
| Compat promise | Additive-only vs the frozen 0.1.x contract; `scripts/compat-baseline` regenerated at 0.
|
|
31
|
-
| Security policy | `npm audit --audit-level=moderate` 0 at 0.
|
|
32
|
-
| Docs freeze | tripwires green including the manifest-count tripwire and the plan
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
##
|
|
27
|
+
| Published graph | **50** publishable manifests at exact **0.2.4** (root + 49 workspace packages: 14 provider adapters + 9 `prism-*` family/profile + 26 capability; generated by `node scripts/package-truth.mjs` → `scripts/package-truth.json`) |
|
|
28
|
+
| Current-line cut | The 0.2.x review-remediation line, additive-only vs the frozen 0.1.x contract: 0.2.0 fail-closed runtime/sandbox security (durable-resume decision validation, work-tool env isolation, explicit sandbox capabilities), 0.2.1 provider completion + outbound trust boundaries (strict stream completion, bounded success bodies, DNS-pinned OIDC/OPA fetches), 0.2.2 concurrent-state/durability integrity (model-budget reservation, conversation-metadata CAS, single-consumer EventMultiplexer, NATS durable identity), 0.2.3 build/coverage/release-evidence integrity (build single-flight, corrected coverage denominators, release skip manifest, stabilized quality gates), 0.2.4 package/documentation/compatibility truth (umbrella wording matches manifests, manifest-derived package truth, peer-version policy Decision A, current-line truth) |
|
|
29
|
+
| Upgrade path | `docs/migration.md` `0.2.3 → 0.2.4` (version literal + peer-version policy only, no migration); store-compatible throughout 0.2.x |
|
|
30
|
+
| Compat promise | Additive-only vs the frozen 0.1.x contract; `scripts/compat-baseline` regenerated at 0.2.4 (version-literal delta only), zero breaking deltas |
|
|
31
|
+
| Security policy | `npm audit --audit-level=moderate` 0 at 0.2.4; threat-suites legs (phase8–11 + phase20–24) green; protected Postgres/NATS/live-canary legs operator-gated |
|
|
32
|
+
| Docs freeze | tripwires green including the canonical manifest-count tripwire (50/49/14/9/26) and the plan 024 package-truth tests (generator reproducibility + artifact equality + closure asserts + derived docs truth) |
|
|
33
|
+
| 0.1.x line | **0.1.7** (plan 019) is the terminal 0.1.x baseline; the 0.1.1 table below keeps the plan 013 snapshot; the 0.1.0 table keeps the plan 012 snapshot; the **0.0.16** values remain the historical network-free floor |
|
|
34
|
+
|
|
35
|
+
## Previous line (0.1.1)
|
|
36
|
+
|
|
37
|
+
## Previous line (0.1.0)
|
|
36
38
|
|
|
37
39
|
| Item | Status |
|
|
38
40
|
|---|---|
|
package/docs/index.md
CHANGED
|
@@ -129,7 +129,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
129
129
|
- [Ponytail behavior integration](ponytail.md): optional `@arnilo/prism-ponytail` — upstream Ponytail skills/commands, `ponytail-mode` injector, session `ponytail-mode` persistence; resolves peer `@dietrichgebert/ponytail` or `upstreamPath`; opt-in (not in code/sdk profiles).
|
|
130
130
|
|
|
131
131
|
## Release and install
|
|
132
|
-
- [Release and install](release-and-install.md): current **0.2.
|
|
133
|
-
- [0.1.0 / 1.0 readiness gates](0.1.0-readiness.md): command-per-gate 1.0 readiness table — frozen API surface + compat gate, migration/docs tripwires, budget table, live-suite matrix, security matrix, current-line status (**0.
|
|
132
|
+
- [Release and install](release-and-install.md): current **0.2.4** 50-package graph (root + 49 workspace packages) — plan 024 the package-documentation-and-compatibility-truth cut: **umbrella wording matches manifests** (`@arnilo/prism-providers` installs 11 of 14 provider adapters — Azure/Bedrock/Vertex are added separately by `prism-all`; `prism-all` installs 20 direct / 43 transitive packages and omits document-reader, OpenAPI tools, NATS, Caveman, Ponytail; membership unchanged in 0.2.x), **manifest-derived package truth** (`scripts/package-truth.mjs` → `scripts/package-truth.json` is the single source for counts, provider membership, and closures; docs literals regenerate from it and drift fails the gates), **peer-version policy Decision A** (exact `@arnilo/prism: 0.2.4` pins, atomic-upgrade rule, ERESOLVE refusal for partial upgrades, `^1.0.0` widening at 1.x), and **current-line truth** (`docs/0.1.0-readiness.md` at the 0.2.x line with 0.1.7 as the terminal 0.1.x baseline); no runtime contract delta (compat gate at 0.2.4: version literal only), no migration; then plan 023 the build-coverage-and-release-evidence-integrity cut: **build serialization** (dependency-free `scripts/with-build-lock.mjs` — one O_EXCL lockfile at `node_modules/.prism-build.lock` serializing every emit/test leaf so concurrent compilers can never expose a partial live `dist/`, stale-PID reclaim, env-overridable `PRISM_BUILD_LOCK_TIMEOUT_MS`, fail-closed; documented direct-`tsc` caveat), **corrected workspace coverage denominators** (package-local `--test-coverage-include=dist/**` so imported core `dist` no longer pollutes workspace rows — `mcp` 45.47→90.25, `rag` 19.70→94.82; evidence-based per-package thresholds in `scripts/coverage-thresholds.json` with `protectedException` for durable-leg packages shown separately, machine-readable `scripts/coverage-summary.json`), **machine-auditable release skip manifest** (`scripts/release-skip-manifest.mjs` → `scripts/release-evidence.json`: every surface recorded `pass`/`skip`/`blocked`/`protected` with reason and required env; the 33 protected/live skips named; a required surface without evidence records `blocked` and fails the release gate fail-closed — missing credentials/services can never convert into a green release), and **stabilized quality gates** (Biome 2.x `preset` config migration with zero lint diagnostics, the racy 150ms MCP bridge timing assert replaced by a deterministic barrier, load-sensitive guards carry documented `ponytail:` ceilings, machine-readable `lint-report.sarif` + `unused-report.json` retained by CI); no runtime contract delta (compat gate at 0.2.3: version literal only), no migration; then plan 022 the concurrent-state-and-durability-integrity cut: atomic model-budget reservation (`ModelRouterStateStore.reserveBudget`/`commitBudget`/`releaseBudget` with fencing tokens, `reservationTtlMs` expiry and unknown-usage reconciliation, rate/budget key-map caps with LRU eviction that never drops a held reservation), atomic conversation metadata (`SessionRecord.version` + `appendSession` `expectedVersion` CAS across Postgres/SQLite — create-only `0`, exact-version `N>0`, legacy last-write-wins when omitted; `SessionMetadataConflictError` `metadata_conflict` with versions only, HTTP 409; concurrent create/branch/archive single-statement with branch caps inside the CAS, archive wins, deleted rows never resurrect), single-consumer `EventMultiplexer` (`EventMultiplexerError` `ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER` instead of silent queue sharing), restart-stable NATS durable consumer identity (`prism_<hmac16>` with no random suffix — crash-resumed subscribe continues from the last ack, orphaned 0.2.1 consumers reclaimed on clean stop), and bounded non-durable active-run registries (sweep + fail-closed 512 cap `ERR_PRISM_WORKFLOW_RUN_REGISTRY_OVERFLOW`); new regression surface `scripts/phase22-security.test.mjs` (4 blockers + gate accounting over built public entrypoints) + packed plain-JS `security22.mjs` consumer + the `@arnilo/prism/testing/state-concurrency-conformance` harness (7 probes across memory/Postgres/SQLite/NATS legs, no timing-only sleeps) + the `scripts/phase22-conformance.test.mjs` gate; additive-only compat (new exports only, no removals); forward-only migrations 008 (`prism_sessions.version`) and 003 (`prism_model_router_budgets.reservations`); migration `0.2.1 → 0.2.2`; then plan 021 the provider-completion-and-outbound-trust-boundaries cut: strict stream completion is the shared OpenAI-compatible default (truncated streams fail `incomplete_delta`, explicit `strictCompletion: false` opt-out), bounded success bodies via `readBoundedResponseJson` on all discovery/quota/embeddings/upload/OAuth JSON endpoints (65,536-byte ceiling, depth/property/shape caps), DNS-pinned OIDC JWKS/OPA/content fetches through the core `pinnedFetch` primitive with 3xx redirects rejected outright (private/metadata answers fail closed `ssrf_denied`), shared bounded OAuth device/token polling (`pollDeviceCodeToken`) across provider-openai and credentials-node, and the four edge fixes (Azure/Vertex credential-once, Bedrock duplicate-case/repeated-query SigV4 canonicalization, OpenAI upload failed-DELETE retention, cache `__overflow__` tokens-only); public-entrypoint threat-suite `scripts/phase21-security.test.mjs` + packed plain-JS consumer; additive-only compat (MCP transport helpers re-exported from core, no removals); migration `0.2.0 → 0.2.1`; then plan 020 the fail-closed runtime-and-sandbox-security cut on the 0.2.x review-remediation line: durable-resume decision validation in core (`assertValidAgentRunResume` — unknown decisions/malformed batches fail closed with `ERR_PRISM_DECISION_*` before any state claim, checkpoint write, or tool execution; server parser remains defense in depth), isolated work-tool subprocess environments (`@arnilo/prism-work-tools` — fixed base allow-list + explicit env + forced HOME/telemetry + late-bound per-identity tokens, 64-name/64-KiB caps, absolute binary/configDir, linear output capture), and explicit sandbox capabilities (`@arnilo/prism-coding-security` — `SandboxAdapter.capabilities` with omission-is-false fail-closed resolution, `SandboxCodingComposition.capabilities` from verified wiring, `containmentClaim` deprecated as the conservative projection; Docker reports only verified controls, native reports filesystem/process/privilege `false`); public-entrypoint security conformance (`scripts/phase20-security.test.mjs`, wired into `security:threat-suites`), packed plain-JS consumer regressions, and the sandbox-browser workflow's fail-loud Docker/native capability evidence gate — 0.2.0 never ships while a blocker is skipped; migration and rollback notes in `docs/migration.md` `0.1.7 → 0.2.0`, store-compatible with 0.1.7 in both directions; 0.1.7 was the performance-and-DX patch — dependency-free `createCacheTelemetry()` per-provider/model cache hit/miss aggregator (bounded cardinality with `__overflow__`, token counters/rates only, host-activated), host-configurable `ModelRouterSelectionPolicy` on `createModelRouter` with the reference `createCostLatencySelection` (ModelCost rank then in-memory latency EMA, default ordered behavior byte-identical), `prism providers add <name>` OpenAI-compatible provider scaffold (manifest/provider/models/cache/conformance test/docs stub, npm-name + traversal + symlink-escape validation, placeholders only), and the async `AgUiProjection` verification closeout (plan 009 Task 15 evidence recorded, no new code); plan 017 the documented breaking cut — deprecated-option removal with `docs/migration.md` `0.1.4 → 0.1.5` section and reviewed compat-baseline regeneration via `--allow-break` then `--update-baseline`: the inert provider request knobs, `RunOptions.maxToolRounds`, observational-memory flat settings keys + top-level worker aliases, `ReadToolOptions.autoResizeImages`, `INIT_PROVIDERS`; all removals fail closed naming their replacement; plan 016 internal god-module split — `agents.ts`/`contracts.ts` reorganized behind barrel re-exports with a byte-identical public entry surface, measured tree-shaking improvement in `scripts/phase16-baseline.json`, and additive `@arnilo/prism-browser` Chrome DevTools Protocol capabilities — `browser_evaluate`/`browser_observe` and `block_urls`/`unblock_urls`/`throttle`/`emulate` act actions; plan 015 dead-code and deprecation hygiene on the frozen 0.1.x line — parameterized benchmark runner `scripts/benchmark.mjs` absorbing the per-version runners, archived review-coverage evidence in `docs/_evidence/`, non-blocking unused-code sweep `npm run sweep:unused`, opt-in checkpoint persistence for loaded-skill names and read-path sets; plan 014 Alibaba provider enrichment — embeddings, video input, verified compatible-mode surface decision table; plan 013 post-release hardening — build single-flight, MCP SSE relay test, combined coverage summary, canonical manifest-count narrative, ACP modes/config persistence guidance; Phase 12 release-candidate hardening; plan 012 — freeze manifest, compatibility matrix, upgrade matrix, packed-install e2e journeys, restart-recovery evidence, capacity envelopes, security policy), exact-peer/install/tarball rules, deterministic resumable publication and publish dry-run, frozen 0.1.x compatibility and support matrix (Node/PostgreSQL/platform/provider/protocol pins and unsupported combinations, machine-checked against `scripts/phase12-freeze-manifest.json`), protected PostgreSQL gate, pinned supply-chain gates, offline tests, the 0.0.15 provider/AI-SDK/RAG/memory protected live-canary matrix, and sandbox-browser Docker/Playwright gates.
|
|
133
|
+
- [0.1.0 / 1.0 readiness gates](0.1.0-readiness.md): command-per-gate 1.0 readiness table — frozen API surface + compat gate, migration/docs tripwires, budget table, live-suite matrix, security matrix, current-line status (**0.2.4** current line; 0.1.7 terminal 0.1.x baseline), signed-publication/live-canary prerequisites for 1.0, and Phase 12 demand-evidence entry criteria.
|
|
134
134
|
- [Review coverage archive](_evidence/): per-phase evidence freezes (plans 067–079, releases 0.0.4–0.0.16) — traceability matrices, provider validation, capability/primitive/limit matrices, benchmark budgets, and artifact-diet findings; tarball-excluded, kept in-repo for audit.
|
|
135
135
|
|
package/docs/migration.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Migration guide
|
|
2
2
|
|
|
3
|
+
## 0.2.3 → 0.2.4 package, documentation, and compatibility truth (plan 024)
|
|
4
|
+
|
|
5
|
+
Release **0.2.4** (plan 024) is the package-documentation-and-compatibility-truth cut: umbrella wording now states the manifest closures (`@arnilo/prism-providers` = 11 of 14 first-party provider adapters, omitting Azure/Bedrock/Vertex; `@arnilo/prism-all` = 20 direct / 43 transitive first-party packages with the named omission set), and `scripts/package-truth.json` (generated by `scripts/package-truth.mjs`) is the manifest-derived single source for counts, provider membership, umbrella closures, and profile closures. **Peer-version policy (Decision A — exact pins):** every code package peers the bare exact `@arnilo/prism@0.2.4` version (no range, no `*`); all `@arnilo/prism-*` packages move at the same version (**atomic-upgrade rule** — a partial upgrade fails clearly at install time with npm `ERESOLVE` naming the conflicting peer); the range widens to `^1.0.0` at the 1.x stable release; third-party `@arnilo/prism-*` adapters peer on the documented exact current version (full policy in the release-and-install Extension notes). **No runtime code path, persisted shape, event schema, default, or exported declaration changed** (the plain reviewed compat gate at 0.2.4 shows the version literal only). Store compatibility with 0.2.3: **compatible in both directions** — no migration step; rollback = restore the 0.2.3 manifests/tag.
|
|
6
|
+
|
|
7
|
+
## 0.2.2 → 0.2.3 build, coverage, and release evidence integrity (no migration)
|
|
8
|
+
|
|
9
|
+
Release **0.2.3** (plan 023) is a **tooling-and-evidence-only cut**: build serialization (`scripts/with-build-lock.mjs` — one `O_EXCL` lockfile serializing every emit/test leaf so concurrent compilers never expose a partial live `dist/`), corrected workspace coverage denominators (package-local `--test-coverage-include=dist/**`, evidence-based per-package thresholds with `protectedException` durable-leg rows), the machine-auditable release skip manifest (`scripts/release-skip-manifest.mjs` → `scripts/release-evidence.json` with `pass`/`skip`/`blocked`/`protected` states; required surfaces without evidence record `blocked` and fail the release gate), and stabilized quality gates (Biome 2.x `preset` config migration with zero lint diagnostics, deterministic timing-assertion barriers, machine-readable `lint-report.sarif` + `unused-report.json`). **No runtime code path, persisted shape, event schema, default, or exported declaration changed** (the plain compat gate at 0.2.3 shows the version literal only). Store compatibility with 0.2.2: **compatible in both directions** — no migration step; rollback = restore the 0.2.2 manifests/tag (stores never change; rollback reopens only the partial-`dist` race and the polluted coverage denominator, both CI/tooling defects, never data defects).
|
|
10
|
+
|
|
3
11
|
## 0.2.1 → 0.2.2 concurrent state and durability integrity (plan 022)
|
|
4
12
|
|
|
5
13
|
Release **0.2.2** (plan 022) makes four concurrency/durability boundaries atomic or fail-loud. The API surface is **additive-only** (plain reviewed compat gate at 0.2.2: expected deltas are the version literal, `ModelRouterStateStore.reserveBudget`/`commitBudget`/`releaseBudget` plus `ModelRouterReservation`/`ModelRouterBudgets.reservationTtlMs`/`ModelRouterLimits.maxRateKeys`/`maxBudgetKeys` (memory + Postgres), `SessionRecord.version` with `appendSession` `expectedVersion`, `EventMultiplexerError` with code `ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER`, and the `@arnilo/prism/testing/state-concurrency-conformance` subpath; no removal, no `--allow-break`). Three of the four changes tighten behavior where 0.2.1 silently accepted a race — concurrent hosts may now see an explicit conflict where 0.2.1 lost an update or oversubscribed a budget:
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
Prism is published as **50 publishable manifests**: the root `@arnilo/prism` core package plus **49 workspace packages** — 14 provider adapters, 9 `prism-*` family/profile packages, and 26 capability packages. (
|
|
5
|
+
Prism is published as **50 publishable manifests**: the root `@arnilo/prism` core package plus **49 workspace packages** — 14 provider adapters, 9 `prism-*` family/profile packages, and 26 capability packages. (Generated by `node scripts/package-truth.mjs` → `scripts/package-truth.json` — the manifest-derived single source for counts, provider membership, umbrella closures, and profile closures.) The 50th manifest is the 0.1.6 plan 018 optional `@arnilo/prism-document-reader` package (bounded PDF/Office literal-text extraction for the coding read tool; ships only because its `doc-reader` closeout is demanded — a deferred closeout keeps the graph at 49). This page describes how they are packed, what each tarball contains, how to install them, the required `@arnilo/prism` peer dependency, the release workflow, and the offline test budget. The measurable 1.0 readiness gates (command-per-gate) live in [`0.1.0-readiness.md`](./0.1.0-readiness.md).
|
|
6
6
|
|
|
7
|
-
Core `@arnilo/prism` ships runtime, CLI, templates, and docs. Every code package has a required `@arnilo/prism@0.
|
|
7
|
+
Core `@arnilo/prism` ships runtime, CLI, templates, and docs. Every code package has a required `@arnilo/prism@0.2.4` peer; profiles are pure manifests. Installation activates no provider, listener, database, browser, credential, or tool capability.
|
|
8
8
|
|
|
9
9
|
Current **50** publishable manifests (root + 49 workspace packages):
|
|
10
10
|
|
|
@@ -31,12 +31,12 @@ Consumers install the core package for the runtime and add first-party packages
|
|
|
31
31
|
| --- | --- |
|
|
32
32
|
| Install core only | `npm install @arnilo/prism` |
|
|
33
33
|
| Scaffold a minimal project | `npx --package @arnilo/prism prism init my-agent [--provider openai] [--with-workflows] [--with-evals]` |
|
|
34
|
-
| Install core +
|
|
34
|
+
| Install core + provider family (11 of 14) | `npm install @arnilo/prism @arnilo/prism-providers` |
|
|
35
35
|
| Install minimal safe profile | `npm install @arnilo/prism-base` |
|
|
36
36
|
| Install compaction strategies only | `npm install @arnilo/prism @arnilo/prism-compaction` |
|
|
37
37
|
| Install coding-agent profile | `npm install @arnilo/prism-code @arnilo/prism-provider-openai` |
|
|
38
38
|
| Install application SDK profile | `npm install @arnilo/prism-sdk @arnilo/prism-provider-openai @arnilo/prism-session-store-sqlite` |
|
|
39
|
-
| Install
|
|
39
|
+
| Install the broad umbrella | `npm install @arnilo/prism-all` |
|
|
40
40
|
| Install core + a single provider | `npm install @arnilo/prism @arnilo/prism-provider-openai` |
|
|
41
41
|
| 0.0.12 AG-UI (after release) | `npm install @arnilo/prism@0.0.12 @arnilo/prism-ag-ui@0.0.12` |
|
|
42
42
|
| Install bounded web research tools | `npm install @arnilo/prism @arnilo/prism-web-tools @arnilo/prism-tool-validator-json-schema` |
|
|
@@ -94,7 +94,7 @@ A packed tarball contains only public compiled output and release files:
|
|
|
94
94
|
- Code packages ship `README.md`, `LICENSE`, and `CHANGELOG.md`; family/profile packages ship `README.md` and `CHANGELOG.md`.
|
|
95
95
|
- The core tarball additionally ships the full `docs/` directory (the docs hub) and `templates/init/` used by `prism init`.
|
|
96
96
|
- `dist/cli.js` and the `bin` link in core.
|
|
97
|
-
- **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.
|
|
97
|
+
- **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.2.4.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.2.4.tgz` / `arnilo-prism-compaction-<name>-0.2.4.tgz` / `arnilo-prism-coding-agent-0.2.4.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.2.4.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
|
|
98
98
|
|
|
99
99
|
Excluded from every tarball by `files` negation:
|
|
100
100
|
|
|
@@ -275,6 +275,54 @@ git push origin v0.1.2 # tag push triggers release.yml publish job (prove
|
|
|
275
275
|
|
|
276
276
|
**Rollback notes.** `release:publish --version 0.1.2 --resume --report release-artifacts/publish-report.json` resumes an interrupted publication and skips only registry versions whose internal dependency fingerprint matches the local manifest. A failed package aborts the run with its status written to the report; re-run after fixing the cause. npm cannot unpublish the `0.1.2` line after 72 hours — a post-publication defect ships as a `0.1.x` patch (additive-only compat promise, `release:gate` enforced), or as a documented break in the next line with a `docs/migration.md` entry. `0.1.2` is store-compatible with `0.1.1` in **both directions** (no migration ran — same checksum-protected contract), so an operator may defer or roll back the patch without a database rollback.
|
|
277
277
|
|
|
278
|
+
### 0.2.4 publish handoff (plan 024 Task 6)
|
|
279
|
+
|
|
280
|
+
**Decision: GO when the operator prerequisites below are recorded.** Release **0.2.4** (plan 024) is the package-documentation-and-compatibility-truth cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.4: delta is the version literal only — no export changes; baselines regenerated with `--update-baseline`, no `--allow-break`; freeze manifest `scripts/phase24-freeze-manifest.json`). Documentation/compatibility truth, **no runtime contract change and no migration**: (1) **umbrella wording matches manifests** — before: `@arnilo/prism-providers` claimed to install every one of the 14 first-party provider adapters while its `dependencies` shipped 11, and `@arnilo/prism-all` claimed to install every first-party package while 5 packages were unreachable from its install set. After: `prism-providers` states **11 of 14** (Azure, Bedrock, Vertex are added separately by `prism-all`; its install list was corrected from 9 to the full 11 — alibaba and ollama were missing from the docs), and `prism-all` states **20 direct / 43 transitive** packages with the complete omission set named (document-reader, OpenAPI tools, NATS, Caveman, Ponytail). **No `dependencies` array changed in 0.2.4** — the manifests were already truthful; only the claims were wrong. Membership itself is 0.3.0 scope (§0.3.0 "Umbrella membership fix"). (2) **generated tables from one source of truth** — `node scripts/package-truth.mjs` reads every manifest and emits `scripts/package-truth.json` (counts 50/49/14/9/26, provider/family/capability membership, umbrella + profile closures, peer policy); all count/closure/current-line docs literals are derived from it and the gates fail on drift (plain JS consumer example):
|
|
281
|
+
|
|
282
|
+
```js
|
|
283
|
+
import { readFileSync } from "node:fs";
|
|
284
|
+
const truth = JSON.parse(readFileSync("scripts/package-truth.json", "utf8"));
|
|
285
|
+
console.log(truth.counts.publishable, truth.umbrella["prism-all"].closure); // 50 43
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
(3) **peer-version policy Decision A (exact pins)** — every code package peers the bare exact current version `@arnilo/prism@0.2.4` (no `~`/`^`/`>=`/`*`) through 0.2.x with the atomic-upgrade rule: all `@arnilo/prism-*` packages move at the same version; a partial upgrade fails clearly at install time with `ERESOLVE unable to resolve dependency tree` naming the conflicting peer (never a silent install of a pair that was never tested); the range widens to `^1.0.0` at the 1.x stable release after the 1.0 readiness gates go operator-green. Third-party `@arnilo/prism-*` adapters declare the same exact peer on the documented current version. (4) **docs semantic, not phrase-only** — the structural docs tests derive every count/closure/current-line assert from the generated artifact (an editorial reword that keeps the derived value passes; a wrong value fails), the stale `0.2.8` stray roadmap section was removed, and `docs/0.1.0-readiness.md`/`docs/index.md` current-line blocks advance to 0.2.4 with **0.1.7** recorded as the terminal 0.1.x baseline (0.1.1/0.1.0 tables demoted to historical record). Release graph stays **50** publishable manifests at exact **0.2.4**; zero new runtime dependency names (core remains dependency-free); 43 code packages + 6 pure-manifest family/profile. Regression surface: `phase24-truth` (12, incl. built-dist version + docs current-line + umbrella wording freeze + gate accounting), packed plain-JS truth conformance in install-smoke (providers tarball = exactly 11 provider deps; prism-all tarball = generated 20 deps + 43-member closure; packed current-line equals docs), and the Task 3 packed ERESOLVE refusal proof. Exit gate green: npm test core + workspace + script gates, `sdk:ready` exit 0, audit 0 moderate, secret scans 0 findings, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.4 (version literal only), release-evidence manifest with zero blocked surfaces; evidence in `scripts/phase24-baseline.json` `exitGate`. **Rollback notes.** Rollback = restore the 0.2.3 manifests/tag. Nothing persisted changes shape and no runtime behavior changed, so downgrade is store-safe; the only visible deltas are the version literal and the corrected docs wording (the old umbrella claims reappear if you revert the docs — the truth tests fail red until the wording is restored).
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# Operator prerequisites recorded: clean tree at the v0.2.4 tag candidate, GPG key, npm OIDC publisher.
|
|
292
|
+
node scripts/release.mjs bump --from 0.2.3 --to 0.2.4 # already applied by Task 6; idempotent
|
|
293
|
+
npm test # core + workspace suites + all script gates (incl. phase24-truth)
|
|
294
|
+
npm run security:threat-suites # phase8-11 + phase20 + phase21 + phase22 + phase23 public-entry conformance
|
|
295
|
+
PRISM_TEST_POSTGRES_URL=postgres://postgres:prism@127.0.0.1:54329/prism_test npm run sdk:ready
|
|
296
|
+
node scripts/release.mjs gate --version 0.2.4 # plain reviewed gate at 0.2.4: version literal only, 0 breaking deltas
|
|
297
|
+
npm run pack:dry-run # twice; diff reports — deterministic
|
|
298
|
+
npm audit --audit-level=moderate
|
|
299
|
+
npm run release:check -- --version 0.2.4 --report /tmp/prism-0.2.4-preflight.json
|
|
300
|
+
npm run release:publish -- --version 0.2.4 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.2.4-dry-run.json
|
|
301
|
+
# run the dry-run twice and diff the reports: deterministic, byte-identical
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Protected evidence (never a passing skip): the durable state-concurrency legs (Postgres `prism_phase24_*` schemas — `npm run test:postgres` under `PRISM_TEST_POSTGRES_URL`; absent credentials record **blocked** per the release skip manifest), the phase24 package-truth conformance over built dist + packed tarballs, and the live canaries (provider OIDC/OPA, MCP, A2A, Brave — always `protected` rows in the manifest, never `pass`). The release skip manifest names every skip class with its required env; missing protected evidence records 0.2.4 as **blocked**, never a passing skip.
|
|
305
|
+
|
|
306
|
+
### 0.2.3 publish handoff (plan 023 Task 6)
|
|
307
|
+
|
|
308
|
+
**Decision: GO when the operator prerequisites below are recorded.** Release **0.2.3** (plan 023) is the build-coverage-and-release-evidence-integrity cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.3: delta is the version literal only — no export changes; baselines regenerated with `--update-baseline`, no `--allow-break`; freeze manifest `scripts/phase23-freeze-manifest.json`). Four tooling/evidence fixes, **no runtime contract change and no migration**: (1) **build serialization** — dependency-free `scripts/with-build-lock.mjs` serializes every emit/test leaf with one `O_EXCL` lockfile at `node_modules/.prism-build.lock` (pid + startedAt, read-back verified, stale-PID reclaim, `PRISM_BUILD_LOCK_TIMEOUT_MS` env override, fail-closed exit 1), so concurrent compilers can never expose a partial live `dist/`; the lock is never held by orchestrator scripts and `PRISM_BUILD_LOCK_HELD=1` prevents accidental nesting. **Caveat:** the lock only guards the wrapped leaves — a direct `tsc` invoked outside the wrapper can still race an importer, exactly like any external writer. (2) **corrected workspace coverage denominators** — workspace coverage runs use package-local `--test-coverage-include=dist/**` (imported core `dist` no longer pollutes package rows), the 60/70/75 core gate is unchanged, per-package line thresholds in `scripts/coverage-thresholds.json` are evidence-based (freeze-run minus 3 pp), env-gated durable-leg packages (`session-store-postgres`, `enterprise-postgres`, `memory`, `session-store-nats`) are `protectedException` rows shown separately, and `scripts/coverage-summary.json` is the machine-readable artifact the release gate reads. (3) **release skip manifest** — `scripts/release-skip-manifest.mjs` records every surface (`pass`/`skip`/`blocked`/`protected`, reason, required env names only) into `scripts/release-evidence.json`; a required surface with absent evidence records `blocked` and `release.mjs gate` fails closed — missing credentials/services can never convert into a green release. (4) **stabilized quality gates** — Biome 2.x `preset` config migration with zero lint diagnostics, the racy 150 ms MCP bridge timing assert replaced by a deterministic barrier, load-sensitive guards carry documented `ponytail:` ceilings, and `lint-report.sarif` + `unused-report.json` are machine-readable and CI-retained. Regression surface: `phase23-build-race` (8), `phase23-coverage` (4), `phase23-skip-manifest` (6), `phase23-quality-gates` (5), `phase23-security` (3, matrix items 4 and 12 by name) + packed plain-JS `security23.mjs` consumer. Exit gate green: npm test core + workspace + script gates, `sdk:ready` exit 0, audit 0 moderate, secret scans 0 findings, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.3, protected Postgres durable conformance evidence, release-evidence manifest with zero blocked surfaces; evidence in `scripts/phase23-baseline.json` `exitGate`. **Rollback notes.** Rollback = restore the 0.2.2 manifests/tag — but that reopens the partial-`dist` race window and the polluted coverage denominator, so prefer fixing the failing host on 0.2.3. Nothing persisted changes shape, so downgrade is store-safe. (CI remediation 2026-08-14: `coding-security` joined the `protectedException` rows — its native-sandbox legs probe `unshare --net` NETNS at load and skip on GitHub Actions runners, so the host-captured freeze threshold can never be met in CI; measured 72.80 lines in CI vs 80.18 on a NETNS-capable host.)
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# Operator prerequisites recorded: clean tree at the v0.2.3 tag candidate, GPG key, npm OIDC publisher.
|
|
312
|
+
node scripts/release.mjs bump --from 0.2.2 --to 0.2.3 # already applied by Task 6; idempotent
|
|
313
|
+
npm test # core + workspace suites + all script gates (incl. phase23 suites)
|
|
314
|
+
npm run security:threat-suites # phase8-11 + phase20 + phase21 + phase22 + phase23 public-entry conformance
|
|
315
|
+
PRISM_TEST_POSTGRES_URL=postgres://postgres:prism@127.0.0.1:54329/prism_test npm run sdk:ready
|
|
316
|
+
node scripts/release.mjs gate --version 0.2.3 # plain reviewed gate at 0.2.3: version literal only, 0 breaking deltas
|
|
317
|
+
npm run pack:dry-run # twice; diff reports — deterministic
|
|
318
|
+
npm audit --audit-level=moderate
|
|
319
|
+
npm run release:check -- --version 0.2.3 --report /tmp/prism-0.2.3-preflight.json
|
|
320
|
+
npm run release:publish -- --version 0.2.3 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.2.3-dry-run.json
|
|
321
|
+
# run the dry-run twice and diff the reports: deterministic, byte-identical
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Protected evidence (never a passing skip): the durable state-concurrency legs (Postgres `prism_phase23_*` schemas for sessions/checkpoints/events + enterprise router reservations/idempotency — `npm run test:postgres` under `PRISM_TEST_POSTGRES_URL`), the phase23 public-entry build-race + coverage-denominator conformance, and the live canaries (provider OIDC/OPA, MCP, A2A, Brave — always `protected` rows in the manifest, never `pass`). The release skip manifest names every skip class with its required env; missing protected evidence records 0.2.3 as **blocked**, never a passing skip.
|
|
325
|
+
|
|
278
326
|
### 0.2.2 publish handoff (plan 022 Task 6)
|
|
279
327
|
|
|
280
328
|
**Decision: GO when the operator prerequisites below are recorded.** Release **0.2.2** (plan 022) is the concurrent-state-and-durability-integrity cut on the 0.2.x review-remediation line. API surface **additive-only** vs 0.2.1 (plain reviewed compat gate at 0.2.2: deltas are the version literal plus `ModelRouterStateStore.reserveBudget`/`commitBudget`/`releaseBudget`, `ModelRouterReservation`, `ModelRouterBudgets.reservationTtlMs`, `ModelRouterLimits.maxRateKeys`/`maxBudgetKeys`, `SessionRecord.version` with `appendSession` `expectedVersion`, `EventMultiplexerError`, and the `@arnilo/prism/testing/state-concurrency-conformance` subpath — no removal; baselines regenerated with `--update-baseline`, no `--allow-break`; freeze manifest `scripts/phase22-freeze-manifest.json` records per-task evidence tokens). Four behavior tightenings documented in `docs/migration.md` `0.2.1 → 0.2.2`: (1) **atomic model-budget reservation** — `reserveBudget` at admission (used + reserved + requested <= window max, `{reservationId, fencingToken, admitted, retryAfterMs?}`), `commitBudget`/`releaseBudget` at outcome, TTL expiry (default 60 s) with late commits reconciled as `unknownUsage: true`; rate/budget key maps capped (4,096 default / 65,536 hard) with LRU eviction that never drops a held-reservation row; durable reservations live in a new `reservations` JSONB column (enterprise migration 003). (2) **atomic conversation metadata** — `SessionRecord.version` + `appendSession` `expectedVersion` (`0` create-only, `N>0` exact-CAS update-only, omitted = legacy last-write-wins); stale writes throw `SessionMetadataConflictError` `metadata_conflict` (versions only, HTTP 409); concurrent create/branch/archive single-statement with branch caps inside the CAS, archive wins, deleted rows never resurrect (migration 008). (3) **single-consumer EventMultiplexer** — second concurrent `subscribe()` throws `EventMultiplexerError` `ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER`. (4) **restart-stable NATS durable identity + bounded non-durable active-run registries** — durable name exactly `prism_<hmac16>`, crash-resume continues from the last ack, orphaned 0.2.1 random-suffixed consumers reclaimed on clean stop; workflow active-run registry sweeps aborted entries and fails closed at the 512 cap. New regression surface: `scripts/phase22-security.test.mjs` (4 blockers + gate accounting over built public entrypoints, wired into `security:threat-suites`), packed plain-JS `security22.mjs` consumer in install-smoke, the `@arnilo/prism/testing/state-concurrency-conformance` harness (7 probes; memory leg in npm test, durable legs in `test:postgres` and the NATS seam; zero timing-only sleeps), and the `scripts/phase22-conformance.test.mjs` gate in the `test:postgres` chain. Store compatibility with 0.2.1: **forward-only migrations** (008 + 003), see `docs/migration.md` for rollback risk. Exit gate green: npm test core + workspace + script gates (incl. phase21-freeze done-phase + phase22 conformance), `sdk:ready` exit 0, audit 0 moderate, secret scans 0 findings, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.2, protected OIDC/OPA evidence + durable state-concurrency evidence; evidence in `scripts/phase22-baseline.json` `exitGate`. Rollback = restore the 0.2.1 manifests/tag — but that reopens all four race windows, so prefer fixing the failing host on 0.2.2.
|
|
@@ -675,8 +723,8 @@ Audit fixes, dependency updates, and security patches land only for the supporte
|
|
|
675
723
|
|
|
676
724
|
## Extension and configuration notes
|
|
677
725
|
|
|
678
|
-
- **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.
|
|
679
|
-
- **Public access.** All
|
|
726
|
+
- **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional **exact** `@arnilo/prism@0.2.4` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). **Peer-version policy (plan 024, Decision A — exact pins):** the peer spec is the bare exact current version — no `~`/`^`/`>=` range, no `*` — for the whole 0.2.x line, and all `@arnilo/prism-*` packages move at the same version (the **atomic-upgrade rule**). A partial upgrade (e.g. `@arnilo/prism@0.2.4` installed with a package peering `@arnilo/prism@0.2.5`) is unsupported and fails clearly at install time with `ERESOLVE unable to resolve dependency tree` naming the conflicting peer — never a silent install of a pair that was never tested together. A third-party `@arnilo/prism-*` adapter declares the same exact peer on the documented current version; an unsupported mixture fails at install time, not at runtime. The range widens to `^1.0.0` at the 1.x stable release (the 1.0 readiness gates go operator-green on the 0.2.x line); rollback of a release moves the pins back atomically with the manifests/tag. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
|
|
727
|
+
- **Public access.** All 50 manifests (root + 49 workspace packages: 43 code packages + 6 pure-manifest family/profile packages — the 9 `prism-*` family/profile set is the 6 pure-manifest profiles plus the 3 code packages `prism-caveman`, `prism-openapi-tools`, `prism-ponytail`) declare `"publishConfig": { "access": "public" }`; the publisher also passes `--access public` explicitly because scoped packages otherwise default to restricted on first publish.
|
|
680
728
|
- **Map retention knob.** Source maps are emitted locally but stripped from tarballs by `!dist/**/*.map`. Removing that `files` negation ships maps in releases (larger tarballs, better consumer stack traces).
|
|
681
729
|
- **Release workflow.** `.github/workflows/release.yml` has six jobs. `verify` runs network-free SDK readiness on Node 24; `node20-compat` builds/imports every public root `exports` default target on Node 20 for declared `engines.node >=20` (docs examples need Node >=22.6 native TypeScript stripping); `postgres-integration` uses `pgvector/pgvector:pg16`; `supply-chain` runs high-severity audit, SPDX/license policy, and tracked-source secret scanning; and tag-only `codeql-release` runs SAST. Tag-only `publish` needs all five gates, preserves clean exact-tag/version/topological publication, and alone receives `NPM_TOKEN`, `id-token: write`, and `attestations: write`. Before npm publish it packs all current tarballs, generates checksums plus SPDX, scans unpacked public artifacts, creates GitHub attestations for tarballs and SBOM, then retains artifacts for 30 days. Registry state remains the resumable journal. Local `npm run release:dry-run` remains network-free SDK readiness; local PostgreSQL coverage is `PRISM_TEST_POSTGRES_URL=... npm run test:postgres`.
|
|
682
730
|
- **Adding a package.** New workspace packages are picked up automatically by `npm run build --workspaces`, `npm test --workspaces`, `npm run pack:dry-run`, the packaging guard (`src/__tests__/packaging.test.ts`), and the install-smoke test (`src/__tests__/install-smoke.test.ts`) via the workspace glob; add the package to both tests' config arrays for explicit per-package assertions.
|
|
@@ -747,10 +795,63 @@ Prism uses one tool for formatting and linting — [Biome](https://biomejs.dev)
|
|
|
747
795
|
| `npm run lint` | `biome lint .` — fails on any lint error (warnings are non-fatal). |
|
|
748
796
|
| `npm run format:check` | `biome format .` — fails if any file is unformatted. |
|
|
749
797
|
| `npm run format` | `biome format --write .` — normalizes formatting in place. |
|
|
750
|
-
| `npm run test:coverage` | `node --test --experimental-test-coverage` over the core suite with enforced minimums: **lines 60%**, **functions 70%**, **branches 75%** (current baseline ≈
|
|
798
|
+
| `npm run test:coverage` | `node --test --experimental-test-coverage` over the core suite with enforced minimums: **lines 60%**, **functions 70%**, **branches 75%** (current baseline ≈ 90.5 / 84.2 / 90.6), then `scripts/coverage-summary.mjs` + the `phase23-coverage` gate. Excludes `__tests__/`, `node_modules/`, `scripts/`, and `packages/` from the core report. |
|
|
751
799
|
|
|
752
800
|
All four gates run inside `npm run sdk:ready` (after `typecheck`, before `pack:dry-run`). A few rules are disabled in `biome.json` because they are false positives for this codebase: `noControlCharactersInRegex` and `noAssignInExpressions` (security/redaction code intentionally matches control characters and uses `while ((m = re.exec(…)))` loops), `noShadowRestrictedNames`, `noThenProperty` (the workflow DSL has a legitimate `then` branch field), `noExplicitAny`, `noVoidTypeReturn`, and `useYield`. Raise the coverage thresholds in `package.json` `test:coverage` as the baseline climbs.
|
|
753
801
|
|
|
802
|
+
### Coverage denominators and per-package thresholds
|
|
803
|
+
|
|
804
|
+
Workspace coverage rows used to include the symlinked root core `dist/` (workspace tests `import … from "@arnilo/prism"`, which resolves via `node_modules/@arnilo/prism -> ../..`), diluting every package denominator. Each workspace coverage run now passes `--test-coverage-include=dist/**`, so only `packages/<name>/dist/**` counts (the core run and its 60/70/75 gate are unchanged).
|
|
805
|
+
|
|
806
|
+
| Fact | Value |
|
|
807
|
+
| --- | --- |
|
|
808
|
+
| Workspace include filter | `--test-coverage-include=dist/**` per package (package-local denominator) |
|
|
809
|
+
| Per-package gate | `lines >= threshold` from `scripts/coverage-thresholds.json` (frozen 2026-08-14 = recompute − 3pp, two runs were byte-identical); branches/functions recorded, not gated |
|
|
810
|
+
| Protected exceptions | `@arnilo/prism-session-store-postgres`, `@arnilo/prism-enterprise-postgres`, `@arnilo/prism-memory`, `@arnilo/prism-session-store-nats` — durable legs need `PRISM_TEST_POSTGRES_URL` or a real NATS server; plus `@arnilo/prism-coding-security` — native-sandbox legs probe `unshare --net` (NETNS) and skip on CI runners (host runs exercise them); exempt from the gate, reported separately with the reason |
|
|
811
|
+
| Artifact | `scripts/coverage-summary.json` (gitignored, CI-retained): per-package `lines`/`branches`/`functions`/`denominatorFiles`/`threshold`/`pass`/`protectedException` + `belowThreshold` |
|
|
812
|
+
| Fail-closed | a non-protected package below its threshold, a suite failure, or a run producing no coverage data exits non-zero; a missing threshold entry is a config error |
|
|
813
|
+
| Overrides | `PRISM_COVERAGE_THRESHOLDS`, `PRISM_COVERAGE_ARTIFACT` (used by the gate regression) |
|
|
814
|
+
|
|
815
|
+
A new workspace package must add an evidence-based threshold entry (or a `protectedException` reason) to `scripts/coverage-thresholds.json` before `test:coverage` passes.
|
|
816
|
+
|
|
817
|
+
### Release evidence and protected skips
|
|
818
|
+
|
|
819
|
+
`npm run release:evidence` (run automatically at the start of `npm run release:gate`, and therefore at the end of `npm run sdk:ready`) aggregates every test surface into `scripts/release-evidence.json` — the machine-auditable release skip manifest. It records env var **names only, never values** (the manifest is retained and uploaded by CI).
|
|
820
|
+
|
|
821
|
+
| State | Meaning | Gate effect |
|
|
822
|
+
| --- | --- | --- |
|
|
823
|
+
| `pass` | the surface ran and its recorded evidence is green | pass |
|
|
824
|
+
| `skip` | a documented partial-skip surface (must carry `reason` + `requiredEnv`) | pass (defensive: an unexplained `skip` fails) |
|
|
825
|
+
| `protected` | a documented, permitted gap with a reason (+ required env where applicable) | pass, always visible |
|
|
826
|
+
| `blocked` | a required release surface cannot be attested (required env absent, or evidence missing) | **fail closed** — `release.mjs gate` refuses to release |
|
|
827
|
+
|
|
828
|
+
Surfaces: core `npm test` (counts and the skip total come from the latest `phase*-baseline.json` `exitGate.counts` — currently 33 protected/live skips, a frozen floor), `security:threat-suites`, every workspace suite (evidence from `scripts/coverage-summary.json` of the same run; `protectedException` packages are named with their reason), `test:postgres` durable conformance (**required**: `PRISM_TEST_POSTGRES_URL` must be set when `release:gate` runs — the release workflow's verify job declares it on the `release:gate` phase only, so the env never leaks into the env-gated docs demo / durable integration suites of `npm test`, and the `postgres-integration` job runs the suite against a real server; a local release must set it too, exactly like the phase-22 release profile), `test:nats` real JetStream legs (protected, 0.3.0), the `PRISM_LIVE_PROVIDER_TESTS` provider legs (protected, per package), and the four live canaries from `scripts/live-canary.mjs` (provider/MCP/A2A/web; run by the scheduled `live-canaries` workflow with real credentials — recorded `protected`, never `pass`). The manifest cross-references the latest baseline's `exitGate`/`protectedEvidence` so per-phase records stay the source of truth.
|
|
829
|
+
|
|
830
|
+
Override `PRISM_RELEASE_EVIDENCE` to redirect the manifest (used by the gate regression). The manifest is gitignored and CI-retained (`release-evidence` artifact). A release cannot ship with a required env absent and unexplained — the operator sees every blocked surface in the retained manifest.
|
|
831
|
+
|
|
832
|
+
### Quality-gate reports and the Biome baseline
|
|
833
|
+
|
|
834
|
+
`npm run lint` runs Biome 2.x with the canonical config (`linter.rules.preset: "recommended"` — the deprecated `recommended: true` key is gone; `npx biome migrate --write` performs the rewrite) and writes a machine-readable SARIF report to `scripts/lint-report.sarif` in the same run (stable `--reporter=sarif`; the experimental `--reporter=json` schema is not used). The repo target is **zero** lint diagnostics; every remaining intentional diagnostic carries a justified `biome-ignore lint/<rule>: reason` comment (shell-interpolated strings, verbatim upstream fixtures, and literal grep targets in tests). Unused-code diagnostics are auto-fixed by `biome lint --write --unsafe .`; public-but-unused exports are never removed by Biome — they route to the unused-code sweep.
|
|
835
|
+
|
|
836
|
+
`npm run sweep:unused` (also part of `npm test`) runs the tsc `--noUnusedLocals/--noUnusedParameters` sweep across the core and every workspace tsconfig and writes both `scripts/unused-sweep-report.txt` (human) and `scripts/unused-report.json` (`--json`, machine-readable: per-tsconfig counts + the dead-export scan). It stays non-blocking by design. Both reports are gitignored and CI-retained (`quality-gate-reports` artifact, 30 days).
|
|
837
|
+
|
|
838
|
+
Timing assertions in tests follow a deterministic-barrier policy: racy wall-clock deltas are replaced by awaiting the conflicting operation and asserting its observable outcome (plus a test-level `timeout` as the anti-hang guard). The few remaining wall-clock guards are generous anti-hang/proof-of-promptness bounds, each marked with a `ponytail:` comment naming its ceiling; the document-reader budget test uses the recorded `scripts/budgets.json` ceilings.
|
|
839
|
+
|
|
840
|
+
## Build serialization
|
|
841
|
+
|
|
842
|
+
`dist/` is compiled by `tsc` in many small writes, so a concurrent build and test in the same working tree could race — a test importing `@arnilo/prism` mid-emit could observe a partially-written module (reproduced during the 0.2.3 review). Emit-producing leaves (`tsc` builds) and dist-consuming test leaves (`node --test dist/__tests__/*.test.js`) are therefore serialized through a dependency-free lock: `node scripts/with-build-lock.mjs <command>` acquires an `O_EXCL` lockfile at `node_modules/.prism-build.lock` (contents: holder `pid` + timestamp, no secrets), waits with a 100ms backoff, and fails closed — never proceeding without the lock. A stale lock whose holder PID is dead is reclaimed; a live lock is never stolen. Acquisition is leaf-only (never the `npm test`/`sdk:ready` orchestrators), so nested `npm run build` children cannot deadlock.
|
|
843
|
+
|
|
844
|
+
| Fact | Value |
|
|
845
|
+
| --- | --- |
|
|
846
|
+
| Lock path | `node_modules/.prism-build.lock` (repo-root-relative; workspaces share the same lock) |
|
|
847
|
+
| Timeout | 120s default; override with `PRISM_BUILD_LOCK_TIMEOUT_MS` |
|
|
848
|
+
| Retry | 100ms backoff; stale-PID reclaim via `process.kill(pid, 0)` |
|
|
849
|
+
| Fail-closed | acquisition error or timeout exits non-zero, nothing runs |
|
|
850
|
+
| Wrapped | `build:core`, every workspace `build`, the `node --test` runs in `test`/`test:coverage`/workspace tests, `coverage-summary.mjs`, the script-gate `node --test` run (the `phase*-conformance`/`phase*-security` gates import `@arnilo/prism` from `dist`) |
|
|
851
|
+
| Not wrapped | `npm run clean` (standalone), `tsc -p examples --noEmit` and workspace `typecheck` (read `dist` `.d.ts`; within any single script the build completes before reads, so only a concurrent external emitter can cause a spurious typecheck error), `scripts/phase23-build-race.test.mjs` (the lock's own regression — it runs unwrapped so its children acquire the real lock) |
|
|
852
|
+
|
|
853
|
+
Directly invoking `tsc` instead of `npm run build` bypasses the lock — use the npm scripts when another build/test could be running in the same tree (CI runs them sequentially).
|
|
854
|
+
|
|
754
855
|
## Dependency major-upgrade isolation
|
|
755
856
|
|
|
756
857
|
Major dependency upgrades are **isolated, compatibility-tested changes — never bundled into a feature release.** A major bump (TypeScript, `@types/node`, `diff`, or any third-party runtime dependency and its successors) ships as its own commit/PR that runs `npm run sdk:ready` plus packed-install evidence, and is reviewed separately from feature work. Release commits contain no unreviewed major bumps.
|
|
@@ -797,7 +898,7 @@ Every release gate maps to an exact enforcement test or command, so the checklis
|
|
|
797
898
|
| Root SDK export surface freeze | `public-export-contract.test.ts` `root export surface is frozen` snapshots every value and type export of `src/index.ts` (107 value + 69 type) so any add/remove is a deliberate test update; `every frozen value export resolves at runtime` rebuilds `dist/index.js` and asserts each value export is present (catches build drift), and `every frozen type export appears in the built type declarations` asserts each type export is in `dist/index.d.ts`. |
|
|
798
899
|
| Examples compile and are listed; runnable demos execute | `npm run typecheck` runs `tsc -p examples --noEmit`; `docs.test.ts` checks every `examples/*.ts` file is listed in `examples/README.md`, then runs demos offline and scans output for secrets. |
|
|
799
900
|
| Examples run to completion with no secret leakage | `docs.test.ts` `examples_demos_run_to_completion_and_emit_no_secret` runs each demo (Node strips TypeScript types natively) with exit-0 and real-secret scans; `external_app_example_*` pins the DB-backed adapter reference exercising the `RunLedger`, branch-handle checkout, fork, and prior-run resume. |
|
|
800
|
-
| Tarball excludes built tests, source maps, and source | `packaging.test.ts` rejects `dist/__tests__/`, `*.map`, `src/`, `plans/`, and internal files; confirms every package ships README/changelog (and code packages ship LICENSE), core ships docs + CLI, and every export target exists. `prism-all` reaches
|
|
901
|
+
| Tarball excludes built tests, source maps, and source | `packaging.test.ts` rejects `dist/__tests__/`, `*.map`, `src/`, `plans/`, and internal files; confirms every package ships README/changelog (and code packages ship LICENSE), core ships docs + CLI, and every export target exists. `prism-all` reaches 43 of the 49 workspace packages (20 direct + 23 transitive); the deliberate Caveman/Ponytail opt-outs and the other non-closure packages (document-reader, OpenAPI tools, NATS) are not in its install set. |
|
|
801
902
|
| NeuralWatt package/docs/examples release gate | `packaging.test.ts` pins `@arnilo/prism-provider-neuralwatt` package exports/type declarations and `@arnilo/prism-providers`/`@arnilo/prism-all` membership; `docs.test.ts` asserts `docs/index.md` links `providers/neuralwatt.md` and `provider-caching.md`, and that `examples/cache-aware-prompt-assembly.ts` plus `examples/neuralwatt-agent-run.ts` exist and are listed. |
|
|
802
903
|
| Enterprise PostgreSQL package/docs/example gate | Packaging/install/public-contract tests include `@arnilo/prism-enterprise-postgres`; `docs.test.ts` pins its API page, four-store migration/ownership/unknown-outcome/async-router guidance, and `examples/enterprise-postgres-state.ts`; `npm run test:postgres` exercises migration, restart, contention, and cleanup with an explicit database URL. |
|
|
803
904
|
| Version graph and resumable publication | `release.test.ts` covers exact package/lock/range validation, topological order, registry collisions, dry-run, interrupted reports/resume, clean tagged git state, provenance/public/tag arguments, and token-safe errors. `release:check` and `release:publish` derive the workspace graph without a manual package list. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnilo/prism",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Agent harness for AI providers, agents, sessions, and tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -142,15 +142,15 @@
|
|
|
142
142
|
"packages/prism-*"
|
|
143
143
|
],
|
|
144
144
|
"scripts": {
|
|
145
|
-
"build:core": "tsc",
|
|
145
|
+
"build:core": "node scripts/with-build-lock.mjs tsc",
|
|
146
146
|
"clean": "rm -rf dist packages/*/dist",
|
|
147
147
|
"build": "npm run build:core && npm run build --workspaces --if-present",
|
|
148
148
|
"typecheck": "npm run build && npm run typecheck --workspaces --if-present && tsc -p examples --noEmit",
|
|
149
|
-
"sweep:unused": "node scripts/sweep-unused.mjs",
|
|
150
|
-
"test": "npm run build && node --test dist/__tests__/*.test.js && node --test scripts/release-gate.test.mjs scripts/tooling-gate.test.mjs scripts/budget-gate.test.mjs scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase11-freeze.test.mjs scripts/phase12-freeze.test.mjs scripts/phase13-freeze.test.mjs scripts/phase14-freeze.test.mjs scripts/phase15-freeze.test.mjs scripts/phase16-freeze.test.mjs scripts/phase17-freeze.test.mjs scripts/phase18-freeze.test.mjs scripts/phase19-freeze.test.mjs scripts/phase20-freeze.test.mjs scripts/phase21-freeze.test.mjs scripts/benchmark-0.1.0.test.mjs scripts/sweep-unused.test.mjs scripts/e2e-enterprise-journey.test.mjs scripts/e2e-coding-journey.test.mjs && npm run test --workspaces --if-present",
|
|
151
|
-
"test:coverage": "node --test --experimental-test-coverage --test-coverage-lines=60 --test-coverage-functions=70 --test-coverage-branches=75 --test-coverage-exclude='**/__tests__/**' --test-coverage-exclude='**/node_modules/**' --test-coverage-exclude='**/scripts/**' --test-coverage-exclude='**/packages/**' --test-coverage-exclude='**/examples/**' dist/__tests__/*.test.js && node scripts/coverage-summary.mjs",
|
|
152
|
-
"coverage:summary": "node scripts/coverage-summary.mjs",
|
|
153
|
-
"lint": "biome lint .",
|
|
149
|
+
"sweep:unused": "node scripts/sweep-unused.mjs --json",
|
|
150
|
+
"test": "npm run build && node scripts/with-build-lock.mjs node --test dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node --test scripts/release-gate.test.mjs scripts/tooling-gate.test.mjs scripts/budget-gate.test.mjs scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase11-freeze.test.mjs scripts/phase12-freeze.test.mjs scripts/phase13-freeze.test.mjs scripts/phase14-freeze.test.mjs scripts/phase15-freeze.test.mjs scripts/phase16-freeze.test.mjs scripts/phase17-freeze.test.mjs scripts/phase18-freeze.test.mjs scripts/phase19-freeze.test.mjs scripts/phase20-freeze.test.mjs scripts/phase21-freeze.test.mjs scripts/benchmark-0.1.0.test.mjs scripts/sweep-unused.test.mjs scripts/e2e-enterprise-journey.test.mjs scripts/e2e-coding-journey.test.mjs scripts/phase23-quality-gates.test.mjs scripts/phase24-truth.test.mjs && node --test scripts/phase23-build-race.test.mjs && npm run test --workspaces --if-present",
|
|
151
|
+
"test:coverage": "node scripts/with-build-lock.mjs node --test --experimental-test-coverage --test-coverage-lines=60 --test-coverage-functions=70 --test-coverage-branches=75 --test-coverage-exclude='**/__tests__/**' --test-coverage-exclude='**/node_modules/**' --test-coverage-exclude='**/scripts/**' --test-coverage-exclude='**/packages/**' --test-coverage-exclude='**/examples/**' dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node scripts/coverage-summary.mjs && node --test scripts/phase23-coverage.test.mjs && node --test scripts/phase23-skip-manifest.test.mjs",
|
|
152
|
+
"coverage:summary": "node scripts/with-build-lock.mjs node scripts/coverage-summary.mjs",
|
|
153
|
+
"lint": "biome lint . --reporter=sarif --reporter-file=scripts/lint-report.sarif",
|
|
154
154
|
"format": "biome format --write .",
|
|
155
155
|
"format:check": "biome format .",
|
|
156
156
|
"pack:dry-run": "npm pack --dry-run && npm run pack:dry-run --workspaces --if-present",
|
|
@@ -158,9 +158,10 @@
|
|
|
158
158
|
"release:dry-run": "npm run sdk:ready",
|
|
159
159
|
"release:check": "node scripts/release.mjs check",
|
|
160
160
|
"release:publish": "node scripts/release.mjs publish",
|
|
161
|
+
"release:evidence": "node scripts/release-skip-manifest.mjs",
|
|
161
162
|
"sdk:ready": "npm run typecheck && npm run lint && npm run format:check && npm test && npm run test:coverage && npm run pack:dry-run && npm run release:gate",
|
|
162
|
-
"release:gate": "node scripts/release.mjs gate",
|
|
163
|
-
"security:threat-suites": "node --test scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase20-security.test.mjs scripts/phase21-security.test.mjs scripts/phase22-security.test.mjs"
|
|
163
|
+
"release:gate": "node scripts/release-skip-manifest.mjs && node scripts/release.mjs gate",
|
|
164
|
+
"security:threat-suites": "node --test scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase20-security.test.mjs scripts/phase21-security.test.mjs scripts/phase22-security.test.mjs scripts/phase23-security.test.mjs"
|
|
164
165
|
},
|
|
165
166
|
"devDependencies": {
|
|
166
167
|
"@biomejs/biome": "^2.5.5",
|