docs: refresh M5 live gate aggregator
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
Reference in New Issue
Block a user