Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ release/calibration/**
!release/calibration/2026-06-04-memory-atom-v16/coretex-launch-v16-artifacts.json
!release/calibration/2026-06-04-memory-atom-v16/bundle-manifest-v2-dgen1-policy-r5-atom-v16-300k-enabled.json
!release/calibration/2026-06-04-memory-atom-v16/evaluator-profile-v2-dgen1-policy-r5-atom-v16-300k-enabled.json
!release/calibration/2026-06-04-memory-atom-v16/screener-threshold-v16-coldstart-floor-repin-livebundle-2026-06-16.json

# Generated DACR corpus (regenerated from HF dataset by scripts/build-corpus-from-dacr.mjs)
benchmark/fixtures/dacr/
Expand Down
4 changes: 2 additions & 2 deletions packages/coretex/src/bundle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ export interface BaseRpcConfigPin {
export const DEFAULT_BASE_RPC_CONFIG: BaseRpcConfigPin = {
chainId: 8453, // Base mainnet
blockTimeSeconds: 2,
targetBlockOffset: 30, // ≈ 60 s on Base
targetBlockOffset: 15, // ≈ 30 s on Base
replayBlockhashLookbackBlocks: 50_000, // ≈ 28 h coverage
};

Expand Down Expand Up @@ -824,7 +824,7 @@ export const DEFAULT_COMPOSITE_WEIGHTS_PIN: CompositeWeightPin = {
};

export const DEFAULT_PATCH_FLOORS: PatchAcceptanceFloorsPin = {
minImprovementPpm: 2500,
minImprovementPpm: 500,
structuralFloor: 0.95,
protectedRegressionFloor: 0.05,
familyCatastrophicFloor: 0.85,
Expand Down
13 changes: 13 additions & 0 deletions packages/coretex/src/coordinator/coretex-coordinator-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ export interface RealEvaluator {
* under the pinned blockhash; the secretless scorer injects them verbatim.
* Requires seedContext. The local CPU evaluator path omits it. */
injectedSeeds?: { readonly gateSeed: string; readonly confirmSeed: string };
/** OPTIONAL coordinator-authoritative offset for the supplied seedContext.
* Remote/keyless evaluators use it to stamp artifacts/proofs with the same
* targetBlockOffset the coordinator used when drawing targetBlock. */
targetBlockOffset?: number;
}): Promise<EvalResult> | EvalResult;
}

Expand Down Expand Up @@ -632,6 +636,15 @@ export class CoreTexCoordinatorCore {

// ── chain-event verification + apply ─────────────────────────────────────
private applyChainEvent(ev: CoreTexStateAdvancedEvent): void {
if (ev.epoch < this.config.epoch) {
// Finalized PRIOR-epoch advance — already folded into this epoch's on-chain
// start root (liveRoot was seeded to it at load). Skip; re-applying would fail
// the parent/transitionIndex checks. Lets the watcher replay from a start block
// that predates the live epoch (e.g. a stale CORETEX_REPLAY_FROM_BLOCK after an
// epoch advance) WITHOUT dead-locking; transitionIndex is per-epoch (resets to 0)
// so contiguity is preserved.
return;
}
if (ev.epoch !== this.config.epoch) {
throw new Error(`watcher: event epoch ${ev.epoch} ≠ configured ${this.config.epoch}`);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/coretex/src/coordinator/per-patch-evaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ export interface PerPatchEvaluatorDeps {
readonly dedupCache: ReadonlyMap<string, PerPatchReceipt>;
/** Per-miner admission counter. Same contract as dedupCache. */
readonly minerAdmissions: ReadonlyMap<string, number>;
/** Max wait for the future blockhash. Defaults to 120 s (2× the
* 60 s budget at targetBlockOffset=30) — generous enough that
/** Max wait for the future blockhash. Defaults to 120 s (4× the
* 30 s budget at targetBlockOffset=15) — generous enough that
* Base must be genuinely stalled for this to fire. */
readonly waitTimeoutMs?: number;
/** §8 anti-grinding — OPTIONAL pinned seed context. When supplied, the
Expand Down
27 changes: 22 additions & 5 deletions packages/coretex/src/coordinator/production-evaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
type AttestedCoordinatorBootAttestation,
type CoreTexBundleManifest,
type EvaluatorProfile,
DEFAULT_BASE_RPC_CONFIG,
} from '../bundle/index.js';
import {
loadProductionCorpus,
Expand Down Expand Up @@ -365,6 +366,11 @@ export type ProductionCoreTexEvaluator = RealEvaluator & {
* seedContext. Requires seedContext. The validator's post-reveal
* re-derivation from the revealed secret is the integrity backstop. */
injectedSeeds?: { readonly gateSeed: string; readonly confirmSeed: string };
/** Coordinator-authoritative target block offset for an injected seedContext.
* The keyless scorer receives this per job and stamps artifacts/proofs with
* the same value the coordinator used to draw targetBlock. Local CPU scoring
* omits it and uses the construction-time bundle/default offset. */
targetBlockOffset?: number;
}): Promise<ProductionEvalResult>;
/** Hash-bound boot attestation (§2): resolved model id + revision +
* reranker mode + instruction + prompt-template hash + Memory-IR mode. */
Expand Down Expand Up @@ -569,6 +575,10 @@ export function createCoreTexEvaluatorCore(deps: ProductionCoreTexEvaluatorCoreD
const onSeedDerived = coordinatorPinnedSeed || priorAttempt
? undefined
: (seedContext: PerPatchSeedContext) => deps.dedupStore.recordSeedDrawnAndAdmission(dedupKey, seedContext, miner);
const effectiveTargetBlockOffset = input.targetBlockOffset ?? deps.targetBlockOffset;
if (!Number.isSafeInteger(effectiveTargetBlockOffset) || effectiveTargetBlockOffset <= 0) {
throw new Error(`targetBlockOffset must be a positive integer (got ${String(effectiveTargetBlockOffset)})`);
}

const dual = await runPerPatchEvaluation({
normalizedPatchBytes: patchBytes,
Expand All @@ -579,7 +589,7 @@ export function createCoreTexEvaluatorCore(deps: ProductionCoreTexEvaluatorCoreD
}, {
rpcClient: deps.rpcClient,
scorer,
targetBlockOffset: deps.targetBlockOffset,
targetBlockOffset: effectiveTargetBlockOffset,
thresholdPpm: effectiveThresholdPpm,
perMinerCap: deps.perMinerCap,
...(deps.epochSecret ? { epochSecret: deps.epochSecret } : {}),
Expand All @@ -594,13 +604,20 @@ export function createCoreTexEvaluatorCore(deps: ProductionCoreTexEvaluatorCoreD
...(onSeedDerived ? { onSeedDerived } : {}),
});

const drewPacks = dual.receivedAtBlock > 0;
if (drewPacks) {
const actualTargetBlockOffset = dual.targetBlock - dual.receivedAtBlock;
if (!Number.isSafeInteger(actualTargetBlockOffset) || actualTargetBlockOffset <= 0 || actualTargetBlockOffset !== effectiveTargetBlockOffset) {
throw new Error(`targetBlockOffset mismatch: targetBlock ${dual.targetBlock} != receivedAtBlock ${dual.receivedAtBlock} + offset ${effectiveTargetBlockOffset}`);
}
}

// The patch consumed a pack draw iff seeds were derived. The admission was
// ALREADY charged ATOMICALLY with the seed pin inside onSeedDerived (which
// runPerPatchEvaluation invokes only AFTER the admission gate passes and
// the seed is derived) — so there is no separate post-result charge to
// make here (exactly-once, crash-safe). We only record the dedup outcome,
// which is what short-circuits a completed resubmission.
const drewPacks = dual.receivedAtBlock > 0;
const record = (outcome: CoreTexEvalDedupRecord['outcome'], code?: string) => {
if (coordinatorPinnedSeed) return Promise.resolve();
const attemptState = outcome === 'reject' ? 'rejected' as const : 'accepted' as const;
Expand Down Expand Up @@ -634,7 +651,7 @@ export function createCoreTexEvaluatorCore(deps: ProductionCoreTexEvaluatorCoreD
epochId: deps.epochId,
receivedAtBlock: dual.receivedAtBlock,
targetBlock: dual.targetBlock,
targetBlockOffset: deps.targetBlockOffset,
targetBlockOffset: effectiveTargetBlockOffset,
blockhash: dual.blockhash.toLowerCase(),
patchHash,
parentStateRoot,
Expand All @@ -655,7 +672,7 @@ export function createCoreTexEvaluatorCore(deps: ProductionCoreTexEvaluatorCoreD
corpusRoot: deps.corpusRoot,
coreVersionHash: deps.bundleHash,
hiddenSeedCommit,
targetBlockOffset: deps.targetBlockOffset,
targetBlockOffset: effectiveTargetBlockOffset,
});

if (stateAdvance) {
Expand Down Expand Up @@ -759,7 +776,7 @@ export async function createProductionCoreTexEvaluator(
stateThresholdPpm,
screenerThresholdPpm,
replayTolerancePpm: profile.replayTolerancePpm,
targetBlockOffset: options.targetBlockOffset ?? 30,
targetBlockOffset: options.targetBlockOffset ?? profile.baseRpcConfig?.targetBlockOffset ?? DEFAULT_BASE_RPC_CONFIG.targetBlockOffset,
perMinerCap: options.perMinerCap,
rpcClient: options.rpcClient ?? new EnvBaseRpcClient(),
dedupStore: options.dedupStore,
Expand Down
2 changes: 1 addition & 1 deletion packages/coretex/src/rewards/difficulty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* as floating-point intermediates and then rounded back to bigint.
*/

export const MIN_IMPROVEMENT_PPM = 2_500n;
export const MIN_IMPROVEMENT_PPM = 500n;
export const MAX_IMPROVEMENT_PPM = 150_000n;

export interface DifficultyInputs {
Expand Down
9 changes: 9 additions & 0 deletions packages/coretex/src/scorer-server-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,14 @@ export function resolveJobSeedContext(
if (!Number.isSafeInteger(targetBlock) || (targetBlock as number) <= 0) {
return { error: `publicEvalContext.targetBlock must be a positive integer (got ${String(targetBlock)})` };
}
const targetBlockOffset = ctx.targetBlockOffset;
if (!Number.isSafeInteger(targetBlockOffset) || (targetBlockOffset as number) <= 0) {
return { error: `publicEvalContext.targetBlockOffset must be a positive integer (got ${String(targetBlockOffset)})` };
}
const expectedTargetBlock = (receivedAtBlock as number) + (targetBlockOffset as number);
if ((targetBlock as number) !== expectedTargetBlock) {
return { error: `publicEvalContext.targetBlock ${String(targetBlock)} != receivedAtBlock ${String(receivedAtBlock)} + targetBlockOffset ${String(targetBlockOffset)}` };
}
if (typeof blockhash !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(blockhash)) {
return { error: 'publicEvalContext.blockhash must be bytes32' };
}
Expand Down Expand Up @@ -400,6 +408,7 @@ export async function handleScoreJob(
// seeds — the scorer never re-rolls a blockhash nor touches a secret.
seedContext: pinnedSeed.seedContext,
injectedSeeds: pinnedSeed.injectedSeeds,
targetBlockOffset: job.publicEvalContext!.targetBlockOffset!,
});
} catch (e) {
return { status: 500, body: { error: 'eval-failure', reason: (e as Error)?.message ?? 'scorePatch threw' } };
Expand Down
4 changes: 2 additions & 2 deletions packages/coretex/test/unit/bundle-base-rpc-config.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ describe('DEFAULT_BASE_RPC_CONFIG', () => {
test('is exported and has Base mainnet values', () => {
assert.equal(DEFAULT_BASE_RPC_CONFIG.chainId, 8453);
assert.equal(DEFAULT_BASE_RPC_CONFIG.blockTimeSeconds, 2);
assert.equal(DEFAULT_BASE_RPC_CONFIG.targetBlockOffset, 30, 'default offset ≈ 60 s on Base — aligned with per-miner rate limit');
assert.equal(DEFAULT_BASE_RPC_CONFIG.targetBlockOffset, 15, 'default offset ≈ 30 s on Base — aligned with the live coordinator/scorer seed pin');
// Must cover one full epoch (24 h = 43_200 blocks @ 2 s) + the offset.
const minLookback = 43_200 + 30;
const minLookback = 43_200 + 15;
assert.ok(DEFAULT_BASE_RPC_CONFIG.replayBlockhashLookbackBlocks >= minLookback, 'lookback must cover one epoch + offset');
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ const MINER_A = '0x' + 'aa'.repeat(20);
const MINER_B = '0x' + 'bb'.repeat(20);

// No static screenerThresholdPpm: the live threshold must derive from the
// baseline plus state-advance threshold (288438 + 2700ppm -> 1350ppm under
// the default policy).
// baseline plus state-advance threshold (288438 + 700ppm -> 355ppm under the
// default policy).
const baseConfig = {
epoch: EPOCH,
expectedChainId: 8453n,
Expand All @@ -67,7 +67,7 @@ const baseConfig = {
receiptTtlSec: 60,
perMinerScreenerCap: 50,
baselineParentScorePpm: 288438,
minImprovementPpm: 2500,
minImprovementPpm: 500,
replayTolerancePpm: 200,
targetBlockOffset: 30,
patchWordBudget: 4,
Expand Down Expand Up @@ -446,7 +446,7 @@ describe('CoreTexCoordinatorCore §9 — FIFO signing queue', () => {
const evaluator = { scorePatch: (input) => screenerResult(input.patchBytesHex, input.parentStateRoot, 320) };
const coord = new CoreTexCoordinatorCore(baseConfig, new MockChain({ head: 1000 }), loadGenesis, evaluator, plainSigner);
await coord.boot();
// baseline 288438 + state threshold 2700 -> live threshold 1350; delta
// baseline 288438 + state threshold 700 -> live threshold 355; delta
// 320 is below it.
const out = await coord.submit(submitBody(makePatchHex(GENESIS_ROOT, 40, 1)));
assert.equal(out.status, 'rejected');
Expand Down Expand Up @@ -490,14 +490,14 @@ describe('CoreTexCoordinatorCore §7 — baseline runtime semantics', () => {
const coord = new CoreTexCoordinatorCore(baseConfig, chain, loadGenesis, evaluator, plainSigner);
await coord.boot();

// Launch context: baseline 288438 with a 2700ppm state threshold -> live
// screener threshold 1350ppm.
// Launch context: baseline 288438 with a 700ppm state threshold -> live
// screener threshold 355ppm.
const status0 = await coord.getStatus();
assert.equal(status0.baselineState, 'ready');
assert.equal(status0.baselineParentScorePpm, 288438);
assert.equal(status0.stateAdvanceThresholdPpm, 2700);
assert.equal(status0.screenerThresholdPpm, 1350);
assert.equal(status0.thresholds.screenerThresholdPpm, 1350);
assert.equal(status0.stateAdvanceThresholdPpm, 700);
assert.equal(status0.screenerThresholdPpm, 355);
assert.equal(status0.thresholds.screenerThresholdPpm, 355);

// A 320ppm screener is below the launch threshold.
const before = await coord.submit(submitBody(makePatchHex(GENESIS_ROOT, 40, 1)));
Expand Down Expand Up @@ -525,7 +525,7 @@ describe('CoreTexCoordinatorCore §7 — baseline runtime semantics', () => {
const status1 = await coord.getStatus();
assert.equal(status1.baselineState, 'ready');
assert.equal(status1.baselineParentScorePpm, 400000);
assert.equal(status1.screenerThresholdPpm, 1350, 'state-threshold floor dominates normal launch baselines');
assert.equal(status1.screenerThresholdPpm, 350, 'state-threshold floor dominates normal launch baselines');
assert.equal(status1.thresholds.baselineParentScorePpm, 400000);

// A 1400ppm screener clears the live gate.
Expand Down Expand Up @@ -569,7 +569,7 @@ describe('CoreTexCoordinatorCore §7 — baseline runtime semantics', () => {
const ready = await coord.getStatus();
assert.equal(ready.baselineState, 'ready');
assert.equal(ready.baselineParentScorePpm, 300000);
assert.equal(ready.screenerThresholdPpm, 1350);
assert.equal(ready.screenerThresholdPpm, 350);
const accepted = await coord.submit(submitBody(makePatchHex(ev0.newRoot, 40, 1), MINER_A, ev0.newRoot));
assert.equal(accepted.status, 'accepted', `expected accept, got ${JSON.stringify(accepted)}`);

Expand Down
32 changes: 24 additions & 8 deletions packages/coretex/test/unit/coretex-coordinator-core.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ const baseConfig = {
receiptTtlSec: 60,
perMinerScreenerCap: 50,
// §7 launch baseline for the pinned (genesis) context. 288438 with the
// default policy and 2700ppm state threshold derives a live screener
// threshold of 1350ppm.
// default policy and the cold-start 700ppm state threshold derives a live
// screener threshold of 355ppm.
baselineParentScorePpm: 288438,
screenerThresholdPpm: 355,
minImprovementPpm: 2500,
minImprovementPpm: 500,
replayTolerancePpm: 200,
targetBlockOffset: 30,
patchWordBudget: 4,
Expand Down Expand Up @@ -240,6 +240,22 @@ describe('CoreTexCoordinatorCore — chain-confirmed-only semantics', () => {
assert.equal(s.unhealthyReason, null);
});

test('watcher SKIPS finalized prior-epoch events (stale replay start does not fail-close)', async () => {
// A finalized event from a PRIOR epoch sits in the replay window (e.g. a stale
// CORETEX_REPLAY_FROM_BLOCK still pointing before this epoch's boundary). It must
// be SKIPPED, not rejected with "watcher: event epoch N != configured N+1".
const chainGen = new EventChain();
const priorEpochEv = { ...chainGen.next({ blockNumber: 500, blockHash: '0x' + '55'.repeat(32) }), epoch: EPOCH - 1n };
const chain = new MockChain({ head: 1000, events: [priorEpochEv], regEpoch: { liveStateRoot: GENESIS_ROOT, transitionCount: 0 } });
const coord = new CoreTexCoordinatorCore(baseConfig, chain, loadGenesis, evaluator);
await coord.boot();
const s = coord.getState();
assert.equal(s.transitionCount, 0, 'prior-epoch event must be skipped, not applied');
assert.equal(s.liveRoot.toLowerCase(), GENESIS_ROOT.toLowerCase(), 'liveRoot unchanged by skipped event');
assert.equal(s.signingEnabled, true, 'boot must not fail-close on a prior-epoch event');
assert.equal(s.unhealthyReason, null);
});

test('mid-run epoch rollover disables signing with CoordEpochMismatch', async () => {
const chain = new MockChain({ head: 1000 });
const coord = new CoreTexCoordinatorCore(baseConfig, chain, loadGenesis, evaluator, signer);
Expand Down Expand Up @@ -674,19 +690,19 @@ describe('CoreTexCoordinatorCore — production submit path', () => {

test('state advance signer boundary enforces replay-tolerant threshold on dual-pack proof', async () => {
const ev = buildEvent({ blockNumber: 500, blockHash: '0x' + '55'.repeat(32) });
const rewritten = rewritePatchScoreDelta(ev.compactPatchBytes, 2800);
const rewritten = rewritePatchScoreDelta(ev.compactPatchBytes, 800);
const evalAdvance = {
scorePatch: () => ({
outcome: 'state_advance',
deterministicDeltaPpm: 2800,
deterministicDeltaPpm: 800,
evalReportHash: '0x' + 'e2'.repeat(32),
artifactHash: '0x' + 'a2'.repeat(32),
scoreBeforePpm: 100,
scoreAfterPpm: 2900,
scoreAfterPpm: 900,
rewrittenPatchBytesHex: rewritten,
evaluationProof: dualProofFor(ev.compactPatchBytes, GENESIS_ROOT, {
gate: { domain: 'gate', seedCommit: '0x' + '91'.repeat(32), accepted: true, scorePpm: 2600 },
confirm: { domain: 'confirm', seedCommit: '0x' + '92'.repeat(32), accepted: true, scorePpm: 2600 },
gate: { domain: 'gate', seedCommit: '0x' + '91'.repeat(32), accepted: true, scorePpm: 600 },
confirm: { domain: 'confirm', seedCommit: '0x' + '92'.repeat(32), accepted: true, scorePpm: 600 },
}),
}),
};
Expand Down
2 changes: 1 addition & 1 deletion packages/coretex/test/unit/difficulty-grace.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('major-delta grace', () => {
qualityAttempts: 200,
majorDeltaActive: true,
});
assert.equal(out.next, 2_500n, 'clamps to MIN_IMPROVEMENT_PPM floor');
assert.equal(out.next, 500n, 'clamps to MIN_IMPROVEMENT_PPM floor');
assert.equal(out.reason, 'major_delta_grace');
});

Expand Down
Loading
Loading