@knights-eye-chess/ai-analysis 0.0.0-stage → 0.1.0-dev.14
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/LICENSE +235 -0
- package/LICENSING.md +26 -0
- package/NOTICE +5 -0
- package/NPM-PUBLISHING.md +24 -0
- package/README.md +141 -2
- package/SOURCE-ORIGIN.json +16 -0
- package/THIRD_PARTY_NOTICES.md +18 -0
- package/build.mjs +22 -0
- package/dist/answer-pipeline.test.mjs +375 -0
- package/dist/chunk-PLKNJRPF.js +10662 -0
- package/dist/chunk-XQDZJOYD.js +2515 -0
- package/dist/index.js +146 -0
- package/dist/owner-tests/chess-reasoning-compact-search-preparation.test.mjs +963 -0
- package/dist/owner-tests/mechanism-encoding.test.mjs +529 -0
- package/dist/owner-tests/move-mechanism-facts.test.mjs +396 -0
- package/dist/owner-tests/pipeline-host-preparation.test.mjs +10556 -0
- package/dist/owner-tests/position-preparation.test.mjs +625 -0
- package/dist/owner-tests/preparation-consolidation.test.mjs +1052 -0
- package/dist/owner-tests/prose-reference-admission.test.mjs +1770 -0
- package/dist/owner-tests/score-comparison-notices.test.mjs +240 -0
- package/dist/owner-tests/simple-engine-presentation.test.mjs +233 -0
- package/dist/owner-tests/tool-input-loop-guard.test.mjs +78 -0
- package/dist/research.js +2274 -0
- package/dist/runtime-closure.json +103 -0
- package/dist/shared-runtime-closure.json +39 -0
- package/dist/shared.js +152 -0
- package/dist/types/ai-request-failure.d.ts +14 -0
- package/dist/types/ai-request-limits.d.ts +4 -0
- package/dist/types/ai-routing-diagnostics.d.ts +14 -0
- package/dist/types/chess-reasoning/ablation-adaptive-evidence-loop.d.ts +127 -0
- package/dist/types/chess-reasoning/ablation-adaptive-runtime.d.ts +178 -0
- package/dist/types/chess-reasoning/ablation-direct-synthesis.d.ts +1030 -0
- package/dist/types/chess-reasoning/ablation-evidence-bundle.d.ts +185 -0
- package/dist/types/chess-reasoning/ablation-evidence-capture.d.ts +37 -0
- package/dist/types/chess-reasoning/ablation-lean-direct-runtime.d.ts +193 -0
- package/dist/types/chess-reasoning/ablation-model-facing-evidence.d.ts +38 -0
- package/dist/types/chess-reasoning/ablation-transport-correction.d.ts +13 -0
- package/dist/types/chess-reasoning/ai-sdk-runtime-support.d.ts +93 -0
- package/dist/types/chess-reasoning/answer-host-contracts.d.ts +59 -0
- package/dist/types/chess-reasoning/answer-model-connector.d.ts +68 -0
- package/dist/types/chess-reasoning/answer-pipeline-exports.d.ts +98 -0
- package/dist/types/chess-reasoning/answer-pipeline.d.ts +41 -0
- package/dist/types/chess-reasoning/answer-reference-validation.d.ts +40 -0
- package/dist/types/chess-reasoning/answer-tool-host.d.ts +8 -0
- package/dist/types/chess-reasoning/branch-expansion-policy.d.ts +13 -0
- package/dist/types/chess-reasoning/branch-expansion.d.ts +39 -0
- package/dist/types/chess-reasoning/causal-claim-checks.d.ts +21 -0
- package/dist/types/chess-reasoning/chess-reference-dictionary.d.ts +13 -0
- package/dist/types/chess-reasoning/classification-question-target.d.ts +22 -0
- package/dist/types/chess-reasoning/classification-reassessment.d.ts +31 -0
- package/dist/types/chess-reasoning/compact-search-preparation.d.ts +7 -0
- package/dist/types/chess-reasoning/concept-registry.d.ts +99 -0
- package/dist/types/chess-reasoning/conversation-context.d.ts +12 -0
- package/dist/types/chess-reasoning/engine-search-failure.d.ts +7 -0
- package/dist/types/chess-reasoning/evidence-citation-normalization.d.ts +9 -0
- package/dist/types/chess-reasoning/evidence-licenses.d.ts +57 -0
- package/dist/types/chess-reasoning/evidence-selector-contract.d.ts +5 -0
- package/dist/types/chess-reasoning/existing-analysis-context.d.ts +104 -0
- package/dist/types/chess-reasoning/fact-observation-provider.d.ts +15 -0
- package/dist/types/chess-reasoning/fact-provider.d.ts +111 -0
- package/dist/types/chess-reasoning/fresh-engine-pv-witnesses.d.ts +67 -0
- package/dist/types/chess-reasoning/historical-prose.d.ts +23 -0
- package/dist/types/chess-reasoning/idea-graph.d.ts +34 -0
- package/dist/types/chess-reasoning/initial-search-plan.d.ts +37 -0
- package/dist/types/chess-reasoning/lossless-evidence-sharing.d.ts +18 -0
- package/dist/types/chess-reasoning/matched-comparison.d.ts +10 -0
- package/dist/types/chess-reasoning/material-accounting.d.ts +80 -0
- package/dist/types/chess-reasoning/material-format.d.ts +4 -0
- package/dist/types/chess-reasoning/mechanical-fact-provider.d.ts +33 -0
- package/dist/types/chess-reasoning/mechanical-ray-facts.d.ts +19 -0
- package/dist/types/chess-reasoning/mechanism-presentation.d.ts +9 -0
- package/dist/types/chess-reasoning/move-mechanism-facts.d.ts +45 -0
- package/dist/types/chess-reasoning/native-answer-connector.d.ts +4 -0
- package/dist/types/chess-reasoning/opening-source-contracts.d.ts +54 -0
- package/dist/types/chess-reasoning/opening-source-credits.d.ts +16 -0
- package/dist/types/chess-reasoning/opponent-threat-preparation.d.ts +7 -0
- package/dist/types/chess-reasoning/piece-identities.d.ts +11 -0
- package/dist/types/chess-reasoning/poc-contracts.d.ts +1026 -0
- package/dist/types/chess-reasoning/poc-hypotheses.d.ts +74 -0
- package/dist/types/chess-reasoning/poc-move-witnesses.d.ts +13 -0
- package/dist/types/chess-reasoning/poc-observations.d.ts +23 -0
- package/dist/types/chess-reasoning/poc-piece-refs.d.ts +12 -0
- package/dist/types/chess-reasoning/poc-plan-model.d.ts +45 -0
- package/dist/types/chess-reasoning/poc-semantic-text.d.ts +8 -0
- package/dist/types/chess-reasoning/poc-tools.d.ts +81 -0
- package/dist/types/chess-reasoning/portable-answer-runtime.d.ts +291 -0
- package/dist/types/chess-reasoning/position-analysis-contracts.d.ts +31 -0
- package/dist/types/chess-reasoning/position-analysis-scope.d.ts +3 -0
- package/dist/types/chess-reasoning/preparation-consolidation.d.ts +21 -0
- package/dist/types/chess-reasoning/production-observation-provider.d.ts +16 -0
- package/dist/types/chess-reasoning/question-routing.d.ts +326 -0
- package/dist/types/chess-reasoning/recorded-main-line.d.ts +37 -0
- package/dist/types/chess-reasoning/recorded-position-tools.d.ts +11 -0
- package/dist/types/chess-reasoning/recorded-reference-context.d.ts +13 -0
- package/dist/types/chess-reasoning/recorded-selected-classification.d.ts +36 -0
- package/dist/types/chess-reasoning/reference-limits.d.ts +2 -0
- package/dist/types/chess-reasoning/research-exports.d.ts +197 -0
- package/dist/types/chess-reasoning/saved-score-presentation.d.ts +14 -0
- package/dist/types/chess-reasoning/score-comparison-notices.d.ts +33 -0
- package/dist/types/chess-reasoning/server-simple-policy.d.ts +31 -0
- package/dist/types/chess-reasoning/simple-agent-config.d.ts +73 -0
- package/dist/types/chess-reasoning/simple-board-analysis.d.ts +85 -0
- package/dist/types/chess-reasoning/simple-compact-evidence.d.ts +7 -0
- package/dist/types/chess-reasoning/simple-completion.d.ts +23 -0
- package/dist/types/chess-reasoning/simple-engine-presentation.d.ts +3 -0
- package/dist/types/chess-reasoning/simple-evidence-preparation.d.ts +17 -0
- package/dist/types/chess-reasoning/simple-evidence-view.d.ts +17 -0
- package/dist/types/chess-reasoning/simple-explanation-coverage.d.ts +90 -0
- package/dist/types/chess-reasoning/simple-fact-delivery.d.ts +43 -0
- package/dist/types/chess-reasoning/simple-fallback-premise.d.ts +5 -0
- package/dist/types/chess-reasoning/simple-prose-references.d.ts +108 -0
- package/dist/types/chess-reasoning/simple-runtime-version.d.ts +1 -0
- package/dist/types/chess-reasoning/stable.d.ts +2 -0
- package/dist/types/chess-reasoning/tool-input-loop-guard.d.ts +5 -0
- package/dist/types/chess-reasoning/types.d.ts +180 -0
- package/dist/types/chess-reasoning/visible-support-lines.d.ts +12 -0
- package/dist/types/chess-reasoning/wikibooks-index.d.ts +30 -0
- package/dist/types/chess-reasoning/wikibooks-tool-context.d.ts +10 -0
- package/dist/types/player-perspective.d.ts +16 -0
- package/dist/types/shared-exports.d.ts +22 -0
- package/docs/API.md +82 -0
- package/docs/OWNERSHIP-ADOPTION.md +35 -0
- package/docs/OWNERSHIP-DRIFT.json +55 -0
- package/docs/RESEARCH-API.md +28 -0
- package/licenses/third-party/INVENTORY.json +202 -0
- package/licenses/third-party/ai-7.0.85/LICENSE +13 -0
- package/licenses/third-party/ai-sdk--gateway-4.0.69/LICENSE +13 -0
- package/licenses/third-party/ai-sdk--provider-4.0.9/LICENSE +13 -0
- package/licenses/third-party/ai-sdk--provider-utils-5.0.34/APACHE-2.0.txt +73 -0
- package/licenses/third-party/ai-sdk--provider-utils-5.0.34/src/to-json-schema/zod3-to-json-schema/LICENSE +16 -0
- package/licenses/third-party/chess.js-1.4.0/LICENSE +23 -0
- package/licenses/third-party/eventsource-parser-3.1.1/LICENSE +21 -0
- package/licenses/third-party/json-schema-0.4.0/LICENSE +195 -0
- package/licenses/third-party/standard-schema--spec-1.1.0/LICENSE +21 -0
- package/licenses/third-party/types--json-schema-7.0.15/LICENSE +21 -0
- package/licenses/third-party/types--node-22.19.19/LICENSE +21 -0
- package/licenses/third-party/undici-7.30.0/LICENSE +21 -0
- package/licenses/third-party/undici-7.30.0/lib/web/fetch/LICENSE +21 -0
- package/licenses/third-party/undici-types-6.21.0/LICENSE +21 -0
- package/licenses/third-party/vercel--oidc-3.2.0/LICENSE +202 -0
- package/licenses/third-party/workflow--serde-4.1.0/APACHE-2.0.txt +73 -0
- package/licenses/third-party/workflow--serde-4.1.0/LICENSE.md +3 -0
- package/licenses/third-party/zod-4.6.5/LICENSE +21 -0
- package/npm-release.json +5 -0
- package/package.json +72 -4
- package/scripts/check-release-tooling.mjs +22 -0
- package/scripts/pack.mjs +68 -0
- package/scripts/publish-reviewed.mjs +72 -0
- package/scripts/release-tooling.json +13 -0
- package/scripts/update-dependency.mjs +44 -0
- package/scripts/verify-release.mjs +52 -0
- package/src/ai-request-failure.ts +34 -0
- package/src/ai-request-limits.ts +4 -0
- package/src/ai-routing-diagnostics.ts +33 -0
- package/src/chess-reasoning/ablation-adaptive-evidence-loop.ts +515 -0
- package/src/chess-reasoning/ablation-adaptive-runtime.ts +924 -0
- package/src/chess-reasoning/ablation-direct-synthesis.ts +1128 -0
- package/src/chess-reasoning/ablation-evidence-bundle.ts +726 -0
- package/src/chess-reasoning/ablation-evidence-capture.ts +513 -0
- package/src/chess-reasoning/ablation-lean-direct-runtime.ts +670 -0
- package/src/chess-reasoning/ablation-model-facing-evidence.ts +212 -0
- package/src/chess-reasoning/ablation-transport-correction.ts +106 -0
- package/src/chess-reasoning/ai-sdk-runtime-support.ts +381 -0
- package/src/chess-reasoning/answer-host-contracts.ts +10 -0
- package/src/chess-reasoning/answer-model-connector.ts +83 -0
- package/src/chess-reasoning/answer-pipeline-exports.ts +98 -0
- package/src/chess-reasoning/answer-pipeline.ts +195 -0
- package/src/chess-reasoning/answer-reference-validation.ts +124 -0
- package/src/chess-reasoning/answer-tool-host.ts +10 -0
- package/src/chess-reasoning/branch-expansion-policy.ts +32 -0
- package/src/chess-reasoning/branch-expansion.ts +80 -0
- package/src/chess-reasoning/causal-claim-checks.ts +256 -0
- package/src/chess-reasoning/chess-reference-dictionary.ts +21 -0
- package/src/chess-reasoning/classification-question-target.ts +30 -0
- package/src/chess-reasoning/classification-reassessment.ts +34 -0
- package/src/chess-reasoning/compact-search-preparation.ts +125 -0
- package/src/chess-reasoning/concept-registry.ts +275 -0
- package/src/chess-reasoning/conversation-context.ts +29 -0
- package/src/chess-reasoning/engine-search-failure.ts +11 -0
- package/src/chess-reasoning/evidence-citation-normalization.ts +15 -0
- package/src/chess-reasoning/evidence-licenses.ts +166 -0
- package/src/chess-reasoning/evidence-selector-contract.ts +5 -0
- package/src/chess-reasoning/existing-analysis-context.ts +544 -0
- package/src/chess-reasoning/fact-observation-provider.ts +134 -0
- package/src/chess-reasoning/fact-provider.ts +250 -0
- package/src/chess-reasoning/fresh-engine-pv-witnesses.ts +128 -0
- package/src/chess-reasoning/historical-prose.ts +116 -0
- package/src/chess-reasoning/idea-graph.ts +224 -0
- package/src/chess-reasoning/initial-search-plan.ts +115 -0
- package/src/chess-reasoning/lossless-evidence-sharing.ts +135 -0
- package/src/chess-reasoning/matched-comparison.ts +40 -0
- package/src/chess-reasoning/material-accounting.ts +55 -0
- package/src/chess-reasoning/material-format.ts +47 -0
- package/src/chess-reasoning/mechanical-fact-provider.ts +1602 -0
- package/src/chess-reasoning/mechanical-ray-facts.ts +123 -0
- package/src/chess-reasoning/mechanism-presentation.ts +94 -0
- package/src/chess-reasoning/move-mechanism-facts.ts +185 -0
- package/src/chess-reasoning/native-answer-connector.ts +13 -0
- package/src/chess-reasoning/opening-source-contracts.ts +47 -0
- package/src/chess-reasoning/opening-source-credits.ts +53 -0
- package/src/chess-reasoning/opponent-threat-preparation.ts +98 -0
- package/src/chess-reasoning/piece-identities.ts +159 -0
- package/src/chess-reasoning/poc-contracts.ts +1097 -0
- package/src/chess-reasoning/poc-hypotheses.ts +759 -0
- package/src/chess-reasoning/poc-move-witnesses.ts +170 -0
- package/src/chess-reasoning/poc-observations.ts +611 -0
- package/src/chess-reasoning/poc-piece-refs.ts +62 -0
- package/src/chess-reasoning/poc-plan-model.ts +345 -0
- package/src/chess-reasoning/poc-semantic-text.ts +10 -0
- package/src/chess-reasoning/poc-tools.ts +978 -0
- package/src/chess-reasoning/portable-answer-runtime.ts +684 -0
- package/src/chess-reasoning/position-analysis-contracts.ts +88 -0
- package/src/chess-reasoning/position-analysis-scope.ts +20 -0
- package/src/chess-reasoning/preparation-consolidation.ts +91 -0
- package/src/chess-reasoning/production-observation-provider.ts +41 -0
- package/src/chess-reasoning/question-routing.ts +332 -0
- package/src/chess-reasoning/recorded-main-line.ts +55 -0
- package/src/chess-reasoning/recorded-position-tools.ts +78 -0
- package/src/chess-reasoning/recorded-reference-context.ts +44 -0
- package/src/chess-reasoning/recorded-selected-classification.ts +54 -0
- package/src/chess-reasoning/reference-limits.ts +2 -0
- package/src/chess-reasoning/research-exports.ts +197 -0
- package/src/chess-reasoning/saved-score-presentation.ts +6 -0
- package/src/chess-reasoning/score-comparison-notices.ts +115 -0
- package/src/chess-reasoning/server-simple-policy.ts +75 -0
- package/src/chess-reasoning/simple-agent-config.ts +58 -0
- package/src/chess-reasoning/simple-board-analysis.ts +57 -0
- package/src/chess-reasoning/simple-compact-evidence.ts +79 -0
- package/src/chess-reasoning/simple-completion.ts +37 -0
- package/src/chess-reasoning/simple-engine-presentation.ts +95 -0
- package/src/chess-reasoning/simple-evidence-preparation.ts +32 -0
- package/src/chess-reasoning/simple-evidence-view.ts +69 -0
- package/src/chess-reasoning/simple-explanation-coverage.ts +118 -0
- package/src/chess-reasoning/simple-fact-delivery.ts +52 -0
- package/src/chess-reasoning/simple-fallback-premise.ts +65 -0
- package/src/chess-reasoning/simple-prose-references.ts +528 -0
- package/src/chess-reasoning/simple-runtime-version.ts +2 -0
- package/src/chess-reasoning/stable.ts +18 -0
- package/src/chess-reasoning/tool-input-loop-guard.ts +38 -0
- package/src/chess-reasoning/types.ts +195 -0
- package/src/chess-reasoning/visible-support-lines.ts +44 -0
- package/src/chess-reasoning/wikibooks-index.ts +56 -0
- package/src/chess-reasoning/wikibooks-tool-context.ts +91 -0
- package/src/player-perspective.ts +41 -0
- package/src/shared-exports.ts +23 -0
- package/test/answer-pipeline.test.mjs +375 -0
- package/test/owner/chess-reasoning-compact-search-preparation.test.mjs +111 -0
- package/test/owner/mechanism-encoding.test.mjs +78 -0
- package/test/owner/move-mechanism-facts.test.mjs +105 -0
- package/test/owner/pipeline-host-preparation.test.mjs +115 -0
- package/test/owner/position-preparation.test.mjs +22 -0
- package/test/owner/preparation-consolidation.test.mjs +74 -0
- package/test/owner/prose-reference-admission.test.mjs +26 -0
- package/test/owner/score-comparison-notices.test.mjs +116 -0
- package/test/owner/simple-engine-presentation.test.mjs +50 -0
- package/test/owner/tool-input-loop-guard.test.mjs +25 -0
- package/test-types.mts +23 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAblationEvidenceClosureBundle,
|
|
3
|
+
validateAblationEvidenceClosureBundle,
|
|
4
|
+
type AblationEvidenceClosureBundle,
|
|
5
|
+
type AblationEvidenceClosureCoverage,
|
|
6
|
+
type AblationEvidenceReferenceAllowlists,
|
|
7
|
+
} from "./ablation-evidence-bundle";
|
|
8
|
+
import { REFERENCE_DOMAINS } from "./concept-registry";
|
|
9
|
+
import { stableHash } from "./stable";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The closure is deliberately larger than the model view: it retains all
|
|
13
|
+
* pre-salience records for evaluator audit. This projection is the one and
|
|
14
|
+
* only boundary at which that closure becomes provider-visible.
|
|
15
|
+
*/
|
|
16
|
+
export const ABLATION_MODEL_FACING_EVIDENCE_VIEW_VERSION = "architecture-ablation-model-facing-evidence/1" as const;
|
|
17
|
+
|
|
18
|
+
/** Lean-only transport: evidence is unchanged; observations are an index, not a second copy of its data. */
|
|
19
|
+
export function compactLeanEvidencePacket(bundle: Readonly<AblationEvidenceClosureBundle>) {
|
|
20
|
+
return {
|
|
21
|
+
context: bundle.context, contextHash: bundle.contextHash, question: bundle.question,
|
|
22
|
+
evidence: bundle.evidence,
|
|
23
|
+
observations: bundle.observations.map((item) => ({
|
|
24
|
+
id: item.id, observationType: item.observationType, exactness: item.exactness,
|
|
25
|
+
factEvidenceIds: item.factEvidenceIds,
|
|
26
|
+
})),
|
|
27
|
+
coverage: bundle.coverage,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type AblationModelFacingEvidenceView = Readonly<{
|
|
32
|
+
schemaVersion: typeof ABLATION_MODEL_FACING_EVIDENCE_VIEW_VERSION;
|
|
33
|
+
/** Immutable audit identity of the complete, pre-salience closure. */
|
|
34
|
+
sourceBundleHash: string;
|
|
35
|
+
/** A separately validated, non-mutating closure containing only visible material. */
|
|
36
|
+
bundle: Readonly<AblationEvidenceClosureBundle>;
|
|
37
|
+
visibleObservationIds: readonly string[];
|
|
38
|
+
visibleEvidenceIds: readonly string[];
|
|
39
|
+
viewHash: string;
|
|
40
|
+
}>;
|
|
41
|
+
|
|
42
|
+
const OMIT = Symbol("ablation-model-facing-omit");
|
|
43
|
+
|
|
44
|
+
function record(value: unknown): value is Record<string, unknown> {
|
|
45
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function clone<T>(value: T): T {
|
|
49
|
+
return structuredClone(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function sorted(values: Iterable<string>): string[] {
|
|
53
|
+
return [...new Set(values)].sort();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function isRankedObservation(value: unknown): value is { presentedToModel: boolean; salience: number; salienceReasons: unknown[] } {
|
|
57
|
+
return record(value)
|
|
58
|
+
&& typeof value.presentedToModel === "boolean"
|
|
59
|
+
&& typeof value.salience === "number"
|
|
60
|
+
&& Number.isFinite(value.salience)
|
|
61
|
+
&& Array.isArray(value.salienceReasons);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function redactHiddenIds(value: unknown, hiddenIds: ReadonlySet<string>): unknown {
|
|
65
|
+
if (typeof value === "string") {
|
|
66
|
+
if (hiddenIds.has(value)) return OMIT;
|
|
67
|
+
let redacted = value;
|
|
68
|
+
for (const id of hiddenIds) redacted = redacted.replaceAll(id, "[withheld]");
|
|
69
|
+
return redacted;
|
|
70
|
+
}
|
|
71
|
+
if (Array.isArray(value)) {
|
|
72
|
+
return value.map((item) => redactHiddenIds(item, hiddenIds)).filter((item) => item !== OMIT);
|
|
73
|
+
}
|
|
74
|
+
if (!record(value)) return value;
|
|
75
|
+
const result: Record<string, unknown> = {};
|
|
76
|
+
for (const [key, child] of Object.entries(value)) {
|
|
77
|
+
const redacted = redactHiddenIds(child, hiddenIds);
|
|
78
|
+
if (redacted !== OMIT) result[key] = redacted;
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function valueContains(value: unknown, sought: string): boolean {
|
|
84
|
+
if (value === sought) return true;
|
|
85
|
+
if (Array.isArray(value)) return value.some((item) => valueContains(item, sought));
|
|
86
|
+
return record(value) && Object.values(value).some((item) => valueContains(item, sought));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function visibleCoverage(
|
|
90
|
+
coverage: AblationEvidenceClosureCoverage,
|
|
91
|
+
visibleObservationIds: ReadonlySet<string>,
|
|
92
|
+
visibleEvidenceIds: ReadonlySet<string>,
|
|
93
|
+
hiddenIds: ReadonlySet<string>,
|
|
94
|
+
): AblationEvidenceClosureCoverage {
|
|
95
|
+
const belongsToHidden = (value: string) => hiddenIds.has(value)
|
|
96
|
+
|| [...hiddenIds].some((id) => value === `observation:${id}` || value === `evidence:${id}` || value.includes(id));
|
|
97
|
+
const visible = (value: string) => visibleObservationIds.has(value) || visibleEvidenceIds.has(value);
|
|
98
|
+
const recordsHidden = hiddenIds.size > 0;
|
|
99
|
+
return {
|
|
100
|
+
// A model-facing subset can never retain the parent closure's exhaustive
|
|
101
|
+
// claim once audit-only records were intentionally withheld.
|
|
102
|
+
complete: recordsHidden ? false : coverage.complete,
|
|
103
|
+
covered: coverage.covered.filter((item) => !belongsToHidden(item)),
|
|
104
|
+
omitted: coverage.omitted.filter((item) => item.domain === "tool" || visible(item.id)),
|
|
105
|
+
unavailable: coverage.unavailable.filter((item) => !belongsToHidden(item.id)),
|
|
106
|
+
limitations: [
|
|
107
|
+
...coverage.limitations.filter((item) => !belongsToHidden(item)),
|
|
108
|
+
...(recordsHidden ? ["This model-facing projection intentionally excludes audit-only closure records."] : []),
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function visibleAllowlists(
|
|
114
|
+
source: Readonly<AblationEvidenceClosureBundle>,
|
|
115
|
+
observations: readonly typeof source.observations[number][],
|
|
116
|
+
evidence: readonly typeof source.evidence[number][],
|
|
117
|
+
hiddenIds: ReadonlySet<string>,
|
|
118
|
+
): AblationEvidenceReferenceAllowlists {
|
|
119
|
+
const visibleEvidenceIds = new Set(evidence.map((item) => item.id));
|
|
120
|
+
const visibleObservationIds = new Set(observations.map((item) => item.id));
|
|
121
|
+
const targetWitnesses = source.referenceAllowlists.moveWitnesses
|
|
122
|
+
.filter((witness) => visibleEvidenceIds.has(witness.evidenceId) && witness.uci === source.context.moveUci);
|
|
123
|
+
const targetSquares = new Set([source.context.moveUci.slice(0, 2), source.context.moveUci.slice(2, 4)]);
|
|
124
|
+
const targetPieces = new Set(targetWitnesses.map((witness) => witness.pieceId));
|
|
125
|
+
const semanticReferences = source.referenceAllowlists.semanticReferences.filter((reference) => {
|
|
126
|
+
if (reference.domain === REFERENCE_DOMAINS.MOVE && reference.id === source.context.moveUci) return true;
|
|
127
|
+
if (reference.domain === REFERENCE_DOMAINS.SQUARE && targetSquares.has(reference.id)) return true;
|
|
128
|
+
if (reference.domain === REFERENCE_DOMAINS.PIECE && targetPieces.has(reference.id)) return true;
|
|
129
|
+
if (observations.some((observation) => observation.participants.some((participant) => participant.ref.domain === reference.domain && participant.ref.id === reference.id))) return true;
|
|
130
|
+
return evidence.some((item) => valueContains(item.data, reference.id) || valueContains(item.replay, reference.id));
|
|
131
|
+
}).map((item) => clone(item));
|
|
132
|
+
return {
|
|
133
|
+
evidenceIds: sorted(visibleEvidenceIds),
|
|
134
|
+
observationIds: sorted(visibleObservationIds),
|
|
135
|
+
toolNames: [...source.referenceAllowlists.toolNames],
|
|
136
|
+
semanticReferences,
|
|
137
|
+
moveWitnesses: source.referenceAllowlists.moveWitnesses
|
|
138
|
+
.filter((witness) => visibleEvidenceIds.has(witness.evidenceId) && !hiddenIds.has(witness.evidenceId))
|
|
139
|
+
.map((witness) => clone(witness)),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Project a full ablation closure to material that the relevant arm may see.
|
|
145
|
+
* Original observations must retain exact ranked presentation metadata. New
|
|
146
|
+
* acquisition/enrichment records are intentionally visible by lineage, while
|
|
147
|
+
* an unlinked admitted probe remains available as concrete evidence.
|
|
148
|
+
*/
|
|
149
|
+
export function projectAblationEvidenceForModel(
|
|
150
|
+
source: Readonly<AblationEvidenceClosureBundle>,
|
|
151
|
+
): AblationModelFacingEvidenceView {
|
|
152
|
+
validateAblationEvidenceClosureBundle(source);
|
|
153
|
+
const acquiredObservationIds = new Set(source.lineage.kind === "enriched" ? source.lineage.acquiredObservationIds : []);
|
|
154
|
+
const acquiredEvidenceIds = new Set(source.lineage.kind === "enriched" ? source.lineage.acquiredEvidenceIds : []);
|
|
155
|
+
const visibleObservations = source.observations.filter((observation) => {
|
|
156
|
+
if (acquiredObservationIds.has(observation.id)) return true;
|
|
157
|
+
if (!isRankedObservation(observation)) {
|
|
158
|
+
throw new Error(`Ablation model-facing projection requires ranked presentation metadata for original observation ${observation.id}`);
|
|
159
|
+
}
|
|
160
|
+
return observation.presentedToModel;
|
|
161
|
+
});
|
|
162
|
+
const visibleObservationIds = new Set(visibleObservations.map((item) => item.id));
|
|
163
|
+
const visibleEvidenceIds = new Set<string>();
|
|
164
|
+
for (const record of source.evidence) {
|
|
165
|
+
if (record.kind === "context" || record.kind === "probe" || acquiredEvidenceIds.has(record.id)) visibleEvidenceIds.add(record.id);
|
|
166
|
+
}
|
|
167
|
+
for (const observation of visibleObservations) {
|
|
168
|
+
for (const evidenceId of observation.factEvidenceIds) visibleEvidenceIds.add(evidenceId);
|
|
169
|
+
}
|
|
170
|
+
const visibleEvidence = source.evidence.filter((record) => visibleEvidenceIds.has(record.id));
|
|
171
|
+
const hiddenIds = new Set([
|
|
172
|
+
...source.observations.filter((item) => !visibleObservationIds.has(item.id)).map((item) => item.id),
|
|
173
|
+
...source.evidence.filter((item) => !visibleEvidenceIds.has(item.id)).map((item) => item.id),
|
|
174
|
+
]);
|
|
175
|
+
const observations = visibleObservations.map((observation) => {
|
|
176
|
+
const redacted = redactHiddenIds(clone(observation), hiddenIds) as typeof observation & Partial<{ salience: number; salienceReasons: string[]; presentedToModel: boolean }>;
|
|
177
|
+
// Enrichment observations are intentional post-baseline acquisition, not
|
|
178
|
+
// candidates for a second salience decision. Make that membership explicit
|
|
179
|
+
// in the model projection without changing the audited source closure.
|
|
180
|
+
if (!isRankedObservation(redacted)) {
|
|
181
|
+
return { ...redacted, salience: 1, salienceReasons: ["ablation-enriched-acquisition"], presentedToModel: true };
|
|
182
|
+
}
|
|
183
|
+
return redacted;
|
|
184
|
+
});
|
|
185
|
+
const evidence = visibleEvidence.map((item) => redactHiddenIds(clone(item), hiddenIds) as typeof item);
|
|
186
|
+
const coverage = visibleCoverage(source.coverage, visibleObservationIds, visibleEvidenceIds, hiddenIds);
|
|
187
|
+
const referenceAllowlists = visibleAllowlists(source, observations, evidence, hiddenIds);
|
|
188
|
+
const bundle = createAblationEvidenceClosureBundle({
|
|
189
|
+
context: clone(source.context),
|
|
190
|
+
question: source.question,
|
|
191
|
+
observations,
|
|
192
|
+
evidence,
|
|
193
|
+
referenceAllowlists,
|
|
194
|
+
coverage,
|
|
195
|
+
});
|
|
196
|
+
const visibleObservationIdList = sorted(visibleObservationIds);
|
|
197
|
+
const visibleEvidenceIdList = sorted(visibleEvidenceIds);
|
|
198
|
+
return Object.freeze({
|
|
199
|
+
schemaVersion: ABLATION_MODEL_FACING_EVIDENCE_VIEW_VERSION,
|
|
200
|
+
sourceBundleHash: source.bundleHash,
|
|
201
|
+
bundle,
|
|
202
|
+
visibleObservationIds: Object.freeze(visibleObservationIdList),
|
|
203
|
+
visibleEvidenceIds: Object.freeze(visibleEvidenceIdList),
|
|
204
|
+
viewHash: stableHash({
|
|
205
|
+
schemaVersion: ABLATION_MODEL_FACING_EVIDENCE_VIEW_VERSION,
|
|
206
|
+
sourceBundleHash: source.bundleHash,
|
|
207
|
+
bundleHash: bundle.bundleHash,
|
|
208
|
+
visibleObservationIds: visibleObservationIdList,
|
|
209
|
+
visibleEvidenceIds: visibleEvidenceIdList,
|
|
210
|
+
}),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { DirectSynthesisIssue } from "./ablation-direct-synthesis";
|
|
2
|
+
import { stableJson } from "./stable";
|
|
3
|
+
|
|
4
|
+
/** A narrow transport-only correction is never a second semantic authoring turn. */
|
|
5
|
+
export class AblationTransportCorrectionError extends Error {
|
|
6
|
+
readonly code = "transport-correction-outside-validator-paths" as const;
|
|
7
|
+
constructor(message: string) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "AblationTransportCorrectionError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type TransportPath = Array<string | number>;
|
|
14
|
+
|
|
15
|
+
function sameRecord(left: unknown, right: unknown): boolean {
|
|
16
|
+
return stableJson(left) === stableJson(right);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function transportCorrectionPath(issue: DirectSynthesisIssue): TransportPath | null {
|
|
20
|
+
// Only exact, leaf-level reference defects are reparable. Broad schema and
|
|
21
|
+
// semantic validation errors fail closed rather than becoming a rewrite.
|
|
22
|
+
if (!new Set(["unknown_evidence", "unknown_local_entity", "unknown_local_relation", "invalid_piece_form", "raw_chess_reference"]).has(issue.code)) return null;
|
|
23
|
+
const tokens = [...issue.path.matchAll(/(?:^|\.)([A-Za-z_][A-Za-z0-9_]*)|\[(\d+)\]/g)]
|
|
24
|
+
.map((match) => match[1] || Number(match[2]));
|
|
25
|
+
if (tokens[0] !== "proposal" || tokens.length < 3 || tokens.some((token) => typeof token === "string" && token === "__proto__")) return null;
|
|
26
|
+
const leaf = tokens.at(-1);
|
|
27
|
+
// Raw concrete chess language is reparable only in an optional
|
|
28
|
+
// qualification text leaf. The correction may make that one text segment
|
|
29
|
+
// less specific, but may not rewrite the claim, its evidence, or its main
|
|
30
|
+
// narrative. A raw reference elsewhere remains a hard validation error.
|
|
31
|
+
if (issue.code === "raw_chess_reference") {
|
|
32
|
+
const [proposal, claims, claimIndex, qualifications, qualificationIndex, segmentIndex, text] = tokens;
|
|
33
|
+
return proposal === "proposal"
|
|
34
|
+
&& claims === "claims"
|
|
35
|
+
&& typeof claimIndex === "number"
|
|
36
|
+
&& qualifications === "qualifications"
|
|
37
|
+
&& typeof qualificationIndex === "number"
|
|
38
|
+
&& typeof segmentIndex === "number"
|
|
39
|
+
&& text === "text"
|
|
40
|
+
&& tokens.length === 7
|
|
41
|
+
? tokens
|
|
42
|
+
: null;
|
|
43
|
+
}
|
|
44
|
+
if (!(["evidenceIds", "entityLocalId", "relationLocalId", "form"] as const).includes(leaf as never)) return null;
|
|
45
|
+
if (issue.code === "unknown_evidence" && leaf !== "evidenceIds") return null;
|
|
46
|
+
if ((issue.code === "unknown_local_entity" && leaf !== "entityLocalId")
|
|
47
|
+
|| (issue.code === "unknown_local_relation" && leaf !== "relationLocalId")
|
|
48
|
+
|| (issue.code === "invalid_piece_form" && leaf !== "form")) return null;
|
|
49
|
+
return tokens;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function deleteExactPath(value: unknown, path: TransportPath): void {
|
|
53
|
+
let cursor = value as Record<string, unknown> | unknown[];
|
|
54
|
+
for (const token of path.slice(1, -1)) {
|
|
55
|
+
if (typeof token === "number") {
|
|
56
|
+
if (!Array.isArray(cursor) || !Object.prototype.hasOwnProperty.call(cursor, token)) throw new AblationTransportCorrectionError("Transport correction issue path is not an exact existing array path");
|
|
57
|
+
cursor = cursor[token] as Record<string, unknown> | unknown[];
|
|
58
|
+
} else {
|
|
59
|
+
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor) || !Object.prototype.hasOwnProperty.call(cursor, token)) throw new AblationTransportCorrectionError("Transport correction issue path is not an exact existing object path");
|
|
60
|
+
cursor = cursor[token] as Record<string, unknown> | unknown[];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const leaf = path.at(-1)!;
|
|
64
|
+
if (typeof leaf !== "string" || !cursor || typeof cursor !== "object" || Array.isArray(cursor) || !Object.prototype.hasOwnProperty.call(cursor, leaf)) {
|
|
65
|
+
throw new AblationTransportCorrectionError("Transport correction issue path is too broad or absent");
|
|
66
|
+
}
|
|
67
|
+
delete (cursor as Record<string, unknown>)[leaf];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function isTransportCorrectableDirectSynthesisIssues(issues: readonly DirectSynthesisIssue[]): boolean {
|
|
71
|
+
return issues.length > 0 && issues.every((issue) => transportCorrectionPath(issue) !== null);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The model may change only exact validator-named reference leaves. Item
|
|
76
|
+
* identity/cardinality and every other semantic/evidence association remain
|
|
77
|
+
* structure-equivalent. This guard is shared by A1 and B/B′ for fairness.
|
|
78
|
+
*/
|
|
79
|
+
export function assertTransportOnlyDirectCorrection(
|
|
80
|
+
originalProposal: unknown,
|
|
81
|
+
correctedProposal: unknown,
|
|
82
|
+
issues: readonly DirectSynthesisIssue[],
|
|
83
|
+
): void {
|
|
84
|
+
const paths = issues.map(transportCorrectionPath);
|
|
85
|
+
if (!paths.length || paths.some((path) => path === null)) throw new AblationTransportCorrectionError("Transport correction does not have a narrow validator-authorized path");
|
|
86
|
+
if (!originalProposal || typeof originalProposal !== "object" || Array.isArray(originalProposal) || !correctedProposal || typeof correctedProposal !== "object" || Array.isArray(correctedProposal)) {
|
|
87
|
+
throw new AblationTransportCorrectionError("Transport correction requires complete object proposals");
|
|
88
|
+
}
|
|
89
|
+
for (const collection of ["hypotheses", "relations", "claims", "demonstrations"] as const) {
|
|
90
|
+
const before = (originalProposal as Record<string, unknown>)[collection];
|
|
91
|
+
const after = (correctedProposal as Record<string, unknown>)[collection];
|
|
92
|
+
if (!Array.isArray(before) || !Array.isArray(after) || before.length !== after.length) throw new AblationTransportCorrectionError("Transport correction changed proposal item cardinality");
|
|
93
|
+
for (let index = 0; index < before.length; index += 1) {
|
|
94
|
+
const beforeId = before[index] && typeof before[index] === "object" ? (before[index] as Record<string, unknown>).localId : undefined;
|
|
95
|
+
const afterId = after[index] && typeof after[index] === "object" ? (after[index] as Record<string, unknown>).localId : undefined;
|
|
96
|
+
if (beforeId !== afterId) throw new AblationTransportCorrectionError("Transport correction changed a proposal item identity");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const before = structuredClone(originalProposal);
|
|
100
|
+
const after = structuredClone(correctedProposal);
|
|
101
|
+
for (const path of paths as TransportPath[]) {
|
|
102
|
+
deleteExactPath(before, path);
|
|
103
|
+
deleteExactPath(after, path);
|
|
104
|
+
}
|
|
105
|
+
if (!sameRecord(before, after)) throw new AblationTransportCorrectionError("Transport correction changed semantic content outside validator-authorized paths");
|
|
106
|
+
}
|