@nexus-cortex/core 4.124.11 → 4.124.13
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/.env.defaults +29 -0
- package/dist/config/RuntimeConfigRegistry.d.ts.map +1 -1
- package/dist/config/RuntimeConfigRegistry.js +5 -0
- package/dist/config/RuntimeConfigRegistry.js.map +1 -1
- package/dist/config/SettingsLoader.d.ts.map +1 -1
- package/dist/config/SettingsLoader.js +5 -0
- package/dist/config/SettingsLoader.js.map +1 -1
- package/dist/config/SettingsSchema.d.ts +5 -0
- package/dist/config/SettingsSchema.d.ts.map +1 -1
- package/dist/config/SettingsSchema.js +13 -0
- package/dist/config/SettingsSchema.js.map +1 -1
- package/dist/config/effectiveConfig.d.ts.map +1 -1
- package/dist/config/effectiveConfig.js +5 -0
- package/dist/config/effectiveConfig.js.map +1 -1
- package/dist/middleware/HelperModelMiddleware.d.ts +11 -0
- package/dist/middleware/HelperModelMiddleware.d.ts.map +1 -1
- package/dist/middleware/HelperModelMiddleware.js +18 -0
- package/dist/middleware/HelperModelMiddleware.js.map +1 -1
- package/dist/orchestrator/CortexOrchestrator.d.ts +12 -0
- package/dist/orchestrator/CortexOrchestrator.d.ts.map +1 -1
- package/dist/orchestrator/CortexOrchestrator.js +129 -3
- package/dist/orchestrator/CortexOrchestrator.js.map +1 -1
- package/dist/training/DecisionStore.d.ts +1 -1
- package/dist/training/DecisionStore.d.ts.map +1 -1
- package/dist/training/endTurnResolver.d.ts +9 -0
- package/dist/training/endTurnResolver.d.ts.map +1 -1
- package/dist/training/endTurnResolver.js +6 -1
- package/dist/training/endTurnResolver.js.map +1 -1
- package/dist/training/requirementLedger.d.ts +84 -0
- package/dist/training/requirementLedger.d.ts.map +1 -0
- package/dist/training/requirementLedger.js +155 -0
- package/dist/training/requirementLedger.js.map +1 -0
- package/package.json +3 -3
|
@@ -23,6 +23,7 @@ import { resolveEndTurnResolverConfig, parseResolverVerdict, effectiveMaxRejects
|
|
|
23
23
|
import { jevAvailable, jevNoul, buildGapHoldState, GAP_HOLD_QUESTIONS } from '../training/jevGate.js'; // R173b
|
|
24
24
|
import { resolveFrameConfig, FRAME_CONTRACT, FRAME_TOOL_NAME } from '../frames/frameConfig.js'; // R179
|
|
25
25
|
import { FrameRunner } from '../frames/frameRunner.js'; // R179
|
|
26
|
+
import { parseRequirementLedger, initLedger, updateLedger, ledgerCounts, ledgerHoldable, formatLedgerForWriter, formatLedgerForJudge, formatLedgerHoldMessage, buildLedgerJevState, buildLedgerJevQuestions, applyLedgerJevAnswers } from '../training/requirementLedger.js'; // R187
|
|
26
27
|
import { isValueShapedTask, parseDerivationReply, methodsDiffer, parseValueLines, extractNumbers, reconcile, buildDerivationHoldMessage, isDerivationCommandAllowed, checkRunPassed, checkRunBody } from '../training/independentDerivation.js'; // R176
|
|
27
28
|
import { resolveDeadlineExitConfig, deadlineExitCallBudget, parseDeadlineExitVerdict } from '../training/deadlineExitMentor.js';
|
|
28
29
|
import { isTaskShaped } from './requirementsVerification.js';
|
|
@@ -249,6 +250,10 @@ export class CortexOrchestrator {
|
|
|
249
250
|
specChecks = null; // R174: blind spec-derived checks authored for this turn (null = not yet)
|
|
250
251
|
specChecksMeta = { genLatencyMs: 0, refused: 0, raw: 0 }; // R174
|
|
251
252
|
specChecksPromise = null; // R174b: authored at lift in the background (CORTEX_JUDGE_SPEC_TESTS_AT=lift)
|
|
253
|
+
reqLedger = null; // R187: the stated-requirement ledger for this turn (null = not yet authored)
|
|
254
|
+
reqLedgerPromise = null; // R187: authored at lift in the background
|
|
255
|
+
reqLedgerHolds = 0; // R187: ledger holds used this turn
|
|
256
|
+
reqLedgerMeta = { genLatencyMs: 0, raw: 0, refused: 0 }; // R187
|
|
252
257
|
specFailHistory = new Map(); // R174b: consecutive identical spec failures
|
|
253
258
|
lastHoldMs = 0; // R173c: wall clock of the last hold/veto this turn
|
|
254
259
|
derivationHolds = 0; // R176: independent-derivation holds this turn (max 1)
|
|
@@ -542,6 +547,7 @@ export class CortexOrchestrator {
|
|
|
542
547
|
void store.recordEvent({
|
|
543
548
|
sessionId, kind: 'lift_plan', detail: { fired: true, planChars: 0, empty: true, ...r171, mentor: this.mentorWire('lift-plan', resolveLiftPlanConfig().effort, resolveLiftPlanConfig().outputBudgetTokens) },
|
|
544
549
|
}).catch(() => { });
|
|
550
|
+
await this.deliverRequirementLedgerToWriter(lastMsg); // R187: the ledger rides even when the plan is empty
|
|
545
551
|
return; // fail-open: proceed without a plan
|
|
546
552
|
}
|
|
547
553
|
const retire = /\bRETIRE\b/i.test(plan);
|
|
@@ -564,6 +570,7 @@ export class CortexOrchestrator {
|
|
|
564
570
|
if (this.config.debug) {
|
|
565
571
|
console.log(`[LiftPlan] plan delivered at lift (${plan.length} chars, retire=${retire}, criteria=${criteriaStated})`);
|
|
566
572
|
}
|
|
573
|
+
await this.deliverRequirementLedgerToWriter(lastMsg); // R187
|
|
567
574
|
}
|
|
568
575
|
catch (e) {
|
|
569
576
|
if (store)
|
|
@@ -574,6 +581,28 @@ export class CortexOrchestrator {
|
|
|
574
581
|
console.warn(`[LiftPlan] delivery failed (continuing without): ${e?.message ?? e}`);
|
|
575
582
|
}
|
|
576
583
|
}
|
|
584
|
+
/** R187: append the requirement ledger to the lift observation the writer is about to see (waits for the lift-time authoring,
|
|
585
|
+
* bounded by the resolver timeout; fail-open to nothing). One-shot per turn. */
|
|
586
|
+
reqLedgerDelivered = false;
|
|
587
|
+
async deliverRequirementLedgerToWriter(lastMsg) {
|
|
588
|
+
const cfg = resolveEndTurnResolverConfig();
|
|
589
|
+
if (!cfg.reqLedger || this.reqLedgerDelivered)
|
|
590
|
+
return;
|
|
591
|
+
try {
|
|
592
|
+
if (this.reqLedger === null && !this.reqLedgerPromise)
|
|
593
|
+
this.maybeAuthorRequirementLedgerAtLift(); // the plan path ran before the lift hook
|
|
594
|
+
const entries = this.reqLedger ?? (this.reqLedgerPromise ? await withTimeout(this.reqLedgerPromise, mentorSurfaceTimeoutMs('endturn-resolver', parseInt(process.env.CORTEX_ENDTURN_RESOLVER_TIMEOUT_MS ?? '90000', 10))) : null);
|
|
595
|
+
const text = formatLedgerForWriter(entries ?? []);
|
|
596
|
+
if (!text)
|
|
597
|
+
return; // nothing authored (yet) — leave the one-shot open
|
|
598
|
+
this.reqLedgerDelivered = true;
|
|
599
|
+
lastMsg?.message?.content?.push?.({ type: 'text', text: `<system-reminder>\n${text}\n</system-reminder>` });
|
|
600
|
+
const store = this.getDecisionStore();
|
|
601
|
+
if (store)
|
|
602
|
+
void store.recordEvent({ sessionId: this.currentSessionId ?? 'unknown', kind: 'requirement_ledger_delivered', toolName: 'EndTurn', detail: { lines: (entries ?? []).length, chars: text.length } }).catch(() => { });
|
|
603
|
+
}
|
|
604
|
+
catch { /* fail-open */ }
|
|
605
|
+
}
|
|
577
606
|
/** Bounded read-only environment recon (ENV_RECON_COMMAND), gathered ONCE and cached — shared by the
|
|
578
607
|
* lift planner and the EndTurn resolver. Fail-open: partial stdout on timeout/non-zero, else empty. */
|
|
579
608
|
gatherEnvReport(opts = {}) {
|
|
@@ -762,6 +791,47 @@ export class CortexOrchestrator {
|
|
|
762
791
|
console.warn(`[EndTurnResolver] R174 SPEC-TESTS — ${this.specChecks.length} blind check(s) authored at ${cfg.specTestsAt} in ${this.specChecksMeta.genLatencyMs} ms (${this.specChecksMeta.refused} refused)`);
|
|
763
792
|
return this.specChecks;
|
|
764
793
|
}
|
|
794
|
+
/** R187: author the requirement ledger (task text + env report ONLY). Sets reqLedger/reqLedgerMeta; never throws. */
|
|
795
|
+
async authorRequirementLedger(task) {
|
|
796
|
+
const cfg = resolveEndTurnResolverConfig();
|
|
797
|
+
const store = this.getDecisionStore();
|
|
798
|
+
const sessionId = this.currentSessionId ?? 'unknown';
|
|
799
|
+
const g0 = Date.now();
|
|
800
|
+
if (!this.helperMiddleware?.deriveRequirementLedger) {
|
|
801
|
+
this.reqLedger = [];
|
|
802
|
+
return [];
|
|
803
|
+
}
|
|
804
|
+
const tmo = mentorSurfaceTimeoutMs('endturn-resolver', parseInt(process.env.CORTEX_ENDTURN_RESOLVER_TIMEOUT_MS ?? '90000', 10));
|
|
805
|
+
try {
|
|
806
|
+
const raw = await withTimeout(this.helperMiddleware.deriveRequirementLedger({ task, envReport: this.gatherEnvReport({ fresh: false }), max: cfg.reqLedgerMax, helperModelId: this.config.reactiveMentorship?.helperModelId }), tmo);
|
|
807
|
+
const lines = parseRequirementLedger(raw ?? '', cfg.reqLedgerMax);
|
|
808
|
+
// a check that is not read-only is dropped (the line stays, unverifiable) — same denylist as every other harness-run check
|
|
809
|
+
let refused = 0;
|
|
810
|
+
const safe = lines.map((l) => (l.check && !isInvestigateCommandAllowed(l.check) ? (refused += 1, { ...l, check: null }) : l));
|
|
811
|
+
this.reqLedger = initLedger(safe);
|
|
812
|
+
this.reqLedgerMeta = { genLatencyMs: Date.now() - g0, raw: (raw ?? '').length, refused };
|
|
813
|
+
}
|
|
814
|
+
catch {
|
|
815
|
+
this.reqLedger = [];
|
|
816
|
+
this.reqLedgerMeta = { genLatencyMs: Date.now() - g0, raw: 0, refused: 0 };
|
|
817
|
+
}
|
|
818
|
+
if (store)
|
|
819
|
+
void store.recordEvent({ sessionId, kind: 'requirement_ledger', toolName: 'EndTurn', detail: { lines: this.reqLedger.map((e) => ({ id: e.id, kind: e.kind, text: e.text, check: e.check })), ...this.reqLedgerMeta, mentor: this.mentorWire('endturn-resolver', cfg.effort, 2000) } }).catch(() => { });
|
|
820
|
+
console.warn(`[EndTurnResolver] R187 REQUIREMENT LEDGER — ${this.reqLedger.length} line(s) (${this.reqLedger.filter((e) => e.check).length} with checks, ${this.reqLedgerMeta.refused} refused) in ${this.reqLedgerMeta.genLatencyMs} ms`);
|
|
821
|
+
return this.reqLedger;
|
|
822
|
+
}
|
|
823
|
+
/** R187: at lift, start authoring the ledger in the background (delivered to the writer by deliverLiftPlanAtLift when ready). */
|
|
824
|
+
maybeAuthorRequirementLedgerAtLift() {
|
|
825
|
+
const cfg = resolveEndTurnResolverConfig();
|
|
826
|
+
if (!cfg.reqLedger || this.reqLedger !== null || this.reqLedgerPromise)
|
|
827
|
+
return;
|
|
828
|
+
if (!resolveEndTurnResolver(process.env))
|
|
829
|
+
return;
|
|
830
|
+
const task = this.lastRealUserText();
|
|
831
|
+
if (!task.trim())
|
|
832
|
+
return;
|
|
833
|
+
this.reqLedgerPromise = this.authorRequirementLedger(task).catch(() => []);
|
|
834
|
+
}
|
|
765
835
|
/** R174b: at lift, start authoring the spec checks in the background so a late first finish still has them. */
|
|
766
836
|
maybeAuthorSpecChecksAtLift() {
|
|
767
837
|
const cfg = resolveEndTurnResolverConfig();
|
|
@@ -872,8 +942,34 @@ export class CortexOrchestrator {
|
|
|
872
942
|
specResults += (specResults ? '\n\n' : '') + x.r + (ev === 'suspect' ? '\n(this check has failed identically at consecutive finishes while everything else passed — treat it as SUSPECT, not as proof of a gap)' : '');
|
|
873
943
|
}
|
|
874
944
|
}
|
|
945
|
+
// R187 HB-REQUIREMENT-LEDGER: run each stated requirement's check; a FAILED line is R166 evidence; an OPEN line (never exercised) can hold once.
|
|
946
|
+
let reqResults = '';
|
|
947
|
+
let reqCounts = { lines: 0, open: 0, exercised: 0, failed: 0, unverifiable: 0 };
|
|
948
|
+
let reqJev = null;
|
|
949
|
+
if (cfg.reqLedger) {
|
|
950
|
+
if (this.reqLedger === null)
|
|
951
|
+
this.reqLedger = await (this.reqLedgerPromise ?? this.authorRequirementLedger(task));
|
|
952
|
+
const runs = this.reqLedger.filter((e) => e.check).map((e) => { const r = runCheck(judgeCwd, e.check, jcfg); return { id: e.id, result: r, cls: classifyCheckRun(r) }; });
|
|
953
|
+
this.reqLedger = updateLedger(this.reqLedger, runs);
|
|
954
|
+
// R187b: Jev decides the lines the shell could not — typed per-line questions on the writer's attestation + harness evidence.
|
|
955
|
+
if (cfg.reqLedgerJev && jevAvailable() && this.reqLedger.some((e) => e.status === 'open' || e.status === 'unverifiable')) {
|
|
956
|
+
const j0 = Date.now();
|
|
957
|
+
try {
|
|
958
|
+
const jr = await jevNoul(buildLedgerJevState({ task, entries: this.reqLedger, attestation, workProduct }), buildLedgerJevQuestions(this.reqLedger));
|
|
959
|
+
const applied = applyLedgerJevAnswers(this.reqLedger, jr ? jr.probabilities : null, cfg.reqLedgerJevMin);
|
|
960
|
+
this.reqLedger = applied.entries;
|
|
961
|
+
reqJev = { asked: applied.asked, closed: applied.closed, latencyMs: Date.now() - j0 };
|
|
962
|
+
}
|
|
963
|
+
catch {
|
|
964
|
+
reqJev = { asked: 0, closed: [], latencyMs: Date.now() - j0, error: true };
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
reqCounts = ledgerCounts(this.reqLedger);
|
|
968
|
+
reqResults = formatLedgerForJudge(this.reqLedger);
|
|
969
|
+
}
|
|
875
970
|
const combinedCheck = [checkResult, namedResults ? `JUDGE-NAMED CHECKS (from your previous fix plan; executed by the harness just now):\n${namedResults}` : '',
|
|
876
|
-
specResults ? `SPEC CHECKS (derived from the TASK text before any work was seen; executed by the harness just now — a FAILED one is a requirement not yet met):\n${specResults}` : ''
|
|
971
|
+
specResults ? `SPEC CHECKS (derived from the TASK text before any work was seen; executed by the harness just now — a FAILED one is a requirement not yet met):\n${specResults}` : '', // R174
|
|
972
|
+
reqResults] // R187
|
|
877
973
|
.filter(Boolean).join('\n\n');
|
|
878
974
|
const callsSince = this.turnToolCallTotal - this.toolCallsAtLastVeto;
|
|
879
975
|
const progressed = this.endTurnResolverRejects === 0 || callsSince >= cfg.progressMinCalls || namedPassed > this.judgePriorNamedPassed; // R166a: newly-passing checks, not any passing check
|
|
@@ -999,7 +1095,7 @@ export class CortexOrchestrator {
|
|
|
999
1095
|
}
|
|
1000
1096
|
}
|
|
1001
1097
|
const holdable = gapHoldable({ gapHold: cfg.gapHold, remainingFrac: resolverRemainingFrac, minRemaining: resolveBudgetContinueMinRemaining(), planChars: verdict.plan.length, jevMode: cfg.gapHoldJev, jevFixable, jevMin: cfg.gapHoldJevMin });
|
|
1002
|
-
const checksFailed = namedFailed > 0 || specFailed > 0; // R166 + R174
|
|
1098
|
+
const checksFailed = namedFailed > 0 || specFailed > 0 || reqCounts.failed > 0; // R166 + R174 + R187
|
|
1003
1099
|
// R173c: a re-hold needs real work since the last hold (elapsed time or a changed open-items list), not just tool calls.
|
|
1004
1100
|
const msSinceLastHold = this.lastHoldMs > 0 ? Date.now() - this.lastHoldMs : null;
|
|
1005
1101
|
const holdProg = holdProgressed({ rejects: this.endTurnResolverRejects, msSinceLastHold, priorPlan: this.judgePriorPlan, plan: verdict.plan, minIntervalMs: cfg.gapHoldMinIntervalMs, maxSimilarity: cfg.gapHoldPlanMaxSimilarity });
|
|
@@ -1026,11 +1122,18 @@ export class CortexOrchestrator {
|
|
|
1026
1122
|
// R173c: the budget floor — below CORTEX_JUDGE_VETO_MIN_REMAINING nothing holds the finish (the gap is recorded).
|
|
1027
1123
|
const belowFloor = cfg.vetoMinRemaining > 0 && resolverRemainingFrac !== null && resolverRemainingFrac < cfg.vetoMinRemaining && action === 'veto';
|
|
1028
1124
|
action = applyVetoFloor(action, resolverRemainingFrac, cfg.vetoMinRemaining);
|
|
1125
|
+
// R187: a finish that would otherwise stand while a STATED requirement is still OPEN (its check never passed nor failed — never
|
|
1126
|
+
// exercised) is held once with the open lines named. Never below the budget floor; a FAILED line already went the R166 evidence way.
|
|
1127
|
+
let reqHold = null;
|
|
1128
|
+
if (cfg.reqLedger && this.reqLedger && action !== 'veto' && action !== 'escalate' && !belowFloor &&
|
|
1129
|
+
ledgerHoldable({ open: reqCounts.open, holdsUsed: this.reqLedgerHolds, maxHolds: cfg.reqLedgerHoldMax, remainingFrac: resolverRemainingFrac, minRemaining: cfg.vetoMinRemaining })) {
|
|
1130
|
+
reqHold = { message: formatLedgerHoldMessage({ entries: this.reqLedger, holdIndex: this.reqLedgerHolds + 1, maxHolds: cfg.reqLedgerHoldMax, remainingFrac: resolverRemainingFrac }) };
|
|
1131
|
+
}
|
|
1029
1132
|
// R176 HB-INDEPENDENT-DERIVATION: on a value-shaped task, before a finish that would otherwise STAND, recompute the result by a
|
|
1030
1133
|
// different method and hold ONCE on disagreement. Never below the budget floor; never more than once per turn.
|
|
1031
1134
|
let derivationHold = null;
|
|
1032
1135
|
let derivationInfo = null;
|
|
1033
|
-
if (cfg.derivation === 'on' && action !== 'veto' && action !== 'escalate' && this.derivationHolds < 1 && !belowFloor &&
|
|
1136
|
+
if (cfg.derivation === 'on' && !reqHold && action !== 'veto' && action !== 'escalate' && this.derivationHolds < 1 && !belowFloor &&
|
|
1034
1137
|
!(cfg.vetoMinRemaining > 0 && resolverRemainingFrac !== null && resolverRemainingFrac < cfg.vetoMinRemaining) && this.helperMiddleware.deriveIndependentCheck) {
|
|
1035
1138
|
const shape = isValueShapedTask(task);
|
|
1036
1139
|
derivationInfo = { valueShaped: shape.valueShaped, reason: shape.reason, artifacts: shape.artifacts };
|
|
@@ -1098,6 +1201,7 @@ export class CortexOrchestrator {
|
|
|
1098
1201
|
specTests: cfg.specTests, specChecks: this.specChecks?.length ?? 0, specRan, specPassed, specFailed, specInconclusive, specSuspect, specGenLatencyMs: this.specChecksMeta.genLatencyMs, specTestsAt: cfg.specTestsAt, // R174 / R174b
|
|
1099
1202
|
vetoMinRemaining: cfg.vetoMinRemaining, belowFloor, holdProgressed: holdProg, holdGapMs: msSinceLastHold, planSim: Number(planSimilarity(this.judgePriorPlan, verdict.plan).toFixed(3)), msSinceLastHold, // R173c
|
|
1100
1203
|
derivation: cfg.derivation, derivationAgreement: derivationInfo?.agreement ?? null, derivationHeld: !!derivationHold, // R176
|
|
1204
|
+
reqLedger: cfg.reqLedger, reqLines: reqCounts.lines, reqOpen: reqCounts.open, reqExercised: reqCounts.exercised, reqFailed: reqCounts.failed, reqUnverifiable: reqCounts.unverifiable, reqHeld: !!reqHold, reqHolds: this.reqLedgerHolds, reqGenLatencyMs: this.reqLedgerMeta.genLatencyMs, reqJev: cfg.reqLedgerJev, reqJevAsked: reqJev?.asked ?? 0, reqJevClosed: reqJev?.closed ?? [], reqJevLatencyMs: reqJev?.latencyMs ?? 0, // R187/R187b
|
|
1101
1205
|
latencyMs, rawLen: (text ?? '').length,
|
|
1102
1206
|
deltaChars: workspaceDelta.length, checkRan: !!checkResult, checkPassed: checkResult ? /→ PASSED/.test(checkResult) : null,
|
|
1103
1207
|
liftPlanChars: this.liftPlanText.length,
|
|
@@ -1137,10 +1241,20 @@ export class CortexOrchestrator {
|
|
|
1137
1241
|
`${verdict.plan}\n\nDo this, verify against the task's own criteria (not your own tests), then call EndTurn again.` +
|
|
1138
1242
|
(namedResultsNow ? `\n\nHARNESS-RUN CHECKS (named by the reviewer, executed just now — the failing ones are the gap):\n${namedResultsNow.slice(0, 3000)}` : '') + // R166
|
|
1139
1243
|
(specFailed > 0 ? `\n\nSPEC CHECKS (derived from the TASK text before your work was seen, executed just now — a FAILED one is a stated requirement not yet met):\n${specResults.slice(0, 3000)}` : '') + // R174
|
|
1244
|
+
(reqCounts.failed > 0 ? `\n\nREQUIREMENT LEDGER (stated requirements, checked just now — a FAILED line is a stated requirement not yet met):\n${reqResults.slice(0, 3000)}` : '') + // R187
|
|
1140
1245
|
(holdable && !checksFailed ? `\n\nNo harness-run check failed, but the reviewer named open items and budget remains — this hold returns them to you (hold ${this.endTurnResolverRejects}/${resolverCap}).` : '') + // R173
|
|
1141
1246
|
budgetedVetoEscalation(this.endTurnResolverRejects, resolverCap, resolverRemainingMs ?? 0, this.turnDeadlineMsActive); // R160
|
|
1142
1247
|
console.warn(`[EndTurnResolver] GAP — vetoed finish (${verdict.plan.length}-char plan, reject ${this.endTurnResolverRejects}/${resolverCap}${resolverRemainingFrac === null ? '' : `, budget remaining ${Math.round(resolverRemainingFrac * 100)}%`})`);
|
|
1143
1248
|
}
|
|
1249
|
+
else if (reqHold) {
|
|
1250
|
+
// R187: the finish would stand, but a stated requirement was never exercised — hold once with the open lines named.
|
|
1251
|
+
this.reqLedgerHolds += 1;
|
|
1252
|
+
this.lastHoldMs = Date.now();
|
|
1253
|
+
ev.endTurnCalled = false;
|
|
1254
|
+
et.is_error = true;
|
|
1255
|
+
et.content = reqHold.message;
|
|
1256
|
+
console.warn(`[EndTurnResolver] R187 LEDGER-HOLD — finish held (${reqCounts.open} open of ${reqCounts.lines} stated requirements; hold ${this.reqLedgerHolds}/${cfg.reqLedgerHoldMax})`);
|
|
1257
|
+
}
|
|
1144
1258
|
else if (derivationHold) {
|
|
1145
1259
|
// R176: the finish would stand, but an independent recomputation disagrees — hold once with both values shown.
|
|
1146
1260
|
this.derivationHolds += 1;
|
|
@@ -2136,6 +2250,11 @@ export class CortexOrchestrator {
|
|
|
2136
2250
|
this.specChecksMeta = { genLatencyMs: 0, refused: 0, raw: 0 };
|
|
2137
2251
|
this.specChecksPromise = null;
|
|
2138
2252
|
this.specFailHistory.clear();
|
|
2253
|
+
this.reqLedger = null;
|
|
2254
|
+
this.reqLedgerPromise = null;
|
|
2255
|
+
this.reqLedgerHolds = 0;
|
|
2256
|
+
this.reqLedgerMeta = { genLatencyMs: 0, raw: 0, refused: 0 };
|
|
2257
|
+
this.reqLedgerDelivered = false;
|
|
2139
2258
|
this.lastHoldMs = 0;
|
|
2140
2259
|
this.derivationHolds = 0; // R165 per-turn / R174 / R173c / R176
|
|
2141
2260
|
this.recordDsmlRecovery(currentAssistantCanonicalMessage);
|
|
@@ -3352,6 +3471,7 @@ export class CortexOrchestrator {
|
|
|
3352
3471
|
// full tool catalog (no-op unless CORTEX_PROMPT_MASS=defer).
|
|
3353
3472
|
await this.deliverDeferredCorpusAtLift(effectiveModel);
|
|
3354
3473
|
this.deliverLiftNudge(allTools, effectiveModel); // A′ proposal-1: SearchTools/AskForAdvice signpost at lift
|
|
3474
|
+
this.maybeAuthorRequirementLedgerAtLift(); // R187: the stated-requirement ledger, authored in the background at lift — BEFORE the plan call so it is ready to ride with the plan
|
|
3355
3475
|
await this.deliverLiftPlanAtLift(effectiveModel); // LIFT_MENTOR_PLANNER: bounded mentor-planner at lift (dark unless CORTEX_LIFT_PLAN)
|
|
3356
3476
|
this.maybeAuthorSpecChecksAtLift(); // R174b: blind spec checks authored in the background at lift (CORTEX_JUDGE_SPEC_TESTS_AT=lift)
|
|
3357
3477
|
if (this.config.debug)
|
|
@@ -4350,6 +4470,11 @@ export class CortexOrchestrator {
|
|
|
4350
4470
|
this.specChecksMeta = { genLatencyMs: 0, refused: 0, raw: 0 };
|
|
4351
4471
|
this.specChecksPromise = null;
|
|
4352
4472
|
this.specFailHistory.clear();
|
|
4473
|
+
this.reqLedger = null;
|
|
4474
|
+
this.reqLedgerPromise = null;
|
|
4475
|
+
this.reqLedgerHolds = 0;
|
|
4476
|
+
this.reqLedgerMeta = { genLatencyMs: 0, raw: 0, refused: 0 };
|
|
4477
|
+
this.reqLedgerDelivered = false;
|
|
4353
4478
|
this.lastHoldMs = 0;
|
|
4354
4479
|
this.derivationHolds = 0; // R165 per-turn / R174 / R173c / R176
|
|
4355
4480
|
this.recordDsmlRecovery(currentAssistantCanonicalMessage);
|
|
@@ -5149,6 +5274,7 @@ export class CortexOrchestrator {
|
|
|
5149
5274
|
// P6 deferral: same one-shot corpus delivery as the sendMessage path.
|
|
5150
5275
|
await this.deliverDeferredCorpusAtLift(effectiveModel);
|
|
5151
5276
|
this.deliverLiftNudge(allTools, effectiveModel); // A′ proposal-1: SearchTools/AskForAdvice signpost at lift
|
|
5277
|
+
this.maybeAuthorRequirementLedgerAtLift(); // R187: the stated-requirement ledger, authored in the background at lift — BEFORE the plan call so it is ready to ride with the plan
|
|
5152
5278
|
await this.deliverLiftPlanAtLift(effectiveModel); // LIFT_MENTOR_PLANNER: bounded mentor-planner at lift (dark unless CORTEX_LIFT_PLAN)
|
|
5153
5279
|
this.maybeAuthorSpecChecksAtLift(); // R174b: blind spec checks authored in the background at lift (CORTEX_JUDGE_SPEC_TESTS_AT=lift)
|
|
5154
5280
|
if (this.config.debug)
|