@restormel/reasoning-core 0.1.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +54 -0
  4. package/dist/constitution/evaluator.d.ts +30 -0
  5. package/dist/constitution/evaluator.d.ts.map +1 -0
  6. package/dist/constitution/evaluator.js +444 -0
  7. package/dist/constitution/rules.d.ts +3 -0
  8. package/dist/constitution/rules.d.ts.map +1 -0
  9. package/dist/constitution/rules.js +91 -0
  10. package/dist/context.d.ts +36 -0
  11. package/dist/context.d.ts.map +1 -0
  12. package/dist/context.js +1 -0
  13. package/dist/extraction.d.ts +6 -0
  14. package/dist/extraction.d.ts.map +1 -0
  15. package/dist/extraction.js +59 -0
  16. package/dist/index.d.ts +8 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +6 -0
  19. package/dist/meta-block.d.ts +10 -0
  20. package/dist/meta-block.d.ts.map +1 -0
  21. package/dist/meta-block.js +24 -0
  22. package/dist/pipeline.d.ts +68 -0
  23. package/dist/pipeline.d.ts.map +1 -0
  24. package/dist/pipeline.js +96 -0
  25. package/dist/prompts/constitution-eval.d.ts +8 -0
  26. package/dist/prompts/constitution-eval.d.ts.map +1 -0
  27. package/dist/prompts/constitution-eval.js +45 -0
  28. package/dist/prompts/reasoning-eval.d.ts +4 -0
  29. package/dist/prompts/reasoning-eval.d.ts.map +1 -0
  30. package/dist/prompts/reasoning-eval.js +36 -0
  31. package/dist/prompts/verification-extraction.d.ts +4 -0
  32. package/dist/prompts/verification-extraction.d.ts.map +1 -0
  33. package/dist/prompts/verification-extraction.js +46 -0
  34. package/dist/reasoning-eval.d.ts +15 -0
  35. package/dist/reasoning-eval.d.ts.map +1 -0
  36. package/dist/reasoning-eval.js +69 -0
  37. package/package.json +53 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Host-injected LLM and routing — no SOPHIA vertex or Keys imports in this package.
3
+ */
4
+ export type ModelRoute = {
5
+ /** Opaque model handle (e.g. Vercel AI SDK LanguageModel). */
6
+ model: unknown;
7
+ modelId: string;
8
+ provider: string;
9
+ resolvedRouteId?: string | null;
10
+ resolvedExplanation?: string | null;
11
+ };
12
+ export type GenerateTextParams = {
13
+ model: unknown;
14
+ system: string;
15
+ prompt: string;
16
+ maxOutputTokens?: number;
17
+ };
18
+ export type GenerateTextResult = {
19
+ text: string;
20
+ usage?: {
21
+ inputTokens?: number;
22
+ outputTokens?: number;
23
+ };
24
+ };
25
+ export type RouteOptions = {
26
+ providerApiKeys?: unknown;
27
+ depthMode?: string;
28
+ failureMode?: "error" | "fallback";
29
+ };
30
+ export type ReasoningCoreContext = {
31
+ generateText: (params: GenerateTextParams) => Promise<GenerateTextResult>;
32
+ resolveExtractionRoute: (options?: RouteOptions) => Promise<ModelRoute>;
33
+ resolveReasoningRoute: (options?: RouteOptions) => Promise<ModelRoute>;
34
+ trackTokens?: (input: number, output: number) => void;
35
+ };
36
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,YAAY,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC1E,sBAAsB,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACxE,qBAAqB,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACvE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import { type ExtractionResult, type VerificationRequest } from "@restormel/contracts/verification";
2
+ import type { ReasoningCoreContext } from "./context.js";
3
+ export declare function extractClaims(request: VerificationRequest, ctx: ReasoningCoreContext, options?: {
4
+ providerApiKeys?: unknown;
5
+ }): Promise<ExtractionResult>;
6
+ //# sourceMappingURL=extraction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../src/extraction.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAkBzD,wBAAsB,aAAa,CACjC,OAAO,EAAE,mBAAmB,EAC5B,GAAG,EAAE,oBAAoB,EACzB,OAAO,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GACtC,OAAO,CAAC,gBAAgB,CAAC,CAsD3B"}
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+ import { ExtractedClaimSchema, ExtractedRelationSchema, ExtractionResultSchema, } from "@restormel/contracts/verification";
3
+ import { extractStructuredMetaBlock } from "./meta-block.js";
4
+ import { buildVerificationExtractionUserPrompt, VERIFICATION_EXTRACTION_SYSTEM_PROMPT, } from "./prompts/verification-extraction.js";
5
+ const ExtractionMetaBlockSchema = z.object({
6
+ claims: z.array(ExtractedClaimSchema).default([]),
7
+ relations: z.array(ExtractedRelationSchema).default([]),
8
+ });
9
+ const MAX_RETRIES = 2;
10
+ function getSourceText(request) {
11
+ return [request.question, request.answer, request.text].filter(Boolean).join("\n\n");
12
+ }
13
+ export async function extractClaims(request, ctx, options) {
14
+ const startedAt = Date.now();
15
+ const sourceText = getSourceText(request);
16
+ let lastError;
17
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {
18
+ try {
19
+ const extractionRoute = await ctx.resolveExtractionRoute({
20
+ providerApiKeys: options?.providerApiKeys,
21
+ failureMode: "error",
22
+ });
23
+ const result = await ctx.generateText({
24
+ model: extractionRoute.model,
25
+ system: VERIFICATION_EXTRACTION_SYSTEM_PROMPT,
26
+ prompt: buildVerificationExtractionUserPrompt(request),
27
+ maxOutputTokens: 2048,
28
+ });
29
+ const inputTokens = result.usage?.inputTokens ?? 0;
30
+ const outputTokens = result.usage?.outputTokens ?? 0;
31
+ ctx.trackTokens?.(inputTokens, outputTokens);
32
+ const { metaBlock } = extractStructuredMetaBlock(result.text, ExtractionMetaBlockSchema);
33
+ if (!metaBlock) {
34
+ throw new Error("Missing or invalid sophia-meta block in extraction output");
35
+ }
36
+ const candidate = {
37
+ claims: metaBlock.claims,
38
+ relations: metaBlock.relations,
39
+ metadata: {
40
+ source_length: sourceText.length,
41
+ extraction_model: extractionRoute.modelId,
42
+ extraction_duration_ms: Date.now() - startedAt,
43
+ tokens_used: {
44
+ input: inputTokens,
45
+ output: outputTokens,
46
+ },
47
+ },
48
+ };
49
+ return ExtractionResultSchema.parse(candidate);
50
+ }
51
+ catch (error) {
52
+ lastError = error;
53
+ if (attempt === MAX_RETRIES) {
54
+ break;
55
+ }
56
+ }
57
+ }
58
+ throw new Error(`Claim extraction failed after retries: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
59
+ }
@@ -0,0 +1,8 @@
1
+ export type { GenerateTextParams, GenerateTextResult, ModelRoute, ReasoningCoreContext, RouteOptions, } from "./context.js";
2
+ export { extractStructuredMetaBlock } from "./meta-block.js";
3
+ export { extractClaims } from "./extraction.js";
4
+ export { evaluateReasoning, type ReasoningEvaluationResult } from "./reasoning-eval.js";
5
+ export { checkContradictionAwareness, checkCorrelationVsCausation, checkEvidenceRequirement, checkNormativeBridge, checkScopeDiscipline, checkSourceDiversity, evaluateConstitution, evaluateConstitutionWithTelemetry, type ConstitutionEvaluationResult, type ConstitutionEvaluationTelemetry, } from "./constitution/evaluator.js";
6
+ export { EPISTEMIC_RULES } from "./constitution/rules.js";
7
+ export { buildVerificationInputText, runVerificationPipeline, type PassOutputsRunner, type VerificationPipelineCallbacks, type VerificationPipelineOptions, type VerificationPipelineResult, } from "./pipeline.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,oBAAoB,EACpB,YAAY,GACb,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAExF,OAAO,EACL,2BAA2B,EAC3B,2BAA2B,EAC3B,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,iCAAiC,EACjC,KAAK,4BAA4B,EACjC,KAAK,+BAA+B,GACrC,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EACvB,KAAK,iBAAiB,EACtB,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,GAChC,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { extractStructuredMetaBlock } from "./meta-block.js";
2
+ export { extractClaims } from "./extraction.js";
3
+ export { evaluateReasoning } from "./reasoning-eval.js";
4
+ export { checkContradictionAwareness, checkCorrelationVsCausation, checkEvidenceRequirement, checkNormativeBridge, checkScopeDiscipline, checkSourceDiversity, evaluateConstitution, evaluateConstitutionWithTelemetry, } from "./constitution/evaluator.js";
5
+ export { EPISTEMIC_RULES } from "./constitution/rules.js";
6
+ export { buildVerificationInputText, runVerificationPipeline, } from "./pipeline.js";
@@ -0,0 +1,10 @@
1
+ import type { z } from "zod";
2
+ /**
3
+ * Extract JSON from a fenced meta block (default: ```sophia-meta).
4
+ * Keeps fence name for prompt compatibility with existing model outputs.
5
+ */
6
+ export declare function extractStructuredMetaBlock<T extends z.ZodTypeAny>(text: string, schema: T, fenceName?: string): {
7
+ cleanedText: string;
8
+ metaBlock: z.infer<T> | null;
9
+ };
10
+ //# sourceMappingURL=meta-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta-block.d.ts","sourceRoot":"","sources":["../src/meta-block.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAI7B;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAC/D,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,CAAC,EACT,SAAS,GAAE,MAAsB,GAChC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;CAAE,CAkBvD"}
@@ -0,0 +1,24 @@
1
+ const DEFAULT_FENCE = "sophia-meta";
2
+ /**
3
+ * Extract JSON from a fenced meta block (default: ```sophia-meta).
4
+ * Keeps fence name for prompt compatibility with existing model outputs.
5
+ */
6
+ export function extractStructuredMetaBlock(text, schema, fenceName = DEFAULT_FENCE) {
7
+ const pattern = new RegExp("```" + fenceName + "\\n?([\\s\\S]*?)\\n?```");
8
+ const metaMatch = text.match(pattern);
9
+ if (!metaMatch) {
10
+ return { cleanedText: text, metaBlock: null };
11
+ }
12
+ try {
13
+ const metaJson = JSON.parse(metaMatch[1]);
14
+ const validated = schema.safeParse(metaJson);
15
+ if (!validated.success) {
16
+ return { cleanedText: text, metaBlock: null };
17
+ }
18
+ const cleanedText = text.replace(pattern, "").trim();
19
+ return { cleanedText, metaBlock: validated.data };
20
+ }
21
+ catch {
22
+ return { cleanedText: text, metaBlock: null };
23
+ }
24
+ }
@@ -0,0 +1,68 @@
1
+ import type { PassType } from "@restormel/contracts/passes";
2
+ import type { VerificationRequest, VerificationResult } from "@restormel/contracts/verification";
3
+ import type { ReasoningCoreContext } from "./context.js";
4
+ export interface VerificationPipelineCallbacks {
5
+ onPassStart?(pass: PassType): void;
6
+ onPassChunk?(pass: PassType, content: string): void;
7
+ onPassComplete?(pass: PassType): void;
8
+ onPassStructured?(pass: PassType, sections: unknown, wordCount: number): void;
9
+ onSources?(sources: unknown): void;
10
+ onGroundingSources?(pass: PassType, sources: unknown): void;
11
+ onGraphSnapshot?(nodes: unknown, edges: unknown): void;
12
+ onClaims?(pass: unknown, claims: unknown, relations: unknown): void;
13
+ onConfidenceSummary?(avgConfidence: number, lowConfidenceCount: number, totalClaims: number): void;
14
+ onMetadata?(totalInputTokens: number, totalOutputTokens: number, durationMs: number, retrieval?: VerificationResult["metadata"]["retrieval"]): void;
15
+ onExtractionComplete?(payload: {
16
+ claims: VerificationResult["extracted_claims"];
17
+ relations: VerificationResult["logical_relations"];
18
+ metadata: {
19
+ source_length: number;
20
+ extraction_model: string;
21
+ extraction_duration_ms: number;
22
+ tokens_used: {
23
+ input: number;
24
+ output: number;
25
+ };
26
+ };
27
+ }): void;
28
+ onReasoningScores?(reasoningQuality: VerificationResult["reasoning_quality"]): void;
29
+ onConstitutionCheck?(constitutionalCheck: VerificationResult["constitutional_check"]): void;
30
+ }
31
+ /** Host-provided multi-pass reasoning (e.g. SOPHIA `runDomainAgnosticReasoning`). */
32
+ export type PassOutputsRunner = (inputText: string, callbacks: VerificationPipelineCallbacks & {
33
+ onError?(error: string): void;
34
+ }, options?: {
35
+ providerApiKeys?: unknown;
36
+ }) => Promise<void>;
37
+ export interface VerificationPipelineOptions {
38
+ ctx: ReasoningCoreContext;
39
+ includePassOutputs?: boolean;
40
+ callbacks?: VerificationPipelineCallbacks;
41
+ providerApiKeys?: unknown;
42
+ /** Required when `includePassOutputs` is true. */
43
+ runPassOutputs?: PassOutputsRunner;
44
+ }
45
+ export interface VerificationPipelineResult {
46
+ inputText: string;
47
+ extracted_claims: VerificationResult["extracted_claims"];
48
+ logical_relations: VerificationResult["logical_relations"];
49
+ reasoning_quality: VerificationResult["reasoning_quality"];
50
+ reasoning_model?: {
51
+ provider: string;
52
+ modelId: string;
53
+ routeId: string | null;
54
+ reason: string | null;
55
+ };
56
+ constitutional_check: VerificationResult["constitutional_check"];
57
+ pass_outputs?: VerificationResult["pass_outputs"];
58
+ retrieval?: VerificationResult["metadata"]["retrieval"];
59
+ extraction_input_tokens: number;
60
+ extraction_output_tokens: number;
61
+ constitution_duration_ms: number;
62
+ constitution_input_tokens: number;
63
+ constitution_output_tokens: number;
64
+ constitution_rule_violations: string[];
65
+ }
66
+ export declare function buildVerificationInputText(request: VerificationRequest): string;
67
+ export declare function runVerificationPipeline(request: VerificationRequest, options: VerificationPipelineOptions): Promise<VerificationPipelineResult>;
68
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { evaluateConstitutionWithTelemetry } from "./constitution/evaluator.js";
2
+ import { extractClaims } from "./extraction.js";
3
+ import { evaluateReasoning } from "./reasoning-eval.js";
4
+ export function buildVerificationInputText(request) {
5
+ return [request.question, request.answer, request.text].filter(Boolean).join("\n\n");
6
+ }
7
+ export async function runVerificationPipeline(request, options) {
8
+ const includePassOutputs = options.includePassOutputs ?? true;
9
+ const callbacks = options.callbacks;
10
+ const ctx = options.ctx;
11
+ const inputText = buildVerificationInputText(request);
12
+ const passOutputs = {};
13
+ let retrievalMeta;
14
+ if (includePassOutputs) {
15
+ if (!options.runPassOutputs) {
16
+ throw new Error("runPassOutputs hook is required when includePassOutputs is true");
17
+ }
18
+ await options.runPassOutputs(inputText, {
19
+ onPassStart(pass) {
20
+ callbacks?.onPassStart?.(pass);
21
+ },
22
+ onPassChunk(pass, content) {
23
+ if (pass !== "verification") {
24
+ passOutputs[pass] = `${passOutputs[pass] ?? ""}${content}`;
25
+ }
26
+ callbacks?.onPassChunk?.(pass, content);
27
+ },
28
+ onPassComplete(pass) {
29
+ callbacks?.onPassComplete?.(pass);
30
+ },
31
+ onPassStructured(pass, sections, wordCount) {
32
+ callbacks?.onPassStructured?.(pass, sections, wordCount);
33
+ },
34
+ onSources(sources) {
35
+ callbacks?.onSources?.(sources);
36
+ },
37
+ onGroundingSources(pass, sources) {
38
+ callbacks?.onGroundingSources?.(pass, sources);
39
+ },
40
+ onGraphSnapshot(nodes, edges) {
41
+ callbacks?.onGraphSnapshot?.(nodes, edges);
42
+ },
43
+ onClaims(pass, claims, relations) {
44
+ callbacks?.onClaims?.(pass, claims, relations);
45
+ },
46
+ onConfidenceSummary(avgConfidence, lowConfidenceCount, totalClaims) {
47
+ callbacks?.onConfidenceSummary?.(avgConfidence, lowConfidenceCount, totalClaims);
48
+ },
49
+ onMetadata(totalInputTokens, totalOutputTokens, durationMs, retrieval) {
50
+ retrievalMeta = retrieval;
51
+ callbacks?.onMetadata?.(totalInputTokens, totalOutputTokens, durationMs, retrieval);
52
+ },
53
+ onError(error) {
54
+ throw new Error(error);
55
+ },
56
+ }, { providerApiKeys: options.providerApiKeys });
57
+ }
58
+ const extraction = await extractClaims(request, ctx, {
59
+ providerApiKeys: options.providerApiKeys,
60
+ });
61
+ callbacks?.onExtractionComplete?.({
62
+ claims: extraction.claims,
63
+ relations: extraction.relations,
64
+ metadata: extraction.metadata,
65
+ });
66
+ const reasoning = await evaluateReasoning(extraction.claims, extraction.relations, request, ctx, {
67
+ providerApiKeys: options.providerApiKeys,
68
+ });
69
+ callbacks?.onReasoningScores?.(reasoning.evaluation);
70
+ const constitutionStartedAt = Date.now();
71
+ const constitutionResult = await evaluateConstitutionWithTelemetry(extraction.claims, extraction.relations, inputText, ctx, { providerApiKeys: options.providerApiKeys });
72
+ const constitutionDurationMs = Date.now() - constitutionStartedAt;
73
+ callbacks?.onConstitutionCheck?.(constitutionResult.check);
74
+ return {
75
+ inputText,
76
+ extracted_claims: extraction.claims,
77
+ logical_relations: extraction.relations,
78
+ reasoning_quality: reasoning.evaluation,
79
+ reasoning_model: reasoning.route,
80
+ constitutional_check: constitutionResult.check,
81
+ pass_outputs: includePassOutputs
82
+ ? {
83
+ analysis: passOutputs.analysis,
84
+ critique: passOutputs.critique,
85
+ synthesis: passOutputs.synthesis,
86
+ }
87
+ : undefined,
88
+ retrieval: retrievalMeta,
89
+ extraction_input_tokens: extraction.metadata.tokens_used.input,
90
+ extraction_output_tokens: extraction.metadata.tokens_used.output,
91
+ constitution_duration_ms: constitutionDurationMs,
92
+ constitution_input_tokens: constitutionResult.telemetry.constitution_input_tokens,
93
+ constitution_output_tokens: constitutionResult.telemetry.constitution_output_tokens,
94
+ constitution_rule_violations: constitutionResult.telemetry.constitution_rule_violations,
95
+ };
96
+ }
@@ -0,0 +1,8 @@
1
+ import type { ConstitutionRule } from "@restormel/contracts/constitution";
2
+ import type { ExtractedClaim, ExtractedRelation } from "@restormel/contracts/verification";
3
+ export interface ConstitutionEvalHeuristics {
4
+ proportional_evidence_low_support_claim_ids?: string[];
5
+ }
6
+ export declare const CONSTITUTION_EVAL_SYSTEM_PROMPT = "You are an epistemic quality auditor. You evaluate whether reasoning meets specific standards of intellectual rigour.\n\nYou will be given:\n1. A set of extracted claims with types and scopes\n2. Logical relations between those claims\n3. A set of epistemic rules to evaluate\n\nFor each rule, determine:\n- \"satisfied\": The reasoning clearly meets this standard\n- \"violated\": The reasoning clearly fails this standard\n- \"uncertain\": Cannot determine from available information\n- \"not_applicable\": The rule does not apply to this text\n\nBe conservative: prefer \"uncertain\" over false \"violated\".\nEvery violation must cite specific claim IDs.\nEvery violation must include a remediation suggestion.\n\nReturn JSON only as an array. Each object must include:\n- rule_id\n- status\n- affected_claim_ids (array of claim IDs)\n- rationale\n- remediation (required when status is \"violated\")";
7
+ export declare function buildConstitutionEvalUserPrompt(claims: ExtractedClaim[], relations: ExtractedRelation[], rules: ConstitutionRule[], originalText: string, heuristics?: ConstitutionEvalHeuristics): string;
8
+ //# sourceMappingURL=constitution-eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constitution-eval.d.ts","sourceRoot":"","sources":["../../src/prompts/constitution-eval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAE3F,MAAM,WAAW,0BAA0B;IACzC,2CAA2C,CAAC,EAAE,MAAM,EAAE,CAAC;CACxD;AAED,eAAO,MAAM,+BAA+B,64BAsBO,CAAC;AAEpD,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,cAAc,EAAE,EACxB,SAAS,EAAE,iBAAiB,EAAE,EAC9B,KAAK,EAAE,gBAAgB,EAAE,EACzB,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,0BAA+B,GAC1C,MAAM,CA0BR"}
@@ -0,0 +1,45 @@
1
+ export const CONSTITUTION_EVAL_SYSTEM_PROMPT = `You are an epistemic quality auditor. You evaluate whether reasoning meets specific standards of intellectual rigour.
2
+
3
+ You will be given:
4
+ 1. A set of extracted claims with types and scopes
5
+ 2. Logical relations between those claims
6
+ 3. A set of epistemic rules to evaluate
7
+
8
+ For each rule, determine:
9
+ - "satisfied": The reasoning clearly meets this standard
10
+ - "violated": The reasoning clearly fails this standard
11
+ - "uncertain": Cannot determine from available information
12
+ - "not_applicable": The rule does not apply to this text
13
+
14
+ Be conservative: prefer "uncertain" over false "violated".
15
+ Every violation must cite specific claim IDs.
16
+ Every violation must include a remediation suggestion.
17
+
18
+ Return JSON only as an array. Each object must include:
19
+ - rule_id
20
+ - status
21
+ - affected_claim_ids (array of claim IDs)
22
+ - rationale
23
+ - remediation (required when status is "violated")`;
24
+ export function buildConstitutionEvalUserPrompt(claims, relations, rules, originalText, heuristics = {}) {
25
+ const payload = {
26
+ original_text_preview: originalText.slice(0, 3000),
27
+ claims: claims.map((claim) => ({
28
+ id: claim.id,
29
+ text: claim.text,
30
+ claim_type: claim.claim_type,
31
+ scope: claim.scope,
32
+ confidence: claim.confidence
33
+ })),
34
+ relations,
35
+ rules: rules.map((rule) => ({
36
+ id: rule.id,
37
+ name: rule.name,
38
+ description: rule.description,
39
+ severity: rule.severity,
40
+ applies_to: rule.applies_to
41
+ })),
42
+ heuristics
43
+ };
44
+ return `Evaluate the rules against this argument structure and return JSON only.\n\n${JSON.stringify(payload, null, 2)}`;
45
+ }
@@ -0,0 +1,4 @@
1
+ import type { ExtractedClaim, ExtractedRelation } from "@restormel/contracts/verification";
2
+ export declare const REASONING_EVAL_SYSTEM_PROMPT = "You evaluate reasoning quality, not factual truth.\n\nScore exactly six dimensions from 0.0 to 1.0:\n1. logical_structure\n2. evidence_grounding\n3. counterargument_coverage\n4. scope_calibration\n5. assumption_transparency\n6. internal_consistency\n\nFor each dimension return:\n- dimension\n- score\n- explanation (1-2 sentences)\n- flagged_claims (array of claim IDs)\n\nCalibrate scores conservatively:\n- 0.5 = average reasoning quality\n- 0.8+ = strong reasoning\n- <0.3 = major reasoning failure\n\nReturn JSON only as an array of six objects in the exact order above.";
3
+ export declare function buildReasoningEvalUserPrompt(claims: ExtractedClaim[], relations: ExtractedRelation[], originalText: string): string;
4
+ //# sourceMappingURL=reasoning-eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning-eval.d.ts","sourceRoot":"","sources":["../../src/prompts/reasoning-eval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAE3F,eAAO,MAAM,4BAA4B,okBAqB6B,CAAC;AAEvE,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,cAAc,EAAE,EACxB,SAAS,EAAE,iBAAiB,EAAE,EAC9B,YAAY,EAAE,MAAM,GACnB,MAAM,CAgBR"}
@@ -0,0 +1,36 @@
1
+ export const REASONING_EVAL_SYSTEM_PROMPT = `You evaluate reasoning quality, not factual truth.
2
+
3
+ Score exactly six dimensions from 0.0 to 1.0:
4
+ 1. logical_structure
5
+ 2. evidence_grounding
6
+ 3. counterargument_coverage
7
+ 4. scope_calibration
8
+ 5. assumption_transparency
9
+ 6. internal_consistency
10
+
11
+ For each dimension return:
12
+ - dimension
13
+ - score
14
+ - explanation (1-2 sentences)
15
+ - flagged_claims (array of claim IDs)
16
+
17
+ Calibrate scores conservatively:
18
+ - 0.5 = average reasoning quality
19
+ - 0.8+ = strong reasoning
20
+ - <0.3 = major reasoning failure
21
+
22
+ Return JSON only as an array of six objects in the exact order above.`;
23
+ export function buildReasoningEvalUserPrompt(claims, relations, originalText) {
24
+ const claimLines = claims
25
+ .map((claim, index) => {
26
+ return `${index + 1}. [${claim.id}] (${claim.claim_type}, scope=${claim.scope}, conf=${claim.confidence.toFixed(2)}) ${claim.text}`;
27
+ })
28
+ .join('\n');
29
+ const relationLines = relations
30
+ .map((relation) => {
31
+ return `- ${relation.from_claim_id} ${relation.relation_type} ${relation.to_claim_id} (conf=${relation.confidence.toFixed(2)}): ${relation.rationale}`;
32
+ })
33
+ .join('\n');
34
+ const textPreview = originalText.slice(0, 2000);
35
+ return `ORIGINAL TEXT (truncated to 2000 chars):\n${textPreview}\n\nEXTRACTED CLAIMS:\n${claimLines || '(none)'}\n\nEXTRACTED RELATIONS:\n${relationLines || '(none)'}\n\nEvaluate the reasoning quality of this argument structure and return JSON only.`;
36
+ }
@@ -0,0 +1,4 @@
1
+ import type { VerificationRequest } from "@restormel/contracts/verification";
2
+ export declare const VERIFICATION_EXTRACTION_SYSTEM_PROMPT = "You extract atomic claims and logical relations from arbitrary domain text.\n\nReturn your answer as prose followed by a required sophia-meta fenced code block.\nThe sophia-meta block must contain valid JSON with this shape:\n{\n \"claims\": [{\n \"id\": \"claim_001\",\n \"text\": \"...\",\n \"claim_type\": \"empirical|causal|explanatory|normative|predictive|definitional|procedural\",\n \"scope\": \"narrow|moderate|broad|universal\",\n \"confidence\": 0.0,\n \"source_span\": \"...\",\n \"source_span_start\": 0,\n \"source_span_end\": 0\n }],\n \"relations\": [{\n \"from_claim_id\": \"claim_001\",\n \"to_claim_id\": \"claim_002\",\n \"relation_type\": \"supports|contradicts|depends_on|responds_to|defines|qualifies\",\n \"confidence\": 0.0,\n \"rationale\": \"...\"\n }]\n}\n\nRequirements:\n- Claims must be atomic and self-contained.\n- Only include relations where both claim IDs exist.\n- Confidence values must be in [0,1].\n- Output JSON only in the sophia-meta block; no markdown lists inside it.";
3
+ export declare function buildVerificationExtractionUserPrompt(request: VerificationRequest): string;
4
+ //# sourceMappingURL=verification-extraction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-extraction.d.ts","sourceRoot":"","sources":["../../src/prompts/verification-extraction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAE7E,eAAO,MAAM,qCAAqC,miCA4BwB,CAAC;AAE3E,wBAAgB,qCAAqC,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAsB1F"}
@@ -0,0 +1,46 @@
1
+ export const VERIFICATION_EXTRACTION_SYSTEM_PROMPT = `You extract atomic claims and logical relations from arbitrary domain text.
2
+
3
+ Return your answer as prose followed by a required sophia-meta fenced code block.
4
+ The sophia-meta block must contain valid JSON with this shape:
5
+ {
6
+ "claims": [{
7
+ "id": "claim_001",
8
+ "text": "...",
9
+ "claim_type": "empirical|causal|explanatory|normative|predictive|definitional|procedural",
10
+ "scope": "narrow|moderate|broad|universal",
11
+ "confidence": 0.0,
12
+ "source_span": "...",
13
+ "source_span_start": 0,
14
+ "source_span_end": 0
15
+ }],
16
+ "relations": [{
17
+ "from_claim_id": "claim_001",
18
+ "to_claim_id": "claim_002",
19
+ "relation_type": "supports|contradicts|depends_on|responds_to|defines|qualifies",
20
+ "confidence": 0.0,
21
+ "rationale": "..."
22
+ }]
23
+ }
24
+
25
+ Requirements:
26
+ - Claims must be atomic and self-contained.
27
+ - Only include relations where both claim IDs exist.
28
+ - Confidence values must be in [0,1].
29
+ - Output JSON only in the sophia-meta block; no markdown lists inside it.`;
30
+ export function buildVerificationExtractionUserPrompt(request) {
31
+ const parts = [];
32
+ if (request.domain_hint) {
33
+ parts.push(`DOMAIN CONTEXT: This text is from the ${request.domain_hint} domain. Apply domain-appropriate interpretation.`);
34
+ }
35
+ if (request.question?.trim()) {
36
+ parts.push(`QUESTION:\n${request.question.trim()}`);
37
+ }
38
+ if (request.answer?.trim()) {
39
+ parts.push(`ANSWER:\n${request.answer.trim()}`);
40
+ }
41
+ if (request.text?.trim()) {
42
+ parts.push(`TEXT:\n${request.text.trim()}`);
43
+ }
44
+ parts.push('Extract claims and relations from the provided content.');
45
+ return parts.join('\n\n');
46
+ }
@@ -0,0 +1,15 @@
1
+ import { type ExtractedClaim, type ExtractedRelation, type ReasoningEvaluation, type VerificationRequest } from "@restormel/contracts/verification";
2
+ import type { ReasoningCoreContext } from "./context.js";
3
+ export interface ReasoningEvaluationResult {
4
+ evaluation: ReasoningEvaluation;
5
+ route: {
6
+ provider: string;
7
+ modelId: string;
8
+ routeId: string | null;
9
+ reason: string | null;
10
+ };
11
+ }
12
+ export declare function evaluateReasoning(claims: ExtractedClaim[], relations: ExtractedRelation[], request: VerificationRequest, ctx: ReasoningCoreContext, options?: {
13
+ providerApiKeys?: unknown;
14
+ }): Promise<ReasoningEvaluationResult>;
15
+ //# sourceMappingURL=reasoning-eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning-eval.d.ts","sourceRoot":"","sources":["../src/reasoning-eval.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAmCzD,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,mBAAmB,CAAC;IAChC,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,CAAC;CACH;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,cAAc,EAAE,EACxB,SAAS,EAAE,iBAAiB,EAAE,EAC9B,OAAO,EAAE,mBAAmB,EAC5B,GAAG,EAAE,oBAAoB,EACzB,OAAO,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GACtC,OAAO,CAAC,yBAAyB,CAAC,CAyCpC"}
@@ -0,0 +1,69 @@
1
+ import { z } from "zod";
2
+ import { ReasoningScoreSchema, } from "@restormel/contracts/verification";
3
+ import { buildReasoningEvalUserPrompt, REASONING_EVAL_SYSTEM_PROMPT } from "./prompts/reasoning-eval.js";
4
+ const ReasoningScoresArraySchema = z.array(ReasoningScoreSchema).length(6);
5
+ const WEIGHTS = {
6
+ logical_structure: 0.25,
7
+ evidence_grounding: 0.2,
8
+ counterargument_coverage: 0.2,
9
+ scope_calibration: 0.15,
10
+ assumption_transparency: 0.1,
11
+ internal_consistency: 0.1,
12
+ };
13
+ function computeOverallScore(scores) {
14
+ const weighted = scores.reduce((sum, score) => {
15
+ const weight = WEIGHTS[score.dimension] ?? 0;
16
+ return sum + score.score * weight;
17
+ }, 0);
18
+ return Number(weighted.toFixed(4));
19
+ }
20
+ function extractJson(text) {
21
+ const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/);
22
+ if (fenced)
23
+ return fenced[1].trim();
24
+ const start = text.search(/[\[{]/);
25
+ return start >= 0 ? text.slice(start) : text;
26
+ }
27
+ function parseScores(text) {
28
+ const parsed = JSON.parse(extractJson(text));
29
+ return ReasoningScoresArraySchema.parse(parsed);
30
+ }
31
+ export async function evaluateReasoning(claims, relations, request, ctx, options) {
32
+ const originalText = [request.question, request.answer, request.text].filter(Boolean).join("\n\n");
33
+ const prompt = buildReasoningEvalUserPrompt(claims, relations, originalText);
34
+ const route = await ctx.resolveReasoningRoute({
35
+ depthMode: request.depth ?? "standard",
36
+ providerApiKeys: options?.providerApiKeys,
37
+ failureMode: "error",
38
+ });
39
+ for (let attempt = 0; attempt < 2; attempt += 1) {
40
+ const result = await ctx.generateText({
41
+ model: route.model,
42
+ system: REASONING_EVAL_SYSTEM_PROMPT,
43
+ prompt: attempt === 0 ? prompt : `${prompt}\n\nReturn ONLY valid JSON.`,
44
+ maxOutputTokens: 1200,
45
+ });
46
+ ctx.trackTokens?.(result.usage?.inputTokens ?? 0, result.usage?.outputTokens ?? 0);
47
+ try {
48
+ const dimensions = parseScores(result.text);
49
+ return {
50
+ evaluation: {
51
+ overall_score: computeOverallScore(dimensions),
52
+ dimensions,
53
+ },
54
+ route: {
55
+ provider: route.provider,
56
+ modelId: route.modelId,
57
+ routeId: route.resolvedRouteId ?? null,
58
+ reason: route.resolvedExplanation ?? null,
59
+ },
60
+ };
61
+ }
62
+ catch {
63
+ if (attempt === 1) {
64
+ throw new Error("Failed to parse reasoning evaluation JSON output");
65
+ }
66
+ }
67
+ }
68
+ throw new Error("Reasoning evaluation failed unexpectedly");
69
+ }