Files
proxmox/scripts/verify/check-gru-global-priority-rollout.sh
defiQUG dbd517b279 Sync workspace: config, docs, scripts, CI, operator rules, and submodule pointers.
- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains
- Omit embedded publish git dirs and empty placeholders from index

Made-with: Cursor
2026-04-12 06:12:20 -07:00

185 lines
6.8 KiB
Bash

#!/usr/bin/env bash
# Compare the GRU global-priority rollout plan against the current repo state.
# Usage:
# bash scripts/verify/check-gru-global-priority-rollout.sh
# bash scripts/verify/check-gru-global-priority-rollout.sh --json
# bash scripts/verify/check-gru-global-priority-rollout.sh --wave=wave1
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
export PROJECT_ROOT
OUTPUT_JSON=0
WAVE_FILTER=""
for arg in "$@"; do
case "$arg" in
--json) OUTPUT_JSON=1 ;;
--wave=*) WAVE_FILTER="${arg#--wave=}" ;;
*)
echo "Unknown argument: $arg" >&2
exit 2
;;
esac
done
need_cmd() {
command -v "$1" >/dev/null 2>&1 || {
echo "[FAIL] Missing required command: $1" >&2
exit 1
}
}
need_cmd node
OUTPUT_JSON="$OUTPUT_JSON" WAVE_FILTER="$WAVE_FILTER" node <<'NODE'
const fs = require('fs');
const path = require('path');
const root = process.env.PROJECT_ROOT;
const outputJson = process.env.OUTPUT_JSON === '1';
const waveFilter = process.env.WAVE_FILTER || '';
function readJson(relPath) {
return JSON.parse(fs.readFileSync(path.join(root, relPath), 'utf8'));
}
const rollout = readJson('config/gru-global-priority-currency-rollout.json');
const manifest = readJson('config/gru-iso4217-currency-manifest.json');
const mapping = readJson('config/token-mapping-multichain.json');
const transport = readJson('config/gru-transport-active.json');
const manifestByCode = new Map((manifest.currencies || []).map((item) => [item.code, item]));
const transportBySymbol = new Map((transport.enabledCanonicalTokens || []).map((item) => [item.symbol, item]));
const cToCw = mapping.cToCwSymbolMapping || {};
const wavesById = new Map((rollout.waves || []).map((item) => [item.id, item]));
const desiredDestinationNetworks = rollout.desiredDestinationNetworks || {};
const destinationSummary = {
evmPublicCwMesh: (desiredDestinationNetworks.evmPublicCwMeshChainIds || []).length,
altEvmPrograms: (desiredDestinationNetworks.altEvmPrograms || []).length,
nonEvmRelayPrograms: (desiredDestinationNetworks.nonEvmRelayPrograms || []).length
};
function manifestSymbolsFor(entry) {
if (!entry || !entry.canonicalAssets) return [];
const out = [];
for (const [form, data] of Object.entries(entry.canonicalAssets)) {
if (data && typeof data.symbol === 'string') {
out.push({ form, symbol: data.symbol });
}
}
return out;
}
function deriveState(bits) {
if (bits.transportActive) return 'live_transport';
if (bits.canonical138Deployed) return 'canonical_only';
if (bits.manifestPresent) return 'manifest_only';
if (bits.cToCwMapped) return 'mapping_only';
return 'backlog';
}
function nextStep(bits) {
if (!bits.manifestPresent) return 'add_to_manifest_and_standards';
if (!bits.canonical138Deployed) return 'deploy_canonical_on_chain138';
if (!bits.cToCwMapped) return 'add_c_to_cw_symbol_mapping';
if (!bits.transportActive) return 'deploy_cw_and_enable_transport';
if (!bits.x402Ready) return 'promote_x402_surface';
return 'monitor_and_scale';
}
const filteredAssets = (rollout.assets || []).filter((asset) => !waveFilter || asset.wave === waveFilter);
const results = filteredAssets.map((asset) => {
const manifestEntry = manifestByCode.get(asset.code);
const rolloutSymbols = (asset.tokenForms || []).map((item) => ({
form: item.form,
canonicalSymbol: item.canonicalSymbol,
wrappedSymbol: item.wrappedSymbol
}));
const manifestSymbols = manifestSymbolsFor(manifestEntry);
const manifestPresent = Boolean(manifestEntry);
const canonical138Deployed = Boolean(manifestEntry?.status?.deployed);
const transportActive = rolloutSymbols.some((item) => {
const transportEntry = transportBySymbol.get(item.canonicalSymbol);
return Boolean(transportEntry);
});
const x402Ready = Boolean(manifestEntry?.status?.x402Ready);
const cToCwMapped = rolloutSymbols.length > 0 && rolloutSymbols.every((item) => cToCw[item.canonicalSymbol] === item.wrappedSymbol);
const manifestMatchesRollout = manifestSymbols.length > 0 && rolloutSymbols.every((item) => manifestSymbols.some((m) => m.symbol === item.canonicalSymbol));
const bits = {
manifestPresent,
canonical138Deployed,
cToCwMapped,
transportActive,
x402Ready
};
return {
code: asset.code,
name: asset.name,
tier: asset.tier,
rank: asset.rank,
wave: asset.wave,
waveName: wavesById.get(asset.wave)?.name || asset.wave,
repoTargetState: asset.repoTargetState,
currentRepoState: deriveState(bits),
nextStep: nextStep(bits),
manifestPresent,
canonical138Deployed,
cToCwMapped,
transportActive,
x402Ready,
manifestMatchesRollout,
canonicalSymbols: rolloutSymbols.map((item) => item.canonicalSymbol),
wrappedSymbols: rolloutSymbols.map((item) => item.wrappedSymbol)
};
});
const summary = {
totalAssets: results.length,
liveTransport: results.filter((item) => item.currentRepoState === 'live_transport').length,
canonicalOnly: results.filter((item) => item.currentRepoState === 'canonical_only').length,
manifestOnly: results.filter((item) => item.currentRepoState === 'manifest_only').length,
backlog: results.filter((item) => item.currentRepoState === 'backlog').length,
mappingOnly: results.filter((item) => item.currentRepoState === 'mapping_only').length
};
if (outputJson) {
console.log(JSON.stringify({ summary, destinationSummary, desiredDestinationNetworks, results }, null, 2));
process.exit(0);
}
console.log('=== GRU Global Priority Cross-Chain Rollout ===');
console.log(`Assets checked: ${summary.totalAssets}`);
console.log(`Desired destination networks: EVM cW mesh=${destinationSummary.evmPublicCwMesh}, ALT/gated EVM=${destinationSummary.altEvmPrograms}, non-EVM relay=${destinationSummary.nonEvmRelayPrograms}`);
console.log(`live_transport: ${summary.liveTransport}`);
console.log(`canonical_only: ${summary.canonicalOnly}`);
console.log(`manifest_only: ${summary.manifestOnly}`);
console.log(`mapping_only: ${summary.mappingOnly}`);
console.log(`backlog: ${summary.backlog}`);
if (waveFilter) {
console.log(`Wave filter: ${waveFilter}`);
}
if ((desiredDestinationNetworks.nonEvmRelayPrograms || []).length > 0) {
const nonEvmNames = desiredDestinationNetworks.nonEvmRelayPrograms
.map((item) => item.identifier)
.join(', ');
console.log(`Non-EVM desired targets: ${nonEvmNames}`);
}
for (const item of results) {
const flags = [
item.manifestPresent ? 'manifest' : 'no-manifest',
item.canonical138Deployed ? 'canonical138' : 'no-canonical138',
item.cToCwMapped ? 'mapped' : 'no-mapping',
item.transportActive ? 'transport' : 'no-transport',
item.x402Ready ? 'x402' : 'no-x402'
].join(', ');
console.log(`- ${item.code} (${item.name}) [${item.tier} / ${item.wave}] -> ${item.currentRepoState}; next: ${item.nextStep}; ${flags}`);
}
NODE