@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 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 !== "ama-bench") {
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 createHash9 } from "crypto";
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
- ...options.benchmarkOptions,
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: createHash9("sha256").update(JUDGE_CACHE_PROTOCOL_VERSION).update("").update(args.amaBenchJudgeProtocol).update("").update(args.role).digest("hex"),
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: createHash9("sha256").update(
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 randomUUID31 } from "crypto";
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: randomUUID31(),
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 createHash10, randomBytes as randomBytes3 } from "crypto";
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: createHash10("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);
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 tokenize3(text) {
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 = tokenize3;
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 ?? tokenize3(m.content)).map((t) => t.toLowerCase()))
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 = tokenize3(query);
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.704",
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.704"
39
+ "@remnic/core": "^9.3.706"
40
40
  },
41
41
  "devDependencies": {
42
42
  "tsup": "^8.5.1",