@verevoir/recipes 0.9.0 → 0.10.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.
- package/dist/engine.d.ts +2 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +2 -0
- package/dist/engine.js.map +1 -1
- package/dist/run-verify.d.ts +46 -0
- package/dist/run-verify.d.ts.map +1 -0
- package/dist/run-verify.js +56 -0
- package/dist/run-verify.js.map +1 -0
- package/dist/verify.d.ts +44 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +20 -0
- package/dist/verify.js.map +1 -0
- package/package.json +1 -1
package/dist/engine.d.ts
CHANGED
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAIA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAIA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
|
package/dist/engine.js
CHANGED
package/dist/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,gFAAgF;AAChF,oFAAoF;AACpF,kFAAkF;AAClF,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,gFAAgF;AAChF,oFAAoF;AACpF,kFAAkF;AAClF,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Verifier, type VerifyFinding } from './verify.js';
|
|
2
|
+
/** Default cap on produce→verify attempts. A few passes to fix what the gate
|
|
3
|
+
* found; if it can't, the run is not done rather than shipping unmet work. */
|
|
4
|
+
export declare const DEFAULT_MAX_VERIFY_ATTEMPTS = 3;
|
|
5
|
+
/** What the producer is told for one attempt: the findings from the previous
|
|
6
|
+
* verify (empty on the first attempt) to fix, and the 1-based attempt number. */
|
|
7
|
+
export interface ProduceAttempt {
|
|
8
|
+
findings: VerifyFinding[];
|
|
9
|
+
attempt: number;
|
|
10
|
+
}
|
|
11
|
+
export interface RunWithVerifyInput {
|
|
12
|
+
capability: string;
|
|
13
|
+
/** The verifier name the capability declared (`descriptor.verify`). */
|
|
14
|
+
verify: string;
|
|
15
|
+
/** Produce the artefact and return the producer's final text. The first call
|
|
16
|
+
* gets no findings; later calls get the prior verdict's findings to fix. */
|
|
17
|
+
produce: (attempt: ProduceAttempt) => Promise<string>;
|
|
18
|
+
/** The resolved check — reads the produced artefact back and verifies it. */
|
|
19
|
+
verifier: Verifier;
|
|
20
|
+
/** Cap on attempts. Defaults to DEFAULT_MAX_VERIFY_ATTEMPTS. */
|
|
21
|
+
maxAttempts?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface RunWithVerifyResult {
|
|
24
|
+
/** The converged producer output, or the last attempt's if it never did. */
|
|
25
|
+
result: string;
|
|
26
|
+
/** How many produce→verify attempts ran (1-based). */
|
|
27
|
+
attempts: number;
|
|
28
|
+
/** Whether the verifier ultimately passed. */
|
|
29
|
+
converged: boolean;
|
|
30
|
+
/** The final attempt's findings — empty when converged. */
|
|
31
|
+
findings: VerifyFinding[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Run the produce→verify loop. Returns the outcome truthfully (converged or not)
|
|
35
|
+
* rather than throwing — the host decides whether a non-converged run fails the
|
|
36
|
+
* work (`enforceConverged`) or is recorded (the cross-model matrix wants the
|
|
37
|
+
* attempt count, not an exception). Always runs `produce` at least once.
|
|
38
|
+
*/
|
|
39
|
+
export declare function runWithVerify(input: RunWithVerifyInput): Promise<RunWithVerifyResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Fail-closed gate over a run's outcome: throw when it didn't converge, with the
|
|
42
|
+
* unmet findings, so a host that must not ship red is a one-liner. Returns the
|
|
43
|
+
* result unchanged when it converged.
|
|
44
|
+
*/
|
|
45
|
+
export declare function enforceConverged(capability: string, verify: string, outcome: RunWithVerifyResult): RunWithVerifyResult;
|
|
46
|
+
//# sourceMappingURL=run-verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-verify.d.ts","sourceRoot":"","sources":["../src/run-verify.ts"],"names":[],"mappings":"AAYA,OAAO,EAA2B,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzF;8EAC8E;AAC9E,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C;iFACiF;AACjF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf;gFAC4E;IAC5E,OAAO,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,6EAA6E;IAC7E,QAAQ,EAAE,QAAQ,CAAC;IACnB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAwB3F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,GAC3B,mBAAmB,CAOrB"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// The verify runner — the shared produce→verify→re-produce loop that enforces a
|
|
2
|
+
// capability's declared postcondition. A capability that declares a `verify` is
|
|
3
|
+
// "done" only when its verifier passes: produce, check, and on a not-clean
|
|
4
|
+
// verdict re-produce with the findings folded in, looping to a cap. The
|
|
5
|
+
// producer's output is an INPUT to the check, never trusted as final.
|
|
6
|
+
//
|
|
7
|
+
// PURE of model + IO: `produce` (the host's enact/tool loop) and `verifier` (the
|
|
8
|
+
// host's resolved check, reading the artefact back through its own adapter) are
|
|
9
|
+
// injected, so the loop is provider-agnostic and unit-testable with no network.
|
|
10
|
+
// It is the binary-gate sibling of the score-based refine loop (Ralph
|
|
11
|
+
// runRefineLoop); a rubric/prose verify that needs scoring routes through that.
|
|
12
|
+
import { isClean, formatFindings } from './verify.js';
|
|
13
|
+
/** Default cap on produce→verify attempts. A few passes to fix what the gate
|
|
14
|
+
* found; if it can't, the run is not done rather than shipping unmet work. */
|
|
15
|
+
export const DEFAULT_MAX_VERIFY_ATTEMPTS = 3;
|
|
16
|
+
/**
|
|
17
|
+
* Run the produce→verify loop. Returns the outcome truthfully (converged or not)
|
|
18
|
+
* rather than throwing — the host decides whether a non-converged run fails the
|
|
19
|
+
* work (`enforceConverged`) or is recorded (the cross-model matrix wants the
|
|
20
|
+
* attempt count, not an exception). Always runs `produce` at least once.
|
|
21
|
+
*/
|
|
22
|
+
export async function runWithVerify(input) {
|
|
23
|
+
// Non-finite (NaN/Infinity from a `Number(unset_env)` or a bad config) falls
|
|
24
|
+
// back to the default — `??` only catches null/undefined, and a NaN cap would
|
|
25
|
+
// make the loop run zero attempts, silently skipping the work.
|
|
26
|
+
const requested = input.maxAttempts;
|
|
27
|
+
const cap = Number.isFinite(requested) ? requested : DEFAULT_MAX_VERIFY_ATTEMPTS;
|
|
28
|
+
const max = Math.max(1, Math.floor(cap));
|
|
29
|
+
let findings = [];
|
|
30
|
+
let result = '';
|
|
31
|
+
for (let attempt = 1; attempt <= max; attempt += 1) {
|
|
32
|
+
result = await input.produce({ findings, attempt });
|
|
33
|
+
const verdict = await input.verifier({
|
|
34
|
+
capability: input.capability,
|
|
35
|
+
verify: input.verify,
|
|
36
|
+
result,
|
|
37
|
+
});
|
|
38
|
+
if (isClean(verdict)) {
|
|
39
|
+
return { result, attempts: attempt, converged: true, findings: [] };
|
|
40
|
+
}
|
|
41
|
+
findings = verdict.findings;
|
|
42
|
+
}
|
|
43
|
+
return { result, attempts: max, converged: false, findings };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fail-closed gate over a run's outcome: throw when it didn't converge, with the
|
|
47
|
+
* unmet findings, so a host that must not ship red is a one-liner. Returns the
|
|
48
|
+
* result unchanged when it converged.
|
|
49
|
+
*/
|
|
50
|
+
export function enforceConverged(capability, verify, outcome) {
|
|
51
|
+
if (!outcome.converged) {
|
|
52
|
+
throw new Error(`${capability} failed its verify (${verify}) after ${outcome.attempts} attempt(s):\n${formatFindings(outcome.findings)}`);
|
|
53
|
+
}
|
|
54
|
+
return outcome;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=run-verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-verify.js","sourceRoot":"","sources":["../src/run-verify.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,gFAAgF;AAChF,2EAA2E;AAC3E,wEAAwE;AACxE,sEAAsE;AACtE,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,gFAAgF;AAChF,sEAAsE;AACtE,gFAAgF;AAEhF,OAAO,EAAE,OAAO,EAAE,cAAc,EAAqC,MAAM,aAAa,CAAC;AAEzF;8EAC8E;AAC9E,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAiC7C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAyB;IAC3D,6EAA6E;IAC7E,8EAA8E;IAC9E,+DAA+D;IAC/D,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC;IACpC,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAE,SAAoB,CAAC,CAAC,CAAC,2BAA2B,CAAC;IAC7F,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,IAAI,QAAQ,GAAoB,EAAE,CAAC;IACnC,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,GAAG,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC;YACnC,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM;SACP,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACrB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACtE,CAAC;QACD,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAAkB,EAClB,MAAc,EACd,OAA4B;IAE5B,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,GAAG,UAAU,uBAAuB,MAAM,WAAW,OAAO,CAAC,QAAQ,iBAAiB,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CACzH,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** How a capability's (or practice's) conformance is checked: a mechanical check
|
|
2
|
+
* (gate), a model scored against a rubric (threshold), or irreducible judgement
|
|
3
|
+
* (advisory, not a gate). */
|
|
4
|
+
export type VerifyKind = 'deterministic' | 'rubric' | 'prose';
|
|
5
|
+
/** One thing a verifier found wrong, model-actionable so a re-produce can fix
|
|
6
|
+
* it. `kind` is the verifier's own finding code (e.g. `DTCG`, `VALUE_DRIFT`). */
|
|
7
|
+
export interface VerifyFinding {
|
|
8
|
+
kind: string;
|
|
9
|
+
file?: string;
|
|
10
|
+
where?: string;
|
|
11
|
+
message: string;
|
|
12
|
+
}
|
|
13
|
+
/** A verifier's verdict. `ok` is the pass/fail (a rubric/prose verifier may pass
|
|
14
|
+
* or fail with no structured findings); `findings` are the actionable detail a
|
|
15
|
+
* re-produce fixes. A deterministic verifier keeps them in lock-step (`ok` ⟺ no
|
|
16
|
+
* findings); use `isClean` rather than reading either field alone. */
|
|
17
|
+
export interface VerifyResult {
|
|
18
|
+
ok: boolean;
|
|
19
|
+
findings: VerifyFinding[];
|
|
20
|
+
}
|
|
21
|
+
/** What the runtime hands a verifier. The producer's `result` is grounding for a
|
|
22
|
+
* rubric/judge; a deterministic verifier ignores it and reads the produced
|
|
23
|
+
* artefact back itself (off a branch, off disk) — which is why the host binds
|
|
24
|
+
* its own IO into the closure rather than this carrying a repo handle. */
|
|
25
|
+
export interface VerifyInput {
|
|
26
|
+
capability: string;
|
|
27
|
+
/** The verifier name the capability declared (`descriptor.verify`). */
|
|
28
|
+
verify: string;
|
|
29
|
+
/** The producer's final text. */
|
|
30
|
+
result: string;
|
|
31
|
+
}
|
|
32
|
+
/** The check the runtime runs as a hard postcondition — the producer's output is
|
|
33
|
+
* an INPUT to it, never trusted as final. Async: a real check reads an artefact
|
|
34
|
+
* back or calls a judge. */
|
|
35
|
+
export type Verifier = (input: VerifyInput) => Promise<VerifyResult>;
|
|
36
|
+
/** True when a run passed its verify — fail-closed across all kinds. A
|
|
37
|
+
* deterministic verifier signals pass by empty findings; a rubric/prose one
|
|
38
|
+
* signals it by `ok` and may carry no structured findings — so EITHER a falsy
|
|
39
|
+
* `ok` or any finding reads as not-clean, and a malformed `{ ok: true,
|
|
40
|
+
* findings: [...] }` stays not-clean too. */
|
|
41
|
+
export declare function isClean(result: VerifyResult): boolean;
|
|
42
|
+
/** Render findings as model-readable lines for a re-produce directive. */
|
|
43
|
+
export declare function formatFindings(findings: VerifyFinding[]): string;
|
|
44
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAMA;;6BAE6B;AAC7B,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE9D;iFACiF;AACjF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;sEAGsE;AACtE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED;;;0EAG0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;4BAE4B;AAC5B,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAErE;;;;6CAI6C;AAC7C,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAErD;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,CAMhE"}
|
package/dist/verify.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// The verify contract — shared vocabulary for a capability's enforced
|
|
2
|
+
// postcondition. A capability declares a `verify` name (index.ts); the runtime
|
|
3
|
+
// resolves it to a Verifier and runs it as a hard gate, looping the producer on
|
|
4
|
+
// its findings until clean. `kind` says how conformance is judged — the same
|
|
5
|
+
// spectrum the refine/eval loop tools use (deterministic / judge / practices).
|
|
6
|
+
/** True when a run passed its verify — fail-closed across all kinds. A
|
|
7
|
+
* deterministic verifier signals pass by empty findings; a rubric/prose one
|
|
8
|
+
* signals it by `ok` and may carry no structured findings — so EITHER a falsy
|
|
9
|
+
* `ok` or any finding reads as not-clean, and a malformed `{ ok: true,
|
|
10
|
+
* findings: [...] }` stays not-clean too. */
|
|
11
|
+
export function isClean(result) {
|
|
12
|
+
return result.ok && result.findings.length === 0;
|
|
13
|
+
}
|
|
14
|
+
/** Render findings as model-readable lines for a re-produce directive. */
|
|
15
|
+
export function formatFindings(findings) {
|
|
16
|
+
return findings
|
|
17
|
+
.map((f) => `- ${f.kind}${f.file ? ` ${f.file}` : ''}${f.where ? ` ${f.where}` : ''}: ${f.message}`)
|
|
18
|
+
.join('\n');
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,+EAA+E;AA0C/E;;;;6CAI6C;AAC7C,MAAM,UAAU,OAAO,CAAC,MAAoB;IAC1C,OAAO,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAAC,QAAyB;IACtD,OAAO,QAAQ;SACZ,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,CAC/F;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verevoir/recipes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Recipe-descriptor format + zero-dependency parser: a flat-frontmatter .md describes a parameterised procedure (typed inputs → instructions → result) that a host compiles to a chat-time tool or an MCP prompt.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|