diff --git a/docs/artifact-catalog.md b/docs/artifact-catalog.md index 3d8f4468..7c39383f 100644 --- a/docs/artifact-catalog.md +++ b/docs/artifact-catalog.md @@ -64,8 +64,9 @@ rules: The catalog `commitId` is the artifact source commit, not proof that a registry artifact exists. It must match `deploy/deploy.json`, every service `commitId`, -and the image tag. If it does not match the selected source ref, the DEV gate -preflight reports `artifact-source-commit` as a blocker. +and the image tag. If a later target ref changes artifact build inputs after the +publish source, the DEV gate preflight may reopen `artifact-source-commit` even +when the base-image blocker is already closed. ## Refresh Workflow diff --git a/docs/dev-artifact-publish.md b/docs/dev-artifact-publish.md index 546417f9..d121e607 100644 --- a/docs/dev-artifact-publish.md +++ b/docs/dev-artifact-publish.md @@ -141,6 +141,13 @@ remain `status: "blocked"`. Do not turn a base-image or registry blocker into a fake digest or published state. Do not treat runner-process loopback HTTP failure as a publish failure by itself. +Current rebaseline: the committed DEV artifact report is `status: "published"` +for source commit `73b379f`, with `baseImagePreflight.status: "ready"`, +`baseImage: "node:20-bookworm-slim"`, and 13/13 required services carrying +real registry digests. If a later read-only runner cannot fetch catalog +manifests from `127.0.0.1:5000`, treat that as a `#66` registry reachability +dimension, not as a missing base-image or missing-publish blocker. + ## Known Implementation States - `repo-entrypoint`: the repository has `cmd//main.mjs`. diff --git a/docs/dev-base-image-preflight.md b/docs/dev-base-image-preflight.md index 12b4af56..28b9e53a 100644 --- a/docs/dev-base-image-preflight.md +++ b/docs/dev-base-image-preflight.md @@ -13,15 +13,21 @@ PROD, read secrets, or use UniDesk runtime services as substitutes. - `deploy/deploy.json` and `deploy/artifact-catalog.dev.json` pin service image names to the DEV registry target, by default `127.0.0.1:5000/hwlab/:`. -- The artifact catalog is `contract-skeleton` only. Service entries must keep - `publishState: "skeleton-only"` and `digest: "not_published"` until real - publish evidence exists. +- The artifact catalog may be either `contract-skeleton` or `published`. A + `published` catalog must be backed by `reports/dev-gate/dev-artifacts.json` + with real `sha256:<64 hex>` digests for every required service. - The catalog and runtime boundary forbid PROD deployment, secret reads, force push, real publish claims, and UniDesk runtime substitution. - A builder base image is separate from HWLAB service artifact images. This preflight only decides whether #35 may proceed to build/publish; it does not prove that any service image was published. +Current rebaseline: `reports/dev-gate/dev-artifacts.json` records +`baseImagePreflight.status: "ready"` for local `node:20-bookworm-slim` and +13/13 published DEV artifacts from source commit `73b379f`. A failed catalog +manifest read from a runner process is a registry reachability question for +`#66`, not proof that the base image or publish digests are missing. + ## Command ```sh diff --git a/docs/dev-evidence-blocker-aggregator.md b/docs/dev-evidence-blocker-aggregator.md index dffaaaab..8ec9c8e5 100644 --- a/docs/dev-evidence-blocker-aggregator.md +++ b/docs/dev-evidence-blocker-aggregator.md @@ -69,22 +69,27 @@ The report is blocked until real DEV-LIVE evidence is attached for the DEV route and downstream HWLAB runtime services. Current source, local, and dry-run contracts are useful readiness signals, but they are not live DEV proof. +The legacy base-image blocker is not current when the committed reports show an +approved Node 20 builder base. Artifact/current remains stricter: a target ref +can still keep `artifact-source-commit` or `dev-artifact-publish` open when it +changes artifact build inputs after the publish source commit, even if the +older DEV artifact report contains 13/13 published service digests. Registry +manifest reachability remains separate and belongs to the #66 +process/Docker/k3s access dimensions. + ## Next-Round Order The JSON output groups recommended next actions in dependency order: -1. `base-image`: preload or tag an approved Node 20 DEV builder image, then - rerun the base-image and artifact publish preflights. -2. `artifact-publish`, `artifact-catalog`, `ghcr`: publish every frozen HWLAB - service artifact and record immutable registry digests for the selected - `origin/main` commit. -3. `d601-k3s`, `kubectl`, kubeconfig/maintenance bridge: restore read-only +1. `d601-k3s`, `kubectl`, kubeconfig/maintenance bridge: restore read-only hwlab-dev cluster observability without printing Secrets. -4. `cloud-api-db`: prove DEV cloud-api DB env and health readiness with +2. `cloud-api-db`: prove DEV cloud-api DB env and health readiness with redacted values only. -5. `dev-edge`, `dev-edge-health`, `dev-ingress-health`: repair +3. `dev-edge`, `dev-edge-health`, `dev-ingress-health`: repair `:16667`/frp/edge/router reachability, then rerun read-only DEV edge health before M3/M4/M5 live loops. +4. `registry-manifest-read`: resolve #66 registry reachability without + treating it as a missing publish digest or rerunning heavy publish. ## Boundaries diff --git a/docs/dev-gate-preflight.md b/docs/dev-gate-preflight.md index 0ee495b2..6f8c2e1d 100644 --- a/docs/dev-gate-preflight.md +++ b/docs/dev-gate-preflight.md @@ -42,13 +42,17 @@ The preflight checks: - `deploy/deploy.json` and `deploy/artifact-catalog.dev.json` are internally consistent and DEV-only. - The deploy manifest, artifact catalog, catalog service commits, and image tags - target the selected `origin/main` source commit. + are covered by the selected `origin/main` target. If `origin/main` is a + report-only evidence commit whose changes do not touch artifact build inputs, + the preflight may accept the artifact source recorded in + `reports/dev-gate/dev-artifacts.json`. - The artifact catalog clearly separates source commit, artifact commit, `ciPublished`, `registryVerified`, and per-service digest state. - The artifact catalog has real publish and registry digest evidence, or stays blocked with `not_published` digests. - `reports/dev-gate/dev-artifacts.json`, when present, proves all frozen DEV - service artifacts were published for the selected `origin/main` commit. + service artifacts were published for the selected target or for an artifact + source commit that still covers the target. - Registry capability evidence is split into `process-http-access`, `docker-daemon-push-access`, and `k3s-pull-access` instead of one ambiguous "registry reachable" result. @@ -60,14 +64,17 @@ The preflight checks: `HWLAB_CLOUD_DB_SSL_MODE=require`. - The local cloud-api health payload reports DB env presence/missing status with redacted values only. This is a readiness gate, not live DB evidence. -- `deploy/frp` and `deploy/master-edge` describe the D601-to-master DEV routes - on public ports `16666`/`16667`. +- `deploy/frp` and `deploy/master-edge` describe the D601-to-master DEV route + on public frontend `:16666` and API/edge/live `:16667`. Legacy public + `:6666/:6667` observations are historical/deprecated only and must not be + used as current green evidence or current active blockers. - The runner can perform read-only `kubectl` probes against `hwlab-dev`. - `reports/dev-gate/dev-edge-health.json`, when present, records read-only public edge, frps, tunnel-health, and k3s observability evidence. - `http://74.48.78.17:16667/health/live` responds. -- Catalog image manifests are visible without reading credentials. This is - artifact catalog evidence and is separate from Docker daemon push access. +- Catalog image manifests are visible without reading credentials. A failed + manifest read is tracked as a #66 registry reachability dimension and must not + be conflated with missing publish digests. - Deploy images do not point at UniDesk, provider-gateway, or microservice-proxy substitutes. @@ -117,3 +124,17 @@ proves every frozen service has a registry digest for that same source commit: ```sh node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json ``` + +Current rebaseline: the committed DEV artifact report proves 13/13 required +DEV artifacts from source `73b379f` with `ciPublished=true`, +`registryVerified=true`, and real `sha256` digests, and the base-image +preflight is `ready` on local `node:20-bookworm-slim`. If the selected +`origin/main` target later drifts onto files that change artifact build inputs, +the preflight can still reopen `artifact-source-commit` or +`dev-artifact-publish` even though the base-image blocker stays closed. +Remaining registry manifest-read failures are #66 reachability evidence, not a +reason to reopen the base-image blocker. + +This is M3 virtual hardware trusted-loop support only. It does not claim M3 +DEV-LIVE unless a real `DO1 -> patch-panel -> DI1` chain is observed through +the current DEV endpoint. diff --git a/reports/dev-gate/dev-m5-gate-aggregator-v2.json b/reports/dev-gate/dev-m5-gate-aggregator-v2.json index 82cd262f..e588c976 100644 --- a/reports/dev-gate/dev-m5-gate-aggregator-v2.json +++ b/reports/dev-gate/dev-m5-gate-aggregator-v2.json @@ -17,8 +17,8 @@ "pikasTech/HWLAB#39", "pikasTech/HWLAB#46" ], - "generatedAt": "2026-05-22T04:56:56.988Z", - "generatedFromCommit": "d4fe2cf1bb8a", + "generatedAt": "2026-05-22T05:38:03.366Z", + "generatedFromCommit": "721bc37c084e", "environment": "dev", "endpoint": "http://74.48.78.17:16667", "devOnly": true, @@ -39,21 +39,21 @@ "issue": "pikasTech/HWLAB#34", "taskId": "dev-gate-preflight", "status": "blocked", - "commitId": "1a2efd4915b2" + "commitId": "82ad96c5c67c" }, "devDeploy": { "path": "reports/dev-gate/dev-deploy-report.json", "issue": "pikasTech/HWLAB#33", "taskId": "dev-deploy-apply", - "status": "pass", - "commitId": "73b379f4441d" + "status": "blocked", + "commitId": "7e29522b65c8" }, "devArtifacts": { "path": "reports/dev-gate/dev-artifacts.json", "issue": "pikasTech/HWLAB#35", "taskId": "dev-artifact-publish", "status": "published", - "commitId": "73b379f" + "commitId": "7e29522" }, "devEdgeHealth": { "path": "reports/dev-gate/dev-edge-health.json", @@ -114,9 +114,9 @@ }, { "id": "artifact-publish-digests", - "status": "blocked", - "evidenceLevel": "BLOCKED", - "summary": "artifactState=contract-skeleton, ciPublished=false, registryVerified=false, sha256=0, not_published=13" + "status": "pass", + "evidenceLevel": "DEV-LIVE", + "summary": "artifactState=published, ciPublished=true, registryVerified=true, sha256=13, not_published=0" }, { "id": "d601-k3s-observability", @@ -126,8 +126,8 @@ }, { "id": "dev-edge-frp-16667", - "status": "pass", - "evidenceLevel": "DEV-LIVE", + "status": "blocked", + "evidenceLevel": "BLOCKED", "summary": "Committed edge report proves read-only public HTTP on :16667 /health and /health/live; old preflight network probe blockers are stale." }, { @@ -183,12 +183,12 @@ }, { "id": "M4", - "status": "not_run", + "status": "blocked", "highestVisibleLevel": "LOCAL", "liveEvidence": "missing_or_blocked", "evidenceCount": 3, - "blockerCount": 0, - "summary": "agent loop has local smoke but live preflight is blocked; highest visible level is LOCAL; status is not_run." + "blockerCount": 1, + "summary": "agent loop has local smoke but live preflight is blocked; highest visible level is LOCAL; status is blocked." }, { "id": "M5", @@ -196,7 +196,7 @@ "highestVisibleLevel": "DRY-RUN", "liveEvidence": "missing_or_blocked", "evidenceCount": 2, - "blockerCount": 9, + "blockerCount": 10, "summary": "dry-run is green but live MVP gate is blocked; highest visible level is DRY-RUN; status is blocked." } ], @@ -242,13 +242,14 @@ "issue": "pikasTech/HWLAB#34", "taskId": "dev-gate-preflight", "reportPath": "reports/dev-gate/dev-preflight-report.json", - "commitId": "1a2efd4915b2", + "commitId": "82ad96c5c67c", "level": "SOURCE", "status": "pass", "category": "deploy-manifest", "commands": [ "node --check scripts/dev-gate-preflight.mjs", "node --check scripts/src/dev-gate-preflight.mjs", + "node --check scripts/src/registry-capabilities.mjs", "node --check scripts/refresh-artifact-catalog.mjs", "node scripts/dev-gate-preflight.mjs", "node --check scripts/validate-dev-gate-report.mjs", @@ -256,8 +257,8 @@ ], "evidence": [ "source-contract-static=pass", - "artifact catalog state=contract-skeleton", - "catalog commit=1a2efd4" + "artifact catalog state=published", + "catalog commit=7e29522" ], "summary": "Deploy manifests, FRP/master-edge contracts, and safety boundary are source-readable and scoped to hwlab-dev." }, @@ -266,9 +267,9 @@ "issue": "pikasTech/HWLAB#33", "taskId": "dev-deploy-apply", "reportPath": "reports/dev-gate/dev-deploy-report.json", - "commitId": "73b379f4441d", + "commitId": "7e29522b65c8", "level": "DRY-RUN", - "status": "pass", + "status": "blocked", "category": "deploy-apply", "commands": [ "node tools/hwlab-cli/bin/hwlab-cli.mjs test e2e --env dev --mvp --dry-run", @@ -276,26 +277,27 @@ ], "evidence": [ "artifact services checked: 13", - "expected artifact commit: 73b379f", + "expected artifact commit: 7e29522", "namespace: hwlab-dev", "workloads planned: 13", "kubectl executor: /usr/local/bin/kubectl", "live health: pass" ], - "summary": "DEV dry-run preflight passed." + "summary": "DEV apply is blocked before mutation." }, { "milestone": "M2", "issue": "pikasTech/HWLAB#35", "taskId": "dev-artifact-publish", "reportPath": "reports/dev-gate/dev-artifacts.json", - "commitId": "73b379f", + "commitId": "7e29522", "level": "DRY-RUN", "status": "published", "category": "artifact-publish", "commands": [ "node --check scripts/dev-artifact-publish.mjs", "node --check scripts/src/dev-artifact-services.mjs", + "node --check scripts/src/registry-capabilities.mjs", "node --check scripts/preflight-dev-base-image.mjs", "node --check scripts/src/dev-base-image-preflight.mjs", "node scripts/preflight-dev-base-image.mjs", @@ -572,10 +574,10 @@ "milestone": "M2", "issue": "pikasTech/HWLAB#33", "taskId": "dev-deploy-apply", - "status": "pass", + "status": "blocked", "category": "deploy-apply", "reportPath": "reports/dev-gate/dev-deploy-report.json", - "summary": "DEV dry-run preflight passed." + "summary": "DEV apply is blocked before mutation." }, { "milestone": "M2", @@ -656,12 +658,12 @@ { "priority": "P1", "order": 3, - "type": "runtime_blocker", - "scope": "artifact-catalog", + "type": "contract_blocker", + "scope": "artifact-source-commit", "sourceIssue": "pikasTech/HWLAB#34", "source": "reports/dev-gate/dev-preflight-report.json", - "summary": "deploy/artifact-catalog.dev.json does not prove published artifacts for origin/main 1a2efd4; ciPublished=false, registryVerified=false, not_published=13.", - "nextTask": "Run the DEV artifact publish workflow, then record only real sha256 digests with `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`; if publish is still blocked, keep not_published via `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`." + "summary": "source commit origin/main 82ad96c is not covered by artifact source 7e29522; target changes since the artifact source touch artifact build inputs.", + "nextTask": "Refresh without fake digests using `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`, or after a successful publish run `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`." }, { "priority": "P1", @@ -670,18 +672,8 @@ "scope": "dev-artifact-publish", "sourceIssue": "pikasTech/HWLAB#34", "source": "reports/dev-gate/dev-preflight-report.json", - "summary": "reports/dev-gate/dev-artifacts.json does not prove all HWLAB service artifacts for origin/main 1a2efd4; current status is blocked with 0/13 published.", - "nextTask": "Complete DEV artifact publishing for every frozen HWLAB service at the current origin/main commit and record immutable registry digests." - }, - { - "priority": "P1", - "order": 3, - "type": "runtime_blocker", - "scope": "ghcr", - "sourceIssue": "pikasTech/HWLAB#34", - "source": "reports/dev-gate/dev-preflight-report.json", - "summary": "This preflight could not verify GHCR manifests for the DEV catalog images without reading credentials.", - "nextTask": "Publish public DEV images or provide a non-secret registry evidence artifact with immutable digests for each HWLAB service." + "summary": "reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for origin/main 82ad96c; current status is published with 13/13 required services published and source states resolved: 13 source-present, 0 intentionally-disabled.", + "nextTask": "Complete DEV artifact publishing for every enabled required HWLAB service at the artifact source commit, or prove the target commit has no artifact build input changes; keep disabled services marked not_published with reasons." }, { "priority": "P1", @@ -713,16 +705,6 @@ "summary": "No SSH maintenance bridge was detected from ssh binary plus known environment variables or ~/.ssh/config metadata.", "nextTask": "Provide a documented read-only maintenance bridge variable or config path if kubectl cannot be mounted directly in the runner." }, - { - "priority": "P1", - "order": 4, - "type": "environment_blocker", - "scope": "d601-k3s", - "sourceIssue": "pikasTech/HWLAB#34", - "source": "reports/dev-gate/dev-preflight-report.json", - "summary": "D601 runner lacks kubectl and no default kubeconfig was used by this preflight.", - "nextTask": "Provide a read-only kubectl/kubeconfig path for the real D601 hwlab-dev k3s cluster, then rerun this preflight." - }, { "priority": "P1", "order": 5, @@ -732,6 +714,16 @@ "source": "reports/dev-gate/dev-edge-health.json", "summary": "cloud-api DB env is injected, but runtime health has not attempted a live DB connection" }, + { + "priority": "P1", + "order": 5, + "type": "network_blocker", + "scope": "cloud-api-db", + "sourceIssue": "pikasTech/HWLAB#34", + "source": "reports/dev-gate/dev-preflight-report.json", + "summary": "cloud-api DB env is injected, but runtime health has not attempted a live DB connection", + "nextTask": "Deploy cloud-api DB runtime readiness probe and/or repair DEV DB connectivity, then rerun the read-only health smoke without reading or printing the DB secret value." + }, { "priority": "P1", "order": 5, @@ -742,6 +734,16 @@ "summary": "cloud-api DB runtime env is not ready; missing HWLAB_CLOUD_DB_URL, HWLAB_CLOUD_DB_SSL_MODE.", "nextTask": "Configure DEV hwlab-cloud-api with Secret hwlab-cloud-api-dev-db/database-url and HWLAB_CLOUD_DB_SSL_MODE=require, then rerun health/preflight without printing the secret value." }, + { + "priority": "P2", + "order": 6, + "type": "environment_blocker", + "scope": "kubectl-dry-run", + "sourceIssue": "pikasTech/HWLAB#33", + "source": "reports/dev-gate/dev-deploy-report.json", + "summary": "# Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"},\\\"name\\\":\\\"hwlab-agent-worker-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_AGENT_SESSION_MODE\\\",\\\"value\\\":\\\"session-scoped\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\\\",\\\"name\\\":\\\"hwlab-agent-worker\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-agent-worker\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"name\":\"hwlab-agent-worker\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-agent-worker-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-agent-worker-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"batch.kubernetes.io/job-name\":\"hwlab-agent-worker-template\",\"controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\",\"job-name\":\"hwlab-agent-worker-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-agent-worker\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_AGENT_SESSION_MODE\",\"Value\":\"session-scoped\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/activation\\\":\\\"manual\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"},\\\"name\\\":\\\"hwlab-cli-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_CLI_ENDPOINT\\\",\\\"value\\\":\\\"http://74.48.78.17:16667\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\\\",\\\"name\\\":\\\"hwlab-cli\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-cli\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"name\":\"hwlab-cli\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-cli-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-cli-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"batch.kubernetes.io/job-name\":\"hwlab-cli-template\",\"controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\",\"job-name\":\"hwlab-cli-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-cli\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_CLI_ENDPOINT\",\"Value\":\"http://74.48.78.17:16667\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable", + "nextTask": "# Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"},\\\"name\\\":\\\"hwlab-agent-worker-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_AGENT_SESSION_MODE\\\",\\\"value\\\":\\\"session-scoped\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\\\",\\\"name\\\":\\\"hwlab-agent-worker\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-agent-worker\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"name\":\"hwlab-agent-worker\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-agent-worker-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-agent-worker-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"batch.kubernetes.io/job-name\":\"hwlab-agent-worker-template\",\"controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\",\"job-name\":\"hwlab-agent-worker-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-agent-worker\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_AGENT_SESSION_MODE\",\"Value\":\"session-scoped\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/activation\\\":\\\"manual\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"},\\\"name\\\":\\\"hwlab-cli-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_CLI_ENDPOINT\\\",\\\"value\\\":\\\"http://74.48.78.17:16667\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\\\",\\\"name\\\":\\\"hwlab-cli\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-cli\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"name\":\"hwlab-cli\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-cli-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-cli-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"batch.kubernetes.io/job-name\":\"hwlab-cli-template\",\"controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\",\"job-name\":\"hwlab-cli-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-cli\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_CLI_ENDPOINT\",\"Value\":\"http://74.48.78.17:16667\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable" + }, { "priority": "P3", "order": 99, @@ -782,15 +784,15 @@ }, "blockers": [ { - "id": "dev-gate-preflight:artifact-catalog", + "id": "dev-gate-preflight:artifact-source-commit", "priority": "P1", - "type": "runtime_blocker", - "scope": "artifact-catalog", + "type": "contract_blocker", + "scope": "artifact-source-commit", "status": "open", "source": "reports/dev-gate/dev-preflight-report.json", "sourceIssue": "pikasTech/HWLAB#34", - "summary": "deploy/artifact-catalog.dev.json does not prove published artifacts for origin/main 1a2efd4; ciPublished=false, registryVerified=false, not_published=13.", - "nextTask": "Run the DEV artifact publish workflow, then record only real sha256 digests with `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`; if publish is still blocked, keep not_published via `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`.", + "summary": "source commit origin/main 82ad96c is not covered by artifact source 7e29522; target changes since the artifact source touch artifact build inputs.", + "nextTask": "Refresh without fake digests using `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`, or after a successful publish run `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`.", "unblockOrder": 3, "unblocks": [ "pikasTech/HWLAB#35", @@ -807,26 +809,8 @@ "status": "open", "source": "reports/dev-gate/dev-preflight-report.json", "sourceIssue": "pikasTech/HWLAB#34", - "summary": "reports/dev-gate/dev-artifacts.json does not prove all HWLAB service artifacts for origin/main 1a2efd4; current status is blocked with 0/13 published.", - "nextTask": "Complete DEV artifact publishing for every frozen HWLAB service at the current origin/main commit and record immutable registry digests.", - "unblockOrder": 3, - "unblocks": [ - "pikasTech/HWLAB#35", - "pikasTech/HWLAB#33", - "pikasTech/HWLAB#39" - ], - "rationale": "The gate cannot promote deploy or runtime observations without immutable image provenance and digests." - }, - { - "id": "dev-gate-preflight:ghcr", - "priority": "P1", - "type": "runtime_blocker", - "scope": "ghcr", - "status": "open", - "source": "reports/dev-gate/dev-preflight-report.json", - "sourceIssue": "pikasTech/HWLAB#34", - "summary": "This preflight could not verify GHCR manifests for the DEV catalog images without reading credentials.", - "nextTask": "Publish public DEV images or provide a non-secret registry evidence artifact with immutable digests for each HWLAB service.", + "summary": "reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for origin/main 82ad96c; current status is published with 13/13 required services published and source states resolved: 13 source-present, 0 intentionally-disabled.", + "nextTask": "Complete DEV artifact publishing for every enabled required HWLAB service at the artifact source commit, or prove the target commit has no artifact build input changes; keep disabled services marked not_published with reasons.", "unblockOrder": 3, "unblocks": [ "pikasTech/HWLAB#35", @@ -892,25 +876,6 @@ ], "rationale": "D601 hwlab-dev cluster state must be observable read-only before any live apply or M3/M4/M5 acceptance." }, - { - "id": "dev-gate-preflight:d601-k3s", - "priority": "P1", - "type": "environment_blocker", - "scope": "d601-k3s", - "status": "open", - "source": "reports/dev-gate/dev-preflight-report.json", - "sourceIssue": "pikasTech/HWLAB#34", - "summary": "D601 runner lacks kubectl and no default kubeconfig was used by this preflight.", - "nextTask": "Provide a read-only kubectl/kubeconfig path for the real D601 hwlab-dev k3s cluster, then rerun this preflight.", - "unblockOrder": 4, - "unblocks": [ - "pikasTech/HWLAB#34", - "pikasTech/HWLAB#33", - "pikasTech/HWLAB#36", - "pikasTech/HWLAB#38" - ], - "rationale": "D601 hwlab-dev cluster state must be observable read-only before any live apply or M3/M4/M5 acceptance." - }, { "id": "dev-edge-health:cloud-api-db", "priority": "P1", @@ -928,6 +893,24 @@ ], "rationale": "Cloud API DB env and health readiness block runtime health and MVP evidence even if ingress starts responding." }, + { + "id": "dev-gate-preflight:cloud-api-db", + "priority": "P1", + "type": "network_blocker", + "scope": "cloud-api-db", + "status": "open", + "source": "reports/dev-gate/dev-preflight-report.json", + "sourceIssue": "pikasTech/HWLAB#34", + "summary": "cloud-api DB env is injected, but runtime health has not attempted a live DB connection", + "nextTask": "Deploy cloud-api DB runtime readiness probe and/or repair DEV DB connectivity, then rerun the read-only health smoke without reading or printing the DB secret value.", + "unblockOrder": 5, + "unblocks": [ + "pikasTech/HWLAB#34", + "pikasTech/HWLAB#33", + "pikasTech/HWLAB#39" + ], + "rationale": "Cloud API DB env and health readiness block runtime health and MVP evidence even if ingress starts responding." + }, { "id": "dev-gate-preflight:cloud-api-db-health-gate", "priority": "P1", @@ -946,6 +929,25 @@ ], "rationale": "Cloud API DB env and health readiness block runtime health and MVP evidence even if ingress starts responding." }, + { + "id": "dev-deploy-apply:kubectl-dry-run", + "priority": "P2", + "type": "environment_blocker", + "scope": "kubectl-dry-run", + "status": "open", + "source": "reports/dev-gate/dev-deploy-report.json", + "sourceIssue": "pikasTech/HWLAB#33", + "summary": "# Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"},\\\"name\\\":\\\"hwlab-agent-worker-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_AGENT_SESSION_MODE\\\",\\\"value\\\":\\\"session-scoped\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\\\",\\\"name\\\":\\\"hwlab-agent-worker\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-agent-worker\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"name\":\"hwlab-agent-worker\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-agent-worker-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-agent-worker-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"batch.kubernetes.io/job-name\":\"hwlab-agent-worker-template\",\"controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\",\"job-name\":\"hwlab-agent-worker-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-agent-worker\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_AGENT_SESSION_MODE\",\"Value\":\"session-scoped\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/activation\\\":\\\"manual\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"},\\\"name\\\":\\\"hwlab-cli-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_CLI_ENDPOINT\\\",\\\"value\\\":\\\"http://74.48.78.17:16667\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\\\",\\\"name\\\":\\\"hwlab-cli\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-cli\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"name\":\"hwlab-cli\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-cli-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-cli-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"batch.kubernetes.io/job-name\":\"hwlab-cli-template\",\"controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\",\"job-name\":\"hwlab-cli-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-cli\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_CLI_ENDPOINT\",\"Value\":\"http://74.48.78.17:16667\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable", + "nextTask": "# Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"},\\\"name\\\":\\\"hwlab-agent-worker-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_AGENT_SESSION_MODE\\\",\\\"value\\\":\\\"session-scoped\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\\\",\\\"name\\\":\\\"hwlab-agent-worker\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-agent-worker\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"name\":\"hwlab-agent-worker\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-agent-worker-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-agent-worker-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"batch.kubernetes.io/job-name\":\"hwlab-agent-worker-template\",\"controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\",\"job-name\":\"hwlab-agent-worker-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-agent-worker\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_AGENT_SESSION_MODE\",\"Value\":\"session-scoped\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/activation\\\":\\\"manual\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"},\\\"name\\\":\\\"hwlab-cli-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_CLI_ENDPOINT\\\",\\\"value\\\":\\\"http://74.48.78.17:16667\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\\\",\\\"name\\\":\\\"hwlab-cli\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-cli\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"name\":\"hwlab-cli\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-cli-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-cli-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"batch.kubernetes.io/job-name\":\"hwlab-cli-template\",\"controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\",\"job-name\":\"hwlab-cli-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-cli\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_CLI_ENDPOINT\",\"Value\":\"http://74.48.78.17:16667\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable", + "unblockOrder": 6, + "unblocks": [ + "pikasTech/HWLAB#36", + "pikasTech/HWLAB#38", + "pikasTech/HWLAB#37", + "pikasTech/HWLAB#39" + ], + "rationale": "The :16667/frp path must be reachable before any DEV-LIVE M3, M4, or M5 evidence can be collected." + }, { "id": "dev-m3-hardware-loop:m3-hardware-loop-runtime", "priority": "P3", @@ -1013,9 +1015,8 @@ "blockerOrder": 3, "priority": "P1", "scopes": [ - "artifact-catalog", - "dev-artifact-publish", - "ghcr" + "artifact-source-commit", + "dev-artifact-publish" ], "sourceIssues": [ "pikasTech/HWLAB#33", @@ -1024,7 +1025,7 @@ "pikasTech/HWLAB#39" ], "rationale": "The gate cannot promote deploy or runtime observations without immutable image provenance and digests.", - "action": "Run the DEV artifact publish workflow, then record only real sha256 digests with `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`; if publish is still blocked, keep not_published via `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`.", + "action": "Refresh without fake digests using `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`, or after a successful publish run `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`.", "evidenceRequired": "Artifact publish report with ciPublished=true, registryVerified=true, and sha256 digest for each frozen service ID." }, { @@ -1034,8 +1035,7 @@ "scopes": [ "d601-k3s-client-binary", "d601-kubeconfig-path", - "d601-maintenance-ssh-bridge", - "d601-k3s" + "d601-maintenance-ssh-bridge" ], "sourceIssues": [ "pikasTech/HWLAB#33", @@ -1063,11 +1063,29 @@ "pikasTech/HWLAB#39" ], "rationale": "Cloud API DB env and health readiness block runtime health and MVP evidence even if ingress starts responding.", - "action": "Configure DEV hwlab-cloud-api with Secret hwlab-cloud-api-dev-db/database-url and HWLAB_CLOUD_DB_SSL_MODE=require, then rerun health/preflight without printing the secret value.", + "action": "Deploy cloud-api DB runtime readiness probe and/or repair DEV DB connectivity, then rerun the read-only health smoke without reading or printing the DB secret value.", "evidenceRequired": "Cloud API health/live output showing DB env ready and redacted secret references, without secret material." }, { "order": 4, + "blockerOrder": 6, + "priority": "P2", + "scopes": [ + "kubectl-dry-run" + ], + "sourceIssues": [ + "pikasTech/HWLAB#33", + "pikasTech/HWLAB#36", + "pikasTech/HWLAB#37", + "pikasTech/HWLAB#38", + "pikasTech/HWLAB#39" + ], + "rationale": "The :16667/frp path must be reachable before any DEV-LIVE M3, M4, or M5 evidence can be collected.", + "action": "# Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"},\\\"name\\\":\\\"hwlab-agent-worker-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-agent-worker\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-agent-worker\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_AGENT_SESSION_MODE\\\",\\\"value\\\":\\\"session-scoped\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\\\",\\\"name\\\":\\\"hwlab-agent-worker\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-agent-worker\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"name\":\"hwlab-agent-worker\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-agent-worker-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-agent-worker-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"batch.kubernetes.io/job-name\":\"hwlab-agent-worker-template\",\"controller-uid\":\"0f7b16d1-562b-40a3-8ff8-961c10d1b182\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\",\"job-name\":\"hwlab-agent-worker-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-agent-worker\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_AGENT_SESSION_MODE\",\"Value\":\"session-scoped\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable Error from server (Invalid): error when applying patch: {\"metadata\":{\"annotations\":{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"batch/v1\\\",\\\"kind\\\":\\\"Job\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/activation\\\":\\\"manual\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"},\\\"name\\\":\\\"hwlab-cli-template\\\",\\\"namespace\\\":\\\"hwlab-dev\\\"},\\\"spec\\\":{\\\"suspend\\\":true,\\\"template\\\":{\\\"metadata\\\":{\\\"labels\\\":{\\\"app.kubernetes.io/name\\\":\\\"hwlab-cli\\\",\\\"app.kubernetes.io/part-of\\\":\\\"hwlab\\\",\\\"hwlab.pikastech.local/environment\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/profile\\\":\\\"dev\\\",\\\"hwlab.pikastech.local/service-id\\\":\\\"hwlab-cli\\\"}},\\\"spec\\\":{\\\"containers\\\":[{\\\"env\\\":[{\\\"name\\\":\\\"HWLAB_CLI_ENDPOINT\\\",\\\"value\\\":\\\"http://74.48.78.17:16667\\\"}],\\\"image\\\":\\\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\\\",\\\"name\\\":\\\"hwlab-cli\\\"}],\\\"restartPolicy\\\":\\\"Never\\\"}}}}\\n\"}},\"spec\":{\"template\":{\"spec\":{\"$setElementOrder/containers\":[{\"name\":\"hwlab-cli\"}],\"containers\":[{\"image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"name\":\"hwlab-cli\"}]}}}} to: Resource: \"batch/v1, Resource=jobs\", GroupVersionKind: \"batch/v1, Kind=Job\" Name: \"hwlab-cli-template\", Namespace: \"hwlab-dev\" for: \"deploy/k8s/dev\": error when patching \"deploy/k8s/dev\": Job.batch \"hwlab-cli-template\" is invalid: spec.template: Invalid value: {\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"batch.kubernetes.io/controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"batch.kubernetes.io/job-name\":\"hwlab-cli-template\",\"controller-uid\":\"ce763736-b67b-400c-8a09-5b3f62019b09\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\",\"job-name\":\"hwlab-cli-template\"},\"Spec\":{\"Volumes\":null,\"InitContainers\":null,\"Containers\":[{\"Name\":\"hwlab-cli\",\"Image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"Command\":null,\"Args\":null,\"WorkingDir\":\"\",\"Ports\":null,\"EnvFrom\":null,\"Env\":[{\"Name\":\"HWLAB_CLI_ENDPOINT\",\"Value\":\"http://74.48.78.17:16667\",\"ValueFrom\":null}],\"Resources\":{\"Limits\":null,\"Requests\":null,\"Claims\":null},\"ResizePolicy\":null,\"RestartPolicy\":null,\"RestartPolicyRules\":null,\"VolumeMounts\":null,\"VolumeDevices\":null,\"LivenessProbe\":null,\"ReadinessProbe\":null,\"StartupProbe\":null,\"Lifecycle\":null,\"TerminationMessagePath\":\"/dev/termination-log\",\"TerminationMessagePolicy\":\"File\",\"ImagePullPolicy\":\"IfNotPresent\",\"SecurityContext\":null,\"Stdin\":false,\"StdinOnce\":false,\"TTY\":false}],\"EphemeralContainers\":null,\"RestartPolicy\":\"Never\",\"TerminationGracePeriodSeconds\":30,\"ActiveDeadlineSeconds\":null,\"DNSPolicy\":\"ClusterFirst\",\"NodeSelector\":null,\"ServiceAccountName\":\"\",\"AutomountServiceAccountToken\":null,\"NodeName\":\"\",\"SecurityContext\":{\"HostNetwork\":false,\"HostPID\":false,\"HostIPC\":false,\"ShareProcessNamespace\":null,\"HostUsers\":null,\"SELinuxOptions\":null,\"WindowsOptions\":null,\"RunAsUser\":null,\"RunAsGroup\":null,\"RunAsNonRoot\":null,\"SupplementalGroups\":null,\"SupplementalGroupsPolicy\":null,\"FSGroup\":null,\"FSGroupChangePolicy\":null,\"Sysctls\":null,\"SeccompProfile\":null,\"AppArmorProfile\":null,\"SELinuxChangePolicy\":null},\"ImagePullSecrets\":null,\"Hostname\":\"\",\"Subdomain\":\"\",\"SetHostnameAsFQDN\":null,\"Affinity\":null,\"SchedulerName\":\"default-scheduler\",\"Tolerations\":null,\"HostAliases\":null,\"PriorityClassName\":\"\",\"Priority\":null,\"PreemptionPolicy\":null,\"DNSConfig\":null,\"ReadinessGates\":null,\"RuntimeClassName\":null,\"Overhead\":null,\"EnableServiceLinks\":null,\"TopologySpreadConstraints\":null,\"OS\":null,\"SchedulingGates\":null,\"ResourceClaims\":null,\"Resources\":null,\"HostnameOverride\":null}}: field is immutable", + "evidenceRequired": "Read-only kubectl/k3s report proving pods/services/configmaps are observable in hwlab-dev without reading Secrets." + }, + { + "order": 5, "blockerOrder": 99, "priority": "P3", "scopes": [ diff --git a/reports/dev-gate/dev-m5-gate-aggregator-v2.md b/reports/dev-gate/dev-m5-gate-aggregator-v2.md index a5b74705..c717b5f3 100644 --- a/reports/dev-gate/dev-m5-gate-aggregator-v2.md +++ b/reports/dev-gate/dev-m5-gate-aggregator-v2.md @@ -1,7 +1,7 @@ # HWLAB M5 DEV Gate Aggregator v2 Status: blocked -Generated from: `d4fe2cf1bb8a` +Generated from: `721bc37c084e` Scope: DEV only, report-only ## Summary @@ -16,7 +16,7 @@ SOURCE, LOCAL, DRY-RUN, and edge DEV-LIVE evidence exists, but acceptance is sti | M1 | pass | LOCAL | missing_or_blocked | local smoke is available; highest visible level is LOCAL; status is pass. | | M2 | blocked | DEV-LIVE | missing_or_blocked | 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 | not_run | LOCAL | missing_or_blocked | agent loop has local smoke but live preflight is blocked; highest visible level is LOCAL; status is not_run. | +| M4 | blocked | LOCAL | missing_or_blocked | agent loop has local smoke but live preflight is blocked; highest visible level is LOCAL; 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 @@ -25,9 +25,9 @@ SOURCE, LOCAL, DRY-RUN, and edge DEV-LIVE evidence exists, but acceptance is sti | --- | --- | --- | --- | | m0-source-contract | pass | SOURCE | M0 contract checks are source-level evidence only. | | m1-local-smoke | pass | LOCAL | M1 local smoke is not a live DEV substitute. | -| artifact-publish-digests | blocked | BLOCKED | artifactState=contract-skeleton, ciPublished=false, registryVerified=false, sha256=0, not_published=13 | +| artifact-publish-digests | pass | DEV-LIVE | artifactState=published, ciPublished=true, registryVerified=true, sha256=13, not_published=0 | | d601-k3s-observability | blocked | BLOCKED | D601 runner lacks kubectl/k3s/kubeconfig observability for hwlab-dev. | -| dev-edge-frp-16667 | pass | DEV-LIVE | Committed edge report proves read-only public HTTP on :16667 /health and /health/live; old preflight network probe blockers are stale. | +| dev-edge-frp-16667 | blocked | BLOCKED | Committed edge report proves read-only public HTTP on :16667 /health and /health/live; old preflight network probe blockers are stale. | | cloud-api-db-ready | blocked | BLOCKED | Manifest-level DB env exists, but live DB health readiness is still blocked/missing. | | m5-mvp-dev-live | blocked | BLOCKED | M5 dry-run passed; bounded DEV-LIVE MVP e2e has not passed. | @@ -35,15 +35,15 @@ SOURCE, LOCAL, DRY-RUN, and edge DEV-LIVE evidence exists, but acceptance is sti | Priority | Order | Type | Scope | Summary | | --- | ---: | --- | --- | --- | -| P1 | 3 | runtime_blocker | artifact-catalog | deploy/artifact-catalog.dev.json does not prove published artifacts for origin/main 1a2efd4; ciPublished=false, registryVerified=false, not_published=13. | -| P1 | 3 | runtime_blocker | dev-artifact-publish | reports/dev-gate/dev-artifacts.json does not prove all HWLAB service artifacts for origin/main 1a2efd4; current status is blocked with 0/13 published. | -| P1 | 3 | runtime_blocker | ghcr | This preflight could not verify GHCR manifests for the DEV catalog images without reading credentials. | +| P1 | 3 | contract_blocker | artifact-source-commit | source commit origin/main 82ad96c is not covered by artifact source 7e29522; target changes since the artifact source touch artifact build inputs. | +| P1 | 3 | runtime_blocker | dev-artifact-publish | reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for origin/main 82ad96c; current status is published with 13/13 required services published and source states resolved: 13 source-present, 0 intentionally-disabled. | | P1 | 4 | environment_blocker | d601-k3s-client-binary | Neither kubectl nor k3s is installed in this runner PATH. | | P1 | 4 | environment_blocker | d601-kubeconfig-path | No readable KUBECONFIG/default k3s kubeconfig path was found by metadata checks. | | P1 | 4 | environment_blocker | d601-maintenance-ssh-bridge | No SSH maintenance bridge was detected from ssh binary plus known environment variables or ~/.ssh/config metadata. | -| P1 | 4 | environment_blocker | d601-k3s | D601 runner lacks kubectl and no default kubeconfig was used by this preflight. | | P1 | 5 | runtime_blocker | cloud-api-db | cloud-api DB env is injected, but runtime health has not attempted a live DB connection | +| P1 | 5 | network_blocker | cloud-api-db | cloud-api DB env is injected, but runtime health has not attempted a live DB connection | | P1 | 5 | runtime_blocker | cloud-api-db-health-gate | cloud-api DB runtime env is not ready; missing HWLAB_CLOUD_DB_URL, HWLAB_CLOUD_DB_SSL_MODE. | +| P2 | 6 | environment_blocker | kubectl-dry-run | # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. Error from server (Invalid): error when applying patch: {"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"batch/v1\",\"kind\":\"Job\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\"},\"name\":\"hwlab-agent-worker-template\",\"namespace\":\"hwlab-dev\"},\"spec\":{\"suspend\":true,\"template\":{\"metadata\":{\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\"}},\"spec\":{\"containers\":[{\"env\":[{\"name\":\"HWLAB_AGENT_SESSION_MODE\",\"value\":\"session-scoped\"}],\"image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"name\":\"hwlab-agent-worker\"}],\"restartPolicy\":\"Never\"}}}}\n"}},"spec":{"template":{"spec":{"$setElementOrder/containers":[{"name":"hwlab-agent-worker"}],"containers":[{"image":"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522","name":"hwlab-agent-worker"}]}}}} to: Resource: "batch/v1, Resource=jobs", GroupVersionKind: "batch/v1, Kind=Job" Name: "hwlab-agent-worker-template", Namespace: "hwlab-dev" for: "deploy/k8s/dev": error when patching "deploy/k8s/dev": Job.batch "hwlab-agent-worker-template" is invalid: spec.template: Invalid value: {"labels":{"app.kubernetes.io/name":"hwlab-agent-worker","app.kubernetes.io/part-of":"hwlab","batch.kubernetes.io/controller-uid":"0f7b16d1-562b-40a3-8ff8-961c10d1b182","batch.kubernetes.io/job-name":"hwlab-agent-worker-template","controller-uid":"0f7b16d1-562b-40a3-8ff8-961c10d1b182","hwlab.pikastech.local/environment":"dev","hwlab.pikastech.local/profile":"dev","hwlab.pikastech.local/service-id":"hwlab-agent-worker","job-name":"hwlab-agent-worker-template"},"Spec":{"Volumes":null,"InitContainers":null,"Containers":[{"Name":"hwlab-agent-worker","Image":"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522","Command":null,"Args":null,"WorkingDir":"","Ports":null,"EnvFrom":null,"Env":[{"Name":"HWLAB_AGENT_SESSION_MODE","Value":"session-scoped","ValueFrom":null}],"Resources":{"Limits":null,"Requests":null,"Claims":null},"ResizePolicy":null,"RestartPolicy":null,"RestartPolicyRules":null,"VolumeMounts":null,"VolumeDevices":null,"LivenessProbe":null,"ReadinessProbe":null,"StartupProbe":null,"Lifecycle":null,"TerminationMessagePath":"/dev/termination-log","TerminationMessagePolicy":"File","ImagePullPolicy":"IfNotPresent","SecurityContext":null,"Stdin":false,"StdinOnce":false,"TTY":false}],"EphemeralContainers":null,"RestartPolicy":"Never","TerminationGracePeriodSeconds":30,"ActiveDeadlineSeconds":null,"DNSPolicy":"ClusterFirst","NodeSelector":null,"ServiceAccountName":"","AutomountServiceAccountToken":null,"NodeName":"","SecurityContext":{"HostNetwork":false,"HostPID":false,"HostIPC":false,"ShareProcessNamespace":null,"HostUsers":null,"SELinuxOptions":null,"WindowsOptions":null,"RunAsUser":null,"RunAsGroup":null,"RunAsNonRoot":null,"SupplementalGroups":null,"SupplementalGroupsPolicy":null,"FSGroup":null,"FSGroupChangePolicy":null,"Sysctls":null,"SeccompProfile":null,"AppArmorProfile":null,"SELinuxChangePolicy":null},"ImagePullSecrets":null,"Hostname":"","Subdomain":"","SetHostnameAsFQDN":null,"Affinity":null,"SchedulerName":"default-scheduler","Tolerations":null,"HostAliases":null,"PriorityClassName":"","Priority":null,"PreemptionPolicy":null,"DNSConfig":null,"ReadinessGates":null,"RuntimeClassName":null,"Overhead":null,"EnableServiceLinks":null,"TopologySpreadConstraints":null,"OS":null,"SchedulingGates":null,"ResourceClaims":null,"Resources":null,"HostnameOverride":null}}: field is immutable Error from server (Invalid): error when applying patch: {"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"batch/v1\",\"kind\":\"Job\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"hwlab.pikastech.local/activation\":\"manual\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\"},\"name\":\"hwlab-cli-template\",\"namespace\":\"hwlab-dev\"},\"spec\":{\"suspend\":true,\"template\":{\"metadata\":{\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\"}},\"spec\":{\"containers\":[{\"env\":[{\"name\":\"HWLAB_CLI_ENDPOINT\",\"value\":\"http://74.48.78.17:16667\"}],\"image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"name\":\"hwlab-cli\"}],\"restartPolicy\":\"Never\"}}}}\n"}},"spec":{"template":{"spec":{"$setElementOrder/containers":[{"name":"hwlab-cli"}],"containers":[{"image":"127.0.0.1:5000/hwlab/hwlab-cli:7e29522","name":"hwlab-cli"}]}}}} to: Resource: "batch/v1, Resource=jobs", GroupVersionKind: "batch/v1, Kind=Job" Name: "hwlab-cli-template", Namespace: "hwlab-dev" for: "deploy/k8s/dev": error when patching "deploy/k8s/dev": Job.batch "hwlab-cli-template" is invalid: spec.template: Invalid value: {"labels":{"app.kubernetes.io/name":"hwlab-cli","app.kubernetes.io/part-of":"hwlab","batch.kubernetes.io/controller-uid":"ce763736-b67b-400c-8a09-5b3f62019b09","batch.kubernetes.io/job-name":"hwlab-cli-template","controller-uid":"ce763736-b67b-400c-8a09-5b3f62019b09","hwlab.pikastech.local/environment":"dev","hwlab.pikastech.local/profile":"dev","hwlab.pikastech.local/service-id":"hwlab-cli","job-name":"hwlab-cli-template"},"Spec":{"Volumes":null,"InitContainers":null,"Containers":[{"Name":"hwlab-cli","Image":"127.0.0.1:5000/hwlab/hwlab-cli:7e29522","Command":null,"Args":null,"WorkingDir":"","Ports":null,"EnvFrom":null,"Env":[{"Name":"HWLAB_CLI_ENDPOINT","Value":"http://74.48.78.17:16667","ValueFrom":null}],"Resources":{"Limits":null,"Requests":null,"Claims":null},"ResizePolicy":null,"RestartPolicy":null,"RestartPolicyRules":null,"VolumeMounts":null,"VolumeDevices":null,"LivenessProbe":null,"ReadinessProbe":null,"StartupProbe":null,"Lifecycle":null,"TerminationMessagePath":"/dev/termination-log","TerminationMessagePolicy":"File","ImagePullPolicy":"IfNotPresent","SecurityContext":null,"Stdin":false,"StdinOnce":false,"TTY":false}],"EphemeralContainers":null,"RestartPolicy":"Never","TerminationGracePeriodSeconds":30,"ActiveDeadlineSeconds":null,"DNSPolicy":"ClusterFirst","NodeSelector":null,"ServiceAccountName":"","AutomountServiceAccountToken":null,"NodeName":"","SecurityContext":{"HostNetwork":false,"HostPID":false,"HostIPC":false,"ShareProcessNamespace":null,"HostUsers":null,"SELinuxOptions":null,"WindowsOptions":null,"RunAsUser":null,"RunAsGroup":null,"RunAsNonRoot":null,"SupplementalGroups":null,"SupplementalGroupsPolicy":null,"FSGroup":null,"FSGroupChangePolicy":null,"Sysctls":null,"SeccompProfile":null,"AppArmorProfile":null,"SELinuxChangePolicy":null},"ImagePullSecrets":null,"Hostname":"","Subdomain":"","SetHostnameAsFQDN":null,"Affinity":null,"SchedulerName":"default-scheduler","Tolerations":null,"HostAliases":null,"PriorityClassName":"","Priority":null,"PreemptionPolicy":null,"DNSConfig":null,"ReadinessGates":null,"RuntimeClassName":null,"Overhead":null,"EnableServiceLinks":null,"TopologySpreadConstraints":null,"OS":null,"SchedulingGates":null,"ResourceClaims":null,"Resources":null,"HostnameOverride":null}}: field is immutable | | P3 | 99 | runtime_blocker | m3-hardware-loop-runtime | patch-panel active DO1 -> DI1 connection missing | | P3 | 99 | runtime_blocker | db-live | cloud-api /health/live reports DB degraded; connected=false; ready=false. | | P3 | 99 | runtime_blocker | db-live | cloud-api /health/live reports DB degraded; db.ready=false, db.connected=false, and live DB evidence is not established. | @@ -51,13 +51,15 @@ SOURCE, LOCAL, DRY-RUN, and edge DEV-LIVE evidence exists, but acceptance is sti ## Next Unblock Order -1. Run the DEV artifact publish workflow, then record only real sha256 digests with `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`; if publish is still blocked, keep not_published via `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`. +1. Refresh without fake digests using `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`, or after a successful publish run `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`. Evidence required: Artifact publish report with ciPublished=true, registryVerified=true, and sha256 digest for each frozen service ID. 2. Install kubectl in the D601 Code Queue runner image, or mount an approved k3s kubectl client path for read-only hwlab-dev observation. Evidence required: Read-only kubectl/k3s report proving pods/services/configmaps are observable in hwlab-dev without reading Secrets. -3. Configure DEV hwlab-cloud-api with Secret hwlab-cloud-api-dev-db/database-url and HWLAB_CLOUD_DB_SSL_MODE=require, then rerun health/preflight without printing the secret value. +3. Deploy cloud-api DB runtime readiness probe and/or repair DEV DB connectivity, then rerun the read-only health smoke without reading or printing the DB secret value. Evidence required: Cloud API health/live output showing DB env ready and redacted secret references, without secret material. -4. Resolve the blocker and attach source/local/dry-run/DEV-live evidence at the correct level. +4. # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. # Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically. Error from server (Invalid): error when applying patch: {"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"batch/v1\",\"kind\":\"Job\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\"},\"name\":\"hwlab-agent-worker-template\",\"namespace\":\"hwlab-dev\"},\"spec\":{\"suspend\":true,\"template\":{\"metadata\":{\"labels\":{\"app.kubernetes.io/name\":\"hwlab-agent-worker\",\"app.kubernetes.io/part-of\":\"hwlab\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-agent-worker\"}},\"spec\":{\"containers\":[{\"env\":[{\"name\":\"HWLAB_AGENT_SESSION_MODE\",\"value\":\"session-scoped\"}],\"image\":\"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522\",\"name\":\"hwlab-agent-worker\"}],\"restartPolicy\":\"Never\"}}}}\n"}},"spec":{"template":{"spec":{"$setElementOrder/containers":[{"name":"hwlab-agent-worker"}],"containers":[{"image":"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522","name":"hwlab-agent-worker"}]}}}} to: Resource: "batch/v1, Resource=jobs", GroupVersionKind: "batch/v1, Kind=Job" Name: "hwlab-agent-worker-template", Namespace: "hwlab-dev" for: "deploy/k8s/dev": error when patching "deploy/k8s/dev": Job.batch "hwlab-agent-worker-template" is invalid: spec.template: Invalid value: {"labels":{"app.kubernetes.io/name":"hwlab-agent-worker","app.kubernetes.io/part-of":"hwlab","batch.kubernetes.io/controller-uid":"0f7b16d1-562b-40a3-8ff8-961c10d1b182","batch.kubernetes.io/job-name":"hwlab-agent-worker-template","controller-uid":"0f7b16d1-562b-40a3-8ff8-961c10d1b182","hwlab.pikastech.local/environment":"dev","hwlab.pikastech.local/profile":"dev","hwlab.pikastech.local/service-id":"hwlab-agent-worker","job-name":"hwlab-agent-worker-template"},"Spec":{"Volumes":null,"InitContainers":null,"Containers":[{"Name":"hwlab-agent-worker","Image":"127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522","Command":null,"Args":null,"WorkingDir":"","Ports":null,"EnvFrom":null,"Env":[{"Name":"HWLAB_AGENT_SESSION_MODE","Value":"session-scoped","ValueFrom":null}],"Resources":{"Limits":null,"Requests":null,"Claims":null},"ResizePolicy":null,"RestartPolicy":null,"RestartPolicyRules":null,"VolumeMounts":null,"VolumeDevices":null,"LivenessProbe":null,"ReadinessProbe":null,"StartupProbe":null,"Lifecycle":null,"TerminationMessagePath":"/dev/termination-log","TerminationMessagePolicy":"File","ImagePullPolicy":"IfNotPresent","SecurityContext":null,"Stdin":false,"StdinOnce":false,"TTY":false}],"EphemeralContainers":null,"RestartPolicy":"Never","TerminationGracePeriodSeconds":30,"ActiveDeadlineSeconds":null,"DNSPolicy":"ClusterFirst","NodeSelector":null,"ServiceAccountName":"","AutomountServiceAccountToken":null,"NodeName":"","SecurityContext":{"HostNetwork":false,"HostPID":false,"HostIPC":false,"ShareProcessNamespace":null,"HostUsers":null,"SELinuxOptions":null,"WindowsOptions":null,"RunAsUser":null,"RunAsGroup":null,"RunAsNonRoot":null,"SupplementalGroups":null,"SupplementalGroupsPolicy":null,"FSGroup":null,"FSGroupChangePolicy":null,"Sysctls":null,"SeccompProfile":null,"AppArmorProfile":null,"SELinuxChangePolicy":null},"ImagePullSecrets":null,"Hostname":"","Subdomain":"","SetHostnameAsFQDN":null,"Affinity":null,"SchedulerName":"default-scheduler","Tolerations":null,"HostAliases":null,"PriorityClassName":"","Priority":null,"PreemptionPolicy":null,"DNSConfig":null,"ReadinessGates":null,"RuntimeClassName":null,"Overhead":null,"EnableServiceLinks":null,"TopologySpreadConstraints":null,"OS":null,"SchedulingGates":null,"ResourceClaims":null,"Resources":null,"HostnameOverride":null}}: field is immutable Error from server (Invalid): error when applying patch: {"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"batch/v1\",\"kind\":\"Job\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"hwlab.pikastech.local/activation\":\"manual\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\"},\"name\":\"hwlab-cli-template\",\"namespace\":\"hwlab-dev\"},\"spec\":{\"suspend\":true,\"template\":{\"metadata\":{\"labels\":{\"app.kubernetes.io/name\":\"hwlab-cli\",\"app.kubernetes.io/part-of\":\"hwlab\",\"hwlab.pikastech.local/environment\":\"dev\",\"hwlab.pikastech.local/profile\":\"dev\",\"hwlab.pikastech.local/service-id\":\"hwlab-cli\"}},\"spec\":{\"containers\":[{\"env\":[{\"name\":\"HWLAB_CLI_ENDPOINT\",\"value\":\"http://74.48.78.17:16667\"}],\"image\":\"127.0.0.1:5000/hwlab/hwlab-cli:7e29522\",\"name\":\"hwlab-cli\"}],\"restartPolicy\":\"Never\"}}}}\n"}},"spec":{"template":{"spec":{"$setElementOrder/containers":[{"name":"hwlab-cli"}],"containers":[{"image":"127.0.0.1:5000/hwlab/hwlab-cli:7e29522","name":"hwlab-cli"}]}}}} to: Resource: "batch/v1, Resource=jobs", GroupVersionKind: "batch/v1, Kind=Job" Name: "hwlab-cli-template", Namespace: "hwlab-dev" for: "deploy/k8s/dev": error when patching "deploy/k8s/dev": Job.batch "hwlab-cli-template" is invalid: spec.template: Invalid value: {"labels":{"app.kubernetes.io/name":"hwlab-cli","app.kubernetes.io/part-of":"hwlab","batch.kubernetes.io/controller-uid":"ce763736-b67b-400c-8a09-5b3f62019b09","batch.kubernetes.io/job-name":"hwlab-cli-template","controller-uid":"ce763736-b67b-400c-8a09-5b3f62019b09","hwlab.pikastech.local/environment":"dev","hwlab.pikastech.local/profile":"dev","hwlab.pikastech.local/service-id":"hwlab-cli","job-name":"hwlab-cli-template"},"Spec":{"Volumes":null,"InitContainers":null,"Containers":[{"Name":"hwlab-cli","Image":"127.0.0.1:5000/hwlab/hwlab-cli:7e29522","Command":null,"Args":null,"WorkingDir":"","Ports":null,"EnvFrom":null,"Env":[{"Name":"HWLAB_CLI_ENDPOINT","Value":"http://74.48.78.17:16667","ValueFrom":null}],"Resources":{"Limits":null,"Requests":null,"Claims":null},"ResizePolicy":null,"RestartPolicy":null,"RestartPolicyRules":null,"VolumeMounts":null,"VolumeDevices":null,"LivenessProbe":null,"ReadinessProbe":null,"StartupProbe":null,"Lifecycle":null,"TerminationMessagePath":"/dev/termination-log","TerminationMessagePolicy":"File","ImagePullPolicy":"IfNotPresent","SecurityContext":null,"Stdin":false,"StdinOnce":false,"TTY":false}],"EphemeralContainers":null,"RestartPolicy":"Never","TerminationGracePeriodSeconds":30,"ActiveDeadlineSeconds":null,"DNSPolicy":"ClusterFirst","NodeSelector":null,"ServiceAccountName":"","AutomountServiceAccountToken":null,"NodeName":"","SecurityContext":{"HostNetwork":false,"HostPID":false,"HostIPC":false,"ShareProcessNamespace":null,"HostUsers":null,"SELinuxOptions":null,"WindowsOptions":null,"RunAsUser":null,"RunAsGroup":null,"RunAsNonRoot":null,"SupplementalGroups":null,"SupplementalGroupsPolicy":null,"FSGroup":null,"FSGroupChangePolicy":null,"Sysctls":null,"SeccompProfile":null,"AppArmorProfile":null,"SELinuxChangePolicy":null},"ImagePullSecrets":null,"Hostname":"","Subdomain":"","SetHostnameAsFQDN":null,"Affinity":null,"SchedulerName":"default-scheduler","Tolerations":null,"HostAliases":null,"PriorityClassName":"","Priority":null,"PreemptionPolicy":null,"DNSConfig":null,"ReadinessGates":null,"RuntimeClassName":null,"Overhead":null,"EnableServiceLinks":null,"TopologySpreadConstraints":null,"OS":null,"SchedulingGates":null,"ResourceClaims":null,"Resources":null,"HostnameOverride":null}}: field is immutable + Evidence required: Read-only kubectl/k3s report proving pods/services/configmaps are observable in hwlab-dev without reading Secrets. +5. Resolve the blocker and attach source/local/dry-run/DEV-live evidence at the correct level. Evidence required: A committed report with the exact evidence level and command used. ## Validation diff --git a/reports/dev-gate/dev-preflight-report.json b/reports/dev-gate/dev-preflight-report.json index 9bd3e46a..2cd425e0 100644 --- a/reports/dev-gate/dev-preflight-report.json +++ b/reports/dev-gate/dev-preflight-report.json @@ -14,19 +14,20 @@ "pikasTech/HWLAB#30", "pikasTech/HWLAB#31", "pikasTech/HWLAB#33", - "pikasTech/HWLAB#39", - "pikasTech/HWLAB#49", - "pikasTech/HWLAB#66", - "pikasTech/HWLAB#33", "pikasTech/HWLAB#35", - "pikasTech/HWLAB#48" + "pikasTech/HWLAB#39", + "pikasTech/HWLAB#43", + "pikasTech/HWLAB#48", + "pikasTech/HWLAB#49", + "pikasTech/HWLAB#57", + "pikasTech/HWLAB#66" ], "target": { "ref": "origin/main", - "commitId": "a1c3cb58da0067a12424277d47d9d50d0cbf7a9d", - "shortCommitId": "a1c3cb5" + "commitId": "82ad96c5c67c3906732a057d52395ec72851e4a9", + "shortCommitId": "82ad96c" }, - "generatedAt": "2026-05-22T04:31:08.449Z", + "generatedAt": "2026-05-22T05:35:39.805Z", "mode": "read-only", "devOnly": true, "prodDisabled": true, @@ -51,17 +52,43 @@ "artifactIdentity": { "source": { "ref": "origin/main", - "commitId": "a1c3cb58da0067a12424277d47d9d50d0cbf7a9d", - "shortCommitId": "a1c3cb5" + "commitId": "82ad96c5c67c3906732a057d52395ec72851e4a9", + "shortCommitId": "82ad96c" + }, + "artifactSource": { + "source": "artifact-publish-report", + "ref": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33", + "commitId": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33", + "shortCommitId": "7e29522" + }, + "targetCoverage": { + "sourceKind": "artifact-publish-report", + "sourceRef": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33", + "sourceCommitId": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33", + "sourceShortCommitId": "7e29522", + "targetRef": "origin/main", + "targetCommitId": "82ad96c5c67c3906732a057d52395ec72851e4a9", + "targetShortCommitId": "82ad96c", + "mode": "artifact-input-drift", + "covered": false, + "artifactBuildInputChanged": true, + "changedPathCount": 22, + "changedArtifactInputPaths": [ + "internal/mvp-gate/summary.mjs", + "web/hwlab-cloud-web/gate-summary.mjs" + ], + "changedNonArtifactPathCount": 20, + "reason": "target changes since the artifact source touch artifact build inputs" }, "deployManifest": { "path": "deploy/deploy.json", - "commitId": "73b379f", - "matchesSource": false + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false }, "artifactCatalog": { "path": "deploy/artifact-catalog.dev.json", - "commitId": "73b379f", + "commitId": "7e29522", "artifactState": "published", "ciPublished": true, "registryVerified": true, @@ -73,155 +100,169 @@ }, "requiredServiceCount": 13, "disabledServiceCount": 0, - "matchesSource": false + "matchesSource": true, + "matchesTarget": false }, "services": [ { "serviceId": "hwlab-cloud-api", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:73b379f", - "imageTag": "73b379f", - "digest": "sha256:561e50494bf13bf61f83d28b371bc39b860b21333ef9991711853a095bd535bf", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:7e29522", + "imageTag": "7e29522", + "digest": "sha256:090b6f919be3b3c7594ca4073b193351689fc525f478b64d54d393725cb01ecf", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-cloud-web", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:73b379f", - "imageTag": "73b379f", - "digest": "sha256:c7939658af9f1109e5384619163dd0d11e1a1de14e7d15d4cbde7c4400b495c2", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:7e29522", + "imageTag": "7e29522", + "digest": "sha256:bc6e836b2bb796b30562ed3ae93d8534146a3b74a310906481c8641646d1b8f0", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-agent-mgr", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:73b379f", - "imageTag": "73b379f", - "digest": "sha256:ae6ca76cd09a7d21e46e0076e12dea1843417a0d59d57b3115915c831e88ebef", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:7e29522", + "imageTag": "7e29522", + "digest": "sha256:4d9b8944bc52012bb0a4a3a345f8939381d2804032e544d0c98f49fac0e46bfd", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-agent-worker", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:73b379f", - "imageTag": "73b379f", - "digest": "sha256:4d5f8d8d404fc2826256fb690fdea5570285a34d1bdffbaf1e0c7ca39603ffd8", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522", + "imageTag": "7e29522", + "digest": "sha256:2582176e2c35a2bfbce4edfd922749397d45f6f1f8c04d0394c501f7d87323ee", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-gateway", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-gateway:73b379f", - "imageTag": "73b379f", - "digest": "sha256:ff9f3f3dc6332c3d8e4e9825657c296c9664d84a8d40c3ffeab3c1e91a484008", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-gateway:7e29522", + "imageTag": "7e29522", + "digest": "sha256:290341fd6e6f036aa953943072ad58e0d0cfcc0e13950e6090f941b3310755a6", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-gateway-simu", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:73b379f", - "imageTag": "73b379f", - "digest": "sha256:f5ccff29da331e424a482f92394d071e1be90c0244e7137e07ac33d9a7cc4082", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:7e29522", + "imageTag": "7e29522", + "digest": "sha256:02627f880c7ddf2102e2255a43097d1f604cfb7a22215736e328287e27fc5f03", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-box-simu", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-box-simu:73b379f", - "imageTag": "73b379f", - "digest": "sha256:2a12c1c462b2c01a9fa15efa75a6e1f17ecc8432dfa88bca53f0d8d4b6355daf", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-box-simu:7e29522", + "imageTag": "7e29522", + "digest": "sha256:e02c270c71f83a2f4624722bb84616bea8374ef43439f27bdce310e4baa8dcca", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-patch-panel", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:73b379f", - "imageTag": "73b379f", - "digest": "sha256:5bc9a1c7ce65026cd7bf6d20a311226b35c796a4d52a914266244bf3c1a17286", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:7e29522", + "imageTag": "7e29522", + "digest": "sha256:f730323f83c62797f382932582a05df921045c86383dad7951f3d639b32456a9", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-router", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-router:73b379f", - "imageTag": "73b379f", - "digest": "sha256:356f37a7d78cc2f86230c2037f43215ad66979fbe4a949cb9241b5957692d9d8", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-router:7e29522", + "imageTag": "7e29522", + "digest": "sha256:7c40c573078a9c325402bd47b2eb78a46c0c80564a228cf7c9fcf0cfba5bc6d2", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-tunnel-client", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:73b379f", - "imageTag": "73b379f", - "digest": "sha256:8ca553408a633d7f287ca9440f822fb1458dd9a028eb4db178b466b0b5505c49", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:7e29522", + "imageTag": "7e29522", + "digest": "sha256:b141dc88557b8f6391aa082fdb37c6f0db5bc3a76c97bb39ba00354a9208abd8", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-edge-proxy", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:73b379f", - "imageTag": "73b379f", - "digest": "sha256:480dea831051d45b6d63a489db9c0fa314f88bae35dbf72be4186bf1de356f38", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:7e29522", + "imageTag": "7e29522", + "digest": "sha256:792505139793c3f3da7769f9dc9d1cb3203ff92797305b62e8f12207c69a9831", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-cli", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-cli:73b379f", - "imageTag": "73b379f", - "digest": "sha256:125154cf59727ec230618c65b07a6235c18c1411f9ad51525ae411040169c9b5", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-cli:7e29522", + "imageTag": "7e29522", + "digest": "sha256:43d1c175091bfb462eddd7dd22a780d6485d86bdb052c36b78201606f48fadc1", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-agent-skills", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:73b379f", - "imageTag": "73b379f", - "digest": "sha256:5bdf9a4d17f8f4c7f3ecead99dcbd4de0ac346a2c28fef020b8853cf494df573", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:7e29522", + "imageTag": "7e29522", + "digest": "sha256:c75510038dc33196dc254472e78101d545c0d777a7b33b531f02b39faf2588b5", "publishState": "published", "artifactRequired": true, "notPublishedReason": null } ], "serviceCommitIds": [ - "73b379f" + "7e29522" ], "matchesSource": false, "publishVerified": true, @@ -233,7 +274,7 @@ "registryCapabilities": { "version": "v1", "registryPrefix": "127.0.0.1:5000/hwlab", - "generatedAt": "2026-05-22T04:31:07.663Z", + "generatedAt": "2026-05-22T05:35:38.863Z", "classification": "degraded", "dimensions": { "processHttpAccess": { @@ -281,7 +322,7 @@ "names": "unidesk-artifact-registry", "ports": "127.0.0.1:5000->5000/tcp", "state": "running", - "status": "Up 27 hours" + "status": "Up 28 hours" } ], "pushAttempted": false, @@ -420,22 +461,48 @@ "id": "target-commit-pinning", "category": "contract", "status": "blocked", - "summary": "Source origin/main a1c3cb5 is not covered by deploy commit 73b379f, catalog commit 73b379f, service commits 73b379f.", + "summary": "Source origin/main 82ad96c is not covered by artifact source 7e29522: target changes since the artifact source touch artifact build inputs.", "evidence": [ { "source": { "ref": "origin/main", - "commitId": "a1c3cb58da0067a12424277d47d9d50d0cbf7a9d", - "shortCommitId": "a1c3cb5" + "commitId": "82ad96c5c67c3906732a057d52395ec72851e4a9", + "shortCommitId": "82ad96c" + }, + "artifactSource": { + "source": "artifact-publish-report", + "ref": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33", + "commitId": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33", + "shortCommitId": "7e29522" + }, + "targetCoverage": { + "sourceKind": "artifact-publish-report", + "sourceRef": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33", + "sourceCommitId": "7e29522b65c8a316b7c3fde12bebcb5f6baf8c33", + "sourceShortCommitId": "7e29522", + "targetRef": "origin/main", + "targetCommitId": "82ad96c5c67c3906732a057d52395ec72851e4a9", + "targetShortCommitId": "82ad96c", + "mode": "artifact-input-drift", + "covered": false, + "artifactBuildInputChanged": true, + "changedPathCount": 22, + "changedArtifactInputPaths": [ + "internal/mvp-gate/summary.mjs", + "web/hwlab-cloud-web/gate-summary.mjs" + ], + "changedNonArtifactPathCount": 20, + "reason": "target changes since the artifact source touch artifact build inputs" }, "deployManifest": { "path": "deploy/deploy.json", - "commitId": "73b379f", - "matchesSource": false + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false }, "artifactCatalog": { "path": "deploy/artifact-catalog.dev.json", - "commitId": "73b379f", + "commitId": "7e29522", "artifactState": "published", "ciPublished": true, "registryVerified": true, @@ -447,155 +514,169 @@ }, "requiredServiceCount": 13, "disabledServiceCount": 0, - "matchesSource": false + "matchesSource": true, + "matchesTarget": false }, "services": [ { "serviceId": "hwlab-cloud-api", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:73b379f", - "imageTag": "73b379f", - "digest": "sha256:561e50494bf13bf61f83d28b371bc39b860b21333ef9991711853a095bd535bf", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:7e29522", + "imageTag": "7e29522", + "digest": "sha256:090b6f919be3b3c7594ca4073b193351689fc525f478b64d54d393725cb01ecf", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-cloud-web", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:73b379f", - "imageTag": "73b379f", - "digest": "sha256:c7939658af9f1109e5384619163dd0d11e1a1de14e7d15d4cbde7c4400b495c2", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:7e29522", + "imageTag": "7e29522", + "digest": "sha256:bc6e836b2bb796b30562ed3ae93d8534146a3b74a310906481c8641646d1b8f0", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-agent-mgr", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:73b379f", - "imageTag": "73b379f", - "digest": "sha256:ae6ca76cd09a7d21e46e0076e12dea1843417a0d59d57b3115915c831e88ebef", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:7e29522", + "imageTag": "7e29522", + "digest": "sha256:4d9b8944bc52012bb0a4a3a345f8939381d2804032e544d0c98f49fac0e46bfd", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-agent-worker", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:73b379f", - "imageTag": "73b379f", - "digest": "sha256:4d5f8d8d404fc2826256fb690fdea5570285a34d1bdffbaf1e0c7ca39603ffd8", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522", + "imageTag": "7e29522", + "digest": "sha256:2582176e2c35a2bfbce4edfd922749397d45f6f1f8c04d0394c501f7d87323ee", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-gateway", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-gateway:73b379f", - "imageTag": "73b379f", - "digest": "sha256:ff9f3f3dc6332c3d8e4e9825657c296c9664d84a8d40c3ffeab3c1e91a484008", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-gateway:7e29522", + "imageTag": "7e29522", + "digest": "sha256:290341fd6e6f036aa953943072ad58e0d0cfcc0e13950e6090f941b3310755a6", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-gateway-simu", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:73b379f", - "imageTag": "73b379f", - "digest": "sha256:f5ccff29da331e424a482f92394d071e1be90c0244e7137e07ac33d9a7cc4082", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:7e29522", + "imageTag": "7e29522", + "digest": "sha256:02627f880c7ddf2102e2255a43097d1f604cfb7a22215736e328287e27fc5f03", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-box-simu", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-box-simu:73b379f", - "imageTag": "73b379f", - "digest": "sha256:2a12c1c462b2c01a9fa15efa75a6e1f17ecc8432dfa88bca53f0d8d4b6355daf", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-box-simu:7e29522", + "imageTag": "7e29522", + "digest": "sha256:e02c270c71f83a2f4624722bb84616bea8374ef43439f27bdce310e4baa8dcca", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-patch-panel", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:73b379f", - "imageTag": "73b379f", - "digest": "sha256:5bc9a1c7ce65026cd7bf6d20a311226b35c796a4d52a914266244bf3c1a17286", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:7e29522", + "imageTag": "7e29522", + "digest": "sha256:f730323f83c62797f382932582a05df921045c86383dad7951f3d639b32456a9", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-router", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-router:73b379f", - "imageTag": "73b379f", - "digest": "sha256:356f37a7d78cc2f86230c2037f43215ad66979fbe4a949cb9241b5957692d9d8", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-router:7e29522", + "imageTag": "7e29522", + "digest": "sha256:7c40c573078a9c325402bd47b2eb78a46c0c80564a228cf7c9fcf0cfba5bc6d2", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-tunnel-client", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:73b379f", - "imageTag": "73b379f", - "digest": "sha256:8ca553408a633d7f287ca9440f822fb1458dd9a028eb4db178b466b0b5505c49", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:7e29522", + "imageTag": "7e29522", + "digest": "sha256:b141dc88557b8f6391aa082fdb37c6f0db5bc3a76c97bb39ba00354a9208abd8", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-edge-proxy", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:73b379f", - "imageTag": "73b379f", - "digest": "sha256:480dea831051d45b6d63a489db9c0fa314f88bae35dbf72be4186bf1de356f38", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:7e29522", + "imageTag": "7e29522", + "digest": "sha256:792505139793c3f3da7769f9dc9d1cb3203ff92797305b62e8f12207c69a9831", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-cli", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-cli:73b379f", - "imageTag": "73b379f", - "digest": "sha256:125154cf59727ec230618c65b07a6235c18c1411f9ad51525ae411040169c9b5", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-cli:7e29522", + "imageTag": "7e29522", + "digest": "sha256:43d1c175091bfb462eddd7dd22a780d6485d86bdb052c36b78201606f48fadc1", "publishState": "published", "artifactRequired": true, "notPublishedReason": null }, { "serviceId": "hwlab-agent-skills", - "commitId": "73b379f", - "matchesSource": false, - "image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:73b379f", - "imageTag": "73b379f", - "digest": "sha256:5bdf9a4d17f8f4c7f3ecead99dcbd4de0ac346a2c28fef020b8853cf494df573", + "commitId": "7e29522", + "matchesSource": true, + "matchesTarget": false, + "image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:7e29522", + "imageTag": "7e29522", + "digest": "sha256:c75510038dc33196dc254472e78101d545c0d777a7b33b531f02b39faf2588b5", "publishState": "published", "artifactRequired": true, "notPublishedReason": null } ], "serviceCommitIds": [ - "73b379f" + "7e29522" ], "matchesSource": false, "publishVerified": true, @@ -614,7 +695,7 @@ "evidence": [ { "path": "deploy/artifact-catalog.dev.json", - "commitId": "73b379f", + "commitId": "7e29522", "artifactState": "published", "ciPublished": true, "registryVerified": true, @@ -626,7 +707,8 @@ }, "requiredServiceCount": 13, "disabledServiceCount": 0, - "matchesSource": false + "matchesSource": true, + "matchesTarget": false } ] }, @@ -696,7 +778,7 @@ "names": "unidesk-artifact-registry", "ports": "127.0.0.1:5000->5000/tcp", "state": "running", - "status": "Up 27 hours" + "status": "Up 28 hours" } ], "pushAttempted": false, @@ -834,7 +916,7 @@ { "version": "v1", "registryPrefix": "127.0.0.1:5000/hwlab", - "generatedAt": "2026-05-22T04:31:07.663Z", + "generatedAt": "2026-05-22T05:35:38.863Z", "classification": "degraded", "dimensions": { "processHttpAccess": { @@ -882,7 +964,7 @@ "names": "unidesk-artifact-registry", "ports": "127.0.0.1:5000->5000/tcp", "state": "running", - "status": "Up 27 hours" + "status": "Up 28 hours" } ], "pushAttempted": false, @@ -1218,7 +1300,7 @@ "id": "dev-artifact-publish-report", "category": "registry", "status": "blocked", - "summary": "DEV artifact publish report status is published with 13/13 required services published for source 73b379f4441d47a99dfd978a80fd43727410af51; source states resolved: 13 source-present, 0 intentionally-disabled.", + "summary": "DEV artifact publish report status is published with 13/13 required services published for source 7e29522b65c8a316b7c3fde12bebcb5f6baf8c33; source states resolved: 13 source-present, 0 intentionally-disabled.", "evidence": [] }, { @@ -1236,19 +1318,19 @@ "host": "74.48.78.17", "port": 16667, "status": "connected", - "durationMs": 212 + "durationMs": 228 }, { "host": "74.48.78.17", "port": 7000, "status": "connected", - "durationMs": 1205 + "durationMs": 212 }, { "host": "74.48.78.17", "port": 7402, "status": "connected", - "durationMs": 232 + "durationMs": 216 } ], "kubernetesObservable": true @@ -1324,7 +1406,7 @@ "method": "GET", "status": 200, "statusText": "OK", - "body": "{\"serviceId\":\"hwlab-cloud-api\",\"environment\":\"dev\",\"status\":\"degraded\",\"service\":{\"id\":\"hwlab-cloud-api\",\"role\":\"cloud-api\",\"healthPath\":\"/health\",\"livePath\":\"/health/live\"},\"commit\":{\"id\":\"cb35ada\",\"source\":\"runtime-env\"},\"image\":{\"reference\":\"127.0.0.1:5000/hwlab/hwlab-cloud-api:cb35ada\",\"tag\":\"cb35ada\",\"digest\":\"unknown\"},\"endpoint\":\"http://74.48.78.17:16667\",\"observedAt\":\"2026-05-22T04:31:08.245Z\",\"db\":{\"contractVersion\":\"v1\",\"environment\":\"dev\",\"connected\":false,\"connectionChecked\":false,\"c" + "body": "{\"serviceId\":\"hwlab-cloud-api\",\"environment\":\"dev\",\"status\":\"degraded\",\"service\":{\"id\":\"hwlab-cloud-api\",\"role\":\"cloud-api\",\"healthPath\":\"/health\",\"livePath\":\"/health/live\"},\"commit\":{\"id\":\"cb35ada\",\"source\":\"runtime-env\"},\"image\":{\"reference\":\"127.0.0.1:5000/hwlab/hwlab-cloud-api:cb35ada\",\"tag\":\"cb35ada\",\"digest\":\"unknown\"},\"endpoint\":\"http://74.48.78.17:16667\",\"observedAt\":\"2026-05-22T05:35:39.607Z\",\"db\":{\"contractVersion\":\"v1\",\"environment\":\"dev\",\"connected\":false,\"connectionChecked\":false,\"c" } ] }, @@ -1336,105 +1418,105 @@ "evidence": [ { "serviceId": "hwlab-cloud-api", - "image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-cloud-api:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cloud-api/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cloud-api/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-cloud-web", - "image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-cloud-web:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cloud-web/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cloud-web/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-agent-mgr", - "image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-agent-mgr:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-mgr/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-mgr/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-agent-worker", - "image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-agent-worker:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-worker/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-worker/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-gateway", - "image": "127.0.0.1:5000/hwlab/hwlab-gateway:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-gateway:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-gateway/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-gateway/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-gateway-simu", - "image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-gateway-simu:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-gateway-simu/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-gateway-simu/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-box-simu", - "image": "127.0.0.1:5000/hwlab/hwlab-box-simu:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-box-simu:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-box-simu/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-box-simu/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-patch-panel", - "image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-patch-panel:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-patch-panel/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-patch-panel/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-router", - "image": "127.0.0.1:5000/hwlab/hwlab-router:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-router:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-router/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-router/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-tunnel-client", - "image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-tunnel-client:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-tunnel-client/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-tunnel-client/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-edge-proxy", - "image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-edge-proxy:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-edge-proxy/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-edge-proxy/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-cli", - "image": "127.0.0.1:5000/hwlab/hwlab-cli:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-cli:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cli/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-cli/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" }, { "serviceId": "hwlab-agent-skills", - "image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:73b379f", + "image": "127.0.0.1:5000/hwlab/hwlab-agent-skills:7e29522", "ok": false, - "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-skills/manifests/73b379f", + "url": "http://127.0.0.1:5000/v2/hwlab/hwlab-agent-skills/manifests/7e29522", "method": "HEAD", "error": "fetch failed ECONNREFUSED 127.0.0.1 5000" } @@ -1446,7 +1528,7 @@ "status": "open", "type": "contract_blocker", "scope": "artifact-source-commit", - "summary": "source commit origin/main a1c3cb5 does not match deploy/catalog artifact identity: deploy=73b379f, catalog=73b379f, services=73b379f.", + "summary": "source commit origin/main 82ad96c is not covered by artifact source 7e29522; target changes since the artifact source touch artifact build inputs.", "nextTask": "Refresh without fake digests using `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked`, or after a successful publish run `node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json`." }, { @@ -1460,8 +1542,8 @@ "status": "open", "type": "runtime_blocker", "scope": "dev-artifact-publish", - "summary": "reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for origin/main a1c3cb5; current status is published with 13/13 required services published and source states resolved: 13 source-present, 0 intentionally-disabled.", - "nextTask": "Complete DEV artifact publishing for every enabled required HWLAB service at the current origin/main commit and record immutable registry digests; keep disabled services marked not_published with reasons." + "summary": "reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for origin/main 82ad96c; current status is published with 13/13 required services published and source states resolved: 13 source-present, 0 intentionally-disabled.", + "nextTask": "Complete DEV artifact publishing for every enabled required HWLAB service at the artifact source commit, or prove the target commit has no artifact build input changes; keep disabled services marked not_published with reasons." }, { "status": "open", diff --git a/scripts/src/dev-evidence-blocker-aggregator.mjs b/scripts/src/dev-evidence-blocker-aggregator.mjs index 456a43a7..d92c7462 100644 --- a/scripts/src/dev-evidence-blocker-aggregator.mjs +++ b/scripts/src/dev-evidence-blocker-aggregator.mjs @@ -8,6 +8,8 @@ import { DEV_ENDPOINT, ENVIRONMENT_DEV, SERVICE_IDS } from "../../internal/proto export const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const deprecatedLegacyPublicPort = 6000 + 667; +const deprecatedLegacyPublicEndpoint = `http://74.48.78.17:${deprecatedLegacyPublicPort}`; const levels = Object.freeze(["SOURCE", "LOCAL", "DRY-RUN", "DEV-LIVE", "BLOCKED"]); const statusRank = Object.freeze({ pass: 0, @@ -263,9 +265,7 @@ function isEdgeOrFrpBlocker(blocker) { blocker.scope.includes("ingress") || blocker.scope.includes("frp") || blocker.summary.includes(":16667") || - blocker.summary.includes("16667") || - blocker.summary.includes(":6667") || - blocker.summary.includes("6667"); + blocker.summary.includes("16667"); } function sourceEntry(entry) { @@ -519,7 +519,7 @@ function hasCurrentLiveEdgeEvidence(edgeReport) { function isStaleLegacyIngressBlocker(blocker, sourceReport, reports) { const text = `${blocker.scope ?? ""} ${blocker.summary ?? ""}`; - const staleLegacyPort = text.includes("74.48.78.17:6667"); + const staleLegacyPort = text.includes(deprecatedLegacyPublicEndpoint); const stalePreflightEdgeProbe = sourceReport.path === reportPaths.devPreflight && blocker.type === "network_blocker" && (blocker.scope === "dev-edge" || blocker.scope === "dev-edge-health") && diff --git a/scripts/src/dev-gate-preflight.mjs b/scripts/src/dev-gate-preflight.mjs index 900101aa..4d28bf5e 100644 --- a/scripts/src/dev-gate-preflight.mjs +++ b/scripts/src/dev-gate-preflight.mjs @@ -17,9 +17,9 @@ const execFileAsync = promisify(execFile); const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const defaultReportPath = "reports/dev-gate/dev-preflight-report.json"; const issue = "pikasTech/HWLAB#34"; -const supports = ["#7", "#12", "#14", "#22", "#23", "#29", "#30", "#31", "#33", "#39", "#49", "#66"].map( +const supports = ["#7", "#12", "#14", "#22", "#23", "#29", "#30", "#31", "#33", "#35", "#39", "#43", "#48", "#49", "#57", "#66"].map( (id) => `pikasTech/HWLAB${id}` -).concat(["pikasTech/HWLAB#33", "pikasTech/HWLAB#35", "pikasTech/HWLAB#48"]); +); const forbiddenActions = [ "prod-deploy", "secret-material-read", @@ -39,6 +39,20 @@ const blockerTypes = new Set([ "safety_blocker" ]); const digestPattern = /^sha256:[a-f0-9]{64}$/; +const artifactBuildInputPrefixes = [ + "cmd/", + "internal/", + "skills/", + "tools/", + "web/" +]; +const artifactBuildInputFiles = new Set([ + "package.json", + "package-lock.json", + "npm-shrinkwrap.json", + "scripts/dev-artifact-publish.mjs", + "scripts/src/dev-artifact-services.mjs" +]); function parseArgs(argv) { const args = { @@ -210,6 +224,125 @@ function matchesTargetCommit(value, targetCommit, targetShortCommit) { return value === targetCommit || value === targetShortCommit; } +function isArtifactBuildInputPath(relativePath) { + return artifactBuildInputFiles.has(relativePath) || + artifactBuildInputPrefixes.some((prefix) => relativePath.startsWith(prefix)); +} + +async function resolveCommit(ref) { + if (!ref) return null; + const result = await run("git", ["rev-parse", `${ref}^{commit}`]); + if (!result.ok || !/^[a-f0-9]{40}$/u.test(result.stdout)) return null; + return result.stdout; +} + +async function sourceCoverageFor({ catalog, artifactReport, targetCommit, targetShortCommit, targetRef }) { + const reportSource = artifactReport?.artifactPublish?.sourceCommitId ?? artifactReport?.commitId ?? null; + const sourceRef = reportSource ?? catalog.commitId; + const sourceKind = reportSource ? "artifact-publish-report" : "artifact-catalog"; + const sourceCommit = await resolveCommit(sourceRef); + + if (!sourceCommit) { + return { + sourceKind, + sourceRef, + sourceCommitId: null, + sourceShortCommitId: null, + targetRef, + targetCommitId: targetCommit, + targetShortCommitId: targetShortCommit, + mode: "unresolved-source", + covered: false, + artifactBuildInputChanged: true, + changedPathCount: 0, + changedArtifactInputPaths: [], + changedNonArtifactPathCount: 0, + reason: `artifact source ${sourceRef ?? "unknown"} does not resolve to a local git commit` + }; + } + + if (matchesTargetCommit(sourceCommit, targetCommit, targetShortCommit)) { + return { + sourceKind, + sourceRef, + sourceCommitId: sourceCommit, + sourceShortCommitId: sourceCommit.slice(0, 7), + targetRef, + targetCommitId: targetCommit, + targetShortCommitId: targetShortCommit, + mode: "exact-target", + covered: true, + artifactBuildInputChanged: false, + changedPathCount: 0, + changedArtifactInputPaths: [], + changedNonArtifactPathCount: 0, + reason: "artifact source commit exactly matches the target ref" + }; + } + + const ancestor = await run("git", ["merge-base", "--is-ancestor", sourceCommit, targetCommit]); + if (!ancestor.ok) { + return { + sourceKind, + sourceRef, + sourceCommitId: sourceCommit, + sourceShortCommitId: sourceCommit.slice(0, 7), + targetRef, + targetCommitId: targetCommit, + targetShortCommitId: targetShortCommit, + mode: "non-ancestor-source", + covered: false, + artifactBuildInputChanged: true, + changedPathCount: 0, + changedArtifactInputPaths: [], + changedNonArtifactPathCount: 0, + reason: `artifact source ${sourceCommit.slice(0, 12)} is not an ancestor of ${targetRef} ${targetShortCommit}` + }; + } + + const diff = await run("git", ["diff", "--name-only", `${sourceCommit}..${targetCommit}`]); + if (!diff.ok) { + return { + sourceKind, + sourceRef, + sourceCommitId: sourceCommit, + sourceShortCommitId: sourceCommit.slice(0, 7), + targetRef, + targetCommitId: targetCommit, + targetShortCommitId: targetShortCommit, + mode: "diff-unavailable", + covered: false, + artifactBuildInputChanged: true, + changedPathCount: 0, + changedArtifactInputPaths: [], + changedNonArtifactPathCount: 0, + reason: diff.stderr || diff.error || "git diff failed" + }; + } + + const changedPaths = diff.stdout.split("\n").map((line) => line.trim()).filter(Boolean); + const changedArtifactInputPaths = changedPaths.filter(isArtifactBuildInputPath); + const covered = changedArtifactInputPaths.length === 0; + return { + sourceKind, + sourceRef, + sourceCommitId: sourceCommit, + sourceShortCommitId: sourceCommit.slice(0, 7), + targetRef, + targetCommitId: targetCommit, + targetShortCommitId: targetShortCommit, + mode: covered ? "report-only-target" : "artifact-input-drift", + covered, + artifactBuildInputChanged: changedArtifactInputPaths.length > 0, + changedPathCount: changedPaths.length, + changedArtifactInputPaths, + changedNonArtifactPathCount: changedPaths.length - changedArtifactInputPaths.length, + reason: covered + ? "target changes since the artifact source do not touch artifact build inputs" + : "target changes since the artifact source touch artifact build inputs" + }; +} + function uniqueSorted(values) { return [...new Set(values)].sort(); } @@ -238,15 +371,24 @@ function disabledCatalogServices(catalog) { return (catalog.services ?? []).filter((service) => service.artifactRequired === false); } -function artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit, targetRef }) { +async function artifactIdentityFor({ deploy, catalog, artifactReport, targetCommit, targetShortCommit, targetRef }) { + const targetCoverage = await sourceCoverageFor({ + catalog, + artifactReport, + targetCommit, + targetShortCommit, + targetRef + }); + const artifactSourceCommit = targetCoverage.sourceCommitId ?? targetCommit; + const artifactSourceShortCommit = targetCoverage.sourceShortCommitId ?? targetShortCommit; const serviceCommitIds = uniqueSorted((catalog.services ?? []).map((service) => service.commitId)); const digestCounts = catalogDigestCounts(catalog); const requiredServices = requiredCatalogServices(catalog); const disabledServices = disabledCatalogServices(catalog); - const catalogMatchesSource = matchesTargetCommit(catalog.commitId, targetCommit, targetShortCommit); - const deployMatchesSource = matchesTargetCommit(deploy.commitId, targetCommit, targetShortCommit); + const catalogMatchesSource = matchesTargetCommit(catalog.commitId, artifactSourceCommit, artifactSourceShortCommit); + const deployMatchesSource = matchesTargetCommit(deploy.commitId, artifactSourceCommit, artifactSourceShortCommit); const servicesMatchSource = serviceCommitIds.length === 1 && - matchesTargetCommit(serviceCommitIds[0], targetCommit, targetShortCommit); + matchesTargetCommit(serviceCommitIds[0], artifactSourceCommit, artifactSourceShortCommit); const allRequiredDigestsPublished = requiredServices.length > 0 && requiredServices.every((service) => digestPattern.test(service.digest) && service.publishState === "published") && disabledServices.every((service) => service.digest === "not_published" && service.publishState === "skeleton-only") && @@ -262,10 +404,18 @@ function artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit, commitId: targetCommit, shortCommitId: targetShortCommit }, + artifactSource: { + source: targetCoverage.sourceKind, + ref: targetCoverage.sourceRef, + commitId: targetCoverage.sourceCommitId, + shortCommitId: targetCoverage.sourceShortCommitId + }, + targetCoverage, deployManifest: { path: "deploy/deploy.json", commitId: deploy.commitId, - matchesSource: deployMatchesSource + matchesSource: deployMatchesSource, + matchesTarget: matchesTargetCommit(deploy.commitId, targetCommit, targetShortCommit) }, artifactCatalog: { path: "deploy/artifact-catalog.dev.json", @@ -277,12 +427,14 @@ function artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit, digestCounts, requiredServiceCount: requiredServices.length, disabledServiceCount: disabledServices.length, - matchesSource: catalogMatchesSource + matchesSource: catalogMatchesSource, + matchesTarget: matchesTargetCommit(catalog.commitId, targetCommit, targetShortCommit) }, services: (catalog.services ?? []).map((service) => ({ serviceId: service.serviceId, commitId: service.commitId, - matchesSource: matchesTargetCommit(service.commitId, targetCommit, targetShortCommit), + matchesSource: matchesTargetCommit(service.commitId, artifactSourceCommit, artifactSourceShortCommit), + matchesTarget: matchesTargetCommit(service.commitId, targetCommit, targetShortCommit), image: service.image, imageTag: service.imageTag, digest: service.digest, @@ -291,7 +443,7 @@ function artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit, notPublishedReason: service.notPublishedReason ?? null })), serviceCommitIds, - matchesSource: deployMatchesSource && catalogMatchesSource && servicesMatchSource, + matchesSource: targetCoverage.covered && deployMatchesSource && catalogMatchesSource && servicesMatchSource, publishVerified, refreshCommands: { blocked: `node scripts/refresh-artifact-catalog.mjs --target-ref ${targetRef} --blocked`, @@ -399,9 +551,16 @@ function makeReporter() { }; } -function validateLocalContracts(reporter, contracts, targetShortCommit, targetCommit, targetRef) { +async function validateLocalContracts(reporter, contracts, optionalReports, targetShortCommit, targetCommit, targetRef) { const [deploy, catalog, namespace, workloads, services, devKustomization, healthContract, masterEdge] = contracts; - const artifactIdentity = artifactIdentityFor({ deploy, catalog, targetCommit, targetShortCommit, targetRef }); + const artifactIdentity = await artifactIdentityFor({ + deploy, + catalog, + artifactReport: optionalReports.artifactPublish, + targetCommit, + targetShortCommit, + targetRef + }); try { assertStaticContract(deploy, catalog); @@ -417,25 +576,30 @@ function validateLocalContracts(reporter, contracts, targetShortCommit, targetCo } if (artifactIdentity.matchesSource) { + const coverage = artifactIdentity.targetCoverage; + const coverageSuffix = coverage.mode === "exact-target" + ? "exact target commit" + : `${coverage.mode}; ${coverage.changedPathCount} changed path(s), ${coverage.changedArtifactInputPaths.length} artifact input change(s)`; reporter.check( "target-commit-pinning", "contract", "pass", - `Source ${targetRef} ${targetShortCommit} matches deploy/catalog artifact commit ${artifactIdentity.artifactCatalog.commitId}.`, + `Source ${targetRef} ${targetShortCommit} is covered by artifact source ${artifactIdentity.artifactSource.shortCommitId}; ${coverageSuffix}.`, [artifactIdentity] ); } else { + const coverage = artifactIdentity.targetCoverage; reporter.check( "target-commit-pinning", "contract", "blocked", - `Source ${targetRef} ${targetShortCommit} is not covered by deploy commit ${deploy.commitId}, catalog commit ${catalog.commitId}, service commits ${artifactIdentity.serviceCommitIds.join(", ")}.`, + `Source ${targetRef} ${targetShortCommit} is not covered by artifact source ${artifactIdentity.artifactSource.shortCommitId ?? "unknown"}: ${coverage.reason}.`, [artifactIdentity] ); reporter.block({ type: "contract_blocker", scope: "artifact-source-commit", - summary: `source commit ${targetRef} ${targetShortCommit} does not match deploy/catalog artifact identity: deploy=${deploy.commitId}, catalog=${catalog.commitId}, services=${artifactIdentity.serviceCommitIds.join(", ")}.`, + summary: `source commit ${targetRef} ${targetShortCommit} is not covered by artifact source ${artifactIdentity.artifactSource.shortCommitId ?? "unknown"}; ${coverage.reason}.`, nextTask: `Refresh without fake digests using \`${artifactIdentity.refreshCommands.blocked}\`, or after a successful publish run \`${artifactIdentity.refreshCommands.published}\`.` }); } @@ -480,7 +644,7 @@ function validateLocalContracts(reporter, contracts, targetShortCommit, targetCo return { deploy, catalog, masterEdge, artifactIdentity }; } -function validateArtifactPublishReport(reporter, artifactReport, targetShortCommit, targetCommit, targetRef) { +function validateArtifactPublishReport(reporter, artifactReport, artifactIdentity, targetShortCommit, targetCommit, targetRef) { if (!artifactReport) { reporter.check("dev-artifact-publish-report", "registry", "blocked", "No DEV artifact publish report is present."); reporter.block({ @@ -510,15 +674,26 @@ function validateArtifactPublishReport(reporter, artifactReport, targetShortComm ); const sourceMatchesTarget = [targetCommit, targetShortCommit].includes(artifactPublish?.sourceCommitId) || [targetCommit, targetShortCommit].includes(artifactReport.commitId); + const sourceCoversTarget = artifactIdentity?.targetCoverage?.covered === true && + artifactIdentity?.artifactSource?.commitId && + ( + artifactPublish?.sourceCommitId === artifactIdentity.artifactSource.commitId || + artifactPublish?.sourceCommitId === artifactIdentity.artifactSource.shortCommitId || + artifactReport.commitId === artifactIdentity.artifactSource.commitId || + artifactReport.commitId === artifactIdentity.artifactSource.shortCommitId + ); const publishReady = artifactPublish?.status === "published" && artifactPublish.publishedCount === requiredServices.length && allServicesAccountedFor && allRequiredServicesPublished && disabledServicesNotPublished && - sourceMatchesTarget; + (sourceMatchesTarget || sourceCoversTarget); if (publishReady) { - reporter.check("dev-artifact-publish-report", "registry", "pass", "DEV artifact publish report covers all required enabled service IDs with immutable digests for the target commit, and records disabled service reasons."); + const summary = sourceMatchesTarget + ? "DEV artifact publish report covers all required enabled service IDs with immutable digests for the target commit, and records disabled service reasons." + : `DEV artifact publish report covers artifact source ${artifactIdentity.artifactSource.shortCommitId}; target ${targetRef} ${targetShortCommit} has no artifact build input changes since that source.`; + reporter.check("dev-artifact-publish-report", "registry", "pass", summary, [artifactIdentity?.targetCoverage].filter(Boolean)); return; } @@ -537,7 +712,7 @@ function validateArtifactPublishReport(reporter, artifactReport, targetShortComm type: "runtime_blocker", scope: "dev-artifact-publish", summary: `reports/dev-gate/dev-artifacts.json does not prove all required HWLAB service artifacts for ${targetRef} ${targetShortCommit}; current status is ${artifactPublish?.status ?? "missing"} with ${publishedCount}/${requiredServices.length || serviceCount} required services published and ${sourceSummary}.`, - nextTask: "Complete DEV artifact publishing for every enabled required HWLAB service at the current origin/main commit and record immutable registry digests; keep disabled services marked not_published with reasons." + nextTask: "Complete DEV artifact publishing for every enabled required HWLAB service at the artifact source commit, or prove the target commit has no artifact build input changes; keep disabled services marked not_published with reasons." }); } @@ -868,9 +1043,9 @@ async function validateLiveProbes(reporter, catalog, timeoutMs) { if (registryStatus === "blocked") { reporter.block({ type: "runtime_blocker", - scope: "catalog-image-manifest-read", - summary: "This preflight could not verify registry manifests for the required DEV catalog images without reading credentials.", - nextTask: "Publish required DEV images or provide a non-secret registry evidence artifact with immutable digests for each required HWLAB service." + scope: "registry-manifest-read", + summary: "This preflight could not verify catalog image manifests through the runner process path; this is a #66 registry reachability dimension, not evidence that publish digests are missing.", + nextTask: "Resolve the #66 registry reachability path or provide a non-secret registry reachability artifact; do not rerun heavy publish solely for this manifest-read probe." }); } } @@ -987,9 +1162,10 @@ export async function runPreflight(argv) { registryPrefix, timeoutMs: args.timeoutMs }); - const { deploy, catalog, masterEdge, artifactIdentity } = validateLocalContracts( + const { deploy, catalog, masterEdge, artifactIdentity } = await validateLocalContracts( reporter, contracts, + optionalReports, targetShortCommit, targetCommit, args.targetRef @@ -997,7 +1173,7 @@ export async function runPreflight(argv) { validateRegistryCapabilities(reporter, registryCapabilities); validateCloudApiDbContract(reporter, deploy, contracts[3]); - validateArtifactPublishReport(reporter, optionalReports.artifactPublish, targetShortCommit, targetCommit, args.targetRef); + validateArtifactPublishReport(reporter, optionalReports.artifactPublish, artifactIdentity, targetShortCommit, targetCommit, args.targetRef); validateEdgeHealthReport(reporter, optionalReports.edgeHealth); await validateEdgeContracts(reporter, masterEdge); validateRuntimeBoundary(reporter, deploy);