test: refresh HWLAB DEV live evidence
Merge PR #71 after commander review. Rebaselines DEV live evidence to 16666/16667, removes stale edge/frp blocker classification, keeps DB live and M3 patch-panel runtime as real blockers. Complies with HWLAB #78 / DC-DCSN-P0-2026-003 by preserving DEV-LIVE evidence boundaries and not treating Gate/UI as MVP success.
This commit is contained in:
@@ -239,7 +239,7 @@ function applyPriority(blocker) {
|
||||
};
|
||||
}
|
||||
|
||||
if (blocker.scope.includes("edge") || blocker.scope.includes("ingress") || blocker.summary.includes("6667")) {
|
||||
if (isEdgeOrFrpBlocker(blocker)) {
|
||||
return {
|
||||
...blocker,
|
||||
priority: "P2",
|
||||
@@ -258,6 +258,16 @@ function applyPriority(blocker) {
|
||||
};
|
||||
}
|
||||
|
||||
function isEdgeOrFrpBlocker(blocker) {
|
||||
return blocker.scope.includes("edge") ||
|
||||
blocker.scope.includes("ingress") ||
|
||||
blocker.scope.includes("frp") ||
|
||||
blocker.summary.includes(":16667") ||
|
||||
blocker.summary.includes("16667") ||
|
||||
blocker.summary.includes(":6667") ||
|
||||
blocker.summary.includes("6667");
|
||||
}
|
||||
|
||||
function sourceEntry(entry) {
|
||||
return {
|
||||
milestone: entry.milestone,
|
||||
@@ -294,6 +304,7 @@ function collectM2Evidence(reports) {
|
||||
const edge = reports.devEdgeHealth;
|
||||
const d601 = reports.d601Observability;
|
||||
const artifactIdentity = preflight.artifactIdentity;
|
||||
const edgeLive = hasCurrentLiveEdgeEvidence(edge);
|
||||
|
||||
return [
|
||||
reportEvidence({
|
||||
@@ -336,7 +347,7 @@ function collectM2Evidence(reports) {
|
||||
}),
|
||||
reportEvidence({
|
||||
milestone: "M2",
|
||||
level: "SOURCE",
|
||||
level: edgeLive ? "DEV-LIVE" : "SOURCE",
|
||||
report: edge,
|
||||
status: edge.edgeHealth?.status ?? primaryStatus(edge),
|
||||
category: "edge-frp-contract",
|
||||
@@ -346,7 +357,9 @@ function collectM2Evidence(reports) {
|
||||
`cloudApiDb=${edge.edgeHealth?.contracts?.deploy?.cloudApiDb?.status ?? "unknown"}`
|
||||
],
|
||||
commands: edge.validationCommands,
|
||||
summary: "Committed edge report is contract-only/not-run; it must not be counted as DEV-LIVE."
|
||||
summary: edgeLive
|
||||
? "Committed edge report proves read-only public HTTP on :16667 /health and /health/live; remaining edge report blocker is DB readiness, not route/frp reachability."
|
||||
: "Committed edge report is contract-only/not-run; it must not be counted as DEV-LIVE."
|
||||
}),
|
||||
reportEvidence({
|
||||
milestone: "M2",
|
||||
@@ -473,12 +486,21 @@ function collectBlockers(reports) {
|
||||
const blockers = [];
|
||||
for (const report of Object.values(reports)) {
|
||||
for (const blocker of report.blockers ?? []) {
|
||||
if (isStaleLegacyIngressBlocker(blocker, report, reports)) {
|
||||
continue;
|
||||
}
|
||||
blockers.push(normalizeBlocker(blocker, report));
|
||||
}
|
||||
for (const blocker of report.artifactPublish?.blockers ?? []) {
|
||||
if (isStaleLegacyIngressBlocker(blocker, report, reports)) {
|
||||
continue;
|
||||
}
|
||||
blockers.push(normalizeBlocker(blocker, report));
|
||||
}
|
||||
for (const blocker of report.devDeployApply?.remainingBlockers ?? []) {
|
||||
if (isStaleLegacyIngressBlocker(blocker, report, reports)) {
|
||||
continue;
|
||||
}
|
||||
blockers.push(normalizeBlocker(blocker, report));
|
||||
}
|
||||
}
|
||||
@@ -487,6 +509,34 @@ function collectBlockers(reports) {
|
||||
return normalized.sort((a, b) => a.unblockOrder - b.unblockOrder || a.id.localeCompare(b.id));
|
||||
}
|
||||
|
||||
function hasCurrentLiveEdgeEvidence(edgeReport) {
|
||||
const publicHttp = edgeReport?.edgeHealth?.publicHttp ?? [];
|
||||
return edgeReport?.edgeHealth?.endpoint === DEV_ENDPOINT &&
|
||||
edgeReport?.edgeHealth?.mode === "live-read-only" &&
|
||||
publicHttp.some((probe) => probe.url === `${DEV_ENDPOINT}/health` && probe.ok === true && probe.status === 200) &&
|
||||
publicHttp.some((probe) => probe.url === `${DEV_ENDPOINT}/health/live` && probe.ok === true && probe.status === 200);
|
||||
}
|
||||
|
||||
function isStaleLegacyIngressBlocker(blocker, sourceReport, reports) {
|
||||
const text = `${blocker.scope ?? ""} ${blocker.summary ?? ""}`;
|
||||
const staleLegacyPort = text.includes("74.48.78.17:6667");
|
||||
const stalePreflightEdgeProbe = sourceReport.path === reportPaths.devPreflight &&
|
||||
blocker.type === "network_blocker" &&
|
||||
(blocker.scope === "dev-edge" || blocker.scope === "dev-edge-health") &&
|
||||
(
|
||||
text.includes(`${DEV_ENDPOINT}/health/live is not reachable`) ||
|
||||
text.includes("live network probes require --live")
|
||||
);
|
||||
|
||||
if (!staleLegacyPort && !stalePreflightEdgeProbe) {
|
||||
return false;
|
||||
}
|
||||
const currentEdgeReachable = hasCurrentLiveEdgeEvidence(reports.devEdgeHealth);
|
||||
return currentEdgeReachable && sourceReport.path !== reportPaths.devM3Hardware &&
|
||||
sourceReport.path !== reportPaths.devM4Agent &&
|
||||
sourceReport.path !== reportPaths.devM5Gate;
|
||||
}
|
||||
|
||||
function deriveMilestones(evidence, blockers) {
|
||||
const evidenceByMilestone = new Map();
|
||||
for (const item of evidence) {
|
||||
@@ -571,6 +621,7 @@ function buildDoD(reports, milestones, blockers) {
|
||||
const preflight = reports.devPreflight;
|
||||
const artifactIdentity = preflight.artifactIdentity;
|
||||
const d601 = reports.d601Observability;
|
||||
const edgeLive = hasCurrentLiveEdgeEvidence(reports.devEdgeHealth);
|
||||
|
||||
return {
|
||||
status: blockers.length === 0 && milestones.every((item) => item.status === "pass") ? "green" : "blocked",
|
||||
@@ -603,10 +654,12 @@ function buildDoD(reports, milestones, blockers) {
|
||||
: "D601 runner lacks kubectl/k3s/kubeconfig observability for hwlab-dev."
|
||||
},
|
||||
{
|
||||
id: "dev-edge-frp-6667",
|
||||
status: hasBlocker(blockers, (blocker) => blocker.scope.includes("edge") || blocker.scope.includes("ingress") || blocker.summary.includes("6667")) ? "blocked" : "pass",
|
||||
evidenceLevel: "BLOCKED",
|
||||
summary: "No committed report proves live HTTP 200/JSON on http://74.48.78.17:16667."
|
||||
id: "dev-edge-frp-16667",
|
||||
status: edgeLive && !hasBlocker(blockers, isEdgeOrFrpBlocker) ? "pass" : "blocked",
|
||||
evidenceLevel: edgeLive && !hasBlocker(blockers, isEdgeOrFrpBlocker) ? "DEV-LIVE" : "BLOCKED",
|
||||
summary: edgeLive
|
||||
? "Committed edge report proves read-only public HTTP on :16667 /health and /health/live; old preflight network probe blockers are stale."
|
||||
: "No committed report proves live HTTP 200/JSON on http://74.48.78.17:16667."
|
||||
},
|
||||
{
|
||||
id: "cloud-api-db-ready",
|
||||
@@ -661,7 +714,7 @@ function actionForBlockerOrder(blockerOrder, items) {
|
||||
function fallbackAction(scope) {
|
||||
if (scope === "base-image") return "Preload or tag node:20-bookworm-slim and rerun the base-image and artifact publish preflights.";
|
||||
if (scope.includes("artifact")) return "Publish DEV artifacts for every frozen HWLAB service and record immutable registry digests.";
|
||||
if (scope.includes("edge") || scope.includes("ingress")) return "Repair frp/master-edge/D601 router path and rerun read-only DEV edge health.";
|
||||
if (scope.includes("edge") || scope.includes("ingress") || scope.includes("frp")) return "Repair frp/master-edge/D601 router path and rerun read-only DEV edge health.";
|
||||
if (scope.includes("cloud-api-db")) return "Configure DEV cloud-api DB env readiness and rerun health/preflight without exposing secrets.";
|
||||
if (scope.includes("kubectl") || scope.includes("k3s")) return "Provide read-only kubectl/kubeconfig observability for hwlab-dev.";
|
||||
return "Resolve the blocker and attach source/local/dry-run/DEV-live evidence at the correct level.";
|
||||
@@ -673,7 +726,7 @@ function evidenceRequiredFor(scope) {
|
||||
if (scope.includes("artifact") || scope === "ghcr") return "Artifact publish report with ciPublished=true, registryVerified=true, and sha256 digest for each frozen service ID.";
|
||||
if (scope.includes("kubectl") || scope.includes("k3s")) return "Read-only kubectl/k3s report proving pods/services/configmaps are observable in hwlab-dev without reading Secrets.";
|
||||
if (scope.includes("cloud-api-db")) return "Cloud API health/live output showing DB env ready and redacted secret references, without secret material.";
|
||||
if (scope.includes("edge") || scope.includes("ingress")) return "Read-only DEV route observation for :16667/frp/edge/router with HWLAB service identity and artifact identity.";
|
||||
if (scope.includes("edge") || scope.includes("ingress") || scope.includes("frp")) return "Read-only DEV route observation for :16667/frp/edge/router with HWLAB service identity and artifact identity.";
|
||||
return "A committed report with the exact evidence level and command used.";
|
||||
}
|
||||
|
||||
@@ -754,7 +807,7 @@ export async function buildReport() {
|
||||
green: dod.green,
|
||||
reason: dod.green
|
||||
? "All #9 DEV DoD checks are green."
|
||||
: "SOURCE, LOCAL, and DRY-RUN evidence exists, but DEV-LIVE acceptance is blocked by artifact, observability, DB, edge/frp, and loop evidence gaps."
|
||||
: "SOURCE, LOCAL, DRY-RUN, and edge DEV-LIVE evidence exists, but acceptance is still blocked by artifact, observability, DB, and loop evidence gaps."
|
||||
},
|
||||
dod,
|
||||
milestones,
|
||||
@@ -777,7 +830,9 @@ export function formatCheckSummary(report) {
|
||||
green: report.overall.green,
|
||||
blockers: report.blockers.length,
|
||||
nextStep: report.nextSteps[0]?.action ?? null,
|
||||
levels
|
||||
levels: Object.fromEntries(
|
||||
Object.entries(report.levels).map(([level, entries]) => [level, entries.length])
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user