@veewo/gitnexus 1.4.11-rc.2 → 1.5.0-rc
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/benchmark/u2-e2e/hydration-policy-repeatability-runner.d.ts +55 -0
- package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.js +190 -0
- package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.test.js +13 -0
- package/dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.d.ts +22 -0
- package/dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.js +100 -0
- package/dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.test.d.ts +1 -0
- package/dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.test.js +13 -0
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.d.ts +27 -0
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.js +118 -0
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.test.d.ts +1 -0
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.test.js +16 -0
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.d.ts +60 -0
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.js +331 -0
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.d.ts +1 -0
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.js +42 -0
- package/dist/benchmark/u2-e2e/reload-v1-acceptance-runner.js +4 -4
- package/dist/benchmark/unity-lazy-context-sampler.d.ts +6 -0
- package/dist/benchmark/unity-lazy-context-sampler.js +49 -13
- package/dist/benchmark/unity-lazy-context-sampler.test.js +4 -0
- package/dist/cli/ai-context.js +6 -1
- package/dist/cli/eval-server.js +0 -3
- package/dist/cli/index.js +8 -0
- package/dist/cli/mcp.js +0 -3
- package/dist/cli/rule-lab.d.ts +42 -0
- package/dist/cli/rule-lab.js +157 -0
- package/dist/cli/rule-lab.test.d.ts +1 -0
- package/dist/cli/rule-lab.test.js +11 -0
- package/dist/cli/tool.d.ts +7 -1
- package/dist/cli/tool.js +6 -0
- package/dist/core/config/unity-config.d.ts +20 -0
- package/dist/core/config/unity-config.js +46 -0
- package/dist/core/graph/types.d.ts +1 -1
- package/dist/core/ingestion/pipeline.js +38 -13
- package/dist/core/ingestion/unity-lifecycle-synthetic-calls.d.ts +0 -2
- package/dist/core/ingestion/unity-lifecycle-synthetic-calls.js +26 -213
- package/dist/core/ingestion/unity-lifecycle-synthetic-calls.test.js +1 -1
- package/dist/core/ingestion/unity-resource-processor.js +87 -22
- package/dist/core/ingestion/unity-resource-processor.test.js +67 -2
- package/dist/core/ingestion/unity-runtime-binding-rules.d.ts +11 -0
- package/dist/core/ingestion/unity-runtime-binding-rules.js +179 -0
- package/dist/core/unity/options.d.ts +4 -0
- package/dist/core/unity/options.js +18 -0
- package/dist/core/unity/options.test.js +11 -1
- package/dist/core/unity/resolver.js +11 -1
- package/dist/core/unity/resolver.test.js +62 -0
- package/dist/core/unity/yaml-object-graph.js +1 -1
- package/dist/core/unity/yaml-object-graph.test.js +16 -0
- package/dist/mcp/local/derived-process-reader.d.ts +2 -0
- package/dist/mcp/local/derived-process-reader.js +15 -0
- package/dist/mcp/local/local-backend.d.ts +56 -0
- package/dist/mcp/local/local-backend.js +1003 -53
- package/dist/mcp/local/local-backend.unity-merge.test.js +1 -1
- package/dist/mcp/local/process-confidence.js +1 -1
- package/dist/mcp/local/process-evidence.d.ts +1 -0
- package/dist/mcp/local/process-evidence.js +22 -0
- package/dist/mcp/local/process-evidence.test.js +11 -1
- package/dist/mcp/local/process-ref.d.ts +24 -0
- package/dist/mcp/local/process-ref.js +33 -0
- package/dist/mcp/local/process-ref.test.d.ts +1 -0
- package/dist/mcp/local/process-ref.test.js +24 -0
- package/dist/mcp/local/runtime-chain-verify.d.ts +15 -1
- package/dist/mcp/local/runtime-chain-verify.js +191 -187
- package/dist/mcp/local/runtime-chain-verify.test.js +546 -19
- package/dist/mcp/local/runtime-claim-rule-registry.d.ts +63 -0
- package/dist/mcp/local/runtime-claim-rule-registry.js +308 -0
- package/dist/mcp/local/runtime-claim-rule-registry.test.d.ts +1 -0
- package/dist/mcp/local/runtime-claim-rule-registry.test.js +215 -0
- package/dist/mcp/local/runtime-claim.d.ts +38 -0
- package/dist/mcp/local/runtime-claim.js +54 -0
- package/dist/mcp/local/runtime-claim.test.d.ts +1 -0
- package/dist/mcp/local/runtime-claim.test.js +27 -0
- package/dist/mcp/local/unity-enrichment.d.ts +1 -0
- package/dist/mcp/local/unity-enrichment.js +1 -1
- package/dist/mcp/local/unity-evidence-view.d.ts +26 -0
- package/dist/mcp/local/unity-evidence-view.js +96 -0
- package/dist/mcp/local/unity-evidence-view.test.d.ts +1 -0
- package/dist/mcp/local/unity-evidence-view.test.js +39 -0
- package/dist/mcp/local/unity-lazy-hydrator.d.ts +2 -2
- package/dist/mcp/local/unity-lazy-hydrator.js +3 -3
- package/dist/mcp/local/unity-lazy-hydrator.test.js +4 -4
- package/dist/mcp/local/unity-parity-cache.js +2 -6
- package/dist/mcp/local/unity-parity-seed-loader.d.ts +1 -0
- package/dist/mcp/local/unity-parity-seed-loader.js +10 -16
- package/dist/mcp/local/unity-parity-seed-loader.test.js +3 -12
- package/dist/mcp/local/unity-runtime-hydration.d.ts +3 -2
- package/dist/mcp/local/unity-runtime-hydration.js +13 -16
- package/dist/mcp/local/unity-runtime-hydration.test.js +15 -1
- package/dist/mcp/resources.js +13 -0
- package/dist/mcp/tools.js +166 -13
- package/dist/rule-lab/analyze.d.ts +12 -0
- package/dist/rule-lab/analyze.js +90 -0
- package/dist/rule-lab/analyze.test.d.ts +1 -0
- package/dist/rule-lab/analyze.test.js +28 -0
- package/dist/rule-lab/compile.d.ts +5 -0
- package/dist/rule-lab/compile.js +51 -0
- package/dist/rule-lab/compiled-bundles.d.ts +30 -0
- package/dist/rule-lab/compiled-bundles.js +36 -0
- package/dist/rule-lab/curate.d.ts +32 -0
- package/dist/rule-lab/curate.js +134 -0
- package/dist/rule-lab/curate.test.d.ts +1 -0
- package/dist/rule-lab/curate.test.js +72 -0
- package/dist/rule-lab/discover.d.ts +13 -0
- package/dist/rule-lab/discover.js +74 -0
- package/dist/rule-lab/discover.test.d.ts +1 -0
- package/dist/rule-lab/discover.test.js +42 -0
- package/dist/rule-lab/paths.d.ts +21 -0
- package/dist/rule-lab/paths.js +37 -0
- package/dist/rule-lab/paths.test.d.ts +1 -0
- package/dist/rule-lab/paths.test.js +46 -0
- package/dist/rule-lab/promote.d.ts +26 -0
- package/dist/rule-lab/promote.js +314 -0
- package/dist/rule-lab/promote.test.d.ts +1 -0
- package/dist/rule-lab/promote.test.js +164 -0
- package/dist/rule-lab/regress.d.ts +60 -0
- package/dist/rule-lab/regress.js +122 -0
- package/dist/rule-lab/regress.test.d.ts +1 -0
- package/dist/rule-lab/regress.test.js +68 -0
- package/dist/rule-lab/review-pack.d.ts +31 -0
- package/dist/rule-lab/review-pack.js +125 -0
- package/dist/rule-lab/review-pack.test.d.ts +1 -0
- package/dist/rule-lab/review-pack.test.js +49 -0
- package/dist/rule-lab/types.d.ts +99 -0
- package/dist/rule-lab/types.js +1 -0
- package/package.json +1 -1
- package/skills/_shared/unity-hydration-contract.md +11 -0
- package/skills/_shared/unity-ui-trace-contract.md +33 -0
- package/skills/gitnexus-cli.md +11 -25
- package/skills/gitnexus-guide.md +2 -0
- package/skills/gitnexus-unity-rule-gen.md +318 -0
- package/dist/core/ingestion/unity-lifecycle-config.d.ts +0 -5
- package/dist/core/ingestion/unity-lifecycle-config.js +0 -25
- package/dist/mcp/local/unity-lazy-config.d.ts +0 -6
- package/dist/mcp/local/unity-lazy-config.js +0 -7
- package/dist/mcp/local/unity-lazy-config.test.js +0 -9
- package/dist/mcp/local/unity-process-confidence-config.d.ts +0 -1
- package/dist/mcp/local/unity-process-confidence-config.js +0 -4
- package/dist/mcp/local/unity-runtime-chain-verify-config.d.ts +0 -1
- package/dist/mcp/local/unity-runtime-chain-verify-config.js +0 -10
- /package/dist/{mcp/local/unity-lazy-config.test.d.ts → benchmark/u2-e2e/hydration-policy-repeatability-runner.test.d.ts} +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
type PolicyName = 'fast' | 'balanced' | 'strict';
|
|
2
|
+
interface PolicyModeObservation {
|
|
3
|
+
requestedMode?: string;
|
|
4
|
+
effectiveMode?: string;
|
|
5
|
+
reason?: string;
|
|
6
|
+
needsParityRetry?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface HydrationPolicyRepeatabilityReport {
|
|
9
|
+
generatedAt: string;
|
|
10
|
+
repoAlias: string;
|
|
11
|
+
repeatability: Record<PolicyName, {
|
|
12
|
+
consistent: boolean;
|
|
13
|
+
runCount: number;
|
|
14
|
+
mismatchCount: number;
|
|
15
|
+
}>;
|
|
16
|
+
policy_mode_matrix: Record<PolicyName, {
|
|
17
|
+
compact: PolicyModeObservation;
|
|
18
|
+
parity: PolicyModeObservation;
|
|
19
|
+
}>;
|
|
20
|
+
policy_mapping: {
|
|
21
|
+
fast: {
|
|
22
|
+
requested: string;
|
|
23
|
+
effective: string;
|
|
24
|
+
reason?: string;
|
|
25
|
+
};
|
|
26
|
+
balanced: {
|
|
27
|
+
compact_requested: string;
|
|
28
|
+
parity_requested: string;
|
|
29
|
+
escalation?: string;
|
|
30
|
+
};
|
|
31
|
+
strict: {
|
|
32
|
+
requested: string;
|
|
33
|
+
effective: string;
|
|
34
|
+
reason?: string;
|
|
35
|
+
downgradeOnFallback: 'verified_partial/verified_segment';
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
missing_evidence_contract: {
|
|
39
|
+
requiresArray: boolean;
|
|
40
|
+
populatedWhenIncomplete: boolean;
|
|
41
|
+
};
|
|
42
|
+
contractCompatibility: {
|
|
43
|
+
needsParityRetryRetained: boolean;
|
|
44
|
+
};
|
|
45
|
+
warmup_cache_state: {
|
|
46
|
+
parityWarmupEnabled: boolean;
|
|
47
|
+
note: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export declare function buildHydrationPolicyRepeatabilityReport(input: {
|
|
51
|
+
repoAlias: string;
|
|
52
|
+
runCount?: number;
|
|
53
|
+
}): Promise<HydrationPolicyRepeatabilityReport>;
|
|
54
|
+
export declare function writeHydrationPolicyRepeatabilityReport(outPath: string, report: HydrationPolicyRepeatabilityReport): Promise<void>;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { LocalBackend } from '../../mcp/local/local-backend.js';
|
|
5
|
+
import { resolveUnityConfig } from '../../core/config/unity-config.js';
|
|
6
|
+
function observeHydrationMeta(out) {
|
|
7
|
+
if (out?.hydrationMeta) {
|
|
8
|
+
return {
|
|
9
|
+
requestedMode: out.hydrationMeta.requestedMode,
|
|
10
|
+
effectiveMode: out.hydrationMeta.effectiveMode,
|
|
11
|
+
reason: out.hydrationMeta.reason,
|
|
12
|
+
needsParityRetry: out.hydrationMeta.needsParityRetry,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
reason: out?.error
|
|
17
|
+
? `missing_hydration_meta:${String(out.error)}`
|
|
18
|
+
: 'missing_hydration_meta:no_hydration_payload',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function snapshotFromResponse(out) {
|
|
22
|
+
return {
|
|
23
|
+
status: String(out?.runtime_claim?.status || 'unknown'),
|
|
24
|
+
evidence_level: String(out?.runtime_claim?.evidence_level || 'none'),
|
|
25
|
+
reason: out?.runtime_claim?.reason ? String(out.runtime_claim.reason) : undefined,
|
|
26
|
+
fallbackToCompact: Boolean(out?.hydrationMeta?.fallbackToCompact),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async function callPolicyProbe(input) {
|
|
30
|
+
const queryOut = await input.backend.callTool('query', {
|
|
31
|
+
repo: input.repoAlias,
|
|
32
|
+
query: 'Reload',
|
|
33
|
+
unity_resources: 'on',
|
|
34
|
+
hydration_policy: input.policy,
|
|
35
|
+
unity_hydration_mode: input.mode,
|
|
36
|
+
runtime_chain_verify: 'on-demand',
|
|
37
|
+
});
|
|
38
|
+
if (queryOut?.hydrationMeta) {
|
|
39
|
+
return queryOut;
|
|
40
|
+
}
|
|
41
|
+
return input.backend.callTool('context', {
|
|
42
|
+
repo: input.repoAlias,
|
|
43
|
+
name: 'ReloadBase',
|
|
44
|
+
file_path: 'Assets/NEON/Code/Game/Graph/Nodes/Reloads/ReloadBase.cs',
|
|
45
|
+
unity_resources: 'on',
|
|
46
|
+
hydration_policy: input.policy,
|
|
47
|
+
unity_hydration_mode: input.mode,
|
|
48
|
+
runtime_chain_verify: 'on-demand',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function classifyConsistency(rows) {
|
|
52
|
+
if (rows.length <= 1)
|
|
53
|
+
return { consistent: true, mismatchCount: 0 };
|
|
54
|
+
const first = JSON.stringify(rows[0]);
|
|
55
|
+
let mismatchCount = 0;
|
|
56
|
+
for (let i = 1; i < rows.length; i += 1) {
|
|
57
|
+
if (JSON.stringify(rows[i]) !== first)
|
|
58
|
+
mismatchCount += 1;
|
|
59
|
+
}
|
|
60
|
+
return { consistent: mismatchCount === 0, mismatchCount };
|
|
61
|
+
}
|
|
62
|
+
export async function buildHydrationPolicyRepeatabilityReport(input) {
|
|
63
|
+
const backend = new LocalBackend();
|
|
64
|
+
const ready = await backend.init();
|
|
65
|
+
if (!ready) {
|
|
66
|
+
throw new Error('LocalBackend failed to initialize for hydration policy repeatability runner');
|
|
67
|
+
}
|
|
68
|
+
const runCount = Math.max(1, Number(input.runCount || 3));
|
|
69
|
+
const policies = ['fast', 'balanced', 'strict'];
|
|
70
|
+
const snapshotsByPolicy = new Map();
|
|
71
|
+
let requiresArray = true;
|
|
72
|
+
let populatedWhenIncomplete = true;
|
|
73
|
+
let needsParityRetryRetained = true;
|
|
74
|
+
for (const policy of policies) {
|
|
75
|
+
const snapshots = [];
|
|
76
|
+
for (let i = 0; i < runCount; i += 1) {
|
|
77
|
+
const out = await callPolicyProbe({
|
|
78
|
+
backend,
|
|
79
|
+
repoAlias: input.repoAlias,
|
|
80
|
+
policy,
|
|
81
|
+
mode: 'compact',
|
|
82
|
+
});
|
|
83
|
+
snapshots.push(snapshotFromResponse(out));
|
|
84
|
+
const missingEvidence = out?.missing_evidence;
|
|
85
|
+
if (missingEvidence !== undefined && !Array.isArray(missingEvidence)) {
|
|
86
|
+
requiresArray = false;
|
|
87
|
+
}
|
|
88
|
+
if (out?.hydrationMeta?.isComplete === false && (!Array.isArray(missingEvidence) || missingEvidence.length === 0)) {
|
|
89
|
+
populatedWhenIncomplete = false;
|
|
90
|
+
}
|
|
91
|
+
if (out?.hydrationMeta?.effectiveMode === 'compact' && out?.hydrationMeta?.isComplete === false) {
|
|
92
|
+
if (typeof out?.hydrationMeta?.needsParityRetry !== 'boolean') {
|
|
93
|
+
needsParityRetryRetained = false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
snapshotsByPolicy.set(policy, snapshots);
|
|
98
|
+
}
|
|
99
|
+
const fastConsistency = classifyConsistency(snapshotsByPolicy.get('fast') || []);
|
|
100
|
+
const balancedConsistency = classifyConsistency(snapshotsByPolicy.get('balanced') || []);
|
|
101
|
+
const strictConsistency = classifyConsistency(snapshotsByPolicy.get('strict') || []);
|
|
102
|
+
const strictRows = snapshotsByPolicy.get('strict') || [];
|
|
103
|
+
const strictFallbackDowngraded = strictRows.every((row) => {
|
|
104
|
+
if (!row.fallbackToCompact)
|
|
105
|
+
return true;
|
|
106
|
+
return row.status === 'verified_partial' && row.evidence_level === 'verified_segment';
|
|
107
|
+
});
|
|
108
|
+
const policy_mode_matrix = {};
|
|
109
|
+
for (const policy of policies) {
|
|
110
|
+
const compactOut = await callPolicyProbe({
|
|
111
|
+
backend,
|
|
112
|
+
repoAlias: input.repoAlias,
|
|
113
|
+
policy,
|
|
114
|
+
mode: 'compact',
|
|
115
|
+
});
|
|
116
|
+
const parityOut = await callPolicyProbe({
|
|
117
|
+
backend,
|
|
118
|
+
repoAlias: input.repoAlias,
|
|
119
|
+
policy,
|
|
120
|
+
mode: 'parity',
|
|
121
|
+
});
|
|
122
|
+
policy_mode_matrix[policy] = {
|
|
123
|
+
compact: observeHydrationMeta(compactOut),
|
|
124
|
+
parity: observeHydrationMeta(parityOut),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
generatedAt: new Date().toISOString(),
|
|
129
|
+
repoAlias: input.repoAlias,
|
|
130
|
+
repeatability: {
|
|
131
|
+
fast: { consistent: fastConsistency.consistent, runCount, mismatchCount: fastConsistency.mismatchCount },
|
|
132
|
+
balanced: { consistent: balancedConsistency.consistent, runCount, mismatchCount: balancedConsistency.mismatchCount },
|
|
133
|
+
strict: { consistent: strictConsistency.consistent && strictFallbackDowngraded, runCount, mismatchCount: strictConsistency.mismatchCount },
|
|
134
|
+
},
|
|
135
|
+
policy_mode_matrix,
|
|
136
|
+
policy_mapping: {
|
|
137
|
+
fast: {
|
|
138
|
+
requested: policy_mode_matrix.fast.compact.requestedMode || 'compact',
|
|
139
|
+
effective: policy_mode_matrix.fast.compact.effectiveMode || 'compact',
|
|
140
|
+
reason: policy_mode_matrix.fast.compact.reason,
|
|
141
|
+
},
|
|
142
|
+
balanced: {
|
|
143
|
+
compact_requested: policy_mode_matrix.balanced.compact.requestedMode || 'compact',
|
|
144
|
+
parity_requested: policy_mode_matrix.balanced.parity.requestedMode || 'compact',
|
|
145
|
+
escalation: 'parity_on_missing_evidence',
|
|
146
|
+
},
|
|
147
|
+
strict: {
|
|
148
|
+
requested: policy_mode_matrix.strict.compact.requestedMode || 'parity',
|
|
149
|
+
effective: policy_mode_matrix.strict.compact.effectiveMode || 'parity',
|
|
150
|
+
reason: policy_mode_matrix.strict.compact.reason,
|
|
151
|
+
downgradeOnFallback: 'verified_partial/verified_segment',
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
missing_evidence_contract: {
|
|
155
|
+
requiresArray,
|
|
156
|
+
populatedWhenIncomplete,
|
|
157
|
+
},
|
|
158
|
+
contractCompatibility: {
|
|
159
|
+
needsParityRetryRetained,
|
|
160
|
+
},
|
|
161
|
+
warmup_cache_state: {
|
|
162
|
+
parityWarmupEnabled: resolveUnityConfig().config.parityWarmup,
|
|
163
|
+
note: 'repeatability sampled under current runtime/cache state',
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export async function writeHydrationPolicyRepeatabilityReport(outPath, report) {
|
|
168
|
+
await fs.mkdir(path.dirname(outPath), { recursive: true });
|
|
169
|
+
await fs.writeFile(outPath, JSON.stringify(report, null, 2));
|
|
170
|
+
}
|
|
171
|
+
async function main(argv) {
|
|
172
|
+
const repoIndex = argv.indexOf('--repo');
|
|
173
|
+
const outIndex = argv.indexOf('--out');
|
|
174
|
+
const repoAlias = String(argv[repoIndex + 1] || '').trim();
|
|
175
|
+
const outPath = path.resolve(String(argv[outIndex + 1] || '').trim());
|
|
176
|
+
if (!repoAlias || !outPath) {
|
|
177
|
+
throw new Error('Usage: node dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.js --repo <alias> --out <path>');
|
|
178
|
+
}
|
|
179
|
+
const report = await buildHydrationPolicyRepeatabilityReport({ repoAlias, runCount: 3 });
|
|
180
|
+
await writeHydrationPolicyRepeatabilityReport(outPath, report);
|
|
181
|
+
process.stdout.write(`phase4 hydration policy repeatability artifact written: ${outPath}\n`);
|
|
182
|
+
}
|
|
183
|
+
const entryPath = process.argv[1] ? path.resolve(process.argv[1]) : '';
|
|
184
|
+
const thisPath = fileURLToPath(import.meta.url);
|
|
185
|
+
if (entryPath === thisPath) {
|
|
186
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
187
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
188
|
+
process.exitCode = 1;
|
|
189
|
+
});
|
|
190
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { buildHydrationPolicyRepeatabilityReport } from './hydration-policy-repeatability-runner.js';
|
|
3
|
+
const { test: rawTest } = process.env.VITEST
|
|
4
|
+
? await import('vitest')
|
|
5
|
+
: await import('node:test');
|
|
6
|
+
const test = rawTest;
|
|
7
|
+
test('phase4 hydration policy repeatability report tracks consistency and compatibility', async () => {
|
|
8
|
+
const report = await buildHydrationPolicyRepeatabilityReport({ repoAlias: 'GitNexus' });
|
|
9
|
+
assert.equal(report.repeatability.fast.consistent, true);
|
|
10
|
+
assert.equal(report.repeatability.balanced.consistent, true);
|
|
11
|
+
assert.equal(report.repeatability.strict.consistent, true);
|
|
12
|
+
assert.equal(report.contractCompatibility.needsParityRetryRetained, true);
|
|
13
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface Phase1ProcessRefAcceptanceReport {
|
|
2
|
+
generatedAt: string;
|
|
3
|
+
repoAlias: string;
|
|
4
|
+
metrics: {
|
|
5
|
+
process_ref: {
|
|
6
|
+
total: number;
|
|
7
|
+
readable_count: number;
|
|
8
|
+
readable_rate: number;
|
|
9
|
+
unreadable_count: number;
|
|
10
|
+
};
|
|
11
|
+
derived_id_stability_rate: number;
|
|
12
|
+
};
|
|
13
|
+
checks: {
|
|
14
|
+
query: string;
|
|
15
|
+
unity_resources: 'on';
|
|
16
|
+
unity_hydration_mode: 'compact';
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare function buildPhase1ProcessRefAcceptanceReport(input: {
|
|
20
|
+
repoAlias: string;
|
|
21
|
+
}): Promise<Phase1ProcessRefAcceptanceReport>;
|
|
22
|
+
export declare function writePhase1ProcessRefAcceptanceReport(outPath: string, report: Phase1ProcessRefAcceptanceReport): Promise<void>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { listRegisteredRepos } from '../../storage/repo-manager.js';
|
|
5
|
+
import { LocalBackend } from '../../mcp/local/local-backend.js';
|
|
6
|
+
import { readResource } from '../../mcp/resources.js';
|
|
7
|
+
function toRate(numerator, denominator) {
|
|
8
|
+
if (denominator <= 0)
|
|
9
|
+
return 1;
|
|
10
|
+
return Math.round((numerator / denominator) * 10000) / 10000;
|
|
11
|
+
}
|
|
12
|
+
function extractDerivedIds(result) {
|
|
13
|
+
const processes = Array.isArray(result?.processes) ? result.processes : [];
|
|
14
|
+
return processes
|
|
15
|
+
.map((entry) => String(entry?.id || ''))
|
|
16
|
+
.filter((id) => id.startsWith('derived:'))
|
|
17
|
+
.sort();
|
|
18
|
+
}
|
|
19
|
+
export async function buildPhase1ProcessRefAcceptanceReport(input) {
|
|
20
|
+
const repos = await listRegisteredRepos({ validate: false });
|
|
21
|
+
const repo = repos.find((entry) => entry.name === input.repoAlias);
|
|
22
|
+
if (!repo) {
|
|
23
|
+
throw new Error(`Repo alias not found: ${input.repoAlias}`);
|
|
24
|
+
}
|
|
25
|
+
const backend = new LocalBackend();
|
|
26
|
+
const ready = await backend.init();
|
|
27
|
+
if (!ready) {
|
|
28
|
+
throw new Error('LocalBackend failed to initialize for phase1 acceptance runner');
|
|
29
|
+
}
|
|
30
|
+
const params = {
|
|
31
|
+
repo: input.repoAlias,
|
|
32
|
+
query: 'Reload',
|
|
33
|
+
unity_resources: 'on',
|
|
34
|
+
unity_hydration_mode: 'compact',
|
|
35
|
+
};
|
|
36
|
+
const first = await backend.callTool('query', params);
|
|
37
|
+
const second = await backend.callTool('query', params);
|
|
38
|
+
const processes = Array.isArray(first?.processes) ? first.processes : [];
|
|
39
|
+
const persistentReaderUris = processes
|
|
40
|
+
.map((entry) => entry?.process_ref)
|
|
41
|
+
.filter((processRef) => processRef?.kind === 'persistent' && typeof processRef.reader_uri === 'string')
|
|
42
|
+
.map((processRef) => processRef.reader_uri);
|
|
43
|
+
let readableCount = 0;
|
|
44
|
+
for (const uri of persistentReaderUris) {
|
|
45
|
+
try {
|
|
46
|
+
await readResource(uri, backend);
|
|
47
|
+
readableCount += 1;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Count as unreadable in behavior-level metric.
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const unreadableCount = Math.max(0, persistentReaderUris.length - readableCount);
|
|
54
|
+
const firstDerived = extractDerivedIds(first);
|
|
55
|
+
const secondDerived = extractDerivedIds(second);
|
|
56
|
+
const derivedStable = firstDerived.length === secondDerived.length
|
|
57
|
+
&& firstDerived.every((id, idx) => id === secondDerived[idx]);
|
|
58
|
+
return {
|
|
59
|
+
generatedAt: new Date().toISOString(),
|
|
60
|
+
repoAlias: input.repoAlias,
|
|
61
|
+
metrics: {
|
|
62
|
+
process_ref: {
|
|
63
|
+
total: persistentReaderUris.length,
|
|
64
|
+
readable_count: readableCount,
|
|
65
|
+
readable_rate: toRate(readableCount, persistentReaderUris.length),
|
|
66
|
+
unreadable_count: unreadableCount,
|
|
67
|
+
},
|
|
68
|
+
derived_id_stability_rate: derivedStable ? 1 : 0,
|
|
69
|
+
},
|
|
70
|
+
checks: {
|
|
71
|
+
query: 'Reload',
|
|
72
|
+
unity_resources: 'on',
|
|
73
|
+
unity_hydration_mode: 'compact',
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export async function writePhase1ProcessRefAcceptanceReport(outPath, report) {
|
|
78
|
+
await fs.mkdir(path.dirname(outPath), { recursive: true });
|
|
79
|
+
await fs.writeFile(outPath, JSON.stringify(report, null, 2));
|
|
80
|
+
}
|
|
81
|
+
async function main(argv) {
|
|
82
|
+
const repoIndex = argv.indexOf('--repo');
|
|
83
|
+
const outIndex = argv.indexOf('--out');
|
|
84
|
+
const repoAlias = String(argv[repoIndex + 1] || '').trim();
|
|
85
|
+
const outPath = path.resolve(String(argv[outIndex + 1] || '').trim());
|
|
86
|
+
if (!repoAlias || !outPath) {
|
|
87
|
+
throw new Error('Usage: node dist/benchmark/u2-e2e/phase1-process-ref-acceptance-runner.js --repo <alias> --out <path>');
|
|
88
|
+
}
|
|
89
|
+
const report = await buildPhase1ProcessRefAcceptanceReport({ repoAlias });
|
|
90
|
+
await writePhase1ProcessRefAcceptanceReport(outPath, report);
|
|
91
|
+
process.stdout.write(`phase1 process_ref acceptance artifact written: ${outPath}\n`);
|
|
92
|
+
}
|
|
93
|
+
const entryPath = process.argv[1] ? path.resolve(process.argv[1]) : '';
|
|
94
|
+
const thisPath = fileURLToPath(import.meta.url);
|
|
95
|
+
if (entryPath === thisPath) {
|
|
96
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
97
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
98
|
+
process.exitCode = 1;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { buildPhase1ProcessRefAcceptanceReport } from './phase1-process-ref-acceptance-runner.js';
|
|
3
|
+
const { test: rawTest } = process.env.VITEST
|
|
4
|
+
? await import('vitest')
|
|
5
|
+
: await import('node:test');
|
|
6
|
+
const test = rawTest;
|
|
7
|
+
test('phase1 process_ref acceptance report emits readable + stable metrics', async () => {
|
|
8
|
+
const report = await buildPhase1ProcessRefAcceptanceReport({
|
|
9
|
+
repoAlias: 'GitNexus',
|
|
10
|
+
});
|
|
11
|
+
assert.equal(report.metrics.process_ref.readable_rate, 1);
|
|
12
|
+
assert.equal(report.metrics.derived_id_stability_rate, 1);
|
|
13
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface Phase2RuntimeClaimAcceptanceReport {
|
|
2
|
+
generatedAt: string;
|
|
3
|
+
repoAlias: string;
|
|
4
|
+
claim_fields_presence: {
|
|
5
|
+
rule_id: boolean;
|
|
6
|
+
rule_version: boolean;
|
|
7
|
+
scope: boolean;
|
|
8
|
+
guarantees: boolean;
|
|
9
|
+
non_guarantees: boolean;
|
|
10
|
+
};
|
|
11
|
+
failure_classification_coverage: string[];
|
|
12
|
+
failure_classification_missing: string[];
|
|
13
|
+
coverage_pass: boolean;
|
|
14
|
+
samples: {
|
|
15
|
+
matched_status?: string;
|
|
16
|
+
matched_reason?: string;
|
|
17
|
+
evidence_missing_reason?: string;
|
|
18
|
+
verification_failed_reason?: string;
|
|
19
|
+
unmatched_reason?: string;
|
|
20
|
+
gate_disabled_reason?: string;
|
|
21
|
+
};
|
|
22
|
+
reproduction_commands: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
export declare function buildPhase2RuntimeClaimAcceptanceReport(input: {
|
|
25
|
+
repoAlias: string;
|
|
26
|
+
}): Promise<Phase2RuntimeClaimAcceptanceReport>;
|
|
27
|
+
export declare function writePhase2RuntimeClaimAcceptanceReport(outPath: string, report: Phase2RuntimeClaimAcceptanceReport): Promise<void>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { LocalBackend } from '../../mcp/local/local-backend.js';
|
|
5
|
+
export async function buildPhase2RuntimeClaimAcceptanceReport(input) {
|
|
6
|
+
const backend = new LocalBackend();
|
|
7
|
+
const ready = await backend.init();
|
|
8
|
+
if (!ready) {
|
|
9
|
+
throw new Error('LocalBackend failed to initialize for phase2 acceptance runner');
|
|
10
|
+
}
|
|
11
|
+
const matched = await backend.callTool('query', {
|
|
12
|
+
repo: input.repoAlias,
|
|
13
|
+
query: 'Reload',
|
|
14
|
+
unity_resources: 'on',
|
|
15
|
+
runtime_chain_verify: 'on-demand',
|
|
16
|
+
});
|
|
17
|
+
const evidenceMissing = await backend.callTool('query', {
|
|
18
|
+
repo: input.repoAlias,
|
|
19
|
+
query: 'Reload',
|
|
20
|
+
unity_resources: 'on',
|
|
21
|
+
runtime_chain_verify: 'on-demand',
|
|
22
|
+
unity_evidence_mode: 'summary',
|
|
23
|
+
max_bindings: 1,
|
|
24
|
+
max_reference_fields: 1,
|
|
25
|
+
});
|
|
26
|
+
const unmatched = await backend.callTool('query', {
|
|
27
|
+
repo: input.repoAlias,
|
|
28
|
+
query: 'UnrelatedUnityChain',
|
|
29
|
+
unity_resources: 'on',
|
|
30
|
+
runtime_chain_verify: 'on-demand',
|
|
31
|
+
});
|
|
32
|
+
// gate_disabled reason is no longer produced (env var gate removed in config migration)
|
|
33
|
+
let gateDisabled;
|
|
34
|
+
try {
|
|
35
|
+
gateDisabled = await backend.callTool('query', {
|
|
36
|
+
repo: input.repoAlias,
|
|
37
|
+
query: 'Reload',
|
|
38
|
+
unity_resources: 'on',
|
|
39
|
+
runtime_chain_verify: 'off',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
}
|
|
44
|
+
const claim = matched.runtime_claim || {};
|
|
45
|
+
const requiredReasons = [
|
|
46
|
+
'rule_not_matched',
|
|
47
|
+
'rule_matched_but_evidence_missing',
|
|
48
|
+
'rule_matched_but_verification_failed',
|
|
49
|
+
'gate_disabled',
|
|
50
|
+
];
|
|
51
|
+
const reasons = [
|
|
52
|
+
claim.reason,
|
|
53
|
+
evidenceMissing.runtime_claim?.reason,
|
|
54
|
+
unmatched.runtime_claim?.reason,
|
|
55
|
+
gateDisabled.runtime_claim?.reason,
|
|
56
|
+
]
|
|
57
|
+
.filter(Boolean)
|
|
58
|
+
.map((reason) => String(reason));
|
|
59
|
+
const failure_classification_coverage = [...new Set(reasons)];
|
|
60
|
+
const failure_classification_missing = requiredReasons.filter((reason) => !failure_classification_coverage.includes(reason));
|
|
61
|
+
const coverage_pass = failure_classification_missing.length === 0;
|
|
62
|
+
const report = {
|
|
63
|
+
generatedAt: new Date().toISOString(),
|
|
64
|
+
repoAlias: input.repoAlias,
|
|
65
|
+
claim_fields_presence: {
|
|
66
|
+
rule_id: Boolean(claim.rule_id),
|
|
67
|
+
rule_version: Boolean(claim.rule_version),
|
|
68
|
+
scope: Boolean(claim.scope),
|
|
69
|
+
guarantees: Array.isArray(claim.guarantees),
|
|
70
|
+
non_guarantees: Array.isArray(claim.non_guarantees),
|
|
71
|
+
},
|
|
72
|
+
failure_classification_coverage,
|
|
73
|
+
failure_classification_missing,
|
|
74
|
+
coverage_pass,
|
|
75
|
+
samples: {
|
|
76
|
+
matched_status: claim.status,
|
|
77
|
+
matched_reason: claim.reason,
|
|
78
|
+
evidence_missing_reason: evidenceMissing.runtime_claim?.reason,
|
|
79
|
+
verification_failed_reason: claim.reason,
|
|
80
|
+
unmatched_reason: unmatched.runtime_claim?.reason,
|
|
81
|
+
gate_disabled_reason: gateDisabled.runtime_claim?.reason,
|
|
82
|
+
},
|
|
83
|
+
reproduction_commands: {
|
|
84
|
+
rule_matched_but_verification_failed: `gitnexus query --repo ${input.repoAlias} --runtime-chain-verify on-demand --unity-resources on "Reload"`,
|
|
85
|
+
rule_matched_but_evidence_missing: `gitnexus query --repo ${input.repoAlias} --runtime-chain-verify on-demand --unity-resources on --unity-evidence-mode summary --max-bindings 1 --max-reference-fields 1 "Reload"`,
|
|
86
|
+
rule_not_matched: `gitnexus query --repo ${input.repoAlias} --runtime-chain-verify on-demand --unity-resources on "UnrelatedUnityChain"`,
|
|
87
|
+
gate_disabled: `gitnexus query --repo ${input.repoAlias} --runtime-chain-verify off --unity-resources on "Reload"`,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
if (!coverage_pass) {
|
|
91
|
+
throw new Error(`phase2 failure classification coverage is incomplete (${failure_classification_coverage.length}/4). Missing: ${failure_classification_missing.join(', ')}`);
|
|
92
|
+
}
|
|
93
|
+
return report;
|
|
94
|
+
}
|
|
95
|
+
export async function writePhase2RuntimeClaimAcceptanceReport(outPath, report) {
|
|
96
|
+
await fs.mkdir(path.dirname(outPath), { recursive: true });
|
|
97
|
+
await fs.writeFile(outPath, JSON.stringify(report, null, 2));
|
|
98
|
+
}
|
|
99
|
+
async function main(argv) {
|
|
100
|
+
const repoIndex = argv.indexOf('--repo');
|
|
101
|
+
const outIndex = argv.indexOf('--out');
|
|
102
|
+
const repoAlias = String(argv[repoIndex + 1] || '').trim();
|
|
103
|
+
const outPath = path.resolve(String(argv[outIndex + 1] || '').trim());
|
|
104
|
+
if (!repoAlias || !outPath) {
|
|
105
|
+
throw new Error('Usage: node dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.js --repo <alias> --out <path>');
|
|
106
|
+
}
|
|
107
|
+
const report = await buildPhase2RuntimeClaimAcceptanceReport({ repoAlias });
|
|
108
|
+
await writePhase2RuntimeClaimAcceptanceReport(outPath, report);
|
|
109
|
+
process.stdout.write(`phase2 runtime_claim acceptance artifact written: ${outPath}\n`);
|
|
110
|
+
}
|
|
111
|
+
const entryPath = process.argv[1] ? path.resolve(process.argv[1]) : '';
|
|
112
|
+
const thisPath = fileURLToPath(import.meta.url);
|
|
113
|
+
if (entryPath === thisPath) {
|
|
114
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
115
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
116
|
+
process.exitCode = 1;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { buildPhase2RuntimeClaimAcceptanceReport } from './phase2-runtime-claim-acceptance-runner.js';
|
|
3
|
+
const { test: rawTest } = process.env.VITEST
|
|
4
|
+
? await import('vitest')
|
|
5
|
+
: await import('node:test');
|
|
6
|
+
const test = rawTest;
|
|
7
|
+
test('phase2 runtime_claim acceptance report tracks contract + failure classification coverage', async () => {
|
|
8
|
+
const report = await buildPhase2RuntimeClaimAcceptanceReport({ repoAlias: 'GitNexus' });
|
|
9
|
+
assert.equal(report.claim_fields_presence.rule_id, true);
|
|
10
|
+
assert.equal(report.claim_fields_presence.rule_version, true);
|
|
11
|
+
assert.equal(report.coverage_pass, true);
|
|
12
|
+
assert.equal(report.failure_classification_coverage.includes('rule_not_matched'), true);
|
|
13
|
+
assert.equal(report.failure_classification_coverage.includes('rule_matched_but_evidence_missing'), true);
|
|
14
|
+
assert.equal(report.failure_classification_coverage.includes('rule_matched_but_verification_failed'), true);
|
|
15
|
+
assert.equal(report.failure_classification_coverage.includes('gate_disabled'), true);
|
|
16
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface Phase5StageCoverageRow {
|
|
2
|
+
stage: 'discover' | 'analyze' | 'review-pack' | 'curate' | 'promote' | 'regress';
|
|
3
|
+
command: string;
|
|
4
|
+
status: 'passed' | 'failed';
|
|
5
|
+
retry_hint?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface Phase5FailureClassification {
|
|
9
|
+
code: string;
|
|
10
|
+
retry_hint: string;
|
|
11
|
+
repro_command: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Phase5RuleLabAcceptanceReport {
|
|
14
|
+
generated_at: string;
|
|
15
|
+
repo_alias: string;
|
|
16
|
+
repo_path: string;
|
|
17
|
+
run_id: string;
|
|
18
|
+
stage_coverage: Phase5StageCoverageRow[];
|
|
19
|
+
metrics: {
|
|
20
|
+
precision: number;
|
|
21
|
+
coverage: number;
|
|
22
|
+
probe_pass_rate: number;
|
|
23
|
+
token_budget: number;
|
|
24
|
+
};
|
|
25
|
+
authenticity_checks: {
|
|
26
|
+
static_no_hardcoded_reload: {
|
|
27
|
+
pass: boolean;
|
|
28
|
+
blocked_symbols: string[];
|
|
29
|
+
};
|
|
30
|
+
dsl_lint_pass: boolean;
|
|
31
|
+
};
|
|
32
|
+
failure_classifications: Phase5FailureClassification[];
|
|
33
|
+
artifact_paths: {
|
|
34
|
+
manifest: string;
|
|
35
|
+
candidates: string;
|
|
36
|
+
review_cards: string;
|
|
37
|
+
curation_input: string;
|
|
38
|
+
curated: string;
|
|
39
|
+
catalog: string;
|
|
40
|
+
promoted_files: string[];
|
|
41
|
+
regress_report?: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export interface BuildPhase5RuleLabAcceptanceInput {
|
|
45
|
+
repoAlias: string;
|
|
46
|
+
repoPath?: string;
|
|
47
|
+
seed?: string;
|
|
48
|
+
}
|
|
49
|
+
export declare function buildPhase5RuleLabAcceptanceReport(input: BuildPhase5RuleLabAcceptanceInput): Promise<Phase5RuleLabAcceptanceReport>;
|
|
50
|
+
export declare function runPhase5RuleLabGate(input: {
|
|
51
|
+
reportPath: string;
|
|
52
|
+
}): Promise<{
|
|
53
|
+
pass: boolean;
|
|
54
|
+
reason?: string;
|
|
55
|
+
}>;
|
|
56
|
+
export declare function writePhase5RuleLabAcceptanceArtifacts(input: {
|
|
57
|
+
report: Phase5RuleLabAcceptanceReport;
|
|
58
|
+
jsonPath: string;
|
|
59
|
+
mdPath: string;
|
|
60
|
+
}): Promise<void>;
|