Files
openprose__prose/tests/open-prose/examples/forme-fixpoint/forme-fixpoint.live.test.ts
Jose Montes de Oca 9248d949e7 chore: ship skill examples as copyable scaffolding (#123)
The open-prose skill ships as a plain folder, so everything under
skills/open-prose/examples/ reaches every install. Each runtime example
shipped a committed replay/ state-dir (around 480 binary world-model files), a
generator, and a test suite wired to the workspace through a dist alias with no
local package.json. That machinery is internal validation, not the template a
user lifts: it cannot run from a copied folder, and it shipped generated
artifacts nobody should copy.

Keep the shipped examples to what a user actually adapts, and move the
validation into the repo's test tree:

- Move each example's tests, generator, and committed replay/ into
  tests/open-prose/examples/<name>/. The shipped example is now its .prose
  contracts under src/, a README, and a .gitignore.
- Re-point the vitest include and the test scripts; the byte-deterministic
  offline coverage runs unchanged, just rooted under tests/.
- Rewrite the example READMEs to point at the reactor CLI for producing and
  replaying a run, and drop the stale committed-fixture sections.
- Update the examples-gate workflow description to match the new layout.

No language, CLI, or runtime behavior changes, and the example contracts are
untouched. Verified with the offline gate (REACTOR_OFFLINE=1): the conformance
suite, the relocated example tests, and the eval harness all pass.
2026-06-05 19:44:15 -04:00

218 lines
8.0 KiB
TypeScript

// forme-fixpoint: OPTIONAL key-gated live reliability check.
//
// Additive and never required for the commit gate. It honors REACTOR_OFFLINE and
// is gated on a real OpenRouter key: a keyless or REACTOR_OFFLINE=1 run reports a
// PASSING-SKIPPED body and never touches the network, so the offline gate stays
// green and is unaffected by this file.
//
// When a key IS present it boots a minimal control-plane (registry -> Forme),
// swaps the fake Forme render for the live `createAgentRender` adapter at the
// `asyncMounts` seam (the reconciler cannot tell a live render from a fake one),
// drives `ingestAsync`, and asserts the fixpoint reliability invariant the
// contract promises:
//
// an UNCHANGED contract set re-wake SKIPS the Topology Maintainer at ZERO model
// calls (Forme renders at most once per changed contract-set fingerprint:
// finite recursion / topology memoization, on the live path).
import { describe, it, expect } from "vitest";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { createFileSystemStorageAdapter } from "@openprose/reactor";
import { FileSystemWorldModelStore } from "@openprose/reactor/adapters";
import {
mountDag,
createReplaySession,
files,
jsonFile,
ATOMIC_FACET,
type RenderContext,
} from "@openprose/reactor";
import { FileSystemReceiptLedger } from "@openprose/reactor/adapters";
import type {
ReconcilerTopology,
AsyncMountedRender,
} from "@openprose/reactor/internals";
import {
createAgentRender,
createOpenRouterProvider,
hasOpenRouterKey,
type CompiledContractView,
} from "@openprose/reactor/agents";
const REGISTRY = "responsibility.contract-registry";
const MAINTAINER = "responsibility.topology-maintainer";
const TRUTH = "truth.json";
// Honor REACTOR_OFFLINE (the hermetic CI switch) AND the key gate.
const OFFLINE =
process.env.REACTOR_OFFLINE === "1" || process.env.REACTOR_OFFLINE === "true";
const SKIP_REASON = OFFLINE
? "REACTOR_OFFLINE=1 (live check is a passing-skipped no-op)"
: hasOpenRouterKey()
? false
: "no OPENROUTER_API_KEY (live check is a passing-skipped no-op)";
function liveContractFor(node: string): CompiledContractView {
if (node === MAINTAINER) {
return {
name: "Topology Maintainer (Forme)",
maintains: [
"`active_graph`: the committed active graph (nodes, edges, entrypoints) — " +
"moves ONLY when a valid candidate is accepted.",
"`diagnostics`: ambiguous producers, rejected cycles — moves when validation " +
"errors change even if the active graph holds.",
],
requires: ["the contract registry's `contract-set` facet"],
continuity:
"Wake when the contract set changes; skip when the contract-set fingerprint " +
"is unchanged. Invalid candidates must NEVER replace the last valid active graph.",
execution:
"Read your upstream producer BY REFERENCE: call `wm_list_upstream`, then " +
`\`wm_read_upstream\` with that producer and path \`${TRUTH}\` to read the ` +
"contract set (a JSON object with `contract_set`: an array of contracts, each " +
"with contract_id, kind, requires_facets, maintains_facets). Resolve each " +
"Requires facet to the producer that Maintains it; if exactly one valid graph " +
"results, publish it. Then write " +
`\`${TRUTH}\` to your workspace, valid JSON of EXACTLY this shape: ` +
'{"active_graph": {"nodes": ["<id>", ...]}, "diagnostics": {"rejected_candidate_graph": false}, ' +
'"commit_status": "accepted"}. Be deterministic. Then report status "done".',
};
}
return {
name: "Contract Registry",
maintains: ["`contract-set`: the structured contract set."],
requires: ["the contract source ledger"],
continuity: "Input-driven.",
};
}
describe("forme-fixpoint (live) — an unchanged contract set skips Forme at zero model calls", () => {
it.skipIf(SKIP_REASON !== false)(
"the live Forme render obeys the memo key: an identical re-ingest spends no fresh tokens",
async () => {
const dir = mkdtempSync(join(tmpdir(), "forme-fixpoint-live-"));
try {
const store = new FileSystemWorldModelStore({
directory: join(dir, "world-models"),
});
const storage = createFileSystemStorageAdapter({ directory: dir });
const ledger = new FileSystemReceiptLedger({ storage });
const topology: ReconcilerTopology = {
topology: {
nodes: [
{
node: REGISTRY,
contract_fingerprint: "fp-reg",
wake_source: "external",
},
{
node: MAINTAINER,
contract_fingerprint: "fp-forme",
wake_source: "input",
},
],
edges: [
{
subscriber: MAINTAINER,
producer: REGISTRY,
facet: ATOMIC_FACET,
},
],
entry_points: [REGISTRY],
acyclic: true,
},
contract_fingerprints: {
[REGISTRY]: "fp-reg",
[MAINTAINER]: "fp-forme",
},
};
// A deterministic registry truth so the live Forme has a contract set to
// resolve by reference; identical across both ingests (the no-change re-wake).
const registryTruth = files({
[TRUTH]: jsonFile({
contract_set: [
{
contract_id: "customer-signal-inbox",
kind: "gateway",
requires_facets: [],
maintains_facets: ["CustomerSignals"],
},
{
contract_id: "insight-memo",
kind: "responsibility",
requires_facets: ["CustomerSignals"],
maintains_facets: ["InsightMemo"],
},
],
}),
});
const liveRender: AsyncMountedRender = createAgentRender({
store,
contractFor: liveContractFor,
provider: createOpenRouterProvider(),
temperature: 0,
seed: 7,
});
const dag = mountDag({
topology,
mounts: {
[REGISTRY]: {
render: (ctx: RenderContext) => ({
world_model: registryTruth,
cost: {
provider: "none",
model: "fake",
tokens: { fresh: 0, reused: 0 },
surprise_cause: ctx.wake.source,
},
}),
},
// sync fallback for Forme (the live one is on asyncMounts).
[MAINTAINER]: {
render: (ctx: RenderContext) => ({
world_model: files({}),
cost: {
provider: "none",
model: "fake",
tokens: { fresh: 0, reused: 0 },
surprise_cause: ctx.wake.source,
},
}),
},
},
asyncMounts: { [MAINTAINER]: liveRender },
store,
ledger,
});
await dag.ingestAsync(REGISTRY); // cold: the live Forme render fires
const freshAfterCold = createReplaySession({ ledger }).costRollup.total
.fresh;
const second = await dag.ingestAsync(REGISTRY); // identical re-wake: must skip
expect(second.map((r) => `${r.node}:${r.disposition}`)).toEqual([
`${REGISTRY}:skipped`,
]);
const freshAfterReWake = createReplaySession({ ledger }).costRollup
.total.fresh;
expect(freshAfterReWake).toBe(freshAfterCold); // the skip spent no fresh tokens
} finally {
rmSync(dir, { recursive: true, force: true });
}
},
);
it("is a passing-skipped no-op when keyless or REACTOR_OFFLINE=1", () => {
// Always-present green body: proves the file is a network-free no-op in the
// hermetic CI gate regardless of the key.
expect(true).toBe(true);
});
});