@principles/core 1.293.4 → 1.294.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime-v2/activation/activation-types.d.ts +2 -0
- package/dist/runtime-v2/activation/activation-types.d.ts.map +1 -1
- package/dist/runtime-v2/activation/activation-types.js.map +1 -1
- package/dist/runtime-v2/activation/sqlite-approval-store.d.ts.map +1 -1
- package/dist/runtime-v2/activation/sqlite-approval-store.js +64 -10
- package/dist/runtime-v2/activation/sqlite-approval-store.js.map +1 -1
- package/dist/runtime-v2/adapter/artificer-l2-adapter.d.ts.map +1 -1
- package/dist/runtime-v2/adapter/artificer-l2-adapter.js +23 -1
- package/dist/runtime-v2/adapter/artificer-l2-adapter.js.map +1 -1
- package/dist/runtime-v2/adapter/l2-agent-loop-adapter.d.ts +9 -0
- package/dist/runtime-v2/adapter/l2-agent-loop-adapter.d.ts.map +1 -1
- package/dist/runtime-v2/adapter/l2-agent-loop-adapter.js +39 -5
- package/dist/runtime-v2/adapter/l2-agent-loop-adapter.js.map +1 -1
- package/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.d.ts +4 -0
- package/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.d.ts.map +1 -1
- package/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.js +18 -4
- package/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.js.map +1 -1
- package/dist/runtime-v2/adapter/output-schema-registry.d.ts.map +1 -1
- package/dist/runtime-v2/adapter/output-schema-registry.js +5 -0
- package/dist/runtime-v2/adapter/output-schema-registry.js.map +1 -1
- package/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts +26 -0
- package/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts.map +1 -1
- package/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js +88 -13
- package/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js.map +1 -1
- package/dist/runtime-v2/index.d.ts +3 -0
- package/dist/runtime-v2/index.d.ts.map +1 -1
- package/dist/runtime-v2/index.js +7 -0
- package/dist/runtime-v2/index.js.map +1 -1
- package/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +2 -2
- package/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/artificer-prompt-builder.js +7 -7
- package/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/artificer-runner.js +5 -2
- package/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-runner.d.ts +3 -0
- package/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/evaluator-runner.js +231 -37
- package/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
- package/dist/runtime-v2/internalization/internalization-transition-decision.d.ts +3 -0
- package/dist/runtime-v2/internalization/internalization-transition-decision.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/internalization-transition-decision.js +7 -1
- package/dist/runtime-v2/internalization/internalization-transition-decision.js.map +1 -1
- package/dist/runtime-v2/internalization/pitask-metadata.d.ts +5 -0
- package/dist/runtime-v2/internalization/pitask-metadata.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/pitask-metadata.js +8 -0
- package/dist/runtime-v2/internalization/pitask-metadata.js.map +1 -1
- package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.js +11 -26
- package/dist/runtime-v2/internalization/refiner-sandbox-wrapper.js.map +1 -1
- package/dist/runtime-v2/internalization/rule-host-input-builder.d.ts +9 -2
- package/dist/runtime-v2/internalization/rule-host-input-builder.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/rule-host-input-builder.js +163 -111
- package/dist/runtime-v2/internalization/rule-host-input-builder.js.map +1 -1
- package/dist/runtime-v2/internalization/rule-reliability-validation.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/rule-reliability-validation.js +12 -7
- package/dist/runtime-v2/internalization/rule-reliability-validation.js.map +1 -1
- package/dist/runtime-v2/internalization/scribe-output.d.ts +19 -2
- package/dist/runtime-v2/internalization/scribe-output.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/scribe-output.js +34 -11
- package/dist/runtime-v2/internalization/scribe-output.js.map +1 -1
- package/dist/runtime-v2/internalization/v2-adversarial-cases.d.ts +6 -44
- package/dist/runtime-v2/internalization/v2-adversarial-cases.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/v2-adversarial-cases.js +25 -146
- package/dist/runtime-v2/internalization/v2-adversarial-cases.js.map +1 -1
- package/dist/runtime-v2/learning-lab/actor-action-output.d.ts +42 -0
- package/dist/runtime-v2/learning-lab/actor-action-output.d.ts.map +1 -0
- package/dist/runtime-v2/learning-lab/actor-action-output.js +63 -0
- package/dist/runtime-v2/learning-lab/actor-action-output.js.map +1 -0
- package/dist/runtime-v2/runtime-protocol.d.ts +17 -0
- package/dist/runtime-v2/runtime-protocol.d.ts.map +1 -1
- package/dist/runtime-v2/runtime-protocol.js +17 -0
- package/dist/runtime-v2/runtime-protocol.js.map +1 -1
- package/dist/runtime-v2/store/sqlite-connection.d.ts.map +1 -1
- package/dist/runtime-v2/store/sqlite-connection.js +4 -0
- package/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
- package/dist/runtime-v2/tools/artificer-l2-tool-contract.js +9 -9
- package/dist/runtime-v2/tools/artificer-l2-tool-contract.js.map +1 -1
- package/dist/runtime-v2/trajectory-schema.d.ts.map +1 -1
- package/dist/runtime-v2/trajectory-schema.js +10 -1
- package/dist/runtime-v2/trajectory-schema.js.map +1 -1
- package/dist/telemetry-event.d.ts +2 -2
- package/dist/telemetry-event.d.ts.map +1 -1
- package/dist/telemetry-event.js +6 -0
- package/dist/telemetry-event.js.map +1 -1
- package/package.json +1 -1
|
@@ -31,6 +31,14 @@ function commonPrefixLength(a, b) {
|
|
|
31
31
|
i += 1;
|
|
32
32
|
return i;
|
|
33
33
|
}
|
|
34
|
+
/** Drop any model-shaped replay claim when this run did not execute the gate. */
|
|
35
|
+
function withoutAdversarialResult(output) {
|
|
36
|
+
if (!isEvaluatorOutputV2(output))
|
|
37
|
+
return output;
|
|
38
|
+
const { adversarialResult, ...sanitized } = output;
|
|
39
|
+
void adversarialResult;
|
|
40
|
+
return sanitized;
|
|
41
|
+
}
|
|
34
42
|
function isRecordValue(value) {
|
|
35
43
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
36
44
|
}
|
|
@@ -704,6 +712,7 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
704
712
|
// explicitly through applyEvaluatorDecisionEffects → maybeSeedArtificerRepair
|
|
705
713
|
// keeps provenance structural rather than inferred.
|
|
706
714
|
let diagnosticReplayEvidence;
|
|
715
|
+
let ownerStampRecoveryRequired = false;
|
|
707
716
|
const gateAssessment = assessArtificerCodeBearing(context.artificerArtifact);
|
|
708
717
|
const outputWantsGate = isEvaluatorOutputV2(output);
|
|
709
718
|
const evaluatorDecision = output.evaluation.decision;
|
|
@@ -803,12 +812,50 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
803
812
|
}
|
|
804
813
|
}
|
|
805
814
|
else if (!this.gateDeps) {
|
|
815
|
+
const taskChannel = hydratePITaskRecord(task)?.channel;
|
|
816
|
+
const sourceArtificer = context.artificerArtifact
|
|
817
|
+
? this.parseArtificerArtifact(context.artificerArtifact)
|
|
818
|
+
: null;
|
|
819
|
+
const promptHasUnstampedV2Code = taskChannel === 'prompt'
|
|
820
|
+
&& sourceArtificer?.requiresContextVersion === 2
|
|
821
|
+
&& !Array.isArray(sourceArtificer.ownerGoldenTraceCases);
|
|
806
822
|
this.emitEvent('adversarial_replay_skipped', taskId, {
|
|
807
823
|
runId,
|
|
808
824
|
reason: 'gate_deps_not_injected',
|
|
809
825
|
nextAction: 'wire_gateDeps_createProductionGateDeps_into_evaluator_runner_assembly',
|
|
810
826
|
});
|
|
811
|
-
if (
|
|
827
|
+
if (promptHasUnstampedV2Code) {
|
|
828
|
+
// An accidental prompt-channel V2 artifact is not a RuleCode request.
|
|
829
|
+
// Keep the ordinary prompt verdict, but drop any model-shaped replay
|
|
830
|
+
// claim so it cannot be mistaken for executed gate evidence.
|
|
831
|
+
finalOutput = withoutAdversarialResult(finalOutput);
|
|
832
|
+
await this.stateManager.updateRunOutput(runId, JSON.stringify(finalOutput));
|
|
833
|
+
try {
|
|
834
|
+
await this.artifactStore.upsertArtifact({
|
|
835
|
+
artifactId,
|
|
836
|
+
artifactKind: 'principle',
|
|
837
|
+
sourceTaskId: taskId,
|
|
838
|
+
lineageArtifactIds,
|
|
839
|
+
validationStatus: 'pending',
|
|
840
|
+
contentJson: JSON.stringify(finalOutput),
|
|
841
|
+
createdAt: now,
|
|
842
|
+
updatedAt: new Date().toISOString(),
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
catch (persistErr) {
|
|
846
|
+
this.emitEvent('adversarial_result_persist_failed', taskId, {
|
|
847
|
+
runId,
|
|
848
|
+
errorMessage: persistErr instanceof Error ? persistErr.message : String(persistErr),
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
this.emitEvent('prompt_code_artifact_ignored', taskId, {
|
|
852
|
+
runId,
|
|
853
|
+
sourceArtificerArtifactId: context.sourceArtificerArtifactId,
|
|
854
|
+
reason: 'owner_golden_trace_stamp_missing',
|
|
855
|
+
nextAction: 'prompt_channel_does_not_create_rulecode_without_an_explicit_code_tool_hook_request',
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
else if (gateAssessment.codeBearing) {
|
|
812
859
|
// PRI-634 R2 (wiring regression guard): a code-bearing Artificer
|
|
813
860
|
// artifact REQUIRES the deterministic gate. Proceeding would yield
|
|
814
861
|
// succeeded + adversarialResult=null — the exact state that broke
|
|
@@ -864,31 +911,96 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
864
911
|
}
|
|
865
912
|
}
|
|
866
913
|
else if (gateAssessment.codeBearing) {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
914
|
+
const missingOwnerStamp = replayOutcome.skipReason === 'owner_golden_trace_stamp_missing_or_invalid';
|
|
915
|
+
const taskChannel = hydratePITaskRecord(task)?.channel;
|
|
916
|
+
if (missingOwnerStamp && taskChannel === 'prompt') {
|
|
917
|
+
// Prompt-channel artifacts are not eligible to create RuleCode.
|
|
918
|
+
// Preserve the ordinary prompt result, but discard any model-shaped
|
|
919
|
+
// replay claim so it cannot masquerade as executed gate evidence.
|
|
920
|
+
finalOutput = withoutAdversarialResult(finalOutput);
|
|
921
|
+
await this.stateManager.updateRunOutput(runId, JSON.stringify(finalOutput));
|
|
922
|
+
try {
|
|
923
|
+
await this.artifactStore.upsertArtifact({
|
|
924
|
+
artifactId,
|
|
925
|
+
artifactKind: 'principle',
|
|
926
|
+
sourceTaskId: taskId,
|
|
927
|
+
lineageArtifactIds,
|
|
928
|
+
validationStatus: 'pending',
|
|
929
|
+
contentJson: JSON.stringify(finalOutput),
|
|
930
|
+
createdAt: now,
|
|
931
|
+
updatedAt: new Date().toISOString(),
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
catch (persistErr) {
|
|
935
|
+
this.emitEvent('adversarial_result_persist_failed', taskId, {
|
|
936
|
+
runId,
|
|
937
|
+
errorMessage: persistErr instanceof Error ? persistErr.message : String(persistErr),
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
this.emitEvent('adversarial_replay_skipped', taskId, {
|
|
941
|
+
runId,
|
|
942
|
+
reason: replayOutcome.skipReason,
|
|
943
|
+
channel: 'prompt',
|
|
944
|
+
nextAction: 'prompt_channel_result_kept_without_rulecode_eligibility',
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
else if (missingOwnerStamp && this.isRepairLoopEnabled()) {
|
|
948
|
+
// Missing system-owned provenance is recoverable through the existing
|
|
949
|
+
// bounded Artificer repair loop. Do not fabricate a gate result.
|
|
950
|
+
ownerStampRecoveryRequired = true;
|
|
951
|
+
finalOutput = withoutAdversarialResult(finalOutput);
|
|
952
|
+
await this.stateManager.updateRunOutput(runId, JSON.stringify(finalOutput));
|
|
953
|
+
try {
|
|
954
|
+
await this.artifactStore.upsertArtifact({
|
|
955
|
+
artifactId,
|
|
956
|
+
artifactKind: 'principle',
|
|
957
|
+
sourceTaskId: taskId,
|
|
958
|
+
lineageArtifactIds,
|
|
959
|
+
validationStatus: 'pending',
|
|
960
|
+
contentJson: JSON.stringify(finalOutput),
|
|
961
|
+
createdAt: now,
|
|
962
|
+
updatedAt: new Date().toISOString(),
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
catch (persistErr) {
|
|
966
|
+
this.emitEvent('adversarial_result_persist_failed', taskId, {
|
|
967
|
+
runId,
|
|
968
|
+
errorMessage: persistErr instanceof Error ? persistErr.message : String(persistErr),
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
this.emitEvent('artificer_owner_stamp_repair_required', taskId, {
|
|
972
|
+
runId,
|
|
973
|
+
sourceArtificerArtifactId: context.sourceArtificerArtifactId,
|
|
974
|
+
nextAction: 'regenerate_artificer_from_current_validated_owner_behavior_example_pack',
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
else {
|
|
978
|
+
// ── PRI-634 R3 (terminal-state invariant) ──
|
|
979
|
+
// A code-bearing Artificer artifact that reached `approved` MUST leave
|
|
980
|
+
// this block carrying an adversarialResult. Anything else reproduces
|
|
981
|
+
// the chain-48371236 terminal state — approved with the deterministic
|
|
982
|
+
// gate never executed, adversarialResult=null, and therefore no
|
|
983
|
+
// pi-rule-* downstream — regardless of WHICH cause prevented the
|
|
984
|
+
// replay (zero adversarial cases, no positive case, unparseable
|
|
985
|
+
// artifact, conversion drift…). Telemetry is not recovery: a task that
|
|
986
|
+
// ends `succeeded` here is indistinguishable from the original defect.
|
|
987
|
+
//
|
|
988
|
+
// errorCategory is `input_invalid` (already listed in
|
|
989
|
+
// permanentErrorCategories) rather than `capability_missing`: the gate
|
|
990
|
+
// IS wired correctly (R2 owns the wiring case) — the upstream
|
|
991
|
+
// Artificer content simply cannot be turned into gate input. Permanent
|
|
992
|
+
// because retrying the LLM cannot make the Artificer emit the missing
|
|
993
|
+
// affectedTools / positive-case path.
|
|
994
|
+
const recoveryAction = replayOutcome.skipReason?.startsWith('template_derivation_failed:')
|
|
995
|
+
? 'have the Artificer emit a complete positive write-kind golden-trace case with a string path or file_path; required templates cannot be replaced by LLM adversarialCases.'
|
|
996
|
+
: 'have the Artificer emit affectedTools plus at least one positive golden-trace case carrying a path, or supply LLM adversarialCases.';
|
|
997
|
+
return this.retryOrFail({
|
|
998
|
+
taskId,
|
|
999
|
+
task,
|
|
1000
|
+
errorCategory: 'input_invalid',
|
|
1001
|
+
failureReason: `PRI-634 R3: Artificer artifact ${context.sourceArtificerArtifactId ?? '(unknown)'} is code-bearing and the evaluator approved it, but the deterministic adversarial replay did not run (reason: ${replayOutcome.skipReason ?? 'unknown'}). Refusing to report succeeded with adversarialResult=null — that is the chain-48371236 terminal state. Fix: ${recoveryAction}`,
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
892
1004
|
}
|
|
893
1005
|
}
|
|
894
1006
|
// ── Round-2 R2 (Owner 指令 2026-09-08): 出界处置先于 intent 落库派生 ──
|
|
@@ -926,9 +1038,14 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
926
1038
|
&& finalOutput.evaluation.decision === 'approved'
|
|
927
1039
|
&& finalOutput.adversarialResult?.passed === false
|
|
928
1040
|
&& this.isRepairLoopEnabled();
|
|
1041
|
+
const approvedOwnerStampRecovery = ownerStampRecoveryRequired
|
|
1042
|
+
&& finalOutput.evaluation.decision === 'approved';
|
|
929
1043
|
await this.recordCompletionOrThrow(taskId, runId, {
|
|
930
1044
|
decision: finalOutput.evaluation.decision,
|
|
931
1045
|
governanceEffect,
|
|
1046
|
+
...(approvedOwnerStampRecovery
|
|
1047
|
+
? { transitionOverrideReason: 'owner_golden_trace_provenance_missing' }
|
|
1048
|
+
: {}),
|
|
932
1049
|
});
|
|
933
1050
|
const ruleAssemblyInput = {
|
|
934
1051
|
artificerArtifact: context.artificerArtifact ?? null,
|
|
@@ -943,7 +1060,9 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
943
1060
|
diagnosticReplayEvidence,
|
|
944
1061
|
// PRI-843: mismatch 处置在效果层先于一切 decision 分支执行
|
|
945
1062
|
...(governanceEffect !== undefined ? { governanceEffect } : {}),
|
|
946
|
-
...(approvedReplayFailed
|
|
1063
|
+
...(approvedReplayFailed || approvedOwnerStampRecovery
|
|
1064
|
+
? { transitionDecisionOverride: 'needs_revision' }
|
|
1065
|
+
: {}),
|
|
947
1066
|
});
|
|
948
1067
|
if (effectResult.kind === 'human_review') {
|
|
949
1068
|
return effectResult.result;
|
|
@@ -1324,7 +1443,7 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
1324
1443
|
* 同 epoch crash/retry 重跑经 maybeResumePendingIntent resume,不重问 LLM。
|
|
1325
1444
|
*/
|
|
1326
1445
|
async recordCompletionOrThrow(taskId, runId, decisionAndEffect) {
|
|
1327
|
-
const { decision, governanceEffect } = decisionAndEffect;
|
|
1446
|
+
const { decision, governanceEffect, transitionOverrideReason } = decisionAndEffect;
|
|
1328
1447
|
try {
|
|
1329
1448
|
const raw = await this.stateManager.getTask(taskId);
|
|
1330
1449
|
if (!raw)
|
|
@@ -1347,6 +1466,7 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
1347
1466
|
...(governanceEffect?.effectReasonCode !== undefined
|
|
1348
1467
|
? { effectReasonCode: governanceEffect.effectReasonCode }
|
|
1349
1468
|
: {}),
|
|
1469
|
+
...(transitionOverrideReason !== undefined ? { transitionOverrideReason } : {}),
|
|
1350
1470
|
},
|
|
1351
1471
|
});
|
|
1352
1472
|
await this.stateManager.updateTaskDiagnosticJson(taskId, createPITaskDiagnosticJson(merged));
|
|
@@ -1493,6 +1613,9 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
1493
1613
|
contextHash,
|
|
1494
1614
|
sourceArtificerArtifactId: assemblySourceId,
|
|
1495
1615
|
ruleAssemblyInput: { artificerArtifact: artificerContent, sourceArtificerArtifactId: assemblySourceId },
|
|
1616
|
+
...(intent.transitionOverrideReason === 'owner_golden_trace_provenance_missing'
|
|
1617
|
+
? { transitionDecisionOverride: 'needs_revision' }
|
|
1618
|
+
: {}),
|
|
1496
1619
|
});
|
|
1497
1620
|
if (effectResult.kind === 'human_review') {
|
|
1498
1621
|
return effectResult.result;
|
|
@@ -1857,8 +1980,9 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
1857
1980
|
// 的 partition) 派生; resume 路径经 recoverIntentOutput 后重读本 intent,
|
|
1858
1981
|
// 无需重算也无需任何瞬时变量。瞬时 evidence 门只作 fresh 快路径与
|
|
1859
1982
|
// 派生时的 provenance 校验, 不再是出界判定的唯一载体 (R2 漂移断点)。
|
|
1983
|
+
const completionIntent = await this.readPendingOrAppliedCompletionIntent(evaluatorTaskId);
|
|
1860
1984
|
{
|
|
1861
|
-
const intent =
|
|
1985
|
+
const intent = completionIntent;
|
|
1862
1986
|
// Round-3: hydrate 将 selectedEffect 归一化为 effect —— 读侧必须两键
|
|
1863
1987
|
// 同读,否则 fresh 分支永不命中、静默回退瞬时 evidence (ERR-024 键不对称)。
|
|
1864
1988
|
if ((intent?.selectedEffect ?? intent?.effect) === 'needs_human_review'
|
|
@@ -1963,7 +2087,12 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
1963
2087
|
// out-of-scope case 清单随载荷流动 — 修复 LLM 明确知道哪些失败属于
|
|
1964
2088
|
// 通道设计限制(不得尝试满足),哪些是真实 Rule 缺陷(必须修复)。
|
|
1965
2089
|
const repairPayload = {
|
|
1966
|
-
requiredChanges:
|
|
2090
|
+
requiredChanges: completionIntent?.transitionOverrideReason === 'owner_golden_trace_provenance_missing'
|
|
2091
|
+
? [
|
|
2092
|
+
...output.evaluation.requiredChanges,
|
|
2093
|
+
'Regenerate this RuleCode from the current validated Owner BehaviorExamplePack so the persisted artifact carries the system-owned ownerGoldenTraceCases; preserve the approved principle semantics.',
|
|
2094
|
+
]
|
|
2095
|
+
: [...output.evaluation.requiredChanges],
|
|
1967
2096
|
concerns: [...output.evaluation.concerns],
|
|
1968
2097
|
previousScore: output.evaluation.score,
|
|
1969
2098
|
repairIteration: priorRepairIteration + 1,
|
|
@@ -1986,6 +2115,7 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
1986
2115
|
let inheritedPipelineMode;
|
|
1987
2116
|
let inheritedTimeoutMs = 300_000;
|
|
1988
2117
|
let inheritedInputArtifactRefs = [];
|
|
2118
|
+
let ownerEvidenceSelection;
|
|
1989
2119
|
for (const depId of evaluatorDeps) {
|
|
1990
2120
|
const depTask = await this.stateManager.getTask(depId);
|
|
1991
2121
|
if (!depTask)
|
|
@@ -2000,6 +2130,7 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2000
2130
|
inheritedPipelineMode = piArtificer.pipelineMode;
|
|
2001
2131
|
inheritedTimeoutMs = piArtificer.timeoutMs;
|
|
2002
2132
|
inheritedInputArtifactRefs = piArtificer.inputArtifactRefs;
|
|
2133
|
+
({ ownerEvidenceSelection } = piArtificer);
|
|
2003
2134
|
break;
|
|
2004
2135
|
}
|
|
2005
2136
|
// Delegate to the injected seeder — core peer runners do NOT call
|
|
@@ -2023,6 +2154,7 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2023
2154
|
inheritedPipelineMode,
|
|
2024
2155
|
inheritedTimeoutMs,
|
|
2025
2156
|
inheritedInputArtifactRefs,
|
|
2157
|
+
ownerEvidenceSelection,
|
|
2026
2158
|
});
|
|
2027
2159
|
this.emitEvent('repair_task_seeded', evaluatorTaskId, {
|
|
2028
2160
|
repairTaskId,
|
|
@@ -2175,7 +2307,7 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2175
2307
|
});
|
|
2176
2308
|
return { updatedOutput: null, skipReason: 'artificer_artifact_unparseable' };
|
|
2177
2309
|
}
|
|
2178
|
-
const { implementationCode, goldenTraceCases, affectedTools } = artificerParsed;
|
|
2310
|
+
const { implementationCode, goldenTraceCases, ownerGoldenTraceCases, affectedTools, requiresContextVersion } = artificerParsed;
|
|
2179
2311
|
if (typeof implementationCode !== 'string' || implementationCode.trim() === '') {
|
|
2180
2312
|
// Artificer output is V1 (no code) but the evaluator emitted V2. This is
|
|
2181
2313
|
// a mismatch — degrade rather than replay against missing code.
|
|
@@ -2189,7 +2321,38 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2189
2321
|
// Merge positive cases from the Artificer golden trace into the adversarial
|
|
2190
2322
|
// trace. buildGoldenTraceFromArtificer validates each case structurally
|
|
2191
2323
|
// (Runtime Contract Rule 4) and returns ok=false on any malformed entry.
|
|
2192
|
-
|
|
2324
|
+
let positiveCases;
|
|
2325
|
+
let ownerNegativeCases = [];
|
|
2326
|
+
if (requiresContextVersion === 2) {
|
|
2327
|
+
if (!Array.isArray(ownerGoldenTraceCases)) {
|
|
2328
|
+
this.emitEvent('adversarial_replay_skipped', taskId, {
|
|
2329
|
+
runId,
|
|
2330
|
+
reason: 'owner_golden_trace_stamp_missing_or_invalid',
|
|
2331
|
+
nextAction: 'regenerate_artificer_artifact_from_the_current_validated_owner_behavior_example_pack',
|
|
2332
|
+
});
|
|
2333
|
+
return { updatedOutput: null, skipReason: 'owner_golden_trace_stamp_missing_or_invalid' };
|
|
2334
|
+
}
|
|
2335
|
+
const ownerBuild = buildGoldenTraceFromArtificer({ cases: ownerGoldenTraceCases });
|
|
2336
|
+
const ownerPositives = ownerBuild.ok ? ownerBuild.trace.cases.filter((c) => c.kind === 'positive') : [];
|
|
2337
|
+
ownerNegativeCases = ownerBuild.ok ? ownerBuild.trace.cases.filter((c) => c.kind === 'negative') : [];
|
|
2338
|
+
if (!ownerBuild.ok || ownerPositives.length === 0 || ownerNegativeCases.length === 0
|
|
2339
|
+
|| ownerBuild.trace.cases.some((c) => c.expectedDecision === 'propose_correction')
|
|
2340
|
+
|| ownerNegativeCases.some((c) => c.expectedDecision !== 'block')) {
|
|
2341
|
+
this.emitEvent('adversarial_replay_skipped', taskId, {
|
|
2342
|
+
runId,
|
|
2343
|
+
reason: 'owner_golden_trace_stamp_invalid_or_missing_positive_negative_pair',
|
|
2344
|
+
nextAction: 'restore_a_validated_owner_pack_with_at_least_one_allow_positive_and_one_block_negative_case',
|
|
2345
|
+
});
|
|
2346
|
+
return { updatedOutput: null, skipReason: 'owner_golden_trace_stamp_invalid_or_missing_positive_negative_pair' };
|
|
2347
|
+
}
|
|
2348
|
+
positiveCases = ownerPositives;
|
|
2349
|
+
}
|
|
2350
|
+
else {
|
|
2351
|
+
// Legacy v1 artifacts predate the system-owned pack stamp and remain
|
|
2352
|
+
// readable. New context-v2 RuleCode never falls back to model-authored
|
|
2353
|
+
// examples as its independent Owner acceptance baseline.
|
|
2354
|
+
positiveCases = this.extractPositiveCases(goldenTraceCases);
|
|
2355
|
+
}
|
|
2193
2356
|
if (positiveCases.length === 0) {
|
|
2194
2357
|
this.emitEvent('adversarial_replay_skipped', taskId, {
|
|
2195
2358
|
runId,
|
|
@@ -2198,10 +2361,9 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2198
2361
|
});
|
|
2199
2362
|
return { updatedOutput: null, skipReason: 'no_positive_case_in_artificer_golden_trace' };
|
|
2200
2363
|
}
|
|
2201
|
-
//
|
|
2202
|
-
//
|
|
2203
|
-
//
|
|
2204
|
-
// alias/path/combination). Degrade with telemetry (rc-9) if the spec
|
|
2364
|
+
// Derive context availability cases from one complete positive write case.
|
|
2365
|
+
// Business decisions come from the Owner pack, not generic path policies.
|
|
2366
|
+
// Degrade with telemetry (rc-9) if the spec
|
|
2205
2367
|
// cannot be derived for a write target — auxiliary cases cannot replace them.
|
|
2206
2368
|
// PRI-634 R1: V1-shaped outputs carry no adversarialCases — the merged
|
|
2207
2369
|
// set below then relies entirely on the auto-generated v2 cases.
|
|
@@ -2214,8 +2376,18 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2214
2376
|
}
|
|
2215
2377
|
// PRI-741: host-name parity case — the rule must reach the same decision
|
|
2216
2378
|
// under the REAL host tool name as under the author's vocabulary.
|
|
2217
|
-
const hostAliasCase = this.generateHostAliasCase(goldenTraceCases, taskId, runId);
|
|
2379
|
+
const hostAliasCase = this.generateHostAliasCase(requiresContextVersion === 2 ? ownerGoldenTraceCases : goldenTraceCases, taskId, runId);
|
|
2380
|
+
const ownerNegativeAdversarial = ownerNegativeCases.map((ownerCase) => ({
|
|
2381
|
+
caseId: `owner:${ownerCase.caseId}`,
|
|
2382
|
+
attackType: 'boundary',
|
|
2383
|
+
toolName: ownerCase.toolName,
|
|
2384
|
+
params: ownerCase.params,
|
|
2385
|
+
expectedDecision: 'block',
|
|
2386
|
+
rationale: 'System-restored Owner-labelled negative behavior example; expected decision comes from the validated BehaviorExamplePack.',
|
|
2387
|
+
...(ownerCase.ruleContext !== undefined ? { ruleContext: ownerCase.ruleContext } : {}),
|
|
2388
|
+
}));
|
|
2218
2389
|
const mergedAdversarialCases = [
|
|
2390
|
+
...ownerNegativeAdversarial,
|
|
2219
2391
|
...v2Cases,
|
|
2220
2392
|
...(hostAliasCase !== null ? [hostAliasCase] : []),
|
|
2221
2393
|
...llmCases,
|
|
@@ -2381,6 +2553,7 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2381
2553
|
return {
|
|
2382
2554
|
implementationCode: parsed.implementationCode,
|
|
2383
2555
|
goldenTraceCases: parsed.goldenTraceCases,
|
|
2556
|
+
ownerGoldenTraceCases: parsed.ownerGoldenTraceCases,
|
|
2384
2557
|
affectedTools: parsed.affectedTools,
|
|
2385
2558
|
requiresContextVersion: parsed.requiresContextVersion,
|
|
2386
2559
|
evidenceRefs: parsed.evidenceRefs,
|
|
@@ -2965,6 +3138,24 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2965
3138
|
nextAction: 'approval_card_keeps_generic_trigger_reason',
|
|
2966
3139
|
});
|
|
2967
3140
|
}
|
|
3141
|
+
const hostContext = this.hostSemanticContext;
|
|
3142
|
+
const hostKinds = hostContext?.hostKinds;
|
|
3143
|
+
const hasHostInputContract = requiresContextVersion === 2
|
|
3144
|
+
&& hostContext !== null
|
|
3145
|
+
&& Array.isArray(hostKinds)
|
|
3146
|
+
&& hostKinds.length > 0
|
|
3147
|
+
&& hostKinds.every((kind) => typeof kind === 'string' && kind.trim() !== '')
|
|
3148
|
+
&& Array.isArray(hostContext.tools)
|
|
3149
|
+
&& hostContext.tools.length > 0
|
|
3150
|
+
&& hostContext.tools.every((tool) => typeof tool.rawToolName === 'string' && tool.rawToolName.trim() !== ''
|
|
3151
|
+
&& typeof tool.canonicalKind === 'string' && tool.canonicalKind.trim() !== '');
|
|
3152
|
+
if (requiresContextVersion === 2 && !hasHostInputContract) {
|
|
3153
|
+
this.emitEvent('rule_host_input_contract_skipped', taskId, {
|
|
3154
|
+
runId,
|
|
3155
|
+
reason: hostContext === null ? 'host_semantic_context_missing' : 'host_semantic_context_invalid_or_empty',
|
|
3156
|
+
nextAction: 'provide_the_nonempty_host_semantic_projection_used_by_the_deterministic_gate',
|
|
3157
|
+
});
|
|
3158
|
+
}
|
|
2968
3159
|
const ruleContent = {
|
|
2969
3160
|
implementationCode,
|
|
2970
3161
|
goldenTrace: traceBuild.trace,
|
|
@@ -2976,6 +3167,9 @@ export class EvaluatorRunner extends BasePeerRunner {
|
|
|
2976
3167
|
sourceArtificerArtifactId: assemblyInput.sourceArtificerArtifactId ?? output.sourceArtificerArtifactId,
|
|
2977
3168
|
adversarialResult: output.adversarialResult,
|
|
2978
3169
|
...(requiresContextVersion === 2 ? { requiresContextVersion } : {}),
|
|
3170
|
+
...(hasHostInputContract ? {
|
|
3171
|
+
ruleHostInputContract: { version: 1, contextVersion: 2, hostKinds: [...hostKinds] },
|
|
3172
|
+
} : {}),
|
|
2979
3173
|
// PRI-490: preserve evidenceRefs from Artificer artifact into rule artifact.
|
|
2980
3174
|
// Only include when the array is valid (non-empty strings) — v1 rules may omit.
|
|
2981
3175
|
...(requiresContextVersion === 2 && Array.isArray(evidenceRefs) && evidenceRefs.every((e) => typeof e === 'string' && e.trim() !== '')
|