@looprun-ai/core 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The declarative PROOF format + the framework-free runners for the @looprun-ai/core testing kit.
3
+ *
4
+ * A {@link GuardProof} states, for ONE guard kind, the L1 (deterministic check in isolation) and optional
5
+ * L3 (full loop) obligations across positive/negative/neutral cases. This file holds only the pieces that
6
+ * need NO framework backend: the proof TYPES, the collective non-interference whitelist, the L1 runner,
7
+ * and the spec builders (isolated / collective) over the fixture surface. The full-loop runners
8
+ * (runProofLoop / expectedSignal / pickRecord / assertSignal) live in the backend package, since they
9
+ * drive a real conversation.
10
+ */
11
+ import { AgentSpecBase } from '../spec.js';
12
+ import { FixtureWorld, FIXTURE_TOOL_NAMES, FIXTURE_THEME, FIXTURE_LEXICON } from './fixture-world.js';
13
+ /** The collective non-interference whitelist — the kinds AgentSpecBase auto-installs. */
14
+ export const AUTO_LAYER_KINDS = [
15
+ 'noDuplicateCall',
16
+ 'degenerationGuard',
17
+ 'emptyReply',
18
+ 'noFalseFailureClaim',
19
+ 'confirmFirst',
20
+ 'destructiveThrottle',
21
+ ];
22
+ /** Fill a GuardCtx from a partial: empty args, a fresh FixtureWorld('seeded-media') unless a world is
23
+ * given, empty observed, turnIndex 0. */
24
+ export function craftCtx(partial = {}) {
25
+ return {
26
+ args: {},
27
+ world: new FixtureWorld('seeded-media'),
28
+ observed: [],
29
+ turnIndex: 0,
30
+ ...partial,
31
+ };
32
+ }
33
+ /** Instantiate a proof's guard, or throw when `make` is absent (the runners require it). */
34
+ export function requireMake(proof) {
35
+ if (!proof.make)
36
+ throw new Error(`GuardProof "${proof.guard}": make() is required to instantiate the guard.`);
37
+ return proof.make;
38
+ }
39
+ /** L1 — run the guard's deterministic check in isolation against a crafted ctx. */
40
+ export async function runL1(proof, c) {
41
+ const guard = requireMake(proof)();
42
+ const reason = await guard.check(craftCtx(c.ctx));
43
+ return { fired: reason != null, reason: reason ?? null };
44
+ }
45
+ /** Build a spec that isolates ONE proof's guard over the fixture surface. */
46
+ export function buildIsolatedSpec(proof) {
47
+ const cfg = {
48
+ id: `proof-${proof.guard}`,
49
+ mode: 'PROOF',
50
+ persona: 'You are the proof agent.',
51
+ tools: [...FIXTURE_TOOL_NAMES],
52
+ theme: FIXTURE_THEME,
53
+ ...(proof.specTweaks ?? {}),
54
+ };
55
+ const spec = new AgentSpecBase(cfg);
56
+ if (!proof.auto) {
57
+ spec.addGuard(proof.hook, proof.target, requireMake(proof)(), { id: `agent:${proof.guard}` });
58
+ }
59
+ return spec;
60
+ }
61
+ /** Build ONE spec with EVERY non-auto proof guard installed — the collective non-interference harness.
62
+ * Auto kinds ride AgentSpecBase (destructiveTools + confirmMechanism + lexicon below). Duplicate kinds
63
+ * at different targets are fine; ids are made unique by suffixing `#2`, `#3`, … */
64
+ export function buildCollectiveSpec(proofs) {
65
+ const spec = new AgentSpecBase({
66
+ id: 'proof-collective',
67
+ mode: 'PROOF',
68
+ persona: 'You are the proof agent.',
69
+ tools: [...FIXTURE_TOOL_NAMES],
70
+ theme: FIXTURE_THEME,
71
+ destructiveTools: ['deleteItem', 'purgeAll'],
72
+ confirmMechanism: { purgeAll: 'prior-ask' },
73
+ lexicon: {
74
+ falseFailureClaimRe: FIXTURE_LEXICON.falseFailureClaimRe,
75
+ confirmAskRe: FIXTURE_LEXICON.confirmAskRe,
76
+ },
77
+ });
78
+ const used = new Set();
79
+ for (const proof of proofs) {
80
+ if (proof.auto || proof.collective === 'skip')
81
+ continue;
82
+ let id = `agent:${proof.guard}`;
83
+ let n = 1;
84
+ while (used.has(id)) {
85
+ n += 1;
86
+ id = `agent:${proof.guard}#${n}`;
87
+ }
88
+ used.add(id);
89
+ spec.addGuard(proof.hook, proof.target, requireMake(proof)(), { id });
90
+ }
91
+ return spec;
92
+ }
93
+ //# sourceMappingURL=proof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proof.js","sourceRoot":"","sources":["../../src/testing/proof.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@looprun-ai/core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "looprun core: the AgentSpec governance layer for LLM agents — typed deterministic guards (prose+check pairing), the byte-stable scoped trunk renderer, and the backend-agnostic governed-turn machine. Framework-free: zero runtime dependencies; backends (@looprun-ai/mastra, …) supply the loop.",
6
6
  "keywords": [
@@ -28,6 +28,10 @@
28
28
  ".": {
29
29
  "types": "./dist/index.d.ts",
30
30
  "default": "./dist/index.js"
31
+ },
32
+ "./testing": {
33
+ "types": "./dist/testing/index.d.ts",
34
+ "default": "./dist/testing/index.js"
31
35
  }
32
36
  },
33
37
  "files": [
@@ -44,6 +48,7 @@
44
48
  "scripts": {
45
49
  "build": "tsc -p tsconfig.build.json",
46
50
  "typecheck": "tsc --noEmit",
47
- "test": "vitest run"
51
+ "test": "vitest run",
52
+ "test:proofs": "vitest run test/proofs --passWithNoTests"
48
53
  }
49
54
  }