create-agdf 0.13.2 → 0.13.3
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/generated/.agdf/control/templates/RUN_STATE.md +22 -0
- package/generated/.agdf/control/templates/artefacts/OR.md +22 -0
- package/generated/.github/skills/agdf-delivery-closeout/SKILL.md +7 -0
- package/generated/.github/skills/agdf-interaction-locales.json +2 -4
- package/generated/.github/skills/agdf-release-or/SKILL.md +14 -4
- package/generated/.github/skills/contracts/closeout.md +49 -0
- package/generated/.github/skills/contracts/control-scaffold.md +2 -0
- package/generated/.github/skills/contracts/interaction.md +23 -12
- package/generated/.opencode/agdf-interaction-locales.json +2 -4
- package/generated/.opencode/contracts/closeout.md +49 -0
- package/generated/.opencode/contracts/control-scaffold.md +2 -0
- package/generated/.opencode/contracts/interaction.md +23 -12
- package/generated/.opencode/skills/agdf-delivery-closeout/SKILL.md +7 -0
- package/generated/.opencode/skills/agdf-release-or/SKILL.md +14 -4
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/control/templates/RUN_STATE.md +22 -0
- package/generated/plugins/agdf/control/templates/artefacts/OR.md +22 -0
- package/generated/plugins/agdf/meta/agdf-interaction-locales.json +2 -4
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/meta/agent-skills-conformance.json +86 -0
- package/generated/plugins/agdf/meta/contracts/closeout.md +49 -0
- package/generated/plugins/agdf/meta/contracts/control-scaffold.md +2 -0
- package/generated/plugins/agdf/meta/contracts/interaction.md +23 -12
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-interaction-locales.json +2 -4
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/delivery-map.js +13 -3
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/doctor.js +9 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-check.js +6 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/gate-policy.js +16 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-evaluation/parent-reconciliation.js +284 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/control-state/run-state-parser.js +39 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/interaction-presentation.js +31 -14
- package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/agdf/scripts/agent-skills-conformance.mjs +543 -0
- package/generated/plugins/agdf/scripts/check-runtime-integrity.mjs +31 -17
- package/generated/plugins/agdf/skills/delivery-closeout/SKILL.md +7 -0
- package/generated/plugins/agdf/skills/release-or/SKILL.md +14 -4
- package/generated/plugins/agdf/submission/openai/availability.md +1 -1
- package/generated/plugins/agdf/submission/openai/capability-matrix.json +2 -2
- package/generated/plugins/agdf/submission/openai/release-notes.md +1 -1
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
- package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/submissions/openai/agdf/meta/agdf-interaction-locales.json +2 -4
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/submissions/openai/agdf/meta/agent-skills-conformance.json +86 -0
- package/generated/submissions/openai/agdf/meta/contracts/closeout.md +49 -0
- package/generated/submissions/openai/agdf/meta/contracts/control-scaffold.md +2 -0
- package/generated/submissions/openai/agdf/meta/contracts/interaction.md +23 -12
- package/generated/submissions/openai/agdf/skills/delivery-closeout/SKILL.md +7 -0
- package/generated/submissions/openai/agdf/skills/release-or/SKILL.md +14 -4
- package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +2 -2
- package/generated/submissions/openai/agdf/submission/openai/inventory.json +19 -15
- package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
- package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
- package/generated/submissions/openai/agdf/submission/openai/release-notes.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
- package/lib/control-evaluation/delivery-map.js +13 -3
- package/lib/control-evaluation/doctor.js +9 -2
- package/lib/control-evaluation/gate-check.js +6 -1
- package/lib/control-evaluation/gate-policy.js +16 -1
- package/lib/control-evaluation/parent-reconciliation.js +284 -0
- package/lib/control-state/run-state-parser.js +39 -1
- package/lib/interaction-presentation.js +31 -14
- package/lib/proportionality-benchmark/blind-prompt.js +2 -1
- package/lib/proportionality-benchmark/contracts.js +16 -7
- package/lib/proportionality-benchmark/corpus-loader.js +132 -21
- package/lib/proportionality-benchmark/evaluator.js +25 -15
- package/lib/proportionality-benchmark/index.js +1 -0
- package/lib/proportionality-benchmark/live-recorder.js +32 -10
- package/lib/proportionality-benchmark/profiles.js +102 -0
- package/lib/proportionality-benchmark/report.js +10 -1
- package/lib/proportionality-benchmark/source-fingerprint.js +6 -2
- package/package.json +4 -2
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { dirname, relative, resolve, sep } from "node:path";
|
|
4
|
-
import { fail, validateBaseline } from "./contracts.js";
|
|
3
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
4
|
+
import { DELIVERY_PATHS, fail, validateBaseline } from "./contracts.js";
|
|
5
|
+
import { getProfileDefinition, isStagedProfile } from "./profiles.js";
|
|
5
6
|
|
|
6
7
|
function inside(root, candidate) {
|
|
7
8
|
const target = resolve(root, candidate);
|
|
@@ -21,7 +22,7 @@ function existingInside(root, candidate) {
|
|
|
21
22
|
function sha256(path) {
|
|
22
23
|
return createHash("sha256").update(readFileSync(path)).digest("hex");
|
|
23
24
|
}
|
|
24
|
-
const stagedForbidden = /expected_|evidence_ref|classification|threshold|trivial_change|compact_delivery|verified_change|structured_slice|structured_delivery/i;
|
|
25
|
+
const stagedForbidden = /expected_|evidence_ref|classification|threshold|reason_code|target_rationale|grading_value|baseline_(version|path)|trivial_change|compact_delivery|verified_change|structured_slice|structured_delivery/i;
|
|
25
26
|
export function validateStagedBlindScenario(scenario, evidencePack = null, baselineScenario = null) {
|
|
26
27
|
if (stagedForbidden.test(JSON.stringify(scenario))) fail(`staged scenario leakage ${scenario.scenario_id}`, "PROPORTIONALITY_LEAKAGE");
|
|
27
28
|
const quickTaskReferences = JSON.stringify(scenario).match(/quick_task/gi)?.length ?? 0;
|
|
@@ -30,31 +31,140 @@ export function validateStagedBlindScenario(scenario, evidencePack = null, basel
|
|
|
30
31
|
|| scenario.control_state_context !== "A durable UR is approved. Brownfield analysis is complete and the stored mode/slice decision is quick_task."
|
|
31
32
|
|| quickTaskReferences !== 1
|
|
32
33
|
)) fail(`staged scenario path leakage ${scenario.scenario_id}`, "PROPORTIONALITY_LEAKAGE");
|
|
33
|
-
if (evidencePack
|
|
34
|
+
if (evidencePack) {
|
|
35
|
+
const leakageEvidence = JSON.parse(JSON.stringify(evidencePack));
|
|
36
|
+
const escalation = leakageEvidence.bounded_change_facts?.escalation;
|
|
37
|
+
if (escalation) {
|
|
38
|
+
if (!["structured_slice", "structured_delivery"].includes(escalation.target)) fail(`invalid structured escalation target ${scenario.scenario_id}`, "PROPORTIONALITY_LEAKAGE");
|
|
39
|
+
delete escalation.target;
|
|
40
|
+
}
|
|
41
|
+
if (stagedForbidden.test(JSON.stringify(leakageEvidence))) fail(`staged evidence-pack leakage ${scenario.scenario_id}`, "PROPORTIONALITY_LEAKAGE");
|
|
42
|
+
}
|
|
34
43
|
if (baselineScenario && (
|
|
35
44
|
JSON.stringify(scenario).includes(baselineScenario.rationale)
|
|
36
45
|
|| JSON.stringify(evidencePack ?? {}).includes(baselineScenario.rationale)
|
|
37
46
|
)) fail(`staged rationale leakage ${scenario.scenario_id}`, "PROPORTIONALITY_LEAKAGE");
|
|
38
47
|
return scenario;
|
|
39
48
|
}
|
|
49
|
+
function recursiveFiles(root) {
|
|
50
|
+
return readdirSync(root, { withFileTypes: true }).flatMap((entry) => {
|
|
51
|
+
const path = join(root, entry.name);
|
|
52
|
+
return entry.isDirectory() ? recursiveFiles(path) : [path];
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const requiredProtectedV2Files = [
|
|
56
|
+
"evals/proportionality/staged-manifest.json",
|
|
57
|
+
"evals/proportionality/staged-scenarios.json",
|
|
58
|
+
"evals/proportionality/fixtures/staged-catalog.json",
|
|
59
|
+
".agdf/control/artefacts/agdf-staged-proportionality-observation/STAGED_PROPORTIONALITY_BASELINE.json",
|
|
60
|
+
".agdf/control/artefacts/agdf-staged-proportionality-observation/STAGED_PROPORTIONALITY_REPORT.json",
|
|
61
|
+
".agdf/control/artefacts/agdf-staged-proportionality-observation/STAGED_PROPORTIONALITY_REPORT.md",
|
|
62
|
+
".agdf/control/artefacts/agdf-staged-proportionality-observation/QA_REPORT.md",
|
|
63
|
+
".agdf/control/artefacts/agdf-staged-proportionality-observation/OR.md",
|
|
64
|
+
];
|
|
65
|
+
const requiredProtectedV2Root = "evals/proportionality/observations/codex-gpt-5.6-sol-agdf-0.11.4-staged-v2-20260729-r3";
|
|
66
|
+
export function validateHistoryInventory(repoRoot, root, manifest) {
|
|
67
|
+
const inventoryPath = existingInside(root, manifest.history_provenance_path);
|
|
68
|
+
const inventory = JSON.parse(readFileSync(inventoryPath, "utf8"));
|
|
69
|
+
if (inventory.schema_version !== "1" || inventory.profile_id !== manifest.profile_id || inventory.inventory_version !== manifest.history_inventory_version) fail("history inventory version mismatch", "PROPORTIONALITY_HISTORY_DRIFT");
|
|
70
|
+
const declared = Object.keys(inventory.protected_files ?? {}).sort();
|
|
71
|
+
if (requiredProtectedV2Files.some((path) => !declared.includes(path))) fail("protected history inventory omits required staged-v2 evidence", "PROPORTIONALITY_HISTORY_DRIFT");
|
|
72
|
+
if (!Array.isArray(inventory.protected_roots) || inventory.protected_roots.length !== 1 || inventory.protected_roots[0] !== requiredProtectedV2Root) fail("protected history root mismatch", "PROPORTIONALITY_HISTORY_DRIFT");
|
|
73
|
+
if (declared.some((path) => !requiredProtectedV2Files.includes(path) && !path.startsWith(`${requiredProtectedV2Root}/`))) fail("protected history inventory contains an out-of-bound path", "PROPORTIONALITY_HISTORY_DRIFT");
|
|
74
|
+
for (const path of declared) {
|
|
75
|
+
const target = existingInside(repoRoot, path);
|
|
76
|
+
if (sha256(target) !== inventory.protected_files[path]) fail(`protected history drift ${path}`, "PROPORTIONALITY_HISTORY_DRIFT");
|
|
77
|
+
}
|
|
78
|
+
for (const protectedRoot of inventory.protected_roots ?? []) {
|
|
79
|
+
const absolute = existingInside(repoRoot, protectedRoot);
|
|
80
|
+
const actual = recursiveFiles(absolute).map((path) => relative(repoRoot, path).split(sep).join("/")).sort();
|
|
81
|
+
const expected = declared.filter((path) => path === protectedRoot || path.startsWith(`${protectedRoot}/`));
|
|
82
|
+
if (actual.length !== expected.length || actual.some((path, index) => path !== expected[index])) fail(`protected history inventory incomplete ${protectedRoot}`, "PROPORTIONALITY_HISTORY_DRIFT");
|
|
83
|
+
}
|
|
84
|
+
return inventory;
|
|
85
|
+
}
|
|
86
|
+
const verifiedFactGroups = ["ownership_boundary", "prohibited_impacts", "deterministic_controls", "baseline_state", "escalation"];
|
|
87
|
+
const impactFacts = ["product_semantics", "runtime", "policy", "persistence", "architecture", "security", "external_api", "cli_contract", "release", "cross_host"];
|
|
88
|
+
const depthTriggerFamilies = ["behavior_or_policy", "architecture_or_runtime", "persistence_or_security", "external_contract", "release_or_cross_host", "unbounded_coordination"];
|
|
89
|
+
const depthChecks = ["scope_boundary", "owner_map", "affected_surfaces", "validation_path", "rollback_boundary", "coordination_boundary", "uncertainty_register"];
|
|
90
|
+
const semanticDepthTargets = {
|
|
91
|
+
"PB-021": "behavior_or_policy",
|
|
92
|
+
"PB-031": "architecture_or_runtime",
|
|
93
|
+
"PB-033": "persistence_or_security",
|
|
94
|
+
"PB-034": "unbounded_coordination",
|
|
95
|
+
"PB-036": "release_or_cross_host",
|
|
96
|
+
"PB-037": "external_contract",
|
|
97
|
+
};
|
|
98
|
+
export function validateV3Facts(index, fixtures, baseline) {
|
|
99
|
+
for (const caseId of ["PB-008", "PB-010", "PB-011"]) {
|
|
100
|
+
const scenarios = index.scenarios.filter((item) => item.case_id === caseId);
|
|
101
|
+
if (!scenarios.length) fail(`missing targeted semantics ${caseId}`);
|
|
102
|
+
for (const scenario of scenarios) {
|
|
103
|
+
if (caseId === "PB-008" && (!scenario.decision_state_facts || typeof scenario.decision_state_facts.effective_control_state !== "string" || typeof scenario.decision_state_facts.currently_permitted_action !== "string" || typeof scenario.decision_state_facts.mutation_intent !== "string" || scenario.decision_state_facts.unresolved_target !== true)) fail(`incomplete decision-state facts ${scenario.scenario_id}`);
|
|
104
|
+
if (["PB-010", "PB-011"].includes(caseId) && (!scenario.task_semantics?.requested_action || !scenario.task_semantics?.semantic_effect || !scenario.task_semantics?.excluded_effects?.length)) fail(`incomplete task semantics ${scenario.scenario_id}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const caseId of ["PB-016", "PB-017", "PB-020"]) {
|
|
108
|
+
const pack = fixtures.evidence_packs[`EP-${caseId}`]?.bounded_change_facts;
|
|
109
|
+
const missingGroup = verifiedFactGroups.find((key) => !(key in (pack ?? {})));
|
|
110
|
+
if (!pack || missingGroup) fail(`incomplete verified-change facts ${caseId}: missing ${missingGroup ?? "bounded_change_facts"}; restore the declared facts and rerun`);
|
|
111
|
+
if (pack.ownership_boundary.canonical_owner_count !== 1 || pack.ownership_boundary.bounded !== true || !Number.isInteger(pack.ownership_boundary.source_path_count) || pack.ownership_boundary.source_path_count < 1 || !Number.isInteger(pack.ownership_boundary.derived_path_count) || pack.ownership_boundary.derived_path_count < 0) fail(`conflicting ownership-boundary facts ${caseId}; correct the facts and rerun`);
|
|
112
|
+
if (!/^[a-f0-9]{40}$/.test(pack.baseline_state.commit ?? "") || pack.baseline_state.tracked_candidate_paths_clean !== true || pack.baseline_state.untracked_candidate_paths_clean !== true || !Array.isArray(pack.baseline_state.conflicts) || pack.baseline_state.conflicts.length) fail(`conflicting baseline-state facts ${caseId}; correct the facts and rerun`);
|
|
113
|
+
if (pack.deterministic_controls.validation !== true || pack.deterministic_controls.propagation !== true) fail(`conflicting deterministic-control facts ${caseId}; correct the facts and rerun`);
|
|
114
|
+
if (pack.prohibited_impacts.complete !== true || impactFacts.some((key) => pack.prohibited_impacts.impacts?.[key] !== false)) fail(`conflicting prohibited-impact facts ${caseId}; correct the facts and rerun`);
|
|
115
|
+
if (!["structured_slice", "structured_delivery"].includes(pack.escalation.target) || !Array.isArray(pack.escalation.conditions) || !pack.escalation.conditions.length) fail(`conflicting escalation facts ${caseId}; correct the facts and rerun`);
|
|
116
|
+
}
|
|
117
|
+
const structuredCases = baseline.cases.filter((item) => ["structured_slice", "structured_delivery"].includes(item.expected_delivery_path));
|
|
118
|
+
for (const item of structuredCases) {
|
|
119
|
+
const facts = fixtures.evidence_packs[`EP-${item.case_id}`]?.structured_depth_facts;
|
|
120
|
+
if (!facts || facts.depth_policy_version !== 1 || facts.fact_state !== "complete" || !Array.isArray(facts.conflicts) || facts.conflicts.length) fail(`incomplete structured-depth facts ${item.case_id}; correct the facts and rerun`);
|
|
121
|
+
if (depthTriggerFamilies.some((key) => typeof facts.trigger_families?.[key] !== "boolean")) fail(`incomplete depth triggers ${item.case_id}; complete all six trigger families and rerun`);
|
|
122
|
+
if (depthChecks.some((key) => typeof facts.bounded_checks?.[key] !== "string" || !facts.bounded_checks[key])) fail(`incomplete depth checks ${item.case_id}; complete all seven bounded checks and rerun`);
|
|
123
|
+
if (semanticDepthTargets[item.case_id] && (facts.semantic_eval_target !== semanticDepthTargets[item.case_id] || facts.trigger_families[facts.semantic_eval_target] !== true)) fail(`invalid semantic depth target ${item.case_id}`);
|
|
124
|
+
}
|
|
125
|
+
if (new Set(Object.values(semanticDepthTargets)).size !== depthTriggerFamilies.length) fail("semantic depth target coverage mismatch");
|
|
126
|
+
}
|
|
40
127
|
export function loadCorpus(repoRoot, profileId = "legacy-v1") {
|
|
128
|
+
const profile = getProfileDefinition(profileId);
|
|
41
129
|
const root = existingInside(repoRoot, "evals/proportionality");
|
|
42
|
-
if (
|
|
43
|
-
const manifest = JSON.parse(readFileSync(existingInside(
|
|
130
|
+
if (isStagedProfile(profile)) {
|
|
131
|
+
const manifest = JSON.parse(readFileSync(existingInside(repoRoot, profile.manifest_path), "utf8"));
|
|
44
132
|
const index = JSON.parse(readFileSync(existingInside(root, manifest.scenarios_path), "utf8"));
|
|
45
133
|
const fixtures = JSON.parse(readFileSync(existingInside(root, manifest.fixture_path), "utf8"));
|
|
46
134
|
const baselinePath = existingInside(repoRoot, manifest.baseline_path);
|
|
47
135
|
const baseline = JSON.parse(readFileSync(baselinePath, "utf8"));
|
|
48
|
-
|
|
49
|
-
manifest.profile_id
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
136
|
+
const versionMismatch = [
|
|
137
|
+
["manifest.profile_id", manifest.profile_id, profile.profile_id],
|
|
138
|
+
["manifest.schema_version", manifest.schema_version, profile.schema_version],
|
|
139
|
+
["manifest.protocol_version", manifest.protocol_version, profile.protocol_version],
|
|
140
|
+
["index.schema_version", index.schema_version, profile.schema_version],
|
|
141
|
+
["index.profile_id", index.profile_id, profile.profile_id],
|
|
142
|
+
["fixtures.schema_version", fixtures.schema_version, profile.schema_version],
|
|
143
|
+
["fixtures.profile_id", fixtures.profile_id, profile.profile_id],
|
|
144
|
+
["fixtures.fixture_version", fixtures.fixture_version, manifest.fixture_version],
|
|
145
|
+
["baseline.schema_version", baseline.schema_version, profile.schema_version],
|
|
146
|
+
["baseline.baseline_version", baseline.baseline_version, manifest.baseline_version],
|
|
147
|
+
].find(([, actual, expected]) => actual !== expected);
|
|
148
|
+
if (versionMismatch || !manifest.corpus_version || !manifest.fixture_version) fail(`staged profile version mismatch: ${versionMismatch?.[0] ?? "manifest corpus/fixture version"}`);
|
|
149
|
+
if (profile.strict_version_links) {
|
|
150
|
+
const strictMismatch = [
|
|
151
|
+
["index.corpus_version", index.corpus_version, manifest.corpus_version],
|
|
152
|
+
["baseline.profile_id", baseline.profile_id, profile.profile_id],
|
|
153
|
+
["baseline.protocol_version", baseline.protocol_version, profile.protocol_version],
|
|
154
|
+
["manifest.adapter_version", manifest.adapter_version, profile.adapter_version],
|
|
155
|
+
["manifest.runner_version", manifest.runner_version, profile.runner_version],
|
|
156
|
+
["manifest.report_version", manifest.report_version, profile.report_version],
|
|
157
|
+
].find(([, actual, expected]) => actual !== expected);
|
|
158
|
+
if (strictMismatch || !manifest.history_inventory_version) fail(`staged profile version mismatch: ${strictMismatch?.[0] ?? "manifest.history_inventory_version"}`);
|
|
159
|
+
}
|
|
160
|
+
const baselineCaseIds = baseline.cases.map((item) => item.case_id);
|
|
161
|
+
const scenarioIds = index.scenarios.map((item) => item.scenario_id);
|
|
162
|
+
if (baseline.cases.length !== 40 || new Set(baselineCaseIds).size !== 40 || baselineCaseIds.some((id) => !/^PB-\d{3}$/.test(id))) fail("staged case identity mismatch");
|
|
163
|
+
if (!Array.isArray(index.scenario_ids) || index.scenario_ids.length !== 72 || index.scenarios.length !== 72 || new Set(index.scenario_ids).size !== 72 || new Set(scenarioIds).size !== 72 || scenarioIds.some((id) => !index.scenario_ids.includes(id))) fail("staged corpus coverage mismatch");
|
|
164
|
+
const pathSet = new Set(baseline.cases.map((item) => item.expected_delivery_path));
|
|
165
|
+
if (DELIVERY_PATHS.some((path) => !pathSet.has(path)) || [...pathSet].some((path) => !DELIVERY_PATHS.includes(path)) || baseline.cases.filter((item) => item.adversarial).length < 10) fail("staged baseline coverage mismatch");
|
|
57
166
|
const expectedIds = new Set(baseline.scenarios.map((item) => item.scenario_id));
|
|
167
|
+
if (baseline.scenarios.length !== 72 || expectedIds.size !== 72 || baseline.scenarios.some((item) => !baselineCaseIds.includes(item.case_id) || item.scenario_id.split(":")[0] !== item.case_id)) fail("staged scenario baseline mismatch");
|
|
58
168
|
if (index.scenarios.some((item) => !expectedIds.has(item.scenario_id)) || baseline.scenarios.some((item) => !index.scenario_ids.includes(item.scenario_id))) fail("staged scenario baseline mismatch");
|
|
59
169
|
for (const scenario of index.scenarios) {
|
|
60
170
|
if (scenario.evidence_pack_id && !fixtures.evidence_packs[scenario.evidence_pack_id]) fail(`missing evidence pack ${scenario.scenario_id}`);
|
|
@@ -64,18 +174,19 @@ export function loadCorpus(repoRoot, profileId = "legacy-v1") {
|
|
|
64
174
|
baseline.scenarios.find((item) => item.scenario_id === scenario.scenario_id),
|
|
65
175
|
);
|
|
66
176
|
}
|
|
177
|
+
const historyProvenance = profile.history_provenance ? validateHistoryInventory(repoRoot, root, manifest) : undefined;
|
|
178
|
+
if (profile.semantic_fact_validation) validateV3Facts(index, fixtures, baseline);
|
|
67
179
|
const cases = index.scenarios.map((scenario) => ({
|
|
68
180
|
...scenario,
|
|
69
|
-
profile_id:
|
|
181
|
+
profile_id: profile.profile_id,
|
|
70
182
|
corpus_version: manifest.corpus_version,
|
|
71
183
|
fixture_version: manifest.fixture_version,
|
|
72
184
|
allowed_stages: ["ungated_execution", "ur", "brownfield_review", "prd", "sd", "tp", "brownfield_analysis", "cd_tests", "cr", "qa", "uat", "or", "blocked"],
|
|
73
185
|
evidence_pack: scenario.evidence_pack_id ? fixtures.evidence_packs[scenario.evidence_pack_id] : null,
|
|
74
186
|
}));
|
|
75
|
-
return { profile_id:
|
|
187
|
+
return { profile_id: profile.profile_id, profile, manifest, baseline, fixtures, ...(historyProvenance ? { history_provenance: historyProvenance } : {}), cases };
|
|
76
188
|
}
|
|
77
|
-
|
|
78
|
-
const manifest = JSON.parse(readFileSync(existingInside(root, "manifest.json"), "utf8"));
|
|
189
|
+
const manifest = JSON.parse(readFileSync(existingInside(repoRoot, profile.manifest_path), "utf8"));
|
|
79
190
|
const provenance = JSON.parse(readFileSync(existingInside(root, "legacy-v1-provenance.json"), "utf8"));
|
|
80
191
|
const index = JSON.parse(readFileSync(existingInside(root, "cases.json"), "utf8"));
|
|
81
192
|
const fixtures = JSON.parse(readFileSync(existingInside(root, "fixtures/catalog.json"), "utf8"));
|
|
@@ -106,5 +217,5 @@ export function loadCorpus(repoRoot, profileId = "legacy-v1") {
|
|
|
106
217
|
repository_context: fixture.repository_context,
|
|
107
218
|
control_state_context: index.case_contexts?.[case_id] ?? fixture.control_state_context,
|
|
108
219
|
}));
|
|
109
|
-
return { profile_id: "legacy-v1", manifest, baseline, fixtures, provenance, cases };
|
|
220
|
+
return { profile_id: "legacy-v1", profile, manifest, baseline, fixtures, provenance, cases };
|
|
110
221
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DELIVERY_PATHS, PATH_RANK, STAGES, fail, stable } from "./contracts.js";
|
|
2
2
|
import { sourceFingerprint } from "./source-fingerprint.js";
|
|
3
|
-
import { ADAPTER_VERSION
|
|
3
|
+
import { ADAPTER_VERSION } from "./live-recorder.js";
|
|
4
|
+
import { getProfileDefinition, isStagedProfile } from "./profiles.js";
|
|
4
5
|
|
|
5
6
|
export function classifyObservation(expected, observation) {
|
|
6
7
|
if (observation.ambiguous || observation.observed_delivery_path === null) return "ambiguous";
|
|
@@ -50,22 +51,25 @@ function stagedCoverageResult(expected, rows, reason) {
|
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
53
|
function evaluateStagedSeries({ repoRoot, corpus, observations, minimumRepeats }) {
|
|
53
|
-
const
|
|
54
|
+
const profile = getProfileDefinition(corpus.profile_id);
|
|
55
|
+
const provenanceKeys = ["series_id", "profile_id", "protocol_version", "corpus_version", "fixture_version", "surface", "runtime_version", "model", "agdf_version", "baseline_version", "adapter_version", ...(profile.evidence_kind_provenance ? ["evidence_kind"] : []), ...(profile.series_profile_metadata ? ["runner_version"] : [])];
|
|
54
56
|
const first = observations[0] ?? {};
|
|
55
57
|
const observationIds = new Set();
|
|
56
58
|
const byScenario = new Map(corpus.cases.map((item) => [item.scenario_id, []]));
|
|
57
59
|
for (const observation of observations) {
|
|
58
60
|
if (!byScenario.has(observation.scenario_id) || observation.case_id !== observation.scenario_id.split(":")[0]) fail(`unknown staged observation ${observation.scenario_id ?? "unknown"}`);
|
|
59
|
-
if (observation.schema_version !==
|
|
61
|
+
if (observation.schema_version !== profile.schema_version || !profile.evidence_kinds.includes(observation.evidence_kind) || !Number.isInteger(observation.repeat) || observation.repeat < 1) fail(`invalid observation ${observation.observation_id ?? "unknown"}`);
|
|
60
62
|
if (!observation.observation_id || observationIds.has(observation.observation_id)) fail(`duplicate observation ${observation.observation_id ?? "unknown"}`);
|
|
61
63
|
if (observation.execution_status !== "completed" || observation.redaction_status !== "pass" || observation.mutation_status !== "pass") fail(`unsafe observation status ${observation.observation_id}`);
|
|
62
64
|
if (!Number.isFinite(Date.parse(observation.recorded_at))) fail(`invalid observation timestamp ${observation.observation_id}`);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
if (
|
|
65
|
+
const versionDrift = [
|
|
66
|
+
["baseline_version", corpus.baseline.baseline_version],
|
|
67
|
+
["corpus_version", corpus.manifest.corpus_version],
|
|
68
|
+
["fixture_version", corpus.manifest.fixture_version],
|
|
69
|
+
].find(([key, expected]) => observation[key] !== expected);
|
|
70
|
+
if (versionDrift) fail(`baseline provenance drift (${versionDrift[0]}) at ${observation.observation_id}`);
|
|
71
|
+
const provenanceDrift = provenanceKeys.find((key) => observation[key] !== first[key]);
|
|
72
|
+
if (provenanceDrift) fail(`series provenance drift (${provenanceDrift}) at ${observation.observation_id}`);
|
|
69
73
|
observationIds.add(observation.observation_id);
|
|
70
74
|
byScenario.get(observation.scenario_id).push(observation);
|
|
71
75
|
}
|
|
@@ -74,7 +78,7 @@ function evaluateStagedSeries({ repoRoot, corpus, observations, minimumRepeats }
|
|
|
74
78
|
const rows = byScenario.get(expected.scenario_id).sort((a, b) => a.repeat - b.repeat);
|
|
75
79
|
const repeats = new Set(rows.map((item) => item.repeat));
|
|
76
80
|
if (rows.length < minimumRepeats || repeats.size !== rows.length) return stagedCoverageResult(expected, rows, "coverage");
|
|
77
|
-
const fingerprint = sourceFingerprint(repoRoot, blind, corpus.fixtures,
|
|
81
|
+
const fingerprint = sourceFingerprint(repoRoot, blind, corpus.fixtures, profile.adapter_version);
|
|
78
82
|
const stale = rows.some((item) => item.source_fingerprint !== fingerprint);
|
|
79
83
|
const invalidAxes = rows.some((item) => (
|
|
80
84
|
expected.stage_required !== (item.stage_evaluability === "evaluated")
|
|
@@ -130,9 +134,9 @@ function evaluateStagedSeries({ repoRoot, corpus, observations, minimumRepeats }
|
|
|
130
134
|
...(ambiguous.length ? ["ambiguous_or_incomplete"] : []),
|
|
131
135
|
];
|
|
132
136
|
return stable({
|
|
133
|
-
schema_version:
|
|
134
|
-
profile_id:
|
|
135
|
-
protocol_version:
|
|
137
|
+
schema_version: profile.schema_version,
|
|
138
|
+
profile_id: profile.profile_id,
|
|
139
|
+
protocol_version: profile.protocol_version,
|
|
136
140
|
evidence_boundary: corpus.manifest.evidence_boundary,
|
|
137
141
|
baseline_version: corpus.baseline.baseline_version,
|
|
138
142
|
corpus_version: corpus.manifest.corpus_version,
|
|
@@ -142,7 +146,13 @@ function evaluateStagedSeries({ repoRoot, corpus, observations, minimumRepeats }
|
|
|
142
146
|
agdf_version: first.agdf_version ?? null,
|
|
143
147
|
adapter_version: first.adapter_version ?? null,
|
|
144
148
|
runtime_version: first.runtime_version ?? null,
|
|
145
|
-
runner_version:
|
|
149
|
+
runner_version: profile.runner_version,
|
|
150
|
+
...(profile.repository_replay_non_claim ? {
|
|
151
|
+
evidence_class: first.evidence_kind ?? "none",
|
|
152
|
+
report_version: profile.report_version,
|
|
153
|
+
authenticated_live_host_evidence: false,
|
|
154
|
+
live_host_non_claim: "No authenticated staged-v3 live-host series was executed or accepted by this repository replay.",
|
|
155
|
+
} : {}),
|
|
146
156
|
freshness_status: scenarios.some((item) => item.blocking_reasons.includes("stale")) ? "stale" : "fresh",
|
|
147
157
|
minimum_repeats: minimumRepeats,
|
|
148
158
|
valid_observations: observations.length,
|
|
@@ -164,7 +174,7 @@ function evaluateStagedSeries({ repoRoot, corpus, observations, minimumRepeats }
|
|
|
164
174
|
}
|
|
165
175
|
export function evaluateSeries({ repoRoot, corpus, observations, minimumRepeats = 3 }) {
|
|
166
176
|
if (!Number.isInteger(minimumRepeats) || minimumRepeats < 3) fail("minimum repeats must be at least 3");
|
|
167
|
-
if (corpus.profile_id
|
|
177
|
+
if (isStagedProfile(getProfileDefinition(corpus.profile_id))) return evaluateStagedSeries({ repoRoot, corpus, observations, minimumRepeats });
|
|
168
178
|
const provenanceKeys = ["series_id", "surface", "runtime_version", "model", "agdf_version", "baseline_version", "adapter_version"];
|
|
169
179
|
const first = observations[0] ?? {};
|
|
170
180
|
const observationIds = new Set();
|
|
@@ -5,11 +5,31 @@ import { dirname, join } from "node:path";
|
|
|
5
5
|
import { executeStructuredAgent } from "../live-agent/read-only-structured.js";
|
|
6
6
|
import { changedPaths, snapshotWorkspace } from "../skill-evals/workspace.js";
|
|
7
7
|
import { buildBlindPrompt } from "./blind-prompt.js";
|
|
8
|
-
import { normalizeAgentOutput, normalizeStagedAgentOutput, OBSERVATION_SCHEMA,
|
|
8
|
+
import { normalizeAgentOutput, normalizeStagedAgentOutput, OBSERVATION_SCHEMA, fail, stagedSchemaForVersion } from "./contracts.js";
|
|
9
|
+
import { getProfileDefinition, isStagedProfile } from "./profiles.js";
|
|
9
10
|
import { behaviorSourceText, sourceFingerprint } from "./source-fingerprint.js";
|
|
10
11
|
|
|
11
|
-
export const ADAPTER_VERSION = "
|
|
12
|
-
export const STAGED_ADAPTER_VERSION = "
|
|
12
|
+
export const ADAPTER_VERSION = getProfileDefinition("legacy-v1").adapter_version;
|
|
13
|
+
export const STAGED_ADAPTER_VERSION = getProfileDefinition("staged-v2").adapter_version;
|
|
14
|
+
export const STAGED_V3_ADAPTER_VERSION = getProfileDefinition("staged-v3").adapter_version;
|
|
15
|
+
export function isRetryableObservationError(error) {
|
|
16
|
+
return error?.code === "GENERATOR_TIMEOUT";
|
|
17
|
+
}
|
|
18
|
+
export function observationAttemptFailure(error, attemptCount, attemptLimit) {
|
|
19
|
+
const messages = {
|
|
20
|
+
GENERATOR_TIMEOUT: "read-only process timed out",
|
|
21
|
+
PROPORTIONALITY_OUTPUT_INVALID: "agent output failed the structured contract",
|
|
22
|
+
PROPORTIONALITY_REDACTION_FAILED: "agent output failed redaction",
|
|
23
|
+
PROPORTIONALITY_MUTATION: "agent mutated the disposable fixture",
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
status: "invalid",
|
|
27
|
+
code: error?.code ?? "EXECUTION_ERROR",
|
|
28
|
+
message: messages[error?.code] ?? "agent execution failed",
|
|
29
|
+
retryable: isRetryableObservationError(error),
|
|
30
|
+
remaining_attempt_budget: Math.max(0, attemptLimit - attemptCount),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
13
33
|
function runtimeVersion(surface) {
|
|
14
34
|
try { return execFileSync(surface, ["--version"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim(); }
|
|
15
35
|
catch { return `${surface} version unavailable`; }
|
|
@@ -40,8 +60,9 @@ export async function recordObservation({
|
|
|
40
60
|
}) {
|
|
41
61
|
if (!/^[a-z0-9][a-z0-9._-]{2,79}$/i.test(seriesId) || !Number.isInteger(repeat) || repeat < 1) fail("invalid series or repeat");
|
|
42
62
|
if (!surface || !model || !agdfVersion || !baselineVersion) fail("surface, model, AGDF version and baseline version are required");
|
|
43
|
-
const
|
|
44
|
-
const
|
|
63
|
+
const profile = getProfileDefinition(testCase.profile_id ?? "legacy-v1");
|
|
64
|
+
const staged = isStagedProfile(profile);
|
|
65
|
+
const adapterVersion = profile.adapter_version;
|
|
45
66
|
const fingerprint = sourceFingerprint(repoRoot, testCase, fixture, adapterVersion);
|
|
46
67
|
const fixtureRoot = mkdtempSync(join(tmpdir(), "agdf-proportionality-"));
|
|
47
68
|
let output;
|
|
@@ -55,7 +76,7 @@ export async function recordObservation({
|
|
|
55
76
|
const before = snapshotWorkspace(fixtureRoot);
|
|
56
77
|
try {
|
|
57
78
|
output = await execute({
|
|
58
|
-
surface, cwd: fixtureRoot, model, timeoutMs, outputSchema: staged ?
|
|
79
|
+
surface, cwd: fixtureRoot, model, timeoutMs, outputSchema: staged ? stagedSchemaForVersion(profile.schema_version) : OBSERVATION_SCHEMA,
|
|
59
80
|
prompt: buildBlindPrompt(testCase, behaviorSourceText(repoRoot)),
|
|
60
81
|
});
|
|
61
82
|
} catch (error) { executionError = error; }
|
|
@@ -63,18 +84,19 @@ export async function recordObservation({
|
|
|
63
84
|
const mutations = changedPaths(before, after);
|
|
64
85
|
if (mutations.length) fail(`agent mutated fixture: ${mutations.join(", ")}`, "PROPORTIONALITY_MUTATION");
|
|
65
86
|
if (executionError) throw executionError;
|
|
66
|
-
const normalized = staged ? normalizeStagedAgentOutput(output, testCase.requested_axes) : normalizeAgentOutput(output);
|
|
87
|
+
const normalized = staged ? normalizeStagedAgentOutput(output, testCase.requested_axes, profile.schema_version) : normalizeAgentOutput(output);
|
|
67
88
|
const observation = {
|
|
68
|
-
schema_version:
|
|
89
|
+
schema_version: profile.schema_version,
|
|
69
90
|
observation_id: `${seriesId}:${staged ? testCase.scenario_id : testCase.case_id}:${repeat}`,
|
|
70
91
|
case_id: testCase.case_id,
|
|
71
92
|
...(staged ? {
|
|
72
|
-
profile_id:
|
|
73
|
-
protocol_version:
|
|
93
|
+
profile_id: profile.profile_id,
|
|
94
|
+
protocol_version: profile.protocol_version,
|
|
74
95
|
corpus_version: testCase.corpus_version,
|
|
75
96
|
fixture_version: testCase.fixture_version,
|
|
76
97
|
scenario_id: testCase.scenario_id,
|
|
77
98
|
lifecycle_stage: testCase.lifecycle_stage,
|
|
99
|
+
...(profile.series_profile_metadata ? { runner_version: profile.runner_version } : {}),
|
|
78
100
|
} : {}),
|
|
79
101
|
series_id: seriesId,
|
|
80
102
|
repeat,
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const definitions = {
|
|
2
|
+
"legacy-v1": {
|
|
3
|
+
profile_id: "legacy-v1",
|
|
4
|
+
family: "legacy",
|
|
5
|
+
manifest_path: "evals/proportionality/manifest.json",
|
|
6
|
+
schema_version: "1",
|
|
7
|
+
protocol_version: "1",
|
|
8
|
+
adapter_version: "1.1.0",
|
|
9
|
+
runner_version: "1.0.0",
|
|
10
|
+
report_version: "1.0.0",
|
|
11
|
+
observation_key: "case_id",
|
|
12
|
+
fixture_strategy: "catalog_fixture",
|
|
13
|
+
evidence_kinds: ["live_agent_observation"],
|
|
14
|
+
evidence_kind_provenance: false,
|
|
15
|
+
history_provenance: false,
|
|
16
|
+
semantic_fact_validation: false,
|
|
17
|
+
fingerprint_profile_metadata: false,
|
|
18
|
+
repository_replay_non_claim: false,
|
|
19
|
+
strict_version_links: false,
|
|
20
|
+
series_profile_metadata: false,
|
|
21
|
+
},
|
|
22
|
+
"staged-v2": {
|
|
23
|
+
profile_id: "staged-v2",
|
|
24
|
+
family: "staged",
|
|
25
|
+
manifest_path: "evals/proportionality/staged-manifest.json",
|
|
26
|
+
schema_version: "2",
|
|
27
|
+
protocol_version: "2",
|
|
28
|
+
adapter_version: "2.1.0",
|
|
29
|
+
runner_version: "2.0.0",
|
|
30
|
+
report_version: "2.0.0",
|
|
31
|
+
observation_key: "scenario_id",
|
|
32
|
+
fixture_strategy: "staged_catalog",
|
|
33
|
+
evidence_kinds: ["live_agent_observation"],
|
|
34
|
+
evidence_kind_provenance: false,
|
|
35
|
+
history_provenance: false,
|
|
36
|
+
semantic_fact_validation: false,
|
|
37
|
+
fingerprint_profile_metadata: false,
|
|
38
|
+
repository_replay_non_claim: false,
|
|
39
|
+
strict_version_links: false,
|
|
40
|
+
series_profile_metadata: false,
|
|
41
|
+
},
|
|
42
|
+
"staged-v3": {
|
|
43
|
+
profile_id: "staged-v3",
|
|
44
|
+
family: "staged",
|
|
45
|
+
manifest_path: "evals/proportionality/staged-v3-manifest.json",
|
|
46
|
+
schema_version: "3",
|
|
47
|
+
protocol_version: "3",
|
|
48
|
+
adapter_version: "3.0.0",
|
|
49
|
+
runner_version: "3.0.0",
|
|
50
|
+
report_version: "3.0.0",
|
|
51
|
+
observation_key: "scenario_id",
|
|
52
|
+
fixture_strategy: "staged_catalog",
|
|
53
|
+
evidence_kinds: ["synthetic_replay", "live_agent_observation"],
|
|
54
|
+
evidence_kind_provenance: true,
|
|
55
|
+
history_provenance: true,
|
|
56
|
+
semantic_fact_validation: true,
|
|
57
|
+
fingerprint_profile_metadata: true,
|
|
58
|
+
repository_replay_non_claim: true,
|
|
59
|
+
strict_version_links: true,
|
|
60
|
+
series_profile_metadata: true,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
function deepFreeze(value) {
|
|
65
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
66
|
+
Object.freeze(value);
|
|
67
|
+
for (const item of Object.values(value)) deepFreeze(item);
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const PROPORTIONALITY_PROFILES = deepFreeze(definitions);
|
|
73
|
+
export const SUPPORTED_PROFILE_IDS = Object.freeze(Object.keys(PROPORTIONALITY_PROFILES));
|
|
74
|
+
|
|
75
|
+
export function getProfileDefinition(profileId) {
|
|
76
|
+
const definition = PROPORTIONALITY_PROFILES[profileId];
|
|
77
|
+
if (!definition) throw Object.assign(new Error(`unknown proportionality profile ${profileId}`), { code: "PROPORTIONALITY_PROFILE_UNKNOWN" });
|
|
78
|
+
return definition;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function isStagedProfile(profileOrId) {
|
|
82
|
+
const definition = typeof profileOrId === "string" ? getProfileDefinition(profileOrId) : profileOrId;
|
|
83
|
+
return definition.family === "staged";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function observationKey(profileOrId, testCase) {
|
|
87
|
+
const definition = typeof profileOrId === "string" ? getProfileDefinition(profileOrId) : profileOrId;
|
|
88
|
+
const value = testCase[definition.observation_key];
|
|
89
|
+
if (!value) throw new Error(`missing ${definition.observation_key} for ${definition.profile_id}`);
|
|
90
|
+
return definition.observation_key === "scenario_id" ? value.replaceAll(":", "__") : value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function fixtureForProfile(profileOrId, corpus) {
|
|
94
|
+
const definition = typeof profileOrId === "string" ? getProfileDefinition(profileOrId) : profileOrId;
|
|
95
|
+
return definition.fixture_strategy === "staged_catalog"
|
|
96
|
+
? corpus.fixtures
|
|
97
|
+
: corpus.fixtures.fixtures[corpus.manifest.fixture_id];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function profileUsage() {
|
|
101
|
+
return SUPPORTED_PROFILE_IDS.join("|");
|
|
102
|
+
}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
import { getProfileDefinition, isStagedProfile } from "./profiles.js";
|
|
2
|
+
|
|
1
3
|
export function renderMarkdown(report) {
|
|
2
|
-
if (report.profile_id
|
|
4
|
+
if (report.profile_id && isStagedProfile(getProfileDefinition(report.profile_id))) {
|
|
3
5
|
const lines = [
|
|
4
6
|
"# AGDF Staged Proportionality Observation",
|
|
5
7
|
"",
|
|
6
8
|
`- Status: \`${report.status}\``,
|
|
7
9
|
`- Evidenzgrenze: ${report.evidence_boundary}`,
|
|
8
10
|
`- Profil/Protokoll: \`${report.profile_id}\` / \`${report.protocol_version}\``,
|
|
11
|
+
...(report.evidence_class ? [
|
|
12
|
+
`- Corpus/Baseline: \`${report.corpus_version}\` / \`${report.baseline_version}\``,
|
|
13
|
+
`- Report-Version: \`${report.report_version}\``,
|
|
14
|
+
`- Evidenzklasse: \`${report.evidence_class}\``,
|
|
15
|
+
`- Authentifizierte Live-Host-Evidenz: \`${report.authenticated_live_host_evidence}\``,
|
|
16
|
+
`- Live-Host-Nichtbehauptung: ${report.live_host_non_claim}`,
|
|
17
|
+
] : []),
|
|
9
18
|
`- Serie: \`${report.series_id ?? "none"}\``,
|
|
10
19
|
`- Surface/Modell: \`${report.surface ?? "none"}\` / \`${report.model ?? "none"}\``,
|
|
11
20
|
`- Runtime/AGDF/Adapter/Runner: \`${report.runtime_version ?? "none"}\` / \`${report.agdf_version ?? "none"}\` / \`${report.adapter_version ?? "none"}\` / \`${report.runner_version}\``,
|
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { stable } from "./contracts.js";
|
|
5
|
+
import { getProfileDefinition } from "./profiles.js";
|
|
5
6
|
|
|
6
7
|
export const BEHAVIOR_SOURCES = Object.freeze([
|
|
7
8
|
"plugin/meta/agdf-agent-router.md",
|
|
@@ -24,7 +25,10 @@ export function behaviorSourceText(repoRoot) {
|
|
|
24
25
|
}
|
|
25
26
|
export function sourceFingerprint(repoRoot, testCase, fixture, adapterVersion) {
|
|
26
27
|
const hash = createHash("sha256");
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const selectedProfile = testCase.profile_id ? getProfileDefinition(testCase.profile_id) : null;
|
|
29
|
+
const profile = selectedProfile?.fingerprint_profile_metadata ? selectedProfile : null;
|
|
30
|
+
hash.update(JSON.stringify(stable(profile ? { testCase, fixture, adapterVersion, profile } : { testCase, fixture, adapterVersion })));
|
|
31
|
+
const sources = profile ? [...BEHAVIOR_SOURCES, ...IMPLEMENTATION_SOURCES, "create-agdf/lib/proportionality-benchmark/profiles.js"] : [...BEHAVIOR_SOURCES, ...IMPLEMENTATION_SOURCES];
|
|
32
|
+
for (const path of sources) hash.update(path).update(readFileSync(join(repoRoot, path)));
|
|
29
33
|
return hash.digest("hex");
|
|
30
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-agdf",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.3",
|
|
4
4
|
"description": "Bootstrap AGDF repository-local plugin files, Copilot/OpenCode instructions, skills, control files and machine-readable checks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -36,10 +36,12 @@
|
|
|
36
36
|
"test:package-build": "node ./scripts/package-build-test.js",
|
|
37
37
|
"test:lifecycle": "node ./scripts/lifecycle-test.js",
|
|
38
38
|
"test:control-state": "node ./scripts/control-state-test.js",
|
|
39
|
+
"test:parent-reconciliation": "node ./scripts/parent-reconciliation-test.js",
|
|
39
40
|
"test:interaction-presentation": "node ./scripts/interaction-presentation-test.js",
|
|
40
41
|
"test:verified-change": "node ./scripts/verified-change-test.js",
|
|
41
42
|
"test:runtime-integrity-layout": "node ./scripts/runtime-integrity-layout-test.js",
|
|
42
43
|
"test:runtime-integrity-negative": "node ./scripts/runtime-integrity-negative-test.js",
|
|
44
|
+
"test:agent-skills-conformance": "node ./scripts/agent-skills-conformance-test.js",
|
|
43
45
|
"test:skill-evals": "node ./scripts/skill-evals-test.js",
|
|
44
46
|
"eval:skills": "node ./scripts/run-skill-evals.js",
|
|
45
47
|
"eval:skills:record": "node ./scripts/record-skill-evals.js",
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
"test:proportionality": "node ./scripts/proportionality-benchmark-test.js",
|
|
49
51
|
"test:release-bootstrap": "node ./scripts/release-bootstrap-smoke-test.js",
|
|
50
52
|
"test:routing": "npm run sync-package-assets && node ./scripts/test-routing.js",
|
|
51
|
-
"smoke-test": "npm run release:prepare && npm run test:cli-modularization && npm run test:local-validator && npm run test:local-marketplace && npm run test:package-build && npm run test:package-contents && npm run test:lifecycle && npm run test:control-state && npm run test:interaction-presentation && npm run test:verified-change && npm run test:runtime-integrity-layout && npm run test:runtime-integrity-negative && npm run test:skill-evals && npm run eval:skills && npm run test:proportionality && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && npm run test:opencode-hardening && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
|
|
53
|
+
"smoke-test": "npm run release:prepare && npm run test:cli-modularization && npm run test:local-validator && npm run test:local-marketplace && npm run test:package-build && npm run test:package-contents && npm run test:lifecycle && npm run test:control-state && npm run test:parent-reconciliation && npm run test:interaction-presentation && npm run test:verified-change && npm run test:runtime-integrity-layout && npm run test:runtime-integrity-negative && npm run test:agent-skills-conformance && npm run test:skill-evals && npm run eval:skills && npm run test:proportionality && npm run test:delivery-path-search && npm run test:delivery-path-search-unit && npm run test:delivery-path-search-generator && npm run test:opencode-hardening && node ./scripts/smoke-test.js && node ./scripts/test-routing.js",
|
|
52
54
|
"prepack": "npm run release:prepare"
|
|
53
55
|
},
|
|
54
56
|
"keywords": [
|