Files
proxmox/scripts/verify/generate-publication-actionable-backlog.mjs
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

146 lines
5.5 KiB
JavaScript

#!/usr/bin/env node
import fs from 'fs';
import path from 'path';
const repoRoot = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..');
const matrixPath = path.join(repoRoot, 'reports', 'status', 'contract_verification_publish_matrix.json');
const packStatusPath = path.join(repoRoot, 'reports', 'status', 'publication-pack-explorer-status.json');
const outJson = path.join(repoRoot, 'reports', 'status', 'publication-actionable-backlog.json');
const outMd = path.join(repoRoot, 'docs', '11-references', 'PUBLICATION_ACTIONABLE_BACKLOG.md');
const targetChainIds = new Set(['1', '10', '56', '137', '8453']);
const nonActionableAutomation = new Set(['inventory-only', 'reference-only']);
const autoSubmittableAutomation = new Set(['repo-supported', 'partial']);
function ensureDir(filePath) {
fs.mkdirSync(path.dirname(filePath), { recursive: true });
}
function loadJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
}
function byAddress(statusReport) {
const index = new Map();
for (const pack of statusReport.packs || []) {
for (const entry of pack.entries || []) {
index.set(`${entry.chainId}:${entry.address.toLowerCase()}`, entry);
}
}
return index;
}
function toRow(entry) {
return `| ${entry.chainId} | ${entry.chainName} | ${entry.label} | \`${entry.address}\` | ${entry.contractType} | ${entry.automation} | ${entry.explorerStatus} | ${entry.nextAction} |`;
}
const matrix = loadJson(matrixPath);
const packStatus = loadJson(packStatusPath);
const statusIndex = byAddress(packStatus);
const backlogEntries = matrix.entries
.filter((entry) => targetChainIds.has(entry.chainId))
.map((entry) => {
const status = statusIndex.get(`${entry.chainId}:${entry.address.toLowerCase()}`) || {};
const explorerStatus = status.explorerStatus || 'not-in-pack-status';
let nextAction = 'No automatic action';
if (nonActionableAutomation.has(entry.automation)) {
nextAction = 'Keep inventory/docs aligned; do not treat as repo-owned submission target';
} else if (autoSubmittableAutomation.has(entry.automation)) {
nextAction = 'Submit automatically with repo-owned verification flow';
} else if (entry.automation === 'manual-or-external') {
nextAction = 'Manual or external closure only; missing repo-supported source bundle or ownership proof';
}
return {
...entry,
explorerStatus,
explorerDetail: status.explorerDetail || null,
nextAction,
};
});
const autoSubmittable = backlogEntries.filter((entry) => autoSubmittableAutomation.has(entry.automation));
const manualOrExternal = backlogEntries.filter((entry) => entry.automation === 'manual-or-external');
const inventoryOnly = backlogEntries.filter((entry) => nonActionableAutomation.has(entry.automation));
const byChain = new Map();
for (const entry of backlogEntries) {
const current = byChain.get(entry.chainId) || {
chainId: entry.chainId,
chainName: entry.chainName,
total: 0,
autoSubmittable: 0,
manualOrExternal: 0,
inventoryOnly: 0,
};
current.total += 1;
if (autoSubmittableAutomation.has(entry.automation)) current.autoSubmittable += 1;
if (entry.automation === 'manual-or-external') current.manualOrExternal += 1;
if (nonActionableAutomation.has(entry.automation)) current.inventoryOnly += 1;
byChain.set(entry.chainId, current);
}
const summaryRows = [...byChain.values()]
.sort((a, b) => Number(a.chainId) - Number(b.chainId))
.map((chain) => `| ${chain.chainId} | ${chain.chainName} | ${chain.total} | ${chain.autoSubmittable} | ${chain.manualOrExternal} | ${chain.inventoryOnly} |`)
.join('\n');
const autoRows = autoSubmittable.length
? autoSubmittable.map(toRow).join('\n')
: '| - | - | - | - | - | - | - | Automatic submission backlog is currently empty for the requested packs |';
const manualRows = manualOrExternal.length
? manualOrExternal.map(toRow).join('\n')
: '| - | - | - | - | - | - | - | No manual-or-external backlog |';
const payload = {
generatedAt: new Date().toISOString(),
targetChains: [...targetChainIds],
summary: [...byChain.values()].sort((a, b) => Number(a.chainId) - Number(b.chainId)),
autoSubmittable,
manualOrExternal,
inventoryOnlyCount: inventoryOnly.length,
};
const md = `# Publication Actionable Backlog
**Generated:** ${payload.generatedAt}
This artifact separates the five requested publication packs into:
- addresses we can honestly treat as **auto-submittable** from the repo
- addresses that are **manual or external**
- addresses that are only **inventory/reference tracking**
## Chain Summary
| Chain ID | Chain | Total Entries | Auto-submittable | Manual / External | Inventory / Reference |
| --- | --- | ---: | ---: | ---: | ---: |
${summaryRows}
## Auto-submittable backlog
| Chain ID | Chain | Label | Address | Type | Automation | Explorer Status | Next Action |
| --- | --- | --- | --- | --- | --- | --- | --- |
${autoRows}
## Manual or external backlog
| Chain ID | Chain | Label | Address | Type | Automation | Explorer Status | Next Action |
| --- | --- | --- | --- | --- | --- | --- | --- |
${manualRows}
## Closure note
For the five requested packs, the repo-owned **automatic** submission pass is complete when the auto-submittable backlog is empty.
Any remaining rows in the manual/external table require source provenance, ownership confirmation, or a non-repo verification process before they can be closed honestly.
`;
ensureDir(outJson);
ensureDir(outMd);
fs.writeFileSync(outJson, JSON.stringify(payload, null, 2) + '\n');
fs.writeFileSync(outMd, md + '\n');
console.log(`Wrote:\n- ${outJson}\n- ${outMd}`);