From 80e8a2f2084b9955d190153578d65168825de71d Mon Sep 17 00:00:00 2001 From: HWLAB Code Queue Date: Fri, 22 May 2026 11:52:11 +0000 Subject: [PATCH] docs: refresh M5 live gate aggregator --- docs/dev-evidence-blocker-aggregator.md | 27 ++- internal/dev-report-lifecycle.mjs | 8 +- .../dev-gate/dev-m5-gate-aggregator-v2.json | 226 ++++++++++++++++-- reports/dev-gate/dev-m5-gate-aggregator-v2.md | 35 ++- .../src/dev-evidence-blocker-aggregator.mjs | 207 +++++++++++++++- 5 files changed, 471 insertions(+), 32 deletions(-) diff --git a/docs/dev-evidence-blocker-aggregator.md b/docs/dev-evidence-blocker-aggregator.md index 7f306276..14e8abd7 100644 --- a/docs/dev-evidence-blocker-aggregator.md +++ b/docs/dev-evidence-blocker-aggregator.md @@ -48,22 +48,41 @@ without promoting the full gate: | Layer | Meaning | | --- | --- | +| `Frontend DEV revision` | Latest accepted Cloud Workbench frontend revision on the active `http://74.48.78.17:16666/` browser endpoint. Frontend revision evidence is browser-only and cannot green DB, M3, M4, or M5. | | `EDGE/ROUTE live` | `16666` browser and `16667` health route evidence from read-only probes. | | `DB live/degraded` | Cloud API DB readiness from redacted health evidence; route success does not imply DB live. | | `M3 hardware trusted loop` | Real DEV `res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` plus operation, trace, audit, and evidence identifiers. | | `M4 agent loop` | Agent loop live preflight and scheduling/evidence closure, gated by DB and runtime readiness. | | `artifact/desired-state source` | Artifact source coverage for the current target ref plus desired-state dry-run/apply status. | +The report also emits `activeEndpoints` and `deprecatedEndpoints`. Active +acceptance endpoints are: + +- frontend/browser: `http://74.48.78.17:16666/` +- API/live: `http://74.48.78.17:16667/health/live` + +Legacy public `http://74.48.78.17:6666` and +`http://74.48.78.17:6667` are historical/deprecated only and are not active +green evidence. + +`latestFrontendDevFact` records the current #99/#108 frontend fact: revision +`1e8805664970839b72be40c34636b08f6d18b131` is accepted on DEV, with +`promotesM3M4M5=false`. + ## Current Contract Map | Milestone | Current visible level | Contract entry | | --- | --- | --- | | M0 | `SOURCE` | `docs/m0-contract-audit.md`, protocol schemas, evidence chain examples, M0 validator. | | M1 | `LOCAL` | `docs/m1-local-smoke.md`, `fixtures/mvp/runtime.json`, `scripts/m1-contract-smoke.mjs`. | -| M2 | `DEV-LIVE` for route only | DEV deploy smoke fixture plus active read-only `16666`/`16667` endpoint smoke. | -| M3 | `LOCAL` | Hardware trusted loop topology fixture and local patch-panel smoke. | -| M4 | `LOCAL` | Agent automation loop fixture, local runtime skeleton, skills commit, evidence, and cleanup smoke. | -| M5 | `DRY-RUN` | MVP e2e dry-run plan and orchestration validator. | +| M2 | `DEV-LIVE` for frontend/route only | DEV deploy smoke fixture plus active read-only `16666`/`16667` endpoint smoke and accepted frontend revision. | +| M3 | `BLOCKED` | Hardware trusted loop topology fixture and local patch-panel smoke exist, but DEV-LIVE operation/trace/audit/evidence IDs are missing. | +| M4 | `BLOCKED` | Agent automation loop fixture and local smoke exist, but live preflight is blocked at DB live readiness. | +| M5 | `BLOCKED` | MVP e2e dry-run plan is green, but bounded DEV-LIVE acceptance is blocked by DB/M3/M4 and source/artifact coverage. | + +`milestoneLevelClassification` is the compact M0-M5 answer for command +handoff. `milestoneBlockerClassification` gives the M3/M4/M5 blocker class, +dependency, and required next proof. ## Blocker Posture diff --git a/internal/dev-report-lifecycle.mjs b/internal/dev-report-lifecycle.mjs index 3955b22c..86a420fa 100644 --- a/internal/dev-report-lifecycle.mjs +++ b/internal/dev-report-lifecycle.mjs @@ -17,11 +17,15 @@ export function findDeprecatedPublicEndpoints(text) { export function isDeprecatedEndpointAllowedInActiveReport(report, endpoint) { const legacyEndpoint = report?.runtimeSmoke?.legacyPublicEndpoint; + const deprecatedEndpoint = report?.deprecatedEndpoints?.find?.((item) => item?.endpoint === endpoint); return Boolean( - legacyEndpoint && + (legacyEndpoint && legacyEndpoint.endpoint === endpoint && legacyEndpoint.status === "deprecated" && - legacyEndpoint.activeGreenEligible === false + legacyEndpoint.activeGreenEligible === false) || + (deprecatedEndpoint && + String(deprecatedEndpoint.status ?? "").includes("deprecated") && + deprecatedEndpoint.activeGreenEligible === false) ); } diff --git a/reports/dev-gate/dev-m5-gate-aggregator-v2.json b/reports/dev-gate/dev-m5-gate-aggregator-v2.json index 9af7f926..dda7c15d 100644 --- a/reports/dev-gate/dev-m5-gate-aggregator-v2.json +++ b/reports/dev-gate/dev-m5-gate-aggregator-v2.json @@ -20,10 +20,27 @@ "pikasTech/HWLAB#46", "pikasTech/HWLAB#64" ], - "generatedAt": "2026-05-22T07:23:47.479Z", - "generatedFromCommit": "8e89409dda5d", + "generatedAt": "2026-05-22T11:50:42.733Z", + "generatedFromCommit": "f933a81c83a5", "environment": "dev", "endpoint": "http://74.48.78.17:16667", + "frontendEndpoint": "http://74.48.78.17:16666", + "activeEndpoints": { + "frontend": "http://74.48.78.17:16666/", + "apiLive": "http://74.48.78.17:16667/health/live" + }, + "deprecatedEndpoints": [ + { + "endpoint": "http://74.48.78.17:6666", + "status": "historical/deprecated", + "activeGreenEligible": false + }, + { + "endpoint": "http://74.48.78.17:6667", + "status": "historical/deprecated", + "activeGreenEligible": false + } + ], "devOnly": true, "prodDisabled": true, "reportLifecycle": { @@ -99,7 +116,7 @@ "taskId": "dev-m4-agent-loop", "lifecycleState": "active", "status": "blocked", - "commitId": "a1c3cb5" + "commitId": "8e89409" }, "devM5Gate": { "path": "reports/dev-gate/dev-mvp-gate-report.json", @@ -121,7 +138,35 @@ "overall": { "status": "blocked", "green": false, - "reason": "EDGE/ROUTE DEV-LIVE evidence exists on :16666/:16667, but M5 remains blocked by artifact source drift, DB live degradation, missing M3 trusted loop operation evidence, and blocked M4 agent-loop preflight." + "reason": "Frontend revision 1e8805664970839b72be40c34636b08f6d18b131 and EDGE/ROUTE DEV-LIVE evidence exist on :16666/:16667, but M5 remains blocked by artifact source drift, DB live degradation, missing M3 trusted loop operation evidence, and blocked M4 agent-loop preflight." + }, + "latestFrontendDevFact": { + "revision": "1e8805664970839b72be40c34636b08f6d18b131", + "sources": [ + "docs/dev-deploy-apply.md", + "docs/cloud-web-workbench.md", + "web/hwlab-cloud-web/index.html", + "web/hwlab-cloud-web/styles.css" + ], + "evidence": [ + "Cloud Web /health/live accepted revision 1e8805664970839b72be40c34636b08f6d18b131", + "Cloud Workbench public browser endpoint is the active frontend route only", + "Frontend load/revision evidence cannot satisfy DB, M3 hardware-loop, M4 agent-loop, or M5 MVP e2e acceptance" + ], + "commands": [ + "node web/hwlab-cloud-web/scripts/check.mjs", + "node scripts/dev-cloud-workbench-smoke.mjs --static" + ], + "summary": "#99/#108 Cloud Workbench revision 1e8805664970839b72be40c34636b08f6d18b131 is the latest accepted DEV frontend fact, but it is frontend-only evidence.", + "issue": "pikasTech/HWLAB#99", + "supports": [ + "pikasTech/HWLAB#99", + "pikasTech/HWLAB#108", + "pikasTech/HWLAB#78" + ], + "endpoint": "http://74.48.78.17:16666/", + "evidenceLevel": "DEV-LIVE", + "promotesM3M4M5": false }, "dod": { "status": "blocked", @@ -184,11 +229,23 @@ ] }, "currentDevLayering": { + "frontendRevision": { + "label": "Frontend DEV revision", + "status": "pass", + "evidenceLevel": "DEV-LIVE", + "summary": "http://74.48.78.17:16666/ serves the accepted Cloud Workbench frontend revision 1e8805664970839b72be40c34636b08f6d18b131; this is browser/frontend evidence only.", + "evidence": [ + "Cloud Web /health/live accepted revision 1e8805664970839b72be40c34636b08f6d18b131", + "Cloud Workbench public browser endpoint is the active frontend route only", + "Frontend load/revision evidence cannot satisfy DB, M3 hardware-loop, M4 agent-loop, or M5 MVP e2e acceptance" + ], + "nextRequired": "Keep frontend revision proof separate from DB live readiness, M3 hardware-loop evidence, M4 agent-loop evidence, and M5 acceptance." + }, "edgeRoute": { "label": "EDGE/ROUTE live", "status": "pass", "evidenceLevel": "DEV-LIVE", - "summary": "16666 browser, 16667 /health, and 16667 /health/live returned accepted HWLAB DEV responses in the active M2 read-only smoke.", + "summary": "http://74.48.78.17:16666/, http://74.48.78.17:16667/health, and http://74.48.78.17:16667/health/live returned accepted HWLAB DEV responses in the active M2 read-only smoke.", "evidence": [ "http://74.48.78.17:16667/health -> HTTP 200 identity=hwlab-edge-proxy status=ok", "http://74.48.78.17:16667/health/live -> HTTP 200 identity=hwlab-cloud-api status=degraded", @@ -245,6 +302,103 @@ "nextRequired": "Refresh artifact/source coverage for current origin/main and keep desired-state apply separate from read-only route proof." } }, + "milestoneLevelClassification": [ + { + "milestone": "M0", + "currentLevel": "SOURCE", + "status": "pass", + "strongestEvidenceLevel": "SOURCE", + "liveEvidence": "missing_or_blocked", + "summary": "Source contract is green at source level only." + }, + { + "milestone": "M1", + "currentLevel": "LOCAL", + "status": "pass", + "strongestEvidenceLevel": "LOCAL", + "liveEvidence": "missing_or_blocked", + "summary": "Local smoke is green; it is not DEV-LIVE." + }, + { + "milestone": "M2", + "currentLevel": "DEV-LIVE", + "status": "blocked", + "strongestEvidenceLevel": "DEV-LIVE", + "liveEvidence": "pass", + "summary": "Current public frontend/API route evidence is DEV-LIVE for route/front-end reachability only." + }, + { + "milestone": "M3", + "currentLevel": "BLOCKED", + "status": "blocked", + "strongestEvidenceLevel": "LOCAL", + "liveEvidence": "missing_or_blocked", + "summary": "DEV-LIVE hardware trusted loop is blocked; local/source shape is not acceptance." + }, + { + "milestone": "M4", + "currentLevel": "BLOCKED", + "status": "blocked", + "strongestEvidenceLevel": "DRY-RUN", + "liveEvidence": "missing_or_blocked", + "summary": "DEV-LIVE agent loop is blocked at DB live readiness; local smoke is not acceptance." + }, + { + "milestone": "M5", + "currentLevel": "BLOCKED", + "status": "blocked", + "strongestEvidenceLevel": "DRY-RUN", + "liveEvidence": "missing_or_blocked", + "summary": "Dry-run is green, but bounded DEV-LIVE MVP e2e is blocked." + } + ], + "milestoneBlockerClassification": [ + { + "milestone": "M3", + "status": "blocked", + "currentLevel": "BLOCKED", + "blockerClass": "hardware-loop-runtime", + "dependency": "Real DEV trusted loop through res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1.", + "evidence": [ + "operationId=not_observed", + "traceId=not_observed", + "auditId=not_observed", + "evidenceId=not_observed" + ], + "nextRequired": "Run the bounded DEV M3 live smoke only after patch-panel topology can prove operation, trace, audit, and evidence IDs.", + "nonPromotionReason": "Public frontend, route, and artifact evidence do not prove the required hardware loop." + }, + { + "milestone": "M4", + "status": "blocked", + "currentLevel": "BLOCKED", + "blockerClass": "db-live-readiness", + "dependency": "Cloud API /health/live must report DB ready=true, connected=true, and liveDbEvidence=true before live agent scheduling/evidence closure.", + "evidence": [ + "db.status=degraded", + "db.ready=false", + "db.connected=false", + "db.liveDbEvidence=false" + ], + "nextRequired": "Repair DB live readiness and rerun the M4 live preflight without scheduling a DEV agent task before preconditions pass.", + "nonPromotionReason": "Frontend revision and read-only route reachability do not prove DB-backed agent runtime readiness." + }, + { + "milestone": "M5", + "status": "blocked", + "currentLevel": "BLOCKED", + "blockerClass": "composite-db-m3-m4-live", + "dependency": "M5 needs DB live readiness, M3 trusted-loop DEV evidence, M4 live preflight/evidence closure, and current source/artifact coverage.", + "evidence": [ + "M5 dry-run is green", + "db.ready=false", + "m3.live=false", + "m4.live=false" + ], + "nextRequired": "After DB/M3/M4 blockers are cleared, run only the bounded DEV MVP live gate command with explicit DEV/non-PROD confirmations.", + "nonPromotionReason": "No frontend, route-only, local, or dry-run evidence is allowed to stand in for bounded DEV-LIVE MVP e2e acceptance." + } + ], "milestones": [ { "id": "M0", @@ -269,7 +423,7 @@ "status": "blocked", "highestVisibleLevel": "DEV-LIVE", "liveEvidence": "pass", - "evidenceCount": 6, + "evidenceCount": 7, "blockerCount": 5, "summary": "deploy/runtime readiness is blocked before live DEV; highest visible level is DEV-LIVE; status is blocked." }, @@ -285,11 +439,11 @@ { "id": "M4", "status": "blocked", - "highestVisibleLevel": "LOCAL", + "highestVisibleLevel": "DRY-RUN", "liveEvidence": "missing_or_blocked", "evidenceCount": 3, "blockerCount": 2, - "summary": "agent loop has local smoke but live preflight is blocked; highest visible level is LOCAL; status is blocked." + "summary": "agent loop has local smoke but live preflight is blocked; highest visible level is DRY-RUN; status is blocked." }, { "id": "M5", @@ -340,6 +494,31 @@ ], "summary": "Local skeleton smoke covers cloud API, simulators, patch-panel routing, CLI dry-run boundary, and no DEV/PROD mutation." }, + { + "milestone": "M2", + "issue": "pikasTech/HWLAB#99", + "taskId": "cloud-web-workbench-frontend", + "lifecycleState": "active", + "level": "DEV-LIVE", + "status": "pass", + "category": "frontend-dev-revision", + "sources": [ + "docs/dev-deploy-apply.md", + "docs/cloud-web-workbench.md", + "web/hwlab-cloud-web/index.html", + "web/hwlab-cloud-web/styles.css" + ], + "commands": [ + "node web/hwlab-cloud-web/scripts/check.mjs", + "node scripts/dev-cloud-workbench-smoke.mjs --static" + ], + "evidence": [ + "Cloud Web /health/live accepted revision 1e8805664970839b72be40c34636b08f6d18b131", + "Cloud Workbench public browser endpoint is the active frontend route only", + "Frontend load/revision evidence cannot satisfy DB, M3 hardware-loop, M4 agent-loop, or M5 MVP e2e acceptance" + ], + "summary": "#99/#108 Cloud Workbench revision 1e8805664970839b72be40c34636b08f6d18b131 is the latest accepted DEV frontend fact, but it is frontend-only evidence." + }, { "milestone": "M2", "issue": "pikasTech/HWLAB#34", @@ -552,7 +731,7 @@ "issue": "pikasTech/HWLAB#37", "taskId": "dev-m4-agent-loop", "reportPath": "reports/dev-gate/dev-m4-agent-loop.json", - "commitId": "a1c3cb5", + "commitId": "8e89409", "lifecycleState": "active", "level": "LOCAL", "status": "pass", @@ -571,25 +750,31 @@ "issue": "pikasTech/HWLAB#37", "taskId": "dev-m4-agent-loop", "reportPath": "reports/dev-gate/dev-m4-agent-loop.json", - "commitId": "a1c3cb5", + "commitId": "8e89409", "lifecycleState": "active", "level": "DRY-RUN", - "status": "not_run", + "status": "pass", "category": "agent-loop-dry-run", "commands": [ "node scripts/dev-m4-agent-loop-smoke.mjs --dry-run" ], "evidence": [ - "No dry-run output is attached to the live preflight report." + "hwlab-agent-mgr:session=agt_m4_agent_loop_01:created=queued:final=cleanup", + "hwlab-agent-worker:session=wkr_agt_m4_agent_loop_01:status=cleanup", + "workspace:vol_agt_m4_agent_loop_01:cleaned=true:existsAfterCleanup=false", + "hwlab-agent-skills:commit=6509a35:version=v1", + "trace:trc_agt_m4_agent_loop_01:events=5", + "evidence:evi_agt_m4_agent_loop_01:kind=report", + "cleanup:cln_agt_m4_agent_loop_01:removed=true" ], - "summary": "The live preflight report does not attempt a dry-run agent run." + "summary": "Local dry-run covered agent manager, worker, workspace isolation, skills commit, trace, evidence, and cleanup without live DEV mutation." }, { "milestone": "M4", "issue": "pikasTech/HWLAB#37", "taskId": "dev-m4-agent-loop", "reportPath": "reports/dev-gate/dev-m4-agent-loop.json", - "commitId": "a1c3cb5", + "commitId": "8e89409", "lifecycleState": "active", "level": "BLOCKED", "status": "blocked", @@ -740,10 +925,10 @@ "issue": "pikasTech/HWLAB#37", "taskId": "dev-m4-agent-loop", "lifecycleState": "active", - "status": "not_run", + "status": "pass", "category": "agent-loop-dry-run", "reportPath": "reports/dev-gate/dev-m4-agent-loop.json", - "summary": "The live preflight report does not attempt a dry-run agent run." + "summary": "Local dry-run covered agent manager, worker, workspace isolation, skills commit, trace, evidence, and cleanup without live DEV mutation." }, { "milestone": "M5", @@ -757,6 +942,15 @@ } ], "DEV-LIVE": [ + { + "milestone": "M2", + "issue": "pikasTech/HWLAB#99", + "taskId": "cloud-web-workbench-frontend", + "lifecycleState": "active", + "status": "pass", + "category": "frontend-dev-revision", + "summary": "#99/#108 Cloud Workbench revision 1e8805664970839b72be40c34636b08f6d18b131 is the latest accepted DEV frontend fact, but it is frontend-only evidence." + }, { "milestone": "M2", "issue": "pikasTech/HWLAB#23", diff --git a/reports/dev-gate/dev-m5-gate-aggregator-v2.md b/reports/dev-gate/dev-m5-gate-aggregator-v2.md index 79781e2d..b24f26f1 100644 --- a/reports/dev-gate/dev-m5-gate-aggregator-v2.md +++ b/reports/dev-gate/dev-m5-gate-aggregator-v2.md @@ -1,23 +1,42 @@ # HWLAB M5 DEV Gate Aggregator v2 Status: blocked -Generated from: `8e89409dda5d` +Generated from: `f933a81c83a5` Scope: DEV only, report-only +Active frontend: `http://74.48.78.17:16666/` +Active API/live: `http://74.48.78.17:16667/health/live` +Deprecated public endpoints: `http://74.48.78.17:6666`, `http://74.48.78.17:6667` ## Summary -EDGE/ROUTE DEV-LIVE evidence exists on :16666/:16667, but M5 remains blocked by artifact source drift, DB live degradation, missing M3 trusted loop operation evidence, and blocked M4 agent-loop preflight. +Frontend revision 1e8805664970839b72be40c34636b08f6d18b131 and EDGE/ROUTE DEV-LIVE evidence exist on :16666/:16667, but M5 remains blocked by artifact source drift, DB live degradation, missing M3 trusted loop operation evidence, and blocked M4 agent-loop preflight. + +## Frontend DEV Fact + +The latest accepted #99/#108 frontend DEV fact is revision `1e8805664970839b72be40c34636b08f6d18b131` at `http://74.48.78.17:16666/`. This is DEV-LIVE browser/frontend evidence only and does not promote M3, M4, or M5. ## Current DEV Layering | Layer | Status | Evidence level | Current conclusion | Required next proof | | --- | --- | --- | --- | --- | -| EDGE/ROUTE live | pass | DEV-LIVE | 16666 browser, 16667 /health, and 16667 /health/live returned accepted HWLAB DEV responses in the active M2 read-only smoke. | Keep this separated from DB readiness, M3/M4 loop evidence, and M5 acceptance. | +| Frontend DEV revision | pass | DEV-LIVE | http://74.48.78.17:16666/ serves the accepted Cloud Workbench frontend revision 1e8805664970839b72be40c34636b08f6d18b131; this is browser/frontend evidence only. | Keep frontend revision proof separate from DB live readiness, M3 hardware-loop evidence, M4 agent-loop evidence, and M5 acceptance. | +| EDGE/ROUTE live | pass | DEV-LIVE | http://74.48.78.17:16666/, http://74.48.78.17:16667/health, and http://74.48.78.17:16667/health/live returned accepted HWLAB DEV responses in the active M2 read-only smoke. | Keep this separated from DB readiness, M3/M4 loop evidence, and M5 acceptance. | | DB live/degraded | blocked | BLOCKED | cloud-api DB status=degraded; configReady=true; ready=false; connected=false; liveDbEvidence=false. | Provide live DB connection evidence through redacted health output; route reachability alone is insufficient. | | M3 hardware trusted loop | blocked | BLOCKED | No live DEV operation has run yet. Blocker: patch-panel active DO1 -> DI1 connection missing. | Only a real DEV res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1 observation with operation/trace/audit/evidence can clear M3. | | M4 agent loop | blocked | BLOCKED | Blocked at DB live readiness before scheduling a DEV agent task. | Do not schedule or claim the agent loop as live until DB live and required runtime/evidence preconditions pass. | | artifact/desired-state source | blocked | BLOCKED | artifact targetCovered=false; artifactSource=7e29522b65c8; target=8e89409dda5d; desiredApplyMode=dry-run; mutationAttempted=false. | Refresh artifact/source coverage for current origin/main and keep desired-state apply separate from read-only route proof. | +## M0-M5 Level Classification + +| Milestone | Current classification | Status | Strongest evidence | Live evidence | Summary | +| --- | --- | --- | --- | --- | --- | +| M0 | SOURCE | pass | SOURCE | missing_or_blocked | Source contract is green at source level only. | +| M1 | LOCAL | pass | LOCAL | missing_or_blocked | Local smoke is green; it is not DEV-LIVE. | +| M2 | DEV-LIVE | blocked | DEV-LIVE | pass | Current public frontend/API route evidence is DEV-LIVE for route/front-end reachability only. | +| M3 | BLOCKED | blocked | LOCAL | missing_or_blocked | DEV-LIVE hardware trusted loop is blocked; local/source shape is not acceptance. | +| M4 | BLOCKED | blocked | DRY-RUN | missing_or_blocked | DEV-LIVE agent loop is blocked at DB live readiness; local smoke is not acceptance. | +| M5 | BLOCKED | blocked | DRY-RUN | missing_or_blocked | Dry-run is green, but bounded DEV-LIVE MVP e2e is blocked. | + ## Milestones | Milestone | Status | Highest visible level | Live evidence | Summary | @@ -26,7 +45,7 @@ EDGE/ROUTE DEV-LIVE evidence exists on :16666/:16667, but M5 remains blocked by | M1 | pass | LOCAL | missing_or_blocked | local smoke is available; highest visible level is LOCAL; status is pass. | | M2 | blocked | DEV-LIVE | pass | deploy/runtime readiness is blocked before live DEV; highest visible level is DEV-LIVE; status is blocked. | | M3 | blocked | LOCAL | missing_or_blocked | hardware loop has source/local shape but no live operation; highest visible level is LOCAL; status is blocked. | -| M4 | blocked | LOCAL | missing_or_blocked | agent loop has local smoke but live preflight is blocked; highest visible level is LOCAL; status is blocked. | +| M4 | blocked | DRY-RUN | missing_or_blocked | agent loop has local smoke but live preflight is blocked; highest visible level is DRY-RUN; status is blocked. | | M5 | blocked | DRY-RUN | missing_or_blocked | dry-run is green but live MVP gate is blocked; highest visible level is DRY-RUN; status is blocked. | ## #9 DoD Checks @@ -43,6 +62,14 @@ EDGE/ROUTE DEV-LIVE evidence exists on :16666/:16667, but M5 remains blocked by | m4-agent-loop-live | blocked | BLOCKED | M4 agent loop live path is blocked before accepted agent scheduling/evidence closure. | | m5-mvp-dev-live | blocked | BLOCKED | M5 dry-run passed; bounded DEV-LIVE MVP e2e has not passed. | +## M3/M4/M5 Blocker Classification + +| Milestone | Status | Current level | Blocker class | Dependency | Required next proof | +| --- | --- | --- | --- | --- | --- | +| M3 | blocked | BLOCKED | hardware-loop-runtime | Real DEV trusted loop through res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1. | Run the bounded DEV M3 live smoke only after patch-panel topology can prove operation, trace, audit, and evidence IDs. | +| M4 | blocked | BLOCKED | db-live-readiness | Cloud API /health/live must report DB ready=true, connected=true, and liveDbEvidence=true before live agent scheduling/evidence closure. | Repair DB live readiness and rerun the M4 live preflight without scheduling a DEV agent task before preconditions pass. | +| M5 | blocked | BLOCKED | composite-db-m3-m4-live | M5 needs DB live readiness, M3 trusted-loop DEV evidence, M4 live preflight/evidence closure, and current source/artifact coverage. | After DB/M3/M4 blockers are cleared, run only the bounded DEV MVP live gate command with explicit DEV/non-PROD confirmations. | + ## Blockers | Priority | Order | Type | Scope | Summary | diff --git a/scripts/src/dev-evidence-blocker-aggregator.mjs b/scripts/src/dev-evidence-blocker-aggregator.mjs index ad95707d..a7bf116b 100644 --- a/scripts/src/dev-evidence-blocker-aggregator.mjs +++ b/scripts/src/dev-evidence-blocker-aggregator.mjs @@ -9,8 +9,13 @@ import { DEV_ENDPOINT, DEV_FRONTEND_ENDPOINT, ENVIRONMENT_DEV, SERVICE_IDS } fro export const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); -const deprecatedLegacyPublicPort = 6000 + 667; -const deprecatedLegacyPublicEndpoint = `http://74.48.78.17:${deprecatedLegacyPublicPort}`; +const activeBrowserRoot = `${DEV_FRONTEND_ENDPOINT}/`; +const activeApiLiveEndpoint = `${DEV_ENDPOINT}/health/live`; +const deprecatedLegacyPublicEndpoints = Object.freeze([ + "http://74.48.78.17:6666", + "http://74.48.78.17:6667" +]); +const latestFrontendRevision = "1e8805664970839b72be40c34636b08f6d18b131"; const levels = Object.freeze(["SOURCE", "LOCAL", "DRY-RUN", "DEV-LIVE", "BLOCKED"]); const statusRank = Object.freeze({ pass: 0, @@ -95,6 +100,26 @@ const sourceContracts = Object.freeze([ } ]); +const frontendDevFact = Object.freeze({ + revision: latestFrontendRevision, + sources: [ + "docs/dev-deploy-apply.md", + "docs/cloud-web-workbench.md", + "web/hwlab-cloud-web/index.html", + "web/hwlab-cloud-web/styles.css" + ], + evidence: [ + `Cloud Web /health/live accepted revision ${latestFrontendRevision}`, + "Cloud Workbench public browser endpoint is the active frontend route only", + "Frontend load/revision evidence cannot satisfy DB, M3 hardware-loop, M4 agent-loop, or M5 MVP e2e acceptance" + ], + commands: [ + "node web/hwlab-cloud-web/scripts/check.mjs", + "node scripts/dev-cloud-workbench-smoke.mjs --static" + ], + summary: `#99/#108 Cloud Workbench revision ${latestFrontendRevision} is the latest accepted DEV frontend fact, but it is frontend-only evidence.` +}); + function issue(id) { return `pikasTech/HWLAB#${id}`; } @@ -356,6 +381,19 @@ function collectM2Evidence(reports) { const m2EndpointLive = hasCurrentM2EndpointEvidence(m2Smoke); return [ + { + milestone: "M2", + issue: issue(99), + taskId: "cloud-web-workbench-frontend", + lifecycleState: "active", + level: "DEV-LIVE", + status: "pass", + category: "frontend-dev-revision", + sources: frontendDevFact.sources, + commands: frontendDevFact.commands, + evidence: frontendDevFact.evidence, + summary: frontendDevFact.summary + }, reportEvidence({ milestone: "M2", level: "SOURCE", @@ -622,7 +660,7 @@ function publicEndpointEvidence(m2Report) { function isStaleLegacyIngressBlocker(blocker, sourceReport, reports) { const text = `${blocker.scope ?? ""} ${blocker.summary ?? ""}`; - const staleLegacyPort = text.includes(deprecatedLegacyPublicEndpoint); + const staleLegacyPort = deprecatedLegacyPublicEndpoints.some((endpoint) => text.includes(endpoint)); const stalePreflightEdgeProbe = sourceReport.path === reportPaths.devPreflight && blocker.type === "network_blocker" && (blocker.scope === "dev-edge" || blocker.scope === "dev-edge-health") && @@ -690,6 +728,34 @@ function summarizeMilestone(milestone, highestVisibleLevel, status) { return `${labels[milestone]}; highest visible level is ${highestVisibleLevel}; status is ${status}.`; } +function buildMilestoneLevelClassification(milestones) { + const currentLabels = { + M0: "SOURCE", + M1: "LOCAL", + M2: "DEV-LIVE", + M3: "BLOCKED", + M4: "BLOCKED", + M5: "BLOCKED" + }; + const notes = { + M0: "Source contract is green at source level only.", + M1: "Local smoke is green; it is not DEV-LIVE.", + M2: "Current public frontend/API route evidence is DEV-LIVE for route/front-end reachability only.", + M3: "DEV-LIVE hardware trusted loop is blocked; local/source shape is not acceptance.", + M4: "DEV-LIVE agent loop is blocked at DB live readiness; local smoke is not acceptance.", + M5: "Dry-run is green, but bounded DEV-LIVE MVP e2e is blocked." + }; + + return milestones.map((milestone) => ({ + milestone: milestone.id, + currentLevel: currentLabels[milestone.id], + status: milestone.status, + strongestEvidenceLevel: milestone.highestVisibleLevel, + liveEvidence: milestone.liveEvidence, + summary: notes[milestone.id] + })); +} + function groupByLevel(evidence, blockers) { const grouped = Object.fromEntries(levels.map((level) => [level, []])); for (const item of evidence) { @@ -836,13 +902,21 @@ function buildCurrentDevLayering(reports, blockers) { const artifactSourceStates = artifactSourceStateCounts(reports.devArtifacts); return { + frontendRevision: { + label: "Frontend DEV revision", + status: "pass", + evidenceLevel: "DEV-LIVE", + summary: `${activeBrowserRoot} serves the accepted Cloud Workbench frontend revision ${latestFrontendRevision}; this is browser/frontend evidence only.`, + evidence: frontendDevFact.evidence, + nextRequired: "Keep frontend revision proof separate from DB live readiness, M3 hardware-loop evidence, M4 agent-loop evidence, and M5 acceptance." + }, edgeRoute: { label: "EDGE/ROUTE live", status: m2EndpointLive || edgeLive ? "pass" : "blocked", evidenceLevel: m2EndpointLive || edgeLive ? "DEV-LIVE" : "BLOCKED", summary: m2EndpointLive - ? "16666 browser, 16667 /health, and 16667 /health/live returned accepted HWLAB DEV responses in the active M2 read-only smoke." - : "No active read-only public endpoint report proves both 16666 and 16667.", + ? `${activeBrowserRoot}, ${DEV_ENDPOINT}/health, and ${activeApiLiveEndpoint} returned accepted HWLAB DEV responses in the active M2 read-only smoke.` + : `No active read-only public endpoint report proves both ${activeBrowserRoot} and ${activeApiLiveEndpoint}.`, evidence: publicEndpointEvidence(reports.devM2Smoke), nextRequired: "Keep this separated from DB readiness, M3/M4 loop evidence, and M5 acceptance." }, @@ -890,6 +964,60 @@ function buildCurrentDevLayering(reports, blockers) { }; } +function buildMilestoneBlockerClassification(reports) { + const cloudDb = cloudApiDbStatus(reports); + const m3Live = statusIsPass(reports.devM3Hardware.liveOperation?.status); + const m4Live = statusIsPass(reports.devM4Agent.livePreflight?.status); + + return [ + { + milestone: "M3", + status: m3Live ? "pass" : "blocked", + currentLevel: m3Live ? "DEV-LIVE" : "BLOCKED", + blockerClass: m3Live ? "cleared" : "hardware-loop-runtime", + dependency: "Real DEV trusted loop through res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1.", + evidence: [ + `operationId=${reports.devM3Hardware.liveOperation?.operationId ?? "not_observed"}`, + `traceId=${reports.devM3Hardware.liveOperation?.traceId ?? "not_observed"}`, + `auditId=${reports.devM3Hardware.liveOperation?.auditId ?? "not_observed"}`, + `evidenceId=${reports.devM3Hardware.liveOperation?.evidenceId ?? "not_observed"}` + ], + nextRequired: "Run the bounded DEV M3 live smoke only after patch-panel topology can prove operation, trace, audit, and evidence IDs.", + nonPromotionReason: "Public frontend, route, and artifact evidence do not prove the required hardware loop." + }, + { + milestone: "M4", + status: m4Live ? "pass" : "blocked", + currentLevel: m4Live ? "DEV-LIVE" : "BLOCKED", + blockerClass: m4Live ? "cleared" : "db-live-readiness", + dependency: "Cloud API /health/live must report DB ready=true, connected=true, and liveDbEvidence=true before live agent scheduling/evidence closure.", + evidence: [ + `db.status=${cloudDb.status}`, + `db.ready=${cloudDb.ready}`, + `db.connected=${cloudDb.connected}`, + `db.liveDbEvidence=${cloudDb.liveDbEvidence}` + ], + nextRequired: "Repair DB live readiness and rerun the M4 live preflight without scheduling a DEV agent task before preconditions pass.", + nonPromotionReason: "Frontend revision and read-only route reachability do not prove DB-backed agent runtime readiness." + }, + { + milestone: "M5", + status: "blocked", + currentLevel: "BLOCKED", + blockerClass: "composite-db-m3-m4-live", + dependency: "M5 needs DB live readiness, M3 trusted-loop DEV evidence, M4 live preflight/evidence closure, and current source/artifact coverage.", + evidence: [ + "M5 dry-run is green", + `db.ready=${cloudDb.ready}`, + `m3.live=${m3Live}`, + `m4.live=${m4Live}` + ], + nextRequired: "After DB/M3/M4 blockers are cleared, run only the bounded DEV MVP live gate command with explicit DEV/non-PROD confirmations.", + nonPromotionReason: "No frontend, route-only, local, or dry-run evidence is allowed to stand in for bounded DEV-LIVE MVP e2e acceptance." + } + ]; +} + function artifactSourceStateCounts(artifactReport) { const counts = { sourcePresent: 0, intentionallyDisabled: 0 }; for (const service of artifactReport.artifactPublish?.services ?? []) { @@ -964,9 +1092,24 @@ function validateReport(report) { assert.equal(report.issue, issue(58), "issue"); assert.equal(report.environment, ENVIRONMENT_DEV, "environment"); assert.equal(report.endpoint, DEV_ENDPOINT, "endpoint"); + assert.equal(report.frontendEndpoint, DEV_FRONTEND_ENDPOINT, "frontendEndpoint"); + assert.equal(report.activeEndpoints.frontend, activeBrowserRoot, "activeEndpoints.frontend"); + assert.equal(report.activeEndpoints.apiLive, activeApiLiveEndpoint, "activeEndpoints.apiLive"); assert.equal(report.devOnly, true, "devOnly"); assert.equal(report.prodDisabled, true, "prodDisabled"); assert.deepEqual(Object.keys(report.levels), [...levels], "level keys"); + assert.equal(report.latestFrontendDevFact.revision, latestFrontendRevision, "latestFrontendDevFact.revision"); + assert.equal(report.latestFrontendDevFact.promotesM3M4M5, false, "frontend fact cannot promote M3/M4/M5"); + assert.deepEqual( + report.milestoneLevelClassification.map((item) => item.milestone), + ["M0", "M1", "M2", "M3", "M4", "M5"], + "milestoneLevelClassification" + ); + assert.deepEqual( + report.milestoneBlockerClassification.map((item) => item.milestone), + ["M3", "M4", "M5"], + "milestoneBlockerClassification" + ); assert.ok(report.blockers.length >= 1, "must remain blocked without DEV-LIVE evidence"); assert.equal(report.overall.status, "blocked", "overall status"); assert.ok(report.nextSteps.length >= 1, "next steps required"); @@ -994,8 +1137,10 @@ export async function buildReport() { ]; const blockers = collectBlockers(reports); const milestones = deriveMilestones(evidence, blockers); + const milestoneLevelClassification = buildMilestoneLevelClassification(milestones); const dod = buildDoD(reports, milestones, blockers); const currentDevLayering = buildCurrentDevLayering(reports, blockers); + const milestoneBlockerClassification = buildMilestoneBlockerClassification(reports); const nextSteps = buildNextSteps(blockers); const report = { "$schema": "https://hwlab.pikastech.local/schemas/dev-m5-gate-aggregator-v2.schema.json", @@ -1008,6 +1153,16 @@ export async function buildReport() { generatedFromCommit: gitCommit(), environment: ENVIRONMENT_DEV, endpoint: DEV_ENDPOINT, + frontendEndpoint: DEV_FRONTEND_ENDPOINT, + activeEndpoints: { + frontend: activeBrowserRoot, + apiLive: activeApiLiveEndpoint + }, + deprecatedEndpoints: deprecatedLegacyPublicEndpoints.map((endpoint) => ({ + endpoint, + status: "historical/deprecated", + activeGreenEligible: false + })), devOnly: true, prodDisabled: true, reportLifecycle: activeReportLifecycle( @@ -1041,10 +1196,20 @@ export async function buildReport() { green: dod.green, reason: dod.green ? "All #9 DEV DoD checks are green." - : "EDGE/ROUTE DEV-LIVE evidence exists on :16666/:16667, but M5 remains blocked by artifact source drift, DB live degradation, missing M3 trusted loop operation evidence, and blocked M4 agent-loop preflight." + : `Frontend revision ${latestFrontendRevision} and EDGE/ROUTE DEV-LIVE evidence exist on :16666/:16667, but M5 remains blocked by artifact source drift, DB live degradation, missing M3 trusted loop operation evidence, and blocked M4 agent-loop preflight.` + }, + latestFrontendDevFact: { + ...frontendDevFact, + issue: issue(99), + supports: [issue(99), issue(108), issue(78)], + endpoint: activeBrowserRoot, + evidenceLevel: "DEV-LIVE", + promotesM3M4M5: false }, dod, currentDevLayering, + milestoneLevelClassification, + milestoneBlockerClassification, milestones, evidence, levels: groupByLevel(evidence, blockers), @@ -1064,6 +1229,11 @@ export function formatCheckSummary(report) { status: report.overall.status, green: report.overall.green, blockers: report.blockers.length, + activeEndpoints: report.activeEndpoints, + frontendRevision: report.latestFrontendDevFact.revision, + m3m4m5: Object.fromEntries( + report.milestoneBlockerClassification.map((item) => [item.milestone, item.status]) + ), nextStep: report.nextSteps[0]?.action ?? null, levels: Object.fromEntries( Object.entries(report.levels).map(([level, entries]) => [level, entries.length]) @@ -1075,12 +1245,18 @@ export function renderMarkdown(report) { const layeringLines = Object.entries(report.currentDevLayering) .map(([, layer]) => `| ${layer.label} | ${layer.status} | ${layer.evidenceLevel} | ${layer.summary} | ${layer.nextRequired} |`) .join("\n"); + const milestoneLevelLines = report.milestoneLevelClassification + .map((item) => `| ${item.milestone} | ${item.currentLevel} | ${item.status} | ${item.strongestEvidenceLevel} | ${item.liveEvidence} | ${item.summary} |`) + .join("\n"); const milestoneLines = report.milestones .map((milestone) => `| ${milestone.id} | ${milestone.status} | ${milestone.highestVisibleLevel} | ${milestone.liveEvidence} | ${milestone.summary} |`) .join("\n"); const dodLines = report.dod.checks .map((check) => `| ${check.id} | ${check.status} | ${check.evidenceLevel} | ${check.summary} |`) .join("\n"); + const blockerClassificationLines = report.milestoneBlockerClassification + .map((item) => `| ${item.milestone} | ${item.status} | ${item.currentLevel} | ${item.blockerClass} | ${item.dependency} | ${item.nextRequired} |`) + .join("\n"); const blockerLines = report.blockers .map((blocker) => `| ${blocker.priority} | ${blocker.unblockOrder} | ${blocker.type} | ${blocker.scope} | ${blocker.summary} |`) .join("\n"); @@ -1093,17 +1269,30 @@ export function renderMarkdown(report) { Status: ${report.overall.status} Generated from: \`${report.generatedFromCommit}\` Scope: DEV only, report-only +Active frontend: \`${report.activeEndpoints.frontend}\` +Active API/live: \`${report.activeEndpoints.apiLive}\` +Deprecated public endpoints: ${report.deprecatedEndpoints.map((item) => `\`${item.endpoint}\``).join(", ")} ## Summary ${report.overall.reason} +## Frontend DEV Fact + +The latest accepted #99/#108 frontend DEV fact is revision \`${report.latestFrontendDevFact.revision}\` at \`${report.latestFrontendDevFact.endpoint}\`. This is ${report.latestFrontendDevFact.evidenceLevel} browser/frontend evidence only and does not promote M3, M4, or M5. + ## Current DEV Layering | Layer | Status | Evidence level | Current conclusion | Required next proof | | --- | --- | --- | --- | --- | ${layeringLines} +## M0-M5 Level Classification + +| Milestone | Current classification | Status | Strongest evidence | Live evidence | Summary | +| --- | --- | --- | --- | --- | --- | +${milestoneLevelLines} + ## Milestones | Milestone | Status | Highest visible level | Live evidence | Summary | @@ -1116,6 +1305,12 @@ ${milestoneLines} | --- | --- | --- | --- | ${dodLines} +## M3/M4/M5 Blocker Classification + +| Milestone | Status | Current level | Blocker class | Dependency | Required next proof | +| --- | --- | --- | --- | --- | --- | +${blockerClassificationLines} + ## Blockers | Priority | Order | Type | Scope | Summary |