@remnic/bench 9.3.704 → 9.3.706
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/index.d.ts +42 -1
- package/dist/index.js +1134 -15
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -528,6 +528,47 @@ interface CustomBenchmarkSpec {
|
|
|
528
528
|
tasks: CustomBenchmarkTask[];
|
|
529
529
|
}
|
|
530
530
|
|
|
531
|
+
/** Generator options. Deterministic given an identical `seed`. */
|
|
532
|
+
interface MemCorrectGeneratorOptions {
|
|
533
|
+
/** Number of personas (each owns ≥2 namespaces). */
|
|
534
|
+
personaCount: number;
|
|
535
|
+
/** Facts per persona, spread across categories. */
|
|
536
|
+
factsPerPersona: number;
|
|
537
|
+
/** PRNG seed. */
|
|
538
|
+
seed: number;
|
|
539
|
+
/** Anchor "now"; all timestamps derive from this. */
|
|
540
|
+
nowIso: string;
|
|
541
|
+
/** Maintenance cycles applied between post-correction and post-reingest. */
|
|
542
|
+
maintenanceCycles: number;
|
|
543
|
+
/** Latency cap (in interaction turns) for `uptake_latency`. */
|
|
544
|
+
uptakeLatencyCap: number;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* The system-agnostic adapter contract. This is the public surface a
|
|
548
|
+
* third-party memory system implements to be scored on MemCorrect.
|
|
549
|
+
*
|
|
550
|
+
* Implementations MUST be isolated: `reset()` returns the system to a clean
|
|
551
|
+
* slate, and no call reaches into another system's durable store.
|
|
552
|
+
*/
|
|
553
|
+
interface MemCorrectSystemAdapter {
|
|
554
|
+
/** Human-readable label for artifact metadata (e.g. "remnic-native"). */
|
|
555
|
+
readonly label: string;
|
|
556
|
+
/** Reset to a clean slate before each scenario. */
|
|
557
|
+
reset(): Promise<void>;
|
|
558
|
+
/** Ingest one conversational turn through the system's normal observe path. */
|
|
559
|
+
ingestTurn(sessionKey: string, role: "user" | "assistant", text: string, at: string): Promise<void>;
|
|
560
|
+
/** Ranked memory/context strings for a probe query in a session. */
|
|
561
|
+
recall(query: string, sessionKey: string): Promise<string[]>;
|
|
562
|
+
/** However the system accepts a correction (explicit tool, turn, contract). */
|
|
563
|
+
correct(text: string, sessionKey: string, at?: string): Promise<void>;
|
|
564
|
+
/**
|
|
565
|
+
* Consolidation / dreams / pattern-reinforcement / contradiction scan.
|
|
566
|
+
* A no-op is allowed; the protocol runs this N times between phases and
|
|
567
|
+
* the `non_resurrection` metric measures whether retired facts survive it.
|
|
568
|
+
*/
|
|
569
|
+
runMaintenance(): Promise<void>;
|
|
570
|
+
}
|
|
571
|
+
|
|
531
572
|
/**
|
|
532
573
|
* Shared types for inbox fixture generators.
|
|
533
574
|
*/
|
|
@@ -3832,4 +3873,4 @@ interface MitigatedTargetConfig {
|
|
|
3832
3873
|
*/
|
|
3833
3874
|
declare function createMitigatedTarget(config: MitigatedTargetConfig): ExtractionAttackTarget;
|
|
3834
3875
|
|
|
3835
|
-
export { AMA_BENCH_DIAGNOSTIC_VARIANTS, ASSISTANT_AGENT_CONFIG_KEY, ASSISTANT_JUDGE_CONFIG_KEY, ASSISTANT_MEETING_PREP_SCENARIOS, ASSISTANT_MEETING_PREP_SMOKE_SCENARIOS, ASSISTANT_MORNING_BRIEF_SCENARIOS, ASSISTANT_MORNING_BRIEF_SMOKE_SCENARIOS, ASSISTANT_NEXT_BEST_ACTION_SCENARIOS, ASSISTANT_NEXT_BEST_ACTION_SMOKE_SCENARIOS, ASSISTANT_RUBRIC_DIMENSIONS, ASSISTANT_RUBRIC_ID_KEY, ASSISTANT_SEEDS_CONFIG_KEY, ASSISTANT_SPOT_CHECK_DIR_KEY, ASSISTANT_SYNTHESIS_SCENARIOS, ASSISTANT_SYNTHESIS_SMOKE_SCENARIOS, type AbstentionRetrievalCase, type AggregateMetrics, type AmaBenchDiagnosticAdapterOptions, type AmaBenchDiagnosticAnswererMode, type AmaBenchDiagnosticBreakdown, type AmaBenchDiagnosticMatrixArtifact, type AmaBenchDiagnosticRecallMode, type AmaBenchDiagnosticRunContext, type AmaBenchDiagnosticTaskEvidence, type AmaBenchDiagnosticTaskRow, type AmaBenchDiagnosticVariant, type AmaBenchDiagnosticVariantSummary, type AnthropicProviderConfig, type AssistantAgent, type AssistantMemoryFact, type AssistantMemoryGraph, type AssistantRubricDimension, type AssistantRubricScores, type AssistantRunnerOptions, type AssistantScenario, type AssistantStance, type AttackRecallOptions, type AttackRetrievalHit, type AttackerMode, BENCHMARK_ARTIFACT_SCHEMA_VERSION, BENCHMARK_INTEGRITY_META_SCHEMA, BENCHMARK_REPRO_MANIFEST_FILENAME, BENCHMARK_REPRO_MANIFEST_SCHEMA_VERSION, BENCHMARK_RESULT_SCHEMA, BENCHMARK_SPLIT_TYPES, type BaselineRow, type BaselineScenario, type BeamDatasetPreview, type BenchConfig, type BenchJudge, type BenchJudgeResult, type BenchMemoryAdapter, type BenchModelSource, type BenchReasoningEffort, type BenchRecallOptions, type BenchResponder, type BenchResponse, type BenchRuntimeProfile, type BenchTier, type BenchmarkArtifact, type BenchmarkArtifactEnvironment, type BenchmarkArtifactHardware, type BenchmarkArtifactJudgeCalibration, type BenchmarkArtifactPerTaskScore, type BenchmarkArtifactSystem, type BenchmarkArtifactTier, type BenchmarkCategory, type BenchmarkDefinition, type BenchmarkIntegrityMeta, type BenchmarkMeta, type BenchmarkMode, type BenchmarkReport, type BenchmarkReproManifest, type BenchmarkReproManifestDataset, type BenchmarkReproManifestFile, type BenchmarkReproManifestResult, type BenchmarkResult, type BenchmarkSplitType, type BenchmarkStatus, type BenchmarkSuiteResult, type BenchmarkTier, type BuildBenchmarkArtifactInput, type BuildBenchmarkPublishFeedOptions, type BuildBenchmarkReproManifestOptions, type BuiltInProvider, CALIBRATION_SLICE_SIZE, CANARY_FIXED_RECALL, CANARY_SCORE_FLOOR, type CalibrationAnswer, type CalibrationVerdictPair, type CanaryAdapterOptions, type CanaryFloorCheck, type CodexCliProviderConfig, type CohenKappaResult, type ComparisonMetricDelta, type ComparisonResult, type CompletionOpts, type CompletionResult, type ConfidenceInterval, type ContaminationCheckResult, type ContaminationEntry, type ContaminationManifest, type CustomBenchmarkScoring, type CustomBenchmarkSpec, type CustomBenchmarkTask, DEFAULT_ABLATION_BOOTSTRAP_SEED, DEFAULT_ASSISTANT_RUBRIC_ID, DEFAULT_BASELINE_SCENARIOS, DEFAULT_JUDGE_BINARIZATION_THRESHOLD, type DatasetSource, type DiscoveredModel, EMPTY_CONTAMINATION_MANIFEST, type EffectSizeInterpretation, type EffectSizeSummary, type ExplainResult, type ExtractedEntity, type ExtractedLink, type ExtractedPage, type ExtractionAttackOptions, type ExtractionAttackResult, type ExtractionAttackTarget, type FixtureGenerator, type FixtureOutput, type FixtureVariant, type GeneratedFile, type GoldEntity, type GoldEntityType, type GoldGraph, type GoldLink, type GoldPage, type HarnessRng, INTEGRITY_CIPHER_ALGORITHM, INTEGRITY_HASH_ALGORITHM, INTEGRITY_META_FIELDS, type IngestionBenchAdapter, type IngestionLog, JUDGE_CALIBRATION_KAPPA_THRESHOLD, type JudgeCalibrationIdentities, type JudgeCalibrationResult, type JudgeCategory, LOCAL_LAB_PROVIDER_KINDS, LOCOMO_DATASET_FILENAMES, LONG_MEM_EVAL_DATASET_FILENAMES, type LeaderboardArtifactWrite, type LlmJudge, type LlmProvider, type LoadDatasetOptions, type LoadSealedQrelsOptions, type LoadedDataset, type LoadedJudgeCalibrationState, type LocalLabManifest, type LocalLabManifestNotes, type LocalLabPhase, type LocalLabPhaseDescriptor, type LocalLabPhaseExecute, type LocalLabPhaseName, type LocalLabPhaseOutcome, LocalLabPreflightError, type LocalLabPreflightFailure, type LocalLabPreflightInput, type LocalLabPreflightOptions, type LocalLabPreflightResult, type LocalLabPreflightSuccess, type LocalLabProviderKind, type LocalLabRoleConfig, type LocalLlmProviderConfig, MEMORY_EVAL_DIMENSIONS, MEMORY_EVAL_PUBLIC_LINE, MIN_CALIBRATION_SOURCE_TASKS, MITIGATED_BASELINE_SCENARIOS, type MemoryEvalCategory, type MemoryEvalDimension, type MemoryEvalDimensionId, type MemoryEvalMetric, type MemoryGraph, type MemoryStats, type MemorySystem, type Message, type MetricAggregate, type MitigatedBaselineConfig, type MitigatedTargetConfig, type MultipleChoiceQuestion, OTHER_NAMESPACE_MEMORIES, type OllamaProviderConfig, type OpenAiCompatibleProviderConfig, PROCEDURAL_REAL_SCENARIOS, PROCEDURAL_REAL_SCENARIOS_SMOKE, PUBLISHED_BENCHMARK_ARTIFACT_IDS, type PersonalizationRetrievalCase, type PreflightDiscoveredModel, type ProceduralAblationArtifact, type ProceduralAblationPerCase, type ProceduralAblationScenario, type ProceduralRealScenario, type ProceduralRealScenarioCategory, type ProviderBaseConfig, type ProviderConfig, type ProviderDiscoveryResult, type ProviderFactoryConfig, type PublishSkipReason, type PublishSkipRecord, type PublishedBenchmarkFeed, type PublishedBenchmarkFeedEntry, type PublishedBenchmarkId, REQUIRED_FRONTMATTER_FIELDS, type RecallMetrics, type RecoveredMemory, type RegressionDetail, type RegressionGateResult, type RemnicAdapterOptions, type ResolveBenchRuntimeProfileOptions, type ResolvedBenchRuntimeProfile, type ResolvedLocalLabProfile, type ResolvedLocalLabRole, type ResolvedRunBenchmarkOptions, type RotatedChoices, type RunBenchmarkOptions, type RunJudgeCalibrationOptions, type RunProceduralAblationCliArgs, type RunProceduralAblationOptions, type RunSequentialPhasesOptions, SCHEMA_TIER_FIXTURE, SCHEMA_TIER_SMOKE_FIXTURE, SEALED_PROMPT_REGISTRY, SYNTHETIC_MEMORIES, type SanitizedDiagnosticProvider, type SavedBaseline, type SchemaTierCorpus, type SchemaTierFixture, type SchemaTierName, type SchemaTierPage, type SchemaTierPageFrontmatter, type SealedArtifact, type SealedJudgeDecision, type SealedJudgeInput, type SealedQrelsArtifact, type SealedQrelsHandle, type SealedRubric, type SearchResult, type SeededMemory, type SeededRng, type SequentialPhaseHooks, type SpotCheckLogger, type StatisticalReport, type StructuredJudge, type SyntheticEmailIngestionAdapterOptions, type SyntheticTargetOptions, type TaskResult, type TaskTokenUsage, type TemporalRetrievalCase, type TierDetail, type TimelineEntry, type TokenUsage, type WriteBenchmarkArtifactResult, addContaminationEntry, aggregateTaskScores, answerBenchmarkQuestion, assertCanaryUnderFloor, assertIntegrityMetaPresent, assertPublishableIntegrity, assertSha256Hex, assistantMeetingPrepDefinition, assistantMorningBriefDefinition, assistantNextBestActionDefinition, assistantSynthesisDefinition, backlinkF1, binarizeJudgeScore, bootstrapMeanConfidenceInterval, buildAmaBenchDiagnosticMatrixArtifact, buildAmaBenchDiagnosticVariantSummary, buildAmaBenchLeaderboardRows, buildBenchmarkArtifact, buildBenchmarkArtifactFilename, buildBenchmarkPublishFeed, buildBenchmarkReproManifest, buildBenchmarkRunSeeds, buildJudgePayload, buildOracleTrajectoryRecall, buildSchemaTierFixture, buildSchemaTierSmokeFixture, calendarFixture, canonicalJsonStringify, chatFixture, checkDatasetContamination, checkRegression, clampScore, cohensD, compareResults, computeCohensKappa, computeSealHash, containsAnswer, createSeededRng as createAdamSeededRng, createAmaBenchDiagnosticAdapter, createAnthropicProvider, createCanaryAdapter, createCodexCliProvider, createDeterministicSpotCheckLogger, createGatewayResponder, createLightweightAdapter, createLiteLlmProvider, createLocalLlmProvider, createMitigatedTarget, createOllamaProvider, createOpenAiCompatibleProvider, createSeededRandom as createProceduralAblationSeededRandom, createProvider, createProviderBackedAmaBenchRecommendedJudge, createProviderBackedJudge, createProviderBackedResponder, createProviderBackedStructuredJudge, createRemnicAdapter, createResponderFromProvider, createSeededRng$1 as createSeededRng, createSpotCheckFileLogger, createStructuredJudgeFromProvider, createSyntheticEmailIngestionAdapter, createSyntheticTarget, createTimeoutGuardedAdapter, defaultBenchmarkBaselineDir, defaultBenchmarkPublishPath, deleteBenchmarkResults, discoverAllProviders, discoveryEndpointFor, emailFixture, entityRecall, exactMatch, extractMarkdownSectionsByTitle, f1Score, fixtureToAblationScenarios, formatHandoffNote, formatMissingDatasetError, generateReport, getBenchmark, getBenchmarkLowerIsBetter, getMemoryEvalDimension, getRemnicVersion, hashBenchmarkArtifact, hashBytes, hashCanonicalJson, hashString, integrityMetaIsComplete, interpretEffectSize, isAmaBenchUnknownLikeAnswer, isContaminationEntry, isContaminationManifest, isSealedQrelsArtifact, isSha256Hex, linkMatches, listBenchmarkBaselines, listBenchmarkResults, listBenchmarks, listMemoryEvalBenchmarkIds, listMemoryEvalDimensions, llmJudgeScore, llmJudgeScoreDetailed, loadAblationFixture, loadBaseline, loadBeamDatasetPreview, loadBenchmarkArtifact, loadBenchmarkBaseline, loadBenchmarkResult, loadCustomBenchmarkFile, loadJudgeCalibrationState, loadLoCoMo10, loadLocalLabManifest, loadLongMemEvalS, loadSealKeyFromEnv, loadSealedQrels, loadSealedRubric, matchEntity, mergeContaminationManifests, openSeal, orchestrateBenchmarkRuns, pairedDeltaConfidenceInterval, parseBenchmarkArtifact, parseCustomBenchmark, parseLocalLabManifest, parseRubricResponse, parseSealedQrels, precisionAtK, preflightLocalLabRole, projectFolderFixture, recallAtK, redactBenchmarkResultSecrets, renderBaselineMarkdown, renderBenchmarkResultExport, renderMemorySummaryForJudge, renderMemoryViewForAgent, resolveAssistantAgent, resolveAssistantRubricId, resolveAssistantSeeds, resolveAssistantSpotCheckDir, resolveBenchRuntimeProfile, resolveBenchmarkPhaseTimeoutMs, resolveBenchmarkProgressLogging, resolveBenchmarkResultReference, resolveBenchmarkRunCount, resolveLocalLabProfile, resolveLocalLabRole, resolveStructuredJudge, rotateDistractors, rougeL, runAssistantBenchmark, runAssistantMeetingPrepBenchmark, runAssistantMorningBriefBenchmark, runAssistantNextBestActionBenchmark, runAssistantSynthesisBenchmark, runBaseline, runBenchSuite, runBenchmark, runCustomBenchmarkFile, runExplain, runExtractionAttack, runJudgeCalibration, runMitigatedBaseline, runProceduralAblation, runProceduralAblationCli, runSealedJudge, runSequentialPhases, safeHexEqual, saveBaseline, saveBenchmarkBaseline, schemaCompleteness, sealPayload, selectAmaBenchDiagnosticVariants, selectCalibrationSlice, selectFixtureVariant, serializeBenchmarkArtifact, serializeJsonl, serializeSealedQrels, shuffleTasks, timed, verifyRubricDigest, writeBenchmarkArtifact, writeBenchmarkPublishFeed, writeBenchmarkReproManifest, writeBenchmarkResult, writeJudgeCalibrationState, writeLeaderboardArtifactsForResult, zeroScores };
|
|
3876
|
+
export { AMA_BENCH_DIAGNOSTIC_VARIANTS, ASSISTANT_AGENT_CONFIG_KEY, ASSISTANT_JUDGE_CONFIG_KEY, ASSISTANT_MEETING_PREP_SCENARIOS, ASSISTANT_MEETING_PREP_SMOKE_SCENARIOS, ASSISTANT_MORNING_BRIEF_SCENARIOS, ASSISTANT_MORNING_BRIEF_SMOKE_SCENARIOS, ASSISTANT_NEXT_BEST_ACTION_SCENARIOS, ASSISTANT_NEXT_BEST_ACTION_SMOKE_SCENARIOS, ASSISTANT_RUBRIC_DIMENSIONS, ASSISTANT_RUBRIC_ID_KEY, ASSISTANT_SEEDS_CONFIG_KEY, ASSISTANT_SPOT_CHECK_DIR_KEY, ASSISTANT_SYNTHESIS_SCENARIOS, ASSISTANT_SYNTHESIS_SMOKE_SCENARIOS, type AbstentionRetrievalCase, type AggregateMetrics, type AmaBenchDiagnosticAdapterOptions, type AmaBenchDiagnosticAnswererMode, type AmaBenchDiagnosticBreakdown, type AmaBenchDiagnosticMatrixArtifact, type AmaBenchDiagnosticRecallMode, type AmaBenchDiagnosticRunContext, type AmaBenchDiagnosticTaskEvidence, type AmaBenchDiagnosticTaskRow, type AmaBenchDiagnosticVariant, type AmaBenchDiagnosticVariantSummary, type AnthropicProviderConfig, type AssistantAgent, type AssistantMemoryFact, type AssistantMemoryGraph, type AssistantRubricDimension, type AssistantRubricScores, type AssistantRunnerOptions, type AssistantScenario, type AssistantStance, type AttackRecallOptions, type AttackRetrievalHit, type AttackerMode, BENCHMARK_ARTIFACT_SCHEMA_VERSION, BENCHMARK_INTEGRITY_META_SCHEMA, BENCHMARK_REPRO_MANIFEST_FILENAME, BENCHMARK_REPRO_MANIFEST_SCHEMA_VERSION, BENCHMARK_RESULT_SCHEMA, BENCHMARK_SPLIT_TYPES, type BaselineRow, type BaselineScenario, type BeamDatasetPreview, type BenchConfig, type BenchJudge, type BenchJudgeResult, type BenchMemoryAdapter, type BenchModelSource, type BenchReasoningEffort, type BenchRecallOptions, type BenchResponder, type BenchResponse, type BenchRuntimeProfile, type BenchTier, type BenchmarkArtifact, type BenchmarkArtifactEnvironment, type BenchmarkArtifactHardware, type BenchmarkArtifactJudgeCalibration, type BenchmarkArtifactPerTaskScore, type BenchmarkArtifactSystem, type BenchmarkArtifactTier, type BenchmarkCategory, type BenchmarkDefinition, type BenchmarkIntegrityMeta, type BenchmarkMeta, type BenchmarkMode, type BenchmarkReport, type BenchmarkReproManifest, type BenchmarkReproManifestDataset, type BenchmarkReproManifestFile, type BenchmarkReproManifestResult, type BenchmarkResult, type BenchmarkSplitType, type BenchmarkStatus, type BenchmarkSuiteResult, type BenchmarkTier, type BuildBenchmarkArtifactInput, type BuildBenchmarkPublishFeedOptions, type BuildBenchmarkReproManifestOptions, type BuiltInProvider, CALIBRATION_SLICE_SIZE, CANARY_FIXED_RECALL, CANARY_SCORE_FLOOR, type CalibrationAnswer, type CalibrationVerdictPair, type CanaryAdapterOptions, type CanaryFloorCheck, type CodexCliProviderConfig, type CohenKappaResult, type ComparisonMetricDelta, type ComparisonResult, type CompletionOpts, type CompletionResult, type ConfidenceInterval, type ContaminationCheckResult, type ContaminationEntry, type ContaminationManifest, type CustomBenchmarkScoring, type CustomBenchmarkSpec, type CustomBenchmarkTask, DEFAULT_ABLATION_BOOTSTRAP_SEED, DEFAULT_ASSISTANT_RUBRIC_ID, DEFAULT_BASELINE_SCENARIOS, DEFAULT_JUDGE_BINARIZATION_THRESHOLD, type DatasetSource, type DiscoveredModel, EMPTY_CONTAMINATION_MANIFEST, type EffectSizeInterpretation, type EffectSizeSummary, type ExplainResult, type ExtractedEntity, type ExtractedLink, type ExtractedPage, type ExtractionAttackOptions, type ExtractionAttackResult, type ExtractionAttackTarget, type FixtureGenerator, type FixtureOutput, type FixtureVariant, type GeneratedFile, type GoldEntity, type GoldEntityType, type GoldGraph, type GoldLink, type GoldPage, type HarnessRng, INTEGRITY_CIPHER_ALGORITHM, INTEGRITY_HASH_ALGORITHM, INTEGRITY_META_FIELDS, type IngestionBenchAdapter, type IngestionLog, JUDGE_CALIBRATION_KAPPA_THRESHOLD, type JudgeCalibrationIdentities, type JudgeCalibrationResult, type JudgeCategory, LOCAL_LAB_PROVIDER_KINDS, LOCOMO_DATASET_FILENAMES, LONG_MEM_EVAL_DATASET_FILENAMES, type LeaderboardArtifactWrite, type LlmJudge, type LlmProvider, type LoadDatasetOptions, type LoadSealedQrelsOptions, type LoadedDataset, type LoadedJudgeCalibrationState, type LocalLabManifest, type LocalLabManifestNotes, type LocalLabPhase, type LocalLabPhaseDescriptor, type LocalLabPhaseExecute, type LocalLabPhaseName, type LocalLabPhaseOutcome, LocalLabPreflightError, type LocalLabPreflightFailure, type LocalLabPreflightInput, type LocalLabPreflightOptions, type LocalLabPreflightResult, type LocalLabPreflightSuccess, type LocalLabProviderKind, type LocalLabRoleConfig, type LocalLlmProviderConfig, MEMORY_EVAL_DIMENSIONS, MEMORY_EVAL_PUBLIC_LINE, MIN_CALIBRATION_SOURCE_TASKS, MITIGATED_BASELINE_SCENARIOS, type MemCorrectGeneratorOptions, type MemCorrectSystemAdapter, type MemoryEvalCategory, type MemoryEvalDimension, type MemoryEvalDimensionId, type MemoryEvalMetric, type MemoryGraph, type MemoryStats, type MemorySystem, type Message, type MetricAggregate, type MitigatedBaselineConfig, type MitigatedTargetConfig, type MultipleChoiceQuestion, OTHER_NAMESPACE_MEMORIES, type OllamaProviderConfig, type OpenAiCompatibleProviderConfig, PROCEDURAL_REAL_SCENARIOS, PROCEDURAL_REAL_SCENARIOS_SMOKE, PUBLISHED_BENCHMARK_ARTIFACT_IDS, type PersonalizationRetrievalCase, type PreflightDiscoveredModel, type ProceduralAblationArtifact, type ProceduralAblationPerCase, type ProceduralAblationScenario, type ProceduralRealScenario, type ProceduralRealScenarioCategory, type ProviderBaseConfig, type ProviderConfig, type ProviderDiscoveryResult, type ProviderFactoryConfig, type PublishSkipReason, type PublishSkipRecord, type PublishedBenchmarkFeed, type PublishedBenchmarkFeedEntry, type PublishedBenchmarkId, REQUIRED_FRONTMATTER_FIELDS, type RecallMetrics, type RecoveredMemory, type RegressionDetail, type RegressionGateResult, type RemnicAdapterOptions, type ResolveBenchRuntimeProfileOptions, type ResolvedBenchRuntimeProfile, type ResolvedLocalLabProfile, type ResolvedLocalLabRole, type ResolvedRunBenchmarkOptions, type RotatedChoices, type RunBenchmarkOptions, type RunJudgeCalibrationOptions, type RunProceduralAblationCliArgs, type RunProceduralAblationOptions, type RunSequentialPhasesOptions, SCHEMA_TIER_FIXTURE, SCHEMA_TIER_SMOKE_FIXTURE, SEALED_PROMPT_REGISTRY, SYNTHETIC_MEMORIES, type SanitizedDiagnosticProvider, type SavedBaseline, type SchemaTierCorpus, type SchemaTierFixture, type SchemaTierName, type SchemaTierPage, type SchemaTierPageFrontmatter, type SealedArtifact, type SealedJudgeDecision, type SealedJudgeInput, type SealedQrelsArtifact, type SealedQrelsHandle, type SealedRubric, type SearchResult, type SeededMemory, type SeededRng, type SequentialPhaseHooks, type SpotCheckLogger, type StatisticalReport, type StructuredJudge, type SyntheticEmailIngestionAdapterOptions, type SyntheticTargetOptions, type TaskResult, type TaskTokenUsage, type TemporalRetrievalCase, type TierDetail, type TimelineEntry, type TokenUsage, type WriteBenchmarkArtifactResult, addContaminationEntry, aggregateTaskScores, answerBenchmarkQuestion, assertCanaryUnderFloor, assertIntegrityMetaPresent, assertPublishableIntegrity, assertSha256Hex, assistantMeetingPrepDefinition, assistantMorningBriefDefinition, assistantNextBestActionDefinition, assistantSynthesisDefinition, backlinkF1, binarizeJudgeScore, bootstrapMeanConfidenceInterval, buildAmaBenchDiagnosticMatrixArtifact, buildAmaBenchDiagnosticVariantSummary, buildAmaBenchLeaderboardRows, buildBenchmarkArtifact, buildBenchmarkArtifactFilename, buildBenchmarkPublishFeed, buildBenchmarkReproManifest, buildBenchmarkRunSeeds, buildJudgePayload, buildOracleTrajectoryRecall, buildSchemaTierFixture, buildSchemaTierSmokeFixture, calendarFixture, canonicalJsonStringify, chatFixture, checkDatasetContamination, checkRegression, clampScore, cohensD, compareResults, computeCohensKappa, computeSealHash, containsAnswer, createSeededRng as createAdamSeededRng, createAmaBenchDiagnosticAdapter, createAnthropicProvider, createCanaryAdapter, createCodexCliProvider, createDeterministicSpotCheckLogger, createGatewayResponder, createLightweightAdapter, createLiteLlmProvider, createLocalLlmProvider, createMitigatedTarget, createOllamaProvider, createOpenAiCompatibleProvider, createSeededRandom as createProceduralAblationSeededRandom, createProvider, createProviderBackedAmaBenchRecommendedJudge, createProviderBackedJudge, createProviderBackedResponder, createProviderBackedStructuredJudge, createRemnicAdapter, createResponderFromProvider, createSeededRng$1 as createSeededRng, createSpotCheckFileLogger, createStructuredJudgeFromProvider, createSyntheticEmailIngestionAdapter, createSyntheticTarget, createTimeoutGuardedAdapter, defaultBenchmarkBaselineDir, defaultBenchmarkPublishPath, deleteBenchmarkResults, discoverAllProviders, discoveryEndpointFor, emailFixture, entityRecall, exactMatch, extractMarkdownSectionsByTitle, f1Score, fixtureToAblationScenarios, formatHandoffNote, formatMissingDatasetError, generateReport, getBenchmark, getBenchmarkLowerIsBetter, getMemoryEvalDimension, getRemnicVersion, hashBenchmarkArtifact, hashBytes, hashCanonicalJson, hashString, integrityMetaIsComplete, interpretEffectSize, isAmaBenchUnknownLikeAnswer, isContaminationEntry, isContaminationManifest, isSealedQrelsArtifact, isSha256Hex, linkMatches, listBenchmarkBaselines, listBenchmarkResults, listBenchmarks, listMemoryEvalBenchmarkIds, listMemoryEvalDimensions, llmJudgeScore, llmJudgeScoreDetailed, loadAblationFixture, loadBaseline, loadBeamDatasetPreview, loadBenchmarkArtifact, loadBenchmarkBaseline, loadBenchmarkResult, loadCustomBenchmarkFile, loadJudgeCalibrationState, loadLoCoMo10, loadLocalLabManifest, loadLongMemEvalS, loadSealKeyFromEnv, loadSealedQrels, loadSealedRubric, matchEntity, mergeContaminationManifests, openSeal, orchestrateBenchmarkRuns, pairedDeltaConfidenceInterval, parseBenchmarkArtifact, parseCustomBenchmark, parseLocalLabManifest, parseRubricResponse, parseSealedQrels, precisionAtK, preflightLocalLabRole, projectFolderFixture, recallAtK, redactBenchmarkResultSecrets, renderBaselineMarkdown, renderBenchmarkResultExport, renderMemorySummaryForJudge, renderMemoryViewForAgent, resolveAssistantAgent, resolveAssistantRubricId, resolveAssistantSeeds, resolveAssistantSpotCheckDir, resolveBenchRuntimeProfile, resolveBenchmarkPhaseTimeoutMs, resolveBenchmarkProgressLogging, resolveBenchmarkResultReference, resolveBenchmarkRunCount, resolveLocalLabProfile, resolveLocalLabRole, resolveStructuredJudge, rotateDistractors, rougeL, runAssistantBenchmark, runAssistantMeetingPrepBenchmark, runAssistantMorningBriefBenchmark, runAssistantNextBestActionBenchmark, runAssistantSynthesisBenchmark, runBaseline, runBenchSuite, runBenchmark, runCustomBenchmarkFile, runExplain, runExtractionAttack, runJudgeCalibration, runMitigatedBaseline, runProceduralAblation, runProceduralAblationCli, runSealedJudge, runSequentialPhases, safeHexEqual, saveBaseline, saveBenchmarkBaseline, schemaCompleteness, sealPayload, selectAmaBenchDiagnosticVariants, selectCalibrationSlice, selectFixtureVariant, serializeBenchmarkArtifact, serializeJsonl, serializeSealedQrels, shuffleTasks, timed, verifyRubricDigest, writeBenchmarkArtifact, writeBenchmarkPublishFeed, writeBenchmarkReproManifest, writeBenchmarkResult, writeJudgeCalibrationState, writeLeaderboardArtifactsForResult, zeroScores };
|
package/dist/index.js
CHANGED
|
@@ -7269,9 +7269,15 @@ function resolveContainedPath(root, ...segments) {
|
|
|
7269
7269
|
import { mkdir as mkdir6, writeFile as writeFile6 } from "fs/promises";
|
|
7270
7270
|
import path8 from "path";
|
|
7271
7271
|
async function writeLeaderboardArtifactsForResult(result, outputDir) {
|
|
7272
|
-
if (result.meta.benchmark
|
|
7273
|
-
return
|
|
7272
|
+
if (result.meta.benchmark === "ama-bench") {
|
|
7273
|
+
return writeAmaBenchLeaderboard(result, outputDir);
|
|
7274
|
+
}
|
|
7275
|
+
if (result.meta.benchmark === "memcorrect-v1") {
|
|
7276
|
+
return writeMemCorrectLeaderboard(result, outputDir);
|
|
7274
7277
|
}
|
|
7278
|
+
return [];
|
|
7279
|
+
}
|
|
7280
|
+
async function writeAmaBenchLeaderboard(result, outputDir) {
|
|
7275
7281
|
const rows = buildAmaBenchLeaderboardRows(result);
|
|
7276
7282
|
if (rows.length === 0) {
|
|
7277
7283
|
return [];
|
|
@@ -7291,6 +7297,29 @@ async function writeLeaderboardArtifactsForResult(result, outputDir) {
|
|
|
7291
7297
|
}
|
|
7292
7298
|
];
|
|
7293
7299
|
}
|
|
7300
|
+
async function writeMemCorrectLeaderboard(result, outputDir) {
|
|
7301
|
+
const row = buildMemCorrectLeaderboardRow(result);
|
|
7302
|
+
if (!row) return [];
|
|
7303
|
+
const outputRoot = path8.resolve(outputDir);
|
|
7304
|
+
const leaderboardDir = resolveContainedPath(outputRoot, "leaderboard");
|
|
7305
|
+
await mkdir6(leaderboardDir, { recursive: true });
|
|
7306
|
+
const timestamp = sanitizeFilenameSegment(result.meta.timestamp.replace(/[:.]/g, "-"));
|
|
7307
|
+
const safeAdapter = sanitizeFilenameSegment(row.adapter);
|
|
7308
|
+
const filePath = resolveContainedPath(
|
|
7309
|
+
leaderboardDir,
|
|
7310
|
+
`memcorrect-${safeAdapter}-${timestamp}.jsonl`
|
|
7311
|
+
);
|
|
7312
|
+
await writeFile6(filePath, `${JSON.stringify(row)}
|
|
7313
|
+
`, "utf8");
|
|
7314
|
+
return [
|
|
7315
|
+
{
|
|
7316
|
+
benchmark: "memcorrect-v1",
|
|
7317
|
+
path: filePath,
|
|
7318
|
+
format: "memcorrect-adapter-metrics-jsonl",
|
|
7319
|
+
records: 1
|
|
7320
|
+
}
|
|
7321
|
+
];
|
|
7322
|
+
}
|
|
7294
7323
|
function buildAmaBenchLeaderboardRows(result) {
|
|
7295
7324
|
const rowsByEpisode = /* @__PURE__ */ new Map();
|
|
7296
7325
|
result.results.tasks.forEach((task, taskIndex) => {
|
|
@@ -7316,6 +7345,34 @@ function buildAmaBenchLeaderboardRows(result) {
|
|
|
7316
7345
|
answer_list: row.answers
|
|
7317
7346
|
}));
|
|
7318
7347
|
}
|
|
7348
|
+
function buildMemCorrectLeaderboardRow(result) {
|
|
7349
|
+
const aggregate = result.config.benchmarkOptions?.aggregateMetrics;
|
|
7350
|
+
if (!aggregate) return null;
|
|
7351
|
+
const adapter = typeof result.config.adapterMode === "string" ? result.config.adapterMode : "unknown";
|
|
7352
|
+
const provenance = aggregate.provenance_fidelity;
|
|
7353
|
+
return {
|
|
7354
|
+
benchmark: "memcorrect-v1",
|
|
7355
|
+
adapter,
|
|
7356
|
+
seed: result.meta.seeds[0] ?? 0,
|
|
7357
|
+
dataset_hash: result.meta.datasetHash ?? "",
|
|
7358
|
+
remnic_version: result.meta.remnicVersion,
|
|
7359
|
+
git_sha: result.meta.gitSha,
|
|
7360
|
+
timestamp: result.meta.timestamp,
|
|
7361
|
+
mode: result.meta.mode,
|
|
7362
|
+
uptake_at_next: numberOrZero(aggregate.uptake_at_next),
|
|
7363
|
+
uptake_latency: numberOrZero(aggregate.uptake_latency),
|
|
7364
|
+
uptake_latency_censored: numberOrZero(aggregate.uptake_latency_censored),
|
|
7365
|
+
non_resurrection: numberOrZero(aggregate.non_resurrection),
|
|
7366
|
+
collateral_delta: numberOrZero(aggregate.collateral_delta),
|
|
7367
|
+
scope_precision: typeof aggregate.scope_precision === "number" ? aggregate.scope_precision : null,
|
|
7368
|
+
false_apply: numberOrZero(aggregate.false_apply),
|
|
7369
|
+
reassertion: typeof aggregate.reassertion === "number" ? aggregate.reassertion : null,
|
|
7370
|
+
provenance_fidelity: typeof provenance === "number" ? provenance : null
|
|
7371
|
+
};
|
|
7372
|
+
}
|
|
7373
|
+
function numberOrZero(value) {
|
|
7374
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
7375
|
+
}
|
|
7319
7376
|
function serializeJsonl(rows) {
|
|
7320
7377
|
return `${rows.map((row) => JSON.stringify(row)).join("\n")}
|
|
7321
7378
|
`;
|
|
@@ -11142,7 +11199,7 @@ async function resolveLocalLabRuntimeProfile(options) {
|
|
|
11142
11199
|
// src/benchmark.ts
|
|
11143
11200
|
import fs2 from "fs";
|
|
11144
11201
|
import path32 from "path";
|
|
11145
|
-
import { createHash as
|
|
11202
|
+
import { createHash as createHash10 } from "crypto";
|
|
11146
11203
|
import { expandTildePath as expandTildePath3 } from "@remnic/core";
|
|
11147
11204
|
|
|
11148
11205
|
// src/judges/judge-cache.ts
|
|
@@ -29862,6 +29919,1062 @@ async function runRetentionAgedDatasetBenchmark(options) {
|
|
|
29862
29919
|
};
|
|
29863
29920
|
}
|
|
29864
29921
|
|
|
29922
|
+
// src/benchmarks/remnic/memcorrect/runner.ts
|
|
29923
|
+
import { randomUUID as randomUUID31 } from "crypto";
|
|
29924
|
+
|
|
29925
|
+
// src/benchmarks/remnic/memcorrect/generator.ts
|
|
29926
|
+
import { createHash as createHash9 } from "crypto";
|
|
29927
|
+
|
|
29928
|
+
// src/benchmarks/remnic/memcorrect/token-pools.ts
|
|
29929
|
+
var PERSONAS = [
|
|
29930
|
+
"Avery",
|
|
29931
|
+
"Blair",
|
|
29932
|
+
"Cassidy",
|
|
29933
|
+
"Dakota",
|
|
29934
|
+
"Emerson",
|
|
29935
|
+
"Finley",
|
|
29936
|
+
"Harper",
|
|
29937
|
+
"Jordan",
|
|
29938
|
+
"Kendall",
|
|
29939
|
+
"Logan"
|
|
29940
|
+
];
|
|
29941
|
+
var SUBJECTS = [
|
|
29942
|
+
"coffee",
|
|
29943
|
+
"editor",
|
|
29944
|
+
"database",
|
|
29945
|
+
"calendar",
|
|
29946
|
+
"standup",
|
|
29947
|
+
"deploy",
|
|
29948
|
+
"notebook",
|
|
29949
|
+
"keyboard"
|
|
29950
|
+
];
|
|
29951
|
+
var VALUES_A = [
|
|
29952
|
+
"oat-milk",
|
|
29953
|
+
"helix",
|
|
29954
|
+
"postgres",
|
|
29955
|
+
"monday",
|
|
29956
|
+
"nine-am",
|
|
29957
|
+
"blue-green",
|
|
29958
|
+
"dotgrid",
|
|
29959
|
+
"mechanical"
|
|
29960
|
+
];
|
|
29961
|
+
var VALUES_B = [
|
|
29962
|
+
"black-coffee",
|
|
29963
|
+
"neovim",
|
|
29964
|
+
"mysql",
|
|
29965
|
+
"wednesday",
|
|
29966
|
+
"ten-am",
|
|
29967
|
+
"canary",
|
|
29968
|
+
"lined",
|
|
29969
|
+
"membrane"
|
|
29970
|
+
];
|
|
29971
|
+
|
|
29972
|
+
// src/benchmarks/remnic/memcorrect/generator.ts
|
|
29973
|
+
var MAX_PRNG_SEED2 = 4294967295;
|
|
29974
|
+
var FACT_CATEGORIES = [
|
|
29975
|
+
"fact",
|
|
29976
|
+
"preference",
|
|
29977
|
+
"decision",
|
|
29978
|
+
"commitment",
|
|
29979
|
+
"relationship"
|
|
29980
|
+
];
|
|
29981
|
+
function mulberry322(seed) {
|
|
29982
|
+
let state = seed >>> 0;
|
|
29983
|
+
return function rng() {
|
|
29984
|
+
state |= 0;
|
|
29985
|
+
state = state + 1831565813 | 0;
|
|
29986
|
+
let t = Math.imul(state ^ state >>> 15, 1 | state);
|
|
29987
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
29988
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
29989
|
+
};
|
|
29990
|
+
}
|
|
29991
|
+
function pick(rng, pool) {
|
|
29992
|
+
return pool[Math.floor(rng() * pool.length) % pool.length];
|
|
29993
|
+
}
|
|
29994
|
+
function pickExcluding(rng, pool, exclude) {
|
|
29995
|
+
const choices = pool.filter((v) => v !== exclude);
|
|
29996
|
+
const source = choices.length > 0 ? choices : pool;
|
|
29997
|
+
return source[Math.floor(rng() * source.length) % source.length];
|
|
29998
|
+
}
|
|
29999
|
+
function pickExcludingSet(rng, pool, used) {
|
|
30000
|
+
const choices = pool.filter((v) => !used.has(v));
|
|
30001
|
+
const source = choices.length > 0 ? choices : pool;
|
|
30002
|
+
return source[Math.floor(rng() * source.length) % source.length];
|
|
30003
|
+
}
|
|
30004
|
+
function isoAfter(baseMs, addMs) {
|
|
30005
|
+
return new Date(baseMs + addMs).toISOString();
|
|
30006
|
+
}
|
|
30007
|
+
function planFacts(rng, options) {
|
|
30008
|
+
const plans = [];
|
|
30009
|
+
const shapes = [
|
|
30010
|
+
"explicit-targeted",
|
|
30011
|
+
"conversational",
|
|
30012
|
+
"scoped",
|
|
30013
|
+
"re-assertion"
|
|
30014
|
+
];
|
|
30015
|
+
for (let p = 0; p < options.personaCount; p += 1) {
|
|
30016
|
+
const persona = PERSONAS[p % PERSONAS.length];
|
|
30017
|
+
const namespaces = [
|
|
30018
|
+
`${persona.toLowerCase()}-work`,
|
|
30019
|
+
`${persona.toLowerCase()}-home`
|
|
30020
|
+
];
|
|
30021
|
+
for (let f = 0; f < options.factsPerPersona; f += 1) {
|
|
30022
|
+
const category = FACT_CATEGORIES[(p * options.factsPerPersona + f) % FACT_CATEGORIES.length];
|
|
30023
|
+
const subject = pick(rng, SUBJECTS);
|
|
30024
|
+
const oldValue = pick(rng, VALUES_A);
|
|
30025
|
+
const newValue = pick(rng, VALUES_B);
|
|
30026
|
+
const namespace = namespaces[f % namespaces.length];
|
|
30027
|
+
const shape = shapes[(p * options.factsPerPersona + f) % shapes.length];
|
|
30028
|
+
plans.push({ persona, namespace, category, subject, oldValue, newValue, shape });
|
|
30029
|
+
}
|
|
30030
|
+
}
|
|
30031
|
+
return plans;
|
|
30032
|
+
}
|
|
30033
|
+
function establishTurns(plan, baseMs, startOffsetMs) {
|
|
30034
|
+
const turns = [
|
|
30035
|
+
{
|
|
30036
|
+
role: "user",
|
|
30037
|
+
text: `My ${plan.subject} preference is ${plan.oldValue}.`,
|
|
30038
|
+
at: isoAfter(baseMs, startOffsetMs)
|
|
30039
|
+
},
|
|
30040
|
+
{
|
|
30041
|
+
role: "assistant",
|
|
30042
|
+
text: `Got it \u2014 noting ${plan.oldValue} for ${plan.subject}.`,
|
|
30043
|
+
at: isoAfter(baseMs, startOffsetMs + 6e4)
|
|
30044
|
+
}
|
|
30045
|
+
];
|
|
30046
|
+
return { turns, nextOffsetMs: startOffsetMs + 12e4 };
|
|
30047
|
+
}
|
|
30048
|
+
function buildCorrection(plan, baseMs, offsetMs) {
|
|
30049
|
+
const retiredContent = [plan.oldValue];
|
|
30050
|
+
const correctedContent = [plan.newValue];
|
|
30051
|
+
let text;
|
|
30052
|
+
switch (plan.shape) {
|
|
30053
|
+
case "explicit-targeted":
|
|
30054
|
+
text = `Correction: my ${plan.subject} record saying ${plan.oldValue} is wrong. It is now ${plan.newValue}.`;
|
|
30055
|
+
break;
|
|
30056
|
+
case "conversational":
|
|
30057
|
+
text = `Oh by the way, we switched ${plan.subject} from ${plan.oldValue} to ${plan.newValue} last month.`;
|
|
30058
|
+
break;
|
|
30059
|
+
case "scoped":
|
|
30060
|
+
text = `For this project, ${plan.subject} is ${plan.newValue} now, not ${plan.oldValue}.`;
|
|
30061
|
+
break;
|
|
30062
|
+
case "re-assertion":
|
|
30063
|
+
text = `Update: ${plan.subject} is ${plan.newValue} going forward instead of ${plan.oldValue}.`;
|
|
30064
|
+
break;
|
|
30065
|
+
}
|
|
30066
|
+
const correction = {
|
|
30067
|
+
shape: plan.shape,
|
|
30068
|
+
turn: { role: "user", text, at: isoAfter(baseMs, offsetMs) },
|
|
30069
|
+
retiredContent,
|
|
30070
|
+
correctedContent
|
|
30071
|
+
};
|
|
30072
|
+
return { correction, nextOffsetMs: offsetMs + 6e4 };
|
|
30073
|
+
}
|
|
30074
|
+
function buildAntiEvents(rng, plan, baseMs, offsetMs) {
|
|
30075
|
+
const kinds = [
|
|
30076
|
+
"quoting-other",
|
|
30077
|
+
"hypothetical",
|
|
30078
|
+
"third-party-correction"
|
|
30079
|
+
];
|
|
30080
|
+
const kind = kinds[Math.floor(rng() * kinds.length) % kinds.length];
|
|
30081
|
+
const decoy = pickExcluding(rng, VALUES_B, plan.newValue);
|
|
30082
|
+
let text;
|
|
30083
|
+
switch (kind) {
|
|
30084
|
+
case "quoting-other":
|
|
30085
|
+
text = `Riley mentioned their ${plan.subject} is set to ${decoy}.`;
|
|
30086
|
+
break;
|
|
30087
|
+
case "hypothetical":
|
|
30088
|
+
text = `If someone asked, I might consider ${decoy} for ${plan.subject}, but I have not decided.`;
|
|
30089
|
+
break;
|
|
30090
|
+
case "third-party-correction":
|
|
30091
|
+
text = `Sage said you should change ${plan.subject} to ${decoy} for them.`;
|
|
30092
|
+
break;
|
|
30093
|
+
}
|
|
30094
|
+
const event = {
|
|
30095
|
+
kind,
|
|
30096
|
+
turn: { role: "user", text, at: isoAfter(baseMs, offsetMs) },
|
|
30097
|
+
probeQuery: `what is my ${plan.subject} preference?`,
|
|
30098
|
+
// The decoy must NOT stick from a third-party / hypothetical cue; if it
|
|
30099
|
+
// surfaces in a later probe the system falsely applied the anti-event.
|
|
30100
|
+
shouldNotAppear: decoy
|
|
30101
|
+
};
|
|
30102
|
+
return { events: [event], nextOffsetMs: offsetMs + 6e4 };
|
|
30103
|
+
}
|
|
30104
|
+
function buildScopedTwin(plan, baseMs, offsetMs) {
|
|
30105
|
+
const otherNamespace = plan.namespace.endsWith("-work") ? plan.namespace.replace(/-work$/, "-home") : plan.namespace.replace(/-home$/, "-work");
|
|
30106
|
+
const twin = {
|
|
30107
|
+
namespace: otherNamespace,
|
|
30108
|
+
establishingTurns: [
|
|
30109
|
+
{
|
|
30110
|
+
role: "user",
|
|
30111
|
+
text: `My ${plan.subject} preference is ${plan.oldValue}.`,
|
|
30112
|
+
at: isoAfter(baseMs, offsetMs)
|
|
30113
|
+
},
|
|
30114
|
+
{
|
|
30115
|
+
role: "assistant",
|
|
30116
|
+
text: `Noted ${plan.oldValue} for ${plan.subject}.`,
|
|
30117
|
+
at: isoAfter(baseMs, offsetMs + 6e4)
|
|
30118
|
+
}
|
|
30119
|
+
],
|
|
30120
|
+
twinContent: plan.oldValue
|
|
30121
|
+
};
|
|
30122
|
+
return { twin, nextOffsetMs: offsetMs + 12e4 };
|
|
30123
|
+
}
|
|
30124
|
+
function buildReassertion(plan, baseMs, offsetMs) {
|
|
30125
|
+
return {
|
|
30126
|
+
turn: {
|
|
30127
|
+
role: "user",
|
|
30128
|
+
text: `Actually, we went back to ${plan.oldValue} for ${plan.subject}.`,
|
|
30129
|
+
at: isoAfter(baseMs, offsetMs)
|
|
30130
|
+
},
|
|
30131
|
+
expectedContent: plan.oldValue
|
|
30132
|
+
};
|
|
30133
|
+
}
|
|
30134
|
+
function buildUnrelatedProbes(rng, plan, baseMs, offsetMs) {
|
|
30135
|
+
const PROBE_COUNT = 2;
|
|
30136
|
+
const probes = [];
|
|
30137
|
+
const usedSubjects = /* @__PURE__ */ new Set([plan.subject]);
|
|
30138
|
+
for (let i = 0; i < PROBE_COUNT; i += 1) {
|
|
30139
|
+
const subject = pickExcludingSet(rng, SUBJECTS, usedSubjects);
|
|
30140
|
+
usedSubjects.add(subject);
|
|
30141
|
+
const value = pick(rng, VALUES_A);
|
|
30142
|
+
const turnBase = offsetMs + i * 12e4;
|
|
30143
|
+
probes.push({
|
|
30144
|
+
query: `what is my ${subject} setting?`,
|
|
30145
|
+
expectedContent: value,
|
|
30146
|
+
establishingTurns: [
|
|
30147
|
+
{
|
|
30148
|
+
role: "user",
|
|
30149
|
+
text: `My ${subject} setting is ${value}.`,
|
|
30150
|
+
at: isoAfter(baseMs, turnBase)
|
|
30151
|
+
},
|
|
30152
|
+
{
|
|
30153
|
+
role: "assistant",
|
|
30154
|
+
text: `Got it \u2014 noting ${value} for ${subject}.`,
|
|
30155
|
+
at: isoAfter(baseMs, turnBase + 6e4)
|
|
30156
|
+
}
|
|
30157
|
+
]
|
|
30158
|
+
});
|
|
30159
|
+
}
|
|
30160
|
+
return { probes, nextOffsetMs: PROBE_COUNT * 12e4 };
|
|
30161
|
+
}
|
|
30162
|
+
function probeFor(plan) {
|
|
30163
|
+
return {
|
|
30164
|
+
query: `what is my ${plan.subject} preference?`,
|
|
30165
|
+
mustContain: [plan.newValue],
|
|
30166
|
+
mustAbsent: [plan.oldValue]
|
|
30167
|
+
};
|
|
30168
|
+
}
|
|
30169
|
+
function generateMemCorrectCorpus(options) {
|
|
30170
|
+
if (!Number.isInteger(options.personaCount) || options.personaCount <= 0) {
|
|
30171
|
+
throw new Error(
|
|
30172
|
+
`personaCount must be a positive integer, got ${options.personaCount}`
|
|
30173
|
+
);
|
|
30174
|
+
}
|
|
30175
|
+
if (!Number.isInteger(options.factsPerPersona) || options.factsPerPersona <= 0) {
|
|
30176
|
+
throw new Error(
|
|
30177
|
+
`factsPerPersona must be a positive integer, got ${options.factsPerPersona}`
|
|
30178
|
+
);
|
|
30179
|
+
}
|
|
30180
|
+
if (!Number.isInteger(options.maintenanceCycles) || options.maintenanceCycles < 0) {
|
|
30181
|
+
throw new Error(
|
|
30182
|
+
`maintenanceCycles must be a non-negative integer, got ${options.maintenanceCycles}`
|
|
30183
|
+
);
|
|
30184
|
+
}
|
|
30185
|
+
if (!Number.isInteger(options.uptakeLatencyCap) || options.uptakeLatencyCap <= 0) {
|
|
30186
|
+
throw new Error(
|
|
30187
|
+
`uptakeLatencyCap must be a positive integer, got ${options.uptakeLatencyCap}`
|
|
30188
|
+
);
|
|
30189
|
+
}
|
|
30190
|
+
if (!Number.isInteger(options.seed) || options.seed < 0 || options.seed > MAX_PRNG_SEED2) {
|
|
30191
|
+
throw new Error(
|
|
30192
|
+
`seed must be an integer in [0, ${MAX_PRNG_SEED2}], got ${options.seed}`
|
|
30193
|
+
);
|
|
30194
|
+
}
|
|
30195
|
+
const baseMs = Date.parse(options.nowIso);
|
|
30196
|
+
if (!Number.isFinite(baseMs)) {
|
|
30197
|
+
throw new Error(`nowIso must be a valid ISO timestamp, got ${options.nowIso}`);
|
|
30198
|
+
}
|
|
30199
|
+
const rng = mulberry322(options.seed);
|
|
30200
|
+
const plans = planFacts(rng, options);
|
|
30201
|
+
const scenarios = [];
|
|
30202
|
+
for (let i = 0; i < plans.length; i += 1) {
|
|
30203
|
+
const plan = plans[i];
|
|
30204
|
+
const scenarioBase = baseMs + i * 864e5;
|
|
30205
|
+
let offset = 0;
|
|
30206
|
+
const established = establishTurns(plan, scenarioBase, offset);
|
|
30207
|
+
offset = established.nextOffsetMs;
|
|
30208
|
+
const unrelated = buildUnrelatedProbes(rng, plan, scenarioBase, offset);
|
|
30209
|
+
offset += unrelated.nextOffsetMs;
|
|
30210
|
+
let scopedTwin;
|
|
30211
|
+
if (plan.shape === "scoped") {
|
|
30212
|
+
const twin = buildScopedTwin(plan, scenarioBase, offset);
|
|
30213
|
+
scopedTwin = twin.twin;
|
|
30214
|
+
offset = twin.nextOffsetMs;
|
|
30215
|
+
}
|
|
30216
|
+
const corrected = buildCorrection(plan, scenarioBase, offset);
|
|
30217
|
+
offset = corrected.nextOffsetMs;
|
|
30218
|
+
const antis = buildAntiEvents(rng, plan, scenarioBase, offset);
|
|
30219
|
+
offset = antis.nextOffsetMs;
|
|
30220
|
+
let reassertion2;
|
|
30221
|
+
if (plan.shape === "re-assertion") {
|
|
30222
|
+
reassertion2 = buildReassertion(plan, scenarioBase, offset);
|
|
30223
|
+
offset += 6e4;
|
|
30224
|
+
}
|
|
30225
|
+
scenarios.push({
|
|
30226
|
+
id: `memcorrect-${options.seed}-${i.toString(16)}`,
|
|
30227
|
+
namespace: plan.namespace,
|
|
30228
|
+
category: plan.category,
|
|
30229
|
+
establishingTurns: established.turns,
|
|
30230
|
+
correction: corrected.correction,
|
|
30231
|
+
probe: probeFor(plan),
|
|
30232
|
+
antiEvents: antis.events,
|
|
30233
|
+
scopedTwin,
|
|
30234
|
+
reassertion: reassertion2,
|
|
30235
|
+
unrelatedProbes: unrelated.probes
|
|
30236
|
+
});
|
|
30237
|
+
}
|
|
30238
|
+
return { options, scenarios };
|
|
30239
|
+
}
|
|
30240
|
+
function corpusHash(corpus) {
|
|
30241
|
+
const canonical = JSON.stringify({
|
|
30242
|
+
personaCount: corpus.options.personaCount,
|
|
30243
|
+
factsPerPersona: corpus.options.factsPerPersona,
|
|
30244
|
+
seed: corpus.options.seed,
|
|
30245
|
+
nowIso: corpus.options.nowIso,
|
|
30246
|
+
maintenanceCycles: corpus.options.maintenanceCycles,
|
|
30247
|
+
uptakeLatencyCap: corpus.options.uptakeLatencyCap,
|
|
30248
|
+
scenarios: corpus.scenarios
|
|
30249
|
+
});
|
|
30250
|
+
return createHash9("sha256").update(canonical).digest("hex");
|
|
30251
|
+
}
|
|
30252
|
+
|
|
30253
|
+
// src/benchmarks/remnic/memcorrect/schema.ts
|
|
30254
|
+
var ALLOWED_CATEGORIES = [
|
|
30255
|
+
"fact",
|
|
30256
|
+
"preference",
|
|
30257
|
+
"decision",
|
|
30258
|
+
"commitment",
|
|
30259
|
+
"relationship"
|
|
30260
|
+
];
|
|
30261
|
+
var ALLOWED_SHAPES = [
|
|
30262
|
+
"explicit-targeted",
|
|
30263
|
+
"conversational",
|
|
30264
|
+
"scoped",
|
|
30265
|
+
"re-assertion"
|
|
30266
|
+
];
|
|
30267
|
+
var ALL_TOKENS = /* @__PURE__ */ new Set([
|
|
30268
|
+
...PERSONAS.map((p) => p.toLowerCase()),
|
|
30269
|
+
...SUBJECTS,
|
|
30270
|
+
...VALUES_A,
|
|
30271
|
+
...VALUES_B,
|
|
30272
|
+
"correction",
|
|
30273
|
+
"update",
|
|
30274
|
+
"actually",
|
|
30275
|
+
"preference",
|
|
30276
|
+
"setting",
|
|
30277
|
+
"for",
|
|
30278
|
+
"this",
|
|
30279
|
+
"project",
|
|
30280
|
+
"my",
|
|
30281
|
+
"is",
|
|
30282
|
+
"now",
|
|
30283
|
+
"not",
|
|
30284
|
+
"wrong",
|
|
30285
|
+
"it",
|
|
30286
|
+
"we",
|
|
30287
|
+
"switched",
|
|
30288
|
+
"from",
|
|
30289
|
+
"to",
|
|
30290
|
+
"last",
|
|
30291
|
+
"month",
|
|
30292
|
+
"going",
|
|
30293
|
+
"forward",
|
|
30294
|
+
"instead",
|
|
30295
|
+
"of",
|
|
30296
|
+
"the",
|
|
30297
|
+
"record",
|
|
30298
|
+
"saying",
|
|
30299
|
+
"oh",
|
|
30300
|
+
"by",
|
|
30301
|
+
"way",
|
|
30302
|
+
"mentioned",
|
|
30303
|
+
"their",
|
|
30304
|
+
"set",
|
|
30305
|
+
"if",
|
|
30306
|
+
"someone",
|
|
30307
|
+
"asked",
|
|
30308
|
+
"i",
|
|
30309
|
+
"might",
|
|
30310
|
+
"consider",
|
|
30311
|
+
"but",
|
|
30312
|
+
"have",
|
|
30313
|
+
"decided",
|
|
30314
|
+
"said",
|
|
30315
|
+
"you",
|
|
30316
|
+
"should",
|
|
30317
|
+
"change",
|
|
30318
|
+
"them",
|
|
30319
|
+
"noting",
|
|
30320
|
+
"noted",
|
|
30321
|
+
"got",
|
|
30322
|
+
"it",
|
|
30323
|
+
"we",
|
|
30324
|
+
"went",
|
|
30325
|
+
"back",
|
|
30326
|
+
"riley",
|
|
30327
|
+
"sage",
|
|
30328
|
+
"what"
|
|
30329
|
+
]);
|
|
30330
|
+
function isStringArray(value) {
|
|
30331
|
+
return Array.isArray(value) && value.every((v) => typeof v === "string");
|
|
30332
|
+
}
|
|
30333
|
+
function isIso(value) {
|
|
30334
|
+
if (typeof value !== "string") return false;
|
|
30335
|
+
const ms = Date.parse(value);
|
|
30336
|
+
return Number.isFinite(ms);
|
|
30337
|
+
}
|
|
30338
|
+
function validateScenario(scenario) {
|
|
30339
|
+
const errors = [];
|
|
30340
|
+
const id = scenario.id;
|
|
30341
|
+
if (scenario.id.length === 0) {
|
|
30342
|
+
errors.push({ scenarioId: id, message: "id must be a non-empty string" });
|
|
30343
|
+
}
|
|
30344
|
+
if (scenario.namespace.length === 0) {
|
|
30345
|
+
errors.push({ scenarioId: id, message: "namespace must be a non-empty string" });
|
|
30346
|
+
}
|
|
30347
|
+
if (!ALLOWED_CATEGORIES.includes(scenario.category)) {
|
|
30348
|
+
errors.push({
|
|
30349
|
+
scenarioId: id,
|
|
30350
|
+
message: `category must be one of ${ALLOWED_CATEGORIES.join(", ")}`
|
|
30351
|
+
});
|
|
30352
|
+
}
|
|
30353
|
+
if (scenario.establishingTurns.length === 0) {
|
|
30354
|
+
errors.push({
|
|
30355
|
+
scenarioId: id,
|
|
30356
|
+
message: "establishingTurns must be a non-empty array"
|
|
30357
|
+
});
|
|
30358
|
+
} else {
|
|
30359
|
+
for (const [index, turn] of scenario.establishingTurns.entries()) {
|
|
30360
|
+
if (turn.role !== "user" && turn.role !== "assistant") {
|
|
30361
|
+
errors.push({
|
|
30362
|
+
scenarioId: id,
|
|
30363
|
+
message: `establishing turn ${index} role invalid`
|
|
30364
|
+
});
|
|
30365
|
+
}
|
|
30366
|
+
if (turn.text.length === 0) {
|
|
30367
|
+
errors.push({
|
|
30368
|
+
scenarioId: id,
|
|
30369
|
+
message: `establishing turn ${index} text empty`
|
|
30370
|
+
});
|
|
30371
|
+
}
|
|
30372
|
+
if (!isIso(turn.at)) {
|
|
30373
|
+
errors.push({
|
|
30374
|
+
scenarioId: id,
|
|
30375
|
+
message: `establishing turn ${index} at not ISO`
|
|
30376
|
+
});
|
|
30377
|
+
}
|
|
30378
|
+
}
|
|
30379
|
+
}
|
|
30380
|
+
if (!ALLOWED_SHAPES.includes(scenario.correction.shape)) {
|
|
30381
|
+
errors.push({
|
|
30382
|
+
scenarioId: id,
|
|
30383
|
+
message: `correction.shape must be one of ${ALLOWED_SHAPES.join(", ")}`
|
|
30384
|
+
});
|
|
30385
|
+
}
|
|
30386
|
+
if (!isStringArray(scenario.correction.retiredContent)) {
|
|
30387
|
+
errors.push({ scenarioId: id, message: "retiredContent must be string[]" });
|
|
30388
|
+
}
|
|
30389
|
+
if (!isStringArray(scenario.correction.correctedContent)) {
|
|
30390
|
+
errors.push({ scenarioId: id, message: "correctedContent must be string[]" });
|
|
30391
|
+
}
|
|
30392
|
+
if (scenario.correction.shape === "scoped" && (!scenario.scopedTwin || scenario.scopedTwin.twinContent.length === 0)) {
|
|
30393
|
+
errors.push({
|
|
30394
|
+
scenarioId: id,
|
|
30395
|
+
message: "scoped correction must carry a scopedTwin with non-empty twinContent"
|
|
30396
|
+
});
|
|
30397
|
+
}
|
|
30398
|
+
if (scenario.correction.shape === "re-assertion" && (!scenario.reassertion || scenario.reassertion.expectedContent.length === 0)) {
|
|
30399
|
+
errors.push({
|
|
30400
|
+
scenarioId: id,
|
|
30401
|
+
message: "re-assertion correction must carry a reassertion block with expectedContent"
|
|
30402
|
+
});
|
|
30403
|
+
}
|
|
30404
|
+
if (scenario.probe.query.length === 0) {
|
|
30405
|
+
errors.push({ scenarioId: id, message: "probe.query empty" });
|
|
30406
|
+
}
|
|
30407
|
+
if (!isStringArray(scenario.probe.mustContain)) {
|
|
30408
|
+
errors.push({ scenarioId: id, message: "probe.mustContain must be string[]" });
|
|
30409
|
+
}
|
|
30410
|
+
if (!isStringArray(scenario.probe.mustAbsent)) {
|
|
30411
|
+
errors.push({ scenarioId: id, message: "probe.mustAbsent must be string[]" });
|
|
30412
|
+
}
|
|
30413
|
+
if (!Array.isArray(scenario.antiEvents)) {
|
|
30414
|
+
errors.push({ scenarioId: id, message: "antiEvents must be an array" });
|
|
30415
|
+
}
|
|
30416
|
+
if (!Array.isArray(scenario.unrelatedProbes)) {
|
|
30417
|
+
errors.push({ scenarioId: id, message: "unrelatedProbes must be an array" });
|
|
30418
|
+
}
|
|
30419
|
+
return errors;
|
|
30420
|
+
}
|
|
30421
|
+
function validateCorpus(corpus) {
|
|
30422
|
+
const errors = [];
|
|
30423
|
+
if (!Array.isArray(corpus.scenarios)) {
|
|
30424
|
+
return {
|
|
30425
|
+
ok: false,
|
|
30426
|
+
errors: [{ scenarioId: "<root>", message: "scenarios must be an array" }]
|
|
30427
|
+
};
|
|
30428
|
+
}
|
|
30429
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
30430
|
+
for (const scenario of corpus.scenarios) {
|
|
30431
|
+
if (seenIds.has(scenario.id)) {
|
|
30432
|
+
errors.push({ scenarioId: scenario.id, message: "duplicate scenario id" });
|
|
30433
|
+
}
|
|
30434
|
+
seenIds.add(scenario.id);
|
|
30435
|
+
errors.push(...validateScenario(scenario));
|
|
30436
|
+
const factTokens = [
|
|
30437
|
+
...scenario.correction?.retiredContent ?? [],
|
|
30438
|
+
...scenario.correction?.correctedContent ?? [],
|
|
30439
|
+
...scenario.scopedTwin ? [scenario.scopedTwin.twinContent] : [],
|
|
30440
|
+
...scenario.reassertion ? [scenario.reassertion.expectedContent] : []
|
|
30441
|
+
];
|
|
30442
|
+
for (const token of factTokens) {
|
|
30443
|
+
if (!ALL_TOKENS.has(token.toLowerCase())) {
|
|
30444
|
+
errors.push({
|
|
30445
|
+
scenarioId: scenario.id,
|
|
30446
|
+
message: `fact token "${token}" is outside the synthetic pools (PII guard)`
|
|
30447
|
+
});
|
|
30448
|
+
}
|
|
30449
|
+
}
|
|
30450
|
+
}
|
|
30451
|
+
return { ok: errors.length === 0, errors };
|
|
30452
|
+
}
|
|
30453
|
+
|
|
30454
|
+
// src/benchmarks/remnic/memcorrect/metrics.ts
|
|
30455
|
+
function tokenize3(text) {
|
|
30456
|
+
const tokens = text.toLowerCase().match(/[a-z0-9][a-z0-9-]*/g);
|
|
30457
|
+
return new Set(tokens ?? []);
|
|
30458
|
+
}
|
|
30459
|
+
function containsAll(haystack, needles) {
|
|
30460
|
+
if (needles.length === 0) return true;
|
|
30461
|
+
const hay = tokenize3(haystack);
|
|
30462
|
+
for (const needle of needles) {
|
|
30463
|
+
if (!hay.has(needle.toLowerCase())) return false;
|
|
30464
|
+
}
|
|
30465
|
+
return true;
|
|
30466
|
+
}
|
|
30467
|
+
function joinedRecall(entry) {
|
|
30468
|
+
return entry.recalled.join(" ");
|
|
30469
|
+
}
|
|
30470
|
+
function recallShowsStaleRetired(entry, correction) {
|
|
30471
|
+
for (const recalled of entry.recalled) {
|
|
30472
|
+
if (!containsAll(recalled, correction.retiredContent)) continue;
|
|
30473
|
+
if (!containsAll(recalled, correction.correctedContent)) return true;
|
|
30474
|
+
}
|
|
30475
|
+
return false;
|
|
30476
|
+
}
|
|
30477
|
+
function probePassesForCorrection(entry, correction) {
|
|
30478
|
+
const hay = joinedRecall(entry);
|
|
30479
|
+
return containsAll(hay, correction.correctedContent) && !recallShowsStaleRetired(entry, correction);
|
|
30480
|
+
}
|
|
30481
|
+
function entriesFor(log, scenarioId, phase) {
|
|
30482
|
+
return log.filter((e) => e.scenarioId === scenarioId && e.phase === phase);
|
|
30483
|
+
}
|
|
30484
|
+
function uptakeAtNext(log, corrections) {
|
|
30485
|
+
if (corrections.length === 0) return 0;
|
|
30486
|
+
let passed = 0;
|
|
30487
|
+
for (const correction of corrections) {
|
|
30488
|
+
const post = entriesFor(log, correction.scenarioId, "post_correction").sort((a, b) => a.turnIndex - b.turnIndex);
|
|
30489
|
+
const eligible = post.filter((e) => e.turnIndex > correction.turnIndex);
|
|
30490
|
+
const first = eligible[0];
|
|
30491
|
+
if (first && probePassesForCorrection(first, correction)) passed += 1;
|
|
30492
|
+
}
|
|
30493
|
+
return passed / corrections.length;
|
|
30494
|
+
}
|
|
30495
|
+
function uptakeLatency(log, corrections, cap) {
|
|
30496
|
+
if (corrections.length === 0) return { mean: 0, censored: 0 };
|
|
30497
|
+
let sum = 0;
|
|
30498
|
+
let censored = 0;
|
|
30499
|
+
for (const correction of corrections) {
|
|
30500
|
+
const post = entriesFor(log, correction.scenarioId, "post_correction").sort((a, b) => a.turnIndex - b.turnIndex).filter((e) => e.turnIndex > correction.turnIndex);
|
|
30501
|
+
let resolved = cap;
|
|
30502
|
+
let found = false;
|
|
30503
|
+
for (const entry of post) {
|
|
30504
|
+
const delta = entry.turnIndex - correction.turnIndex;
|
|
30505
|
+
if (delta > cap) break;
|
|
30506
|
+
if (probePassesForCorrection(entry, correction)) {
|
|
30507
|
+
resolved = delta;
|
|
30508
|
+
found = true;
|
|
30509
|
+
break;
|
|
30510
|
+
}
|
|
30511
|
+
}
|
|
30512
|
+
if (!found) censored += 1;
|
|
30513
|
+
sum += resolved;
|
|
30514
|
+
}
|
|
30515
|
+
return { mean: sum / corrections.length, censored };
|
|
30516
|
+
}
|
|
30517
|
+
function nonResurrection(log, corrections) {
|
|
30518
|
+
if (corrections.length === 0) return 0;
|
|
30519
|
+
let stayedRetired = 0;
|
|
30520
|
+
for (const correction of corrections) {
|
|
30521
|
+
const postMaint = entriesFor(log, correction.scenarioId, "post_maintenance");
|
|
30522
|
+
const postReingest = entriesFor(log, correction.scenarioId, "post_reingest");
|
|
30523
|
+
const both = [...postMaint, ...postReingest];
|
|
30524
|
+
if (both.length === 0) continue;
|
|
30525
|
+
const allRetired = both.every(
|
|
30526
|
+
(e) => !recallShowsStaleRetired(e, correction)
|
|
30527
|
+
);
|
|
30528
|
+
if (allRetired) stayedRetired += 1;
|
|
30529
|
+
}
|
|
30530
|
+
return corrections.length > 0 ? stayedRetired / corrections.length : 0;
|
|
30531
|
+
}
|
|
30532
|
+
function collateralDelta(before, after) {
|
|
30533
|
+
if (before.length === 0) return 0;
|
|
30534
|
+
const mean3 = (xs) => xs.reduce((s, x) => s + x, 0) / xs.length;
|
|
30535
|
+
return mean3(after) - mean3(before);
|
|
30536
|
+
}
|
|
30537
|
+
function scopePrecision(log, corrections) {
|
|
30538
|
+
let scopedCount = 0;
|
|
30539
|
+
let passed = 0;
|
|
30540
|
+
for (const correction of corrections) {
|
|
30541
|
+
const twin = correction.scopedTwin;
|
|
30542
|
+
if (!twin) continue;
|
|
30543
|
+
scopedCount += 1;
|
|
30544
|
+
const primaryPost = entriesFor(log, correction.scenarioId, "post_correction").filter((e) => e.turnIndex > correction.turnIndex).sort((a, b) => a.turnIndex - b.turnIndex)[0];
|
|
30545
|
+
const twinPost = log.filter(
|
|
30546
|
+
(e) => e.scenarioId === correction.scenarioId && e.namespace === twin.namespace && e.phase === "post_correction" && e.turnIndex > correction.turnIndex
|
|
30547
|
+
).sort((a, b) => a.turnIndex - b.turnIndex)[0];
|
|
30548
|
+
if (!primaryPost || !twinPost) continue;
|
|
30549
|
+
const primaryRetired = !recallShowsStaleRetired(primaryPost, correction);
|
|
30550
|
+
const twinIntact = containsAll(joinedRecall(twinPost), [twin.twinContent]);
|
|
30551
|
+
if (primaryRetired && twinIntact) passed += 1;
|
|
30552
|
+
}
|
|
30553
|
+
return scopedCount > 0 ? passed / scopedCount : null;
|
|
30554
|
+
}
|
|
30555
|
+
function falseApply(log, antiEvents) {
|
|
30556
|
+
if (antiEvents.length === 0) return 0;
|
|
30557
|
+
let triggered = 0;
|
|
30558
|
+
for (const anti of antiEvents) {
|
|
30559
|
+
const probes = log.filter(
|
|
30560
|
+
(e) => e.scenarioId === anti.scenarioId && e.phase === "post_correction"
|
|
30561
|
+
);
|
|
30562
|
+
const leaked = probes.some(
|
|
30563
|
+
(e) => containsAll(joinedRecall(e), [anti.shouldNotAppear])
|
|
30564
|
+
);
|
|
30565
|
+
if (leaked) triggered += 1;
|
|
30566
|
+
}
|
|
30567
|
+
return triggered / antiEvents.length;
|
|
30568
|
+
}
|
|
30569
|
+
function reassertion(log, reassertions) {
|
|
30570
|
+
if (reassertions.length === 0) return null;
|
|
30571
|
+
let recalled = 0;
|
|
30572
|
+
for (const re of reassertions) {
|
|
30573
|
+
const post = entriesFor(log, re.scenarioId, "post_reassertion");
|
|
30574
|
+
const found = post.some(
|
|
30575
|
+
(e) => containsAll(joinedRecall(e), [re.expectedContent])
|
|
30576
|
+
);
|
|
30577
|
+
if (found) recalled += 1;
|
|
30578
|
+
}
|
|
30579
|
+
return recalled / reassertions.length;
|
|
30580
|
+
}
|
|
30581
|
+
function provenanceFidelity(citeLog) {
|
|
30582
|
+
if (citeLog.length === 0) return null;
|
|
30583
|
+
if (citeLog.every((v) => v === null)) return null;
|
|
30584
|
+
const scored = citeLog.filter((v) => v !== null);
|
|
30585
|
+
if (scored.length === 0) return null;
|
|
30586
|
+
return scored.reduce((s, v) => s + v, 0) / scored.length;
|
|
30587
|
+
}
|
|
30588
|
+
function computeMetricBundle(args) {
|
|
30589
|
+
const latency = uptakeLatency(
|
|
30590
|
+
args.log,
|
|
30591
|
+
args.corrections,
|
|
30592
|
+
args.uptakeLatencyCap
|
|
30593
|
+
);
|
|
30594
|
+
return {
|
|
30595
|
+
uptake_at_next: uptakeAtNext(args.log, args.corrections),
|
|
30596
|
+
uptake_latency: latency.mean,
|
|
30597
|
+
uptake_latency_censored: latency.censored,
|
|
30598
|
+
non_resurrection: nonResurrection(args.log, args.corrections),
|
|
30599
|
+
collateral_delta: collateralDelta(args.collateralBefore, args.collateralAfter),
|
|
30600
|
+
scope_precision: scopePrecision(args.log, args.corrections),
|
|
30601
|
+
false_apply: falseApply(args.log, args.antiEvents),
|
|
30602
|
+
reassertion: reassertion(args.log, args.reassertions),
|
|
30603
|
+
provenance_fidelity: provenanceFidelity(args.provenanceCites)
|
|
30604
|
+
};
|
|
30605
|
+
}
|
|
30606
|
+
|
|
30607
|
+
// src/benchmarks/remnic/memcorrect/adapters.ts
|
|
30608
|
+
function createRemnicMemCorrectAdapter(adapter, options = {}) {
|
|
30609
|
+
const label = options.label ?? "remnic-native";
|
|
30610
|
+
const sessionPrefix = options.sessionPrefix ?? "memcorrect";
|
|
30611
|
+
return {
|
|
30612
|
+
label,
|
|
30613
|
+
async reset() {
|
|
30614
|
+
await adapter.reset();
|
|
30615
|
+
},
|
|
30616
|
+
async ingestTurn(sessionKey, role, text, at) {
|
|
30617
|
+
await adapter.store(`${sessionPrefix}:${sessionKey}`, [
|
|
30618
|
+
{ role, content: text, timestamp: at }
|
|
30619
|
+
]);
|
|
30620
|
+
},
|
|
30621
|
+
async recall(query, sessionKey) {
|
|
30622
|
+
const text = await adapter.recall(`${sessionPrefix}:${sessionKey}`, query);
|
|
30623
|
+
const trimmed = text.trim();
|
|
30624
|
+
if (trimmed.length === 0) return [];
|
|
30625
|
+
return trimmed.split(/\n\s*\n/).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
30626
|
+
},
|
|
30627
|
+
async correct(text, sessionKey, at) {
|
|
30628
|
+
await adapter.store(`${sessionPrefix}:${sessionKey}`, [
|
|
30629
|
+
{ role: "user", content: text, timestamp: at }
|
|
30630
|
+
]);
|
|
30631
|
+
},
|
|
30632
|
+
async runMaintenance() {
|
|
30633
|
+
await adapter.drain?.();
|
|
30634
|
+
}
|
|
30635
|
+
};
|
|
30636
|
+
}
|
|
30637
|
+
|
|
30638
|
+
// src/benchmarks/remnic/memcorrect/runner.ts
|
|
30639
|
+
var memcorrectDefinition = {
|
|
30640
|
+
id: "memcorrect-v1",
|
|
30641
|
+
title: "MemCorrect (correction / steerability)",
|
|
30642
|
+
tier: "remnic",
|
|
30643
|
+
status: "ready",
|
|
30644
|
+
runnerAvailable: true,
|
|
30645
|
+
meta: {
|
|
30646
|
+
name: "memcorrect-v1",
|
|
30647
|
+
version: "1.0.0",
|
|
30648
|
+
description: "Open correction/steerability benchmark: uptake, non-resurrection, collateral, scope-precision, false-apply, reassertion. System-agnostic adapter interface; hermetic seeded synthetic corpus.",
|
|
30649
|
+
category: "conversational",
|
|
30650
|
+
citation: "Remnic MemCorrect v1 (issue #1584). Open benchmark; adapter contract is the public contribution."
|
|
30651
|
+
}
|
|
30652
|
+
};
|
|
30653
|
+
var MEMCORRECT_LOWER_IS_BETTER = /* @__PURE__ */ new Set([
|
|
30654
|
+
"uptake_latency",
|
|
30655
|
+
"uptake_latency_censored",
|
|
30656
|
+
"false_apply"
|
|
30657
|
+
]);
|
|
30658
|
+
var QUICK_OPTIONS2 = {
|
|
30659
|
+
personaCount: 2,
|
|
30660
|
+
factsPerPersona: 4,
|
|
30661
|
+
seed: 12613607,
|
|
30662
|
+
nowIso: "2026-07-05T00:00:00.000Z",
|
|
30663
|
+
maintenanceCycles: 3,
|
|
30664
|
+
uptakeLatencyCap: 5
|
|
30665
|
+
};
|
|
30666
|
+
var FULL_OPTIONS2 = {
|
|
30667
|
+
personaCount: 5,
|
|
30668
|
+
factsPerPersona: 8,
|
|
30669
|
+
seed: 12613607,
|
|
30670
|
+
nowIso: "2026-07-05T00:00:00.000Z",
|
|
30671
|
+
maintenanceCycles: 5,
|
|
30672
|
+
uptakeLatencyCap: 8
|
|
30673
|
+
};
|
|
30674
|
+
function resolveAdapter(options) {
|
|
30675
|
+
const override = options.benchmarkOptions?.["adapter"];
|
|
30676
|
+
if (override && typeof override === "object" && "reset" in override && "ingestTurn" in override && "recall" in override) {
|
|
30677
|
+
const adapter = override;
|
|
30678
|
+
return { adapter, adapterLabel: adapter.label ?? "custom" };
|
|
30679
|
+
}
|
|
30680
|
+
return {
|
|
30681
|
+
adapter: createRemnicMemCorrectAdapter(options.system, {
|
|
30682
|
+
label: "remnic-native"
|
|
30683
|
+
}),
|
|
30684
|
+
adapterLabel: "remnic-native"
|
|
30685
|
+
};
|
|
30686
|
+
}
|
|
30687
|
+
async function runScenario(scenario, adapter, maintenanceCycles, uptakeLatencyCap) {
|
|
30688
|
+
await adapter.reset();
|
|
30689
|
+
const log = [];
|
|
30690
|
+
let turn = 0;
|
|
30691
|
+
const sessionKey = scenario.namespace;
|
|
30692
|
+
const recordProbe = (phase, query, namespace, recalled, at) => {
|
|
30693
|
+
log.push({ scenarioId: scenario.id, phase, turnIndex: turn, namespace, query, recalled, at });
|
|
30694
|
+
};
|
|
30695
|
+
for (const t of scenario.establishingTurns) {
|
|
30696
|
+
await adapter.ingestTurn(sessionKey, t.role, t.text, t.at);
|
|
30697
|
+
turn += 1;
|
|
30698
|
+
}
|
|
30699
|
+
if (scenario.scopedTwin) {
|
|
30700
|
+
for (const t of scenario.scopedTwin.establishingTurns) {
|
|
30701
|
+
await adapter.ingestTurn(scenario.scopedTwin.namespace, t.role, t.text, t.at);
|
|
30702
|
+
turn += 1;
|
|
30703
|
+
}
|
|
30704
|
+
}
|
|
30705
|
+
for (const probe of scenario.unrelatedProbes) {
|
|
30706
|
+
for (const t of probe.establishingTurns) {
|
|
30707
|
+
await adapter.ingestTurn(sessionKey, t.role, t.text, t.at);
|
|
30708
|
+
turn += 1;
|
|
30709
|
+
}
|
|
30710
|
+
}
|
|
30711
|
+
const collateralBefore = [];
|
|
30712
|
+
for (const probe of scenario.unrelatedProbes) {
|
|
30713
|
+
turn += 1;
|
|
30714
|
+
const recalled = await adapter.recall(probe.query, sessionKey);
|
|
30715
|
+
recordProbe("baseline", probe.query, sessionKey, recalled, scenario.correction.turn.at);
|
|
30716
|
+
collateralBefore.push(
|
|
30717
|
+
containsAll(recalled.join(" "), [probe.expectedContent]) ? 1 : 0
|
|
30718
|
+
);
|
|
30719
|
+
}
|
|
30720
|
+
await adapter.correct(scenario.correction.turn.text, sessionKey, scenario.correction.turn.at);
|
|
30721
|
+
turn += 1;
|
|
30722
|
+
const correctionTurnIndex = turn;
|
|
30723
|
+
{
|
|
30724
|
+
turn += 1;
|
|
30725
|
+
const recalled = await adapter.recall(scenario.probe.query, sessionKey);
|
|
30726
|
+
recordProbe("post_correction", scenario.probe.query, sessionKey, recalled, scenario.correction.turn.at);
|
|
30727
|
+
}
|
|
30728
|
+
for (const anti of scenario.antiEvents) {
|
|
30729
|
+
await adapter.ingestTurn(sessionKey, anti.turn.role, anti.turn.text, anti.turn.at);
|
|
30730
|
+
turn += 1;
|
|
30731
|
+
turn += 1;
|
|
30732
|
+
const recalled = await adapter.recall(anti.probeQuery, sessionKey);
|
|
30733
|
+
recordProbe("post_correction", anti.probeQuery, sessionKey, recalled, anti.turn.at);
|
|
30734
|
+
}
|
|
30735
|
+
if (scenario.scopedTwin) {
|
|
30736
|
+
turn += 1;
|
|
30737
|
+
const recalled = await adapter.recall(scenario.probe.query, scenario.scopedTwin.namespace);
|
|
30738
|
+
recordProbe("post_correction", scenario.probe.query, scenario.scopedTwin.namespace, recalled, scenario.correction.turn.at);
|
|
30739
|
+
}
|
|
30740
|
+
const collateralAfter = [];
|
|
30741
|
+
for (const probe of scenario.unrelatedProbes) {
|
|
30742
|
+
const recalled = await adapter.recall(probe.query, sessionKey);
|
|
30743
|
+
collateralAfter.push(
|
|
30744
|
+
containsAll(recalled.join(" "), [probe.expectedContent]) ? 1 : 0
|
|
30745
|
+
);
|
|
30746
|
+
}
|
|
30747
|
+
for (let i = 0; i < maintenanceCycles; i += 1) {
|
|
30748
|
+
await adapter.runMaintenance();
|
|
30749
|
+
turn += 1;
|
|
30750
|
+
}
|
|
30751
|
+
{
|
|
30752
|
+
const recalled = await adapter.recall(scenario.probe.query, sessionKey);
|
|
30753
|
+
recordProbe("post_maintenance", scenario.probe.query, sessionKey, recalled, scenario.correction.turn.at);
|
|
30754
|
+
turn += 1;
|
|
30755
|
+
}
|
|
30756
|
+
for (const t of scenario.establishingTurns) {
|
|
30757
|
+
await adapter.ingestTurn(sessionKey, t.role, t.text, t.at);
|
|
30758
|
+
turn += 1;
|
|
30759
|
+
}
|
|
30760
|
+
{
|
|
30761
|
+
const recalled = await adapter.recall(scenario.probe.query, sessionKey);
|
|
30762
|
+
recordProbe("post_reingest", scenario.probe.query, sessionKey, recalled, scenario.correction.turn.at);
|
|
30763
|
+
turn += 1;
|
|
30764
|
+
}
|
|
30765
|
+
let reassertion2 = null;
|
|
30766
|
+
if (scenario.reassertion) {
|
|
30767
|
+
await adapter.ingestTurn(
|
|
30768
|
+
sessionKey,
|
|
30769
|
+
scenario.reassertion.turn.role,
|
|
30770
|
+
scenario.reassertion.turn.text,
|
|
30771
|
+
scenario.reassertion.turn.at
|
|
30772
|
+
);
|
|
30773
|
+
turn += 1;
|
|
30774
|
+
const recalled = await adapter.recall(scenario.probe.query, sessionKey);
|
|
30775
|
+
recordProbe("post_reassertion", scenario.probe.query, sessionKey, recalled, scenario.reassertion.turn.at);
|
|
30776
|
+
turn += 1;
|
|
30777
|
+
reassertion2 = {
|
|
30778
|
+
scenarioId: scenario.id,
|
|
30779
|
+
namespace: sessionKey,
|
|
30780
|
+
expectedContent: scenario.reassertion.expectedContent
|
|
30781
|
+
};
|
|
30782
|
+
}
|
|
30783
|
+
const correction = {
|
|
30784
|
+
scenarioId: scenario.id,
|
|
30785
|
+
namespace: sessionKey,
|
|
30786
|
+
turnIndex: correctionTurnIndex,
|
|
30787
|
+
retiredContent: scenario.correction.retiredContent,
|
|
30788
|
+
correctedContent: scenario.correction.correctedContent,
|
|
30789
|
+
scopedTwin: scenario.scopedTwin
|
|
30790
|
+
};
|
|
30791
|
+
const antiEvents = scenario.antiEvents.map((anti) => ({
|
|
30792
|
+
scenarioId: scenario.id,
|
|
30793
|
+
namespace: sessionKey,
|
|
30794
|
+
probeQuery: anti.probeQuery,
|
|
30795
|
+
shouldNotAppear: anti.shouldNotAppear
|
|
30796
|
+
}));
|
|
30797
|
+
const provenanceCite = null;
|
|
30798
|
+
const metrics = computeMetricBundle({
|
|
30799
|
+
log,
|
|
30800
|
+
corrections: [correction],
|
|
30801
|
+
antiEvents,
|
|
30802
|
+
reassertions: reassertion2 ? [reassertion2] : [],
|
|
30803
|
+
collateralBefore,
|
|
30804
|
+
collateralAfter,
|
|
30805
|
+
provenanceCites: [provenanceCite],
|
|
30806
|
+
uptakeLatencyCap
|
|
30807
|
+
});
|
|
30808
|
+
return {
|
|
30809
|
+
log,
|
|
30810
|
+
correction,
|
|
30811
|
+
antiEvents,
|
|
30812
|
+
reassertion: reassertion2,
|
|
30813
|
+
collateralBefore,
|
|
30814
|
+
collateralAfter,
|
|
30815
|
+
provenanceCite,
|
|
30816
|
+
metrics
|
|
30817
|
+
};
|
|
30818
|
+
}
|
|
30819
|
+
async function runMemCorrectBenchmark(options) {
|
|
30820
|
+
const baseOptions = options.mode === "quick" ? QUICK_OPTIONS2 : FULL_OPTIONS2;
|
|
30821
|
+
const seed = typeof options.seed === "number" ? options.seed : baseOptions.seed;
|
|
30822
|
+
const generatorOptions = { ...baseOptions, seed };
|
|
30823
|
+
const corpus = generateMemCorrectCorpus(generatorOptions);
|
|
30824
|
+
const validation = validateCorpus(corpus);
|
|
30825
|
+
if (!validation.ok) {
|
|
30826
|
+
throw new Error(
|
|
30827
|
+
`MemCorrect corpus failed schema validation: ${validation.errors.map((e) => `${e.scenarioId}: ${e.message}`).join("; ")}`
|
|
30828
|
+
);
|
|
30829
|
+
}
|
|
30830
|
+
const { adapter, adapterLabel } = resolveAdapter(options);
|
|
30831
|
+
const { limit } = options;
|
|
30832
|
+
let scenarios;
|
|
30833
|
+
if (typeof limit !== "number") {
|
|
30834
|
+
scenarios = corpus.scenarios;
|
|
30835
|
+
} else if (!Number.isInteger(limit) || limit < 0) {
|
|
30836
|
+
throw new Error(
|
|
30837
|
+
`MemCorrect --limit must be a non-negative integer; got ${String(limit)}`
|
|
30838
|
+
);
|
|
30839
|
+
} else {
|
|
30840
|
+
scenarios = corpus.scenarios.slice(0, limit);
|
|
30841
|
+
}
|
|
30842
|
+
const tasks = [];
|
|
30843
|
+
const aggregateLog = [];
|
|
30844
|
+
const aggregateCorrections = [];
|
|
30845
|
+
const aggregateAntiEvents = [];
|
|
30846
|
+
const aggregateReassertions = [];
|
|
30847
|
+
const aggregateCollateralBefore = [];
|
|
30848
|
+
const aggregateCollateralAfter = [];
|
|
30849
|
+
const aggregateProvenance = [];
|
|
30850
|
+
for (const scenario of scenarios) {
|
|
30851
|
+
const started = performance.now();
|
|
30852
|
+
const run = await runScenario(
|
|
30853
|
+
scenario,
|
|
30854
|
+
adapter,
|
|
30855
|
+
generatorOptions.maintenanceCycles,
|
|
30856
|
+
generatorOptions.uptakeLatencyCap
|
|
30857
|
+
);
|
|
30858
|
+
const latencyMs = Math.round(performance.now() - started);
|
|
30859
|
+
aggregateLog.push(...run.log);
|
|
30860
|
+
aggregateCorrections.push(run.correction);
|
|
30861
|
+
aggregateAntiEvents.push(...run.antiEvents);
|
|
30862
|
+
if (run.reassertion) aggregateReassertions.push(run.reassertion);
|
|
30863
|
+
aggregateCollateralBefore.push(...run.collateralBefore);
|
|
30864
|
+
aggregateCollateralAfter.push(...run.collateralAfter);
|
|
30865
|
+
aggregateProvenance.push(run.provenanceCite);
|
|
30866
|
+
const m = run.metrics;
|
|
30867
|
+
const scores = {
|
|
30868
|
+
uptake_at_next: m.uptake_at_next,
|
|
30869
|
+
uptake_latency: m.uptake_latency,
|
|
30870
|
+
uptake_latency_censored: m.uptake_latency_censored,
|
|
30871
|
+
non_resurrection: m.non_resurrection,
|
|
30872
|
+
false_apply: m.false_apply
|
|
30873
|
+
};
|
|
30874
|
+
if (m.scope_precision !== null) scores.scope_precision = m.scope_precision;
|
|
30875
|
+
if (m.reassertion !== null) scores.reassertion = m.reassertion;
|
|
30876
|
+
const task = {
|
|
30877
|
+
taskId: scenario.id,
|
|
30878
|
+
question: scenario.probe.query,
|
|
30879
|
+
expected: JSON.stringify({
|
|
30880
|
+
correctedContent: scenario.correction.correctedContent,
|
|
30881
|
+
retiredContent: scenario.correction.retiredContent
|
|
30882
|
+
}),
|
|
30883
|
+
actual: JSON.stringify({
|
|
30884
|
+
shape: scenario.correction.shape,
|
|
30885
|
+
namespace: scenario.namespace,
|
|
30886
|
+
postCorrectionRecall: run.log.find(
|
|
30887
|
+
(e) => e.phase === "post_correction" && e.namespace === scenario.namespace
|
|
30888
|
+
)?.recalled.slice(0, 3) ?? []
|
|
30889
|
+
}),
|
|
30890
|
+
scores,
|
|
30891
|
+
latencyMs,
|
|
30892
|
+
tokens: { input: 0, output: 0 },
|
|
30893
|
+
details: {
|
|
30894
|
+
scenarioId: scenario.id,
|
|
30895
|
+
shape: scenario.correction.shape,
|
|
30896
|
+
category: scenario.category,
|
|
30897
|
+
namespace: scenario.namespace,
|
|
30898
|
+
adapter: adapterLabel,
|
|
30899
|
+
metrics: {
|
|
30900
|
+
memcorrect: m
|
|
30901
|
+
}
|
|
30902
|
+
}
|
|
30903
|
+
};
|
|
30904
|
+
tasks.push(task);
|
|
30905
|
+
options.onTaskComplete?.(task, tasks.length, scenarios.length);
|
|
30906
|
+
}
|
|
30907
|
+
const aggregateMetrics = computeMetricBundle({
|
|
30908
|
+
log: aggregateLog,
|
|
30909
|
+
corrections: aggregateCorrections,
|
|
30910
|
+
antiEvents: aggregateAntiEvents,
|
|
30911
|
+
reassertions: aggregateReassertions,
|
|
30912
|
+
collateralBefore: aggregateCollateralBefore,
|
|
30913
|
+
collateralAfter: aggregateCollateralAfter,
|
|
30914
|
+
provenanceCites: aggregateProvenance,
|
|
30915
|
+
uptakeLatencyCap: generatorOptions.uptakeLatencyCap
|
|
30916
|
+
});
|
|
30917
|
+
const remnicVersion = await getRemnicVersion();
|
|
30918
|
+
const totalLatencyMs = tasks.reduce((sum, t) => sum + t.latencyMs, 0);
|
|
30919
|
+
const { adapter: _liveAdapter, ...persistableBenchmarkOptions } = options.benchmarkOptions ?? {};
|
|
30920
|
+
return {
|
|
30921
|
+
meta: {
|
|
30922
|
+
id: randomUUID31(),
|
|
30923
|
+
benchmark: options.benchmark.id,
|
|
30924
|
+
benchmarkTier: options.benchmark.tier,
|
|
30925
|
+
version: options.benchmark.meta.version,
|
|
30926
|
+
remnicVersion,
|
|
30927
|
+
gitSha: getGitSha(),
|
|
30928
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30929
|
+
mode: options.mode,
|
|
30930
|
+
runCount: 1,
|
|
30931
|
+
seeds: [seed],
|
|
30932
|
+
datasetHash: corpusHash(corpus)
|
|
30933
|
+
},
|
|
30934
|
+
config: {
|
|
30935
|
+
runtimeProfile: options.runtimeProfile ?? null,
|
|
30936
|
+
systemProvider: options.systemProvider ?? null,
|
|
30937
|
+
judgeProvider: options.judgeProvider ?? null,
|
|
30938
|
+
adapterMode: adapterLabel,
|
|
30939
|
+
remnicConfig: options.remnicConfig ?? {},
|
|
30940
|
+
benchmarkOptions: {
|
|
30941
|
+
...persistableBenchmarkOptions,
|
|
30942
|
+
personaCount: generatorOptions.personaCount,
|
|
30943
|
+
factsPerPersona: generatorOptions.factsPerPersona,
|
|
30944
|
+
maintenanceCycles: generatorOptions.maintenanceCycles,
|
|
30945
|
+
uptakeLatencyCap: generatorOptions.uptakeLatencyCap,
|
|
30946
|
+
// Headline metric bundle computed across the union of all scenario
|
|
30947
|
+
// probe logs (more robust than the per-task mean for fraction
|
|
30948
|
+
// metrics when scenario sizes vary). `aggregateTaskScores` in
|
|
30949
|
+
// results.aggregates is the per-task-mean view.
|
|
30950
|
+
aggregateMetrics
|
|
30951
|
+
}
|
|
30952
|
+
},
|
|
30953
|
+
cost: {
|
|
30954
|
+
totalTokens: 0,
|
|
30955
|
+
inputTokens: 0,
|
|
30956
|
+
outputTokens: 0,
|
|
30957
|
+
estimatedCostUsd: 0,
|
|
30958
|
+
totalLatencyMs,
|
|
30959
|
+
meanQueryLatencyMs: tasks.length > 0 ? totalLatencyMs / tasks.length : 0,
|
|
30960
|
+
judgeModelCalls: 0
|
|
30961
|
+
},
|
|
30962
|
+
results: {
|
|
30963
|
+
tasks,
|
|
30964
|
+
aggregates: aggregateTaskScores(tasks.map((t) => t.scores)),
|
|
30965
|
+
statistics: {
|
|
30966
|
+
confidenceIntervals: {},
|
|
30967
|
+
bootstrapSamples: 0
|
|
30968
|
+
}
|
|
30969
|
+
},
|
|
30970
|
+
environment: {
|
|
30971
|
+
os: process.platform,
|
|
30972
|
+
nodeVersion: process.version,
|
|
30973
|
+
hardware: process.arch
|
|
30974
|
+
}
|
|
30975
|
+
};
|
|
30976
|
+
}
|
|
30977
|
+
|
|
29865
30978
|
// src/registry.ts
|
|
29866
30979
|
var REGISTERED_BENCHMARKS = [
|
|
29867
30980
|
{
|
|
@@ -29995,6 +31108,10 @@ var REGISTERED_BENCHMARKS = [
|
|
|
29995
31108
|
{
|
|
29996
31109
|
...retentionAgedDatasetDefinition,
|
|
29997
31110
|
run: runRetentionAgedDatasetBenchmark
|
|
31111
|
+
},
|
|
31112
|
+
{
|
|
31113
|
+
...memcorrectDefinition,
|
|
31114
|
+
run: runMemCorrectBenchmark
|
|
29998
31115
|
}
|
|
29999
31116
|
];
|
|
30000
31117
|
function listBenchmarks() {
|
|
@@ -30023,8 +31140,9 @@ function finalizeBenchmarkResultConfig(result, options) {
|
|
|
30023
31140
|
result.config.runtimeProfile ??= options.runtimeProfile ?? null;
|
|
30024
31141
|
result.config.internalProvider ??= options.internalProvider ?? null;
|
|
30025
31142
|
if (options.benchmarkOptions !== void 0 || options.limit !== void 0) {
|
|
31143
|
+
const { adapter: _omitAdapter, ...persistableOptions } = options.benchmarkOptions ?? {};
|
|
30026
31144
|
result.config.benchmarkOptions = {
|
|
30027
|
-
...
|
|
31145
|
+
...persistableOptions,
|
|
30028
31146
|
...options.limit !== void 0 ? { limit: options.limit } : {},
|
|
30029
31147
|
...result.config.benchmarkOptions ?? {}
|
|
30030
31148
|
};
|
|
@@ -30234,13 +31352,13 @@ function wrapJudgeWithCache(args) {
|
|
|
30234
31352
|
// differentiator is part of the prompt hash. Bumping
|
|
30235
31353
|
// JUDGE_CACHE_PROTOCOL_VERSION invalidates verdicts when judge
|
|
30236
31354
|
// prompt/parse semantics change (PR #1591, High).
|
|
30237
|
-
judgePromptHash:
|
|
31355
|
+
judgePromptHash: createHash10("sha256").update(JUDGE_CACHE_PROTOCOL_VERSION).update("").update(args.amaBenchJudgeProtocol).update("").update(args.role).digest("hex"),
|
|
30238
31356
|
judgeModelId: args.provider?.model !== void 0 && args.provider.model.length > 0 ? `${args.provider.model}${crossJudgeIdSuffix}` : `unknown-${args.role}-judge`,
|
|
30239
31357
|
// Full judge configuration, deterministically serialized (sorted
|
|
30240
31358
|
// keys) so provider/base-url/retry changes produce fresh cache
|
|
30241
31359
|
// keys. `role` is included so primary and cross judges never
|
|
30242
31360
|
// share a paramsHash.
|
|
30243
|
-
judgeParamsHash:
|
|
31361
|
+
judgeParamsHash: createHash10("sha256").update(
|
|
30244
31362
|
stableStringify2({
|
|
30245
31363
|
role: args.role,
|
|
30246
31364
|
provider: args.provider
|
|
@@ -30671,7 +31789,8 @@ function compareResults(baseline, candidate, threshold = 0.05, lowerIsBetter = /
|
|
|
30671
31789
|
}
|
|
30672
31790
|
var LOWER_IS_BETTER_BY_BENCHMARK = {
|
|
30673
31791
|
"ingestion-setup-friction": INGESTION_SETUP_FRICTION_LOWER_IS_BETTER,
|
|
30674
|
-
"retrieval-reasoning-trace": RETRIEVAL_REASONING_TRACE_LOWER_IS_BETTER
|
|
31792
|
+
"retrieval-reasoning-trace": RETRIEVAL_REASONING_TRACE_LOWER_IS_BETTER,
|
|
31793
|
+
"memcorrect-v1": MEMCORRECT_LOWER_IS_BETTER
|
|
30675
31794
|
};
|
|
30676
31795
|
function getBenchmarkLowerIsBetter(benchmarkId) {
|
|
30677
31796
|
return LOWER_IS_BETTER_BY_BENCHMARK[benchmarkId] ?? /* @__PURE__ */ new Set();
|
|
@@ -30995,7 +32114,7 @@ function formatError(error) {
|
|
|
30995
32114
|
}
|
|
30996
32115
|
|
|
30997
32116
|
// src/benchmarks/custom/runner.ts
|
|
30998
|
-
import { randomUUID as
|
|
32117
|
+
import { randomUUID as randomUUID32 } from "crypto";
|
|
30999
32118
|
import path33 from "path";
|
|
31000
32119
|
import { expandTildePath as expandTildePath4 } from "@remnic/core";
|
|
31001
32120
|
async function runCustomBenchmarkFile(filePath, options) {
|
|
@@ -31083,7 +32202,7 @@ async function runCustomBenchmark(spec, options) {
|
|
|
31083
32202
|
const totalOutputTokens = tasks.reduce((sum, task) => sum + task.tokens.output, 0);
|
|
31084
32203
|
return finalizeBenchmarkResultConfig({
|
|
31085
32204
|
meta: {
|
|
31086
|
-
id:
|
|
32205
|
+
id: randomUUID32(),
|
|
31087
32206
|
benchmark: options.benchmark.id,
|
|
31088
32207
|
benchmarkTier: options.benchmark.tier,
|
|
31089
32208
|
version: options.benchmark.meta.version,
|
|
@@ -32080,7 +33199,7 @@ var chatFixture = {
|
|
|
32080
33199
|
};
|
|
32081
33200
|
|
|
32082
33201
|
// src/judges/calibration-slice.ts
|
|
32083
|
-
import { createHash as
|
|
33202
|
+
import { createHash as createHash11, randomBytes as randomBytes3 } from "crypto";
|
|
32084
33203
|
import { mkdir as mkdir16, readFile as readFile21, rename as rename3, unlink as unlink3, writeFile as writeFile15 } from "fs/promises";
|
|
32085
33204
|
import path34 from "path";
|
|
32086
33205
|
|
|
@@ -32157,7 +33276,7 @@ function selectCalibrationSlice(questionIds, size = CALIBRATION_SLICE_SIZE) {
|
|
|
32157
33276
|
unique.push(id);
|
|
32158
33277
|
}
|
|
32159
33278
|
}
|
|
32160
|
-
return unique.map((id) => ({ id, digest:
|
|
33279
|
+
return unique.map((id) => ({ id, digest: createHash11("sha256").update(id, "utf8").digest("hex") })).sort((a, b) => a.digest < b.digest ? -1 : a.digest > b.digest ? 1 : 0).slice(0, Math.min(size, unique.length)).map((entry) => entry.id);
|
|
32161
33280
|
}
|
|
32162
33281
|
async function runJudgeCalibration(options) {
|
|
32163
33282
|
const binScore = options.binScore ?? ((score) => binarizeJudgeScore(score));
|
|
@@ -32823,7 +33942,7 @@ var PROCEDURAL_REAL_SCENARIOS_SMOKE = [
|
|
|
32823
33942
|
];
|
|
32824
33943
|
|
|
32825
33944
|
// src/security/extraction-attack/tokenize.ts
|
|
32826
|
-
function
|
|
33945
|
+
function tokenize4(text) {
|
|
32827
33946
|
return text.toLowerCase().split(/[^a-z0-9]+/u).filter((t) => t.length > 2);
|
|
32828
33947
|
}
|
|
32829
33948
|
|
|
@@ -32865,7 +33984,7 @@ function createSeededRng2(seed) {
|
|
|
32865
33984
|
}
|
|
32866
33985
|
};
|
|
32867
33986
|
}
|
|
32868
|
-
var tokenizeContent =
|
|
33987
|
+
var tokenizeContent = tokenize4;
|
|
32869
33988
|
function recoveryTokensFor(memory) {
|
|
32870
33989
|
if (memory.tokens && memory.tokens.length > 0) {
|
|
32871
33990
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -33344,11 +34463,11 @@ function createSyntheticTarget(options) {
|
|
|
33344
34463
|
}
|
|
33345
34464
|
const normalized = memories.map((m) => ({
|
|
33346
34465
|
memory: m,
|
|
33347
|
-
tokens: new Set((m.tokens ??
|
|
34466
|
+
tokens: new Set((m.tokens ?? tokenize4(m.content)).map((t) => t.toLowerCase()))
|
|
33348
34467
|
}));
|
|
33349
34468
|
return {
|
|
33350
34469
|
async recall(query, recallOptions) {
|
|
33351
|
-
const qTokens =
|
|
34470
|
+
const qTokens = tokenize4(query);
|
|
33352
34471
|
if (qTokens.length === 0) return [];
|
|
33353
34472
|
const requestedNs = recallOptions?.namespace;
|
|
33354
34473
|
if (enforceNamespaceAcl && requestedNs !== void 0 && requestedNs !== allowedNamespace) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/bench",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.706",
|
|
4
4
|
"description": "Retrieval latency ladder benchmarks + CI regression gates for @remnic/core",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"hyparquet": "^1.25.7",
|
|
38
38
|
"yaml": "^2.4.2",
|
|
39
|
-
"@remnic/core": "^9.3.
|
|
39
|
+
"@remnic/core": "^9.3.706"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"tsup": "^8.5.1",
|