From 44851d8eb32fb320cf640bf67b2518d3c4428556 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 28 May 2026 21:16:43 +0800 Subject: [PATCH] docs: consolidate v0.2 documentation governance --- AGENTS.md | 9 +- README.md | 102 ----- docs/artifact-catalog.md | 189 --------- docs/cloud-api-runtime.md | 130 ------ docs/cloud-web-workbench.md | 169 -------- docs/d601-k3s-readonly-observability.md | 57 --- docs/dev-acceptance-matrix.md | 150 ------- docs/dev-base-image-preflight.md | 142 ------- docs/dev-edge-health.md | 113 ------ docs/dev-evidence-blocker-aggregator.md | 135 ------ docs/dev-gate-preflight.md | 159 -------- docs/dev-gate-report.md | 151 ------- docs/dev-m4-agent-loop.md | 78 ---- docs/m0-contract-audit.md | 109 ----- docs/m1-local-smoke.md | 82 ---- docs/m3-hardware-loop.md | 142 ------- docs/m4-agent-loop.md | 72 ---- docs/m5-mvp-e2e.md | 116 ------ docs/operator-runbook.md | 384 ------------------ docs/plan/device-pod-cli-mvp.md | 85 ---- docs/plan/device-pod-server-mvp.md | 12 - docs/plan/device-pod-sidebar-fake-service.md | 35 -- docs/plan/hwlab-v02-namespace-cicd.md | 178 -------- docs/plan/v02-device-pod-spec-migration.md | 136 ------- docs/plan/v02-multi-user-migration.md | 145 ------- docs/reference/architecture.md | 10 +- docs/reference/cloud-workbench.md | 4 +- docs/reference/commander-collaboration.md | 2 +- docs/reference/dev-runtime-boundary.md | 6 +- docs/reference/device-pod.md | 2 +- docs/reference/documentation-governance.md | 6 +- docs/reference/spec-device-pod.md | 2 + docs/reference/spec-user-access.md | 5 +- docs/reference/spec-v02-cicd.md | 6 +- .../spec-v02-documentation-governance.md | 64 +++ docs/runtime-boundary-guard.md | 60 --- docs/schema-drift-map.md | 83 ---- docs/topology-constraints.md | 46 --- .../mvp/m5-e2e}/dev-acceptance-checklist.json | 6 +- fixtures/mvp/m5-e2e/dry-run-plan.json | 4 +- internal/mvp-gate/summary.mjs | 18 +- .../m0-contract/deploy-manifest.dev.json | 8 + .../examples/m0-contract/service-ids.json | 1 + scripts/artifact-publish.mjs | 7 +- scripts/dev-m3-hardware-loop-smoke.mjs | 12 +- scripts/dev-m4-agent-loop-smoke.mjs | 2 +- scripts/m5-mvp-e2e-dry-run.mjs | 6 +- scripts/src/dev-cloud-workbench-smoke-lib.mjs | 5 +- scripts/src/dev-edge-health-smoke-lib.mjs | 6 +- .../src/dev-evidence-blocker-aggregator.mjs | 2 +- scripts/validate-m0-contract.mjs | 13 +- 51 files changed, 139 insertions(+), 3327 deletions(-) delete mode 100644 README.md delete mode 100644 docs/artifact-catalog.md delete mode 100644 docs/cloud-api-runtime.md delete mode 100644 docs/cloud-web-workbench.md delete mode 100644 docs/d601-k3s-readonly-observability.md delete mode 100644 docs/dev-acceptance-matrix.md delete mode 100644 docs/dev-base-image-preflight.md delete mode 100644 docs/dev-edge-health.md delete mode 100644 docs/dev-evidence-blocker-aggregator.md delete mode 100644 docs/dev-gate-preflight.md delete mode 100644 docs/dev-gate-report.md delete mode 100644 docs/dev-m4-agent-loop.md delete mode 100644 docs/m0-contract-audit.md delete mode 100644 docs/m1-local-smoke.md delete mode 100644 docs/m3-hardware-loop.md delete mode 100644 docs/m4-agent-loop.md delete mode 100644 docs/m5-mvp-e2e.md delete mode 100644 docs/operator-runbook.md delete mode 100644 docs/plan/device-pod-cli-mvp.md delete mode 100644 docs/plan/device-pod-server-mvp.md delete mode 100644 docs/plan/device-pod-sidebar-fake-service.md delete mode 100644 docs/plan/hwlab-v02-namespace-cicd.md delete mode 100644 docs/plan/v02-device-pod-spec-migration.md delete mode 100644 docs/plan/v02-multi-user-migration.md create mode 100644 docs/reference/spec-v02-documentation-governance.md delete mode 100644 docs/runtime-boundary-guard.md delete mode 100644 docs/schema-drift-map.md delete mode 100644 docs/topology-constraints.md rename {docs => fixtures/mvp/m5-e2e}/dev-acceptance-checklist.json (98%) diff --git a/AGENTS.md b/AGENTS.md index d1d991e7..0695024b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,6 +30,12 @@ HWLAB 是硬件实验室运行面和控制面项目。本文是 agent、指挥 - 架构迁移时,过时的自检、预检、guard、gate 优先拆除;不要在旧门禁上继续加例外、加复杂度或制造噪声。 - 新增自检、预检、guard、gate 必须遵循最小原则,只覆盖明确高价值风险;禁止乱加门禁导致系统僵化、难迁移、难调试或产生大量误报和摩擦。 +## P0 v0.2 文档治理 + +- `AGENTS.md` 是唯一顶级入口;`README.md`、`docs/*.md`、`docs/*.json` 和 `docs/plan/*.md` 不再作为 v0.2 仓库内文档形态保留。 +- 计划、里程碑、阶段迁移、一次性排障和旧报告全文迁入 GitHub issue;长期参考只吸收稳定结论并引用对应 issue。 +- v0.2 文档树收敛、D601/G14 旧口径处理和 JSON 放置边界见 [docs/reference/spec-v02-documentation-governance.md](docs/reference/spec-v02-documentation-governance.md)。 + ## 工作区 - G14 分支固定 source workspace 是 G14 节点上的 `/root/hwlab`,固定使用 `G14` 分支和 `origin git@github.com:pikasTech/HWLAB.git`。在 G14 上进行代码、文档、GitOps render、Tekton/poller/Argo CD 修复或 CI/CD 验证前,必须先确认 `pwd` 为 `/root/hwlab` 且 `git status --short --branch` 为 `G14...origin/G14`;不满足时先停止并修正 workspace。 @@ -78,6 +84,7 @@ HWLAB 是硬件实验室运行面和控制面项目。本文是 agent、指挥 - 中文优先规则:[docs/reference/chinese-first-documentation.md](docs/reference/chinese-first-documentation.md) - 用户反馈分流规则:[docs/reference/user-feedback-triage.md](docs/reference/user-feedback-triage.md) - 文档治理与 docs-spec 本地权威:[docs/reference/documentation-governance.md](docs/reference/documentation-governance.md) +- v0.2 文档治理规格、过程文档迁 issue、`docs/` 根目录清理和 D601/G14 旧口径收敛:[docs/reference/spec-v02-documentation-governance.md](docs/reference/spec-v02-documentation-governance.md) - 架构和 M3 主线:[docs/reference/architecture.md](docs/reference/architecture.md) - DEV 运行态、端口、k3s 和 DB DNS 边界:[docs/reference/dev-runtime-boundary.md](docs/reference/dev-runtime-boundary.md) - G14 GitOps 发布、SecretRef preflight、runner/host 边界、镜像发布和单纯文档/CLI 直推规则:[docs/reference/g14-gitops-cicd.md](docs/reference/g14-gitops-cicd.md)、[docs/reference/commander-collaboration.md](docs/reference/commander-collaboration.md) @@ -97,7 +104,7 @@ HWLAB 是硬件实验室运行面和控制面项目。本文是 agent、指挥 - 中文优先:issue、PR 正文、长期参考文档和用户可见说明默认用中文;英文术语只在命令、协议、接口、ID、路径和标准名需要保真时保留,详见 [docs/reference/chinese-first-documentation.md](docs/reference/chinese-first-documentation.md)。 - 用户反馈优先:用户和参谋提出的问题默认按高优先级用户反馈处理,blocker 状态不能替代反馈分流,必须挂到 [pikasTech/HWLAB#7](https://github.com/pikasTech/HWLAB/issues/7) 醒目位置,详见 [docs/reference/user-feedback-triage.md](docs/reference/user-feedback-triage.md)。 - docs-spec 本地权威优先:涉及 `AGENTS.md`、`docs/reference/*.md` 或过程文档蒸馏时,先按 [docs/reference/documentation-governance.md](docs/reference/documentation-governance.md) 执行,不另建同级规则副本。 -- 交付路径按风险选择:单纯文档、CLI/helper 轻量变更直接提交并 push 到 `origin/G14`,不开 PR;业务代码、运行面、发布链路、Secret、权限、数据迁移、PROD 或其他高风险变更走 PR 工作流,详见 [docs/reference/commander-collaboration.md](docs/reference/commander-collaboration.md)。 +- 交付路径按风险选择:单纯文档、CLI/helper 轻量变更直接提交并 push 到当前工作线的 source branch,G14 默认 `origin/G14`,`v0.2` 默认 `origin/v0.2`;业务代码、运行面、发布链路、Secret、权限、数据迁移、PROD 或其他高风险变更走 PR 工作流,详见 [docs/reference/commander-collaboration.md](docs/reference/commander-collaboration.md)。 ## 常用轻量命令 diff --git a/README.md b/README.md deleted file mode 100644 index d1e6da23..00000000 --- a/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# HWLAB - -HWLAB is the hardware lab runtime and control plane for MVP development. - -This repository is intentionally small at L0. It defines the shared protocol -contract, schema skeletons, deploy manifest schema, and minimal validation -entry points that later service implementations must follow. - -## MVP Freeze - -- MVP scope is DEV only. -- DEV browser/frontend endpoint is fixed at `http://74.48.78.17:16666/`. -- DEV API/edge/live endpoint is fixed at `http://74.48.78.17:16667`. -- Legacy `:6666` and `:6667` are historical/deprecated only and are not MVP - acceptance targets. -- UniDesk may be used only as an external scheduling, CI, or CD base. -- HWLAB runtime services must not be replaced by UniDesk backend, - provider-gateway, or microservice proxy implementations. - -## Frozen Service IDs - -- `hwlab-cloud-api` -- `hwlab-cloud-web` -- `hwlab-agent-mgr` -- `hwlab-agent-worker` -- `hwlab-gateway` -- `hwlab-gateway-simu` -- `hwlab-box-simu` -- `hwlab-patch-panel` -- `hwlab-router` -- `hwlab-tunnel-client` -- `hwlab-edge-proxy` -- `hwlab-cli` -- `hwlab-agent-skills` - -## Frozen Repository Layout - -The MVP branches may add implementation files under these paths: - -- `cmd/...` -- `internal/...` -- `web/hwlab-cloud-web` -- `tools/hwlab-cli` -- `skills` -- `protocol/schemas` -- `deploy/deploy.json` -- `deploy/k8s/base/dev/prod` -- `deploy/master-edge` -- `deploy/frp` -- `scripts/bootstrap-skills.sh` -- `scripts/worker-entrypoint.sh` - -## Contract Index - -- Protocol contract: [protocol/README.md](protocol/README.md) -- JSON-RPC envelope: [protocol/json-rpc.md](protocol/json-rpc.md) -- Error codes: [protocol/errors.md](protocol/errors.md) -- Audit fields: [protocol/audit.md](protocol/audit.md) -- Capability model: [protocol/capabilities.md](protocol/capabilities.md) -- Topology constraints: [protocol/topology.md](protocol/topology.md) -- MVP e2e contract: [protocol/mvp-e2e-contract.md](protocol/mvp-e2e-contract.md) -- JSON Schemas: [protocol/schemas](protocol/schemas) -- Deploy schema: [deploy/deploy.schema.json](deploy/deploy.schema.json) -- M3 rollout support runbook: [docs/reference/m3-loop-rollout-runbook.md](docs/reference/m3-loop-rollout-runbook.md) - -## Validation - -Run the lightweight validation suite: - -```sh -npm run check -``` - -Run only the L2 gateway/box simulator runtime smoke: - -```sh -npm run l2:smoke -``` - -## L6 Manual Acceptance Entry - -The external MVP acceptance surface is DEV-only and report-driven: - -```sh -npm run l6:smoke -npm run web:m3-readonly -npm run web:check -npm run cli:dry-run -node tools/hwlab-cli/bin/hwlab-cli.mjs test e2e --env dev --mvp -``` - -`npm run web:m3-readonly` is the Cloud Web #59 guardrail: it checks that the -browser entry remains on public `:16666`, API/edge diagnostics remain on public -`:16667`, the page only calls read-only diagnostics RPCs, and M3 stays blocked -unless the real `DO1 -> hwlab-patch-panel -> DI1` DEV-LIVE evidence exists. - -The CLI command defaults to a JSON dry-run plan sourced from -`GitHub issue/PR comments` and -`fixtures/mvp/m5-e2e/dry-run-plan.json`. A live DEV attempt requires -`--live --confirm-dev --confirmed-non-production`; with open gate blockers it -returns `BLOCKED` evidence rather than using fixtures or UniDesk runtime as a -substitute. diff --git a/docs/artifact-catalog.md b/docs/artifact-catalog.md deleted file mode 100644 index a84f98d8..00000000 --- a/docs/artifact-catalog.md +++ /dev/null @@ -1,189 +0,0 @@ -# HWLAB Artifact Catalog Contract - -The artifact catalog is the DEV-only MVP contract for interpreting generated -deployment artifacts. It pins which HWLAB service image, commit, profile, -namespace, and health path GitOps render must inject into runtime manifests. -`deploy/deploy.json` stays the human-authored runtime config truth source. - -This file is not automatically a CI publish record. It proves only the state it -declares: - -- `artifactState: "contract-skeleton"` means the source/artifact commit and image - tags are aligned, but `ciPublished=false`, `registryVerified=false`, and every - digest must stay `not_published`. -- `artifactState: "published"` is allowed only after a DEV publish report proves - every required enabled service was published for the same source commit with a - real `sha256:<64 hex>` registry digest. Services explicitly disabled in the - service inventory must stay `not_published` and carry a disabled reason. - -Do not infer registry existence, digest values, or deployment from commit tags. -Real publish evidence must come from the publishing workflow and registry -metadata, then be copied into the catalog by the refresh command below. - -## Scope - -- Environment: DEV only. -- Namespace: `hwlab-dev`. -- Public DEV endpoint: `http://74.48.78.17:16667`. -- Profile: `dev`. -- Health path: `/health/live`. -- Artifact state: contract skeleton only. -- PROD deployment, PROD smoke, secret reads, force push, real image publish, and - UniDesk runtime substitution are forbidden. - -## Files - -| File | Role | -| --- | --- | -| `deploy/artifact-catalog.dev.json` | Machine-readable DEV artifact identity truth for generated image, digest, commit, and publish provenance fields. | -| `deploy/deploy.json` | Human-authored DEV runtime config such as service topology, env, health, profile, replicas, and endpoints. | -| `scripts/g14-gitops-render.mjs` | Declares the Tekton primitive CI tasks and minimal guardrails that generate the G14 CI/CD control plane. | -| `scripts/deploy-desired-state-plan.mjs` | Read-only planner/checker for catalog artifact identity, generated identity leakage into deploy config, and deploy/runtime config contracts. | -| `scripts/refresh-artifact-catalog.mjs` | Previews artifact catalog identity by default; only G14 Tekton promotion uses `--write` to update `deploy/artifact-catalog.dev.json` before committing generated state to `G14-gitops`. | -| `scripts/validate-artifact-catalog.mjs` | Local static validator for the catalog and deploy manifest skeleton. | -| `scripts/preflight-dev-base-image.mjs` | Local DEV builder base-image preflight for future artifact publish. | -| `docs/dev-base-image-preflight.md` | Operator contract for interpreting preflight readiness and blockers. | - -## Pin Rules - -Every service entry in `deploy/artifact-catalog.dev.json` must satisfy these -rules: - -| Field | Rule | -| --- | --- | -| `serviceId` | Must be one of the frozen HWLAB service IDs and must appear exactly once. | -| `commitId` | Must match the top-level catalog commit ID. Short or full lowercase Git SHA is allowed. | -| `image` | Must match the DEV registry target `//:`. The matching field must not be copied into `deploy/deploy.json`. | -| `imageTag` | Must be the first seven characters of `commitId`. Mutable tags such as `latest`, `dev`, or `main` are forbidden. | -| `profile` | Must be `dev`. | -| `namespace` | Must be `hwlab-dev`. | -| `healthPath` | Must be `/health/live` and match the DEV health contract. | -| `publishState` | Must be `skeleton-only` in a blocked skeleton catalog, or `published` only when the catalog was refreshed from a successful publish report. | -| `sourceState` | Must be `source-present` for MVP services with repository source, or `intentionally-disabled` for zero-replica services excluded from MVP publication. | -| `artifactRequired` | Must match `serviceInventory.requiredServiceIds`; only required services need publish digests. | -| `artifactScope` | `required` for services that must be published, or `disabled` with a `notPublishedReason`. | -| `digest` | Must be `not_published` in the skeleton catalog; it may be a registry `sha256:<64 hex>` digest only after publish evidence exists. | - -The catalog `commitId` is the artifact source commit, not proof that a registry -artifact exists. It must match every service `commitId` 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. - -## Desired-State Plan - -Use the read-only planner before refreshing or reviewing deploy desired-state: - -```sh -node scripts/deploy-desired-state-plan.mjs --plan --pretty -node scripts/deploy-desired-state-plan.mjs --check -node scripts/deploy-desired-state-plan.mjs --target-ref origin/G14 --pretty -node scripts/deploy-desired-state-plan.mjs --target-tag --pretty -node scripts/deploy-desired-state-plan.mjs --promotion-commit --check -``` - -The planner treats `deploy/deploy.json` as human-authored runtime config, -`deploy/artifact-catalog.dev.json` as artifact identity truth, and -`deploy/k8s/base/workloads.yaml` as a runtime template. It reports catalog -service `commitId`/`image`/`imageTag`, blocks generated artifact identity that -leaks into `deploy.json`, and leaves workload image/env mirror values to GitOps -render because render overwrites them from the catalog. - -`--check` exits non-zero when the source files are missing or invalid, generated -artifact identity leaks into `deploy.json`, an explicit target tag is invalid or -mutable, or catalog artifact identity does not match the requested target. The -source branch catalog is only a seed contract; published artifact identity is -stored on `G14-gitops`. The optional report snapshot is contextual evidence only -and is not an authoritative desired-state source. - -For PR review or CI/CD promotion handoff, use `--promotion-commit ---check`. That mode is stricter than a `--target-ref` plan: the catalog -top-level commit and each catalog service commit/image tag must align with the -promotion commit/tag. A stale but internally consistent catalog is a blocker in -promotion mode because applying it would roll DEV back. - -The planner does not prove registry existence, publish success, DEV apply, or -M3 DEV-LIVE. Only real DEV observation of -`res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` with operation, -trace, audit, and evidence records can be called M3 DEV-LIVE. - -## Refresh Boundary - -Human source work must not refresh artifact identity into the source branch. To -preview what a blocked catalog would look like, use read-only mode: - -```sh -node scripts/refresh-artifact-catalog.mjs --target-ref HEAD --blocked --no-write -node scripts/deploy-desired-state-plan.mjs --check -``` - -This prints the planned catalog state and does not modify any repository file. -Blocked skeleton refresh is intentionally preview-only. - -After a successful DEV artifact publish, only the G14 Tekton promotion path may -record digests from the publish report: - -```sh -node scripts/refresh-artifact-catalog.mjs --target-ref --publish-report /workspace/source/dev-artifacts.json --write -``` - -The publish-report mode refuses to update the catalog unless the report says -`artifactPublish.status="published"`, covers every frozen service in the v2 -publish plan, matches the target source commit, and contains a valid `sha256` -digest for each required service. Disabled services remain `skeleton-only` with -`digest: "not_published"`. The written catalog is committed only to -`G14-gitops`; `deploy/deploy.json` remains human-authored source truth. - -## Relationship To `deploy/deploy.json` - -`deploy/deploy.json` remains the human-authored deploy manifest. The artifact -catalog does not replace it and must not be consumed as proof that a release was -built. GitOps render combines human config from `deploy.json` with generated -artifact identity from the catalog; artifact identity must not be copied back -into `deploy.json`. - -If a future CI workflow publishes real images, it should update or generate a -publish result that includes registry digests and provenance. That publish -result may be compared with this contract, but it must not be inferred from this -contract. - -## DEV Builder Preflight - -Before a future DEV artifact publish attempts to build or publish service -images, run: - -```sh -npm run --silent dev-base-image:preflight -``` - -The preflight is local-only and checks for an approved builder base image through -`HWLAB_DEV_BASE_IMAGE`, a local `node:20-*` Docker image, or an explicit local -HWLAB dev base tag such as `hwlab-dev-base:`. It prints the image source, -local tag, image ID, publish usability, blockers, next steps, and -machine-readable preload/provision commands. The recommended source is -`node:20-bookworm-slim`; the recommended HWLAB-local tag is -`127.0.0.1:5000/hwlab/hwlab-dev-base:node20-bookworm-slim`. A blocked result -means artifact publish must stop and must not be reported as a successful -publish. - -## Validation - -Run the local static validator: - -```sh -node --check scripts/deploy-desired-state-plan.mjs -node --check scripts/src/deploy-desired-state-plan.mjs -node --test scripts/deploy-desired-state-plan.test.mjs -node scripts/deploy-desired-state-plan.mjs --check -node --check scripts/validate-artifact-catalog.mjs -node --check scripts/refresh-artifact-catalog.mjs -node --check scripts/preflight-dev-base-image.mjs -node --check scripts/src/dev-base-image-preflight.mjs -node scripts/validate-artifact-catalog.mjs -``` - -The validator and refresh command read local repository files and optional -publish reports; refresh is read-only unless `--write` is explicitly supplied. -The desired-state planner has the same read-only boundary. -These commands do not contact a registry, read secrets, build images, push -images, deploy to DEV, or deploy to PROD. diff --git a/docs/cloud-api-runtime.md b/docs/cloud-api-runtime.md deleted file mode 100644 index 9a8ba229..00000000 --- a/docs/cloud-api-runtime.md +++ /dev/null @@ -1,130 +0,0 @@ -# Cloud API Runtime - -The L1 `hwlab-cloud-api` runtime is a minimal local HTTP/JSON-RPC service. It -does not deploy to DEV or PROD from source tests and does not claim live -database persistence unless both DB readiness and the durable runtime adapter -readiness are live. - -## Local Smoke - -Run: - -```sh -node scripts/cloud-api-runtime-smoke.mjs -``` - -The smoke starts `cmd/hwlab-cloud-api` on `127.0.0.1` with an ephemeral port -and verifies: - -- `GET /health` reports `status: "degraded"` when live DB persistence is not - connected. -- `GET /health` reports DB readiness and runtime durable adapter readiness as - separate components. A memory adapter remains non-durable even when DB env - fields are present. -- The DB contract reports required env names, redacted Secret refs, env - injection, connection attempt status, connection result, `liveConnected`, - `liveDbEvidence`, DNS/TCP/auth/schema readiness layers, and redaction/safety - fields without exposing DB URL or secret values. -- `gateway.session.register`, `box.resource.register`, - `box.capability.report`, `hardware.invoke.shell`, `audit.event.query`, and - `evidence.record.query` round-trip through the same runtime store. -- Shell invoke requests are accepted as recorded cloud operations but report - `dispatchStatus: "not_connected"` until a real gateway shell adapter exists. -- Audit and evidence records use the protocol schema field names. - -## Persistence Boundary - -The default local runtime store is process-local memory: - -- `runtime.adapter: "memory"` -- `runtime.durable: false` -- `runtime.status: "degraded"` - -This remains the safe local default. DEV can opt into the durable adapter with -non-secret env flags: - -- `HWLAB_CLOUD_RUNTIME_ADAPTER=postgres` -- `HWLAB_CLOUD_RUNTIME_DURABLE=true` - -The Postgres adapter uses `HWLAB_CLOUD_DB_URL` from -`hwlab-cloud-api-dev-db/database-url`; source records only the Secret reference -and non-secret DNS contract. `HWLAB_CLOUD_DB_SSL_MODE` is the runtime authority -for DB TLS mode; if it is `disable`, the adapter strips URL `sslmode` query -parameters before opening the Postgres pool so stale Secret URL parameters -cannot override the DEV SSL contract. The adapter reports `runtime.durable: true` -only after the configured adapter proves all durable gates through read-only -runtime checks: - -- auth/query access to the configured DB path; -- required runtime table and column schema; -- the source-controlled migration ledger row for - `0001_cloud_core_skeleton` / `runtime-durable-postgres-v1`; -- read readiness against the runtime tables used by audit and evidence - queries. - -If DB SSL negotiation, auth, schema, migration, or read readiness is missing, `/health/live` -stays degraded with `runtime.durable: false`, `runtime.durableRequested: true`, -and a runtime blocker such as `runtime_durable_adapter_ssl_blocked`, -`runtime_durable_adapter_auth_blocked`, `runtime_durable_adapter_schema_blocked`, or -`runtime_durable_adapter_migration_blocked`. Fixture data and env presence are -never promoted to `runtime.liveRuntimeEvidence`. - -When the Postgres durable adapter is selected or requested, JSON-RPC -`audit.event.query` and `evidence.record.query` must also honor that durability -gate. If auth, schema, migration, durability-query, or table read-query evidence -is blocked, the method returns a JSON-RPC error with redacted blocker data such -as `adapter: "postgres"`, `durableRequested: true`, -`liveRuntimeEvidence: false`, `secretMaterialRead: false`, and the classified -blocker. It must not -return `events: []`, `records: []`, or `count: 0` on a blocked durable read. -Empty successful result sets are valid only after the durable adapter has -completed the read and the matching durable table rows are actually absent. - -If `HWLAB_CLOUD_DB_URL` and `HWLAB_CLOUD_DB_SSL_MODE` are absent, health -reports `db.status: "blocked"`. -If both env vars are present, cloud-api attempts a short read-only TCP -connection to the DB endpoint from the injected runtime env. The health payload -keeps all endpoint details redacted and reports only: - -The runtime DB readiness authority is the host parsed from the injected -`HWLAB_CLOUD_DB_URL` Secret value. Health reports this as -`db.endpointSource: "secret-url-host"` without printing the host, username, -password, or full URL. The `cloud-api-db` name is only an optional future alias; -it is not the TCP probe target and a missing alias must not reverse-fail live DB -success from the Secret URL host. -`.invalid` hosts, including `hwlab-dev-db.invalid`, are forbidden as DEV -runtime targets and may be used only as negative fixtures. - -- `db.configReady`: required env names are present. -- `db.endpointSource`: `secret-url-host`, the authoritative redacted TCP dial - target parsed from `HWLAB_CLOUD_DB_URL`. -- `db.optionalPublicDnsAlias`: diagnostic metadata for the non-authoritative - `cloud-api-db` alias; `requiredForReadiness` and `usedForProbe` stay false. -- `db.connectionAttempted`: the runtime tried the live connection path. -- `db.connectionResult`: redacted classifier such as `connected`, `refused`, - `timeout`, `dns_error`, `invalid_url`, or `unsupported_protocol`. -- `db.liveConnected`: the TCP connection completed. -- `db.liveDbEvidence`: true only when the live connection completed; env - presence, fixtures, and disabled probes must keep this false. -- `db.redaction` and `db.safety`: confirm values/endpoints are redacted and - secret material was not read by the health path. -- `db.readinessLayers`: records DNS, TCP, auth, and schema status separately so - DNS/TCP repair cannot be confused with authenticated schema readiness. -- `db.ready`: currently aliases `db.liveConnected`. - -Env presence alone is not treated as green. If the runtime has env injection -but `db.connectionAttempted` is false, `db.liveConnected` is false, or -`db.liveDbEvidence` is false, the gate must stay blocked/degraded with the -reported blocker. - -Fixture: `fixtures/cloud-api-runtime/minimal-runtime.json`. - -## Code Agent Provider Boundary - -`hwlab-cloud-api` supports OpenAI Responses for the Code Agent chat endpoint. -DEV source contracts require `OPENAI_API_KEY` from Secret -`hwlab-code-agent-provider/openai-api-key` and -`HWLAB_CODE_AGENT_OPENAI_BASE_URL` through the DEV egress/proxy URL. Runtime -health and `/v1` may report provider status, missing env names, Secret ref -names, model, and redacted egress status, but must never print the API key or a -Bearer token. diff --git a/docs/cloud-web-workbench.md b/docs/cloud-web-workbench.md deleted file mode 100644 index a041662f..00000000 --- a/docs/cloud-web-workbench.md +++ /dev/null @@ -1,169 +0,0 @@ -# HWLAB Cloud Workbench Frontend Contract - -This document is the review contract for -`DC-DCSN-P0-2026-003`, `pikasTech/HWLAB#99`, and -`pikasTech/HWLAB#78`. It defines the Cloud Workbench frontend design and -acceptance surface for later implementation. It is documentation-only: it does -not authorize deployment, service restart, PROD access, heavyweight browser -automation, or hardware mutation. - -The default Cloud Web experience may be rebuilt from scratch to satisfy this -contract. Existing Gate or M3 diagnostics screens from `#59` are not the -default homepage contract. - -## Product Position - -Cloud Workbench is the default browser entry at -`http://74.48.78.17:16666`. It should feel like a VS Code-style operator -workbench for HWLAB DEV: resources on the left, agent conversation and trace in -the center, evidence and hardware context on the right, and commands at the -bottom. - -The workbench is a read-only or dry-run coordination surface until a later -contract explicitly enables a narrow write path. It must not become a generic -hardware control panel. - -## Route Structure - -The frontend route model must keep the workbench as the default route and move -diagnostics under secondary routes: - -| Route | Purpose | Default | Source boundary | -| --- | --- | --- | --- | -| `/` | Cloud Workbench default. Shows agent conversation, trace, selected resource context, hardware/evidence side panel, and command input. | Yes | Same-origin `/v1`, read-only `/json-rpc`, source/gate report, blocked report. | -| `/workbench` | Explicit alias for the default workbench. | Yes, alias | Same as `/`. | -| `/gate` | Internal static alias for the read-only gate diagnostics view. | No | Same as `/diagnostics/gate`; source/gate report and same-origin read-only diagnostics only. | -| `/diagnostics` | Secondary diagnostics hub that links to status and gate views. | No | Same-origin `/v1` and report fixtures only. | -| `/diagnostics/status` | Read-only DEV status: edge, router, API, web, DB readiness, agent service health, and artifact identity. | No | Same-origin `/v1/status` or equivalent read-only status endpoint. | -| `/diagnostics/gate` | Read-only gate and M3 diagnostics inherited from `#59`: topology, route, health, blockers, and evidence summary. | No | Gate report and blocked report; read-only `/json-rpc` only when already defined. | -| `/agents` | Agent sessions, workers, skills, trace timeline, and cleanup status. Can be a focused view or a left-rail activity inside `/`. | No | Same-origin `/v1` agent summaries and source report. | -| `/hardware` | Hardware resources, gateway sessions, patch-panel topology, box simulators, capabilities, and blockers. | No | Read-only `/json-rpc` status/list methods and same-origin `/v1` summaries. | -| `/records` | Trusted records: evidence, audit, trace, operation IDs, artifact tag/commit/digest, and report links. | No | Gate report, source report, blocked report, and same-origin `/v1` summaries. | - -The route relationship is: - -- `/` and `/workbench` are the primary product surface. -- `/gate` is a short internal alias for the same hidden gate view as - `/diagnostics/gate`; it must not become the default route. -- `diagnostics/status` and `diagnostics/gate` are auxiliary views for - troubleshooting and acceptance review. -- Agent, hardware resources, and trusted records are first-class workbench - domains. They may be implemented as routes, tabs, or focused activity-rail - modes, but the default route must show how they relate to each other. -- `#59` diagnostics remain available under `/diagnostics/gate`; they must not - define the default homepage. - -## Layout Structure - -The default workbench layout must use four stable regions: - -| Region | Required content | Required behavior | `sourceKind` labels | -| --- | --- | --- | --- | -| Left activity rail and resource tree | Activity icons for Workbench, Agent, Hardware, Records, Diagnostics; resource tree for project, gateway sessions, patch-panel, box resources, capabilities, agent sessions, workers, and reports. | Selecting an item changes the center and right-panel context without implying mutation. Unknown or blocked items remain visible with disabled actions. | `SOURCE`, `DRY-RUN`, `DEV-LIVE`, `BLOCKED`. | -| Center agent conversation and trace | Agent conversation stream, plan/trace events, selected operation timeline, agent/worker/session IDs, and blocker messages. | Conversation input defaults to no-mutation guidance. Any future action that could mutate hardware is disabled unless a later contract explicitly enables it. Trace rows are clickable and open evidence context. | `SOURCE`, `LOCAL`, `DRY-RUN`, `DEV-LIVE`, `BLOCKED`. | -| Right hardware/evidence side panel | Selected hardware resource, patch-panel wiring, gateway/box status, evidence record, audit record, operation ID, artifact commit/tag/digest, and report provenance. | Panel is read-only. It explains why an item is blocked, dry-run, source-only, or live. It must not expose generic hardware write controls. | `SOURCE`, `DRY-RUN`, `DEV-LIVE`, `BLOCKED`. | -| Bottom command/input area | Command composer, dry-run preview, selected scope, source boundary, and disabled live controls. | Default mode is read-only or dry-run. Live hardware execution controls are disabled with an explicit blocker reason until a separate acceptance contract permits them. | `DRY-RUN`, `BLOCKED`, optionally `DEV-LIVE` for read-only observations only. | - -The UI may use a full rewrite of `web/hwlab-cloud-web`. It should preserve -the public `:16666` entrypoint and same-origin API assumptions rather than the -old diagnostics-first component structure. - -## Data Sources - -Every visible panel must display or carry a `sourceKind` value. The frontend -must keep these data sources separate: - -| Source | Use | Allowed calls | `sourceKind` | -| --- | --- | --- | --- | -| Same-origin `/v1` | Cloud API summaries for status, agents, records, health, artifact identity, and read-only workbench aggregation. | `GET` or documented read-only RPC wrappers through the same origin as the web bundle. | `DEV-LIVE` only when observed from the real DEV route; otherwise `BLOCKED` or `SOURCE`. | -| Read-only `/json-rpc` | Hardware/gateway/patch-panel status, capabilities, topology, and evidence lookups already defined as safe reads. | Only list/status/get/describe methods. No generic write, no direct box mutation, no bypass of patch-panel ownership. | `DEV-LIVE` for read-only real DEV observations; `DRY-RUN` for fixture-backed previews. | -| Source report | Checked-in contracts, manifests, schemas, service IDs, and documentation. | Static fetch or bundled build asset only. | `SOURCE`. | -| Gate report | `/tmp/hwlab-dev-gate` gate summaries, DEV layer status, artifact identity, and M3/M4/M5 readiness. | Read-only local report content or same-origin report endpoint. | `SOURCE`, `DRY-RUN`, `DEV-LIVE`, or `BLOCKED` exactly as reported. | -| Blocked report | Open blockers for DB, M3, M4, edge/route, artifacts, registry, and evidence gaps. | Read-only report content or same-origin summary endpoint. | `BLOCKED`. | - -The frontend must not infer `DEV-LIVE` from successful page load on `:16666`. -`DEV-LIVE` requires an observation from the real DEV route for the specific -thing being displayed. - -## Status Labels - -Use these labels consistently: - -| Label | Meaning | UI rule | -| --- | --- | --- | -| `SOURCE` | Repository documentation, schemas, source fixtures, manifests, or checked-in reports. | May be shown as design/contract readiness only. Never claim live state. | -| `LOCAL` | Localhost or in-process smoke result. | May appear in trace or acceptance summaries, but not as live DEV evidence. | -| `DRY-RUN` | Fixture-backed or no-mutation preview. | Command previews and agent plans default here. Must state that no DEV/PROD state changed. | -| `DEV-LIVE` | Read-only observation from the real DEV route for the exact component, record, or route shown. | May mark edge, API, DB, artifact, agent, or hardware status only when supported by specific evidence. | -| `BLOCKED` | Missing, stale, unsafe, or not-yet-authorized evidence or action. | Must show blocker reason and keep unsafe or unproven controls disabled. | - -The UI must never upgrade `SOURCE`, `LOCAL`, `DRY-RUN`, edge-only, or -front-end-only observations into M3 or M4 `DEV-LIVE`. - -## Interaction Boundaries - -Allowed interactions for this contract: - -- Navigate routes and activity rail modes. -- Select project, gateway, box, patch-panel, capability, agent, worker, - evidence, audit, trace, operation, and report records. -- Refresh read-only `/v1` status, read-only `/json-rpc` status/list/get - methods, source reports, gate reports, and blocked reports. -- Compose a command and view a dry-run preview with selected scope, expected - evidence, and blocker reasons. -- Copy IDs, links, commands, and report references. - -Disabled in the first workbench implementation: - -- Run live agent hardware operations. -- Change patch-panel wiring. -- Write box, gateway, simulator, or hardware state. -- Start or stop gateway, worker, tunnel, edge, router, API, web, DB, or PROD - services. -- Deploy images, apply manifests, restart services, read secrets, or run - heavyweight e2e/Playwright flows. -- Mark M3, M4, or M5 accepted from the browser. - -Future buttons may be visible only if they are disabled and explain the -required contract, for example `BLOCKED: live command requires M0-M5 gate, -DEV-only authorization, and patch-panel-owned operation evidence`. - -Do not add a generic hardware command form. Any future write path must be -narrow, named, patch-panel owned, audited, evidenced, DEV-only, and covered by -a new acceptance contract. - -## Relationship To `#59` - -`#59` defined a read-only diagnostics console for M3 topology, route, health, -blockers, and evidence summary. For `#99`, that surface is retained as -`/diagnostics/gate` and may also appear as a Diagnostics activity in the left -rail. - -`#59` must not define `/`, `/workbench`, product navigation, or the default -homepage. The default homepage is the Cloud Workbench described here. - -The `npm run web:m3-readonly` guard remains useful as a safety check for the -diagnostics route and same-origin read-only boundary. A later implementation -may update the script to reflect the new workbench route model, but it must -continue to fail on hardware write APIs, public endpoint drift, and evidence -misclassification. - -## DEV Acceptance Contract - -Acceptance for the frontend design and later implementation is: - -| Area | Acceptance | -| --- | --- | -| Default page | `http://74.48.78.17:16666/` opens the Cloud Workbench, not the Gate/M3 Diagnostics dashboard; its first screen does not show Gate, `BLOCKED`, `M0-M5`, or acceptance-review copy. | -| API status | `http://74.48.78.17:16667` remains the DEV API/edge/status boundary; browser code uses same-origin `/v1` for workbench data and only read-only `/json-rpc` methods for diagnostics/hardware status. | -| Routes | `/`, `/workbench`, `/gate`, `/diagnostics`, `/diagnostics/status`, `/diagnostics/gate`, Agent, hardware resources, and trusted records are represented in navigation or route aliases. | -| Layout | Left activity rail/resource tree, center agent conversation/trace, right hardware/evidence side panel, and bottom command/input area are present on the default workbench. | -| Labels | `SOURCE`, `LOCAL`, `DRY-RUN`, `DEV-LIVE`, and `BLOCKED` labels are visible where evidence state is shown and follow the rules above. | -| Read-only boundary | Hardware resources and diagnostics are read-only. Live controls are disabled with blocker reasons. | -| Browser smoke | A lightweight screenshot/manual browser smoke may verify that the default page loads, the workbench regions are visible, diagnostics is secondary, and no text or controls imply generic hardware writes. | -| Artifact identity | Acceptance notes must include web image tag, commit, digest or `not_applicable` reason, build source, deploy environment, and health timestamp when runtime evidence is claimed. | -| Blocker display | DB, M3, and M4 blockers must be displayed separately when present. DB readiness cannot green M3/M4; edge route live cannot green DB, M3, or M4. | - -This document does not require a heavy check or browser e2e run. For the -documentation PR, the minimum validation is `git diff --check` and an `rg` -scan for the task terms and frozen labels. diff --git a/docs/d601-k3s-readonly-observability.md b/docs/d601-k3s-readonly-observability.md deleted file mode 100644 index dbabf5f7..00000000 --- a/docs/d601-k3s-readonly-observability.md +++ /dev/null @@ -1,57 +0,0 @@ -# D601 k3s Readonly Observability - -This entry point supports `pikasTech/HWLAB#46` and the DEV runtime blockers in -`#7`, `#33`, `#36`, `#38`, `#39`, and `#42`. It is a read-only preflight for -the D601 Code Queue runner and the `hwlab-dev` namespace. - -It does not authorize PROD, read Secret resources, print kubeconfig/token -material, print ConfigMap values, mutate cluster state, restart runtime -services, or run heavy checks on the master server. - -## Command - -Run from the repository root: - -```sh -node --check scripts/d601-k3s-readonly-observability.mjs -node --check scripts/src/d601-k3s-readonly-observability.mjs -node scripts/d601-k3s-readonly-observability.mjs -``` - -The command writes `/tmp/hwlab-dev-gate/d601-k3s-readonly-observability.json` and prints a -short JSON summary. A `blocked` conclusion means the preflight ran and recorded -the missing binary, kubeconfig path, SSH bridge, or read permission. Use -`--fail-on-blocked` only in CI jobs that should fail when observability is not -ready. - -Useful options: - -```sh -node scripts/d601-k3s-readonly-observability.mjs --pretty -node scripts/d601-k3s-readonly-observability.mjs --timeout-ms 5000 -node scripts/d601-k3s-readonly-observability.mjs --no-write -node scripts/d601-k3s-readonly-observability.mjs --report /tmp/hwlab-dev-gate/d601-k3s-readonly-observability.json -``` - -## What It Checks - -- `kubectl`, `k3s`, `k3sctl`, and `ssh` availability and version output. -- `KUBECONFIG`, `~/.kube/config`, `/etc/rancher/k3s/k3s.yaml`, and the k3s - admin kubeconfig path by file metadata only. -- SSH maintenance bridge hints from known environment variable names and - `~/.ssh` metadata only. -- If a Kubernetes executor is available, read-only access to `hwlab-dev` - namespace, pods, services, and ConfigMaps. -- Summaries for pods, services, and ConfigMap key names only. ConfigMap data - values are not printed. - -## Ready Criteria - -`ready` requires a direct executor, such as `kubectl` or `k3s kubectl`, to read -pods, services, and ConfigMaps from `hwlab-dev` and no open environment or -observability blocker. - -`blocked` keeps the report consumable by follow-up issues. The report includes -open blockers with `scope`, `summary`, and `nextTask` fields so runner image or -mount work can be tracked without guessing which binary, permission, or path is -missing. diff --git a/docs/dev-acceptance-matrix.md b/docs/dev-acceptance-matrix.md deleted file mode 100644 index 96e494d3..00000000 --- a/docs/dev-acceptance-matrix.md +++ /dev/null @@ -1,150 +0,0 @@ -# HWLAB DEV Acceptance Matrix - -This matrix is the DEV acceptance contract for the MVP runtime. It is scoped to -static review and lightweight smoke checks only. It does not authorize a real -DEV or PROD deployment. - -## Fixed Boundary - -- DEV frontend endpoint: `http://74.48.78.17:16666` -- DEV API/edge endpoint: `http://74.48.78.17:16667` -- Deploy environment: `dev` -- Legacy public endpoints `:6666` and `:6667` are deprecated; browser entry - is `:16666` and API/health entry is `:16667`. -- Internal k3s service ports may still use `6667`, for example - `hwlab-cloud-api` and `hwlab-edge-proxy`. Internal `6667` is not a public - DEV acceptance endpoint. -- Runtime route: client, master `hwlab-edge-proxy`, `frp`, D601 - `hwlab-dev/hwlab-router`, then HWLAB cloud/runtime services. -- UniDesk backend, provider-gateway, and microservice proxy are not accepted as - substitutes for HWLAB runtime services in this first version. They may remain - external scheduling, CI, or CD support only. - -## M3 Evidence Classification - -Current P0 DEV acceptance remains the M3 virtual hardware trusted loop: two -`hwlab-box-simu` instances, two `hwlab-gateway-simu` instances, and one -`hwlab-patch-panel`. - -`M3 live` can be claimed only when a DEV observation proves the live -`res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` path and records -the operation, trace, audit, and evidence identifiers. The patch panel must -own the route decision; direct box-to-box propagation or fixture output is not -M3 live evidence. - -`M3 support` includes this endpoint freeze, read-only public edge curl -evidence, source contracts, static manifest cardinality, local smoke output, -and dry-run fixtures. These items support release or pre-release decisions, but -they are not P0 live acceptance. - -`Non-P0` includes SOURCE, LOCAL, DRY-RUN, fixture-only, diagnostic, and -edge-only observations that do not prove the full -`res_boxsimu_1 -> hwlab-patch-panel -> res_boxsimu_2` link. These observations -must not be written as `DEV-LIVE`. - -## Required Artifact Observability - -Every deployable HWLAB artifact that participates in DEV acceptance must expose -or be joined with these fields: - -| Field | Requirement | -| --- | --- | -| `serviceId` | One of the frozen HWLAB service IDs. | -| `commitId` | Git commit that produced the artifact, short or full SHA. | -| `image` | Image repository/name when containerized, or package artifact name for non-container artifacts. | -| `tag` | Immutable or traceable tag, preferably including the commit. | -| `digest` | Content digest when the artifact is an image or build output that supports digests. | -| `buildSource` | Source repository, branch/ref, and build workflow or local command. | -| `deployEnv` | Must be `dev` for this matrix. | -| `healthTimestamp` | ISO-8601 timestamp from the health observation or smoke collector. | - -Missing `digest` is allowed only for non-container client assets or local dry-run -artifacts, and must be recorded as `not_applicable` with a reason. - -## Health Contract - -All health responses must be JSON, include `serviceId`, identify `dev`, and -provide a current health timestamp. Existing skeleton services may expose -`observedAt`; the acceptance collector maps it to `healthTimestamp`. - -| Component | Service ID | Check | Success | Failure | -| --- | --- | --- | --- | --- | -| DEV API/edge ingress | `hwlab-edge-proxy` | `GET http://74.48.78.17:16667/health` or routed service health | HTTP 2xx/3xx reaches HWLAB DEV path and reports edge identity or downstream HWLAB identity | Timeout, non-HWLAB response, PROD route, missing artifact fields | -| master edge proxy | `hwlab-edge-proxy` | Edge proxy health and route table observation | Route for `http://74.48.78.17:16667` forwards to `frp` and identifies commit/image | No DEV route, wrong port, missing route observability | -| frp tunnel | `hwlab-tunnel-client` | Tunnel session/status observation | Tunnel for DEV route is established to D601 router and identifies commit/image | Tunnel down, wrong target, ambiguous service identity | -| D601 router | `hwlab-router` | `hwlab-dev/hwlab-router` health/status | Router is live, environment is `dev`, route target is cloud API/web or runtime service | Namespace mismatch, route missing, stale health timestamp | -| Cloud API | `hwlab-cloud-api` | `GET /health`, `GET /live`, optional JSON-RPC `/rpc` probe | Returns service ID, `dev`, healthy/live status, redacted DB env readiness, and accepts a harmless protocol probe | HTTP error, unknown service ID, wrong environment, invalid JSON-RPC envelope, missing DB env readiness | -| Cloud Web | `hwlab-cloud-web` | `GET http://74.48.78.17:16666/`, static asset check, and the workbench contract in `docs/cloud-web-workbench.md` | Public browser entry serves the Cloud Workbench on `:16666`; default page is a VS Code-style workbench with left activity rail/resource tree, center Agent conversation/trace, right hardware/evidence side panel, and bottom command/input area; API/edge status remains on `http://74.48.78.17:16667`; browser data uses same-origin `/v1`, read-only `/json-rpc`, source/gate report, and blocked report with explicit `sourceKind` labels | Endpoint drift, public web served from `:6667`, Gate/M3 Diagnostics used as default homepage, direct write/control endpoint text or calls, missing `SOURCE`/`DRY-RUN`/`DEV-LIVE`/`BLOCKED` labeling, edge-only evidence presented as M3 `DEV-LIVE`, missing asset | -| Agent manager | `hwlab-agent-mgr` | Agent scheduling health/status | Reports live manager, commit/image, and DEV environment; no worker leak after smoke | Scheduler unavailable, wrong environment, unbounded worker session | -| Agent worker | `hwlab-agent-worker` | Worker health/status during dry-run or scoped smoke | Worker session is scoped to DEV project and emits trace/audit identifiers | Missing session identity, unsafe mutation, cleanup failure | -| Agent skills | `hwlab-agent-skills` | Skill bundle version/status | Skill artifact is traceable to commit/build source and compatible with worker | Unversioned skill bundle, missing build source | -| Gateway | `hwlab-gateway` | `GET /health/live` and `GET /status` when present | Reports DEV gateway boundary and does not bypass patch-panel constraints | Hardware boundary unavailable, non-DEV gateway, direct box mutation | -| Gateway simulator | `hwlab-gateway-simu` | `GET /health/live`, `GET /status`, `GET /boxes` | Simulator is live, lists expected box resources, and identifies DEV project; this is M3 support until paired with the full patch-panel link observation | Simulator down, box list missing, stale timestamp | -| Box simulator | `hwlab-box-simu` | `GET /health/live`, `GET /status` | Simulator is live and reports resources, ports, and patch-panel-only propagation; this is M3 support until paired with the full patch-panel link observation | Cross-device propagation outside patch panel, missing resource state | -| Patch panel | `hwlab-patch-panel` | `GET /health/live`, `GET /status`, `GET /wiring` | Wiring config is parseable and patch-panel state owns routing decisions; M3 live also requires a traced `DO1 -> patch-panel -> DI1` operation | Invalid topology, direct bypass path, stale patch state | -| CLI | `hwlab-cli` | `npm run cli:health` and dry-run command | CLI uses DEV endpoint and dry-run states no DEV/PROD changes were made | Wrong endpoint, missing dry-run guard, real mutation attempted | - -## DEV Smoke Matrix - -The smoke sequence must run in order and stop on the first critical blocker. -Network checks may be replaced by recorded observations when the runner cannot -reach the DEV host, but replacement evidence must include the artifact fields -listed above. - -Cloud Web workbench smoke is covered by: - -- `node scripts/dev-cloud-workbench-smoke.mjs --static` -- `node scripts/dev-cloud-workbench-smoke.mjs --dom-only --url http://74.48.78.17:16666/` -- `node scripts/dev-cloud-workbench-smoke.mjs --live --url http://74.48.78.17:16666/` - -The static mode is SOURCE-level contract evidence only and must report -`devLive=false`; it cannot promote SOURCE, LOCAL, DRY-RUN, or fixture evidence -to DEV-LIVE. It observes the PR #114 Markdown help surface as ready when -`web/hwlab-cloud-web/help.md`, the vendored `marked` renderer, and the -non-default internal help route are present. The `--dom-only` mode is a -live-read-only DOM validation path: it preserves runtime/web-asset identity -preflight semantics, may still inspect deployed DOM wiring after identity drift, -and records Code Agent as `not_applicable` without sending `/v1/agent/chat`. -The live mode is optional read-only HTTP plus browser DOM observation and must -report `blocked` or `skip` structure instead of a false green when the browser -check is unavailable. - -| Step | Probe | Success Criteria | Failure Criteria | Blocker Class | -| --- | --- | --- | --- | --- | -| 1 | Confirm repository contract files and JSON checklist parse. | `docs/dev-acceptance-matrix.md` exists and `docs/dev-acceptance-checklist.json` parses. | Missing file or invalid JSON. | `contract_blocker` | -| 2 | Verify frozen DEV endpoints. | Public frontend is exactly `http://74.48.78.17:16666`; public API/edge is exactly `http://74.48.78.17:16667`; internal `6667` appears only as a k3s service/listen port. | Any alternate public DEV endpoint, old public `:6667`, or PROD target. | `environment_blocker` | -| 3 | Observe DEV API/edge ingress health. | Request reaches HWLAB DEV route and returns HWLAB identity or accepted downstream health. | Timeout, non-HWLAB target, wrong public port. | `network_blocker` | -| 4 | Observe master edge proxy route. | Edge route maps DEV endpoint to `frp` and records artifact identity. | Missing route, stale route, missing artifact identity. | `network_blocker` | -| 5 | Observe `frp` tunnel. | Tunnel links master edge to D601 router for DEV. | Tunnel down or target mismatch. | `network_blocker` | -| 6 | Observe D601 `hwlab-dev/hwlab-router`. | Router is live and forwards only to HWLAB DEV services. | Namespace mismatch or route bypass. | `runtime_blocker` | -| 7 | Check cloud API/web surface. | Cloud API health is valid on public `:16667`; web assets are served on public `:16666`; Cloud Web default route is the Cloud Workbench defined in `docs/cloud-web-workbench.md`; diagnostics/status/gate are secondary; data sources are same-origin `/v1`, read-only `/json-rpc`, source/gate report, and blocked report; `npm run web:m3-readonly` or its workbench-aware successor passes. | Bad health, endpoint drift, Gate/M3 Diagnostics used as default homepage, direct hardware write/control surface from web, missing source labels, or edge-only evidence promoted to M3 `DEV-LIVE`. | `runtime_blocker` | -| 8 | Check gateway, simulator, box simulator, and patch-panel contracts. | Health/status JSON is parseable and topology keeps routing under patch-panel ownership; for M3 live, a traced `DO1 -> patch-panel -> DI1` operation exists. | Missing health, invalid topology, bypass path, or any attempt to promote support/fixture evidence to M3 live. | `runtime_blocker` | -| 9 | Check agent manager, worker, and skills contracts. | Agent artifacts are traceable; dry-run/scoped smoke emits session, trace, audit, and cleanup evidence. | Missing traceability, unsafe mutation, cleanup leak. | `agent_blocker` | -| 10 | Verify evidence and artifact observability. | Every accepted artifact has service ID, commit, image/tag/digest or reason, build source, env, and health timestamp. | Missing required observability field. | `observability_blocker` | - -## Pass And Fail Rules - -The matrix passes only when every smoke step is either observed as successful or -explicitly marked not applicable with a non-production reason. A step is failed -when the observed result contradicts a frozen contract, cannot be parsed, or -cannot be tied to a traceable HWLAB artifact. - -M3 live cannot be inferred from SOURCE, LOCAL, DRY-RUN, edge-only, or -front-end-only evidence. If the evidence does not show the operation, trace, -audit, and evidence IDs on the `res_boxsimu_1 -> hwlab-patch-panel -> -res_boxsimu_2` chain, it is not a pass. - -Critical blockers are `contract_blocker`, `environment_blocker`, -`network_blocker`, `runtime_blocker`, `agent_blocker`, -`observability_blocker`, and `safety_blocker`. A `safety_blocker` must be raised -for any attempted PROD deployment, real deployment from this matrix, secret -read, heavyweight e2e run, or UniDesk runtime substitution. - -## First Version Exclusions - -- No PROD deployment or PROD smoke. -- No real DEV deployment from this document. -- No heavyweight e2e or destructive hardware action. -- No secret or token reads. -- No replacement of HWLAB runtime services by UniDesk backend, - provider-gateway, or microservice proxy. diff --git a/docs/dev-base-image-preflight.md b/docs/dev-base-image-preflight.md deleted file mode 100644 index d06a1d49..00000000 --- a/docs/dev-base-image-preflight.md +++ /dev/null @@ -1,142 +0,0 @@ -# HWLAB DEV Base Image Preflight - -This preflight is the lightweight builder gate for DEV artifact publish work. It -checks whether the D601 builder has an approved local base image before any -artifact publish attempt claims readiness. - -The command is local-only. It does not pull, build, push, deploy, contact DEV or -PROD, read secrets, or use UniDesk runtime services as substitutes. - -## Current Repository Constraints - -- No repository Dockerfile is present in the DEV skeleton. -- `deploy/artifact-catalog.dev.json` pins service image names to the DEV - registry target, by default - `127.0.0.1:5000/hwlab/:`; `deploy/deploy.json` - remains human-authored runtime config and must not carry generated image - identity. -- The artifact catalog may be either `contract-skeleton` or `published`. A - `published` catalog must be backed by `/tmp/hwlab-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. - -Committed artifact reports may record successful base-image and publish evidence -for an older source commit. Compare their source commit with the desired-state -commit before using them for refresh or apply review. 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 -npm run --silent dev-base-image:preflight -``` - -Equivalent direct command: - -```sh -node scripts/preflight-dev-base-image.mjs -``` - -The direct command always prints JSON. Use `npm run --silent` when npm is the -entry point and the output needs to be machine parsed. Exit code `0` means -`status: "ready"` and the base image can be used by #35 DEV artifact publish. -Exit code `2` means `status: "blocked"` and artifact publish must stop. - -## Image Selection - -Selection order is intentionally narrow: - -1. If `HWLAB_DEV_BASE_IMAGE` is set, it must name an approved image that already - exists in the local Docker image cache. -2. If `HWLAB_DEV_BASE_IMAGE` is not set, the preflight looks for local - `node:20-*` images and selects the first deterministic local tag. -3. If no `node:20-*` tag exists, the preflight also accepts a local HWLAB base - tag such as `127.0.0.1:5000/hwlab/hwlab-dev-base:node20-bookworm-slim`. -4. If neither source is available, the result is a blocker. - -Explicit base image values must match local `node:20-*`, `hwlab-dev-base:*`, -`hwlab-node20-base:*`, or `hwlab-node-runtime-base:*` references. They must not -reference UniDesk, Code Queue, `backend-core`, `provider-gateway`, -`microservice-proxy`, or an HWLAB runtime service image. A service image such as -`127.0.0.1:5000/hwlab/hwlab-cloud-api:` is an artifact output, not a -builder base image. - -The recommended D601 preload source is `node:20-bookworm-slim`. The recommended -HWLAB-specific local tag is: - -```sh -127.0.0.1:5000/hwlab/hwlab-dev-base:node20-bookworm-slim -``` - -## Output Contract - -Important fields: - -| Field | Meaning | -| --- | --- | -| `status` | `ready` or `blocked`. | -| `imageSource` | `env:HWLAB_DEV_BASE_IMAGE`, `local-docker-node:20-*`, or `none`. | -| `requestedImage` | The explicit environment value, when present. | -| `localTag` | Local Docker tag selected for the builder base image. | -| `imageId` | Local Docker image ID from `docker image inspect`. | -| `candidates` | Approved local builder base images found in Docker. | -| `rejectedCandidates` | Near misses such as local non-Node-20 Node images. | -| `publishUsable` | Boolean gate for #35 artifact publish. | -| `blockers` | Deterministic reasons artifact publish must stop. | -| `nextSteps` | Operational fixes that do not require secret reads or runtime substitution. | -| `recommendation` | Machine-readable recommended source, env var, and base image tags. | -| `provision` | Copy-pasteable online, HWLAB-tag, offline import, and dry-run commands. | -| `blockedReport` | Minimal machine-readable blocked report: exact blocker, expected tag, env value, and next preload command. | - -## Blocker Handling - -When blocked, preload or build an approved DEV builder base image into the D601 -Docker cache, set `HWLAB_DEV_BASE_IMAGE` to the exact local tag if it is not a -`node:20-*` tag, and rerun the preflight. Do not claim artifact publish success -until the preflight returns `status: "ready"`. - -Online D601 preload: - -```sh -docker pull node:20-bookworm-slim -HWLAB_DEV_BASE_IMAGE=node:20-bookworm-slim node scripts/preflight-dev-base-image.mjs -``` - -Optional HWLAB-local tag provision: - -```sh -docker pull node:20-bookworm-slim -docker tag node:20-bookworm-slim 127.0.0.1:5000/hwlab/hwlab-dev-base:node20-bookworm-slim -HWLAB_DEV_BASE_IMAGE=127.0.0.1:5000/hwlab/hwlab-dev-base:node20-bookworm-slim node scripts/preflight-dev-base-image.mjs -``` - -Optional dependency runtime base provision: - -```sh -node scripts/dev-runtime-base-image.mjs --dry-run -node scripts/dev-runtime-base-image.mjs -HWLAB_DEV_BASE_IMAGE=127.0.0.1:5000/hwlab/hwlab-node-runtime-base:deps- node scripts/preflight-dev-base-image.mjs -``` - -This runtime base caches `package.json` / `package-lock.json` dependencies in -`/opt/hwlab-node-runtime-base/node_modules`. Service artifact builds copy that -directory when present, which avoids repeating the same `npm ci` layer for each -service. - -Offline preload path when D601 cannot pull directly: - -```sh -docker pull node:20-bookworm-slim -docker save node:20-bookworm-slim -o hwlab-node20-bookworm-slim.tar -docker load -i hwlab-node20-bookworm-slim.tar -HWLAB_DEV_BASE_IMAGE=node:20-bookworm-slim node scripts/preflight-dev-base-image.mjs -``` - -The preflight may use UniDesk and Code Queue as scheduling infrastructure only. -It must not use their runtime images as HWLAB service images or builder base -image substitutes. diff --git a/docs/dev-edge-health.md b/docs/dev-edge-health.md deleted file mode 100644 index 0957871d..00000000 --- a/docs/dev-edge-health.md +++ /dev/null @@ -1,113 +0,0 @@ -# HWLAB DEV Edge Health - -This check is DEV-only and targets the frozen endpoint: - -```sh -node scripts/dev-edge-health-smoke.mjs --live --report /tmp/hwlab-dev-gate/report.json -``` - -The smoke is read-only. It does not touch PROD, restart services, read -secrets, or substitute UniDesk backend/provider-gateway/microservice-proxy for -HWLAB runtime. - -## Health Evidence - -`GET http://74.48.78.17:16667/health` must return HWLAB DEV JSON with: - -- `serviceId` for the HWLAB service answering the request; -- `environment: "dev"`; -- `commit` evidence; -- `image` evidence; -- `service` evidence. - -`hwlab-cloud-api` also serves `GET /health/live` for k3s probes and edge -forwarding checks. - -`db` in the cloud-api health payload is a redacted configuration gate. It -reports required env names, presence, missing names, and Secret reference names -only. Runtime health additionally reports redacted DB readiness layers: -`configReady`, `envInjected`, `endpointSource`, `connectionAttempted`, -`connectionResult`, and `liveConnected`. It must not expose a connection -string, token, password, DB host, username, or claim fixture output as live DB -evidence. - -Required DEV DB config names: - -- `HWLAB_CLOUD_DB_URL` from Secret reference - `hwlab-cloud-api-dev-db/database-url`. -- `HWLAB_CLOUD_DB_SSL_MODE=disable`. -- Runtime TCP dial target: the redacted host parsed from - `HWLAB_CLOUD_DB_URL`, reported as `endpointSource="secret-url-host"`. - -`cloud-api-db` is only an optional desired alias. Until this repo owns the -Service plus Endpoint or EndpointSlice manifests and rollout/apply contract, it -is not a readiness authority, is not the TCP probe target, and a missing alias -must not reverse-fail live DB success from the Secret URL host. - -When the Secret/env is absent, the health JSON should keep -`db.connected: false`, set `db.status: "blocked"`, and list the missing env -names so gate reports can identify `cloud-api-db-health-gate`. When the env is -present but no live DB probe is attempted, the gate remains blocked with -`connectionResult: "not_attempted"`. When a probe is attempted but -`liveConnected` is false, the gate remains blocked/degraded with the redacted -connection classifier. `connectionResult: "dns_error"` with -`classification: "dns_resolution_failed"` means DB endpoint DNS failed from the -cloud-api runtime for the Secret URL host. Env presence alone is not live DB -evidence. - -The Code Agent provider Secret for #143 is a separate blocker. The edge-health -report may record only key-presence evidence for -`hwlab-code-agent-provider/openai-api-key` and runtime error classification such -as `provider_secret_missing`; it must not read or print provider Secret values. -Do not collapse this #143 provider Secret gap into the DB live blocker. - -## Route Classification - -The smoke classifies failures into these blockers: - -- `frp_blocker`: public `:16667` is unavailable and frps control or tunnel - health ports also refuse connections. -- `edge_proxy_blocker`: frps is reachable, but public `:16667` refuses. -- `k3s_service_blocker`: k3s is observable but HWLAB DEV services/endpoints are - missing. -- `dns_port_firewall_blocker`: public endpoint times out or cannot be resolved - as a port/network path. -- `app_health_blocker`: public HTTP reaches an app but health JSON is wrong, - missing evidence, returns an HTTP error, or reports DB env injected without a - live DB connection. - -## Machine-Readable Diagnosis - -Blocked `frp_blocker` and `edge_proxy_blocker` reports now include a -`diagnosis` object in `/tmp/hwlab-dev-gate/dev-edge-health.json` with: - -- `likelyLayer`: the most likely broken layer, such as `master-edge/frps`; -- `confidence`: coarse confidence for the diagnosis; -- `likelyCause`: a single-sentence blocker summary; -- `evidence`: the TCP probes that support the diagnosis; -- `notProven`: layers this probe did not rule out; -- `nextTask`: the smallest read-only follow-up or ops action. - -## Current Blocker - -The committed report at `/tmp/hwlab-dev-gate/dev-edge-health.json` records a -read-only live run where public `http://74.48.78.17:16667/health/live` returned -HWLAB DEV health from `hwlab-cloud-api`, DB config was present, and runtime -health attempted a redacted TCP DB probe. The probe was not connected: -`connected=false`, `liveConnected=false`, `liveDbEvidence=false`, -`connectionResult="dns_error"`, and -`classification="dns_resolution_failed"`. This is a DB live readiness blocker -for #49, not proof that DB is connected. - -The same report records the #143 Code Agent provider Secret gap separately as -`provider_secret_missing` when key-presence evidence for -`hwlab-code-agent-provider/openai-api-key` is absent. DB live readiness, -provider-backed Code Agent chat, M3 hardware trusted-loop proof, M4 live agent -loop, and M5 DEV-LIVE acceptance remain separate evidence layers. - -## DEV FRP Contract - -`deploy/frp/frps.dev.toml` reserves public `16666` for `hwlab-cloud-web` and -public `16667` as a TCP `remotePort` for `hwlab-dev-edge-proxy`. Do not bind `vhostHTTPPort = 16667` in the same frps -config; that collides with the TCP proxy and can keep the DEV route from -registering cleanly. diff --git a/docs/dev-evidence-blocker-aggregator.md b/docs/dev-evidence-blocker-aggregator.md deleted file mode 100644 index 7a386d1e..00000000 --- a/docs/dev-evidence-blocker-aggregator.md +++ /dev/null @@ -1,135 +0,0 @@ -# DEV Evidence / Blocker Aggregator - -This is the lightweight report-only entry point for `pikasTech/HWLAB#41` and -the M5 DEV gate aggregator v2 for `pikasTech/HWLAB#58`. It helps a commander -decide whether the DEV acceptance path is green, blocked, or ready for another -repair round across `#33-#39`, `#46`, `#7`, and the MVP DoD in `#9`. - -Run from the repository root: - -```sh -node scripts/dev-evidence-blocker-aggregator.mjs --pretty -``` - -For a short validation response: - -```sh -node scripts/dev-evidence-blocker-aggregator.mjs --check -``` - -To refresh the committed v2 machine and human reports: - -```sh -node scripts/dev-evidence-blocker-aggregator.mjs --report /tmp/hwlab-dev-gate/report.json -``` - -The generated files are: - -- `/tmp/hwlab-dev-gate/dev-m5-gate-aggregator-v2.json` -- `/tmp/hwlab-dev-gate/dev-m5-gate-aggregator-v2.md` - -## Source Levels - -The aggregator keeps evidence levels separate so fixture output cannot be -promoted to live DEV evidence: - -| Level | Meaning | -| --- | --- | -| `SOURCE` | Repository contracts, schemas, docs, manifests, or examples. | -| `LOCAL` | Localhost or in-process smoke results only. | -| `DRY-RUN` | Fixture-backed or no-mutation dry-run readiness evidence. | -| `DEV-LIVE` | Read-only evidence observed from the real DEV route; this may prove entrypoint reachability without proving downstream DB, M3, M4, or M5 acceptance. | -| `BLOCKED` | Missing issue reads, missing DEV evidence, missing artifacts, or other open blockers. | - -## Current DEV Layering - -The v2 report exposes `currentDevLayering` so the public route can be green -without promoting the full gate: - -| Layer | Meaning | -| --- | --- | -| `Frontend DEV revision` | Latest Cloud Workbench frontend revision visible on the active `http://74.48.78.17:16666/` browser endpoint. While API health or runtime durability is degraded, this may only be summarized as deployed UI usable in degraded/read-only mode; frontend evidence cannot green DB, M3, M4, or M5. | -| `EDGE/ROUTE live` | `16666` browser and `16667` health route evidence from read-only probes. | -| `DB live/degraded` | Cloud API DB readiness from redacted health evidence; route success and env presence do not imply DB live. A `dns_error`/`dns_resolution_failed` DB probe is a DB live blocker. | -| `Code Agent provider Secret` | #143 provider-backed chat readiness from redacted runtime error and Secret key-presence evidence only; missing provider Secret is independent from DB live. | -| `M3 hardware trusted loop` | Real DEV `res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` plus operation, trace, audit, and evidence identifiers. | -| `M4 agent loop` | Agent loop live preflight and scheduling/evidence closure, gated by DB and runtime readiness. | -| `artifact/desired-state source` | Artifact source coverage for the current target ref plus desired-state dry-run/apply status. | - -The report also emits `activeEndpoints` and `deprecatedEndpoints`. Active -acceptance endpoints are: - -- frontend/browser: `http://74.48.78.17:16666/` -- API/live: `http://74.48.78.17:16667/health/live` - -Legacy public `http://74.48.78.17:6666` and -`http://74.48.78.17:6667` are historical/deprecated only and are not active -green evidence. - -`latestFrontendDevFact` records the current #99/#108 frontend visibility fact: -revision `1e8805664970839b72be40c34636b08f6d18b131` is visible on DEV in -degraded/read-only mode, with `promotesM3M4M5=false`. - -## Current Contract Map - -| Milestone | Current visible level | Contract entry | -| --- | --- | --- | -| M0 | `SOURCE` | `docs/m0-contract-audit.md`, protocol schemas, evidence chain examples, M0 validator. | -| M1 | `LOCAL` | `docs/m1-local-smoke.md`, `fixtures/mvp/runtime.json`, `scripts/m1-contract-smoke.mjs`. | -| M2 | `DEV-LIVE` for frontend/route only | DEV deploy smoke fixture plus active read-only `16666`/`16667` endpoint smoke and degraded/read-only frontend visibility. | -| M3 | `BLOCKED` | Hardware trusted loop topology fixture, local patch-panel smoke, and the no-write DEV plan exist, but DEV-LIVE operation/trace/audit/evidence IDs for `res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` are missing. | -| M4 | `BLOCKED` | Agent automation loop fixture and local smoke exist, but live preflight is blocked at runtime durable adapter readiness and skills commit/version injection, not stale DB-live readiness. | -| M5 | `BLOCKED` | MVP e2e dry-run plan is green, but bounded DEV-LIVE acceptance is blocked by runtime durable adapter, skills injection, M3/M4, and source/artifact coverage. | - -`milestoneLevelClassification` is the compact M0-M5 answer for command -handoff. `milestoneBlockerClassification` gives the M3/M4/M5 blocker class, -dependency, and required next proof. - -## Blocker Posture - -The v2 report reads committed report fixtures only: - -- `/tmp/hwlab-dev-gate/dev-preflight-report.json` -- `/tmp/hwlab-dev-gate/dev-deploy-report.json` -- `/tmp/hwlab-dev-gate/dev-artifacts.json` -- `/tmp/hwlab-dev-gate/dev-edge-health.json` -- `/tmp/hwlab-dev-gate/dev-m2-deploy-smoke-active.json` -- `/tmp/hwlab-dev-gate/dev-m3-hardware-loop.json` -- `/tmp/hwlab-dev-gate/dev-m4-agent-loop.json` -- `GitHub issue/PR comments` -- `/tmp/hwlab-dev-gate/d601-k3s-readonly-observability.json` - -The report remains blocked until real DEV-LIVE evidence is attached for the -required downstream HWLAB runtime services. Public route evidence on -`16666/16667` is necessary but not sufficient: DB live readiness, #143 Code -Agent provider Secret readiness, M3 trusted loop evidence, M4 agent-loop -evidence, and artifact/desired-state source coverage stay separate. - -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. `d601-k3s`, `kubectl`, kubeconfig/maintenance bridge: restore read-only - hwlab-dev cluster observability without printing Secrets. -2. `cloud-api-db`: prove DEV cloud-api DB env and health readiness with - redacted values only. -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 - -The aggregator does not deploy, call DEV, call PROD, run browser tests, run -heavy e2e, read secrets, restart services, or replace HWLAB runtime services -with UniDesk services. It is a local report generator and static contract -checker only. diff --git a/docs/dev-gate-preflight.md b/docs/dev-gate-preflight.md deleted file mode 100644 index 7dfbd4ea..00000000 --- a/docs/dev-gate-preflight.md +++ /dev/null @@ -1,159 +0,0 @@ -# HWLAB DEV Gate Preflight - -This preflight is the read-only gate before a real DEV deploy or DEV smoke on -D601. It decides whether the current `origin/main` can enter the real -`hwlab-dev` runtime path, or whether it is blocked by missing contract, -artifact, cluster, registry, edge, or safety evidence. - -It does not authorize PROD, restart runtime services, read secrets or tokens, -substitute UniDesk services for HWLAB runtime, or run heavyweight/browser e2e. - -## Command - -Run from the repository root: - -```sh -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/deploy-desired-state-plan.mjs -node --check scripts/src/deploy-desired-state-plan.mjs -node --check scripts/dev-runtime-migration.mjs -node --check scripts/src/dev-runtime-migration.mjs -node --check scripts/refresh-artifact-catalog.mjs -node scripts/deploy-desired-state-plan.mjs --target-ref origin/main --check -node scripts/dev-runtime-migration.mjs --check -node scripts/dev-gate-preflight.mjs -``` - -The command writes `/tmp/hwlab-dev-gate/dev-preflight-report.json` and prints a -short JSON summary. A `blocked` conclusion means the preflight ran correctly but -found blockers; the command exits zero by default so the report can be committed -as evidence. Use `--fail-on-blocked` only in CI jobs that should fail on an open -gate. - -Useful options: - -```sh -node scripts/dev-gate-preflight.mjs --target-ref origin/main -node scripts/dev-gate-preflight.mjs --report /tmp/hwlab-dev-gate/dev-preflight-report.json -node scripts/dev-gate-preflight.mjs --timeout-ms 5000 -node scripts/dev-gate-preflight.mjs --no-write -``` - -## Read-Only Scope - -The preflight checks: - -- `deploy/deploy.json` and `deploy/artifact-catalog.dev.json` are internally - consistent and DEV-only. -- `scripts/deploy-desired-state-plan.mjs --target-ref origin/main --check` can - be run as a read-only source support check for deploy commit/image/tag/workload - and env mirror convergence. It does not contact a registry or prove DEV - runtime state. -- The deploy manifest, artifact catalog, catalog service commits, and image tags - 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 - `/tmp/hwlab-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. -- `/tmp/hwlab-dev-gate/dev-artifacts.json`, when present, proves all frozen DEV - 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. -- `deploy/k8s/base` and `deploy/k8s/dev` parse and remain scoped to - `hwlab-dev`. -- `hwlab-cloud-api` declares the DEV DB env contract: - `HWLAB_CLOUD_DB_URL` from Secret reference - `hwlab-cloud-api-dev-db/database-url` and - `HWLAB_CLOUD_DB_SSL_MODE=disable`. Runtime readiness dials the redacted host - parsed from that Secret URL. `cloud-api-db` is an optional desired alias only - until this repo owns Service plus Endpoint or EndpointSlice manifests and - rollout/apply contract. -- `scripts/dev-runtime-migration.mjs --check` validates the runtime migration - source and ledger contract without live DB access. Live read verification and - migration apply are separate DEV-only modes requiring explicit flags; default - preflight does not read DB secrets or write the DB. -- 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 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 `KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl` - probes against `hwlab-dev` and verify node `d601`; default `docker-desktop` - kubeconfig output is not DEV evidence. -- `/tmp/hwlab-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. A failed - manifest read is tracked as a #66 registry reachability dimension and must not - be conflated with missing publish digests. -- Catalog images do not point at UniDesk, provider-gateway, or microservice-proxy - substitutes; `deploy/deploy.json` must not contain generated image identity. - -## Registry Capability Dimensions - -`registryCapabilities` appears in both the preflight report and the artifact -publish report. The dimensions are: - -- `process-http-access`: runner/BuildKit-side HTTP access to `/v2/`. This is - the publish-path registry API preflight for the current BuildKit-based G14 - pipeline. -- `docker-daemon-push-access`: read-only Docker daemon evidence for the - local/internal registry target. This is a legacy diagnostic only; it is not a - publish-path capability and must not block BuildKit publish readiness. -- `k3s-pull-access`: read-only native-k3s `kubectl` evidence for whether the - DEV cluster can inspect image pull state. This is the deploy-path capability. - -## Verdict Rules - -`ready` requires all checks to pass and no open blocker. - -`degraded` means a non-required capability is observable but incomplete, such as -legacy Docker daemon registry visibility being unavailable after the G14 publish -path has moved to BuildKit. `blocked` is expected until the required real DEV -runtime path can be proven. Each blocker includes a `type`, `scope`, `summary`, -and `nextTask` so the next task is the smallest repair needed before rerunning -the preflight. - -The DB gate has two common blocked scopes: - -- `cloud-api-db-env-contract`: manifest/Kubernetes placeholders are incomplete. - The optional `cloud-api-db` alias is not part of this readiness gate. -- `cloud-api-db-health-gate`: runtime env presence is missing. The next task is - to configure the DEV Secret/env names, not to print or commit any secret - value. - -For catalog commit mismatch, the preflight emits an -`artifactIdentity.refreshCommands.blocked` command. Use it when the source -commit changed but publish is still blocked: - -```sh -node scripts/deploy-desired-state-plan.mjs --target-ref origin/main --pretty -node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked --no-write -``` - -Only use the published refresh path after `/tmp/hwlab-dev-gate/dev-artifacts.json` -proves every frozen service has a registry digest for that same source commit: - -```sh -node scripts/deploy-desired-state-plan.mjs --target-ref origin/main --pretty -node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report /tmp/hwlab-dev-gate/dev-artifacts.json --no-write -``` - -Committed DEV artifact reports can prove required service digests only for the -source commit they name. If the selected `origin/main` target 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/docs/dev-gate-report.md b/docs/dev-gate-report.md deleted file mode 100644 index 92daa883..00000000 --- a/docs/dev-gate-report.md +++ /dev/null @@ -1,151 +0,0 @@ -# HWLAB DEV Gate Report Contract - -This document defines the canonical DEV gate report format for -`pikasTech/HWLAB#31` and the DEV deploy apply report extension for -`pikasTech/HWLAB#33`. It is the handoff surface for the parallel workstreams -behind `#7/#9/#12/#17/#20/#21/#22/#23/#24/#25/#26`, so source-contract -evidence, local smoke, dry-run notes, real DEV prerequisites, and remaining -blockers stay in one place. - -This contract is report-only. It does not authorize a real DEV or PROD -deployment. - -## Report Lifecycle - -Each committed DEV gate report must carry `reportLifecycle`: - -- `state: "active"` means the report belongs to the current DEV gate surface. - Its `activeEndpoint` must be `http://74.48.78.17:16667`, its - `activeBrowserEndpoint` must be `http://74.48.78.17:16666`, and - `deprecatedEndpoint` must be `null`. -- `state: "historical"` means the report is retained only for evidence - provenance. It may name a deprecated endpoint such as - `http://74.48.78.17:6667`, but it must stay blocked/non-green and cannot be - consumed as active acceptance evidence. -- Active reports may preserve a legacy public endpoint only inside an explicit - `runtimeSmoke.legacyPublicEndpoint` object with `status: "deprecated"` and - `activeGreenEligible: false`. -- Active reports must not present `:6666` or `:6667` as a current public DEV - endpoint in endpoint, route, health, ingress, API, frontend, or browser - evidence. Internal k3s service/listen ports may still be `6667` when the - surrounding field names them as cluster-local service ports rather than - public endpoints. -- M3 DEV-LIVE remains narrower than report freshness: it requires - `res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` in real DEV - plus operation, audit, and evidence identifiers. SOURCE, LOCAL, DRY-RUN, - fixture, and historical report evidence are support/diagnostics only. -- M5 DEV-LIVE cannot be inferred from public entrypoint reachability. Reports - must keep EDGE/ROUTE live, DB live/degraded, M3 hardware trusted loop, - M4 agent loop, and artifact/desired-state source status as separate layers. - If the only read-only evidence is `16666/16667` reachability, M5 must remain - blocked/non-green. -- Gate/report aggregators must cross-check DB, M3, M4, and M5 acceptance - against the corresponding source reports before showing `DEV-LIVE` or green - status. Frontend/browser revision facts, public route reachability, source - manifests, local smoke, dry-run output, and fixtures are non-promoting - support evidence for those layers. - -## Files - -- `/tmp/hwlab-dev-gate/dev-gate-report.example.json`: machine-readable example. -- `/tmp/hwlab-dev-gate/dev-deploy-report.json`: DEV deploy apply/preflight result. -- `scripts/validate-dev-gate-report.mjs`: local validator for the report shape. -- `scripts/report-lifecycle.mjs`: lightweight lifecycle helper for validating - one report or marking a replaced report historical/deprecated after endpoint - changes. - -## Required Fields - -Every report must include: - -- `$schema` -- `$id` -- `reportVersion` -- `issue` -- `taskId` -- `commitId` -- `acceptanceLevel` -- `devOnly` -- `prodDisabled` -- `reportLifecycle` -- `sourceContract` -- `validationCommands` -- `localSmoke` -- `dryRun` -- `devPreconditions` -- `blockers` - -## Field Rules - -- `issue` is fixed to `pikasTech/HWLAB#31`. -- `devOnly` must be `true`. -- `prodDisabled` must be `true`. -- `commitId` must be a git SHA string. -- `taskId` and `acceptanceLevel` must be stable slugs, not free-form prose. -- `validationCommands` must record the exact commands used to validate the - report contract. -- `sourceContract.documents` should point at the frozen docs that define the - gate contract. -- `localSmoke`, `dryRun`, and `devPreconditions` should each summarize their - own state with a status, command list, evidence list, and short summary. -- `blockers` should list the remaining open blockers as machine-readable - objects. -- DB gate extensions may add redacted `db`, `cloudApiDb`, or check evidence - objects. These must include only env names, presence/missing status, Secret - reference names, and redacted readiness layers such as `configReady`, - `envInjected`, `connectionAttempted`, `connectionResult`, and - `liveConnected`. They must not include connection strings, passwords, tokens, - DB hostnames from the secret URL, or fixture output presented as live DB - evidence. -- DEV deploy apply reports must include - `devDeployApply.templateJobReplacementPolicy` and - `devDeployApply.templateJobReplacements`. These fields document the - DEV-only suspended template Job replacement allowlist, plus each planned or - executed replacement with namespace, Job name, old image, new image, and - result. The allowlist is limited to `hwlab-agent-worker-template` and - `hwlab-cli-template` in `hwlab-dev`; it must not generalize to ordinary Jobs - or non-Job resources. - -## Validation - -Run: - -```sh -node --check scripts/validate-dev-gate-report.mjs -node scripts/validate-dev-gate-report.mjs -``` - -The validator scans `/tmp/hwlab-dev-gate/*.json` by default. It only checks the -contract shape and the frozen report metadata; it does not run any DEV or PROD -deployment. - -For M5 aggregator reports, the validator also verifies non-promotion -boundaries by reading the declared source report paths. DB acceptance must come -from redacted live DB readiness (`ready=true`, `connected=true`, and -`liveDbEvidence=true`); M3 must come from a real live operation with operation, -trace, audit, and evidence identifiers; M4 must come from the live preflight; -and M5 must remain blocked until DB, M3, M4, and the M5 live source report -each pass their own source checks. Frontend route, source, dry-run, and -fixture evidence may remain in the report, but it cannot promote those layers -to DEV-LIVE acceptance. - -## Invalidate/Rebuild Workflow - -When the public DEV endpoint mapping changes, do not rewrite historical -evidence strings. Preserve the old facts and mark any report that can no longer -represent the active gate as historical: - -```sh -node --check scripts/report-lifecycle.mjs -node scripts/report-lifecycle.mjs invalidate /tmp/hwlab-dev-gate/.json \ - --deprecated-endpoint http://74.48.78.17:6667 \ - --reason "Public DEV endpoint moved to frontend :16666 and API/edge :16667" \ - --out /tmp/hwlab-dev-gate/historical/-legacy-6667.json -node scripts/validate-dev-gate-report.mjs /tmp/hwlab-dev-gate/historical/-legacy-6667.json -``` - -Then regenerate the active report through its owning script so the active file -uses `http://74.48.78.17:16666` for browser/frontend evidence and -`http://74.48.78.17:16667` for API/edge/live evidence. Keep PR notes explicit: -which legacy reports were moved or marked historical, which active reports were -regenerated, and which current reports still need real DEV reruns. diff --git a/docs/dev-m4-agent-loop.md b/docs/dev-m4-agent-loop.md deleted file mode 100644 index c79d5e0e..00000000 --- a/docs/dev-m4-agent-loop.md +++ /dev/null @@ -1,78 +0,0 @@ -# DEV M4 Agent Loop - -This document records the DEV-only M4 agent loop smoke for -`pikasTech/HWLAB#37`. - -## Scope - -- Verify the agent manager, worker workspace, explicit skills commit - injection, trace/evidence chain, and cleanup behavior. -- Keep the runtime path on the fixed DEV boundary at - `http://74.48.78.17:16667`. -- Avoid secret reads, PROD access, long-running agent tasks, and direct gateway - access. - -## Local Checks - -Run the source-only smoke first: - -```sh -node scripts/m4-agent-loop-smoke.mjs -``` - -That smoke stays local and checks the runtime skeleton, workspace isolation, -and explicit skills commit handling. - -Run the bounded M4 dry-run before live preflight: - -```sh -node scripts/dev-m4-agent-loop-smoke.mjs --dry-run -``` - -The dry-run uses only temporary local state. It records manager, worker, -workspace, skills commit, trace, evidence, and cleanup evidence as `DRY-RUN`; -it is not `DEV-LIVE`. - -## Live DEV Preflight - -Run the live preflight only if the DEV route is reachable and the operator has -authorized a short read-only window: - -```sh -node scripts/dev-m4-agent-loop-smoke.mjs --live --confirm-dev --confirmed-non-production -``` - -The live path must only observe existing DEV state. It must not read tokens or -secrets, must not try to run a real agent workload, and must stop if the M3 -runtime preconditions are not ready. - -On D601, the live preflight also records native k3s evidence with the explicit -kubeconfig and namespace: - -```sh -KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n hwlab-dev get pods,svc,deploy,job,cm -o wide -``` - -Worker createability is checked with server-side dry-run admission from the -existing `hwlab-agent-worker-template`. The generated Job stays suspended and is -not persisted: - -```sh -KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl -n hwlab-dev create -f - --dry-run=server -o json -``` - -The smoke may check Secret RBAC with `kubectl auth can-i`, but it must not read -Secret resources, kubeconfig contents, or token values. - -Any hardware assistance from M4 must go through the cloud API hardware surface -and the patch-panel trusted path for `DO1 -> patch-panel -> DI1`. The agent -must not connect directly to box or gateway simulators. - -## Expected Evidence - -- `agent-mgr` creates a scoped worker session. -- The worker workspace is isolated per session. -- The skills artifact is tied to an explicit commit. -- Trace, evidence, and cleanup records stay linked. -- If live DEV is blocked, the report must say why and keep the blocker class - explicit. diff --git a/docs/m0-contract-audit.md b/docs/m0-contract-audit.md deleted file mode 100644 index 8b0ef4a1..00000000 --- a/docs/m0-contract-audit.md +++ /dev/null @@ -1,109 +0,0 @@ -# M0 Contract Audit - -This audit independently reviews whether the L0 skeleton is enough for M0 -contract work under the issue constraints supplied for pikasTech/HWLAB#19 and -the referenced #7/#11/#12/#16 guardrails. - -Applied constraints: - -- MVP acceptance is DEV only at `http://74.48.78.17:16667`. -- PROD is reserved and must not be deployed for this audit. -- HWLAB runtime services must keep their frozen service IDs and must not be - replaced by UniDesk services. -- This audit does not modify L1-L6 service implementation directories and does - not create or claim the L5 deploy manifest. - -## Audit Result - -Status: conditionally passes M0 after this audit patch. - -The repository already contains the L0 contract skeleton needed by parallel -MVP work: - -- Root README freezes MVP scope, DEV endpoint, service IDs, and repository - layout. -- `internal/protocol/index.mjs` centralizes DEV endpoint, frozen service IDs, - table names, JSON-RPC version, and HWLAB error codes. -- `protocol/*.md` documents JSON-RPC envelopes, error codes, audit fields, - capability model, topology constraints, and the sequence-level MVP flow. -- `protocol/schemas/*.json` names the key protocol records and uses - draft-2020-12 JSON Schema shape files. -- `deploy/deploy.schema.json` names the deploy manifest fields and reuses the - frozen service ID list. -- `scripts/validate-contract.mjs` already checks protocol constants against - the common and deploy schemas. - -This patch adds M0 examples under `protocol/examples/m0-contract/` and a -lightweight executable check in `scripts/validate-m0-contract.mjs` so the audit -is not document-only. - -## Coverage Matrix - -| Contract area | Current L0 source | Added M0 sample/check | Result | -| --- | --- | --- | --- | -| Frozen service IDs | `README.md`, `internal/protocol/index.mjs`, `protocol/schemas/common.json`, `deploy/deploy.schema.json` | `service-ids.json`, deploy sample, exact list comparison | Covered | -| JSON-RPC request/response | `protocol/json-rpc.md`, `json-rpc-envelope.schema.json`, runtime validators | `json-rpc-request.json`, `json-rpc-response.json` | Covered | -| Error envelope | `protocol/errors.md`, runtime `ERROR_CODES` | `json-rpc-error.json`, reserved code and stable `error.data` fields | Covered | -| Audit fields | `protocol/audit.md`, `audit-event.schema.json` | `audit-event.json`, required field and ID checks | Covered | -| Capability and topology | `protocol/capabilities.md`, `protocol/topology.md`, related schemas | `capability-topology.json`, cross-reference checks | Covered for M0 | -| Deploy schema fields | `deploy/deploy.schema.json`, `deploy/README.md` | `deploy-manifest.dev.json`, DEV-only example checks | Covered without L5 manifest changes | - -## Rework Risk Register - -Blocker: persisted schema naming drift before L1/L4/L6 integration. -`internal/db/migrations/0001_cloud_core_skeleton.sql` uses placeholder columns -such as `request_id`, `actor`, `source`, `operation`, `result`, `operation_type`, -and `evidence_type`, while the protocol schemas use `auditId`, `traceId`, -`actorType`, `serviceId`, `action`, `outcome`, `capabilityId`, and `kind`. -Before services persist real records, L1 must either align the migration with -the protocol names or provide an explicit mapping layer that is tested. - -Blocker: schema files are parseable but not fully enforced at runtime. -The existing validators and the new M0 check intentionally avoid heavyweight -dependencies and do not evaluate all JSON Schema references. L1-L6 service -entry points need a shared validator such as Ajv or a generated equivalent -before accepting untrusted API, gateway, or agent payloads. - -Blocker: topology constraints are partly prose-only. -M0 can verify that examples cross-reference known resources, capabilities, and -sessions. M1-M3 need a real topology validator for cycle detection, active -resource-group exclusivity, patch-panel override behavior, and gateway/box -ownership. - -Blocker: deploy schema allows future `prod` profile shape. -That is acceptable for L0 compatibility, but L5 must keep MVP execution DEV-only -and reject any real PROD deploy path until a later milestone explicitly changes -the acceptance target. - -Enhancement: RPC method catalog is not yet complete. -M0 freezes envelope shape, method naming, and representative -`hardware.operation.request`. Later milestones should add a method registry with -params/result schemas for project, gateway, patch-panel, worker, evidence, and -cleanup flows. - -Enhancement: capability constraints are generic JSON objects. -This keeps M0 flexible, but hardware-facing work should add typed constraint -profiles for common operations such as voltage ranges, serial settings, -firmware flashing, and measurement tolerances. - -Enhancement: evidence integrity is structural only. -The sample checks SHA-256 format but does not hash referenced artifacts. M4/M5 -should verify artifact existence, size, content hash, and retention policy. - -Enhancement: service ID drift checks are duplicated. -Current validation compares runtime constants with schema enums. A later cleanup -could generate schema enums and docs from one registry. - -## Validation - -Run: - -```sh -npm run check -node --check scripts/validate-m0-contract.mjs -node scripts/validate-m0-contract.mjs -``` - -The M0 script parses all JSON files in `protocol/examples/m0-contract/`, checks -the audit Markdown headings, and verifies the representative cross-document -invariants needed for M0. diff --git a/docs/m1-local-smoke.md b/docs/m1-local-smoke.md deleted file mode 100644 index 6ab741a8..00000000 --- a/docs/m1-local-smoke.md +++ /dev/null @@ -1,82 +0,0 @@ -# M1 SOURCE/LOCAL Contract Smoke - -The M1 local smoke is a fast contract check for the current HWLAB MVP -runtime. It runs only on the local machine, uses short-lived localhost -processes, and does not deploy or call the frozen DEV endpoint. It is -SOURCE/LOCAL evidence only, not DEV-LIVE evidence. - -Run it from the repository root: - -```sh -node scripts/m1-contract-smoke.mjs -``` - -The equivalent npm entry point is: - -```sh -npm run m1:smoke -``` - -## What It Checks - -- Starts `hwlab-cloud-api` on `127.0.0.1` with an ephemeral port and checks - `/health`, `/live`, `GET /v1`, and `POST /rpc`. -- Verifies the cloud-api runtime returns degraded `system.health` when DB - persistence is not connected, describes the REST and JSON-RPC adapter - surface, registers a gateway/box/capability, and records an accepted - `hardware.operation.request` in process-local memory. -- Starts `hwlab-gateway-simu`, `hwlab-box-simu`, and `hwlab-patch-panel` on - ephemeral localhost ports. -- Checks simulator health and status payloads, confirms cross-device - propagation is `patch-panel-only`, writes a local box port value, and routes a - signal through the patch panel fixture. -- Checks `hwlab-agent-mgr` local health and sample manager lifecycle JSON - (`health`, `create`, `status`, `cleanup`) in a temporary state directory. -- Parses `fixtures/mvp/runtime.json` through the CLI dry-run path and verifies - the dry-run output names the MVP route, closed loops, evidence fixture, and - the no-DEV/PROD-change disclaimer. - -## Boundary - -This smoke is not the future DEV e2e acceptance test. It intentionally does not: - -- deploy to DEV or PROD; -- call `http://74.48.78.17:16667`; -- run browser e2e; -- read secrets, tokens, kubeconfig, tunnel credentials, or deploy manifests; -- validate real gateway, router, frp, edge proxy, agent, worker, or hardware - behavior; -- replace the L5 deploy manifest work. - -The check is scoped to the local M1 contract boundary: existing cloud-api, -patch-panel, simulator, agent-mgr, Code Agent chat schema, and CLI dry-run -runtime paths can be started or parsed and still agree on the frozen service -IDs, DEV environment, JSON-RPC/REST surface, DB degradation contract, local -manager lifecycle shape, and patch-panel-only topology assumptions. - -The Code Agent chat check intentionally exercises only SOURCE/LOCAL contract -shape. User workbench backend routing may be present in the codebase, but a -real assistant reply and provider-backed completion must be validated by separate -DEV-LIVE work. - -## Follow-On DEV e2e - -A later real DEV e2e should run against the deployed DEV route, exercise the -actual cloud-web/cloud-api, gateway/router/tunnel path, hardware trusted closed -loop, agent automation closed loop, evidence persistence, and cleanup behavior. -That later test should produce deployment/evidence artifacts and must remain -separate from this local smoke harness. - -## L2 Runtime Smoke - -The L2 simulator runtime has a separate local check: - -```sh -npm run l2:smoke -``` - -It starts two `hwlab-gateway-simu` and two `hwlab-box-simu` processes on -ephemeral localhost ports. It proves simulator identity, AI/AO/DI/DO/FREQ -state operations, gateway register/heartbeat/capability/invoke forwarding, -error codes, audit/evidence shapes, and the patch-panel-only propagation -boundary. It does not call DEV or PROD. diff --git a/docs/m3-hardware-loop.md b/docs/m3-hardware-loop.md deleted file mode 100644 index ab8c1b0d..00000000 --- a/docs/m3-hardware-loop.md +++ /dev/null @@ -1,142 +0,0 @@ -# M3 Hardware Trusted Loop Local Contract - -This contract smoke proves the local M3 wiring path for: - -```text -box-simu-1 DO1 -> box-simu-2 DI1 -``` - -The fixture is `fixtures/mvp/m3-hardware-loop/topology.json`. It contains two -`hwlab-box-simu` resources, two `hwlab-gateway-simu` sessions, and one -`hwlab-patch-panel` status object. The active wiring config has one exclusive -connection from `res_boxsimu_1:DO1` to `res_boxsimu_2:DI1`. - -Run the smoke locally: - -```sh -node scripts/m3-hardware-loop-smoke.mjs -``` - -## What It Checks - -- DEV-only topology with two boxes, two gateways, and one active patch panel. -- Patch-panel-only propagation; box local loopback is not accepted as a - cross-device substitute. -- Direct local call into the existing patch-panel model routes - `box-simu-1 DO1` to `box-simu-2 DI1`. -- An unwired local signal does not cross devices. -- The expected audit event includes the L0 audit fields: - `auditId`, `traceId`, `actorType`, `actorId`, `action`, `targetType`, - `targetId`, `serviceId`, `environment`, and `occurredAt`, plus project, - gateway session, operation, outcome, and metadata fields. - -## Boundary - -This is a local contract smoke only. It does not deploy DEV or PROD services, -does not connect to real hardware, does not read secrets or tokens, and does -not write `audit_events` rows to a database. The audit event in the fixture is -an expected record shape for the future real flow. - -The later real DEV M3 path must replace the in-process direct call with live -service boundaries: cloud request validation, gateway session ownership, -patch-panel state application, real or simulator box observation, persisted -audit events, and evidence records. That future work must preserve the same -wiring contract and must keep routing decisions under `hwlab-patch-panel` -ownership instead of mutating another box directly. - -## L2 Local Runtime Smoke - -Issue 53 adds a runnable localhost-only L2 simulator contract: - -```sh -npm run l2:smoke -``` - -The smoke starts two `hwlab-box-simu` instances (`box-a`, `box-b`) and two -`hwlab-gateway-simu` instances (`gateway-a`, `gateway-b`) on ephemeral -localhost ports. It verifies: - -- box ports for `AI1`, `AO1`, `DI1`, `DO1`, and `FREQ1`; -- internal port API writes for patch-panel-owned delivery; -- gateway register, heartbeat, capability report, and invoke forwarding; -- multi-instance identity separation for `box-a`/`box-b` and - `gateway-a`/`gateway-b`; -- HWLAB JSON-RPC error codes for missing gateway registration and unavailable - capabilities; -- returned audit and evidence object shapes. - -This smoke is still not a DEV deploy or PROD deploy. It proves the minimum -runtime surface that later M3/M5 live checks can call. Cross-device propagation -is not implemented as box-simu loopback; the only accepted cross-device owner -remains `hwlab-patch-panel`, which calls the box internal port API. - -## DEV Runtime Smoke - -Use the no-write plan first: - -```sh -node scripts/dev-m3-hardware-loop-smoke.mjs --dry-run -``` - -The dry-run plan writes `/tmp/hwlab-dev-gate/dev-m3-hardware-loop.json` by -default, records `dryRunPlan.evidenceLevel: "DRY-RUN"`, lists the live write -preconditions, enumerates the endpoints that a later live run would call, and -keeps `liveOperation.status: "not_run"`. It does not call DEV endpoints, does -not send `/ports/write` or `/signals/route`, and cannot be promoted to -`DEV-LIVE`. - -Use this command only for the approved DEV simulator runtime window: - -```sh -node scripts/dev-m3-hardware-loop-smoke.mjs --live --confirm-dev --expect-non-prod -``` - -The legacy `--confirmed-non-production` flag is accepted as compatibility, but -new handoffs should use `--expect-non-prod`. Missing or incomplete live -authorization stays on the source/read-only plan path, and `--dry-run` combined -with `--live` remains no-write. - -The live smoke writes `/tmp/hwlab-dev-gate/dev-m3-hardware-loop.json`. It first -checks the frozen DEV endpoint, `http://74.48.78.17:16667`, and stops at the -first critical blocker from `docs/dev-acceptance-matrix.md`. When DEV ingress -is not observable, the report is `blocked` and the script does not run the live -`do.write true -> di.read true` operation. - -If DEV ingress is reachable, the script requires explicit direct DEV simulator -targets through these environment variables: - -```text -HWLAB_DEV_BOX_SIMU_1_URL -HWLAB_DEV_BOX_SIMU_2_URL -HWLAB_DEV_GATEWAY_SIMU_1_URL -HWLAB_DEV_GATEWAY_SIMU_2_URL -HWLAB_DEV_PATCH_PANEL_URL -``` - -Those targets must be two distinct HWLAB DEV simulator services for each -box/gateway role, plus one callable HWLAB DEV patch panel, not UniDesk -substitutes. Missing direct targets are classified as `target_missing`, -duplicated box or gateway identities as `identity_not_distinct`, and missing -`res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` wiring as -`patch_panel_wiring_missing`. Each of those stop conditions keeps -`liveOperation.status` at `not_run` and prevents the DEV write/read smoke from -starting. The script then checks two box simulators, two gateway simulators, -active patch-panel wiring for -`res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1`, a live direct -call that reads `DI1=true`, and returned operation, trace, audit, and evidence -identifiers. Fixture-backed local M3 output is never accepted as live DEV -evidence. - -## Read-Only Continuation Evidence - -When DEV ingress is blocked, continuation work may still record read-only -evidence. The smoke report includes a static comparison of -`deploy/k8s/base/workloads.yaml` against the M3 requirement for two -`hwlab-box-simu` instances and two `hwlab-gateway-simu` instances. This is not -live runtime proof. The checked-in DEV manifests are source-ready only when -`node scripts/validate-dev-m3-cardinality.mjs` passes: two `hwlab-box-simu` -replicas with `boxsimu_1,boxsimu_2`, two `hwlab-gateway-simu` replicas with -`res_boxsimu_1,res_boxsimu_2`, and one `hwlab-patch-panel`. If the live runtime -still lacks the required simulator cardinality, the fix is a separate -authorized DEV deploy or runtime task, not a mutation inside the M3 evidence -collection task. diff --git a/docs/m4-agent-loop.md b/docs/m4-agent-loop.md deleted file mode 100644 index 86cd72e6..00000000 --- a/docs/m4-agent-loop.md +++ /dev/null @@ -1,72 +0,0 @@ -# M4 Agent Automation Loop Local Contract Smoke - -Run the local M4 smoke from the repository root: - -```sh -node scripts/m4-agent-loop-smoke.mjs -``` - -This check stays local. It uses the `internal/agent` runtime skeleton and a -repo fixture to verify: - -- lifecycle coverage for `create`, `start`, `trace`, `finish`, and `cleanup`; -- manager `create/status/trace/evidence/cleanup` contract behavior through the - local file-system runtime; -- worker `dry-run` task claim, trace write, evidence write, and temporary - workspace cleanup; -- workspace isolation per agent session; -- explicit skills `commitId` and `version` wiring; -- evidence record fields, URI shape, and SHA-256 digest; -- the fixture evidence note that marks the run as local-only. - -The local CLI contract is JSON-only and short-lived: - -```sh -STATE_DIR="$(mktemp -d)" -node cmd/hwlab-agent-mgr/main.mjs create --state-dir "$STATE_DIR" \ - --agent-session-id agt_local_m4 --project-id prj_local_m4 \ - --goal "verify local agent loop" --prompt "dry-run" \ - --skill-commit-id 6509a35 --skill-version v1 -node cmd/hwlab-agent-worker/main.mjs dry-run --state-dir "$STATE_DIR" \ - --agent-session-id agt_local_m4 \ - --skill-commit-id 6509a35 --skill-version v1 -node cmd/hwlab-agent-mgr/main.mjs status --state-dir "$STATE_DIR" \ - --agent-session-id agt_local_m4 -node cmd/hwlab-agent-mgr/main.mjs trace --state-dir "$STATE_DIR" \ - --agent-session-id agt_local_m4 -node cmd/hwlab-agent-mgr/main.mjs evidence --state-dir "$STATE_DIR" \ - --agent-session-id agt_local_m4 -node cmd/hwlab-agent-mgr/main.mjs cleanup --state-dir "$STATE_DIR" \ - --agent-session-id agt_local_m4 -``` - -If either skills `commitId` or `version` is omitted, health and evidence are -reported as `degraded`; no fallback commit or external skill source is inferred. - -## Real DEV Preconditions - -A real DEV M4 run is separate from this smoke. It would need a live DEV -environment, a seeded `prj_*` project, the `hwlab-agent-mgr`, -`hwlab-agent-worker`, and `hwlab-agent-skills` services, and a stable -`hwlab-agent-skills` artifact with an explicit `commitId`. - -That live path must not read tokens or secrets from the runner. Do not inspect -`GH_TOKEN`, `GITHUB_TOKEN`, kubeconfig material, tunnel credentials, or any -other secret-bearing source as part of this smoke. If a live M4 path cannot run -without those reads, the blocker is safety, not contract shape. - -## Failure Classification - -- `contract_blocker`: fixture, lifecycle, or field shape mismatch. -- `environment_blocker`: DEV-only boundary or endpoint assumptions are wrong. -- `agent_blocker`: workspace isolation, cleanup, or evidence wiring fails. -- `observability_blocker`: a live artifact cannot be tied to service or - `commitId` identity. -- `safety_blocker`: any secret read, real deployment, or long-running agent - task. - -## What This Is Not - -This does not deploy, does not call production, and does not run a real agent -job. It only checks the local runtime skeleton contract and its fixture-backed -evidence note. diff --git a/docs/m5-mvp-e2e.md b/docs/m5-mvp-e2e.md deleted file mode 100644 index 21a3fa12..00000000 --- a/docs/m5-mvp-e2e.md +++ /dev/null @@ -1,116 +0,0 @@ -# M5 MVP E2E Dry-Run Orchestration - -M5 is the static orchestration gate before the first real DEV MVP e2e run. It -does not deploy, does not call DEV, does not run browser e2e, and does not read -secrets. The source contract gate is: - -```sh -node scripts/m5-mvp-e2e-dry-run.mjs -``` - -The script reads the frozen protocol contracts, the DEV acceptance checklist, -`fixtures/mvp/runtime.json`, and `fixtures/mvp/m5-e2e/dry-run-plan.json`. It -validates the dependency graph and checks that each step has resolvable inputs -and outputs. - -The L6 external acceptance CLI wraps the same report and dry-run plan: - -```sh -node tools/hwlab-cli/bin/hwlab-cli.mjs test e2e --env dev --mvp -``` - -Cloud Web #59 adds a separate read-only diagnostics contract: - -```sh -node web/hwlab-cloud-web/scripts/check.mjs -``` - -This contract is source-only. It verifies the public frontend/API endpoint -split, the read-only JSON-RPC calls used by Cloud Web, the visible topology, -route, health, and M3 evidence summary, and the rule that edge-only -observations cannot be displayed as M3 `DEV-LIVE`. - -This command defaults to a JSON dry-run plan. `--dry-run` is accepted for -backward compatibility, but it is no longer required for safety. The output -must identify the M0-M5 report source, artifact and DEV health contract counts, -two gateway sessions, two box resources, patch-panel status, agent and worker -session IDs, evidence records, open blockers, and the statement that no -DEV/PROD changes were made. - -## Dry-Run Flow - -| Order | Step | Purpose | Required Inputs | Required Outputs | -| --- | --- | --- | --- | --- | -| 1 | DEV health | Confirm the frozen DEV endpoint and recorded edge/frp/D601/cloud health contracts. | DEV endpoint, ingress, edge route, frp, router, cloud API/web health records | Route, tunnel, namespace, cloud service identities | -| 2 | Gateway/box status | Confirm gateway, simulator, resources, and capabilities are present. | Gateway sessions, box resources, capabilities | Gateway session, resource IDs, capability IDs | -| 3 | Wiring | Confirm the active wiring config is patch-panel owned. | Wiring config, patch-panel status | Wiring config ID, patch-panel status ID | -| 4 | Direct hardware call | Validate the direct JSON-RPC hardware operation envelope and field flow. | RPC request/response, resource, capability, patch-panel status | Operation ID, trace ID | -| 5 | Audit | Confirm mutating setup and direct operation audit records exist. | Project, gateway, wiring, operation audit records | Direct operation audit ID | -| 6 | Agent session | Confirm agent manager, worker, and skills contracts are linked. | Agent/worker sessions, agent health records | Agent session ID, worker session ID | -| 7 | Agent hardware call | Validate the agent worker JSON-RPC hardware operation envelope and field flow. | RPC request/response, agent, worker, resource, capability, patch-panel status | Operation ID, trace ID | -| 8 | Evidence | Confirm both hardware operations emit trace and evidence records. | Trace events, evidence records | Evidence IDs | -| 9 | Cleanup | Confirm worker and gateway transient cleanup are recorded. | Cleanup records, cleanup audit | Cleanup IDs | - -## M0-M4 Dependency Graph - -M5 closes over the earlier MVP contracts as contract-only prerequisites: - -| Source | Provides | Consumed By M5 | -| --- | --- | --- | -| M0 contract audit | Frozen service IDs, protocol schemas, MVP e2e sequence contract | DEV health, hardware operation envelopes, evidence contract | -| M1 local smoke | Static parse boundary and dry-run safety posture | DEV health and cleanup safety checks | -| M2 cloud core | Project record, JSON-RPC envelope, audit surface | Audit, direct hardware call, agent hardware call | -| M3 hardware loop | Gateway session, box resources/capabilities, wiring config, patch-panel status | Gateway/box status, wiring, direct hardware call, agent hardware call | -| M4 agent runtime | Agent session, worker session, trace events, evidence, cleanup | Agent session, agent hardware call, evidence, cleanup | - -The graph must remain acyclic. Each M5 step may only depend on earlier steps -except the agent hardware call, which also depends on the already-established -wiring step. - -## Blocker Classes - -M5 keeps the blocker classes from the DEV acceptance matrix: - -| Class | Meaning | -| --- | --- | -| `contract_blocker` | Static contract, schema, checklist, or documentation cannot be parsed or contradicts frozen names. | -| `environment_blocker` | DEV endpoint, environment, namespace, or PROD boundary is wrong. | -| `network_blocker` | Master edge, frp, D601 route, or public DEV ingress cannot be observed or routes incorrectly. | -| `runtime_blocker` | HWLAB cloud, router, gateway, simulator, box simulator, or patch-panel runtime contract fails. | -| `agent_blocker` | Agent manager, worker, skills, trace, audit, or cleanup contract fails. | -| `observability_blocker` | Artifact identity, commit, image/tag/digest, build source, deploy env, or health timestamp is missing. | -| `safety_blocker` | Any prohibited action was attempted: real deployment, PROD target, browser/heavyweight e2e, secret read, force push, or UniDesk runtime substitution. | - -## Real DEV E2E Gate - -Do not switch to the real command until all of these are true: - -1. `node scripts/m5-mvp-e2e-dry-run.mjs` passes on `origin/main`. -2. `docs/dev-acceptance-checklist.json` and `docs/dev-acceptance-matrix.md` - still freeze DEV at `http://74.48.78.17:16667`. -3. Every accepted artifact has `serviceId`, `commitId`, `image`, `tag`, - `digest` or `not_applicable` reason, `buildSource`, `deployEnv`, and - `healthTimestamp`. -4. DEV ingress, master edge proxy, frp, and D601 `hwlab-dev/hwlab-router` have - current route observations. -5. Cloud API/web, gateway, gateway simulator, box simulator, patch panel, agent - manager, worker, and skills are all observed in DEV with HWLAB service - identities. -6. Gateway and box control remain patch-panel owned; no direct box bypass path - is accepted. -7. Agent worker scope, trace, audit, evidence, and cleanup are observable and - tied to one DEV project. -8. No blocker class is open and a human has explicitly approved a real DEV - smoke. - -Only after those gates are satisfied should the runner switch from dry-run to -the explicit live DEV command: - -```sh -hwlab-cli test e2e --env dev --mvp --live --confirm-dev --confirmed-non-production -``` - -That command is intentionally not executed by M5. While -`GitHub issue/PR comments` contains open blockers, the CLI -must return `code: "BLOCKED"` with blocker evidence instead of substituting -fixture output as live DEV evidence. diff --git a/docs/operator-runbook.md b/docs/operator-runbook.md deleted file mode 100644 index ae0f68b1..00000000 --- a/docs/operator-runbook.md +++ /dev/null @@ -1,384 +0,0 @@ -# HWLAB Operator Runbook - -This runbook is the manual acceptance guide for commanders and operators during -the first HWLAB DEV-only MVP. It defines when a phase may start, when it must -stop, how failures are classified, and which actions are prohibited. - -The runbook supports M0-M5 and the DEV-only MVP path. It does not authorize a -real DEV deployment, PROD deployment, secret access, service restart, or -heavyweight e2e run by itself. - -## Fixed Boundary - -- Repository: `pikasTech/HWLAB`. -- MVP environment: `dev`. -- DEV frontend endpoint: `http://74.48.78.17:16666`. -- DEV API/edge endpoint: `http://74.48.78.17:16667`. -- Legacy public endpoints `:6666` and `:6667` are deprecated and are not MVP acceptance targets. -- Internal k3s service ports may still use `6667`; internal `6667` is not a public acceptance endpoint. -- Runtime route: client, master `hwlab-edge-proxy`, `frp`, D601 - `hwlab-dev/hwlab-router`, then HWLAB cloud/runtime services. -- HWLAB runtime services must keep the frozen service IDs in `README.md`. -- UniDesk services may support scheduling, CI, or CD only. They are not accepted - as substitutes for HWLAB runtime services. -- Code Agent provider credentials are DEV-only runtime inputs: `OPENAI_API_KEY` - must come from Secret `hwlab-code-agent-provider/openai-api-key`, and - `HWLAB_CODE_AGENT_OPENAI_BASE_URL` must route through the DEV egress/proxy - path, not direct public `api.openai.com`. -- Cloud API DB readiness is layered as DNS, TCP, auth, and schema. `.invalid` - hosts are never desired DEV runtime targets; they are negative fixtures only. - -## M3 MVP Acceptance - -M3 MVP PASS is the smallest real DEV evidence chain that proves the hardware -trusted loop. It requires: - -- two box simulators with different observable identities; -- two gateway simulators with different observable identities; -- one active patch-panel participant; -- the traced `res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` - operation with trace, audit, operation, and evidence IDs; -- no box loopback substitution, no front-end direct state edit, and no - UniDesk runtime or proxy substitution. - -Cloud Workbench, generic console work, artifact report generation, and -desired-state planning are support surfaces only. They may help operators, but -they do not count as M3 PASS on their own and cannot replace the loop evidence -above. - -The detailed step order and misclassification bans live in -`docs/reference/m3-loop-rollout-runbook.md`; this runbook and the acceptance -matrix mirror that contract. - -## Runner Issue Visibility Handoff - -GitHub issue and PR threads are auxiliary context only. The runner prompt must be self-contained and must include the full task objective, background, constraints, acceptance, and validation commands. - -Do not assume issue comments are readable in the runner. If a task depends on GitHub visibility, use `docs/reference/runner-issue-visibility-handoff.md` as the stable prompt contract and run `node scripts/runner-issue-visibility-preflight.mjs` before queueing the work. - -The current runner class may have git transport access while GitHub REST issue and PR reads are blocked. Treat that as a prompt-handoff requirement, not a reason to omit context from the prompt. - -## Hard Stop Actions - -Stop the run immediately and classify the event as a safety blocker if any -operator, script, or agent attempts one of these actions: - -- Perform a real DEV deployment from this runbook. -- Deploy, smoke, or mutate PROD in any form. -- Read, print, copy, or infer secrets, tokens, kubeconfig, tunnel credentials, - API keys, or private environment values. -- Restart UniDesk, Code Queue, or `backend-core`. -- Run heavyweight e2e, destructive hardware tests, load tests, or unbounded - browser automation. -- Use UniDesk backend, provider-gateway, or microservice proxy as the HWLAB - runtime instead of `hwlab-cloud-api`, `hwlab-router`, `hwlab-gateway`, - `hwlab-patch-panel`, agent services, and the other frozen HWLAB services. -- Promote SOURCE, LOCAL, DRY-RUN, or edge-only result as real DEV evidence. -- Treat Cloud Workbench polish, generic console work, artifact reports, or - desired state plans as M3 PASS evidence. -- Leave an emergency DEV runtime hotfix as the only source of truth after it - unblocks a P0 path. The follow-up must codify source manifests, contracts, - docs, and validation without rerunning the live patch. - -## Evidence Log - -Every phase result must be recorded in the operator log before the next phase -starts. The log may be a ticket comment, incident note, or release checklist, -but it must include: - -- phase name and milestone IDs; -- command or observation used; -- commit SHA; -- environment, which must be `dev` for MVP evidence; -- endpoint, when a network observation is made; -- pass, fail, blocked, or not-applicable status; -- failure class, when failed or blocked; -- artifact identity for deployable runtime observations: `serviceId`, - `commitId`, `image`, `tag`, `digest` or `not_applicable` reason, - `buildSource`, `deployEnv`, and `healthTimestamp`; -- evidence, audit, trace, operation, agent session, worker session, gateway - session, and project IDs when the phase touches an MVP loop. - -## DEV Gate Aggregator v2 - -Use `/tmp/hwlab-dev-gate/dev-m5-gate-aggregator-v2.json` and -`/tmp/hwlab-dev-gate/dev-m5-gate-aggregator-v2.md` as the current report-only M5 -gate summary for `pikasTech/HWLAB#58`. Refresh them only from committed -fixtures: - -```sh -node scripts/dev-evidence-blocker-aggregator.mjs --report /tmp/hwlab-dev-gate/report.json -node scripts/validate-dev-gate-report.mjs -``` - -The aggregator separates `SOURCE`, `LOCAL`, `DRY-RUN`, `DEV-LIVE`, and -`BLOCKED`. It must never promote source, local, dry-run, contract-only, -not-run, or failed-live evidence into `DEV-LIVE`. - -Current unblock order: - -1. Provide an approved Node 20 DEV builder base image for artifact publish. -2. Publish every frozen HWLAB service artifact and record immutable registry - digests for the selected `origin/main` commit. -3. Restore read-only D601 `hwlab-dev` k3s observability with - `KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl` or an approved - kubeconfig/maintenance bridge, without reading Secrets. Do not use a default - `docker-desktop` kubeconfig as DEV evidence; the control-plane incident is - tracked in pikasTech/unidesk#138. -4. Prove DEV `hwlab-cloud-api` DB env and health readiness with redacted values - only. -5. Repair the `:16667`/`frp`/edge/router path and rerun read-only DEV edge - health before any M3, M4, or M5 live loop. - -For #164-style hotfix follow-up, treat provider and DB fixes as independent -contracts: - -- Code Agent provider: source and k8s workload env must declare - `OPENAI_API_KEY` from `hwlab-code-agent-provider/openai-api-key` and - `HWLAB_CODE_AGENT_OPENAI_BASE_URL` through DEV egress/proxy. Validation may - prove Secret ref shape and key-presence evidence only; it must not print the - API key. -- DB live: source and runtime health must reject `.invalid` as a DEV target and - report DNS/TCP/auth/schema readiness separately. `liveDbEvidence=true` is - allowed only after live runtime connectivity evidence, never from fixtures or - env presence alone. -- Follow-up automation: update `deploy/deploy.json`, - `deploy/k8s/base/workloads.yaml`, source contract code, docs, and tests; do - not apply manifests, restart services, mutate PROD, or repeat the manual - hotfix from the source PR. - -## Phase Gates - -Run phases in order. A later phase may start only after every earlier required -exit condition is met or explicitly marked not applicable with a DEV-only -reason. - -| Phase | Covers | Entry Conditions | Exit Conditions | -| --- | --- | --- | --- | -| Source-only | M0 contract, M2/M4/M5 source readiness | Worktree is based on latest `origin/main`; no secret or deployment access is needed; target files are docs, protocol, schema, fixtures, scripts, or manifests only. | Contract files parse; frozen endpoint and service IDs are unchanged; `npm run check` or the narrow validation command passes; no DEV/PROD mutation occurred. | -| Local smoke | M1 plus local M3/M4 contract smoke | Source-only has passed; commands use localhost or fixture data only; ports are ephemeral; no DEV endpoint call is needed. | Smoke commands pass; generated output states local or dry-run boundary; no real hardware, tunnel, kube, or deploy action occurred. | -| Dry-run | M2/M4/M5 readiness without runtime mutation | Source-only and local smoke pass; CLI/runtime fixtures identify `dev` and `http://74.48.78.17:16667`; operator confirms command includes `--dry-run` where applicable. | Dry-run output names MVP route, hardware trusted closed loop, agent automation closed loop, evidence records, and cleanup plan; output states no DEV/PROD changes were made. | -| DEV runtime smoke | M2 DEV runtime observation | M0-M1 and required dry-runs pass; commander explicitly authorizes a read-only DEV smoke window; expected HWLAB artifacts and rollback owner are known; no secret reads are required. | Read-only health/status observations match `docs/dev-acceptance-matrix.md`; every observed service is HWLAB, in `dev`, and traceable to commit/image/tag/digest or a documented `not_applicable` reason. | -| MVP e2e | M3/M4/M5 DEV-only MVP acceptance | DEV runtime smoke has passed; commander explicitly authorizes a narrow DEV-only MVP smoke; project/gateway/agent/hardware scope is named; cleanup owner and stop criteria are recorded. | One bounded DEV-only flow completes: project, gateway session, resources, patch-panel wiring, agent and worker sessions, hardware operation, trace events, audit events, evidence record, and cleanup. No PROD or heavyweight e2e action occurred. | - -## Milestone Coverage - -| Milestone | Operator Gate | Required Acceptance | -| --- | --- | --- | -| M0 contract audit | Source-only | `docs/m0-contract-audit.md`, protocol docs, schemas, deploy schema, and M0 examples agree on service IDs, JSON-RPC envelope, errors, audit fields, topology, and DEV-only deploy shape. | -| M1 local contract smoke | Local smoke | `npm run m1:smoke` or `node scripts/m1-contract-smoke.mjs` passes on localhost and confirms the local cloud-api runtime, simulator contracts, patch-panel routing, CLI dry-run boundary, and no DEV/PROD changes. | -| M2 DEV deploy/runtime smoke | Dry-run, then authorized DEV runtime smoke | Source/manifests and `docs/dev-acceptance-matrix.md` identify the DEV route through edge, `frp`, and D601 router. Real DEV observation is read-only and must not be performed without commander authorization. | -| M3 hardware trusted loop | Local smoke, then MVP e2e | `node scripts/m3-hardware-loop-smoke.mjs` proves the local contract, but M3 MVP PASS in DEV requires the live `res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1` evidence chain with distinct box/gateway identities and operation, trace, audit, and evidence IDs. | -| M4 agent automation loop | Source-only or dry-run, then MVP e2e | Agent manager, worker, skills, session lifecycle, scoped workspace, trace events, cleanup, and evidence chain are observable in fixtures or dry-run before any DEV runtime action. | -| M5 MVP e2e dry-run and acceptance | Dry-run, then MVP e2e | `npm run cli:dry-run` or equivalent names the MVP route, closed loops, evidence, and cleanup without mutation. Real acceptance is DEV-only, bounded, and requires prior DEV runtime smoke pass. | - -## L6 CLI/Web Acceptance Entry - -Use the L6 entry points for external manual acceptance triage. They read the -checked-in `GitHub issue/PR comments` and -`fixtures/mvp/m5-e2e/dry-run-plan.json`; they do not call UniDesk runtime and -do not claim live DEV evidence from fixtures. - -Safe source and dry-run checks: - -```sh -npm run l6:smoke -npm run web:m3-readonly -npm run web:check -npm run cli:dry-run -node tools/hwlab-cli/bin/hwlab-cli.mjs test e2e --env dev --mvp -``` - -For Cloud Web #99, `docs/cloud-web-workbench.md` is the frontend design and -acceptance contract. The browser endpoint remains public `:16666`, while -API/edge status remains public `:16667`. The default page must be the Cloud -Workbench: left activity rail/resource tree, center Agent conversation/trace, -right hardware/evidence side panel, and bottom command/input area. - -Cloud Web #59 diagnostics move under the secondary diagnostics route. Keep -`diagnostics/status` and `diagnostics/gate` available for read-only -topology/route/health/evidence review, but do not use Gate or M3 Diagnostics -as the default homepage. - -`npm run web:m3-readonly` remains the current safety guard until replaced by a -workbench-aware equivalent. It must keep same-origin `/v1`, read-only -`/json-rpc`, source/gate report, and blocked report boundaries; it must fail -on hardware write APIs, endpoint drift, missing `SOURCE`/`DRY-RUN`/`DEV-LIVE` -or `BLOCKED` source labels, and edge-only observations presented as M3 -`DEV-LIVE`. - -The default CLI MVP command is a JSON dry-run plan even when `--dry-run` is not -provided. It must include the DEV endpoint, artifact/health counts, two -gateway sessions, two box resources, the patch-panel status, agent and worker -session IDs, evidence records, and a statement that no DEV/PROD changes were -made. - -The dry-run shape is support evidence only. It cannot be promoted to M3 PASS -unless the real DEV loop above is present and traceable. - -The live DEV entry point is intentionally separate: - -```sh -node tools/hwlab-cli/bin/hwlab-cli.mjs test e2e --env dev --mvp --live --confirm-dev --confirmed-non-production -``` - -When the M0-M5 gate report still has open blockers, the live command must stop -with `code: "BLOCKED"` and include the blocker evidence. It must not use -fixture data, UniDesk services, PROD, heavy e2e, restarts, or secret reads to -produce a green result. - -## Phase Procedures - -### Source-Only Procedure - -Use this gate for contract review, static checks, fixture checks, and manifest -review. It is the default state before any runtime action is authorized. - -Entry: - -- `git fetch origin main` has completed. -- The working tree is based on latest `origin/main`. -- The change or review does not require secrets, kube access, tunnel access, or - a deployment command. -- The operator has identified the relevant contract source: - `README.md`, `protocol/`, `deploy/deploy.schema.json`, - `docs/dev-acceptance-matrix.md`, M0/M1/M3 docs, or MVP fixtures. - -Exit: - -- Frozen DEV endpoint remains `http://74.48.78.17:16667`. -- PROD is not introduced as an acceptance target. -- Frozen service IDs remain HWLAB service IDs. -- JSON, schema, script syntax, and documented contract checks pass. -- Any unresolved issue is logged under one of the failure classes below. - -### Local Smoke Procedure - -Use this gate for localhost skeleton checks and in-process model checks. - -Entry: - -- Source-only gate passed. -- Commands are known local checks such as `npm run m1:smoke`, - `node scripts/m3-hardware-loop-smoke.mjs`, or targeted `node --test`. -- No command calls `http://74.48.78.17:16667`, `:16666`, kube, `frp`, edge - runtime, or real hardware. - -Exit: - -- Local services start on loopback or ephemeral ports and shut down cleanly. -- Patch-panel-only propagation is preserved. -- CLI output states dry-run or local boundary when applicable. -- Audit and evidence expectations are shape-checked but not claimed as - persisted DEV records. - -### Dry-Run Procedure - -Use this gate for CLI, web, runtime plan, agent loop, and MVP e2e readiness -without mutation. - -Entry: - -- Source-only and required local smoke gates passed. -- The dry-run command has an explicit dry-run flag or documented fixture input. -- The operator has confirmed the command cannot deploy, restart services, read - secrets, write to real hardware, or mutate DEV/PROD state. - -Exit: - -- Output identifies the DEV endpoint and MVP route. -- Output includes both required loops: hardware trusted closed loop and agent - automation closed loop. -- Output includes expected trace, audit, evidence, and cleanup records. -- Output explicitly states that no DEV/PROD changes were made. - -### DEV Runtime Smoke Procedure - -Use this gate only after commander authorization for read-only DEV observation. -This runbook does not grant that authorization. - -Entry: - -- M0, M1, and required dry-runs passed. -- Commander recorded an authorized DEV-only, read-only smoke window. -- The operator has the expected artifact list and service IDs. -- The planned observations require no secret reads and no restart. -- Stop criteria and rollback owner are recorded. - -Exit: - -- DEV endpoint responds through the HWLAB route, not a UniDesk substitute. -- Edge, `frp`, D601 router, cloud API/web, gateway or simulator, - patch-panel, agent manager, agent worker, agent skills, and CLI observations - match `docs/dev-acceptance-matrix.md` where applicable. -- Every observed runtime component identifies `dev` and a HWLAB service ID. -- Artifact identity is traceable or a `not_applicable` reason is recorded. -- Any timeout, stale health, wrong namespace, wrong endpoint, or missing - identity is classified before further action. - -### MVP E2E Procedure - -Use this gate only for a bounded DEV-only MVP acceptance run after DEV runtime -smoke has passed. It must remain much narrower than a heavyweight e2e suite. - -Entry: - -- DEV runtime smoke passed in the same acceptance window or was explicitly - accepted by the commander as still current. -- The MVP scenario is named and scoped to one project, one gateway path, one - patch-panel wiring config, one agent session, and one worker session unless - the commander records a narrower or equivalent scope. -- Expected hardware operation, cleanup action, evidence target, and stop - criteria are recorded. -- No PROD, secret read, restart, or UniDesk runtime substitute is involved. - -Exit: - -- Project is created or selected. -- Gateway session starts for `hwlab-gateway` or `hwlab-gateway-simu`. -- Box resources and capabilities are registered. -- Patch-panel wiring config passes topology validation and owns routing. -- Agent and worker sessions start with scoped identity. -- Hardware operation is requested through the HWLAB JSON-RPC path. -- Trace events cover accepted, dispatched, executed, completed, evidence, and - cleanup milestones. -- Audit events cover mutating steps and final outcome. -- Evidence record is persisted or, for a dry-run, fixture-bound and clearly - marked as not persisted. -- Cleanup completes and no worker, gateway, patch, project, or hardware state - leak remains. - -## Failure Classes - -Classify failures before retrying. If more than one class applies, choose the -earliest blocker in the run path and mention secondary symptoms in the log. - -| Failure Class | Typical Symptoms | Immediate Operator Action | -| --- | --- | --- | -| Contract failure | Schema parse failure, JSON-RPC envelope mismatch, service ID drift, endpoint drift, topology rule mismatch, audit field drift, unsupported PROD target in an MVP artifact. | Stop phase; link the failing file or command; keep investigation source-only until contract drift is fixed. | -| Image/version failure | Missing image, mutable tag, missing digest, health reports wrong commit, skill bundle has no commit ID, web or CLI artifact cannot be tied to source. | Stop runtime promotion; require artifact rebuild or provenance fix; do not substitute another service. | -| k3s/frp/edge failure | DEV ingress timeout, wrong port, edge route missing, `frp` tunnel down, D601 router namespace mismatch, stale route, non-HWLAB response. | Stop DEV runtime smoke; record route segment and timestamp; do not restart UniDesk, Code Queue, `backend-core`, or unrelated infrastructure. | -| Agent failure | Agent manager unavailable, worker session unscoped, missing agent/worker IDs, unsafe mutation, skill mismatch, worker cleanup leak, missing trace event. | Stop agent loop or MVP e2e; preserve logs and IDs; do not rerun with broader permissions or secret access. | -| Hardware loop failure | Gateway unavailable, box resource missing, capability mismatch, direct box mutation, patch-panel bypass, topology conflict, DO/DI observation mismatch. | Stop hardware loop; leave hardware state unchanged when possible; require patch-panel/topology review before retry. | -| Evidence/audit failure | Missing audit event, missing evidence record, trace/audit/evidence IDs not linked, wrong environment, missing operation ID, artifact hash mismatch, cleanup not evidenced. | Stop acceptance; do not claim MVP pass; repair evidence chain or rerun only the smallest authorized DEV-only scope. | - -## DEV-Only MVP Acceptance Path - -The commander may call MVP accepted only when all items below are true: - -1. M0 source-only contract gate passed. -2. M1 local smoke gate passed. -3. M2 dry-run readiness passed and any real DEV runtime smoke was explicitly - authorized, read-only, and passed. -4. M3 hardware trusted loop passed locally and, when authorized, through the - DEV HWLAB route with patch-panel ownership. -5. M4 agent automation loop passed dry-run or source contract checks and, when - authorized, through scoped DEV agent and worker sessions. -6. M5 dry-run passed, then the bounded DEV-only MVP e2e completed with trace, - audit, evidence, and cleanup records. -7. The evidence log contains no unclassified failure, safety blocker, PROD - action, secret read, unauthorized restart, heavyweight e2e, or UniDesk - runtime substitution. - -If any item is missing, the result is blocked or partially passed, not MVP -accepted. diff --git a/docs/plan/device-pod-cli-mvp.md b/docs/plan/device-pod-cli-mvp.md deleted file mode 100644 index 29a943ec..00000000 --- a/docs/plan/device-pod-cli-mvp.md +++ /dev/null @@ -1,85 +0,0 @@ -# Device Pod CLI MVP 计划 - -本文描述 `device-pod-cli` 第一阶段实现计划。它保留为历史 CLI MVP 闭环记录;正式 v0.2 多用户接入规格以 [../reference/spec-device-pod.md](../reference/spec-device-pod.md) 为准。本文中的本地 `.device-pod/` profile 只代表早期 MVP 输入,不适用于正式 profile authority、授权或路由决策。 - -## 目标 - -`device-pod-cli` 是给 HWLAB code agent 使用的独立硬件能力 CLI,不并入 `hwlab-cli`,也不继承 `hwlab-cli` 的广泛管理权限。第一版目标是先不实现真正的 `device-pod-server`,而是把 `device-pod` 当作 profile 驱动的抽象能力单元,通过以下路径跑通最小真实闭环: - -```text -code agent -> device-pod-cli -> hwlab cloud-api/gateway -> device-host-cli -> debug probe / serial / WiFi / vendor protocol -> target -``` - -gateway 保持单纯 cmd 转发;硬件协议、串口、下载器和厂商工具复杂度隔离在用户 PC 上的 `device-host-cli` 后面。`device-pod-cli` 只暴露 workspace、debug-probe、io-probe 的受控语义能力,不提供泛化远程 shell。 - -## Profile 来源 - -CLI 每次执行都从 HWLAB code agent workspace 的 `.device-pod/` 目录读取 profile。推荐文件名为 `.device-pod/.json`;后续可以兼容 YAML,但 MVP 优先使用 JSON,方便 schema 校验和 trace 记录。 - -在 CLI MVP 阶段,profile 是本地执行输入,不做中心注册。CLI 输出必须包含 `profilePath`、`profileHash`、`devicePodId` 和 `targetId`,便于确认每次操作实际使用的是哪个 profile。profile 中只允许描述 route、受控 workspace root、debug-probe 能力、io-probe 能力和 host CLI 能力;不得写入 Git key、云端 token、kubeconfig、数据库 URL 或长期 secret。正式 v0.2 接入后,这些路由字段必须迁移到 `cloud-api` 服务端权威 profile,本地 profile 不再决定 gateway/resource/workspace。 - -## 命令口径 - -统一 locator 语法为: - -```text -device-pod-cli :[:] [args...] -``` - -MVP surface 固定为: - -- `workspace`:源码、工程、构建产物和受控文件操作。 -- `debug-probe`:下载、复位、探针状态和芯片 ID。 -- `io-probe`:UART、GPIO、AI/AO/DI/DO、状态采样和日志读取。 - -workspace 操作采用 busybox 风格白名单,不提供 `cmd` 子命令。已跑通的 CLI MVP 先开放 `ls`、`cat`、`rg`、`apply-patch` 和 `build`;`stat`、`find`、`head`、`tail`、`wc`、`upload`、`download`、`clean` 和 `artifact list` 作为后续扩展进入同一白名单模型。所有文件路径必须限制在 profile 声明的 workspace root 内。 - -示例: - -```text -device-pod-cli device-pod-71-freq:workspace:/firmware ls -device-pod-cli device-pod-71-freq:workspace:/firmware/main.c cat --max-bytes 12000 -device-pod-cli device-pod-71-freq:workspace:/firmware/main.c apply-patch < fix.patch -device-pod-cli device-pod-71-freq:workspace:/firmware build --profile debug -device-pod-cli device-pod-71-freq:debug-probe download --artifact build/app.hex --approved --reason "DEV smoke" -device-pod-cli device-pod-71-freq:debug-probe reset --approved --reason "DEV smoke" -device-pod-cli device-pod-71-freq:debug-probe chip-id -device-pod-cli device-pod-71-freq:io-probe:/uart/1 read --max-bytes 12000 -device-pod-cli device-pod-71-freq:io-probe:/inner/gpio/pa1 read -``` - -`io-probe:/inner/...` 必须显式表示从 target 内部状态读取,例如寄存器、全局变量、debug memory 或固件导出的状态。默认 `io-probe:/gpio/pa1`、`io-probe:/uart/1` 等路径表示外部真实 I/O probe、仪器或另一个设备观测到的物理信号。验收证据中不得混淆 inner 和外部 I/O。 - -## 输出与权限 - -CLI 默认输出 JSON。成功和失败都必须包含 `devicePodId`、`targetId`、`surface`、`operation`、`traceId`、`operationId`、`profileHash`、`route`、`status`、`blocker`、`evidence` 和截断元数据。输出文本、串口日志和命令日志必须有 `maxBytes` 或分页边界。 - -下载、复位、写 I/O、修改 workspace 等动作属于 mutating operation,必须要求显式 approval 参数,并写入 reason。长耗时操作返回 `jobId`,CLI 轮询或拉取 job output,不让一次 HTTP/gateway 调用长期阻塞。 - -## 开发方式 - -1. 先实现 profile schema、loader、locator parser 和 JSON 输出合同,用 fake profile 在本地单元测试覆盖成功、缺 profile、坏 profile、路径越界和未知 surface。 -2. 实现 workspace busybox 操作和 fake gateway adapter,先在不接硬件时证明路径裁剪、输出截断和错误结构稳定。 -3. 实现 debug-probe 与 io-probe 的 adapter 接口,先用 fake `device-host-cli` 返回 chip ID、UART 样例和下载 job 状态。 -4. 在 D518 Windows 上开发自包含 `device-host-cli`,通过 `D518:win` 做真实 DAPLink、串口或下载器 smoke;Keil、串口监控、mklink 和文件编辑 skill 只能作为实现参考,不作为运行时依赖。D518 侧只承载硬件上位机逻辑,不改变 G14 source truth。 -5. 在 G14 code agent pod 中开发和验证 `device-pod-cli`,code agent pod 不放完整 HWLAB 源码和 Git key;CLI 通过 skill 分发到预装位置,并在 skill 说明中写清仅适用于 HWLAB 内部 code agent。 -6. fake 闭环通过后再做 G14 -> gateway -> D518 -> 硬件的最小 live smoke,然后把修复固化到源码、测试和长期参考。 - -## 调试方式 - -- `--dry-run` 只解析 profile、locator 和路由计划,不触发 gateway 或硬件动作。 -- `--trace-id` 可传入外部 trace;未传入时 CLI 生成 trace,并在所有 adapter 输出中透传。 -- `--verbose` 只展开结构化 adapter 阶段和截断摘要,不直接打印 secret 或无限日志。 -- fake adapter 用于本地和 CI;live adapter 只在明确选择 profile route 时启用。 -- 真实硬件问题先在 D518 `device-host-cli` 单独复现,再通过 `device-pod-cli` 验证端到端链路。 - -## 验收标准 - -MVP 通过至少需要满足: - -- `.device-pod/.json` 能被读取、校验、hash 并体现在每次 CLI JSON 输出中。 -- workspace `ls/cat/rg/apply-patch/build` 在受控 root 内可用,路径越界、过大输出和未知命令有结构化失败;`artifact list` 进入后续扩展。 -- `debug-probe chip-id/download/reset` 能通过 fake adapter 稳定返回 job/evidence;live smoke 至少证明一次真实 debug probe 路径可达。 -- `io-probe:/uart/1 read` 与 `io-probe:/inner/... read` 在输出中明确标注外部/内部来源,不互相冒充。 -- gateway 仍只是 cmd transport;CLI 不暴露任意 shell、不接收泛化 `cmd` 子命令、不绕过 profile 访问硬件。 -- 文档、CLI 帮助和 skill 说明明确写明该 CLI 只用于 HWLAB 内部 code agent,不适用于 UniDesk 外部开发者工作区。 diff --git a/docs/plan/device-pod-server-mvp.md b/docs/plan/device-pod-server-mvp.md deleted file mode 100644 index 145c4516..00000000 --- a/docs/plan/device-pod-server-mvp.md +++ /dev/null @@ -1,12 +0,0 @@ -# Device Pod Server MVP 历史计划 - -本文保留为历史计划入口。正式 v0.2 device-pod 接入规格已收敛到 [../reference/spec-device-pod.md](../reference/spec-device-pod.md),迁移计划见 [v02-device-pod-spec-migration.md](v02-device-pod-spec-migration.md)。 - -旧计划中“`device-pod-server` 与 `device-pod` 一一对应”和“code agent workspace `.device-pod/` 是 profile source-of-truth”的口径,只适用于早期 CLI MVP 讨论,不适用于正式多用户系统。 - -当前权威口径: - -- 一个 `hwlab-device-pod` Deployment/Service 在 v0.2 第一阶段管理多个逻辑 `devicePodId`。 -- `cloud-api` 和 Postgres 中的 `device_pods.profile_json` 是正式 profile authority。 -- `device-pod-cli` 只做 REST 客户端,不再用本地 profile 决定 gateway/resource/workspace。 -- `hwlab-device-pod` 承接 job、freshness、blocker 和 gateway/device-host-cli adapter,不保存用户 grant。 diff --git a/docs/plan/device-pod-sidebar-fake-service.md b/docs/plan/device-pod-sidebar-fake-service.md deleted file mode 100644 index 18121ba3..00000000 --- a/docs/plan/device-pod-sidebar-fake-service.md +++ /dev/null @@ -1,35 +0,0 @@ -# Device Pod 右侧看板与 fake service 方案 - -## 目标 - -- 将 Cloud Workbench 右侧区域收敛为 Device Pod 看板,默认只显示 summary。 -- 看板内部不做展开/收起;用户点击 summary 卡片后,通过弹窗查看细节。 -- 事件流降级为最简单的纯文本窗口,更新时不抢占用户正在滚动的位置。 -- 当前先提供 `hwlab-device-pod` fake 服务,完成前端信息模型、Cloud API fallback/proxy 与静态合同闭环。 - -## 前端规划 - -- 右侧固定入口为 `aside#device-pod-sidebar`,包含 Pod Summary、Target、Workspace、Debug、IO 和纯文本事件流。 -- Summary 卡片只展示关键字段;完整 payload 通过 `dialog#device-detail-dialog` 展示,避免在右侧看板内部嵌套折叠面板。 -- 事件流使用 `pre#device-event-text`,滚动容器使用 `overscroll-behavior: contain`,并记录 `followEvents`、`unreadEvents` 与用户滚动活动时间。 -- 前端默认不展示旧硬件拓扑面板,不连接旧模拟硬件拓扑,不提供浏览器侧泛化硬件写入口。 -- 删除旧 `web/hwlab-cloud-web/gate-summary.mjs` 生成型前端拓扑资产,以及生成它的 `scripts/export-web-gate-summary.mjs`/`web:summary` 入口,避免 gateway-simu、box-simu 和 patch-panel 通过前端资产回流。 - -## 服务规划 - -- 新增 `cmd/hwlab-device-pod/main.mjs`,默认端口 `7601`,先服务 fake 数据。 -- 新增 `internal/device-pod/fake-data.mjs` 作为 fake 数据与 REST payload 构造器,覆盖列表、status、events、chip-id、UART 状态和 UART tail。 -- `hwlab-cloud-api` 对 `/v1/device-pods` 做 upstream proxy;upstream 不可用或未配置时回退到 fake payload,前端不直接连接 Device Pod 后端。 - -## 部署规划 - -- `internal/protocol`、deploy manifest、k8s service/workload、health contract 与 artifact catalog 均登记 `hwlab-device-pod`。 -- DEV 环境默认 `HWLAB_DEVICE_POD_ID=device-pod-71-freq`,`HWLAB_DEVICE_POD_PORT=7601`。 -- 该阶段只证明 fake service 与前端右侧看板合同,不声明真实设备闭环通过。 - -## 验收标准 - -- `node web/hwlab-cloud-web/scripts/check.mjs` 只按 Device Pod 右侧看板、summary 弹窗、纯文本事件流和 fake service 合同检查。 -- `node --check` 覆盖新增 fake 数据、Device Pod 服务、Cloud API、前端 app、live-status 与 check 脚本。 -- 右侧看板 HTML 中不存在内部 `
` 展开/收起结构;旧硬件面板 DOM 与旧硬件 API 调用不作为验收目标。 -- Cloud Web runtime/dist 与 L6 Web smoke 不再依赖 `gate-summary.mjs`,也不再断言 gateway-simu、hwlab-box-simu 或 hwlab-patch-panel 前端拓扑。 diff --git a/docs/plan/hwlab-v02-namespace-cicd.md b/docs/plan/hwlab-v02-namespace-cicd.md deleted file mode 100644 index 4b4a0496..00000000 --- a/docs/plan/hwlab-v02-namespace-cicd.md +++ /dev/null @@ -1,178 +0,0 @@ -# HWLAB v0.2 namespace 与 CI/CD 扩容计划 - -本文是 `v0.2` 分支上的执行计划,用于把 `hwlab-v02` 作为 G14 上的独立运行面接入当前 Tekton + GitOps + Argo CD 体系。目标是只做加法扩容,保持现有 G14 DEV/PROD 100% 稳定。长期规格、命名、硬边界和验收标准以 [../reference/spec-v02-cicd.md](../reference/spec-v02-cicd.md) 为准;本文只保留迁移阶段、风险处理和执行顺序。 - -## 固定命名 - -- Source branch:`v0.2`,从当前 `G14` 分支 fork。 -- Source workspace:`G14:/root/hwlab-v02`,固定跟踪 `origin/v0.2`。 -- Runtime namespace:`hwlab-v02`。 -- GitOps branch:规划使用 `v0.2-gitops`,避免写入 `G14-gitops` 的 DEV/PROD desired state。 -- Artifact catalog:规划使用 `v0.2-gitops:deploy/artifact-catalog.v02.json`;它是 CI/CD 生成物和 artifact identity truth,不在 `v0.2` source branch 跟踪或手写维护。 -- Runtime path:规划使用 `v0.2-gitops:deploy/gitops/g14/runtime-v02`;它是 rendered desired state,不在 `v0.2` source branch 跟踪。 -- Argo CD Application:规划使用 `hwlab-g14-v02`。 -- Public FRP entry:Cloud Web `http://74.48.78.17:19666/`,API/live `http://74.48.78.17:19667/health/live`。 - -## 不变边界 - -- 不删除、不重命名、不复用 `hwlab-dev` 或 `hwlab-prod` namespace。 -- 不改写现有 `G14` branch poller、`G14-gitops` DEV/PROD runtime path 或 `hwlab-g14-dev` / `hwlab-g14-prod` Argo Application。 -- 不复用 DEV/PROD 的 FRP 端口、Secret、DB 凭据、PVC 或运行态热修资源。 -- 不清理或重构 `G14` source branch 里已经存在的历史生成物;本计划只规定 `v0.2` 起新增生成物彻底隔离到 GitOps branch。 -- 不在 `v0.2` source branch 新增或维护 `deploy/artifact-catalog.v02.json`、`deploy/gitops/g14/runtime-v02/*` 或 rendered Tekton/Argo runtime manifests。 -- 阻碍 `v0.2` 扩容的旧 DEV/D601/main 门禁一律从 `v0.2` 调用链彻底拆除;不做兼容性迁移、fallback、legacy mode、绕路或在旧门禁上叠加例外。 -- 不在 master server 上运行仓库级 check、browser smoke、镜像构建或集群写操作。 -- 在计划被 issue 追踪并人工确认前,不执行 namespace 创建、Argo sync、FRP 切流或 Tekton 控制面 apply。 - -## 技术决策:v0.2 生成物隔离 - -`G14` 分支上现有 source 里的历史生成物保持不动,避免为了整理历史而影响 DEV/PROD 稳定性。从 `v0.2` 开始采用更严格的 source/GitOps 分层:source branch 只存人类意图、源码、模板、脚本和计划;GitOps branch 存 CI/CD 生成的 artifact catalog、runtime manifests 和 Argo 可消费的 desired state。 - -`v0.2` source branch 可以包含: - -- `deploy/deploy.json` 或等价 lane 配置,作为 human-authored runtime intent。 -- k8s 模板、render 脚本、CI/CD helper 和文档计划。 -- artifact catalog schema、示例或说明,但示例不得伪装成当前发布真相。 - -`v0.2-gitops` branch 必须包含: - -- `deploy/artifact-catalog.v02.json`,记录 image tag、digest、source commit、component commit/hash、publish/reuse evidence。 -- `deploy/gitops/g14/runtime-v02/*`,记录 Argo CD 实际消费的 rendered manifests。 -- 必要的 generated rollout metadata,但不得包含 Secret 值。 - -CI/CD 的初始化规则:Tekton 执行 `v0.2` lane 时必须先读取 `v0.2-gitops:deploy/artifact-catalog.v02.json`。首次初始化时若该文件尚不存在,只允许由 `v0.2` lane 的正式初始化步骤创建第一版 catalog;不得 fallback 到 `G14` source catalog、`G14-gitops` catalog、DEV runtime path 或 source branch 生成物。publish 成功后,刷新后的 catalog 和 runtime manifests 只提交到 `v0.2-gitops`,不得写回 `v0.2` source branch。 - -真相源划分如下: - -| 内容 | `v0.2` source branch | `v0.2-gitops` branch | -|---|---|---| -| 人类运行配置 | 是,`deploy/deploy.json` 或 lane 配置 | 否 | -| 模板和 render 逻辑 | 是 | 否 | -| artifact identity | 否 | 是,`deploy/artifact-catalog.v02.json` | -| rendered runtime manifests | 否 | 是,`deploy/gitops/g14/runtime-v02/*` | -| Argo CD 消费路径 | 否 | 是 | - -这个决策的目标是避免 `v0.2` source branch 出现“看似可手改、实际由 CI 生成”的半真相文件;后续所有复用、跳过构建、digest 对齐和 runtime identity 判断都必须以 GitOps branch 的 artifact catalog 为输入。 - -## 陈旧门禁与处理策略 - -扩容 `v0.2` 时会遇到两类历史依赖:核心 artifact/GitOps 机制需要保留并参数化;旧 DEV-only 自检、preflight、guard 和报告校验不得进入 `v0.2` 路径。凡是阻碍 `v0.2` 的旧门禁,处理方式只有从 `v0.2` 调用链删除;不做兼容性迁移、不做 fallback、不保留 legacy mode、不在旧门禁上加例外。 - -必须参数化保留的核心路径: - -| 位置 | 当前问题 | v0.2 处理 | -|---|---|---| -| `scripts/g14-gitops-render.mjs` | 默认 `G14`、`G14-gitops`、`deploy/artifact-catalog.dev.json`、`runtime-dev`/`runtime-prod`。 | 增加显式 lane/source/gitops/catalog/runtime/namespace/endpoint 参数;`v0.2` 只写 `v0.2-gitops`。 | -| `scripts/refresh-artifact-catalog.mjs` | catalog path、namespace、environment、endpoint 被 DEV-only 断言固定。 | 改成 lane contract;`v0.2` 从 GitOps checkout 读写 `deploy/artifact-catalog.v02.json`,不读写 source catalog。 | -| `scripts/src/g14-ci-plan-lib.mjs` | 复用判断依赖 artifact catalog;默认路径仍是 DEV catalog。 | 保留复用能力,但 `v0.2` 必须传入 GitOps catalog path;catalog 缺失只能触发 `v0.2` 正式初始化或失败,不得回退到 DEV/source catalog。 | -| `scripts/artifact-publish.mjs` / `scripts/g14-artifact-publish.mjs` | preflight 仍把 `hwlab-dev`、DEV catalog 和 DEV-only contract 作为唯一合法目标。 | 保留 build/publish helper;`v0.2` 调用链必须删除这类 DEV-only preflight,只在 build/publish 自然写入点做最小内联断言。 | - -不应进入 `v0.2` 发布门禁的陈旧路径: - -| 位置 | 陈旧点 | 处理 | -|---|---|---| -| `scripts/src/dev-gate-preflight.mjs` | 默认 `origin/main`、`hwlab-dev`、D601/kubectl 口径和旧 `16666/16667` DEV 入口。 | 从 `v0.2` 发布调用链删除;不得改造成 `v0.2` 兼容门禁。 | -| `scripts/src/artifact-runtime-readiness-guard.mjs` | 以 source catalog、latest-main 和 DEV runtime identity 为核心假设。 | 从 `v0.2` 发布调用链删除;如需检查,新增只读 `v0.2` 最小 runtime identity 检查,不复用旧 guard。 | -| `scripts/validate-artifact-catalog.mjs` | 强制校验 `deploy/artifact-catalog.dev.json` 与 `hwlab-dev`。 | 不在 `v0.2` 路径运行;不把它改成多 lane 兼容脚本。 | -| `scripts/src/deploy-desired-state-plan.mjs` | 默认从 source 读取 DEV catalog,容易形成 source desired-state 幻觉。 | 不作为 `v0.2` apply 前门禁;若阻碍扩容,直接移出 `v0.2` 发布流程。 | -| `scripts/src/dev-cloud-workbench-smoke-lib.mjs`、`scripts/src/rpt004-mvp-e2e-harness.mjs`、M3/M4 DEV smoke | 固定 DEV 端口、DEV-LIVE 术语和历史报告 schema。 | 不复用为 `v0.2` gate;必要时新增独立 `v02` smoke,只验证 `19666/19667` 与 `hwlab-v02`。 | -| `scripts/validate-contract.mjs`、旧 `deploy/README.md` / `deploy/master-edge/*` | 仍含历史 `16666/16667` 或 D601 DEV 合同。 | 不让这些旧合同阻塞 `v0.2`;若某项仍被 CI 调用,先从 `v0.2` CI 删除该调用。 | -| source branch 中的 rendered `deploy/gitops/g14/tekton/*` | 可能是历史生成快照,不是 Argo/Tekton 当前真相。 | `v0.2` 不在 source 更新这些生成物;只改 render 入口和 GitOps branch 输出。 | - -`v0.2` 不新增综合 preflight 或大范围 guard。只保留以下硬边界,并优先在已有自然写入点做内联断言:render 断言 runtime path/namespace,promote 断言 GitOps branch/changed paths,Argo spec 断言 Application destination,验收只看 `19666/19667` 与 `hwlab-v02` identity。不要为每一条设计约定再写一个独立 gate。 - -- source branch 必须是 `v0.2`,GitOps branch 必须是 `v0.2-gitops`,runtime namespace 必须是 `hwlab-v02`。 -- runtime path 必须是 `deploy/gitops/g14/runtime-v02`,Argo Application 必须指向 `v0.2` GitOps lane 和 `hwlab-v02`。 -- `v0.2` source branch 在 publish 后不得出现 `deploy/artifact-catalog.v02.json` 或 `deploy/gitops/g14/runtime-v02/*` 变更。 -- 文档、issue、trace 和 report 只出现 SecretRef 名称和 key,不出现 Secret 值。 -- 公网验收只使用 `74.48.78.17:19666/19667`,不得把 `17666/17667` 或 `18666/18667` 作为 `v0.2` 通过证据。 - -## G14 与 v0.2 CI/CD 共存风险 - -G14 与 `v0.2` 可以共享 G14 k3s、Tekton controller、Argo CD controller、本地 registry 和 Git 仓库,但不得共享发布真相、默认入口和生成物。共存原则是:共享底层设施,隔离 source branch、GitOps branch、artifact catalog、runtime path、namespace、Argo Application、poller/reconciler/PipelineRun 名称和 FRP 入口。 - -| 风险 | 具体表现 | 化解方式 | -|---|---|---| -| 控制面资源覆盖 | `v0.2` render/apply 覆盖 `hwlab-g14-ci-image-publish`、`hwlab-g14-branch-poller` 或 `hwlab-g14-control-plane-reconciler`。 | `v0.2` 使用独立资源名,例如 `hwlab-v02-ci-image-publish`、`hwlab-v02-branch-poller`、`hwlab-v02-control-plane-reconciler`;共享 Tekton controller,不共享具体 Pipeline/CronJob。 | -| 默认值漂移 | 为支持 `v0.2` 修改 G14 默认值,导致现有 DEV/PROD 行为变化。 | G14 默认值完全不动;`v0.2` 必须显式传入 lane/source/gitops/catalog/runtime/namespace/endpoint。 | -| GitOps 写错分支 | `v0.2` promotion 误 push 到 `G14-gitops`。 | promote 前硬校验 `sourceBranch=v0.2`、`gitopsBranch=v0.2-gitops`,且 changed paths 只能在 `deploy/artifact-catalog.v02.json` 与 `deploy/gitops/g14/runtime-v02/**`。 | -| runtime path 串线 | `v0.2` 写入 `runtime-dev` 或 `runtime-prod`。 | `v0.2` render 输出路径硬限制为 `deploy/gitops/g14/runtime-v02`;发现 DEV/PROD runtime path 变更直接失败。 | -| artifact catalog 串线 | `v0.2` 读取或复用 `deploy/artifact-catalog.dev.json`、`G14-gitops` catalog 或 source branch 生成物。 | `v0.2` 只读写 `v0.2-gitops:deploy/artifact-catalog.v02.json`;缺失只能正式初始化或失败,不 fallback。 | -| 旧门禁阻塞 | DEV/D601/main 门禁拦住 `v0.2` 发布。 | 从 `v0.2` 调用链删除旧门禁;需要保护时只在自然写入点做最小内联断言。 | -| Argo Application 指错 | `hwlab-g14-v02` 指到 `G14-gitops`、`runtime-dev` 或 `hwlab-dev`。 | Application spec 固定为 `v0.2-gitops:deploy/gitops/g14/runtime-v02`,destination 固定为 `hwlab-v02`。 | -| namespace 资源串用 | Secret、PVC、ServiceAccount、FRP Deployment 或 runtime Service 复用 DEV/PROD。 | namespace 独立;runtime SecretRef 只在 `hwlab-v02` 内解析;cluster-scoped 资源必须独立命名或禁止进入 `v0.2` runtime。 | -| registry tag/digest 混淆 | G14 和 `v0.2` 使用短 SHA tag 时被误判为同一运行态。 | `v0.2` 镜像 tag 使用完整 source commitId,runtime manifest 使用 digest pin;lane 身份记录在 catalog 和 runtime annotation。不要把 lane-specific 配置 bake 进镜像。 | -| 清理任务误删 | stale PipelineRun cleanup、registry GC 或 Argo prune 误触 G14 DEV/PROD。 | 初期不新增自动 registry GC;如后续启用 cleanup,selector 必须带 lane label,registry GC 保护集取 `G14-gitops` 与 `v0.2-gitops` 的 digest union。 | -| 并发资源争抢 | 两个分支同时 build,G14 DEV rollout 变慢。 | `v0.2` 初期使用较低 poller 频率或手动触发;设置 Pipeline resources requests/limits;G14 DEV/PROD 优先级高于 `v0.2`。 | -| 观测混淆 | 把 `17666/17667` 或 `18666/18667` 的结果当成 `v0.2` 通过。 | `v0.2` 验收只认 `19666/19667`;health payload 必须能看到 lane、namespace 或 revision 与 `hwlab-v02` 对齐。 | - -`v0.2` 第一阶段不得做“一个 Pipeline 入口同时兼容两个分支”的设计。正确做法是:G14 保持现有 poller、reconciler、pipeline 和 GitOps branch 不变;`v0.2` 新增独立 poller、reconciler、pipeline 和 GitOps branch,复用底层脚本库、工具镜像、registry 和 controller。共享实现能力,不共享状态、默认入口或生成物。 - -## 扩容前决策表 - -开始创建 namespace、改 Tekton/Argo 或触发 `v0.2` CI/CD 前,先按下表定案。该表不是新增门禁清单;除硬边界外,设计约定和 runbook 不得自动实现为新的 preflight、guard、gate 或报告生成器。 - -| 决策项 | 建议定案 | 性质与降噪要求 | -|---|---|---| -| CI 控制面命名 | 使用独立 `hwlab-v02-*`:`hwlab-v02-ci-image-publish`、`hwlab-v02-branch-poller`、`hwlab-v02-control-plane-reconciler`、`hwlab-v02-ci-poll-`。 | 硬边界;只防覆盖 G14 资源,不扩展成大范围命名审计。 | -| ServiceAccount/RBAC | 推荐新建 `hwlab-v02-tekton-runner`,权限只覆盖 `v0.2` GitOps 写入、PipelineRun 创建和 `hwlab-v02` 运行面观察。 | 设计边界;不做复杂权限 gate,先通过清晰命名和最小 RBAC manifest 表达。 | -| `v0.2-gitops` 初始化 | 新建独立分支 `v0.2-gitops`;首版只放 `deploy/artifact-catalog.v02.json` 和 `deploy/gitops/g14/runtime-v02/*`;提交身份使用 CI/GitOps bot。 | 硬边界;catalog 缺失只能正式初始化或失败,不 fallback 到 G14/DEV。 | -| `deploy.json` lane 表达 | 在 `v0.2` source branch 新增显式 `lanes.v02` 或等价 lane 字段,由 render `--lane v02` 读取;不把现有 `dev` 或 `prod` 改义成 `v0.2`。 | 设计定案;不要为 schema 选择额外做兼容迁移路线。 | -| 镜像 tag | `v0.2` 镜像 tag 使用完整 40 位 source commitId;runtime 以 digest pin 为部署身份;catalog 记录 lane/sourceBranch/gitopsBranch/sourceCommitId/digest。 | 简化策略;不引入 `v02-` tag,不把 lane 差异 bake 进镜像。 | -| 构建输入边界 | 同一 commit 对同一 service 应生成同一镜像;lane 差异放入 manifest/env/SecretRef/namespace/FRP/DB 配置。 | 设计边界;若同 commit 生成不同镜像,先修构建边界,不用 lane tag 掩盖。 | -| SecretRef | `hwlab-v02` 使用独立 Secret 对象;key 名可以沿用服务合同,值不得复用 DEV/PROD,文档只记录对象名和 key。 | 硬安全边界;只禁止 Secret 值外泄,不做 Secret 内容读取 gate。 | -| 数据面 | 推荐独立 DB user + 独立 database;PVC 独立;如后续选择 schema 隔离,必须在计划中单独说明原因。 | 设计定案;不把 DB 方案选择变成 CI gate。 | -| Argo CD | 新建 `hwlab-g14-v02`,source 固定 `v0.2-gitops:deploy/gitops/g14/runtime-v02`,destination 固定 `hwlab-v02`。 | 硬边界;通过 Application spec 表达,不新增平行 Argo 审计脚本。 | -| Argo prune | 允许在 `hwlab-v02` Application 范围内 prune;不得跨 namespace 或管理 DEV/PROD 资源。 | 运行策略;不做 apply 前大检查,靠 Application scope 和 resource labels 限定。 | -| FRP | frpc 名称用 `hwlab-v02-frpc`,只暴露 `19666/19667`,Service 指向 `hwlab-v02` 内 Cloud Web 和 edge/API。 | 硬入口边界;验收只认 v02 端口。 | -| 最小验收 | 只看 `hwlab-g14-v02` revision/sync、`hwlab-v02` 长驻 workload ready、`19666/19667` health/runtime identity。 | 验收口径;旧 DEV/M3/RPT smoke 不进入 `v0.2` gate。 | -| 旧门禁 | DEV/D601/main 门禁凡阻碍 `v0.2`,直接从 `v0.2` 调用链删除。 | 硬治理原则;不做兼容迁移、fallback、legacy mode 或旧门禁例外。 | -| 资源策略 | 初期手动触发或低频 poller;限制 `v0.2` 构建并发和 CPU/memory,G14 DEV/PROD 优先。 | 运行策略;不作为发布 gate。 | -| 清理策略 | 初期不启用新增自动 registry GC;若后续启用,cleanup selector 必须带 `lane=v02`,registry GC 保护集取 `G14-gitops` + `v0.2-gitops` digest union。 | 运行手册;不是扩容前 gate。 | -| 回滚/暂停 | 失败时先停 `hwlab-v02-branch-poller`,再 suspend/delete `hwlab-g14-v02`,最后处理 `hwlab-v02` runtime 资源。 | runbook;不阻塞首次部署,且不得触碰 DEV/PROD。 | -| G14 到 `v0.2` 同步 | bugfix 用显式 cherry-pick 或人工 merge,不做自动同步,不让 `v0.2` 反向影响 G14。 | 分支治理;不做自动 gate。 | -| 变更路径 | 文档和计划可直推 `origin/v0.2`;namespace、Argo、Tekton、Secret、DB、FRP 和 rollout 变更必须引用 issue 和 plan 分步执行。 | 执行纪律;不引入额外 PR/gate 要求。 | - -## 实施阶段 - -1. 文档与 issue 基线 - - 确认 `origin/G14` 和 `origin/v0.2` 都包含 `v0.2` 加法扩容长期参考。 - - 创建 GitHub issue 引用本文,作为 `hwlab-v02` namespace 与 CI/CD 接入的跟踪入口。 - -2. Namespace 与基础 Secret 规划 - - 在 G14 k3s 中新增 `hwlab-v02` namespace。 - - 为 `hwlab-v02` 准备独立 SecretRef:`hwlab-v02-postgres/POSTGRES_PASSWORD`、`hwlab-cloud-api-v02-db/database-url`、`hwlab-v02-code-agent-provider/openai-api-key`、`hwlab-v02-code-agent-codex-auth/*`;key 名按服务合同保留,Secret 对象名与值不得复用 DEV/PROD。 - - Secret 计划只记录对象名和 key,不在文档、issue、日志或 trace 中写入值。 - -3. GitOps desired state 扩容 - - 扩展 render 支持显式 lane 参数:source branch `v0.2`、GitOps branch `v0.2-gitops`、catalog `deploy/artifact-catalog.v02.json`、runtime path `deploy/gitops/g14/runtime-v02`、namespace `hwlab-v02`。 - - render 在执行时从 `v0.2-gitops` 读取上一版 catalog;catalog 缺失时只能执行 `v0.2` 正式初始化或失败,不能 fallback 到 DEV/G14 catalog。 - - 新增 `v0.2-gitops` 生成分支或等价隔离 GitOps 目标;不得把 v02 生成物写入 DEV/PROD runtime path,也不得写回 `v0.2` source branch。 - - 新增 frpc runtime manifest,只暴露 `19666/19667`,内部服务端口继续按现有 Cloud Web `8080`、edge/API `6667` 约定。 - -4. Tekton lane 扩容 - - 在 `hwlab-ci` 中新增 `v0.2` 独立 poller/reconciler/Pipeline,不复用或覆盖现有 G14 控制面资源名。 - - `v0.2` PipelineRun 前缀使用 `hwlab-v02-ci-poll-`,方便和 `hwlab-g14-ci-poll-` 区分。 - - Pipeline 必须 checkout `v0.2` source 和 `v0.2-gitops` generated state;build/publish helper 可复用现有工具镜像、registry 和 BuildKit 机制,但产物 catalog、GitOps branch、runtime path 必须隔离。 - - 镜像 tag 使用完整 source commitId,最终部署 identity 以 digest pin 为准。 - -5. Argo CD 扩容 - - 新增 `hwlab-g14-v02` Application,source 指向 `v0.2` 专属 GitOps lane,destination 指向 `hwlab-v02`。 - - 不修改 `hwlab-g14-dev` 与 `hwlab-g14-prod` 的 source path、revision、namespace 或 sync policy。 - - 首次同步先 dry-run / diff / health 观察,再进入真实 sync。 - -6. `deploy.json` 扩容 - - 在 `v0.2` 分支上新增显式 `lanes.v02` 或等价 lane 配置,服务清单以 `hwlab-v02` 为目标 namespace。 - - 不把现有 `dev` 或 `prod` 环境静默改义为 v02。 - - `deploy.json` 只承载 human-authored runtime intent;image digest、publish state、source commit、reuse evidence 不得写入 `deploy.json`。 - - 如果 render 需要新增 schema 字段,字段必须向后兼容现有 DEV/PROD 配置,并在 v02 lane 中显式启用。 - -7. 验收 - - `tran G14:k3s kubectl -n hwlab-v02 get deploy,sts,svc,pod -o wide` 显示长驻 workload ready。 - - `tran G14:k3s kubectl -n argocd get application hwlab-g14-v02` 显示目标 revision、sync 和 health 与 v02 GitOps lane 对齐。 - - `http://74.48.78.17:19666/` 返回 v02 Cloud Web。 - - `http://74.48.78.17:19667/health/live` 返回 v02 runtime health,payload 的 namespace、revision 或 runtime identity 能和 `v0.2` lane 对齐。 - -## 回滚边界 - -`v0.2` 是新增运行面。若接入失败,回滚应只删除或暂停 `hwlab-v02` lane 的新增 Application、poller、reconciler、runtime path、FRP 入口或 namespace 资源;不得回滚、删除或重启现有 `hwlab-dev` / `hwlab-prod` 运行面。 diff --git a/docs/plan/v02-device-pod-spec-migration.md b/docs/plan/v02-device-pod-spec-migration.md deleted file mode 100644 index bb679a7d..00000000 --- a/docs/plan/v02-device-pod-spec-migration.md +++ /dev/null @@ -1,136 +0,0 @@ -# v0.2 Device Pod 正式接入迁移计划 - -本文记录当前 v0.2 源码到 [../reference/spec-device-pod.md](../reference/spec-device-pod.md) 的迁移路径。目标是把已经跑通的 `device-pod-cli -> cloud-api/gateway -> device-host-cli` 最小闭环,迁移成正式多用户系统中的 `cloud-api` 授权 REST 和 `hwlab-device-pod` 设备业务服务。 - -## 当前态 - -从 v0.2 源码看,当前实现仍处于 fake service + CLI MVP 混合状态: - -- `cmd/hwlab-device-pod/main.mjs` 只提供 GET fake payload 和 `/health`,不连接真实硬件,不执行 job。 -- `internal/device-pod/fake-data.mjs` 构造 `/v1/device-pods`、`/status`、`/events`、`/debug-probe/chip-id` 和 UART tail 的 fake 数据。 -- `internal/cloud/server.mjs` 对 `/v1/device-pods` 做 upstream proxy;upstream 不可用时回退 fake payload,没有授权过滤、profile authority、job route 或 lease。 -- `tools/device-pod-cli.mjs` 从 code agent workspace 的 `.device-pod/` 读取 profile,并直接调用 `cloud-api /v1/rpc/hardware.invoke.shell`。 -- `skills/device-pod-cli/assets/device-host-cli.mjs` 承载了真实业务:workspace 文件操作、Keil build/download、pyOCD chip-id/reset、UART read/write 和 host 侧 job 状态。 -- `deploy/k8s/base/workloads.yaml` 已有 `hwlab-device-pod` Deployment,当前是 `replicas=1` 的 fake 服务。 -- G14 集群当前 `hwlab-dev` 存在 running `hwlab-device-pod` Service/Pod;`hwlab-v02` namespace 尚未落地 device-pod 运行面。 - -## 目标差距 - -| 领域 | 当前态 | 规格目标 | -| --- | --- | --- | -| Profile authority | code agent 本地 `.device-pod/*.json` 决定 gateway/resource/workspace | `cloud-api` DB 中 `device_pods.profile_json` 是唯一权威 | -| CLI | 读取 profile 并拼 RPC/gateway shell | 只把 selector 转成 cloud-api REST 请求 | -| Device service | fake GET payload | 多 `devicePodId` registry、profile runtime validation、job/freshness/blocker | -| Cloud API | proxy/fake fallback | auth、grant、lease、profile admin API、job proxy | -| K8s | 一个 fake Deployment | 一个正式 Deployment 管多个 `devicePodId` | -| 用户安全 | 本地 profile 可被 code agent 改写 | code agent 无法改变 gateway route 或硬件资源边界 | - -## 迁移原则 - -- 不引入单独 user-management 或 device-profile 微服务;profile authority 先放在 `cloud-api` 和 Postgres。 -- 不为每个 device pod 创建独立 k8s Deployment/Service;第一阶段一个 `hwlab-device-pod` 管多个逻辑 `devicePodId`。 -- 不把本地 `.device-pod/*.json` 做兼容权威路径;正式模式只允许本地 hint/cache。 -- 不让 `hwlab-device-pod` 接受用户、code agent 或浏览器上传的 profile 执行 job。 -- 不把 fake fallback 标为 live;fake 只用于 UI/fixture/降级展示。 - -## 阶段 1:Schema 收口 - -在多用户迁移中同步调整 `device_pods` 表: - -- 使用 `profile_json` 保存权威 profile。 -- 使用 `profile_hash` 保存规范化 profile hash。 -- 删除或不新增 `profile_ref`、`gateway_ref`、`device_pod_json` 这类容易分散权威的字段。 -- `device_pod_grants` 只表达用户是否拥有完整使用权,不保存 profile 和 capability。 - -不兼容处理:早期 `.device-pod/.json` 不导入为普通用户可写配置;如需复用,只能由 admin 一次性导入为 server-side profile。 - -## 阶段 2:cloud-api Profile 和 Grant API - -在 `hwlab-cloud-api` 内实现: - -- `POST /v1/admin/device-pods`:创建 device pod 和 profile。 -- `PUT /v1/admin/device-pods/{devicePodId}`:更新 profile、状态和名称。 -- `GET /v1/device-pods`:按 `admin/user + device_pod_grants` 过滤。 -- `GET /v1/device-pods/{devicePodId}/status`:授权后读取状态。 -- `POST /v1/device-pods/{devicePodId}/jobs`:授权、必要时 lease、转发内部 service。 - -cloud-api 返回给普通用户的 profile 只能是脱敏摘要和 `profileHash`。`route.gatewaySessionId`、`resourceId`、`hostWorkspaceRoot`、`hostCli`、probe UID 和串口端口不进入普通用户响应。 - -不兼容处理:未登录或未授权访问 `/v1/device-pods*` 返回 `401/403`,不再回退到 default fake device pod。 - -## 阶段 3:hwlab-device-pod 多设备服务 - -把 `cmd/hwlab-device-pod/main.mjs` 从 fake GET 改造成正式服务: - -- 维护内存 registry:`devicePodId -> profileHash/status/freshness/jobs`。 -- 提供内部 REST:status、short probe、job create/status/output/cancel。 -- 从 cloud-api 内部请求接收 profile snapshot,或用内部服务凭据向 cloud-api 拉取 profile。 -- 调用现有 gateway transport 和 Windows 侧 `device-host-cli`。 -- 解析 `device-host-cli` JSON 输出,统一 blocker、bounded output、freshness 和 evidence 字段。 - -`hwlab-device-pod` 不保存用户 grant,不判断用户身份;它只信任来自 cloud-api 的内部服务请求。内部服务凭据不得挂载进 code agent worker/session Pod。 - -不兼容处理:普通用户和 code agent 直连 `hwlab-device-pod` Service 不是支持路径;缺少内部服务凭据时返回 `401/403`。 - -## 阶段 4:device-pod-cli REST 化 - -把 `tools/device-pod-cli.mjs` 改为 1:1 REST 客户端: - -- selector parser 和 JSON 输出合同可以复用。 -- profile loader 降级为 hint/cache loader;正式执行只接受 `devicePodId`、operation、args 和 reason。 -- 删除或禁用正式路径中的 `/v1/rpc/hardware.invoke.shell` 直调。 -- `doctor` 改为检查 cloud-api 可见 device pod、profileHash、授权状态和 REST route,而不是要求本地 profile 可写。 - -不兼容处理:旧 profile bootstrap、uploadHostCli、uploadProfile 仍可保留在历史/维修命令中,但不能作为正式用户操作的默认下一步。 - -## 阶段 5:复用 device-host-cli 业务 - -短期不要重写 Windows 侧硬件能力。`hwlab-device-pod` 通过 gateway 调用已存在的 `device-host-cli`: - -- `workspace ls/cat/rg/apply-patch/build` -- `debug-probe status/chip-id/download/reset/launch-flash` -- `io-probe ports/read/write/read-after-launch-flash` - -`device-host-cli` 仍部署在 Windows workspace 的 `tools\device-host-cli.mjs`,但其路径来自 server-side profile,不来自 code agent 本地文件。 - -## 阶段 6:Cloud Web 和 Admin UI - -Cloud Web 调整: - -- 普通用户只显示授权 device pod。 -- admin 增加 device pod 创建/更新/禁用、profile 编辑、grant 授权/撤销的最小 UI。 -- Device Pod 右侧看板显示 `profileHash`、status、freshness、chip-id、UART tail 和 job 状态。 -- fake fallback 必须明确标记 fake,不参与 DEV-LIVE 判定。 - -## 阶段 7:v0.2 部署面 - -在 `hwlab-v02` namespace 中部署: - -- 一个 `hwlab-device-pod` Deployment,`replicas=1`。 -- 一个 `hwlab-device-pod` ClusterIP Service。 -- cloud-api 和 device-pod 共享的内部服务凭据 Secret,但不挂载给 code agent session Pod。 -- cloud-api 指向 v0.2 独立 Postgres/Secret,不复用 `hwlab-dev` pgdata。 - -不做 per-device Deployment/Service。未来只有在设备数量、隔离要求或资源差异明确出现后,才考虑 shard 或 per-device workload。 - -## 微服务调整 - -| 微服务 | 调整 | -| --- | --- | -| `hwlab-cloud-api` | 增加 profile authority、admin device-pod API、grant/lease、job proxy、脱敏 profile 响应。 | -| `hwlab-device-pod` | 从 fake GET 改成多 devicePodId REST/job service,调用 gateway/device-host-cli。 | -| `device-pod-cli` | 从本地 profile 执行器改成 cloud-api REST 客户端;本地 profile 只作 hint/cache。 | -| `device-host-cli` | 保持 Windows 侧业务能力,后续按真实硬件问题局部增强。 | -| `hwlab-cloud-web` | 增加 admin profile/grant UI,普通用户视图按授权过滤。 | -| `hwlab-agent-worker` | 为 code agent 提供 session-scoped cloud-api credential,不提供 gateway route/profile secret。 | -| GitOps/render | v0.2 新增 device-pod internal token Secret、env 注入和 `hwlab-v02` Service/Deployment。 | - -## 最小验证 - -- 修改 code agent 本地 `.device-pod/*.json` 不能改变正式 device operation 的 gateway/resource/workspace。 -- 未授权 `user` 调用 `/v1/device-pods/{devicePodId}/jobs` 返回 `403`。 -- 授权用户通过 `device-pod-cli` 发起 `workspace.build` 时,请求路径是 `/v1/device-pods/{devicePodId}/jobs`。 -- `hwlab-device-pod` 能在同一进程中管理至少两个 fake 或 real-profile `devicePodId`。 -- `debug.chip-id`、`io.uart.read` 和 `workspace.build` 的响应包含同一 `profileHash`、`traceId`、`operationId`、`freshness` 和 bounded output metadata。 -- code agent session Pod 中不存在可用于调用内部 `hwlab-device-pod` profile/job API 的服务凭据。 -- fake fallback 响应不会被前端或 health 判定为正式 DEV-LIVE device-pod 证据。 diff --git a/docs/plan/v02-multi-user-migration.md b/docs/plan/v02-multi-user-migration.md deleted file mode 100644 index 9b4a3c39..00000000 --- a/docs/plan/v02-multi-user-migration.md +++ /dev/null @@ -1,145 +0,0 @@ -# v0.2 多用户访问迁移计划 - -本文记录 v0.2 当前源码状态、与目标用户和权限管理规格的差距,以及推荐迁移路径。长期目标和稳定判定标准以 [../reference/spec-user-access.md](../reference/spec-user-access.md) 为准。 - -## 当前态 - -从 v0.2 源码看,当前系统还没有真正的多用户访问控制: - -- `docs/reference/spec-user-access.md` 已定义 `admin/user`、session owner 和 device pod grant 的目标规格,但还没有对应实现。 -- `internal/db/migrations/0001_cloud_core_skeleton.sql` 已有 `projects`、`gateway_sessions`、`hardware_operations`、`audit_events`、`agent_sessions`、`worker_sessions`、`agent_trace_events`、`evidence_records` 和 migration ledger;没有 `users`、`user_sessions`、`device_pods`、`device_pod_grants`、`device_leases`,`agent_sessions` 也没有 `owner_user_id`。 -- `internal/db/runtime-store.mjs` 支持 memory/postgres runtime store 和 readiness,但主要服务 L1 硬件 runtime 数据;用户身份和授权尚未进入 runtime store。 -- `web/hwlab-cloud-web/auth.mjs` 是轻量登录前端,默认 `admin/hwlab2026`,并有 local session fallback;它不是正式用户体系。 -- `internal/dev-entrypoint/cloud-web-routes.mjs` 仍把 `POST /v1/agent/chat`、`POST /v1/agent/chat/cancel`、`GET /v1/agent/chat/result/*`、`GET /v1/agent/chat/trace/*` 视为 public proxy route,多用户下必须收敛为 auth-required。 -- `internal/cloud/code-agent-session-registry.mjs` 以内存 Map 维护 session/conversation/facts,没有 owner、用户 session、Postgres 持久归属或跨 Pod 恢复。 -- `internal/cloud/server.mjs` 的 `/v1/device-pods` 只是代理 `hwlab-device-pod` 或回退 fake payload,没有按 actor 过滤,也没有 profile authority、POST job 或 lease 权限入口。 -- `cmd/hwlab-device-pod/main.mjs` 和 `internal/device-pod/fake-data.mjs` 当前只提供 fake GET 数据,不连接真实硬件,也不持久化 device pod 管理数据。 -- `tools/device-pod-cli.mjs` 当前从 code agent workspace 的 `.device-pod/` 读取 profile,并直接调用 `/v1/rpc/hardware.invoke.shell`;正式多用户接入后,本地 profile 不能继续作为 gateway/resource/workspace 的权威来源。 -- G14 当前集群里 `hwlab-dev` 有 `hwlab-g14-postgres` 和 PVC;`hwlab-v02` namespace 还未成为独立运行面。v0.2 权限数据不能混用 `hwlab-dev` pgdata。 - -## 目标差距 - -| 领域 | 当前态 | 目标态 | -| --- | --- | --- | -| 用户 | 前端默认账号和本地 session fallback | Postgres `users` + `user_sessions`,`admin/user` 两角色 | -| Code Agent session | 内存 ownerless registry | `agent_sessions.owner_user_id` 持久归属,result/trace/cancel 按 owner 校验 | -| Device Pod | fake GET 数据,所有人可见;CLI 本地 profile 可决定 route | `device_pods.profile_json/profile_hash` 服务端权威 + `device_pod_grants` 授权过滤 | -| Device 操作 | 还不是正式 job/lease 权限入口 | cloud-api 授权后转发到 device-pod,独占操作用 `device_leases` | -| Cloud Web 路由 | 部分 agent route public | 除 health/static/login 外,用户态 API 都 auth-required | -| 微服务 | 没有用户服务 | 不新增用户服务,cloud-api 内置 user/auth/access 模块 | -| v0.2 数据面 | namespace/Postgres 目标未落地 | `hwlab-v02` 独立 namespace + 独立 Postgres DB/PVC/Secret | - -## 迁移原则 - -- 不做 group/project/capability/read-operate 分级迁移;直接收敛到 `admin/user` 和 grant-exists-is-full-access。 -- 不新增 user-management 微服务;先把用户管理做成 cloud-api 内部模块和 admin API。 -- 不把 `audit_events` 复用成用户审计;保留它作为既有硬件证据链数据。 -- 不把普通用户映射成 Kubernetes user/namespace/RBAC。 -- 不为了兼容旧 public route 长期保留双路径;不兼容变更在同一阶段同步改后端、前端和测试。 -- v0.2 数据面不复用 `hwlab-dev` pgdata;如需导入历史数据,显式写一次性迁移脚本并记录来源和目标。 - -## 推荐实施阶段 - -### 阶段 1:Schema 和 bootstrap admin - -新增 `0002_multi_user_access_v1` 迁移: - -- 新增 `users`、`user_sessions`、`device_pods`、`device_pod_grants`、`device_leases`。 -- 扩展现有 `agent_sessions`:`owner_user_id`、`conversation_id`、`thread_id`、`last_trace_id`、`session_json`、`updated_at`。 -- 写入 bootstrap `admin`,密码只存 hash。 -- 为 fake/default `device-pod-71-freq` 写入一条 `device_pods` 记录,并由 admin 导入 server-side `profile_json/profile_hash`,便于前端从 fake 数据迁到 DB 管理数据。 - -不兼容处理:已有 ownerless `agent_sessions` 不继续作为普通用户 session。迁移时一次性归属 bootstrap `admin` 或标记 `expired`,迁移后新 session 必须有 owner。 - -### 阶段 2:cloud-api auth/access 模块 - -在 cloud-api 内新增模块: - -- `authenticateRequest(request)`:从 cookie/session token 解析 actor。 -- `requireActor(request)`:未登录返回 `401`。 -- `requireAdmin(actor)`:非 admin 返回 `403`。 -- `authorizeAgentSession(actor, sessionId|traceId|conversationId)`:admin 或 owner。 -- `authorizeDevicePod(actor, devicePodId)`:admin 或存在 `device_pod_grants`。 - -不兼容处理:除 `/health`、`/health/live`、静态资源和登录接口外,用户态 `/v1/*` 不再允许匿名访问。旧 public code agent poll route 直接改为 auth-required,不保留 legacy public mode。 - -### 阶段 3:Cloud Web 登录和 admin UI - -调整 cloud-web: - -- `/auth/session`、`/auth/login`、`/auth/logout` 代理或落到 cloud-api authority。 -- 移除多用户运行态下的 local auth fallback;没有 server session 时显示登录页。 -- 增加最小 admin UI:用户列表、创建/禁用用户、device pod 授权/撤销。 -- 普通用户只显示自己的 code agent session 和被授权 device pod。 - -不兼容处理:默认 `admin/hwlab2026` 只能作为 bootstrap 初始化入口;完成初始化后应由管理员改密码或替换。前端测试 fixture 同步改成 server-session 模式。 - -### 阶段 4:Code Agent session owner 持久化 - -调整 `/v1/agent/chat` 及相关路由: - -- 创建或复用 session 时写入 `agent_sessions.owner_user_id`。 -- `conversation_id -> session_id` 绑定迁到 Postgres 或至少写入 session record。 -- result/trace/cancel/inspect 根据 owner 校验。 -- code agent prompt 中只暴露当前 actor 可见的 device pod 列表。 - -不兼容处理:部署前存在的浏览器本地 conversation/session 可能失效;前端应在 `401/403/session_expired` 时提示重新登录或新建会话,不做 ownerless session 兼容恢复。 - -### 阶段 5:Device Pod 管理和授权过滤 - -调整 `/v1/device-pods`: - -- list/status 从 `device_pods` 读取管理数据,再按 actor 过滤。 -- `admin` 可创建/更新/禁用 device pod。 -- `admin` 是 profile authority,只能通过 cloud-api 创建/更新 `device_pods.profile_json`。 -- `admin` 可 upsert/delete `device_pod_grants`。 -- 未授权用户访问具体 device pod 返回 `403`。 - -不兼容处理:普通用户不再默认看到 `device-pod-71-freq`。如果需要演示用户看到它,必须显式给该用户授权。code agent 本地 `.device-pod/*.json` 不再能改变正式 device pod route。 - -### 阶段 6:Device jobs 和 lease - -为真实设备操作增加 cloud-api job routes: - -- `POST /v1/device-pods/{devicePodId}/jobs` -- `GET /v1/device-pods/{devicePodId}/jobs/{jobId}` -- `POST /v1/device-pods/{devicePodId}/jobs/{jobId}/cancel` - -cloud-api 先校验 actor 和 grant,再按操作类型获取 `device_leases`,最后转发到 `hwlab-device-pod` 内部 Service。 - -不兼容处理:device-pod 服务不面向普通用户直接暴露,不接受浏览器或 worker 直连作为授权依据,也不接受调用方上传 profile 作为执行依据;所有真实操作必须经过 cloud-api。 - -### 阶段 7:v0.2 namespace 和数据面 - -部署面调整: - -- 创建 `hwlab-v02` namespace。 -- 建立 v0.2 独立 Postgres StatefulSet、Service、PVC 和 DB Secret。 -- cloud-api v0.2 指向 v0.2 DB URL 和独立 migration ledger。 -- Cloud Web/API FRP 使用 v0.2 规划入口 `19666/19667`。 - -不兼容处理:不把 `hwlab-dev` 数据自动复制到 v0.2。需要保留的数据必须写明迁移对象、来源、目标和回滚方式;用户权限数据默认从 bootstrap admin 开始重建。 - -## 其他微服务调整 - -| 微服务 | 必要调整 | -| --- | --- | -| `hwlab-cloud-api` | 新增 user/auth/access 模块、admin API、session owner 校验、device grant/lease 校验。 | -| `hwlab-cloud-web` | 登录改为 server-session authority;增加 admin UI;普通用户视图按授权过滤。 | -| `hwlab-edge-proxy` | 保持透明转发,确保 cookie/header 不被丢弃;不注入业务 actor。 | -| `hwlab-agent-mgr` | session 创建参数和状态摘要带 `owner_user_id`、`session_id` label;不自行做最终授权。 | -| `hwlab-agent-worker` | Pod/Job/PVC label 带 owner/session,工具调用 device pod 时走 cloud-api。 | -| `hwlab-device-pod` | 从 fake GET 逐步扩展到多 `devicePodId` jobs API;信任 cloud-api 内部调用,不保存用户 grant,不接受用户上传 profile。 | -| `hwlab-agent-skills` | device-pod-cli 默认目标改为 cloud-api 授权 REST 入口,不直连 device-pod Service,不再以本地 profile 作为正式 route authority。 | -| GitOps/render | v0.2 增加 namespace、Postgres、SecretRef、ServiceAccount、PVC 和 env 注入。 | - -## 最小验证 - -- 未登录访问 `/v1/agent/chat/result/*`、`/v1/agent/chat/trace/*` 和 `/v1/device-pods` 返回 `401`。 -- `admin` 能创建用户、创建设备、授权和撤销授权。 -- 未授权 `user` 看不到 device pod,访问具体 device pod 返回 `403`。 -- 授权后 `user` 能看到并使用 device pod。 -- `user A` 不能读取或取消 `user B` 的 code agent session。 -- `admin` 可以跨用户查看和取消 session。 -- 同一个 device pod 的独占操作只能被一个 active lease 持有。 -- v0.2 cloud-api health 报告连接的是 v0.2 DB,不是 `hwlab-dev` pgdata。 diff --git a/docs/reference/architecture.md b/docs/reference/architecture.md index 01aa7e79..eaf57070 100644 --- a/docs/reference/architecture.md +++ b/docs/reference/architecture.md @@ -18,8 +18,8 @@ M3 virtual hardware trusted loop before broadening the product surface. ## Runtime Shape -The frozen service IDs live in [README.md](../../README.md). The runtime path -is: +Current service ownership and v0.2 keep/remove decisions are authoritative in +[spec-v02-services.md](spec-v02-services.md). The current G14 runtime path is: ```text browser or CLI @@ -90,6 +90,6 @@ Code Agent chat 证据单独分级:只有真实同源 `/v1/agent/chat` board and priority status. - [pikasTech/HWLAB#78](https://github.com/pikasTech/HWLAB/issues/78): M3 decision and prompt/review guardrails. -- [docs/operator-runbook.md](../operator-runbook.md): operator phase gates. -- [docs/dev-acceptance-matrix.md](../dev-acceptance-matrix.md): DEV acceptance - matrix and health contracts. +- [dev-runtime-boundary.md](dev-runtime-boundary.md): G14 DEV/PROD and v0.2 runtime boundary. +- [spec-v02-services.md](spec-v02-services.md): v0.2 microservice keep/remove and dependency boundary. +- [spec-v02-documentation-governance.md](spec-v02-documentation-governance.md): root README and legacy process document migration. diff --git a/docs/reference/cloud-workbench.md b/docs/reference/cloud-workbench.md index a2aec6cd..115f4e5a 100644 --- a/docs/reference/cloud-workbench.md +++ b/docs/reference/cloud-workbench.md @@ -273,7 +273,7 @@ blockers/failures:`viewport`、`selector`、`failureType`、summary 和 artifa resource explorer collapse and controlled resize feedback. - [code-agent-chat-readiness.md](code-agent-chat-readiness.md): Code Agent chat 同源 readiness 和 provider credential blocker 边界。 -- [docs/cloud-web-workbench.md](../cloud-web-workbench.md): detailed frontend - contract. +- [spec-v02-services.md](spec-v02-services.md): Cloud Web runtime wrapper and browser-side TypeScript migration boundary. +- [pikasTech/HWLAB#532](https://github.com/pikasTech/HWLAB/issues/532): archived historical `docs/cloud-web-workbench.md` content. - [g14-gitops-cicd.md](g14-gitops-cicd.md): Cloud Web rollout through G14 Tekton, GitOps and Argo CD path. diff --git a/docs/reference/commander-collaboration.md b/docs/reference/commander-collaboration.md index 258cdff2..c58dd3c3 100644 --- a/docs/reference/commander-collaboration.md +++ b/docs/reference/commander-collaboration.md @@ -31,7 +31,7 @@ ## 分支和交付工作流 - 单纯文档、CLI/helper 轻量变更默认直接提交并 push 到 `origin/G14`,不开 PR;这类变更仍要先从最新 `origin/G14` 创建独立 worktree,提交前审查 diff,只提交当前任务相关文件。 -- `v0.2` 线的单纯文档和计划可以直接提交并 push 到 `origin/v0.2`,不开 PR;涉及 namespace 创建、Argo CD Application、Tekton poller/reconciler、FRP、Secret、DB、权限或 runtime rollout 的变更必须先有 `docs/plan/` 计划和 GitHub issue,再按计划分步执行。 +- `v0.2` 线的单纯文档和规格更新可以直接提交并 push 到 `origin/v0.2`,不开 PR;涉及 namespace 创建、Argo CD Application、Tekton poller/reconciler、FRP、Secret、DB、权限或 runtime rollout 的变更必须先有 GitHub issue 承接过程计划,再按 issue 和对应 `docs/reference/spec-*.md` 分步执行。仓库内不再新增 `docs/plan/*.md`。 - 业务代码、运行面、发布链路、Secret、权限、数据迁移、PROD、重启服务、CI/CD 控制面高风险变更或其他影响 runtime truth 的变更默认走 PR 工作流。 - 用户或指挥官给出最新交付纠偏时,以最新要求为准,删除旧断言或旧门禁,不用 feature flag、legacy mode 或双路径长期并存绕开最新要求。 diff --git a/docs/reference/dev-runtime-boundary.md b/docs/reference/dev-runtime-boundary.md index 64eeb196..03590f56 100644 --- a/docs/reference/dev-runtime-boundary.md +++ b/docs/reference/dev-runtime-boundary.md @@ -449,10 +449,8 @@ M4, or M5 live evidence. ## Stable Sources - [deploy/frp/README.md](../../deploy/frp/README.md): FRP DEV contract. -- [docs/d601-k3s-readonly-observability.md](../d601-k3s-readonly-observability.md): - read-only k3s visibility command. -- [docs/dev-acceptance-matrix.md](../dev-acceptance-matrix.md): DEV endpoint - and health acceptance. +- [spec-v02-cicd.md](spec-v02-cicd.md): v0.2 runtime namespace, FRP ports and GitOps lane boundary. +- [pikasTech/HWLAB#532](https://github.com/pikasTech/HWLAB/issues/532): archived legacy D601 observability and DEV acceptance root docs. - [pikasTech/HWLAB#164](https://github.com/pikasTech/HWLAB/issues/164): Code Agent provider and DB live hotfix follow-up contract. - [pikasTech/HWLAB#61](https://github.com/pikasTech/HWLAB/issues/61): manual diff --git a/docs/reference/device-pod.md b/docs/reference/device-pod.md index 204fdcae..2af630a2 100644 --- a/docs/reference/device-pod.md +++ b/docs/reference/device-pod.md @@ -10,4 +10,4 @@ - v0.2 第一阶段使用一个 `hwlab-device-pod` Deployment/Service 管理多个逻辑 `devicePodId`,避免过早引入 per-device k8s workload 运维压力。 - 正式访问路径是 `device-pod-cli/cloud-web -> cloud-api -> hwlab-device-pod -> gateway -> device-host-cli -> target`。 -迁移计划见 [../plan/v02-device-pod-spec-migration.md](../plan/v02-device-pod-spec-migration.md)。历史 CLI MVP 闭环见 [../plan/device-pod-cli-mvp.md](../plan/device-pod-cli-mvp.md),但其中本地 profile 权威口径不适用于正式 v0.2 多用户接入。 +实施跟踪见 [pikasTech/HWLAB#533](https://github.com/pikasTech/HWLAB/issues/533)。旧迁移计划和 CLI MVP 闭环全文已迁入该 issue 评论;其中本地 profile 权威口径不适用于正式 v0.2 多用户接入。 diff --git a/docs/reference/documentation-governance.md b/docs/reference/documentation-governance.md index 1be17706..cac6f2a1 100644 --- a/docs/reference/documentation-governance.md +++ b/docs/reference/documentation-governance.md @@ -2,12 +2,14 @@ 本文是 HWLAB 仓库内固化的 `docs-spec` 规则副本和可执行摘要,也是本仓库唯一维护 `docs-spec` 使用规则的长期参考。它等价承担 `docs/reference/docs-spec.md` 的职责;不要再新增同级 `docs-spec` 规则副本,避免多处口径漂移。编辑 `AGENTS.md`、`docs/reference/*.md` 或把过程记录蒸馏为长期参考时,必须先按本文执行;如果 runner 能读取外部 `docs-spec` skill,也要以本文作为 HWLAB 本地权威落点。 +`v0.2` 文档树的额外收敛规格见 [spec-v02-documentation-governance.md](spec-v02-documentation-governance.md)。该规格禁止仓库保留根 `README.md`、`docs/*.md`、`docs/*.json` 和 `docs/plan/*.md` 作为长期或过程文档入口;计划、里程碑和一次性记录必须迁入 GitHub issue。 + 中文优先规则只在 [chinese-first-documentation.md](chinese-first-documentation.md) 维护,用户和参谋反馈分流规则只在 [user-feedback-triage.md](user-feedback-triage.md) 维护。本文只交叉引用这些规则,不替代 [commander-collaboration.md](commander-collaboration.md) 中由 [pikasTech/HWLAB#131](https://github.com/pikasTech/HWLAB/issues/131) 固化的一手事实和真实推进边界。 ## AGENTS.md 规则 - `AGENTS.md` 是 agent、指挥官和 runner 的唯一入口,用于快速定位命令、入口和长期参考文档。 -- 与 `AGENTS.md` 同等作用的文档,例如 `README.md`、`docs/reference/README.md`、`CLAUDE.md`,不得作为入口或索引;如果必须存在,只能说明应回到 `AGENTS.md`,避免多套口径漂移。 +- 与 `AGENTS.md` 同等作用的文档,例如 `README.md`、`docs/reference/README.md`、`CLAUDE.md`,不得作为入口或索引;`v0.2` 不保留这类二级入口,历史内容迁入 issue 或吸收到对应 reference。 - 每个命令在 `AGENTS.md` 中只保留一条主索引;参数、背景、判定标准写入链接的 reference 文档。 - `AGENTS.md` 的主标题、章节名和列表摘要必须中文优先;`Agent`、`runner`、`Cloud Workbench`、命令和路径等可保留原文,但要放在中文语境中解释。 - 每个列表项只描述一个功能点,用一句中文概括,不在顶层展开实现细节。 @@ -27,6 +29,7 @@ - 过程文档是历史资料,通常带时间戳,时效性强,不能直接进入长期参考。 - 蒸馏只提取稳定结论、边界、验收标准和禁止事项。 +- 计划、plan、里程碑、阶段迁移、一次性报告和旧 gate 文档全文迁入 GitHub issue;仓库内不再维护 `docs/plan/*.md`。 - 不篡改过程文档;过程记录是原始来源。 - 大文件按滑动窗口阅读,读一段就提炼稳定结论,不等全部读完才更新 reference。 - 新稳定结论覆盖旧冲突结论;旧过程只作为历史来源。 @@ -53,6 +56,7 @@ - `#121` 要求 issue 和长期文档中文化。 - `#122` 要求用户和参谋反馈默认高优先级并挂到 `#7`。 - `#123` 要求 docs-spec 规则固化进 HWLAB 长期参考文档,而不是只在 issue 里引用外部 skill;本文就是该规则的等价本地文档。 +- `#532` 是 `v0.2` 文档治理规格和被删除根文档/过程文档的全文归档入口;当前收敛规格见 [spec-v02-documentation-governance.md](spec-v02-documentation-governance.md)。 - 当前 HWLAB 的 G14 DEV `17666/17667`、G14 PROD `18666/18667`、G14 工作区、M3 证据、Cloud Workbench 默认路由和 PR 工作流,分别由本目录的专项 reference 维护;D601 只作为 legacy 迁移/事故回放口径维护。 ## docs-spec 原文副本 diff --git a/docs/reference/spec-device-pod.md b/docs/reference/spec-device-pod.md index 6b3fff2f..ca1f6eba 100644 --- a/docs/reference/spec-device-pod.md +++ b/docs/reference/spec-device-pod.md @@ -2,6 +2,8 @@ 本文是 HWLAB `v0.2` 正式接入 `device-pod` 的规格说明。`device-pod` 是一个逻辑设备能力单元,不是 Kubernetes Pod 名称,也不是 code agent 本地 profile 文件。正式接入后,profile 定义 `device-pod`,因此 profile 必须由管理员和服务端权威存储管理,不能由 code agent 本地文件决定路由或资源边界。 +实施跟踪见 [pikasTech/HWLAB#533](https://github.com/pikasTech/HWLAB/issues/533),原 `docs/plan/v02-device-pod-spec-migration.md` 和旧 device-pod MVP 计划全文已迁入该 issue 评论。 + 旧的 `device-pod-cli` 本地 profile 闭环只用于 CLI MVP 和真实硬件最小验证。进入正式多用户系统后,所有用户态设备访问必须收敛到: ```text diff --git a/docs/reference/spec-user-access.md b/docs/reference/spec-user-access.md index a5defead..292d714a 100644 --- a/docs/reference/spec-user-access.md +++ b/docs/reference/spec-user-access.md @@ -4,6 +4,8 @@ 本规格与 [spec-device-pod.md](spec-device-pod.md) 配套:用户和权限规格定义谁可以看见、创建和使用 device pod;device-pod 规格定义 profile authority、REST/job 和硬件执行边界。 +实施跟踪见 [pikasTech/HWLAB#531](https://github.com/pikasTech/HWLAB/issues/531),原 `docs/plan/v02-multi-user-migration.md` 迁移计划全文已迁入该 issue 评论。 + ## 在系统中的职责划分 用户和权限管理不是独立微服务,权威实现收敛在 `hwlab-cloud-api`:它负责登录、session、角色、device pod grant、device lease 和 code agent session owner 校验。`hwlab-cloud-web` 只提供浏览器 UI 和同源代理;`hwlab-device-pod` 只执行设备语义;`hwlab-agent-mgr`、`hwlab-agent-worker` 和 Code Agent runtime 只能消费已经由 cloud-api 判断过的 actor/session/device 权限。 @@ -307,7 +309,7 @@ Kubernetes 只做运行时隔离和资源兜底,不承载 HWLAB 用户权限 - code agent 到 device pod 的访问应收敛到 `code agent -> cloud-api -> device-pod`,避免普通 session Pod 直接调用 device pod Service 绕过应用层授权。 - 第一轮不引入 Keycloak、Dex、oauth2-proxy、OpenFGA、Capsule、vCluster、Kyverno 或 service mesh;需要正式外部身份源或集群 admission 兜底时再单独设计。 -当前态、差距和迁移步骤见 [../plan/v02-multi-user-migration.md](../plan/v02-multi-user-migration.md)。 +当前态、差距和迁移步骤已迁入 [pikasTech/HWLAB#531](https://github.com/pikasTech/HWLAB/issues/531) 评论。 ## 测试规格 @@ -332,4 +334,3 @@ Kubernetes 只做运行时隔离和资源兜底,不承载 HWLAB 用户权限 | Code Agent owner 绑定 | 未完全实现 | `agent_sessions` 已存在,owner 字段和鉴权链路仍需落地。 | | device pod 授权模型 | 未完全实现 | grant 语义已定义;当前 device-pod 仍主要是 fake/只读 payload。 | | 不用 Kubernetes 表达用户权限 | 已实现/持续约束 | 规格明确禁止普通用户持有 kubeconfig 或直连 Service 权限。 | - diff --git a/docs/reference/spec-v02-cicd.md b/docs/reference/spec-v02-cicd.md index ac11791e..3c0eefbe 100644 --- a/docs/reference/spec-v02-cicd.md +++ b/docs/reference/spec-v02-cicd.md @@ -2,7 +2,7 @@ 本文是 HWLAB `v0.2` 在 G14 上接入 CI/CD 的长期规格。目标是把 `v0.2` 作为独立加法 lane 接入现有 G14 k3s、Tekton、GitOps 和 Argo CD 体系,同时保持 `G14` DEV/PROD 发布面稳定。 -实施跟踪见 [pikasTech/HWLAB#530](https://github.com/pikasTech/HWLAB/issues/530),阶段计划见 [../plan/hwlab-v02-namespace-cicd.md](../plan/hwlab-v02-namespace-cicd.md)。本文只记录稳定规格、边界和判定标准;不要把一次性执行记录、排障流水账或临时证据写入本文。 +实施跟踪见 [pikasTech/HWLAB#530](https://github.com/pikasTech/HWLAB/issues/530),原 `docs/plan/hwlab-v02-namespace-cicd.md` 阶段计划全文已迁入该 issue 评论。本文只记录稳定规格、边界和判定标准;不要把一次性执行记录、排障流水账或临时证据写入本文。 ## 在系统中的职责划分 @@ -69,7 +69,7 @@ CI/CD 内部由 branch poller、PipelineRun、component planner、BuildKit publi `v0.2` source branch 可以包含: -- 源码、测试、文档和人写计划。 +- 源码、测试、文档、人写配置和模板。 - `deploy/deploy.json` 或等价 lane 配置。 - k8s 模板、render 脚本、CI/CD helper 和 catalog schema。 @@ -195,7 +195,7 @@ GitOps branch 已更新、source branch render 通过、PipelineRun 名称存在 ## 平行 lane 运维边界 -后续新增 `v0.x` 或其他平行 runtime lane 时,优先复用本节的判定顺序和排障边界,避免把一次性补丁沉淀成新的宽泛门禁。本节只保留可复用的运维边界;具体执行记录、排障流水和一次性证据应放在 issue、PR 或 `docs/plan/` 中。 +后续新增 `v0.x` 或其他平行 runtime lane 时,优先复用本节的判定顺序和排障边界,避免把一次性补丁沉淀成新的宽泛门禁。本节只保留可复用的运维边界;具体执行记录、排障流水和一次性证据应放在 issue 或 PR 中。 ### Secret 导入与重启边界 diff --git a/docs/reference/spec-v02-documentation-governance.md b/docs/reference/spec-v02-documentation-governance.md new file mode 100644 index 00000000..ab3a80fd --- /dev/null +++ b/docs/reference/spec-v02-documentation-governance.md @@ -0,0 +1,64 @@ +# v0.2 文档治理规格 + +本文是 HWLAB `v0.2` 文档体系的长期规格。它定义哪些文档可以留在仓库、哪些过程材料必须迁入 GitHub issue、旧 D601/G14 口径如何处理,以及 `docs/` 根目录不得再堆放 Markdown 或 JSON 的收敛规则。 + +实施和历史归档见 [pikasTech/HWLAB#532](https://github.com/pikasTech/HWLAB/issues/532)。本文只记录稳定规则;被迁移文档的全文在 issue 评论中按源路径归档。 + +## 设计目标 + +- `AGENTS.md` 是唯一顶级入口;不再维护根 `README.md` 或 `docs/reference/README.md`。 +- `docs/reference/` 是长期参考唯一目录,只放规格、约束、入口、判定标准和稳定 runbook。 +- `v0.2` 专项长期规格必须使用 `spec-` 前缀,例如 `spec-v02-cicd.md`、`spec-user-access.md`。 +- 计划、里程碑、阶段推进、一次性排障、报告合同和历史验收材料不留在仓库文档树;全文迁入 GitHub issue 后删除源 Markdown。 +- `docs/` 根目录不得直接放 `*.md` 或 `*.json`。机器契约放 `protocol/`、`deploy/` 或源码相邻目录;临时报告放 `/tmp`、`.state` 或 CI artifact。 +- D601、旧 DEV gate、旧 `16666/16667`、M0-M5 里程碑和 simulator/patch-panel 旧规格只作为历史归档,不作为 `v0.2` 当前规格。 + +## 允许的文档形态 + +| 位置 | 允许内容 | 不允许内容 | +| --- | --- | --- | +| `AGENTS.md` | 入口索引、一句话规则、长期参考链接 | 详细设计、计划全文、过程记录、二级 README 口径 | +| `docs/reference/*.md` | 长期规格、稳定边界、判定标准、可复用 runbook | 日期化流水账、阶段计划、迁移 TODO 全文、临时 evidence、旧规格副本 | +| GitHub issue/PR | 计划全文、里程碑拆解、过程记录、一次性排障、执行证据 | 作为长期权威替代 `docs/reference` | +| `protocol/` / `deploy/` | 机器可消费 schema、deploy intent、GitOps 模板 | 人写过程报告、临时 JSON dump | +| `/tmp` / `.state` / CI artifact | 临时报告、运行输出、截图、trace dump | 需要长期复用的规格 | + +## 迁移规则 + +1. 发现 `README.md`、`docs/*.md`、`docs/*.json` 或 `docs/plan/*.md` 时,先判断是否有长期价值。 +2. 有长期价值的,只把稳定结论吸收到对应 `docs/reference/` 权威文档;不要整篇搬入 reference。 +3. 属于计划、里程碑、阶段迁移、报告、一次性排障或历史验收的,全文迁入 GitHub issue body/comment,再删除源文件。 +4. 属于旧规格且与当前 `v0.2` spec 冲突的,直接删除;必要时在新 spec 中用一句话说明旧口径已被替代。 +5. 迁移后的 reference 必须引用相关 issue,尤其是规格尚未完全实现、仍需要 issue 承接实施步骤时。 +6. GitHub issue/PR 写入必须走 UniDesk CLI `bun scripts/cli.ts gh ...`,不能直接用原生 `gh` 或手写 GitHub API。 + +## D601/G14 口径处理 + +- 当前 HWLAB DEV/PROD 真相是 G14 k3s、`G14`/`G14-gitops` 和 `hwlab-dev`/`hwlab-prod`。 +- `v0.2` 真相是 `origin/v0.2`、`v0.2-gitops`、`hwlab-v02` 和 `19666/19667`,权威规格见 [spec-v02-cicd.md](spec-v02-cicd.md)。 +- D601 只允许作为 legacy 事故回放、迁移对照或 Windows 硬件 bridge 背景出现在长期参考中;不得作为当前 `v0.2` 发布、验收或权限规格。 +- 任何根文档或计划文档如果仍把 D601、旧 DEV gate、旧 `main`、旧 `16666/16667` 或 simulator/patch-panel 写成当前规格,应删除或改为引用新 spec。 + +## 本次收敛映射 + +| 被删除来源 | 处理 | +| --- | --- | +| `README.md` | 有效入口信息已由 `AGENTS.md`、[architecture.md](architecture.md)、[dev-runtime-boundary.md](dev-runtime-boundary.md) 和 [spec-v02-services.md](spec-v02-services.md) 承接;全文归档到 #532。 | +| `docs/cloud-web-workbench.md` | 稳定前端约束由 [cloud-workbench.md](cloud-workbench.md) 承接;全文归档到 #532。 | +| `docs/dev-acceptance-matrix.md`、`docs/dev-gate-*`、`docs/dev-evidence-*` | 旧 DEV/D601 gate 和报告材料仅作历史归档;当前边界见 [dev-runtime-boundary.md](dev-runtime-boundary.md)、[MVP-e2e-acceptance.md](MVP-e2e-acceptance.md) 和 [spec-v02-cicd.md](spec-v02-cicd.md)。 | +| `docs/dev-acceptance-checklist.json` | 从 `docs/` 根目录移出;仍被旧 M5 dry-run 使用的机器 fixture 放到 `fixtures/mvp/m5-e2e/dev-acceptance-checklist.json`,历史全文归档到 #532。 | +| `docs/m0-*`、`docs/m1-*`、`docs/m3-*`、`docs/m4-*`、`docs/m5-*`、`docs/operator-runbook.md` | 旧里程碑和 operator 阶段材料迁入 #532;当前 M3 判定见 [m3-loop-rollout-runbook.md](m3-loop-rollout-runbook.md)。 | +| `docs/topology-constraints.md` | simulator/patch-panel 旧拓扑规格与 `v0.2` 裁撤口径冲突;当前服务取舍见 [spec-v02-services.md](spec-v02-services.md)。 | +| `docs/schema-drift-map.md` | 人写摘要归档到 #532;机器 source of truth 仍是 `protocol/schema-drift-map.json`。 | +| `docs/plan/hwlab-v02-namespace-cicd.md` | 全文迁入 [pikasTech/HWLAB#530](https://github.com/pikasTech/HWLAB/issues/530) 评论;长期规格见 [spec-v02-cicd.md](spec-v02-cicd.md)。 | +| `docs/plan/v02-multi-user-migration.md` | 全文迁入 [pikasTech/HWLAB#531](https://github.com/pikasTech/HWLAB/issues/531) 评论;长期规格见 [spec-user-access.md](spec-user-access.md)。 | +| `docs/plan/v02-device-pod-spec-migration.md` 和旧 device-pod MVP plan | 全文迁入 [pikasTech/HWLAB#533](https://github.com/pikasTech/HWLAB/issues/533) 评论;长期规格见 [spec-device-pod.md](spec-device-pod.md)。 | + +## 验收标准 + +- `AGENTS.md` 索引本文,并且不再把 `README.md` 当入口。 +- `find docs -maxdepth 1 -type f \( -name '*.md' -o -name '*.json' \)` 为空。 +- `docs/plan` 不再包含仓库内计划 Markdown;后续计划写入 GitHub issue。 +- `docs/reference/` 中不存在指向已删除根文档或 `docs/plan` 的相对链接。 +- `D601` 只以 legacy/回放/bridge 背景出现在长期参考;不会作为 `v0.2` 当前规格或验收路径。 +- 任何未完成规格都必须引用承接实施的 GitHub issue。 diff --git a/docs/runtime-boundary-guard.md b/docs/runtime-boundary-guard.md deleted file mode 100644 index ada9aac8..00000000 --- a/docs/runtime-boundary-guard.md +++ /dev/null @@ -1,60 +0,0 @@ -# HWLAB Runtime Boundary Guard - -The HWLAB runtime may use UniDesk CI/CD infrastructure and Code Queue -scheduling, but it must not use UniDesk backend, provider-gateway, or -microservice proxy as replacement runtime services. Those systems are external -supporting infrastructure only. - -This guard is intentionally static. It reads repository files and does not -contact the DEV endpoint, deploy to DEV or PROD, read secrets, or restart any -UniDesk or HWLAB runtime process. - -## Boundary Rule - -- HWLAB runtime service identity is the frozen `hwlab-*` service ID set. -- DEV is the only accepted runtime environment for this guard. -- The fixed DEV endpoint is `http://74.48.78.17:16667`. -- The DEV namespace is `hwlab-dev`. -- PROD deployment and PROD acceptance remain disabled. -- UniDesk backend, provider-gateway, and microservice proxy are forbidden - runtime substitutes. - -UniDesk may remain in the control-plane path for CI, CD, and Code Queue -scheduling. It must not terminate HWLAB health, API, gateway, router, tunnel, -agent, simulator, patch-panel, CLI, or skills runtime contracts on behalf of -HWLAB. - -## Checked Artifacts - -The machine-readable fixture is -`protocol/examples/runtime-boundary/guard.dev.json`. It records the expected -DEV-only boundary, frozen service IDs, forbidden substitutes, and paths checked -by `scripts/validate-runtime-boundary.mjs`. - -The validator checks: - -- `deploy/deploy.json` keeps `environment: dev`, `hwlab-dev`, the fixed DEV - endpoint, the complete HWLAB service set, HWLAB image names, and a disabled - PROD profile. -- `deploy/master-edge/health-contract.json` keeps the `frp` D601-to-master - reverse link, HWLAB contract service IDs, and the forbidden substitute list. -- `deploy/k8s/base/workloads.yaml` keeps workload names, labels, container - names, and images under HWLAB service IDs. -- `deploy/k8s/base/services.yaml` keeps Kubernetes service names and labels - under HWLAB service IDs. -- `deploy/k8s/dev/*` keeps the DEV overlay and runtime substitute policy. -- `deploy/k8s/prod/*` keeps PROD as a disabled placeholder only. - -## Validation - -Run: - -```sh -node --check scripts/validate-runtime-boundary.mjs -node scripts/validate-runtime-boundary.mjs -``` - -The script is lightweight and has no package dependency. It fails if a checked -artifact drifts toward a UniDesk runtime substitute, a non-DEV environment, an -unexpected namespace, an unexpected endpoint, or an incomplete HWLAB service -boundary. diff --git a/docs/schema-drift-map.md b/docs/schema-drift-map.md deleted file mode 100644 index caabe96e..00000000 --- a/docs/schema-drift-map.md +++ /dev/null @@ -1,83 +0,0 @@ -# Schema Drift Map - -This document records the naming drift between the protocol schemas, the L1 -cloud-core migration skeleton, the audit chain, the evidence chain, and the -deploy manifest example. It is a closure artifact for M0 audit work only. - -## Scope - -- protocol: `protocol/schemas/*.json` -- DB migration: `internal/db/migrations/0001_cloud_core_skeleton.sql` -- audit event: `protocol/schemas/audit-event.schema.json` -- evidence chain: `protocol/evidence-chain.md` -- evidence record: `protocol/schemas/evidence-record.schema.json` -- deploy manifest: `deploy/deploy.json` -- deploy schema: `deploy/deploy.schema.json` - -The source of truth for machine checks is `protocol/schema-drift-map.json`. -This page is the human summary. - -## Aligned Fields - -The following IDs are already aligned at the protocol layer and are carried -through the current examples: - -- `projectId` -- `operationId` -- `auditId` -- `traceId` -- `evidenceId` -- `serviceId` -- `environment` -- `resourceId` -- `sessionId` family: `gatewaySessionId`, `agentSessionId`, `workerSessionId` -- evidence chain roots: `chainId`, `schemaVersion`, `scenario`, `title` -- evidence chain collections: `hardwareOperation`, `auditEvents`, `traceEvents`, `evidenceRecords` - -## Known Gaps - -These are the places where the L1 skeleton still drifts from protocol naming -and needs a real persistence fix before production data is written: - -- `audit_events.request_id` should become `traceId` -- `audit_events.actor` should split into `actorType` and `actorId` -- `audit_events.source` should become `actorId` -- `audit_events.operation` should become `action` -- `audit_events.target` should split into `targetType` and `targetId` -- `audit_events.timestamp` should become `occurredAt` -- `evidence_records.evidence_type` should become `kind` -- `evidence_records.metadata_json.sha256` needs a first-class persisted target -- `hardware_operations.operation_json.resourceId` needs a tested mapping path -- `hardware_operations.operation_json.capabilityId` needs a tested mapping path - -## Evidence Chain - -The evidence chain fixture set is already internally coherent. It binds the -root IDs to the protocol schemas without changing the storage model: - -- `chainId` anchors the fixture -- `operationId` ties hardware, audit, trace, and evidence together -- `traceId` threads through audit and trace events and is copied into evidence - metadata -- `gatewaySessionId`, `agentSessionId`, and `workerSessionId` stay consistent - where they appear -- `hardwareOperation`, `auditEvents`, `traceEvents`, and `evidenceRecords` - each point back to their schema counterparts - -## Impact - -The current examples and validators are sufficient for audit evidence and MVP -closure, but they are not a persistence contract. The drift map is intentionally -read-only so later implementation work can pick one of two paths: - -1. rename the real storage columns to match the protocol, or -2. keep the current skeleton and add a tested mapping layer before writes. - -## Validation - -Run: - -```sh -node --check scripts/validate-schema-drift-map.mjs -node scripts/validate-schema-drift-map.mjs -``` diff --git a/docs/topology-constraints.md b/docs/topology-constraints.md deleted file mode 100644 index b092b46b..00000000 --- a/docs/topology-constraints.md +++ /dev/null @@ -1,46 +0,0 @@ -# Topology Constraint Validator - -`scripts/validate-topology-constraints.mjs` is a local contract validator for -the MVP topology rules that were prose-only after M0. It reads fixtures from -`fixtures/mvp/topology-constraints/` and does not call DEV, PROD, real -hardware, databases, secrets, or service endpoints. - -Run it locally: - -```sh -node scripts/validate-topology-constraints.mjs -``` - -## Contract - -- The fixture must describe a DEV topology with `hwlab-box-simu`, - `hwlab-gateway-simu`, and one active `hwlab-patch-panel` status object. -- Cross-device propagation must remain `patch-panel-only`. Box simulator local - loopback is not a valid substitute for cross-device sync. -- Wiring endpoints must reference known box resources and declared ports. -- Active wiring configs must not contain resource-level directed cycles. -- Active config exclusivity is enforced per project and resource group. The - resource group is `wiringConfig.constraints.resourceGroupId` when present; - otherwise it is the sorted set of resources touched by the config. -- A resource group may have only one active wiring config unless the active - patch panel reports `metadata.activeConfigOverride`. -- A patch-panel override is valid only when it is reported by an active - `hwlab-patch-panel`, preserves `patch-panel-only`, lists exactly the active - config ids for the resource group, gives a non-empty reason, and selects the - same `wiringConfigId` as the patch panel status object. -- The patch panel's `activeConnections` must match the selected wiring config. - -## Fixtures - -| Fixture | Expected result | Purpose | -| --- | --- | --- | -| `valid-topology.json` | valid | One active acyclic config routed by `hwlab-patch-panel`. | -| `invalid-cycle.json` | `wiring_cycle` | Detects a directed resource cycle in active wiring. | -| `invalid-multiple-active-configs.json` | `active_config_exclusivity` | Rejects multiple active configs in the same resource group without an override. | -| `invalid-patch-panel-override.json` | `patch_panel_override_invalid` | Rejects a patch-panel override whose selected config disagrees with patch panel state. | - -Each fixture stores `expectedValidation` beside the topology. The validator -passes only when valid fixtures produce no violations and invalid fixtures -produce the expected violation code set. This makes the validator a pre-DEV -contract for the future real M3 flow while keeping the current M3 hardware loop -smoke focused on local patch-panel behavior. diff --git a/docs/dev-acceptance-checklist.json b/fixtures/mvp/m5-e2e/dev-acceptance-checklist.json similarity index 98% rename from docs/dev-acceptance-checklist.json rename to fixtures/mvp/m5-e2e/dev-acceptance-checklist.json index 6e6ebbcf..5e8d57fe 100644 --- a/docs/dev-acceptance-checklist.json +++ b/fixtures/mvp/m5-e2e/dev-acceptance-checklist.json @@ -1,6 +1,6 @@ { - "$schema": "https://hwlab.pikastech.local/docs/dev-acceptance-checklist.schema.json", - "$id": "https://hwlab.pikastech.local/docs/dev-acceptance-checklist.json", + "$schema": "https://hwlab.pikastech.local/fixtures/mvp/m5-e2e/dev-acceptance-checklist.schema.json", + "$id": "https://hwlab.pikastech.local/fixtures/mvp/m5-e2e/dev-acceptance-checklist.json", "matrixVersion": "v1", "issue": "pikasTech/HWLAB#22", "environment": "dev", @@ -434,7 +434,7 @@ { "id": "static-contract-parse", "order": 1, - "probe": "Parse docs/dev-acceptance-checklist.json and confirm docs/dev-acceptance-matrix.md exists.", + "probe": "Parse fixtures/mvp/m5-e2e/dev-acceptance-checklist.json and confirm docs/reference/MVP-e2e-acceptance.md exists.", "successCriteria": "Checklist JSON parses and markdown file is present.", "failureCriteria": "Missing file or invalid JSON.", "blockerClass": "contract_blocker" diff --git a/fixtures/mvp/m5-e2e/dry-run-plan.json b/fixtures/mvp/m5-e2e/dry-run-plan.json index 5aba8b26..0523db2f 100644 --- a/fixtures/mvp/m5-e2e/dry-run-plan.json +++ b/fixtures/mvp/m5-e2e/dry-run-plan.json @@ -13,8 +13,8 @@ "allowSecrets": false, "allowedSourceGlobs": [ "protocol/**", - "docs/dev-acceptance-checklist.json", - "docs/dev-acceptance-matrix.md", + "fixtures/mvp/m5-e2e/dev-acceptance-checklist.json", + "docs/reference/MVP-e2e-acceptance.md", "fixtures/mvp/runtime.json", "fixtures/mvp/m5-e2e/**" ], diff --git a/internal/mvp-gate/summary.mjs b/internal/mvp-gate/summary.mjs index 3490e8c6..3eb30cfa 100644 --- a/internal/mvp-gate/summary.mjs +++ b/internal/mvp-gate/summary.mjs @@ -83,18 +83,12 @@ function defaultMvpGateReport() { sourceContract: { status: "pass", documents: [ - "docs/dev-gate-report.md", - "docs/dev-acceptance-matrix.md", - "docs/m0-contract-audit.md", - "docs/m1-local-smoke.md", - "docs/m2-dev-deploy-smoke.md", - "docs/m3-hardware-loop.md", - "docs/m4-agent-loop.md", - "docs/m5-mvp-e2e.md", - "docs/runtime-boundary-guard.md", - "docs/topology-constraints.md", - "docs/artifact-catalog.md", - "docs/schema-drift-map.md", + "docs/reference/MVP-e2e-acceptance.md", + "docs/reference/m3-loop-rollout-runbook.md", + "docs/reference/dev-runtime-boundary.md", + "docs/reference/spec-v02-documentation-governance.md", + "docs/reference/g14-gitops-cicd.md", + "docs/reference/spec-v02-services.md", "protocol/README.md", "protocol/audit.md", "protocol/evidence-chain.md", diff --git a/protocol/examples/m0-contract/deploy-manifest.dev.json b/protocol/examples/m0-contract/deploy-manifest.dev.json index 755b7431..5f6ecbdd 100644 --- a/protocol/examples/m0-contract/deploy-manifest.dev.json +++ b/protocol/examples/m0-contract/deploy-manifest.dev.json @@ -49,6 +49,14 @@ "profile": "dev", "replicas": 1 }, + { + "serviceId": "hwlab-device-pod", + "image": "ghcr.io/pikastech/hwlab-device-pod:6509a35", + "namespace": "hwlab-dev", + "healthPath": "/healthz", + "profile": "dev", + "replicas": 1 + }, { "serviceId": "hwlab-gateway", "image": "ghcr.io/pikastech/hwlab-gateway:6509a35", diff --git a/protocol/examples/m0-contract/service-ids.json b/protocol/examples/m0-contract/service-ids.json index df7f67b8..84224ef7 100644 --- a/protocol/examples/m0-contract/service-ids.json +++ b/protocol/examples/m0-contract/service-ids.json @@ -6,6 +6,7 @@ "hwlab-cloud-web", "hwlab-agent-mgr", "hwlab-agent-worker", + "hwlab-device-pod", "hwlab-gateway", "hwlab-gateway-simu", "hwlab-box-simu", diff --git a/scripts/artifact-publish.mjs b/scripts/artifact-publish.mjs index 83faf2e9..d503d409 100644 --- a/scripts/artifact-publish.mjs +++ b/scripts/artifact-publish.mjs @@ -1972,11 +1972,10 @@ function createReport({ args, repo, commitId, shortCommit, mode, services, artif sourceContract: { status: fatalBlocked ? "blocked" : "pass", documents: [ - "docs/dev-acceptance-matrix.md", - "docs/m0-contract-audit.md", - "docs/artifact-catalog.md", + "docs/reference/MVP-e2e-acceptance.md", + "docs/reference/spec-v02-documentation-governance.md", "docs/reference/g14-gitops-cicd.md", - "docs/dev-base-image-preflight.md" + "docs/reference/spec-v02-cicd.md" ], summary: `${environment} artifact publish evidence; runtime acceptance stays separate from artifact publication.` }, diff --git a/scripts/dev-m3-hardware-loop-smoke.mjs b/scripts/dev-m3-hardware-loop-smoke.mjs index 0091ef51..c26ed29e 100644 --- a/scripts/dev-m3-hardware-loop-smoke.mjs +++ b/scripts/dev-m3-hardware-loop-smoke.mjs @@ -1415,8 +1415,8 @@ function baseReport({ commitId, observedAt }) { sourceContract: { status: "pass", documents: [ - "docs/dev-acceptance-matrix.md", - "docs/m3-hardware-loop.md", + "docs/reference/MVP-e2e-acceptance.md", + "docs/reference/m3-loop-rollout-runbook.md", "fixtures/mvp/m3-hardware-loop/topology.json" ], summary: "Source contracts define DEV-only M3 simulator wiring and prohibit fixture output as live evidence." @@ -1463,8 +1463,8 @@ function baseReport({ commitId, observedAt }) { status: "pass", summary: "DEV M3 smoke contract files were readable before live probing.", evidence: [ - "docs/dev-acceptance-matrix.md", - "docs/m3-hardware-loop.md" + "docs/reference/MVP-e2e-acceptance.md", + "docs/reference/m3-loop-rollout-runbook.md" ] }, { @@ -1611,8 +1611,8 @@ function addNotRunM3Checks(report, reason) { } async function ensureContractFiles() { - await access(path.join(repoRoot, "docs/dev-acceptance-matrix.md")); - await access(path.join(repoRoot, "docs/m3-hardware-loop.md")); + await access(path.join(repoRoot, "docs/reference/MVP-e2e-acceptance.md")); + await access(path.join(repoRoot, "docs/reference/m3-loop-rollout-runbook.md")); await access(path.join(repoRoot, "fixtures/mvp/m3-hardware-loop/topology.json")); } diff --git a/scripts/dev-m4-agent-loop-smoke.mjs b/scripts/dev-m4-agent-loop-smoke.mjs index 1b2f79dc..000f9fdc 100644 --- a/scripts/dev-m4-agent-loop-smoke.mjs +++ b/scripts/dev-m4-agent-loop-smoke.mjs @@ -35,7 +35,7 @@ import { const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const fixedNow = () => "2026-05-22T00:00:00.000Z"; -const requiredDocs = ["docs/dev-acceptance-matrix.md", "docs/dev-m4-agent-loop.md"]; +const requiredDocs = ["docs/reference/MVP-e2e-acceptance.md", "docs/reference/code-agent-chat-readiness.md"]; const reportPath = tempReportPath("dev-m4-agent-loop.json"); const preflightCommand = "node scripts/dev-m4-agent-loop-smoke.mjs --live --confirm-dev --confirmed-non-production"; const dryRunCommand = "node scripts/dev-m4-agent-loop-smoke.mjs --dry-run"; diff --git a/scripts/m5-mvp-e2e-dry-run.mjs b/scripts/m5-mvp-e2e-dry-run.mjs index dbd384fd..da3e7b44 100644 --- a/scripts/m5-mvp-e2e-dry-run.mjs +++ b/scripts/m5-mvp-e2e-dry-run.mjs @@ -9,8 +9,8 @@ import { DEV_ENDPOINT, ENVIRONMENT_DEV } from "../internal/protocol/index.mjs"; const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const planPath = "fixtures/mvp/m5-e2e/dry-run-plan.json"; -const checklistPath = "docs/dev-acceptance-checklist.json"; -const matrixPath = "docs/dev-acceptance-matrix.md"; +const checklistPath = "fixtures/mvp/m5-e2e/dev-acceptance-checklist.json"; +const matrixPath = "docs/reference/MVP-e2e-acceptance.md"; const runtimePath = "fixtures/mvp/runtime.json"; const contractPath = "protocol/mvp-e2e-contract.md"; const commonSchemaPath = "protocol/schemas/common.json"; @@ -598,7 +598,7 @@ const [plan, checklist, runtime, contract, matrix, commonSchema] = await Promise serviceIds = commonSchema.$defs.serviceId.enum; serviceIdSet = new Set(serviceIds); -assert.equal(matrix.includes("HWLAB DEV Acceptance Matrix"), true, "acceptance matrix exists"); +assert.equal(matrix.includes("HWLAB MVP E2E"), true, "MVP E2E reference exists"); assertObjectHasOnlyDryRunSafety(plan); assertEndpointFreeze(plan, checklist, runtime, contract); const artifacts = assertArtifacts(plan, checklist); diff --git a/scripts/src/dev-cloud-workbench-smoke-lib.mjs b/scripts/src/dev-cloud-workbench-smoke-lib.mjs index ae8dbc66..300f8578 100644 --- a/scripts/src/dev-cloud-workbench-smoke-lib.mjs +++ b/scripts/src/dev-cloud-workbench-smoke-lib.mjs @@ -1384,7 +1384,6 @@ function layoutSourceContract() { return { status: "pass", documents: [ - "docs/cloud-web-workbench.md", "docs/reference/cloud-workbench.md", "docs/reference/code-agent-chat-readiness.md" ], @@ -1518,7 +1517,6 @@ function baseReport({ sourceContract: { status: "pass", documents: [ - "docs/cloud-web-workbench.md", "docs/reference/cloud-workbench.md", "docs/reference/code-agent-chat-readiness.md" ], @@ -2704,8 +2702,7 @@ function findHelpMarkdownFiles() { "web/hwlab-cloud-web/help.md", "web/hwlab-cloud-web/help/README.md", "web/hwlab-cloud-web/help/index.md", - "docs/dev-cloud-workbench-help.md", - "docs/cloud-web-workbench.md" + "docs/reference/cloud-workbench.md" ]; return files.filter((relativePath) => fs.existsSync(path.join(repoRoot, relativePath))); } diff --git a/scripts/src/dev-edge-health-smoke-lib.mjs b/scripts/src/dev-edge-health-smoke-lib.mjs index a42cfdac..1e84972c 100644 --- a/scripts/src/dev-edge-health-smoke-lib.mjs +++ b/scripts/src/dev-edge-health-smoke-lib.mjs @@ -165,9 +165,9 @@ async function createDevGateReport(edgeHealth) { sourceContract: { status: "pass", documents: [ - "docs/dev-acceptance-matrix.md", - "docs/m0-contract-audit.md", - "docs/dev-edge-health.md", + "docs/reference/dev-runtime-boundary.md", + "docs/reference/spec-v02-documentation-governance.md", + "docs/reference/g14-gitops-cicd.md", "deploy/frp/README.md", "deploy/master-edge/README.md" ], diff --git a/scripts/src/dev-evidence-blocker-aggregator.mjs b/scripts/src/dev-evidence-blocker-aggregator.mjs index 57101d6a..3936e785 100644 --- a/scripts/src/dev-evidence-blocker-aggregator.mjs +++ b/scripts/src/dev-evidence-blocker-aggregator.mjs @@ -307,7 +307,7 @@ function buildEvidence() { category: "contract", level: "SOURCE", status: "pass", - sources: ["protocol/README.md", "docs/dev-acceptance-matrix.md"], + sources: ["protocol/README.md", "docs/reference/MVP-e2e-acceptance.md"], commands: ["node scripts/validate-contract.mjs"], summary: "Frozen contracts remain the source-ready baseline." }), diff --git a/scripts/validate-m0-contract.mjs b/scripts/validate-m0-contract.mjs index f33ec468..5e43193f 100644 --- a/scripts/validate-m0-contract.mjs +++ b/scripts/validate-m0-contract.mjs @@ -14,7 +14,7 @@ import { const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const examplesDir = "protocol/examples/m0-contract"; -const auditDocPath = "docs/m0-contract-audit.md"; +const auditDocPath = "docs/reference/spec-v02-documentation-governance.md"; const timestampPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/; const idPattern = /^[a-z][a-z0-9]*_[A-Za-z0-9._:-]+$/; @@ -226,16 +226,13 @@ function assertDeployManifest(doc) { async function assertAuditMarkdown() { const doc = await readFile(path.join(repoRoot, auditDocPath), "utf8"); for (const needle of [ - "# M0 Contract Audit", - "## Audit Result", - "## Coverage Matrix", - "## Rework Risk Register", - "## Validation" + "# v0.2 文档治理规格", + "docs/m0-*", + "旧里程碑", + "#532" ]) { assert.ok(doc.includes(needle), `${auditDocPath} missing ${needle}`); } - assert.ok(doc.includes("Blocker"), `${auditDocPath} must classify blocker risks`); - assert.ok(doc.includes("Enhancement"), `${auditDocPath} must classify enhancement risks`); } const examples = await loadExamples();