From 201bdee372ce48c560d32ec4fb59500cd560e126 Mon Sep 17 00:00:00 2001 From: Antigravity Date: Tue, 6 Oct 2026 14:12:58 +0000 Subject: [PATCH] Use Gitea Releases for installation and ship VS Code highlighting --- .gitignore | 2 + .trellis/spec/backend/directory-structure.md | 4 +- .trellis/spec/backend/quality-guidelines.md | 6 +- .../spec/backend/toolchain-and-library.md | 12 +- .../tasks/09-04-dever-language-mvp/design.md | 793 ------- .../09-04-dever-language-mvp/implement.md | 819 -------- .../tasks/09-04-dever-language-mvp/prd.md | 990 --------- .../research/package-distribution.md | 51 - .../research/runtime-dependencies.md | 55 - .../tasks/09-04-dever-language-mvp/task.json | 38 - .../check.jsonl | 0 .../implement.jsonl | 0 .../prd.md | 72 - .../research/cross-compilation.md | 35 - .../research/distribution-licensing.md | 23 - .../research/native-backend-options.md | 104 - .../task.json | 28 - .../tasks/09-12-http2-performance/check.jsonl | 3 - .../tasks/09-12-http2-performance/design.md | 84 - .../09-12-http2-performance/implement.jsonl | 3 - .../09-12-http2-performance/implement.md | 50 - .trellis/tasks/09-12-http2-performance/prd.md | 40 - .../research/current-benchmark-and-h2-api.md | 31 - .../tasks/09-12-http2-performance/task.json | 26 - .trellis/tasks/09-12-http2/check.jsonl | 4 - .trellis/tasks/09-12-http2/design.md | 21 - .trellis/tasks/09-12-http2/implement.jsonl | 5 - .trellis/tasks/09-12-http2/implement.md | 49 - .trellis/tasks/09-12-http2/prd.md | 16 - .trellis/tasks/09-12-http2/task.json | 26 - .../09-12-runtime-performance-p2/check.jsonl | 3 - .../09-12-runtime-performance-p2/design.md | 11 - .../implement.jsonl | 4 - .../09-12-runtime-performance-p2/implement.md | 21 - .../tasks/09-12-runtime-performance-p2/prd.md | 12 - .../09-12-runtime-performance-p2/task.json | 26 - .../09-12-runtime-performance/check.jsonl | 1 - .../tasks/09-12-runtime-performance/design.md | 9 - .../09-12-runtime-performance/implement.jsonl | 2 - .../09-12-runtime-performance/implement.md | 18 - .../tasks/09-12-runtime-performance/prd.md | 14 - .../tasks/09-12-runtime-performance/task.json | 26 - .trellis/tasks/09-13-typed-orm/check.jsonl | 7 - .trellis/tasks/09-13-typed-orm/design.md | 409 ---- .../tasks/09-13-typed-orm/implement.jsonl | 10 - .trellis/tasks/09-13-typed-orm/implement.md | 297 --- .trellis/tasks/09-13-typed-orm/prd.md | 211 -- .../research/architecture-options.md | 76 - .../research/driver-selection.md | 39 - .../09-13-typed-orm/research/field-types.md | 192 -- .../research/go-orm-reference.md | 45 - .../research/implicit-suspension.md | 48 - .../research/migration-practices.md | 20 - .../09-13-typed-orm/research/query-api.md | 199 -- .../research/schema-change-matrix.md | 90 - .trellis/tasks/09-13-typed-orm/task.json | 26 - .../09-19-application-testing/check.jsonl | 8 - .../tasks/09-19-application-testing/design.md | 143 -- .../09-19-application-testing/implement.jsonl | 11 - .../09-19-application-testing/implement.md | 123 -- .../tasks/09-19-application-testing/prd.md | 101 - .../tasks/09-19-application-testing/task.json | 28 - .trellis/tasks/09-20-durable-jobs/check.jsonl | 6 - .trellis/tasks/09-20-durable-jobs/design.md | 100 - .../tasks/09-20-durable-jobs/implement.jsonl | 5 - .../tasks/09-20-durable-jobs/implement.md | 127 -- .trellis/tasks/09-20-durable-jobs/prd.md | 50 - .../research/implementation-map.md | 109 - .trellis/tasks/09-20-durable-jobs/task.json | 26 - .trellis/tasks/09-20-port-adapter/check.jsonl | 3 - .trellis/tasks/09-20-port-adapter/design.md | 47 - .../tasks/09-20-port-adapter/implement.jsonl | 3 - .../tasks/09-20-port-adapter/implement.md | 68 - .trellis/tasks/09-20-port-adapter/prd.md | 42 - .../research/implementation-map.md | 138 -- .trellis/tasks/09-20-port-adapter/task.json | 26 - .../tasks/09-20-production-api/check.jsonl | 3 - .trellis/tasks/09-20-production-api/design.md | 130 -- .../09-20-production-api/implement.jsonl | 3 - .../tasks/09-20-production-api/implement.md | 173 -- .trellis/tasks/09-20-production-api/prd.md | 86 - .trellis/tasks/09-20-production-api/task.json | 26 - .../check.jsonl | 3 - .../design.md | 113 - .../implement.jsonl | 4 - .../implement.md | 90 - .../prd.md | 102 - .../task.json | 34 - .../09-20-secure-data-contracts/check.jsonl | 3 - .../09-20-secure-data-contracts/design.md | 29 - .../implement.jsonl | 4 - .../09-20-secure-data-contracts/implement.md | 71 - .../tasks/09-20-secure-data-contracts/prd.md | 37 - .../research/secure-contracts-source-map.md | 70 - .../09-20-secure-data-contracts/task.json | 26 - .../tasks/09-20-time-typed-codec/check.jsonl | 3 - .../tasks/09-20-time-typed-codec/design.md | 28 - .../09-20-time-typed-codec/implement.jsonl | 3 - .../tasks/09-20-time-typed-codec/implement.md | 64 - .trellis/tasks/09-20-time-typed-codec/prd.md | 37 - .../research/time-wire-source-map.md | 81 - .../tasks/09-20-time-typed-codec/task.json | 26 - .../tasks/09-28-shared-toolchain/check.jsonl | 2 - .../tasks/09-28-shared-toolchain/design.md | 86 - .../09-28-shared-toolchain/implement.jsonl | 2 - .../tasks/09-28-shared-toolchain/implement.md | 46 - .trellis/tasks/09-28-shared-toolchain/prd.md | 81 - .../tasks/09-28-shared-toolchain/task.json | 26 - .../09-29-build-cache-storage/check.jsonl | 4 - .../tasks/09-29-build-cache-storage/design.md | 76 - .../09-29-build-cache-storage/implement.jsonl | 4 - .../09-29-build-cache-storage/implement.md | 67 - .../tasks/09-29-build-cache-storage/prd.md | 74 - .../research/cache-boundaries.md | 14 - .../tasks/09-29-build-cache-storage/task.json | 26 - .../09-29-external-lib-ecosystems/check.jsonl | 3 - .../09-29-external-lib-ecosystems/design.md | 23 - .../implement.jsonl | 4 - .../implement.md | 42 - .../09-29-external-lib-ecosystems/prd.md | 37 - .../09-29-external-lib-ecosystems/task.json | 26 - .../09-29-external-lib-packaging/check.jsonl | 4 - .../09-29-external-lib-packaging/design.md | 21 - .../implement.jsonl | 4 - .../09-29-external-lib-packaging/implement.md | 49 - .../tasks/09-29-external-lib-packaging/prd.md | 36 - .../09-29-external-lib-packaging/task.json | 26 - .../09-29-external-lib-protocol/check.jsonl | 4 - .../09-29-external-lib-protocol/design.md | 23 - .../implement.jsonl | 4 - .../09-29-external-lib-protocol/implement.md | 40 - .../tasks/09-29-external-lib-protocol/prd.md | 32 - .../09-29-external-lib-protocol/task.json | 26 - .../tasks/09-29-external-libs/check.jsonl | 4 - .trellis/tasks/09-29-external-libs/design.md | 62 - .../tasks/09-29-external-libs/implement.jsonl | 5 - .../tasks/09-29-external-libs/implement.md | 33 - .trellis/tasks/09-29-external-libs/prd.md | 77 - .trellis/tasks/09-29-external-libs/task.json | 30 - .../check.jsonl | 12 - .../design.md | 39 - .../implement.jsonl | 14 - .../implement.md | 890 -------- .../09-29-language-production-closure/prd.md | 93 - .../research/apparmor-nonroot.md | 40 - .../research/ecosystem-closure.md | 125 -- .../research/ecosystem-pack-inputs.md | 95 - .../research/linux-ci-scope.md | 147 -- .../research/native-pack-production-inputs.md | 71 - .../task.json | 26 - .../tasks/10-05-install-entry/check.jsonl | 2 - .trellis/tasks/10-05-install-entry/design.md | 19 - .../tasks/10-05-install-entry/implement.jsonl | 3 - .../tasks/10-05-install-entry/implement.md | 83 - .trellis/tasks/10-05-install-entry/prd.md | 38 - .trellis/tasks/10-05-install-entry/task.json | 26 - .../2026-09/00-bootstrap-guidelines/prd.md | 19 - .../2026-09/00-bootstrap-guidelines/task.json | 28 - .../2026-09/09-09-markdown-source/check.jsonl | 1 - .../2026-09/09-09-markdown-source/design.md | 17 - .../09-09-markdown-source/implement.jsonl | 1 - .../09-09-markdown-source/implement.md | 24 - .../2026-09/09-09-markdown-source/prd.md | 25 - .../research/source-flow.md | 8 - .../2026-09/09-09-markdown-source/task.json | 26 - .../09-13-http2-ceiling-soak/check.jsonl | 3 - .../09-13-http2-ceiling-soak/design.md | 70 - .../09-13-http2-ceiling-soak/implement.jsonl | 3 - .../09-13-http2-ceiling-soak/implement.md | 32 - .../2026-09/09-13-http2-ceiling-soak/prd.md | 42 - .../research/client-bottleneck.md | 27 - .../09-13-http2-ceiling-soak/task.json | 26 - .../check.jsonl | 3 - .../09-18-cms-dual-source-contracts/design.md | 26 - .../implement.jsonl | 3 - .../implement.md | 38 - .../09-18-cms-dual-source-contracts/prd.md | 18 - .../09-18-cms-dual-source-contracts/task.json | 26 - .../09-20-large-cms-acceptance/check.jsonl | 3 - .../09-20-large-cms-acceptance/design.md | 24 - .../implement.jsonl | 4 - .../09-20-large-cms-acceptance/implement.md | 40 - .../2026-10/09-20-large-cms-acceptance/prd.md | 25 - .../09-20-large-cms-acceptance/task.json | 26 - .../10-04-developer-onboarding/check.jsonl | 1 - .../10-04-developer-onboarding/design.md | 9 - .../implement.jsonl | 1 - .../10-04-developer-onboarding/implement.md | 34 - .../2026-10/10-04-developer-onboarding/prd.md | 16 - .../10-04-developer-onboarding/task.json | 26 - .../10-04-external-command/check.jsonl | 3 - .../2026-10/10-04-external-command/design.md | 36 - .../10-04-external-command/implement.jsonl | 4 - .../10-04-external-command/implement.md | 56 - .../2026-10/10-04-external-command/prd.md | 33 - .../2026-10/10-04-external-command/task.json | 26 - .../10-04-linux-arm64-cross-build/check.jsonl | 2 - .../10-04-linux-arm64-cross-build/design.md | 25 - .../implement.jsonl | 4 - .../implement.md | 61 - .../10-04-linux-arm64-cross-build/prd.md | 33 - .../10-04-linux-arm64-cross-build/task.json | 26 - .../10-04-slim-distribution/check.jsonl | 5 - .../2026-10/10-04-slim-distribution/design.md | 37 - .../10-04-slim-distribution/implement.jsonl | 8 - .../10-04-slim-distribution/implement.md | 57 - .../2026-10/10-04-slim-distribution/prd.md | 33 - .../10-04-slim-distribution/research/libs.md | 159 -- .../research/release.md | 101 - .../2026-10/10-04-slim-distribution/task.json | 26 - AGENTS.md | 2 +- Cargo.lock | 12 +- Cargo.toml | 2 +- IMPLEMENTATION.md | 2 +- LANGUAGE.md | 8 +- README.md | 186 +- crates/dever-cli/src/toolchain/launcher.rs | 9 +- crates/dever-cli/src/toolchain/release.rs | 18 +- .../dever-cli/src/toolchain/release_source.rs | 225 +- editor/vscode/.gitignore | 2 + editor/vscode/.vscodeignore | 5 + editor/vscode/README.md | 32 + editor/vscode/language-configuration.json | 18 + editor/vscode/package-lock.json | 1872 +++++++++++++++++ editor/vscode/package.json | 56 + .../syntaxes/dever-markdown.tmLanguage.json | 31 + editor/vscode/syntaxes/dever.tmLanguage.json | 95 + install | 92 +- sdk/README.md | 2 - sdk/native-release.md | 303 --- skills/SKILL.md | 2 +- skills/assets/template/README.md | 2 +- skills/references/development.md | 2 +- skills/references/install.md | 58 +- test/ci/README.md | 2 +- test/dever-cli-tests/release_source.rs | 335 ++- .../fixtures/core/complete_package.dever | 150 ++ test/dever-tests/tests/core_semantics.rs | 12 +- test/dever-tests/tests/formatter.rs | 5 +- test/dever-tests/tests/syntax_and_format.rs | 5 +- test/editor-vscode/highlight.test.cjs | 264 +++ test/onboarding/test_installer.py | 101 +- test/onboarding/verify_prepared_release.py | 25 +- 243 files changed, 3289 insertions(+), 12521 deletions(-) delete mode 100644 .trellis/tasks/09-04-dever-language-mvp/design.md delete mode 100644 .trellis/tasks/09-04-dever-language-mvp/implement.md delete mode 100644 .trellis/tasks/09-04-dever-language-mvp/prd.md delete mode 100644 .trellis/tasks/09-04-dever-language-mvp/research/package-distribution.md delete mode 100644 .trellis/tasks/09-04-dever-language-mvp/research/runtime-dependencies.md delete mode 100644 .trellis/tasks/09-04-dever-language-mvp/task.json delete mode 100644 .trellis/tasks/09-06-private-compiler-distribution/check.jsonl delete mode 100644 .trellis/tasks/09-06-private-compiler-distribution/implement.jsonl delete mode 100644 .trellis/tasks/09-06-private-compiler-distribution/prd.md delete mode 100644 .trellis/tasks/09-06-private-compiler-distribution/research/cross-compilation.md delete mode 100644 .trellis/tasks/09-06-private-compiler-distribution/research/distribution-licensing.md delete mode 100644 .trellis/tasks/09-06-private-compiler-distribution/research/native-backend-options.md delete mode 100644 .trellis/tasks/09-06-private-compiler-distribution/task.json delete mode 100644 .trellis/tasks/09-12-http2-performance/check.jsonl delete mode 100644 .trellis/tasks/09-12-http2-performance/design.md delete mode 100644 .trellis/tasks/09-12-http2-performance/implement.jsonl delete mode 100644 .trellis/tasks/09-12-http2-performance/implement.md delete mode 100644 .trellis/tasks/09-12-http2-performance/prd.md delete mode 100644 .trellis/tasks/09-12-http2-performance/research/current-benchmark-and-h2-api.md delete mode 100644 .trellis/tasks/09-12-http2-performance/task.json delete mode 100644 .trellis/tasks/09-12-http2/check.jsonl delete mode 100644 .trellis/tasks/09-12-http2/design.md delete mode 100644 .trellis/tasks/09-12-http2/implement.jsonl delete mode 100644 .trellis/tasks/09-12-http2/implement.md delete mode 100644 .trellis/tasks/09-12-http2/prd.md delete mode 100644 .trellis/tasks/09-12-http2/task.json delete mode 100644 .trellis/tasks/09-12-runtime-performance-p2/check.jsonl delete mode 100644 .trellis/tasks/09-12-runtime-performance-p2/design.md delete mode 100644 .trellis/tasks/09-12-runtime-performance-p2/implement.jsonl delete mode 100644 .trellis/tasks/09-12-runtime-performance-p2/implement.md delete mode 100644 .trellis/tasks/09-12-runtime-performance-p2/prd.md delete mode 100644 .trellis/tasks/09-12-runtime-performance-p2/task.json delete mode 100644 .trellis/tasks/09-12-runtime-performance/check.jsonl delete mode 100644 .trellis/tasks/09-12-runtime-performance/design.md delete mode 100644 .trellis/tasks/09-12-runtime-performance/implement.jsonl delete mode 100644 .trellis/tasks/09-12-runtime-performance/implement.md delete mode 100644 .trellis/tasks/09-12-runtime-performance/prd.md delete mode 100644 .trellis/tasks/09-12-runtime-performance/task.json delete mode 100644 .trellis/tasks/09-13-typed-orm/check.jsonl delete mode 100644 .trellis/tasks/09-13-typed-orm/design.md delete mode 100644 .trellis/tasks/09-13-typed-orm/implement.jsonl delete mode 100644 .trellis/tasks/09-13-typed-orm/implement.md delete mode 100644 .trellis/tasks/09-13-typed-orm/prd.md delete mode 100644 .trellis/tasks/09-13-typed-orm/research/architecture-options.md delete mode 100644 .trellis/tasks/09-13-typed-orm/research/driver-selection.md delete mode 100644 .trellis/tasks/09-13-typed-orm/research/field-types.md delete mode 100644 .trellis/tasks/09-13-typed-orm/research/go-orm-reference.md delete mode 100644 .trellis/tasks/09-13-typed-orm/research/implicit-suspension.md delete mode 100644 .trellis/tasks/09-13-typed-orm/research/migration-practices.md delete mode 100644 .trellis/tasks/09-13-typed-orm/research/query-api.md delete mode 100644 .trellis/tasks/09-13-typed-orm/research/schema-change-matrix.md delete mode 100644 .trellis/tasks/09-13-typed-orm/task.json delete mode 100644 .trellis/tasks/09-19-application-testing/check.jsonl delete mode 100644 .trellis/tasks/09-19-application-testing/design.md delete mode 100644 .trellis/tasks/09-19-application-testing/implement.jsonl delete mode 100644 .trellis/tasks/09-19-application-testing/implement.md delete mode 100644 .trellis/tasks/09-19-application-testing/prd.md delete mode 100644 .trellis/tasks/09-19-application-testing/task.json delete mode 100644 .trellis/tasks/09-20-durable-jobs/check.jsonl delete mode 100644 .trellis/tasks/09-20-durable-jobs/design.md delete mode 100644 .trellis/tasks/09-20-durable-jobs/implement.jsonl delete mode 100644 .trellis/tasks/09-20-durable-jobs/implement.md delete mode 100644 .trellis/tasks/09-20-durable-jobs/prd.md delete mode 100644 .trellis/tasks/09-20-durable-jobs/research/implementation-map.md delete mode 100644 .trellis/tasks/09-20-durable-jobs/task.json delete mode 100644 .trellis/tasks/09-20-port-adapter/check.jsonl delete mode 100644 .trellis/tasks/09-20-port-adapter/design.md delete mode 100644 .trellis/tasks/09-20-port-adapter/implement.jsonl delete mode 100644 .trellis/tasks/09-20-port-adapter/implement.md delete mode 100644 .trellis/tasks/09-20-port-adapter/prd.md delete mode 100644 .trellis/tasks/09-20-port-adapter/research/implementation-map.md delete mode 100644 .trellis/tasks/09-20-port-adapter/task.json delete mode 100644 .trellis/tasks/09-20-production-api/check.jsonl delete mode 100644 .trellis/tasks/09-20-production-api/design.md delete mode 100644 .trellis/tasks/09-20-production-api/implement.jsonl delete mode 100644 .trellis/tasks/09-20-production-api/implement.md delete mode 100644 .trellis/tasks/09-20-production-api/prd.md delete mode 100644 .trellis/tasks/09-20-production-api/task.json delete mode 100644 .trellis/tasks/09-20-production-application-language/check.jsonl delete mode 100644 .trellis/tasks/09-20-production-application-language/design.md delete mode 100644 .trellis/tasks/09-20-production-application-language/implement.jsonl delete mode 100644 .trellis/tasks/09-20-production-application-language/implement.md delete mode 100644 .trellis/tasks/09-20-production-application-language/prd.md delete mode 100644 .trellis/tasks/09-20-production-application-language/task.json delete mode 100644 .trellis/tasks/09-20-secure-data-contracts/check.jsonl delete mode 100644 .trellis/tasks/09-20-secure-data-contracts/design.md delete mode 100644 .trellis/tasks/09-20-secure-data-contracts/implement.jsonl delete mode 100644 .trellis/tasks/09-20-secure-data-contracts/implement.md delete mode 100644 .trellis/tasks/09-20-secure-data-contracts/prd.md delete mode 100644 .trellis/tasks/09-20-secure-data-contracts/research/secure-contracts-source-map.md delete mode 100644 .trellis/tasks/09-20-secure-data-contracts/task.json delete mode 100644 .trellis/tasks/09-20-time-typed-codec/check.jsonl delete mode 100644 .trellis/tasks/09-20-time-typed-codec/design.md delete mode 100644 .trellis/tasks/09-20-time-typed-codec/implement.jsonl delete mode 100644 .trellis/tasks/09-20-time-typed-codec/implement.md delete mode 100644 .trellis/tasks/09-20-time-typed-codec/prd.md delete mode 100644 .trellis/tasks/09-20-time-typed-codec/research/time-wire-source-map.md delete mode 100644 .trellis/tasks/09-20-time-typed-codec/task.json delete mode 100644 .trellis/tasks/09-28-shared-toolchain/check.jsonl delete mode 100644 .trellis/tasks/09-28-shared-toolchain/design.md delete mode 100644 .trellis/tasks/09-28-shared-toolchain/implement.jsonl delete mode 100644 .trellis/tasks/09-28-shared-toolchain/implement.md delete mode 100644 .trellis/tasks/09-28-shared-toolchain/prd.md delete mode 100644 .trellis/tasks/09-28-shared-toolchain/task.json delete mode 100644 .trellis/tasks/09-29-build-cache-storage/check.jsonl delete mode 100644 .trellis/tasks/09-29-build-cache-storage/design.md delete mode 100644 .trellis/tasks/09-29-build-cache-storage/implement.jsonl delete mode 100644 .trellis/tasks/09-29-build-cache-storage/implement.md delete mode 100644 .trellis/tasks/09-29-build-cache-storage/prd.md delete mode 100644 .trellis/tasks/09-29-build-cache-storage/research/cache-boundaries.md delete mode 100644 .trellis/tasks/09-29-build-cache-storage/task.json delete mode 100644 .trellis/tasks/09-29-external-lib-ecosystems/check.jsonl delete mode 100644 .trellis/tasks/09-29-external-lib-ecosystems/design.md delete mode 100644 .trellis/tasks/09-29-external-lib-ecosystems/implement.jsonl delete mode 100644 .trellis/tasks/09-29-external-lib-ecosystems/implement.md delete mode 100644 .trellis/tasks/09-29-external-lib-ecosystems/prd.md delete mode 100644 .trellis/tasks/09-29-external-lib-ecosystems/task.json delete mode 100644 .trellis/tasks/09-29-external-lib-packaging/check.jsonl delete mode 100644 .trellis/tasks/09-29-external-lib-packaging/design.md delete mode 100644 .trellis/tasks/09-29-external-lib-packaging/implement.jsonl delete mode 100644 .trellis/tasks/09-29-external-lib-packaging/implement.md delete mode 100644 .trellis/tasks/09-29-external-lib-packaging/prd.md delete mode 100644 .trellis/tasks/09-29-external-lib-packaging/task.json delete mode 100644 .trellis/tasks/09-29-external-lib-protocol/check.jsonl delete mode 100644 .trellis/tasks/09-29-external-lib-protocol/design.md delete mode 100644 .trellis/tasks/09-29-external-lib-protocol/implement.jsonl delete mode 100644 .trellis/tasks/09-29-external-lib-protocol/implement.md delete mode 100644 .trellis/tasks/09-29-external-lib-protocol/prd.md delete mode 100644 .trellis/tasks/09-29-external-lib-protocol/task.json delete mode 100644 .trellis/tasks/09-29-external-libs/check.jsonl delete mode 100644 .trellis/tasks/09-29-external-libs/design.md delete mode 100644 .trellis/tasks/09-29-external-libs/implement.jsonl delete mode 100644 .trellis/tasks/09-29-external-libs/implement.md delete mode 100644 .trellis/tasks/09-29-external-libs/prd.md delete mode 100644 .trellis/tasks/09-29-external-libs/task.json delete mode 100644 .trellis/tasks/09-29-language-production-closure/check.jsonl delete mode 100644 .trellis/tasks/09-29-language-production-closure/design.md delete mode 100644 .trellis/tasks/09-29-language-production-closure/implement.jsonl delete mode 100644 .trellis/tasks/09-29-language-production-closure/implement.md delete mode 100644 .trellis/tasks/09-29-language-production-closure/prd.md delete mode 100644 .trellis/tasks/09-29-language-production-closure/research/apparmor-nonroot.md delete mode 100644 .trellis/tasks/09-29-language-production-closure/research/ecosystem-closure.md delete mode 100644 .trellis/tasks/09-29-language-production-closure/research/ecosystem-pack-inputs.md delete mode 100644 .trellis/tasks/09-29-language-production-closure/research/linux-ci-scope.md delete mode 100644 .trellis/tasks/09-29-language-production-closure/research/native-pack-production-inputs.md delete mode 100644 .trellis/tasks/09-29-language-production-closure/task.json delete mode 100644 .trellis/tasks/10-05-install-entry/check.jsonl delete mode 100644 .trellis/tasks/10-05-install-entry/design.md delete mode 100644 .trellis/tasks/10-05-install-entry/implement.jsonl delete mode 100644 .trellis/tasks/10-05-install-entry/implement.md delete mode 100644 .trellis/tasks/10-05-install-entry/prd.md delete mode 100644 .trellis/tasks/10-05-install-entry/task.json delete mode 100644 .trellis/tasks/archive/2026-09/00-bootstrap-guidelines/prd.md delete mode 100644 .trellis/tasks/archive/2026-09/00-bootstrap-guidelines/task.json delete mode 100644 .trellis/tasks/archive/2026-09/09-09-markdown-source/check.jsonl delete mode 100644 .trellis/tasks/archive/2026-09/09-09-markdown-source/design.md delete mode 100644 .trellis/tasks/archive/2026-09/09-09-markdown-source/implement.jsonl delete mode 100644 .trellis/tasks/archive/2026-09/09-09-markdown-source/implement.md delete mode 100644 .trellis/tasks/archive/2026-09/09-09-markdown-source/prd.md delete mode 100644 .trellis/tasks/archive/2026-09/09-09-markdown-source/research/source-flow.md delete mode 100644 .trellis/tasks/archive/2026-09/09-09-markdown-source/task.json delete mode 100644 .trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/check.jsonl delete mode 100644 .trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/design.md delete mode 100644 .trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/implement.jsonl delete mode 100644 .trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/implement.md delete mode 100644 .trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/prd.md delete mode 100644 .trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/research/client-bottleneck.md delete mode 100644 .trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/task.json delete mode 100644 .trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/check.jsonl delete mode 100644 .trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/design.md delete mode 100644 .trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/implement.jsonl delete mode 100644 .trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/implement.md delete mode 100644 .trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/prd.md delete mode 100644 .trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/task.json delete mode 100644 .trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/check.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/design.md delete mode 100644 .trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/implement.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/implement.md delete mode 100644 .trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/prd.md delete mode 100644 .trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/task.json delete mode 100644 .trellis/tasks/archive/2026-10/10-04-developer-onboarding/check.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/10-04-developer-onboarding/design.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-developer-onboarding/implement.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/10-04-developer-onboarding/implement.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-developer-onboarding/prd.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-developer-onboarding/task.json delete mode 100644 .trellis/tasks/archive/2026-10/10-04-external-command/check.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/10-04-external-command/design.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-external-command/implement.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/10-04-external-command/implement.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-external-command/prd.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-external-command/task.json delete mode 100644 .trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/check.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/design.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/implement.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/implement.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/prd.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/task.json delete mode 100644 .trellis/tasks/archive/2026-10/10-04-slim-distribution/check.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/10-04-slim-distribution/design.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-slim-distribution/implement.jsonl delete mode 100644 .trellis/tasks/archive/2026-10/10-04-slim-distribution/implement.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-slim-distribution/prd.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-slim-distribution/research/libs.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-slim-distribution/research/release.md delete mode 100644 .trellis/tasks/archive/2026-10/10-04-slim-distribution/task.json create mode 100644 editor/vscode/.gitignore create mode 100644 editor/vscode/.vscodeignore create mode 100644 editor/vscode/README.md create mode 100644 editor/vscode/language-configuration.json create mode 100644 editor/vscode/package-lock.json create mode 100644 editor/vscode/package.json create mode 100644 editor/vscode/syntaxes/dever-markdown.tmLanguage.json create mode 100644 editor/vscode/syntaxes/dever.tmLanguage.json delete mode 100644 sdk/native-release.md create mode 100644 test/dever-tests/fixtures/core/complete_package.dever create mode 100644 test/editor-vscode/highlight.test.cjs diff --git a/.gitignore b/.gitignore index 632822d..525487e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ /config/setting.json /.release-key.*/ /.trellis/workspace/ +/.trellis/tasks/ +/.trellis/private/ /.agents/ /.codex/ **/__pycache__/ diff --git a/.trellis/spec/backend/directory-structure.md b/.trellis/spec/backend/directory-structure.md index cc7d1f0..629a892 100644 --- a/.trellis/spec/backend/directory-structure.md +++ b/.trellis/spec/backend/directory-structure.md @@ -35,12 +35,12 @@ - `check/cache.rs`: per-thread last-result cache with complete source identity; bundled AST caching belongs to `lib.rs`/`source.rs`. - `native/build/cache.rs`: native artifact identity, integrity validation and atomic publication. `native/build.rs` owns current runtime freshness, snapshots and isolated executable lifetimes. - `crates/dever-cli/src/main.rs` and `format.rs`: argument parsing, source loading, direct execution of the owned native program, local clean command adaptation and prepared/atomic source formatting writes. `test_runner.rs` is the single owner of application-test ordering, isolated native processes, captured output and temporary project cleanup. -- CLI binary-private `compile.rs` owns LLVM/object/LLD orchestration; `worker.rs` is the service-owned source compiler. Shared `toolchain/runtime_pack.rs` validates packs/snapshots without bridge imports; `compilation.rs` owns canonical input and staging validation, while `service/` owns authenticated transport and child supervision. Reuse core `native::compile_artifact` for private builds and `NativeProgram` for caller-owned received executables. `toolchain/packaging.rs` owns deterministic native release assembly/signing from explicit author inputs; `sdk/native-release.rs` only adapts its private author CLI. Root `runtime-pack` profile and `sdk/native-release.md` own the four-archive build recipe. `test/dever-cli-tests/support/llvm_inputs.rs` holds explicit fixture SDK inputs, and `support/daemon.rs` holds the shared owned-daemon lifecycle; neither is a production input discovery mechanism. +- CLI binary-private `compile.rs` owns LLVM/object/LLD orchestration; `worker.rs` is the service-owned source compiler. Shared `toolchain/runtime_pack.rs` validates packs/snapshots without bridge imports; `compilation.rs` owns canonical input and staging validation, while `service/` owns authenticated transport and child supervision. Reuse core `native::compile_artifact` for private builds and `NativeProgram` for caller-owned received executables. `toolchain/packaging.rs` owns deterministic native release assembly/signing from explicit author inputs; `sdk/native-release.rs` only adapts its private author CLI. Root `runtime-pack` profile owns the four-archive build settings. `test/dever-cli-tests/support/llvm_inputs.rs` holds explicit fixture SDK inputs, and `support/daemon.rs` holds the shared owned-daemon lifecycle; neither is a production input discovery mechanism. - `library/dever/json/`: ordinary Dever JSON algorithm. `library/dever/http.dever`, `sse.dever`, `websocket.dever` and `tls.dever`: public protocol types/helpers and the native bridge; no duplicate source protocol stack. `task.dever` exposes runtime configuration, sleep and periodic streams. - `examples/cms/dever/` and `examples/cms/md/`: maintained CMS projects with equal declarations, schema, settings, business behavior and application tests. Generated API/CMD roots replace `module/main.dever`; `api/admin/**` and `api/front/**` are assigned by `sites..path`. Both projects keep matching `test///` cases and `config/setting.json`. - `examples/old/`: archived pre-role-layout language and regression material. It is not a current application root and must not be presented as a directory or visibility template. Formal tests remain under root `test/`. - `examples/README.md`: current CMS commands and the archive boundary. Historical rejection fixtures keep their original diagnostics only when invoked by dedicated compiler-level tests, not as current application projects. -- `test/dever-tests/tests/`: permanent focused tests. The canonical full-language syntax example is read directly from the PRD so a copied fixture cannot drift. +- `test/dever-tests/tests/`: permanent focused tests. Parser, checker and formatter share `test/dever-tests/fixtures/core/complete_package.dever`; public tests do not depend on private task records. Core foundations, formatting, optional reference evaluation, official library follow-through and the SQLite/PostgreSQL static ORM have concrete implementations. Compiler distribution and self-hosting remain unshipped; validation evidence belongs to the active task, not this directory map. Compiler phase APIs are bootstrap internals, not an alternative program source format. diff --git a/.trellis/spec/backend/quality-guidelines.md b/.trellis/spec/backend/quality-guidelines.md index a6769b7..26fac86 100644 --- a/.trellis/spec/backend/quality-guidelines.md +++ b/.trellis/spec/backend/quality-guidelines.md @@ -4,9 +4,9 @@ Workspace-owned Rust forbids unsafe code. Decimal128 and insertion-ordered Map r Root dev/test profiles keep `debug = 0` and `incremental = false` so independent focused test binaries do not recreate multi-gigabyte debuginfo and incremental object trees. Release keeps fat LTO and one codegen unit. Native runtime feature combinations share `target/native-runtime/cargo`; exact per-build inputs live under `target/native-runtime/inputs`. Do not restore one complete Cargo target per feature combination. -Native ABI release archives use the root `runtime-pack` profile and one shared `target/native-runtime-abi` Cargo target for all four driver combinations. Save each completed archive before the next feature build. Preserve link symbols, keep `embedded` disabled, and distinguish deterministic pack assembly from cross-host source reproduction; the author workflow and assertion points live in toolchain-and-library.md and sdk/native-release.md. +Native ABI release archives use the root `runtime-pack` profile and one shared `target/native-runtime-abi` Cargo target for all four driver combinations. Save each completed archive before the next feature build. Preserve link symbols, keep `embedded` disabled, and distinguish deterministic pack assembly from cross-host source reproduction; the contracts and assertion points live in toolchain-and-library.md. -Tests exercise source contracts and observable AST structure, not private helper implementations. Include the PRD's complete package, precedence and associativity, Unicode and line positions, lexical failures, excluded syntax, recovery, structural limits and directory loading. Filesystem tests create and remove only their own temporary directories; source loading never follows symbolic links. +Tests exercise source contracts and observable AST structure, not private helper implementations. Include the shared `test/dever-tests/fixtures/core/complete_package.dever` fixture, precedence and associativity, Unicode and line positions, lexical failures, excluded syntax, recovery, structural limits and directory loading. Filesystem tests create and remove only their own temporary directories; source loading never follows symbolic links. Explicit LLVM Worker acceptance consumes the prepared immutable `target/native-release-inputs/component-fixture`, with recorded source and binary digests. Cargo's `target/debug/component-fixture` is a mutable build output: feature unification can change its bytes while running the workspace matrix. Ordinary Worker tests use their Cargo-provided executable; never bypass the CI input-change gate to treat a mutable output as a fixed author input. @@ -37,7 +37,7 @@ cargo clippy --offline -p dever-core -p dever-runtime -p dever-tests --test hell cargo clippy --offline -p dever-cli --bin dever -- -D warnings ``` -The hello target retains stdout, value mutation, package boundaries, missing toolchain and artifact cleanup regressions. Core targets cover the full PRD sample, static rejection, clause permutation, concrete native output, COW ordering, nullable flattening and source-located faults. Foundation-extension cases additionally cover contextual handler syntax, forwarding/specialization recursion, value-only clause domains, List/Bytes/Stream traversal, early stop/resume and one terminal stream failure. Resource tests create only their own temporary files and loopback sockets on port 0 with bounded reads/timeouts. CLI changes also require the actual check/run/build command. These are focused compiler checks, not an integration environment or workspace-wide test run. +The hello target retains stdout, value mutation, package boundaries, missing toolchain and artifact cleanup regressions. Core targets cover the shared complete-package fixture, static rejection, clause permutation, concrete native output, COW ordering, nullable flattening and source-located faults. Foundation-extension cases additionally cover contextual handler syntax, forwarding/specialization recursion, value-only clause domains, List/Bytes/Stream traversal, early stop/resume and one terminal stream failure. Resource tests create only their own temporary files and loopback sockets on port 0 with bounded reads/timeouts. CLI changes also require the actual check/run/build command. These are focused compiler checks, not an integration environment or workspace-wide test run. Parentheses must not affect context inference: use the shared Group-unwrapping helper for nulls, empty literals and named handlers. Handler signature types must reuse ordinary boundary validation, including generic arity and nested Map-key rules. Stream adapters must preserve `Pull::Last` rather than turning it into an ordinary item. Never retype an existing Decimal/Int local as Float, even after constant propagation. Float zero patterns match both signs, so substituting the pattern constant for the actual input changes division semantics. Preserve source field and Map pair evaluation order in generated code; declaration order controls layout/display only. diff --git a/.trellis/spec/backend/toolchain-and-library.md b/.trellis/spec/backend/toolchain-and-library.md index 6789120..cbc73d5 100644 --- a/.trellis/spec/backend/toolchain-and-library.md +++ b/.trellis/spec/backend/toolchain-and-library.md @@ -4,7 +4,7 @@ Application deployment targets belong to `toolchain::BuildTarget`, independently of the compiler host. Public `build --target linux-aarch64` may run on Linux x86_64; omitted targets and `run/test` stay native. Propagate the selected target through Lib preparation, CompileRequest, runtime pack selection, signature closure verification and both caches. Verify ELF machine/type for archive members and ordinary objects; a matching manifest label/hash alone does not prove architecture. A warm shared cache must still validate the selected target pack. Do not globally replace `platform_identity` or require an ARM compiler core for cross builds. -Target runtime/interpreter/extension/exec/sandbox assets must match the deployment target. Go build tools explicitly declare `build.host`, while Go output and stdlib headers match `build.goos/goarch` and version. Their sandbox uses host assets; emitted Workers use target assets. Product processes keep cleared environments; author-only cross linker settings or Go overlays must not become application configuration/environment knobs. Python sdist/npm hook execution requires a matching execution environment or a previously prepared complete target receipt; never relabel host native output. The canonical author maps and preparation commands are in `sdk/native-release.md`. +Target runtime/interpreter/extension/exec/sandbox assets must match the deployment target. Go build tools explicitly declare `build.host`, while Go output and stdlib headers match `build.goos/goarch` and version. Their sandbox uses host assets; emitted Workers use target assets. Product processes keep cleared environments; author-only cross linker settings or Go overlays must not become application configuration/environment knobs. Python sdist/npm hook execution requires a matching execution environment or a previously prepared complete target receipt; never relabel host native output. Executable modes are also part of the cross-target resource contract. Sandbox packaging and application embedding share `asset_executable`; classify both supported target loaders independently of the author's host, while retaining target ELF validation. Regressions must check actual packaged modes from non-executable source inputs and execute the embedded Worker. Host-only loader assertions and successful linking cannot establish target bootstrap behavior. Full-system sandbox fixtures must switch from initramfs rootfs to a normal root mount before bubblewrap uses `pivot_root`; do not loosen the production sandbox to accommodate a fixture mount error. @@ -22,7 +22,7 @@ Private task constructors without suspension remain ordinary functions. Scope ad Private `dever run/build/test` uses checked HIR → LLVM → object → in-process LLD, without Rust/Cargo/cc lookup or fallback. Keep LLVM calls binary-private; shared `toolchain/runtime_pack` validates compiler-relative `runtime//manifest.json`, normalized paths, version/v1 ABI/target, four profiles and exact CRT/archive digests. Shared code must not reference bridge target methods: actual linkage pulls LLVM into launcher/daemon even when the call appears to be metadata only. Reject symlinks, scripts, thin archives and incomplete references; snapshot/recheck selected inputs before linking. Private compilation reuses `native::compile_artifact`; managed compilation requires authenticated daemon IPC and never falls back. Ephemeral signed Linux fixtures do not establish trimmed or formal six-target release assets. -Native authoring now uses the independent four-profile `runtime-pack` build recipe and `sdk/native-release.md`; the old all-features debug archive remains a test fixture only. Signing prepared inputs and compiling source are separate operations. Do not move Cargo/tool discovery into the maker or application run/build. +Native authoring uses the independent four-profile `runtime-pack` build; the old all-features debug archive remains a test fixture only. Signing prepared inputs and compiling source are separate operations. Do not move Cargo/tool discovery into the maker or application run/build. Linux first installation reuses the release signature and machine version owner. Author `bootstrap` inputs provide launcher/daemon and their own complete private ELF library closure. The independently authenticated installer reads only its absolute root-owned `config/setting.json`; its public key must be supplied outside the downloaded release, then pinned atomically without key replacement. A bounded journal may name only the seven fixed bootstrap destinations, including the sandbox helper tree and dedicated AppArmor policy. Persist final file modes and child directories before publication; recover uncommitted changes, but never roll back a committed publication because cleanup failed. Stop a newly started service before removing its unit; restore previous service state after restoring files. Offline image installation never invokes systemctl. Incoming packages must match the supported service template; existing signed versions retain their original template and remain usable by pinned projects. Actual global activation and public release require separate operational authorization and evidence. @@ -30,7 +30,7 @@ Process main is separate from callable roots. Initialize Unix SIGPIPE policy bef ## 2. Signatures -- First installation: root `install` is the sole installer source and supports `bash install` and `curl -fsSL https://git.dever.cc/shemic/dever/install | bash`. Its Bash entry forwards `--version`, `--release`, `--trusted-key`, `--system-root`, and `--no-start` to its embedded Python implementation. Maintain this file directly; skills provide guidance, not another installer, and there is no generation step. +- First installation: root `install` is the sole installer source and supports `bash install` and `curl -fsSL https://git.dever.cc/shemic/dever/raw/branch/main/install | bash`. Its Bash entry forwards `--version`, `--release`, `--trusted-key`, `--system-root`, and `--no-start` to its embedded Python implementation. Maintain this file directly; skills provide guidance, not another installer, and there is no generation step. - Project creation: `dever new [--markdown]`; `project::create(&Path, bool)` consumes the single template source under the ordinary `skills/assets/template` directory in the same repository revision. The machine launcher selects the active core without reading nonexistent target configuration. - AI guidance: `dever skill path [project-root]` resolves and verifies the active or project-pinned release's `skills/dever-language`; `dever skill install ` atomically publishes a stable loader that invokes the absolute machine launcher. Skill resolution is a public read-only operation and must not open the root-only install lock. @@ -84,7 +84,7 @@ Process main is separate from callable roots. Initialize Unix SIGPIPE policy bef Developer onboarding uses one official source repository, `ssh://git@git.dever.cc:2222/shemic/dever.git`. Its ordinary `skills/` directory is committed and versioned with the compiler, without a submodule or separate skill repository; it distinguishes this language from Go Dever. Author `skill` is a required list of `{source,path,sha256}` entries published as signed `skills/dever-language/` artifacts, including SKILL.md; at most 256 files, 1 MiB each and 8 MiB total. New-project source bytes come from the same skill templates; Markdown documentation wraps them without a second semantic copy. Keep the generated configuration CMD-only and free of database/auth prerequisites. -Official `install`, `update` and extension preparation explicitly download from the compiled `https://git.dever.cc/shemic/dever/dist` origin; neither project setting.json nor environment variables choose that origin. Metadata uses `latest/` or `/`; after authentication every payload uses the exact signed version directory, without `v` or `download/`. `dever-release-v2` binds base `artifacts` and optional `extensions` in one signature. Each platform publishes `dever-.manifest.json`, `.manifest.sig`, `.tar.zst`, plus `.ext--.tar.zst`, under immutable version directories. Kind is runtime-pip/npm/go, build-pip/npm, or target; target holds nonhost native runtime/CRT and sandbox. Validate closed IDs, path namespaces, duplicate/overlapping paths, digests and size/count limits in the shared catalog owner. Base retains all four host database profiles, compiler closure, bootstrap, host sandbox and skill. Extensions cannot override base files. Do not fabricate an unsigned merged manifest. +Official `install`, `update` and extension preparation resolve `https://git.dever.cc/api/v1/repos/shemic/dever/releases/latest` or `/tags/v` anonymously. Neither project setting.json nor environment variables choose that origin. Resolve once per operation; the selected stable tag must match the signed manifest even for latest. Metadata is bounded to 2 MiB and 1–512 unique attachments with positive bounded sizes. Download the exact attachment name through its validated `browser_download_url`, enforcing the declared length and HTTPS same-origin redirects. Reject draft/prerelease, malformed tags, duplicate names, missing assets, foreign URLs, truncation and tag/signature mismatch before publication. `dever-release-v2` binds base `artifacts` and optional `extensions` in one signature. Each release publishes `dever-.manifest.json`, `.manifest.sig`, `.tar.zst`, plus `.ext--.tar.zst`. Kind is runtime-pip/npm/go, build-pip/npm, or target; target holds nonhost native runtime/CRT and sandbox. Validate closed IDs, path namespaces, duplicate/overlapping paths, digests and size/count limits in the shared catalog owner. Base retains all four host database profiles, compiler closure, bootstrap, host sandbox and skill. Extensions cannot override base files. Do not fabricate an unsigned merged manifest. Authenticate the catalog before extraction. Zstandard is a single checksummed frame with window_log_max=27; verify complete compressed EOF/trailer and bounded expansion even after TAR EOF. USTAR contains only its signed ordinary artifact files, with no duplicate, escaping or extra entries; require complete terminator/padding and reject trailing content. Redirects remain on fixed official HTTPS hosts. Publication never replaces another writer's directory. First-install raw `.blob-` assets include the launcher and every bootstrap/lib dependency, independently digest-checked before execution. The launcher owns extraction; Python must not implement a second TAR/Zstd parser or require system zstd. @@ -92,7 +92,7 @@ Shared extensions live in service-writable `cache/extensions//` value and preserves the current static-call model. - -```dever -first = run(load_user(first_id)) -second = run(load_user(second_id)) -first_user = await(first) -second_user = await(second) -``` - -`await(async_call(...))` invokes and waits without creating a separately owned Task. `run(async_call(...))` starts first and returns an affine Task whose associated output signature remains in checked HIR. `await(task)` consumes it and yields the same zero, single or named multi-output shape as the function. Task operations consistently use the language's existing call appearance; no second prefix spelling is accepted. - -Static handler syntax places `async` before `handler`: - -```dever -async serve( - route: async handler(request: Request) (response: Response) -) () { - response = await(route(request)) -} -``` - -`async` has one canonical declaration position immediately before the function name. Existing `pure` and `recover` contracts retain their post-signature positions. Parser, formatter, Markdown signatures and examples must change atomically; no postfix async spelling is accepted. - -### Task Ownership - -Task is a compiler-owned affine local type, not a new user-defined generic facility. It may be held only in a local slot of the async function that created it. It cannot be copied, compared, stored in an aggregate, passed as an ordinary value, returned, captured by a handler or left live at any clause exit. - -Each async entry and spawned task has an internal runtime Scope; the compiler treats every async function as a lexical ownership scope. Directly awaited calls inherit the current Scope because runtime faults cannot be caught, while `run` and Group create a supervised child Scope. Every Task must be consumed exactly once by `await` or `stop`. On abnormal runtime exit, the root or child supervisor requests cancellation and waits for descendant and blocking-work cleanup before returning the failure. There is no detached task in the first release. - -`stop` means cancel-and-wait, not fire-and-forget cancellation. To keep failure and output obligations explicit, the first release accepts only zero-output Task values. Result-bearing tasks must be awaited. Cancellation is cooperative at await/yield boundaries; it neither kills a running synchronous operation nor rolls back effects that already occurred. - -### Dynamic Task Groups - -`group(limit)` creates an affine Group for a dynamic number of zero-output async calls. It is needed for later connection/session ownership without allowing detached children: - -```dever -workers = group(128) -run(workers, serve_connection(connection)) -await(workers) -``` - -`run(group, async_call(...))` transfers the child into the Group and returns no Task. It may suspend while the positive capacity limit is full, providing backpressure before starting more work. Ungrouped `run(async_call(...))` is likewise subject to the owning function scope's task limit. `await(group)` closes admission, waits for all children and consumes the Group. `stop(group)` closes admission, requests cancellation, waits for every child and consumes the Group. Group cannot be copied, stored or escape its creating async function. - -Only zero-output calls enter a Group, so the runtime cannot accumulate unbounded result values and expected failures cannot be silently discarded. A later result-collecting combinator must define ordering and memory limits separately. - -### Thread Transfer And Execution Classes - -The type model derives a `transferable` property recursively, alongside the existing comparison/move/transfer properties. Bool, numeric values, Text, Id and Bytes are transferable. Records, choices, nullable values, Lists and Maps are transferable only when every nested value is transferable. Each opaque resource is opted in only when its runtime representation and lifecycle are thread-safe; the current pull-based Stream is initially non-transferable. - -Values live across an `await`, captured by `run`, or passed through channel/parallel boundaries must be transferable. Last-use analysis may move uniquely owned values into a task; otherwise ordinary value semantics require a copy. This rule is checked before native emission and is not delegated to a Rust compiler error. - -Execution classes remain distinct: - -- ordinary synchronous calls execute inline; -- `run` schedules an async call on the shared runtime; -- `parallel(sync_call(...))` accepts only a pure synchronous target with transferable inputs/outputs and runs it through bounded CPU execution; -- `blocking(sync_call(...))` accepts a synchronous target whose transitive effect summary contains a compiler-known blocking system boundary and uses bounded blocking capacity. - -`parallel` and `blocking` are async-context operations in the first release: they suspend their caller until the synchronous call completes. Synchronous code continues to use `parallel_each`; it does not initialize Tokio solely to access these operators. - -Existing synchronous `parallel_each` keeps its public behavior and joined scoped workers. Async List/Bytes lowering requires a named synchronous function with no transitive concurrency effect, then submits bounded batches directly to the shared Tokio blocking executor, so it neither blocks a Tokio scheduling worker nor creates a nested thread pool. Other collection operations inspect the complete handler effect and cannot hide blocking, concurrency or an unconstrained handler effect on a Tokio scheduling worker. The first release has no handler effect bounds, so an async function cannot invoke a synchronous handler parameter inline. Both parallel paths share worker-limit and batch-size validation. Synchronous Stream remains unavailable in async functions until async Stream is designed. - -### Channels - -`channel(Type, capacity)` is compiler-contextual syntax: its first operand is a TypeRef, not a runtime type value. It creates a bounded `Channel` resource. Capacity is required, positive and capped. This deliberately avoids adding generic function invocation syntax solely for one constructor. - -Channel aliases share one state. `send(channel, value)` asynchronously waits for capacity; `receive(channel)` asynchronously waits for an item and returns `Item?`, where a value is an item and `null` means the Channel is closed. Because nullable types are idempotent, receiving from `Channel` also returns `Item?`; native emission flattens the runtime's nested option. A runtime scheduler or Channel fault remains a located fatal execution failure rather than a domain value. `close(channel)` is idempotent and wakes blocked senders and receivers. No unbounded constructor exists. Values must be transferable. Channel itself cannot be a Map key or comparable value, and its close/alias behavior follows explicit resource semantics rather than ordinary value semantics. - -### Effects, Failures And Static Handlers - -Async is part of a function and handler signature. Sync callers cannot invoke async functions or async handlers. Async callers may invoke sync code directly and async code only through an explicit async operation. Collection handlers remain synchronous because collection operations do not await handler futures; async handlers are called only through `await` or `run`. Handler specialization keys include the async signature bit, and cycle detection continues across await/run/forwarding edges; async does not legalize recursion. - -`await`, `run`, `stop`, group operations, channel waits, timers, `parallel` and `blocking` are effects. The existing transitive effect graph owns these facts, so the first release rejects `async` together with `pure`. Task boundaries do not discharge error-bearing outputs: awaiting restores the original output obligations, while Group and stop accept only zero-output work. Runtime scheduler failure is a located fatal execution failure; expected domain failures remain explicit source choice values. - -### HIR And Native Boundaries - -The syntax tree records the async modifier and contextual concurrency expressions. Checked HIR owns explicit `AwaitCall`, `RunCall`, `AwaitTask`, `StopTask`, Group and Channel operations. It never represents a generic user-visible Future. Function metadata and HandlerSignature carry the async bit; Task stores its concrete checked output fields. - -Native emission generates concrete Rust futures and direct calls. Static handlers remain specialized direct targets; no boxed dynamic callback, generic runtime Value, reflection registry or garbage collector is introduced. The runtime owns scheduler construction, task/group/channel state, limits and cancellation primitives. Compiler checks own source legality, transferability, affine consumption and diagnostic locations. - -Runtime cancellation separates a business future from its supervisor. Task/Group stop aborts the business future; the supervisor itself remains alive, drains its child Scope, and only then publishes completion to the parent Scope. Started `spawn_blocking` jobs register a sticky completion signal because Tokio cannot abort them safely. Drop paths request cancellation and detach only supervisor handles whose completion is still owned and awaited by the parent Scope; no Drop implementation calls `block_on`. - -### Compatibility And Deferred Work - -Existing synchronous source and `parallel_each` behavior stay valid. `LANGUAGE.md`, Markdown contracts and API snapshots are updated with the implementation. The `run` source operator is distinct from the CLI command by grammar context. - -The task-foundation phase deferred networking; N1 above resumes AsyncStream and TCP on these primitives. The HTTP engine and WebSocket/SSE remain later work. Detached tasks, arbitrary shared mutation, locks, user thread creation, unbounded channels and forceful cancellation remain out of scope. - -## Markdown Source Follow-through (2026-09-09) - -`.dever.md` is an additional source container alongside `.dever`. Top-level literal `dever` and `typescript dever` fences contain ordinary Dever declarations; the latter supplies a TypeScript highlighting hint while retaining an explicit Dever marker. A dedicated Markdown contract parser maps one H1 to the package header and one H2 to each type or logical function group before formatting. After shared signature resolution, semantic validation compares package/API/use metadata, type fields/variants and function inputs/outputs with syntax and HIR, retaining both documentation and declaration spans in diagnostics. Shared fence extraction keeps original spans for parsing, diagnostics and per-block formatting. `.dever` and language/runtime semantics are unchanged. The authoritative source-format contract is `LANGUAGE.md` and `.trellis/spec/backend/toolchain-and-library.md`; earlier `.dever`-only and unconstrained-heading limits below are superseded. - -## Performance Implementation Boundary (2026-09-08) - -- Compiler analysis worker owns types.rs, check.rs integration and contracts dependency scheduling: memoized type properties and monotone reverse-dependency work queues, retaining handler substitution and proof limits. Existing graph traversal is reused. -- Cache worker owns source/parse caching, native/build.rs and its cache helper plus CLI cache integration if necessary. Cache identities include effective source, compiler/toolchain/runtime and options; checked API baselines stay outside cached native execution. No new external dependency or source format. -- Main owns native liveness/emission, runtime collections, JSON/HTTP source algorithms, performance fixtures and integration. Record updates preserve value aliases and evaluation order; consuming iteration retains resource scope; direct split consumption avoids eager character lists; HTTP parsing tracks incremental boundaries and framing in Dever. -- Root tests own semantic regressions and bounded before/after measurements; no services/full suite/commit. Workers are not alone and must preserve unrelated edits. Shared check.rs edits require coordination with the analysis owner. Independent final review checks values, failure order, cache invalidation and protocol bounds. - -## Follow-through Implementation Design (2026-09-07) - -This section owns the current follow-through; older extension boundaries below describe completed milestones. - -- Formatter: add an AST writer using existing spans, preserved comments and precedence. Preserve record initializer expression order. CLI owns filesystem mutation and prepares every result before any rewrite. Expose syntax-only formatting separately from semantic checking. -- Reference evaluator: add an opt-in `reference` compiler feature, not a runtime dependency. Consume checked HIR, normalized domains and static handler bindings; reuse runtime number/resource primitives. Frames hold value locals and preserve copy semantics. Capture stdout and named results for differential tests. Do not add an evaluator production CLI path. -- Standard library: extend the single intrinsic/checker/native catalog for atomic representation/OS operations only. Public result choices live in `library/`; share runtime implementations with the evaluator. Text indexes are Unicode scalar positions; Bytes indexes remain byte offsets. Number parse failures are nullable results, never a silent zero; finite Decimal rules remain unchanged. -- Optimization: analyze actual read order and writes per clause, retaining outputs and assignment hosts. Move dead values, preserve live aliases and short-circuit paths; transfer reduction state between iterations. Verify value semantics before performance comparison. -- Parallel ownership: formatter worker owns formatter modules, formatting CLI and root format tests; reference worker owns evaluator modules and root differential tests. Main agent owns libraries, primitive integration, native optimization, task documents and integration. Coordinate shared module registration edits. -- Verification uses offline focused targets and test-owned files/processes. Performance checks are bounded local computation, exclude compiler startup and use matching numeric/collection wrappers. Existing user sources are never formatter test fixtures. -- Production native compilation and matching performance baselines share one optimization-argument owner (`opt-level=3`, `codegen-units=1`). The single generated source compiles as one unit to keep generic collection inlining independent of source size; compilation time is measured separately from hot paths. - -- Status: Core foundations and foundation extension implemented and verified on 2026-09-07 -- Date: 2026-09-04 -- Product source of truth: `prd.md` - -## Completed Foundation Boundary (Historical) - -Extend the implemented core with the approved sequence and resource foundation: `reduce`, `reduce_until`, Bytes traversal, `Stream`, restricted static handler inputs, and file/TCP stream wrappers. Existing clause-only branching, linear bodies and the ban on source loops and user recursion remain permanent. Compiler distribution, cross-platform work and full HTTP/JSON/CRUD packages remain deferred. - -Extend the existing checker and HIR in place. Represent user types nominally, resolve every function signature before bodies, prove clause coverage over symbolic input domains, and emit concrete native types/functions. Keep source expression order, including record construction; formatting must not reorder effectful field expressions. Use one runtime implementation for numeric operations, ordered collections and resource primitives. Bundled `.dever` sources define official wrappers and result types through the same frontend as user packages; only fixed primitive signatures have native implementations. - -## Foundation Extension Design - -This section records the completed foundation-extension design. The Follow-through Implementation Design above owns subsequent additions; later numbered sections retain the original Core roadmap. - -### Sequence Contract And Reuse - -The checker extends the existing collection-operation owner rather than adding parallel validators. One internal sequence classifier returns the element type and source kind for `List`, Bytes and `Stream`; `each`, `reduce` and `reduce_until` reuse it for handler checking and lowering. - -- `reduce(handler, sequence, initial_state)` requires a two-input handler `(Item, State) -> State` and returns `State`. -- `reduce_until(handler, sequence, initial_state)` requires `(Item, State) -> (State, stop: Bool)`, processes the current item before stopping, and returns only `State`. -- List and Bytes use finite direct loops. Bytes yields Int values from 0 through 255 without allocating `List`. -- Stream consumption calls its pull boundary only when the next item is needed. `reduce_until` leaves the next item unread; `reduce` consumes through natural exhaustion. -- `each(Stream)` accepts only a zero-output handler. List/Bytes retain their existing zero-output action and one-output mapping behavior. `filter`, `find` and `sum` remain List-only. -- Core `close(stream)` is a zero-output, idempotent Stream operation. It shares the same sequence operation registry but is checked as resource termination, not traversal. - -Handler signature diagnostics, sequence classification and output-shape validation each have one semantic owner. Native lowering receives already classified sequence and handler facts; it does not repeat source-level type decisions. - -### Static Handler Representation - -`handler(inputs) (named_outputs)` is contextual syntax allowed only after a function input colon. The syntax tree represents value patterns and handler parameter declarations as separate input kinds; it does not disguise a handler as an ordinary `TypeRef`. The semantic model likewise keeps `HandlerSignature` separate from runtime `Type`, because a handler is a compile-time binding rather than a value. - -`HandlerSignature` stores positional input types and ordered named output fields. Input names do not participate in compatibility; output name, position and type all do. The checker accepts only a matching named function or a handler parameter already in scope. Handler references cannot enter local slots, aggregates, outputs, comparisons or clause domains. - -HIR uses explicit call and argument forms: - -```text -HandlerTarget = NamedFunction(FunctionId) | Parameter(HandlerParameterId) -CallTarget = NamedFunction(FunctionId) | Handler(HandlerTarget) -CallArgument = Value(Expression) | Handler(HandlerTarget) -``` - -Collection/sequence HIR stores the same `HandlerTarget`; it no longer carries a collection-specific optional function ID. This is the reusable representation for direct handler calls, sequence operations and multi-level forwarding. - -Native compilation treats a function with handler inputs as a template. A specialization key is the function ID plus its ordered concrete named-function bindings. Forwarding substitutes bindings until every handler call has a concrete target, then emits an ordinary direct call. The specialization graph rejects a repeated active key as direct or indirect recursion before any private Rust source is compiled. Generated handler plumbing contains no function pointers, closures, virtual dispatch or reflective registry; the opaque Stream producer described below is the only dynamic call boundary. - -### Stream Representation And Lifecycle - -The semantic type model adds `Stream(Box)`. It is the only new compiler-provided generic type; it is a valid parameter, local, field and choice payload but is not comparable and cannot be a Map key. Copying it preserves opaque resource semantics: every alias shares one cursor, exhausted flag and explicit-close flag. - -`dever-runtime` adds one generic pull-stream owner backed by shared synchronized state. Its producer returns either one item or natural end. The only dynamic producer abstraction is inside this opaque I/O boundary, where the PRD explicitly permits it; Dever handlers remain statically specialized. Pulling and closing are serialized, with no prefetch, worker thread or async task. - -The terminal rules are: - -1. Normal EOF marks the Stream exhausted and releases its producer without yielding an element. -2. A terminal file/socket read error is converted once to `ReadEvent.Failed`, then the Stream becomes exhausted. -3. A terminal accept error is converted once to `ConnectResult.Failed`, then the Stream becomes exhausted. -4. `close(stream)` marks all aliases closed, drops the producer and is a no-op when repeated; later traversal sees ordinary exhaustion. -5. Closing a separately held File, Socket or Listener invalidates the shared underlying resource. The dependent Stream then yields its one typed Failed item and ends. -6. Closing only the Stream drops its source alias but does not close a separately held source handle. Native destruction remains the final cleanup fallback. - -`reduce_until` never pre-pulls, so its stop item is consumed and the following item remains available to every Stream alias. Concurrent consumption is outside the language contract; the synchronized state protects resource integrity but does not introduce concurrency semantics. - -### Official Package And Runtime Boundary - -The public stream API remains ordinary bundled `.dever` source: - -```dever -type ReadEvent { - Chunk(bytes: Bytes) - Failed(message: Text) -} - -type ReadStreamResult { - Streaming(stream: Stream) - Failed(message: Text) -} -``` - -`dever.io.chunks(file, limit)` and `dever.net.chunks(socket, limit)` return `dever.io.ReadStreamResult`; `dever.net.connections(listener)` returns `Stream`. Existing one-shot `read` remains unchanged. Invalid limits and already-closed sources fail during stream creation; later source failures become one terminal stream item. - -The ownership flow remains: - -```text -bundled .dever function and result choices - -> fixed dever.system intrinsic signature - -> generated typed adapter - -> dever-runtime Stream/resource primitive -``` - -The generated adapter maps runtime pull outcomes (item, natural end or error) into the source-defined concrete choices. Runtime code therefore owns pulling, locking and OS resources, while `.dever` owns public names and recoverable result shapes. No HTTP parser, route table, JSON codec or user model enters the runtime. - -### Implementation And Rollback Boundaries - -Implementation proceeds through coherent compiler boundaries: syntax/semantic handler declarations; shared handler and sequence HIR; List/Bytes reduce lowering; runtime Stream; file/TCP adapters; then native specialization and end-to-end fixtures. Each boundary must compile and pass its focused tests before the next. Unsupported handler or Stream positions remain compile diagnostics; there is no compatibility fallback to runtime values or eager Stream collection. - -The existing one-shot file/TCP APIs, List operations and generated-binary boundary remain compatible. No stored data or public artifact format needs migration. Reverting the extension removes its syntax, standard source declarations, HIR forms and runtime module together while leaving the completed core foundations intact. - -## Historical Hello Milestone (2026-09-06) - -The completed deliverable is a native `user.dever` whose `main() ()` prints `hello`. A future user API may start with in-memory fixtures; database selection is no longer a prerequisite. Existing parser and surface syntax are preserved. - -The implemented Text/action subset covers package and function resolution, Text parameters and local assignment, zero-output calls, checked HIR, native Rust emission and local check/build/run. It checks all source declarations and rejects unsupported constructs, duplicate symbols, invalid exposures, private cross-package calls, source/package mismatches and cycles. This is not full Core checking. - -The standard `dever.io.println(Text)` signature resolves to a typed intrinsic. Its implementation belongs to a small dependency-free `dever-runtime`; the native backend embeds that same runtime source in disposable generated Rust. Text uses owned Rust Strings to preserve Dever value semantics. User function and local identifiers lower to numeric IDs, not raw Rust identifiers. Output failures propagate internally to a nonzero process exit with the Dever call location; no new source exception syntax is introduced. - -The CLI owns argument parsing and process execution; the core owns checked programs and native compilation. Invoke rustc directly without a shell, using RUSTC or PATH. Compile into an exclusively created temporary directory, retain it through execution and remove owned artifacts afterwards. Explicit build output must not overwrite an existing file. No external dependency, package distribution, interpreter or service is needed. - -The following sections describe the wider roadmap. Implemented foundations are recorded in the Active Core Checklist and Core Foundation Evidence in `implement.md`; formatter, reference evaluator, performance gates and application packages are not part of this delivery. - -## Deferred Application Architecture - -This is a later HTTP/JSON/CRUD direction, not part of the approved foundation extension. It must be reconsidered against the implemented Stream and static-handler contracts before application work begins. - -The native path remains `.dever -> parser -> resolver/checker -> typed HIR -> private Rust -> native executable`. HTTP requests must execute the compiled business functions, not an interpreter or a handwritten Rust user service. - -| Owner | Required responsibility | -| --- | --- | -| `.dever` application packages | User/input types, validation, CRUD orchestration, parameterized queries, routes and business error mapping | -| `dever-core` | Symbol/type/clause/initialization checks, standard signatures, I/O effects, typed handler checks and native code generation | -| `dever-runtime` | Mature HTTP and JSON implementations, the selected database driver, connection/resource lifecycle and per-request fault boundary | -| CLI | Configuration inputs, `check`, native `build/run` and diagnostics | - -Necessary semantic adaptations, with no new surface keywords: - -- Allow named function references in fixed HTTP registration positions, extending the existing collection-handler mechanism. They remain statically resolved, not general first-class functions. -- Add opaque standard resource types for database pools and server resources. Ordinary records/collections keep value semantics; resource handles explicitly identify external state and cannot be serialized or mutated as records. -- Give standard I/O operations fixed effect metadata and propagate effects through the call graph. Preserve statement/expression evaluation order; internal async lowering does not introduce `async` or `await` into `.dever`. -- Reuse choice results for recoverable HTTP/JSON/database failures. Program faults are isolated to the failing request and retain Dever source locations. -- Bundle only the required standard HTTP/JSON/database contracts with the toolchain. External package distribution remains deferred. - -The current `TypeRef` AST can represent parameterized standard types, but `parser.rs::type_ref_inner` presently recognizes only List/Map/MapEntry generic spellings. Any required qualified standard generic type must be supported through the standard-type contract, without a User-specific parser branch. User-defined generics remain deferred. - -Persistence selection is pending. The initial design candidate uses parameterized SQL and static type-driven row decoding, with schema/query definitions owned by one application persistence package. Do not build an ORM or multi-database framework speculatively. JSON and row decoding should share resolved type facts, rather than duplicate user field definitions in Rust. - -Verification must show that changing `.dever` handlers, types or routes changes the compiled API. A second small schema/route fixture should prove that compiler/runtime code contains no user-API special case. Report actual CRUD throughput, latency percentiles, errors and memory against equivalent native code under identical database/durability settings; finalize the performance budget after storage and deployment scope are selected. - -## 1. Architecture Decision - -Core 0.1 is a textual language toolchain, not a semantic-graph workbench. It has one checked frontend and two deliberately different consumers of the same typed HIR: - -```text -.dever source root - | - v -source loader -> lexer -> parser -> syntax tree - | | - | +-> formatter - v - package/name resolver - v - type + clause + flow checks - v - typed HIR - / \ - v v - reference evaluator native specialization - v - private Rust emission - v - rustc / LLVM -> binary - -dever CLI -> load / check / format / build / run -``` - -Dever text in `.dever` files or program blocks of `.dever.md` files is the program source. The syntax tree and typed HIR are in-memory compiler representations; they are not editable JSON formats or public compatibility contracts. The evaluator defines a simple executable reference for conformance tests. Production `build` and `run` use ahead-of-time native compilation and never route through the evaluator. - -The bootstrap compiler is implemented in Rust because rustc provides a mature LLVM path. The repository starts without an existing workspace or implementation. This is an implementation choice, not a surface-language dependency: diagnostics, type identities and runtime semantics are owned by Dever, and generated Rust is a disposable private build artifact. - -## 2. Scope Boundaries - -The implementation contains three production crates: - -```text -crates/ - dever-core/ - src/ - source.rs - diagnostic.rs - token.rs - lexer.rs - syntax.rs - parser.rs - format.rs - package.rs - resolve.rs - types.rs - clauses.rs - check.rs - hir.rs - value.rs - stdlib.rs - eval.rs - native.rs - lib.rs - dever-runtime/ - src/ - number.rs - collections.rs - fault.rs - lib.rs - dever-cli/ - src/ - main.rs -``` - -Compiler phases remain in one `dever-core` library rather than separate syntax, semantic and IR crates. They share source spans and language contracts and will evolve together during 0.1. `dever-runtime` is the only justified split because generated native programs consume it without depending on parser, checker, evaluator or CLI code. It contains only language-owned numeric, ordered-collection and runtime-fault primitives; it does not contain a dynamic interpreter or plugin layer. - -`dever-cli` owns argument parsing, filesystem invocation, exit codes and rendering. It calls `dever-core` APIs and contains no parser, type or evaluation rules. - -Permanent integration tests stay under repository-root `test/`, matching project policy. Plain-source examples live under `examples/dever/`; Markdown examples live under `examples/markdown/`. Both may contain small fixture data when needed. - -## 3. Reuse And Replacement - -### Reuse - -- Pinned dependency discipline in the new Rust workspace. -- Small modules and explicit data structures. -- The idea that every diagnostic maps back to a source location. -- Root-level integration tests and deterministic fixtures. - -### Replace - -- `SemanticGraph`, canonical JSON loading and semantic hashing. -- Refiner candidates, approval, scrap and quarantine workflows. -- Dever IR designed around the old graph. -- Old target-facing Rust and React source generators and their public backend contracts. -- Workbench presentation and temperature-alarm example. -- Old child-task plan and old repository rules that call the semantic graph trusted source. - -No adapter translates old JSON into new `.dever`. Such a bridge would preserve the rejected architecture, expand the change surface and create two sources of truth. - -The replacement list describes rejected concepts, not files present at kickoff. No old implementation exists in the working tree or HEAD. Initialize `dever-core` and the root test crate first; add the runtime and CLI when their real consumers exist, without empty crates or partially working public commands. - -## 4. Source Model - -### 4.1 Source Files And Spans - -`SourceFile` owns: - -- canonical source-root-relative path; -- UTF-8 text; -- precomputed line-start offsets. - -`Span` contains a file identifier and half-open byte range. Line and column are calculated only when rendering a diagnostic, keeping compiler nodes small. Every token, syntax node, resolved reference and HIR instruction retains a span. - -The loader: - -1. walks the supplied source root for `.dever` files; -2. sorts paths lexically before parsing; -3. rejects invalid UTF-8 and duplicate canonical paths; -4. derives the expected package name from the path; -5. returns all diagnostics in deterministic file/span order. - -### 4.2 Tokens And Trivia - -The lexer emits semantic tokens plus newline and `#` comment trivia. Newlines matter for separating linear statements; whitespace otherwise does not. Comments attach to the following syntax item, or to the preceding item when trailing on the same line, so the formatter can preserve them. `//` is always one integer-division token and is never considered comment syntax. - -Numeric text remains unconverted in tokens. Parsing a very large literal directly into i64 or f64 would lose the ability to issue precise range and rounding diagnostics; conversion happens during checking with the expected type. An inexact Decimal literal is rejected rather than silently rounded, while checked Decimal arithmetic may produce the specified rounded result. - -### 4.3 Syntax Tree - -The parser produces a lossless-enough typed AST: - -- `PackageDecl` and exposed names; -- record/choice `TypeDecl`; -- `FunctionClause`; -- input patterns and output declarations; -- assignment/call statements; -- value construction, call, field, literal, unary and binary expressions. - -The parser does not resolve names or infer types. It supports bounded recovery at a newline, closing delimiter or next top-level declaration and returns a partial tree plus diagnostics. Later phases run only for packages without syntax errors. - -## 5. Formatter - -The formatter consumes the syntax tree and attached comments, never performs string replacements over raw source, and owns one layout: - -- two-space indentation; -- multiline package exposure and type members, one item per line; -- commas only where grammar requires positional separation; -- no semicolons; -- stable spaces around operators; -- record fields in declaration order after successful resolution; -- parentheses inserted only when required by precedence; -- one blank line between top-level definitions and no trailing whitespace. - -`format(format(source)) == format(source)` is an acceptance invariant. Invalid files are not rewritten in Core 0.1; the CLI reports diagnostics and leaves them untouched. - -## 6. Resolution And Symbols - -Resolution runs in three passes: - -1. Register every package, type, function name and function arity. -2. Register record fields, choice variants and full function signatures. -3. Resolve bodies, patterns, exposed names and cross-package references. - -Symbols use compiler-assigned integer IDs internally. User-visible identity remains the package-qualified source name, not an opaque semantic graph ID. - -The resolver enforces: - -- one file per package and exact path/package match; -- local source plus the fixed compiler-owned standard catalog as the only Core 0.1 package origins; -- reserved core single-segment names and the `dever.*` namespace, which local source cannot declare; -- unique names inside a package; -- one function signature per name/arity; -- contiguous clauses for the same signature; -- public access only through `exposes`; -- full qualification across packages; -- acyclic package, type and function-call graphs. - -Resolution never performs network access or searches outside the supplied source root in Core 0.1. An unavailable official or third-party package is an ordinary unknown-package diagnostic. Future lockfile-pinned components will be registered as an additional origin before these same resolution passes; this does not require imports, aliases or version text in `.dever` calls. - -### 6.1 Distribution Compatibility Contract - -External distribution is deferred to 0.2, but Core 0.1 must not close off its confirmed identity model: - -- a stable component ID such as `shemic.contact` owns the root of package and type identity; -- registry, Git and local paths are replaceable source transports and never appear in `.dever` references; -- Git additions require an explicit tag or revision, then lock the full commit and normalized SHA-256 content hash; -- CLI-maintained `dever.mod` records direct dependency intent while `dever.lock` records the complete exact graph; -- verified sources live in a global read-only content-addressed store shared across projects; -- only explicit `add`, `update` and `fetch` operations may access the network; -- every package supplied by a component must remain under that component ID, and duplicate providers are errors. - -No 0.2 parser, Git client, resolver, store or command is implemented speculatively in Core 0.1. The current resolver needs only reserved namespaces and origin-neutral internal symbol IDs so adding a locked package origin later does not change source names. - -The ordinary call graph is computed after all bodies resolve. Sequence handlers and handler-input forwarding are explicit HIR edges; native specialization checks the fully substituted instance graph, so indirect recursion cannot hide behind `each`, `reduce`, `reduce_until` or a handler parameter. - -## 7. Type System - -`TypeId` points to interned compiler types: - -- the six scalar types; -- user record and choice types; -- `Nullable(TypeId)`; -- `List(TypeId)`; -- `Map(KeyTypeId, ValueTypeId)`; -- compiler-owned `MapEntry(KeyTypeId, ValueTypeId)`; -- compiler-owned `Stream(ItemTypeId)` opaque resources; -- ephemeral named multi-output result types. - -There are no user-defined generic parameters in 0.1. List, Map, MapEntry, Stream and sequence functions are compiler-provided generic contracts. Static `HandlerSignature` is a separate function-parameter contract and is not a runtime `Type`. - -The type interner owns idempotent nullable construction for standard generic returns; explicit doubled `?` syntax remains invalid. Structural equality follows the PRD, including ordered Map pairs and IEEE Float comparisons inside aggregates. Checking, reference evaluation and native lowering must share these contracts. - -Checking is expression-directed: - -- function inputs and outputs provide declared boundary types; -- assignment provides an expected type once the local is initialized; -- an uninitialized local takes the inferred type of its first complete assignment; -- empty List/Map and context-sensitive numeric literals require an expected type; -- the only implicit numeric conversion is Int to Decimal; -- function output, static handler and sequence-operation contracts are checked before lowering. - -Linear bodies make definite assignment a forward pass. The checker tracks each local as uninitialized or initialized with one stable type. Record field writes require an initialized record and preserve its type. - -## 8. Clause Analysis - -Clause-based conditional dispatch is a permanent source-language constraint, not a Core 0.1 deferral. Native decision trees are its internal implementation and do not introduce another source-level branching form. - -Each same-name/same-arity group becomes one `FunctionDef` with multiple clauses. Analysis separates base input types from clause patterns. - -Patterns normalize into symbolic sets: - -- Bool and no-payload choice types become finite atoms. -- Nullable adds a distinct null atom. -- Payload choices keep the variant atom and bind payload fields after selection. -- Text/numeric constants become singleton sets. -- Int and Decimal comparisons become normalized intervals with open or closed endpoints. -- `other` is computed as the complement of all explicit patterns in that argument position and group. - -A multi-input clause is a product of its per-input sets. The analyzer incrementally subtracts each product from the function input universe: - -- intersection with prior coverage means overlap; -- an empty clause domain means unreachable; -- remaining universe after all clauses means non-exhaustive. - -The algorithm works on finite atoms and interval boundaries, not enumerated i64 or Decimal values. Float range patterns are rejected before this phase. The source order is never part of selection. - -At runtime, HIR stores a compiler-chosen decision tree built from the normalized domains. It can optimize tests while preserving order-independent semantics; no runtime “first matching clause” rule exists. - -## 9. HIR And Reference Evaluation - -The typed HIR contains only resolved IDs and typed operations: - -- constants and value construction; -- local/field load and store; -- checked numeric/text/boolean operations; -- direct function and statically bound handler calls; -- standard collection/sequence calls with explicit handler targets; -- clause decision nodes; -- named outputs. - -The evaluator uses an explicit call frame with owned locals and a source span for every operation. There is no global mutable program state. - -Runtime values are: - -```text -Bool -Int(i64) -Decimal(DecimalValue) -Float(f64) -Text -Id -Record -Choice -Nullable -List -Map -Stream -MultiOutput -``` - -Aggregate values use shared immutable storage with copy-on-write mutation. This implements source-level value semantics without eagerly cloning every nested List, Map or record. The optimization is internal and must pass alias-observation tests. - -Map storage uses an insertion-ordered map. In Rust, `indexmap::IndexMap` is the planned implementation; replacement keeps the same wrapper contract. Removal must use order-preserving removal, and overwrite must retain the existing position. - -Evaluation returns either named outputs or a `RuntimeFault`. A fault carries category, message and originating `Span` and unwinds only to the current CLI execution boundary. There is no language-level catch path. - -The evaluator is intentionally not optimized as the production runtime. Its job is to make language semantics easy to inspect, to evaluate focused tests and to serve as a differential oracle for native output. - -## 10. Native AOT Compilation - -The native path consumes only fully checked typed HIR. It performs whole-program specialization from the selected zero-input entry function and emits one transient Rust crate: - -```text -reachable typed HIR - | - v -specialize concrete List/Map/Stream and handler-binding combinations - | - v -emit static Rust records, enums, functions and loops - | - v -cargo build --release -> native executable -``` - -There is no generic `Value` in generated function signatures. Dever records lower to concrete Rust structs, choices to concrete enums, nullable values to an internal option representation, and calls to direct functions. Clause domains lower to compiler-selected decision trees. Because sequence handlers are concrete after specialization, `each`, `reduce`, `reduce_until`, `filter`, `find` and `sum` lower to direct calls and loops. List/Bytes loops have no virtual dispatch; only opaque Stream pulling may use the internal producer abstraction at the I/O boundary. - -Source-level value semantics do not require eager deep copies. A last-use/liveness pass may move a value when the source is dead; when both aliases remain live, generated aggregates use a language-owned clone or copy-on-write representation. This is invisible to `.dever` and is verified against the evaluator. Locals and non-escaping records remain eligible for normal Rust/LLVM stack and register optimization. The AOT runtime has no garbage collector and no reflection registry. - -Checked Int and Decimal behavior is emitted explicitly, so the release profile cannot remove language-required overflow or invalid-operation faults. Runtime helpers carry compact source-location IDs; the executable maps a fault back to the original `.dever` path and span. Internal Rust compiler errors are toolchain failures, not Dever diagnostics, and generated Rust names must never appear as user symbols. - -The transient crate depends only on `dever-runtime`. Its generated source and Cargo metadata live in a compiler-managed build directory, are not emitted by a public command and may be deleted at any time. The optimized profile starts with `opt-level = 3`, thin LTO and one codegen unit; benchmark evidence may change those internal settings without changing the language. - -The first backend deliberately uses stable Rust as a bootstrap bridge to LLVM. A later direct LLVM or Cranelift backend can consume the same checked HIR and runtime contracts without changing `.dever` source. No `dever-backend-rust` public crate or target-specific surface syntax is introduced. - -Self-hosting is a staged replacement, not a Core 0.1 syntax promise: - -1. The Rust bootstrap compiler establishes parser, checker, HIR, native semantics and conformance fixtures. -2. Later language phases add the explicit file/process/memory capabilities required to write compilers. -3. The frontend and standard library are reimplemented in `.dever` against the same fixtures and HIR contracts. -4. A stage-1 compiler builds stage 2; stage 2 builds stage 3; stage-2/stage-3 behavior and reproducible artifacts are compared before the Rust frontend becomes only a seed. - -## 11. Numeric Implementation - -`dever-runtime::number` is the only module allowed to depend on the decimal implementation. It exposes a language-owned `DecimalValue` and operations returning: - -```text -Result -``` - -Core 0.1 uses the Rust `dec` crate's `Decimal128` plus a reusable Context configured for 34 digits and round-half-even. Its status flags are cleared and checked around every operation: inexact/rounded is an accepted rounded result, while overflow, underflow, division by zero and invalid operation become Dever runtime faults. Decimal NaN/Infinity never enter a normal Dever `Value`. Compile-time constant evaluation and the reference evaluator call this same runtime wrapper, so native and reference behavior cannot acquire separate Decimal implementations. - -This boundary is necessary because `dec` uses libdecnumber internally and exposes more IEEE decimal states than the language permits. Conformance tests, not the dependency's default operators, define Dever behavior. - -Int operations use Rust checked arithmetic. Division and remainder explicitly handle zero and `i64::MIN / -1`. Int-to-Decimal conversion is exact. - -Float uses Rust f64 operations without fast-math transformations. List summation is left-to-right. NaN/Infinity classification is exposed through `math` functions. - -## 12. Standard Library Boundary - -Core names such as `each`, `reduce`, `reduce_until`, `close` and `get` are registered from a static table containing: - -- accepted arities; -- generic input/output constraints; -- whether an argument is a sequence, value or statically bound handler; -- evaluator function. - -Qualified standard packages (`text`, `decimal`, `float`, `math`) use the same table with qualified names. This is a fixed compiler-owned catalog, not a plugin registry. - -Every implemented standard operation has one checking contract and one native lowering rule. Sequence source classification and handler validation are shared so List, Bytes and Stream forms cannot drift. The deferred evaluator must later consume these same checked contracts rather than define a second interpretation. - -## 13. CLI Contract - -`dever-cli` builds one `dever` binary: - -```text -dever check -dever fmt -dever build --output -dever run -``` - -- `check` loads every package and runs all static phases. -- `fmt` prepares every file before writing; if any source file is invalid, no file is modified. Record-field reordering requires successful resolution. -- `build` checks the complete source root, specializes one exposed zero-input function as the entry point and writes an optimized native executable to the requested path. -- `run` uses the same native compilation path in a compiler-managed directory and then invokes the executable; it does not run the reference evaluator. -- Outputs print in declaration order using deterministic Dever value formatting. -- Diagnostics go to stderr; program output goes to stdout. -- Exit 0 means success, exit 1 means source/runtime diagnostics, exit 2 means invalid CLI usage. - -The CLI is deliberately not a project/package manager. Source-root selection avoids introducing a manifest before dependency versions or executable targets are designed. - -Core 0.1 therefore has no `add`, `update`, registry, signature or component-cache commands. Those are a 0.2 distribution concern; `check`, `build` and `run` remain offline and deterministic. - -### 13.1 Command Identity And Coexistence - -The Cargo binary and canonical product command remain `dever`. Command examples, help semantics and the public CLI contract use that name. - -During Core 0.1 coexistence with the existing Dever framework CLI, a machine may expose this compiler on `PATH` as `deverc`. That entry is a symlink or launcher for the same compiler binary, not a second CLI implementation. It must not replace, shadow or modify the existing `dever` executable. - -Repository builds and automated tests invoke the built binary directly and never mutate global executables or shell configuration. Installing, updating or removing the temporary `deverc` entry is an explicitly authorized machine-level operation. Moving the compiler onto the global `dever` name requires a separate migration plan. - -## 14. Diagnostics - -All compile diagnostics use one structure: - -```text -severity -code -message -primary span -zero or more labeled related spans -optional help -``` - -Examples include both conflicting clause spans, declaration and bad-reference spans, or first initialization and later type-changing assignment. Rendering uses `path:line:column` and a source excerpt. Messages describe the violated Dever rule and never expose Rust type names, crate names or implementation stack traces. - -Runtime faults use the same renderer with a runtime category. The CLI may include a Dever call trace, but the first diagnostic always points to the failing `.dever` operation. - -## 15. Migration And Repository Cleanup - -Implementation starts from the documentation-only repository verified on 2026-09-05: - -1. Initialize `dever-core` and `dever-tests`; add `dever-runtime` and `dever-cli` at their implementation stages. -2. Implement `dever-core` around textual language phases. -3. Do not recreate old Refiner, IR, Workbench, generated backend or semantic JSON architecture. -4. Preserve the existing deletion of superseded planning documents; no old child links exist. -5. Update repository `AGENTS.md` and Trellis package specs so future work treats `.dever` as the trusted source. -6. Add the Core 0.1 examples and tests. - -No database, persisted user data or old implementation exists, so there is no migration. Git history retains the old planning documents. - -## 16. Verification Strategy - -Tests are organized by behavior rather than compiler module: - -```text -test/dever-tests/tests/ - syntax_and_format.rs - package_resolution.rs - type_checking.rs - clause_analysis.rs - value_semantics.rs - collections.rs - numbers.rs - failures.rs - native.rs - differential.rs - performance.rs - cli.rs -``` - -Fixtures include valid programs plus one focused invalid case per diagnostic. Tests assert diagnostic code and relevant spans, not full prose, except dedicated rendering tests. - -The highest-risk property tests are: - -- parse/format/parse semantic equivalence and formatter idempotence; -- clause order permutation does not change coverage or result; -- Int division/remainder identity across boundary samples; -- Decimal conformance vectors for precision, rounding and fault flags; -- copy-on-write values do not expose alias mutation; -- Map overwrite/remove/reinsert order; -- Float sum remains left-to-right. -- reference evaluator and native executable produce identical outputs/fault categories for the conformance corpus; -- generated executables do not link the evaluator or perform per-element dynamic dispatch; -- representative native hot paths stay within the PRD performance budget against equivalent safe Rust baselines. - -The foundation extension adds focused cases to the existing `syntax_and_format`, `core_semantics`, `core_native`, `runtime_foundations` and `hello_native` targets. They cover handler syntax and forbidden positions, signature matching and forwarding, specialization-cycle rejection, List/Bytes reduce behavior, Stream alias/EOF/stop/close/error behavior, official package compilation, and actual CLI check/run/build of a chunked state parser. File fixtures use test-owned temporary directories; TCP fixtures use only loopback port 0, bounded data and explicit timeouts. - -No existing service, browser, npm build, full workspace test or external integration environment is involved in this extension. - -## 17. Key Trade-offs - -- One compiler crate is less independently reusable than many compiler crates, but avoids unstable public boundaries during the first grammar; the native runtime is separate only because generated programs are a real independent consumer. -- No recursion/effects limits programs to finite pure computation, but makes the first language deterministic and prevents hidden control flow. -- Full clause checking is more compiler work than ordered pattern matching, but it directly enforces the user's requirement that AI-written code cannot hide behavior in ordering or nested branches. -- A decimal dependency is safer than hand-written decimal128 arithmetic; the wrapper and conformance suite prevent it from defining public language behavior. -- A small fixed standard catalog is less extensible than plugins, but keeps the first implementation inspectable and removes speculative architecture. -- Rust emission gets optimized native code much earlier than implementing an LLVM backend, while typed HIR, differential tests and a private artifact boundary prevent Rust from becoming the language definition. -- Keeping a reference evaluator adds implementation work, but it localizes semantic debugging and gives native code generation a deterministic oracle; it is excluded from production binaries. -- Separating component identity from Git/registry location adds two CLI-managed metadata files in 0.2, but prevents repository moves from becoming source-breaking type renames and enables one verified global source store. -# Compiler Contract Extension (2026-09-08) - -Extend existing AST fields and clause modifiers, normalize field bounds with the same interval owner as patterns, then analyze checked HIR before publishing Program. Keep private checks in field access/construction owners. Function/package metadata feeds effect/dependency checks and deterministic API snapshots. Failure obligations follow values across aggregates and calls, with explicit source recovery declarations as the only normal-value discharge boundary. Static handlers share existing specialization bindings. Facts must be conservative on mutation and unknown operations; no runtime interpreter, speculative fallback, new dependencies or source keyword for every domain. - -Independent syntax/formatter work owns syntax.rs/parser.rs/format.rs; effect/API work owns contracts/effects.rs/api.rs and CLI; main owns semantic types, HIR integration, fact/failure analysis, standard-source migration, tests and docs. All workers preserve shared changes. Core check is the single enforcement entry used by CLI and native execution. - -# AI-Oriented Source Architecture Design (2026-09-19) - -Source classification is one compiler-owned value derived from the relative source path. It records main or component/domain/role/topic identity and is reused by parsing, Model registration, symbol resolution, API route construction and architecture diagnostics. Those layers must not rediscover roles with independent string searches. - -Every physical source still has a unique internal owner name so diagnostics, HIR ownership and native symbol generation remain deterministic. App declarations additionally receive one stable logical alias, `..`, regardless of whether they live in `app.dever` or `app/.dever`. Alias collisions are duplicate declarations. Topic paths remain an implementation detail and never leak into API snapshots or call sites. - -Name lookup tries the current physical owner first, then role-relative names in the current domain, same-component App aliases, and finally full App aliases. A resolved reference is accepted only when the role dependency matrix permits it. Main and API may call App; App may call private roles in its own domain and App aliases elsewhere; private roles may collaborate only inside their own domain. API functions are registered for HTTP routing but rejected as source call targets. Model type identity stays path-derived, while generated operations are restricted to their owning domain. - -Application `public` modifiers are rejected. App functions and App-declared types form the external contract automatically; Model record/choice/ID types remain type-visible where relations or App contracts require them. After failure inference, every App function is also checked so a private Domain/Adapter error type cannot leak through its effective error set. Bundled standard sources keep compiler-internal visibility metadata because they are not application architecture. The existing API baseline and unused-export checks consume logical App names. - -Architecture validation runs before semantic bodies: legal layouts, reserved names, file/directory exclusivity, flat non-API topic directories and the no-single-file-role-directory rule. Declaration-role validation then keeps API thin, Model storage-only and App as the sole cross-domain capability boundary. Port syntax itself is not expanded in this change; `port` is a reserved architectural role until a separately approved replaceable-boundary declaration contract exists. diff --git a/.trellis/tasks/09-04-dever-language-mvp/implement.md b/.trellis/tasks/09-04-dever-language-mvp/implement.md deleted file mode 100644 index 23ba125..0000000 --- a/.trellis/tasks/09-04-dever-language-mvp/implement.md +++ /dev/null @@ -1,819 +0,0 @@ -# Dever Minimal Core 0.1 Implementation Plan - -## HTTP/2 Ceiling And Soak (2026-09-18, Complete) - -子任务 `09-13-http2-ceiling-soak` 复用既有负载器,将客户端 worker/CPU 集合参数贯通 HTTP/1、HTTP/2 和长连接入口。34 项运行器定向测试及最小 loopback 回归通过;生产运行时未改。1 CPU、128 MiB 下 h2c/TLS+h2 的 16x16、30k/45k/60k/90k 双次扫描表明本机吞吐约 36k-40k req/s 时服务端接近 1 核,客户端仍占 1.4-2 核;请求槽丢弃使它不是纯服务端上限。28k 的首轮稳态未达 99% 成功率,故改用 20k:128/64 MiB 各 60 秒的四组成功率为 99.77%/99.92%/99.94%/99.80%,无请求错误、OOM 或 FD 残留。h2c/TLS+h2 各 100 轮重连无错误或 FD 残留;短时 RSS 数据不证明小时级无泄漏。原始报告、命令和限制见 `test/performance/README.md`。 - -HTTP/2 有界验收和 typed ORM 子任务均已完成。根任务保持进行中:历史计划的编译器发行/跨平台与自举仍未交付,小时级稳定性等扩展也没有在本轮获批或验证;不得凭子任务完成数宣称整个语言路线图结束。 - -## N5 HTTP/2 (2026-09-12, Complete) - -子任务 `09-12-http2` 完成:Hyper/h2 buffered/live 服务端、single-use/pooled 客户端、TLS ALPN、固定流控窗口与每连接流配额、逐流 handler/上传/下载/SSE、RST 隔离及 GOAWAY 排空。官方 `Limits.http2: Http2Limits?` 与检查器一起直接演进,静态原生桥接复用既有 Nullable/Record;没有新 intrinsic 或兼容层。 - -Hyper Executor 的协议任务接入 Dever 子 Scope,关闭 admission 与登记串行,故障上报/注销在 completion 之前;不可取消 supervisor 清理协议任务和已启动 blocking 后代后才释放物理许可。池连接归持久 driver;上传/下载共享流租约。只有 Hyper 结构化交回的未发送请求可在原期限重排,已发请求不重放。 - -88 个不同定向用例通过:HTTP/2 client/server 各6,HTTP engine12、HTTP library7、live16、pooled network14、pooled library6、async runtime10、structured concurrency11。独立 h2 对端覆盖流控、取消、容量、ALPN、语义与故障;原生程序覆盖单连接 TLS 嵌套代理、流式上传、SSE、run/await 和原有 HTTP/1/WSS。修复传输取消误升为整服故障、响应发布锁重入、GOAWAY 未发请求卡住旧租约和 Response TE 静默删除;测试端句柄和 WSS 独立连接预算也已修正。 - -最终 CLI release 构建、backend check/fmt-check、network_bench/reference 编译及源码检查通过;独立审查闭环。Rustfmt/Clippy 不可用,官方库 fmt-check 的原有 net.dever 差异未改。临时构建目录和暂存约378 MiB可再生缓存已清理,旧编译器与性能报告保留。不提交、不自动归档;N5 实现没有运行 HTTP/2 性能矩阵。后续仍有 HTTP/2 压测、小时级稳定性、入口调度优化、RFC 8441/协议扩展、数据库、发行和自举。 - -## P2 Async Comparison And Long Connections (2026-09-12, Complete) - -子任务 `09-12-runtime-performance-p2` 继续复用 P1 工具,完成同语义 Rust run/wait 对照、perf 调度定位、HTTP/HTTPS 高负载和 TCP/WS/SSE 分阶段回收测量。12 个运行器检查、4 个独立对端检查、11 个原生入口及新 Rust examples 的离线构建通过;未修改生产编译器/运行时。 - -1 CPU/128 MiB 下,Dever run/await root约15.50 µs、实验worker约2.003 µs,与Rust15.59/1.984 µs接近;任务入口跨线程切换是明确优化方向,根任务配额、Send和取消语义需保留。54组HTTP高负载发出1500830请求全部成功、299170计划请求未发出;压测槽位已限制结果,不是服务上限。 - -最终27组长连接覆盖32/128/512条,每组3轮;18144连接、377061消息均成功,81次FD回基线。另各协议512连接十轮,共15360连接、471207消息,无错误/OOM且30次FD回基线;SSE RSS在约25.3 MiB趋稳。修正采样退出与阶段交接竞态、SSE无心跳误通过和客户端清理;完整证据与限制集中在 `test/performance/README.md`。 - -P2 结束时尚未启用http2/h2依赖;当时规划的TLS ALPN、独立流/连接预算、流控、取消隔离和GOAWAY已由后续N5交付。小时级soak与入口调度优化另行落地,总语言路线图保持未完成。 - -## P1 Standalone Runtime Performance (2026-09-12, Complete) - -用户批准建立常驻内存、异步调度和 HTTP/HTTPS 三组基准,取代旧网络实施阶段的局部“不压测”限制。子任务 `09-12-runtime-performance` 完成:真实原生二进制、Rust runtime/Hyper 对照、有界固定速率负载、Linux RSS/PSS/CPU 和专属 cgroup 预算、原始 JSON 报告。生产语言/运行时未改动。 - -7 个运行器与 2 个独立 HTTP 对端检查通过;离线原生/release 构建和格式检查通过,Rustfmt/Clippy 不可用。最终 78 组主测、18 组新连接、15 组 64 MiB 空闲基线均完成且无 OOM;主测网络发出 107962 请求全部成功,38 个计划请求未发出并按原因记录。当前只是热缓存、短时、指定负载结果,不是吞吐极限、冷启动整机内存或长期稳定性结论。 - -运行命令、确切统计口径和首轮数据以 `test/performance/README.md` 为准,原始产物/报告保存在 `target/performance/`。后续候选:同语义 Rust 异步对照与调度剖析、高负载扫描、TCP/WS/SSE 长连接;其余语言/后端路线图仍未完成。 - -## N4 Concurrent Composition And Reusable Clients (2026-09-12, Complete) - -- [x] Implement source runtime configuration, typed handler context, timeout/race and pull-driven stream adapters; extend async memory traversal. -- [x] Add verified TLS transport and bounded reusable HTTP clients with streamed uploads/downloads; integrate HTTPS/WSS and TLS servers. -- [x] Wire compiler contracts, official source, native conversion and examples together. -- [x] Run focused compiler/native and independent loopback protocol/lifecycle tests; review final ownership and limits. -- [x] Update canonical language/spec docs and record evidence without a commit or archive. - -### N4 Evidence - -83 distinct focused cases passed: async_composition 7, pooled_network 14, pooled_library 5, structured_concurrency 11, async_network 9, http_engine 12, http_library 6 and live_network 16. Reruns are not counted twice. The old structured-concurrency case that rejected async List handlers was migrated to the newly accepted contract and checked for a concurrency effect. - -New coverage includes source runtime bounds/start-once, timeout cleanup of started blocking children, race loser cleanup/fault propagation, Channel null/drain/close and periodic stream timing, static handler/output checks, C012 stream failure obligations, async memory traversal/fusion and concrete HTTP Context transfer. Native programs exercise HTTPS, pooled proxy calls through shared Context, streamed uploads/downloads, SSE, WSS and graceful shutdown. - -Independent peers verify physical connection reuse, repeated headers, early chunks beyond the response-head deadline, chunked upload, slow/abandoned/truncated bodies, upload failure/cancellation, queue/body/idle deadlines, pool close wakeups, unpolled-task cleanup, certificate CA/name rejection and WSS frames. A reproduced lifetime defect allowed a pool's unpolled driver to escape its creator; constructing the driver owner guard before task creation fixes it. Native checks also exposed missing Channel Debug/Render for shared records and async handlers entering synchronous fusion; both are corrected. Final bounded cleanup removed an infallible Result from the private lease-completion path; all 14 pool cases passed afterward. - -Actual CLI backend example check and fmt-check passed without warnings. Offline build produced a standalone binary; running with an empty environment and PATH restricted to /usr/bin:/bin printed exactly `Hello /Dever\nrequests = 1\n` and exited successfully. Official source formatting, optional-reference core/runtime/CLI cargo check, whitespace/conflict-marker and final ownership/contract inspection passed. Rustfmt/Clippy are not installed, so their checks were unavailable; Rust layout was reviewed manually. - -Only initial dependency preparation fetched locked packages; validation/builds were offline. All network peers used owned loopback random ports and static test certificates under test/. No full suite, prior performance baseline, existing service, persistent example launch, global install or commit. No throughput/RSS improvement is inferred from functional checks. Temporary build, certificate-generation, formatting and demo directories are removed at handoff; workspace native caches remain. N4 is complete; HTTP2, protocol extensions/close metadata, database, distribution/cross-platform and self-hosting keep the umbrella task active. - -## N3 Streaming HTTP, SSE And WebSocket (2026-09-12, Complete) - -- [x] Add `serve_live`, HttpReply and LiveLimits while keeping ordinary serve direct. Reuse request/response codecs and connection configuration; one-slot body channel and one-handler Group per live connection. -- [x] Add SSE field encoding, bounded chunks, Last-Event-ID access and body-driven heartbeat timers; no event history or extra heartbeat task. -- [x] Reuse tokio-tungstenite 0.30.0 handshake/protocol for server/client Text/Binary/Ping/Pong, AsyncStream messages and close handshakes. Shared Endpoint lifecycle, 4 KiB read buffer, bounded messages/write buffers and independent directions. -- [x] Integrate resource types, exact nominal records/choices, async effects, static handlers, native conversion, API/Markdown names and Render. No new syntax, compatibility layer, dynamic interpreter or generic transport abstraction. -- [x] Verify owned wire peers and real native programs; update canonical docs/example and manually record the session without a commit or archive. - -### N3 Evidence - -46 distinct focused cases passed: live_network 16, live_library 3, http_engine 12, http_library 6, async_network 9. Repeated checks after corrections are not counted again. All final checks passed; the earlier slow-peer test assumed normal return and was corrected to observe cleanup on either return or cancellation. - -Wire evidence covers early chunk delivery, bounded slow-peer output, SSE exact encoding/heartbeats past the ordinary deadline, idle failure isolation, HEAD cleanup, handler faults, upgrade capacity/preread bytes, independent client masks, fragmentation/UTF-8/control frames, close, partial writes, waiting-writer cancellation and started blocking descendant drain. A reproduced regression showed duplicate response publication closed the existing body; cancellation ownership now starts only after publication is accepted, and the regression passes. - -The native source program exercised all four routes (buffered, stream, SSE, WebSocket), including client connect/send/receive/close and static async message-stream handlers. Existing native HTTP clients also matched independent wire peers. Final optional-reference cargo check, actual CLI example check (no warnings), CLI fmt-check, source format roundtrips and explicit whitespace/owner inspection passed. Rustfmt/Clippy are not installed and were not run. No throughput/RSS claims or old baseline. - -Only a one-time dependency fetch accessed the registry; checks/builds ran offline. No full suite, existing service, persistent example launch, global install or commit. N3 is complete; TLS/WSS, HTTP2, client pools, protocol extensions, close metadata, database/distribution and other roadmap work keep the umbrella task active. - -## N2 HTTP Engine (2026-09-12, Complete) - -The user approved continuing after N1. Execute inline; no further planning approval. Reuse Hyper HTTP/1 on the shared Tokio runtime. No legacy compatibility, old baseline, full suite, service checks or global installation. - -- [x] Replace the custom HTTP parser/transport with Hyper server/client primitives and migrate all source callers. -- [x] Preserve repeated headers as `List
` with byte values; buffer bodies within explicit limits. Reuse byte storage across the engine boundary. -- [x] Add `serve(async handler, Listener, Limits) -> ()` with bounded structured connections, server keep-alive, chunked input and cancellation cleanup. Configuration/accept/handler faults propagate; peer protocol failures terminate only that connection. -- [x] Add one-shot `send(address, port, Request, Limits) -> ResponseResult`. Poll its driver in the request future; no detached tasks, implicit retries or client pool. -- [x] Check static handler contracts/effects and native record conversion. Replace obsolete parser tests with independent loopback wire cases and focused compiler/native tests. -- [x] Update canonical docs and record evidence. TLS, HTTP/2, client pooling, streaming response bodies, WebSocket and SSE remain later work. - -Limits: header buffer at least 8192 bytes (Hyper requirement), nonnegative body bytes, positive timeout, bounded connections. Defaults: 8192 / 1048576 / 5000 ms / 32. Runtime owns HTTP framing; outgoing Content-Length/Transfer-Encoding are rejected. Request header/body/handler and stalled write deadlines prevent one idle peer retaining a connection indefinitely. Static Dever handlers specialize directly; no dynamic interpreter dispatch. - -### N2 Evidence - -- 44 distinct focused cases passed: http_engine 12, http_library 6, async_network 9, structured_concurrency 11, native_ownership byte cases 3, runtime_foundations bytes case 1, contract_execution selected example checks 2. Repeats after local corrections are not counted again. -- Independent wire cases cover persistence/pipelining, HEAD and 204/205/304, fragmented/chunked/binary bodies, repeated and non-UTF8 headers, conflicting lengths, header/body limits, unsupported trailers/upgrades, truncated responses, all deadlines, connection capacity and descendant cleanup. Header timeout closes directly; body/handler timeouts produce 408/504. Native tests execute real compiled send/serve and compare client bytes to an independent peer. -- Bytes tests retain unique Text storage transfer, shared-alias behavior, shared slices and consuming iteration. Connection setup now configures TCP_NODELAY once through one helper. No old-performance baseline, throughput or RSS claims were derived from correctness tests. -- Core compiled offline with the optional reference feature. Actual CLI HTTP example check/fmt-check and formatting roundtrips passed; the persistent example was not started. Final owning-layer, dependency, obsolete-reference and whitespace review passed. Rustfmt and Clippy were unavailable (components not installed), not reported as passing. -- Hyper 1.11.1, hyper-util 0.1.20, http-body-util 0.1.5 and bytes 1.12.1 are pinned. Missing transitive development dependencies were fetched once; builds/tests remained offline. No Axum, TLS or HTTP2 features were added. -- No full suite, existing service check, load test, global install, commit or task archive. N2 is complete; the umbrella task remains active for N3 and other unshipped roadmap work. - -## N1 Async Stream And TCP (2026-09-12, Complete) - -- [x] Persist the approved new-language/no-compatibility policy; use existing inline execution routing. -- [x] Add bounded, cancellable async stream consumption and Tokio TCP resources to the shared runtime. -- [x] Integrate AsyncStream types, async handlers, effects/liveness and concrete native code generation. -- [x] Replace synchronous TCP source contracts and migrate official HTTP transport, examples and tests. -- [x] Verify stream backpressure, close/stop, duplex I/O, timeout and compiler/native behavior with focused tests. -- [x] Update public contracts, inspect the final changed flows and record evidence. N2 HTTP engine and N3 WS/SSE remain deferred. - -### N1 Evidence - -- 62 distinct focused cases passed: async_network 9, async_stream 6, structured_concurrency 11, async_native 6, async_runtime 10, http_library 11, core_native `official_` 5, runtime_foundations `stream` 3, and the reference/native file-stream differential case 1. The HTTP benchmark stayed ignored. Repeated individual checks after local fixes are not counted again. -- Network tests owned only loopback port-0 sockets. A one-worker runtime proved duplex progress, pending close wakeups, read timeout reuse, partial-write cancellation closure, pre-pull backpressure, failure while the producer is idle, child cleanup and listener release. The persistent server example was checked without starting it. -- Native execution exposed missing Render implementations for new resource types; those were fixed at the runtime owner and the affected native checks passed. Migrated TCP differential cases now assert independent native expectations; the synchronous evaluator no longer carries a duplicate TCP implementation. -- Compiler/default and optional reference builds passed offline. Source formatting round trips, explicit whitespace checks and final owning-layer inspection passed. Rustfmt/Clippy were unavailable because those components are not installed; no claim of passing them. -- No workspace-wide tests, service checks, old-performance baseline, network load test, global install or commit. The task remains active for N2 HTTP engine and N3 WebSocket/SSE, not for unfinished N1 work. - -## Structured Concurrency Implementation (2026-09-12, Complete) - -The user approved this preceding implementation. Networking was paused during it; N1 above resumes AsyncStream/TCP. Each phase uses only focused offline tests under root `test/`; do not run the workspace-wide suite, service checks, old-performance baselines or network load tests. - -### Phase A: Freeze Syntax And Semantic Model - -- [x] Add the canonical `async name(...)` modifier while retaining post-signature `pure`/`recover`; update lexer/parser/formatter and Markdown signature model together. -- [x] Add async to function identity metadata and HandlerSignature compatibility without changing package/name/arity lookup. -- [x] Reject `async` together with `pure` in the first release and classify every concurrency operator through the existing transitive effect owner. -- [x] Add contextual `await`, `run`, `stop`, `group`, `parallel`, `blocking` and `channel` syntax; reject async calls as ordinary stored values. -- [x] Add HIR task/group/channel operations and compiler-owned affine local metadata; do not add a user-visible Future or generic evaluator value. -- [x] Extend recursive type properties with thread transferability and explicit resource opt-in. -- [x] Add focused syntax/format/check cases for clause agreement, sync-to-async rejection, handler mismatch, forbidden Task escape and transfer failures. - -Rollback point: syntax/HIR-only changes must leave all existing synchronous HIR and formatted output unchanged. - -### Phase B: Await And One Shared Runtime - -- [x] Add Tokio with the smallest required features and one runtime owner in `dever-runtime`. -- [x] Emit async functions as concrete Rust futures while retaining direct sync emission for wholly synchronous entry graphs. -- [x] Implement direct `await(async_call(...))` and async entry execution; preserve zero/single/named multi-output and source-located failures. -- [x] Implement async timer sleep as the first real suspension boundary; do not use TCP/HTTP as the proof fixture. -- [x] Verify multiple sleeping tasks can make progress without one OS thread per task and sync binaries do not initialize the runtime. - -Rollback point: runtime dependency and native entry changes are isolated from Task ownership and can be removed while keeping Phase A diagnostics. - -### Phase C: Structured Task And Group Ownership - -- [x] Implement `run(async_call(...)) -> Task`, `await(task)`, and exactly-once affine consumption across local writes and every clause exit. -- [x] Implement zero-output `stop(task)` as cooperative cancel-and-wait; reject result-bearing stop and repeated consume. -- [x] Implement positive bounded `group(limit)`, backpressured `run(group, call)`, `await(group)` and `stop(group)`. -- [x] Ensure normal and abnormal parent completion cleans all children; no detached path or swallowed expected failure. -- [x] Verify start-before-await concurrency, output equivalence, cancellation cleanup, capacity backpressure and bounded task ownership. - -Rollback point: Task and Group runtime modules remain separate from scheduler construction and do not change direct await. - -### Phase D: Multi-thread And Blocking Work - -- [x] Implement `parallel(sync_call(...))` for pure transferable calls using bounded execution; preserve existing numerical/error semantics. -- [x] Implement the compiler-owned `blocking` boundary only for calls with a transitive compiler-known blocking effect; bound active workers plus queued submissions. -- [x] Route async use of `parallel_each` away from Tokio workers while retaining the current synchronous contract and shared worker validation. -- [x] Configure conservative defaults from available parallelism with explicit hard maxima; do not create per-call runtimes or unconstrained pools. -- [x] Verify multi-core execution, no scheduler starvation under bounded blocking work, exact output/error behavior and small-worker configurations. - -Rollback point: retain the existing synchronous `parallel_each` implementation until the common executor passes its focused compatibility cases. - -### Phase E: Bounded Channels And Contract Integration - -- [x] Add compiler-contextual `channel(Type, capacity)` and the runtime Channel resource. -- [x] Implement async `send`/`receive`, idempotent `close`, wakeup behavior and explicit source-defined result choices. -- [x] Extend effect, failure, dependency, redundancy, API snapshot and Markdown checks for every new signature/operation. -- [x] Add documentation only for implemented behavior and a runnable non-network producer/consumer example. -- [x] Run the available focused syntax/semantic/native/runtime/concurrency, reference-feature and whitespace checks; record unavailable rustfmt/Clippy components explicitly. - -Final gate: inspect generated native code for concrete futures/direct static handlers and absence of generic Value/handler dispatch. Record passed, failed and unrun checks without claiming network readiness. - -### Final Evidence - -- `structured_concurrency`: 11 passed; syntax, formatter shape, affine ownership, transferability, effects/failures, handler boundaries and Channel contracts. -- `async_runtime`: 10 passed; recursive cleanup, cancel-and-wait, Group backpressure, bounded channels, shared blocking limits and async `parallel_each` peak concurrency. -- `async_native`: 6 passed; real native execution of await/Task/Group/Channel/parallel/blocking/timer, sync-entry isolation and nullable Channel flattening. -- Existing synchronous `concurrency`: 5 passed and its explicit benchmark remained ignored; the async example and nullable-result native regressions each passed their exact case. -- `dever-core` with the optional `reference` feature compiled offline. `git diff --check` and explicit trailing-whitespace scans passed. Dependency inspection confirmed Tokio uses only runtime, sync and time features in this phase. -- The installed Rust toolchain has no rustfmt or Clippy component, so those two checks were unavailable rather than passed. No full suite, build, service, network, old-performance baseline, global installation or commit was run. -- Independent final review found no remaining blocking defect after nullable Channel emission, synchronous collection-handler enforcement and transitive async effect boundaries were corrected. - -### Deferred Follow-through - -- [x] Design and implement AsyncStream/Tokio TCP on the shared runtime in N1. HTTP engine and WebSocket/SSE integration remain later phases. -- [ ] Measure the new packaged binary and live network behavior only after network integration; the user explicitly waived an old-runtime baseline. - -## Active Performance Checklist (2026-09-08) - -- [x] Capture bounded compiler, record/text/list/map/JSON/HTTP and concurrency baselines. -- [x] Memoize type properties and schedule effect/failure summaries by dependencies. -- [x] Eliminate redundant record field copies and consume unique list elements safely. -- [x] Optimize direct character-list consumption and eligible collection fusion without changing fault order. -- [x] Implement incremental HTTP framing and test in-memory fragments/limits/malformed inputs. -- [x] Cache bundled frontend work and native artifacts with complete invalidation and API checks. -- [x] Measure concurrent task granularity; batch only where justified and preserve bounded Stream consumption. -- [x] Run affected offline tests, native/reference regressions, strict lint, formatting and independent final review; record measurements and update owning docs. - -User has authorized the complete implementation. This extends the active task and does not require another planning approval. Two bounded implement workers own analysis and cache respectively; main owns emission/runtime/protocols and benchmark integration. All permanent tests stay in root test/. Never run workspace-wide tests, existing services or global installation; use test-owned temporary inputs/processes only. - -## Packaged Runtime Footprint Follow-through (2026-09-09) - -- Composite runtime values and generated records/choices now append recursively through `Render::render_to`; named entry outputs reuse that same String instead of building a rendered value and then copying it into a second formatted String. Numeric `to_text` retains its direct `to_string()` path after the bounded hot-path gate exposed a slower generic formatting attempt. -- Native binding temporaries now transfer uniquely owned Text/Bytes storage and List/Map values through consuming operations. Live aliases retain copy-on-write behavior, and resource-containing values remain non-movable under the existing type-property contract. -- Exact-size finite parallel iterators create no more workers than items/batches. Unknown-length Stream dispatch keeps the caller-requested worker limit, bounded queue, cancellation and joined lifecycle. -- Production optimization arguments now use fat LTO and strip symbols; the workspace release runtime uses matching fat LTO/one-unit settings. The same allocation-performance fixture decreased from 4,680,864 to 452,352 bytes (90.3%) and measured 3,468 KiB peak RSS, versus 3,608 KiB without LTO. -- Thin LTO was rejected because ordered Map reached a 1.255 native/baseline ratio. Fat LTO passed all five gates: Int 0.713, Float 1.001, List 0.668, Decimal 0.985 and ordered Map 1.030. It trades substantially longer cold compilation for the user-approved packaged-runtime priority. -- An attempted fixed 64 KiB clamp for one-shot reads was rejected and removed: it changed a 1 MiB regular-file result to 64 KiB and failed the exact performance result. `read(limit)` remains caller-sized; low-memory programs use smaller limits or `chunks`. -- Focused runtime/concurrency/native ownership/core-native checks and both explicit performance scenarios cover the final contracts. No workspace-wide suite, service, external network, global installation or commit was used. - -## Performance Evidence (2026-09-08) - -- Nominal type properties are memoized after cycle validation. Facts, effects and failures share one dependency graph; summary changes reschedule callers instead of rescanning every function. The same 24-level shared-type debug regression went from 11.56 s to 0.47 s across the combined analysis/frontend changes. -- Native emission reuses checked HIR and last-use analysis. Safe record aliases are coalesced, scalar reads can be snapshotted before consuming large records, and exact field overwrites can move their old value. Unique Lists move elements; shared Lists clone only consumed elements. Resources retain their original lifetime and aliases retain value semantics. Empty Bytes concatenation reuses storage without weakening copy-on-write. -- Text splitting has one iterator implementation. Direct consumers avoid an intermediate List; eligible each/filter stages fuse only when handlers are proven free of observable effects and faults. A pure Int handler alone is insufficient because overflow can change fault order. Generated-code, alias, mutation and native/reference cases cover these boundaries. -- HTTP wire decoding now retains its header boundary and parsed frame between feeds. Transport uses that state; legacy one-shot scan delegates to the same implementation. Three new in-memory cases cover fragmentation, binary bodies, EOF, limits, duplicate headers and private/aliased state; five existing pure protocol tests passed. No live HTTP service was used. -- Bundled AST and the last complete frontend result are cached within a process. Native artifacts persist across processes, keyed by source-generated code, compiler/toolchain/runtime/dependency identities and native options. Atomic publication, fingerprint validation, isolated executable copies and create-new saves preserve correctness. All six cache tests and the explicit actual-CLI API-baseline regression passed. Independent CLI processes still check current sources and API baselines; no persistent HIR cache was introduced. -- Finite parallel inputs use bounded batches through the existing cancellation/join owner; Stream keeps bounded producer-driven pulls. With 32,768 inputs and four workers, median light-handler queue/batch/serial times were 140.945/3.894/0.247 ms; 512-round handlers measured 178.267/20.033/60.185 ms. Batching reduces dispatch cost but does not make tiny tasks preferable to serial execution. -- Main-agent final ownership/JSON/reference verification passed 9/7/10 tests respectively; only three network-dependent differential cases were skipped. Concurrency passed five functional cases, contracts passed 38 affected cases, and strict Clippy/type checks passed for core/runtime/CLI and affected test targets. Actual CLI library formatting and contracts/library checks passed. Independent final review found no blocking issue. -- After the final Bytes optimization, the main agent reran all three incremental HTTP cases and six default native-cache cases successfully. The actual-CLI cache test is ignored by default and had already passed when explicitly selected. Final targeted Rust formatting and new-file whitespace checks passed. - -The same source was compiled before and after this change. Linux x86-64, Rust 1.98.0, CPU affinity 4; five alternating processes per side, native internal timing excluding compilation/startup. Text/List/JSON each retain five samples per process after discarding warmup; Map retains one per process. All expected results were asserted. Medians: - -| Source workload | Before | After | -| --- | --- | --- | -| 16,384 record Text appends | 14.093 ms | 0.279 ms | -| 16,384 Text List elements | 4.786 ms | 1.342 ms | -| Long JSON string parsing | 28.072 ms | 6.977 ms | -| Record accumulation of 16,384 distinct Map keys | 548.061 ms | 1.999 ms | -| Process peak resident memory | 4,648 KiB | 3,604 KiB | - -- Separate HTTP strategy measurement used identical 16,947-byte input in 64-byte fragments, both paths on the new compiler, seven alternating samples after warmup: repeated one-shot scan 4.541 ms, incremental decode 0.366 ms. This is parser work, not server throughput or an old/new compiler comparison. -- Same release CLI hello: cold native miss 0.84 s; subsequent independent-process hits 0.17/0.17/0.16 s, including source/API checks and runtime freshness. In-process frontend cold/hit measured 171.273/3.742 ms. -- The existing five-kernel matching-runtime gate passed again with 45 effective samples per side: native/baseline Int 0.989, Float 0.998, List 0.578, Decimal 0.979, ordered Map 1.006 (limit 1.15). This checks code-generation overhead against the same runtime, not against the old compiler. Build times were measured separately: native 2,137–2,693 ms, baseline 252–680 ms. -- These are bounded local workloads, not whole-language speed guarantees. README, IMPLEMENTATION and owning specs describe the optimization boundaries. No full suite, service integration, global installation or commit; the performance scope is complete while the umbrella language roadmap remains active. - -## Active Follow-through Checklist (2026-09-07) - -- [x] AST formatter, comments/precedence/idempotence, all-file preparation and CLI fmt/check. -- [x] Text/number library expansion and explicit argument/environment/clock primitives. -- [x] Opt-in reference evaluator, core semantics and native differential cases. -- [x] Last-use and reduction-state ownership optimization with alias/order regressions. -- [x] Bounded reproducible native performance baseline and evidence. -- [x] JSON/HTTP source packages and focused protocol fixtures. -- [x] Controlled concurrent execution with explicit limits/lifecycle and focused verification. -- [ ] Resolve database choice from pending user answer; implement or record explicit deferral. -- [x] Integrate delivered flows, review, update canonical specs and actual validation evidence. - -Workers implement formatter and reference evaluator independently; the main agent owns libraries and integration. Checks are targeted, offline and bounded; no full suite, live service, global install, commit or cross-platform distribution. Later checklists are historical. - -## Follow-through Evidence (2026-09-07) - -- Implemented syntax-only AST formatting and CLI `fmt`/`--check`. Source snapshots are reloaded before staging and before replacement, comparing both the complete path set and file contents. Independent review found the initial missing path-set check; the shared source loader now closes that gap without a second traversal implementation. Per-file replacement remains atomic, not a multi-file OS transaction. -- Added Unicode Text operations, numeric parsing/rendering, process arguments/environment and explicit clocks/sleep through the existing intrinsic catalog and source-defined result choices. JSON and HTTP algorithms are ordinary `.dever` packages; no runtime JSON/HTTP parser or new dependency was added. -- JSON validates grammar, precise numeric spelling, duplicate keys, Unicode, graph references, nesting and expansion limits. HTTP supports a declared HTTP/1.1 single-message subset with binary bodies, Content-Length, strict ASCII headers and typed failures; independent peers check canonical request/response bytes, fragmentation, invalid requests/400, EOF and no-body statuses. Blocking read/write syscalls have explicit timeouts; no strict overall message deadline is claimed. -- `parallel_each` reuses static handlers/sequence classification and adds a bounded producer/worker owner with explicit worker limits, fault cancellation at pull boundaries and joined completion. Stream remains producer-owned; worker inputs/context cannot recursively contain Stream. -- Ordinary last-use moves and transferred reduction state preserve live aliases and output/field order. Resource-containing locals retain lexical lifetime; a differential socket regression verifies no premature peer EOF. Full-domain Int/Decimal guards omit redundant comparisons without altering bounded clauses. -- Passed 25 targeted core/library tests: `standard_library` 5, `native_ownership` 3, `concurrency` 4 and opt-in `differential` 13. `formatter` passed 11 tests including added/renamed source snapshots and all current official packages/examples. JSON passed 7 and HTTP passed 8 in worker validation; the main agent independently reran Unicode/exact-number JSON and the real HTTP server wire/400 case. Production CLI feature resolution excludes `reference`. -- Actual CLI `check`, `fmt`, `run` and `build` succeeded for `examples/library/src`; normal run and a standalone executable under `env -i PATH=/nonexistent` printed `json = {"message":"你好 Dever","total":6}` and `http_roundtrip = true`. -- Independent final review found no remaining blocker in formatter, reference, ownership, numeric domain optimization, concurrency and JSON after the snapshot fix. Main-agent HTTP review checked framing/status/timeout contracts. Database selection remains pending rather than implicitly chosen. -- Passed the explicitly ignored performance target on Linux x86-64, CPU affinity 4, Rust 1.98.0, cached runtime, optimization level 3 and one codegen unit. Each side used five alternating processes and 45 effective samples. Native/baseline median ratios: checked Int 0.952, Float 1.000, List each/filter/sum 0.207, Decimal 1.001, ordered Map 1.145; all met 1.15. Native build times were 1,206–1,793 ms, baseline compile times 255–668 ms, recorded separately from execution. These figures cover the selected kernels only. -- Decimal comparison was corrected to use identical lexical `0.0` representation with baseline parsing outside timing. Map diagnostics identified missed generic hash-table inlining under multiple codegen units; production and baseline now share one optimization-argument constant. This changes compiler optimization scope without changing hashing, panic, arithmetic or value semantics; it trades compilation parallelism for optimization consistency. -- After the final native compiler setting, all 13 differential cases passed again, including exact fault traces, signed zero, Map semantics and resource lifetime. Strict Clippy/type checks passed for core/runtime/CLI and every new test target; targeted rustfmt and explicit whitespace checks passed. The complete follow-through has 51 functional tests plus one five-kernel performance gate, not a full workspace test run. -- No full suite, existing service, external database, global toolchain/command change, Git commit or archive. Distribution/cross-platform remains deferred; self-hosting is still unshipped. - -- Status: Approved core foundations and foundation extension implemented and verified on 2026-09-07 -- Requirement source: `prd.md` -- Architecture source: `design.md` -- Execution mode: one tightly coupled task; no obsolete child-task dispatch - -## Completed Foundation Delivery Rule (Historical) - -Implement the foundation extension as one bounded delivery: `reduce`, `reduce_until`, Bytes traversal, `Stream`, restricted static handler inputs, file/TCP stream wrappers and focused verification. Reuse the existing collection checker, typed HIR, intrinsic catalog, native emitter and resource owner; do not build a parallel execution path. Compiler distribution, cross-platform work, formatter/evaluator work and full HTTP/JSON/CRUD/database packages remain deferred. The completed core and hello milestones are regression baselines; the old API and original phase checklists are historical. - -## Foundation Extension Checklist (Authoritative, Complete) - -### 1. Syntax And Semantic Contracts - -- [x] Parse contextual `handler(inputs) (named_outputs)` only in function input declarations, using a dedicated AST input kind rather than an ordinary value type. -- [x] Parse `Stream` through the standard generic-type path; reject wrong arity, nullable handler signatures and handler syntax in fields, outputs or local/value positions. -- [x] Add semantic `HandlerSignature` and handler-parameter symbols separately from runtime `Type`; add opaque `Stream(Item)` to the type model with non-comparable, non-Map-key resource semantics. -- [x] Centralize handler compatibility, allowed reference positions and sequence element classification so direct calls, forwarding, `each`, `reduce` and `reduce_until` cannot drift. - -### 2. Typed HIR And Static Specialization - -- [x] Replace collection-only handler IDs with shared `HandlerTarget`, `CallTarget` and handler/value call arguments. -- [x] Lower direct handler calls and multi-level forwarding without storing handlers in value locals or aggregates. -- [x] Key native specializations by function plus ordered concrete handler bindings, substitute every forwarded target, and emit only direct calls. -- [x] Detect direct and indirect cycles in the substituted specialization graph before private Rust compilation. - -### 3. Sequence Operations - -- [x] Add `reduce` and `reduce_until` to the single standard-operation registry and HIR, with exact state and `stop: Bool` output contracts. -- [x] Lower List and Bytes traversal as left-to-right direct loops; emit Bytes elements as Int values without an intermediate List. -- [x] Extend `each` to Bytes and zero-output Stream consumption while preserving existing List mapping/action behavior. -- [x] Leave `filter`, `find` and `sum` List-only and reject implicit Stream collection. -- [x] Add idempotent zero-output `close(stream)` and reject it for non-Stream values. - -### 4. Stream Runtime And Official Packages - -- [x] Add one generic runtime Stream owner with shared cursor/end/close state and serialized pull/close operations; do not add prefetch, threads or async machinery. -- [x] Implement natural EOF, one terminal typed failure item, idempotent close, alias continuation after `reduce_until`, and release of only the Stream-held source alias. -- [x] Add `ReadEvent`, `ReadStreamResult` and `chunks` to bundled `dever.io`; add socket `chunks` and listener `connections` to bundled `dever.net`. -- [x] Extend fixed `dever.system` intrinsic signatures and generated typed adapters only for Stream creation/pulling; keep public result choices in `.dever` source and OS/resource mechanics in runtime. -- [x] Preserve existing one-shot read/write/accept/close contracts without compatibility aliases or behavior changes. - -### 5. Focused Verification And Cleanup - -- [x] Add parser/semantic negatives for handler placement, type/arity/output mismatch, forbidden storage/return/comparison/clause use and indirect recursion. -- [x] Add native List/Bytes cases for empty input, order, state typing, stop behavior, zero-output each and absence of intermediate Bytes allocation. -- [x] Add runtime/native Stream cases for shared aliases, natural EOF, early stop/resume, repeated close, source close, invalid limit and one terminal failure. -- [x] Compile official wrappers through the normal source loader and test file chunks plus loopback socket chunks/connections with owned resources, bounded data and timeouts. -- [x] Exercise actual CLI `check`, `run`, `build` and the resulting standalone executable with a chunked state-parser fixture whose behavior is defined in `.dever`. -- [x] Run focused formatting/type/lint/test checks only, inspect generated code/artifacts for direct handler calls, validate Trellis context and run whitespace checks. -- [x] Review the final diff for duplicate contracts, runtime handler dispatch, eager Stream collection, HTTP/JSON leakage and unrelated changes; update the canonical specs and implementation evidence. - -Planned focused validation targets: - -```bash -cargo test --offline -p dever-tests --test syntax_and_format -cargo test --offline -p dever-tests --test core_semantics -cargo test --offline -p dever-tests --test core_native -cargo test --offline -p dever-tests --test runtime_foundations -cargo test --offline -p dever-tests --test hello_native -cargo check --offline -p dever-core -p dever-runtime -p dever-cli -python3 ./.trellis/scripts/task.py validate 09-04-dever-language-mvp -git diff --check -``` - -Filters will be replaced by the concrete test names introduced during implementation. No full suite, workspace-wide test, performance gate, service start, external network call or global command mutation is authorized. File tests use test-owned temporary directories; TCP tests bind only `127.0.0.1:0` and terminate within explicit bounds. - -Rollback boundaries are syntax/semantic representation, HIR/specialization, finite sequences, runtime Stream and official wrappers. A boundary is not accepted while it relies on a runtime function value, duplicated checker rule, eager collection fallback or partially exposed public API. - -## Foundation Extension Evidence (2026-09-07) - -- Handler inputs use dedicated syntax, semantic symbols and HIR arguments. Clause coverage and runtime locals traverse value parameters only. One specialization graph resolves direct and multi-level handler forwarding, records real cross-package handler references and rejects substituted recursion; generated functions contain direct calls and no user-handler function values. -- `reduce`, `reduce_until` and `each` reuse one sequence classifier. List and Bytes lower to direct left-to-right loops, Stream pulls on demand, and `reduce_until` does not pull past the stopping item. Bytes traversal yields Int directly without constructing a List. -- Runtime `Stream` shares cursor/end/close state across aliases and serializes pull/close. File/socket chunks validate creation, release their producer at EOF or after one terminal failure, and support early-stop continuation. Bundled `dever.io` and `dever.net` expose source-defined stream choices through the normal loader. -- Passed `cargo check --offline -p dever-core -p dever-runtime -p dever-cli` and strict Clippy for core/runtime/CLI plus the root test crate. `cargo fmt --all --check` passed. -- Passed 74 focused tests: 22 `syntax_and_format`, 16 `core_semantics`, 16 `core_native`, 8 `runtime_foundations` and 12 `hello_native`. File tests owned their temporary directories; TCP tests used `127.0.0.1:0`, explicit timeouts and bounded transfers. -- Final review made handler signatures reuse ordinary nested Map validation, preserved `Pull::Last` through mapped official streams, and added generated-code plus official creation-failure regressions. An independent read-only review then found no blocking correctness, safety or contract issue. -- Actual CLI `check`, `run` and `build` succeeded for `examples/stream/src`; run and the standalone executable both printed `total = 208`. The executable also ran with an empty environment and no Cargo/Rust path. -- No formatter/evaluator, async/concurrency system, HTTP/JSON/database package, external service, full workspace test, benchmark, distribution change, global command change or commit was included. - -## Active Core Checklist - -- [x] Record clause-only conditional dispatch as a permanent language rule and remove conditional blocks from the deferral list. -- [x] Retain settled repetition rules and remove the redundant planning blocker. -- [x] Record the user's approval and map the implementation boundary to core language and system interfaces. -- [x] Implement scalar/aggregate types, complete symbols, expressions, outputs and value-semantic assignments. -- [x] Implement clause type inference, normalization, overlap/exhaustiveness analysis and typed native dispatch. -- [x] Implement numeric and collection runtime operations plus shared intrinsic contracts. -- [x] Compile bundled official source and implement Bytes/file/TCP resource foundations. -- [x] Verify focused semantic/native/runtime cases and review the final cross-layer changes. - -## Core Foundation Evidence (2026-09-07) - -- Implemented six scalars, records/choices/nullable/List/Map/MapEntry, typed expressions, named outputs, stable assignments and value semantics through check/HIR/native execution. Added naming and unused-write diagnostics. -- Function groups infer one signature, use symbolic per-axis domains and rectangle subtraction to prove disjoint coverage, and lower into concrete native dispatch. No conditional blocks, source loops or user recursion were introduced. -- Official source in `library/` shares the same frontend; one intrinsic enum bridges the small system boundary. Decimal128 and ordered maps reuse pinned `dec`/`indexmap` runtime wrappers. Added Bytes, create-new/read-only files, TCP and shared-close opaque handles with explicit source-defined result choices. -- Passed 46 focused tests: 13 `core_semantics`, 9 `core_native`, 5 `runtime_foundations`, 12 existing `hello_native`, and 7 relevant `syntax_and_format` source/diagnostic regressions. Runtime tests used owned temporary files and loopback port 0 only. No full suite or integration environment was run. -- Passed targeted rustfmt and strict Clippy/type checks for compiler/runtime/CLI and affected test targets. Existing tool archives were invoked with command-scoped paths; a local ignored verification wrapper supplies the toolchain library path after Cargo sanitizes its environment. No global installation or environment changes. -- Actual CLI `run examples/core/src app.main` produced all 22 expected named outputs. `check` succeeded with nonexistent RUSTC. `build` produced `target/dever-core-example`, confirmed as a native Linux x86-64 ELF, and it produced the same outputs with `env -i PATH=/nonexistent`. -- Independent read-only review found and closed duplicate choice Map keys, Group-sensitive inference, null-only `first`, and Float signed-zero constant propagation. Added semantic/native regressions; Float literal contextual typing does not retype existing Decimal/Int locals. -- The initial wrapper/fixture errors and one stale numeric rejection fixture were corrected; final affected checks passed. Trellis context validation passed with implementation/check JSONL absent and skipped for inline work. Ordinary `git diff --check` passes but does not inspect the untracked compiler files; targeted formatting and explicit new-file whitespace checks cover those files. -- Formatter, reference evaluator/differential checks, performance gates, full HTTP/JSON/database packages, self-hosting and distribution/cross-compilation were not implemented or claimed by this delivery. No commit/archive; the wider language task remains active. - -## Completed Hello Checklist - -- [x] Correct the superseded API-first requirements and record the approved Text/action subset. -- [x] Add package/function resolution, semantic diagnostics and checked HIR. -- [x] Add standard output runtime and native compilation. -- [x] Add local check/build/run CLI and `examples/hello/src/app/user.dever`. -- [x] Run focused semantic/native/runtime tests and the actual hello command; announce local process execution first. -- [x] Review the final changes, update implementation evidence and record the session. - -## Native Hello Evidence (2026-09-06) - -- Implemented the approved Text/action subset, checked HIR, shared stdout runtime, native Rust generation and local `deverc` CLI. Example: `examples/hello/src/app/user.dever`. -- Passed 12 `hello_native` tests and the existing 20 `syntax_and_format` tests. After the final emitter readability change, reran all 12 native tests successfully. -- Passed rustfmt and strict Clippy for core/runtime, both targeted test binaries and the actual CLI binary. -- Actual CLI `check` succeeds even with a nonexistent RUSTC, proving it does not invoke compilation. `run` prints exactly `hello\n`; an unknown entry returns exit 1. `build` produced `target/hello-user`, identified as a native x86-64 ELF, which prints `hello\n` with PATH containing no Rust tools. -- Independent read-only reviewer found no blocking issue; the noted CLI verification gap was closed by the actual commands above. Tests exercise Unicode/escaping, source locations, value semantics and write failures, not a User/hello-specific execution branch. -- Added README run/build instructions and updated owning compiler specs. No global command replacement, external dependency, commit, service, database or load test. -- This bounded milestone is complete. The overall language roadmap remains open; HTTP/JSON/CRUD and persistence are deferred pending the user's next step. - -Preserve unrelated changes and do not create a commit without explicit authorization. Verification for the new API must use its own local process and test storage, with functional checks and bounded performance checks described before execution. Do not test against, restart or benchmark existing services. No runtime or load check has been run during this planning turn. - -## Historical API Replanning Checklist (Deferred) - -- [x] Record the real user API goal and supersede the pure-computation-only boundary. -- [x] Keep `.dever` source and the existing surface syntax; defer the speculative contract-declaration system. -- [ ] Confirm persistence selection. -- [ ] Specify typed HTTP/JSON/storage boundaries and necessary effect/concurrency semantics. -- [ ] Finalize user API behavior and meaningful performance acceptance. -- [ ] Replace the next execution steps with a bounded native application delivery plan. -- [ ] Review the concrete plan with the user before implementation. - -Proposed delivery order, to finalize after the open product decisions: - -1. Implement name/type/clause/flow checking and HIR for the language features the API actually uses. -2. Establish concrete native business-function execution and source-located failures. -3. Add typed HTTP/JSON boundaries, explicit resource/effect semantics and the selected persistent database adapter. -4. Implement `examples/user-api` entirely in `.dever`, with real CRUD and configuration supplied by the runtime environment. -5. Run announced, isolated functional/persistence/concurrency checks and a bounded native performance comparison. - -Complete Decimal/Float/Map libraries, the full reference evaluator, formatter, component distribution and AI indexing remain on the roadmap; they are not all prerequisites for the first user API. Preserve unsupported-source diagnostics rather than silently approximating unimplemented language behavior. - -## Initial Frontend Evidence (2026-09-05) - -- Implemented: dependency-free Rust workspace, source directory loading, UTF-8 and line/column handling, deterministic diagnostics, lexer, spanned AST and parser. -- Passed: 20 focused `syntax_and_format` tests, including the complete PRD package; Rust formatting check; focused Clippy with `-D warnings`; diff whitespace check. -- Independent review: fixed iterative expression-tree depth bypass and removed inaccurate terminal-width caret rendering. Follow-up review confirmed both fixes. -- Validation tools: rustc/Cargo 1.98.0 are installed but absent from the default PATH. Rustfmt and Clippy were missing, so their exact 1.98.0 official archives were downloaded to ignored `target/verification-tools/`, checked against the installed Rust manifest SHA-256 values and invoked directly with command-scoped library/tool paths. No global toolchain installation or command replacement occurred. -- At that checkpoint, native/differential/performance checks had not run. The Native Hello Evidence above records the subsequently implemented and verified native subset. -- The previous API-first next step was superseded by the approved hello-world milestone; formatter and other language work remain on the roadmap. - -## Historical Original Roadmap Notice - -The phase checklist below records the original repository bootstrap plan. Its unchecked boxes are not the current implementation status and do not expand the authoritative extension above. The Active Core Checklist and dated evidence describe completed work. - -## Phase 1: Initialize The Repository - -### 1.1 Preserve and classify current changes - -- [x] Record `git status --short`; current changes contain planning and agent metadata, plus two deleted old documents. -- [x] Confirm no old Rust workspace, implementation or test files exist in the working tree or HEAD. -- [x] Preserve existing user changes; no old implementation needs removal. - -### 1.2 Establish the new workspace - -- [x] Create `crates/dever-core` as the single language library. -- [ ] Add `crates/dever-runtime` in Phase 7 when numeric/fault consumers exist; keep parser, checker, HIR and evaluator code out of it. -- [ ] Add `crates/dever-cli` in Phase 10 for the `dever` binary; do not expose syntax-only success as the public semantic `check` command. -- [x] Create `test/dever-tests` as the only permanent test crate. -- [x] Create root `Cargo.toml`; pin external dependencies when they are first consumed. -- [ ] Add a decimal128 dependency behind `dever-runtime::number` and reuse that wrapper from the evaluator. -- [ ] Add an insertion-ordered map dependency behind `dever-runtime::collections` and reuse that wrapper from the evaluator. -- [x] Do not add parser generators, async runtimes, plugin systems or CLI frameworks. - -### 1.3 Establish current rules - -- [x] Confirm the rejected prototype and its fixtures/tests are absent; do not add migration scaffolding. -- [x] Preserve existing deletion of superseded plan/spec documents. -- [x] State in `AGENTS.md` that `.dever` source is the trusted source. -- [x] Replace relevant Trellis spec placeholders with the actual frontend ownership and verification rules. - -Rollback point: kickoff adds compiler files and updates canonical planning only; existing user deletions and unrelated metadata are preserved. - -## Phase 2: Source, Diagnostics And Lexer - -### 2.1 Source ownership - -- [x] Implement `SourceId`, `SourceFile`, `SourceMap` and half-open `Span`. -- [x] Precompute line starts and render stable one-based line/column positions. -- [x] Load `.dever` paths in lexical order and reject invalid UTF-8. - -### 2.2 Diagnostics - -- [x] Implement the shared diagnostic model; semantic phases will consume it when implemented. -- [x] Support primary and related spans plus stable diagnostic codes. -- [x] Sort diagnostics deterministically. -- [x] Add renderer tests for the syntax-phase messages, related source files and Unicode locations. - -### 2.3 Lexer - -- [x] Tokenize identifiers, keywords, delimiters, operators, newlines and comments. -- [x] Preserve numeric spelling and comment trivia. -- [x] Decode Text escapes with precise bad-escape diagnostics. -- [x] Reject non-ASCII identifiers while allowing UTF-8 strings/comments. - -Focused checks: - -```bash -cargo test --offline -p dever-tests --test syntax_and_format -``` - -## Phase 3: Parser And Formatter - -### 3.1 Syntax tree - -- [x] Define focused AST nodes for package, type, function clauses, patterns, statements and expressions. -- [x] Keep every node spanned; do not attach resolved IDs or runtime values. -- [x] Preserve ordered comments with source spans; formatter attachment remains part of Phase 3.3. - -### 3.2 Recursive-descent parser - -- [x] Parse the package header and exposure list. -- [x] Parse record and choice type declarations. -- [x] Parse function signatures, clause patterns and linear bodies. -- [x] Parse record/List/Map values, calls, field access and operators with fixed precedence. -- [x] Recover only at bounded declaration/statement delimiters. -- [x] Reject excluded constructs rather than accepting compatibility syntax. - -### 3.3 Canonical formatter - -- [ ] Format every valid syntax node from structure. -- [ ] Preserve comments and normalize whitespace, blank lines and indentation. -- [ ] Add parse-format-parse and twice-format idempotence tests. -- [ ] Refuse to rewrite invalid files. - -Focused check: - -```bash -cargo test -p dever-tests --test syntax_and_format -``` - -Milestone boundary: the parser is currently an internal library for focused tests. Do not expose a public checked-source or formatting command until its complete contracts are implemented. - -## Phase 4: Package And Name Resolution - -- [ ] Register package/type/function headers before resolving bodies. -- [ ] Validate path/package equality and one-file ownership. -- [ ] Load only the supplied source root and fixed standard catalog; do not search external paths or perform network access. -- [ ] Reserve core single-segment package names and `dever.*` against local declarations. -- [ ] Validate `exposes` against locally declared names. -- [ ] Resolve local short names and cross-package fully qualified names. -- [ ] Enforce visibility without import tables. -- [ ] Group same-name/same-arity clauses and enforce contiguity. -- [ ] Reject package, recursive type and direct/indirect function cycles. -- [ ] Include standard core and qualified package names through one fixed catalog. -- [ ] Report unavailable future official/third-party references as unknown packages without an implicit install fallback. - -Focused check: - -```bash -cargo test -p dever-tests --test package_resolution -``` - -## Phase 5: Type Checking And Linear Flow - -### 5.1 Type interning and declarations - -- [ ] Implement scalar, record, choice, nullable, List, Map, MapEntry, Stream and multi-output types, with static handler inputs represented separately from values. -- [ ] Reject record/choice member mixing and recursive user types. -- [ ] Validate choice payload arity and record completeness. -- [ ] Validate Map key eligibility. - -### 5.2 Expressions and calls - -- [ ] Check literals using expected type without premature numeric conversion. -- [ ] Implement operator tables exactly as specified in the PRD. -- [ ] Permit only lossless Int-to-Decimal implicit promotion. -- [ ] Resolve positional function calls and named multi-output access. -- [ ] Restrict named handler references to sequence operations, direct static invocation and approved handler-input forwarding. - -### 5.3 Definite assignment and mutation - -- [ ] Track uninitialized/initialized locals in one forward pass. -- [ ] Reject reads and field writes before complete initialization. -- [ ] Require every output on every clause path. -- [ ] Keep a local's inferred type stable across reassignment. -- [ ] Report unused writes without adding defensive runtime behavior. - -Focused check: - -```bash -cargo test -p dever-tests --test type_checking -``` - -## Phase 6: Clause Analysis And Typed HIR - -### 6.1 Normalize patterns - -- [ ] Normalize Bool, null, choice, scalar constant and `other` patterns. -- [ ] Normalize Int/Decimal comparisons into open/closed intervals. -- [ ] Support at most one lower and one upper bound joined by `and`. -- [ ] Reject Float ranges and dynamic/function-based guards. - -### 6.2 Prove clause validity - -- [ ] Compute overlap, reachability and exhaustiveness over symbolic domains. -- [ ] Support products of multiple input domains without enumerating numeric values. -- [ ] Emit diagnostics that label both conflicting clauses or the uncovered domain. -- [ ] Prove that permuting source clauses leaves the normalized decision model unchanged. - -### 6.3 Lower typed HIR - -- [ ] Lower only fully checked packages. -- [ ] Replace names with resolved IDs and attach static types/spans. -- [ ] Build decision nodes from normalized clause domains. -- [ ] Keep HIR internal to `dever-core`; do not serialize it as a second source format. - -Focused check: - -```bash -cargo test -p dever-tests --test clause_analysis -``` - -Rollback point: do not add an ordered first-match fallback if coverage analysis is incomplete. Unsupported patterns must fail compilation. - -## Phase 7: Values, Numbers And Reference Evaluator - -### 7.1 Runtime values - -- [ ] Implement the language-owned `Value` variants. -- [ ] Use shared immutable aggregate storage with copy-on-write updates. -- [ ] Wrap insertion-ordered Map behavior and use order-preserving removal. -- [ ] Implement deterministic value rendering and named output order. - -### 7.2 Numeric layer - -- [ ] Implement checked i64 arithmetic, including negative division/remainder edges. -- [ ] Wrap Decimal128 Context with round-half-even and per-operation status clearing/checks; accept inexact/rounded and fault on overflow, underflow, division by zero or invalid operation. -- [ ] Reject Decimal special values at the `DecimalValue` boundary. -- [ ] Implement exact Int-to-Decimal and explicit Int-to-Float conversion. -- [ ] Reject inexact Decimal literals while allowing specified inexact/rounded arithmetic results. -- [ ] Implement f64 arithmetic and IEEE classification functions without fast math. -- [ ] Add Decimal conformance and numeric fault fixtures. - -### 7.3 Evaluator - -- [ ] Execute HIR with explicit frames and no mutable global state. -- [ ] Select clauses through compiled decision nodes. -- [ ] Preserve source-level value semantics during local and field mutation. -- [ ] Return named outputs or an uncatchable `RuntimeFault` with source span. -- [ ] Add a Dever call trace only as diagnostic context. -- [ ] Keep evaluator entry points internal to compiler tests; production `build` and `run` must not depend on them. - -Focused checks: - -```bash -cargo test -p dever-tests --test value_semantics -cargo test -p dever-tests --test numbers -cargo test -p dever-tests --test failures runtime -``` - -## Phase 8: Standard Functions - -- [ ] Define one static signature/evaluator catalog for core and qualified standard names. -- [ ] Implement `append`, `first`, `get`, `put`, `remove` and `entries`. -- [ ] Implement `each`, `reduce`, `reduce_until`, `filter`, `find` and `sum` with shared sequence/handler helpers. -- [ ] Enforce one optional context and element-first handler inputs. -- [ ] Preserve order and short-circuit `find`. -- [ ] Keep Float sum left-to-right. -- [ ] Implement minimum `text`, `decimal`, `float` and `math` functions used by the PRD. -- [ ] Do not add unrequested collection aliases, lazy Stream transforms or reduction names besides `reduce` and `reduce_until`. - -Focused check: - -```bash -cargo test -p dever-tests --test collections -cargo test -p dever-tests --test numbers standard_functions -``` - -## Phase 9: Native AOT Compilation - -### 9.1 Whole-program specialization - -- [ ] Start from one checked, exposed, zero-input entry function and collect its reachable HIR. -- [ ] Specialize every concrete record, choice, nullable, List, Map, Stream and static handler-binding combination. -- [ ] Lower clauses to deterministic native decision trees and collection functions to direct loops. -- [ ] Perform last-use/liveness analysis so dead sources move instead of clone while observable value semantics remain unchanged. -- [ ] Reject any native path that would require a generic runtime `Value`, reflective lookup or virtual per-element dispatch. - -### 9.2 Private Rust emission - -- [ ] Emit concrete Rust types and direct functions from typed HIR through one structured writer with centralized identifier/literal escaping. -- [ ] Emit explicit checked numeric and source-located runtime-fault operations. -- [ ] Make generated programs depend only on `dever-runtime`, never `dever-core` or the evaluator. -- [ ] Keep generated Rust and Cargo metadata in a compiler-owned transient directory with no public emit command. -- [ ] Compile with an optimized release profile starting at opt-level 3, thin LTO and one codegen unit. -- [ ] Translate toolchain failures into stable compiler diagnostics without leaking generated identifiers as Dever names. - -### 9.3 Native conformance and performance - -- [ ] Differentially compare evaluator and native outputs/fault categories across the language conformance corpus. -- [ ] Inspect native artifacts to prove the evaluator is not linked. -- [ ] Benchmark scalar arithmetic and List `each`/`filter`/`sum` against equivalent safe Rust using the same algorithm, data layout and toolchain. -- [ ] Benchmark Decimal and ordered Map separately against Rust baselines using the same underlying semantic wrappers. -- [ ] Fail the performance gate when representative median native hot-path time exceeds 1.15 times the matching Rust baseline. - -Focused checks: - -```bash -cargo test -p dever-tests --test native -cargo test -p dever-tests --test differential -cargo test -p dever-tests --test performance -- --ignored -``` - -Rollback point: the evaluator remains the semantic oracle, but an incomplete native backend cannot silently become the production `run` path. Unsupported lowering is a compile diagnostic. - -## Phase 10: CLI And End-To-End Example - -### 10.1 CLI - -- [ ] Implement `check`, `fmt`, `build` and `run` as thin adapters. -- [ ] Do not add registry, `add`, `update`, signature or component-cache commands in Core 0.1. -- [ ] Validate exact argument counts and stable exit codes. -- [ ] Keep diagnostics on stderr and results on stdout. -- [ ] Make `fmt` all-or-nothing when any source file is invalid. -- [ ] Restrict `build` and `run` to exposed zero-input functions. -- [ ] Make `build` write an optimized native executable to `--output` and make `run` compile/execute the same native path. -- [ ] Keep the Cargo binary and canonical command name as `dever`; do not rename compiler internals or public command semantics to `deverc`. -- [ ] Treat `deverc`, when explicitly installed for coexistence, as a thin link or launcher to the same compiler binary with no divergent behavior. -- [ ] Do not replace the existing framework `dever`, modify system `PATH` or create global executables during repository implementation or automated tests. -- [ ] If global `deverc` setup is later authorized, resolve and record both command targets and verify that the existing global `dever` remains unchanged. - -### 10.2 Example and integration - -- [ ] Add the canonical account/user package from the PRD. -- [ ] Add a zero-input executable example covering types, clauses, collections and numbers. -- [ ] Verify multiple source files and full qualification. -- [ ] Verify the zero-input example produces identical evaluator and native results. -- [ ] Ensure no example source depends on Rust, JSON graph, React or a hidden host fallback. - -Focused check: - -```bash -cargo test -p dever-tests --test cli -``` - -## Phase 11: Cleanup And Final Verification - -### 11.1 Structural review - -- [ ] Search for duplicate operator, standard-function, diagnostic and type rules. -- [ ] Keep each language rule owned by one table/module. -- [ ] Remove obsolete compatibility code, commented code, placeholders and old architecture references. -- [ ] Confirm the CLI contains no language semantics. -- [ ] Confirm no public Rust API leaks into `.dever` diagnostics or docs. -- [ ] Confirm generated binaries depend on the minimal runtime but not compiler/evaluator modules. -- [ ] Confirm private generated Rust is not documented or tested as a public compatibility format. - -### 11.2 Acceptance mapping - -- [ ] Map all 20 PRD acceptance criteria to named test cases. -- [ ] Run each relevant focused test target. -- [ ] Run static formatting and diff checks. -- [ ] Record passed, failed, skipped and not-run checks separately. - -Permitted final checks, announced before execution: - -```bash -cargo fmt --check -cargo check -p dever-core -p dever-runtime -p dever-cli -cargo test -p dever-tests --test syntax_and_format -cargo test -p dever-tests --test package_resolution -cargo test -p dever-tests --test type_checking -cargo test -p dever-tests --test clause_analysis -cargo test -p dever-tests --test value_semantics -cargo test -p dever-tests --test collections -cargo test -p dever-tests --test numbers -cargo test -p dever-tests --test failures -cargo test -p dever-tests --test native -cargo test -p dever-tests --test differential -cargo test -p dever-tests --test cli -python3 ./.trellis/scripts/task.py validate 09-04-dever-language-mvp -git diff --check -``` - -The performance test is an explicit, separately announced gate and is not part of the default test list. Do not substitute `cargo test --workspace`, `npm run build` or service/integration tests. If a focused check reveals a shared compiler defect, fix the owning implementation once and rerun only affected targets. - -## Finalization - -- [ ] Run `trellis-check` after implementation. -- [ ] Update canonical Trellis specs for the new crate ownership and language rules. -- [ ] Review the final diff against PRD scope and remove accidental abstractions. -- [ ] Do not commit until the user explicitly authorizes a commit. -- [x] Confirm there are no obsolete planning children to archive. -# Active Compiler Contract Checklist (2026-09-08) - -- [x] Contract syntax, formatter and semantic metadata. -- [x] Field privacy, numeric facts, construction/write/output constraints. -- [x] Failure obligations and explicit recovery, including nested values and static handlers. -- [x] Transitive effects, package dependencies and API snapshot/CLI enforcement. -- [x] Evidence-backed redundancy diagnostics and application export analysis. -- [x] Official source/examples migration, targeted tests, native equivalence, docs/specs and final review. - -User approved the full contract implementation. Complete the list before claiming delivery. Keep earlier evidence below as historical; no full test suite, external services, distribution work or commit. - -## Compiler Contract Evidence (2026-09-08) - -- Implemented private record fields, normalized Int/Decimal field/payload/output/handler bounds, explicit error/recover and pure/depends. HIR facts reuse existing clause domains; handler boundaries support safe variance and concrete output inference without forcing wrapper annotations. -- Failure obligations follow copies, nested fields, calls and collections. Official Failed variants are explicitly marked; HTTP transport preserves earlier failure state and returns the inspected result with its stop decision. The Stream example now propagates a CountResult failure instead of silently returning zero. Presentation/test recovery reasons are explicit and consistent across clauses. -- Effects and recovery policies propagate through invoked static handlers. API generation is create-new; check/run/build compare an existing baseline. Adding a private recovering helper changes the effective public snapshot without exposing that helper's name. Depends includes normalized system resource types. W001 is reused; W002–W005 and entry-scoped W007 are advisory, not arbitrary abstraction requirements. -- Final six contract targets passed 47 tests: syntax 4, facts 16, semantics 10, API 9, redundancy 6, execution 2. Existing core semantics passed 16 (15 in the first run, W001 assertion narrowed to its diagnostic then rerun); existing syntax passed 22, formatter passed 11 and the new contracts example roundtrip passed. The independent expected-output core differential case passed. Forty-one migrated source fixtures were checked without executing their network/resource scenarios; the temporary probe was removed. -- Actual CLI api/check/run/build and standalone execution with `env -i PATH=/nonexistent` passed. A temporary source's new exposure was rejected by its unchanged baseline. `examples/contracts/src/dever.api` records the example's contract. Strict installed-driver Clippy/type checks passed for core/CLI and focused contract tests; formatting and explicit whitespace checks cover untracked files as well. -- Independent review found and closed empty-reduce seed consumption, primitive resource dependency omission, and exponential/deep proof graphs. Added positive/negative regressions; immutable shared fact/value graphs preserve aliases, proof work is capped at 16,384 and iterative nominal depth validation caps 128 before recursive analysis. Exhaustion reports C015; no incomplete proof becomes a successful Program. -- Updated LANGUAGE.md, IMPLEMENTATION.md, README and the owning compiler-contract spec. No database/distribution expansion, full suite, integration environment, existing service, global installation or Git commit. The umbrella task stays active for its previously deferred roadmap; this approved contract extension is complete. - -## Direct Example Roots And Coverage (2026-09-08) - -- Moved all five original source roots from `examples//src` to `examples/`, including the unchanged contracts API baseline. Removed empty src directories; package-relative nesting, such as hello/app/user.dever, remains. Updated executable test references, current guides and owning specs; earlier dated evidence retains its historical paths. -- Added sequences, text, privacy, parallel and system examples, bringing runnable roots to ten. Added six separately checkable rejected roots for C006/C009/C011/C012/C013/C014. The examples index documents commands, outputs, nondeterministic ordering, runtime input paths and explicit recovery boundaries. -- Reused compiler/check/native APIs in one example runner. Automatic discovery checks every runnable root and any baseline; formatter coverage discovers all examples, including rejection fixtures. No compiler or runtime behavior changed. -- Passed seven example-target tests covering all ten successful roots, nine native executions and six rejection cases; the existing core native test separately verified its 22 expected outputs. The targeted formatter roundtrip passed over every official/example source. Actual CLI contract check and expected C012 rejection passed; example fmt --check passed. Strict Clippy/type checks compiled all affected test targets, including feature-gated differential references. -- No full suite, network/service integration, compiler feature expansion, global installation, commit or archive. - -## Isolated PostgreSQL And Dual-source CMS Measurements (2026-09-18) - -- In a nonprivileged, owned PostgreSQL 16 instance with a private Unix socket and no TCP listener, the ignored `postgres_orm_uses_the_configured_isolated_database` test passed 1/1. Its shared schema cleanup left no test schemas. Added a focused live named-migration probe for bound before/after SQL, atomic rollback on after failure, successful DDL and once-only re-execution. Test connection came only from a temporary root `config/setting.json`; no database URL environment variable or existing PostgreSQL service was used. After verification, the temporary setting was deleted, the owned instance stopped and its test data removed. -- Focused `cms-profiles` build compiles both current `examples/cms/{dever,md}` source formats using one shared benchmark entry and separately builds base/SQLite/PostgreSQL/both runtime profiles. Artifacts: `target/performance/cms-dual-build-09-18-v2/manifest.json` and `profile-report.json`. Profile bytes: 411,352 / 2,558,200 / 2,708,112 / 4,672,888. CMS Dever/Markdown bytes: 3,151,352 / 3,151,416. -- `target/performance/cms-dual-rss-09-18/report.json` completed all six runs (three per source, READY=3 throughout). Dever/Markdown median readiness 19.87/19.69 ms, idle RSS 5.37/5.37 MiB, PSS 3.28/3.33 MiB, VmHWM 5.37/5.37 MiB. This is warm-cache initialization and bounded idle sampling, not throughput. No hard 64/128 MiB CMS budget or cgroup peak: the local controller is not writable. No broad/full suite, existing service check, or global installation. -- Benchmark runner unit tests pass 40/40; focused test compiled with `--features postgres`; Trellis task context validation passed. Rustfmt and Clippy are unavailable in the installed toolchain. This root roadmap remains in progress; API stays deferred pending its redesign, and hard-budget CMS stress requires a delegated cgroup environment. - -# Source Visibility And Module API Implementation (2026-09-18) - -- Replaced `package/exposes` syntax with path-derived package identity and explicit `public` for cross-package type/function visibility; fixed private `main.main` as the only run/build entry. Updated bundled sources, CMS Dever/Markdown roots, old runnable examples and Markdown metadata. The hello example now delegates through a public library function to its own `main.dever`. -- Added statically checked module `api/` routes with GET/POST/DELETE naming, recursive paths, private handlers and one `response` output. `dever.api.serve()` opts the application into routing and the existing bounded HTTP engine; typed inputs, JSON serialization and `{code,message,data}` envelopes reuse a single runtime adapter. Listener settings are read from `config/setting.json`, not environment variables; no CMS business API or authentication policy was added. -- Focused checks: core/CLI/runtime/tests cargo check passed; `source_visibility` 10/10, `syntax_and_format` 22/22, `core_semantics` 16/16, `formatter` 11/11 and `markdown_source` 20/20 passed. `api_routes` passed 7/7 before the final test adjustment, then its application-mode native compilation passed 1/1 with config bootstrap and no listener. An isolated temporary-project CLI `check/run/build` and API-baseline rejection test passed. Maintained examples, CMS Dever/Markdown source parity and rejection fixtures passed selected contract tests. Two ORM fixture static-check tests passed without database connections. `deverc check` passed for hello and both CMS formats (CMS retains W001 unused-write warnings). -- Not run: full suite, live HTTP/API service check, real PostgreSQL, CMS runtime/build or benchmarks. Rustfmt and Clippy binaries are unavailable in the installed toolchain. The umbrella task remains in progress for separately deferred roadmap work; historical entries above retain their original date/context. - -# AI-Oriented Source Architecture Implementation (2026-09-19, Complete) - -- [x] Add one shared source-role classifier and project-layout validation. -- [x] Replace application `public` visibility with automatic App capabilities and logical App aliases. -- [x] Enforce role dependency direction, API non-callability and Model-operation ownership. -- [x] Migrate the Dever and Markdown CMS sources from `service/` to component/domain roles without function-per-file fragmentation. -- [x] Update the language, Markdown and backend compiler/database contracts. -- [x] Add focused layout, visibility, API, Model and CMS parity tests; run only the affected checks. - -The implementation does not add environment variables, implicit HTTP startup, authentication policy, a new Port declaration syntax, or backward compatibility for the superseded application layout. - -## AI-Oriented Source Architecture Evidence (2026-09-19) - -- `SourceLayout` is the single main/component/domain/role/topic classifier. Strict project loading rejects loose application paths, generic buckets, role file/directory conflicts, nested non-API topics and one-file role directories. The check cache includes strict-layout identity; in-memory compiler fragments remain isolated from project-layout enforcement and cannot weaken CLI projects. -- App declarations receive stable `..` identities without exposing topic filenames. Role-aware lookup enforces Main/API/App/private-role direction, API non-callability and owning-domain Model operations. App signatures and inferred failures reject private type leakage. Port remains a reserved, rejected declaration role. -- Plain and Markdown CMS now contain only `main`, `user/account/{app,domain,model}` and `news/article/{app,model}`. Both forms have equal normalized declarations, Model/API snapshots and settings. Current examples contain no package/exposes/public syntax, old service/model roots or environment-variable configuration. -- The current performance packager now stages `benchmark//app.dever` plus generated `main.dever`; it no longer generates package/exposes headers or passes arbitrary entries to `deverc build`. ORM, profile, Dever CMS and Markdown CMS staged projects all passed actual CLI check. The CLI CMS regression test compiles against the fixed main-only interface and uses a test-owned App probe instead of injecting a loose root source. -- Focused verification passed: core/runtime/CLI Cargo check; `source_architecture` 8/8; `source_visibility` 10/10; `orm_performance_fixture` 3/3; `concurrency` 5/5 with its explicit benchmark ignored; CMS source/config parity 1/1; archived parallel and source-root native regressions passed after the synchronous typed-error fix. Earlier in this same phase `api_routes` passed 7/7. Actual CLI `check` and `fmt --check` passed for both CMS formats, and Python syntax checking passed for the performance builder. -- Not run: full workspace suite, live CMS `run/build`, `cms_project` integration execution, HTTP listener, real PostgreSQL, performance/size/RSS builds or 64/128 MiB stress. Rustfmt and Clippy components remain unavailable. The umbrella language roadmap stays in progress for separately deferred work. diff --git a/.trellis/tasks/09-04-dever-language-mvp/prd.md b/.trellis/tasks/09-04-dever-language-mvp/prd.md deleted file mode 100644 index b8022df..0000000 --- a/.trellis/tasks/09-04-dever-language-mvp/prd.md +++ /dev/null @@ -1,990 +0,0 @@ -# Dever Language Definition - -## N5:HTTP/2(已完成) - -用户在 P2 性能验证结束后批准继续接入 HTTP/2。使用 Hyper 实现 buffered/live 服务端和 single-use/pooled 客户端;复用既有请求/响应、TLS、AsyncStream 与 SSE 接口。Limits.http2 显式配置协议和每连接流数、接收窗口,TLS 必须协商 h2,明文使用 prior knowledge。每流取消隔离,Hyper 内部任务保留 Dever Scope,GOAWAY 排空不自动重试已发请求。详细验收以 `../09-12-http2/prd.md` 为准。 - -N5 已由 88 项定向测试、原生执行和独立审查验收。后续 HTTP/2 性能矩阵与有界稳态/恢复压测已由子任务完成;小时级稳定性、编译器发行/跨平台、自举及其余路线图仍未完成。 - -仅定向协议、生命周期与原生桥接验证;不重跑 P1/P2 性能矩阵,不改根任务调度,不接 RFC 8441、h2c Upgrade、推送、trailer、数据库或发行工具。下文各轮排除范围仅约束相应历史阶段。 - -## 已完成阶段 N4:并发组合与可复用网络客户端(2026-09-12) - -用户批准完成上一轮清单的 1 和 2。交付源码运行参数、静态 HTTP handler 的类型化上下文、任务超时/多路竞争等待、周期与 Channel 流、异步内存序列遍历;有界 HTTP 连接池、域名、流式请求/响应、HTTPS/WSS 客户端和 TLS 服务端。保留 N3 SSE/WS 会话、取消和背压契约。HTTP/2、数据库、协议扩展和分发工具不属于本轮。 - -任务、连接及正文队列有界;取消和关闭回收所属工作,已开始的阻塞工作必须排空。复用 Tokio、Hyper、tungstenite 和 Rustls,不维护兼容接口或自写协议栈。只运行定向编译/测试及自有 loopback 随机端口,不测旧性能基线,不启动现有服务,不提交。 - -以上范围已接通 checked source、原生编译和运行时。83 项定向用例、实际 CLI check/fmt/build 与无 Rust 工具链环境中的独立后端示例通过;具体证据见 implement.md 的 N4 Evidence,公开用法以 LANGUAGE.md 为准。 - -## 已完成阶段 N3:流式响应、SSE 与 WebSocket(2026-09-12) - -用户已授权“做下一阶段”,沿用新语言直接演进和低内存运行目标。保留普通 HTTP 的直接 handler 路径,增加 `serve_live` 和 HttpReply:同端口处理完整响应、逐块正文、SSE 和 WebSocket。HTTP 请求仍有界缓冲;响应通道只有 1 个槽位,长连接配置与普通请求期限分开。 - -WebSocket 服务端/客户端复用 tokio-tungstenite 0.30.0(handshake feature),提供 Text/Binary/Ping/Pong、AsyncStream 消息消费和关闭握手。SSE 提供字段编码、Last-Event-ID 访问和空闲注释心跳,历史重放归应用所有。HttpReply/WebSocket 进入编译器资源、类型、effects、API、Markdown 和 native 契约;不引入新语法、旧 API 兼容或自写 WebSocket 协议栈。 - -连接、handler 及升级后会话共用 Scope/Group 上限与取消排空;等待写锁时取消不能破坏另一任务的帧。仅执行根 test/ 下的定向编译器/运行时验证和自有回环端口,不测试旧性能基线、常驻示例或已有服务。TLS/WSS、HTTP/2、客户端池、子协议/压缩扩展、关闭帧元数据和数据库不属于 N3。 - -## 前一阶段 N2:HTTP 引擎(2026-09-12,已完成) - -用户在 N1 完成后批准继续。采用 Hyper 1.x HTTP/1 引擎、hyper-util TokioIo/Timer 和共享 bytes 缓冲区;不额外引入路由框架。此阶段取代历史“HTTP 全部由 Dever 自写”的实现决定。官方类型与静态业务 handler 仍由 Dever 定义,不保留旧协议 API 或备用解析器。 - -- `serve(async handler, Listener, Limits) -> ()`:持久连接、流水线、chunked 输入,复用现有有界任务组、背压、超时和取消清理。accept/配置/程序故障沿任务传播,对端协议错误只结束对应连接。 -- `send(address, port, Request, Limits) -> ResponseResult`:单次请求,无客户端池和重试,driver 与请求同生命周期。 -- Header 列表保留重复头和字节值;消息体在显式上限内缓冲,单帧共享,多帧增量合并。 -- 直接迁移示例、检查器、native bridge 和测试。只用离线定向检查、自有 loopback 随机端口,不测旧基线、不跑全量或现有服务。 -- TLS、HTTP/2、流式响应、客户端池、非空 trailer、WebSocket/SSE 留待后续;N3 优先处理长连接协议。 - -## 前一阶段 N1:异步 Stream 与 TCP(2026-09-12,已完成) - -用户批准继续,并明确这是全新的语言:无需旧源码兼容,不增加兼容别名、回退实现或推测性的防御分支。仓库调用方直接迁移。此决定取代下文历史阶段中的“网络暂停”和“兼容基线”要求。 - -- 增加 `AsyncStream`,支持在 async function 中按需 `each`、`reduce`、`reduce_until`,以及有界 `parallel_each`;handler 可为 async,关闭/提前结束释放生产端。 -- `dever.net` 直接采用 Tokio 异步 TCP;connect、listen、accept、read、write 为 async。资源名称仍为 Socket、Listener;无 sync/aio 两套 API。 -- 连接流和字节流不预取;并发消费先等待容量再拉取。复用现有结构化 Task/Group,停止后等待子任务清理,连接支持同时读写。 -- 保留协议必须的输入约束、失败输出、超时、关闭和取消语义;写入中断不得自动重发已写字节。 -- 现有 HTTP 传输调用链随 TCP 改为 async;成熟 HTTP 引擎接入属于 N2,WebSocket/SSE 属于 N3,本轮不实施。 -- 只做根 test/ 下定向检查及自己创建的 loopback 随机端口验证;不测旧性能基线,不运行全量测试、业务服务、全量 build 或全局安装。 - -## 前一阶段:并发基础(2026-09-12,已完成) - -前一阶段先完成同步、异步和多线程(含协程/任务)基础,网络当时暂停;当前 N1 恢复异步 Stream/TCP。下述并发契约已经进入编译器前端、HIR、原生后端和 runtime;最终状态以本任务的定向验证和 `LANGUAGE.md` 公开契约为准。不测旧实现性能基线。 - -### 暂存的网络方案 - -- 后续需要 TCP、HTTP、WebSocket、SSE 长连接,复用成熟 Rust 库。 -- 候选栈:Tokio 统一网络调度,Hyper/hyper-util 处理 HTTP,Axum 复用服务路由、升级和 SSE,WebSocket 复用其 tungstenite 生态,bytes 管理共享缓冲区。实施前核对版本、工具链和 feature 兼容性。 -- 共用连接限额、有界队列、背压、超时、取消与关闭。长连接保活独立于普通请求超时;SSE 事件历史保存/重放属于应用责任。 -- 不在每次 I/O 上 block_on,也不把同步阻塞 handler 直接放入异步调度线程。HTTPS/WSS、HTTP/2 的首轮范围尚未确定。 -- 取消旧性能基线工作,不取消新能力必要的定向正确性验证;不启动业务服务或压测。 - -### 并发语言契约(已批准实施) - -#### Goal - -增加可明确推理的同步、异步协程和多线程能力,为 TCP、HTTP、WebSocket 与 SSE 提供统一运行基础。小机器只运行打包后的二进制;空闲任务不占用一个系统线程,任务、线程和队列都有明确上限。契约可以直接演进,维护值/资源语义的清晰性,不承担旧源码兼容义务。 - -#### In Scope - -- 普通 function 保持同步;`async` 声明异步 function,`await` 等待异步调用或已启动任务。 -- `run` 启动异步调用并返回受限 Task;`stop` 采用“请求协作取消并等待清理完成”的安全语义,而不是仅发送信号。 -- 每个 async function 是默认结构化任务域;动态数量的零输出任务可由有界 `group` 统一拥有、等待和停止。 -- `parallel` 将 pure 同步计算交给有界多线程执行;`blocking` 供明确的阻塞边界使用。`parallel_each` 按序列类型复用相应的有界执行器。 -- 有界 `channel` 以及 `send`、`receive`、`close` 用于任务通信;禁止无界队列。 -- async 静态 handler、跨线程可传递性、任务消费、effects/failures、API 快照、Markdown 契约、格式化和原生代码生成均由编译器检查。 -- 运行时复用 Tokio 的协程与多线程调度;整个程序最多建立一个异步运行时,CPU/阻塞任务使用受限执行通道。 - -#### Out of Scope - -- 本阶段不实现 TCP、HTTP、WebSocket、SSE、TLS 或数据库;网络方案按上节暂存。 -- 不加入裸线程、共享可变全局对象、用户锁、分离后无人管理的后台任务、无界 channel、强杀线程或副作用回滚。 -- 不同时加入 lambda、闭包、一等 function、用户泛型、用户递归、循环块或异常机制。 -- 同步 `Stream` 保持当前阻塞拉取契约;异步流在网络恢复前单独设计,不做隐式转换。 - -#### Acceptance Criteria - -1. 完全同步的入口不启动 Tokio runtime;接口发生变化时直接迁移仓库源码。 -2. async function 和 async 静态 handler 的调用都必须直接位于 `await(...)` 或 `run(...)` 上下文;同步 function 中的异步调用在原生构建前拒绝。 -3. `await(call(...))` 顺序执行并保持原函数的命名输出;`task = run(call(...))` 先启动,`await(task)` 恰好消费一次任务并取得相同输出。 -4. Task 不能复制、存入 record/List/Map/Stream、作为普通参数/输出逃逸、重复等待或在 function 返回时仍未消费;必须 `await` 或 `stop`。 -5. `stop(...)` 第一阶段只接受零输出 Task 或 Group,协作取消并等待清理;已发生的副作用不回滚,长时间同步计算不承诺立即停止。 -6. `group(limit)` 的 limit 必须为正且有实现上限;只拥有零输出异步任务。容量已满时 `run(group, call(...))` 施加背压,不无限排队;`await(group)` 或 `stop(group)` 消费该 Group。 -7. `parallel(call(...))` 只接受 pure 同步 function,参数和输出必须可跨线程传递;`blocking(call(...))` 只接受编译器传递 effect 分析确认包含阻塞系统边界的同步调用。二者第一阶段只能用于 async function,并使用明确的有界容量;同步代码继续使用现有 `parallel_each`。 -8. `channel(Type, capacity)` 容量必须为正且有实现上限;send 在满时等待,receive 在空时等待并返回 `Item?`(值表示 Item,`null` 表示 Closed),close 唤醒等待方;调度器或 Channel 内部故障作为带源码位置的 fatal error 传播。 -9. async handler 的同步/异步属性是签名的一部分;所有同签名分句必须一致,专门化和递归检查不能因异步边界失效。 -10. 任务启动、等待、停止、channel、时间等待和 blocking 均进入传递 effect 分析;pure function 不能隐藏这些效果,失败义务不能因任务边界被吞掉。 -11. 异步入口只创建一次运行时;多个挂起任务不按任务创建线程。工作线程、阻塞线程、group、channel 与待处理任务均有保守默认上限及显式配置边界。 -12. 仅运行根 `test/` 下针对新增语法、检查、原生执行、取消/关闭和有界调度的离线定向测试;不跑全量测试、服务测试、旧实现基线或网络压测。 - -#### Key Naming Decisions - -- 保留 `async`、`await`、`parallel`、`blocking`、`channel`、`send`、`receive`、`close`。 -- 使用 `run` 代替 spawn,使用 `stop` 代替 cancel,使用 `group` 表示动态任务所有者;不再增加 join,统一由 `await` 等待。任务操作沿用函数式调用外观,不提供第二套前缀语法。 -- 协程是 async Task 的运行时实现,不增加 coroutine 关键字。 - -## Markdown Source Follow-through (2026-09-09) - -用户批准保留 `.dever`,新增 `.dever.md` 源码容器,并进一步要求编译器强制说明与代码一致。顶层 `dever` 或 `typescript dever` 围栏内写正常 Dever 声明,共用原有语法、契约、API 和原生路径。一个 H1 说明 package;每个 H2 只说明一个 type 或一个 `(函数名, 参数数量)` 及其全部分句。编译器核对 package 名、公开类型/方法/使用方式、类型字段/分支、函数输入输出的名称、类型、数量和顺序,空项显式写 `无`。`typescript dever` 的首个标记供编辑器尝试 TypeScript 语法高亮。跨格式同包重复拒绝;格式化保留说明,诊断定位原文并关联代码。此决定替代下方历史阶段“只加载 `.dever` 文件”及“标题说明无约束”的范围限制,不开放其它语言或 HIR/JSON 作为源码。正式写法见 `LANGUAGE.md` 的 Markdown 小节。 - -## Approved Performance Follow-through (2026-09-08) - -用户批准实施本轮性能方案。保持现有语法、值/资源语义、错误位置、数值顺序和编译器契约。交付类型属性缓存、依赖驱动契约分析、记录更新复制消除、独占列表消费、直接消费字符列表的遍历优化、HTTP 增量扫描、标准库及原生产物缓存。循环融合必须证明副作用和失败顺序等价;并发分批以有限测量为依据,不要求线程池。补编译/运行/内存定向基准并记录优化前后证据。只运行离线定向测试、自有临时文件/进程和内存协议输入,不运行全量或服务压测,不提交或安装全局命令。 - -## Current Follow-through (2026-09-07) - -用户在剩余项盘点后要求“实施剩下的”。继续完成已确定语言的工具、标准库和验证工作,并推进后续运行能力;既有语法、分句、静态 handler、值/资源语义保持兼容。下方历史里程碑的暂缓项不阻止本次明确要求的工作。 - -- 提供 `.dever` 的规范格式化及 CLI `fmt`/只读检查,保留注释、表达式含义和求值顺序;任一输入语法错误时不改写文件。 -- 补常用 Text、数值解析/格式化、进程参数/环境和时钟接口。公开接口与组合逻辑仍由普通 `.dever` package 定义。 -- 实现仅用于验证的 HIR 基准解释器,覆盖已实现核心语义并与原生结果、故障位置对照;生产 build/run 始终使用原生编译。 -- 实现保持值语义的最后使用优化,提供可复现、有限工作量的同语义性能基线,不对现有服务压测。 -- 继续推进 JSON、HTTP 与受控并发等官方包所需能力;协议与应用逻辑使用 Dever 基础语法,系统边界保持最小。 -- 数据库引擎此前未定,已向用户异步询问;这一选择不阻塞其余工作。 -- 编译器发行、跨平台沿用此前暂缓安排;自举仍是尚未交付的长期项。本次不安装或替换全局命令,不提交,不访问既有服务。 - -验收按每项真实完成的行为和定向证据记录,不将已完成的基础语法测试当作新增工具和库的验收。 - -## Goal - -当前目标是实现已经确定的基础语言,使官方 package 与应用能够用同一套 `.dever` 语法编写。2026-09-07 用户批准实现基础类型、表达式、函数输出、分句、赋值和值语义、集合与处理函数、统一 package 编译及最小系统接口。原生 Hello World 里程碑已于 2026-09-06 完成,作为回归基线。 - -长期目标仍是改善 AI 开发中的硬编码、重复实现、无依据兜底和大项目上下文问题。表面语法保留 package、type、function、分句和值语义;用户所说的“用户类”用已有 `type User` 表达,不引入 class 或继承。Rust 等引导技术不进入用户源码或语言兼容契约。 - -基础阶段曾将 HTTP、JSON 和性能验证后移;当前 Follow-through 已推进这些能力。编译器发行与跨平台仍暂缓,数据库引擎未定;用户 CRUD 示例不是基础语言的额外交付。保留原生执行方向和既有表面语法,不增加契约 DSL。 - -## Approved Core Implementation - -- 沿用既定条件分句、线性 body 和集合函数;不再把循环语法作为待确认项,不增加条件块、循环块或用户递归。 -- 每项语言能力贯通源码检查、typed HIR 与原生执行;不能以 AST 已解析代替支持。 -- 官方 `.dever` package 与本地 package 共用语言规则。官方命名空间由编译器随附源码提供,本地源码不能冒充官方来源。 -- 系统接口提供 Bytes、opaque 文件/TCP 资源、读写和显式关闭;普通值保持值语义,资源别名标识同一外部资源,关闭后操作得到显式失败。 -- 可恢复系统错误以官方源码声明的选择型结果返回;程序故障保持源码定位。系统原语不包含 HTTP 路由或应用业务。 -- 验收覆盖完整语言样例、负例诊断、分句顺序变化、集合顺序与值语义,以及隔离临时文件和本地回环连接。使用必要的最小定向检查,不运行全量测试、既有服务或压测。 - -## Approved Foundation Extension - -Status: implemented and verified on 2026-09-07. - -### Goal And Scope - -补齐官方 `.dever` package 编写协议解析、持续 I/O 组合和宿主回调所需的最小表达能力,同时保留分句条件、线性 body、无循环 block 和无用户递归的长期规则。本阶段一次完成 `reduce`、`reduce_until`、Bytes 遍历、`Stream`、受限静态 handler 参数,以及文件/TCP 的流式包装;不在 runtime 中加入 HTTP 或业务特例。 - -### Sequence Operations - -- 带状态遍历对外名称固定为 `reduce`;此前讨论中的 `fold` 和 `accumulate` 名称作废。 -- `reduce(handler, sequence, initial_state)` 固定从左到右执行,始终显式提供初始状态;空序列直接返回初始状态。 -- handler 依次接收当前元素和上一步状态,必须输出一个与状态类型相同的下一步状态: - -```dever -add(value: Int, total: Int) (next_total: Int) { - next_total = total + value -} - -total(values: List) (result: Int) { - result = reduce(add, values, 0) -} -``` - -- `reduce_until(handler, sequence, initial_state)` 使用相同顺序,但 handler 必须有两个输出:第一项是下一步状态,第二项必须命名为 `stop` 且类型为 Bool。处理完当前元素后,`stop` 为 true 就立即返回,不再请求下一个元素。 -- `reduce` 和 `reduce_until` 不提供额外 context 参数;共享配置应组合进状态,避免同一调用同时维护两套跨元素数据。 -- sequence 只接受 `List`、Bytes 或 `Stream`。Bytes 的元素静态类型为 Int,运行时值保证在 0 至 255,不先复制为 `List`。Text 如需按 UTF-8 遍历,必须显式使用 `dever.bytes.from_text`。 -- `each(List/Bytes)` 保留零输出动作和单输出 List 映射;`each(Stream)` 只接受零输出 handler,不把未知长度或无限输出隐式收集到内存。Stream 的最终状态由 `reduce`/`reduce_until` 返回。 -- `filter`、`find`、`sum` 本阶段仍只处理 List;不增加 Stream 到 Stream 的惰性 map/filter 管道。 - -### Static Handler Inputs - -function 输入可以声明受限 handler 签名: - -```dever -serve( - route: handler(request: Request) (response: Response), - config: Config -) (result: ServeResult) { - result = serve_with(route, config) -} -``` - -- handler 类型只允许出现在 function 输入中;输入按位置匹配类型,命名输出同时匹配名称、顺序和类型。 -- 调用方只能传入签名匹配的具名 function,或转发当前 function 的 handler 参数。 -- handler 参数可以直接调用,也可以传给 `each`、`reduce`、`reduce_until` 或另一个 handler 输入;不能参与分句匹配,不能赋给局部值、存入 record/List/Map/Stream、比较或作为输出返回。 -- handler 不是运行时值。typed HIR 保留静态绑定,AOT 以 function 和实际 handler 绑定组成专门化实例,生成直接调用;不产生函数指针、闭包、虚调用或反射注册表。 -- 递归检查覆盖 handler 调用与转发后的专门化调用图,不能通过 handler 绕过无递归规则。 - -### Stream And Resource Contract - -- `Stream` 是编译器提供的唯一新增标准泛型类型,用户仍不能声明泛型 type 或泛型 function。 -- Stream 是拉取式、顺序、一次消费的 opaque 资源;复制 Stream 只产生同一资源的别名,所有别名共享读取位置、结束状态和显式关闭状态。Stream 不可比较,也不能成为 Map key。 -- `reduce_until` 提前停止时 Stream 保持可用,调用方可从下一个未消费元素继续处理。正常耗尽后继续消费只得到结束,不会重新执行生产者。 -- 正常 EOF 使用 Stream 自然结束表示,不作为普通元素。可恢复 I/O 错误必须作为官方 choice 的 `Failed(message: Text)` 元素交给 handler;终止性错误产生一个 Failed 后结束 Stream,不能转换成默认值或程序故障。 -- 流式读取使用 `dever.io.ReadEvent`,其分支固定为 `Chunk(bytes: Bytes)` 和 `Failed(message: Text)`;现有单次 `read` 继续返回 `ReadResult.Read/End/Failed`,两种接口不混用结束语义。 -- 流创建结果固定为 `dever.io.ReadStreamResult`,其分支为 `Streaming(stream: Stream)` 和 `Failed(message: Text)`。`dever.io.chunks(file, limit)` 与 `dever.net.chunks(socket, limit)` 都返回该类型;非正数、无法表示的 limit 或创建时已经关闭的源立即返回 Failed。 -- `dever.net.connections(listener)` 直接产生 `Stream`;创建后关闭 listener 或终止性 accept 错误产生一个 `ConnectResult.Failed` 后结束。 -- 核心操作 `close(stream)` 没有输出并且幂等。它停止该 Stream 及其别名并释放 Stream 持有的底层资源引用,但不主动关闭调用方仍单独持有的 File、Socket 或 Listener;关闭后的 Stream 与正常耗尽一样不再产生元素。调用方先关闭底层资源时,依赖它的未关闭 Stream 产生一个 Failed 后结束;最后一个资源别名离开作用域时仍由原生资源析构兜底。 -- 首阶段只有阻塞、顺序执行;Socket 延续显式 timeout。没有预取、后台线程、async、await、并发消费或共享可变业务全局状态。 - -### Acceptance Criteria - -1. List 和 Bytes 的 `reduce` 按源顺序传递状态,空序列返回初始状态;Bytes 不经过中间 List。 -2. `reduce_until` 在 stop 元素之后不调用 handler 或拉取 Stream;同一 Stream 随后从未消费位置继续。 -3. `each(Stream)` 接受零输出 handler,拒绝单输出或多输出 handler;List/Bytes 的既有映射和动作语义不回归。 -4. handler 输入支持具名 function、跨 package function 和多层静态转发;签名不匹配、存储、返回、比较和 handler 间接递归均在原生构建前拒绝。 -5. 生成程序中的 handler 是专门化直接调用;不引入通用 runtime Value、运行时函数指针或逐元素虚拟 handler 分派。 -6. Stream 别名共享游标、结束和关闭状态;自然 EOF、提前停止、幂等 `close`、底层关闭与终止性错误均有确定测试。 -7. 官方 `dever.io`/`dever.net` 流式接口作为普通 `.dever` 源码经过同一 parser、resolver、checker 和 HIR;runtime 只拥有系统读取和 Stream 拉取原语。 -8. 文件验证只使用测试自有临时目录,TCP 验证只使用 `127.0.0.1` 随机端口、有限数据和超时;不连接、启动或修改现有服务。 -9. 实际 `check`、`run`、`build` 与独立原生程序覆盖一个分块状态解析样例,证明结果来自 `.dever` handler 和状态,而非编译器特判。 - -### Out Of Scope - -- HTTP、JSON、CRUD、数据库、并发服务器和异步语法;本阶段交付的是这些 package 可复用的底层表达能力。 -- 一般化用户泛型、lambda、闭包、一等 function、Stream 惰性转换、循环 block、用户递归和异常机制。 -- formatter、语义基准解释器、性能门槛、自举、package 分发、跨平台构建和全局命令迁移。 - -### Known Risks And Controls - -- 静态 handler 转发可能产生重复原生实例;专门化键按 function 与完整 handler 绑定去重,并且只生成入口可达实例,不退化为运行时分派。 -- Stream 的内部生产者调用有固定边界成本;文件和 Socket 以 Bytes chunk 为单位拉取,不按单字节跨越动态边界,有限 List/Bytes 热路径仍是直接循环。 -- 首阶段的阻塞 Stream 不能承担并发服务器;这是明确范围限制,不能在 HTTP package 中用隐藏线程或全局队列规避。 -- 把 I/O 失败作为最后一个元素要求 handler 穷尽处理官方 choice;类型检查和终止状态测试共同防止错误被静默丢弃或无限重复。 - -## Completed Hello Milestone - -- 示例位于 `examples/dever/hello/app/user.dever`,与 `package app.user` 路径一致。 -- 支持 Text 字面量、Text 参数、局部赋值、普通零输出函数调用和公开零输入入口。 -- 内置标准签名为 `dever.io.println(text: Text) ()`,输出 UTF-8 文本和一个换行;写入失败报告 Dever 调用位置并以非零状态退出。 -- 修改文本、调用其他自定义函数、跨包调用公开函数都必须由实际源码驱动;不能特判示例名称或内容。 -- 名称、参数、可见性、包路径和重复定义检查在原生编译前完成;递归及包依赖循环按既有契约拒绝。 -- 未实现的类型、表达式、分句和输出签名明确报不支持,不静默生成近似代码。 -- 提供本地 `check `、`run `、`build --output `;不替换全局命令。 -- 验收真实 stdout、错误定位、原生可执行文件和输出失败;不启动任何服务或执行全量测试。 - -## Deferred User API Proposal - -以下保留之前的 API 讨论作为后续参考;其中持久化、并发与性能要求尚未重新确认,不属于当前验收或实施前置条件。 - -### Confirmed Requirements - -- 应用业务使用 Dever 源码(`.dever` 或 `.dever.md` 的程序块);不能手写 Rust 用户 CRUD 再把 Dever 当作装饰。 -- 用户模型只有 ID、姓名、手机号,CRUD 和 HTTP JSON 交互必须实际可用。 -- 保留已经讨论的表面语法;只增加实际应用所需的标准 package 能力和必要语义。 -- 编译器与通用运行时不能特判 `User`、`name`、`phone` 或 `/users`;这些信息来自应用源码。修改业务类型和路由不能要求修改编译器。 -- 数据需要真实持久化;重启后仍可查询,不能用进程内 Map 冒充实际存储。 -- 性能验证覆盖真实读写、序列化和持久化,不用空接口成绩替代 CRUD 性能。 - -业务模型沿用现有语法: - -```dever -type User { - id: Id - name: Text - phone: Text -} -``` - -### Proposed API Acceptance - -以下为待最终收敛的最小 API 行为,不增加登录、管理页面或其它业务模块: - -| Request | Behavior | -| --- | --- | -| `POST /users` | 提交姓名和手机号;服务端生成 ID,返回创建的用户 | -| `GET /users/{id}` | 查询单个用户;不存在时返回明确的未找到结果 | -| `GET /users` | 按稳定顺序、有上限地分页查询 | -| `PUT /users/{id}` | 完整更新姓名和手机号,ID 不可变 | -| `DELETE /users/{id}` | 删除指定用户,删除后无法查询到 | - -- `name`、`phone` 使用 Text;不把手机号当数值,也不擅自添加特定国家的手机号规则或手机号唯一约束。 -- 缺少字段、非法 JSON、无效 ID、未知用户和存储失败需要明确响应;不能静默填值或伪装成功。 -- 并发访问不能产生重复 ID、半写入或未说明的丢失更新;具体并发写入契约随存储设计确定。 -- 吞吐、p50/p95/p99 延迟、错误率和资源使用需要在固定数据量、读写比例、并发和持久化配置下报告,并与同环境、同功能的原生基线比较。数值性能门槛仍待收敛,现有计算内核的 1.15 倍预算不能直接替代 API 指标。 - -### Open Decisions - -- 后续 API 先允许内存测试数据;需要持久化时再讨论数据库、并发更新和性能预算。 - -### Deferred From This Milestone - -- 契约 DSL、AI 生成器、全面重复语义检测和完整的大项目上下文工具。 -- 登录/RBAC、前端页面、多租户、分布式部署及其它没有被请求的用户业务。 -- 与用户 API 无关的完整数值标准库、全部集合组合、自举和组件分发系统;既有语言契约作为后续路线保留。 - -## Language Roadmap - -后续章节保留原 Minimal Core 的语言契约,作为本轮定义讨论的基础。已确认的长期规则与首版能力限制分别标明;讨论中的功能不代表已经实现,编译器仍须明确拒绝尚未支持的源码。 - -## Repository Evidence - -- 仓库当前没有已发布的 `.dever` parser、formatter 或兼容格式。 -- 2026-09-05 开工检查确认:当前仓库只有规划资料,没有 Cargo workspace、Rust 源码或测试。HEAD 也只包含两份旧规划文档。 -- 新语言没有兼容旧语义图、旧 CLI、旧生成结果或旧测试的义务。旧规划由 Git 文档历史保留,不在新实现中增加迁移层。 -- 从零建立 Rust workspace;复用源码位置诊断思路和仓库根目录 `test/` 约束。旧领域模型和旧后端契约不能决定新语法。 - -## Core Language Roadmap Scope - -1. `.dever` 源文件、UTF-8 文本、注释、literal 和唯一 formatter。 -2. package 路径、公开名称、完整限定名和源码根目录内的自动依赖解析。 -3. 被动 type、字段型值、选择型值、可空值、List、Map、Bytes 和 opaque Stream 资源。 -4. 显式 function 边界、线性 body、局部类型推断和值语义修改。 -5. 通过同名 function 分句表达的穷尽、互斥条件规则。 -6. 算术、比较、布尔和文本连接表达式。 -7. `each`、`reduce`、`reduce_until`、`filter`、`find`、`sum` 以及最小 List/Map 标准函数。 -8. Int、Decimal、Float 的确定数值语义和最小 `math`/`decimal` 标准 package。 -9. parser、formatter、resolver、type checker、clause analyzer、语义基准解释器、原生 AOT 编译和 CLI。 -10. Rust 编写的首代引导编译器,以及不依赖 Rust 表面语法、可被未来 Dever 自举编译器复用的 typed HIR 和运行语义。 - -## Language Contract - -### 1. Source And Package - -- 源文件后缀固定为 `.dever`,编码为 UTF-8。 -- 代码标识符只使用 ASCII 英文;注释、字符串和文档可以使用任意 UTF-8。 -- `#` 开始单行注释;Core 0.1 不提供块注释。`//` 只表示整数除法,不具有第二种词法含义。 -- 语句和声明按换行或结构边界分隔,不写分号。 -- 一个文件完整拥有一个 package;同一 package 不能拆到多个文件。 -- 源文件相对 `src/` 的路径必须与 package 点分名称一致。 - -```text -src/account/user.dever -> package account.user -``` - -文件第一项必须是 package 声明: - -```dever -package account.user exposes ( - User - create -) -``` - -`exposes` 只能列出当前 package 已声明的 type 或 function。未列出的名称只在当前 package 可见;公开 function 名称会公开该名称的全部签名和分句。 - -同 package 引用使用短名称,跨 package 引用必须使用完整限定名: - -```dever -normalized = normalize_email(email) -user = account.user.create(id, name, email) -``` - -Core 0.1 不提供 `import`、`use`、通配导入或别名。编译器从完整限定引用建立依赖图,并拒绝 package 循环依赖。`app`、`domain`、`feature`、`flow`、`policy`、`view` 和 `scenario` 都不是关键字,需要时只是普通 package 路径段。 - -#### Package Origins And Distributed Components - -语言层只有 package,不新增 `component` 关键字。package 是源码和 API 命名空间;“组件”只是 registry 中用于安装、签名和版本管理的发布单元,可以包含一个根 package 及若干子 package。组件不能绕过各 package 的 `exposes` 边界。 - -package 来源固定分为三类: - -| 来源 | 名称规则 | 示例 | 获取方式 | -| --- | --- | --- | --- | -| 核心标准 package | 编译器保留的单段名称 | `text`、`math`、`decimal` | 随编译器提供 | -| Dever 官方组件 | `dever.` 根路径 | `dever.http`、`dever.sql` | 显式安装 | -| 公共第三方组件 | `.` 根路径 | `stripe.payment`、`shemic.robot` | 显式安装 | - -本地业务 package 继续使用项目内路径,例如 `account.user`、`order.checkout`。本地源码不能声明核心标准名称或 `dever.*` 官方命名空间。同一个构建中如果本地源码、标准库或未来已安装组件提供了相同 package 名称,编译器直接报告重复定义,不进行覆盖或静默择优。 - -调用形式对所有来源一致,版本不会进入业务源码: - -```dever -user = account.user.create(input) -name = text.trim(raw_name) -response = dever.http.send(request) -payment = stripe.payment.create(order) -``` - -从 0.2 起,组件的稳定身份与下载来源相互独立。`shemic.contact` 是进入 package 名称和类型身份的 component id;GitHub、其他 Git 服务或 Dever registry 只是可以替换的 source。仓库迁移不会迫使业务源码改名。 - -公共组件必须通过命令显式加入,不能因为遇到未知名称就在 `check` 或 `build` 时自动联网: - -```text -dever add dever.http@1 -dever add stripe.payment@3 -dever add shemic.contact --git https://github.com/shemic/contact.git --tag v1.2.0 -dever add shemic.contact --git https://github.com/shemic/contact.git --rev 8f34c2a -dever update stripe.payment -dever fetch -``` - -Git source 必须同时给出 tag 或 revision,不接受未固定的默认分支 HEAD。tag 在加入时解析为完整 commit;`dever.lock` 同时记录 source URL、完整 commit 和规范化源码内容的 SHA-256,后续 tag 被移动也不会改变构建。组件内全部 package 必须位于 component id 根路径下,例如 `shemic.contact` 可以提供 `shemic.contact.phone`,不能同时冒充 `account.user`。 - -0.2 的项目根目录增加两个由 CLI 维护、需要提交的元数据文件: - -```text -dever.mod # component id、直接依赖及其 registry/git/path 来源要求 -dever.lock # 完整依赖图、精确版本/commit、内容摘要和实际提供的 package -``` - -开发者仍只手写 `.dever`;`dever add`、`dever update` 和未来的本地 link 命令负责规范化更新元数据。分开保存意图和精确结果,使直接依赖保持可读,同时保证所有机器解析出同一份源码。 - -下载源码不复制到每个项目。Dever 使用平台级、可由 `DEVER_HOME` 改址的全局只读内容寻址仓库: - -```text -$DEVER_HOME/ - git// # Git bare mirror,只负责取对象 - store/sha256// # 已校验、不可修改的组件源码 - build/// # 可删除的编译缓存 -``` - -项目目录只保留 `src/`、`dever.mod`、`dever.lock` 和可删除的 `target/dever/` 构建结果。多个项目依赖相同 commit 时共享同一份 store 内容。`dever add`、`dever update`、`dever fetch` 是仅有的默认联网入口;普通 `check`、`build` 和 `run` 只读取本地源码、内置标准 package、lock 与 store,缺失时明确要求执行 `dever fetch`,不隐式下载。 - -Core 0.1 只实现本地 package 与随编译器提供的核心标准 package,同时锁定上述命名和解析边界。registry、`dever add`、签名验证和外部组件缓存确定延后到 0.2,不影响现有 `.dever` 调用形式。 - -### 2. Canonical Naming - -| 对象 | 唯一格式 | 示例 | -| --- | --- | --- | -| package 路径段 | `lower_snake_case`,优先单数领域名 | `account.user`、`sales_order` | -| 文件名 | `lower_snake_case` | `user.dever` | -| type | `UpperCamelCase` | `User`、`CreateResult` | -| 选择项 | `UpperCamelCase` | `Pending`、`Created` | -| function | `lower_snake_case` | `create`、`can_sign_in` | -| 输入、输出、局部值、字段 | `lower_snake_case` | `user_id`、`created_at` | -| 标准泛型参数 | 有含义的 `UpperCamelCase` | `Item`、`Key`、`Value` | - -大小写不控制公开性。缩写按普通单词处理:`Id`、`Url`、`HttpClient`、`user_id`、`callback_url`。编译器强制可机械判断的大小写、ASCII 和路径格式;“是否是好名称”只产生规范诊断,不依赖英语词典阻止编译。 - -### 3. Types And Literals - -Core 0.1 的基础标量只有: - -| 类型 | 语义 | -| --- | --- | -| `Bool` | `true` 或 `false` | -| `Int` | 有符号 64 位整数,范围 `-9223372036854775808` 至 `9223372036854775807` | -| `Decimal` | decimal128,最多 34 位有效十进制数字,round half to even | -| `Float` | IEEE 754 binary64 近似数 | -| `Text` | UTF-8 文本;相等按实际字符序列判断,不做隐式 Unicode 规范化 | -| `Id` | 不透明稳定标识,只支持相等比较、传递和序列化 | - -Core 0.1 不提供 `UInt`、`BigInt`、`Percent`、字符类型或隐式动态 `Json` 类型。 - -- 整数 literal 默认是 Int。 -- 带小数点的 literal 默认是 Decimal;在明确要求 Float 的静态上下文中直接成为 Float。 -- 科学计数 literal,例如 `1.25e6`,是 Float。 -- Decimal literal 必须能被 34 位 decimal128 精确表示;源码常量不会被静默舍入,超出精度或范围时由编译器拒绝。运行时算术仍按已确定的银行家舍入产生结果。 -- Text 使用双引号,支持 `\\`、`\"`、`\n`、`\r`、`\t` 和 `\u{HEX}` Unicode 转义。 -- `true`、`false` 和 `null` 是保留 literal。 -- 源码不提供 NaN 或 Infinity literal;Float 运算可以产生这些值。 - -用户定义 type 只有两种形状,不能混写: - -```dever -type User { - id: Id - name: Text - phone: Text? -} - -type CreateResult { - Created(user: User) - InvalidPhone(reason: Text) - EmailAlreadyUsed(email: Text) -} -``` - -字段型 type 是固定字段数据;选择型 type 表示同一时间只能是其中一种选择。type 没有方法、构造器、hook、继承或行为,也不能递归包含自身。 - -选择项必须通过所属 type 限定: - -```dever -result = CreateResult.Created(user) -``` - -选择项携带的数据在声明中必须有名称和类型,构造时按声明位置传入。字段型值必须一次完整创建: - -```dever -user = User { - id = id - name = name - phone = null -} -``` - -未知、重复或遗漏字段都是编译错误,包括值为 `null` 的可空字段。formatter 按 type 声明顺序输出字段。点号只访问或修改已经完整存在的字段型值,不能逐字段创建半初始化对象。 - -`Value?` 表示 `Value` 或 `null`。普通类型永远不能为 `null`,`Value??` 非法,也没有 `?.`、`??`、强制解包或隐式默认值。可空值必须交给穷尽的 function 分句处理。 - -标准泛型函数产生可空返回值时,可空化是幂等的:`first(List)`、`find` 的同类调用及 `get(Map, key)` 都返回 `Int?`,不产生嵌套可空类型。返回 `null` 不区分“没有元素/键”和“已有值为 null”;需要区分时,业务使用带显式选择项的 Value 类型。源码仍禁止显式书写 `Int??`。 - -### 4. List And Map Values - -List 使用方括号创建: - -```dever -users = [first_user, second_user] -empty_users() (users: List) { - users = [] -} -``` - -List 元素必须是同一静态类型。空 List 必须能从 output、参数或其他静态上下文推断元素类型,否则编译错误。 - -Map 是 `Map`,使用裸大括号创建: - -```dever -default_labels() (labels: Map) { - labels = { - "env" = "production" - "region" = "china" - } -} -``` - -同一 Map literal 的 key 类型一致、value 类型一致,重复 key 是编译错误;空 Map 也必须能推断完整类型。`Type { ... }` 是固定字段型值,裸 `{ ... }` 是动态 Map,二者不会合并成万能对象。 - -Map key 只允许 Text、Int、Bool、Id 和不携带数据的选择型 type。Decimal、Float、可空值、字段型值、List 和 Map 不能成为 key。 - -Map 保证插入顺序。literal 保留源码顺序;`put` 新 key 时追加,覆盖已有 key 不移动位置;`remove` 后重新写入视为新的末尾项。`entries`、显示和未来的 JSON 边界都必须遵守这一顺序。 - -### 5. Function Definitions And Calls - -所有行为只有一种定义形式: - -```dever -line_total(line: Line) (total: Decimal) { - total = line.price * line.quantity -} -``` - -- 第一组括号是输入,第二组是命名输出。 -- 普通输入和输出必须写成 `name: Type`;body 内局部值可以推断。 -- 没有输入或输出时仍写空括号。 -- 不使用 `function` 或 `return` 关键字。 -- 输入名称是当前分句的局部绑定;输出名称和输入输出类型属于稳定签名。 -- 调用只按位置传参,不提供命名参数调用。 -- 用户 function 以“package、名称、输入数量”确定签名;同名同参数数量的全部分句必须具有相同的基础输入类型和输出契约。不同参数数量可以形成独立签名。 -- 同一签名的全部分句必须在同一文件中连续书写。 -- Core 0.1 禁止直接或间接递归;重复执行只能通过 `each`、`reduce` 和 `reduce_until` 这些受检查的具名 handler 组合器进入。 - -选择项会提供所属选择型 type,普通 type 会提供自身类型;`null` 和 `other` 则从同组其他分句推断基础输入类型。只写 `null`/`other` 而没有任何可推断类型的分句组是编译错误。`Text` 与 `null` 两个分句共同形成 `Text?` 输入,而不是两个运行时重载。 - -单输出调用直接得到该值,零输出调用作为一条动作语句,多输出调用得到只能按输出名称访问的结果: - -```dever -allowed = can_sign_in(user.status) -parts = split_name(name) -display = parts.first + parts.last -``` - -不提供按位置拆包。命名 function 只能在普通调用位置、作为标准序列/集合操作的 handler,或传给受限静态 handler 输入;Core 0.1 不提供 lambda、闭包,也不能把 function 存入局部值、字段、List、Map 或 Stream。 - -### 6. Function Clauses Replace Conditional Blocks - -function 分句是 Dever 唯一的条件分派机制。这是 2026-09-07 用户确认的长期语言规则;条件 block 和条件表达式不属于后续待增加能力。Bool 表达式及其短路规则仍按第 8 节定义,业务分支通过调用具名 function 的分句选择。 - -示例: - -```dever -can_pay(status: OrderStatus.Draft) (allowed: Bool) { - allowed = true -} - -can_pay(status: other) (allowed: Bool) { - allowed = false -} -``` - -冒号左侧始终是当前分句的局部输入名称;不同分句可以使用不同名称。右侧允许: - -- 普通类型,表示该类型的任意值; -- `true`、`false`、`null`、Text 或数值常量; -- 完整限定的选择项及其数据绑定,例如 `CreateResult.Created(user)`; -- 选择项中的 `_`,表示忽略该携带值; -- Int 或 Decimal 的静态常量比较; -- 上述数值比较的一个上下界组合; -- 上下文关键词 `other`。 - -数值范围直接放在输入中: - -```dever -absolute(value: Int < 0) (result: Int) { - result = -value -} - -absolute(value: Int >= 0) (result: Int) { - result = value -} - -grade(score: Int >= 60 and < 90) (name: Text) { - name = "pass" -} - -grade(score: Int < 60) (name: Text) { - name = "fail" -} - -grade(score: Int >= 90) (name: Text) { - name = "excellent" -} -``` - -Float 不进入静态范围分句,因为 NaN 不具有普通全序;先通过 `math.is_nan` 等 function 得到 Bool,再对 Bool 写分句。 - -分句没有源码顺序优先级。编译器把同一签名的全部分句作为一组规则,拒绝类型不一致、重叠、遗漏和不可达情况。多输入 function 中,每个 `other` 是该输入位置全部明确模式的补集,编译器再检查各位置组合是否覆盖完整输入空间。`other` 只在分句输入冒号右侧具有该含义,不能作为普通值存储、传递或组合。 - -分句输入中不能调用任意 function 或读取运行时状态。更深一层的业务选择必须调用另一个有名称的 function,源码不提供 `if`、`else`、`switch`、`match`、`when` 或 `by` block。 - -### 7. Linear Body And Value Semantics - -body 只包含顺序赋值和 function 调用: - -```dever -final_price(price: Decimal, rate: Decimal) (result: Decimal) { - discounted = price * (1 - rate) - result = decimal.round(discounted, 2) -} -``` - -表达式由 literal、名称、字段访问、值构造、function 调用、一元运算和二元运算组成。没有条件表达式、循环 block、匿名 function、复合赋值或隐藏控制流。 - -`=` 既用于初始化,也用于修改当前 function 的 input、局部值或 output。编译器强制: - -- 读取前已经完整初始化; -- 字段修改的宿主值已经完整初始化; -- function 结束时全部命名输出都已赋值; -- 赋值类型稳定,不通过再次赋值改变局部类型; -- 无意义覆盖和写入后未读取至少产生诊断。 - -普通值的赋值、传参和输出采用值语义。修改只属于当前局部名称,调用方或其他名称不会观察到共享别名变化;变化只能通过命名 output 或未来的显式 effect function 离开当前调用。实现可以用唯一所有权或写时复制消除真实复制,但源码不暴露借用、生命周期或 `clone`。File、Socket、Listener 和 Stream 是显式 opaque 资源例外:复制只建立同一资源状态的别名,不复制外部资源。 - -### 8. Expressions And Operators - -普通算术直接使用符号: - -```dever -subtotal = price * quantity -ratio = 5 / 2 -page = 5 // 2 -remainder = 5 % 2 -eligible = user.active and user.age >= 18 -``` - -| 运算 | 规则 | -| --- | --- | -| `+ - *` | Int、Decimal 或 Float 的同类运算;Int 与 Decimal 混合时 Int 无损提升为 Decimal | -| `/` | Int/Int 返回 Decimal;Decimal 与 Int 返回 Decimal;Float/Float 返回 Float | -| `//` | 只接受 Int,结果向零截断 | -| `%` | 只接受 Int,余数符号跟随被除数,并满足 `a = (a // b) * b + (a % b)` | -| `+` | 也可连接两个 Text | -| `== !=` | 相同可比较类型 | -| `< <= > >=` | Int、Decimal 或 Float 的同类比较;Int 可提升为 Decimal | -| `and or not` | 只接受 Bool,并具有短路语义 | - -可比较类型包括上述标量,以及成员递归可比较的字段型、选择型、可空、List、Map 和 MapEntry。字段型按声明字段逐项比较;选择型比较选择项和携带值;List 按位置比较;Map 按插入顺序比较 key/value 对,因此顺序不同的 Map 不相等;可空值中只有两个 null 相等,两个非 null 值继续比较其内容。Float 保持下文的 NaN 规则,包括嵌套在集合或字段中时。命名多输出结果只能访问输出字段,不能直接比较。相等运算不做 Int/Decimal 提升。 - -Decimal 与 Float 不隐式混合,实际 Int 值转为 Float 也必须显式调用 `float.from_int`。Core 0.1 不提供 Float 到 Decimal 的隐式或有损转换。 - -运算优先级从高到低固定为:调用和字段访问、一元 `-`/`not`、`* / // %`、`+ -`、比较、`and`、`or`。同级二元运算从左到右;括号可以显式改变顺序。formatter 不依赖空白表达优先级。 - -### 9. Collection And Sequence Functions - -Core 0.1 只保留以下集合行为,不增加循环语法: - -```dever -views = each(to_view, users) -views = each(to_view, users, context) - -active = filter(is_active, users) -active = filter(is_active, users, context) - -user = find(is_target, users) -user = find(is_target, users, context) - -total = sum(prices) -total = sum(line_total, lines) -total = sum(line_total, lines, context) - -state = reduce(update_state, values, initial_state) -state = reduce_until(update_until_done, values, initial_state) - -parallel_each(consume, values, 4) -parallel_each(consume, values, 4, context) -``` - -- `each`、`filter`、`find` 和投影式 `sum` 最多有一个末尾 context;需要多项共享数据时先组合成字段型值,其 handler 先接收元素、再接收 context。 -- `reduce` 和 `reduce_until` 的第三项是必需的初始状态,不是可选 context;handler 先接收元素、再接收当前状态,且不接受第四项参数。 -- `each` 的处理 function 有一个输出时按输入顺序产生 `List`;没有输出时只按顺序执行动作;多个输出不合法。 -- `filter` 的处理 function 必须输出 Bool,并保留原列表顺序。 -- `find` 找到第一个 Bool 为 true 的元素后停止,返回 `Item?`;没有结果返回 `null`。 -- `sum(List)` 直接求和;投影形式要求处理 function 输出 Int、Decimal 或 Float。 -- 空 List 的 `sum` 返回相应数值类型的零。 -- 除显式 `parallel_each` 外,List 操作按列表顺序执行,Bytes 按字节位置执行,Stream 按拉取顺序执行;Float 求和不得为了优化而重排。 -- `reduce` 和 `reduce_until` 的完整 List/Bytes/Stream、状态和停止契约由 Approved Foundation Extension 定义;它们不开放循环 block 或用户递归。 -- `parallel_each` 接受 List、Bytes 或 Stream、1–256 个工作线程和可选 context;handler 必须零输出,输入依次是元素和 context。复用既有静态 handler 与专门化规则,不产生用户可存储的 function 值。 -- 生产端顺序拉取且队列有界,工作端的副作用顺序不保证。handler 输入与 context 不能递归包含 Stream,源 Stream 只在生产端拉取;文件与 Socket 等别名仍遵守共享资源规则。 -- `parallel_each` 返回前等待全部已启动动作;程序故障在后续拉取边界停止分派,保留第一个已记录故障并传播源码位置。已经阻塞的拉取或系统调用由显式系统超时约束,不提供强制取消或后台遗留任务。非法线程数在拉取前产生程序故障。 - -其他最小标准函数: - -```dever -users = append(users, user) -user = first(users) - -value = get(labels, "env") -labels = put(labels, "env", "development") -labels = remove(labels, "env") -pairs = entries(labels) -``` - -`append` 返回新 List;`first(List)` 返回 `Item?`。`get` 返回 `Value?`;`put` 和 `remove` 返回新 Map;`entries` 返回按插入顺序排列的 `List>`。没有 `list.add`、数字点号索引、`map.key` 或 `map[key]`。 - -`any`、`all`、`min`、`max` 不进入首版;真实重复需求出现后再增加普通标准 function。 - -### 10. Recoverable Failures And Runtime Faults - -可恢复业务失败使用选择型输出: - -```dever -create_message(result: CreateResult.Created(user)) (message: Text) { - message = user.name -} - -create_message(result: CreateResult.InvalidPhone(reason)) (message: Text) { - message = reason -} - -create_message(result: CreateResult.EmailAlreadyUsed(email)) (message: Text) { - message = email + " already exists" -} -``` - -这同时替代 `throw` 和 `catch`。调用方接收完整选择值,再通过命名分句显式转换。Core 0.1 不提供 exception、自动错误传播、隐藏提前退出或类似 Rust `?` 的语法。 - -编译器可以证明的不变量错误直接拒绝编译。只能在运行时发现的程序故障终止当前执行边界,并至少报告故障类别、文件、行和列;普通 function 不能捕获、忽略或转换程序故障。执行边界由宿主确定,例如一次 CLI 调用,未来可以是一次请求或任务。 - -数据库、网络等只要存在恢复可能,就必须在未来以显式选择型结果返回,不能伪装成程序故障。 - -### 11. Numeric Semantics - -- Int 是固定 i64;不环绕、不饱和。静态可证明的溢出是编译错误,运行时溢出是程序故障。 -- `Int / Int` 先无损提升为 Decimal 再除,因此 `5 / 2` 是 Decimal `2.5`。 -- `Int // Int` 向零截断;`Int % Int` 与商保持代数恒等式。除数为零以及 `-9223372036854775808 // -1` 属于溢出故障。 -- Decimal 使用 decimal128 的 34 位有效数字和银行家舍入;算术中的正常 inexact/rounded 状态产生舍入结果,指数上溢、下溢、除零或无效运算产生程序故障,不向源码暴露 Decimal NaN/Infinity。 -- 金额位数由 `decimal.round(value, places)` 显式处理;核心算术不根据变量名、字段名或业务场景猜测两位小数。 -- Float 遵守 IEEE 754 binary64 非捕获行为:溢出产生正负 Infinity,无效运算产生 NaN,除零产生 Infinity 或 NaN。 -- Float 的 NaN 与任何值的 `==` 都为 false,`!=` 为 true,有序比较均为 false;使用 `math.is_finite`、`math.is_nan` 和 `math.is_infinite` 分类。 -- 常用科学函数通过 `math.sqrt`、`math.sin`、`math.cos`、`math.log` 和 `math.pow` 等普通标准 package function 提供。 -- Decimal 与 Float 不隐式混合。任意精度整数/小数、向量、矩阵、复数、统计与单位系统以后由独立 package 提供。 - -## Standard Names - -无需 import 即可使用的核心名称只有: - -- Bool、Int、Decimal、Float、Text、Id、Bytes、List、Map、MapEntry、Stream; -- true、false、null、other; -- each、parallel_each、reduce、reduce_until、filter、find、sum、append、first、get、put、remove、entries、length、用于 Stream 的 close; -- 仅用于 function 输入签名的上下文关键词 handler; -- 算术、比较和布尔运算符。 - -其他标准行为使用完整 package 名,例如 `text.trim`、`text.lower`、`decimal.round`、`float.from_int` 和 `math.sqrt`。这避免大量隐式全局名称,也让标准库与业务 package 遵守同一调用模型。 - -## CLI Identity And Coexistence - -- 语言、编译器产品和正式命令名保持为 `dever`,文档与命令语义以 `dever` 为准。 -- Core 0.1 与现有 Dever 框架 CLI 共存期间,系统 `PATH` 中可以暂时用 `deverc` 暴露语言编译器;不得覆盖、替换或遮蔽现有的 `dever` 命令。 -- `deverc` 只是指向同一编译器二进制的安装入口,不形成第二套命令、配置或行为契约。 -- 仓库构建与自动测试直接调用构建产物,不修改系统 `PATH` 或全局可执行文件;创建、更新或移除全局 `deverc` 入口必须单独获得用户授权。 -- 未来是否让语言编译器接管全局 `dever` 命令属于独立迁移决策,不在 Core 0.1 默认实施范围内。 - -## Complete Package Example - -```dever -public type UserStatus { - Pending - Active - Disabled(reason: Text) -} - -public type CreateInput { - id: Id - name: Text - email: Text - phone: Text? - score: Int - labels: Map -} - -public type CreateResult { - Created(user: User) - InvalidName(reason: Text) - InvalidEmail(reason: Text) -} - -public type User { - id: Id - name: Text - email: Text - phone: Text? - score: Int - labels: Map - status: UserStatus -} - -public type UserView { - id: Id - name: Text - email: Text - phone: Text - score: Int - can_sign_in: Bool -} - -public create(input: CreateInput) (result: CreateResult) { - normalized = normalize(input) - result = create_name(normalized, normalized.name) -} - -normalize(input: CreateInput) (result: CreateInput) { - result = input - result.name = text.trim(input.name) - result.email = text.lower(text.trim(input.email)) -} - -create_name(input: CreateInput, name: "") (result: CreateResult) { - result = CreateResult.InvalidName("name is required") -} - -create_name(input: CreateInput, name: other) (result: CreateResult) { - result = create_email(input, name, input.email) -} - -create_email(input: CreateInput, name: Text, email: "") (result: CreateResult) { - result = CreateResult.InvalidEmail("email is required") -} - -create_email(input: CreateInput, name: Text, email: other) (result: CreateResult) { - user = User { - id = input.id - name = name - email = email - phone = input.phone - score = input.score - labels = input.labels - status = UserStatus.Pending - } - result = CreateResult.Created(user) -} - -public activate(user: User) (result: User) { - result = user - result.status = UserStatus.Active -} - -public disable(user: User, reason: Text) (result: User) { - result = user - result.status = UserStatus.Disabled(reason) -} - -public can_sign_in(status: UserStatus.Active) (allowed: Bool) { - allowed = true -} - -public can_sign_in(status: other) (allowed: Bool) { - allowed = false -} - -phone_text(phone: Text) (result: Text) { - result = phone -} - -phone_text(phone: null) (result: Text) { - result = "Not provided" -} - -public to_view(user: User) (view: UserView) { - view = UserView { - id = user.id - name = user.name - email = user.email - phone = phone_text(user.phone) - score = user.score - can_sign_in = can_sign_in(user.status) - } -} - -public to_views(users: List) (views: List) { - views = each(to_view, users) -} - -is_active(user: User) (result: Bool) { - result = can_sign_in(user.status) -} - -public active_views(users: List) (views: List) { - active = filter(is_active, users) - views = each(to_view, active) -} - -has_id(user: User, expected: Id) (matches: Bool) { - matches = user.id == expected -} - -public find_user(users: List, id: Id) (user: User?) { - user = find(has_id, users, id) -} - -public put_label(user: User, key: Text, value: Text) (result: User) { - result = user - result.labels = put(user.labels, key, value) -} - -public label(user: User, key: Text) (value: Text?) { - value = get(user.labels, key) -} - -score_bonus(user: User, rate: Decimal) (amount: Decimal) { - amount = user.score * rate -} - -public total_score_bonus(users: List, rate: Decimal) (total: Decimal) { - total = sum(score_bonus, users, rate) -} -``` - -该源码只要求开发者理解 package、type、function、值和普通表达式。它同时覆盖显式业务结果、局部修改、条件分句、可空处理、列表转换、筛选、查找、Map 更新和 Decimal 聚合,所有路径保持平铺且可由编译器完整检查。 - -## Original Core Deferrals - -以下保留原 Core 0.1 的暂缓能力,具体版本安排在后续需求中确定。HTTP、JSON、持久化以及异步/并发 I/O 的应用扩展仍属暂缓 API 提案。 - -- AI、自然语言转译、画布和业务 DSL; -- Web 页面、React,以及超出首个 API 需要的数据库、网络和部署能力; -- 超出首个 API 需要的 effect/capability、异步、并发和事务能力;不开放任意共享可变业务全局变量; -- package registry、版本解析和项目清单; -- `for/while/break/continue/iterate/recur/repeat`、用户递归和其它通用循环结构; -- class、继承、interface、annotation、macro、unsafe、FFI; -- import、别名、命名参数、lambda、闭包和一般化一等 function; -- 用户泛型 type、递归 type、Set 和动态 Json;首个 API 的 JSON 边界应由静态类型驱动; -- UInt、BigInt、任意精度 Decimal、Percent、日期时间和单位类型; -- 直接 LLVM/Cranelift backend、完成自举、所有权或生命周期表面语法。 - -这些内容保留为 Core 0.1 暂缓项,不改变 Dever 最终成为通用编程语言的方向。条件 block 已从暂缓清单移除,条件分派始终遵守第 6 节的长期规则。 - -## Core Roadmap Acceptance Criteria - -这些是完整语言路线的验收项。2026-09-07 的基础语法、最小系统接口和后续工具/库分别验收,实际状态与证据见 `implement.md`;发行和自举不因基础里程碑完成而视为已交付。 - -1. 一个源码根目录中的多个 `.dever` 文件可以被加载;Core 0.1 只读取该根目录和内置标准 package,不隐式联网或搜索外部目录;路径与 package 不一致、保留命名空间、重复 package、未知公开名、未知引用和循环依赖均得到带源码位置的确定诊断。 -2. parser 覆盖本 PRD 的 package、两种 type、function、分句、value、statement 和 expression;拒绝已排除的关键字或语法。 -3. formatter 对合法程序产生唯一布局,连续执行两次结果不变,并保持注释和程序含义。 -4. 编译器强制命名格式、显式 function 边界、位置调用、一文件一 package、连续分句和无递归调用图;同 package 使用短名称,跨 package 必须使用完整限定名,并且只能访问对方 `exposes` 中的名称。 -5. type checker 拒绝未知/重复/遗漏字段、半初始化字段写入、未初始化读取、遗漏 output、非法 null、类型漂移、非法 Map key 和未授权隐式转换。 -6. clause analyzer 对选择型、可空、Bool、Text 常量、Int/Decimal 范围和多输入组合检查互斥、穷尽与可达性;分句移动顺序不改变执行结果。 -7. 本 PRD 的完整 package 示例可以通过解析、格式化、名称解析和类型检查;独立的零输入示例在语义基准解释器和原生程序中产生相同的确定命名输出。 -8. 局部赋值和字段修改不会改变调用方或其他名称持有的原值;编译器实现可以优化复制但不能改变可观察语义。 -9. `each`、`reduce`、`reduce_until`、`filter`、`find` 和 `sum` 的顺序、handler、context、初始/空结果、停止和类型规则全部有定向测试。 -10. List、Map、Bytes 和 Stream,以及 `append`、`first`、`get`、`put`、`remove`、`entries` 遵守可空返回、值/资源语义和稳定顺序。 -11. `5 / 2` 得到 Decimal `2.5`,`-5 // 2` 得到 Int `-2`,`-5 % 2` 得到 Int `-1`,并满足商余恒等式。 -12. Decimal 能证明 `0.1 + 0.2 == 0.3`,`1 / 3` 使用 34 位有效数字和 round half to even;`decimal.round` 显式控制业务位数。 -13. 静态 Int/Decimal 溢出或零除数被拒绝编译;动态故障终止当前执行边界并定位 `.dever` 源码,不环绕、饱和或返回默认值。 -14. Float 使用 binary64 和科学计数法,能够产生并通过 `math.is_nan`、`math.is_finite`、`math.is_infinite` 判断 NaN/Infinity;Decimal 与 Float 混用被拒绝。 -15. 可恢复失败只能通过选择型输出和穷尽分句传播;源码中不存在 exception、`throw`、`catch` 或自动传播语法。 -16. 正式 CLI 名为 `dever`,至少提供 `dever check `、`dever fmt `、`dever build --output ` 和 `dever run `;与现有框架 CLI 共存时,临时全局入口 `deverc` 必须调用同一编译器且不得覆盖现有 `dever`;build/run 首版只接受公开的零输入 function,run 执行与 build 相同的原生路径并确定性打印命名输出。 -17. 新实现不依赖旧 canonical JSON、SemanticGraph、Refiner、Workbench、温度示例或 Rust/React 生成后端,仓库文档不再把旧路线描述为当前架构。 -18. 生产产物不链接通用解释器,不携带运行时 type tag 分派或垃圾回收器;record、choice、List、Bytes 和静态 handler 在 AOT 路径中具有具体原生表示,热循环不发生逐元素动态 handler 分派或无必要堆分配;opaque Stream 只在 I/O 资源拉取边界保留内部生产者抽象。 -19. 在同一算法、数据布局、工具链和机器上的 release 基准中,Int/Float 算术及 List `each`/`filter`/`sum` 代表性热路径的中位执行时间不得超过等价 safe Rust 基线的 1.15 倍;Decimal 与有序 Map 分别对使用相同底层语义的 Rust 基线比较,编译时间单独报告。 -20. Rust 生成文件只存在于编译器管理的临时构建目录,不是用户源码、公共输出格式或兼容接口;删除这些文件不影响 `.dever` 工程。 - -## Risks And Deferred Items - -- 条件分句的穷尽分析是首版最复杂的静态检查,应先支持有限选择域与一维 Int/Decimal 区间,再组合多个输入;不引入通用定理证明器。 -- decimal128 需要成熟实现与一致状态标志。Core 0.1 采用 Rust `dec` crate 的 Decimal128 和可配置 Context,并将其封装在内部数值适配层;语言级测试锁定行为,依赖 API 不得泄漏到 `.dever`。 -- 当前仍禁止用户递归,已按批准范围提供显式文件/TCP 系统操作和结构化异步并发;异步网络、一般化 effect 和事务模型尚未实现,因此不是最终完整运行时。 -- Float 运算遵守平台 IEEE 754 语义,但任何未来的快速数学优化都必须显式设计,首版不得重排计算。 - -# Current Source And Module API Contract (2026-09-18) - -This user-approved contract supersedes historical `package/exposes`, arbitrary entry arguments and "API deferred" wording above. Source filenames relative to `module/` define package names in both `.dever` and `.dever.md`; top-level type/function declarations default private and may opt into cross-package access with `public`. `deverc run/build ` always invokes private `main()` from `module/main.dever` (or `.dever.md`) and accepts no entry argument. Markdown H1 documents path-derived package and public declarations with no executable H1 block. - -Each module may own recursive `api/` source containing only private `get_`/`post_`/`delete_` ordinary functions with one `response` output. Routes are statically validated and compiled only when reachable `main()` calls `dever.api.serve()`. GET/DELETE query inputs and POST JSON-object inputs are typed Text/Int/Bool (nullable allowed), and HTTP responses have JSON `code/message/data` envelopes. Listener settings are read only from `config/setting.json`. No application-config environment variable, implicit listener, new auth policy or CMS HTTP business endpoint is part of this milestone. Current canonical contracts are in `LANGUAGE.md`, `MARKDOWN-SYNTAX.md` and `.trellis/spec/backend/`. - -# Current AI-Oriented Source Architecture Contract (2026-09-19) - -This section supersedes the 2026-09-18 application visibility and package rules above. An application starts only at `module/main.dever` or `module/main.dever.md`; `main()` is implicit and private, and HTTP starts only when it calls `dever.api.serve()`. Application source contains no `package`, `exposes`, `public`, `internal` or import declarations. - -Business source uses `module///.dever` or `module////.dever`, where role is exactly `app`, `domain`, `model`, `port`, `adapter` or `api`. A role file and its same-name directory are mutually exclusive. Non-API role directories are flat; only `api/` may add nested URL scopes. A role directory containing only one source file is rejected because it creates structure without separation; keep that implementation in the role file instead. - -Files group cohesive behavior rather than individual functions. One role file may contain multiple related functions, and one topic file may contain multiple related functions. The topic filename never becomes part of an App call. All App functions are cross-domain capabilities and are addressed as `..`; a same-component caller may use `.`, and source in the same domain may use `app.`. Every other role is domain-private. Cross-domain and cross-component calls may target only App. Model types and ID types may appear in relations and signatures across domains, but generated Model operations remain callable only inside their owning domain. API handlers are HTTP entry adapters and are never source-callable. - -App inputs, outputs and inferred failure sets are one public contract. They cannot expose a private Domain/Adapter type; a business error that may leave the domain is declared in App and referenced from same-domain private source as `app.`. - -The dependency direction is `api -> app`, `app -> domain/model/port/adapter` plus another domain's App, while domain/model/port/adapter remain implementation details. Generic dumping grounds such as `common`, `shared`, `utils`, `helper`, `base` and physical `service/` are invalid application architecture. Keep one-use logic inline, same-topic reuse beside its callers, cross-topic domain rules in `domain`, persistence in `model`, and external integrations in `adapter`; introduce `port` only for a real replaceable boundary. - -API route prefixes and JSON `code/message/data` envelopes remain as approved on 2026-09-18. Runtime settings still come only from `config/setting.json`; environment-variable configuration remains prohibited. Authentication remains business composition through App/domain capabilities rather than a compiler-owned HTTP policy. diff --git a/.trellis/tasks/09-04-dever-language-mvp/research/package-distribution.md b/.trellis/tasks/09-04-dever-language-mvp/research/package-distribution.md deleted file mode 100644 index e67a52b..0000000 --- a/.trellis/tasks/09-04-dever-language-mvp/research/package-distribution.md +++ /dev/null @@ -1,51 +0,0 @@ -# Package Distribution Research - -## Question - -How should a Dever project consume a component downloaded from GitHub or another Git host without leaking transport details into `.dever` source or losing reproducible builds? - -## Primary Evidence - -- Go defines a module as a versioned collection of packages. The module path is also the prefix of package import paths and usually identifies where the module can be downloaded. Downloaded source is shared through a module cache, and hashes are verified against `go.sum`. - - https://go.dev/ref/mod - - https://go.dev/doc/modules/gomod-ref -- Cargo permits registry, Git and local path sources. Git dependencies may select a tag or revision, and Cargo locks the resolved commit in `Cargo.lock` until an explicit update. - - https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html -- Cargo and Go both separate downloaded source caches from project build artifacts. Go also supports optional vendoring for a fully project-local source tree. - - https://go.dev/ref/mod#module-cache - - https://go.dev/ref/mod#vendoring - - https://doc.rust-lang.org/cargo/reference/config.html#cache - -## Alternatives - -### Git URL as package identity - -Example: `github.com.shemic.contact.phone.parse(raw)`. - -This is easy to locate but couples every source reference and type identity to the current hosting provider. Repository transfer, self-hosting or registry mirroring then becomes a source-breaking rename. It also creates long names that obscure the business API. - -### Project-local copied dependencies - -Example: clone every dependency under `vendor/`. - -This is transparent and offline-friendly but duplicates source across projects, increases repository size and makes accidental dependency edits likely. It is useful as an explicit export mode, not the default store. - -### Stable identity plus independent source - -Example identity: `shemic.contact`; example source: `https://github.com/shemic/contact.git` at an exact resolved commit. - -This preserves short, stable `.dever` names while allowing registry, Git, mirrors and local development to use the same package identity. It requires dependency metadata and identity verification, but those responsibilities belong to the package manager rather than business source. - -## Recommendation - -Use the third model: - -1. `component id` is the stable namespace and type-identity root. -2. `source` is a replaceable registry, Git or local transport selected outside `.dever`. -3. `dever.mod` records direct dependency intent and source requirements. -4. `dever.lock` records the complete graph, full Git commits and normalized content hashes. -5. A global immutable content-addressed store deduplicates verified source across projects. -6. `check`, `build` and `run` never perform implicit network access; explicit `add`, `update` and `fetch` do. -7. Package declarations must remain beneath the component root, preventing one dependency from supplying another component's namespace. - -This deliberately combines Go's small module/package model and shared verified cache with Cargo's source flexibility and exact Git locking, while avoiding Go's coupling between source-level identity and repository location. diff --git a/.trellis/tasks/09-04-dever-language-mvp/research/runtime-dependencies.md b/.trellis/tasks/09-04-dever-language-mvp/research/runtime-dependencies.md deleted file mode 100644 index 4dbeee0..0000000 --- a/.trellis/tasks/09-04-dever-language-mvp/research/runtime-dependencies.md +++ /dev/null @@ -1,55 +0,0 @@ -# Core 0.1 Runtime Dependency Research - -- Checked: 2026-09-03 -- Scope: dependencies required by already-approved Decimal and Map semantics - -## Decimal128 - -Selected for the MVP: `dec = "=0.4.11"`. - -Evidence: - -- The [dec crate documentation](https://docs.rs/dec/latest/dec/) describes `Decimal128` as a 128-bit decimal representation with 34 digits of precision and exposes a configurable `Context` with rounding and exceptional-condition status. -- The [Decimal128 API](https://docs.rs/dec/latest/dec/struct.Decimal128.html) supports the required arithmetic and classification operations. - -Reason: - -- It directly implements the approved decimal128 contract instead of approximating it with a lower-precision financial decimal. -- Context status lets Dever convert overflow, division by zero and invalid Decimal states into language-level runtime faults. -- A reusable Context avoids the per-operation default-context overhead documented by the crate. - -Constraint: - -- `dec` is a safe Rust wrapper over libdecnumber and therefore introduces a native C build dependency. It must remain isolated behind `dever_runtime::number::DecimalValue`. -- Dever conformance tests, not the crate's operator defaults or special-value surface, define public behavior. -- A future pure-Rust replacement is allowed only when it passes the same conformance suite; this does not change `.dever` semantics. - -Rejected for Core 0.1: - -- `rust_decimal`: pure Rust, but its 96-bit coefficient does not provide the approved 34-digit decimal128 contract. -- Hand-written decimal arithmetic: correct rounding, exponent handling and status behavior are too risky for the language MVP. -- Newly published decimal128 implementations: potentially useful later, but less established than the selected reference implementation. - -## Insertion-Ordered Map - -Selected for the MVP: `indexmap = "=2.14.0"`. - -Evidence: - -- The [IndexMap project](https://github.com/indexmap-rs/indexmap) documents hash-based lookup with iteration independent of hash order. -- The [IndexMap API](https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html) documents that insertion appends new keys, overwriting preserves the existing position, and order-preserving removal is available. - -Reason: - -- Those operations match the approved Dever Map contract without maintaining a duplicate vector-plus-index implementation. -- Lookup remains hash based while iteration is deterministic. - -Constraint: - -- Dever wraps IndexMap and exposes only `get`, `put`, `remove` and `entries`. -- Removal uses the order-preserving operation rather than swap removal. -- Dependency-specific index access never appears in `.dever` or public diagnostics. - -## Dependency Discipline - -These are planned pins; the initial parser milestone has no external dependencies. Verify availability and pin each version when the runtime first consumes it. No dependency becomes a public language contract. Upgrading either dependency requires running the focused Decimal/Map conformance tests and confirming that serialized/displayed Dever values remain unchanged. diff --git a/.trellis/tasks/09-04-dever-language-mvp/task.json b/.trellis/tasks/09-04-dever-language-mvp/task.json deleted file mode 100644 index b55f2bf..0000000 --- a/.trellis/tasks/09-04-dever-language-mvp/task.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "id": "dever-language-mvp", - "name": "dever-language-mvp", - "title": "Dever Language Compiler Contracts And Library Follow-through", - "description": "N5 HTTP/2、定向性能矩阵与有界稳态/恢复压测、typed ORM 及双源码 CMS 合同修正已完成;业务 API 等用户重新设计,编译器发行/跨平台与自举仍未交付,根语言路线图保持进行中。", - "status": "in_progress", - "dev_type": null, - "scope": ".", - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-04", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [ - "09-12-runtime-performance", - "09-12-runtime-performance-p2", - "09-12-http2", - "09-12-http2-performance", - "09-13-http2-ceiling-soak", - "09-13-typed-orm", - "09-18-cms-dual-source-contracts", - "09-19-application-testing" - ], - "parent": null, - "relatedFiles": [], - "notes": "2026-09-18: HTTP/2 有界饱和扫描、128/64 MiB 各 60 秒稳态与各 100 轮重连验收完成;typed ORM 子任务也已完成。原始结果见 test/performance/README.md,历史阶段证据见 implement.md。根任务仍需单独界定发行/跨平台、自举等后续路线;未运行全量测试、操作现有服务、安装全局命令或提交。", - "meta": { - "planning_workflow": "trellis", - "execution_mode": "inline" - } -} \ No newline at end of file diff --git a/.trellis/tasks/09-06-private-compiler-distribution/check.jsonl b/.trellis/tasks/09-06-private-compiler-distribution/check.jsonl deleted file mode 100644 index e69de29..0000000 diff --git a/.trellis/tasks/09-06-private-compiler-distribution/implement.jsonl b/.trellis/tasks/09-06-private-compiler-distribution/implement.jsonl deleted file mode 100644 index e69de29..0000000 diff --git a/.trellis/tasks/09-06-private-compiler-distribution/prd.md b/.trellis/tasks/09-06-private-compiler-distribution/prd.md deleted file mode 100644 index 45b389a..0000000 --- a/.trellis/tasks/09-06-private-compiler-distribution/prd.md +++ /dev/null @@ -1,72 +0,0 @@ -# Dever 私有编译器与公开发行边界 - -## Goal - -让用户只接触 Dever 语言、工具链和发行物,不接触或依赖 Rust/Cargo/rustc;Rust 仅作为私有仓库中的首代引导实现,不进入公开源码、安装流程、命令输出或用户运行环境。 - -## Background - -- 当前 `/data/project/dever` 没有配置 Git 远端,Cargo workspace、Rust 源码、测试和 README 尚未提交,因此没有证据表明实现已经对外发布。 -- 当前仓库及 Git 历史包含 Rust 实现信息,不能直接转换为公开仓库。 -- 当前 `deverc run/build` 调用用户环境中的 `rustc`,并在临时目录生成 Rust 源码;这不符合对外隐藏实现和免 Rust 工具链的要求。 -- 二进制实现无法可靠抵抗专业逆向识别。本任务隐藏正常产品表面和源码实现,不承诺不可逆向。 -- 当前 Rust 编译器及计划使用的 LLVM 后端都有必须合规审查的第三方许可证;不能通过删除或伪造法定声明隐藏实现。 - -## Requirements - -### Repository Boundary - -- 当前编译器仓库保持私有,不向公开仓库推送现有 Git 历史、Cargo 文件、Rust 源码或内部设计资料。 -- 对外发行使用一个没有当前仓库历史的新仓库或等价的独立公开渠道。 -- 公开内容只包含 Dever 用户需要的文档、`.dever` 示例、安装入口和构建后的发行物,不包含编译器实现源码。 - -### Product Surface - -- 用户只使用正式的 `dever` 命令和 `.dever` 源码,不需要了解 Cargo、Rust、rustc 或内部生成语言。 -- 公开文档、安装器、帮助文本、普通诊断、日志和临时文件不得暴露 Rust/Cargo/rustc 实现细节。 -- `dever check/run/build` 不要求用户安装 Rust 工具链,也不得调用用户 PATH 中的 `rustc` 或 `cargo`。 -- `dever build` 生成的程序可独立运行,不依赖 Cargo、Rust 工具链或私有编译器源码。 -- 更换公开发行边界和原生后端不得改变已经确认的 `.dever` 表面语法、诊断位置或当前可执行语义。 - -### Native Backend - -- Rust 可以继续用于私有编译器本身,但用户侧原生编译路径必须由随 `dever` 交付的内置后端完成。 -- 不采用“把 rustc 改名或静默捆绑”来满足隐藏要求;底层工具链不能作为可观察的用户侧子进程或安装前置条件。 -- 编译必须在用户本机离线完成,不上传 `.dever` 源码或中间表示,也不依赖远程构建节点。 -- 不采用云端编译来回避本地后端,因为这会额外引入源码上传、网络依赖和服务可用性边界。 - -### Initial Platform Boundary - -- 首版支持 Linux、Windows 和 macOS;所有编译均在用户本机离线完成。 -- Linux、Windows 和 macOS 均提供 x86_64 与 ARM64 版 `dever`。 -- 任一受支持宿主上的 `dever build` 都必须能够离线生成 Linux、Windows 和 macOS 的 x86_64/ARM64 程序,形成 6 个宿主发行物到 6 个目标的完全对称矩阵。 -- 生成跨平台程序不能依赖远程构建节点或上传源码及中间表示。 -- 目标后端、链接能力和 Dever 平台运行时随发行物提供,不能要求用户另行安装目标平台编译器或 SDK。 -- `dever build` 为 macOS 目标生成平台运行所需的离线 ad-hoc 链接签名;它不代表开发者身份,也不能通过 Gatekeeper 分发验证。 -- Developer ID 身份签名和 Apple 公证是独立的可选发布阶段,不属于 `dever build`;Developer ID 安全时间戳和 Apple 公证均允许并必然需要联网。 - -## Acceptance Criteria - -- [ ] 从一台没有 `cargo` 和 `rustc` 的目标机器安装公开发行物后,可以执行当前里程碑对应的 `dever check/run/build`。 -- [ ] 安装、帮助、正常运行、普通错误和构建临时目录中均不出现 Rust、Cargo、rustc 或 `.rs` 源码。 -- [ ] `dever build` 的输出是可独立运行的目标平台程序,并保持当前 `.dever` 示例的可观察行为。 -- [ ] 公开仓库或公开发行包不包含当前私有仓库的 Git 历史、Cargo metadata、Rust 源码或私有 Trellis 资料。 -- [ ] 自动检查能够证明公开构建路径没有启动 `cargo` 或 `rustc`,并覆盖没有 Rust 工具链的干净环境。 -- [ ] 断网且未安装 Windows 编译工具链的 Linux 环境可以生成 Windows 程序,并在真实 Windows 环境验证其行为。 -- [ ] 断网且未安装 Xcode 或 Apple SDK 的受支持环境可以生成 macOS 程序,并在真实 Intel Mac 和 Apple Silicon Mac 上验证其行为。 -- [ ] 六个宿主发行物分别能够生成六个目标程序,36 种宿主到目标组合使用同一命令合同并通过确定性产物检查;每个目标程序均在对应真实系统与架构上执行验证。 -- [ ] macOS ARM64 产物包含可离线生成的有效 ad-hoc 链接签名;编译不访问开发者身份或公证服务。 -- [ ] 单独的发布流程明确区分 ad-hoc 链接签名、需要联网安全时间戳的 Developer ID 身份签名和需要联网的 Apple 公证。 -- [ ] 私有仓库仍可维护和验证 Rust 引导编译器,公开边界不迫使内部源码改名或制造重复实现。 - -## Out Of Scope - -- 阻止专业人员通过反汇编、二进制指纹或运行时特征推断实现语言。 -- 为隐藏实现而混淆、加壳或伪造二进制来源。 -- 在本任务中实现 HTTP、JSON、数据库、CRUD 或完整 Dever 语言路线。 -- 公开编译器源代码或建立外部贡献者的编译器开发环境。 -- 在 `dever build` 中管理用户的 Developer ID 凭据、执行身份签名或隐式提交 Apple 公证。 - -## Open Question - -- 是否允许依法必须提供的第三方许可证清单提及 Rust;如果不允许,则 Rust 引导编译器只能作为私有 seed,Dever 自举编译器必须成为首次公开发行的前置条件? diff --git a/.trellis/tasks/09-06-private-compiler-distribution/research/cross-compilation.md b/.trellis/tasks/09-06-private-compiler-distribution/research/cross-compilation.md deleted file mode 100644 index cf9dda2..0000000 --- a/.trellis/tasks/09-06-private-compiler-distribution/research/cross-compilation.md +++ /dev/null @@ -1,35 +0,0 @@ -# Linux Host Cross-Compilation - -## Confirmed Toolchain Facts - -- LLVM is designed as a cross-compiler, but target code generation alone is insufficient. A complete build also needs target-specific headers, libraries, linker behavior and usually a sysroot: . -- LLD supports ELF, Windows PE/COFF and macOS Mach-O. Its PE/COFF port is described as complete; Mach-O support exists but is listed after ELF and PE/COFF in completeness: . -- Microsoft publishes the PE/COFF executable and object format specification, so a Linux-hosted backend can produce Windows artifacts without invoking a Windows compiler: . -- Apple's documented universal-binary workflow requires Xcode on a Mac and uses Apple target tooling. Distributed macOS software also has Developer ID signing and notarization requirements: and . -- Apple exposes a Notary REST API, so submission need not use `notarytool`, but this does not remove SDK, linking, signing or real-device validation concerns: . - -## Product Consequences - -### Linux to Windows - -This is a practical offline target. A target-neutral Dever frontend can feed an embedded native backend, then a PE/COFF linker can combine generated code with a versioned Dever Windows runtime and required import libraries. The resulting `.exe` still needs validation on real x86_64 and ARM64 Windows systems. - -### Linux to macOS - -Generating x86_64 or ARM64 instructions and a Mach-O file on Linux is technically possible. Treating that file as a supported macOS product is harder: platform libraries, minimum OS versions, Mach-O signing details, Developer ID distribution, notarization and testing remain Apple-platform concerns. Redistributing an Apple SDK inside the Linux compiler also introduces a licensing boundary and must not be assumed acceptable. - -For the current Text/println subset, a self-contained Dever runtime and purpose-built Mach-O path could avoid most SDK use. That shortcut does not establish a maintainable path for the planned HTTP, TLS, files, database and other system integrations. - -Local compilation and public distribution are separate contracts. Once the target backend and versioned Dever macOS runtime are installed, `dever build` can remain offline. Apple Silicon requires every executable to be signed, so the linker must create an identity-free ad-hoc signature as part of offline output: . Developer ID distribution signing requires the developer's identity and an online secure timestamp: . Apple's notarization service then requires uploading the signed artifact. Apple exposes a REST API for non-macOS notarization clients, but the service is necessarily online: . - -## Recommended Boundary - -- Keep parsing, checking, HIR and target selection shared. -- Support offline Linux-to-Windows cross-build as a normal target once the embedded backend exists. -- Keep all first-release compilation local and offline; do not transfer source or intermediate representations to a build service. -- Include macOS as an offline compilation target without introducing controlled Mac build infrastructure. Treat Developer ID signing and Apple notarization as separate optional publishing stages, and require real Intel and Apple Silicon validation for supported Mach-O output. -- Implement each target through small ABI/runtime/object-format adapters rather than duplicating compiler flows. - -## Open Product Decision - -Resolved: the first release uses a fully symmetric Linux, Windows and macOS x86_64/ARM64 host-to-target matrix. Six host distributions must each produce all six targets locally and offline. diff --git a/.trellis/tasks/09-06-private-compiler-distribution/research/distribution-licensing.md b/.trellis/tasks/09-06-private-compiler-distribution/research/distribution-licensing.md deleted file mode 100644 index d4ad083..0000000 --- a/.trellis/tasks/09-06-private-compiler-distribution/research/distribution-licensing.md +++ /dev/null @@ -1,23 +0,0 @@ -# Distribution Licensing And Implementation Disclosure - -## Confirmed Facts - -- The Rust project and standard library are distributed under `MIT OR Apache-2.0`: and . -- A public compiler binary built from the current Rust implementation can contain Rust standard-library code. Its exact notice obligations require a release-license audit; the project must not assume that deleting all Rust attribution is permitted. -- LLVM is `Apache-2.0 WITH LLVM-exception`. LLVM states that binaries including LLVM must reproduce its copyright notice, while permitting closed-source and commercial use: . -- Apple licenses prohibit separately using Apple SDKs or running Apple Software on non-Apple-branded hardware, and generally prohibit redistributing Apple Software in whole or part without permission: . - -## Consequences - -Hiding Cargo files, symbols and implementation-specific diagnostics is a product-surface concern. Required third-party notices are a separate compliance concern and must remain truthful. - -There are two viable disclosure boundaries: - -1. Ship the Rust bootstrap compiler initially. Normal product surfaces mention only Dever, but a compliant third-party notice may identify Rust and LLVM. Professional binary identification is already outside the task scope. -2. Never ship the Rust bootstrap compiler publicly. Use it only as the private stage-1 seed, complete enough Dever language and runtime capabilities to build a stage-2 compiler, and publicly distribute the verified stage-2/stage-3 Dever compiler. LLVM attribution can remain if LLVM is embedded, but Rust is absent from the public executable and notices. - -The second boundary matches a strict “no public Rust trace” requirement but makes self-hosting a release prerequisite rather than a later roadmap item. It materially expands the first public release. - -## Rule - -Do not use renamed tools, stripped license files, misleading notices, obfuscation or packaging tricks as a substitute for the chosen disclosure boundary. diff --git a/.trellis/tasks/09-06-private-compiler-distribution/research/native-backend-options.md b/.trellis/tasks/09-06-private-compiler-distribution/research/native-backend-options.md deleted file mode 100644 index 2de76f4..0000000 --- a/.trellis/tasks/09-06-private-compiler-distribution/research/native-backend-options.md +++ /dev/null @@ -1,104 +0,0 @@ -# Native Backend Options - -## Required Properties - -- Consume checked Dever HIR without changing `.dever` syntax or semantics. -- Generate x86_64 and ARM64 ELF, PE/COFF and Mach-O on every supported host. -- Run fully offline without Cargo, rustc, a target SDK or a remote build service. -- Preserve direct native calls, concrete value layouts and the existing native performance direction. -- Keep generated IR, objects and link details private, owned temporary artifacts. -- Avoid six target-specific compiler implementations. - -## Options - -| Option | Strengths | Blocking weaknesses | Decision | -| --- | --- | --- | --- | -| Pinned LLVM code generation plus LLD | Mature optimization; x86_64/ARM64; ELF, PE/COFF and Mach-O; supports in-process use | Large host binaries, native integration boundary, mandatory LLVM notices, target runtimes still required | Recommended | -| Cranelift plus LLD | Safe Rust-facing library, fast compilation, x86_64/ARM64 | Still needs a cross-format linker and target runtimes; optimization quality creates risk against the native performance contract | Keep as fallback only if measured LLVM integration cost is unacceptable | -| Custom machine-code and executable writers | Full control and small artifacts for the current subset | Reimplements two ISAs, three formats, relocation, unwind and linking; duplicates platform logic and does not scale to the language roadmap | Reject | -| WebAssembly or a bytecode VM inside native launchers | Simple portable execution model | Changes the AOT/runtime architecture, adds a production VM and jeopardizes native performance requirements | Reject for production build/run | -| Generated Rust plus bundled or renamed rustc | Reuses current implementation | Exposes the forbidden toolchain, produces Rust temporary source and makes offline target support depend on Rust sysroots/linkers | Replace completely | - -LLVM's cross-compilation documentation still requires target-specific sysroots/libraries beyond machine-code generation: . LLD supports the three required executable formats and can be embedded for compiler-owned trusted objects: and . - -## Proposed Ownership - -```text -dever-core - checked, target-neutral HIR and source diagnostics - -dever-native - fixed target catalog - HIR -> LLVM lowering - object emission - LLD integration - target-pack selection - owned temporary artifacts - -dever-runtime - Dever-owned ABI and runtime behavior - six release-built target packs - -dever-cli - --target parsing, host/default selection, output and process adaptation -``` - -`dever-native` is one justified private workspace boundary: it isolates the large native dependency and target mechanics from parsing/checking. It is not a public backend plugin API. Target variation uses one explicit catalog and small data/config adapters, not inheritance or a registry. - -## Build Data Flow - -```text -.dever -> check -> typed HIR -> specialize reachable program - -> shared LLVM lowering -> target object in memory - -> fixed target specification + versioned Dever runtime pack - -> embedded LLD driver -> new executable output -``` - -- LLVM IR and object files are never public output formats. -- `dever build` creates a new output and keeps the current no-overwrite contract. -- `dever run` always builds the host target and runs it; cross-target execution/emulation is not added. -- A cross-target `build` only generates an artifact. Real target runners validate it in release CI. - -## Target Catalog - -The public catalog has exactly six initial targets: - -```text -linux-x86_64 -linux-arm64 -windows-x86_64 -windows-arm64 -macos-x86_64 -macos-arm64 -``` - -Each target definition owns its LLVM triple, CPU baseline, object format, calling convention, executable suffix, runtime pack and deterministic linker settings. Shared OS and architecture helpers remove repetition; target entries remain explicit and reviewable. - -## Runtime Packs - -Generated code must use a Dever-owned ABI rather than Rust's unstable ABI or Rust `String` layout. Each target pack contains only Dever-owned startup/runtime objects and permitted platform import metadata. It must not contain Rust standard-library objects, Apple SDK files or target compiler binaries. - -The current `dever-runtime` source is a behavior reference, not a stable native ABI. The first backend milestone defines the minimal Text slice, result/fault and `println` ABI once, then supplies six compiled implementations or target-specific adapters behind that contract. Future collections, numbers, HTTP, TLS and storage extend this ABI deliberately rather than reaching into host-language layouts. - -## Determinism And Matrix Verification - -- Pin one LLVM/LLD source revision and runtime-pack version for all six host builds. -- Remove timestamps, absolute build paths, random UUID inputs and host-dependent ordering. -- Each of six host compilers builds all six targets, producing 36 artifacts. -- Artifacts for the same target and source should be byte-identical across hosts. Hash equality reduces execution validation to one artifact per target; all six target artifacts still run on real matching systems. -- Offline checks deny network access and remove Cargo, rustc, Xcode, Visual Studio, GCC and target SDKs from PATH. - -## Release And License Gates - -- LLVM permits proprietary distribution but requires its copyright notice in binaries that include it: . -- No Apple SDK file may enter a target pack. Apple's agreement prohibits separately using SDKs on non-Apple hardware and redistributing Apple Software in part: . -- Before implementation commits to the macOS target, prove that both Mach-O targets can link the minimal Dever runtime without redistributed Apple SDK material and pass real-machine execution. -- The public-compiler Rust attribution decision in `distribution-licensing.md` remains a product gate. - -## Rejected Shortcuts - -- Do not rename or conceal rustc, Cargo, LLD or license files. -- Do not special-case the hello example or patch prebuilt executable templates. -- Do not implement one backend per OS. -- Do not upload source or HIR when local target support is missing. -- Do not silently fall back to a VM, host execution or another target. diff --git a/.trellis/tasks/09-06-private-compiler-distribution/task.json b/.trellis/tasks/09-06-private-compiler-distribution/task.json deleted file mode 100644 index 9c7de7d..0000000 --- a/.trellis/tasks/09-06-private-compiler-distribution/task.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "id": "private-compiler-distribution", - "name": "private-compiler-distribution", - "title": "Dever 私有编译器与公开发行边界", - "description": "隐藏 Rust 引导实现并建立不依赖 Rust 工具链的公开发行路径", - "status": "planning", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-06", - "completedAt": null, - "branch": null, - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [ - "09-28-shared-toolchain" - ], - "parent": null, - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/09-12-http2-performance/check.jsonl b/.trellis/tasks/09-12-http2-performance/check.jsonl deleted file mode 100644 index 5b9a0a0..0000000 --- a/.trellis/tasks/09-12-http2-performance/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"检查 HTTP/2 配置与运行时公开合同一致"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"检查测量公平性、计数完整性、资源预算和验证范围"} -{"file":".trellis/tasks/09-12-http2-performance/research/current-benchmark-and-h2-api.md","reason":"核对实现是否真正拆分物理连接和并发流"} diff --git a/.trellis/tasks/09-12-http2-performance/design.md b/.trellis/tasks/09-12-http2-performance/design.md deleted file mode 100644 index 2a7be5a..0000000 --- a/.trellis/tasks/09-12-http2-performance/design.md +++ /dev/null @@ -1,84 +0,0 @@ -# 设计 - -## 1. 边界与复用 - -继续使用 `test/performance` 的“构建与测量分离”结构:`build.py` 只生成并指纹化产物,`run.py` 只启动清单内的二进制并采样。进程、cgroup、直方图、逐 case 落盘和失败保留逻辑全部复用。新增的唯一核心抽象是 HTTP 连接拓扑: - -```text -ConnectionShape - physical_connections - streams_per_connection - request_slots = physical_connections * streams_per_connection -``` - -HTTP/1.1 要求 `streams_per_connection = 1`;HTTP/2 要求复用连接。这个模型避免继续把并发请求与 TCP 连接混为一个 `connections` 参数,也让报告能解释吞吐和内存差异来自哪里。 - -## 2. Rust 基准对端与负载端 - -`network_bench` 的统一负载入口调整为: - -```text -network_bench load h1|h2 URL PATH RATE SECONDS PHYSICAL_CONNECTIONS STREAMS_PER_CONNECTION TIMEOUT_MS REUSE CA -``` - -所有仓库调用者一次性迁移,不保留第二套旧参数解析。 - -- HTTP/1.1 保留现有“一名 worker 独占一条连接”的实现,并要求 streams 为 1。 -- HTTP/2 在计时前主动建立指定数量的物理连接;每条连接由 Hyper HTTP/2 client driver 持有,`SendRequest` 按该连接的请求槽克隆给 worker。总 worker 数为 shape 的乘积,worker 固定映射到连接,不额外建立连接。 -- HTTP/2 连接中断后不重试请求或静默补建连接。失败必须进入错误计数,避免恢复逻辑污染吞吐数据。 -- 两种协议共享现有速率调度、队列、响应校验、延迟直方图和结果守恒逻辑,不复制 metrics/validation。 -- 结果新增 `http_version`、`physical_connections`、`streams_per_connection`、`request_slots` 和 `successful_handshakes`。H2 的握手数必须等于物理连接数。 - -H2 请求使用完整 scheme/authority/path 和 `Version::HTTP_2`。明文使用 prior knowledge;TLS client/server 配置按协议派生 ALPN,H2 只允许 `h2`,不改变运行时用于 WSS 的共享 TLS 配置。 - -服务模式新增 `runtime-http2`、`runtime-https2`、`hyper-http2`、`hyper-https2`。`ServiceKind` 集中派生 runtime/TLS/H2 三个维度,避免模式分支散落。直接 runtime 使用 `Http2Limits`;原生 Hyper 使用 `http2::Builder`,显式配置与 N5 相同的 streams、窗口、header/frame/send-buffer 上限。两者继续复用同一响应路由和连接生命周期。 - -## 3. Dever 夹具与构建清单 - -HTTP 夹具暴露 `http`、`https`、`http2`、`https2` 四个入口。`serve` 接收 `dever.http.Limits` 参数,四个 worker 只负责选择 TLS 和协议配置,避免复制路由与关闭流程。 - -`build.py` 增加 HTTP/2 构建参数并写入 manifest: - -- `http2_streams = 16` -- `http2_stream_window_bytes = 65535` -- `http2_connection_window_bytes = 262144` - -`config.dever` 分别生成 HTTP/1.1 和 HTTP/2 limits;`task_capacity` 继续按有界并发计算,并校验正式拓扑的总请求槽不超过语言上限。旧产物目录和报告不修改,新构建必须使用新的输出目录。 - -## 4. Python 运行器 - -新增两个显式 suite: - -- `http2`:吞吐、延迟与活跃资源矩阵。 -- `http2-recovery`:同一服务进程上的多轮连接建立、请求和断开。 - -`--http2-connections` 接受物理连接档位,默认 `1,4`;每连接流数从 manifest 读取。`--implementations` 可将 smoke 或 64 MiB 场景限制为 `dever`,正式矩阵默认为 `dever,runtime,hyper`。已有 `http` suite 的 `--concurrency` 和连接新建/复用语义不变。 - -吞吐 case 的流程为:启动服务并取得 READY,运行独立 warmup,等待连接释放并采样基线,运行正式负载,同时采样服务端与客户端;负载退出后再次采样以记录 FD/RSS 回落。case 名和 JSON 主键包含实现、传输、路径、速率、物理连接、每连接流和 repeat,避免结果覆盖或混淆。 - -恢复 case 使用独立参数 `--recovery-connections`、`--recovery-rate`、`--recovery-path`,复用 `--cycles` 与 `--duration`。每轮启动一次负载进程,在同一服务上建立固定 shape,完成请求后关闭连接;运行器等待稳定窗口并保存该轮末样本。FD 不回到 READY 基线、请求错误、握手数不符或服务提前退出均使 case 失败。RSS 只报告趋势,不以“没有立即回到启动值”单独判断泄漏。 - -报告继续保留 `cases.jsonl` 和 `report.json`,并在完整或部分结果上生成结构化 `summary`。摘要按实现、协议、TLS、路径、速率和 topology 分组,对成功 QPS、p99、RSS/PSS/FD 峰值取各 repeat 中位数;不把不同 offered rate 或饱和/未饱和 case 混合。 - -## 5. 测量矩阵 - -正式测量固定服务端 1 worker、1 CPU、128 MiB cgroup、swap=0;客户端绑定另一 CPU且位于服务预算之外。每组 0.5 秒预热、2 秒正式负载、3 个独立服务进程 repeat: - -| 正文 | offered rate | topology | 实现 | 传输 | -| --- | --- | --- | --- | --- | -| `/plain` 5 B | 5k / 15k / 30k req/s | 1x16、4x16 | Dever/runtime/Hyper | h2c、TLS+h2 | -| `/bytes` 64 KiB | 100 / 500 / 1k req/s | 1x16、4x16 | Dever/runtime/Hyper | h2c、TLS+h2 | - -另运行 10 轮、1x16、`/plain` 的恢复矩阵,以及 64 MiB 下 Dever 的 1x16 明文/TLS 活跃代表场景。若当前机器不能创建指定 cgroup,工具必须明确失败;不得回退为无预算结果后仍标记完成。 - -## 6. 解释与决策 - -- 主要比较同一 H2 topology 下 Dever、runtime 和 Hyper 的差异,定位语言桥接、运行时结构化任务和底层协议栈各自成本。 -- 1x16 与 4x16 比较多路复用和多物理连接扩展;它们不是“连接数相同”的横向比较。 -- `/bytes` 的速率按响应字节量降低,避免只测客户端或 loopback 带宽耗尽;65536 字节正文会越过 65535 字节默认单流窗口,可观察 WINDOW_UPDATE 路径。 -- `dropped_capacity` 表示负载端无法在计划时间取得请求槽,不算服务错误;分析时必须同时看 actual QPS、请求延迟和服务 CPU,不能只看 offered rate。 -- 不设预定胜负线。若 Dever 相对 direct runtime 出现稳定的大幅差距,或内存随 recovery 周期持续增长,则把证据和复现命令交给后续独立优化任务。 - -## 7. 回退形态 - -本阶段不迁移生产 API。若 H2 基准实现无法通过独立 smoke,删除新增 suite、服务模式和夹具入口即可回到原有 H1 基准;历史产物目录不受影响。任何正式测量都写入新的 `target/performance/*` 目录,失败结果保留且不覆盖旧报告。 diff --git a/.trellis/tasks/09-12-http2-performance/implement.jsonl b/.trellis/tasks/09-12-http2-performance/implement.jsonl deleted file mode 100644 index b330ae6..0000000 --- a/.trellis/tasks/09-12-http2-performance/implement.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"HTTP/2 streams、窗口、ALPN、结构化任务和资源预算合同"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"独立二进制基准、cgroup、报告和定向验证规则"} -{"file":".trellis/tasks/09-12-http2-performance/research/current-benchmark-and-h2-api.md","reason":"现有 H1 基准限制、锁定 Hyper API 和 H2 负载模型结论"} diff --git a/.trellis/tasks/09-12-http2-performance/implement.md b/.trellis/tasks/09-12-http2-performance/implement.md deleted file mode 100644 index 1f9e423..0000000 --- a/.trellis/tasks/09-12-http2-performance/implement.md +++ /dev/null @@ -1,50 +0,0 @@ -# 执行计划 - -## 1. 任务启动 - -- [x] 用户审核本 PRD、设计和执行计划后,运行 `task.py start`;启动前不改产品或基准源码。 -- [x] 使用 `trellis-before-dev` 重新加载 backend 规范,核对工作区状态和已有性能产物,不清理用户文件。 - -## 2. 基准协议模型 - -- [x] 在 `network_bench` 中加入 `h1|h2` 与 `ConnectionShape` 参数校验;H1 限制每连接一槽,H2 限制复用且乘积有界。 -- [x] 保留一个速率调度和 metrics 路径;把 H1 独占连接与 H2 共享 sender 封装为两个小的协议执行分支,不引入通用 trait 层级。 -- [x] H2 计时前建立固定数量物理连接,按连接分配 sender clone,关闭时排空/终止 driver;不重试、不自动扩容。 -- [x] 在结果中输出并校验协议、shape 和握手计数,继续保证全部请求计数守恒和完整正文校验。 - -## 3. 三类服务实现 - -- [x] 扩展 `ServiceKind` 和 TLS ALPN 派生,新增 runtime/raw Hyper 的 h2c 与 TLS+h2 模式。 -- [x] direct runtime 与 raw Hyper 使用相同的 streams、窗口、header/frame/send-buffer 约束;复用响应路由、accept 限额和关闭流程。 -- [x] 重构 Dever HTTP fixture,让四个入口共享 serve/route/lifecycle,只在入口选择协议和 TLS。 -- [x] 扩展构建配置与 manifest,生成并指纹化 `http2`、`https2`,保留 H1 产物。 - -## 4. 运行器与摘要 - -- [x] 增加 `http2`、`http2-recovery` suite、物理连接档位、实现筛选及恢复参数,并按 manifest 校验 capacity、streams 和窗口。 -- [x] HTTP/2 吞吐 case 记录 warmup、正式负载、断开后样本、服务/客户端资源和 cgroup 状态;case 标识包含完整维度。 -- [x] 恢复 case 在一个服务进程内运行多轮固定 shape,逐轮校验请求和握手并记录 FD/RSS 回落。 -- [x] 从逐 case 结果生成分组中位数 summary;失败时仍保存已完成 case 和可诊断日志。 - -## 5. 定向验证 - -- [x] 运行 `python3 -m unittest discover -s test/performance -p 'test_runner.py' -v`,覆盖参数、计数、summary、进程回收和错误路径。 -- [x] 离线 release 构建 `network_bench`,运行现有独立 Python H1 对端测试,确认一次性 CLI 迁移没有改变 H1 测量语义。 -- [x] 运行 H2 loopback smoke,覆盖 1 条物理连接、至少 16 个请求槽、明文/TLS、`/plain`/`/bytes`、三类服务模式和错误正文拒绝。 -- [x] 用新的输出目录构建 Dever 性能夹具,核对 manifest 指纹、HTTP/2 limits 和四个 HTTP 入口。 -- [x] 运行最小 `http2`/`http2-recovery` runner smoke,检查失败报告、FD 回落和原始计数完整性。 - -## 6. 有界正式测量 - -- [x] 先确认可用 CPU affinity、cgroup v2 cpu/memory 控制器、磁盘和已有服务边界,再说明将执行的有界命令。 -- [x] 运行 128 MiB `/plain` 矩阵:5k/15k/30k,1x16/4x16,三实现、h2c/TLS、3 repeats。 -- [x] 运行 128 MiB `/bytes` 矩阵:100/500/1000,1x16/4x16,三实现、h2c/TLS、3 repeats。 -- [x] 运行 128 MiB 10 轮恢复矩阵,并运行 64 MiB Dever 1x16 明文/TLS 活跃场景。 -- [x] 核对全部报告 status、errors、dropped、OOM、FD、RSS/PSS、CPU 和摘要分组;不以单次异常样本下结论。 - -## 7. 收尾审查 - -- [x] 更新 `test/performance/README.md` 和 `.trellis/spec/backend/quality-guidelines.md` 的 CLI、矩阵、实测结果和边界说明。 -- [x] 检查最终改动是否仍有重复协议分支、混合职责或无必要依赖;确认未修改生产运行时、旧报告和用户文件。 -- [x] 运行任务 JSONL 校验、Python 语法检查及受影响的最小回归;不运行全量测试。 -- [x] 记录实际通过、失败、跳过和不可用项;完成 Trellis 检查与会话记录,不提交 Git。 diff --git a/.trellis/tasks/09-12-http2-performance/prd.md b/.trellis/tasks/09-12-http2-performance/prd.md deleted file mode 100644 index 839a233..0000000 --- a/.trellis/tasks/09-12-http2-performance/prd.md +++ /dev/null @@ -1,40 +0,0 @@ -# HTTP/2 性能基准 - -N5 已完成 HTTP/2 服务端、客户端和连接池的功能接入,但现有独立二进制基准仍只测 HTTP/1.1。当前阶段为 HTTP/2 建立可重复的小机器性能证据,不凭功能测试或理论值宣称性能提升。 - -## 需求 - -- 扩展现有显式运行的独立二进制基准,新增 HTTP/2 suite;保留已有 HTTP/1.1、异步和长连接基准的语义及历史报告。 -- 覆盖明文 prior knowledge 和 TLS ALPN 两种 HTTP/2 传输,统一比较原生 Dever 程序、直接 `dever-runtime` 和原生 Hyper 三种实现。 -- 负载模型必须把物理 TCP 连接数与每连接并发流数分开。每个报告明确记录协议、TLS、物理连接数、每连接请求槽、总请求槽、服务端流/窗口配置和正文大小。 -- 至少覆盖单连接多流和多连接多流;请求必须校验状态码、Content-Type 和完整正文,所有计划、发送、完成、失败及丢弃请求均可核对。 -- 记录实际成功吞吐、总延迟/排队延迟/请求延迟的 p50/p95/p99,以及服务端和客户端 RSS、PSS、峰值、线程、FD、CPU 和 cgroup 内存/OOM 数据。 -- 同一服务进程上重复建立、使用和关闭 HTTP/2 连接,记录每轮断开后的 FD/RSS 差值,验证物理连接能够回收且内存不按轮持续增长。 -- 生成按实现、传输、路径、速率和连接拓扑分组的中位数摘要,同时保留逐 case 原始样本和失败时已完成的数据。 -- 完成 1 worker、1 服务 CPU、128 MiB、无 swap 的正式矩阵,并完成 64 MiB 下的 Dever 活跃 HTTP/2 代表场景;负载端使用独立 CPU且不计入服务预算。 - -## 约束 - -- 本任务只改基准夹具、基准对端、运行器、定向测试和对应性能文档;不修改 `crates/dever-runtime`、编译器或语言公共 API。基准揭示的生产瓶颈另建优化任务,避免边测边改导致基线失效。 -- 复用仓库锁定的 Hyper 1.11.1、h2 0.4.19、rustls 和现有进程/cgroup 采样器,不引入新的协议栈或压测依赖。 -- HTTP/2 明文只使用 prior knowledge;TLS 只协商 `h2`,不降级 HTTP/1.1。HTTP/1.1 每连接请求槽固定为 1,HTTP/2 只测复用连接,不测每请求新建连接。 -- 服务端与客户端固定使用 N5 默认值:每连接 16 流、65535 字节单流接收窗口、262144 字节连接接收窗口,以及运行时已有的 16 KiB frame/send-buffer 上限。 -- `/plain` 用于小响应调度和协议开销,`/bytes` 使用 65536 字节正文并跨越默认单流窗口;`/json` 不进入正式矩阵,因为当前夹具只返回预制 JSON,信息与小响应重复。 -- 不设与机器无关的绝对 QPS 或内存门槛。错误、OOM、计数不守恒和 FD 未回落属于失败;容量丢弃与相对性能只作为结果,不伪装成通过或失败阈值。 -- 仅运行本任务的 Python 单元测试、独立 loopback smoke、必要的离线 release 构建和显式有界性能命令;不运行全量测试,不替换全局二进制,不接触已有服务,不提交 Git。 - -## 验收标准 - -- [x] HTTP/1.1 旧入口仍通过现有独立 Python 对端测试;HTTP/2 smoke 证明一条实际物理连接承载至少 16 个并发请求槽,明文和 TLS 均完整成功。 -- [x] 构建清单包含 `http2`/`https2` Dever 产物、HTTP/2 配置及所有二进制指纹;运行阶段只使用清单中的已构建产物。 -- [x] `http2` suite 覆盖三种实现、两种传输、`/plain` 与 `/bytes`、`1 x 16` 与 `4 x 16` 两种拓扑,并保存可核对的逐 case 数据与聚合摘要。 -- [x] `http2-recovery` suite 在同一服务进程上完成至少 10 轮连接周期;每轮请求正确,断开后 FD 回到 READY 基线,且报告保留 RSS 变化序列。 -- [x] 128 MiB 正式矩阵中无请求错误、无 OOM;丢弃请求如实报告。64 MiB 代表场景无 OOM,并报告峰值而非只报告进程 RSS。 -- [x] 文档写明运行命令、环境、矩阵、限制和实测结论;不得将 HTTP/2 结果外推为所有后端负载或真实网络的性能保证。 -- [x] 定向测试覆盖参数校验、计数守恒、连接拓扑字段、摘要分组、H2 明文/TLS 正文校验、进程失败和连接回收;相关检查全部通过。 - -## 排除项 - -- RFC 8441 WebSocket-over-HTTP/2、h2c Upgrade、HTTP/3、服务器推送、非空 trailers、HTTP/2 客户端自动重试。 -- 小时级 soak、跨主机网络、丢包/限速故障注入、真实公网站点和多平台硬件矩阵。 -- 本阶段根据一次测量直接改写运行时热路径或承诺固定的 Fiber/Go 对比数字。 diff --git a/.trellis/tasks/09-12-http2-performance/research/current-benchmark-and-h2-api.md b/.trellis/tasks/09-12-http2-performance/research/current-benchmark-and-h2-api.md deleted file mode 100644 index 7599ded..0000000 --- a/.trellis/tasks/09-12-http2-performance/research/current-benchmark-and-h2-api.md +++ /dev/null @@ -1,31 +0,0 @@ -# 现有基准与 HTTP/2 API 调研 - -## 现有结构 - -- `test/performance/build.py` 负责生成 Dever fixtures、复制 Rust peers、记录配置和 SHA-256;`run.py` 只执行已指纹化产物。这一分离可直接复用。 -- 当前 HTTP suite 覆盖 Dever、direct runtime、raw Hyper,但三者都只使用 HTTP/1.1。`config.dever` 明确写入 `http2 = null`。 -- 当前 loader 的 `connections` 同时决定 worker 数和连接数,每个 worker 串行持有一条 HTTP/1.1 连接;它无法证明 HTTP/2 多路复用。 -- 现有 runner 已有固定速率调度、三类延迟直方图、进程 RSS/PSS/FD/CPU 采样、cgroup memory/peak/OOM 采样、逐 case 落盘和异常清理,不应重写。 -- `live` suite 已有多轮连接后 FD/RSS 差值的报告方式,可复用其 phase 后采样语义,但 HTTP/2 负载和连接创建应继续由 `network_bench` 负责。 - -## N5 已有合同 - -- `Http2Limits` 的公开维度为 streams、stream window 和 connection window;默认分别为 16、65535、262144。 -- cleartext HTTP/2 使用 prior knowledge;TLS 配置必须协商 `h2`,不能降级或影响 WSS 的 HTTP/1.1 TLS 配置。 -- 客户端按流租约复用物理连接,服务端连接和流均受限;固定 16 KiB frame/send-buffer,关闭自适应窗口。 -- `/bytes` fixture 为 65536 字节,恰好跨过默认 65535 字节单流窗口,适合覆盖 flow-control 热路径。 - -## 锁定依赖可用能力 - -- Cargo.lock 固定 Hyper 1.11.1、h2 0.4.19、rustls 0.23.44 和 tokio-rustls 0.26.5,不需要新依赖。 -- Hyper HTTP/2 `SendRequest` 实现 `Clone`,可让多个请求 worker 共享同一物理连接的 driver。 -- Hyper HTTP/2 client/server builder 可显式设置 initial stream/connection window、adaptive window、max concurrent streams、max frame、max send buffer 和 header list size。 -- Hyper HTTP/2 request future 的取消会对单流发送 RST_STREAM;基准不需要自己实现帧协议。 - -## 设计结论 - -1. 物理连接与请求槽必须拆开;只给现有 loader 换 HTTP/2 handshake 会得到错误的“一 worker 一连接”模型。 -2. H2 连接应在计时前主动建立,worker 固定映射到已建 sender;这样报告的物理连接数由 loader 自己控制和证明。 -3. H1 和 H2 共享调度、计数和响应校验,但连接执行策略分开。不存在足够稳定的公共行为值得引入 trait 或继承式抽象。 -4. raw Hyper 对照必须显式复制 N5 的协议参数;使用 Hyper 默认值会把配置差异误判为 Dever/runtime 开销。 -5. 性能任务不同时修改生产 runtime。测量发现的瓶颈需要在固定基线后另立任务验证,否则优化前后结果不可复现。 diff --git a/.trellis/tasks/09-12-http2-performance/task.json b/.trellis/tasks/09-12-http2-performance/task.json deleted file mode 100644 index 6fb6010..0000000 --- a/.trellis/tasks/09-12-http2-performance/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "http2-performance", - "name": "http2-performance", - "title": "HTTP/2 performance benchmarks", - "description": "扩展现有独立二进制基准,测量小内存下 HTTP/2 多路复用的吞吐、尾延迟、内存和连接回收。", - "status": "completed", - "dev_type": null, - "scope": "test/performance + test/dever-tests/examples/network_bench* + performance docs/spec", - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-12", - "completedAt": "2026-09-13", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-04-dever-language-mvp", - "relatedFiles": [], - "notes": "HTTP/2 benchmark complete: 224 formal cases plus 60 recovery cycles, fixed 1x16/4x16 topology, h2c/TLS and Dever/runtime/Hyper comparisons. All request errors, OOM and FD deltas were zero; 64 MiB active Dever cases passed. Sixteen runner tests, three loopback tests, release cargo check, Dever fmt-check and independent review passed. No full suite, Rustfmt/Clippy, commit or archive.", - "meta": {} -} diff --git a/.trellis/tasks/09-12-http2/check.jsonl b/.trellis/tasks/09-12-http2/check.jsonl deleted file mode 100644 index 02213de..0000000 --- a/.trellis/tasks/09-12-http2/check.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"检查 HTTP2 的结构化归属、资源容量和桥接"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"定向测试和无全量测试约束"} -{"file":".trellis/tasks/09-12-http2/prd.md","reason":"完整范围和验收"} -{"file":".trellis/tasks/09-12-http2/design.md","reason":"协议配置与生命周期"} diff --git a/.trellis/tasks/09-12-http2/design.md b/.trellis/tasks/09-12-http2/design.md deleted file mode 100644 index 211bd78..0000000 --- a/.trellis/tasks/09-12-http2/design.md +++ /dev/null @@ -1,21 +0,0 @@ -# 设计 - -## API 与复用 - -在官方 `dever.http.Limits` 增加 `http2: Http2Limits?`;`Http2Limits` 三个 Int 字段为 `streams`、`stream_window_bytes`、`connection_window_bytes`。默认关闭 HTTP/2,`default_http2_limits()` 返回 16 流、65535 字节单流窗口、262144 字节连接窗口。沿用现有 serve/serve_tls/serve_live/client/open/open_stream/send,不增加平行 API。 - -`Limits.check` 统一校验;HTTP/2 streams 和 connections 的乘积不得超过 65536,窗口遵循 HTTP/2 31 位限制(连接窗口至少 65535)。关闭自适应窗口,保持帧和发送缓存有界。源语言 exact-record 检查与原生结构转换同步修改。 - -## 运行时边界 - -- 协议配置、Hyper builder 和 HTTP 专用 TLS ALPN 配置集中在 HTTP 模块,原有 TLS trust/session cache 和 Transport 复用。不能修改共享 TLS 配置使 WSS 错误协商 h2。 -- 编解码复用 message;按协议校验头字段,HTTP/2 使用路径查询而不是绝对 URI 作为 source Request.target,authority 与 Host 一致。 -- HTTP/1 仍独占连接 lease;HTTP/2 持有共享连接与独立流 lease。EOF 或取消释放流,只有连接 owner 结束才释放物理连接许可。空闲回收不能中止活跃流。 -- Hyper Executor 必须接入已有结构化任务 Scope,不能直接用脱离作用域的 TokioExecutor。每流清理独立,程序故障明确传给服务任务,peer reset 只结束该流。 -- GOAWAY 排空与业务取消分开;应用已有 timeout(server, grace_ms, fallback) 控制最长排空时间。 - -## 验证 - -仅运行本次相关 Rust 定向测试、编译器官方库检查和隔离 loopback 原生程序。独立 HTTP/2 对端验证真正单连接多流、SETTINGS/流控、RST_STREAM、GOAWAY、ALPN 和请求语义。保留已有性能报告;缓存可重建部分暂存到专用 /dev/shm 目录以腾出构建空间。 - -协议依据:[RFC 9113](https://www.rfc-editor.org/rfc/rfc9113.html) 与当前锁定 Hyper 1.11.1 源码。 diff --git a/.trellis/tasks/09-12-http2/implement.jsonl b/.trellis/tasks/09-12-http2/implement.jsonl deleted file mode 100644 index 8c6037b..0000000 --- a/.trellis/tasks/09-12-http2/implement.jsonl +++ /dev/null @@ -1,5 +0,0 @@ -{"file":".trellis/spec/backend/directory-structure.md","reason":"Rust 语言分层与 root test 布局"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"HTTP、TLS、流、结构化任务及原生桥接合同"} -{"file":".trellis/spec/backend/error-handling.md","reason":"程序故障与 peer 失败边界"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"有界定向验证与原生测试"} -{"file":".trellis/tasks/09-12-http2/design.md","reason":"本阶段已批准接口与生命周期设计"} diff --git a/.trellis/tasks/09-12-http2/implement.md b/.trellis/tasks/09-12-http2/implement.md deleted file mode 100644 index 8f5db6b..0000000 --- a/.trellis/tasks/09-12-http2/implement.md +++ /dev/null @@ -1,49 +0,0 @@ -# 执行记录 - -## 实现 - -- [x] 用户批准方案后实施,复用 Hyper 1.11.1;启用 http2 feature,锁定 h2 0.4.19 和四个传递依赖,不引入第二套协议栈。 -- [x] 官方 Limits.http2/Http2Limits、精确记录检查和仓库调用者一起迁移;原生桥接复用 Nullable/Record 转换,无新增 intrinsic。 -- [x] protocol/message 集中拥有流控预算、ALPN 派生、authority/Host 和方向相关的头校验。 -- [x] buffered/live 服务端和 single-use/pooled 客户端接通;流式上传、下载、SSE、GOAWAY 和取消沿用现有 API。 -- [x] ScopedOwner/ScopedSpawner 接入已有 Task Scope、全局容量和 blocking 清理;每流独立 Group,物理许可持有到协议后代清理完成。 -- [x] 按工作流完成服务端/客户端实现分工及独立并发、全范围检查;主代理复查关键所有权和运行证据。 -- [x] 更新现有 LANGUAGE、IMPLEMENTATION、README、toolchain-and-library 和性能说明;P1/P2 报告仍保留为 HTTP/1 数据。 -- [x] 最终定向验证与检查闭环。 -- [x] 完成任务状态、会话记录和自有临时目录清理,不提交。 - -## 复现及修正 - -- Hyper Executor 不携带 Dever CURRENT_SCOPE:协议 future 改由连接 owner 创建子 Scope;关闭 admission 与登记使用同一把锁。故障报告/注销先于完成信号;不可取消 supervisor 排空后代,等待者被取消也不能遗失 completion。 -- 池握手的连接 owner 必须在持久 driver 首次 poll 时创建,不能归临时请求 Scope。 -- RST/正文 idle 超时使背压 write 同时失败:先记录传输取消,避免把该流结束当成全局 handler 故障;真正程序错误仍保留原消息。发布失败时先释放 state 锁再析构响应体,避免取消标记重入锁。 -- GOAWAY 后 Hyper dispatch ready 不等于能建新流:仅 TrySendError 结构化返回的未发送请求可在原期限内重排;先释放旧上传/流租约,不重放已发送请求。 -- HTTP/2 Response TE 必须显式拒绝,不能交给 Hyper 静默删除;请求 TE 只接受 trailers。 -- 测试修正:Dever 子任务用 await;静默 h2 peer 可能先收到 SETTINGS,需读到 EOF;独立 h2 的 FlowControl/RecvStream/SendStream 在等 driver 结束前释放。共享原生 fixture 的 HTTP/1 服务端保留三条连接容量,两条供池内嵌套代理,一条供独立 WSS;HTTP/2 客户端仍只允许一条物理连接。 - -## 验证约束 - -使用 PATH 指向已有 stable 工具链、CARGO_TARGET_DIR=target/native-runtime、TMPDIR=/dev/shm/dever-http2-native.fW3PNS,Cargo 均 --offline --locked --release。一轮 fetch 后不再联网。仅自有随机 loopback 端口和 test/ 下测试证书,不运行全量测试、既有服务、性能矩阵或全局安装。 - -首轮 CLI release 构建和 backend 示例 check 通过。官方库 fmt-check 仅报告原有 net.dever 格式差异;修改的 http.dever 无差异。Rustfmt/Clippy 未安装,不作为通过项。 - -低磁盘处理仅将可再生 target/debug/{incremental,deps,build} 暂存到 /dev/shm/dever-http2-cache.wOoaI9;现有 debug/deverc、源码和 target/performance 报告保留。最后统一记录验证结果与缓存清理。 - -## 最终测试证据 - -88 个不同定向用例全部通过(修复后重跑不重复计数):http2_client 6、http2_server 6、http_engine 12、http_library 7、live_network 16、pooled_network 14、pooled_library 6、async_runtime 10、structured_concurrency 11。 - -- 独立 h2 对端证明一条物理连接的并发请求、流式上传/下载、RST 前后隔离、背压写取消、WINDOW_UPDATE 恢复、流上限与活跃正文不会被 idle 回收、GOAWAY 的物理预算与连接替换、TLS ALPN 成功/拒绝、Host/target、413 与原始 handler 故障。 -- 原生 Dever 程序证明 single-use HTTP/2、TLS 同池嵌套代理(客户端只有一个物理名额)、上传、SSE 和 handler 内 run/await。共享 HTTP/1 变体另覆盖 WSS 与优雅停机;测试服务端三连接容量的修正经实际运行确认。 -- 最新响应发布取消/锁序改动已重新编译,并由 http2_server 6 项和 live_network 16 项覆盖;已有结构化任务、HTTP/1 连接池与源码语义检查通过。 -- 源码空白/冲突标记扫描、性能构建器 Python 语法和任务 context JSONL 验证通过。Rustfmt/Clippy 未安装;未运行性能矩阵、全量测试或既有服务验证。 - -复现上述范围: - -```bash -cargo test --offline --locked --release -p dever-tests --test http2_client --test http2_server --test http_engine --test http_library --test live_network --test pooled_network --test pooled_library --test async_runtime --test structured_concurrency -``` - -最终 CLI release 构建通过,产物为 `target/native-runtime/release/deverc`;backend 示例的实际 CLI check/fmt-check 均无输出并退出 0。迁移后的 network_bench example 及启用 reference 的 core/runtime 离线 release check 通过。未替换全局命令。 - -独立审查与主代理最终所有权、调用链、规范和改动范围核对闭环,无剩余生产阻断。清理专属 shm 构建目录,并删除暂存的约 378 MiB 可重建 debug 中间缓存;源码、现有编译器和全部性能报告保留。按用户约束手动更新状态/日志,不提交、不调用自动提交归档流程。N5 完成,HTTP/2 性能测量、RFC 8441、数据库与发行等仍在后续路线图。 diff --git a/.trellis/tasks/09-12-http2/prd.md b/.trellis/tasks/09-12-http2/prd.md deleted file mode 100644 index ef7df6d..0000000 --- a/.trellis/tasks/09-12-http2/prd.md +++ /dev/null @@ -1,16 +0,0 @@ -# N5 HTTP/2 - -用户已批准上一阶段提出的 HTTP/2 接入方案,并要求继续实现。复用 Hyper,面向小机器控制运行内存;不实现旧源码兼容层,不改运行时根任务调度策略。 - -## 范围与验收 - -- buffered/live 服务端和 single-use/pooled 客户端支持 HTTP/2;HTTPS 必须通过 ALPN 协商 h2,明文为 prior knowledge。 -- `Limits.http2: Http2Limits?` 显式选择协议;null 为 HTTP/1,非空为 HTTP/2。配置包含 streams、stream_window_bytes、connection_window_bytes,连接限额仍由 connections 持有。仓库调用者直接迁移。 -- 连接内复用请求,流式上传/下载与 SSE 复用现有正文接口;并发流、窗口、发送缓存有界,单流中止不取消相邻流。 -- Hyper 内部任务保留 Dever 的作用域归属;子任务、已启动 blocking、取消及故障完整排空,容量持有到清理完成。 -- 监听器关闭发送 GOAWAY 并排空在途流;客户端不向已 GOAWAY 连接派发新请求,不自动重试已发送请求。 -- 使用独立线协议对端和原生 Dever 程序验证多路复用、TLS ALPN、流控、取消隔离和生命周期,选取 HTTP/1 与 WS 回归。 - -## 排除 - -本阶段不接 RFC 8441 WebSocket-over-HTTP/2、h2c Upgrade、服务器推送、非空 trailers、自动协议降级,不跑全量测试或重新做性能矩阵,不替换全局二进制,不提交 Git。 diff --git a/.trellis/tasks/09-12-http2/task.json b/.trellis/tasks/09-12-http2/task.json deleted file mode 100644 index 9932924..0000000 --- a/.trellis/tasks/09-12-http2/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "http2", - "name": "http2", - "title": "HTTP/2 server and multiplexed client", - "description": "复用 Hyper 接入 HTTP/2 服务端、客户端多路复用、TLS ALPN、流控和结构化取消;验证流式正文与 SSE,保留 HTTP/1 和普通 WebSocket。", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-12", - "completedAt": "2026-09-12", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-04-dever-language-mvp", - "relatedFiles": [], - "notes": "N5 complete: 88 focused cases passed, native HTTP/2/TLS proxy/upload/SSE and HTTP/1/WSS verified; CLI build/check and independent review passed. No performance matrix, global install or commit.", - "meta": {} -} diff --git a/.trellis/tasks/09-12-runtime-performance-p2/check.jsonl b/.trellis/tasks/09-12-runtime-performance-p2/check.jsonl deleted file mode 100644 index 13a30a8..0000000 --- a/.trellis/tasks/09-12-runtime-performance-p2/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Benchmark verification contracts"} -{"file":".trellis/tasks/09-12-runtime-performance-p2/prd.md","reason":"Scope and acceptance"} -{"file":".trellis/tasks/09-12-runtime-performance-p2/design.md","reason":"Semantic comparison and lifecycle"} diff --git a/.trellis/tasks/09-12-runtime-performance-p2/design.md b/.trellis/tasks/09-12-runtime-performance-p2/design.md deleted file mode 100644 index 3d84786..0000000 --- a/.trellis/tasks/09-12-runtime-performance-p2/design.md +++ /dev/null @@ -1,11 +0,0 @@ -# Design - -现有 test/performance 负责产物和采样,Rust examples 负责压力对端。保留该分工,不增加第二套预算与报告框架。 - -异步对照使用独立 async_bench example:相同 run/wait、checked Int 加法、输入与批次;runtime-root 与 runtime-worker 仅改变批次所在任务。worker 模式增加一个结构化外层任务,不修改生产调度。对照程序输出 P1 SAMPLE 协议,Python 复用校验和与样本汇总。 - -长连接使用新增 Dever fixture 与 Rust 对端。Rust 对端有固定连接上限、阶段标记、消息校验和超时;Python 根据阶段采样同一个服务进程,复用 Process/Budget。每轮连接、保持、断开后等待采样,最后重连探测服务可用。TCP/WS 做小正文交互;SSE 校验有限事件,保留流直到断开。 - -高负载扫描复用现有 HTTP load,不重写压测器。使用独立 CPU 亲和性和 128 MiB 服务预算,合理短窗口与重复次数;保留客户端瓶颈和短窗口限制。 - -HTTP/2 只做本地依赖/池/协议边界核查:Hyper h2、TLS ALPN、流与连接预算、复用客户端、GOAWAY、取消隔离;HTTP/1 WebSocket 升级保持独立。 diff --git a/.trellis/tasks/09-12-runtime-performance-p2/implement.jsonl b/.trellis/tasks/09-12-runtime-performance-p2/implement.jsonl deleted file mode 100644 index 8f6caf9..0000000 --- a/.trellis/tasks/09-12-runtime-performance-p2/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/index.md","reason":"Rust language owning layers"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Bounded standalone benchmark contracts"} -{"file":".trellis/tasks/09-12-runtime-performance-p2/prd.md","reason":"Approved scope and acceptance"} -{"file":".trellis/tasks/09-12-runtime-performance-p2/design.md","reason":"Reuse and ownership"} diff --git a/.trellis/tasks/09-12-runtime-performance-p2/implement.md b/.trellis/tasks/09-12-runtime-performance-p2/implement.md deleted file mode 100644 index 159bfff..0000000 --- a/.trellis/tasks/09-12-runtime-performance-p2/implement.md +++ /dev/null @@ -1,21 +0,0 @@ -# Execution - -- [x] 主代理:async_bench、Python 集成、HTTP 扫描、采样、结果分析与 HTTP/2 就绪评估。 -- [x] trellis-implement:long connection Rust 对端及 Dever fixture,独立文件所有权,不修改生产代码。 -- [x] 定向 offline release 构建、生成原生 fixture、校验工具错误路径、执行有界矩阵。 -- [x] trellis-check:复查统计、语义、连接清理和最终结果;主代理复核关键证据。 -- [x] 更新现有性能 README、任务与日志,不提交。 - -磁盘空间有限;复用 target/native-runtime 的 release 依赖。原生构建 TMPDIR 使用任务独有 /dev/shm 临时目录,结束移除自有目录。不并行执行 Cargo 构建。 - -## 已取得证据 - -- HTTP/HTTPS 高负载完整 54 组,report: target/performance/http-load-p2-final/report.json。1800000 计划、1500830 实际成功、0 错误、299170 未发出;三实现均有压测槽位丢弃,不能推断服务端吞吐上限。无 OOM。 -- 首次 http-load-p2 在子进程退出采样竞态中断:/proc memory teardown 早于 waitpid 状态。已修复采样拥有层,补定向回归,保留中断报告。 -- run/wait Rust 对照用生产 task runtime、Bytes 和 checked Int;build 工具使用与 native 相同优化参数和 runtime rlib。async-p2 已完成 18 组:Dever root/worker 15.50/2.003 µs,Rust 15.59/1.984 µs,三轮校验均通过且无 OOM。独立 perf 确认 root/worker 线程切换为 465149/56 次;生产运行时未修改。 -- 独立 review 修正了 live 总超时遗漏关闭阶段预算、SSE 保持期无心跳仍通过的问题;静态发现并修正 SSE driver 早期错误所有权和任意截止点半帧误判。所有修改均在 benchmark 工具/fixture 内。 -- 首次 live-p2 消息校验通过,但发现阶段读/采样间跨轮竞态:下一轮 FD 混入上轮 disconnected。修复为采样前后 progress 必须一致,丢弃过渡阶段观察,并新增回归。最终 live-p2-final 完整重跑 27 组、18144 连接、377061 消息;错误/OOM 为零,81 次断开 FD 差值均为零。 -- live-cycles-p2 对三个协议各做 512 连接十轮重连、每轮 3 秒;15360 连接、471207 消息,错误/OOM 为零,30 次 FD 均回基线。SSE RSS 在前三轮升到约25 MiB,后七轮在25.24–25.36 MiB;TCP约8.8、WS约17 MiB。短时证据不宣称小时级稳定性。 -- 12 个 Python 运行器定向检查、4 个独立 TCP/SSE 对端检查通过;11 个 Dever 入口生产优化构建和两个新 Rust example 离线 release/原生优化构建通过。Dever fmt-check、Python解析、源码空白/冲突和范围检查通过;Rustfmt/Clippy 不可用,未运行。 -- /dev/shm/dever-perf-p2.E84QV8 已空并移除。保留原始构建/剖析/中断与最终报告以供复核;不提交,不运行自动归档或自动日志提交脚本。 -- 最终独立检查无剩余阻断;主代理复核四份最终报告、全部 OOM/FD 计数及无残留预算组。P2 完成,可进入 HTTP/2 阶段,未将实验调度变化当作已实现的生产优化。 diff --git a/.trellis/tasks/09-12-runtime-performance-p2/prd.md b/.trellis/tasks/09-12-runtime-performance-p2/prd.md deleted file mode 100644 index a858b0b..0000000 --- a/.trellis/tasks/09-12-runtime-performance-p2/prd.md +++ /dev/null @@ -1,12 +0,0 @@ -# Runtime performance P2 - -用户已批准继续上一阶段;本阶段完成同语义异步对照、高负载 HTTP/HTTPS 扫描和 TCP/WebSocket/SSE 有界长连接测试,并回答 HTTP/2 的接入条件。HTTP/2 实现留到下一阶段。 - -## 验收 - -- Rust 对照调用现有 Dever task runtime,保留 run/wait 的任务额度、结构化取消和清理;单独标注工作线程调度实验的边界。 -- 复用 P1 构建、进程采样、cgroup 和报告逻辑,记录校验和、样本、CPU、上下文切换、RSS/PSS 与环境;不以不同语义的裸 Tokio 数字宣称语言损耗。 -- HTTP/HTTPS 固定正文在更高输入速率下记录成功、错误、容量丢弃、调度落后及服务端/客户端 CPU;限速结果不宣称极限吞吐。 -- TCP、WebSocket、SSE 支持有限数量的长连接保持、正文验证和多轮断开重连;记录服务端连接前、保持中、断开后的内存和 FD。 -- 运行仅限自有 loopback 服务和独立预算组;所有任务、连接和进程有明确停止边界,结束无残留。执行最小定向测试,不运行全量测试、不修改全局安装、不提交。 -- 不添加兼容分支、无证据的运行时重构或新依赖;发现实际阻断后再定位归属。 diff --git a/.trellis/tasks/09-12-runtime-performance-p2/task.json b/.trellis/tasks/09-12-runtime-performance-p2/task.json deleted file mode 100644 index 90ff435..0000000 --- a/.trellis/tasks/09-12-runtime-performance-p2/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "runtime-performance-p2", - "name": "runtime-performance-p2", - "title": "Runtime performance and long connections", - "description": "Continue approved runtime benchmarks: equivalent async Rust comparison, bounded HTTP load scan and TCP/WebSocket/SSE connection recovery; assess HTTP/2 readiness without implementing it.", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-12", - "completedAt": "2026-09-12", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-04-dever-language-mvp", - "relatedFiles": [], - "notes": "", - "meta": {} -} diff --git a/.trellis/tasks/09-12-runtime-performance/check.jsonl b/.trellis/tasks/09-12-runtime-performance/check.jsonl deleted file mode 100644 index badd547..0000000 --- a/.trellis/tasks/09-12-runtime-performance/check.jsonl +++ /dev/null @@ -1 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Benchmark validation and evidence limits"} diff --git a/.trellis/tasks/09-12-runtime-performance/design.md b/.trellis/tasks/09-12-runtime-performance/design.md deleted file mode 100644 index ac4f5e6..0000000 --- a/.trellis/tasks/09-12-runtime-performance/design.md +++ /dev/null @@ -1,9 +0,0 @@ -# 测量边界 - -现有 performance.rs 拥有计算热路径基准,保持原有语义与 1.15 门槛。新增根 test/performance/ 的 Python 标准库驱动,分离构建、进程采样、场景执行和报告。Dever fixtures 经过现有 CLI build 成为独立二进制。Rust 辅助程序作为 dever-tests 的显式 example,复用 workspace 已锁定的 Tokio/Hyper/Rustls。 - -网络辅助程序同时提供等价 Rust runtime / 原生 Hyper 对照服务和独立负载端;不自行解析 HTTP。固定速率调度以计划发送时间计算延迟,并记录有界并发容量不足或调度逾期导致的丢弃。TLS 校验证书和主机名,复用已有测试 CA;新连接与连接复用分别测量。 - -进程通过 READY|port(空闲/计算用 READY|0)报告可采样状态。配置统一使用 BENCH_WORKERS、BENCH_CONNECTIONS、BENCH_TIMEOUT_MS、BENCH_LIFETIME_MS、BENCH_CERT、BENCH_KEY 等环境变量。负载 CLI 为 network_bench load URL PATH RATE SECONDS CONNECTIONS TIMEOUT_MS REUSE CA,JSON 标准输出。服务 CLI 为 network_bench runtime-http/runtime-https/hyper-http/hyper-https。各服务 /plain 返回 hello,/json 返回 {"ok":true},/bytes 返回 65536 个 x;带对应 Content-Type,不启用日志。 - -Linux /proc 采样独立于子程序;cgroup 为可选且显式启用的进程预算,使用新建的专属子组,不调整宿主或已有服务的 cgroup。负载发生器不进入服务预算。默认不声称隔离或峰值吞吐;报告采样间隔、负载端 CPU 和限额状态。汇总保留每轮原始数据,不建立未经校准的绝对性能门槛。 diff --git a/.trellis/tasks/09-12-runtime-performance/implement.jsonl b/.trellis/tasks/09-12-runtime-performance/implement.jsonl deleted file mode 100644 index eab87a2..0000000 --- a/.trellis/tasks/09-12-runtime-performance/implement.jsonl +++ /dev/null @@ -1,2 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused owned benchmarks and unchanged runtime semantics"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Native optimization and HTTP/TLS/task contracts"} diff --git a/.trellis/tasks/09-12-runtime-performance/implement.md b/.trellis/tasks/09-12-runtime-performance/implement.md deleted file mode 100644 index d5f2df1..0000000 --- a/.trellis/tasks/09-12-runtime-performance/implement.md +++ /dev/null @@ -1,18 +0,0 @@ -# 执行顺序 - -- [x] 主代理实现 Dever 场景和 Python 构建/采样/报告入口。 -- [x] 独立 implement 代理实现 test/dever-tests/examples/network_bench.rs 及其私有模块;复用现有网络依赖。 -- [x] 编译定向 fixtures/example,最小验证测量统计和清理,短时 loopback HTTP/HTTPS 对照。 -- [x] 检查最终文件、响应校验、延迟分母、丢弃/失败计数、资源预算和退出清理;记录初始结果与限制。 -- [x] 更新 test/performance/README.md、现有质量规范及任务证据;不提交。 - -工具链使用 /root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin 的命令级 PATH;所有 Cargo 构建 offline。只运行本任务的最小定向检查,不执行旧 performance target 或全量测试。 - -## 最终证据 - -- 七个 Python 运行器定向测试和两个独立 Python HTTP 对端测试通过;负例响应正文必须记 error、成功延迟为空。覆盖热身去除、正确结果/数量、完整窗口、计数守恒、已退出进程和缺控制器时清理。 -- Rust example 离线 release check/build 通过;七个 Dever 入口经 CLI 格式化、语义检查和生产优化原生构建。Rustfmt/Clippy 未安装,未报告为通过;显式源码空白/冲突标记检查与 Dever fmt-check 通过。 -- 最终基线 78 组:15 内存、9 异步、54 HTTP/HTTPS;另 18 组新连接和 15 组 64 MiB 空闲基线。各组实际调用环境见 target/performance/*/report.json,结果解释以 test/performance/README.md 首轮结果为准。 -- 54 组正式网络共计划 108000 请求,发出并成功 107962,错误 0;未发出 38(窗口过期 32、容量不足 6)。预热单独记录。新连接 900 请求全部成功,无丢弃;全部自有预算组无 OOM,结束后没有残留 dever-perf-* cgroup。 -- 对照复查修正了大正文逐请求重复分配、短窗口吞吐分母、定时器抖动错误计丢弃、请求 driver 取消所有权、负载线程环境污染、缺控制器清理以及实际请求延迟校验。独立只读 review 最终没有剩余阻断。 -- 仅构建/测试工具、fixtures、Cargo 测试依赖和文档发生变化;生产编译器/运行时未修改。保留产物和原始报告,不提交、不运行自动归档脚本。更高负载、长连接/持续稳定性和运行时优化是后续工作。 diff --git a/.trellis/tasks/09-12-runtime-performance/prd.md b/.trellis/tasks/09-12-runtime-performance/prd.md deleted file mode 100644 index 22880cb..0000000 --- a/.trellis/tasks/09-12-runtime-performance/prd.md +++ /dev/null @@ -1,14 +0,0 @@ -# 独立二进制运行性能基准 - -用户批准实施上一轮提出的第一阶段:常驻内存、异步调度、HTTP/HTTPS。小机器只运行已编译程序;构建资源不是本阶段优化目标。此批准取代历史网络开发阶段不运行压测的局部限制,仅限本任务拥有的有界基准。 - -验收: -- 根 test/ 内提供显式运行的构建与测量入口,默认测试不启动压测。 -- 测量真实 Dever 编译产物,复用现有优化设置;编译不进入运行计时。 -- 覆盖同步/异步/HTTP/HTTPS 空闲内存,任务启动/Channel/取消,以及 HTTP/HTTPS 固定速率请求。 -- HTTP 对照使用相同 Dever runtime 的 Rust 服务和原生 Tokio/Hyper 服务;校验响应内容,记录成功、失败、未发出请求和尾延迟。 -- 输出机器可读结果、环境/配置/二进制身份、CPU/RSS/PSS/线程/FD;可选独立 cgroup 限额,缺少权限时报错,不虚构限额。 -- 自有随机 loopback 端口、测试证书、有界时间和负载,退出清理子进程;不访问已有服务,不跑全量测试,不提交。 -- 完成短时定向验证和至少一组可解释的初始测量;长时间、多机器/多档压力矩阵明确留待显式运行。 - -不包含运行时优化、数据库、服务端流式请求、信号 API、TCP/WS/SSE 长连接稳定性和发行工具链。 diff --git a/.trellis/tasks/09-12-runtime-performance/task.json b/.trellis/tasks/09-12-runtime-performance/task.json deleted file mode 100644 index 3f96765..0000000 --- a/.trellis/tasks/09-12-runtime-performance/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "runtime-performance", - "name": "runtime-performance", - "title": "Runtime performance baselines", - "description": "Measure standalone Dever memory, async scheduling and HTTP/HTTPS with reproducible bounded workloads and equivalent Rust baselines.", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-12", - "completedAt": "2026-09-12", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-04-dever-language-mvp", - "relatedFiles": [], - "notes": "", - "meta": {} -} diff --git a/.trellis/tasks/09-13-typed-orm/check.jsonl b/.trellis/tasks/09-13-typed-orm/check.jsonl deleted file mode 100644 index 2b10ee7..0000000 --- a/.trellis/tasks/09-13-typed-orm/check.jsonl +++ /dev/null @@ -1,7 +0,0 @@ -{"file":".trellis/spec/backend/error-handling.md","reason":"数据库错误、事务失败、取消和资源回收必须显式传播"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"检查数据库测试边界、内存限制、无重复驱动逻辑和最小验证"} -{"file":".trellis/tasks/09-13-typed-orm/research/architecture-options.md","reason":"复核实现只暴露 Model 包短函数,没有混入实例 method、链式查询器或动态 Value 路径"} -{"file":".trellis/tasks/09-13-typed-orm/prd.md","reason":"逐项核对已确认的 Model、查询、配置、事务、错误、迁移和小内存验收合同"} -{"file":".trellis/tasks/09-13-typed-orm/design.md","reason":"复核编译器/runtime/dialect 边界、driver profile、单连接事务与错误根边界没有重复实现"} -{"file":".trellis/tasks/09-13-typed-orm/research/schema-change-matrix.md","reason":"确认所有自动 schema 变化均无静默数据损失,危险变化必须由命名 migrate 表达"} -{"file":".trellis/tasks/09-13-typed-orm/research/driver-selection.md","reason":"确认 SQLite/PostgreSQL 只复用驱动和连接池,不引入第二套 ORM 或无界池"} diff --git a/.trellis/tasks/09-13-typed-orm/design.md b/.trellis/tasks/09-13-typed-orm/design.md deleted file mode 100644 index c9155fb..0000000 --- a/.trellis/tasks/09-13-typed-orm/design.md +++ /dev/null @@ -1,409 +0,0 @@ -# 类型安全 ORM 技术设计 - -## 设计目标 - -实现一个静态、无反射、默认有界的 ORM,并让数据库能力自然接入 Dever 的顺序调用、结构化并发、错误传播和 AOT 产物裁剪。Model 只描述持久化事实和数据访问;数据库驱动不拥有语言层查询语义。 - -## 总体边界 - -```text -Dever source - -> parser / formatter - -> model + function semantic checking - -> effect / error / database binding inference - -> typed QueryPlan + normalized ModelSchema - -> native emitter - -> shared ORM runtime - -> SQLite dialect/executor - -> PostgreSQL dialect/executor - -> packaged binary + external config/setting.json -``` - -- 编译器拥有 Model 识别、字段类型、查询表达式、静态关系、错误集合和 transaction 合法性。 -- ORM runtime 拥有配置、连接生命周期、绑定值、行流、事务、schema 执行和统一错误分类。 -- dialect 只拥有 SQL/DDL 差异;driver executor 只拥有具体连接、参数编码和行解码入口。 -- 生成代码拥有每个 Model 的具体创建输入、更新输入、查询返回、字段绑定和行 decoder。 -- 不建立通用 Repository/BaseModel 层,也不让 SQLite/PostgreSQL 分别复制 CRUD 流程。 - -## 源码合同 - -### Model 文件 - -```dever -package app.model.user exposes ( - User -) - -type UserStatus { - Active = "启用" - Disabled = "禁用" -} - -type User { - uuid: Uuid generated unique - email: Text(254) unique - display_name: Text(1, 64) from nickname - status: UserStatus default UserStatus.Active index - organization_id: app.model.organization.id? -} - -index(status, created_at) - -seed { - { - email = "admin@example.com" - display_name = "Admin" - status = UserStatus.Active - } -} - -migrate remove_legacy_code { - drop legacy_code -} -``` - -`database `、`index`、`unique`、`relation`、`seed` 和 `migrate` 只在 Model 文件中合法。需要显式使用报告库时,在 package header 后增加 `database report`;未写时按根包/default 规则绑定。普通文件继续只有普通 type/function 语义。 - -### 查询与事务 - -```dever -users = user.list({ - where = status == UserStatus.Active and organization_id == organization_id - order = [created_at.desc, id.desc] - page = 1 - size = 20 - with = [organization] -}) - -transaction disable_organization( - target_organization_id: app.model.organization.id -) () { - user.update({ - where = organization_id == target_organization_id - }, { - status = UserStatus.Disabled - }) - organization.update(target_organization_id, { - active = false - }) -} -``` - -匿名创建/更新/查询块只在对应参数位置出现,由目标 Model 提供字段命名空间。它们不会成为可传递的动态 Map 或持久查询对象。 - -### 类型化原生 SQL - -复杂查询通过 Model 文件内的专用 `sql` 声明提供,不引入通用泛型或 type-as-value: - -```dever -type UserSummary { - status: UserStatus - total: Int -} - -sql active(status: UserStatus) (users: List) { - sqlite = "SELECT id, created_at, email, status FROM user WHERE status = ?1" - postgres = "SELECT id, created_at, email, status FROM user WHERE status = $1" -} - -sql summary(status: UserStatus) (summary: UserSummary?) { - sqlite = "SELECT status, COUNT(*) FROM user WHERE status = ?1 GROUP BY status" - postgres = "SELECT status, COUNT(*) FROM user WHERE status = $1 GROUP BY status" -} -``` - -- 两种方言都必须是静态 Text 字面量。SQLite 显式使用 `?N`,PostgreSQL 显式使用 `$N`;编译器不重写 SQL。 -- 参数按声明顺序和具体字段类型绑定;禁止插值、动态列名及动态行 `Map`。 -- 结果只能是一个具体 `Model`、`Model?`、`List`,或同文件私有辅助 record 的对应形状。 -- Model 文件仍只有文件名对应且 exposed 的 record 注册为 Model。辅助 record 必须被 SQL 结果使用,不生成表,也不能 exposed。 -- Model 结果复用生成的 Model decoder;辅助 record 生成具体字段顺序 decoder。缺列、多列、类型不匹配,以及单行结果的零行/多行都作为运行时数据库数据错误传播。 -- 调用形式与内置 CRUD 一致,例如 `user.active(status)`。执行复用既有 statement cache、值绑定和隐藏 transaction executor;`List` 只物化该静态 SQL 实际返回的行,不建立额外动态缓存。 - -## 编译器设计 - -### 1. 语法与格式化 - -- 根据源文件相对路径判定是否属于 `model/`;Model 文件仍解析一个普通 record type,不新增通用 type 种类。 -- 在 AST 中增加目的明确的 Model 元数据节点:数据库绑定、字段修饰、复合索引、关系、Seed 和命名迁移。不要把它们编码为字符串或普通函数调用后再反解析。 -- 函数声明使用 `FunctionKind::Ordinary | Transaction`,取代继续叠加多个布尔修饰位。 -- 删除源码 `async` 和 `await` 节点;`run`、`wait`、`stop` 保留为明确的并发上下文表达式。 -- `result(call)` 和 `fail(error_variant)` 作为两个目的单一的核心表达式进入 AST/HIR,不借此加入 try/catch、annotation 或 macro。 -- formatter、Markdown 合同解析和 API snapshot 与新语法同步更新;不保留旧语法分支。 - -### 2. Model 注册与静态元数据 - -- SourceMap 加载后先建立 `ModelId`,验证文件名、package 路径、唯一公开 record 和 Model 表名。 -- 为每个 Model 合成: - - 不透明 `.id`; - - 完整 record 中的 `id`/`created_at`; - - 创建和更新输入 shape; - - CRUD/query/relationship 符号; - - choice options 常量; - - 具体 row decoder 与 bind encoder 描述。 -- 同一逻辑连接中发生表名、索引名或内部对象名冲突时,在生成 SQL 前报告源码诊断。 -- Model CRUD 是编译器合成的包能力,不要求开发者在 `exposes` 中逐个列出,也不扩展成通用 type-as-value。 - -### 3. 规范化 Schema - -新增与方言无关的 `ModelSchema`: - -- 稳定 Model/package/table identity; -- 有序字段、逻辑类型、可空性、默认值、generated、旧字段来源; -- 主键、外键、choice CHECK、单列/复合索引; -- relation、Seed 和命名迁移规范化表示。 - -revision 只对逻辑 schema 和迁移意图计算,不包含 SQLite/PostgreSQL SQL 文本、连接串、文件绝对路径或源码格式。这样两个方言完成后记录相同逻辑身份。 - -### 4. QueryPlan - -所有短函数共用一个静态 IR: - -- operation:select/insert/update/delete/upsert/count/exists; -- projection 与具体结果 shape; -- condition tree、稳定 order、page/cursor、limit; -- relation load plan; -- 参数槽位及 Dever 类型; -- transaction requirement 与 Model binding。 - -查询块在 checker 中解析为 Model 字段 ID 和类型化运算,不把字段名字符串留到 runtime。native emitter 将固定 SQL shape 和参数提取代码写入生成程序。 - -类型化原生 SQL 作为同一 Model operation HIR 的专用分支:HIR 只保存已校验的 operation 索引和类型化参数,方言文本保留在 `ModelSchema`。native emitter 选择 runtime profile 对应文本,并复用普通 ORM 的 bind encoder、database executor 与 row decoder;不会把 SQL 或结果 shape 推迟到 runtime 解释。`Record`/`Record?` 最多拉取两行以判定基数错误;`List` 最多保留 `database.max_page_size` 行并额外探测一行,超限失败而不静默截断,因此漏写 SQL `LIMIT` 也不会形成无界进程内结果集。 - -#### Relation 结果与加载计划 - -- 编译器公开内置 `Related`,只有 `Unloaded` 和 `Loaded(value)` 两态。ORM 负责构造值;业务代码可以用 `Related.Unloaded()` 和 `Related.Loaded(value)` 分句穷尽匹配。 -- `Related` 使用间接 native 布局 `Loaded(Box)`。Model 类型环只有穿过 `Related` 才合法,基础 row decoder 始终把合成关系字段初始化为 `Unloaded`。 -- 持久化字段 `_id: target.id` 自动合成 `: Related`;可空外键合成 `Related`。显式 `relation children = target.parent_id` 合成 `children: Related>`。持久化 schema、bind encoder 和基础 decoder 不包含这些合成字段。 -- `with = [organization, children]` 在 checker 中解析为 `QueryPlan` 的静态 relation 索引,只允许一层裸 relation 名称;未知、重复和嵌套关系均拒绝。`with` 只允许 `first`、`list`、`cursor`,`stream` 明确拒绝。 -- to-one 使用受控 `LEFT JOIN` 或 `INNER JOIN`,支持同一父查询的多个关系;`list` 的 count 查询保持只访问父表,`cursor` 不生成 count。 -- to-many 在父结果确定后按父 ID 批量加载并归组,不逐父查询。子记录按 `id ASC` 稳定排序,每个父记录最多加载 `database.max_page_size` 条;父 ID 每 998 个一批,为 SQLite 的第 999 个参数保留 relation limit。空父列表不会生成 `IN ()`。 -- 关系查询数量由生成代码 shape 测试验证:每个 relation 只有一个按固定参数批次循环的 `query_owned` 调用点,不在生产热路径加入计数原子。 - -### 5. 挂起 Effect - -- intrinsic 和官方库函数标记基础挂起 effect;调用、静态 handler 和 collection handler 通过现有依赖图传递。 -- AST 不再存 `is_async`,HIR 在 effect 收敛后记录内部 `suspends`。native emitter 仅对可达挂起函数生成 Rust `async fn` 和内部 `.await`。 -- 普通调用根据目标 effect 降低为同步 call 或内部 await call;源码语义始终是顺序完成。 -- 同步入口的完整可达图没有挂起 effect 时沿用直接 `main`;否则生成唯一 Tokio runtime 入口。 - -### 6. Error Effect - -- `error` choice 变体仍是命名、带类型 payload 的领域失败;`fail(...)` 把对应变体加入当前函数错误集合。 -- 调用图为每个函数推导封闭错误集合。普通调用在 HIR 中自动传播失败,native 使用具体 Rust `Result`;源码不写 `?`。 -- 对存在多个正常状态的操作,把正常状态保留为非 error choice,例如 `ReadState.Read/End`,错误集合与成功类型分开。 -- `result(call)` 阻止当前调用自动传播,并生成编译器内部 `CapturedResult`。它不引入用户泛型;checker 只允许通过现有穷尽函数分句消费、继续返回或传递,且必须覆盖成功形状和全部 error 变体。 -- native 为当前可达程序生成一个具体的错误 enum,并为函数记录精确子集;API/docs/editor 显示每个函数的静态错误集合。没有动态错误对象、字符串类型分派或按变体名猜 HTTP 状态。 -- 现有 C012 改为检查 error effect 和 captured result 的消费,继续拒绝丢弃、覆盖、仅打印或仅记录。 - -### 7. Database Effect 与 Transaction - -- 每个 Model operation 在 HIR 标记 `DatabaseEffect(ModelId)`;普通 helper 通过调用图传递 Model 集合。 -- 每个 Model 保存声明式 `ConnectionSelector::Explicit(name) | PackageRoot(root)`。source check 可拒绝显然不同的显式绑定;native build 读取 setting 后做最终连接解析和 transaction 单连接验证。 -- Transaction 函数必须具有至少一个数据库 effect,且所有 effect 在构建配置中解析为同一连接;并发子调用中的数据库 effect 直接诊断。 -- HIR 为 transaction 调用链增加隐藏 `DatabaseContext` 参数。普通路径使用 registry slot,事务路径使用同一 connection 的 transaction handle;不查询线程局部或任务局部状态。 - -## 配置与构建能力 - -### 项目根与源码根 - -- 应用命令接收项目根;项目根内的 `module/` 是唯一 SourceMap 根,package 按文件相对 `module/` 的路径校验和派生。 -- `module/user/model/user.dever` 因而对应 `user.model.user`,根包数据库绑定解析为 `database.user`;不存在时才使用 `database.default`。 -- `config/`、`data/` 与输出二进制都在项目根下,但不参与 Dever 源码扫描。编译器内部只传递规范化后的项目根和源码根,不在 parser/checker 中重复猜目录。 -- 旧的单目录语言 fixture 由测试工具显式传入源码根;应用 CLI 不增加自动回退或第二套模糊目录探测。 - -### setting.json - -配置路径固定为 `/config/setting.json`。数据库对象直接按连接名组织: - -```json -{ - "app": {}, - "http": {}, - "database": { - "default": { - "type": "sqlite", - "path": "data/db/app.db", - "max_connections": 1, - "max_page_size": 100 - }, - "report": { - "type": "postgres", - "url": "postgres://user:password@db.example.com/report", - "tls": "system", - "min_connections": 0, - "max_connections": 4, - "max_page_size": 100, - "wait_timeout_ms": 5000, - "io_timeout_ms": 30000 - } - }, - "log": {} -} -``` - -- 使用严格的结构化 JSON 解析;未知数据库 type、缺失 default、无效数值或被引用连接不存在均失败。 -- PostgreSQL 的 `tls` 必须显式为 `system` 或 `disabled`;`system` 使用现有 rustls 系统根并校验证书与主机名,不提供从 TLS 静默回落明文的 `prefer` 模式。 -- PostgreSQL 的 `wait_timeout_ms` 限制池等待,`io_timeout_ms` 独立限制 SQL、事务和迁移 I/O;二者范围均为 1–300000 毫秒。 -- 相对数据库/日志/upload/cache/tmp 路径都相对可执行文件目录,不相对 cwd。 -- 启动时创建 `data/db`、`data/upload`、`data/log`、`data/cache`、`data/tmp`;不创建或修复 setting。 -- 连接 selector 按“显式名称 -> 根包同名键 -> default”解析一次,Model 保存连接 slot。 - -### RuntimeProfile - -发布构建读取 setting 中全部数据库 `type`,生成 `RuntimeProfile { sqlite, postgres, async, log }`: - -- 只读取能力类型,不把 URL、密码、路径或池参数嵌入二进制或缓存 key。 -- runtime 的 SQLite/PostgreSQL 依赖使用 optional Cargo features。 -- profile、runtime rlib/dependency 快照和生成源码共同进入 native cache identity。 -- 编译器 parse/check 不依赖 setting;生成可部署原生程序时需要 setting。程序启动会再次严格解析实际 setting。 -- 运行时配置可以在已打包驱动集合内修改。若改成未打包的数据库类型,启动明确失败并要求重新构建,不做动态下载或回退。 - -### CMS 纵向样例 - -```text -examples/dever/cms/ - config/setting.json - data/ - module/ - cms.dever - user/model/user.dever - user/service/register.dever - news/model/news.dever - news/service/publish.dever -``` - -- `user.model.user` 保存账户及初始化管理员,`news.model.news` 通过 `author_id: user.model.user.id` 建立静态外键。 -- `user.service.register` 与 `news.service.publish` 使用 transaction 函数表达真实业务边界,直接复用编译器生成的 Model 操作。 -- `cms.main` 只编排可观察的纵向流程,不复制 CRUD、迁移或连接选择逻辑。 -- 默认 setting 只启用 bundled SQLite,既是新项目模板也是 SQLite-only 原生产物和小内存基准的真实用例。 - -## Runtime 设计 - -### 连接注册表 - -`DatabaseRegistry` 在应用入口启动 HTTP/任务前完成: - -1. 定位并解析 setting; -2. 创建数据目录; -3. 构造所有被 Model 引用的连接池; -4. 解析 Model -> connection slot; -5. 验证 transaction 单连接不变量; -6. 获取每个连接的 schema 锁,执行 migration 和 Seed; -7. 成功后才进入用户入口。 - -热路径通过整数 slot 取连接,不执行字符串查找。连接实现使用小枚举静态分派,不使用每行/每值 trait object。 - -### SQLite - -- 使用 `deadpool-sqlite` + `rusqlite bundled`。 -- pool 上限不超过 Dever 全局 blocking 容量;每次同步交互都通过既有 blocking permit 和 pool object 生命周期。 -- 默认一个连接,开启 foreign keys,设置 busy timeout;WAL 是否启用由连接配置明确决定,不在 runtime 猜测。 -- transaction 独占同一个 pool object 直到 commit/rollback;RowStream 不能在释放连接后继续读取。 - -### PostgreSQL - -- 使用 `deadpool-postgres` + `tokio-postgres`;TLS 连接通过 `tokio-postgres-rustls` 复用当前 rustls/webpki roots。 -- pool 获取、连接建立、查询和 row stream 都使用 Tokio,且有独立的连接上限、获取等待和 I/O 超时。 -- driver future 归属连接/pool 的结构化 scope;关闭 registry 时停止接收、等待借出连接归还并排空 driver task。 -- 对固定 QueryPlan 使用 statement cache;迁移 DDL 与一次性动态片段不进入无界缓存。 - -### 统一错误 - -driver 错误在所属 executor 边界映射为稳定 `DatabaseError`: - -- Connection、Timeout、Cancelled; -- Constraint(含 unique/foreign-key/check/not-null 分类); -- NotFound; -- Decode/Encode; -- Migration/SchemaConflict; -- Busy/PoolExhausted; -- Driver(保留可记录的内部 code/cause,但不直接暴露到 HTTP)。 - -非幂等写入不自动重试。原始 driver cause 进入诊断链,公开 error 只暴露稳定字段。 - -## Schema 与 Seed 执行 - -### 内部状态 - -每个数据库使用一个保留前缀的内部 history 表记录: - -- Model identity; -- kind:schema/migration/seed; -- logical name/revision; -- normalized checksum; -- applied_at。 - -history 不是目标 schema 的替代品。每次启动仍核对数据库 catalog;history 与实际 schema 冲突时拒绝继续,不猜测修复。 - -### 启动流程 - -- PostgreSQL 使用数据库级 advisory lock;SQLite 使用写事务锁,防止多个进程同时迁移同一 schema。 -- 表不存在:直接创建当前最终表、索引与约束,不回放 `from` 或历史 migrate。 -- 表存在:catalog -> normalized actual schema -> diff -> validation plan -> DDL plan。 -- 收紧变化先运行只读验证 SQL,任一失败都不执行 DDL。 -- 命名 migrate 校验未执行/内容未改,再与 DDL/history 在一个连接事务中提交。 -- Seed 在 schema 成功后执行,按唯一键 conflict-do-nothing;只忽略目标唯一冲突。 -- 多连接无法拥有全局原子迁移。各连接独立加锁和提交,按连接名稳定顺序执行;后续连接失败时应用不启动,已完成连接依靠 checksum 幂等重跑。 - -## 查询执行数据流 - -```text -generated Model function - -> evaluate typed arguments - -> acquire connection or reuse hidden transaction - -> dialect renders fixed QueryPlan - -> prepare/cache statement - -> bind concrete values - -> execute / pull rows - -> generated row decoder - -> Model/List/Page/Cursor result - -> release connection or retain for bounded RowStream -``` - -- to-one include 与主查询共享受控 join 计划。 -- to-many include 在获得父页后用一个有界 `IN (...)` 批次查询并按父 ID 归组;超过参数上限时按固定上限分批,不按父记录逐条查询。 -- list 的 count 与 data 查询按同一条件树生成;cursor 只执行 data 查询。 -- stream 持有连接和 statement 生命周期,消费者停止、Task 取消或 fault 时通过 Drop/scope 清理归还。 - -## Transaction 执行 - -- 最外层 transaction 从已验证 slot 获取一个连接并 begin。 -- 生成的 `DatabaseContext` 携带 `ConnectionSlot + TransactionHandle`,只沿隐藏参数传递。 -- 普通 Model call 检测到上下文时验证 slot 相同并直接使用 handle;无上下文时从 pool 获取。 -- 同连接嵌套 transaction 只增加逻辑作用域,不 begin/commit。 -- 函数成功时最外层 commit;error/fault/取消路径统一进入 rollback guard,rollback 完成后再传播原始失败。 -- rollback 自身失败追加到诊断 cause,不覆盖原始业务 error/fault。 -- transaction context 不能进入 `run`、Group、Channel、Stream producer 或返回值,因此不存在逃逸连接。 - -## 日志与执行边界 - -- runtime 维护一个结构化 `DiagnosticContext`,包含 fault/error code、source span、request/task id 和 cause chain。 -- lower layer 只附加 cause/context,不记录根日志;HTTP、ownerless Task、CLI 等根边界决定是否记录。 -- HTTP 未映射失败在 rollback 后返回通用 500;显式 handler 可把预期 error 映射为 4xx。 -- 日志 front-end 先检查 level,再构造字段。队列容量固定;debug/info 满时丢弃并累计,warn/error 等待容量。 -- 文件 sink 的编码、轮转和压缩策略不在本任务冻结;先完成有界队列、stderr emergency path 和一次记录合同。 - -## 性能设计 - -- 生成代码只保留可达 Model、字段 decoder、QueryPlan 和 driver profile。 -- 相同静态 SQL shape 使用每连接 statement cache;值变化不创建新 SQL 字符串或缓存项。PostgreSQL 每连接缓存暂定上限为 64;to-many 参数批次生成的动态 SQL 不进入缓存,最终上限由阶段 10 基准收敛。 -- page size、to-many 子项、IN 批次、批量写入、pool、blocking、RowStream、日志全部由一个明确上限约束。 -- SQLite 默认一连接,PostgreSQL 默认零预热小池;最终默认值由 64/128 MiB 定向基准确定,并固化为命名常量和文档。 -- 性能基准实测 RSS/PSS/VmHWM、cgroup、线程/FD、吞吐、p50/p95/p99 和二进制体积;配置的 pool capacity 单独记录。生产 runtime 尚无低成本观测点的 pool wait、SQL 数量和数据库连接数必须标记为 `unavailable`,不能用 FD 或配置值推算冒充实测。 -- 构建产物以 manifest 的 SHA-256 和字节数校验后才运行;每个 ORM case 使用独立 bundle。PostgreSQL URL 的唯一 `{case}` 必须位于数据库名,敏感 URL 只进入权限为 `0600` 的 case setting,不进入 manifest/report。 -- transaction cancel 使用单连接 pool:先证明连接可用,再证明长事务占用 pool、客户端在响应前断开、连接在 handler timeout 前归还且事务行数为零,避免把 handler timeout 回滚误报为请求取消。 -- 先验证稳定内存和正确回收,再优化 SQL 生成、statement 命中或 decoder;不以缓存未绑定 SQL 或扩大队列换吞吐。 - -## 风险与处理 - -- 隐式挂起和错误传播会触及编译器、官方库和全部异步 fixture,应先单独完成语义迁移并保持 Rust runtime 行为,再叠加 ORM。 -- SQLite DDL 经常需要重建表;schema planner 必须以真实 catalog fixture 验证,不能只比较生成 SQL 字符串。 -- 外部 setting 与驱动裁剪可能不一致;构建记录 capability,启动严格校验,错误要求重建,不加载动态插件。 -- 多数据库迁移无法跨连接原子提交;稳定顺序、单连接事务和 checksum 幂等是唯一可维护恢复路径。 -- PostgreSQL 测试依赖真实服务;实施阶段只运行隔离的定向 fixture,不连接开发或生产数据库。 - -## 回滚边界 - -- 每一实施阶段必须在独立语义门槛下完成;不在半迁移状态同时保留新旧源码语法。 -- 自动 schema 操作在提交前不改 history;失败回滚。跨连接已有成功迁移不反向回滚,由幂等重启继续。 -- 发布二进制始终保留上一个版本;危险命名 migrate 需要先有数据库备份,自动回滚程序版本不能逆转已提交的数据迁移。 diff --git a/.trellis/tasks/09-13-typed-orm/implement.jsonl b/.trellis/tasks/09-13-typed-orm/implement.jsonl deleted file mode 100644 index bf60dd1..0000000 --- a/.trellis/tasks/09-13-typed-orm/implement.jsonl +++ /dev/null @@ -1,10 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"model、查询计划、资源和公开 API 必须在 checker/HIR/native 中保持静态合同"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"数据库公共包、驱动选择、runtime 构建与缓存必须复用现有工具链边界"} -{"file":".trellis/tasks/09-13-typed-orm/research/architecture-options.md","reason":"依据现有无反射 AOT 和资源语义选择 ORM 表面"} -{"file":".trellis/spec/backend/error-handling.md","reason":"实现默认错误传播、事务回滚、根边界处理和 C012 合同"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"检查数据库测试边界、内存限制、无重复驱动逻辑和最小验证"} -{"file":".trellis/tasks/09-13-typed-orm/research/implicit-suspension.md","reason":"统一删除 Dever async/await,并保留编译器推导协程、run/wait/stop 和同步入口裁剪合同"} -{"file":".trellis/tasks/09-13-typed-orm/research/field-types.md","reason":"实现隐式字段、常用数据库类型、Uuid、choice、关联 ID、Seed 和索引语义"} -{"file":".trellis/tasks/09-13-typed-orm/research/schema-change-matrix.md","reason":"按变更类别实现自动 diff、数据验证、from、命名 migrate 和两种方言的等价结果"} -{"file":".trellis/tasks/09-13-typed-orm/research/query-api.md","reason":"实现已确认的 Model 短函数、块式查询、分页、关联、事务和连接解析表面"} -{"file":".trellis/tasks/09-13-typed-orm/research/driver-selection.md","reason":"接入 rusqlite/deadpool-sqlite 与 tokio-postgres/deadpool-postgres,并按 runtime profile 裁剪驱动"} diff --git a/.trellis/tasks/09-13-typed-orm/implement.md b/.trellis/tasks/09-13-typed-orm/implement.md deleted file mode 100644 index a4950d9..0000000 --- a/.trellis/tasks/09-13-typed-orm/implement.md +++ /dev/null @@ -1,297 +0,0 @@ -# 类型安全 ORM 实施清单 - -## 开始前门槛 - -- [x] 用户在最终规划摘要之后明确批准进入实现,并要求增加 `examples/dever/cms` 项目。 -- [x] 运行 `python3 ./.trellis/scripts/task.py start 09-13-typed-orm`,加载 `trellis-before-dev` 上下文。 -- [x] 核对 `Cargo.lock` 中待加入驱动与当前 Rust 1.85/MSRV、license 和 feature;只锁定实际使用的最小 feature。 -- [x] 为每个阶段建立对应的根目录 `test/` 定向测试目标;不运行 workspace 全量测试或集成压测。 - -## 阶段 1:隐式挂起语言表面 - -目标:删除 Dever 源码 `async`/`await`,保留 Rust runtime 的真实异步执行。 - -- [x] 调整 lexer/parser/syntax/formatter,删除 function/handler async 与 `await(...)`,保留 `run`/`wait`/`stop`。 -- [x] 将 `FunctionClause.is_async` 拆为编译器推导的 HIR `suspends`,复用现有调用依赖图传递基础挂起 effect。 -- [x] 更新 checker:普通调用自动按目标 effect 顺序等待;`run` 接受可启动调用,Task/Group 仍保持结构化所有权。 -- [x] 更新 native emitter:同步可达图生成直接入口,挂起可达图生成唯一 Tokio 入口和内部 await。 -- [x] 更新 API snapshot、Markdown 合同、官方 `dever.task/net/http/websocket/sse` 源码、examples 与相关 fixture,不保留旧语法。 -- [x] 清理旧 `AwaitCall`、`TaskStart`、公开 async 专属诊断和死分支,保留 runtime Rust async 节点。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test -p dever-tests --test structured_concurrency -cargo test -p dever-tests --test async_native -cargo test -p dever-tests --test async_network -cargo test -p dever-tests --test http_library -cargo test -p dever-tests --test live_library -``` - -完成条件:HTTP/TCP/WS/SSE 的 Dever fixture 不含源码 async/await,协议、背压、取消和同步程序无 Tokio 入口的定向测试通过。 - -## 阶段 2:默认错误传播与执行边界 - -目标:建立 `fail`、`result(call)`、推导错误集合和运行时统一兜底。 - -- [x] 在 AST/HIR 增加 `Fail`、`CaptureResult` 和静态 `FailureSet`,通过现有 dependency worklist 传递。 -- [x] 将普通调用降低为自动传播,`result(call)` 降低为编译器内部 captured result;不增加用户泛型或每函数 error 声明。 -- [x] 拆分官方库中“正常状态 choice”与 error effect,迁移现有 Result choice 的调用方。 -- [x] 扩展 C012,覆盖默认传播、captured result 穷尽消费、覆盖、丢弃、仅日志和 `recover`。 -- [x] 生成可达应用的具体 Rust error enum、cause chain 和 source span;API snapshot 显示每函数精确错误集合。 -- [x] 建立 HTTP、Task、CLI 根边界:事务回滚后分别返回 500/Task failure/非零退出,且只记录一次。 -- [x] 增加 `dever.log` level API、共享诊断上下文和有界队列;文件 sink 格式/轮转仍不在本阶段冻结。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test -p dever-tests --test contract_syntax -cargo test -p dever-tests --test contract_semantics -cargo test -p dever-tests --test contract_execution -cargo test -p dever-tests --test hello_native -cargo test -p dever-tests --test http_engine -``` - -完成条件:默认传播、主动捕获、自定义 fail、C012、HTTP/Task/CLI 边界及一次日志都有正反 fixture。 - -## 阶段 3:Model 语法与静态 Schema - -目标:编译器能从一个 Model 文件得到完整静态持久化合同。 - -- [x] 增加 Model 路径识别和 Model 专属 declaration/field metadata AST。 -- [x] 实现文件名/package/唯一公开 record 校验,合成 `id`、`created_at`、创建输入和更新输入。 -- [x] 实现 `Bool/Int/Float/Decimal/Text/Bytes/Uuid/DateTime/Date/Time/Duration/Json/choice/model.id` 及 nullable/static bounds。 -- [x] 实现 `generated/default/index/unique/from`、复合 index/unique、relation、seed、migrate 的解析、格式化和源码诊断。 -- [x] 实现不透明 Model ID 的解析与类型检查、隐式 FK/index、choice labels 与 `Choice.options`。 -- [x] 建立与方言无关的 `ModelSchema` 规范化和稳定 checksum;检查同连接内表/对象名冲突。 -- [x] API/Markdown 输出 Model、隐式字段、choice options 和持久化元数据,但不暴露内部输入类型噪音。 - -建议新增测试目标:`model_syntax`、`model_semantics`、`model_schema`。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test -p dever-tests --test model_syntax -cargo test -p dever-tests --test model_semantics -cargo test -p dever-tests --test model_schema -``` - -完成条件:字段/索引/关联/Seed/migrate 的合法和非法边界在 native build 前有稳定诊断,schema checksum 不受格式或方言影响。 - -## 阶段 4:配置、目录与 RuntimeProfile - -目标:严格加载外部 setting,并按实际能力构建最小 runtime。 - -- [x] 增加严格 `setting.json` 结构化解析和可执行文件目录定位。 -- [x] CLI 应用命令以项目根为输入,统一把 `/module` 交给 SourceMap;fixture 的显式源码根入口保持内部测试用途,不做应用级自动回退。 -- [x] 创建固定 `data/db|upload|log|cache|tmp` 目录;setting 缺失/无效直接失败。 -- [x] 实现显式连接、根包连接、default 的一次性解析和生成 Model 句柄缓存。 -- [x] 将 SQLite/PostgreSQL/config 依赖拆为 runtime optional features。 -- [x] native build 从 setting 提取驱动 capability,构建对应 runtime rlib;capability 进入 cache identity,敏感配置不进入生成源码或 identity。 -- [x] 启动时复核实际 setting 的驱动集合和 transaction binding;未打包驱动明确失败。 -- [x] 增加 base/sqlite/postgres/both 四种产物的依赖和二进制体积报告。 - -建议新增测试目标:`application_config`、`native_profiles`。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test -p dever-tests --test application_config -cargo test -p dever-tests --test native_cache -cargo test -p dever-tests --test native_profiles -``` - -完成条件:cwd 改变不影响定位,缺失配置无回退;SQLite-only/PostgreSQL-only 产物不含另一驱动。 - -## 阶段 5:共享 QueryPlan 与 SQLite 纵向闭环 - -目标:先用一个真实数据库打通静态 CRUD 和有界查询。 - -- [x] 实现 Model 短函数符号与匿名 create/update/query 块的上下文类型检查。 -- [x] 建立共享 QueryPlan、条件树、参数槽、稳定排序、page/cursor/stream 和结果 shape。 -- [x] 接入 `deadpool-sqlite` + `rusqlite bundled` 和有界 pool。 -- [x] 实现当前 CRUD 所需 SQLite dialect:标识符、占位符、类型/值编码、RETURNING、CHECK/FK/index。 -- [x] 生成 Model 专属 bind/row decoder;所有值参数化,不使用反射或动态 Map。 -- [x] 实现 create/get/first/list/cursor/count/exists/stream/update/delete/upsert 与有界 create_many。 -- [x] 验证 stream/取消/超时/pool exhaustion 后连接归还。 - -建议新增测试目标:`orm_query`、`sqlite_orm`。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test -p dever-tests --test orm_query -cargo test -p dever-tests --test sqlite_orm -``` - -完成条件:临时 SQLite 数据库完成 CRUD、分页、游标、stream、约束错误和清理;目标机器路径不需要系统 SQLite。 - -## 阶段 6:Schema Diff、迁移与 Seed - -目标:SQLite 先完成空库、升级、危险变化拒绝和幂等初始化。 - -- [x] 建立 catalog 列 introspection 与 history 中的规范化 actual schema。 -- [x] 实现内部 history 表、schema/seed checksum 和并发启动锁。 -- [x] 实现空库最终 schema 创建,不回放 `from`/历史 migrate。 -- [x] 实现安全字段 diff、约束数据库验证和 SQLite 表重建。 -- [x] 实现字段 `from`、稳定命名 migrate、内容不可改和事务性 history。 -- [x] 实现 Seed 唯一身份检查、缺失插入、非唯一冲突失败和 checksum 快速跳过。 -- [x] 对每一种自动/拒绝/显式变化保留真实 catalog 和数据断言,不只断言 SQL 字符串。 - -建议新增测试目标:`orm_migration`、`orm_seed`。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test -p dever-tests --test orm_migration -cargo test -p dever-tests --test orm_seed -``` - -完成条件:新库、旧库 rename、长度放宽/收紧、唯一/FK、重建失败回滚、重复启动和 Seed 追加全部通过。 - -## 阶段 7:PostgreSQL 复用接入 - -目标:只增加方言和 executor,不复制 Model/QueryPlan/schema 语义。 - -- [x] 接入 `deadpool-postgres` + `tokio-postgres`;使用 `tokio-postgres-rustls` 支持系统根 TLS 校验和显式禁用。 -- [x] 实现当前 CRUD 所需 PostgreSQL dialect、值编码/解码、RETURNING、catalog introspection 和 advisory migration lock。 -- [x] 对固定 QueryPlan 使用 statement cache;缓存 key 只来自编译器生成的静态 SQL shape。 -- [x] 复用 SQLite 同一 CRUD/schema/Seed fixture 数据集和断言,仅替换隔离数据库适配。 -- [x] 验证 pool wait、连接断开、取消、timeout、constraint code 映射、TLS 主机名/证书拒绝和 shutdown drain。 - -建议新增测试目标:`postgres_orm`,默认标记为 ignored;仅在仓库根 `config/setting.json` 的 `database.postgres_test` 明确配置隔离测试 PostgreSQL 时手动运行,不接触现有服务。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test --offline -p dever-tests --features postgres --test postgres_orm -- --ignored --exact postgres_orm_uses_the_configured_isolated_database -``` - -完成条件:PostgreSQL 与 SQLite 对共享 fixture 返回相同逻辑结果和 schema revision,差异仅存在于 dialect/executor。 - -## 阶段 8:Transaction 与多数据库 - -目标:实现无显式句柄、单连接静态约束的 transaction 函数。 - -- [x] 实现 `FunctionKind::Transaction` 检查和 `DatabaseEffect(ModelId)` 传播。 -- [x] build/runtime 分别解析 transaction Model 集合到唯一 connection。 -- [x] native 生成隐藏数据库上下文参数和最外层 begin/commit/rollback guard。 -- [x] 同连接嵌套 transaction 复用 handle;不创建 savepoint。 -- [x] 拒绝无数据库 effect、跨连接、动态切库、transaction context 逃逸和并发数据库子任务。 -- [x] 验证 error/fault 时先 rollback,再传播原始失败;rollback failure 只追加 cause。 -- [x] 验证 default、根包、显式 report 三种连接绑定和多连接启动顺序/幂等恢复。 - -建议新增测试目标:`orm_transaction`、`orm_connections`。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test -p dever-tests --test orm_transaction -cargo test -p dever-tests --test orm_connections -cargo test --offline -p dever-tests --features postgres --test postgres_orm -- --ignored --exact postgres_orm_uses_the_configured_isolated_database -``` - -完成条件:两种数据库都验证提交、回滚、嵌套复用、取消和连接归还,跨数据库在执行前被拒绝。 - -## 阶段 9:Relation 与原生 SQL 逃生口 - -目标:完成后端常用关联读取和复杂查询能力。 - -- [x] 实现 to-one relation 推导、显式反向 to-many relation 和 `with` 计划。 -- [x] to-one 使用受控 JOIN;to-many 按父页批量加载、稳定排序、数量和参数批次上限。 -- [x] 加入生成代码 query-shape 探针,断言父记录数增长不会产生 N+1。 -- [x] 实现参数化 typed native SQL,显式 SQLite/PostgreSQL 方言和具体 Model/record decoder。 -- [x] 拒绝 SQL 插值、动态列 Map、结果列缺失和类型不匹配。 -- [x] 建立 `examples/dever/cms/module/{user,news}/{model,service}`,用用户注册、新闻发布和 author 外键覆盖 Model/Service/transaction 纵向流程。 - -建议新增测试目标:`orm_relations`、`orm_native_sql`。 - -定向验证: - -```bash -cargo fmt --all -- --check -cargo test -p dever-tests --test orm_relations -cargo test -p dever-tests --test orm_native_sql -``` - -完成条件:两种数据库返回相同关系结果,to-many SQL 数量有固定上界,原生 SQL 保持参数化和静态解码。 - -## 阶段 10:小内存与压力验证 - -目标:在正确性完成后冻结小机器默认值并找出真实瓶颈。 - -- [x] 扩展 `test/performance` 构建器,产出 sync/base、SQLite-only、PostgreSQL-only 和 HTTP+JSON+DB fixture。 -- [x] 构建和测量分离;运行阶段只启动已打包二进制。 -- [x] 添加 SQLite/PG idle、CRUD、list/cursor/stream、pool saturation、transaction cancel 场景;PG 仅在根 `config/setting.json` 显式配置 `database.postgres_test` 时运行。 -- [x] 报告 binary size、RSS/PSS/VmHWM、cgroup current/peak/OOM、线程/FD、配置 pool capacity、吞吐和 p50/p95/p99;当前无法直接观测的连接数、pool wait、SQL 数明确标记 unavailable。 -- [x] 先跑 1 核/128 MiB,再跑 64 MiB;不设置假 QPS 门槛,以无 OOM、无错误、内存有界、连接回收和相对对照为硬条件。 -- [x] 根据报告收敛 SQLite pool、PG min/max、page size、row buffer、IN batch 和 statement cache 上限;两档最大 RSS 高水位均约 7 MiB、OOM 为 0,现有有界默认值有充分余量,因此不做无数据依据的调参。 -- [x] 最后做 cleanup:删除临时 fixture、重复驱动分支、旧 async/await 代码和未使用 feature。 -- [x] 以 `examples/dever/cms` 验证项目级 check/run/build 和 SQLite-only 打包产物。 -- [x] 以 `examples/dever/cms` 验证真实业务内存基线。 - -最小基准检查: - -```bash -python3 -m unittest discover -s test/performance -p 'test_runner.py' -v -python3 test/performance/run.py run \ - --artifacts target/performance/orm-current \ - --output target/performance/orm-128m \ - --suite orm --duration 10 --warmup 2 --repeats 3 \ - --cgroup-parent /sys/fs/cgroup/system.slice \ - --memory-mib 128 --cpu-quota 1 -``` - -该运行会启动隔离的本地测试进程并使用 cgroup;执行前必须说明,确认不会影响现有服务。PostgreSQL 场景只使用专门测试实例。 - -## 最终自检 - -- [x] `rg` 确认 Dever 官方库、examples、fixture 不再出现源码 `async`/`await`。 -- [x] `rg` 确认没有旧 ORM、链式 Query、显式 Database/Transaction 或双 CRUD 表面。 -- [x] 检查生成 SQL 的所有值都通过 bind 参数,只有编译器生成的标识符进入 SQL。 -- [x] 检查 SQLite/PostgreSQL 共享 QueryPlan/schema/error 流程,没有复制业务算法。 -- [x] 检查所有队列、池、page、batch、stream、日志和 blocking 路径有明确上限。 -- [x] 检查最终改动没有调试输出、TODO、临时测试、无用依赖或未使用兼容分支。 -- [x] 只报告实际运行的定向验证;未运行 PostgreSQL、压测或受权限限制的 cgroup 检查必须明确标注。 - -## 高风险文件与回滚点 - -- 编译器语法/HIR:`crates/dever-core/src/{lexer,parser,syntax,hir,format}.rs`。 -- 效果与错误:`crates/dever-core/src/contracts/*`、`check/*`、`native/*`、`api.rs`。 -- native profile/cache:`crates/dever-core/src/native/build.rs`、`native/build/cache.rs`、workspace/runtime Cargo 配置。 -- Runtime:新增 config/database/orm/dialect 模块与 `crates/dever-runtime/src/task.rs` 的 bounded blocking 接口。 -- 官方库和示例:`library/dever/*`、`examples/dever/*`。 -- 所有长期测试只能放在仓库根 `test/`。 - -阶段 1、2 属于语言合同迁移,完成后不回退旧语法;阶段 3-9 每阶段保持编译器与 runtime 同步可用。schema 变更只靠数据库事务/history 回滚,已成功提交的命名迁移不由程序版本回退。 - -## 2026-09-17 收口验证 - -- `cargo check --offline -p dever-runtime --features postgres` 通过。 -- `application_config` 3/3 通过;PostgreSQL 配置默认值和超时范围已覆盖。 -- 原 `postgres_orm` 无环境变量时提前返回却显示 1/1 通过,该证据无效。测试现已改为默认 ignored,并只从根 `config/setting.json` 读取 `database.postgres_test`;真实 PostgreSQL 验收仍未运行。 -- PostgreSQL 配置入口回归:performance runner 27/27 定向单测通过,`cargo check --offline -p dever-tests --features postgres --test postgres_orm` 通过;未连接数据库。 -- handler effect 替换回归通过;全部维护中示例按 `/module` 统一源码根通过静态检查。 -- `cms_project` 已完成 1/1 check/run/build/打包程序验证;最终复验因根文件系统空间不足在链接测试二进制前中止,不是测试逻辑失败。 -- rustfmt、clippy 组件未安装;全量测试、真实 PostgreSQL、二进制体积、64/128 MiB 和 cgroup 压测未运行。 - -## 2026-09-17 最终验收 - -- 共享 fixture 已落在 `test/dever-tests/tests/support/orm_fixture.rs`;SQLite 与 PostgreSQL 使用同一 schema/Seed、CRUD、create_many、upsert、list/cursor/stream、transaction 和 catalog 断言。SQLite 1/1、隔离 PostgreSQL 1/1 最终复验通过。 -- PostgreSQL 真实验收修复并覆盖三处仅靠编译无法发现的问题:cursor 可空参数显式 SQL 类型 cast、UUID 原生二进制参数直接使用 `::uuid`、shutdown SQLSTATE 映射为 connection error。pool wait、断连、timeout、constraint、TLS 拒绝和 drain 均通过。 -- PostgreSQL 测试与性能工具只从仓库根 `config/setting.json` 读取 `database.postgres_test`;没有数据库 URL/TLS 环境变量或命令行覆盖入口。测试实例为独立临时 PostgreSQL,未接触现有 5432/5433 服务。 -- 四 profile 使用同一最小源码:base 413,880 B、sqlite 2,562,808 B、postgres 2,711,632 B、both 4,676,472 B。依赖报告确认单驱动产物不包含另一驱动,证据见 `target/performance/typed-orm-build-v2/profile-report.json`。 -- 1 CPU、无 swap、128 MiB 与 64 MiB 各完成 48/48 ORM case(SQLite/PostgreSQL × 8 场景 × 3 重复),两档 OOM/OOM kill 均为 0,最大 RSS 高水位分别 7,184,384 B 与 7,102,464 B;所有 cancel case 均确认池饱和、零提交和超时前连接回收。报告见 `target/performance/typed-orm-128m-v2/report.json` 与 `target/performance/typed-orm-64m/report.json`。 -- 现有 SQLite pool=1、PostgreSQL min/max=0/4、page size=100 以及有界 row/IN/statement 路径均有充分内存余量;本轮数据不支持进一步缩减,保持默认值。 -- CMS 128 MiB 与 64 MiB 各 3/3 完成,业务基线每次为 2 条记录,OOM 为 0,RSS 高水位中位数分别 5,513,216 B 与 5,562,368 B。报告见 `target/performance/cms-128m/report.json` 与 `target/performance/cms-64m/report.json`。 -- 定向回归:performance runner 32/32、`application_config` 3/3、`orm_query` 8/8、`cms_project` 1/1(实际 check/run/build/打包程序)通过;`cargo check --offline -p dever-runtime --features postgres` 通过。 -- 最终独立复核修正了两个收口问题:普通 SQLite `setting.json` 缺少 `database.postgres_test` 时现在按未启用 PostgreSQL 处理,只有显式但非法的测试连接才失败;真实 PostgreSQL fixture 使用 PID+纳秒+计数隔离 schema,并在断言失败/panic 后清理再恢复原始失败。修正后 runner 32/32、PostgreSQL cargo check 与真实验收 1/1 通过,结束后隔离 schema=0、活动连接=0。 -- rustfmt、clippy 组件未安装,未运行全量 workspace 测试;以上限制不影响本任务已列出的定向验收。 diff --git a/.trellis/tasks/09-13-typed-orm/prd.md b/.trellis/tasks/09-13-typed-orm/prd.md deleted file mode 100644 index 1db57db..0000000 --- a/.trellis/tasks/09-13-typed-orm/prd.md +++ /dev/null @@ -1,211 +0,0 @@ -# SQLite 与 PostgreSQL 类型安全 ORM - -## 目标 - -为 Dever 增加编译期类型检查、AOT 生成具体代码且无需反射的 ORM。第一轮完整支持 SQLite 和 PostgreSQL,共用 Model、查询计划、事务、迁移和错误合同;小内存机器只运行打包后的二进制,不承担 Rust 编译成本。 - -## 背景与约束 - -- Dever 是全新语言,不保留旧 ORM、旧 `async`/`await` 或其它源码兼容层,也不增加防御性回退路径。 -- 当前编译器没有用户泛型、反射、动态 `Value`、method 或 type-as-value;公开 ORM 必须保持静态、直接和可 AOT 降低。 -- Rust runtime 继续使用 Tokio 和真实异步 I/O。删除 Dever 源码中的 `async`/`await` 只改变语言表面,不把 HTTP、TCP、WebSocket、SSE 或数据库驱动改成阻塞线程模型。 -- SQLite 面向单机、小内存程序;PostgreSQL 面向并发后端。二者共享语义,不强行共享执行机制。 -- Model、Transaction、RowStream 等数据库资源沿用现有所有权、结构化任务、背压和取消清理原则。 - -## Model 与字段 - -- `model/` 下一个源文件定义一个 Model,继续使用普通 record `type`,不增加 `model` 关键字。 -- 文件只公开一个与文件名对应的 Model record;表名和列名按文件名、字段名精确派生,不做复数化猜测。 -- 同一文件集中字段、索引、关联、choice、Seed、迁移和紧贴持久化的数据访问操作,不增加外部 schema 映射文件。 -- 每个 Model 隐式拥有只读 `id` 和 `created_at: DateTime`。二者出现在完整查询结果中,但不出现在创建输入中;`updated_at` 不隐式生成。 -- `.id` 是数据库生成的有符号 64 位正整数,也是 Model 专属不透明类型。PostgreSQL 使用 64 位 identity,SQLite 使用 `INTEGER PRIMARY KEY`;不同 Model 的 ID 不能混用,也不能按普通 `Int` 运算。 -- 关联字段直接引用目标主键,例如 `owner_id: app.model.user.id`、`parent_id: app.model.category.id?`。作为 Model 字段时自动生成外键和普通索引,但不触发隐式加载。 -- 第一轮字段类型包括 `Bool`、`Int`、`Float`、`Decimal(P, S)`、`Text`、`Bytes`、Model `.id`、`Uuid`、`DateTime`、`Date`、`Time`、`Duration`、`Json`、无载荷 choice 及其可空形式。 -- `List`、`Map` 和普通 record 不隐式序列化为列;结构化持久化必须显式使用 `Json`。 -- 字段元数据使用可解析、可格式化、可静态检查的语法,不使用字符串 tag。 - -### 字符串、字节与数值 - -- `Text` 表示无界 UTF-8 文本,`Text(max)` 表示最多 max 个 Unicode codepoint,`Text(min, max)` 表示 min 至 max 个 Unicode codepoint;不增加语义重复的 `Char`。 -- `Bytes`、`Bytes(max)`、`Bytes(min, max)` 使用相同边界形式,但长度单位是字节。 -- PostgreSQL 有界 Text 使用 `VARCHAR` 与必要的 CHECK;SQLite 使用 `TEXT` 与等价 CHECK,不能依赖 SQLite 忽略 VARCHAR 长度。 -- `Decimal(P, S)` 必须满足 decimal128 的精度边界;两种数据库往返后保持精确值,不静默舍入。 - -### UUID 与时间 - -- `Uuid` 是固定 128 位值,运行时不使用堆分配 Text。PostgreSQL 使用原生 UUID,SQLite 使用 16-byte BLOB;API/JSON/文本统一为小写、带连字符的 36 字符格式。 -- 普通 `Uuid` 由调用方提供;`Uuid generated` 由 ORM 创建 UUIDv7 并从创建输入省略;`generated` 与可空不能同时使用。 -- `Uuid` 不隐式表示关系,关系仍使用 Model `.id`。 -- `DateTime` 表示 UTC 毫秒时间点;`Date` 表示公历日期;`Time` 表示日内毫秒时间;`Duration` 表示固定毫秒时长,不使用包含月份换算的数据库 interval。 - -### Choice - -- Model 文件可声明供字段使用的无载荷 choice;只有文件名对应的 record 生成表。 -- 可选项写成 `Pending = "待处理"`。数据库和 API 存储左侧稳定变体名,右侧显示名称不入库。 -- 编译器生成保持声明顺序的只读 `Choice.options: Map`;一个 choice 的变体必须全部带显示名或全部不带。 -- 第一轮不支持 choice payload,也不创建 PostgreSQL 专有 enum。 - -## 索引、Schema 与迁移 - -- 单字段索引写为字段后的 `index` 或 `unique`;复合索引写为 `index(a, b)` 或 `unique(a, b)`。 -- 索引描述当前目标 schema,不写版本号或手工名称;编译器稳定生成数据库对象名并静态检查字段引用和重复列。 -- 当前 Model schema 是唯一目标。ORM 比较数据库系统目录、内部 history 与二进制嵌入的规范化 schema,不生成源码级 `table/` 状态目录。 -- 新表直接按当前最终 schema 创建;新增可空字段、有合法常量默认值的非空字段、普通索引等意图唯一的变化自动应用。 -- 长度、精度、可空性、默认值和约束直接修改目标字段。放宽变化自动应用;收紧变化先验证现有数据,数据不满足时整次迁移失败并要求命名 migrate,绝不截断、舍入、猜测补值或删除数据。 -- 简单字段重命名写为 `display_name: Text(64) from nickname`。已有旧表执行 rename;全新数据库忽略历史来源,只创建最终字段。 -- `from` 只供 schema 规划,不进入运行时字段、CRUD 输入、查询 SQL 或最终约束。 -- 开发者不维护数字 schema 版本。编译器根据规范化 schema 和变更计划生成 revision 校验值,嵌入二进制并记录到数据库内部 history。 -- 复杂数据变化使用 Model 文件内稳定命名的 `migrate { ... }`,包括拆分、合并、跨行转换、删除前归档和显式 drop。 -- 一个命名迁移只成功执行一次;已执行迁移的规范化内容改变时拒绝启动。迁移和 history 写入在同一数据库事务内完成。 -- SQLite 无法直接 ALTER 的变化由方言层在事务内重建表;PostgreSQL 使用对应 DDL。两者完成后必须得到相同逻辑 schema revision。 -- 只有结构化迁移无法表达时,命名 migrate 才可包含明确方言的参数化原生 SQL;不承诺该 SQL 跨数据库复用。 - -## Seed - -- 每个 Model 文件最多一个无版本 `seed { ... }` 块,块内直接写多个匿名创建数据块,不重复 Model 名或 `create`。 -- Seed 数据按 Model 创建输入静态检查,不能填写 `id`、`created_at` 或其它 generated 字段。 -- 每条 Seed 必须完整提供至少一个单字段或复合唯一键,用于稳定识别初始化记录。 -- 编译器为规范化 Seed 生成校验值。内容未变化时启动不执行 Seed SQL;变化时在 schema 迁移成功后,以一个事务重新执行“缺失则插入”。 -- 唯一键冲突保留数据库现值;其它非空、CHECK、外键或解码错误必须失败。Seed 不覆盖或删除线上数据,修改/删除内置数据使用命名 migrate。 - -## 查询与内置操作 - -- Model 包生成唯一一套短函数:`create`、`create_many`、`get`、`first`、`list`、`cursor`、`count`、`exists`、`stream`、`update`、`delete`、`upsert`。 -- 业务代码直接调用 `user.list(...)`、`user.update(...)`,不暴露 `User.Query`、`User.List`、Active Record 实例方法或第二套 CRUD。 -- 创建、更新和查询配置使用上下文推导的匿名块;底层生成具体静态输入和结果类型,不引入动态字段 Map。 -- 查询只采用一次性配置块: - -```dever -users = user.list({ - where = status == UserStatus.Active - and age >= 18 - and (city == "北京" or city == "上海") - order = [created_at.desc, id.desc] - page = 1 - size = 20 - with = [owner] -}) -``` - -- 不提供 `user.where(...).order(...).list()` 链式查询器;链式查询不会提升数据库性能,却会要求新增 method、泛型查询对象和所有权语义。 -- 多个条件使用现有 `and`、`or`、`not` 和括号;支持比较、`in`、`between`、`contains`、`starts_with`、`ends_with`、null 与关联字段路径。 -- 查询表达式在编译期降低为类型检查后的 `QueryPlan`。字段、排序、关系和 SQL 结构不能来自运行时字符串;所有值通过参数绑定。 -- `list()` 默认返回第一页,默认 size 为 20,并受 `setting.json` 的统一上限约束;排序不是唯一键时自动追加 `id` 保证稳定分页。 -- `list` 返回 `items/page/size/total/pages`;`cursor` 返回 `items/next/has_more` 且不执行 count;`stream` 全量遍历但保持有界内存,不提供无界 `all()`。 -- 正向 to-one 由关联 ID 推导;反向 to-many 在 Model 中显式声明 `relation tasks = app.model.task.owner_id`。 -- `with` 才加载关系。to-one 使用受控 JOIN 或等价单次查询;to-many 按当前父页 ID 批量加载并归组,必须有排序和数量上限;禁止 lazy loading 和 N+1。 -- 多对多使用显式中间 Model,不生成隐藏表。 -- 复杂查询保留参数化、类型化的原生 SQL 逃生口。调用必须声明具体 Model/record 结果和方言;不返回动态行 Map,不允许 SQL 字符串插值。 - -## 数据库配置与绑定 - -- 应用项目根采用固定布局:`module/` 是唯一 Dever 源码根,`config/` 保存 `setting.json`,`data/` 保存运行数据。编译器从项目根加载时按 `module/` 的相对路径派生逻辑 package,`module` 本身不进入 package 名;`config/` 和 `data/` 不参与源码扫描。 -- 可执行文件按自身所在目录解析固定布局,不使用进程当前目录,也不提供环境变量覆盖: - -```text -app/ - app - config/ - setting.json - data/ - db/ - upload/ - log/ - cache/ - tmp/ -``` - -- `config/setting.json` 是唯一配置文件;缺失、无法解析或数据库配置无效时启动失败。运行时按需创建 `data/` 子目录,不生成默认 setting。 -- `setting.json` 顶层使用 `app`、`http`、`database`、`log` 等对象;`database` 直接映射连接名,不增加 `connections` 包装层。 -- `database.default` 必须存在;其它名称由应用定义,例如 `database.report`。 -- Model 连接按以下顺序在启动时解析并缓存: - 1. Model 文件显式 `database report`; - 2. 否则按根包名查找,例如 `app.model.user` 查 `database.app`; - 3. 根包连接键不存在时使用 `database.default`。 -- 只有“根包连接键不存在”允许回落 default。显式连接不存在、default 不存在或被选连接无效都直接启动失败。 -- 普通 CRUD 不接收 Database 或 Transaction 参数,也不允许按运行时字符串切换连接。 -- SQLite 使用 bundled `rusqlite`,同步调用进入现有有界 blocking 通道,默认小连接数并明确单写者约束。 -- PostgreSQL 使用 `tokio-postgres` 与有界异步连接池;池容量、等待和超时全部受配置上限约束。TLS 必须显式选择系统根验证或禁用,不允许验证失败后静默回落明文。 -- 编译器按可达数据库能力选择 runtime profile。SQLite-only 二进制不链接 PostgreSQL 驱动,PostgreSQL-only 二进制不链接 SQLite;驱动集合进入原生产物缓存身份。 - -## CMS 示例项目 - -- 在 `examples/dever/cms/` 建立可检查、可运行、可构建的完整项目,而不是只展示孤立语法片段。 -- 固定目录为 `config/setting.json`、`data/`、`module/cms.dever`、`module/user/model/`、`module/user/service/`、`module/news/model/`、`module/news/service/`。 -- `module/user` 和 `module/news` 分别是组件根;逻辑 package 使用 `user.model.*`、`user.service.*`、`news.model.*`、`news.service.*`,入口为 `cms.main`。 -- Model 展示隐式 `id`/`created_at`、Uuid、choice、Seed、索引和跨组件关联;Service 只承载注册、发布等事务业务,不包装 Model 已生成的普通 CRUD。 -- 示例默认使用 SQLite 和相对路径 `data/db/cms.db`,因此打包二进制可在无外部数据库服务的机器上直接运行;PostgreSQL 通过独立定向 fixture 验证,不让 CMS 示例依赖现有服务。 - -## 顺序调用、并发与事务 - -- Dever 源码删除 function/handler 的 `async` 标记和直接调用外层的 `await`。普通调用表示顺序等待完成,编译器根据传递挂起 effect 自动降低为 Rust coroutine。 -- 只有 `run(call)` 显式开始并发,`wait(task/group)` 消耗并等待结果,`stop(task/group)` 请求取消并等待结构化清理。 -- 同步入口的可达图没有挂起 effect 时不启动异步 runtime;包含网络、数据库、定时器、Channel 或异步 Stream 时只启动一个有界 Tokio runtime。 -- 事务使用专用函数声明: - -```dever -transaction create_order(...) (...) { - order = order.create({...}) - inventory.update({...}) -} -``` - -- 源码不出现 `@transaction`、Database、Transaction、begin、commit、rollback、`async` 或 `await`。 -- 编译器分析完整受控调用链中的 Model 数据库 effect,静态推导唯一连接,并通过隐藏参数传递事务上下文;不使用线程局部、任务局部或全局“当前事务”。 -- 最外层 transaction 函数开启物理事务;正常完成提交,error、fault 或取消先回滚再传播原始失败。 -- 同连接的嵌套 transaction 函数复用外层事务,不开启 savepoint,也不提前提交。 -- 无数据库 effect、跨连接、动态无法确定连接,或在 `run`/并发子任务中执行数据库 effect 的 transaction 函数在编译期拒绝。第一轮不支持分布式事务。 - -## Error、Fault 与日志边界 - -- choice 变体继续用 `error` 标记可恢复失败;编译器保留并扩展 C012,禁止丢弃、覆盖或仅用日志观察失败。 -- 普通可失败调用直接返回成功值,失败自动向当前边界传播,不写 `?`: - -```dever -user = user.get(id) -``` - -- 需要主动处理完整结果时使用一个核心操作 `result(call)`,再由现有穷尽函数分句处理成功和 error 变体。 -- 自定义业务失败使用 `fail(OrderError.OutOfStock(id))`。错误集合由编译器沿调用图静态推导并显示在 API、文档和编辑器信息中,不要求每个函数重复声明错误类型。 -- `error` 表示可恢复业务/外部失败;`fault` 表示程序不变量、编译器已知资源或 runtime 故障。普通业务函数第一轮不能捕获 fault。 -- HTTP 未处理 error/fault 只终止当前请求,回滚事务后返回不泄露内部细节的 500,并在服务端根边界记录一次;预期 4xx 必须由 handler 显式映射。 -- Task 失败由 `wait`/`result` 返回;无 owner 的任务边界记录一次。CLI 输出 stderr 并返回非零退出码。 -- 日志是观察,不是错误处理;`log.error` 不满足 C012。底层驱动、事务和 Service 不重复记录同一失败。 -- 正式日志 API 采用 `dever.log.debug/info/warn/error(message, fields)` 与共享结构化诊断上下文。队列有界:debug/info 满时丢弃当前事件并累计数量,warn/error 施加背压;logger 自身失败或最终 fault 直接写 stderr。 - -## 性能与资源边界 - -- ORM 只生成具体 Model 输入、行解码和静态查询计划;共享查询规划、schema diff 和方言实现,不为每个 Model 复制算法。 -- 查询使用绑定参数和可复用预编译语句;结果按行拉取,有界缓冲,不默认收集全表。 -- 连接池、SQLite blocking、批量写入、分页、关系子列表、stream 和日志队列全部有明确上限。 -- 不静默重试非幂等写入;约束冲突、连接失败、超时、取消和解码失败保持可区分。 -- 小机器验收以打包二进制的稳定 RSS、空闲连接成本、并发请求内存斜率和取消后的资源回收为准,不以构建机编译耗时或峰值内存为主要目标。 - -## 验收标准 - -- 合法 Model 在原生构建前生成确定 schema、创建输入、查询结果和 CRUD;字段、索引、Seed、关系或查询中的非法引用产生源码定位诊断。 -- 未声明 `id`/`created_at` 的 Model 仍能读取这两个字段,创建时无需填写;不同 Model ID 无法误传。 -- SQLite 与 PostgreSQL 对全部首批字段类型、默认值、长度、精度、choice、外键和索引产生等价逻辑约束并正确往返;PostgreSQL 系统根 TLS 校验和显式明文模式分别通过定向验证。 -- 同一个查询配置块在两种数据库生成正确的参数化 SQL,支持分页、游标、stream、复合条件和显式关联加载;to-many 不产生 N+1。 -- `list` 默认有界并返回 total/pages,`cursor` 不执行 count,`stream` 在慢消费者下保持有界内存。 -- 从空数据库启动时直接创建最终 schema 并执行缺失 Seed;重复启动无重复数据。已存在数据库能安全自动升级,危险变化在没有有效 migrate 时保持原 schema/数据并启动失败。 -- 带 `from` 的稳定二进制既能初始化新数据库,也能保留旧列数据完成 rename;自动 revision 和命名迁移 history 可重复验证且不可静默改写。 -- 默认、根包和显式连接按既定优先级绑定;显式缺失连接和无效配置启动失败。事务调用链只能使用一个已解析连接。 -- create/get/update/delete/list、事务提交、事务回滚和取消清理分别通过 SQLite 与 PostgreSQL 的定向真实数据库 fixture。 -- 普通 Dever 网络和数据库调用无需 `async`/`await` 仍是非阻塞 I/O;只有 `run` 建立业务并发,同步程序不启动 Tokio。 -- 可恢复 error 不能被丢弃或用日志代替处理;默认传播、`result(call)`、`fail(...)`、HTTP/Task/CLI 边界和事务回滚具有定向编译与运行验证。 -- SQLite-only 与 PostgreSQL-only 发布二进制只包含所用驱动;目标机器不需要 Cargo、Rust、SQLite 动态库或 PostgreSQL 客户端 SDK。 -- 在 64 MiB 与 128 MiB 约束下分别测量 SQLite、PostgreSQL 的空闲基线、稳定请求负载、流式读取和连接池上限;持续运行时 RSS 不无界增长,取消后连接与事务槽位回到基线。 -- `deverc check examples/dever/cms`、`deverc run examples/dever/cms cms.main` 和以同一项目根执行的原生构建均使用 `module/` 作为源码根,并能由 CMS Service 完成初始化数据、注册和发布的纵向流程。 - -## 暂不纳入第一轮 - -- 旧源码兼容、第二套 CRUD、链式查询、动态 Model、反射字段访问或运行时动态 SQL 结构。 -- MySQL/MariaDB、SQL Server、Oracle 驱动;只保留真实共享边界,不提前增加空适配器。 -- 非默认主键、自定义主键类型、以任意 UUID 唯一键建立关系、主键策略迁移。 -- choice 稳定变体改名和表/Model 重命名的通用简写;第一轮使用命名 migrate。 -- lazy loading、自动 N+1、隐藏多对多表、跨数据库 join、分布式事务、savepoint、读写分离和自动故障转移。 -- 数据库专有数组/enum/interval、分区表、表空间、物化视图、触发器、行级安全和在线无锁迁移。 -- 通用 annotation、decorator、macro、AST 改写和用户编写的编译期函数处理器。 -- 前端、管理页面、package registry、跨平台发行和编译器自举。 -- 日志文件 sink 的最终格式、轮转默认值和压缩策略;该项在错误基础设施子阶段收敛,不阻塞 ORM 合同。 diff --git a/.trellis/tasks/09-13-typed-orm/research/architecture-options.md b/.trellis/tasks/09-13-typed-orm/research/architecture-options.md deleted file mode 100644 index d900b76..0000000 --- a/.trellis/tasks/09-13-typed-orm/research/architecture-options.md +++ /dev/null @@ -1,76 +0,0 @@ -# ORM 架构选项 - -## 现有语言约束 - -- 一个源文件完整拥有一个 package,源码相对路径必须与 package 名匹配,因此可用 `model/` 路径承载 Model 身份,不需要再增加 `model` 声明。 -- `crates/dever-core/src/native/records.rs` 为用户 record/choice 生成具体类型;生产路径没有通用运行时 Value 或反射分派。 -- 系统资源由 `types.rs`、`check/symbols.rs`、`intrinsic.rs`、native emitter 和 runtime 共同定义,错误由官方 `.dever` choice 暴露。 -- static handler 是编译期绑定而非运行时函数值,可复用于行映射与查询回调,但不能单独解决表名、主键、索引和关联元数据。 -- 当前 native build 复用一个预编译 runtime rlib;数据库驱动选择必须进入可达性、runtime build 和缓存身份,不能只依赖链接器偶然消除代码。 - -## 表面模型比较 - -### 显式 Data Mapper(已否决) - -概念形态: - -```text -find(User, database, id) -insert(database, user) -update(database, user) -``` - -Model 是数据/schema,Database 和 Transaction 都由调用方显式传递。虽然实现直接,但业务表面重复且容易把同一事务漏传给某次操作;用户已明确否决,不作为公开或兼容 API 保留。 - -### Active Record(已否决) - -概念形态: - -```text -User.find(database, id) -user.save(database) -``` - -该方案会把生成类型和成员暴露给业务代码,用户已明确否决,不作为兼容表面保留。链式查询同样需要新增 method 和中间查询对象语义,且不改善生成 SQL;首版已经确定不采用。 - -### SQL-first typed mapper - -概念形态:参数化 SQL + 静态 row decoder。它不单独承担 ORM,只作为模型包短函数之外的高级逃生口保留:参数必须绑定,调用方必须声明具体 Model/record 结果,数据库专有语句明确选择对应 dialect。 - -## Model 文件约定 - -推荐形态: - -```dever -package app.model.user exposes ( - User -) - -type User { - email: Text(254) unique - name: Text(1, 64) - bio: Text? -} -``` - -- 路径 `app/model/user.dever` 对应 `package app.model.user`,文件名 `user` 精确对应公开 record `User` 和表名 `user`;不做复数化猜测。 -- 文件只能公开一个 Model record。私有辅助声明是否允许由实现阶段按真实需要决定,不能形成第二个持久化类型。 -- 主键 `id` 和 `created_at` 由 Model 文件约定隐式生成,不进入创建输入;查询结果仍可读取 `user.id` 与 `user.created_at`。其它 Model 通过 `app.model.user.id` 引用该强类型主键。 -- 编译器可合成 `User.New` 创建输入和固定 CRUD 成员;这属于 Model 专用静态语义,不意味着加入通用嵌套 type、反射或 type-as-value。 -- 简单字段属性紧邻字段;复合唯一约束、复合索引、初始化数据和有序迁移使用同文件的独立声明,避免把复杂结构压进字段行或外部配置。 -- 安全且意图唯一的 schema 变化自动生成;索引和 Seed 不使用版本号。简单重命名通过新字段的 `from ` 明确,编译器自动生成 revision;删除、类型收窄和数据转换等复杂操作才使用 Model 文件底部的命名 migrate。revision/迁移校验值记录在 history 中,SQLite 表重建由 dialect 隐藏。 -- Model 文件可以声明自定义持久化操作,但优先组合生成的查询/事务能力;不能覆盖通用 CRUD 的事务、错误和资源合同。 - -## 驱动边界 - -- SQLite:成熟 Rust 驱动支持 bundled SQLite,适合产生无需目标系统 SQLite 的单文件程序;同步 API 必须通过 Dever 已有 bounded blocking 资源执行。 -- PostgreSQL:成熟 Tokio 驱动原生异步并支持流水线;连接 driver 必须属于 Database/Pool 的结构化作用域。 -- 两者共享 QueryPlan、绑定值、行 schema、错误分类和迁移意图;SQL 编码与执行机制保持独立。 - -## 结论 - -采用 Model 包短函数作为唯一首版表面,例如 `user.list(...)`、`user.update(...)`。Model 用一文件一普通 `type` 的约定识别,不增加 `model` 关键字;创建、更新和查询块由调用上下文推导,不暴露 `User.Query` 等生成类型。复杂查询使用参数化、类型化的原生 SQL,不引入动态行对象。 - -跨操作事务采用 `transaction ` 专用函数声明。普通调用按顺序等待完成,编译器根据传递挂起 effect 自动降低为协程;Dever 源码不出现 `async`、`await`、Database、Transaction、begin、commit 或 rollback。编译器从 Model 数据库效果推导唯一连接,并把内部事务上下文沿受控调用链传递;正常完成自动提交,error、fault 或取消自动回滚。首版不允许事务中的数据库效果进入并发子任务,也不提供跨库事务、嵌套物理事务或 savepoint。 - -不引入 `@` 或通用函数装饰器。注解本身并不能减少事务实现,只会额外增加解析、注解解析、顺序、参数、扩展权限和源码映射合同;用户自定义处理还需要通用函数泛型、闭包捕获、async 包装与错误转发。完全自动推导事务和调用点 `transaction(handler)` 也分别存在边界隐蔽与包装遗漏问题,因此都不作为公开表面。 diff --git a/.trellis/tasks/09-13-typed-orm/research/driver-selection.md b/.trellis/tasks/09-13-typed-orm/research/driver-selection.md deleted file mode 100644 index c99b3a0..0000000 --- a/.trellis/tasks/09-13-typed-orm/research/driver-selection.md +++ /dev/null @@ -1,39 +0,0 @@ -# 数据库驱动与连接池选择 - -## 结论 - -- SQLite 使用 [rusqlite](https://github.com/rusqlite/rusqlite) 并启用 `bundled`,目标机器不依赖系统 SQLite。 -- SQLite 池与同步任务适配使用 [deadpool-sqlite](https://docs.rs/crate/deadpool-sqlite/latest),它直接基于 rusqlite,并能把 `bundled` feature 传递给 rusqlite。 -- PostgreSQL 使用 [tokio-postgres](https://github.com/sfackler/rust-postgres),保留原生异步连接与流水线能力;TLS 使用 [tokio-postgres-rustls](https://docs.rs/tokio-postgres-rustls/latest/tokio_postgres_rustls/) 复用项目现有 rustls 根证书和主机名校验。 -- PostgreSQL 连接池使用 [deadpool-postgres](https://docs.rs/deadpool-postgres/latest/deadpool_postgres/),复用其连接回收和静态语句缓存,不自行实现通用连接池。 - -## 选择理由 - -- 四个 crate 属于两组相互配套的驱动/池实现,不需要引入完整 ORM 或第二套查询语义。 -- rusqlite 的 bundled 模式静态编译 SQLite,符合打包后二进制直接运行的要求。 -- tokio-postgres 与当前 Dever Tokio runtime 一致;它的连接 driver 可以纳入现有结构化任务生命周期。 -- deadpool-postgres 已包装 `tokio_postgres::Client`/`Transaction` 并提供 statement cache,适合 Dever 已静态确定 SQL 形状的查询。 -- deadpool-sqlite 负责连接池和同步连接的安全交互;Dever 仍在外层施加全局 blocking 上限、取消和超时合同。 - -## 不采用的方案 - -- 不采用 SQLx、Diesel 或 SeaORM:Dever 自己拥有 Model、QueryPlan、迁移和类型检查,再引入完整 ORM 会形成重复语义与额外二进制负担。 -- 不直接手写 PostgreSQL/SQLite 连接池:池的回收、等待、关闭与失效连接处理不是 Dever 的业务差异点。 -- 不让 SQLite 和 PostgreSQL 共用同一个执行 trait object 热路径;共享的是静态 QueryPlan 和错误分类,具体执行通过编译时 profile 与连接枚举分派。 - -## 二进制裁剪 - -`dever-runtime` 将数据库依赖设为 optional features: - -- `sqlite`:deadpool-sqlite + rusqlite bundled -- `postgres`:deadpool-postgres + tokio-postgres + tokio-postgres-rustls -- `database`:共享 config、ORM 值和错误基础 - -构建阶段从 `config/setting.json` 读取所有连接的数据库类型,只把驱动能力集合加入 runtime profile 和原生产物缓存身份,不嵌入账号、连接串或其它配置值。运行时设置可以在同一能力集合内改变;改用未打包的数据库类型必须重新构建。 - -## 验证重点 - -- 分别比较 base、SQLite-only、PostgreSQL-only 和双驱动二进制大小。 -- 64/128 MiB 环境测量空池、最大池、稳定负载和连接归还后的 RSS。 -- 验证连接获取超时、取消、driver task 失败、SQLite busy 和 shutdown drain。 -- 对静态 SQL 验证 statement cache 命中;迁移 DDL 不进入无界 statement cache。 diff --git a/.trellis/tasks/09-13-typed-orm/research/field-types.md b/.trellis/tasks/09-13-typed-orm/research/field-types.md deleted file mode 100644 index 4faf7a0..0000000 --- a/.trellis/tasks/09-13-typed-orm/research/field-types.md +++ /dev/null @@ -1,192 +0,0 @@ -# ORM 字段类型与隐式字段 - -## 默认字段 - -`model/` 中的每个 Model 即使源码不写,也具有: - -```dever -id: .id -created_at: DateTime -``` - -- `id` 是编译器合成、数据库生成的 64 位正整数主键字段;它的公开静态类型就是当前 Model 的 `.id`,不能当作普通 Int 运算,不同 Model 之间也不能混用。 -- `created_at` 由 ORM 在插入时写入当前 UTC DateTime。 -- 两个字段都存在于完整 Model 和查询结果中,不存在于 `Model.New` 创建输入中。 -- `updated_at` 不默认生成。Go Dever 现有 Model 中 created_at 明显比 updated_at 普遍;只有确实需要跟踪修改时间的 Model 才显式声明自动更新字段。 -- `deleted_at`、version、tenant_id 和操作者字段都具有业务含义,不作为所有 Model 的隐式字段。 - -因此最小 Model 可以写成: - -```dever -type User { - name: Text(1, 64) - email: Text(254) unique -} -``` - -读取 `user.id`、`user.created_at` 合法,但创建时只提供 name/email。 - -## 通用类型矩阵 - -| Dever 类型 | 逻辑语义 | PostgreSQL | SQLite | -| --- | --- | --- | --- | -| Bool | 布尔值 | BOOLEAN | INTEGER + CHECK | -| Int | 有符号 64 位整数 | BIGINT | INTEGER | -| Float | binary64 | DOUBLE PRECISION | REAL | -| Decimal(P, S) | 最多 34 位十进制定点数 | NUMERIC(P,S) | 精确定点编码与约束 | -| Text | 无界 UTF-8 文本 | TEXT | TEXT | -| Text(N) | 0 至 N 个 Unicode codepoint | VARCHAR(N) | TEXT + CHECK | -| Text(M, N) | M 至 N 个 Unicode codepoint | VARCHAR(N) + CHECK | TEXT + CHECK | -| Bytes | 无界字节 | BYTEA | BLOB | -| Bytes(N) / Bytes(M, N) | 有界字节 | BYTEA + CHECK | BLOB + CHECK | -| `.id` | 具体 Model 的不透明 64 位主键/外键投影 | BIGINT identity | INTEGER PRIMARY KEY | -| Uuid | 128 位 UUID | UUID | 16-byte BLOB | -| DateTime | UTC 时间点,毫秒精度 | TIMESTAMPTZ(3) | epoch-millis INTEGER | -| Date | 公历日期 | DATE | epoch-day INTEGER | -| Time | 一天内时间,毫秒精度 | TIME(3) | millis-of-day INTEGER | -| Duration | 固定毫秒时长 | BIGINT | INTEGER | -| Json | 已验证 JSON 值 | JSONB | UTF-8 TEXT | -| 无载荷 choice | 封闭枚举 | TEXT + CHECK | TEXT + CHECK | - -List、Map、普通 record 不自动变成 JSON 列。调用方必须显式选择 Json,避免字段重构在不知情时改变持久化格式。 - -## UUID 字段 - -UUID 不是每个 Model 的隐式字段。只有业务需要公开不可预测标识、跨系统交换标识或在写入数据库前生成标识时才显式声明: - -```dever -type User { - uuid: Uuid generated unique - name: Text(1, 64) -} -``` - -- `uuid: Uuid` 由调用方提供,存在于创建输入中。 -- `uuid: Uuid generated` 由 ORM 在创建时生成 UUIDv7,不存在于创建输入中。 -- `uuid: Uuid?` 接受空值;`generated` 与可空不能同时使用。 -- 运行时使用固定 16 字节值,不用堆分配的 Text 保存 UUID。 -- PostgreSQL 使用原生 UUID,SQLite 使用 16-byte BLOB,索引不会保存 36 字符文本。 -- API、JSON、日志及显式文本转换统一输出小写、带连字符的 36 字符形式;解析只接受语言标准库定义的 UUID 文本格式。 -- Uuid 字段不会自动成为关联。关联仍写成 `app.model.user.id`,以保持外键类型检查和紧凑索引。 - -## 初始化数据写法 - -Seed 是当前 Model 的可重复初始化数据。一个块可以包含多条数据,值使用 Model 创建输入进行静态检查: - -```dever -type Status { - code: Text(32) unique - name: Text(64) - enabled: Bool default true -} - -seed { - { - code = "pending" - name = "待处理" - } - - { - code = "done" - name = "已完成" - enabled = true - } -} -``` - -以后增加初始化记录时直接追加数据块,不维护 Seed 版本号。编译器按 Seed 内容校验值判断是否需要执行;执行时整体使用事务,唯一冲突保留已有记录。源码移除 Seed 也不删除数据,需要修改或删除时使用显式命名迁移。 - -## 可选项 - -固定可选项复用语言现有的无载荷 choice `type`,不另造 ORM enum: - -```dever -type TaskStatus { - Pending = "待处理" - Running = "进行中" - Done = "已完成" -} - -type Task { - title: Text(1, 160) - status: TaskStatus default TaskStatus.Pending -} - -seed { - { - title = "初始化任务" - status = TaskStatus.Pending - } -} -``` - -`Task` 是文件对应的 Model record;`TaskStatus` 是同文件的辅助 choice,不生成表。ORM 第一轮只接受不带 payload 的 choice,并将左侧变体名映射为带 CHECK 约束的 Text。右侧显示名称不存入业务列。 - -推荐由编译器把显示名称提供为保持声明顺序的只读 Map,不再重复定义映射: - -```dever -task_status_options() (options: Map) { - options = TaskStatus.options -} -``` - -需要选项子集或自定义顺序时再返回 `List` 或组合 `TaskStatus.options`。choice 负责限制合法值,生成的 Map 负责名称和默认顺序。 - -## 索引与迁移写法 - -单字段索引直接跟在字段后,复合索引放在 Model 后;它们都描述当前目标 schema,不使用版本号或手工数据库名称: - -```dever -type Task { - tenant_id: app.model.tenant.id - code: Text(32) - status: TaskStatus index - title: Text(1, 160) -} - -unique(tenant_id, code) -index(status, created_at) -``` - -简单字段重命名直接写在新字段旁边: - -```dever -type Task { - summary: Text from description -} -``` - -编译器生成 `RENAME COLUMN`,不会把它误判成删旧列再加新列。revision 由编译器根据规范化 schema 和计划自动生成并写入数据库 history,源码不维护版本号。 - -拆分、合并、删除前归档等无法附着在单个新字段上的数据变化,才保留一次性命名迁移: - -```dever -migrate remove_legacy_code { - drop legacy_code -} -``` - -迁移名称是复杂操作的稳定身份,内容校验值用于阻止已经执行的迁移被悄悄修改。`from` 需要保留到所有可能升级的数据库都已越过该变更。 - -## 关联 ID - -```dever -type Article { - author_id: app.model.user.id - category_id: app.model.category.id? - title: Text(1, 160) -} -``` - -- `app.model.user.id` 与 `app.model.category.id` 是不同静态类型,不能误传。 -- 点分路径的最后一段 `id` 是目标 Model 的隐式字段投影,不是新增的普通小写 type;它也能用于 function 输入、输出和局部类型位置。 -- 非空和可空关联第一轮都使用 `ON DELETE RESTRICT`;SET NULL 或 CASCADE 的通用关系选项不在第一轮,必要时使用明确方言的命名 migrate。 -- 每个关联 ID 自动创建普通索引和外键约束。它只表达持久化关系,不自动查询目标对象。 -- 关系预加载必须显式请求并保持有界,不能形成隐藏 N+1。 - -## 时间 API 方向 - -- DateTime 值始终代表 UTC 时间点,不在值内携带可变时区数据库。 -- 时区只参与解析、格式化和日历换算;数据库比较、排序和相减使用统一时间点。 -- `created_at` 自动取当前 DateTime。`updated_at` 不隐式生成;第一轮需要该字段时按普通 `DateTime` 明确写入,自动更新修饰词后续单独设计。 -- DateTime/Date/Time 的 parse、format、比较和加减由标准 package 提供;数据库函数通过 ORM 查询表达式或明确的原生 SQL 使用。 diff --git a/.trellis/tasks/09-13-typed-orm/research/go-orm-reference.md b/.trellis/tasks/09-13-typed-orm/research/go-orm-reference.md deleted file mode 100644 index b55a232..0000000 --- a/.trellis/tasks/09-13-typed-orm/research/go-orm-reference.md +++ /dev/null @@ -1,45 +0,0 @@ -# Go Dever ORM 参考结论 - -## 已核对实现 - -- `/data/project/shemic/backend/dever/orm/schema_registry.go` 通过 Go 反射读取 `dorm` 字符串 tag;Text 默认 `VARCHAR(255)`,`size:N` 生成 `VARCHAR(N)`,也允许直接写 `type:varchar(N)` 或 `type:text`。 -- `ModelConfig.Index`/`Indexes` 使用额外 Go struct 表达单列或复合索引;`ModelConfig.Seeds` 使用 `[]map[string]any` 表达初始化数据。 -- `/data/project/shemic/backend/dever/orm/schema_apply.go` 能建表、加字段、修改部分数据库的字段类型、删旧字段,并同步新增、变化和删除的索引。 -- 当前 Seeds 只在表首次创建时插入;已有表后来新增 Seed 不会自动补入。Seed 使用动态 Map,字段名和值类型不能在编译期完整检查。 -- 当前自动迁移直接对数据库执行,再可选记录 SQL;它会删除不在目标 schema 中的字段和索引。字段重命名只对大小写或下划线差异做有限推断,无法可靠判断任意重命名。 -- `database.persist=true` 会把目标 schema 写入 `data/table/*.json`,`dever migrate` 再读取这些文件应用到目标数据库。该目录是 schema 传递/发布产物,不包含某个数据库实例是否成功执行的可靠状态;同一文件可以对应多个状态不同的数据库。 -- Go Model wrapper 可以嵌入通用 `orm.Model[T]` 并增加 `AfterSave`、`AfterDelete` 或自定义查询方法。普通 Model 直接复用通用 CRUD,不需要 wrapper。 - -## 新语言应复用的设计 - -- 一个 Model 文件集中字段、索引、默认排序、初始化数据和少量紧贴持久化生命周期的扩展。 -- 通用 CRUD、过滤、排序、分页、事务和批量操作由 ORM 提供,不为每个 Model 重写。 -- 单列与复合索引都从 Model 目标 schema 自动同步。 -- Model 声明生成确定的数据库 schema,SQLite/PostgreSQL 只负责方言差异。 - -## 不应照搬的部分 - -- 不使用字符串 tag、反射、`any`、动态字段 Map 或运行时猜测字段名。 -- 不把无界 Text 默认截成 `VARCHAR(255)`;`Text` 表示无界文本,只有显式长度上限才产生 VARCHAR/CHECK。 -- 不只在首次建表时处理初始化数据。每条 Seed 必须有稳定身份并可重复应用。 -- 不把“字段从目标结构中消失”直接等同于可以删列,也不把任意新增/缺失列猜成重命名。 -- 不把本地 `table/` 文件是否存在当作数据库建表或迁移完成标记。新语言将目标 schema 嵌入二进制,实际状态记录在数据库并通过系统目录核对。 -- 不允许自定义方法覆盖并改变通用 CRUD 的基本事务、错误和资源合同;自定义操作组合通用查询或参数化 SQL。 - -## 推荐字段形态 - -```dever -type User { - name: Text(1, 64) - email: Text(254) unique - bio: Text? - credit: Decimal(18, 2) default 0 - status: Int >= 0 and <= 2 default 1 -} -``` - -- `Text(N)` 表示最多 N 个 Unicode codepoint,`Text(M, N)` 表示 M 至 N 个;无参数 Text 是无界文本。 -- `Bytes(N)` 表示最多 N 个字节,`Bytes(M, N)` 表示 M 至 N 个字节。 -- `Decimal(P, S)` 描述数据库精度与小数位,必须满足 `1 <= P <= 34`、`0 <= S <= P`,与 Dever decimal128 的 34 位有效数字上限一致。 -- `?` 已经表达可空,不再增加 `null/not null` 两套写法。 -- `id` 与 `created_at` 由 Model 隐式生成;关联主键用 `app.model.user.id` 这种字段投影引用。默认值和简单 unique 靠字段元数据;复合索引、无版本 Seed 和命名迁移使用同文件的独立声明,避免把复杂结构塞进一行字段。 diff --git a/.trellis/tasks/09-13-typed-orm/research/implicit-suspension.md b/.trellis/tasks/09-13-typed-orm/research/implicit-suspension.md deleted file mode 100644 index 5e378e7..0000000 --- a/.trellis/tasks/09-13-typed-orm/research/implicit-suspension.md +++ /dev/null @@ -1,48 +0,0 @@ -# 隐式挂起的顺序调用 - -## 决定 - -Dever 源码删除 function/handler 的 `async` 标记和直接异步调用外层的 `await(...)`。普通调用始终表示调用完成后才执行下一条语句;如果调用链包含数据库、网络、定时器、Channel 或异步 Stream 等挂起效果,编译器自动把对应函数降低为协程。 - -```dever -route(request: dever.http.Request) (response: dever.http.Response) { - user = user.get(request.user_id) - response = render(user) -} -``` - -等待 I/O 时只挂起当前协程,Tokio 工作线程可以执行其它连接和任务。语法简化不意味着阻塞线程,也不改变 HTTP/TCP/WS/SSE runtime、连接池、背压、超时与取消清理。 - -## 并发边界 - -普通调用严格顺序;只有 `run` 显式启动并发: - -```dever -first = run(load_user(first_id)) -second = run(load_user(second_id)) -first_user = wait(first) -second_user = wait(second) -``` - -- `run(call(...))` 创建受限 Task。 -- `wait(task_or_group)` 消耗任务或任务组并取得结果/等待排空。 -- `stop(task_or_group)` 请求取消并等待结构化清理。 -- CPU 同步计算继续使用 `parallel`,明确阻塞调用继续使用 `blocking`。 -- 普通调用不产生 Task,也不允许把可挂起调用结果当 Future 保存。 - -## 编译器边界 - -- 系统 intrinsic 和官方库入口提供基础挂起效果;调用图、静态 handler 专门化和 collection handler 传播效果。 -- checker 在效果推导后区分顺序调用、`run` 和 Task `wait`;HIR/native 仍可保留内部 coroutine/await 节点,但不把它们暴露到源码。 -- 同步入口的完整可达图没有挂起效果时沿用直接原生入口,不初始化 Tokio。 -- handler 是否允许挂起由其使用位置和实际效果静态检查,不再由源码 `async handler` 标记。 -- API snapshot、Markdown 合同和格式化输出的是新语法;旧 `async`/`await` 不保留兼容分支。 - -## 迁移范围 - -- lexer、parser、syntax AST、checker、effect/cycle/failure 分析、HIR 与 native emitter。 -- `dever.task`、`dever.net`、`dever.http`、`dever.websocket`、`dever.sse` 的官方 Dever 声明。 -- HTTP/1、HTTP/2、TCP、TLS、WebSocket、SSE、AsyncStream、Channel 和结构化并发测试中的嵌入源码。 -- backend/http/live/async 示例、性能 fixtures、LANGUAGE 与 Trellis backend 规范。 - -Rust runtime 内的 Rust `async/.await` 不在迁移范围;删除它们会把高并发 I/O 退化为阻塞或线程堆叠,与目标相反。 diff --git a/.trellis/tasks/09-13-typed-orm/research/migration-practices.md b/.trellis/tasks/09-13-typed-orm/research/migration-practices.md deleted file mode 100644 index 2a8117e..0000000 --- a/.trellis/tasks/09-13-typed-orm/research/migration-practices.md +++ /dev/null @@ -1,20 +0,0 @@ -# 字段重命名与迁移版本调研 - -## 官方实现结论 - -- [Alembic Autogenerate](https://alembic.sqlalchemy.org/en/latest/autogenerate.html) 明确说明无法检测表名和列名变化;它会生成 add/drop 候选,要求开发者审查并改为 rename。 -- [Prisma 自定义迁移](https://docs.prisma.io/docs/orm/prisma-migrate/workflows/customizing-migrations) 的字段重命名示例同样默认得到 drop/add,需要先生成草稿迁移,再人工改成 `RENAME COLUMN`。Prisma 用迁移目录和数据库 `_prisma_migrations` 表维护历史。 -- [EF Core 管理迁移](https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/managing) 说明框架无法判断“删除并新增”和“重命名”的真实意图;生成代码需要改为 `RenameColumn`,否则会丢失旧列数据。 -- [Django 迁移操作](https://docs.djangoproject.com/en/5.2/ref/migration-operations/) 提供显式 `RenameField(old_name, new_name)`;[Django 迁移流程](https://docs.djangoproject.com/en/6.0/topics/migrations/) 把迁移文件视为数据库 schema 的版本控制,并在数据库记录应用历史。 -- [Atlas 声明式重命名](https://atlasgo.io/changelog/declarative-schema-renames) 使用紧邻目标列的 `renamed_from` 显式表达意图。Atlas 早期依赖交互式询问,但非交互部署无法回答,因此把 rename 意图写回声明式 schema。 -- [Atlas 声明式与版本式对比](https://atlasgo.io/concepts/declarative-vs-versioned) 表明声明式流程可以从目标 schema 规划实际数据库差异;版本式流程则保留完整迁移文件历史。两者都不能依靠一个数字版本推导 rename 意图。 - -## 对 Dever 的结论 - -- 只增加 Model 数字版本不能解决字段重命名;版本只标识状态先后,不包含旧列与新列的对应关系。 -- 不采用字段名相似度自动猜测。相同类型的删一列、加一列既可能是 rename,也可能是两个独立业务变化。 -- 简单 rename 采用声明式字段来源:`new_field: Type from old_field`。它比单独 migrate 块短,并把意图放在所属字段旁。 -- 编译器为规范化目标 schema 与迁移计划自动产生 revision id/校验值,嵌入二进制;数据库内部 history 记录实际应用状态。开发者不写数字版本。 -- `from` 必须保留到所有需要升级的数据库越过该变化;这与 Atlas 把 `renamed_from` 放进 schema 的原则一致。 -- `from` 只描述已有表的升级路径。目标表不存在时直接创建当前最终 schema,只创建新字段,不要求旧字段存在,也不先创建旧结构再回放 rename。 -- 拆分、合并、跨行回填、删除前归档等没有单字段对应关系的变化,仍需要命名 migrate。该复杂度来自数据转换本身,不能由版本号或启发式推断消除。 diff --git a/.trellis/tasks/09-13-typed-orm/research/query-api.md b/.trellis/tasks/09-13-typed-orm/research/query-api.md deleted file mode 100644 index 9324180..0000000 --- a/.trellis/tasks/09-13-typed-orm/research/query-api.md +++ /dev/null @@ -1,199 +0,0 @@ -# ORM 查询与内置操作方案 - -## 结论 - -公开表面只使用 Model 包短函数和一次性查询配置块: - -```dever -users = user.list({ - where = status == UserStatus.Active and age >= 18 - order = [created_at.desc, id.desc] - page = 1 - size = 20 - with = [owner] -}) -``` - -不提供 `User.Query`、`User.List`、Active Record 实例方法或 `user.where(...).order(...).list()` 链式查询器。编译器把匿名块直接静态降低为 `QueryPlan`;源码没有 `async`/`await`,普通调用顺序等待完成。 - -## 为什么选择配置块 - -块式和链式可以生成相同 SQL,链式本身没有数据库性能优势。Dever 当前没有通用 method、lambda、用户泛型或 type-as-value,链式方案会额外引入查询对象类型、所有权、复用和执行时机合同。配置块则有以下特点: - -- `create`、`update` 和 `list` 保持同一种上下文推导形式。 -- 一次调用完整展示条件、排序、分页和关系加载。 -- 编译器直接生成一个静态计划,不产生运行时中间查询对象。 -- 公开 API 只有一套写法,不需要兼容或维护等价表面。 - -将来若动态 HTTP 参数确实需要逐步组合条件,应增加受限的类型化 where 值,而不是改造全部 CRUD 为链式查询。 - -## 基本 CRUD - -```dever -users = user.list() -current = user.get(user_id) -created = user.create({ - name = "Dever" - status = UserStatus.Active -}) -updated = user.update(user_id, { - name = "New name" -}) -deleted = user.delete(user_id) -``` - -`create` 和 `update` 的匿名数据块由调用上下文推导字段。不能写入的 generated 字段、拼错的字段和不兼容值在编译期拒绝;底层仍是具体输入 record,不是动态 Map。 - -普通可失败调用成功时直接产生成功值,失败自动传播。需要主动处理完整结果时写: - -```dever -result = result(user.get(user_id)) -``` - -随后使用现有穷尽函数分句处理成功和 error 变体,不为 ORM 增加 try/catch 或 `?`。 - -## List、Cursor 与 Stream - -`user.list()` 返回有界默认第一页。完整配置为: - -```dever -users = user.list({ - where = status == UserStatus.Active and created_at >= start - order = [created_at.desc, id.desc] - page = 1 - size = 20 - with = [owner] -}) -``` - -查询块处于当前 Model 上下文,所以字段直接写 `status`、`created_at`、`owner`,不重复 Model 名。它不是动态 Map,字段、运算符、值、排序和关系都由编译器检查。 - -- `page` 默认 1,`size` 默认 20,并受统一配置上限约束。 -- 默认排序为 `id.desc`;自定义排序不是唯一键时自动追加 `id`,保证页边界稳定。 -- 返回 `items`、`page`、`size`、`total`、`pages`。 -- 页码查询执行数据查询和 count;不需要 total 时使用 cursor。 - -深翻页使用同一个配置块: - -```dever -users = user.cursor({ - after = next - size = 100 - where = status == UserStatus.Active - order = [created_at.desc, id.desc] -}) -``` - -`cursor` 返回 `items`、`next`、`has_more`,不执行 count。全表处理使用 `user.stream(query?)`,按行拉取并保持有界缓冲;不提供无界 `all()`。 - -## Where - -多个条件直接组成一个布尔表达式,不增加条件数组: - -```dever -users = user.list({ - where = status == UserStatus.Active - and age >= 18 - and age < 60 - and (city == "北京" or city == "上海") -}) -``` - -- 比较支持 `==`、`!=`、`<`、`<=`、`>`、`>=`。 -- 逻辑组合使用既有 `and`、`or`、`not` 和括号。 -- 集合与区间使用 `in`、`between`。 -- Text 匹配使用 `contains`、`starts_with`、`ends_with`。 -- 可空字段可直接与 `null` 比较。 -- 关系条件使用字段路径,例如 `owner.status == UserStatus.Active`;筛选关系不会自动把关系放进结果。 - -ORM 将表达式规范化为静态条件树,按源码顺序收集绑定值。相同字段可重复出现,矛盾条件由数据库返回空结果;不引入运行时条件解释器。 - -## 关联 - -正向 to-one 从关联 ID 推导: - -```dever -type Task { - owner_id: app.model.user.id -} -``` - -查询时使用 `with = [owner]`。反向 to-many 无法可靠推断名称,因为目标 Model 可能有多个外键,因此在当前 Model 文件显式命名: - -```dever -relation tasks = app.model.task.owner_id -``` - -- to-one 使用受控 JOIN 或等价单次查询。 -- to-many 按当前父页 ID 批量加载并归组,不逐父记录查询。 -- to-many 子列表必须有稳定排序和数量上限。 -- 多对多使用显式中间 Model,不生成隐藏表。 -- 不提供 lazy loading,读取普通字段不会在背后访问数据库。 - -## 内置函数 - -| 函数 | 用途 | -| --- | --- | -| `user.create(data)` | 创建一条并返回完整 Model | -| `user.create_many(list)` | 有界批量创建 | -| `user.get(id)` | 按主键获取一条 | -| `user.first(query?)` | 按条件获取第一条 | -| `user.list(query?)` | 自动页码分页 | -| `user.cursor(query?)` | 稳定游标分页 | -| `user.count(where?)` | 统计数量 | -| `user.exists(where?)` | 判断是否存在 | -| `user.stream(query?)` | 有界流式遍历 | -| `user.update(id_or_query, changes)` | 单条或条件批量更新 | -| `user.delete(id_or_query)` | 单条或条件批量删除 | -| `user.upsert(key, create, update)` | 按唯一键新增或更新 | - -`update`/`delete` 根据首个参数静态区分主键和条件,不增加重复的 `update_many`/`delete_many` 名称。批量写入返回影响行数;业务状态流转、跨表原子编排和外部调用由 transaction 函数组合。 - -## 数据库绑定 - -普通调用不传 `Database`: - -```dever -user.list({...}) -user.update(user_id, {...}) -``` - -Model 的连接在程序启动时解析并缓存: - -1. Model 文件显式 `database report`; -2. 否则按根包名查找,例如 `app.model.user` 查 `database.app`; -3. 根包键不存在时使用必需的 `database.default`。 - -显式连接不存在、default 不存在或选中配置无效时启动失败。生成代码访问固定连接槽位,不按字符串进行每请求查找,也不允许 CRUD 临时切库。 - -## 自动事务 - -事务不属于 Model API,源码不取得或传递 Transaction: - -```dever -transaction assign_task( - user_id: app.model.user.id, - title: Text -) (result: AssignResult) { - user.update(user_id, { - active = true - }) - task.create({ - owner_id = user_id - title = title - }) - result = AssignResult.Assigned -} -``` - -编译器分析完整调用链,从 Model 数据库 effect 推导唯一连接。进入最外层函数时自动开启物理事务,直接或经普通顺序 helper 执行的操作都使用隐藏事务上下文;正常完成提交,error、fault 或取消先回滚再离开。 - -同连接嵌套 transaction 复用外层事务,不使用 savepoint。跨连接事务和事务中的并发数据库子任务在编译期拒绝。该设计不引入 `@`、decorator、显式 begin/commit/rollback 或动态当前事务。 - -## 实现与性能 - -- 所有 Model 复用一个编译期 `QueryPlan`、schema 引擎和方言执行层,只生成字段专属的薄代码。 -- 参数绑定、预编译语句和具体行解码不经过反射或动态 Map。 -- to-many 批量加载避免 N+1,也避免多个 to-many JOIN 产生笛卡尔膨胀。 -- 分页、关联子列表、批量写入、行流、连接池和 SQLite blocking 全部有界。 -- SQLite 和 PostgreSQL 可以用不同执行器,但必须消费同一逻辑查询计划并返回同一 Dever 类型。 diff --git a/.trellis/tasks/09-13-typed-orm/research/schema-change-matrix.md b/.trellis/tasks/09-13-typed-orm/research/schema-change-matrix.md deleted file mode 100644 index 3c333ac..0000000 --- a/.trellis/tasks/09-13-typed-orm/research/schema-change-matrix.md +++ /dev/null @@ -1,90 +0,0 @@ -# Model schema 变更分类 - -## 设计原则 - -Model 始终声明当前目标 schema。ORM 只保留三种演进机制: - -1. 目标 schema diff:处理意图唯一且不会静默丢失数据的变化。 -2. `from`:补充 diff 无法推断的旧身份,例如字段重命名。 -3. 命名 `migrate`:处理需要业务决定的数据转换、修复和删除。 - -不为长度、默认值、可空性、索引等每类变化增加单独版本或迁移关键字。SQLite 和 PostgreSQL 的 DDL 差异由 dialect 处理。 - -## 变更矩阵 - -| 变化 | Model 写法 | 默认处理 | -| --- | --- | --- | -| 新建表 | 新增 Model 文件 | 直接创建当前最终 schema | -| 新增可空字段 | 新增 `field: Type?` | 自动添加 | -| 新增必填字段并有常量默认值 | 新增 `field: Type default value` | 自动添加并由数据库填充已有行 | -| 新增必填字段但无默认值 | 新增 `field: Type` | 空表可自动添加;有数据时要求 migrate 回填 | -| 字段重命名 | `new_field: Type from old_field` | 旧表执行 rename;新表只创建新字段 | -| 字段重命名并放宽类型约束 | `new_field: WiderType from old_field` | rename 后自动修改类型/约束 | -| 字段重命名并收紧类型约束 | `new_field: NarrowerType from old_field` | 先验证数据;不满足时要求 migrate | -| Text/Bytes 最大长度增加 | 直接修改类型参数 | 自动修改 | -| Text/Bytes 最大长度减小 | 直接修改类型参数 | 先验证现有值长度;不截断,失败时要求 migrate | -| Text/Bytes 最小长度增加 | 直接修改类型参数 | 先验证现有值;失败时要求 migrate | -| Text/Bytes 最小长度减小 | 直接修改类型参数 | 自动放宽约束 | -| Decimal 精度/小数位变化 | 直接修改类型参数 | 仅可精确往返时自动;可能溢出或舍入时要求 migrate | -| 同族无损类型扩大 | 直接修改字段类型 | 按编译器固定无损转换表自动执行 | -| 跨族或可能有损类型转换 | 直接修改字段类型并提供 migrate | 必须明确转换表达式,禁止依赖数据库隐式强转 | -| 必填改可空 | `Type` 改为 `Type?` | 自动移除 NOT NULL | -| 可空改必填 | `Type?` 改为 `Type` | 验证无 NULL;否则要求 migrate 回填 | -| 增加默认值 | 增加 `default value` | 自动修改,只影响后续写入 | -| 修改默认值 | 修改 `default value` | 自动修改,只影响后续写入 | -| 删除默认值 | 删除 `default value` | 自动修改,不改已有数据 | -| 普通索引增加/删除 | 增删 `index` 或 `index(...)` | 自动同步,不改业务数据 | -| 普通索引列或顺序变化 | 修改 `index(...)` | 删除旧索引并创建新索引 | -| 增加唯一约束 | 增加 `unique` 或 `unique(...)` | 先验证无重复;失败时要求 migrate 去重 | -| 删除唯一约束 | 删除 `unique` | 自动删除约束/索引 | -| 普通索引改唯一 | `index` 改为 `unique` | 先验证无重复 | -| 唯一索引改普通 | `unique` 改为 `index` | 自动放宽 | -| 增加外键/修改关联目标 | 改为 `.id` | 验证无孤儿记录;失败时要求 migrate | -| 删除外键 | 改为普通字段类型或删除关联 | 自动删除约束;字段数据保留 | -| 修改外键删除行为 | 第一轮使用命名 migrate | 默认 RESTRICT;通用关系选项语法后续设计 | -| choice 增加变体 | 增加变体 | 自动放宽 CHECK | -| choice 修改显示名称 | 修改右侧文本 | 无 schema 迁移,存储值不变 | -| choice 删除稳定变体 | 删除变体 | 验证没有旧值;否则要求 migrate 映射 | -| choice 稳定变体改名 | 第一轮使用命名 migrate | 显式更新已有存储值并重建 CHECK | -| 删除字段 | 从 record 删除并写命名 migrate | 必须显式确认 drop;关联约束和索引按依赖顺序删除 | -| 删除表 | 删除 Model 并写命名 migrate | 必须显式确认,禁止仅因文件消失自动删表 | -| 表/Model 重命名 | 第一轮使用命名 migrate | 显式执行表 rename 并更新 schema identity | -| 字段拆分 | 当前字段 + 命名 migrate | migrate 负责回填多个目标字段 | -| 字段合并 | 当前字段 + 命名 migrate | migrate 负责合并与冲突规则 | -| 主键策略或主键类型变化 | 命名 migrate | 重建引用关系,首轮不自动处理 | -| generated 策略变化 | 直接修改声明并按需 migrate | 只影响新值时自动;需要改已有值时 migrate | -| Seed 新增记录 | 修改 `seed` | 按唯一键只插入缺失记录 | -| Seed 修改/删除已有记录 | 命名 migrate | Seed 不覆盖或删除线上数据 | -| 字段声明顺序变化 | 调整源码顺序 | 不改变已有数据库列顺序,不产生迁移 | -| 注释、标签、自定义方法变化 | 直接修改源码 | 不产生数据库迁移 | - -## 长度修改示例 - -```dever -type User { - display_name: Text(128) from nickname -} -``` - -如果旧字段是 `nickname: Text(64)`,规划顺序是先 rename,再把最大长度放宽到 128。全新数据库只创建 `display_name` 的最终定义。 - -收窄时仍只修改目标类型: - -```dever -type User { - display_name: Text(32) from nickname -} -``` - -ORM 先验证已有值都不超过 32 个 Unicode codepoint。全部满足就应用约束;存在超长值则整个迁移失败,不做自动截断。开发者必须通过命名 migrate 明确选择截断、拒绝、归档或其它业务规则。 - -## 方言执行边界 - -- PostgreSQL 原生支持 rename、类型变更、默认值、可空性和约束变更;类型变更可以使用 `USING` 表达式。 -- SQLite 直接 ALTER 能力较少。不能原地完成的同一逻辑变化由 dialect 在事务中创建目标临时表、复制转换后的数据、替换旧表并重建索引/约束。 -- 两个方言必须得到相同的规范化目标 schema 和 revision;底层是否重建表不能泄漏到 Dever Model 语法。 -- Dever 不使用静默截断、自动填充猜测、名称相似度推断或数据库特有隐式类型转换。 - -## 不属于首轮通用 Model 的数据库管理能力 - -分区表、表空间、存储参数、物化视图、触发器、行级安全策略、数据库专有索引方法和在线无锁迁移不进入首轮跨数据库 Model 协议。这些能力需要 PostgreSQL 专有扩展或显式原生迁移,不能伪装成 SQLite/PostgreSQL 通用行为。 diff --git a/.trellis/tasks/09-13-typed-orm/task.json b/.trellis/tasks/09-13-typed-orm/task.json deleted file mode 100644 index ae2cb7a..0000000 --- a/.trellis/tasks/09-13-typed-orm/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "typed-orm", - "name": "typed-orm", - "title": "Typed ORM for SQLite and PostgreSQL", - "description": "为 Dever 增加隐式挂起与错误传播基础、一文件 Model、数据库无关查询计划,以及 SQLite/PostgreSQL 的类型安全 ORM、事务和迁移能力。", - "status": "completed", - "dev_type": null, - "scope": "implicit suspension/error contracts + compiler model/query/transaction contracts + runtime config/orm/sqlite/postgres/log foundations + focused database and memory fixtures", - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-13", - "completedAt": "2026-09-17", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-04-dever-language-mvp", - "relatedFiles": [], - "notes": "", - "meta": {} -} diff --git a/.trellis/tasks/09-19-application-testing/check.jsonl b/.trellis/tasks/09-19-application-testing/check.jsonl deleted file mode 100644 index 838d423..0000000 --- a/.trellis/tasks/09-19-application-testing/check.jsonl +++ /dev/null @@ -1,8 +0,0 @@ -{"file": ".trellis/tasks/09-19-application-testing/prd.md", "reason": "逐项核对应用测试验收标准"} -{"file": ".trellis/tasks/09-19-application-testing/design.md", "reason": "核对实现未偏离最终架构与隔离边界"} -{"file": ".trellis/tasks/09-19-application-testing/implement.md", "reason": "核对分阶段交付与允许执行的验证"} -{"file": ".trellis/spec/backend/compiler-contracts.md", "reason": "检查语言合同和生产编译路径无回归"} -{"file": ".trellis/spec/backend/error-handling.md", "reason": "检查诊断与测试失败报告"} -{"file": ".trellis/spec/backend/quality-guidelines.md", "reason": "检查重复、职责和定向覆盖"} -{"file": ".trellis/spec/backend/database-guidelines.md", "reason": "检查临时 SQLite 隔离且不触达正式数据库"} -{"file": ".trellis/spec/guides/cross-layer-thinking-guide.md", "reason": "检查源码到 CLI/runtime 的跨层闭环"} diff --git a/.trellis/tasks/09-19-application-testing/design.md b/.trellis/tasks/09-19-application-testing/design.md deleted file mode 100644 index e50a041..0000000 --- a/.trellis/tasks/09-19-application-testing/design.md +++ /dev/null @@ -1,143 +0,0 @@ -# Dever 应用测试体系技术设计 - -## Architecture - -```text -module/ + test/ - -> one SourceMap with compiler-assigned Application/Test origins - -> existing parser and Markdown extraction - -> existing declaration registration and semantic checker - -> Test layout/access rules - -> filename-matched TestCase metadata - -> test-only assert/assert_eq lowering - -> checked Program - -> one native suite containing every checked TestCase specialization - -> case-id dispatch into one isolated native process + temporary project directory per case - -> captured result + deterministic CLI summary -``` - -There is no test interpreter, dynamic test registry, source macro, runtime reflection or production test symbol. Test behavior is a thin compiler-owned entry mode over the same checked Program and native backend. - -## Source Ownership And Identity - -`SourceFile` gains a compiler-assigned source origin rather than inferring test authority from a user-controlled path. Production loading remains the current `SourceMap::load(module_root)` behavior. A dedicated project-test loader loads `module/` as application sources and an existing `test/` as test sources; a missing test root is an empty set, while a non-directory or unreadable root is an explicit load error. - -Test sources retain two paths: - -- display path: `test/user/account/register.dever`, used by diagnostics and CLI output; -- logical path: `user/account/register.dever`, used for package identity and Markdown package documentation. - -The new `SourceLayout::Test { component, domain, topic }` is valid only for exactly three logical segments. It applies existing lower-snake-case and generic-bucket rules. `.dever` and `.dever.md` with the same logical stem are one duplicate test identity. - -The checker cache identity includes source origin/logical path so a strict application source and a test source with equal bytes cannot share the wrong checked result. - -## Test Entry Contract - -For `test/user/account/register.dever`, the logical package is `user.account.register`; the checker selects its only ordinary `register() ()` function and records a `TestCase` containing: - -- stable public identity `user/account/register`; -- checked private function id; -- source span and whether its reachable graph uses a Model. - -Other declarations stay private to the same test file. A same-name overload, transaction/recovery entry, parameters or outputs are rejected before native compilation. Test functions are never marked public and never enter API/model snapshots. - -`Program` exposes read-only test metadata to the CLI. Native compilation accepts an already checked test-case id through a dedicated method instead of weakening `Program::entry` or making test functions public. - -## Visibility - -Test resolution extends the existing role-aware symbol owner rather than adding a parallel resolver: - -- same file: private helper functions/types; -- same domain: App and Domain functions/types; -- other domains: App public surface only; -- Model values/types: readable under existing public/type rules; -- Model operations: still rejected because only the owning App role may issue CRUD; -- Adapter, Port, API and other Test owners: not callable. - -All production callers reject Test targets before ordinary same-domain checks, preventing reverse dependencies. Test assertions are available only while checking a Test owner. - -## Assertions - -`assert` and `assert_eq` are compiler-owned test intrinsics, not bundled library functions. They reuse the existing `Intrinsic` expression shape so dependency, effect, liveness and native traversal do not gain a second assertion IR hierarchy. - -- `assert(value)` checks one `Bool` expression. -- `assert_eq(actual, expected)` checks the left expression first, uses its exact type as the right-hand expectation, and requires the existing `Type::comparable` contract. -- both return Unit and are legal only as ordinary zero-output actions in Test-owned functions; -- declarations named `assert` or `assert_eq` remain ordinary outside tests and are reserved inside a test file. - -Native emission evaluates each operand once and preserves source order. On failure it creates a source-located assertion error. `assert_eq` renders concrete typed values through the existing `Render` implementations; generated records/choices retain their source-shaped renderer. No generic runtime `Value`, serialization round-trip or reflection is introduced. - -## Native Execution And Reporting - -The CLI checks the combined source set once, sorts `TestCase` metadata, then compiles one native test suite and runs each case serially. The suite unions the existing specialization graphs and dispatches one checked private entry by its stable sorted case index. It does not introduce a dynamic function registry or runtime reflection. - -Every case still starts a fresh process from the same immutable suite executable. The runner stages that executable beside a new temporary project for each process, so runtime singletons, generated SQLite settings, Model initialization and data remain isolated without an in-process reset protocol. A suite that contains any database test links the SQLite-capable runtime once; only a selected database branch loads its generated setting and initializes Models. A non-database branch does neither. - -Native cache identity continues to cover generated code, compiler identity, runtime bytes, toolchain, platform, environment and compiler options. Tests use a dedicated fast compilation profile because they validate behavior rather than production code generation performance; `run` and `build` retain the production optimization contract. - -For each case the runner: - -1. creates an owned temporary project directory; -2. reuses the single compiled suite and selects the checked private test entry by internal case index; -3. stages the executable in that directory; -4. writes a generated `config/setting.json` only when the reachable graph uses Model operations; -5. runs the executable with the temporary project as its executable/config root; -6. captures stdout/stderr and records pass/failure; -7. drops all owned native and runtime artifacts before continuing. - -Successful process output is captured and omitted from runner status. Failed output is printed in clearly labelled blocks below the case result. A source/check failure prevents all execution; a per-case compile/start/run/assert/business/fault failure is recorded and later cases continue. The final exit status is nonzero when any case failed or was not run. - -The first release has no child timeout or signal manager. Explicit cancellation may terminate the command; recoverable success/failure paths own deterministic cleanup. - -## SQLite Isolation - -The runner never loads the project's deployment database configuration for tests. If no test graph has a database effect, the suite uses the base runtime profile. A mixed suite links the SQLite-capable runtime once, but a selected non-database case writes no setting file and does not call database bootstrap or Model initialization. - -If the graph has a database effect, the runner generates a temporary setting with: - -- `database.default` as SQLite; -- one SQLite entry for each explicit Model connection name; -- paths below that case's `data/db/`; -- one connection and the existing bounded page defaults. - -Package-root selectors retain runtime resolution semantics: an undeclared root falls back to `default`; explicit selectors retain separate connections. The generated settings are parsed by `dever_runtime::config::Settings`, validated by `Program::validate_database_settings`, and consumed by the normal bootstrap, schema migration, Seed, transaction and shutdown code. No test-only database handle reaches Dever source. - -The emitter currently initializes the application's complete Model schema once a reachable test uses the database. This preserves foreign keys, migrations and Seed as an application-wide contract. A non-database test uses no database profile even when unrelated Models exist in the module. - -## CLI And Formatting - -`Action::Test` is added to the existing explicit CLI argument parser; there is no generic subcommand framework. The command performs semantic checking, normal warnings and API baseline validation before execution. - -Formatting remains syntax-only. `fmt` discovers both source roots, prepares every replacement before committing any, validates both snapshots again, then performs atomic per-file renames. A missing `test/` contributes no files. This prevents module files from changing when a test Markdown contract or file permission fails. - -Human output follows one stable shape: - -```text -running 2 tests -test news/article/publish ... ok -test user/account/register ... FAILED - -test result: FAILED. 1 passed; 1 failed; 0 not run -``` - -No JSON/JUnit output or test filter is introduced. - -## Markdown And CMS - -Test Markdown uses the existing strict document contract. Its package metadata names the logical package (for example `user.account.register`), and its function section documents the filename-matched entry. No test-specific Markdown headings are added. - -The maintained CMS Dever and Markdown projects receive equivalent application tests. They call existing App boundaries and assert observable business values and Model counts. They do not add test-only production App functions or duplicate CRUD. - -## Compatibility And Trade-offs - -- Production `check/api/run/build` continue loading only `module/`; their checked Program and native cache inputs remain unchanged. -- `fmt` intentionally expands to the optional test root because tests are first-class Dever source. -- One suite link removes per-case native compilation. Process-per-case dispatch retains runtime/database isolation, while the suite may be larger than one reachability-pruned test binary. -- Real PostgreSQL application tests are deferred. Adding them later requires an explicit safe test connection and cleanup contract; it must not alter default SQLite behavior. -- There are no fixture hooks or shared test modules. A later addition must prove that it does not introduce hidden order or shared mutable state. - -## Cleanup And Rollback - -All test execution artifacts are owned by RAII temporary-directory and native-program guards. Cleanup errors do not replace the primary test result. No project source, deployment setting or data path is rewritten by `dever test`. - -The change is additive. Rollback removes the Test source origin/layout, assertion lowering, CLI action and example tests; no production source migration or database migration is required. diff --git a/.trellis/tasks/09-19-application-testing/implement.jsonl b/.trellis/tasks/09-19-application-testing/implement.jsonl deleted file mode 100644 index 6861dfb..0000000 --- a/.trellis/tasks/09-19-application-testing/implement.jsonl +++ /dev/null @@ -1,11 +0,0 @@ -{"file": ".trellis/tasks/09-19-application-testing/prd.md", "reason": "当前应用测试需求、边界与验收标准"} -{"file": ".trellis/tasks/09-19-application-testing/design.md", "reason": "已收口的编译器与运行器技术设计"} -{"file": ".trellis/tasks/09-19-application-testing/implement.md", "reason": "分阶段实施与最小验证清单"} -{"file": ".trellis/spec/backend/compiler-contracts.md", "reason": "保持语言、检查器、HIR 与原生后端单一路径合同"} -{"file": ".trellis/spec/backend/directory-structure.md", "reason": "约束源码目录、crate 与测试文件归属"} -{"file": ".trellis/spec/backend/error-handling.md", "reason": "约束源码诊断、运行失败与错误传播"} -{"file": ".trellis/spec/backend/quality-guidelines.md", "reason": "约束复用、复杂度与回归测试质量"} -{"file": ".trellis/spec/backend/toolchain-and-library.md", "reason": "约束 Rust 工具链、依赖与定向命令"} -{"file": ".trellis/spec/backend/database-guidelines.md", "reason": "约束 Model、SQLite 隔离与 PostgreSQL 边界"} -{"file": ".trellis/spec/guides/code-reuse-thinking-guide.md", "reason": "避免测试路径形成平行 parser/checker/runtime"} -{"file": ".trellis/spec/guides/cross-layer-thinking-guide.md", "reason": "核对 CLI 到 checker/native/runtime 的完整数据流"} diff --git a/.trellis/tasks/09-19-application-testing/implement.md b/.trellis/tasks/09-19-application-testing/implement.md deleted file mode 100644 index a498d61..0000000 --- a/.trellis/tasks/09-19-application-testing/implement.md +++ /dev/null @@ -1,123 +0,0 @@ -# Dever 应用测试体系实施清单 - -## Start Gate - -- [x] 用户在最终规划摘要之后明确批准实施。 -- [x] 运行 `python3 ./.trellis/scripts/task.py start 09-19-application-testing`,确认任务进入 `in_progress`。 -- [x] 重新加载 `trellis-before-dev`,核对当前 PRD、设计、执行清单和 backend specs。 -- [x] 开工前记录实际 git/worktree 状态,只处理本任务拥有的文件,不清理用户已有改动。 - -## Phase 1: Test Source Layout And Static Contract - -- [x] 在 `source.rs` 增加编译器赋予的 Test 来源、显示/逻辑路径和组合项目加载;保持现有生产 `SourceMap::load` 合同。 -- [x] 在 layout/parser/checker 中加入严格的 `//` Test 布局,不增加源码关键字或第二套 parser。 -- [x] 在检查结果中建立按身份排序的 `TestCase`,强制同名 ordinary 零输入零输出入口和文件内私有辅助声明。 -- [x] 扩展 role-aware function/type resolution:同领域 App+Domain、跨领域 App、禁止 Model CRUD/Adapter/Port/API/其他测试。 -- [x] 把来源/逻辑路径加入 check cache identity,防止 Test 与普通 strict source 误复用。 -- [x] 增加路径、入口、重复身份和可见性的定向正反测试。 - -## Phase 2: Assertions And Native Entry - -- [x] 复用 `Intrinsic` HIR 形状加入仅 Test owner 可构造的 `assert`/`assert_eq`,保持普通同名业务函数语义不变。 -- [x] `assert` 强制 Bool;`assert_eq` 强制相同 comparable 类型并保持左右各求值一次、源顺序不变。 -- [x] 在 native emitter 生成源码定位的 assertion failure,复用现有 `Render` 输出 actual/expected。 -- [x] 增加从 checked `TestCase` 编译私有入口的 native API,不放宽生产 `Program::entry` 的公开性要求。 -- [x] 验证标量、record、choice、nullable、List、Map、MapEntry、Model ID,以及不可比较/类型不匹配/生产源码调用断言的拒绝。 - -## Phase 3: CLI Runner And Isolation - -- [x] 在 CLI 增加 `test `,复用现有 module 检查、warning 和 API baseline 路径。 -- [x] 建立单一 `test_runner` owner,负责排序、单套件 compile、逐用例独立进程、输出捕获、状态汇总和临时目录生命周期;不创建通用 runner/framework 层。 -- [x] 无测试时输出 `0 tests` 成功;源码检查失败时零执行;单用例失败后继续后续用例。 -- [x] 对无数据库 effect 的用例使用 base profile,不读写 setting。 -- [x] 对有数据库 effect 的用例生成临时 SQLite setting,复用正式 Settings 校验、Model schema/Seed/transaction/shutdown。 -- [x] 每用例使用独立临时项目和数据库;确认项目 `config/setting.json`、`data/` 与环境变量不参与数据库选择。 -- [x] 失败时分区展示捕获的 stdout/stderr,runner 状态行不与测试输出混合。 -- [x] 覆盖编译失败、启动失败错误映射、断言失败、未捕获业务失败、runtime fault 和清理。 - -## Phase 4: Formatter And Maintained CMS - -- [x] 调整 CLI formatter,使 module/test 两个可选源码集合先完整诊断和 prepare,再统一 commit;任一失败时零改写。 -- [x] 为 CMS Dever 项目增加 `test///.dever` 业务用例。 -- [x] 为 CMS Markdown 项目增加相同路径、入口和合同的 `.dever.md` 用例,遵守现有 Markdown 文档协议。 -- [x] 删除 CMS CLI 回归中被正式应用测试替代的临时 probe 源码注入,仅保留仍验证 build/package 的独立职责。 -- [x] 更新 `LANGUAGE.md`、`MARKDOWN-SYNTAX.md`、根 README 和 examples README 的正式测试合同与命令。 - -## Phase 5: Refactor And Verification - -- [x] 检查 SourceMap 双根加载、test metadata、assert lowering、runner 报告和 temp ownership 是否存在重复 owner 或平行逻辑。 -- [x] 搜索并删除调试输出、过渡 API、无用 helper、死分支、临时测试文件和过期 CMS probe。 -- [x] 确认生产 source set、API snapshot、main entry、native cache、runtime profile 与无测试项目行为不变。 -- [x] 检查磁盘空间后再运行会链接原生程序的定向测试;不运行 workspace 全量测试、真实 PostgreSQL 或性能压测。 - -## Verification Record - -- `cargo check --offline -p dever-core --features reference -p dever-cli -p dever-tests --test application_testing`:通过。 -- `application_testing`:8/8 通过;包含 plain/Markdown 发现、可见性、类型、`result(call)`、复合断言、源码位置及含未引用 Model 的 base profile。 -- `formatter`:12/12 通过;module/test 统一 prepare 和只读失败零改写通过;两套 CMS `fmt --check` 通过。 -- `source_architecture`:8/8 通过;`markdown_source`:20/20 通过。 -- `source_visibility`:10/10 通过;`contract_execution`:9/9 通过;`api_routes`(`api` feature):7/7 通过。 -- `cms_project_checks_runs_and_builds_from_an_isolated_copy`:通过;Dever/Markdown 各连续测试两次,部署 setting 被替换为非法 JSON 时测试仍为 2/2,通过后 check/run/build/打包程序仍通过,且无效 test 源码不进入生产命令。 -- CLI 零测试、失败继续/输出分区、成功/失败临时目录清理:分别通过;`RUSTC=/bin/false` 定向故障注入确认两个编译失败均汇总且零临时残留。 -- 未捕获业务失败和动态数值 fault 的既有原生定向用例:通过。 -- `git diff --check` 和变更文件尾随空白扫描:通过;CLI 默认依赖仅启用 `dever-core` default feature,不含 reference。 -- `rustfmt`、`clippy` 组件未安装,未运行;未运行 workspace 全量测试、真实 PostgreSQL、性能/内存压测或持久服务。 - -## Phase 6: Test Suite Compilation Performance - -- [x] 在 native owner 中生成一个包含全部 checked TestCase specialization 的测试套件,不增加解释器或动态注册表。 -- [x] 复用 native 构建缓存并使用测试专用快速编译参数;生产 `run/build` 优化参数保持不变。 -- [x] CLI 只编译一次套件,按稳定用例编号逐个启动独立进程并保留失败继续、输出捕获和临时目录清理。 -- [x] 混合数据库/非数据库套件仅在数据库分支加载临时 SQLite 配置并初始化 Model。 -- [x] 增加多入口分派、一次编译、缓存命中、配置隔离和失败继续的定向回归。 -- [x] 记录 CMS 冷/暖执行耗时和峰值 RSS;不把本机数据外推为生产性能。 - -### Phase 6 Verification Record - -- `cargo check --offline -p dever-core -p dever-cli -p dever-tests --test application_testing --test native_cache`:通过。 -- `application_testing`:8/8 通过;一个 native suite artifact 按两个稳定编号执行成功/失败入口,并确认第二次编译命中 native cache。 -- `native_cache`:6/6 通过,另有 1 个既有显式 ignored;runtime 内容变化、工具链/参数变化、并发发布、损坏产物拒绝、原始快照与元数据摘要备忘均通过。 -- CLI 定向回归:混合数据库/非数据库套件 3/3 通过;失败后继续与 stdout/stderr 捕获通过;零测试不调用编译并成功;套件编译失败时 2/2 用例统一标记失败并清理临时目录。 -- 普通单入口 native hello 定向用例通过,确认 `run/build` 共用的生产发射路径未被套件抽取破坏。 -- CMS Dever 实际 `deverc test`:2/2 通过。稳定 runtime 下首次单套件链接为 21.37 秒、峰值 346068 KiB;随后内容缓存命中为 1.79 秒、峰值 54132 KiB。优化前同项目为 119.40 秒、594772 KiB。 -- 在 Cargo 测试环境的绝对 `RUSTC` 与普通 PATH `rustc` 之间切换会触发 Cargo 重建 native runtime;一次 75.56 秒、594976 KiB 的观测包含该重建,不作为测试套件链接基线。 -- runtime 摘要目录只保留当前元数据身份;`/tmp` 无 `dever-application-test-*`、`dever-build-*` 或 `dever-cms-project-*` 残留,CMS 示例无数据库或测试可执行文件残留。 -- `git diff --check` 与变更文件尾随空白扫描通过。`rustfmt`、`clippy` 组件仍未安装;未运行 workspace 全量测试、真实 PostgreSQL、64/128 MiB/cgroup 压测或持久服务。 - -## Focused Validation - -允许且计划执行的最小检查: - -```bash -cargo check --offline -p dever-core -p dever-cli -cargo test --offline -p dever-tests --test application_testing -cargo test --offline -p dever-tests --test source_architecture -cargo test --offline -p dever-tests --test markdown_source -cargo test --offline -p dever-cli --test cms_project -git diff --check -``` - -如 `rustfmt`/`clippy` 组件可用,再执行: - -```bash -cargo fmt --all -- --check -cargo clippy --offline -p dever-core -p dever-runtime -p dever-cli -p dever-tests --test application_testing -- -D warnings -``` - -不运行: - -- workspace 全量测试; -- `cargo build` 或应用全量发布构建; -- 真实 PostgreSQL; -- 64/128 MiB、cgroup 或吞吐压测; -- 持久 HTTP/网络服务。 - -## High-risk Files And Review Points - -- `crates/dever-core/src/source.rs`、`check.rs`、`check/layout.rs`、`check/symbols.rs`:来源身份和可见性不能泄漏到生产。 -- `crates/dever-core/src/check/expressions.rs`、`intrinsic.rs`、`native.rs`、`native/intrinsics.rs`、`native/records.rs`:断言必须静态类型化、单次求值并保留源码位置。 -- `crates/dever-core/src/native/build.rs`、`model.rs`:私有测试入口不能放宽生产 entry,SQLite profile 必须来自测试生成配置。 -- `crates/dever-cli/src/main.rs`、`format.rs`、新增 runner:临时目录、输出捕获、失败继续和格式化原子性。 -- `examples/cms/{dever,md}`:两套测试合同必须同步,不给生产 App 增加测试专用能力。 - -任何实现如果需要 Test 关键字、共享动态值、生产公开测试函数、环境变量数据库配置或真实 PostgreSQL,均视为超出当前设计,回到 planning 复核。 diff --git a/.trellis/tasks/09-19-application-testing/prd.md b/.trellis/tasks/09-19-application-testing/prd.md deleted file mode 100644 index 44c11d5..0000000 --- a/.trellis/tasks/09-19-application-testing/prd.md +++ /dev/null @@ -1,101 +0,0 @@ -# Dever 应用测试体系 - -## Goal - -让 Dever 应用可以用 Dever 源码编写和运行确定性的领域回归测试,使 AI 修改 App、Domain 或 Model 后能够验证业务合同,而不依赖 Rust 宿主测试、HTTP 接口或正式数据库。 - -测试是可选能力。没有测试的项目保持现有开发和运行方式;测试能力不得引入第二套解释器、生产可见测试入口或环境变量配置。 - -## Background - -- 当前 CLI 只有 `check`、`api`、`fmt`、`run` 和 `build`,应用自身没有测试命令。 -- 编译器仓库已有 Rust 回归测试,但它们验证编译器实现,不能表达具体 Dever 应用的业务合同。 -- 生产源码从 `module/` 加载,`main.main` 是 `run/build` 的唯一启动入口;App 是跨领域能力边界,Domain、Model、Port、Adapter 和 API 是领域实现边界。 -- parser、checker、HIR、原生后端、源码位置、错误传播、Model 迁移和 Seed 已有单一正式路径,应由测试复用。 -- ORM 的真实 PostgreSQL 验收已经由独立编译器测试覆盖,不属于首版应用测试命令。 - -## Requirements - -### Source And Discovery - -- 应用测试固定放在项目根 `test/`,与 `module/` 生产源码分离。 -- 测试路径必须是 `test///.dever` 或 `test///.dever.md`,不支持更深层级。 -- 每个测试文件由文件名选择同名普通函数作为唯一入口。例如 `test/user/account/register.dever` 执行其中的 `register() ()`。 -- 测试入口必须是零输入、零输出的 ordinary 函数。缺少同名函数、同名入口签名错误或重复测试身份必须在执行前产生源码诊断。 -- 测试文件中的其他函数和类型只属于该文件,不自动执行,也不能被其他测试文件或生产源码调用。 -- 不增加 `test` 关键字、`test_` 前缀、每文件 `main()`、package/expose 声明或顶层可执行语句。 -- `dever test ` 同时加载生产源码和测试源码,并在运行任何用例前完成全部语法、名称、类型、分句、effect、失败义务和架构检查。 -- 发现顺序按测试身份稳定排序,不依赖文件系统遍历顺序。 -- 项目没有 `test/` 或目录为空时,合法项目执行 `dever test` 输出 `0 tests` 并成功退出。 -- `check/api/run/build` 不加载测试源码。测试声明不进入生产二进制、API 快照或 HTTP 路由。 -- `fmt` 作为源码工具应同时格式化 `module/` 和存在的 `test/`,保持两者统一的 `.dever`/`.dever.md` 格式合同;任一源码失败时不得部分改写。 - -### Architecture And Visibility - -- 测试文件是所属 `/` 的测试友元,可以调用同领域 App 和 Domain。 -- 跨领域调用只能经过目标 App。 -- 测试可以读取 App 返回的 Model 值和同领域类型,但不能直接调用 Model CRUD、Adapter、Port 或 API。 -- 生产 App、Domain 和其他测试文件都不能反向调用测试函数或访问测试私有类型。 -- 测试不能声明 Model、HTTP 路由或生产 App 能力。 -- 测试文件必须表达一个内聚业务场景;不建立 `common`、`shared`、`utils`、`helper`、全局 fixture 等测试垃圾桶。 - -### Assertions And Failures - -- 首版只提供测试源码专用的 `assert(condition)` 和 `assert_eq(actual, expected)`。 -- `assert` 只接受 `Bool`。`assert_eq` 要求两侧是相同且可比较的类型,不做数值提升、字符串求值或运行时反射。 -- `assert_eq` 复用现有比较与渲染合同,支持标量、record、choice、可空值、List、Map、MapEntry 和 Model ID;失败报告测试身份、源码位置、实际值和期望值。 -- 不增加 `assert_true`、`assert_false`、`assert_not_equal`、`assert_null`、异常断言或自定义 matcher。 -- 业务失败继续使用现有 `result(call)` 和 choice 分句验证;不增加 `try/catch/throws`。 -- 测试成功表示入口正常完成;断言失败、未捕获业务失败或程序 fault 表示该用例失败。 -- 一个用例失败后继续运行其余独立用例,最终汇总通过、失败和未运行数量,并以非零状态结束。 - -### Isolation And Lifecycle - -- 首版没有 `before/after`、全局 setup、共享 fixture、用例排序依赖或测试间共享状态。 -- 每个测试文件在独立原生进程和独立临时项目目录中运行。 -- 不触达 Model 的测试不初始化数据库。 -- 触达 Model 的测试由运行器生成每用例独立的临时 SQLite 配置,走正式配置解析、迁移、Seed、事务、连接池和 shutdown 路径。 -- 测试运行器不读取、复制或连接项目正式数据库 URL;不使用环境变量或命令行数据库覆盖。 -- 临时数据库、数据目录、配置、可执行文件和运行产物在成功或失败后由运行器清理,不写入项目 `data/`。 -- 首版不使用外层事务回滚代替隔离,因为这会改变被测 App 的真实提交和回滚语义。 -- 测试按稳定顺序串行运行;并行、随机顺序、重试和自动超时不属于首版。 - -### CLI And Reporting - -- 新增正式命令 `dever test `;当前开发二进制对应 `deverc test `。 -- 默认输出简洁的人类可读状态和最终汇总。测试进程 stdout/stderr 被捕获,不得冒充 runner 状态;失败时按独立区块展示。 -- 源码诊断、原生编译失败、进程启动失败、断言失败、业务失败和 runtime fault 保留各自可辨认的信息。 -- 测试复用与 `run/build` 相同的原生后端、runtime feature 裁剪、源码位置和构建缓存,不链接 reference evaluator。 -- 首版不增加测试名过滤、机器报告格式或新的数据库配置结构。 - -### Maintained Example - -- CMS 的 Dever 与 Markdown 项目各自增加等价测试,验证账户规范化、Model 写入/Seed 和文章发布等现有 App 合同。 -- 两套测试使用相同路径、入口名称和断言,只因源码容器格式不同而不同。 -- 旧 `examples/old/` 不迁移为应用测试模板。 - -## Acceptance Criteria - -- [x] `.dever` 与 `.dever.md` 测试均能按 `//` 稳定发现,文件名选择同名零输入、零输出函数。 -- [x] 非法路径、缺失/错误入口、重复身份、测试跨域越权、直接 Model/API 调用和生产源码反向访问测试均在执行前被拒绝并定位源码。 -- [x] `assert` 和 `assert_eq` 有正反类型检查;相等失败包含测试身份、原源码位置、实际值和期望值。 -- [x] 测试可以通过 `result(call)` 验证业务失败;未捕获业务失败、断言失败和 runtime fault 均使当前用例失败而不阻止后续用例。 -- [x] 无 `test/` 的合法项目执行 `dever test` 报告 `0 tests` 并成功;非法生产源码仍被拒绝。 -- [x] 纯非数据库套件使用 base runtime;混合套件的非数据库用例不读取配置或初始化数据库;使用 Model 的两个测试各自执行迁移和 Seed,写入互不影响,顺序互换结果不变。 -- [x] 测试不读取正式 `setting.json` 的数据库 URL,不连接 PostgreSQL,不在项目 `data/` 或源码目录留下临时文件。 -- [x] 测试进程成功和失败后均清理临时配置、SQLite 文件、可执行文件和 native 临时目录。 -- [x] `check/api/run/build` 的源码集合、API 快照、CMS 运行结果和生产产物不因存在 `test/` 而变化。 -- [x] `fmt` 对 module/test 的变更采用同一次准备后提交;任一格式诊断或准备失败时两处源码均保持原样。 -- [x] CMS Dever/Markdown 测试覆盖相同业务合同并由 `dever test` 通过。 -- [x] 同一项目连续运行两次时测试顺序和汇总一致,生成测试产物不链接 reference evaluator。 -- [x] 一次 `dever test` 只生成和编译一个测试套件程序;每个用例仍在独立子进程和临时项目中运行。 -- [x] 测试套件复用 native 内容寻址缓存;未改变有效生成代码时再次运行不调用 rustc 编译测试程序。 -- [x] 混合数据库/非数据库用例时,只有数据库用例进程读取运行器生成的 SQLite 配置并初始化 Model;非数据库用例不读取配置或初始化数据库。 - -## Out Of Scope - -- 真实 PostgreSQL 应用测试配置、schema 管理和外部数据库清理;继续由现有 `postgres_orm` 专项验收负责。 -- 自动 `before/after`、共享 fixture 文件、mock/stub、Port/Adapter 替身和依赖注入协议。 -- 测试筛选、watch、并行、随机顺序、重试、自动超时、覆盖率、快照、属性测试和模糊测试。 -- 浏览器/UI、HTTP 录制回放、外部服务沙箱和机器可读报告。 -- API 新设计、本体、智能体、package registry、跨平台发行和编译器自举。 diff --git a/.trellis/tasks/09-19-application-testing/task.json b/.trellis/tasks/09-19-application-testing/task.json deleted file mode 100644 index 7a5e057..0000000 --- a/.trellis/tasks/09-19-application-testing/task.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "id": "application-testing", - "name": "application-testing", - "title": "Dever 应用测试体系", - "description": "为 Dever 应用建立根 test 目录、dever test 命令、类型安全断言、隔离 fixture 与可重复执行合同", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-19", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-04-dever-language-mvp", - "relatedFiles": [], - "notes": "", - "meta": { - "execution_mode": "inline" - } -} \ No newline at end of file diff --git a/.trellis/tasks/09-20-durable-jobs/check.jsonl b/.trellis/tasks/09-20-durable-jobs/check.jsonl deleted file mode 100644 index eff2287..0000000 --- a/.trellis/tasks/09-20-durable-jobs/check.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused runtime/database/process checks"} -{"file":".trellis/spec/backend/error-handling.md","reason":"Retry, dead-letter and cancellation error behavior"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"Job owner separation and no parallel queue implementation"} -{"file": ".trellis/tasks/09-20-durable-jobs/research/implementation-map.md", "reason": "Verify corrected transaction, lease, cron and shutdown contracts"} -{"file": ".trellis/spec/backend/compiler-contracts.md", "reason": "Verify language and native emitter contract parity"} -{"file": ".trellis/spec/backend/database-guidelines.md", "reason": "Verify transaction and lease correctness"} diff --git a/.trellis/tasks/09-20-durable-jobs/design.md b/.trellis/tasks/09-20-durable-jobs/design.md deleted file mode 100644 index bdeacdb..0000000 --- a/.trellis/tasks/09-20-durable-jobs/design.md +++ /dev/null @@ -1,100 +0,0 @@ -# Dever 持久化 Job 设计 - -## Source Contract - -Job role 使用 `job.dever` 或平铺的 `job/*.dever`,继续遵守角色文件与目录互斥、单 topic 必须合并的规则。Job 只是持久任务入口,不是可调用的普通函数: - -```dever -database default - -job publish_due(input: app.PublishInput) () retry(5) timeout(30000) { - app.publish_due(input.article_id) -} - -job cleanup_sessions() () retry(3) timeout(30000) { - app.cleanup_expired() -} - -schedule cleanup_sessions = "0 * * * *" -``` - -Payload record 由同领域 App 声明为公开契约,Job 不新增第二套 DTO 可见性。Job 只能有零个输入,或一个 wire-safe record 输入;输出必须为空;`retry(n)` 表示包含首次执行在内最多执行 `n` 次。`timeout(ms)` 和 `retry` 都是必填、有硬上限的正整数。 - -共享 wire schema 增加 nominal ModelId 节点。编码仍使用既有 ModelId 数值表示,但 fingerprint 包含所属 Model identity,不能把两个 Model 的 id 降级为同一种 Int/Id。Job payload 仍拒绝 Secret、private Model data、Choice、handler 和不稳定类型。 - -App 通过 compiler-owned 静态 target 入队: - -```dever -id = dever.job.enqueue(job.publish_due, input, key) -id = dever.job.enqueue_at(job.publish_due, input, key, run_at) -id = dever.job.enqueue(job.cleanup_sessions, key) -id = dever.job.enqueue_at(job.cleanup_sessions, key, run_at) -``` - -Target 不是普通值,不能存储、转发或用于普通 call/run/group。enqueue 使用专用 HIR,不把 Job handler 加入同步调用/effect/递归图;Job handler 作为 worker 独立 root 生成并检查。 - -## Effect And Transaction Integration - -Model 和 Job 都映射到一个统一 database binding。effect 系统记录有类型的 database owner,并通过唯一 accessor 解析为现有 `ConnectionSelector`;Model CRUD 仍保留 Model schema owner,不制造虚假 Model,也不增加第二套 transaction context。 - -enqueue 只传播队列连接的 database/suspension/failure effect,不同步传播 Job handler 的 Model、Port 或业务 failure。transaction App 的 enqueue 使用现有隐藏 `_database: Option<&Transaction>` 和 `Executor::new`,与同连接 Model 写入共享物理 transaction;无 ambient transaction 时开启并提交短 transaction。显式不同连接在语义检查拒绝,依赖 default/package fallback 的冲突在 settings-aware run/build bootstrap 拒绝。 - -## Private Schema And States - -每个使用 Job 的逻辑 database 初始化 runtime-owned versioned schema,独立于 Model history、snapshot、seed 和 migration。至少包含: - -- Job:id、target identity、schema fingerprint、payload、dedupe key、state、run_at、attempt、max attempts、timeout、claim token、lease deadline、安全错误分类/摘要和时间戳。 -- Schedule cursor:稳定 schedule identity、cron fingerprint、last processed UTC minute 和更新时间。 - -状态为 pending、running、succeeded、dead、blocked。业务 key 只在 pending/running 上保证 `(target, key)` 唯一,终结后可重用;schedule occurrence 由持久 cursor 保证永久单窗口物化一次,不能依赖 active-only 唯一索引。 - -未知 target、schema mismatch 和 corrupt payload 不执行 App,保留原记录并进入 blocked。历史记录的实际 timeout 也必须满足当前 SQLite lease 约束,否则以固定 `invalid_policy` 进入 blocked。attempt 耗尽进入 dead,并由独立有界清理处理,不占用领取可执行任务的槽。运行时不保存 Secret、完整 payload、backtrace 或未经控制的 `AppError::to_string()`;只保存固定类别和有界安全摘要。 - -## Claim, Lease And Retry - -PostgreSQL 使用短 transaction、bounded batch 和 `FOR UPDATE SKIP LOCKED`;SQLite 使用短 `BEGIN IMMEDIATE` 与条件 update。只按当前空闲执行槽 claim,不能预占后在无界内存队列等待。 - -每次成功 claim 时原子增加 attempt,并生成独立随机 claim token。这样进程在 handler 返回前崩溃也会消耗一次 attempt。过期 running 在 attempt 未达上限时可重领,已达上限时转 dead。 - -renew、success、retry、blocked/dead 更新均使用 `id + claim token + running state + 未过期 lease` CAS。claim 在获得写锁后读取时钟并建立租约;renew/complete 先锁定 claim 行,再读取同一 Clock,不能用锁等待前的时间续租或确认已过期任务。CAS 失败表示已失去所有权,旧执行者不得覆盖新 owner 状态。worker 在 lease 周期内续租;handler timeout 或安全业务失败按 checked exponential backoff 重新 pending,且不超过配置上限。语义为 at-least-once,外部副作用仍由业务 idempotency 保证。 - -## UTC Schedule - -Cron 固定为五字段 UTC:minute、hour、day-of-month、month、day-of-week。支持 `*`、单值、逗号列表、闭区间和步长;范围分别是 `0..59`、`0..23`、`1..31`、`1..12`、`0..6`,其中 Sunday 为 0。day-of-month 与 day-of-week 同时受限时采用 cron 的 OR 语义,否则匹配受限字段。 - -首次启用从当前 UTC minute 建 cursor,不回放历史。以后在同一 transaction 锁定 cursor、插入 occurrence、推进 cursor;每轮最多扫描并推进 256 个分钟槽,只对匹配 cron 的槽生成任务,剩余分钟后续继续补。slot key 包含稳定 schedule identity 和 UTC minute,与业务 key 分离。相同 schedule identity 的 cron fingerprint 不一致时启动失败关闭,禁止多版本互相改写 cursor。 - -## Runtime Topology And Shutdown - -严格配置只来自 `config/setting.json`: - -```json -{ - "runtime": { "mode": "all", "shutdown_ms": 30000 }, - "job": { - "workers": 4, - "poll_ms": 250, - "lease_ms": 60000, - "retry_base_ms": 1000, - "retry_max_ms": 300000 - } -} -``` - -`runtime.mode` 只能为 api、worker、all。generated entry 在 listen、schema materialize 或 claim 前统一校验 source capabilities、HTTP/Job 配置、driver 和所有上限。api 模式中的 `dever.job.serve()`、worker 模式中的 `dever.api.serve()`安全 no-op;同一 binary 保留两套静态 dispatch roots,不按运行模式裁剪。 - -没有 worker capability 的纯 API 应用可省略 runtime,默认 api 和 30000 ms;有 worker capability 时必须显式配置。worker 连接池必须比 worker 槽至少多一个连接,供 claim/heartbeat 使用;不引入独立控制连接池。SQLite 只有一个写者,额外连接无法绕过业务写事务,因此启动前还必须验证 `lease_ms > Job timeout_ms`,让租约覆盖 handler 的最长执行时间;PostgreSQL 可继续使用较短租约并续租。 - -generated entry 拥有唯一 lifecycle:结构化等待应用 root 与 SIGTERM/Ctrl-C。收到信号后广播 shutdown;API 关闭 listener 并复用 HTTP connection drain,Job 停止 schedule/claim 后等待 active handlers。到 `runtime.shutdown_ms` 才取消剩余作用域;未确认 success 的 Job 保留/恢复 lease。应用 root 汇合后执行 database shutdown,再 flush log。Tokio signal 是既有依赖的 feature 扩展,不引入 signal/queue/cron 框架或 unsafe handler。 - -Job timeout 上限为 3,600,000 ms,lease 的有界范围为 100..7,200,000 ms。测试使用 lease 上限,保证所有合法 Job timeout 都能在隔离 SQLite 中执行,仍复用生产 claim/dispatch/finish 和策略检查。 - -## Application Testing - -每个 test case 保持独立 native module、进程、临时目录、Port fake graph 和 SQLite connections。闭包同时包含:test 直接 enqueue 的 Job、Job handler 调用的 App/Port,以及 handler 的 Model connections;生产 Adapter 和部署 settings 不得回退进入 case。 - -测试专用 compiler-owned 操作提供 case-local clock advance 和 bounded due-job drain。它们复用生产 claim/dispatch/finish 状态机,不启动永久 `serve()`,不真实 sleep,也不允许测试直接调用 Job entry。无 database/Job effect 的纯测试仍不加载 settings。 - -## Explicit Non-Goals - -不增加动态 target string、通用 DI/queue framework、外部 broker、非 UTC schedule、exactly-once 外部副作用、payload 自动迁移或 Job 管理 API/front。真实 PostgreSQL 并发、锁与取消仍需隔离 fixture 验收;feature check 不能替代运行证据。 diff --git a/.trellis/tasks/09-20-durable-jobs/implement.jsonl b/.trellis/tasks/09-20-durable-jobs/implement.jsonl deleted file mode 100644 index 0015871..0000000 --- a/.trellis/tasks/09-20-durable-jobs/implement.jsonl +++ /dev/null @@ -1,5 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Source role, static target, effect and visibility contracts"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"Transaction, connection, migration and cancellation invariants"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Structured concurrency, native runtime and shutdown"} -{"file":".trellis/tasks/09-13-typed-orm/design.md","reason":"Existing SQLite/PostgreSQL transaction and pool architecture"} -{"file": ".trellis/tasks/09-20-durable-jobs/research/implementation-map.md", "reason": "Verified source ownership and implementation risks"} diff --git a/.trellis/tasks/09-20-durable-jobs/implement.md b/.trellis/tasks/09-20-durable-jobs/implement.md deleted file mode 100644 index 5f151b2..0000000 --- a/.trellis/tasks/09-20-durable-jobs/implement.md +++ /dev/null @@ -1,127 +0,0 @@ -# Dever 持久化 Job 实施计划 - -## Start Gate - -- [x] time-typed-codec 与 port-adapter 完成。 -- [x] 用户批准父任务规划并允许继续实现。 -- [x] 读取 structured concurrency、ORM transaction/settings、native profile、application test runner 和 HTTP drain owner。 -- [x] 完成源码 implementation map 与独立设计复核。 -- [x] 收紧 ModelId、connection effect、claim attempt、cron cursor、lifecycle 和测试 harness 契约。 - -## 1. Source And Static Contract - -- [x] 增加 Job SourceRole、layout、contextual declaration、policy、schedule、formatter 和 Markdown parity。 -- [x] 增加 Program Job metadata、静态 target identity、App-owned payload schema 和 nominal ModelId wire codec。 -- [x] 增加 enqueue/enqueue_at 专用检查与 HIR;拒绝普通 call、handler/run/group 转发和非法 role/type/signature。 -- [x] 将 Job handler 作为独立生成 root,不把 enqueue 视为同步依赖或递归 edge。 - -Gate:新增 `durable_jobs` 源码/Markdown测试覆盖合法声明、路径、签名、可见性、payload、policy、cron和target正反例。 - -## 2. Connection Effect And Atomic Enqueue - -- [x] 将 Model-only database effect 推广为统一的有类型 connection owner,并集中解析 ConnectionSelector。 -- [x] enqueue 只传播队列连接 effect,不传播 handler 业务 effect/failure。 -- [x] native emitter 复用 `_database`、Executor 和 wire codec,实现 standalone short transaction 与 ambient transaction enqueue。 -- [x] settings-aware bootstrap/test runner 使用统一 connection effect;拒绝解析后的跨连接 transaction。 - -Gate:enqueue-only transaction 可生成;Model write + enqueue 同时 commit/rollback;跨连接拒绝;同 transaction 不二次 checkout。 - -## 3. Private Store State Machine - -- [x] 实现 SQLite/PostgreSQL runtime private schema、版本校验和初始化锁,不进入 Model history。 -- [x] 实现 active-key 原子幂等 enqueue、run-at、bounded row/value limits。 -- [x] 实现 bounded claim、claim-time attempt、随机 token、lease renew/expiry 与 owner CAS。 -- [x] 实现 success、retry/backoff、dead、blocked 及受控错误分类/摘要。 - -Gate:SQLite temp DB 覆盖并发去重、终结后 key 重用、到期、双 claimant、崩溃耗尽、过期重领、旧 token 拒绝和 schema/decode/target blocked;PostgreSQL 验证 feature/SQL 生成。 - -## 4. Schedule, Worker And Test Harness - -- [x] 实现共享五字段 UTC cron parser、匹配与 bounded next-slot 搜索(每轮扫描最多 256 个分钟槽,不做无界寻找)。 -- [x] 实现持久 cursor、同 transaction occurrence materialize/advance、首次启用和每轮最多 256 个补偿窗口。 -- [x] 实现 bounded worker pool、timeout、heartbeat 和静态 payload dispatch。 -- [x] 扩展 application test closed graph、case-local clock 和 bounded due-job drain,复用生产状态机。 - -Gate:多 scheduler 同 slot、completed occurrence 不重建、cursor rollback/restart、cron fingerprint 冲突和补偿上限;不同 case fake/clock/database 不泄漏且不读取部署配置。 - -## 5. Mode And Lifecycle - -- [x] 增加严格 runtime/job settings、source capability 预检和 runtime profile feature/cache identity。 -- [x] 实现 api/worker/all gating,保留同 binary 的 API/Job dispatch roots。 -- [x] 增加结构化 SIGTERM/Ctrl-C owner;API stop-accept/drain 与 Job stop-claim/drain 共享 deadline。 -- [x] generated entry 在应用汇合后统一 database shutdown、log flush,覆盖启动失败和超时取消。 - -Gate:缺失/非法配置在 listen/claim 前失败;三 mode 只启动应有服务;test-owned 进程验证信号后停止新工作、drain/超时取消和关闭顺序。 - -## 6. Documentation And Focused Verification - -- [x] 更新 LANGUAGE、MARKDOWN-SYNTAX、compiler/database/toolchain 中的 application-testing 契约。 -- [x] 检查无环境变量入口、动态 target、第二套 codec/transaction/pool、脱管 task 或生产 Adapter 测试回退。 -- [x] 完成独立 Trellis check,修复 in-scope findings。 -- [x] 主代理最终复核并更新父任务 checklist。 - -```bash -cargo check --locked --offline -p dever-core -p dever-runtime -p dever-cli -cargo check --locked --offline -p dever-runtime --features sqlite,postgres -cargo test --locked --offline -p dever-tests --test durable_jobs -cargo test --locked --offline -p dever-tests --test source_architecture -cargo test --locked --offline -p dever-tests --test error_effects -cargo test --locked --offline -p dever-tests --test orm_query -cargo test --locked --offline -p dever-tests --test sqlite_orm -cargo test --locked --offline -p dever-tests --test application_config -cargo test --locked --offline -p dever-tests --test application_testing -cargo test --locked --offline -p dever-tests --test structured_concurrency -cargo test --locked --offline -p dever-tests --test pooled_network graceful_shutdown -git diff --check -``` - -所有 Cargo 命令使用无增量、debug info 关闭和串行测试。默认不运行 workspace 全量测试、真实性能套件或持久服务。真实 PostgreSQL 仅在仓库隔离 `config/setting.json` fixture 明确存在且用户知情时运行;否则明确记录为未运行。 - -## 实施记录 - -- 源码、共享 wire/connection owner、生产 store/worker、native/test roots、mode/lifecycle 已接通;以上勾选表示实现完成,最终 Gate 证据记录在下方,不代替独立 Trellis check。 -- 启用既有 Tokio `signal` feature;经主代理明确授权解析依赖,Cargo.lock 仅新增 `errno 0.3.14` 与 `signal-hook-registry 1.4.8` 两个传递项。后续命令均 `--locked --offline`。 -- API-only 保留既有省略 runtime 配置的兼容行为(api、30000 ms);有 worker capability 的应用必须显式配置 runtime。worker pool 比执行槽至少多一个连接,以免 handler 事务耗尽 heartbeat/claim 容量。 -- enqueue 使用单条 active-key upsert + RETURNING,避免 PostgreSQL 上冲突 insert 后、查询 Id 前任务终结的竞态。 -- 新增测试发现 case 裁剪不可达 transaction 后被误报空事务;修复共同 effects validator,真实空事务仍有 clause 并继续被拒绝。 -- 数据库服务、真实 PostgreSQL、全量测试、性能/内存压测未运行;rustfmt/clippy 未安装,不安装。 - -### 最终实施验证 - -- `cargo check --locked --offline -p dever-core -p dever-runtime -p dever-cli`:通过。 -- 同一 check 加 `--features dever-runtime/sqlite,dever-runtime/postgres,dever-runtime/api,dever-core/reference`:通过。PostgreSQL 仅 feature 编译证据,未连接真实数据库,不把它算作锁、并发或 SQL 执行验收。 -- `durable_jobs`(sqlite):14/14。覆盖源码/Markdown、跨连接拒绝、nominal ModelId native 往返、同物理事务 commit/rollback、active-key 并发幂等、定时到期、claim-time attempt、旧 token CAS、崩溃耗尽、schema/corrupt/unknown 的 generated dispatch blocked、多 scheduler、完成窗口不重建、cursor 中途失败回滚/重启、256 窗口上限、case-local SQLite/clock/fake 与无数据库 empty drain。 -- 同一 `durable_jobs` 目标包含真实 native 二进制的 api/worker/all 三 mode:临时回环监听和临时 SQLite;api 不 claim、worker 不监听、all 同时工作,均 SIGTERM 正常退出。独立 runtime 子进程另覆盖 heartbeat、停止 claim、在途排空与 shutdown deadline 取消后关闭数据库/flush 日志。 -- `application_config`:3/3;`application_testing`:8/8;`source_architecture`:8/8。 -- `pooled_network graceful_shutdown`:1/1,验证已有 HTTP 停止 accept 并完成在途响应。 -- `time_codec wire_schemas_do_not_change_model_time_storage_identity`:1/1。该条旧断言随 nominal ModelId wire 合同更新;无 private/bounded 字段的 Model record 也可通过共享 codec,存储 snapshot 不变。该 fixture 已调整为当前 App 路径,未顺带改造其余旧测试。 -- 上述测试均串行;`CARGO_INCREMENTAL=0`,dev/test debug info 为 0,固定 stable toolchain PATH。`git diff --check` 通过;新 Job/lifecycle 源码检查未发现环境变量读取、动态 target、脱管 spawn 或 unsafe。 -- 独立 Trellis check 结果见下方;父任务 checklist 由主代理收口,任务仍保持 `in_progress`。 - -## 独立检查与修复 - -- 复现 SQLite handler 持写事务时短租约无法续租:业务已提交,但任务仍为 running。当前源码的启动预检要求 SQLite `lease_ms > timeout_ms`;PostgreSQL 继续支持短租约续租。领取在获得锁后建立 lease,续租/完成先锁 claim 行再读注入 Clock,避免使用锁等待前的旧时间。 -- worker 在调用业务前重新验证持久化记录的实际 timeout/max attempts;旧策略不满足当前 SQLite lease 或已越界时进入 `blocked/invalid_policy`,不执行 App。公共 timeout 上限仍为 3,600,000 ms,lease 上限为 7,200,000 ms;测试使用最大 lease,合法长任务不会因测试固定短租约被误拒绝。 -- 耗尽 attempts 的到期记录改为同一 claim 事务内独立有界清理;eligible 查询跳过耗尽记录,避免它占据执行槽并使 drain 误判队列为空。 -- 信号测试原来对同一 run_at 的任务假定按业务 key 执行,但实际稳定排序使用 run_at/UUID;同毫秒 UUID 带随机部分。改用不同到期时间表达本测试的执行次序,同时保留实际 heartbeat、持事务 drain 和超时取消检查。 -- 保持既有已审阅的 API-only 默认配置契约;有 worker capability 时 runtime 必填。统一 cron 文档为每轮扫描/推进最多 256 个分钟槽,只有匹配 cron 的槽生成任务。 -- 同步 LANGUAGE、design、compiler 目录 owner 图以及 database/toolchain 规范;未增加环境变量、第二套 pool/transaction/codec、动态 target 或脱管任务。 - -### 独立验证证据 - -- 最终 `cargo check --locked --offline -p dever-core -p dever-runtime -p dever-cli --features dever-runtime/sqlite,dever-runtime/postgres,dever-runtime/api,dever-core/reference`:通过。 -- 最终 `cargo test --locked --offline -p dever-tests --features sqlite --test durable_jobs -- --test-threads=1`:14/14,通过,122.86 秒。包含最大合法 timeout 的 case-local SQLite/fake、claim/renew/complete 锁等待时钟回归、exhausted 后正常任务 drain、旧持久策略 blocked、三 mode 和 SIGTERM 的 grace/timeout/持事务三场景。 -- 主代理最终复核再次运行 `sqlite_durable_state_machine`:1/1 通过;core/runtime/CLI 的 SQLite+PostgreSQL+API+reference feature check 再次通过。 -- Cargo 命令统一固定 stable PATH、`CARGO_INCREMENTAL=0`、dev/test debug info 为 0。`git diff --check` 和改动 Job 文件尾空白检查通过。 -- 一次中间 suite 为 13/14:信号 fixture 的同到期时间随机顺序断言失败;已按上述原因修复,最终完整定向 target 14/14。 -- rustfmt/clippy 二进制未安装,未安装或运行;全量测试、真实 PostgreSQL、性能/内存压测未运行。PostgreSQL 证据仅 feature 编译与代码审查,不宣称已完成真实锁/并发/SQL 执行验收。 -- 本次独立检查没有剩余已知实现阻塞;任务状态按调度要求保持 `in_progress`,交由主代理最终复核。 - -## 待复核风险 - -- 业务 commit 与 Job insert 必须共享同一 physical transaction,不能 after-commit 补写。 -- attempt 必须在 claim 时增加;finish/renew/retry 必须比较独立 claim token 和有效 lease。 -- cron materialization 必须由 cursor transaction 保证,不能复用 active-only key 或单进程内存 timer。 -- enqueue 不得引入 handler 同步 effect/递归;worker/test root 必须包含 handler 的真实 Model/Port/fake 闭包。 -- runtime mode 必须在副作用前统一预检;signal drain 不能调用立即 abort 的 Group::stop 伪装优雅退出。 -- payload/schema identity 是持久协议;未知版本必须 blocked/fail closed,不能 best-effort decode。 diff --git a/.trellis/tasks/09-20-durable-jobs/prd.md b/.trellis/tasks/09-20-durable-jobs/prd.md deleted file mode 100644 index 55527f4..0000000 --- a/.trellis/tasks/09-20-durable-jobs/prd.md +++ /dev/null @@ -1,50 +0,0 @@ -# Dever 持久化 Job - -## Goal - -为 Dever 提供数据库持久化、事务一致、可恢复且有界的后台任务和 UTC 定时任务,使 API 与 worker 可使用同一编译产物独立或组合部署,禁止用脱离结构化作用域的异步任务代替可靠 Job。 - -## Dependencies - -- `time-typed-codec`:DateTime、payload codec 和 schema fingerprint。 -- `port-adapter`:Job 调用的 App 可以通过 Port 执行外部副作用。 -- 复用既有 SQLite/PostgreSQL ORM transaction、pool、settings 和 shutdown。 - -## Requirements - -- 新增 Job source role;允许 `job.dever` 或平铺 `job/*.dever`,角色目录遵守现有 file/directory exclusivity 和 no-single-topic 规则。 -- Job entry 使用明确 contextual declaration,零输入或一个 App-owned wire-safe record 输入、零输出,只能调用同领域 App,不能直接访问 Domain/Model/Port/Adapter/API;Job payload 支持保留 Model identity 的 ModelId。 -- Job entry 不可被普通 source call;App 只能通过 compiler-owned enqueue/enqueue_at target reference 创建持久化任务。 -- 每个 enqueue 必须提供业务 idempotency key;同 Job identity + key 的未终结任务不重复插入。 -- Job 声明绑定一个逻辑 database connection,并声明有界 timeout/max attempts;`retry(n)` 表示包含首次执行在内最多执行 n 次,不允许零/负/越界值。 -- 立即和 run-at Job 持久化 target identity、payload、schema fingerprint、key、run_at、attempt/state、lease 和错误摘要。 -- 周期 Job 使用编译期验证的五字段 UTC cron declaration且只能绑定零输入Job;持久 cursor、occurrence insert 和推进在同一 transaction,每个计划窗口生成确定性key,多进程及已完成任务不能重复创建同一occurrence。带payload的业务计划使用enqueue_at。 -- transaction App 内 enqueue复用隐藏 transaction context;Model effect与Job connection不同则编译失败。非 transaction enqueue使用自身短事务。 -- SQLite/PostgreSQL使用runtime private versioned schema;初始化、claim、lease renew/expiry、success、retry、dead-letter均有明确事务边界。 -- worker采用至少一次执行;attempt 在 claim 时原子增加,每次 claim 使用独立 fencing token;失败按有界指数退避重试,达到上限进入 dead-letter,不无限循环或静默丢弃。 -- payload schema不兼容、未知 Job target和解码失败进入dead-letter/blocked状态并记录脱敏原因,不best-effort执行。 -- `dever.job.serve()`显式启动worker。combined main使用现有Group并发启动API/Job;不增加隐式后台线程。 -- `config/setting.json`提供严格 `runtime.mode=api|worker|all` 和 job worker/lease/poll/shutdown上限;不接受环境变量或CLI覆盖。 -- SIGTERM/Ctrl-C停止API accept和Job claim,排空在途工作到deadline,再停止、释放lease/连接并执行数据库/log shutdown。 -- 应用测试的Job数据库由runner生成隔离SQLite;不读取部署setting或自动连接PostgreSQL。 - -## Acceptance Criteria - -- [x] Job合法路径/签名可检查和格式化;ModelId payload 保持 nominal identity;普通调用、非法输出/类型、跨域或直接Model/Port访问被拒绝。 -- [x] 业务Model写入与Job入队在同一transaction一起commit/rollback;跨连接组合在编译期拒绝。 -- [x] 相同identity+key并发入队只保留一个可执行任务,不丢失已提交业务状态。 -- [x] 到期前不执行,UTC run-at到期执行;周期任务在多个worker下每个window最多创建一次。 -- [x] worker崩溃/取消会消耗 attempt,lease 到期可由另一 worker 恢复;活跃 lease 不被重复 claim,旧 fencing token 不能提交迟到结果。 -- [x] handler失败按策略重试,成功终结,达到attempt上限进入dead-letter;错误信息不含Secret/payload全文。 -- [x] schema mismatch、unknown target、corrupt payload不会执行App并保留可诊断记录。 -- [x] api/worker/all三种mode分别只启动应有服务;缺少相应配置在监听/claim前失败。 -- [x] SIGTERM/Ctrl-C定向runtime test验证停止新工作、排空或超时取消以及最终数据库/log关闭顺序。 -- [x] SQLite端到端通过;PostgreSQL feature编译通过,真实行为只在隔离 `postgres_test` 明确存在时运行。 - -## Out Of Scope - -- Exactly-once外部副作用、分布式事务和跨数据库原子提交。 -- Redis/Kafka/RabbitMQ/SQS和第三方队列。 -- 非UTC cron、DST和动态用户时区调度。 -- Job管理front;dead-letter运维界面后续由业务API/front实现。 -- 无界任务fan-out、优先级抢占和动态代码任务。 diff --git a/.trellis/tasks/09-20-durable-jobs/research/implementation-map.md b/.trellis/tasks/09-20-durable-jobs/research/implementation-map.md deleted file mode 100644 index ff9df80..0000000 --- a/.trellis/tasks/09-20-durable-jobs/research/implementation-map.md +++ /dev/null @@ -1,109 +0,0 @@ -# Research: Durable Job implementation map - -- Query: 核实持久化 Job 的源码接入点、最小复用架构、SQL/生命周期风险和定向验收。 -- Scope: mixed;以当前本地源码为准,外部资料仅核对 SQL/信号基础能力。 -- Date: 2026-09-20 - -## Findings - -### 当前事实和实施前须解决的契约矛盾 - -1. 当前没有 Job source role、Job runtime、cron parser 或 SIGTERM/Ctrl-C owner。`rg signal|SIGTERM|ctrl_c|cron|Job crates library` 仅发现 `core/wire.rs` 的 `Policy::Job`。不可将设计中的这些能力当作已有实现。 -2. `wire::Policy::Job` 已存在,拒绝 Secret/private Model;现有 wire 同样拒绝 ModelId。设计示例 `PublishInput.article_id: content.article.model.id` 因而不成立。需要明确选择:扩展共享 wire owner 支持保持 nominal 身份的 ModelId,或修改示例使用当前 wire-safe DTO;不得只给 Job 私加类型白名单。考虑 Job 最常见用途正是实体异步操作,建议在共享 schema/codegen 增加 ModelId 节点,协议用字符串,fingerprint 保留所属 Model 身份,同时明确适用 policy。当前 `native/wire.rs:32` 的普通 `Id` 已映射 runtime `Id`,不可把 ModelId 在类型系统里降级成普通 Text/Id。 -3. `hir.rs:21`、`contracts/effects.rs:18` 的 database effects 是 Model ID 集合;`native.rs:436` 的 transaction 取第一个 Model 找连接。纯 Job enqueue 无 Model 时无法运行。必须推广为连接资源 effect,不能伪造 Model 或复制第二套 transaction context。 -4. 现有跨连接检查在 `model.rs:256` 的 `validate_database_settings`,依赖设置解析后连接名,而非仅 AST check。明确显式不同连接可在 check 拒绝;PackageRoot fallback 仍需要 settings-aware CLI 检查/启动校验。不要错误拒绝不同 selector 最终落在同一个 default 的合法情形。 -5. `retry(5)` 的含义必须固定为最多 5 次 attempt,还是首次之外 5 次重试。PRD 用 max attempts,建议前者并准确写明;不能只在失败后加 attempt,否则每次执行中崩溃会无限重领。 -6. 设计只规定 UTC cron,未规定字段语法、DOM/DOW 组合、停机补跑和首次部署起点。最小实现应固定五字段数字语法、范围/列表/步长和 DOM/DOW 规则;持久 checkpoint、每轮有界补齐。拒绝不能满足的日期组合或规定有界搜索失败,不能无穷找下个时间。 - -### Owner 文件与复用入口 - -| 文件/符号 | 当前职责与 Job 接入 | -| --- | --- | -| `crates/dever-core/src/source.rs:25` SourceRole/from_name/name | 当前 App/Domain/Model/Port/Adapter/Api;增加 Job,沿用 path-derived identity。 | -| `check/layout.rs:14,56` RoleFiles | 已有 role file/directory 排他、非 API 平铺、目录至少两文件;增加枚举后复用,不另写 Job scanner。 | -| `syntax.rs:169,184` FunctionClause/FunctionKind | 已有 ordinary/transaction、fails/bodyless;Job kind 和 bounded policy 作为声明元信息。schedule 用独立声明。 | -| `parser.rs:210,707,761` declaration/function/function_contracts | contextual transaction 的 dispatch 可复用;增加 job/retry/timeout/schedule;勿让 retry/timeout 成普通函数调用。 | -| `format.rs:120,258` declaration/function | 共享 AST formatter,输出 job 前缀和稳定 policy 顺序。 | -| `markdown/contract/parse.rs:198,237,261` / `validate.rs:247` | function 元信息、非 function directive 标识已有 owner;schedule 需加入 directive 分支;Markdown policy 元信息应与 source 一致。 | -| `check.rs:321,423,438` Program/test registration | 注册 Job metadata 和 target map;test case closed graph 与 fakes 已完成,必须沿用。 | -| `check/symbols.rs:222` can_call / `:277` can_access_type | API 不可调用的现有模式适用于 Job;普通 function resolution 和 handler resolution 都必须拒绝 Job。Job 仅调用同域 App,DTO 类型访问另定规则。 | -| `check/expressions.rs:521,620,655` static call/handler reference | 可复用 named-path 解析形态,但 enqueue target 不是 Handler 参数,不能转发。新增专用 checked enqueue path,参数先解 target 再按 payload schema 检查。 | -| `hir.rs:164,507,524` ExpressionKind/static_call/CallArgument | 用 JobEnqueue {target,payload,key,run_at} 明确表达入队;遍历/变更遍历要覆盖三个值表达式。enqueue 不等价同步 call。 | -| `contracts/dependencies.rs`, `contracts/effects.rs:61,505`, `contracts/error_effects.rs` | enqueue 引入本 Job 连接、database failures 和 suspension;不得传播 Job handler 的业务失败/网络 effect 到 enqueue 的 App。 | -| `specialize.rs:77,120,178` database_effects/concrete/successors | 独立执行根收集 Job handlers;不要把 enqueue->handler 当普通递归 edge,App 入队自己未来工作的循环是正常队列行为。 | -| `native.rs:292,418,434,569` DB setup/function/call | 统一隐藏 `_database: Option<&Transaction>`;普通 enqueue 继承,Job handler 执行从 None 开始。 | -| `native/orm.rs` | 现有 Executor/参数/错误转换供 Job emitter 复用;不复制数据库错误到字符串再猜类别。 | -| `native/api.rs`, `native/ports.rs` | 静态 dispatcher 和 startup initialization 可参考;Job 生成 concrete decoder + direct function invocation,不造 runtime Value 解释器。 | -| `native/build.rs:120,309,349` | suite profile、runtime features、缓存身份;Job 无 Model 仍需 database+wire+已选驱动。feature/cache 与源码变化同步。 | -| `crates/dever-runtime/src/database.rs:167,317,458` | Database/begin、Executor::new、database_for;所有 Job SQL 通过既有 Sql 双方言和 Value/Row 编解码。 | -| `sqlite.rs:174,223,279` | BEGIN IMMEDIATE、transaction 方法、未确认完成 Drop 丢弃 pool object。可直接用于 claim 短事务。 | -| `postgres.rs:236,302,383` | BEGIN、带 I/O deadline 的事务、Drop 丢弃连接;claim 使用 SKIP LOCKED。 | -| `sqlite/migration.rs`, `postgres/migration.rs:73,109` | Model 自己的 schema/history owner;Job 私有 schema 不进入它们,但复用事务/advisory lock 纪律。 | -| `config.rs:11,70,144,325,356` | 单一 Settings,严格 top-level/duplicate wire 验证,bootstrap/http lazy read。扩展 typed runtime/job config。 | -| `task.rs:78,488`, `task/scoped.rs` | 单 runtime、Scope supervisor、Group;worker/heartbeat/signal 等所有活动必须有结构化 owner。 | -| `api.rs:13`, `http/mod.rs:147,176`, `net.rs:47,232` | API 内创建 listener;HTTP 已响应 listener.close 并 graceful drain。新增 signal owner 触发此路径,不用取消 serve 代替优雅关闭。 | -| `database.rs:496,502`, `postgres.rs:462,473` | prepare/shutdown 当前只负责 PostgreSQL;SQLite 没有显式 pool shutdown 路径。若 PRD 保证最终关闭 SQLite,需补 owner。 | -| `core/wire.rs:10,55,64`, `native/wire.rs:8` | Job policy、稳定版本 schema identity、concrete codec;当前 fingerprint 是确定性描述串,不是固定长度加密 hash。持久字段可存完整 identity,不误称 SHA。 | -| `cli/test_runner.rs:73,126` / `check.rs:466` | 每 case 新进程/临时目录,runner 生成 SQLite setting;无 DB case 无 setting。加入 Job connection、harness,仍不读部署配置。 | - -### 建议最小架构和数据流 - -保留 Job body 为 Function/HIR,额外 Program.jobs 持有 identity/function/connection/payload schema/policy/schedule。compiler 专用 enqueue 表达式只保存静态 target ID 和普通参数;不将 target 暴露成值类型。Job entry 的 ordinary/handler 调用拒绝统一放符号访问 owner。 - -数据库 effect 推荐抽为统一 `DatabaseBinding`(selector + fallback root 的稳定值或 intern ID),Model 与 Job 都引用。Model 的 CRUD schema/index 仍保持 Model ID,仅 effects/transaction/startup/test 配置改用连接 binding。为最小改动也可用明确的资源枚举 Model/Job 并统一 `binding()` accessor,但不应让消费者每处重复 match。 - -源码 Job → checked metadata/payload Schema → enqueue HIR → 编码 Encoded JSON → 同一 Executor 写入 → commit → worker claim → 校验 target/schema → concrete decode → direct App 调用 → owner-CAS finish/retry。enqueue 的调用图不包含 handler 业务 effect;worker 启动根和 test harness 根要独立包含 handler/App/Port fake graph,避免漏链接及错误递归判定。 - -runtime 可由 `job.rs` 拥有 public compiler bridge,`job/store.rs` 拥有 DB 状态机和 SQL,`job/schedule.rs` 拥有 cron/slot,`job/worker.rs` 拥有有界执行;只有职责确实需要时拆这些文件,不添加通用 queue framework。compile-time cron 验证可调用纯 runtime cron parser,避免编译期/运行时双实现。chrono std-only 已存在,复用 UTC calendar;无须引入时区库。 - -### SQL/租约策略 - -- runtime private version 表 + job 表 + schedule checkpoint 表。SQLite BEGIN IMMEDIATE,PG 独立 runtime namespace advisory transaction lock;version 不认识时明确失败,不能 CREATE IF NOT EXISTS 后假装兼容。 -- enqueue 的 active-only 唯一索引覆盖 `(target,dedupe_key)` 且 predicate 只含待执行/执行中状态;参数化 INSERT ON CONFLICT DO NOTHING,再返回已有 active ID。不能用 SELECT-before-INSERT 作为唯一保障。业务失败 rollback 必须撤销同物理事务的入队。 -- PostgreSQL claim:短事务选取到期 pending 或过期 running,`FOR UPDATE SKIP LOCKED LIMIT ...`,写 owner、lease_until、attempt 后提交。SQLite 同过程已有 BEGIN IMMEDIATE 序列化。只 claim 有空闲执行容量的条目,不能先批量占 lease 再在无界内存队列等候。 -- attempts 建议在成功 claim 时递增;超时/失败/崩溃恢复都耗费次数。过期且 attempts 达上限的条目需进入 dead-letter,不能永远排除于查询而残留 running。 -- owner token 每次 claim 新生成,不能仅以进程 worker ID 作为 fence;旧执行在同 worker 中过期重领后仍可能迟到。finish/renew/retry 带 id + token + state,必要时判断 lease_until;影响行数为 0 即丢失租约,不可继续确认成功。复用现有 OS randomness/Uuid owner,不硬编码 ID。 -- renewal 不与 handler 持有同一 transaction;需预算 worker 数与 pool 容量,避免单连接长事务使 heartbeat 饿死。取消后复用当前丢弃未知连接的规则。若 handler 无法强制立即停止,最多只能保证至少一次,外部副作用依赖业务 idempotency。 -- PG runtime Int bind 是 i64,SQL 数值列和参数使用 BIGINT 语境;时间全部 epoch ms,勿调用 SQL now 导致测试时钟不一致。错误摘要写固定错误类别/有界安全信息,不保存 AppError Display(业务 message 可含 payload)。 -- cron occurrence 幂等不能只用 active-only job 索引:已经成功的 occurrence 可能被另一 scheduler 再建。锁定 checkpoint 行,插入 jobs 与推进 last slot 同事务;或者永久唯一 occurrence ledger。checkpoint 必须按规范化 cron identity,计划变更不能回放全部历史。每轮扫描/补跑有界。 -- key/payload/target/schema/error 等都有确定上限;wire 16 MiB 默认上限已经有界,但 worker 并发乘以该值仍需评估,不宣称低内存性能。 - -### Mode、启动与关闭 - -当前 RuntimeProfile 只有 sqlite/postgres;Tokio RuntimeConfig 只有线程/任务容量,均没有 api/worker/all。严格 runtime/job 文档必须进入 Settings 的真实解析,不能仅在 serve 里临时读 JSON。主程序调用 serve 的能力图用于校验 mode:worker-only 不要求 HTTP;API-only 不 claim;all 按 main 的 Group 并行拥有两个 server。启动前校验对应模式的缺失配置及所有启用 Job timeout/lease 关系,不能 API 已监听后才发现 Job 不可用。 - -API runtime::serve 需在创建 listener 后把关闭与 drain 接到同一 shutdown token。signal watcher 是 generated entry/运行时生命周期拥有的 future,不可 detached spawn;SIGINT/SIGTERM 一次广播,停止 accept/claim/schedule 后等待在途工作到统一 deadline。deadline 到达使用现有 Task/Group cancel-and-drain,再执行 database shutdown 和 log flush。`Group::stop` 当前直接 abort body,正常收到 signal 时先合作排空,超时才 stop。 - -Tokio 1.53.1 当前 features 不含 signal(根 Cargo.toml:20),Cargo.lock 未找到 signal-hook。需启用 Tokio signal feature 并确认 offline 所需依赖已缓存;不要用 unsafe libc handler(workspace 禁 unsafe)或 shell signal 轮询做替代。PG driver shutdown 当前存在;SQLite pool explicit close 和 startup failure 清理须单独覆盖。generated entry 当前仅 profile.postgres 时调用 shutdown,需按完成的生命周期设计调整。 - -### Application test 隔离 - -保持每 case 单独 native module、closed fake graph、进程和临时目录。test metadata 收集 enqueue 与 harness 执行的 Job 连接以及 handler 访问的 Model;不能只看 test 主函数的直接 Model effects。每 case SQLite default/explicit connections 由 runner 生成。Job-only case 也生成 setting;非数据库 case 仍无 setting。 - -设计还没有给 compiler-owned test harness 的源码调用协议,不能只实现 Rust store 单元测试便声称应用测试可用。建议最小 test-only drain-due/advance-clock 操作,返回有界观察结果或保证已处理 due work,测试通过 App 查业务状态;不开放 DB handle 或普通直接 Job entry 调用。假时钟作为 case-owned Clock 注入 store/scheduler,不改全局系统时间、不真实 sleep。 - -### 定向验收建议 - -1. 新 `durable_jobs` 源码/formatter/Markdown 定向 target:合法声明、错误 role/直接 call/handler reference、0/1 record 参数、Secret/private/非法 payload、policy 上下界、cron 非法、纯 Job transaction 与跨连接。 -2. runtime SQLite temp DB:业务写入+入队 commit/rollback;并发 active key 去重;终结后 key 重用;run_at;多 claimant;租约过期、旧 token finish/renew 拒绝、崩溃耗尽 attempts;有界退避/溢出;损坏/schema/unknown target 不执行。 -3. cron 两个独立 scheduler 同 slot、已完成 job 后再次调度、checkpoint rollback/restart、停机补跑上限、闰年/月底/DOM-DOW 规则。 -4. `application_testing` 精确 case:同二进制不同 case fake 完全隔离;Job-only SQLite setting;部署 PostgreSQL 配置未读取;受控时钟/harness 触达 App。 -5. config 三 mode 缺失/未知/重复字段、timeout/lease/poll/shutdown 约束。测试专有子进程 signal,明确 deadline;仅所属随机回环 listener(若批准)验证停止新请求和 HTTP drain;不向已有服务发送信号。 -6. `structured_concurrency`/`pooled_network graceful_shutdown` 受影响 case;SQLite one-connection cancellation 后可恢复;PG 仅 feature cargo check 与 SQL 生成断言,真实 DB 另行授权条件。 - -## External references - -- PostgreSQL SELECT locking 官方说明:`SKIP LOCKED` 适合多消费者 queue 场景,但仅跳过 row lock,仍有表级锁:https://www.postgresql.org/docs/10/sql-select.html 。这是 SQL 策略依据,不是对本仓库 PostgreSQL 实测。 -- SQLite 官方 partial index 文档:https://www2.sqlite.org/partialindex.html ,UNIQUE 可只约束满足 predicate 的行。 -- Tokio signal 官方 Rustdoc:https://docs.rs/tokio/latest/tokio/signal/unix/fn.signal.html ,Unix signal API 要求 signal feature。仓库实际 pin 1.53.1,应以本地锁定版编译验证依赖。 -- 本地版本:Tokio 1.53.1、chrono 0.4.45 std-only;SQLite/Postgres pool 沿现有锁定依赖,不建议增加队列或 cron 框架。 - -## Related specs - -已查 `.trellis/workflow.md`、任务 prd/design/implement/task.json,以及 backend `index.md`、`directory-structure.md`、`error-handling.md`、`quality-guidelines.md`、`compiler-contracts.md`、`database-guidelines.md`、`toolchain-and-library.md`、`logging-guidelines.md`。Job 新约束尤其会改变 compiler-contracts 的 Model-only effect 描述及 test runner 数据库触发条件。 - -## Caveats / Not Found - -- 子 agent `task.py current --source` 返回 none;父 dispatch 明确提供本任务绝对路径,本研究仅写此 research/,不改 active state。 -- 未改源码、spec、任务状态;未运行 build、测试、服务、外部数据库或性能测量。 -- 当前研究证明复用边界和缺失点,不证明 Job 可执行。policy、cron、payload ModelId 和 test harness 上述未落实契约必须在实施/验收中明确,不能悄悄删需求。 diff --git a/.trellis/tasks/09-20-durable-jobs/task.json b/.trellis/tasks/09-20-durable-jobs/task.json deleted file mode 100644 index 7627c19..0000000 --- a/.trellis/tasks/09-20-durable-jobs/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "durable-jobs", - "name": "durable-jobs", - "title": "Dever 持久化 Job", - "description": "实现事务内原子入队、延迟和周期任务、重试租约与 API/worker/all 运行模式", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-20", - "completedAt": "2026-09-20", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-20-production-application-language", - "relatedFiles": [], - "notes": "", - "meta": {} -} diff --git a/.trellis/tasks/09-20-port-adapter/check.jsonl b/.trellis/tasks/09-20-port-adapter/check.jsonl deleted file mode 100644 index 4d4476c..0000000 --- a/.trellis/tasks/09-20-port-adapter/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused architecture/effect/config tests"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"Single symbol/dispatch owner and legal role layout"} -{"file":".trellis/spec/backend/error-handling.md","reason":"Port failure subset and diagnostics"} diff --git a/.trellis/tasks/09-20-port-adapter/design.md b/.trellis/tasks/09-20-port-adapter/design.md deleted file mode 100644 index b6a446a..0000000 --- a/.trellis/tasks/09-20-port-adapter/design.md +++ /dev/null @@ -1,47 +0,0 @@ -# Dever Port 与 Adapter 设计 - -## Source Contract - -Port role按路径给出边界身份。根 `port.dever` 的 identity 为 `.`;topic Port 增加 topic。bodyless contract 示例: - -```dever -send(message: Text) () fails app.DeliveryError -``` - -`fails` 必须引用同领域 App 的公开 error choice(例:App 定义 `DeliveryError`),或公开标准 error choice;至少有一个显式 error variant。Port 自有类型仍私有。这样保留 App 全部函数公开的规则,App 能传播自己的错误,无需增加隐式私有 helper。Port/Adapter 只能引用 Port 签名使用的 App 类型,不能调用 App。普通有 body function 仍沿调用图推断 failure,不新增通用 throws 声明。 - -Adapter/Test 通过 qualified definition 实现,例如 `port.send(...) () { ... }` 或 `port.mail.send(...) () { ... }`。普通单名 function 是该文件 helper。一个生产 Adapter 文件完整实现一个 Port identity;禁止跨 Port 聚合。一个 TestCase 可以完整 fake 多个 Port。 - -## Registration And Dispatch - -Checker 在所有签名完成后建立 Port contract/implementation table。实现身份来自 adapter role topic;根 `adapter.dever` 使用 `default`。逻辑 Port identity 不包含 Adapter 文件路径。每个可达 Port 必须至少有一个生产实现;不可达声明按既有 unused contract 报 warning。 - -单实现 native call 直接静态调用。多实现生成固定选择和 concrete match,分支调用具体 specialization。effect analysis 在 HIR 中看到生产实现保守并集;failure 摘要固定为声明全集,实现实际失败必须是子集。运行时选择不改变类型正确性。 - -## Settings - -Adapter 文件可声明一个 contextual `setting` record,并以只读 `setting.` 访问。编译器把它纳入共享 setting wire schema。建议 JSON: - -```json -{ - "adapter": { - "notification.mail": { - "use": "smtp", - "setting": { - "endpoint": "https://mail.example.test", - "token": "secret-value" - } - } - } -} -``` - -`use` 在多实现时必需,单实现可省略但若提供必须匹配。端点/证书/凭据属于 Adapter setting;重试业务规则和权限不放配置。错误只报告 Port/Adapter/字段位置,不回显 Secret 值。 - -## Test Fakes - -Test qualified implementation使用相同 signature/failure checker,但 owner 是 TestCase。Suite emission 为每个 case 生成独立 closed binding;case selection 同时选择 test entry 和 fake table。没有 fake 的可达 Port 在测试检查阶段失败,不退回生产 Adapter,确保测试不会意外访问外部系统。 - -## Role Matrix Migration - -`check/symbols.rs` 继续作为唯一 call/type access owner。新增明确矩阵而不是负向条件组合。Model operation owner 检查保持独立但与 role matrix 一致。现有 CMS 尚未使用 Adapter,迁移只需修复拒绝 fixtures 和文档,不保留 App-to-Adapter compatibility。 diff --git a/.trellis/tasks/09-20-port-adapter/implement.jsonl b/.trellis/tasks/09-20-port-adapter/implement.jsonl deleted file mode 100644 index 08364c0..0000000 --- a/.trellis/tasks/09-20-port-adapter/implement.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Source role, visibility, failure and effect contracts"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Native dispatch, setting and official package boundary"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"Transaction effect propagation and settings source"} diff --git a/.trellis/tasks/09-20-port-adapter/implement.md b/.trellis/tasks/09-20-port-adapter/implement.md deleted file mode 100644 index 9593e9b..0000000 --- a/.trellis/tasks/09-20-port-adapter/implement.md +++ /dev/null @@ -1,68 +0,0 @@ -# Dever Port 与 Adapter实施计划 - -## Start Gate - -- [x] secure-data-contracts 和 time-typed-codec 已完成。 -- [x] 用户批准父任务规划。 -- [x] 读取 source layout、parser declarations、symbol access、effects、application testing 和 config owners。 - -## Implementation - -- [x] 增加 Port bodyless contract、fails modifier、AST/formatter/Markdown contract。 -- [x] 注册 Port types/contracts 和 Adapter/Test qualified implementations。 -- [x] 集中实现 role call/type matrix,删除宽泛 private-role互调分支。 -- [x] 检查 implementation signature、outputs、failures、effects 和覆盖完整性。 -- [x] 生成单实现直接调用和多实现 closed dispatch。 -- [x] 增加 Adapter setting declaration、共享 codec 接入和严格 setting.json binding。 -- [x] 把 Port effect 纳入 specialization/transaction/concurrency 检查。 -- [x] 扩展 TestCase fake binding 和 suite case隔离。 -- [x] 更新 LANGUAGE、Markdown、compiler/toolchain/application-testing specs。 - -## Implementation evidence (2026-09-20) - -- 保留 Port 的 Function ID,附加生产实现 successors;shared dependencies/effects/specialization 纳入这些边,failure 直接 seed 声明全集。新 `check/ports.rs` 拥有声明、完整实现、setting schema 和 fake 绑定验证;`native/ports.rs` 生成直接调用/closed match 与不可变 setting/binding。 -- 合同修正:App 只有公开函数且语言用函数分句匹配,故“Port 私有失败再由 App 私有 helper 映射”不可表达。采用主代理确定的 `fails app.ErrorChoice`;App/Port/Adapter 共享已公开错误合同,禁止反向业务调用,不放宽私有类型导出。 -- 每个测试进程选定 case fake;check 与套件生成共用逐 case 的闭合图,Port successors 只替换为该 case 的 fake,生产 Adapter/配置不可达。每个 case 独立原生模块与同步/挂起入口,仍只编译一次套件。一个 case 可完整 fake 多个 Port;缺 fake 编译拒绝。 -- 新反例发现 Port 无 HIR body 导致原有挂起阻塞检查漏过合成 dispatch;已在同一 shared effects owner 校验 Port successors,拒绝挂起 Port 内联选择阻塞实现。 -- 当前已通过:`port_adapter` 10/10(单实现无配置、多实现同二进制切换、Secret setting、错误配置/重复字段、Markdown/fails、角色与 effects、逐 case fake 隔离);`source_architecture` 8/8;`source_visibility` 10/10;`application_config` 3/3;`markdown_source` 20/20。 -- 最终 `core/runtime/CLI` feature check(reference + api + postgres)通过;`application_testing` 8/8;`error_effects::result_capture_requires_matching_success_and_error_variants` 1/1;`git diff --check` 通过。 -- `structured_concurrency` 3/11 通过、8 个旧 fixture 失败:仍把 time/task.sleep 的 Unit 当 SleepResult、chunks 当 ReadStreamResult、直接构造 error variant,以及 Markdown H1 放代码。失败先发生在这些旧协议校验,未扩到无关 fixture 迁移;新 Port 挂起/阻塞定向反例已通过。 -- 未运行全量、外部服务、真实数据库或性能测试;rustfmt/clippy 组件未安装。Port 当前明确拒绝 handler 参数和输入/输出范围 bounds;配置选择/setting 仅原生后端执行,reference 对单个无 setting 实现可执行,其余给显式不支持错误。 -- 已完成清理自审:声明注册与实现注册分开;role I/O 验证收敛到 shared effects;配置可执行目录定位复用同一函数;Port/setting 合成函数不参与重复实现建议。任务状态留给主会话复核后推进,未提交或归档。 - -## Independent review (2026-09-20) - -已修复四项实际问题: - -- 测试 fake 曾在 native 阶段跨 case 合并;一个阻塞、一个挂起 fake 会触发错误的 Port 阻塞诊断。生产合同推断也曾使用 Test body。现在生产推断排除 Test body,check/native 共用 `ports::test_program` 的 case 闭合图;共享 dependency owner 保留未实例化 helper 的声明检查,逐 case 校验所有 fake operation 的 failure 子集。原生套件按 case 生成独立模块与同步/异步入口,仍一次 rustc、一个二进制。混合 fake 回归先失败、修复后通过;同 case 阻塞违规、未调用 fake 的越界 failure、未实例化 pure helper 的副作用均被拒绝。 -- `setting()` 普通函数曾被 parser 误判为 setting record;现在只在 `setting {` 时识别 contextual 声明。 -- 显式 `adapter: null` 曾被 serde Option 吞成缺省,单实现可意外启动;保留原始 null 交给 shared wire validator 拒绝,单实现无文件仍可运行。 -- Port-local DTO 内嵌 App DTO 曾在合同图展开之前触发 C006。现在在 shape access check 前按既有名字解析规则展开合同类型图;合法嵌套 DTO 通过,无关 App 类型仍被拒绝。正例已先复现失败再通过。 - -最终验证:`port_adapter` **10/10**、`application_testing` **8/8**、`source_visibility` **10/10**;core/runtime/CLI `cargo check`(reference + api + postgres)通过。命令使用 stable PATH、CARGO_INCREMENTAL=0、locked/offline、dev/test debug=0、serial tests。`git diff --check` 与本轮修改文件逐文件 `git diff --no-index --check /dev/null` 均无空白错误(后者有文件差异时退出 1,不代表空白错误)。LANGUAGE 与 compiler-contracts 已同步。 - -rustfmt/clippy 未安装,未运行且未安装组件。未运行全量测试、服务、真实数据库或性能测试。此前 structured_concurrency 的旧 fixture 失败记录仍适用,不在本轮扩改。无新增未修复的 in-scope 阻塞;未提交、未归档、未更改任务状态。 - -## Focused Verification - -```bash -cargo check --offline -p dever-core -p dever-runtime -p dever-cli -cargo test --offline -p dever-tests --test source_architecture -cargo test --offline -p dever-tests --test source_visibility -cargo test --offline -p dever-tests --test error_effects -cargo test --offline -p dever-tests --test structured_concurrency -cargo test --offline -p dever-tests --test application_config -cargo test --offline -p dever-tests --test application_testing -cargo test --offline -p dever-tests --test markdown_source -git diff --check -``` - -不运行外部网络、全量测试、真实数据库或性能基准。Adapter runtime 正例使用 test-owned本地确定性实现,不连接服务。 - -## Review Risks - -- Port implementation不能被普通 name lookup 当成可调用函数。 -- 多实现 effect/failure union不能因当前 setting 选择而缩窄静态合同。 -- setting schema identity必须包含实现选择,且错误不得回显 Secret。 -- 单 suite 的 fake registry不能跨 TestCase共享可变状态或生产绑定。 -- role matrix应由一个表/函数拥有,避免 call与type access规则漂移。 diff --git a/.trellis/tasks/09-20-port-adapter/prd.md b/.trellis/tasks/09-20-port-adapter/prd.md deleted file mode 100644 index f905881..0000000 --- a/.trellis/tasks/09-20-port-adapter/prd.md +++ /dev/null @@ -1,42 +0,0 @@ -# Dever Port 与 Adapter - -## Goal - -把外部 HTTP、邮件、对象存储等依赖变成编译期验证、运行时可配置替换的 Port/Adapter 边界,同时收紧应用角色依赖,禁止 App 绕过 Port 和 Domain/Adapter 反向依赖业务层。 - -## Dependencies - -- `secure-data-contracts`:Secret setting 和不可观察边界。 -- `time-typed-codec`:类型化 setting 解码和共享 wire schema。 - -## Requirements - -- `port.dever`/`port/*.dever` 只允许类型和 bodyless function contract;每个 contract 显式 `fails` 同领域 App 公开 error choice 或公开标准 error choice,至少一个显式 error variant。Port 自有 DTO 仍私有。 -- Port contract 输入、命名输出、failure contract 和逻辑身份稳定,不从任一 Adapter 实现反推。 -- Adapter 通过 qualified Port target 显式实现;签名必须相同,实际 failure set 必须是声明集合的子集。 -- Adapter 可包含同文件私有类型/helper,但不能调用 App、Domain、Model、其他 Adapter 或 Port;只能调用标准库和自身 helper。 -- App 只能调用同领域 Port;Domain 只能调用同领域 Domain;Model 无业务函数;API/Job 只调用同领域 App。 -- Port 调用的 suspend/effect 是所有可选实现的保守并集,仍由现有静态 effect 系统决定 worker/await 边界。 -- 单实现自动绑定;多个实现必须由 `config/setting.json` 的稳定 Port identity 选择,未配置、未知实现或未知 setting 字段启动失败。 -- Adapter 可声明一个 typed setting record;只有被选择实现的 setting 必须存在并解码,Secret 字段不进入日志/错误。 -- 编译产物包含闭合实现集合和直接 match,不使用动态库、反射、trait-object business dispatch 或运行时源码扫描。 -- Test 可在同一个测试文件完整 fake 多个 Port;fake 只绑定当前 TestCase,测试不读取项目 Adapter setting 或回退到生产实现。 -- Port/Adapter 的 `.dever.md` 文档合同与普通源码一致。 - -## Acceptance Criteria - -- [x] 合法 bodyless Port 和单 Adapter 可被 App 调用并生成直接静态实现调用。 -- [x] Port body、Adapter 缺失/重复实现、签名/命名输出/failure 不匹配在 check 阶段拒绝。 -- [x] App 直调 Adapter、Domain 访问 Model/Port/Adapter、Adapter 反调 App/Domain/Model 和跨领域 Port 调用全部拒绝。 -- [x] 多 Adapter 通过 `setting.json` 在不重新编译的情况下选择;未知选择、缺配置、未知字段和错误类型启动失败。 -- [x] 未选择 Adapter 的 setting 不要求存在,其代码仍通过静态检查并包含在闭合产物中。 -- [x] Secret setting 可以用于批准 sink,但不能出现在日志、错误、API/Job output 或普通字符串中。 -- [x] 两个应用测试可以对同一 Port 使用不同 fake,单套件编译后各自运行且互不泄漏。 -- [x] Port effect/failure 通过 App、transaction、handler specialization 正确传播,不出现动态 fallback。 - -## Out Of Scope - -- 运行时安装插件、动态库、服务发现和远端代码加载。 -- 跨领域直接共享 Port;领域间继续通过 App 合同协作。 -- 通用依赖注入容器、Service locator 或应用可变全局 registry。 -- Adapter 热切换;setting 在进程启动时验证并固定。 diff --git a/.trellis/tasks/09-20-port-adapter/research/implementation-map.md b/.trellis/tasks/09-20-port-adapter/research/implementation-map.md deleted file mode 100644 index 51e981b..0000000 --- a/.trellis/tasks/09-20-port-adapter/research/implementation-map.md +++ /dev/null @@ -1,138 +0,0 @@ -# Research: Port / Adapter 最小落地路径 - -- Query: 按现有编译器、静态合同、共享 wire、应用测试机制实现 bodyless Port、闭合 Adapter 选择和 case-local fake。 -- Scope: internal -- Date: 2026-09-20 -- Task: `/data/project/dever/.trellis/tasks/09-20-port-adapter`,来自父代理显式分派;本代理 `task.py current --source` 返回 none,未修改 task 状态。 - -## Findings - -### 1. 语法与声明注册 - -现状:`syntax.rs:168` FunctionClause 的 name 是单个 Name,body 为 Vec;`FunctionKind` 只有 Ordinary/Transaction。`parser.rs:685` 强制单名和 `{}`,不存在可复用 bodyless 声明;`function_contracts:718` 已将 pure/recover 作为 contextual Name 处理,可复用 `at_name`,无需新增全局 token 关键字。Parser 已拥有 source layout,但结构只保留 model/application,可增加 role 或必要布尔上下文。 - -建议最小 AST:保留普通 name,不将所有函数名改 Path;加 `implementation: Option`、`failure: Option` 与明确 bodyless 标记(FunctionKind::Port 或独立 declaration kind 均可,不能用空 Vec 判断,因为普通空函数合法)。qualified definition 的末段仍为 name,前缀保存 Port target。仅 Port role 接受 bodyless/fails;仅 Adapter/Test 接受以 port 开始的 qualified definition。普通函数继续当前推断合同,遇到 fails 直接拒绝。Port 仅一个无模式、无 handler 参数的签名起步,拒绝 transaction/recover、重载歧义和多 clause;若要支持 handler 合同,必须额外定义实现方 failure/effect 参数依赖,不能默默沿用未闭合语义。 - -推荐语法(其中 `setting` 是新 contextual record 声明,不是 `type setting`): - -```dever -// module/notification/mail/port.dever -type DeliveryError { - error Unavailable(message: Text) - error Rejected(message: Text) -} -send(message: Text) () fails DeliveryError - -// module/notification/mail/adapter/smtp.dever -setting { - endpoint: Text - token: Secret -} -port.send(message: Text) () { - deliver(message, setting.endpoint, setting.token) -} -// deliver 为同文件 helper;真实外部失败需捕获并映射到 port.DeliveryError - -// test/notification/mail/delivery.dever -port.send(message: Text) () { - assert_eq(message, "hello") -} -delivery() () { - app.deliver("hello") -} -``` - -注意:目前 role 目录至少两文件,不能以只含 smtp.dever 的 adapter/ 作为合法单实现例子。单实现使用 adapter.dever(identity default),多个实现再用 adapter/smtp.dever 与 adapter/local.dever。 - -`check.rs:97-177` 按 qualified name + arity 合并 clauses;qualified 实现必须有自己的物理内部函数 ID,另存 target contract ID,不能注册为原 Port 名或让两个 Adapter 合并成 clauses。`check.rs:236` 先完成全部签名,适合在此后建立 contract/implementation table;bodyless 跳过 clauses coverage/body 输出赋值检查。`check/names.rs:60` 对 qualified 各段独立 snake 检查。`check.rs:485` 现有 Port 一律拒绝应替换成正向声明校验。 - -### 2. 路径、调用与类型权限 - -路径已有足够信息:`source.rs:25-105` SourceRole 含 Port/Adapter,Role 保存 component/domain/topics,Test 保存 component/domain/topic。`check/layout.rs` 负责 role 文件/目录互斥、flat topics、至少两文件;不需新目录体系。 - -`check/symbols.rs:206` can_call 当前:App 能调全部同域 private role;Domain/Model/Port/Adapter 可相互调同域非 App;Test 只能同域 Domain / 任意 App / 自身 Test;API 完全不可作为目标。需要集中 role policy,至少区分 Call 与 Type,不能用同一布尔强行覆盖所有访问。 - -建议调用矩阵:Main→App;API→本域 App;App→任意 App、本域 Domain/Port;Domain→本域 Domain;Adapter→同文件普通 helper;Test→同文件 helper、本域 Domain、任意 App。Port contract 无 body。生产 qualified implementation 永远不能被 source lookup/handler capture 直接引用。Adapter 不能调其他 Adapter 的 helper,即使同域也不行。Model 操作仍由 `check/orm.rs:247-258` 独立限定本域 App,不能只靠 function call 矩阵,因为 ORM bypass 普通函数 lookup。 - -`can_access_type:256` 目前先放行 public Model type、自己文件,然后同域 Domain/Port/Adapter 类型互通;因此“Domain 不访问 Model”“Adapter 不反向依赖业务层”必须同时收紧类型 owner,而不是只收紧调用。建议 Adapter 可引用自身类型、本域所实现 Port 的合同类型、public 标准类型;Port 可引用本 Port 类型/public 标准类型,避免通过 App/Domain 造成反向依赖;Domain 可引用本域 Domain 与允许的 App DTO(若保留现有 business error 约定),但不可访问 Model/Port/Adapter。App 可引用本域 Domain/Port、公开 App/Model,不能引用 Adapter setting/helper type。Test 为 fake 新增本域 Port 类型访问,但不新增直接 Port 调用权限。类型矩阵是否允许 Domain 引用 App DTO 与“Domain 只调用 Domain”并不冲突,需明确不要顺手删除现有 App 错误类型引用约定。 - -重要合同矛盾:`check.rs:559` 拒绝 App 传播 private error 类型。Port 内定义的 DeliveryError 是 private,不能直接从 App 泄漏。最小解法是 App 用既有 result capture + error-only choice wrapper 捕获,再映射 App 自己的公开 error;不要将 Port 类型整体 public 或放开跨域 Port。Port 返回私有 DTO 同理在 App 映射 View。 - -另一个绕过:can_call 在 `target.bundled` 提前放行所有标准公开函数。单纯角色矩阵不能阻止 App/Domain 直接调用 HTTP/socket/process/file,也不能阻止 Adapter 调用 dever.api.serve。若目标包括“不绕过 Port 外部 I/O”,必须添加 capability 校验并覆盖 direct system intrinsics、别名、handler 与间接调用。现有 effects 是 time/network/blocking 等粗粒度,不能只禁止全部 network(API serve 需要);应按具体允许的边界/effect owner 定义规则,不从模块名 substring 猜。需要父代理固定本期准确范围。 - -### 3. HIR / failure / effect / specialization - -`hir.rs:11` Program 存摘要向量,`Function:71` 存普通函数签名与 clauses,`CallTarget:513` 仅 Function/Handler。最低侵入路径:Port 仍拥有一个 Function ID,新增 Program.port_contracts / adapter_implementations;调用保留 CallTarget::Function(port_function),native 对该函数发出 compiler-owned dispatcher。这样签名解析、result、run/blocking、handler reference 继续用一个 ID,不必对所有 CallTarget match 添加 Port 分支。但必须让 contract Function 明确无 body,并在每个分析 owner 注入 Port 摘要和实现边,不能仅生成 native wrapper。 - -推荐数据:PortContract { function, identity, allowed_failures: BTreeSet, implementations: Vec };AdapterImplementation { owner, name, port, operations: BTreeMap, setting_type: Option };TestCase.fake_bindings: BTreeMap。identity 根为 component.domain、topic 为 component.domain.topic;实现 name 为 adapter topic 或 default,不使用 package 路径、源码 ID、排序下标作为 JSON 稳定身份。不同 operation 同名/同 arity 用完整 Port identity 区分。 - -`contracts/dependencies.rs:11` 是共享依赖 owner:contract→所有生产实现;effects/failure worklist reverse callers 必须看到这些边。`specialize.rs:174` Frame::new 当前只遍历 expression static calls,应扩展 synthetic Port successors;`concrete()` 会枚举所有普通函数,也要避免把 fake 当全局生产实现。native `expressions.rs:310` 统一 call_instance/invoke 可复用;dispatcher 每个分支直接调用具体 specialization,并按分支实际 suspension await。所有候选实现必须参与 reachable/codegen,不能按 build-time setting 剪枝,否则无法不重编译切换且 runtime features 错漏。 - -failure 不是简单 union:`contracts/error_effects.rs:42` 每轮从空摘要推断;Port 函数需每轮 seed **声明允许集合**,而非实现实际 union。否则一个实现暂未抛出的声明错误会消失,`result(call)` 精确错误集合验证随实现变化,违反合同稳定性。允许集从指定 Shape::Choice 中 `variant.error == true` 变体映射 `Failure {ty,variant}`;不得按名字或消息匹配。实现实际 program.failures 是允许集子集,且必须无未约束 handler error 集。实现不写 fails;实现 errors 超集在 contracts 完成后报错。凡 choice 非 error variant 不属于允许集;建议要求至少一个 error variant。是否允许 error-free Port 需明确无失败语法,当前 PRD “每个显式 choice”没有表达空集合的办法,不能假造 error。 - -`contracts/effects.rs:228` Effects 摘要要 union 所有候选的 known/recoveries/databases/blocking/suspends/handler dependencies;Port 无 body时目前会推成空。`contracts/failures.rs:571` 为值内 failure obligation,不等于 error_effects 的传播错误,不能混淆。`contracts/facts` / clause bounds 如果 Port 带输出 bounds,需要使用已声明输出保证且严格校验实现,不能因空 body绕过保证。最低范围可拒绝 Port bounds,文档明确,而非静默忽略。 - -### 4. config 与 Secret setting - -`runtime/config.rs:72` Document deny_unknown_fields,目前仅 app/http/database/log;app/log 被丢弃,http 延迟解析。加入 adapter 顶层必须修改此唯一 owner。`Settings::load:138` 使用 serde_json::from_str,map 会丢失重复 key;不要先 from_value 再 wire decode,因为重复 key 已不可恢复。建议 adapter 部分保留 raw JSON 子树或用既有 runtime wire Node 从原文本定位,再交共享 concrete decoder;对 Port key、use、setting 重复/未知字段都严格检查。以 bounded wire parse 先验证整个文档也可,但要确认既有配置大小/深度合同变化。 - -`wire.rs:7` Policy::SettingInput 已允许 Secret;`Schema::build/from_field` 是 eligibility owner,支持 visible record,不允许 bounded/private fields、Choice/Map/ModelId/Related。`native/wire.rs:7` emit 已产生 `_decode(text)` 返回具体 T{id},SettingInput 不产生 encoder;Secret 使用 from_input(text bytes),无 need 自制 JSON 转换。register setting 为 owner-private 合成 record(如物理 Adapter 下 Settings),字段本身不可 private,schema fingerprint 包含 policy/nominal identity。setting 字段读取应新 HIR SettingField 或 Setting record expression;禁止赋值、局部 shadow 绕过、从 Adapter 输出 Secret。无需暴露 generic runtime Value 给业务。 - -JSON 建议仍使用设计稿 `{ "adapter": { "notification.mail": { "use":"smtp", "setting":{...} } } }`:它表达一个 Port identity 选一个实现,该实现完整实现此 Port 的所有 operations。一份 Adapter 实现多个 Port 时,setting 生命周期/多份配置 ownership 尚不一致,MVP 应禁止并以明确诊断说明,或先规定每 Port 独立配置,不能暗中跨 Port 复用某一个 setting。 - -单实现无 setting 时可完全省略 adapter 条目;单实现有 setting 时条目/setting 必需,use 可省略;多实现必需 use;若配置 use 必须匹配。未选实现 setting 不解码,但所有候选源码/Schema 要检查。未知 Port identity 需按编译闭合表拒绝。选中实现无 setting 时若提供非空 setting 应拒绝(建议完全不允许 setting key,规则更清晰)。错误上下文只报 Port/Adapter/字段路径,不回显原值。 - -`config::bootstrap:272` 当前将 settings/数据库初始化与 OnceLock 绑定;`native.rs:96` 仅有 profile 才调用 database setup。Port-only 应用也要初始化选择,不能搭便车要求 database 或 HTTP。建议从数据库 setup 抽取共享 settings 初始化/读访问,再生成 Adapter 初始化,保持只读固定绑定;按全部 required bindings 校验完再执行用户 main 或任何外部 I/O。generated immutable OnceLock 符合“一次启动固定”且不是可变 service registry。Secret 不可 Debug/render、不要 derivation泄漏。 - -`native/build.rs:346` runtime feature selection 与 generated code关联;所有候选 emission保证 HTTP/crypto特征不丢。`native/build/cache.rs:163` cache 包含生成源码和 runtime 输入;选择值不应进入生成源码,metadata/schema/候选集合必须进入。CLI run/build 会预读部署 Settings,须允许新 adapter section且 build不把 use 静态固化;测试运行时不读取部署 Settings。 - -### 5. case-local fake - -`hir.rs:28` TestCase 只有 checked function/span/database metadata;`check.rs` finalize_tests 在 contracts 后;适合加入 fake table 以及每 case Port reachable 验证。相同测试文件就是一个 entry/TestCase,qualified fake 私有实现归属该 owner。fake 与生产实现都走同一个签名/allowed failure checker,fake 不加入生产 adapter table;无 fake的可达 Port check 失败,即使生产恰好单实现也不能退回。 - -`native.rs:142` suite 单次 emit_definitions 全部 test roots,selected index选择 case;`test_runner.rs:70` 每 case 独立进程/临时项目,仅数据库 case写隔离SQLite setting,现成强隔离可复用。 - -建议使 specialization 带 immutable binding context(Production / Test(case id)),并在传播 App/helper/handler调用时保持此上下文,Port 在 Test context仅追加对应 fake successor。同一个 App 被两个 case调用将生成两个必要 specialization,不会共享错误 fake。alternative 是每进程选定 immutable fake dispatch enum,但 suite静态 effect/reachability必须仍排除生产实现,并处理同 App不同 fake suspension;该路线较易误把生产代码/features带入 suite。切忌用可变全局 fake registry且每 case reset。 - -静态生产合同仍是生产实现 effect union,fake不得让业务合同缩窄;测试 codegen可使用各 fake实际 suspension决定 await,但函数签名/specialization应一致,必要时保守 async化。finalize_tests 的 database metadata 要基于 Test context可达集合,防止从生产Adapter推导数据库(理论上Adapter禁止Model操作,但其他effects同理)。测试缺fake检查应检查经App、普通helper、静态handler、run/blocking所有到达路径,不能只扫Test直接calls。 - -### 6. Markdown / formatter - -`format.rs:264-309` 从token重新组装函数名、pure/recover、body;需要输出qualified path、fails类型、bodyless无花括号,保留注释消费顺序。setting 新 Declaration 分支须覆盖 formatter、markdown::declaration_span、source section validation、names及所有 Declaration exhaustive matches。 - -`markdown/contract/model.rs:36/60` 文档函数仅name/inputs/outputs;`metadata.rs:52` strict ordered元数据,建议Port段新增 `- 允许失败:` 只在Port存在,与 AST failure choice精确比较;Adapter段 name 使用完整 `port.send`,无额外猜测。setting段作为独立record-like Section,字段类型/顺序/数量与源码一致。`validate.rs:232` 用 owner + 最后一段函数名 + arity寻找HIR,会错误定位qualified实现,改为AST declaration span或显式 declaration↔HIR ID映射,不能 `.rsplit('.').next()` 猜。public_functions metadata继续角色导出规则,不能把实现列为公开App能力。 - -### 7. 建议分阶段实现与最小定向测试 - -1. AST/parser/formatter/Markdown + contract/implementation registration + role矩阵;只检查,不先运行native。正反例包括Port body、普通fails、qualified非法owner、缺/重复operation、参数类型/输入名/输出名/顺序/arity不匹配、跨域target。 -2. 固定failure declaration seed、effect union、synthetic dependencies、handler/run/transaction分析;测试一个blocking实现+一个suspending实现的保守拒绝、错误子集/超集、捕获声明全集,生产配置不能改变合同。 -3. shared wire setting + strictJSON选择 +直接native dispatch;确定性本地实现两分支,不联网;同一二进制仅换配置得到不同结果、未知use、缺use、未知字段、重复key、错误类型、未选配置不需存在、选中Secret错误不回显。 -4. TestCase绑定与specialization context;两个测试同一个App各自fake结果、同套件单编译、无fake失败、生产配置坏/含真实地址仍不读取、生产实现不作为fallback、case执行失败不影响后续。 -5. 同步LANGUAGE/Markdown/compiler/toolchain与root test fixtures,独立复核。 - -现有入口:`test/dever-tests/tests/{source_architecture,source_visibility,error_effects,structured_concurrency,application_config,application_testing,markdown_source,formatter}.rs`。建议新 `port_adapter.rs` 聚合端到端闭合合同;只运行必要exact测试和cargo check,无真实HTTP/数据库/全量。旧source_architecture中“port reserved”和App→Adapter正例要按新合同更新,不能保留兼容开关。 - -## Related specs - -### 补充:建议本期固定的执行决定 - -Port failure 合同建议本期采用声明全集、实现子集、App显式映射三条规则。普通App不透传Port私有错误;`fails DeliveryError` 只提取error variants,result仍要求全集匹配。先要求每个Port都有至少一个error variant,error-free语法另行设计,避免本期引入第二种fails语义。 - -“App不能绕过Port”必须本期实施,否则PRD目标未满足。最小可执行限制是:App/Domain禁止未经Port边界的 `file` 和 `network` intrinsic可达路径;Domain的Model操作另由既有owner检查拒绝。复用 `contracts/effects.rs:547` 的穷尽intrinsic_effect分类,不另写模块名白名单。新增一个内部摘要 `unmediated_io`,沿普通函数和具体handler传递,但穿过Port contract时清空这一项;正常effect/blocking/suspension摘要仍完整union,不能一并清空。这能允许App→Port→Adapter→HTTP,并拒绝App→helper/标准包装→HTTP。检查direct intrinsic同样经过此摘要,handler绑定用既有specialization保守展开。Adapter只允许自己的helpers/标准库,仍需单独禁止 `ApiServe`,并将该入口限制为Main显式启动;不要把整个network类禁在Adapter上。日志、时间、随机、密码散列、process.arguments本期保持已有授权,不把“Port约束”扩大为全新纯函数制度。若希望Domain完全无任何副作用,属于更强约束,不能偷偷从本期文件/网络隔离推出。 - -- `.trellis/workflow.md`:研究仅写task research;main负责后续 implement/check。 -- `.trellis/spec/backend/compiler-contracts.md`:source角色、App公共边界、failure/effects/shared dependencies、Model owner、Test权限、wire sole owner。 -- `.trellis/spec/backend/toolchain-and-library.md`:Markdown严格合同、native cache/feature选择、配置只用setting.json、Secret不可观察。 -- `.trellis/spec/backend/directory-structure.md`:目录/role归属。 - -## External references - -本研究仅依据当前仓库,不引入新依赖,不需要外部版本或API资料。 - -## Caveats / Not Found - -- 当前没有 bodyless contract、qualified实现、setting record、Port dispatch 或 fake机制;均不能靠修改一条调用矩阵完成。 -- PRD未给error-free Port表示法、App绕过Port的标准库I/O精确限制、跨Port Adapter setting owner;这些应在实现前由主代理用既有范围做一致决定并同步设计。 -- 明确区分“Port已声明failure全集”和“所有实现实际failure并集”;后者不能替代前者。 -- 查不到单独 `.trellis/spec/backend/application-testing.md`,应用测试规则当前在compiler-contracts与toolchain文档;不要引用不存在的规范文件。 -- 未运行测试,未修改源码/规范/状态。 diff --git a/.trellis/tasks/09-20-port-adapter/task.json b/.trellis/tasks/09-20-port-adapter/task.json deleted file mode 100644 index a0980cd..0000000 --- a/.trellis/tasks/09-20-port-adapter/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "port-adapter", - "name": "port-adapter", - "title": "Dever Port 与 Adapter", - "description": "实现可替换 Port 合同、Adapter 实现和 setting.json 绑定,并收紧角色调用方向", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-20", - "completedAt": "2026-09-20", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-20-production-application-language", - "relatedFiles": [], - "notes": "", - "meta": {} -} diff --git a/.trellis/tasks/09-20-production-api/check.jsonl b/.trellis/tasks/09-20-production-api/check.jsonl deleted file mode 100644 index 10b7cb3..0000000 --- a/.trellis/tasks/09-20-production-api/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Bounded HTTP/1, HTTP/2 and resource tests"} -{"file":".trellis/spec/backend/error-handling.md","reason":"Input/API/internal error mapping"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"Thin API owner and shared HTTP path"} diff --git a/.trellis/tasks/09-20-production-api/design.md b/.trellis/tasks/09-20-production-api/design.md deleted file mode 100644 index 2cb9828..0000000 --- a/.trellis/tasks/09-20-production-api/design.md +++ /dev/null @@ -1,130 +0,0 @@ -# Dever 生产 API 边界设计 - -## 2026-09-28 自动权限设计 - -### 静态权限身份 - -权限是 checked HIR 的入口元数据,不是业务 Text 常量。每个非 public API 入口拥有一个 `Permission`:`key/component/domain/site/action/method`。site 由现有目录映射得到,custom action 来自 API 声明,REST 展开为 read/create/replace/delete。key 不包含 HTTP method;同一 component/domain/site 下重复自定义 action 必须静态拒绝。public 入口没有 Permission。 - -权限清单由 native application 内嵌。应用数据库初始化后、服务开始前,Runtime 在控制数据库事务中创建并同步 `_dever_permission`:当前清单 upsert 为 active,清单外旧行标记 inactive。build/check 不连接数据库,同步失败时服务不得启动。 - -### 标准角色存储与请求授权 - -官方 auth runtime 在授权数据库维护 `_dever_auth_role`、`_dever_auth_role_permission`、`_dever_auth_user_role`,并以 `_dever_auth_version` 管理私有 schema。关系使用稳定 permission key,不使用环境相关自增权限 ID。Role 以 `(site, id)` 为身份,user-role 和 role-permission 同样携带 site 复合边界;不同站点可以复用同一角色 ID,且不能互相覆盖或授权。旧单列角色 ID schema 在一个事务中按 role.site 回填关系并替换三表,未知或不完整 schema 拒绝启动。授权只做 allow 并集,`all_permissions` 受 site 和 enabled 限制。 - -verify 输出收缩为 `id: Text, user_id: ModelId?, tenant_id: ModelId?`。Runtime 完成身份 scope 后,使用当前 user、site 和 permission key 对角色关系执行单次 EXISTS 查询;没有用户或授权记录返回 Forbidden。权限不进入 token、Session claims、Identity 或源码能力。租户应用在 tenant scope 内查询本租户角色库;平台入口查询控制数据库。 - -认证、组件可用性、接口授权和业务执行顺序固定为:路由/站点与凭据校验 -> verify -> 建立 tenant scope -> 检查可达租户组件 -> 检查 permission key -> 解码请求与调用 App。public 入口跳过 verify 与角色检查,并且其完整调用图必须静态证明不触达租户组件。 - -角色写入由 Runtime 的窄接口统一完成:列出 active 权限、创建/更新角色、事务替换角色权限、分配/撤销用户角色。写入时验证 site、active permission、角色状态和当前租户;这些能力只能从受保护的写 API 到达,业务组件不直接写私有表。租户 provision 时创建 site-scoped owner role并分配首个用户,避免授权死锁;保留 Owner 不能通过普通 save/grant/revoke/disable 修改。 - -### Job 与租户组件 - -User Job 只保存一个入口 permission key 和既有 provider/site/subject/session/tenant 身份引用。执行顺序固定为重新 verify、确认当前编译权限、检查租户组件、查询当前角色;失败转 blocked 且不进入业务 dispatch。v4 capability 列表迁移到新 schema 时,旧活跃 User Job 统一阻断为 `authorization_contract_changed`,物理删除旧 capability 列,历史终态记录保留。 - -编译器以 tenant Model 和 tenant Job 的静态归属识别租户组件,并为 API/CMD/Job 入口计算可达租户组件集合。混合组件整体视为租户组件,它拥有的全部 Job 都绑定租户队列,即使单个 Job 只访问 global 数据。控制库 `_dever_tenant_component(tenant_id, component, disabled_at)` 只存禁用例外。禁用优先于角色授权,不删除租户数据或改变 schema。 - -### 配置收缩 - -租户配置只有 `database/max_pools/idle_timeout_ms`。`database` 选择控制连接;物理租户数据库仍由现有 database 配置的 tenant target 派生。旧 `mode`、`control_database` 及 table/field 值明确失败,不保留双读或迁移别名。 - -## 2026-09-26 身份、站点与租户修订 - -此节是用户批准后的当前合同,替代旧 Auth Boundary 中的无身份运行时限制。实现仍复用既有 AST/HIR、wire、静态路由、隐藏请求上下文、ORM、Job 和 Port,不增加 Go 应用框架层。 - -### 配置与路由 - -`sites. = { path, auth, hosts? }`。path 相对每个领域 api 目录,只匹配物理父目录(SourceLayout topics 排除文件名),空 path 用于单站根 API。保留完整 topics 生成 URL,站点不改写路径。每条 HTTP API 必须得到无歧义站点归属,Host 是进一步限制,不是认证结果。CMD 不从 HTTP 目录映射取得可信身份。 - -API 仅有 rest 和动词到 App 的绑定,增加单个 HTTP 声明的 public 修饰;禁止源码 site 声明、隐式全站共享接口及强制按站点复制 App/Model。注册后的路由元信息是认证 Provider 选择的唯一依据。 - -### 认证与权限 - -`auth.providers.` 保存凭据验证配置和业务 App verify 引用。配置引用必须经过静态签名/Effect 校验并进入生产调用图、native emission、数据库初始化和 API 契约。密码/角色/成员业务复用账号领域,认证代码并不要求名为 auth 的目录。 - -运行时校验凭据后由受控桥接调用 verify;普通源 record 不能写入当前身份。verify 在租户业务自动事务之前完成。只读上下文包含身份来源、站点和可选用户/租户,不携带权限集合。App 可读 auth,Domain 保持纯规则。租户一经建立在当前调用链内不变,切换接口签发新凭据。 - -操作权限由 API/REST 静态入口自动生成并由 Runtime 查询标准角色关系;源码不登记或检查权限字符串。自动 REST 与 App 共享权限失败及标准 JSON Error 映射。身份对象不包含权限集合或可渲染原始 Token/Cookie。 - -### 数据边界 - -Model 的静态结构与物理存储分离:global 使用平台连接,其他持久化 Model 在 tenant 开启时要求可信租户。持久化模式只支持 database。数据库名只由内部稳定租户标识导出,不提供 table/field 分支。 - -普通 ORM 与自动 REST 使用共同存储/范围合同;不可证明符合隔离的原生 SQL 拒绝。连接由显式可回收拥有者管理,不永久泄漏每租户的 static handle。租户初始化有受控状态与 schema 版本,业务请求不能自行建库。跨平台库引用为逻辑引用,不能产生跨库 FK/Join;写入口只拥有单物理库事务。 - -### 后台执行与差异实现 - -Job 的租户身份由入口系统生成并与入队原子持久化,不信任 payload 内自报身份。User Job 只保存 Provider、站点、subject、session、租户声明和一个入口 permission key,不保存 token 或权限集合;执行时重新调用 verify,并查询最新角色关系复核该权限。受控 System 与 User 身份明确区分,缺少可信身份或旧 schema 不能降级。Worker 使用有界调度,租户任务不得回退平台队列。CMD 使用 System 身份,不能读取 HTTP Header/Cookie 或自报用户。 - -租户功能、额度及配置是业务数据。Port 候选实现静态编译、共享同一签名/失败/Effect 合同,选取依据可信租户配置。log 配置使用现有 logger 并关联调用元数据;runtime 缺省按 API/Job 能力选择模式,显式 CMD 不改变部署配置。 - -### 验证边界 - -先静态反例和 runtime in-process 验证,再生成代码/AOT 及双源码 CMS 定向用例。网络/数据库用例只使用 test 自有临时目录、随机 loopback 端口或明确配置的隔离数据库,运行前说明,不启动现有服务,不运行全量测试,不使用环境变量配置。 - -## Source And Generated CRUD - -本节记录目标方向。声明式 API/CMD、编译器生成入口、基础 REST 和部分隐藏请求上下文能力已实现;Model 字段绑定、可信 `owner`、完整 Cookie 策略、标准 API Error 与 Upload 仍是待实施合同,不能把下述示例全部视为现有语法。 - -```dever -# module/user/profile/model.dever -type Profile { - owner user_id: user.account.model.id = user.auth.id() - name: Text(1, 64) index - bio: Text? -} - -# module/user/profile/api.dever -rest -``` - -路径是 `/user/profile`,不重复目录名。仅当同领域主 Model 唯一时允许无参数 `rest`;多 Model 必须显式指定,歧义时报编译错误。生成 REST 覆盖 GET 列表与 `/{id}` 详情、POST、PUT 全量替换、DELETE,默认只传输本表公开字段和外键 ID,不自动展开或嵌套写关联。分页有界,外部筛选仅允许显式 `search` 或已索引的静态字段,不接受任意 QueryPlan。 - -Model 字段不重复列读/写名单:普通字段由编译器按字段名推导;`create`、`replace`、`search` 表达式仅描述不同的输入来源或纯转换。`owner field = context_read()` 对生成 REST 的创建赋值及所有读写施加同一行范围;GET/PUT/DELETE 的身份条件必须进入同一数据库查询或写语句,客户端不得设置或修改 owner。字段表达式仅在生成的 REST 入口执行,不改变普通 App `model.create/get/...` 的行为。只读上下文能力和纯函数可作为静态调用目标;数据库、网络、任务和写 Effect 不允许出现在字段绑定中。多个接口需要不同权限策略时使用明确的 App 操作。 - -```dever -# 自定义动作才需要 App;App 签名就是 API 输入输出合同。 -post publish = app.publish -cmd rebuild = app.rebuild -``` - -`get`、`post`、`put`、`delete` 是 API 声明而非函数名前缀;`cmd` 独立于 HTTP。GET 调用链禁止数据库写 Effect;POST/PUT/DELETE 和 CMD/Job 的数据库写入在入口调用链自动建立事务,失败或取消回滚。`rest` 与同路径同方法的显式声明冲突时报错,不暗中覆盖。无需 App 透传 CRUD、`crud ... on model`、`expose`、`package` 或手写启动 `main.dever`。 - -应用业务源码由 `//` 唯一确定身份;固定 role 为 app/domain/model/port/adapter/api/job。App 函数均为领域公开能力,Domain 保留私有纯业务规则;topic 文件名不进入 App 调用名。非 API 主题目录只允许一层。App/Domain/Port/Adapter/Job 的根文件与主题目录互斥;主 `model.dever` 可以和附属 `model/.dever` 共存,`api.dever` 可以和 `api/**` 共存。`user/` 仅为 component,`user/profile/` 为 domain。主 Model 的逻辑身份与表名保持 domain 名,附属 Model 的身份与表名取 topic;移动文件不是纯重构。 - -生成的应用入口收集 API、Job 和 CMD;没有命令参数时按 setting 的 runtime mode 启动服务,CMD 由稳定的 `..` 名称和一个 JSON 输入显式选择。CMD 选择不能改写部署配置;没有可运行入口或 CMD 名称歧义时失败。基础 REST 和自定义 HTTP/CMD 共享类型化 wire 与固定 JSON envelope,不能维护第二套动态解码器。 - -函数约束使用已检查 HIR 和生产入口调用图,不按长度或函数数量猜测质量。未被生产入口或其他真实函数引用的私有实现、完全不增加类型/范围/失败/效果合同的私有转发、只有原样 Model CRUD 的公开 App 包装是硬错误。应用 build/run 对不可达 App 能力报错;库式 check 不推测外部调用方,保留提示。W003 相似实现仍是提示,不自动合并不同业务含义。所有分句保持同文件连续声明,合法单用途复杂规则不受影响。 - -## Custom Handler Shapes - -GET/DELETE 从类型化 query/path 输入读取,POST/PUT 从静态 JSON 请求体读取;multipart 入口接收一个包含受限 scalar/Upload 字段的 record。API 自动继承绑定的 App 签名,不再机械重写参数和唯一 `response` 输出。请求值和业务失败继续使用共享静态 codec 与固定 JSON envelope。 - -## Context And Response Metadata - -Runtime 为每个 request 创建仅在调用链内有效的 opaque Context handle,不作为源函数参数传递。受控 API 能力返回复制的 Text 或 Secret 值,并修改 Context-owned response metadata。Native route 在 handler 成功/标准失败后统一合并 headers/cookies 并构造 envelope;handler 不能直接获得底层 Response。 - -Cookie使用具体record/choice表示属性。Secret cookie sink接受Secret并直接编码header,不产生Text中间值。普通response header仅接受Text且经过token/CRLF和forbidden-name检查。 - -## Error Mapping - -官方 `dever.api.Error` 是唯一可离开API handler并被协议映射的error choice。API通常通过 `result(app.call(...))` 捕获业务错误,再用小的API-local clause映射。Native route区分: - -- success -> 200/0/ok/data; -- api.Error ->对应status/code/message/null; -- InputError -> 400; -- other inferred failure/fault -> log request metadata, return generic500。 - -错误message有长度上限且不得包含Secret/private value。业务层不依赖HTTP status。 - -## Upload Lifecycle - -HTTP request reader为multipart路径提供bounded streaming/spool模式。Parser逐part验证headers和limits,将文件写入 `data/tmp` 下create-new随机名,业务只看到opaque Upload、原始filename展示值、declared MIME和size。Scalar fields经过shared decoder。 - -Upload资源owner跟踪临时文件。Storage Adapter通过批准runtime file/stream操作消费并显式commit ownership;未commit drop/close删除。API response完成前检查所有Upload已消费/关闭,防止隐式长期文件。 - -普通JSON路径保留现有bounded full body,因为全局body limit明确;multipart不复用会全量聚合的`Request.body`。 - -## Auth Boundary - -登录、Session 和资源级授权仍由业务实现。业务 verify 向隐藏调用上下文提供只读身份,供 `owner` 绑定或 App 中显式 `dever.auth` 能力使用;接口角色关系由官方 auth runtime 读取。CMD 使用受控 System 身份;认证请求入队的 User Job 持久化最小身份来源和入口 permission key,并在执行时重跑 verify 与当前授权查询。`owner` 只约束自动 REST,手写 App 的 Model 操作必须明确检查其数据范围。 diff --git a/.trellis/tasks/09-20-production-api/implement.jsonl b/.trellis/tasks/09-20-production-api/implement.jsonl deleted file mode 100644 index 479bdc1..0000000 --- a/.trellis/tasks/09-20-production-api/implement.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"API role, typed inputs, public outputs and failure contracts"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"HTTP/native/runtime resource and codec boundaries"} -{"file":".trellis/spec/backend/logging-guidelines.md","reason":"Request context and secret-free error logging"} diff --git a/.trellis/tasks/09-20-production-api/implement.md b/.trellis/tasks/09-20-production-api/implement.md deleted file mode 100644 index c39caf4..0000000 --- a/.trellis/tasks/09-20-production-api/implement.md +++ /dev/null @@ -1,173 +0,0 @@ -# Dever 生产 API 边界实施计划 - -## 2026-09-28 自动权限与租户收口 - -- [x] 用户确认最终方案:API 自动权限、分层权限目录、标准角色关系、database-only 租户、组件禁用例外和 Job 当前权限复核。 -- [x] 修改前完整备份:`/data/project/dever-backups/pre-auto-rbac-20260928-105925/dever.tar.gz`;gzip 校验通过,SHA-256 `700c2756dfcb4c5bceaff9dc1a16b86cfe94599fdeea798740ebc5fe3a461eb0`,约 1.5 MiB。 -- [x] HIR/API checker 生成 custom/REST 权限元数据,public 不生成权限,重复 action 静态拒绝。 -- [x] Runtime 控制库同步 `_dever_permission`,并提供按 component/domain/site/action 分组的只读目录。 -- [x] 官方 auth runtime 建立角色、角色权限和用户角色私有表,提供事务化授权写入与单 key EXISTS 校验;verify Identity 删除 permissions。 -- [x] 删除 `dever.auth.require`、`AuthRequire` intrinsic、源码权限字符串和 Job capability 集合;所有非 public API/REST 在 handler 前自动授权。 -- [x] Job schema 升级并保存单一 permission key;执行时重新 verify 和查询当前角色,旧活跃 User Job 安全阻断。 -- [x] 租户配置改为 `tenant.database`,删除 mode/control_database,不保留兼容分支。 -- [x] 自动识别租户组件,生成入口可达组件集合;实现 `_dever_tenant_component` 和 API/CMD/Job 统一禁用检查及 CLI enable/disable。 -- [x] CMS Dever/Markdown 改为标准角色分配和自动权限;删除 membership 硬编码权限列表及所有手工 require。 -- [x] 增加编译器、配置、Runtime SQLite、Job、组件闭包和双源码 CMS 定向正反测试。 -- [x] 运行允许的最小 cargo check/定向测试、diff 检查和独立终审;真实 PostgreSQL 作为需要外部隔离实例的单独验收项记录。 -- [x] 抽取只读根 `config/setting.json` 的共享 PostgreSQL fixture,并让 ORM 与授权验收复用同一隔离数据库/随机 schema/失败清理合同;SQLite 与 PostgreSQL 授权目标复用同一数据库无关断言。 -- [x] 在真实 PostgreSQL 上运行授权目录、v1→v2 角色迁移、跨站同名角色、多角色、Owner 与失效权限的 ignored 定向验收;2026-09-30 再次通过,使用显式自有实例和临时根配置,结束后恢复配置文件不存在,不探测默认服务。 - -## 2026-09-26 已授权执行清单 - -- [x] 用户批准完整修订方案,并要求修改前备份;认证优先复用现有账号领域。 -- [x] 备份完整工作目录(包含 untracked 源码与 .git,排除 target)到 `/data/project/dever-backups/pre-auth-tenancy-20260926-rm6kL6/dever.tar.gz`;gzip 检查和 tar 对源逐项比较均通过。SHA-256 `e4f0666d054ca241484e8333c16270f039a26c3c616b7ddd0f0bea50476ca9b7`,约 1.4 MiB。 -- [x] 读取现有调用链和规范;确认站点 path 必须匹配 API 父目录,认证 hook 需进入生产根,Model/Job/Adapter 当前启动固定绑定。 -- [x] 配置、目录站点归属、public HTTP 声明、静态认证 hook、只读身份和标准错误。 -- [x] global/tenant Model、database 模式按租户选择物理库、有界池、显式初始化迁移和单库事务。 -- [x] 多用户成员角色示例、能力检查、REST owner 行范围与字段来源;普通 ORM 保持显式业务范围。 -- [x] Job/CMD 可信租户、日志配置、runtime 缺省、app 配置消费者迁移;CMD 不接受 JSON 自报租户/用户。 -- [x] 租户组件启停由核心私有表和受控 CLI 完成;table/field 隔离及租户级动态 Adapter 已被后续 database-only 决策取消,不保留兼容模式。 -- [x] 完成普通/Secret Cookie、标准错误和受限 Upload 合同。 -- [x] Dever/Markdown CMS 同步、定向正反验收和现有规范同步。 -- [x] 独立最终审查收口;限定复核外部 Origin、密码事务、public POST 错误、契约夹具和 Job 身份撤销,未发现 P0/P1 阻断。 - -实施与检查使用 Trellis 子代理;最多两个独立代理并行,共享文件必须先分配唯一拥有者。主会话负责合同、整合及最终证据。现有用户改动不回退、不提交 Git。测试仅限当前改动相关定向目标。 - -## Start Gate - -- [x] secure-data-contracts、time-typed-codec、port-adapter完成。 -- [x] 用户批准父任务规划,并批准 2026-09-25 的文件/函数/入口/API 改造方案。 -- [x] 核对路径冲突、主 Model 推导、CMD 输入合同及现有 API/native/runtime、SourceLayout、ORM、HTTP 边界。 - -## Implementation - -- [x] 收紧 role 布局:Model/API 根文件可与主题目录共存,其余 role 保持互斥;主 Model 身份沿用现有规则。 -- [x] 实现 `get/post/put/delete/cmd/rest` 声明、App 绑定、路径生成与 `{id}` 路由;应用严格模式拒绝旧前缀 API 函数体。 -- [x] 实现生成的 run/build 入口与 CMD JSON 选择;移除维护中 CMS 的手写 main。 -- [x] 实现主 Model 基础 REST:公开字段、GET 列表/详情、POST/PUT/DELETE、静态 SQL 和有界分页。 -- [x] 实现 Model 字段 `create/replace/search` 来源、可信 `owner` 身份绑定与所有自动 REST 读写同语句行范围;普通 App ORM 不受隐式修改。 -- [x] 实现 GET 写 Effect 拒绝和写入口自动事务;覆盖 API/CMD/Job 生成路径,持续补足提交、回滚与取消的定向运行验证。 -- [x] 基于生产调用图拒绝可证明的无用私有函数、无契约纯转发、简单 Model CRUD App 包装及应用构建不可达 App;保留警告和库检查。 -- [x] 扩展 API input shape 检查和 shared decoder generation,CMD 使用同一严格 JSON 对象解析。 -- [x] 增加 runtime 请求级隐藏作用域,不暴露可保存或伪造的 Context 源参数;HTTP/CMD/Job 调用链静态区分。 -- [x] 增加受控 Header 读取/响应写入、Secret Cookie 原始字节的版本化 base64url 读取/写入和 typed CookieOptions;禁止敏感 Header 经 Text 读取、Header 注入及 Secret Cookie 缺少 Secure/HttpOnly。 -- [x] `client_address()` 由 HTTP/1、HTTP/2 的 TCP peer 提供,不信任转发 Header;HTTP/1 loopback 定向验证通过。 -- [x] 拒绝 CMD/Job 或脱离请求的 Task/parallel/blocking 调用 HTTP Context;HTTP/2 并发流的 request id、path、peer 和响应 Header 隔离定向测试通过。 -- [x] 完成普通 Text Cookie 的安全读策略;Secret Cookie 保持独立非 Text 通道。 -- [x] 增加官方API Error及native status/envelope映射。 -- [x] 重构 request read boundary,认证/路由先于正文,multipart 使用 bounded streaming/spool。 -- [x] 增加 affine Upload runtime owner、App→Port→Adapter 单次传递、storage consume/close/cleanup 和 checker 规则。 -- [x] JSON request、request id 与现有 HTTP/1、HTTP/2 dispatch 路径共享;后续仍需定向运行验证 HTTP/2/drain。 -- [x] 更新 README、LANGUAGE、Markdown 语法与 CMS 两套源码,迁移至编译器生成入口;其余协议文档随 Context/Error/Upload 实施更新。 -- [x] Job 私有存储最终升级到 v5:只持久化可复核身份引用和单一入口 permission key,拒绝无身份入队;CMD/cron/Test 显式 System,User 每次执行重新 verify,v4 活跃 User 行阻断并删除旧 capability 列。 -- [x] 响应 Header/Cookie 改为 pending/committed 两阶段,序列化和数据库提交成功后才发布;登录类请求使用严格同源校验,Cookie 签发/清理统一读取配置。 -- [x] PostgreSQL database 租户由显式 `tenant migrate` 通过控制连接幂等创建后迁移;普通请求/worker 保持无创建、无回退。 - -## 2026-09-25 定向结果 - -- `cargo check --offline -p dever-core -p dever-runtime -p dever-cli` 通过。 -- API 声明测试 10/10、语法/格式 22/22、基础 REST 4/4、目录规则 12/12、旧 HTTP 路由 7/7 通过。 -- CMS Dever/Markdown `check`、`fmt --check` 通过;CMS 同源与生成入口测试 1/1 通过。 -- 无 main 的 API/CMD AOT 编译和实际 CMD JSON 调用通过,输出固定 envelope;Job AOT 编译通过。生成入口定向测试 11/11 通过。独立审查指出的必填 Json、事务并发、日志泄漏和 REST Text 边界已修复,并增加定向反例。请求上下文和 TCP peer 测试 5/5、HTTP/2 多路复用定向测试 1/1 通过;CMS 同源测试 1/1 通过。 -- 仍需确定 `owner` 的可信业务 actor 来源,以及声明式 API 如何把 App 业务失败映射到官方 API Error;两项不能用客户端 Header/Cookie 自报身份或让 App 隐式依赖 HTTP 状态来代替。Model `create/replace/search` 绑定、普通 Text Cookie 策略及 multipart Upload 还未实现。 -- 未运行全量测试、服务级 CMS/HTTP 集成测试、真实数据库或性能/内存压测;rustfmt/clippy 组件未安装。 - -## 2026-09-26 身份与配置定向结果 - -- typed `auth/sites/log` 配置、API 物理目录站点归属、单声明 `public`、静态 verify hook、只读 `site/auth` 上下文、HS256 凭据、Cookie Origin 约束和标准 API Error 映射已实现。 -- `app` 顶层配置已移除,性能工具迁移到顶层 `performance`;runtime 缺省按 API/Job 能力推导。UUID 官方 parse/to_text 能力已补齐,供业务会话与租户标识使用。 -- `/root/.cargo/bin/cargo check --offline -p dever-core -p dever-cli` 通过;`/root/.cargo/bin/cargo check --offline -p dever-runtime --features api` 通过;`api_routes` 7/7 通过(含 native/AOT);此前 `auth_runtime` 2/2、`application_config` 5/5、API 声明 14/14、性能工具 Python 测试 40/40 通过。 -- database 模式多租户物理存储、Job/CMD 可信租户、普通 Text Cookie、Upload、REST owner 与字段绑定已经完成;CMS 双源码正在最终复验。 -- 此处当时记录的 table/field 隔离与租户级动态 Adapter 后续已由 database-only 决策取消;当前不保留这些模式或兼容分支。 - -## 2026-09-26 多租户、REST 字段与 Upload 定向结果 - -- database-only 租户已贯通 global/tenant Model、无回退物理库选择、ready/fingerprint、显式 `tenant migrate`、有界池回收、单库事务和 tenant Job 恢复;当前配置入口是 `tenant.database`。SQLite 无回退/幂等迁移 CMD 1/1、tenant Job 物理库隔离 1/1 通过。 -- REST `owner/create/replace/search` 已进入 checked HIR、生产可达图与 native;owner+search 复合索引、双静态 SQL、pure Domain/可信上下文正例和数据库/时间/响应/并发反例通过。SQLite AOT 1/1 通过(74.46 秒)。 -- multipart/Upload 边界 5/5 通过,包含流式分块、limits/重复字段/路径穿越、取消清理、affine 静态反例和 loopback POST→App→Port→Adapter→storage 实际 AOT;临时目录在成功后为空。 -- 写入口事务允许等待完成且目标无数据库/并发的 `blocking`,仍拒绝 `run` 等逃逸并发;自动事务、拒绝反例和显式 transaction 定向 3/3 通过。 -- API AOT 路由复验 1/1 通过;认证运行时此前 2/2、CMD tenant migration 1/1 通过。CMS Plain/Markdown 使用部署 settings 的同源/application reachability 复验 1/1 通过。 -- 未运行全量测试、真实 PostgreSQL、HTTP/2 上传 reset、外部对象存储原子发布、服务压测或性能/内存压测;rustfmt/clippy 组件未安装。 - -## 2026-09-26 可信身份与事务收口结果 - -- CMS Plain/Markdown 的发布操作统一调用 `dever.auth.owns_user(stored.author_id)`;租户 verify 同时要求 `platform.tenant.active`,避免仅凭有效会话绕过资源所有者或停用租户。 -- public API 不再从浏览器 Cookie 建立身份,显式无效 Authorization 仍拒绝;Origin 与 Host 按站点配置的外部 HTTP/HTTPS scheme、主机和有效端口精确匹配,不根据内部监听协议或转发 Header猜测。Cookie 名称、TTL、签发和清理均来自 `config/setting.json`,没有环境变量入口。 -- `_dever_jobs` 当前 v5 区分队列物理租户与执行租户,保存 provider/site/subject/session/tenant 引用及单一入口 permission key;不保存 token、Cookie、角色或权限集合。User Job 每次重试均重新 verify 并查询当前角色,legacy v4 活跃 User 行转为 `blocked/authorization_contract_changed`,匿名/无身份路径不能退化为 System。 -- SQLite 写事务继续 `BEGIN IMMEDIATE`。含 password verify/hash 的 HTTP 调用链不再生成外层事务,编译器要求全部写入进入显式短 `transaction` 并禁止事务内密码计算;CMS 登录在短事务内重新检查账户、租户和成员关系后创建 session。响应元数据只在响应序列化和数据库提交后转为 committed。 -- PostgreSQL 租户迁移会通过配置的控制连接创建派生数据库,SQLSTATE `42P04` 作为并发/重复创建成功处理;尚未连接真实 PostgreSQL 验证权限和服务端行为。 -- 定向结果:核心/runtime 的 API、SQLite、PostgreSQL feature `cargo check` 通过;durable Job 静态、生成入口、SQLite 状态机、v5 迁移/持久化、public 边界和 tenant 隔离各 1/1 通过;认证 runtime 3/3、配置 6/6、安全契约 12/12、生成 User Job AOT 1/1 通过。 -- 新增撤销回归通过 1/1:测试拥有的临时 SQLite 应用先以有效会话入队 User Job,再撤销 session 并启动 worker;任务转为 `blocked/identity_rejected`,业务副作用表保持为空。该验证使用临时 loopback 与子进程,无外部服务。 -- 密码窗口并发回归包含在安全契约中:账号读取与 session 短事务之间模拟密码计算,同时另一连接可完成无关写入;短事务重新读取状态后正常创建 session,不持有跨密码计算的 SQLite 写锁或旧读快照。 -- CMS Plain/Markdown `check` 与 `fmt --check` 均通过;两套源码/Model/API/config 同源检查 1/1 通过。两套 `check` 各保留 3 个预期 W001,不影响编译。 -- 独立终审只读复核上述五项实现与执行路径,未发现 P0/P1 阻断;真实 PostgreSQL、性能、table/field 和动态 Adapter 不属于本轮收口范围。 -- 未运行全量测试、持久服务、真实 PostgreSQL、HTTP 集成、性能/内存压测;rustfmt/clippy 组件未安装。table/field 租户隔离和租户级动态 Adapter 仍按已确认范围延期。 - -## 2026-09-28 自动权限与租户收口结果 - -- 权限由 checked HIR 自动生成,custom 使用 action,REST 使用 `read/create/replace/delete`;method 仅作元数据。跨 method/path 重复 key、public 触达租户组件、public/GET 调用角色管理能力均在 native 前拒绝。 -- `_dever_permission` 在服务启动前同步;授权库使用版本化 `_dever_auth_role`、`_dever_auth_role_permission`、`_dever_auth_user_role`,三表以 `(site, role_id)` 隔离同名角色,旧单列 ID schema 事务迁移并保留授权数据。精确权限使用索引化 EXISTS,多角色取并集,`all_permissions` 只覆盖同站点。保留 `_dever_owner:` 只能由 `tenant owner` provision,普通 save/grant/revoke/disable 全部拒绝。 -- Identity 已固定为 `id/user_id/tenant_id`;源码 `auth.require`、AuthRequire intrinsic、权限列表和 Job capability 集合已删除。受保护 API 顺序固定为 verify、tenant scope、组件检查、精确权限、输入解码和 App。 -- Job 已升级到 v5,只保存一个入口 permission key;每次执行按 verify、编译目录、租户组件、当前角色的顺序复核。v4 活跃 User Job 迁移为 `blocked/authorization_contract_changed` 并删除旧 capability 列,System 任务保持可执行。 -- 租户只支持 `tenant.database/max_pools/idle_timeout_ms`。租户组件从 tenant Model/Job 自动推导,混合组件拥有的全部 Job 统一使用租户队列,并通过 `deverc tenant component enable|disable` 控制;public 入口不能静态触达租户组件。 -- CMS Plain/Markdown 已同步为核心角色管理薄适配,admin/front 各有同站点管理入口,启动说明要求迁移后分别 provision Owner;membership 只表达业务成员关系。两套 `test` 此前各 1/1 通过;本次最终源码改动后,两套 `check`、`fmt --check` 及当前编译器双源码同源/完整应用可达检查通过,check 仅保留 3 个既有 W001。受磁盘空间限制未重复链接两套完整 CMS 测试程序。 -- 定向验证通过:core/runtime/CLI cargo check;`application_config` 6/6、`api_declarations` 16/16、`contract_api` 9/9、`auth_runtime` 3/3、`authorization_runtime` 1/1(含旧角色 schema 迁移与跨站同名角色);REST 权限、Identity、Job v4->v5 删列、撤销后 Job 阻断、混合组件 Job 租户 AOT、租户组件 disable/enable、CMS 双源码同源及受保护 auth/Job 顺序 AOT 各 1/1。 -- 两轮独立终审指出的站点角色主键、混合组件 Job、CMS 首次 Owner、v5 旧列、Job 复验顺序和旧授权 schema 升级问题均已修复并复验;最终未发现新的 P0/P1。 -- 未运行全量 workspace 测试、真实 PostgreSQL、持久服务或性能/内存压测;rustfmt/clippy 组件未安装。本轮实现没有环境变量配置入口。 - -## 2026-09-28 PostgreSQL 授权验收准备结果 - -- 新增共享 PostgreSQL 测试 fixture,只接受仓库根 `config/setting.json` 的 `database.postgres_test`;URL 的数据库名必须包含且只包含一个 `{case}`。fixture 为每个目标派生专用数据库名并创建随机 schema,测试成功或 panic 后都从独立 runtime 尽力清理。 -- `postgres_orm` 已迁移到共享 fixture;新增 ignored `authorization_postgres` 目标。SQLite 与 PostgreSQL 共用唯一授权合同,覆盖权限目录、旧 v1 schema 数据保留迁移、跨站同 role id、多角色并集、角色禁用/撤销、保留 Owner 限制和失效权限拒绝。 -- `/root/.cargo/bin/cargo check --offline -p dever-tests --features api,postgres --test postgres_orm --test authorization_postgres` 通过;SQLite 授权 exact 1/1 通过。无 feature 的 `syntax_and_format` 与仅 SQLite 无 API 的 `sqlite_orm` 编译检查由实施子任务验证通过。 -- 独立检查发现 PostgreSQL URL 的 `dbname` 查询参数可覆盖路径数据库,已拒绝明文和百分号编码的覆盖形式;纯 URL 隔离回归 1/1 通过。复验期间磁盘一度归零,两个重复定向链接已中止并清理本轮生成的可重建测试二进制/增量对象,未删除源码、配置或用户数据。 -- 真实 PostgreSQL 未运行:仓库根当前没有 `config/setting.json`。测试不会读取环境变量或命令行连接覆盖,也不会自动连接、创建或清理未明确配置的数据库。 -- `cargo fmt --all --check` 未运行成功,因为 rustfmt 组件未安装;新增 Rust 已手工按现有样式整理。 - -## 2026-09-29 真实 PostgreSQL 定向验收 - -- 使用仓库根 `config/setting.json` 的 `database.postgres_test` 配置(测试凭据仅存在于被 `.gitignore` 忽略的临时文件,验收后已删除),在本机隔离 PostgreSQL 数据库上运行 `authorization_postgres` ignored 定向目标,1/1 通过。 -- 本次实际覆盖权限目录同步、v1 角色 schema 迁移、跨站点同名角色、多角色权限并集、角色禁用、用户角色撤销、Owner 保留限制和失效权限拒绝;测试使用随机 schema,临时数据库在验收后清理。 -- `postgres_orm` 未通过,失败发生在数据库连接前的共享 fixture 编译阶段:旧 fixture 仍从 `main.dever` 调用 `user.create`,当前 Model 规则要求 Model 操作只在 owning-domain App 中调用。SQLite 共享 fixture 同样复现该编译失败,因此这是独立的 ORM fixture/语言契约迁移项,不是 PostgreSQL 实例或配置问题。 -- 没有读取环境变量或命令行连接覆盖;仓库工作区未保留真实 PostgreSQL 凭据或 `config/setting.json`。 - -## 2026-09-30 当前 PostgreSQL 组合补验 - -- 共享 ORM fixture 已按 owning-domain App/Model 合同迁移,真实 PostgreSQL ORM/授权 Store ignored 各 1/1 通过,旧 09-29 ORM 失败已关闭。 -- `postgres_api` exact ignored 1/1 通过 stock Dever CMS 的真实 HTTP、两个物理租户数据库、同 slug 独立发布、跨站 Cookie/跨租户登录拒绝、普通非 Owner 的多角色/跨站同名角色及同一会话撤销立即失效。测试注册仅在副本追加 `test/dever-tests/fixtures/postgres_api/` 片段,不修改生产 CMS 或 Owner 保留角色规则。 -- 新报告 `target/performance/postgres-http-09-30-v1/report-1968019-1790739069361983512.json`;`test-rbac-final.log` 和 `server-rbac.log` 保留真实结果与服务日志。失败轮的站点目录读取和 DELETE body 工具错误已按现行合同修正,未放宽 checker/runtime。 -- 临时控制库/租户库全部清理,自有 PG 已停,根 `config/setting.json` 恢复原先不存在;PG 下载/数据目录移入回收站可恢复。Python 工具 57/57、Rust postgres_api 非 ignored 3/3;不宣称 Markdown PostgreSQL/HTTP2 所有组合或全 workspace 复验已运行。 - -## Focused Verification - -```bash -cargo check --offline -p dever-core -p dever-cli -cargo check --offline -p dever-core -p dever-runtime --features dever-runtime/api,dever-runtime/sqlite,dever-runtime/postgres -cargo test --offline -p dever-tests --features api,crypto,sqlite --test secure_contracts --test auth_runtime --test application_config -cargo test --offline -p dever-tests --features api,crypto,sqlite --test durable_jobs revoked_user_job_is_blocked_before_business_dispatch -- --exact -cargo test --offline -p dever-tests --features api,crypto,sqlite --test contract_execution cms_formats_share_source_model_api_and_configuration_contracts -- --exact -cargo test --offline -p dever-tests --features api,postgres --test authorization_postgres postgres_authorization_preserves_site_scoped_roles_and_catalog -- --ignored --exact -cargo run --offline --quiet -p dever-cli -- check examples/cms/dever -cargo run --offline --quiet -p dever-cli -- check examples/cms/md -cargo run --offline --quiet -p dever-cli -- fmt examples/cms/dever --check -cargo run --offline --quiet -p dever-cli -- fmt examples/cms/md --check -cargo test --offline -p dever-tests --features api --test api_routes -cargo test --offline -p dever-tests --test http_engine -cargo test --offline -p dever-tests --test http2_server -cargo test --offline -p dever-tests --test logging -cargo test --offline -p dever-tests --test pooled_network -cargo test --offline -p dever-tests --test source_architecture -cargo test --offline -p dever-tests --test markdown_source -git diff --check -``` - -上传测试只使用test-owned临时目录和bounded loopback peer,提前说明后运行;不启动持久服务、外部网络、全量测试或性能基准。 - -## Review Risks - -- Context/Upload不能通过record、Task、Channel、App参数或输出逃逸request scope。 -- multipart错误/取消所有路径必须删除已创建part,且不能信任filename作为路径。 -- Secret cookie不能生成可被Render/log捕获的中间Text。 -- API Error必须与未知App failure区分,不能把内部错误message返回客户端。 -- HTTP/2并发stream的Context/temporary ownership不能串请求。 -- 目录或文件重排不得隐式改变 Model identity、表名、App 调用名和 API 路由;旧 API/Main 方案不能与新方案共存。 diff --git a/.trellis/tasks/09-20-production-api/prd.md b/.trellis/tasks/09-20-production-api/prd.md deleted file mode 100644 index cd79dea..0000000 --- a/.trellis/tasks/09-20-production-api/prd.md +++ /dev/null @@ -1,86 +0,0 @@ -# Dever 生产 API 边界 - -## 2026-09-28 自动权限与 database-only 租户修订 - -本节替代下文所有关于手写 `auth.require`、verify 返回权限列表、框架不提供 RBAC、`tenant.mode`、`tenant.control_database`、table/field 租户模式和 Job capability 列表的旧合同。 - -- `public` 是唯一匿名入口。所有非 public HTTP API 默认同时要求可信身份和当前接口权限;源码不得手写权限字符串或调用 `dever.auth.require`。 -- 编译器根据 `//api//**` 和 API 声明自动生成权限目录。权限 key 为 `component.domain.site.action`;HTTP method 只保存为元数据,不进入 key。`rest` 自动生成 `read/create/replace/delete`,自定义 API 使用声明 action。public API 不生成权限项。 -- 权限目录由构建产物携带,并在应用初始化时幂等同步到控制数据库 `_dever_permission`;移除的 API 标记 inactive,不直接删除授权历史。源码、组件和业务代码不注册权限。 -- 官方 auth runtime 提供租户内 `_dever_auth_role`、`_dever_auth_role_permission`、`_dever_auth_user_role`。用户只通过角色取得权限,多角色取并集;不支持直接用户授权、deny、角色继承或权限优先级。`all_permissions` 仅覆盖同一站点的 active 权限。 -- verify 只建立 `id/user_id/tenant_id` 可信身份,不返回权限列表。Runtime 针对当前 permission key 做索引化 EXISTS 查询,不把大量权限写入 JWT、Session 或请求上下文。`dever.auth` 只公开身份读取及签发/清理凭据能力。 -- API 权限只决定能否调用动作。资源归属、状态流转和其它数据权限仍由 App 读取可信身份后调用纯 Domain 规则;Domain 不读取隐式身份。未认证返回 401,接口权限或业务授权失败返回 403。 -- 多租户只保留 database 隔离。配置改为 `tenant.database`,删除 `tenant.mode` 和 `tenant.control_database`,不保留兼容分支。 -- 编译器自动识别组件:拥有 tenant Model 或 tenant Job 的组件属于租户组件,其余为平台组件;混合组件按租户组件处理。租户组件默认启用,控制库 `_dever_tenant_component` 只保存禁用例外。入口携带静态可达组件集合,Runtime 在 API/CMD/Job 入口统一检查。 -- User Job 保存可重新验证的身份引用和一个发起操作 permission key,不保存权限集合;每次执行前重新 verify,并按当前角色关系复核该 permission。旧 capability schema 的活跃 User Job 在迁移时阻断,不能降级为 System。 -- `_dever_permission` 和 `_dever_tenant_component` 是 Runtime 私有控制表;角色表由官方 auth runtime 统一拥有。项目仍拥有 User、Session、Tenant 业务 Model。 - -## 2026-09-26 已批准修订 - -用户已批准在备份后实施完整站点、可信身份、多用户权限和多租户方案。本节替代下文涉及身份、租户、入口配置的旧限制;尚未完成的字段绑定、Cookie、标准错误和上传仍属任务,不因新增范围而消失。 - -- `sites..path` 是每个组件/领域 `api/` 下的相对源码目录,递归包含子目录;不是 URL 前缀。`admin` 只匹配 `api/admin/**`,不能匹配同名 `api/admin.dever`。URL 保持现有组件/领域/API topic 生成规则,不增加源码 `site` 声明。站点匹配遗漏、歧义和路由冲突在服务开始前拒绝。 -- `public` 只修饰 HTTP API 声明,普通接口默认认证。站点选择配置中的认证 Provider,Host 可进一步约束入口;客户端提供的站点/用户/租户值不能自行成为可信身份。 -- Provider 验证签名和站点凭据后,调用静态检查的业务 App verify,检查账号、会话、成员关系并建立只读 `site.key`、`auth.id/user_id/tenant_id`。优先复用已有账号领域,不要求新建 `auth` 领域或 `admin` 组件。 -- 身份、接口权限和数据范围分别检查。接口权限由 Runtime 自动校验,数据范围由业务 App/Domain 处理,所有入口不能绕过对应边界。 -- 开启多租户后,普通持久化 Model 属于当前租户,`global` Model 使用平台库;只支持 database 分库。不影响普通 DTO,不因缺租户而回退平台库。CRUD、REST、统计、关联和批量路径共用隔离合同。 -- 租户连接池有界且可回收;初始化/迁移属于受控租户生命周期。跨库引用保留类型但不能隐式建立物理外键/Join;自动事务只覆盖一个物理数据库。隔离模式切换必须经过数据迁移。 -- 租户功能开通和规则配置属于业务数据;实现差异复用已编译 Port/Adapter。禁止租户 ID 分支、复制整套项目或执行数据库内代码。 -- Job 原子入队并保存受控租户/执行身份,执行时恢复并复核资格;CMD 不能通过自报用户 ID 伪造身份。日志关联站点/身份/租户而不泄漏凭据。 -- 所有部署配置仅来自 `config/setting.json`,无环境变量。保留并应用 log,runtime 可选并按能力选择服务,移除无用途 app 配置及迁移其工具消费者。 -- 同步 Dever/Markdown CMS,验证站点目录、跨站凭据、两个租户相同记录 ID、不同角色、匿名边界、Job 上下文、事务回滚和平台共享数据。 - -本轮已完成并逐项比对的修改前备份:`/data/project/dever-backups/pre-auth-tenancy-20260926-rm6kL6/dever.tar.gz`。SHA-256:`e4f0666d054ca241484e8333c16270f039a26c3c616b7ddd0f0bea50476ca9b7`。 - -## Goal - -在保持固定 JSON envelope 的前提下,以 Model + `rest` 覆盖受约束的普通 CRUD,以显式 API 动词绑定 App 业务动作;同时让 API 安全承载结构化请求、会话 Cookie、显式业务错误、隐藏请求上下文和受限文件上传。本任务正在实施,以下是完整目标合同;已实现的子集以 implement.md 为准。 - -## Dependencies - -- `secure-data-contracts`:Secret Cookie/token 和私密输出拒绝。 -- `time-typed-codec`:结构化请求/响应和完整标量 codec。 -- `port-adapter`:上传后的对象存储由业务 App 调用 storage Port。 - -## Requirements - -- API 使用 `get`、`post`、`put`、`delete`、`cmd` 和 `rest` 声明;移除 `get_`/`post_`/`delete_` 前缀语法,不加入 `patch`。同领域唯一主 Model 可由无参数 `rest` 推导,自动路径为 `//`;自定义动作以 `post publish = app.publish` 等形式绑定 App 签名。 -- 纯 CRUD 无需 App;编译器生成的 `rest` 才可直接降低到同领域 Model 操作。手写 API 不直接调用 Model;需要业务处理时调用同领域 App。App 中所有函数都是领域公开能力,私有辅助逻辑归 Domain,不增加 `expose` 或 `crud ... on model` 声明。 -- Model 普通字段按名称推导 CRUD 输入输出;只有例外才声明 `create`、`replace`、`search` 或 `owner` 字段绑定。`owner = ` 为自动 REST 创建赋值及 GET/PUT/DELETE 行范围,客户端不能覆盖。字段绑定表达式只能使用静态类型可检查的纯计算或只读上下文能力,禁止数据库、网络和写 Effect;它们不隐式作用于手写 App 的 Model 调用。 -- `get` 调用链禁止数据库写 Effect;`post`、`put`、`delete` 写调用链默认同一事务。`cmd`、Job 的数据库写入也按 Effect 建立事务,不依赖 HTTP 动词。无需在 App 源码重复声明 `transaction`。 -- 源码身份固定为 `//.dever[.md]`,role 只接受 `app/domain/model/port/adapter/api/job`。一个领域优先每个角色一个文件;按主题拆分时非 API 主题只允许一层。App、Domain、Port、Adapter、Job 的根文件与主题目录互斥;主 `model.dever` 可与附属 `model/.dever` 共存,基础 `api.dever` 可与路径分组 `api/**` 共存。主题必须表达业务含义,不按函数机械拆文件;搬动 Model 文件可能改变持久化身份,不能作为无迁移的整理。 -- `deverc run/build` 的目标入口由编译器生成,不要求应用编写 `main.dever`。无命令参数时按 `config/setting.json` 启动 API/worker;指定 CMD 时命令行 JSON 由该 CMD 的静态签名解码。没有可运行入口时报错;部署选择继续只读 `config/setting.json`,不用环境变量覆盖。 -- App 函数只表达有生产用途的公开业务能力;私有纯业务规则属于同领域 Domain。静态拒绝可证明无生产调用的私有函数、没有增加契约的纯转发以及只透传 Model CRUD 的 App 包装;应用构建还应拒绝不可达的 App 能力,测试调用不算生产用途。结构相似但业务含义可能不同的实现先保留警告,不用函数数量或行数配额。 -- 保留 JSON envelope:成功 HTTP 200、`code=0`、`message="ok"`;错误使用 HTTP status 对应数值 code,`data=null`。 -- GET/DELETE 接受 wire-safe scalar 和 nullable query 参数;POST/PUT JSON 使用静态类型请求体,不接受动态字段名或任意查询 Map。 -- POST multipart 接受一个包含受限 scalar/Upload 字段的 static record;JSON 和 multipart 模式由签名静态决定且互斥。 -- Runtime 隐式传递请求上下文,不在业务函数签名中声明 `dever.api.Context` 参数,也不允许存储或输出。API 的受控能力提供 request id、method/path、受信任边界内的 client address、受限 Header 读取、Text/Secret Cookie 读取,以及受控 response Header/Secure Cookie 写入;身份解析仍由业务实现。 -- Header name/value严格校验;禁止应用设置Content-Length、Transfer-Encoding、Connection和原始Set-Cookie。Cookie属性使用typed API并限制Domain/Path/SameSite/Secure/HttpOnly/Max-Age。 -- 自定义 API handler 必须把业务失败显式映射为标准 `dever.api.Error`:Invalid/Unauthorized/Forbidden/NotFound/Conflict/TooManyRequests。生成的 REST 使用固定输入、归属和数据库错误映射;未捕获失败返回通用 500 并只写脱敏结构化日志。 -- API response继续直接返回静态业务值,不暴露 `dever.http.Response`,不允许自定义绕过envelope的JSON。 -- Upload采用流式读取到runtime-owned临时文件或等价有界spool,不将大文件整体复制到内存;限制总字节、单文件、part数、字段数、header和filename长度。 -- Upload filename不作为路径,MIME只作声明且需业务/Adapter复核;拒绝路径穿越、重复字段和不完整multipart。 -- Upload handle为affine资源:必须由批准storage操作消费或显式close;正常、失败、timeout、取消和进程退出均清理未接管临时文件。 -- 登录、Session 和资源级授权由项目 App/Domain 实现;接口 RBAC 由官方 auth runtime 自动执行,不增加业务 middleware。 - -## Acceptance Criteria - -- [x] `rest` 自动生成 GET 列表/详情、POST、PUT、DELETE;显式动词/CMD 和固定 envelope 在 Dever 与 Markdown 源码中一致,DateTime 等标量按 shared codec 格式。 -- [x] 路径、角色、Model 自动识别、字段绑定 Effect、`owner` 的所有 REST 读写范围和无歧义规则均有正反例;手写 App Model 调用不受 REST 字段绑定的隐藏影响。 -- [x] GET 写入被静态拒绝,POST/PUT/DELETE 及 CMD/Job 写调用链的提交、错误回滚和取消行为有定向验证。 -- [x] POST/PUT record 和 GET/DELETE query/path 严格验证 duplicate/unknown/missing/type/size;非法输入返回 400 固定 envelope。 -- [x] 请求上下文由 runtime 隐式传递,客户端无法伪造;源码不得声明、存储或返回原始 Context。 -- [x] Cookie parse/write覆盖Secure/HttpOnly/SameSite/Path/Max-Age,header injection和受禁header拒绝。 -- [x] Secret session token不能日志/JSON/string泄漏,但可通过typed secret cookie sink发送。 -- [x] 标准API Error映射到400/401/403/404/409/429;未映射App failure返回脱敏500。 -- [x] multipart正常上传不全量驻留内存;越界、畸形、取消和handler失败后无临时文件残留。 -- [x] 手写 API 只绑定同领域 App;自动 REST 仅通过编译器生成的 Model 路径。认证示例由业务解析会话并提供只读身份能力。 -- [x] HTTP/1和HTTP/2已有deadline、request id、connection drain回归不退化。 -- [x] Model/API 根文件和主题目录共存、其他 role 冲突、无 main 的 run/build/CMD JSON、缺少入口以及无意义私有/App 包装都有正反测试;合法单用途业务规则和库检查不被误拒绝。 - -## Out Of Scope - -- GraphQL、gRPC、WebDAV和任意动态路由。 -- 外部 IAM、OAuth Provider、直接用户权限、deny、角色继承和复杂策略语言。 -- front CORS策略和浏览器页面。 -- 断点续传、分片合并、病毒扫描和对象存储协议;由后续业务Port/Adapter扩展。 diff --git a/.trellis/tasks/09-20-production-api/task.json b/.trellis/tasks/09-20-production-api/task.json deleted file mode 100644 index bb579ca..0000000 --- a/.trellis/tasks/09-20-production-api/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "production-api", - "name": "production-api", - "title": "Dever 生产 API 边界", - "description": "补齐结构化请求、请求上下文、Cookie、响应 Header 与受限上传能力", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-20", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-20-production-application-language", - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/09-20-production-application-language/check.jsonl b/.trellis/tasks/09-20-production-application-language/check.jsonl deleted file mode 100644 index 05738cb..0000000 --- a/.trellis/tasks/09-20-production-application-language/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused verification and no-full-suite policy"} -{"file":".trellis/spec/backend/error-handling.md","reason":"Diagnostics, failure propagation and cleanup review"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"Owner boundaries and duplicate implementation review"} diff --git a/.trellis/tasks/09-20-production-application-language/design.md b/.trellis/tasks/09-20-production-application-language/design.md deleted file mode 100644 index 6a0299f..0000000 --- a/.trellis/tasks/09-20-production-application-language/design.md +++ /dev/null @@ -1,113 +0,0 @@ -# Dever 生产级大型应用语言支持设计 - -## 1. Delivery Shape - -父任务只拥有跨阶段合同、子任务顺序和最终集成验收,不直接实施源码。六个子任务按下列依赖执行: - -```text -secure-data-contracts ---+ - +--> port-adapter --------+ -time-typed-codec --------+ +--> large-cms-acceptance - +--> durable-jobs --------+ - +--> production-api ------+ -``` - -Port 的类型化配置依赖 Secret 和 typed codec;Job 依赖 DateTime、typed codec 和数据库事务;生产 API 依赖 Secret、typed codec 和既有 HTTP 引擎。CMS 只在所有语言能力分别通过后扩展。 - -## 2. Source Architecture - -最终角色矩阵: - -| Caller | Allowed application targets | -| --- | --- | -| Generated entry | configured API/Job startup and shutdown | -| handwritten API | own-domain App | -| generated REST | own-domain Model operations under checked field/access rules | -| Job | own-domain App | -| App | own Domain, own Model operations, own Port, any App | -| Domain | own Domain | -| Model | no business functions; field bindings are checked at generated REST entry | -| Port | declarations only | -| Adapter | implemented Port target, same-file helpers, bundled packages | -| Test | same-domain App/Domain, any App, test-local Port fakes | - -Type visibility is narrower than call visibility. App contracts may use public business records and Model IDs, but cannot expose private Model fields, Adapter/Domain implementation types or non-observable runtime resources. Port types remain domain-private. Job/API types must pass the shared wire-schema validator. - -## 3. Shared Static Value Schema - -The checker derives one internal wire schema from existing concrete `Type` and `Definition` data. It is compiler metadata, not a source-visible reflection API. Three emitters consume it: - -- setting decoder: strict JSON object to concrete Adapter/runtime settings; -- Job codec: concrete payload to/from persisted JSON bytes plus schema fingerprint; -- API codec: query/JSON request decode and response encode. - -Private fields, Secret and resources are represented in the schema policy, not rediscovered by each emitter. The runtime may reuse bounded JSON token parsing and scalar conversion, but generated programs retain concrete Rust values; no universal application `Value` interpreter crosses business calls. - -## 4. Secure Values And Model Privacy - -`Secret` is an opaque source scalar with no Render, comparison, ordinary JSON, Map-key or Model storage implementation. Approved constructors are secure random/token generation and typed setting/API decoding. Approved consumers are password/HMAC operations and narrowly typed transport sinks such as secure Cookie or bearer-auth construction. Secret cannot be converted to Text by a generic helper. - -Model `private` fields remain stored normally but receive domain-owned access metadata. Generated CRUD blocks in the owning App may assign them; field projection is available only to that App. A type containing a private Model field is rejected at App public signatures, API/Job wire boundaries and test assertions. This keeps the existing Model record internally useful without adding DTO directories; App declares explicit view records beside capabilities. - -Password hashing uses a maintained Argon2id implementation with runtime-selected secure salt and encoded hash text. Verification accepts Secret plaintext plus stored private hash and returns Bool/failure without exposing intermediate bytes. Security parameters are named runtime constants with tests, not application configuration knobs. - -## 5. Port And Adapter Dispatch - -Port role declarations use bodyless function signatures and explicit allowed failure choices. Adapter/Test sources may define a qualified Port implementation; ordinary unqualified functions remain local helpers. The checker builds one Port contract and statically verifies implementation inputs, named outputs and effective failure subsets. - -Single implementation binds directly. Multiple implementations receive a compiler-generated closed enum and direct match; `config/setting.json` selects one stable implementation identity. This is runtime selection among compiled functions, not dynamic linking or trait-object business dispatch. Only the selected implementation's setting object is required and decoded. - -Test-local fakes are associated with the owning TestCase. The single compiled test suite contains all fakes, while the selected case installs only its own compile-checked binding before entry. Production bindings and project deployment settings are not read by application tests. - -## 6. Durable Job Data Flow - -Each Job contract has a stable logical identity, concrete input shape, schema fingerprint, logical database binding, timeout and retry policy. Job inputs are zero or one wire-safe record; outputs are empty. Job handlers are registered entries and cannot be called as ordinary functions. - -```text -App write call under an automatically owned entry transaction - -> typed enqueue/schedule(job target, payload, dedupe key) - -> hidden transaction context writes _dever_job row - -> business rows and job row commit together - -Job worker - -> atomically claims due row with lease - -> decodes exact schema - -> calls own-domain App - -> marks success, schedules retry, or moves to dead-letter -``` - -SQLite uses a short write transaction and compare-and-update claim. PostgreSQL uses row locking/skip-locked semantics and the existing typed driver boundary. Leases have owner and expiry so a terminated worker does not permanently lose a task. A completed external side effect followed by process failure may execute again; this is documented at-least-once behavior. - -Immediate and one-shot scheduled tasks are inserted by App calls. Recurring UTC schedules are compile-time validated declarations and materialize deterministic slot keys so multiple workers do not create duplicate occurrences. Payload signature drift never falls back to best-effort decoding; incompatible work is retained with an explicit failure reason. - -## 7. Runtime Modes And Shutdown - -`config/setting.json` gains strict runtime/job sections. A single compiled program supports: - -- `api`: API server active, Job worker does not claim work; -- `worker`: Job worker active, API listener is not opened; -- `all`: both active for local/small deployments. - -The target source contract no longer requires `main.dever` or source-level `serve()` calls. The compiler generates API/Job startup for the configured mode and owns their bounded group, shutdown and resource cleanup. Disabled services return without opening resources. This is a planned migration; the current compiler still uses Main. - -The process signal owner is runtime-level and broadcasts to active services. API closes its listener and reuses existing connection drain. Job stops polling/claiming and drains active leases to its deadline. The generated entry then closes databases and flushes logs. Service failure cancels and drains its Group siblings. - -## 8. Production API - -API route discovery remains compiler-owned. The target syntax uses `get/post/put/delete/cmd/rest`; `rest` lowers plain CRUD to the same-domain Model, while custom actions bind the same-domain App signature. POST/PUT accept typed bodies; query routes accept named wire-safe scalars. A request Context is hidden in the runtime rather than declared as a source parameter. Validated transport observations and bounded Cookie/Header mutation are available through controlled API capabilities; no raw request/response handle reaches App. The detailed contract is owned by the `09-20-production-api` child task. - -Handler success is encoded into the existing `{code,message,data}` envelope. Recoverable App failures must be captured and mapped to a standard `dever.api.Error`; uncaptured failures produce a generic internal envelope and structured, secret-free log. This keeps business errors independent of HTTP while allowing explicit 400/401/403/404/409/429 mapping. - -Uploads are streamed to an owned temporary file under runtime data/tmp with checked total size, part count, filename and MIME metadata. API receives an opaque upload handle/metadata, and a storage Port consumes it. Drop, cancellation and handler failure remove unclaimed temporary files. The CMS does not expose arbitrary filesystem paths. - -## 9. CMS Integration - -The maintained CMS is the cross-feature acceptance application, not a second implementation of framework logic. Plain and Markdown forms retain equal normalized declarations. Plain CRUD uses generated REST; domains own explicit App views and commands when business behavior requires them. No dto/service/repository folders are introduced. - -Authentication uses Secret password input, private password hash storage, hashed session token storage and secure Cookie output. Media uses a storage Port with a local production Adapter and test fake. Publishing writes the state transition, audit row and scheduled Job atomically. Job execution rechecks state/idempotency before publishing and can retry safely. - -## 10. Compatibility And Rollback - -This language is pre-release and repository callers migrate atomically; no legacy aliases, environment fallback, old JSON date encoding or dual role matrix remains. Each child task is a rollback boundary. A child is not accepted while canonical docs, Markdown contracts or maintained CMS callers use two protocols. - -No database destructive migration is run against user data during compiler tests. Runtime private Job schema uses additive/versioned initialization and test-owned databases. Real PostgreSQL verification requires an explicitly configured isolated database. diff --git a/.trellis/tasks/09-20-production-application-language/implement.jsonl b/.trellis/tasks/09-20-production-application-language/implement.jsonl deleted file mode 100644 index 2a7916c..0000000 --- a/.trellis/tasks/09-20-production-application-language/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Source roles, visibility, effects, API and application contract baseline"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"Model privacy, transactions, settings and SQLite/PostgreSQL invariants"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Official package, native runtime and lifecycle contracts"} -{"file":".trellis/spec/backend/logging-guidelines.md","reason":"Secret-free logging and HTTP request boundary"} diff --git a/.trellis/tasks/09-20-production-application-language/implement.md b/.trellis/tasks/09-20-production-application-language/implement.md deleted file mode 100644 index 43e3f79..0000000 --- a/.trellis/tasks/09-20-production-application-language/implement.md +++ /dev/null @@ -1,90 +0,0 @@ -# Dever 生产级大型应用语言支持执行计划 - -## Start Gate - -- [x] 用户审阅并明确批准本 PRD、设计和执行顺序。 -- [x] 父任务保持 planning;不把父任务作为实现目标。 -- [x] 依次完善并启动拥有当前交付物的子任务。 -- [x] 开始每个子任务前读取 `trellis-before-dev`、子任务文档和 backend specs。 -- [x] 保留现有脏工作区和历史任务,不提交、不归档、不清理用户改动。 - -## Child Order - -### 1. secure-data-contracts - -- [x] Model private 字段的领域所有权和公共边界。 -- [x] Secret 类型、批准 sink、泄漏拒绝。 -- [x] secure random、Argon2id、SHA-256/HMAC、常量时间验证。 -- [x] 删除应用 `dever.process.environment`,迁移仓库调用方和文档。 -- [x] 定向安全、Model、API/log 边界测试。 - -### 2. time-typed-codec - -- [x] UTC DateTime/Date/Time/Duration API 和无溢出运算。 -- [x] 共享静态 wire schema 与具体编码/解码生成。 -- [x] 严格 JSON、日期格式、大小/深度和私密/Secret 拒绝。 -- [x] 迁移当前 API response codec,保持 envelope。 -- [x] 定向 codec、API、Markdown、ORM 表示回归。 - -### 3. port-adapter - -- [x] Port bodyless contract、明确 failure contract 和 formatter/Markdown 文档。 -- [x] Adapter/test fake 实现检查与静态 dispatch。 -- [x] 收紧角色调用矩阵和类型可见性。 -- [x] setting.json 多实现绑定、Adapter-local typed setting 和 Secret 字段。 -- [x] 单实现、多实现、错误绑定、fake 隔离和 effect/failure 回归。 - -### 4. durable-jobs - -- [x] Job role、声明、目标引用、payload schema 和 effect 分析。 -- [x] SQLite/PostgreSQL 私有 schema、原子入队、claim/lease/retry/dead-letter。 -- [x] immediate、run-at、UTC recurring schedule 和 schema drift 行为。 -- [x] `dever.job.serve()`、runtime mode、signal/drain 和数据库关闭顺序。 -- [x] 应用测试隔离、SQLite 端到端和 PostgreSQL 定向编译/可选隔离验收。 - -### 5. production-api - -- [ ] POST record/query scalar decode 与共享 codec 接入。 -- [ ] 注入 Context、Cookie/Header/request metadata。 -- [ ] 标准 API Error 映射和未映射失败脱敏。 -- [ ] 受限上传、临时文件生命周期和 storage Port 路径。 -- [ ] 路由、输入、错误、上传取消和 HTTP drain 回归。 - -### 6. large-cms-acceptance - -- [ ] 扩展 plain/Markdown CMS 领域和等价文档。 -- [ ] 实现账户、会话、权限、内容、修订、分类、媒体、发布和审计业务。 -- [ ] 接入 secure values、Port/Adapter、Job、API 和 runtime all mode。 -- [ ] 增加等价应用测试和无外部服务 fake。 -- [ ] 执行最终定向 check/test;任何 run/build 或持久服务验证先向用户说明。 - -## Cross-child Gates - -- [ ] 每个阶段的公共合同只有一个 owner;JSON、配置、Job payload 不复制类型转换。 -- [ ] 新增 Intrinsic 时 checker、effects、native emitter、reference policy 和官方 package 同步穷尽。 -- [ ] `.dever` 与 `.dever.md` 使用同一 AST/check/HIR,不增加 Markdown 专用语义。 -- [ ] 所有长期测试位于仓库根 `test/`,一次性 fixture 在交付前删除。 -- [ ] 任何配置只来自 `config/setting.json`;搜索确认无应用环境变量兼容分支。 -- [ ] 不添加 front、分发、外部队列、动态插件或内置 RBAC。 - -## Focused Validation Policy - -每个子任务在自己的 `implement.md` 中列出具体命令。共同允许: - -```bash -cargo check --offline -p dever-core -p dever-runtime -p dever-cli -cargo test --offline -p dever-tests --test -git diff --check -python3 ./.trellis/scripts/task.py validate -``` - -如 rustfmt/clippy 组件存在,再运行受影响 package/target 的检查;组件缺失时如实记录。默认不运行 workspace 全量测试、性能套件、真实 PostgreSQL、front build、全量应用 build 或持久服务。 - -## Parent Completion Gate - -- [ ] 六个子任务分别完成质量检查、规范同步和归档。 -- [ ] 父任务重新核对所有 Requirement 与跨子任务数据流。 -- [ ] CMS plain/Markdown 的 schema/API/Job/Port/settings/test 快照一致。 -- [ ] 搜索确认不存在旧环境变量入口、App 直调 Adapter、公开私密字段或无界后台任务。 -- [ ] 汇总实际通过、跳过和受阻的验证,不把定向测试描述成全量证明。 -- [ ] 未经用户明确授权不创建 Git commit。 diff --git a/.trellis/tasks/09-20-production-application-language/prd.md b/.trellis/tasks/09-20-production-application-language/prd.md deleted file mode 100644 index 1a638dd..0000000 --- a/.trellis/tasks/09-20-production-application-language/prd.md +++ /dev/null @@ -1,102 +0,0 @@ -# Dever 生产级大型应用语言支持 - -## Goal - -在不引入 front、编译器分发或任意动态插件系统的前提下,补齐 Dever 编写生产级大型后端所需的安全数据、时间与静态编解码、Port/Adapter、持久化 Job、生产 API 和大型 CMS 验收能力。最终应用保持路径驱动、静态类型、显式副作用和 `config/setting.json` 单一部署配置来源,AI 生成代码不能通过新增随意目录、直接调用实现层或脱离作用域的后台任务绕过架构边界。 - -## Background - -- 当前应用架构已经支持 `main/app/domain/model/port/adapter/api` 路径角色,但 `port` 仍拒绝所有声明,尚无 `job` 角色。 -- 当前 App 可以直接调用同领域 Adapter,Domain/Model/Port/Adapter 之间的调用范围也过宽,不能形成真实可替换边界。 -- 当前 Model 拒绝私密字段;CMS 的密码哈希仍是普通公开 Model 字段。 -- 当前 API 只接收 Text/Int/Bool 参数,无法安全承载登录、Cookie、结构化输入和上传。 -- `config/setting.json` 的 `app`、`log` 对象当前没有运行时合同,应用仍能调用环境变量读取函数。 -- DateTime 等类型已有数据库表示,但缺少 UTC 构造、解析、格式化和运算;API 输出仍使用内部整数表示。 -- HTTP 底层已有 listener close 和连接排空;本任务只补进程信号、API/Job 组合生命周期,不重写 HTTP 引擎。 -- 应用测试体系已经具备根 `test/`、类型安全断言、独立进程、隔离 SQLite fixture 和单套件编译缓存,可承接新能力的长期回归。 - -## Requirements - -### R1. Stable Application Architecture - -- 应用源码角色最终限定为 `app`、`domain`、`model`、`port`、`adapter`、`api`、`job`;不增加 service、repository、controller、dto、middleware、common、shared、internal 或 manager 目录。 -- 手写 API/Job 只调用同领域 App;自动 REST 由编译器生成同领域 Model 操作;App 调用同领域 Domain/Model/Port 和其他领域 App;Domain 只调用同领域 Domain;Adapter 只实现 Port 并调用标准库或自身私有辅助函数。`deverc run/build` 的应用入口由编译器生成,不要求源码 `main.dever`。 -- Model 不声明业务函数;Port 不含实现;API 和 Job 不承载业务规则;跨领域只能调用 App。 -- 单文件与同名角色目录继续互斥;除 API 可按 URL 嵌套外,角色主题目录保持平铺且单主题文件不得机械拆分。 - -### R2. Secure Data And Configuration - -- Model 支持领域私密字段;只有拥有领域的 App 和编译器生成的 Model 代码可以读写,其他领域、API、Job、测试和公开 App 合同不能观察该字段。 -- App/API/Job 输出和日志不能包含私密字段或 Secret;静态检查必须在生成本地代码前拒绝。 -- 提供不渲染、不可比较、不可序列化到普通 JSON 的 Secret 值,以及安全随机 token、Argon2id 密码 hash/verify、SHA-256/HMAC 和常量时间验证能力。 -- Secret 只能进入编译器认可的安全 sink;不得通过字符串拼接、日志、普通 HTTP Header 构造或错误信息隐式解密。 -- 部署配置只来自可执行文件相邻的 `config/setting.json`。移除应用层环境变量读取;命令行参数保留为显式程序输入,但不能覆盖应用配置。 -- Adapter 和运行时配置具有静态 schema、未知字段拒绝、Secret 字段保护和启动前验证;App/Domain 不直接读取部署配置,业务可变数据继续放 Model。 - -### R3. Time And Shared Typed Codec - -- 后端时间统一使用 UTC;提供 DateTime 当前时间、RFC3339 解析/格式化、Date/Time 解析/格式化和 DateTime/Duration 安全运算。 -- 数据库存储继续使用整数毫秒,不改变既有 SQLite/PostgreSQL 列表示。 -- 编译器建立一套静态类型值 schema 和具体代码生成路径,供 Adapter setting、Job payload、API 输入/输出共同使用;不得增加运行时反射 Value 解释器。 -- JSON 解码拒绝重复键、未知字段、越界数值、错误日期和过深/过大的输入;编码拒绝私密字段、Secret、资源、Task、Stream 和非有限 Float。 -- DateTime 的外部 JSON 表示为 UTC RFC3339 字符串,Decimal/Id/Uuid 保持无损文本表示,Duration 明确使用整数毫秒。 - -### R4. Port And Adapter - -- Port 源只声明类型、签名和允许失败,不包含函数体;App 通过 Port 调用外部边界。 -- Adapter 显式实现 Port,签名必须完全匹配,实际失败必须落在 Port 声明的集合内;不依赖运行时 trait object 或动态代码加载。 -- 单实现自动选择;多实现由 `config/setting.json` 按稳定 Port 身份选择。缺失、未知或不完整绑定在启动前失败。 -- 每个 Adapter 可声明自身类型化 setting;未选择 Adapter 的配置不得强制存在。 -- 应用测试可为可达 Port 提供用例私有 fake;fake 不进入生产源码、部署配置或其他测试用例。 - -### R5. Durable Job - -- 新增 `job.dever` 或平铺 `job/*.dever`;Job 声明为非源码可调用的后台入口,只能调用同领域 App,输入必须是可持久化静态类型,输出必须为空。 -- 支持立即任务、指定 UTC 时间任务和编译期校验的 UTC 周期计划。 -- Job 采用数据库持久化、租约领取、并发上限、执行超时、有界退避重试、dead-letter 和崩溃后租约恢复;语义明确为至少一次执行。 -- Job payload 保存稳定任务身份和 schema 指纹。部署后遇到不兼容 payload 时进入明确失败状态,不静默误解码。 -- App 事务内入队必须复用同一逻辑数据库事务;Job 与业务事务连接不一致时编译失败,避免业务提交成功但任务丢失。 -- 任务表、租约和调度状态属于运行时私有 schema,不要求业务创建 Job Model。 -- 同一产物支持 `api`、`worker`、`all` 三种运行模式,仅由 `config/setting.json` 选择;编译器生成对应的 API/Job 启动与排空入口,不要求应用手写 `main()` 或 `serve()` 调用。 -- SIGTERM/Ctrl-C 停止接收新请求和领取新任务,在配置的期限内排空 HTTP 与在途 Job,再执行数据库和日志关闭。 - -### R6. Production API Boundary - -- 使用 `get/post/put/delete/cmd/rest` 声明,保留固定 `{code,message,data}` JSON envelope,不返回低层 `dever.http.Response`。唯一主 Model 的 `rest` 自动生成受约束的 CRUD,手写 API 绑定同领域 App。 -- POST/PUT 支持静态类型请求体;GET/DELETE 支持完整可表示标量的 query/path 输入;复用共享 typed codec 和严格未知字段检查,不暴露动态查询 Map。 -- Model 可为自动 REST 声明受 Effect 约束的字段来源和 `owner` 行范围,普通字段由编译器推导;这些绑定不隐式改变手写 App 的 Model 操作。 -- 请求 Context 在 runtime 隐式传递;受控 API 能力读取 Header/Cookie/request ID/client address,并设置 Cookie/响应 Header。原始 Context 不出现在源函数签名,也不得存储或输出。 -- GET 调用链禁止数据库写入;POST/PUT/DELETE 和 CMD/Job 的写调用链自动建立事务,业务源码无需重复标记 `transaction`。 -- API 失败必须显式映射到标准 API Error,未映射业务失败继续视为 500 并脱敏记录。 -- 上传使用有总量、单文件、字段数、MIME 和文件名限制的流式/临时文件边界;拒绝路径穿越,临时资源在成功、失败和取消后均清理。 -- 鉴权、会话和授权属于业务 App/Domain;不增加 middleware 业务层或框架内置 RBAC。 - -### R7. Large CMS Acceptance - -- 同步维护 `examples/cms/dever` 与 `examples/cms/md`,两者具有等价声明、Model schema、API、Job、Port binding 和测试合同。 -- CMS 至少覆盖 user/account、user/session、user/access、content/article、content/revision、content/category、media/asset、publishing/schedule 和 audit/operation。 -- 验证密码 hash、Secret token、私密字段、会话 Cookie、权限判断、媒体存储 Port、fake Adapter、事务内发布任务、定时发布、失败重试和审计记录。 -- CMS 不引入 front;普通 CRUD 只使用编译器生成的 `rest`,不写透传 App/API 函数。登录、命令、上传等业务入口仍通过手写 API 绑定 App。 - -## Acceptance Criteria - -- [ ] 非法角色路径、App 直调 Adapter、Domain 访问 Model/Port/Adapter、API/Job 跨域调用等在 `deverc check` 阶段稳定拒绝。 -- [ ] Model 私密字段可由所属 App 持久化和验证,但无法进入 App/API/Job 输出、日志、其他领域或测试观察面。 -- [ ] Secret、密码和安全随机能力有成功、错误和泄漏拒绝回归;应用源码无法读取环境变量配置。 -- [ ] UTC 时间和静态 typed codec 对 `.dever`/`.dever.md` 结果一致,API、setting 和 Job 不维护平行编解码逻辑。 -- [ ] Port 单实现、多实现配置选择、缺失绑定、签名/失败不匹配和测试 fake 均有正反测试。 -- [ ] SQLite Job 可验证原子入队、租约恢复、延迟/周期调度、重试、dead-letter、payload 不兼容和优雅停止;PostgreSQL 代码路径通过定向编译,真实 PostgreSQL 只在隔离配置存在时验收。 -- [ ] `api`、`worker`、`all` 三种模式只读取 `config/setting.json`,无环境变量或命令行配置覆盖。 -- [ ] 生产 API 验证结构化输入、标准错误、Cookie/Header、请求上下文和受限上传清理,仍保持固定 JSON envelope。 -- [ ] Dever 与 Markdown CMS 的 check、test 和行为合同一致;最终定向运行验证不依赖 front 或外部服务。 -- [ ] 每个子任务只运行对应最小离线检查;不运行 workspace 全量测试、默认性能压测、真实外部服务或未说明的持久服务。 - -## Out Of Scope - -- front、Page JSON、React 插件和浏览器界面。 -- 私有编译器分发、交叉编译、自托管、包注册表和动态插件加载。 -- 内置用户/RBAC/租户业务模型;这些由 CMS App/Domain 实现。 -- Exactly-once 外部副作用保证;Job 明确采用至少一次语义,业务动作负责幂等。 -- 任意 cron 时区和 DST 规则;周期计划首版固定 UTC。 -- Redis、Kafka、RabbitMQ 或外部队列依赖;首版复用 SQLite/PostgreSQL。 -- 全量测试、默认真实 PostgreSQL、64/128 MiB 压测和 front 构建。 diff --git a/.trellis/tasks/09-20-production-application-language/task.json b/.trellis/tasks/09-20-production-application-language/task.json deleted file mode 100644 index 2aea388..0000000 --- a/.trellis/tasks/09-20-production-application-language/task.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "id": "production-application-language", - "name": "production-application-language", - "title": "Dever 生产级大型应用语言支持", - "description": "补齐 Port/Adapter、安全基础、持久化 Job、生产 API 与大型双源码 CMS 验收,front 和编译器分发延期", - "status": "planning", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-20", - "completedAt": null, - "branch": null, - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [ - "09-20-secure-data-contracts", - "09-20-time-typed-codec", - "09-20-port-adapter", - "09-20-durable-jobs", - "09-20-production-api", - "09-20-large-cms-acceptance", - "09-29-external-libs" - ], - "parent": null, - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/09-20-secure-data-contracts/check.jsonl b/.trellis/tasks/09-20-secure-data-contracts/check.jsonl deleted file mode 100644 index 49ed001..0000000 --- a/.trellis/tasks/09-20-secure-data-contracts/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused compiler/runtime test selection"} -{"file":".trellis/spec/backend/error-handling.md","reason":"Typed crypto failure and diagnostic rules"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"Single owner across checker, emitter and runtime"} diff --git a/.trellis/tasks/09-20-secure-data-contracts/design.md b/.trellis/tasks/09-20-secure-data-contracts/design.md deleted file mode 100644 index f3f4072..0000000 --- a/.trellis/tasks/09-20-secure-data-contracts/design.md +++ /dev/null @@ -1,29 +0,0 @@ -# Dever 安全数据合同设计 - -## Model Privacy - -复用现有字段 `private` 语法,不增加 Model 专用修饰符。类型检查为字段记录声明 owner 的 domain identity:普通 record private 继续 package-owned,Model private 改为 domain-App-owned。Model 生成 CRUD 的匿名 create/update block允许所属 App 写 private 字段,但投影、记录构造和公开边界仍由统一字段访问检查控制。 - -App 是跨领域能力边界,因此任何直接或嵌套包含 private Model 字段的 nominal record 都不能出现在 App 参数、输出或可传播错误中。Model ID 和不含 private 字段的显式 View 仍可公开。API/Job/wire 检查复用同一 `observable` 类型属性,不再各自遍历字段猜测。 - -## Secret Type - -Secret 是独立非泛型标量,内部持有受保护字节,不实现普通 Render/Clone-to-Text/JSON。值语义允许受控传参和 record 字段,但以下静态能力为 false:comparable、Map key、persistent、ordinary wire output、fault rendering。 - -构造来源: - -- `dever.crypto.token(bytes)`; -- 后续 typed setting/API Secret 字段解码; -- 必要的测试固定 Secret 构造仅存在于 compiler-owned Test source,不进入生产标准库。 - -消费 sink 由 Intrinsic 精确枚举,不能通过一个通用 reveal 函数扩散。后续 API/Adapter 新 sink 必须在 checker effect/role policy 中显式加入。 - -## Crypto Runtime - -使用固定版本的成熟 Rust crates 实现 Argon2id、HMAC/SHA-256 与 constant-time 比较;随机源复用 OS getrandom。Argon2id 参数是经过测试的运行时常量,避免应用通过 setting 降低成本。hash 输出为标准 PHC Text,verify 对格式错误返回显式失败而非 panic。 - -标准 `.dever` package 定义公开 Result choice 和简单函数;runtime 只承载密码学实现。checker 校验官方 choice shape,native emitter 复用现有 resource-result 模式,不创建第二套失败协议。 - -## Environment Removal - -从官方 `dever.process`、Intrinsic、checker effect、native emitter 和 runtime system bridge 同步删除 environment。仓库调用方整体迁移到 setting.json 或测试显式输入,不添加 feature flag 或旧名兼容。 diff --git a/.trellis/tasks/09-20-secure-data-contracts/implement.jsonl b/.trellis/tasks/09-20-secure-data-contracts/implement.jsonl deleted file mode 100644 index 7876e05..0000000 --- a/.trellis/tasks/09-20-secure-data-contracts/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Private fields, public boundaries and type properties"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"Model field schema and generated CRUD ownership"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Official package and intrinsic implementation rules"} -{"file":".trellis/spec/backend/logging-guidelines.md","reason":"Secret-free render and log requirements"} diff --git a/.trellis/tasks/09-20-secure-data-contracts/implement.md b/.trellis/tasks/09-20-secure-data-contracts/implement.md deleted file mode 100644 index f728a41..0000000 --- a/.trellis/tasks/09-20-secure-data-contracts/implement.md +++ /dev/null @@ -1,71 +0,0 @@ -# Dever 安全数据合同实施计划 - -## Start Gate - -- [x] 用户批准父任务最终规划后启动本子任务。 -- [x] 读取 compiler-contracts、database、logging、toolchain/library specs。 -- [x] 记录当前 private 字段、Model field access、Render/JSON/log 和 process intrinsic 所有调用点,见 research/secure-contracts-source-map.md。 - -## Implementation - -- [x] 扩展类型属性和字段访问 owner,允许 Model private 并限制为所属 App。 -- [x] 在现有 App/API/入口/错误/测试边界复用 observable 检查;Job 的消费检查由 durable-jobs 子任务接入相同属性。 -- [x] 增加 Secret 类型、语法类型解析、HIR/native/reference 表示和禁止能力。 -- [x] 增加 crypto 官方 package、Intrinsic、runtime 实现和依赖;保证失败类型化与错误脱敏。 -- [x] 删除 environment 官方函数、Intrinsic/runtime 分支、effect 分类、文档与调用方。 -- [x] CMS 账户使用 private password_hash: Text(255),AccountView/ArticleView 隐藏私有值及作者关联;两套源码同步,没有新增登录 API。 -- [x] 更新 LANGUAGE/Markdown/compiler/database/logging canonical docs。 - -## Focused Verification - -```bash -cargo check --offline -p dever-core -p dever-runtime -p dever-cli -cargo test --offline -p dever-tests --test model_syntax -cargo test --offline -p dever-tests --test source_visibility -cargo test --offline -p dever-tests --test contract_semantics -cargo test --offline -p dever-tests --test standard_library -cargo test --offline -p dever-tests --test logging -cargo test --offline -p dever-tests --test markdown_source -git diff --check -``` - -如组件存在,增加受影响 package/target 的 rustfmt 和 `clippy -D warnings`。不运行全量测试、真实数据库、服务或性能测试。 - -## Review Risks - -- private Model 字段不能破坏生成 SQL 列顺序、迁移 fingerprint 或 row decode。 -- Secret 不得因派生 Render/Debug、错误路径或 generic collection 自动获得观察能力。 -- crypto 失败不得包含输入;随机源和 password verify 不得 panic。 -- 删除 environment 后必须穷尽 checker/emitter/reference/effect match,不能留不可达旧分支。 - -## Implementation Notes — 2026-09-20 - -- Secret 位于基础 runtime/secret.rs,Clone 保持值语义、Debug 固定脱敏、zeroize 清除已持有字节;argon2/sha2/hmac/getrandom/subtle 由独立 crypto feature 控制。原生构建根据已裁剪代码中的 crypto 调用选特性,也覆盖直接 system intrinsic。 -- Model 私有字段访问统一经过 Context::owns_private_fields。类型安全属性缓存沿 Related 关联图做单调反向传播,不把 ORM 关联环当成布局递归。 -- Argon2 0.5.3 官方文档核对后采用 Argon2id v19 / Params::default;verify 在计算前限制 PHC 算法、版本、成本及结果长度。执行一次 cargo fetch,锁定 12 个新增依赖包;zeroize 复用已存在的 1.9.0。 -- `secure_contracts` 新定向目标 8/8 通过(含 reference、原生与 Test source 执行)。覆盖隐私所有权/Model schema 不变、嵌套非观察边界、Related 自环、环境入口拒绝、密码错误/损坏/资源上限、SHA/HMAC 已知向量、token 独立性及脱敏 Debug。 -- 编译检查 core/runtime/cli + crypto/reference 通过。首次验证因磁盘只剩 65 MiB 导致 source_visibility 链接 Bus error,随后 rlib 报 No space left on device;主会话清理 target/debug/incremental 后恢复验证。后续使用 `--config build.incremental=false --config profile.dev.debug=0 --config profile.test.debug=0`,始终 offline + locked,原生测试串行。 -- rustfmt/clippy 组件未安装;没有安装全局工具。没有运行全量测试、真实 PostgreSQL、持久服务、CMS 打包运行或性能测试;OS 随机源不可用分支未做系统故障注入。 -- contract_semantics 完整目标初次 6/12:6 个旧样例直接构造 error variant,在既有 `construct_variant_with_kind` 禁令处收到 C005;本次没有改该 error 构造语义,也未重写这些旧样例。最终报告保留未通过,不据此宣称全目标成功。 - -## Verification Results - -| 定向验证 | 结果 | -| --- | --- | -| cargo check:core/runtime/cli + crypto/reference | 通过 | -| secure_contracts(crypto,reference,串行) | 8/8 通过 | -| model_syntax | 3/3 通过 | -| source_architecture | 8/8 通过 | -| source_visibility | 10/10 通过 | -| markdown_source | 20/20 通过 | -| standard_library | 5/5 通过 | -| logging | 1/1 通过 | -| differential::time_failures_are_source_defined_results | 1/1 通过;移除 environment 样例后保留显式 result 的时间失败 native/reference 一致性 | -| contract_execution | 首轮 7/9;两个 CMS 失败因关联传播要求 ArticleView,修复后 CMS parity 与 maintained root checker 各 1/1 通过;未重复整个目标 | -| contract_semantics | 完整目标 6/12;6 个既有 error 直接构造样例未重跑;当前 private_fields_protect_access_mutation_and_construction 精确用例 1/1 通过 | -| git diff --check / 本次文件尾随空白扫描 | 通过;项目源码目前未跟踪,因此额外执行显式文件扫描 | -| rustfmt/clippy | 未安装组件;rustfmt 启动失败,未安装或绕过 | - -contract_semantics 未通过用例:failure_cannot_be_discarded_overwritten_logged_or_laundered、errors_can_be_returned_translated_or_explicitly_recovered、failure_summaries_follow_long_calls_and_unused_handler_dependency_cycles、nested_failure_survives_value_copies_and_projection、empty_traversal_does_not_handle_context_and_singleton_projection_transfers_failure、possibly_empty_or_null_outputs_cannot_hide_another_failure。首个诊断均为 C005 `error choice variants can only be used with fail`。 - -当前没有新配置入口、没有登录业务、没有真实数据库/全量/服务/性能验收。Model create/update/读取 private 字段通过静态检查与 schema 不变验证;未据此声称已完成真实数据库运行验收。 diff --git a/.trellis/tasks/09-20-secure-data-contracts/prd.md b/.trellis/tasks/09-20-secure-data-contracts/prd.md deleted file mode 100644 index a2f59a4..0000000 --- a/.trellis/tasks/09-20-secure-data-contracts/prd.md +++ /dev/null @@ -1,37 +0,0 @@ -# Dever 安全数据合同 - -## Goal - -让密码、令牌和部署密钥在 Dever 中具有编译器可识别的非观察边界,使大型应用能够存储私密 Model 字段、处理 Secret 和调用成熟密码算法,同时彻底移除环境变量配置入口。 - -## Dependencies - -- 无前置子任务;这是 Port setting、认证 API 和 CMS 会话的基础。 - -## Requirements - -- Model `private` 字段由所属 component/domain 的 App 拥有;生成的 Model CRUD 可以持久化,所属 App 可以访问,其他角色和领域不能访问。 -- 含 private Model 字段的完整 Model 不能出现在 App 输入/输出、API/Job wire 输出、日志或跨领域类型观察面;App 使用显式 View record。 -- 新增 opaque `Secret` 标量:不可 Render、比较、拼接、普通 JSON 编码、Map key、Model 存储或错误 payload。 -- Secret 只允许进入批准 sink:Argon2id hash/verify、HMAC、常量时间验证、后续受控 Cookie/bearer setting sink;不提供通用 Secret-to-Text。 -- 提供操作系统 CSPRNG token、Argon2id 密码 hash/verify、SHA-256、HMAC-SHA256 和常量时间字节/摘要验证;使用成熟依赖,不自实现密码算法。 -- 密码哈希存储为 private Text,明文密码使用 Secret;错误不得包含明文、密钥或摘要原文。 -- 删除 `dever.process.environment` 及对应 intrinsic/runtime bridge、文档和测试;不保留别名、fallback 或 deprecated 路径。 -- `dever.process.arguments` 保留,但不得成为 setting override;配置来源规则由后续 Port/Job/API setting 合同继续约束。 -- `.dever` 与 `.dever.md` 使用相同语法/语义;所有正式测试放根 `test/`。 - -## Acceptance Criteria - -- [ ] 所属 App 可创建、更新、读取 private Model 字段,并能用其验证密码;其他角色/领域的字段访问在 check 阶段拒绝。 -- [ ] App 签名、API response、日志和普通 JSON 对 private/Secret 的直接或嵌套泄漏均被静态拒绝。 -- [ ] Secret 不能被渲染、比较、拼接、存入 Model/Map key 或放进普通错误 payload。 -- [ ] secure token 两次调用不复用值且使用 OS CSPRNG;无随机源时返回显式安全失败。 -- [ ] Argon2id hash/verify 验证成功、错误密码、损坏 hash 和资源上限;SHA/HMAC 与已知向量一致。 -- [ ] 搜索和负向编译测试确认应用无法调用环境变量读取,仓库没有兼容入口。 -- [ ] 既有普通 record private 字段、Model schema、API envelope、日志和 Markdown 回归保持通过。 - -## Out Of Scope - -- 通用密钥管理服务、密钥轮换协议和硬件安全模块。 -- JWT/OAuth、会话业务模型、RBAC 和登录 API;由后续 API/CMS 子任务实现。 -- 数据库列加密;private 表示可见性,不声称静态或磁盘加密。 diff --git a/.trellis/tasks/09-20-secure-data-contracts/research/secure-contracts-source-map.md b/.trellis/tasks/09-20-secure-data-contracts/research/secure-contracts-source-map.md deleted file mode 100644 index e586ac2..0000000 --- a/.trellis/tasks/09-20-secure-data-contracts/research/secure-contracts-source-map.md +++ /dev/null @@ -1,70 +0,0 @@ -# Research: 安全数据合同源码边界 - -- Query: Model private、Secret、密码学及 environment 移除的最小实现路径。 -- Scope: internal -- Date: 2026-09-20 - -## Findings - -### 字段与领域身份 - -- `crates/dever-core/src/syntax.rs:124` 的 AST `Field.private` 已存在;`parser.rs:517`、`:556` 解析普通 record 的 private,选择分支不允许 private。无需新增语法关键字。 -- `check/symbols.rs:373` 将 AST private 原样落到 `types.rs:188` 的 checked `Field`。HIR 表达式直接持有 checked Type,因此不需要另造字段隐私 HIR。 -- `types.rs:209` 的 `Definition` 已有 owner、kind;`DefinitionKind::Model` 可区分普通 record 与 Model。`source.rs:25` 的 SourceRole、`:84` 的 `SourceLayout::domain()` 是领域身份唯一来源,不应拆字符串判断归属。 -- `check/model.rs:539` 当前硬拒绝 Model private;移除此拒绝后已有字段落地流程可保留 metadata。`synthesize_fields`(`:219`)仅插入公开 id/created_at,生成 Page/Cursor 及 Related 字段。持久 schema `ModelField` 不必承载语言隐私,因为数据库列格式不因访问策略改变。 -- `check/expressions.rs:167` 的 `Body::field_type` 按 type.owner == context.owner 检查私有字段;写路径复用字段解析。`check/values.rs:41` 独立进行 record 构造授权。两处应改用同一 owner 检查:普通 record 保留 package 私有;Model 只允许同领域 App。可直接复用 `check/orm.rs:247` 对 SourceRole::App 和 layout.domain 的判定。 -- `check.rs:506` 的 validate_public_boundaries 只拒绝 private nominal type,并跳过 public record 的 private 字段;它不会拒绝一个 public Model 内含 private 字段。`:557` 的 validate_exported_failures 只检查错误类型自身 public 标志,嵌套 Model 同样需要补覆盖。 -- `check/api.rs:149` 的 json_type 已拒绝 record private,但自写递归,与 App 合同尚未共享。建议统一类型可观察性属性,再由 API 保留具体可编码标量白名单。 - -### Secret 与类型能力唯一所有者 - -- `types.rs:7` 的 Type 增加独立 Secret;`check/symbols.rs:300` 附近是源码内置标量解析入口;`native.rs:766` 附近是 Rust 表示映射;`reference/value.rs:17` 是 reference Value 枚举。不要用 Named record 或 Bytes 别名模拟 Secret。 -- `types.rs:232` 的 Properties + `cache_properties` 已按 nominal DAG 缓存 comparable/transferable/movable。建议在此集中增加可渲染/敏感类型属性;避免在 API、App、fault 三处复制 nominal 图遍历。 -- `check/symbols.rs:452` 的 map_key 是独立白名单,Secret 默认不匹配;`check/model.rs:1320` 的 normalize_field_type 是持久化白名单,Secret 默认不可持久化。无需把所有存储参数检查迁入通用 Properties;仅共享安全属性。 -- 风险:`Type::Related` 目前直接返回 Properties::ALL(types.rs:92),且 referenced_types(check/symbols.rs:471)特意不展开 Related,避免合法关联 Model 环。敏感信息属性若沿用该路径会漏检,若简单递归则可能死循环。使用有界反向传播/固定点处理关联图,或者在对外可观察类型中拒绝 Related;不能影响现有布局/可比较缓存算法。 -- `native/records.rs:40`、`:82` 无条件为 record/choice 生成 Render,逐字段调用 render_to,当前 private 字段同样被渲染。`reference/value.rs:134`、`:177` 同样逐字段展示。Secret 的静态禁令必须覆盖容器和选择 payload;不应靠运行期脱敏代替编译拒绝。 -- 原生类型统一 derive Clone/Debug(native/records.rs:25);Secret Rust 表示可有安全 Debug 占位,但不能输出原始字节。不提供普通 Render 实现时,生成器需要避免为包含 Secret 的 nominal 类型生成不可编译 Render,同时错误/入口输出等 render sinks 必须先检查。 -- 日志内置签名在 `check/intrinsics.rs:108`,当前接收 Text;应保持此边界,不增加任意值日志转换。JSON 标准库采用显式 JSON 类型,API 泛型序列化是需额外保护的边界。 - -### environment 完整删除链 - -1. `library/dever/process.dever:6` EnvironmentResult、`:23` environment 及两个 environment_value 分支。 -2. `crates/dever-core/src/intrinsic.rs:26` ProcessEnvironment 枚举、`:140` process_environment 名称解析。 -3. `check/intrinsics.rs:85` 签名及官方 EnvironmentResult shape 验证。 -4. `contracts/effects.rs:549` process effect 分类,保留 ProcessArguments。 -5. `native/intrinsics.rs:72` resource_result → `dever_runtime::process::environment`。 -6. `reference/intrinsics.rs:69` recover → 同一个 runtime 函数。 -7. `crates/dever-runtime/src/process.rs:16` environment 桥接函数。 -8. `test/dever-tests/tests/standard_library.rs:77` process 输入测试及 `:115` 直接 runtime 错误测试;`differential.rs:331` environment 错误一致性样例。 -9. `README.md:65` 文档明确宣传该入口,也需要同步删掉。 - -已有 argv arguments 是独立能力,保留。测试环境配置不要换成另一个应用环境变量入口;删除 environment 专项并增加旧 API/旧 intrinsic 被拒绝的定向断言。 - -### 依赖与密码学复用 - -- `Cargo.toml:36` 已精确锁定 getrandom = 0.2.17;runtime `orm.rs:86` 用 getrandom::getrandom。runtime Cargo.toml 当前只在 database feature 下启用,非数据库 crypto 不能依赖 database 才有随机源。 -- Cargo.lock 中另有 getrandom 0.4.3(433)、hmac 0.13.0(490)、sha2 0.11.0(1059)、subtle 2.6.1(1143);这些只是已解析的间接依赖,不代表 runtime 可直接 import。 -- Cargo.lock 已有 zeroize(1650);没有 argon2。采用 Argon2 crate 时需核对其 digest/password-hash/rand_core 版本,不应假定已锁 sha2/hmac 与任意版本 Argon2 相容。 -- 官方包装遵循 process/time 的 Result choice + checker shape 校验 + native resource_result + reference recover;crypto 重用该协议。运行时集中到 crypto 模块;Secret 字节访问保持 crate 内部,禁止公共 reveal。 - -### 最小定向测试 - -- `contract_semantics::private_fields_protect_access_mutation_and_construction`(218)保留普通 record package-owner 基线。 -- `source_architecture::model_operations_belong_to_the_owning_domain_app`(209)扩展 Model private 字段读写、同领域不同 App topic、Domain/API/Test/跨域拒绝、App 嵌套参数/输出/错误泄漏。 -- `model_syntax` 覆盖 private 持久声明及 Secret 存储拒绝;`markdown_source` 验证 private 往返和两种源码一致。 -- `contract_api` 覆盖快照不会暴露私有表示,以及公开边界敏感类型拒绝。 -- crypto 新的根 test/dever-tests/tests 定向文件可以集中运行时已知答案、native/reference 一致性、Secret 禁止 Render/eq/Map-key/JSON/persistence;`test/dever-tests/Cargo.toml` autotests=false,必须注册新目标。 -- `standard_library` 和 reference feature 下 `differential` 修改 environment 案例。优先 cargo test -p dever-tests --test ,无需真实数据库、服务、全量测试。 - -### Related specs / External references - -- `.trellis/spec/backend/compiler-contracts.md`:字段隐私、App 边界、角色及有界类型图。 -- `.trellis/spec/backend/database-guidelines.md`:Model 所有权、静态 schema、settings-only 配置。 -- 当前任务 `design.md`:Model domain-App owner、opaque Secret、无环境变量兼容路径。 -- 外部资料未访问;版本事实来自当前 Cargo.lock,密码算法参数/具体 crate API 需实施者按实际选定版本的官方资料核实。 - -## Caveats / Not Found - -- 子会话 `task.py current --source` 返回 none;输出路径由父代理明确提供,未修改任何任务指针。 -- 未执行构建、测试或服务;结论为源码研究,不是运行验收。 -- 未发现可复用 Secret 或 argon2 实现。上述 Render 风险是当前实现事实;静态渲染入口完整枚举应在实现阶段继续检查 native entry/failure/assert 渲染,不能只修改 native record emitter。 diff --git a/.trellis/tasks/09-20-secure-data-contracts/task.json b/.trellis/tasks/09-20-secure-data-contracts/task.json deleted file mode 100644 index 6c84504..0000000 --- a/.trellis/tasks/09-20-secure-data-contracts/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "secure-data-contracts", - "name": "secure-data-contracts", - "title": "Dever 安全数据合同", - "description": "实现 Model 私密字段、Secret、密码与安全随机能力,并移除应用环境变量配置入口", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-20", - "completedAt": "2026-09-20", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-20-production-application-language", - "relatedFiles": [], - "notes": "Model private/Secret/crypto/environment removal/CMS View contracts complete. Independent quality gate and final review found no blocker; focused checks and secure_contracts 8/8 passed. Known unrelated contract_semantics legacy failures remain documented.", - "meta": {} -} diff --git a/.trellis/tasks/09-20-time-typed-codec/check.jsonl b/.trellis/tasks/09-20-time-typed-codec/check.jsonl deleted file mode 100644 index f1d169b..0000000 --- a/.trellis/tasks/09-20-time-typed-codec/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"JSON/time/API focused test matrix"} -{"file":".trellis/spec/backend/error-handling.md","reason":"Parse failure and source diagnostic behavior"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"Single codec owner across consumers"} diff --git a/.trellis/tasks/09-20-time-typed-codec/design.md b/.trellis/tasks/09-20-time-typed-codec/design.md deleted file mode 100644 index 9a34dd3..0000000 --- a/.trellis/tasks/09-20-time-typed-codec/design.md +++ /dev/null @@ -1,28 +0,0 @@ -# Dever 时间与类型化编解码设计 - -## Time Representation - -保留现有 i64 毫秒运行时表示和数据库 codec。新增成熟、固定版本的日期时间库只用于严格解析、日历校验、UTC 格式化和 checked arithmetic,不手写日历算法。DateTime format 统一输出 `Z`,parse 可接受 RFC3339 offset 后转换 UTC。Duration 是有符号毫秒。 - -官方 `dever.time` 继续用普通 `.dever` Result choice 暴露失败,system intrinsic 返回具体 i64/Text。`unix_millis` 可保留为底层数值能力,但业务首选 `now() -> DateTime`。 - -## Shared Wire Schema - -在 checker/HIR 边界新增一个只读的具体 wire schema 描述,节点仅包含已解析类型、record 字段顺序和策略标记。schema 构建复用 nominal cycle/depth 和 private/Secret 属性,不独立遍历 AST。 - -Schema policy 区分: - -- ordinary/API input:可按协议解码,显式 Secret 字段生成 opaque Secret; -- ordinary output:必须可观察且无 Secret/private; -- setting input:允许 Secret,但不允许资源和业务 failure choice; -- persisted Job payload:要求跨进程稳定、无资源和 Secret。 - -Native emitter 为每个被使用 schema 生成具体转换函数并缓存 specialization。runtime 只提供重复键可见的 bounded JSON parser、标量 parse/format 和错误位置;业务值保持具体 Rust struct/list/scalar。 - -## API Migration - -先将 `native/api.rs` 的 response `json_value` 迁移到共享 encoder,保持 envelope 构造仍归 API owner。输入扩展留给 production-api 子任务。迁移后删除原有平行 Type match,添加生成代码断言防止回退。 - -## Compatibility - -数据库和 Model snapshot 不变。DateTime API JSON 从内部整数改为 RFC3339 是预发布协议的直接替换;仓库内 API fixture 同步迁移,不保留双格式输入输出。 diff --git a/.trellis/tasks/09-20-time-typed-codec/implement.jsonl b/.trellis/tasks/09-20-time-typed-codec/implement.jsonl deleted file mode 100644 index 40157ea..0000000 --- a/.trellis/tasks/09-20-time-typed-codec/implement.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Type properties, private boundaries and generated contracts"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Official time/json packages and native runtime boundary"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"Date/time storage representation and ORM compatibility"} diff --git a/.trellis/tasks/09-20-time-typed-codec/implement.md b/.trellis/tasks/09-20-time-typed-codec/implement.md deleted file mode 100644 index 8265643..0000000 --- a/.trellis/tasks/09-20-time-typed-codec/implement.md +++ /dev/null @@ -1,64 +0,0 @@ -# Dever 时间与类型化编解码实施计划 - -## Start Gate - -- [x] `secure-data-contracts` 完成并提供稳定 Secret/private 类型属性。 -- [x] 用户已批准父任务规划。 -- [x] 读取 compiler/toolchain/database/error specs 和当前 API codec、JSON runtime、DateTime ORM codec。 - -## Implementation - -- [x] 增加 checked DateTime/Date/Time/Duration runtime 操作与官方 time API。 -- [x] 增加共享 wire schema 类型分类、策略和 schema fingerprint 基础。 -- [x] 增加 bounded strict JSON input parser/decoder 和 concrete value encoder。 -- [x] 生成具体 scalar/list/record/nullable codec,缓存重复 schema。 -- [x] 将 API response 迁移到共享 encoder,删除 `native/api.rs` 平行转换。 -- [x] 保持 ORM storage codec/fingerprint 不变并增加回归。 -- [x] 更新 LANGUAGE、Markdown、compiler/toolchain/database specs。 - -### 实施合同(2026-09-20) - -- 固定 chrono 0.4.45,std-only;主代理统一 fetch 后全部定向检查使用 locked/offline。Date 是 UTC 午夜 epoch 毫秒,Time 是午夜起毫秒;RFC3339 offset 转 UTC,拒绝闰秒、超过三位小数和四位日历范围以外值。checked 算术仅检查 i64 溢出,超日历范围在格式化边界失败。 -- `core/wire.rs` 是唯一类型允许表,policy 进入 identity;`native/wire.rs` 生成具体类型的双向 helper,API 按 identity 缓存。允许 Secret 的输入 policy 只生成 decoder。private/bounds/Choice/Map/ModelId/Related/resource 稳定拒绝;没有放行尚未实施的字段约束验证。 -- runtime wire 使用借用 RawValue 保留原始 JSON 数字,逐层 visitor 检查重复键;16 MiB、64 层容器、65536 个值。concrete decoder 拒绝未知和缺失必填字段,缺失 nullable 得到 None。API envelope 只嵌入 Encoded,移除旧 response Value round-trip。 -- 官方标准库原来没有 `.dever.md` 副本。经主代理确认,不新增同包重复源码;以 LANGUAGE 合同和 plain/Markdown 调用方同签名、同输出 parity 覆盖 Markdown 验收。 -- 没有改 ORM/model fingerprint owner、配置来源、API 输入协议或 CMS 业务;无应用环境变量配置。 - -### 验证结果(2026-09-20) - -- core/runtime/cli,api + reference,以及 postgres + api + reference 两次定向 cargo check:通过。 -- 新 `time_codec` 最终 9/9 通过(40.39 秒)。覆盖实际编译运行的 concrete decoder、Decimal/Id/Uuid/负零/原始 Json 精度、缺失/未知/重复字段、无监听器 API dispatch、native/reference 时间成功和失败、plain/Markdown、预算与 policy。随后仅增强 Model 专项为当前 App → Model 调用,独立复验 1/1 通过:四种时间值仍编码为 ORM Int,存储 logical type 和 i64 表示不变。 -- 既有 `api_routes` 7/7、`json_library` 7/7、`markdown_source` 20/20、`model_syntax` 3/3、`standard_library` 5/5 均通过。 -- `sqlite_orm::shared_orm_fixture_remains_valid_without_opening_a_database`:失败,未打开数据库。`support/orm_fixture.rs` 的旧 fixture 在 `main.dever` 中直接调用 `user.create`,当前 `check/orm.rs::resolve_model` 只允许 Loose 使用 table 短名,当前 Main/App 角色合同不再接受该用法,报 C004。该 fixture 和角色/ORM owner 本次均未修改;按主代理确认记录现存不匹配,不扩大本任务迁移旧 fixture。其余 SQLite 执行用例未运行。 -- `git diff --check` 通过;仓库主体为既有未跟踪文件,另对本次新增源码做显式空白和旧转换路径扫描。没有旧 `json_type`、`json_value` 或 API `parse_json` 输出路径残留。 -- 未运行全量、真实 PostgreSQL、服务、性能;rustfmt/clippy 组件缺失,未安装。 - -## Focused Verification - -### Trellis 独立检查(2026-09-20) - -- 核对共享 schema policy/identity、nominal ID 位移稳定性、根 response bounds、private/Secret/资源拒绝、具体 decoder 与 API envelope;没有发现并行输出类型允许表或 ORM storage/fingerprint 改动。 -- 修复 runtime Encoder 的异常状态:对象缺值时 `end()` 保留未完成 frame;写入部分 JSON 后触及字节上限时锁定失败,`finish()` 不再可能发布残缺 Encoded。新增缺值、闭合括号超限和逗号写入后值超限三个回归,同步 toolchain spec。生成代码原本逐步 `?` 传播,修复针对公共 Encoder 自身的 Encoded 不变量。 -- 独立 `cargo check --locked --offline -p dever-core -p dever-runtime -p dever-cli --features dever-runtime/postgres,dever-runtime/api,dever-core/reference` 通过(16.79 秒)。命令使用上述 incremental/debug/toolchain 设置。 -- 修复后 `time_codec` 9/9 通过(44.22 秒),包括新增 Encoder 回归、native/reference 时间、生成 concrete codec 与无监听器 API dispatch。 -- `git diff --check` 及新增/修改源码显式尾随空白扫描通过。rustfmt/clippy 二进制未安装,不能宣称 lint 全通过;未安装组件。 -- 未运行全量、真实 PostgreSQL、SQLite 执行、服务或性能测试。已有 SQLite fixture 角色不匹配仍按上述记录保留;无本任务未修复阻塞。 - -```bash -cargo check --locked --offline -p dever-core -p dever-runtime -p dever-cli --features dever-runtime/postgres,dever-runtime/api,dever-core/reference -cargo test --locked --offline -p dever-tests --features api,reference --test time_codec -- --test-threads=1 -cargo test --locked --offline -p dever-tests --features api,reference --test standard_library --test json_library --test api_routes --test model_syntax --test markdown_source -- --test-threads=1 -cargo test --locked --offline -p dever-tests --features sqlite --test sqlite_orm shared_orm_fixture_remains_valid_without_opening_a_database -- --exact --test-threads=1 -git diff --check -``` - -不运行全量测试、真实 PostgreSQL、服务或性能基准。PostgreSQL 仅做受影响 feature 的定向 `cargo check`,除非隔离连接被明确提供。 - -以上命令实际均额外使用 `CARGO_INCREMENTAL=0`、`--config profile.dev.debug=0 --config profile.test.debug=0` 和已安装 stable toolchain 的命令级 PATH;这些是编译工具设置,不是应用配置。 - -## Review Risks - -- JSON parser 必须保留 duplicate key 可见性,不能先解析成会覆盖键的 Map。 -- DateTime 外部格式变化不能修改数据库列类型、migration history 或内部排序。 -- schema 缓存 identity 必须包含 policy,避免 setting 允许的 Secret 被普通 output 复用。 -- 生成 codec 必须保留 record 声明顺序和输入求值顺序,且不泄漏 runtime Value 到业务层。 diff --git a/.trellis/tasks/09-20-time-typed-codec/prd.md b/.trellis/tasks/09-20-time-typed-codec/prd.md deleted file mode 100644 index 90cfb49..0000000 --- a/.trellis/tasks/09-20-time-typed-codec/prd.md +++ /dev/null @@ -1,37 +0,0 @@ -# Dever 时间与类型化编解码 - -## Goal - -补齐生产业务所需的 UTC 日期时间操作,并建立唯一的静态类型 wire 编解码合同,为 Adapter setting、Job payload 和 API 输入输出提供同一套安全、无损、可审计的转换。 - -## Dependencies - -- `secure-data-contracts`:提供 Secret 和统一不可观察类型属性。 - -## Requirements - -- DateTime 内部和数据库继续使用 Unix epoch 整数毫秒;Date/Time/Duration 保持既有 i64 存储兼容。 -- `dever.time` 提供 UTC now、RFC3339 DateTime parse/format、Date/Time parse/format、Duration 构造,以及 DateTime 加减 Duration、DateTime difference;溢出和非法文本返回显式失败。 -- 外部 wire 表示固定:DateTime 为规范 UTC RFC3339 字符串,Date 为 `YYYY-MM-DD`,Time 为带可选毫秒的 `HH:MM:SS[.sss]`,Duration 为整数毫秒。 -- 编译器从具体 Type/Definition 派生共享静态 wire schema;setting、Job 和 API 只能通过该 owner 请求 encode/decode 代码。 -- 支持 Bool/Int/Float/Decimal/Text/Id/Uuid/DateTime/Date/Time/Duration、nullable、List 和无 private 字段的 record;Json 作为已验证原始 JSON 时保留既有语义。Secret 只允许在 API/setting input policy 中解码,禁止普通 output 和 Job payload。 -- Float 编码拒绝 NaN/Infinity;Decimal/Id/Uuid 使用无损字符串;整数严格检查 i64。 -- 对象解码拒绝重复键、未知字段和缺失必填字段;嵌套深度、集合长度和总字节受运行时已有/新增明确上限约束。 -- 编解码器生成具体值,不把动态 `serde_json::Value` 传入业务函数,不增加反射或 runtime 类型注册表。 -- 迁移当前 API response 编码使用共享 schema,保持 `{code,message,data}` envelope 和既有路由行为。 - -## Acceptance Criteria - -- [ ] 时间 parse/format round-trip、UTC 规范化、闰年边界、负 epoch、非法文本和 i64 溢出均有定向测试。 -- [ ] SQLite/PostgreSQL Model 的整数毫秒表示和现有 schema fingerprint 不因外部格式变化而改变。 -- [ ] 支持类型的 encode/decode round-trip 无损;Decimal/Id/Uuid/DateTime 不经 Float。 -- [ ] duplicate/unknown/missing/over-depth/over-size/non-finite/private/resource 稳定拒绝;Secret 仅在批准输入策略成功,普通输出和 Job payload 稳定拒绝。 -- [ ] API response 改用共享 codec 后,已有 envelope、状态码和 API route tests 保持一致;DateTime 输出变为 RFC3339。 -- [ ] `.dever` 与 `.dever.md` 的时间签名、文档合同和生成行为一致。 -- [ ] 后续 setting/Job/API 能消费一个公共 compiler schema API,而无需复制类型匹配分支。 - -## Out Of Scope - -- 本地时区数据库、DST 推断和用户界面格式化。 -- 任意 schema registry、Avro/Protobuf 或动态 JSON schema 发布。 -- Model 结构自动存储为 JSON;持久化仍需显式 Json 字段。 diff --git a/.trellis/tasks/09-20-time-typed-codec/research/time-wire-source-map.md b/.trellis/tasks/09-20-time-typed-codec/research/time-wire-source-map.md deleted file mode 100644 index 80e766b..0000000 --- a/.trellis/tasks/09-20-time-typed-codec/research/time-wire-source-map.md +++ /dev/null @@ -1,81 +0,0 @@ -# Research: 时间与共享类型化 wire codec 源码地图 - -- Query: 查清现有时间表示、API JSON 路径、可复用 parser/schema/type graph、依赖和最小验证入口。 -- Scope: mixed -- Date: 2026-09-20 - -## Findings - -### 已有时间表示和必须保留的合同 - -- `crates/dever-core/src/types.rs:18` 已有 DateTime/Date/Time/Duration 四个独立 Type;`check/symbols.rs:313` 负责源码类型解析。它们不是 Int 别名,源码不能随意把 Int 赋给 DateTime。 -- `native.rs:770` 四种类型均生成 Rust i64;`native/orm.rs:1312` 编码为 ORM 整数,`:1375` 通过 `orm::int` 解码;`:1746` PostgreSQL DDL 为 BIGINT。不要为外部字符串格式修改这些分支。 -- `model.rs:146` Model revision、`:158` model_snapshot、`:364` field_type 共同拥有 Model 语义身份;四种时间 logical type 字符串应保持原样。SQLite/PostgreSQL fingerprint 属持久化合同,wire schema 不应写入它。 -- `.trellis/spec/backend/database-guidelines.md:83` 已明确 Date/time 使用整数毫秒。建议 Date 为 epoch 起 UTC 午夜毫秒,Time 为午夜起毫秒且限制 `[0, 86400000)`;不能悄悄改为 Date epoch 天数。当前没有更具体的 Date 单位/范围实现,需在实现文档明确。 -- `reference/value.rs:14` 只有 Int 值载体,没有四种单独时间变体;HIR 保留具体 Type,reference 新 intrinsic 可复用 Value::Int,不必新建动态时间对象。 -- `crates/dever-runtime/src/time.rs:4` 仅有 unix_millis、monotonic_nanos、sleep;unix_millis 当前拒绝系统时钟早于 epoch,但 parse/format 应独立支持负 epoch。 -- `library/dever/time.dever:1` ClockResult.Read(Int)、SleepResult;普通函数调用系统 intrinsic 后分派并 fail,继续复用这种真实源码 Result choice。 -- 桥接修改位置:`intrinsic.rs:33/152` enum/name mapping;`check/intrinsics.rs:91` 签名和 Result shape;`native/intrinsics.rs:79` resource_result;`reference/intrinsics.rs:76` recover;`contracts/effects.rs:529/553` blocking/time effect。只有 now/时钟读取有 time effect;确定性 parse/format/算术应 pure,不能给所有时间 intrinsic 统一外部 time effect。 - -### API 与 parser 路径 - -- `check/api.rs:121` 调用私有 `json_type` (`:149`) 递归判断输出可序列化,`native/api.rs:72` 有平行 `json_value` Type match。共享 schema 应同时替换这两份允许类型逻辑,否则 checker 和 emitter 会继续漂移。 -- `native/api.rs:51` 是 response 转换接入点,转换失败保持日志脱敏和 500;`:32` handler 输入只绑定 Text/Int/Bool(nullable),本任务不要顺手扩大 API 输入协议。 -- `runtime/api.rs:188` success 和 `:216` envelope 拥有 `{code,message,data}`;404/405 Allow/500 保持 API owner,不塞入通用 codec。 -- `runtime/api.rs:140` InputObject 仅拒绝顶层重复键;nested `serde_json::Value` 会静默覆盖重复键。`:191` parse_json 是普通 serde_json parse,没有项目字节/集合上限。不能宣称已有全面严格 parser。 -- `library/dever/json/parse.dever:31` 普通 Dever parser;`:212` depth guard、`:288` duplicate rejection;`json/value.dever:27` maximum_depth=256;`json/write.dever:24` 输出预算 16 MiB。它使用 postorder Document/Number(raw Text),保持原始数字准确性;不能把它当现成可调用 Rust runtime parser。没有发现 parser 输入字节或集合总量上限。 -- `runtime/config.rs:142` serde_json::from_str(Document),`:182` HTTP from_value;未来 setting 需接新 parser,当前无需实现 setting 功能。 - -### 最小清晰 owner/API - -1. 新 `crates/dever-core/src/wire.rs`:只依赖已检查 Type/Definition,导出 crate 可见的 Policy、Schema/Node、从具体 Type 构建 schema 的 Result API。当前 Type 本身 crate-private,因此所谓公共 compiler API 是 compiler 各消费者共用,不必把所有 HIR 类型变成外部 public。 -2. 新 `native/wire.rs`:从 schema 生成具体 Rust encode/decode helper;名义类型按 type-id + policy + direction 缓存 specialization,用 schema 引用而非展开共享 DAG。API、setting、Job 只能调用此 owner。最终业务参数必须具体 T{id}/List/scalar,Value 只停留在转换边界。 -3. 新 `runtime/wire.rs`:serde DeserializeSeed/Visitor 式递归 bounded parser,每层 map 在插入前检测重复键,进入容器/接收元素时扣预算。输入总字节在 parse 前检查、显式 end() 拒绝尾随内容;未知字段/必填字段由具体 decoder 检查。不要先 Value parse 再检查 duplicates。 -4. runtime scalar conversion 复用 `number.rs:44` DecimalValue::parse(严格拒绝 inexact/nonfinite)、`orm.rs:53` Uuid::parse、`lib.rs:40` Id(String) 和新增 time parse/format。Float decode/encode 拒绝非有限。Id/Decimal/Uuid 只收字符串,Int 只收精确 i64 JSON number。 -5. 新 wire runtime feature 最自然由 api/database 等消费者启用;当前 serde/serde_json 在 runtime 是 optional,`native/build.rs:309` runtime artifact cache identity 与 feature 选择要同时包含任何新 feature。不要让生成 decode helper 依赖未启用模块,也不要为未使用 codec 的普通程序开启整套 JSON。 - -### 类型图与敏感值 - -- `types.rs:84` observable 复用缓存的 Secret/private Model 敏感性;缓存 `cache_properties` 在名义类型校验后生成。不要在其初始化之前调用 observable。 -- `types.rs:290` cache_properties 用依赖顺序算属性;`nominal_sensitivity` 独立 worklist 传播 Related 环。`check/cycles.rs` 拒绝正常名义布局环。新 schema 不该再从 AST 建图,也不能把 Related 当普通记录递归展开。 -- wire 支持 record 且每个 field 必须非 private;observable 单独不够,因为普通 record private 不属于 private Model 敏感性,仍须逐字段拒绝。 -- API/setting input 允许 Secret,ordinary output/Job payload 禁止;不要用 transferable 代替 wire eligibility(Secret 可 transferable,资源也可能 transferable)。Choice、Map、Related、资源均不在当前 PRD 支持集。 -- `DefinitionKind::ModelId` 是特殊 nominal(native为 T{id}(i64)),不是 builtin Id(String);当前 API json_type 对非 record 已拒绝它。不可意外将 ModelId 当空 record 编码 `{}`,若本任务不扩展其合同应稳定拒绝。 -- 当前 bounds 是 Field.hir::Domain;任务只要求类型转换,但 decoder 若接收受约束 record,必须防止生成值绕过既有字段范围保证。应明确生成 bounds 校验或 schema 构造拒绝未支持 bounds,不能默认通过。 - -### 日期依赖与精度风险 - -- 检查 Cargo.lock 和 `/root/.cargo/registry/{src,cache}`,未发现 chrono/time/jiff 日期库。不能按离线已缓存处理;引入固定版本后需由主代理统一 fetch/lock,再使用 offline+locked 验证。 -- 官方 chrono 0.4.45 文档给出 MSRV 1.62,满足工作区 Rust 1.85;可固定 `=0.4.45`, default-features=false, features=["std"],复用已有 SystemTime,不开启 clock/local timezone。相关官方文档见下面链接。 -- Chrono 的 from_timestamp_millis 返回 Option,日期范围小于全 i64;格式化超出日历范围应返回明确失败。RFC3339 秒小数与 leap-second 不能直接 timestamp_millis 截断:对非毫秒精度和 `:60` 要显式拒绝或先固定精确可表示策略,避免静默丢失。 -- 四位 `YYYY-MM-DD` wire 合同意味着需要限制年份表示;DateTime canonical 精度(固定 .sss 或零毫秒省略)须统一定义并测试。Time 可选毫秒只能接受可无损表示文本。 -- DateTime 加减 Duration、difference、Duration 倍率构造复用 checked_add/sub/mul;i64 checked 成功不代表仍能格式化成约定 RFC3339。 - -### 定向验证与现有缺口 - -- `test/dever-tests/tests/standard_library.rs:105` clock_failures_are_results 可扩展时间 wrapper;更完整的新 `time_codec` target 可集中 runtime 时间边界和 compiler native/reference 最小回环,避免散入一堆测试。 -- `api_routes.rs:37` 生成路径检查、`:64` native compile(不启动监听)、`:118` typed input、`:148` errors/envelope;运行需 `--features api --test api_routes`。 -- 注意 `api_routes.rs:148` malformed_or_extra_inputs 中 if-let 仅检查解析成功分支,未断言坏输入一定失败;新 parser 回归必须直接 assert error,覆盖 nested duplicate、unknown/missing、i64 extremes、depth/bytes/list limits、NaN/Infinity。 -- `json_library.rs:47/85/146/237` 覆盖 ordinary Dever JSON 正常/坏输入/depth/构造图限制。新 Rust parser 不应改变此官方源码 JSON API;需要原始 Json 数字精度保真测试,serde_json 默认 Value 可能把巨大原始数字转浮点并改变值。 -- `model_syntax`/`markdown_source`/`contract_execution` 可以验证 Model snapshot/plain-Markdown parity,schema/int codegen 字符串断言可确认 PostgreSQL BIGINT 而不连真实数据库。 -- 已有 API DateTime 序列化是整数 (`native/api.rs:75`),本任务将明确改成 UTC 字符串,需要新 fixture 证明,而不只是测试 time runtime。 - -## External References - -- https://docs.rs/crate/chrono/0.4.45 — 固定版特性、MSRV、日期范围。 -- https://docs.rs/chrono/0.4.45/chrono/struct.DateTime.html — parse_from_rfc3339、from_timestamp_millis、timestamp_millis、to_rfc3339_opts。 - -## Related Specs - -- `.trellis/spec/backend/{index,directory-structure,error-handling,quality-guidelines}.md` -- `.trellis/spec/backend/compiler-contracts.md`:type depth、敏感属性、API 输入/输出。 -- `.trellis/spec/backend/toolchain-and-library.md`:源码 JSON 与 intrinsic/reference 合同。 -- `.trellis/spec/backend/database-guidelines.md`:整数毫秒和 fingerprint。 -- 当前任务 `prd.md`、`design.md`。 - -## Caveats / Not Found - -- 子代理 `task.py current --source` 返回 none;输出目录由主代理 dispatch 显式指定,没有猜路径或更改 task 状态。 -- 此研究未改源码、规范或任务状态;未运行服务、数据库、全量或性能测试。 -- Shared schema 与 typed decoder 目前不存在;上面的文件名/API 是最小新增 owner 建议,不是已有事实。 -- 普通 JSON 的 exact raw numeric 保真与 serde_json Value 的数字语义有真实差异,需要实现前固定 Json passthrough 策略。 diff --git a/.trellis/tasks/09-20-time-typed-codec/task.json b/.trellis/tasks/09-20-time-typed-codec/task.json deleted file mode 100644 index a7e9bdd..0000000 --- a/.trellis/tasks/09-20-time-typed-codec/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "time-typed-codec", - "name": "time-typed-codec", - "title": "Dever 时间与类型化编解码", - "description": "补齐 UTC 日期时间能力和编译器共享的静态类型 JSON 编解码合同", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-20", - "completedAt": "2026-09-20", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-20-production-application-language", - "relatedFiles": [], - "notes": "UTC time API, shared typed wire schema/codegen, strict bounded JSON and API response migration completed. Focused checks passed; one pre-existing SQLite fixture role mismatch remains recorded outside this task.", - "meta": {} -} diff --git a/.trellis/tasks/09-28-shared-toolchain/check.jsonl b/.trellis/tasks/09-28-shared-toolchain/check.jsonl deleted file mode 100644 index d60a564..0000000 --- a/.trellis/tasks/09-28-shared-toolchain/check.jsonl +++ /dev/null @@ -1,2 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"复核共享缓存的身份、完整性、并发和验证要求"} -{"file":".trellis/tasks/09-28-shared-toolchain/prd.md","reason":"按当前子任务的验收标准进行最终检查"} diff --git a/.trellis/tasks/09-28-shared-toolchain/design.md b/.trellis/tasks/09-28-shared-toolchain/design.md deleted file mode 100644 index 5bc117e..0000000 --- a/.trellis/tasks/09-28-shared-toolchain/design.md +++ /dev/null @@ -1,86 +0,0 @@ -# Design - -## Boundary - -本任务增加机器级 Dever 管理层。它拥有稳定入口、版本目录、项目版本分派、更新事务和共享缓存服务;版本化编译器继续拥有源码检查、生成和运行语义。项目仍通过现有 CLI 合同进入编译器。 - -## Directory Contract - -发行安装器按平台选择机器级根目录,但根内布局一致: - -```text -/ - bin/ - dever stable launcher - deverd cache/build service - state/ - active-version - install.lock - versions/ - / - dever-core - manifest.json - runtime/ - cache/ - native/ - downloads/ - staging/ -``` - -`bin/dever` 是机器上唯一公开入口。`versions/*`、`state/*` 与缓存目录不加入 PATH,也不要求用户直接操作。目录根由安装器写入 launcher 自身的安装位置,运行时不读取环境变量。 - -## Command Flow - -1. launcher 解析命令和项目根,不读取 Dever 源码。 -2. 对项目命令只解析 `config/setting.json` 的 `dever.version`;存在时精确选择,否则读取机器 `active-version`。 -3. launcher 校验版本 manifest 和核心可执行文件身份,然后把原参数分派给版本核心。 -4. 核心完成现有 check/run/build 流程;需要原生产物时通过本机受保护 IPC 请求 `deverd`。 -5. `deverd` 根据已安装版本和完整构建输入自行计算缓存键、编译或恢复产物,再将结果返回请求用户,客户端不能指定缓存文件路径。 - -`config/setting.json` 增加可选配置: - -```json -{ - "dever": { - "version": "0.1.0" - } -} -``` - -runtime 配置解析器接受并忽略已经由 launcher 消费的 `dever` 段,确保同一配置可以同时用于 `run` 和独立构建产物;构建产物不使用该字段选择自身 runtime。 - -## Ownership - -- `dever-cli`:稳定 launcher 命令合同、项目版本读取和版本核心分派。 -- 独立 machine manager 模块:安装、更新、切换、卸载、签名验证和原子状态变更;不把这些分散进每个命令分支。 -- `dever-runtime::config`:只增加严格的 `dever.version` 配置合同,不承担安装或版本选择。 -- `dever-core::native::build`:把默认缓存请求交给共享服务;保留显式隔离缓存入口供测试使用。 -- cache service:唯一可写共享缓存的进程,负责密码学键、编译、恢复、并发发布、租约和清理。 -- 平台 adapter:只封装全局路径、权限提升、服务管理和 IPC 差异;上层状态机和版本规则只有一套。 - -## Install And Update Transaction - -下载先进入 `cache/downloads`,验证发行 manifest 签名、包摘要、平台和版本后解包到 `cache/staging`。核心自检成功后原子发布到 `versions/`,最后原子更新 `active-version`。任一步失败都删除 staging 并保留旧版本。卸载同样持有 `install.lock`,不能删除当前版本或正在服务请求的版本。 - -初次安装由签名的系统安装器建立全局入口、机器服务、权限和初始版本;之后统一由 `dever install/update/use/uninstall` 管理。需要管理员权限时使用平台标准提权流程,不保存凭据。 - -## Cache Security And Cleanup - -- `deverd` 使用专用系统身份,缓存目录只允许该身份写入。 -- 本地 IPC 使用操作系统凭据识别调用者;请求只包含规范化构建输入,不接受任意读写路径。 -- 缓存键使用 SHA-256 等密码学摘要;命中前复核 manifest 与产物摘要。 -- 客户端只有提交完整相同输入才能取得同一产物,服务不提供缓存目录列表或其他项目索引。 -- 运行中的条目持有租约。清理只删除无租约的 staging、损坏条目和按策略选出的旧条目,并使用原子删除/替换。 -- `cache status` 输出容量、条目数和版本占用,不输出项目源码、路径或用户信息。 - -## Failure Contract - -全局入口、活动版本状态、项目锁定、签名、版本 manifest、IPC 或缓存完整性任一验证失败时返回明确错误。不得静默切换版本、使用用户 PATH 中的编译器、改写项目配置或执行未验证产物。 - -## Compatibility - -开发态 `deverc` 保持为私有仓库入口直到正式发行链完成。正式 `dever` 不读取开发仓库 `target/native-artifacts`。已有项目无需新增配置;只有需要固定版本的项目才增加 `dever.version`。 - -## Deferred Complexity - -本任务不重复实现父发行任务的原生后端、目标包生产和发布基础设施。安装管理层必须以父任务提供的签名发行包为输入;在发行包合同完成前可以实现和测试本地 fixture,但不能宣称公开安装链已完成。 diff --git a/.trellis/tasks/09-28-shared-toolchain/implement.jsonl b/.trellis/tasks/09-28-shared-toolchain/implement.jsonl deleted file mode 100644 index 281b0e9..0000000 --- a/.trellis/tasks/09-28-shared-toolchain/implement.jsonl +++ /dev/null @@ -1,2 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"定义原生产物缓存、工具链边界和定向验证合同"} -{"file":".trellis/tasks/09-06-private-compiler-distribution/prd.md","reason":"约束本子任务不扩大到公开发行、内置后端和跨平台矩阵"} diff --git a/.trellis/tasks/09-28-shared-toolchain/implement.md b/.trellis/tasks/09-28-shared-toolchain/implement.md deleted file mode 100644 index 6437681..0000000 --- a/.trellis/tasks/09-28-shared-toolchain/implement.md +++ /dev/null @@ -1,46 +0,0 @@ -# Implementation Plan - -## Phase 1: Contracts - -- [x] 定义唯一的机器目录布局、发行 manifest、版本语法、签名输入、active-version 状态和平台权限合同。 -- [x] 在 `config/setting.json` 增加严格的可选 `dever.version`,并覆盖未知字段、非法版本和独立产物读取行为。 -- [x] 固定用户命令:`install/update/use/uninstall/version/cache status/cache clean`,现有项目命令不改变。 - -## Phase 2: Global Launcher And Version Store - -- [x] 把稳定 launcher 与版本核心分开;所有项目命令通过同一选择函数分派。 -- [x] 实现版本安装、签名/摘要验证、staging、自检、原子发布和 active-version 可恢复原子切换。 -- [x] 实现更新回滚、当前版本卸载保护、缺失锁定版本诊断和显式降级拒绝。 -- [ ] 实现 Linux、macOS、Windows 平台标准提权适配。 -- [ ] 为 Linux、macOS、Windows 分别实现机器级入口、目录权限和服务注册,平台差异只留在 adapter。 - -## Phase 3: Cross-user Build Cache - -- [ ] 将版本核心原生编译接入受保护的 daemon build service;已完成的 Status/Clean/Lib artifact IPC 不代替编译请求。 -- [ ] 使用密码学内容摘要统一编译器、runtime、目标、生成内容与选项身份;SHA-256 与 store 已实现,但版本核心尚未通过受保护服务使用它。 -- [x] 实现认证 IPC、并发请求合并、不可变原子发布、租约、完整性复核和安全结果交付。(IPC 客户端只接受 token-authenticated `deverd` 响应,未恢复同进程 fallback。) -- [x] 实现 `cache status/clean` 与更新/卸载后的损坏、staging 和无引用条目清理。 -- [x] Linux 采用内核 peer credential 接受不同 UID 的 content-addressed Lib artifact put/get 和 metadata-only status;拒绝非 owner clean/管理 token 读取,限制每 UID/总连接、单资产/总容量/条目数。 - -## Phase 4: Integration And Documentation - -- [x] 将现有 `check/api/fmt/test/run/build/tenant` 命令接入统一 launcher,验证参数和退出码透传。 -- [x] 更新 `README.md`、`LANGUAGE.md`、`IMPLEMENTATION.md` 和 backend toolchain spec,明确用户只有一个 `dever`。 -- [x] 使用签名本地 fixture 验证双版本、双项目、并发缓存发布、升级故障与缓存清理。 -- [x] 使用 root 与自有 uid=65534 fixture 客户端验证同一 launcher、不同 UID 的 status/artifact IPC、token/clean/admission 隔离;不创建系统账号或安装真实全局服务。 -- [x] 运行受影响 crate 检查和定向测试;不默认运行全量测试或替换当前机器的真实全局命令。 -- [ ] 最终安全审查安装提权、路径穿越、符号链接、TOCTOU、缓存投毒、降级与跨用户信息泄露。 - -## Rollback - -安装和更新始终保留上一活动版本,active-version 只在新版本自检通过后切换。launcher 或服务升级失败时恢复上一套文件和服务定义;缓存是可再生数据,回滚不迁移或修改任何项目目录。 - -## Implementation Record (2026-09-29) - -- 已完成稳定 `dever` 二进制、严格项目版本读取、签名/摘要/平台验证、双版本安装与切换、活动版本追加校验日志、失败回滚、缺失锁定版本诊断、参数与退出码透传。 -- 已完成开发态原生缓存 SHA-256 化,以及未来 `deverd` 内部 store 的不可变发布、完整性复核、读/写租约、状态与清理算法;该 store 明确不构成 IPC 或跨用户权限边界。 -- 复审后,launcher 的 `cache status/clean` 在认证 IPC 未完成前统一明确失败,不再直接构造 store;安装复制固定为机器共享只读权限,launcher 在执行前复核状态、公钥、版本目录和发行文件的属主与可写位,并拒绝 `update` 通过 `latest` 隐式降级。 -- 本地签名 fixture 已覆盖双版本、双项目、并发缓存发布、篡改拒绝、健康检查失败、部分 active 记录恢复和清理租约。没有创建真实系统用户、安装全局命令或变更系统服务。 -- 真实 Linux/macOS/Windows 提权与服务注册 adapter、认证 IPC、版本核心到 `deverd` 的构建请求、签名发行目录与下载(当前 `latest` 只是未签名本地 fixture 指针)、内置后端发行包和六宿主发行验证仍由父任务 `09-06-private-compiler-distribution` 阻塞;这些项保持未勾选,不能用同进程 store 代替。 -- 最终定向复验:受影响的 `dever-cli`、`dever-runtime`、`dever-core` 离线 `cargo check` 通过;`shared_toolchain` 6/6、`application_config` 6/6 通过。`rustfmt`、`clippy` 未安装;未运行全量、性能、真实系统安装或跨平台测试。 -- 本轮补充 `deverd --root ` 本地服务和长度分帧 IPC:token 文件与 socket 均限制为 owner-only,`cache status/clean` 通过服务访问 CacheStore;服务不可用时客户端失败,不构造本地 store。跨平台 peer credential、系统服务注册、提权和真实双用户验证仍未完成。 diff --git a/.trellis/tasks/09-28-shared-toolchain/prd.md b/.trellis/tasks/09-28-shared-toolchain/prd.md deleted file mode 100644 index 3cca00b..0000000 --- a/.trellis/tasks/09-28-shared-toolchain/prd.md +++ /dev/null @@ -1,81 +0,0 @@ -# Dever 本机共享工具链 - -## Goal - -让一台机器上的所有用户和所有 Dever 项目始终使用同一个全局 `dever` 命令。Dever 内部负责安装、升级、版本选择、项目锁定、安全共享缓存和清理;用户不需要理解或指定编译器真实路径。 - -## Background - -- `deverc check/run/build ` 已经可以处理任意项目根目录,但当前只是开发仓库中的单个引导编译器。 -- 当前没有正式的全局 `dever` 入口、机器级安装目录、版本选择、项目锁定、升级回滚或卸载合同。 -- 当前 `compile`、`compile_application`、`compile_project` 和 `compile_test_suite` 把默认缓存固定到编译器源码工作区的 `target/native-artifacts`,不能作为多用户机器级缓存。 -- 现有缓存键已经包含编译器、后端工具、runtime、生成内容、平台和编译选项,并且发布过程具有完整性校验和并发原子性。 -- 项目配置只读取各项目自己的 `config/setting.json`;工具链选择也必须遵守这一配置边界,不增加环境变量或第二个项目配置文件。 - -## Requirements - -### Global Command - -- 每台机器只公开一个 `dever` 命令;普通用户和所有项目都调用这个入口。 -- 全局入口不得要求用户设置 `PATH` 之外的 Dever 环境变量,也不得要求用户知道内部版本目录。 -- `check/api/fmt/test/run/build/tenant` 等现有命令参数保持项目根合同,入口只负责选择工具链后原样分派。 - -### Installation And Versions - -- 提供 `dever install `、`dever update`、`dever use ` 和 `dever uninstall `。 -- 初次安装、版本安装、切换和卸载按操作系统要求获取管理员权限;日常项目命令不需要管理员权限。 -- 多个版本安装在机器级版本目录,安装与切换使用 staging + atomic rename,失败时保留当前可用版本。 -- 下载的发行物必须校验受信签名和内容摘要;不得执行未验证的编译器。 -- `dever update` 安装并切换到新版本;失败或健康检查不通过时自动保留旧版本。 -- 卸载当前默认版本必须先切换到其它版本;项目锁定了已卸载版本时给出明确的安装命令,不静默改用其它版本。 - -### Project Selection - -- 项目可以在 `config/setting.json` 中可选声明 `dever.version`。 -- 已锁定项目精确选择该版本;未锁定项目使用机器默认版本。 -- 版本缺失、格式非法或不受支持时在读取项目源码和运行项目程序前失败。 -- 版本选择不读取环境变量,不新增 `.dever-version`、lock 文件或用户级配置。 - -### Machine Sharing And Isolation - -- 所有操作系统用户共享同一个全局入口、已安装版本、标准库、runtime/target packs 和机器级缓存服务。 -- 每个项目的源码、`config/setting.json`、`data/`、构建输出、端口和运行进程保持独立,不复制到工具链目录。 -- 普通用户不能直接修改全局入口、已安装版本、默认版本状态或缓存条目。 -- 跨用户缓存不得让一个用户写入随后由另一个用户直接执行的未验证文件,也不得提供按目录浏览其他项目产物的能力。 - -### Shared Cache - -- 共享缓存由机器级 Dever 缓存/编译服务独占写入;客户端只提交完整构建输入并接收验证后的结果。 -- 缓存键改为密码学内容摘要,并继续覆盖编译器版本、runtime、目标平台、生成内容和编译选项。 -- 相同版本和相同完整输入可以跨项目、跨用户复用;不同输入、版本或目标不得复用。 -- 缓存发布保持不可变、完整性校验和并发原子性;普通用户不能伪造缓存命中。 -- 提供 `dever cache status` 和 `dever cache clean`;更新或卸载后自动清理没有引用的临时文件和损坏条目。 -- 缓存服务不可用时明确失败,不退回不受保护的全局可写目录;是否允许本次不使用共享缓存必须是显式 CLI 选项,而不是隐藏回退。 - -## Acceptance Criteria - -- [ ] 安装后,机器上的两个不同系统用户都通过同一路径的 `dever` 命令运行各自项目,无需用户级 Dever 安装。 -- [ ] 未锁定项目自动使用机器默认版本;`config/setting.json` 锁定版本的项目自动使用对应已安装版本。 -- [ ] 安装、升级、切换和卸载具有原子性;故障注入后旧的可用版本和全局入口不受损。 -- [ ] 签名错误、摘要错误、版本缺失和卸载当前版本均返回明确错误,不执行错误版本。 -- [ ] 两个项目或用户产生相同完整原生输入时命中同一缓存;输入、版本或目标改变时不会错误复用。 -- [ ] 非特权用户无法修改版本、默认状态或伪造缓存条目供其他用户执行。 -- [ ] 项目源码、配置、运行数据和显式构建输出不会进入共享安装目录或被其他用户通过 Dever 浏览。 -- [ ] `dever cache status/clean` 可检查和清理共享缓存;并发构建与清理不会暴露半成品或删除正在使用的条目。 -- [ ] 所有选择和运行行为不读取 `HOME`、`XDG_*`、`DEVER_*`、`RUSTC` 或其它 Dever 配置环境变量。 -- [ ] Linux、macOS 和 Windows 分别验证全局入口、系统权限、版本分派和升级回滚;实际支持平台必须与父发行任务一致。 - -## Out Of Scope - -- 修改 `.dever` 语言语法或应用业务目录规范。 -- 将项目运行配置移出 `config/setting.json`。 -- 云端编译、上传源码或依赖远程构建服务。 -- 在本任务重复实现父任务负责的 LLVM/LLD 后端和六目标交叉编译器;本任务消费父任务交付的可安装发行物。 -- 承诺不同源码产生的程序可以共享缓存;共享仅发生在完整输入一致时。 - -## Key Decisions - -- “简单”指用户只面对一个 `dever` 命令和项目现有的 `config/setting.json`,不是减少产品功能。 -- 全局入口与真实编译器版本分离:入口稳定,版本可以并存、切换和回滚。 -- `dever.version` 是唯一项目级工具链选择;机器默认版本是唯一未锁定项目选择,不存在更多优先级。 -- 跨用户写共享可执行缓存是安全边界,因此由机器服务持有,不能使用所有用户可写目录代替。 diff --git a/.trellis/tasks/09-28-shared-toolchain/task.json b/.trellis/tasks/09-28-shared-toolchain/task.json deleted file mode 100644 index 6f608e1..0000000 --- a/.trellis/tasks/09-28-shared-toolchain/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "shared-toolchain", - "name": "shared-toolchain", - "title": "Dever 本机共享工具链", - "description": "让一台机器上的所有用户和项目通过一个全局 dever 命令共享版本化工具链,并自动完成版本选择、更新与安全缓存", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-28", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-06-private-compiler-distribution", - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/09-29-build-cache-storage/check.jsonl b/.trellis/tasks/09-29-build-cache-storage/check.jsonl deleted file mode 100644 index ddf593b..0000000 --- a/.trellis/tasks/09-29-build-cache-storage/check.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"核对允许的离线定向检查和测试入口兼容性"} -{"file":".trellis/tasks/09-29-build-cache-storage/research/cache-boundaries.md","reason":"复核 clean 与机器级 cache clean 的安全边界"} -{"file":".trellis/spec/backend/error-handling.md","reason":"复核失败清理、符号链接拒绝和原始错误保留"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"复核 owner 唯一性并避免平行缓存实现"} diff --git a/.trellis/tasks/09-29-build-cache-storage/design.md b/.trellis/tasks/09-29-build-cache-storage/design.md deleted file mode 100644 index c81608b..0000000 --- a/.trellis/tasks/09-29-build-cache-storage/design.md +++ /dev/null @@ -1,76 +0,0 @@ -# Design - -## Boundaries - -本任务只修改编译器仓库构建策略、native runtime 准备路径和 CLI 临时产物清理。Cargo 开发产物由 Cargo profile 管理;native runtime 依赖由 `dever-core::native::build` 管理;项目命令解析由 `dever-cli` 管理。机器级缓存继续归 `deverd` 合同所有。 - -## Cargo Profiles - -根 `Cargo.toml` 增加 dev/test profile: - -```toml -[profile.dev] -debug = 0 -incremental = false - -[profile.test] -debug = 0 -incremental = false -``` - -这把多个任务已经稳定使用的命令级覆盖固化成仓库默认值。release profile 不变。测试目标、文件和选择命令全部保留。 - -## Native Runtime Layout - -当前每个 profile 都有完整 target: - -```text -target/native-runtime//release/... -``` - -改为一个共享 Cargo target 和不可变的精确输入视图: - -```text -target/native-runtime/ - cargo/ shared Cargo target - inputs// exact runtime/dependency files for one build identity - operations/ build locks/staging -``` - -`runtime_library` 根据 database、api、crypto、wire、external 得到规范化 feature 集。Cargo 使用 `--message-format=json-render-diagnostics` 报告本次图中的产物;代码通过结构化 JSON 解析收集当前 `dever-runtime` 及其依赖的 rlib/dylib,不扫描并吞入整个历史 `release/deps`。 - -收集后的文件先写入同一文件系统的 staging,再按内容身份原子发布到 `inputs/`。相同文件优先使用硬链接以复用共享 target 的磁盘块;不支持或失败时复制。已发布输入视图只读且不可变,`RuntimeInputs` 继续对精确文件集合计算身份并在编译前复核。并发操作使用 create-new 锁和 staging,失败只清理本次 staging。 - -## Temporary Directory Contract - -`BuildDirectory` 保留 RAII 清理。创建目录时增加固定格式 owner marker,至少包含格式版本、创建时间、进程 ID 和当前编译器身份。清理逻辑集中在 `native/build`,不在 CLI 复制一套删除规则。 - -自动清理和显式 clean 共同调用这一逻辑: - -1. 只枚举系统临时目录直属的 `dever-build--`。 -2. 使用 `symlink_metadata`,拒绝符号链接和非真实目录。 -3. marker 必须完整匹配且创建时间达到 24 小时过期阈值。 -4. 当前进程目录永不删除;不满足任一条件即跳过。 -5. 删除前统计普通文件字节数,返回结构化 summary。 - -24 小时阈值避免误删并发或长时间构建;正常流程仍由 `Drop` 立即清理,因此阈值只影响异常退出遗留物。 - -## Run Flow - -`NativeProgram` 已拥有可执行文件和临时目录,`run_native` 直接执行 `native.executable()`。借用在子进程退出前持续有效,随后 `NativeProgram` 的 `BuildDirectory` 统一回收。删除 `StagedExecutable` 和项目根二次复制路径。 - -## Clean Command - -CLI 增加 `Action::Clean` 和 `clean ` 参数合同。launcher 把它视为普通项目命令,用项目的 `config/setting.json` 选择版本后原样分派。 - -核心不解析或修改项目源码,只调用 native build 的限定清理 API,并兼容清理项目根中符合旧 `.dever-run-` 命名、普通文件、当前用户和 24 小时阈值的历史遗留物。输出固定摘要,不把未删除的未知文件当作成功删除。 - -该命令不接触 `target/debug`;编译器贡献者仍使用 `cargo clean` 管理 Cargo 开发产物。它也不接触机器共享缓存;后者仍是 `dever cache clean`。 - -## Compatibility And Rollback - -- Dever 源码、配置、语言行为和 release 构建参数不变。 -- 现有测试目标名与定向命令不变。 -- 旧 `target/native-runtime/` 不再读取;可由 `cargo clean` 删除,不提供双路径兼容。 -- 共享 runtime target 若出现问题,可回滚 `native/build` 布局而不迁移项目数据;所有相关内容均可重建。 -- clean 只删除严格识别的过期临时产物,回滚不需要恢复数据。 diff --git a/.trellis/tasks/09-29-build-cache-storage/implement.jsonl b/.trellis/tasks/09-29-build-cache-storage/implement.jsonl deleted file mode 100644 index 8817898..0000000 --- a/.trellis/tasks/09-29-build-cache-storage/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/directory-structure.md","reason":"确认 native build、CLI、测试目录和单一 owner 边界"} -{"file":".trellis/tasks/09-29-build-cache-storage/research/cache-boundaries.md","reason":"保持 locked/offline 工具链、launcher 与机器共享缓存合同"} -{"file":".trellis/spec/backend/error-handling.md","reason":"保持临时目录生命周期、原子发布和清理错误合同"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"遵守定向测试与低磁盘验证约束"} diff --git a/.trellis/tasks/09-29-build-cache-storage/implement.md b/.trellis/tasks/09-29-build-cache-storage/implement.md deleted file mode 100644 index 14a10f2..0000000 --- a/.trellis/tasks/09-29-build-cache-storage/implement.md +++ /dev/null @@ -1,67 +0,0 @@ -# Implementation Plan - -## 1. Cargo Development Footprint - -- [x] 在根 `Cargo.toml` 固化 dev/test 的 `debug = 0` 与 `incremental = false`,保留 release profile。 -- [x] 增加静态回归,确认 profile 合同及所有既有 `[[test]]` 目标仍存在,不移动或合并测试源码。 - -## 2. Shared Native Runtime Target - -- [x] 把 runtime feature/profile 规范化为单一 build key,复用现有 runtime 身份与 native cache owner。 -- [x] 使用一个 `target/native-runtime/cargo` 执行 locked/offline Cargo build,并解析 Cargo JSON 产物消息。 -- [x] 原子发布只包含当前构建图精确文件的不可变 `inputs/`;复用公共文件且拒绝符号链接、缺失文件和不完整 staging。 -- [x] 让 `RuntimeInputs` 消费显式文件清单,不再扫描整个 `release/deps`。 -- [x] 增加 base、API、SQLite、PostgreSQL、component/external profile 隔离、复用、失败和并发定向测试。 - -## 3. Temporary Build Cleanup - -- [x] 为 `BuildDirectory` 增加 owner marker 与统一 cleanup summary;正常 `Drop` 行为保持。 -- [x] 在创建 native build 前执行有界的 24 小时过期清理,跳过当前、未知、未过期和符号链接目录。 -- [x] `run_native` 直接执行 `NativeProgram::executable()`,移除项目根 staging 和 `StagedExecutable`。 -- [x] 增加成功、编译错误、子进程失败、过期目录和恶意同名路径的定向回归。 - -## 4. Clean Command - -- [x] 给版本核心增加 `clean ` 解析和执行;输出删除目录、文件及字节汇总。 -- [x] 给稳定 launcher 增加项目根识别和帮助文本,保持 `dever cache clean` 的认证服务失败合同。 -- [x] 兼容回收严格匹配且过期的旧 `.dever-run-*` 普通文件,不删除显式 output 或其它隐藏文件。 -- [x] 增加 CLI 参数、版本分派、限定删除和重复 clean 幂等测试。 - -## 5. Documentation And Verification - -- [x] 更新 README、backend directory/toolchain/error/quality 规范,说明三种清理边界与默认低磁盘 profile。 -- [x] 运行 `git diff --check`。 -- [x] 运行 core/CLI/runtime 的 offline focused check,不运行 workspace 全量测试。 -- [x] 分别选择 default、API、SQLite、PostgreSQL、component 的最小定向编译或测试;PostgreSQL 只编译,不连接数据库。 -- [x] 测量 fresh target 和重复执行后的占用,验证低于 16 GiB 基线的 40% 且无变化重复增长不超过 5%。 -- [x] 复查磁盘空间、临时目录和项目根,确认没有遗留本轮测试产物。 - -## Completion Evidence (2026-09-29) - -- `cargo check --offline --locked -p dever-core -p dever-cli` passed. -- `deverc` argument tests passed 5/5; local clean, selected-version launcher dispatch and authenticated `cache clean` refusal regressions passed. -- Exact runtime input publication/reuse/concurrency regression passed. Actual native base, API, SQLite, PostgreSQL and external/component profile checks passed; PostgreSQL was compile-only and opened no database. -- The runtime layout contains one `target/native-runtime/cargo` plus content-addressed `inputs`; no per-feature Cargo target remains. Repeating the external native check changed target usage from 1,625,111,299 bytes to 1,625,111,299 bytes (0%). -- The final focused matrix used 1,642,122,909 bytes (about 1.64 GB), 10.2% of the former 16 GiB baseline and below the 6.4 GiB budget. `target/debug/incremental` is an empty Cargo-created directory (0 files, 4 KiB), not an incremental object cache. -- No `/tmp/dever-build-*` or project `.dever-run-*` artifact remained. Final filesystem availability was about 17 GiB. -- `cargo fmt --all --check` and `cargo clippy ...` were unavailable because the installed toolchain lacks rustfmt and clippy. Workspace-wide tests, real PostgreSQL, frontend builds and performance/RSS benchmarks were not run by scope. -- Two pre-existing source fixtures were not counted as task verification: `rest_model::rest_field_bindings_are_checked_and_emit_static_search_sql` references missing generated `api_require_components`/`job_migrate_tenant`, and `sqlite_orm::database_failures_are_captured_after_transaction_rollback_and_task_wait` exposes a private `ReadResult` from `public main`. The selected SQLite and PostgreSQL profile checks passed through independent valid fixtures. - -## Final Review Evidence (2026-09-29) - -- Final review found and fixed three correctness gaps: runtime publication now selects the current `dever-runtime` manifest's hashed `release/deps` rlib instead of the mutable top-level Cargo alias; runtime input views reject symbolic links and unknown entries; stale cleanup preserves artifacts owned by any still-active recorded PID, not only the current process. -- The clean regression now keeps both a marked build directory and legacy `.dever-run-*` file for a live child process. Input-view regressions cover concurrent publication, exact dependency sets, unknown files and symbolic links. -- `cargo check --offline --locked -p dever-core -p dever-cli` passed after the fixes. -- `cargo test --offline --locked -p dever-tests --test native_cache runtime_input_views -- --nocapture` passed 2/2; the real concurrent native publication test passed twice and left no temporary artifact. -- `cargo test --offline --locked -p dever-cli --test cms_project clean_removes_only_stale_owned_dever_artifacts -- --exact --nocapture` passed 1/1. -- Selected-version launcher dispatch and authenticated `cache clean` refusal passed 1/1 each; `deverc` argument tests passed 5/5; the Cargo profile/test-target contract passed 1/1. -- Repeating the same concurrent native check left `target/` at exactly 1,689,816,322 bytes (0% growth). Final follow-up checks left it at 1,689,817,710 bytes (about 1.69 GB, 10.6% of the former 16 GiB baseline). Only `cargo` and `inputs` exist directly under `target/native-runtime`; `target/debug/incremental` contains zero files. -- No `/tmp/dever-build-*` or repository-root `.dever-run-*` remained. `git diff --check` passed and about 17 GiB remained available. -- `rustfmt` and `clippy` remain unavailable because those toolchain components are not installed. Workspace-wide tests, real PostgreSQL, frontend builds and performance/RSS benchmarks remain not run by scope. - -## Risks And Rollback Points - -- Runtime input discovery depends on Cargo's JSON artifact contract. Missing or ambiguous current-manifest runtime artifacts fail explicitly instead of scanning historical files. -- Process-state detection is conservative: an inspection failure preserves the candidate, so cleanup may leave an old artifact rather than risk deleting an active one. -- The shared target and input views are rebuildable. Rollback removes this layout through `cargo clean`; no project data migration is involved. -- Native test linking can still consume significant time and space even with deduplicated runtime inputs, so broad matrices remain opt-in. diff --git a/.trellis/tasks/09-29-build-cache-storage/prd.md b/.trellis/tasks/09-29-build-cache-storage/prd.md deleted file mode 100644 index 5f2a18c..0000000 --- a/.trellis/tasks/09-29-build-cache-storage/prd.md +++ /dev/null @@ -1,74 +0,0 @@ -# Dever 构建缓存与磁盘占用治理 - -## Goal - -在不改变 Dever 程序语义、发布构建性能和现有定向测试入口的前提下,显著降低编译器开发与原生运行时构建的磁盘占用,并让 Dever 自有临时产物可以可靠回收。 - -## Background - -- 2026-09-29 清理前,仓库 `target/` 占用约 16 GiB:`target/debug/deps` 约 11 GiB、`target/debug/incremental` 约 2.3 GiB、`target/native-runtime` 约 2.3 GiB。 -- `test/dever-tests` 有 67 个独立集成测试目标。每个目标都会单独链接 Dever runtime;清理前单个 debug 测试程序约 120-173 MiB。 -- 多个既有任务已经通过命令行反复使用 `profile.dev.debug=0`、`profile.test.debug=0` 和 `build.incremental=false` 避免磁盘耗尽,说明这些设置是已验证的仓库开发约束,但尚未固化。 -- `crates/dever-core/src/native/build.rs` 当前按 `base/database/sqlite/postgres` 与 `api/crypto/wire` 组合创建独立 Cargo target;公共依赖因此被完整复制到每个 profile 目录。 -- `BuildDirectory` 已在正常返回和普通错误时通过 `Drop` 清理,但进程被强制终止或链接器崩溃时仍会留下 `/tmp/dever-build--`。 -- `dever cache clean` 已属于机器级共享缓存合同,必须等待认证 `deverd` IPC;本任务不得以本地直写方式绕过该安全边界。 - -## Requirements - -### R1. Cargo Development Profiles - -- 在仓库 Cargo 配置中固化 dev/test 的低磁盘设置,不再依赖每条验证命令重复传入临时覆盖项。 -- dev/test 不生成完整调试信息且禁用增量对象;release 的 `fat LTO`、优化级别和最终程序行为保持不变。 -- 保留现有独立测试目标及 `cargo test --test ` 合同;本阶段不通过合并测试文件换取空间。 - -### R2. Shared Native Runtime Build Target - -- 所有 runtime feature profile 共享一个 Cargo 构建 target,公共依赖只保存一份。 -- 每次 native 编译只消费当前 Cargo 调用实际报告的 runtime 与依赖产物,不把其它 profile 的历史依赖混入缓存身份或链接输入。 -- 不同数据库/API/加密/wire/external profile 仍有独立、完整且可验证的 runtime 身份;并发构建不得读到正在改写的半成品。 -- 继续使用 locked/offline Cargo,不引入网络、环境配置或第二套构建协议。 - -### R3. Temporary Build Ownership - -- 正常成功、编译失败和运行结束继续即时清理本次临时目录。 -- `run` 直接执行 `NativeProgram` 已拥有的临时可执行文件,不再向项目根复制 `.dever-run-`。 -- 临时目录写入 Dever 自有标记;启动构建和显式清理只处理名称、标记、类型、属主和年龄均符合合同的目录。 -- 清理拒绝符号链接、未知目录、活跃或未达到过期阈值的目录;清理失败不得掩盖原始编译或运行错误。 - -### R4. Local Clean Command - -- 版本核心提供 `clean `,开发入口 `deverc` 与正式 launcher 分派后的 `dever` 使用同一实现。 -- 命令只回收当前用户的 Dever 过期临时构建目录和旧版遗留的过期 `.dever-run-*`,并输出删除数量与字节数。 -- 命令不得删除显式 build 输出、项目源码/配置/data、Cargo registry、Lib 缓存、机器共享缓存或其它项目文件。 -- `dever cache clean` 的名称、失败合同和认证 IPC 边界保持不变。 - -### R5. Documentation And Regression Coverage - -- README 和 toolchain 规范明确区分 `clean`、`cache clean` 与编译器仓库维护用的 `cargo clean`。 -- 测试覆盖参数解析、限定删除、符号链接拒绝、未过期目录保留、runtime profile 隔离和共享依赖复用。 - -## Acceptance Criteria - -- [ ] dev/test profile 默认不生成完整 debuginfo,也不创建 incremental 目录;release profile 保持原值。 -- [ ] 现有 `cargo test --test ` 入口不变,至少一个默认、API、SQLite、PostgreSQL 和 component 定向目标可以继续被单独选择。 -- [ ] 连续准备至少两个不同 runtime profile 时只存在一个 Cargo target,公共依赖不再按 profile 复制;每个 profile 链接到自身准确的 runtime 产物。 -- [ ] 并发或失败的 runtime 准备不会发布半成品,也不会让一个 profile 复用另一个 profile 的 runtime 身份。 -- [ ] `run` 不再创建项目根 `.dever-run-*`;成功和普通失败后本次临时目录不存在。 -- [ ] `clean ` 只删除符合 Dever 标记和过期规则的自有临时产物,并报告回收结果;未知文件、符号链接、未过期目录及显式输出保持不变。 -- [ ] `dever cache clean` 仍明确走机器共享缓存服务,未实现认证 IPC 时不允许本地回退。 -- [ ] 在全新 target 上完成允许的代表性 feature 定向检查后,`target/` 总占用不超过清理前 16 GiB 基线的 40%;重复同一组检查且源码不变时占用增长不超过 5%。 -- [ ] `git diff --check` 和受影响 crate 的离线定向检查通过;不运行 workspace 全量测试、真实 PostgreSQL、前端构建或性能压测。 - -## Out Of Scope - -- 实现或绕过尚未完成的认证 `deverd` IPC 和跨用户共享缓存清理。 -- 删除用户业务数据、显式构建输出、第三方包缓存或正在使用的缓存。 -- 改变 release 优化、最终程序语义、Dever 语言语法或应用配置格式。 -- 本阶段合并 67 个测试目标;只有 profile 与 runtime 去重后仍不能达到磁盘预算时再单独评估。 -- 把 Cargo 开发目标暴露成 Dever 应用运行时配置。 - -## Key Decisions - -- 根因是完整 debuginfo、增量对象、独立测试链接和 profile target 重复,不是源码本身或最终 Dever 二进制达到 16 GiB。 -- 保留小而可定向的测试目标比合并成少量巨大 runner 更有维护价值;先使用低磁盘 Cargo profile 解决体积。 -- 本地 `clean` 和机器级 `cache clean` 是不同安全边界,不能为了“一个命令”让普通项目进程直接写共享缓存。 diff --git a/.trellis/tasks/09-29-build-cache-storage/research/cache-boundaries.md b/.trellis/tasks/09-29-build-cache-storage/research/cache-boundaries.md deleted file mode 100644 index 0caf59e..0000000 --- a/.trellis/tasks/09-29-build-cache-storage/research/cache-boundaries.md +++ /dev/null @@ -1,14 +0,0 @@ -# Cache Boundary Evidence - -## Existing Owners - -- `.trellis/spec/backend/toolchain-and-library.md`:正式 `dever` launcher 统一选择版本并分派项目命令;机器共享缓存只能通过认证 `deverd` 服务访问,服务不可用时必须明确失败,不能退回普通用户可写目录。 -- `.trellis/tasks/09-28-shared-toolchain/prd.md`:`dever cache status/clean` 属于跨项目、跨用户的机器级缓存合同,运行条目使用租约,清理与构建必须互斥。 -- `crates/dever-cli/src/toolchain/launcher.rs:58`:当前 `cache status/clean` 调用统一返回认证缓存服务尚不可用,未直接构造 `CacheStore`。 -- `crates/dever-cli/src/toolchain/cache.rs:157`:`CacheStore::clean` 是未来特权服务内部的文件系统引擎,不是项目进程可调用的公开回退路径。 - -## Task Boundary - -- 新的 `clean ` 只能清理当前用户、当前 Dever 版本严格识别的过期临时构建目录和旧项目 staging 文件。 -- `clean` 不读取、修改或删除机器共享缓存条目,不改变 `dever cache clean` 的命令和失败合同。 -- 编译器仓库的 `target/debug` 继续由 Cargo 管理;普通 Dever 项目不会通过应用配置控制 Cargo 开发缓存。 diff --git a/.trellis/tasks/09-29-build-cache-storage/task.json b/.trellis/tasks/09-29-build-cache-storage/task.json deleted file mode 100644 index f851354..0000000 --- a/.trellis/tasks/09-29-build-cache-storage/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "build-cache-storage", - "name": "build-cache-storage", - "title": "Dever 构建缓存与磁盘占用治理", - "description": "降低 Rust 测试和原生运行时构建占用,可靠清理临时产物并提供统一清理命令", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-29", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/09-29-external-lib-ecosystems/check.jsonl b/.trellis/tasks/09-29-external-lib-ecosystems/check.jsonl deleted file mode 100644 index 4d3188d..0000000 --- a/.trellis/tasks/09-29-external-lib-ecosystems/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"CLI、filesystem、offline fixture 和确定性测试"} -{"file":".trellis/spec/backend/error-handling.md","reason":"resolver/cache/protocol failure 分类"} -{"file":".trellis/tasks/09-29-external-lib-ecosystems/prd.md","reason":"生态子任务验收标准"} diff --git a/.trellis/tasks/09-29-external-lib-ecosystems/design.md b/.trellis/tasks/09-29-external-lib-ecosystems/design.md deleted file mode 100644 index d56eab9..0000000 --- a/.trellis/tasks/09-29-external-lib-ecosystems/design.md +++ /dev/null @@ -1,23 +0,0 @@ -# Design - -## Resolver Boundary - -CLI 使用一个 closed ecosystem dispatch:parse requested spec、resolve fixture/registry metadata、fetch verified artifact、produce normalized locked graph。生态实现只处理自己的 metadata;缓存发布、摘要、路径安全、lock 排序和诊断由共享 owner 负责。 - -## Lock - -`dever.lock` 是 compiler-owned canonical document,包含 format version、Dever toolchain identity、Adapter identity、Port schema hash、ecosystem、requested spec、runtime pack、target artifacts、dependency graph 和 SHA-256。未知字段、重复键或手工修改在 doctor/project command 中拒绝并提示重新解析。 - -每个 Adapter 拥有隔离 dependency graph,因此两个 Adapter 可以锁定同一生态包的不同版本。共享 cache 只按已验证内容去重,不合并运行环境。 - -## Runtime Packs And SDK - -- pip:固定 CPython pack,优先验证 wheel;source distribution 只能进入隔离构建 sandbox。 -- npm:固定 Node pack,lifecycle scripts 默认禁用,需要的 build hook 进入隔离 sandbox。 -- go:固定 Go pack,按 target 编译 worker;需要 cgo 时必须存在受管 target toolchain,否则明确拒绝。 - -三个 SDK 共用生成的 operation/type/error schema fixture;语言层只负责数据映射和协议循环。日志写 stderr,不能读取应用 setting 文件或环境变量配置。 - -## Network Boundary - -网络只由显式 add/update resolver 使用。registry URL 和信任根属于签名工具链发行合同,不由项目或环境变量覆盖。测试使用本地 fixture registry 和 test-owned cache,不连接真实 registry。 diff --git a/.trellis/tasks/09-29-external-lib-ecosystems/implement.jsonl b/.trellis/tasks/09-29-external-lib-ecosystems/implement.jsonl deleted file mode 100644 index 09ca814..0000000 --- a/.trellis/tasks/09-29-external-lib-ecosystems/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"CLI、cache、offline、runtime pack 和 config boundary"} -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Adapter schema identity 与业务边界"} -{"file":".trellis/tasks/09-28-shared-toolchain/design.md","reason":"机器级共享 cache、版本和权限 owner"} -{"file":".trellis/tasks/09-29-external-lib-protocol/design.md","reason":"SDK 必须实现的唯一协议"} diff --git a/.trellis/tasks/09-29-external-lib-ecosystems/implement.md b/.trellis/tasks/09-29-external-lib-ecosystems/implement.md deleted file mode 100644 index 0419246..0000000 --- a/.trellis/tasks/09-29-external-lib-ecosystems/implement.md +++ /dev/null @@ -1,42 +0,0 @@ -# Implementation Plan - -- [x] 定义 requested/locked/artifact/runtime-pack 内部模型和 canonical lock codec。 -- [x] 实现共享 resolver orchestration、SHA-256、归档安全、atomic lock/cache publish 和 doctor。 -- [x] 增加 `dever lib add/list/update/remove/doctor` 并复用统一项目根/诊断处理。 -- [x] 提供 `ArtifactStore` 适配边界和 test-owned 内容寻址 fixture;正式 `deverd` IPC 仍由共享工具链任务提供。 -- [x] 实现 PyPI wheel/PEP 508/440、npm packument/semver/SRI 和 Go proxy/MVS resolver,接入已验证安装版本及签名 runtime 描述。 -- [ ] 发行正式 CPython/Node/Go runtime/build pack 并运行无宿主验收。 -- [x] 完成锁定 host-target build pack 的受管 Go compile/link、build tags、module ZIP、go:embed 与同名操作绑定;源码移除和清空环境独立 Worker 执行通过。 -- [x] 完成 Python extras/wheel/sdist/PEP517、npm 高级依赖图/安装钩子/native addon 与 Go sumdb;2026-10-02 已运行官方第三方依赖隔离构建和离线 Worker 验收,证据见父生产化任务。 -- [x] Python、JavaScript、Go SDK 协议库、checked manifest typed 校验及显式宿主验收;Python/JS 自动同名 entry 绑定已接入打包器。 -- [x] 使用本地 fixture registry 覆盖 deterministic lock、摘要、归档路径、冲突、offline 和双 target cache 隔离。 -- [x] ArtifactStore 提供 verified `get`,并拒绝摘要不匹配;npm scoped name 和 remove 依赖关系有明确诊断。 -- [x] 增加 `LibResolver`/`ProviderManifest` 边界和真实 provider 接线;仅显式 Lib 命令解析/下载,不读取 PATH 或环境变量。 -- [x] `doctor` 按各生态校验精确依赖图、可达闭包和构建收据;npm 允许合法依赖环。ArtifactStore 在 Worker 启动前验证目标和摘要。 -- [x] 编译器/CLI 接通 external Adapter 的精确 Lib 请求:支持 `lib "pip:name@version"`、`lib "npm:name@version"`、`lib "go:name@version"`,请求进入 schema identity 并参与 lock 校验。 -- [x] 更新 LANGUAGE、README、IMPLEMENTATION 与 compiler/toolchain specs,保留尚未实现和缺发行资产的边界。 -- [x] 运行 CLI/lib resolver/SDK 定向测试;只使用注入 transport、自有 loopback 镜像和显式宿主 fixture,不访问公网 registry、不运行全量。 - -## Current implementation boundary - -2026-10-02:当前锁格式为 v5,Python extras/原生 wheel/sdist 构建、npm 嵌套/peer/optional/bundled 图、安装钩子与 native 分类裁剪、Go sumdb 已实现。最终默认解析 **71/71**,Worker **7/7**,严格 CLI Clippy 通过;simplejson3.20.1、bufferutil4.0.9 和 google/uuid1.6.0 的显式真实构建与离线 Worker 均通过。命令、作者资产与运行日志统一记录于 `../09-29-language-production-closure/implement.md`,不复制历史进度为当前缺口。正式公开及其他平台资产尚未交付,任务暂不归档。以下为历史基线。 - -本阶段已完成 compiler-owned lock/resolver boundary、真实 registry resolver、机器共享资产缓存及三 SDK typed manifest。显式宿主协议验收不是正式受管 pack/无宿主发行验收;未安装签名 runtime 描述的开发入口仍明确失败,不使用系统包管理器或宿主语言环境。 - -2026-09-30:Lib 声明统一到 `config/setting.json.lib`,拒绝旧独立文件;canonical v2 lock 绑定 checked Worker contract 与 runtime(零 Lib managed Worker 也锁 runtime)。每个 Worker 独立 resolve/doctor,跨 Worker 版本可以不同。嵌入精确比对完整 provider 元数据。CLI `external_libs` 最终 27/27 通过,真实 provider 测试注入协议 transport,Go ZIP 的受限跳转使用自有 loopback HTTP 镜像;不使用 FixtureRegistry 冒充产品解析,也不声称已访问公网/发行 pack。Linux 不同 UID 的 artifact put/get、token 隔离和 owner-only clean 通过。CLI Clippy `-D warnings` 与所属文件私有 rustfmt check 通过。 - -## Review Gates - -- 不让各 resolver 重复 lock/cache/path/HTTP 验证。 -- Go ZIP 重定向仅允许固定 GCS bucket、最多两跳、总 30 秒;URL 规范化、userinfo/fragment/端口/路径检查与循环/Location 检查都在后续请求前,诊断不回显签名 URL。 -- 不在 run/build 中解析版本或联网。 -- 不允许项目 registry URL、runtime path 或 token 来自环境变量。 -- 不把生态依赖模型暴露成 Dever 业务类型。 - -## Verification - -- `cargo check --offline -p dever-cli`:通过。 -- `cargo test --offline -p dever-cli --lib libs::tests`:4/4 通过。 -- `cargo test --offline -p dever-cli --test external_libs`:3/3 通过。 -- 手工 `deverc lib add/list/doctor`:通过。 -- 未运行公网 registry 下载、正式签名 runtime 或全量测试;真实 resolver 的定向证据来自注入 transport 的协议元数据,不能等同于发行验收。 diff --git a/.trellis/tasks/09-29-external-lib-ecosystems/prd.md b/.trellis/tasks/09-29-external-lib-ecosystems/prd.md deleted file mode 100644 index 1d63b7c..0000000 --- a/.trellis/tasks/09-29-external-lib-ecosystems/prd.md +++ /dev/null @@ -1,37 +0,0 @@ -# Dever Lib 生态解析 - -## Goal - -在统一 external Adapter/Worker 协议之上,实现确定性的 `dever lib`、`dever.lock`、机器级内容缓存以及首批 pip/npm/go resolver 和官方 SDK。 - -## Dependencies - -- `external-lib-protocol` 已完成并冻结协议版本和 external Adapter HIR。 -- `shared-toolchain` 提供机器级版本目录、权限和共享 cache API;本任务不复制该实现。 - -## Requirements - -- 命令固定为 `lib add/list/update/remove/doctor ...`,保持 CLI 的显式项目根合同。 -- spec 使用 `pip:name@version`、`npm:name@version`、`go:module@version`;禁止无版本请求进入 lock。 -- `add/update` 解析完整传递依赖、平台 artifact、runtime pack 与摘要,写 canonical `dever.lock`;写入采用 prepared + atomic replace。 -- `list/doctor/remove` 默认不联网;`doctor` 校验声明、lock、缓存和 Adapter schema identity 一致。 -- 共享 cache 按 verified bytes 和 target identity 去重;项目之间不共享可写 dependency state。 -- pip/npm/go 各自使用固定 resolver adapter,不执行项目提供的 shell;需要构建的生态 hook 必须在声明 capability 的隔离构建 sandbox 内运行。 -- Python、JavaScript、Go SDK 实现同一个协议和生成的类型合同;SDK 不定义第二套业务 schema。 -- 所有项目命令离线消费 lock;缺失 artifact 给出需要执行的精确 `dever lib` 命令,不隐式下载。 - -## Acceptance Criteria - -- [ ] 三个生态的本地 fixture registry 解析出确定性 lock;重复解析字节一致。 -- [ ] 版本冲突、摘要错误、篡改 cache、非法归档路径、缺平台 artifact 和 schema 漂移均明确失败。 -- [ ] 两个项目共享相同 artifact bytes,但 lock、Adapter setting 和项目文件保持隔离。 -- [ ] Python/Node/Go SDK fixture 完成 handshake、success、declared error、cancel 和 shutdown。 -- [ ] PATH 中放置伪造 python/node/go 不影响选择;不读取语言相关环境变量。 -- [ ] 断网且 cache 完整时项目命令前置验证成功;cache 缺失时不联网。 -- [ ] 新 resolver 可通过固定内部接口加入,不修改 CLI 命令、lock 核心 schema 或 Worker 协议。 - -## Out Of Scope - -- Maven、NuGet、Composer、Gem 的正式 resolver。 -- 公共 registry 服务建设和真实互联网端到端测试。 -- 最终应用资源嵌入与目标机器运行。 diff --git a/.trellis/tasks/09-29-external-lib-ecosystems/task.json b/.trellis/tasks/09-29-external-lib-ecosystems/task.json deleted file mode 100644 index 9c92018..0000000 --- a/.trellis/tasks/09-29-external-lib-ecosystems/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "external-lib-ecosystems", - "name": "external-lib-ecosystems", - "title": "Dever Lib 生态解析", - "description": "实现 dever lib、dever.lock、机器缓存及 pip/npm/go 依赖解析和 SDK", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-29", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-29-external-libs", - "relatedFiles": [], - "notes": "2026-10-02:高级生态产品实现和Linux实际第三方构建/Worker验收已补齐,最终external_libs71/71、workers7/7,CLI严格Clippy通过。包括extras/原生wheel/sdist/PEP517、npm复杂安装图/hooks/native分类与物理裁剪、Go sumdb及官方UUID。正式公开/其他平台资产仍未交付;保留in_progress,不将私有签名fixture冒充正式发行。准确命令和运行证据统一见09-29-language-production-closure/implement.md。", - "meta": {} -} diff --git a/.trellis/tasks/09-29-external-lib-packaging/check.jsonl b/.trellis/tasks/09-29-external-lib-packaging/check.jsonl deleted file mode 100644 index 911bc7c..0000000 --- a/.trellis/tasks/09-29-external-lib-packaging/check.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"actual run/build、filesystem integrity 和 isolated executable tests"} -{"file":".trellis/spec/backend/error-handling.md","reason":"resource/Worker startup failure 必须保持 runtime fault"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"build/runtime ownership 和 root test 位置"} -{"file":".trellis/tasks/09-29-external-lib-packaging/prd.md","reason":"打包子任务验收标准"} diff --git a/.trellis/tasks/09-29-external-lib-packaging/design.md b/.trellis/tasks/09-29-external-lib-packaging/design.md deleted file mode 100644 index 237c066..0000000 --- a/.trellis/tasks/09-29-external-lib-packaging/design.md +++ /dev/null @@ -1,21 +0,0 @@ -# Design - -## Build Graph - -native specialization 保留所有生产 Adapter successors。构建器从可达 external Adapter 收集 locked environment,按 target 调用 ecosystem packager,得到 `{manifest, executable/runtime files, digests}`。相同 digest 的资源在应用资源表中 intern 一次。 - -## Embedded Resource Format - -应用资源表包含 format/version/target/path/mode/length/SHA-256 和压缩 bytes。entry path 是 manifest 内部标识,不接受部署配置覆盖。生成程序启动时验证 resource table,再按需释放 selected Adapter 的完整 environment。 - -## Extraction - -根固定为可执行文件同级 `data/cache/lib`。每个 digest 使用 `.staging--` 私有目录,写入时拒绝 symlink、父级跳转和重复 path;逐文件 fsync/权限设置/摘要复核后原子 rename。已发布目录必须复核 manifest 和 entry digest,失败即报错,不原地修补。 - -## Package Resolution - -Dever Package 发布内容保留 external declaration 和 requested Lib specs,不携带开发者机器的 lock/cache。应用项目统一解析所有直接与传递请求到自己的 `dever.lock`;每个 Adapter environment 独立,因此版本差异不需要强行全局合并。相同 artifact bytes 仍由机器 cache 和应用资源表去重。 - -## Output Contract - -保持当前单个独立可执行文件合同。外部 runtime 增加体积但不改变命令;`dever build` 输出确定性 size report,避免把 Python/Node runtime 成本误认为 Dever 核心体积。 diff --git a/.trellis/tasks/09-29-external-lib-packaging/implement.jsonl b/.trellis/tasks/09-29-external-lib-packaging/implement.jsonl deleted file mode 100644 index 236d1cc..0000000 --- a/.trellis/tasks/09-29-external-lib-packaging/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"native build、cache、standalone output 和 runtime lifecycle"} -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"closed Adapter reachability、effects 和 test fake"} -{"file":".trellis/tasks/09-06-private-compiler-distribution/prd.md","reason":"正式 target/runtime pack 与公开发行边界"} -{"file":".trellis/tasks/09-29-external-lib-ecosystems/design.md","reason":"locked environment 与 runtime pack 输入合同"} diff --git a/.trellis/tasks/09-29-external-lib-packaging/implement.md b/.trellis/tasks/09-29-external-lib-packaging/implement.md deleted file mode 100644 index c52a289..0000000 --- a/.trellis/tasks/09-29-external-lib-packaging/implement.md +++ /dev/null @@ -1,49 +0,0 @@ -# Implementation Plan - -- [x] 扩展 native build graph,按可达 external Adapter 精确收集 locked environment;Adapter 声明 `lib ":@"`,Program 导出去重后的精确请求,run/build 统一校验同一 lock。 -- [x] 定义 target packager 输出和共享 embedded resource manifest。 -- [x] 实现资源摘要、确定性排序和构建体积报告;当前 fixture 资源不做额外压缩。 -- [x] 在 runtime 实现安全 extraction、复核、atomic publish、并发首次启动和清理。 -- [x] 增加锁定依赖的传递闭包和 ArtifactStore 摘要/尺寸验证边界;Worker 启动前会拒绝缺失、环依赖或不完整 artifact。 -- [x] 让 run/build 共用 Worker preparation owner,不形成开发/生产两套路径。 -- [x] 实现 Python/JavaScript checked manifest、同名操作绑定、依赖/runtime 展开和受控启动;支持 Python 隔离、ESM/CommonJS、可信 SDK 优先加载。 -- [x] 实现锁定 build pack 的受管 Go compile/link、目标文件选择、module ZIP、go:embed 和静态操作绑定;独立 Worker 只携带编译产物与合同。 -- [ ] 交付正式签名语言 pack;自有 host-target Go pack 不代替六平台无宿主发行验收。 -- [x] 把 Dever Package external requests 接入项目 lock resolution、source loading 和 package 更新检查;保留组件级所有权与无本地回退边界。 -- [x] 保持 Adapter runtime selection;全部 checked exec 候选打包,只有 selected Worker 启动。 -- [ ] 增加无系统 runtime 的隔离执行、资源篡改/中断/并发、Package 传递依赖和 test fake 回归(当前已覆盖资源完整性、路径逃逸和重复发布 fixture)。 -- [ ] 更新 LANGUAGE、README、IMPLEMENTATION、toolchain/package/security specs。 -- [ ] 运行 run/build/package 定向测试和二进制体积分项检查;不运行全量或性能压测。 - -## Review Gates - -- 不把 `setting.json` 的当前 Adapter 选择编译进产物。 -- 不在运行时联网、解析版本或调用系统包管理器。 -- 不允许释放目录成为跨应用或跨用户的可写执行共享边界。 -- 不改变无 external Adapter 应用的资源、启动和输出合同。 - -## Current implementation boundary - -`dever lib` 已接真实 registry resolver、传递依赖和 daemon 资产缓存;packaging 把支持的锁定资源编译进 native application,入口经 `dever-runtime::external` 做私有 staging、SHA-256 复核和原子发布,`*.external.json` 输出分项体积报告。Python/JS preparation 生成 checked runner/SDK/launch manifest;`run` 与 `build` 共用同一份 lock/preparation 校验。raw pack/archive 在展开后仅为 config/exec 仍需的消费者保留,原生二进制输入按实际摘要去重;不同 Worker 的释放路径和清单仍隔离。 - -阶段收口补充:external Adapter 在声明体内列出精确 Lib 请求。编译器把请求纳入 external schema identity,CLI 从已检查 Program(含 Package 源码)收集每个 Worker 的请求,与 `config/setting.json.lib` 和 v2 `dever.lock` 精确核对。Dever Package 已接通版本/传递依赖、共享缓存、源码注入和统一 Lib 锁;不能以局部锁测试代替正式语言 pack 的发行验收。 - -真实 resolver、三 SDK typed manifest、Python/JS 自动 Worker、受管 Go compile/link、Dever Package 集成和 Linux 跨用户 artifact IPC 已实现。daemon build IPC、高级生态安装语义仍缺产品代码;正式签名 runtime pack 和无宿主目标验收未交付。宿主工具制作的自有 pack 定向用例不能等同于正式发行验收。 - -2026-09-30:实际 exec Worker 随程序嵌入,资源 identity 包含可执行位,启动绑定当前精确清单并重验字节和私有 Unix 权限。`external_resources` 6/6 通过,包括并发原子提取、路径/权限拒绝、部署目录不含源码 Worker、清空环境两次独立运行和篡改拒绝;`native_entry` 15/15、`port_adapter` 15/15、CLI `external_libs` 14/14 通过。这证明 exec 打包,不证明无 Python/Node/Go 环境的生态包执行。 - -## Verification - -2026-10-02当前状态:上方阶段记录中的v2与“daemon编译/高级生态未实现”已过时。当前使用v5 lock/源码构建收据,Linux daemon LLVM编译、签名pack/完整ELF闭包、真实第三方高级依赖和OS隔离已实现。展开输出在所有raw消费者消失后才裁剪。增强三生态签名安装/受管编译/移除源码与机器目录后的无系统语言独立执行 **1/1通过**(755.81秒),包含Python/Node原生依赖,Go第三方UUID另有独立Worker证据。Linux签名首装/双项目/真实双UID共享 **1/1通过**(231.51秒)。公开和其他平台发行仍未完成;精确限制与日志见`09-29-language-production-closure/implement.md`。 - -以下保留09-29历史检查,不能覆盖上述当前结果: - -- `cargo check --offline --workspace`:通过。 -- `cargo test --offline -p dever-runtime --features external external::tests`:1/1 通过(含路径逃逸、缓存污染和完整性校验)。 -- `cargo test --offline -p dever-cli --lib libs::tests`:4/4 通过。 -- `cargo test --offline -p dever-cli --test external_libs`:2/2 通过。 -- `cargo test --offline -p dever-tests --test native_entry project_entry_can_embed_verified_external_resources`:1/1 通过。 -- `cargo test --offline -p dever-tests --features component --test external_component`:1/1 通过。 -- `cargo test --offline -p dever-tests --test api_declarations`:16/16 通过。 -- 资源 native 完整编译/启动 smoke 曾尝试,但在当前磁盘/链接器约 120 秒限制内未完成,不能记为通过。 -- 未运行全量测试、真实 registry、真实 Python/Node/Go Worker、独立目标机运行和体积/内存压测。 diff --git a/.trellis/tasks/09-29-external-lib-packaging/prd.md b/.trellis/tasks/09-29-external-lib-packaging/prd.md deleted file mode 100644 index 18b0944..0000000 --- a/.trellis/tasks/09-29-external-lib-packaging/prd.md +++ /dev/null @@ -1,36 +0,0 @@ -# Dever Lib 构建与 Package 集成 - -## Goal - -把已锁定的 external Adapter 接入 `dever run/build`,生成无需目标机器安装第三方语言环境的自包含应用,并允许 Dever Package 声明和传递 Lib 依赖。 - -## Dependencies - -- `external-lib-protocol` 与 `external-lib-ecosystems` 已完成。 -- 私有编译器发行任务提供正式目标 runtime/worker packs;没有正式 pack 的目标不能标记支持。 - -## Requirements - -- `run` 在用户代码前验证 external declarations、lock、cache、runtime pack 和 schema,启动选中 Adapter Worker,并在应用生命周期结束时完整清理。 -- `build` 为目标平台准备所有运行时可选 external Adapter,不按当前 `setting.json` 偷偷裁剪闭合实现集合。 -- Worker、语言 runtime、依赖和 manifest 作为摘要保护的只读资源嵌入现有独立应用输出,不把源码、下载 cache 或构建工具链带入产物。 -- 运行时只释放到应用目录的 `data/cache/lib/`,使用私有 staging、完整性验证和原子发布;不执行已存在但摘要不匹配的文件。 -- Dever Package 中的 external declaration 是传递 Lib 请求来源;项目解析统一 lock,Package 使用者不需要直接运行 `lib add` 才能理解依赖,但缺 cache 时仍需显式联网命令。 -- Package 更新导致 Lib/schema 变化时必须更新 lock;旧 lock 不回退、猜测或运行。 -- 同一项目的不同 Adapter 可以携带不同 runtime/版本;构建报告分项显示体积,不隐藏大 runtime 成本。 - -## Acceptance Criteria - -- [ ] `run` 对 exec/Python/Node/Go fixture 自动启动、调用和关闭 Worker,现有纯 Dever 项目行为不变。 -- [ ] `build` 输出在没有 Python、Node、Go 和 Dever 编译器的隔离目标环境运行成功。 -- [ ] 资源截断、替换、权限错误、staging 中断和并发首次启动不会执行未验证或半成品 Worker。 -- [ ] 切换 `adapter..use` 不重新构建即可选择已打包候选;未打包/未知选择启动失败。 -- [ ] 安装一个携带 Lib 的 Dever Package 后,项目 lock 可确定性解析并离线重建。 -- [ ] 构建报告列出每个 runtime/Worker/依赖的压缩与释放体积,重复内容只嵌入一次。 -- [ ] application tests 继续使用 case fake,不释放或启动生产 Lib。 - -## Out Of Scope - -- 动态从生产网络下载缺失 Worker。 -- 把不同应用的运行时释放目录合并为全局可写执行目录。 -- FFI、共享库加载和外语源码调试器集成。 diff --git a/.trellis/tasks/09-29-external-lib-packaging/task.json b/.trellis/tasks/09-29-external-lib-packaging/task.json deleted file mode 100644 index 75a32a5..0000000 --- a/.trellis/tasks/09-29-external-lib-packaging/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "external-lib-packaging", - "name": "external-lib-packaging", - "title": "Dever Lib 构建与 Package 集成", - "description": "将外部 Lib 接入 run/build 自包含打包并允许 Dever Package 传递 Lib 依赖", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-29", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-29-external-libs", - "relatedFiles": [], - "notes": "2026-10-02:LLVM run/build、Package传递Lib、v5源码构建收据、精确runtime/产物身份、二进制资源附件及npm展开输出裁剪已接线。默认消费者71/7/12/11及当前native_release17/17通过。最终三生态签名安装/受管编译/移除源码和机器目录/无系统语言独立执行1/1通过755.81秒,含simplejson C扩展与bufferutil addon;Linux签名首装双项目双UID验收1/1通过231.51秒。正式公开/其他平台资源仍未交付,详细证据见09-29-language-production-closure/implement.md。", - "meta": {} -} diff --git a/.trellis/tasks/09-29-external-lib-protocol/check.jsonl b/.trellis/tasks/09-29-external-lib-protocol/check.jsonl deleted file mode 100644 index cbd48a4..0000000 --- a/.trellis/tasks/09-29-external-lib-protocol/check.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"parser、native process 和 bounded resource 定向测试"} -{"file":".trellis/spec/backend/error-handling.md","reason":"business error 与 runtime fault 不得混淆"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"compiler/runtime/CLI owner 和测试目录规则"} -{"file":".trellis/tasks/09-29-external-lib-protocol/prd.md","reason":"协议子任务验收标准"} diff --git a/.trellis/tasks/09-29-external-lib-protocol/design.md b/.trellis/tasks/09-29-external-lib-protocol/design.md deleted file mode 100644 index 03f7385..0000000 --- a/.trellis/tasks/09-29-external-lib-protocol/design.md +++ /dev/null @@ -1,23 +0,0 @@ -# Design - -## Compiler Model - -HIR `Adapter` 增加 closed implementation kind:`Dever` 或 `External`. `External` 保存 ecosystem、entry、capabilities 和 compiler-generated Port wire schema。Port 仍是唯一 Function ID;dependency/effect/failure owners 看到外部实现的显式摘要,不解析外语源码。 - -Parser 仅在 Adapter role 把 `external`、`lib` 和 `allow` 识别为 contextual syntax。首个子任务只接受 `external exec`,但 AST/HIR ecosystem 使用封闭 enum,后续 pip/npm/go 不复制 parser 或 dispatch。 - -## Wire - -每帧为 `u32 big-endian length + UTF-8 JSON`,最大正文复用 runtime wire 16 MiB 限制。消息包含固定 `kind` 与按 kind 严格字段;payload 使用 compiler-generated concrete codec,不把动态 Node 交给业务。 - -启动序列:supervisor 启动进程 -> `hello` -> Worker `ready` -> admission。关闭序列:停止 admission -> cancel pending -> `shutdown` -> join -> bounded kill。协议 EOF、非法 frame 或进程退出关闭全部 pending request,并保留第一个 runtime fault。 - -## Process Ownership - -新增 runtime `component` owner,封装 Child、stdin writer、stdout reader、stderr bounded logger、pending request table 和 Scope guard。所有 task 注册到现有结构化作用域;Drop 只能触发已有 supervisor 清理,不能 detached kill/reap。 - -不使用 shell、PATH 或应用环境变量。entry 由构建器规范化为当前项目/产物拥有的文件;运行器传入专用管道和固定协议参数。初期 sandbox adapter 提供统一拒绝/允许合同,平台强化放在后续生态/打包子任务,不假装纯 Rust 检查等于 OS sandbox。 - -## Failure Semantics - -Worker 返回的业务 error 必须匹配 Port declared error identity。启动、协议、timeout、crash 和 sandbox 失败转为 source-located runtime fault,不伪造业务 variant,不自动重放请求。崩溃后允许下一次调用创建新 Worker,但有固定启动频率上限。 diff --git a/.trellis/tasks/09-29-external-lib-protocol/implement.jsonl b/.trellis/tasks/09-29-external-lib-protocol/implement.jsonl deleted file mode 100644 index 2b1644b..0000000 --- a/.trellis/tasks/09-29-external-lib-protocol/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"external Adapter 必须复用 Port、role、failure/effect 和 test fake 合同"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"wire、native emission、settings 和 structured lifecycle 合同"} -{"file":".trellis/tasks/09-20-port-adapter/design.md","reason":"现有 Adapter registration、closed dispatch 和 setting 设计"} -{"file":".trellis/tasks/09-29-external-libs/design.md","reason":"父任务协议、source 和安全边界"} diff --git a/.trellis/tasks/09-29-external-lib-protocol/implement.md b/.trellis/tasks/09-29-external-lib-protocol/implement.md deleted file mode 100644 index 7d1daad..0000000 --- a/.trellis/tasks/09-29-external-lib-protocol/implement.md +++ /dev/null @@ -1,40 +0,0 @@ -# Implementation Plan - -- [x] 扩展 syntax/parser/formatter/Markdown,仅在 Adapter role 接受 external 声明并保持精确诊断。 -- [x] 扩展 HIR/Port 注册、role matrix、dependencies/effects/failures/specialization,复用现有 Adapter owner。 -- [x] 从 Port/setting 类型生成 Component Protocol schema hash 和 native codecs。 -- [x] 在 runtime 增加有界 frame codec、消息状态机和严格请求 ID 管理。 -- [x] 实现结构化 Worker supervisor、stdin/stdout/stderr、timeout/cancel/shutdown 和 crash cleanup。 -- [x] 将 external Port dispatch 接入 native emitter;reference 明确拒绝。 -- [x] 在仓库根 `test/` 增加 parser/contract/protocol/lifecycle/Port 回归,fixture 只使用测试自有可执行程序。 -- [x] 更新 LANGUAGE、IMPLEMENTATION、compiler/toolchain/directory/error specs。 -- [x] 运行受影响 crate check 及 external protocol、port_adapter、application_testing 定向测试;不运行全量或外部服务。 - -## Review Gates - -2026-10-02补充:以下09-29记录为历史切片。当前Rust/LLVM入口共用Scope-owned Worker与Linux namespace/seccomp;kernel能力/资源/后代清理、协议及LLVM定向已通过。GPU/其他平台拒绝,受限AppArmor非root入口尚未收口。准确日志与最终组合状态见`09-29-language-production-closure/implement.md`。 - -- 不新增第二套 JSON parser、effect graph、Adapter registry 或进程作用域。 -- 不允许外语 entry、Lib 或 capability 成为 App 可见类型。 -- 不使用 shell command string、PATH lookup、环境变量配置、detached process 或自动 retry。 - -## Implementation Record (2026-09-29) - -- Adapter-only `external exec` syntax、format 和 Markdown declaration contract 已接通;entry 只接受领域内的可移植相对路径,capability 固定为 `network/file/process/gpu`。 -- checker 从同领域唯一 Port 合成完整实现,复用原有 Adapter 选择、setting、wire、effect、failure、dependency 和 specialization owner;schema checksum 绑定 setting、操作、顶层 wire 字段名、具体类型和业务错误 payload。 -- native 生成具体输入/输出/error codec,正式调用统一进入 runtime Component Protocol;reference 对可达外部实现明确报不支持。 -- runtime Worker 使用显式 canonical entry、清空环境和固定参数启动,具有有界队列、启动频率、frame/JSON 限额、严格消息字段/request id、health、timeout/cancel drain、crash restart 和 bounded shutdown。关闭时先封闭 admission,再取消在途调用并丢弃排队调用;所有协议写入有期限,fault 和 shutdown 都在 supervisor 内显式 kill/wait。协议 fault 先关闭旧 receiver,再允许下一次调用重建 Worker,不继续复用已失配流。 -- 生成应用入口在 success、business error 和 runtime fault 后统一调用 `component::shutdown()`,随后才关闭数据库;主错误不被 cleanup error 覆盖。 -- capability 当前保证为编译期固定集合/effect 汇总以及 `ready` 精确回显校验;没有实现或宣称 OS 级 syscall/network/filesystem/GPU sandbox。 -- 未实现 resolver、`dever.lock`、机器级共享缓存、最终 build 资源嵌入、shell/PATH/env fallback、detached process 或 FFI。 - -## Verification Record (2026-09-29) - -- 初次 native 复验因根盘仅余约 156 MiB 无法暂存 runtime;仅删除仓库内可重建的 `target/debug/incremental` 后释放约 8.7 GiB,随后完成下列复验。未删除 Cargo 依赖缓存、native runtime 缓存、源码或用户数据。 -- PASS: `cargo check --offline -p dever-runtime --features wire`。 -- PASS: `cargo check --offline -p dever-core`。 -- PASS: `external_component` 1/1;覆盖 setting handshake、health、两次调用、业务 error、主动 cancel、timeout、crash/restart、fault cleanup、shutdown、80 个并发/排队调用的 admission closure、重复字段、乱序 ID、未知 kind、超大和截断 frame。 -- PASS: 完整 `port_adapter` target 14/14;覆盖 Adapter-only parser/check/format/Markdown、setting 与顶层 wire 名称的 schema 漂移、effect/failure、test fake、native Worker 端到端 dispatch 和 cleanup。 -- PASS: `application_testing` 8/8;application-test 发现、隔离、错误和 native suite 回归通过。 -- UNAVAILABLE: `cargo fmt --all -- --check` 与 Clippy;stable toolchain 未安装 rustfmt/cargo-fmt 和 cargo-clippy component。 -- NOT RUN: 全量、外部服务、数据库和性能测试;遵守本任务定向验证范围。 diff --git a/.trellis/tasks/09-29-external-lib-protocol/prd.md b/.trellis/tasks/09-29-external-lib-protocol/prd.md deleted file mode 100644 index f0edecc..0000000 --- a/.trellis/tasks/09-29-external-lib-protocol/prd.md +++ /dev/null @@ -1,32 +0,0 @@ -# Dever Lib 协议与 Worker - -## Goal - -在不引入任何具体语言包管理器的前提下,完成外部 Adapter 的语言合同、统一进程协议、通用 `exec` Worker 和安全生命周期,为所有后续生态提供唯一运行边界。 - -## Requirements - -- 仅 Adapter role 接受一个 contextual `external exec "relative/entry"` 声明;它可与一个现有 `setting` record 共存,不可与 Dever 实现函数混合。 -- 外部 Adapter 自动完整实现其对应 Port;缺 Port、多个 Port identity、非法 entry、Lib/capability 字段或不完整 Worker handshake 均在入口前失败。 -- 初始 capability 固定为 `network`、`file`、`process`、`gpu`;未知、重复或与平台不兼容的 capability 拒绝。 -- 复用 Port 的类型/failure/effect/setting schema,不向 App 暴露 Worker/JSON/进程类型。 -- 实现版本化、长度分帧、预算受限的 Component Protocol,并拒绝重复字段、未知消息、重复/未知请求 ID、错误 schema 和非法 error variant。 -- Worker 由应用 Scope 拥有,使用显式可执行路径和清理后的环境,不通过 shell 或 PATH 查找。 -- Test 继续要求 case-local Port fake,不启动生产 Worker,不读取 Adapter setting。 -- reference backend 对 external Adapter 返回明确不支持;native backend 完成正式执行,不增加模拟 fallback。 - -## Acceptance Criteria - -- [ ] 合法 external Adapter 通过 check/format/Markdown 合同,并参与现有 Port effect/failure/specialization。 -- [ ] 通用 fixture Worker 完成 setting handshake、两次调用、业务 error、取消、健康检查和正常关闭。 -- [ ] schema/Port/Adapter/protocol 不匹配、超大/截断/重复/乱序消息均在有界时间失败。 -- [ ] Worker 启动失败、崩溃、超时、调用取消和主程序退出不遗留子进程或悬挂任务。 -- [ ] stdout 只能承载协议,stderr 日志不会破坏响应;Secret 和输入值不进入协议错误。 -- [ ] 未声明 capability 的受控操作被 supervisor 拒绝;声明 capability 进入 Port 保守 effect。 -- [ ] 现有 Dever Adapter 选择和 application-test fake 回归保持通过。 - -## Out Of Scope - -- pip/npm/go resolver、SDK、联网下载和项目 lock。 -- 把 Worker 资源嵌入最终 build 产物。 -- FFI、动态库、任意 shell 和远程 Worker。 diff --git a/.trellis/tasks/09-29-external-lib-protocol/task.json b/.trellis/tasks/09-29-external-lib-protocol/task.json deleted file mode 100644 index 88bb6ab..0000000 --- a/.trellis/tasks/09-29-external-lib-protocol/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "external-lib-protocol", - "name": "external-lib-protocol", - "title": "Dever Lib 协议与 Worker", - "description": "实现 external Adapter 合同、统一组件协议、通用 exec Worker 与安全生命周期", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-29", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-29-external-libs", - "relatedFiles": [], - "notes": "2026-10-02:external Adapter、统一协议/Scope生命周期已接Rust及LLVM。Linux exec/managed共用OS namespace/seccomp边界,真实内核拒绝、线程/子进程/取消回收与协议回归通过;不再只有capability回显。GPU和未支持平台明确拒绝,受限AppArmor非root验收未通过。当前证据统一见09-29-language-production-closure/implement.md,保留未完成平台边界。", - "meta": {} -} diff --git a/.trellis/tasks/09-29-external-libs/check.jsonl b/.trellis/tasks/09-29-external-libs/check.jsonl deleted file mode 100644 index e743f06..0000000 --- a/.trellis/tasks/09-29-external-libs/check.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"定向测试、真实 CLI 和资源生命周期验证要求"} -{"file":".trellis/spec/backend/error-handling.md","reason":"业务 error、runtime fault 和协议错误边界"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"新增实现必须归属现有 compiler/runtime/CLI owners"} -{"file":".trellis/tasks/09-29-external-libs/prd.md","reason":"父任务跨子任务验收标准"} diff --git a/.trellis/tasks/09-29-external-libs/design.md b/.trellis/tasks/09-29-external-libs/design.md deleted file mode 100644 index 8a1c33a..0000000 --- a/.trellis/tasks/09-29-external-libs/design.md +++ /dev/null @@ -1,62 +0,0 @@ -# Design - -## Architecture - -```text -App -> typed Port -> selected Adapter -> Worker supervisor -> Component Protocol -> Lib -``` - -Port 保持现有 compiler-owned Function ID 和闭合实现集合。外部 Adapter 是新的实现种类,不是新业务调用层;checker 从 Port 合同合成 Worker operation schema,并把显式 capability 纳入既有 effect/dependency 分析。 - -## Source Contract - -建议外部 Adapter 保持现有 topic identity: - -```text -module/ai/embedding/port.dever -module/ai/embedding/adapter/python.dever -module/ai/embedding/adapter/python/main.py -``` - -```dever -setting { - model: Text -} - -external pip "python/main.py" { - lib "sentence-transformers@3.3.1" - allow gpu -} -``` - -一个外部 Adapter 文件恰好有一个 `external` 声明,可选现有 typed `setting`,没有 Dever operation body/helper。它由编译器合成该 Port 的全部实现,Worker handshake 必须提供全部 operation。入口必须是所属 Adapter 目录内的规范化相对路径。 - -## Component Protocol - -传输使用专用双向管道和四字节大端长度分帧 JSON,复用现有 wire codec 的 16 MiB、64 层、65536 值预算。stderr 只承载日志,不能进入协议。 - -消息固定为:`hello/ready/call/result/error/cancel/health/shutdown`。每次握手包含协议版本、Port identity、schema hash、Adapter identity 和 capability 集;不匹配立即结束 Worker。请求 ID 在单 Worker 生命周期内唯一,输出必须属于当前未完成请求。 - -## Worker Ownership - -每个选中外部 Adapter 启动一个长驻 Worker 和有界请求队列。supervisor 属于现有应用 Scope;入口启动完成后才允许用户代码,关闭时停止 admission、取消未完成请求、发送 shutdown 并在期限内 join/kill。崩溃使当前请求 fault;后续调用可以受限重启,但绝不重放已发送请求。 - -## Lib Resolution - -生态 resolver 共用请求/锁模型:requested spec -> exact artifacts -> content hashes -> runtime pack -> target set。resolver 只能在显式 `lib add/update` 联网,结果写 canonical `dever.lock` 并原子替换。项目命令只验证 lock 与缓存,不重新解析版本。 - -机器级 cache 和 runtime pack 消费 `09-28-shared-toolchain` 的全局工具链合同;在该合同完成前,生态子任务只使用测试自有 fixture store,不新增临时用户缓存协议。 - -## Build Packaging - -每个 Adapter 生成目标专用 Worker artifact。`build` 将所有运行时可选 Adapter、runtime pack、lock manifest 和摘要作为只读资源嵌入应用。首次使用时写入 `data/cache/lib/` 的私有 staging,校验后原子发布;主程序只执行匹配 manifest 的文件。 - -## Extension Boundary - -新增生态只实现四个固定面:spec parser、resolver、runtime/build packager、SDK。它不能扩展语法、Port 协议、业务类型系统、setting 来源或进程生命周期。 - -## Dependencies - -- 通用协议子任务可以先实现和验证。 -- 生态解析依赖机器级共享工具链目录/缓存合同。 -- 生产自包含打包依赖父发行任务提供可分发 runtime/target pack;本地 fixture 可以先验证封装格式。 diff --git a/.trellis/tasks/09-29-external-libs/implement.jsonl b/.trellis/tasks/09-29-external-libs/implement.jsonl deleted file mode 100644 index b307cb0..0000000 --- a/.trellis/tasks/09-29-external-libs/implement.jsonl +++ /dev/null @@ -1,5 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Port/Adapter、role visibility、failure/effect 和 application testing 合同"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"wire、settings、native build、CLI、runtime 生命周期和离线工具链合同"} -{"file":".trellis/tasks/09-20-port-adapter/design.md","reason":"复用现有闭合 Port dispatch、typed setting 与 test fake 设计"} -{"file":".trellis/tasks/09-28-shared-toolchain/design.md","reason":"复用机器级全局命令、版本和安全共享缓存边界"} -{"file":".trellis/tasks/09-06-private-compiler-distribution/prd.md","reason":"约束最终 runtime/target pack 与公开发行依赖"} diff --git a/.trellis/tasks/09-29-external-libs/implement.md b/.trellis/tasks/09-29-external-libs/implement.md deleted file mode 100644 index 0285f25..0000000 --- a/.trellis/tasks/09-29-external-libs/implement.md +++ /dev/null @@ -1,33 +0,0 @@ -# Implementation Plan - -- [x] 完成并验收 `external-lib-protocol`,冻结语法、wire 和生命周期合同。 -- [x] 完成全局工具链共享缓存的依赖接口,不在 Lib 任务复制机器安装/版本管理。 -- [x] 完成并验收 `external-lib-ecosystems` 的离线确定性边界,以本地 fixture registry 覆盖 lock/doctor/artifact 校验。 -- [x] 完成并验收 `external-lib-packaging` 的 fixture 资源打包、摘要复核和私有 extraction 边界。 -- [x] 跨子任务复核 Port effects/failures、setting/Secret、测试 fake、缓存身份和 `run/build` 行为。 -- [x] 更新 LANGUAGE、README、IMPLEMENTATION 和 backend specs,删除已被正式合同替代的占位说明。 -- [ ] 只运行各子任务列出的定向检查;不默认运行全量、真实外部 registry、服务或性能测试。 - -## 当前收口补充(2026-09-29) - -- [x] 已增加 `ProviderManifest`/`LibResolver` 边界,fixture provider 与真实 pip/npm/Go provider 明确分离。 -- [x] `dever.lock` doctor 现在校验传递依赖闭包、环依赖和缺失依赖;ArtifactStore 在 Worker 使用前可验证目标、摘要和尺寸。 -- [x] 真实三生态 registry resolver、checked manifest 三 SDK、Python/JS 自动 Worker、Linux 不同 UID 的共享 artifact IPC 已接线并定向验收;当前证据见下方和生产化收口任务。 -- [x] Go managed compile/link 和 Dever Package 安装/传递 Lib 已实现并有定向 fixture 证据;具体完整链路与当前计数见生产化收口任务。 -- [x] 高级生态安装/Go sumdb已在2026-10-02完成Linux实现及真实第三方包定向验收。 -- [ ] 正式公开签名语言packs与其他平台发行尚未交付。缺少时明确失败,不回退到PATH、环境变量或宿主包管理器。当前Linux增强签名程序复验见生产化任务,历史fixture不替代新证据。 - -## 2026-09-29 收口复验 - -- `cargo check --offline --locked --workspace`、`external_libs` 6/6、CLI Lib 单测 4/4、Port Adapter Lib 请求定向 1/1 通过。 -- 本阶段已完成仓库内可安全验证的协议、lock、fixture resolver、artifact 校验、embedded resource 和 run/build preparation;真实 pip/npm/Go registry、受管 CPython/Node/Go runtime、正式三语言 SDK、Package 发布元数据和无宿主运行仍为发行资产阻塞。 - -## Integration Gate - -2026-09-30 当前边界:Port/Adapter 16/16、协议 lifecycle 1/1、typed 三 SDK 宿主协议、Python/JS 默认 Worker 6/6、资源 9/9、Linux cache 14/14 与实际不同 UID 1/1 已通过。managed Node 已由 checked App CMD 编进独立 Native 程序;受管 Go Worker 已按锁编译并完成源码移除、清空环境的独立执行;Package 已实际完成安装→check/test/run/build→停止 daemon→独立运行。自有工具包不等于正式签名或无宿主发行;高级生态安装、daemon 编译和正式后端仍有未实现代码,不仅是“发行资产阻塞”。 - -三个子任务完成后,使用同一 Port 的 Dever/exec/Python/Node/Go 实现进行定向端到端验证,并证明目标环境没有系统 Python、Node、Go 时构建产物仍可运行。 - -## Rollback - -外部 Adapter 是新语法且没有旧兼容面。若某子任务未通过,不启用对应生态或打包入口;现有纯 Dever Port/Adapter、run/build 与配置合同保持可用。 diff --git a/.trellis/tasks/09-29-external-libs/prd.md b/.trellis/tasks/09-29-external-libs/prd.md deleted file mode 100644 index 08aae82..0000000 --- a/.trellis/tasks/09-29-external-libs/prd.md +++ /dev/null @@ -1,77 +0,0 @@ -# Dever 外部 Lib 生态 - -## Goal - -让 Dever Package 通过现有 Port/Adapter 边界安全复用 PyPI、npm、Go Modules 及后续其它语言生态。用户统一使用 `dever lib` 管理依赖,`dever run/build` 自动管理 Worker;业务源码不直接调用外语函数,也不接触语言工具链、环境变量或进程协议。 - -## Definitions - -- **Package**:Dever 组件的发行单位,包含 `.dever` 业务源码并接受完整静态检查。 -- **Lib**:PyPI、npm、Go Modules 等外部生态依赖。 -- **Adapter**:Port 与 Lib 之间唯一合法的桥接层。 -- **Worker**:运行外部 Adapter 的隔离进程,不是用户可调用的业务层。 - -## Requirements - -### Language Boundary - -- 外部 Adapter 继续属于 `module///adapter`,完整实现同领域一个 Port。 -- App 只调用 Port;Domain、Model、API、Job 不直接调用 Lib、Worker 或外部 SDK。 -- `port.dever` 仍是输入、输出、failure、effect 和 schema 的唯一来源;不得从 Python annotation、TypeScript 类型或 Go 接口反向定义业务合同。 -- 外部 Adapter 使用严格的 `external ` 声明,可包含 Lib 与 capability 声明;禁止任意 shell/build 命令。 -- 普通 Dever Adapter、测试 Port fake 与现有运行时选择合同保持不变。 - -### Protocol And Lifecycle - -- 所有语言共用一个版本化 Dever Component Protocol,而不是在编译器中增加 `python_call`、`go_call`、`js_call` 特例。 -- 协议支持 handshake、schema identity、typed setting、call、result/error、cancel、health 和 shutdown。 -- Worker 长驻并由结构化生命周期拥有;启动失败、崩溃、超时、取消和关闭均有界,不产生 detached 进程。 -- 业务错误只能返回 Port 声明的 error variant;协议破坏、进程崩溃和非法输出成为安全 runtime fault,不自动重试。 - -### Dependency Management - -- 用户命令为 `dever lib add/list/update/remove/doctor`;生态使用 `pip:`、`npm:`、`go:` 等明确前缀。 -- 解析结果写入编译器生成的项目根 `dever.lock`,记录精确版本、传递依赖、内容摘要、runtime、目标平台和 Port schema identity。 -- `dever.lock` 是可提交、不可手改的构建输入,不替代只负责部署配置和 Secret 的 `config/setting.json`。 -- 只有显式 `lib add/update` 可以联网;`check/test/run/build` 默认离线且不得从用户 PATH 或环境变量选择语言 runtime。 -- 首批正式生态是 `exec`、`pip`、`npm` 和 `go`;Maven、NuGet、Composer、Gem 通过同一扩展合同后续增加,不修改语言核心和协议。 - -### Security And Capabilities - -- 外部源码不受 Dever 内部静态检查,因此默认无网络、项目外文件、子进程、设备和 GPU 权限。 -- Adapter 必须显式声明所需 capability;声明参与 Port effect 的保守分析,并由 Worker sandbox 执行。 -- Worker 只接收当前 Adapter 的 typed setting,不读取完整 `setting.json`;Secret 不进入日志、协议诊断或缓存身份明文。 -- 安装脚本、路径、符号链接、归档解包和原生产物必须经过边界、摘要和所有权校验。 - -### Run, Build And Package - -- `dever run` 从机器级 Dever 缓存准备并监督选中的 Worker,不要求用户手动启动服务。 -- `dever build` 把所有可运行时选择的外部 Adapter、runtime 与锁定依赖封装进自包含应用;目标机器不需要 Python、Node、Go 或包管理器。 -- 嵌入资源以内容摘要验证后释放到应用 `data/cache/lib`,不覆盖项目源码、配置或用户文件。 -- Dever Package 可以携带外部 Adapter 声明;普通使用者只执行 `dever package add`,项目解析时把传递 Lib 统一锁定。 -- 不同 Adapter 的依赖环境隔离,允许同一外部包的不同版本共存;机器缓存按内容去重。 - -## Acceptance Criteria - -- [ ] 同一个 Port 可以分别由 Dever、`exec`、Python、JavaScript 和 Go Adapter 实现,App 调用代码不变。 -- [ ] 协议 schema、operation、输入、输出或 error 不匹配在用户业务代码执行前失败。 -- [ ] Worker 崩溃、取消、超时和主程序关闭不会遗留进程或把半条响应当成功结果。 -- [ ] `lib add/update` 产生确定性 lock;断网 `check/run/build` 使用相同 lock 和机器缓存成功,缺失依赖明确失败且不隐式联网。 -- [ ] Python、Node 和 Go 组件在目标机器没有对应系统 runtime/toolchain 时仍可由构建产物运行。 -- [ ] 未声明 capability 的网络、文件、进程和设备访问被拒绝;Secret 与其他项目路径不出现在诊断或状态输出。 -- [ ] 一个 Dever Package 可以封装外部 Lib,另一个项目只安装该 Package 即可构建和运行。 -- [ ] 新增第四种生态只实现 resolver/runtime pack/SDK,不修改 Port、Component Protocol 或 App 调用规则。 - -## Out Of Scope - -- FFI、动态库加载和同进程外语解释器。 -- 自动把任意第三方函数、类或对象模型暴露成 Dever API;普通生态库仍需要薄 Adapter bridge。 -- 云端编译、源码上传或运行时联网安装。 -- 外部 Adapter 热切换、请求级实现选择和无约束自动重试。 -- 修改现有 Dever Package/Component/Domain 的业务命名和调用规则。 - -## Child Deliverables - -1. `09-29-external-lib-protocol`:语言合同、统一协议、通用 `exec` Worker 和生命周期。 -2. `09-29-external-lib-ecosystems`:`dever lib`、`dever.lock`、共享缓存及 pip/npm/go resolver 和 SDK。 -3. `09-29-external-lib-packaging`:`run/build` 自包含打包与 Dever Package 传递依赖。 diff --git a/.trellis/tasks/09-29-external-libs/task.json b/.trellis/tasks/09-29-external-libs/task.json deleted file mode 100644 index 1f3d544..0000000 --- a/.trellis/tasks/09-29-external-libs/task.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "id": "external-libs", - "name": "external-libs", - "title": "Dever 外部 Lib 生态", - "description": "让 Dever Package 通过 Port/Adapter 安全复用 PyPI、npm、Go Modules 及其它语言生态,并由统一 Lib 命令、协议和构建链管理", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-29", - "completedAt": null, - "branch": null, - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [ - "09-29-external-lib-protocol", - "09-29-external-lib-ecosystems", - "09-29-external-lib-packaging" - ], - "parent": "09-20-production-application-language", - "relatedFiles": [], - "notes": "2026-10-02:协议/Worker、三生态高级解析构建、v5锁与收据、Package传递Lib、LLVM独立打包及Linux OS隔离已实施;原planning状态过时。官方simplejson/bufferutil/UUID构建及离线Worker通过。最终三生态签名安装、受管check/run/build及移除源码/机器目录后的无系统语言独立执行1/1通过755.81秒,Linux首装双项目双UID共享1/1通过231.51秒。正式公开和其他平台发行仍未完成。准确状态及日志统一见09-29-language-production-closure/implement.md。", - "meta": {} -} diff --git a/.trellis/tasks/09-29-language-production-closure/check.jsonl b/.trellis/tasks/09-29-language-production-closure/check.jsonl deleted file mode 100644 index 397986f..0000000 --- a/.trellis/tasks/09-29-language-production-closure/check.jsonl +++ /dev/null @@ -1,12 +0,0 @@ -{"file":".trellis/tasks/09-29-language-production-closure/prd.md","reason":"按总任务验收标准检查范围是否完整"} -{"file":".trellis/tasks/09-29-language-production-closure/design.md","reason":"检查 API、Lib、工具链边界是否重复或越界"} -{"file":"LANGUAGE.md","reason":"核对当前语言已交付和未交付边界"} -{"file":"IMPLEMENTATION.md","reason":"核对开发编译器与正式发行路径的实际差异"} -{"file":".trellis/tasks/09-20-production-api/prd.md","reason":"本批LLVM API/REST/auth/tenant最新业务安全合同与原实现等价"} -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"typed roots/reachability/failure/affine Upload不放宽"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"原事务/owned Session/数据库隔离和真实fixture"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"canonical ABI/布局/profile/清理"} -{"file":".trellis/spec/backend/logging-guidelines.md","reason":"单logger、配置owner和敏感信息边界"} -{"file":".trellis/tasks/09-19-application-testing/design.md","reason":"LLVM Test使用case-local checked/fake/数据库/虚拟时钟,保持单suite和原失败合同"} -{"file": ".trellis/tasks/09-29-external-lib-protocol/prd.md", "reason": "沿用 external Adapter 协议、capability、超时取消与业务错误边界"} -{"file": ".trellis/tasks/09-29-external-lib-packaging/prd.md", "reason": "沿用独立 Worker 资源校验和无宿主环境合同"} diff --git a/.trellis/tasks/09-29-language-production-closure/design.md b/.trellis/tasks/09-29-language-production-closure/design.md deleted file mode 100644 index ecf9c11..0000000 --- a/.trellis/tasks/09-29-language-production-closure/design.md +++ /dev/null @@ -1,39 +0,0 @@ -# Dever 语言生产化收口设计 - -## 2026-10-02 Linux 两项收口 - -当前缺口是完整质量门/持续负载证据,以及 AppArmor 限制下非 root 的 namespace 创建入口。CI 复用根 test 与 performance owners,通过显式设置记录工具路径、作者输入、阶段结果及源码摘要;ignored 内部探针由父测试调用,缺配置不算通过。实际持续测试覆盖双 CMS、HTTP/2 和连接回收的 64/128 MiB 预算,每个关键场景至少 30 分钟。总负载使用自有 cgroup 限制为 2 CPU/4 GiB,压力客户端与服务分别计量。格式门历史差异采用备份后的机械格式化,不混入语言规则变更。 - -AppArmor 审计确认当前私有 loader 才是首个 exec,bwrap 路径规则不会附着。将已签名 bwrap 资产改为静态 ELF 并直接 exec;受限主机只用固定 root-owned 内容地址 helper,精确匹配嵌入摘要并验证无符号链接、不可组/其他用户写、无 setuid/file capability。复用现有签名安装/事务 owner 安装 helper 与专用 ABI 4.0 profile,不新增任意执行代理或信任源。profile 按上游 bwrap 能力分离结构限制其子进程,必须验证 NNP、直接 aa-exec 与 namespace/capability 拒绝。宿主加载操作独立审批,不能关闭系统限制或用 root 通过替代非 root 验收。 - -修改归属:test/ci 与 test/performance 管验收;dever-sandbox 管入口/资产检查;CLI toolchain packaging/bootstrap 管可信资产和固定安装目标;SDK 作者输入及根 test 随合同同步。其他平台、公开发布、语言/API/CMS 业务重构不在当前范围。 - -## 总体边界 - -收口工作分为四个相互独立、最终统一验收的边界:应用运行边界、外部生态边界、工具链/发行边界和验收证据边界。已有编译器和运行时不做平行重写;每个缺口只在实际拥有该行为的层修复。 - -## 1. 应用运行边界 - -API 只负责请求适配、参数解码、上下文读取和响应编码;核心业务继续由现有 Model、领域规则、Port/Adapter 和 Job 承载。真实 PostgreSQL 验收使用项目配置文件提供连接信息,不新增环境变量兼容路径。权限和租户上下文从可信运行时来源进入请求链路,数据库模式租户选择在数据访问边界完成。 - -CMS Dever 与 Markdown 实现共享行为合同和验收矩阵,但不共享会掩盖实现差异的业务源码。每一套实现都必须经过同样的输入、状态和输出断言。 - -## 2. External Lib 边界 - -Dever Package 只声明和组合 Port/Adapter;Lib resolver 负责解析锁定、缓存和运行时准备;Worker 负责统一进程协议。解析、下载、准备和启动是显式阶段,`run/build` 只消费已经锁定并验证的结果。不同生态的差异封装在 resolver/runtime provider 中,不进入 Dever 语言层或业务 API。 - -所有 Worker 通过统一协议传递版本、capability、请求、响应、错误、取消和超时。构建时可嵌入运行时和依赖,运行时只启动锁定选择的 Worker,并验证内容完整性。 - -Go Worker 复用同一个由签名发行物和 `dever.lock` 精确摘要绑定的 `runtime.pack`。包内 `dever-runtime.json` 的 Go 专用 `build` 段固定 compiler、linker、源码分析器与目标标准库 importcfg;工具和标准库仅在构建阶段解包到私有临时目录,使用绝对路径和清空的子进程环境。编译按目标 build tags 选择源码,沿已锁定的 Go module 闭包解析导入,并以包内标准库和本次生成的依赖 archive 形成 importcfg。Go SDK 与生成的 `main` 同编译;生成入口把已检查的 operation 名静态绑定到同名导出的 Go 函数,Go 编译器校验统一签名,业务源码不手写注册表或 `main`。产物只嵌入编译好的 Worker 和 checked manifest,运行时继续复用既有 Worker 启动与协议校验。缺少构建资源、导入、目标或不支持的 cgo/汇编能力均明确失败;私有固定目标 pack maker 只用于自有 fixture,不代表正式签名发行或 Go sumdb 验收。 - -## 3. 工具链与发行边界 - -本地开发仍可使用 Rust 后端,但公开发行物必须将编译/运行所需的私有实现封装在受保护的工具链和 `deverd` 服务边界内。共享缓存不再由普通 CLI 直接读写;服务负责认证、路径解析、租约、发布和清理。平台实现通过适配层隔离 Linux/macOS/Windows 的权限、服务注册和安装差异。 - -## 4. 验收与回滚 - -- 每个阶段先运行最小定向检查,再运行该阶段的集成检查。 -- 真实数据库、跨平台构建和外部网络解析不可用时,不修改测试使其“通过”;记录阻塞原因和重新运行命令。 -- 新实现必须保留 fixture/fake 路径,普通单元测试不强制启动真实外部 Lib。 -- 发行边界先通过离线 fixture 和干净目录检查,再接入真实平台/注册表。 -- 若某阶段失败,回滚到该阶段前的任务边界,不回退已完成的编译器、缓存和协议基础。 diff --git a/.trellis/tasks/09-29-language-production-closure/implement.jsonl b/.trellis/tasks/09-29-language-production-closure/implement.jsonl deleted file mode 100644 index 349918e..0000000 --- a/.trellis/tasks/09-29-language-production-closure/implement.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"file":".trellis/tasks/09-29-language-production-closure/prd.md","reason":"总任务需求、范围和验收标准"} -{"file":".trellis/tasks/09-19-application-testing/prd.md","reason":"现有应用Test入口、case-local fake及普通测试隔离合同"} -{"file":".trellis/tasks/09-19-application-testing/design.md","reason":"复用test_program、每case执行/数据库与错误呈现,不新建测试解释器"} -{"file":".trellis/tasks/09-20-production-api/prd.md","reason":"现有API/REST/可信身份/自动权限/database-only租户最新合同;旧权限设计不得复活"} -{"file":".trellis/tasks/09-20-production-api/implement.md","reason":"原native实际语义、复用owner及已有验收证据"} -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"checked HIR、typed LLVM roots/failure/effect/Upload边界"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"独立runtime ABI profiles、私有ffi与资源所有权"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"共享SQL/driver、owned Session、事务及租户数据库隔离"} -{"file":".trellis/spec/backend/logging-guidelines.md","reason":"复用单一logger及隐私/清理合同"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"compiler/runtime归属和根test约束"} -{"file":".trellis/spec/backend/error-handling.md","reason":"来源级拒绝、标准API错误映射和原始故障保留"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"最小定向/原caller等价验收,不把object当完整发行"} -{"file": ".trellis/tasks/09-29-external-lib-protocol/prd.md", "reason": "沿用 external Adapter 协议、capability、超时取消与业务错误边界"} -{"file": ".trellis/tasks/09-29-external-lib-packaging/prd.md", "reason": "沿用独立 Worker 资源校验和无宿主环境合同"} diff --git a/.trellis/tasks/09-29-language-production-closure/implement.md b/.trellis/tasks/09-29-language-production-closure/implement.md deleted file mode 100644 index 58d61cb..0000000 --- a/.trellis/tasks/09-29-language-production-closure/implement.md +++ /dev/null @@ -1,890 +0,0 @@ -# Dever 语言生产化收口执行计划 - -## 2026-10-02 继续:Linux质量门与非root Worker - -最新范围只推进完整CI/长压测和受限AppArmor非root Worker,其他平台及公开发行暂缓。复用现有任务,不新建平行实现或重新设计语言。 - -2026-10-03用户因耗时明确允许不做剩余长测,要求尽快收口。已停止长测队列;此决定替代下文全部18个子场景必须跑完的本轮要求。保留CMS64/128和HTTP2-64正式通过证据,HTTP2-128记主动中止,recovery/live四阶段未执行;不标为通过。用户仍保留完整CI要求,默认/全功能矩阵已经通过,不再追加长测。随后用户明确回复“可以”,授权临时部署可信helper、加载AppArmor策略、启用严格转换限制并在验收后恢复;授权已经取得,不再重复询问。 - -1. [x] 核对workspace/feature/ignored检查清单,复用现有测试与性能owner建立可重复Linux质量门。 -2. [x] 实测定位AppArmor启动边界,完成不放宽隔离的修复和专用部署策略;已在授权的严格宿主策略下完成验收并恢复原状。 -3. [x] 串行完整检查并修复实际失败;磁盘/内存预算、源版本、未运行项与日志一并保留。 -4. [x] 按2026-10-03最新范围完成长测收口:CMS64/128、HTTP2-64通过,其余长测经用户允许停止/免跑,未冒充全矩阵通过。 -5. [x] 独立复核两项交付、清理自有测试资源,更新当前结果;不以旧定向结果替代新质量门。 - -实施边界:CI/长测逻辑归根test与已有performance runner;Worker启动归dever-sandbox,可信发行资产及可选部署接线归现有CLI toolchain owner。不改App/API/CMS业务语法;最初只读宿主的限制已由上述明确授权替代,仅允许本轮临时部署与严格策略验收,结束后恢复。 - -### 2026-10-03 最终结果:本轮 Linux CI 与受限 AppArmor 非 root Worker 已收口 - -- **最终源码与证据边界**:源码 `7310a568ebe3fbb3cc747e343ab2fd17ff1eada8da32d54e98bb143c3dca6cba`,固定完整输入 `e40b7f16cf6f7a84d256210024a3569143d5716f3cc6b34152162f4d4049e873`。本次接续只修改测试 owner:修复嵌套 libtest 汇总重复计数及标准库 TLS 缓存造成的分配账本误报,新增确定性回归。恢复 `target/ci-harness-before-37kQnY` 的四个原测试文件并排除两个新增回归文件,精确重现旧源码指纹 `90245dd9737bfed7ebe13240a05958e5eba9b088457ba1e90de093d8fa3fa379`;编译器、runtime、SDK 和产品输入均未改变。因此保留原矩阵证据,不重写其指纹、不重复长时间矩阵,也不声称所有阶段在同一新指纹下重跑。 -- **最终专项**:`target/linux-ci/native/1791040913590327459/result.json` **185/185**,`target/linux-ci/sandbox/1791040885539823828/result.json` **9/9**,`target/linux-ci/python/1791040504277745773/result.json` **92/92** 全部通过。inventory `1791040538867110700` 覆盖108目标/217项分类;原生原失败用例固定重复 `target/linux-ci-parallel-repro/1791040439295737989/result.json` **20/20**。真实泄漏和错误返回的负面回归均仍被拒绝;没有放宽断言或重试到通过。 -- **完整矩阵及其他检查**:上述产品字节一致的旧指纹下,default `1791029064673984868` **651/651**、all-features `1791031757319396825` **873/873** 通过;全局格式/默认与全功能全target Clippy、19 feature组合与依赖树、三语言SDK、真实PG **7/7**、有界性能 **3/3** 均保留原正式通过证据。阶段报告在 `target/linux-ci/` 对应目录;不把用户免跑的长测或不同指纹报告拼成严格 `run.py summary` 全阶段通过。 -- **严格宿主与真实非 root**:`target/linux-ci-apparmor/1791040870463419164/result.json` 验收通过且回滚完成。四种普通/立即 `aa-exec`、有/无 `--no-new-privs` 组合均实际运行探针并由内核拒绝 `uid_map`(errno1),未以启动失败代替隔离证据。`target/closure-sandbox-ecosystem-release-acceptance.json` 验证签名安装、三生态受管check/run/build、隔离独立程序和 **UID65534 的 pip/npm/go 全部通过**,包含源码原生依赖与离线构建收据重放。 -- **预算与清理**:最终队列日志 `target/linux-ci-final-ledger.log`,用时1小时3分28秒;父cgroup峰值3,565,158,400字节,另预留32MiB,总计小于4GiB,OOM/oom_kill均0。自有unit已停止,cgroup和PG已退出;临时helper目录 `/opt/dever`、策略文件及两个已加载profile均移除,无残余附着进程。sysctl恢复原值 `apparmor_restrict_unprivileged_unconfined=0`、`apparmor_restrict_unprivileged_userns=1`,后者始终未关闭。根临时 `config/setting.json` 校验SHA `4758568903fd1233d565cd381372353b598f994517fede3d117c6508c948e2bb` 后移至私有 `target/linux-ci-session-BrZ5t3/setting-final.json`(0600),恢复根配置原先不存在的状态;日志、固定输入与备份可恢复保留。 -- **长测与父任务**:CMS64/128及HTTP2-64正式长测通过,均0错误/0 OOM;HTTP2-128主动中止,recovery/live的64/128四阶段未运行,按用户最新要求免跑且不记通过。其他平台适配与正式公开发行继续延期,父任务保持 `in_progress`;本轮两项 Linux 交付无剩余阻塞,不提交、不归档。 - -### 以下为历史执行记录 - -记录中的“进行中”“未授权”“尚未通过”均描述当时状态,最终结论以上节为准;失败和中止证据原样保留。 - -- **分配账本误报定位与修复**:native `1791038231061444951` 的前137项通过,在 `native::synchronous_file_stream_parallel_failure_releases_workers_and_rows` 报+1;宿主报告 `target/linux-ci-apparmor/1791038179604022584/result.json` 确认恢复完成。固定20次复现 `target/linux-ci-parallel-repro/1791039680829850445` 为14通过/6失败。临时指针追踪六次均余留48字节;保存ELF `target/parallel-trace-kernel`,`addr2line -f -i -C ... 0xb0ff6` 明确为 `Arc::new -> Context::new:69`,不是业务owner丢失。根因类别E(隐含假设):一次warmup不保证触发满队列producer的TLS缓存,主线程未退出时缓存仍正常存活。共享managed-driver改为每次入口经独立pthread并join后计数,保持进程初始化、warmup1+重复64和严格delta=0;不改产品队列/ABI、不增加容忍值或概率预热。新增确定性C fixture覆盖warmup后TLS初始化、故意泄漏和错误返回;19项CI单元通过,原driver对合法late TLS稳定失败,修复后通过且两种真错误仍被拒绝。临时trace已移除,备份原driver SHA `3050becbd464c1640739dd1db5df7dcdbe1cb41095e28f7faf4053089a7ca46b`。只读并发专家复核通过;观测边界是入口及宿主线程退出,未声称证明长寿命宿主TLS无增长。当前 `7310a568...` 正进行固定20次复验以及Python/inventory/sandbox/native完整接续;原生门尚未宣布通过。 - -- **2026-10-03已授权宿主验收续跑**:首次部署报告 `target/linux-ci-apparmor/1791037194864425474/result.json`,四种aa-exec转换组合均实际执行探针并被内核拒绝;真实UID65534的 `enforces_unprivileged_namespace` 及子探针均成功退出。沙箱gate误将父/子两条libtest结果相加为2,导致精确单用例门禁失败;宿主已完整恢复(strict=0、userns=1、helper/策略移除、无残余附着进程)。本次只修改CI Python owner:直接单harness验收取最终父汇总,仍要求1通过/0失败/0忽略;保留普通Cargo多汇总计数。17项定向回归通过,包含子测试成功但父测试空跑/忽略/失败的拒绝。当前串行重跑Python、当前inventory、完整sandbox/native;不重跑已通过的Rust默认/全功能矩阵,不制备新作者输入、不追加长测。其旧证据保留原源码指纹,不伪装为这次Python改动后的新证据。 - -- **2026-10-03本轮最终状态**:当前源码 `90245dd9737bfed7ebe13240a05958e5eba9b088457ba1e90de093d8fa3fa379` / 验收输入 `e40b7f16cf6f7a84d256210024a3569143d5716f3cc6b34152162f4d4049e873` 的default `1791029064673984868` **651/651**、all-features `1791031757319396825` **873/873**正式通过,覆盖78/113目标。合计1小时56分17秒,峰值3,565,158,400字节(另预留32MiB),memory.max回收2489次、OOM/oom_kill均0。当前静态、19组合+依赖树、Python88、三SDK、PG7、性能3和3项长测均有同版正式通过证据。完整native185/sandbox9门仍缺受限AppArmor非root授权验收,不称整个CI全绿。 -- **清理/交付**:压测与CI unit已退出,owned cgroup和PG进程不存在,最后复核无自有验收进程;测试可执行文件按既有gate规则回收。原先不存在的根 `config/setting.json` 已确认仍为本轮SHA `4758568903fd1233d565cd381372353b598f994517fede3d117c6508c948e2bb`,移动到私有 `target/linux-ci-session-BrZ5t3/setting.json` 留作复现,恢复根目录无临时测试配置的状态。日志/固定输入/编译缓存保留;将来复验须显式恢复该配置后再运行。宿主AppArmor未改,profile/helper未安装。父任务保持in_progress,无commit/发布/归档。 -- 取消剩余长测后的当前版本 default `1791029064673984868` **651/651通过**,source `90245dd9...` / inputs `e40b7f16...` 起止稳定,覆盖78个目标;all-features `1791031757319396825` 已接续运行。此轮不重制author输入、不追加长测,也不将缺授权的native/sandbox完整正式门标为通过。 -- 已精确向本轮 `http2-128` gate PID1085911发送SIGINT,运行器保存 `KeyboardInterrupt`(命令3002.8秒),自有服务、cgroup、PG均已退出,无残留压测进程。整轮4小时13分钟,峰值3,052,568,576字节、OOM/max事件0;保留 `target/linux-ci-cms-recovery-final.log` 和原始中断报告。宿主strict仍0/userns限制1,helper/profile均未安装。 -- 只读独立审计确认旧651/873完整矩阵仍是历史通过证据,当前source `90245dd9...` / inputs `e40b7f16...` 不可冒用其正式标签。当前88项Python、静态/features/SDK/PG7/bounded3及3项正式长测已通过;`target/linux-ci-final-matrix-without-soaks.log` 现只安排default→all-features。native185/sandbox9完整正式门受非root宿主授权阻塞;旧184/8诊断保留其对应版本,不做无效重跑。 -- HTTP2-64 `1791022159074052799` **通过**:明文/TLS各1800秒、计划各9,000,000请求,成功8,996,761 / 8,996,074(4998.20 / 4997.82次/秒),均0错误、0 OOM、断连FD差0;请求P99 1.328 / 1.376ms,含客户端调度的P99 2.848 / 2.912ms,RSS峰值4.90 / 5.67MiB。3/8长测阶段已完成,HTTP2-128 `1791025811330571248` 进行中;不把固定5000目标负载当饱和吞吐。 -- CMS128 `1791018511743113541` **通过**:双源码各1800秒,Dever/MD为1,760,530 / 1,744,559次成功鉴权读、978.05 / 969.18次/秒,0错误/0 OOM;RSS峰值29.10 / 29.04MiB、后半段增量8 / 12KiB,FD合同通过。64/128MiB四个CMS场景合计7,020,593次成功请求。HTTP2-64 `1791022159074052799` 正在执行,CMS之后其余6阶段长测及最终矩阵未完成。 -- 正式长测首阶段 CMS64 `1791014862780230485` **通过**(source `90245dd9...` / inputs `e40b7f16...`):Dever/MD各1800秒,1,754,220 / 1,761,284次逐回复校验的鉴权读,974.56 / 978.46次/秒,均0错误、0 OOM,RSS峰值29.37 / 29.22MiB,后半段增量16 / 28KiB,非DB句柄恢复且数据库句柄在池上限内。吞吐来自2CPU总预算下8并发闭环,并非服务饱和上限。CMS128 `1791018511743113541` 继续;其余长测与最终矩阵仍待完成。 -- 最终CMS修订版源码 `90245dd9...` 已完成 inventory `1791013634029656866`、author `1791013959047970369`(6/6)、static `1791014156347447546`、features `1791014186612471905`、Python `1791014213163412921`、SDK `1791014240370055980`、PG `1791014295204024541`(7/7)及bounded-perf `1791014699485900727`(3/3)。作者完成后完整输入固定为 `e40b7f16cf6f7a84d256210024a3569143d5716f3cc6b34152162f4d4049e873`;5内核比0.707/1.004/0.538/1.014/1.069,原1.15门槛不变。`target/linux-ci-cms-recovery-final.log` 中正式CMS64 `1791014862780230485` 已启动,后接其余7个长测阶段、完整default/all-features及独立native/sandbox诊断;当前仅记进行中,owned PG已停止,非root宿主策略授权仍待回复。 -- CMS句柄检查修订后的完整短矩阵 `target/linux-ci-soak-smoke/1791013117430967380` **8/8通过**:64/128MiB各覆盖双源码CMS、HTTP/2明文/TLS、两种HTTP/2连接恢复及TCP/WS/SSE。源码 `90245dd9737bfed7ebe13240a05958e5eba9b088457ba1e90de093d8fa3fa379`、输入 `1649db21a5bd7fb2224f4120d191fad7c034edba9d28bc8072907035ba380b75` 起止一致,6分47秒、峰值126,705,664字节、OOM0;这是短诊断,正式30分钟各场景仍全部待重新执行。下一轮先完成author再冻结输入,串行重跑完整质量门与长矩阵。以下保留历史尝试及其对应版本,不能把其中的进行中描述当作当前状态。 -- 首个真实30分钟CMS64长测 `1791010360837130398` 在1801.7秒后因总FD差断言失败,后续阶段自动停止;运行中RSS约28.9→29.1MiB、OOM0,但失败不能记通过。75秒诊断 `target/linux-ci-cms-fd-diagnostics/1791012321412052347` 确认17→28 FD由SQLite双池各扩3连接(12个主/WAL句柄)与控制socket空闲关闭(-1)组成,压测8连接均关闭;原报告丢失case详细结果。 -- 只修测试owner:CMS关闭控制client后取完整FD目标快照,非DB目标Counter精确恢复;已知SQLite主/WAL各≤配置4、SHM≤1(与锁定bundled SQLite实现及实际句柄一致),CI复用同一校验,不忽略任意文件增长;发布/基线/读负载逐步写入case结果,失败也保存raw/预算/错误并进入总报告。50项runner及15项gate单测通过,覆盖同数socket替换/dup、超池上限及两类失败证据保留;真实75秒复验 `1791012808869143017` 通过,16→28仅为受限数据库池增长,非DB全部恢复、OOM0。当前测试源码已变,准备先完成短协议检查,再冻结新版本重跑正式长测;不把75秒当30分钟。 -- `be785533...` / `1649db21...` SDK `1791009652252648482`、真实PG `1791009708083087094` **7/7**、bounded-perf `1791010181020595614` **3/3正式通过**,材料起止一致。固定25进程×9样本的5内核比值依次0.710/0.998/0.546/1.014/1.053,保留原1.15阈值和全部分组日志,不把参考Rust后端的微基准当LLVM服务吞吐。长测已实际开始:CMS64阶段 `1791010360837130398`,Dever服务PID944306,当前只记running,完成后还需MD与其余7阶段。owned PG已停止。 -- 固定25组采样版本源码 `be785533e4ee767df5d3500570868533c40f2489a0e42c4ff3790fa80d226f8f` 已通过inventory `1791009039923269723`(217项ignored分类)、author `1791009367171058428`(6/6)、static `1791009565839581267`、features `1791009598346719330` 和Python `1791009624921947548`;完整输入为 `1649db21a5bd7fb2224f4120d191fad7c034edba9d28bc8072907035ba380b75`。`target/linux-ci-stable-sampling-closure.log` 串行安排SDK、PG、固定采样性能门、8个长测阶段、default/all-features及不依赖待授权宿主策略的native/sandbox诊断。先完成author再冻结长测输入,后续不重制材料使长测证据失效。长测尚未开始,非root宿主授权仍待回复。 -- 正式PG `1791007358946731625` **7/7通过**。随后bounded-perf `1791007764657474746` **2/3**:Map比值1.421超过1.15,其他4内核及allocation/任务粒度通过,后续长测未启动。固定同一对ELF的诊断保存在 `target/linux-ci-map-diagnostic`、`target/linux-ci-map-diagnostic.log` 和 `target/linux-ci-map-affinity.log`;实际机器码两侧都执行SipHash/Map覆盖写,handler已内联,没有每步Result调用或Map克隆。相同ELF在各CPU仍出现约1.6/2.2–2.3ms成簇耗时,具体宿主/种子根因未定;CPU0前5组比1.370、后5组1.072,合10组1.073,说明原5进程门有采样偏差风险。只将固定进程数5→25并永久保留每组9个原始样本,算法/优化参数/1.15阈值不变,不动态补样直到通过;临时Rust诊断测试已移除。无绑定25组诊断比1.069只是证据,不能替代新正式门;长压测、最终矩阵和待授权非root验收继续。 -- 最新源码仍为 `d39a1108...`。正式inventory `1791006147903077573`、author `1791006502867605785`(6/6)、static `1791006705602191313`(fmt及默认/全功能全target Clippy)、features `1791007065359258253`(19组合+依赖树)、Python和SDK `1791007302833243256` 已全部通过。author重建材料后完整输入更新为 `1acd35250dbdb0872e68744cf9c434ae160a3caf60a5328e65bfcc965009d566`;旧 `c6aebfab...` 的184/8/3诊断不冒充这批新材料的正式native/sandbox证据。`target/linux-ci-final-acceptance-soak.log` 已串行排入新版本PG/有界性能、8阶段约9小时持续测试,以及最后default/all-features;当前PG `1791007358946731625` 进行中。压力阶段不并行Cargo。 -- `d39a1108...` / `c6aebfab...` 独立验收全部完成:原生 `1791003377055500069` **184/184**、沙箱 `1791005949517983914` **8/8**、有界性能 `1791003223649311165` **3/3**,source/input起止一致。三轮在同一2CPU/3400MiB unit共45分52秒,峰值2,988,834,816字节,无max/OOM事件。覆盖此前SIGPIPE、Node大程序链接、Package全链、真实180秒deadline与PID清理、跨UID共享、四profile签名/exec移源、bootstrap228秒双项目双UID和root真实沙箱。**明确排除**待宿主授权的 `enforces_unprivileged_namespace` 及签名三生态非root独立执行;不把这三份诊断记录替代完整native/sandbox正式门。宿主strict仍0/userns限制1,profile/helper均未安装。 -- 新测试源码 `d39a1108526fc593ea192e17f80191ecad7aaec5b26b083195f81bedf24acd54` 的有界性能诊断 `1791003223649311165` **3/3通过**,source/input起止一致(input仍 `c6aebfab...`)。含任务粒度、分配/记录/列表/JSON/Map原生3进程和5内核对匹配runtime基线;不是正式bounded-perf门或LLVM长测。随后 `1791003377055500069` 执行184项不依赖待授权宿主规则的原生用例;三生态签名独立非root链明确未选,待AppArmor策略授权后单独完成,不将184项当185项全通过。 -- 分配基准夹具已迁移为 `main.dever` → `benchmark/allocation/app.dever` 的run入口,删除旧package/exposes和strict Main不允许的public标记,并将7处错误Choice消费改为显式result。保留14轮倍增/16,384字节、每进程text/list/json各6次和map1次、原计时边界及3进程断言。诊断 `1791002981413191937` **2/3通过**,allocation首轮仍被public标记拒绝(已修);热路径5内核原阈值1.15下实际比值0.710/0.998/0.537/1.012/1.062通过。这是Rust参考后端对匹配runtime基线,不能冒充LLVM HTTP/CMS长测。当前再次复验分配基准;测试源码已变化,之前正式门仍保留对应版本身份。 -- 根盘可用空间另行回升至约12GiB(超出本轮明确清理155MiB,不归功于本任务)。在owned 2CPU/4GiB unit内持Cargo锁,将确切RAM缓存逐文件SHA/类型/权限验证后恢复为普通 `target/native-runtime` 目录,删除本轮 `/dev/shm/dever-ci-reference-cache-7Qn1JD`,释放962,711,552字节内存盘;3971项校验及报告见 `target/linux-ci-reference-restoration.json`,无dangling链接,OOM为0。源码、固定输入及验证摘要未因此改变。 -- 当前 `93971614...` / `c6aebfab...` 的正式PostgreSQL `1791002131949151822` **7/7通过**:私有REST身份/权限/事务、Model组合/stream/schema升级、两类错误回滚、权限目录、CMS双物理租户和ORM池/取消/关闭/TLS拒绝。临时PG34889已停止。紧接的bounded-perf `1791002657426882136` 1/3通过后失败:allocation fixture的根app.dever仍沿用旧package exposes/目录规则,计时前C003拒绝;热路径基准尚未运行,不记性能通过。正在只迁移测试夹具,保留算法、样本规模和断言。该unit共9分15秒,峰值2,433,675,264字节加参考缓存预留996,265,984字节低于4GiB,max/OOM事件均0。 -- 最新完整矩阵正式完成:default `1790994992208925145` **651/651**(78目标)、all-features `1790997779069364253` **873/873**(113目标),源码均为 `93971614df839969267bce14e98a2400c3a68fee80ad78b9ec9fcbc061e7a507`、完整输入 `c6aebfabf6103f85758aa9d1c8145dbd7b019738df4cc541c68616a260ca0bc1`,起止摘要一致。两阶段共1小时57分19秒;OOM/oom_kill为0,memory.max回收2817次,进程峰值3,358,203,904字节加参考缓存预留936,763,392字节达到总4GiB限额。静态与最小feature等正式准备门沿用同版通过证据;当前版本真实PG、显式native/sandbox、长压测继续,尚非完整CI全部收口。 -- 矩阵完全退出后,独立artifact联合图与当前工具fingerprint依赖闭包核对11个旧编译缓存;主线程持Cargo锁重查最新artifact、单链接、固定输入排除及进程maps/fd后回收162,013,184字节。明细 `target/linux-ci-reviewed-libraries-cleanup.json`;仅可重建库/元数据,源码、当前工具、固定归档和报告保留。临时目录只读审计没有其他确定可回收的大型残留,归属不明的旧SQLite目录保留。 -- all-features正式尝试 `1790997779069364253` 中,runtime_entry_cleanup 4/4、完整durable_jobs 18/18均通过;后者277秒,覆盖先前栈膨胀相关的SQLite状态机、信号退出和api/worker/all模式。全矩阵仍执行中,不能以这两组结果代替整组通过。 -- 正式default `1790994992208925145` **651项全部通过**,source `93971614...`,输入摘要由正式门验证稳定;同一受限unit已接续all-features `1790997779069364253`。default末段出现memory.max回收事件(当前202次),OOM/oom_kill仍0;不称“未触顶”。全feature、显式native/PG/sandbox和真实长测仍未完成。 -- 冻结测试源码 `93971614df839969267bce14e98a2400c3a68fee80ad78b9ec9fcbc061e7a507` 后,正式inventory `1790993660614204359`、author `1790993991491934824`(6/6)、static `1790994189999992691`(fmt+两组全target Clippy)、features `1790994532647168020`(19组合+依赖树)、Python `1790994744317023527`(85项)、SDK `1790994771348473444`(三语言)全部通过。19分27秒,进程峰值3,077,398,528字节+参考缓存预留936,763,392字节低于4GiB,OOM/max事件均0。完整default/all-feature矩阵继续,不以准备门替代。 -- 准备门停止且确认无编译/测试活动后,复用元数据回收规则删除555个无配套rlib/a/so的单链接检查元数据,323,555,328字节;`target/linux-ci-fixture-metadata-cleanup.json`保留明细。仅可重建缓存,固定输入/源码/报告保留。全矩阵的native-artifacts使用unit私有768MiB tmpfs并计入总内存限额,退出自动释放;根盘已有缓存保留,测试在独立挂载中使用新缓存,不更改产品配置。 -- `1790993368772328336` 两项新fixture exact均通过:取消/断连/真实180秒期限回收,以及CMD/App缓存与接口基线拒绝。源码/输入摘要前后一致;开始最终fixture版本正式inventory/author/static/features/Python/SDK门。受限AppArmor宿主策略仍未获用户回复,不修改sysctl或安装profile/helper;尚不能记非root通过。 -- 补验 `1790992602334552404` 9/12通过,包括Package check/test/run/build/独立执行、真实跨UID共享编译、官方Python wheel/source、签名四profile及新增exec移源独立运行。三个失败分别是共用wait超时、Node参考backend链接Bus error和native_cache旧main入口。取消fixture已拒绝空/非法PID并区分mode/phase(保留10秒);cache fixture已迁移CMD/App并保留篡改基线拒绝check/run/build与不生成产物。Node用自有/tmp内存盘复测 `1790993196374065418` exact通过48.4秒;同轮测试源码有其他fixture编辑,因此整个诊断记录仍为failed,不能记正式门通过。两处新fixture独立复验进行中。 -- 剩余native诊断 `1790990565345235019` 的TLS exact及共享suite均通过;累计89项通过,未完成整组。两个接线失败已修:external_workers参考backend fixture遗漏sandbox资产,复用prepare_sandboxed_worker与真实pip用例;llvm_cli旧unsigned真实Lib正向场景迁至既有签名四profile/daemon验收,保留run/build/删整个源项目后独立data7,原私有路径改精确拒绝,新增第5条编译缓存断言。三生态signed在npm run因ENOSPC退出,未到非root;Package完整链在test阶段失败但旧断言丢失stdout/status,现补诊断。随后根盘仅12MiB,主代理SIGINT停止全部自有unit,当前managed_compile exact记中断,不把systemd的success终止摘要算CI通过。 -- 完全idle复核后清理精确中断目录 `/tmp/dever-core-test-699057-0`(内容匹配managed_compile source_project/签名sleeper)及121个无活动maps/fd、单链接、完整三文件native-artifacts条目,273,723,392字节缓存;`target/linux-ci-idle-cache-cleanup.json`保留明细。源码/固定原料/报告未删除,缓存可重编。根盘约109→643MiB。运行期间提出的旧PID缓存回收在PID退出检查时被取消,没有执行。下一轮先做Package/三处fixture迁移与此前未执行的native定向验收。 -- 正式native `1790989136780529193` 86项通过后在TLS HTTP2上传下载被SIGPIPE终止,18分12秒、无OOM;不是完整通过。根因为公共C测试驱动绕过产品process main却漏调用已有 `dever_rt_v1_process_init`。产品进程入口已有正确初始化,可调用root依法不改嵌入宿主信号策略。仅在 `test/native-runtime-abi/managed-driver.c` 首次执行前复用canonical header/初始化并检查返回值,indexed suite自动共用;独立复核通过。既有ABI驱动已有SIG_DFL→init→raise的确定性断言,保留TLS真实网络和allocation ledger复验。继续收集剩余native失败,再冻结测试源码重跑正式门;产品runtime/CLI/压力产物字节未变。 -- 正式 PostgreSQL `1790988576909213458` **7/7通过**,source `6515b6d8...` / input `6a7b4ee8...` 前后一致;涵盖原生Model组合、两类失败回滚、私有REST权限事务、站点角色目录、CMS双租户数据库和ORM连接池/取消/断开/TLS拒绝。耗时8分47秒,进程峰值1,407,135,744字节,无OOM/预算触顶;owned PG端口34889已停止,postmaster.pid不存在,server日志已保存。全矩阵、原生发行和长测继续,非root宿主策略授权仍待用户回复。 -- 2026-10-03 source `6515b6d8...` / input `6a7b4ee8...` 正式准备门通过:inventory `1790987099128193601`(108目标/217分类),author `1790987506507180413`(6/6),static `1790987706540255061`(fmt及两组全target Clippy),features `1790988062781869337`(19组合+依赖树),Python `1790988269722882336`(85项),SDK `1790988297034468817`(三语言)。20分54秒,无OOM;memory.events max=336是限额内回收,不能称未触顶。正式PG、全矩阵、native/sandbox和长测仍待运行。 -- 准备检查结束根盘仅196MiB;持Cargo锁确认无编译器后,回收568个无配套rlib/a/so的单链接检查元数据,323,489,792字节,排除固定inputs。明细 `target/linux-ci-check-metadata-cleanup.json`;可重建,未删除源文件/报告/固定资产。随后以独立loopback端口34889启动本轮owned PostgreSQL,日志 `target/linux-ci-runtime-postgres.log`,退出由托管器停止。 -- 2026-10-03 四runtime、CLI/guard/maker/init、3 peer和双CMS/协议产物全部重建成功;`target/linux-ci-author-runtime-closure/provenance.json` 绑定 source `6515b6d8...`。耗时29分10秒,进程峰值3,414,069,248字节+已预留参考缓存876,298,240字节,合计低于4GiB,无OOM。双CMS为8,325,896/8,328,136字节,sha分别1bdabcf5.../e528684e...。component-fixture固定副本同步刷新为f89f6af7...;临时setting指向新产物(自身SHA47585689...)。本轮临时runtime编译缓存已回收。 -- 重建后磁盘一度仅35MiB,独立审查确认只回收早期Rust backend完整缓存,不能仅凭源码mtime宣称全部失效。主代理持Cargo锁、排除活跃writer/maps/fd和固定inputs,逐项复核mtime/inode/单链接/完整三文件后原子移出并删除287条目,397,664,256字节;`target/linux-ci-native-cache-cleanup.json`保留明细。较新118条目、CLI LLVM cache和所有报告/固定原料保留,删除项可重编恢复。空闲现534MiB,准备启动新源码/新资产的正式门。 -- `1790981698051341418` 最终67目标/605项实际通过,source前后同为 `6515b6d8243fa1ac9fb925510ab2e0b191a644243c9075ec88b745737bdabeeb`,耗时50分34秒、进程峰值1,213,997,056字节、无OOM。包括入口清理4、完整Job18、借用/non-Send新回归及剩余all-feature目标。这是修复充分性诊断,不替代完整正式门;下一步重编四runtime/CLI/guard/maker/peer以及双CMS和协议程序,再冻结资产完成正式验收。 -- 入口/Job scope 修复后 `target/linux-ci-job-probe/1790981398350130546` 三 exact 全通过:SQLite状态机、signal三种退出场景、API/worker/all模式;无OOM,进程峰值933,769,216字节。独立只读复核未见新增类型限制或清理/错误语义回归。新增借用Rc跨await的根入口及cleanup回归;`target/linux-ci-diagnostics/1790981698051341418` 入口清理4/4已通过,继续完整Job及剩余all-feature目标,尚非正式全矩阵通过。 -- 最新 all-features `1790978249784275058` 在 durable_jobs 失败:此前271项通过,本组15通过/3失败,完整门未通过。两个真实问题是根 Future 在入口/task-local 包装间按值搬运导致栈膨胀:信号用例根 Future 294,544字节,入口 block_on poll 单帧3,535,480字节。入口改为首次 Box 后进入共享执行owner,SQLite状态机 exact 已通过(`1790980718162628429`);信号用例仍溢出,继续修正 Job scope 的同源包装,保持默认栈、身份惰性、清理与错误语义。模式用例旧API body迁移为声明+App+CMD,使用全局Model保持原非租户三模式检查。第二轮复验进行中,不记通过;临时尺寸输出已删除。运行时改动意味着四profile归档和验收程序必须重新生成,之前静态/feature/SDK通过不能算新源码最终证据。 -- 源码备份 `/tmp/dever-linux-quality-backup-hI3zdG/source.tar.gz`(SHA256 `096aa0755e79b88acd5d1acc19f008b7b81feb38460ba750eae86c97d5c6ce20`);全仓机械格式化完成。初始格式门1174处Diff位置/132文件。初查Clippy修复CLI旧测试多余clone、network peer手工clamp;完整正式门尚未通过。 -- 静态bwrap 0.11.0制作并验证无INTERP/动态依赖;只替换自有作者输入,未安装宿主helper/profile。root沙箱7项实际隔离、2项默认合同、helper不安全路径拒绝1项通过;日志 `target/linux-ci-sandbox-*.log`。非root旧fixture在root构造Launch后才降UID导致仍走私有路径,已修为先降UID清groups再构造Launch,待重编验收。 -- CLI native_release默认18/18通过(6项明确ignored),日志 `target/linux-ci-bootstrap-default.log`;这是增加安全宿主前置检查之前的定向结果,不代表新的签名安装/非root通过。 -- CI入口与持续CMS/FD/RSS门已落地并完成独立复核;gate13、CMS12、runner48项Python定向通过。补齐最新尝试、完整ignored owner和实际长测预算核验。实际完整Cargo矩阵、作者输入、真实PG/SDK和约9小时长测矩阵待完成。 -- 安全独立复核发现 `aa-exec` 可直接进入新父profile;已在产品启动和实际宿主安装增加严格profile切换前置检查,并通过代码复审与定向回归。已发起异步授权询问,待用户批准临时strict=1、安装指定摘要helper和加载专用规则后真实测试;验收后先卸载新规则再恢复strict原值。当前没有获得该操作授权,也未更改任何宿主策略。 -- 完整all-target/all-feature Clippy `-D warnings`通过(`target/linux-ci-all-features-clippy-fixed.log`)。修复旧测试遗漏External声明分支和lint,更新live peer装箱后的关闭调用。默认全workspace矩阵开始预检;最终阶段仍须绑定准备后的输入摘要重跑。磁盘不足已清除三个过时编译快照(bootstrap-cli-snapshot-s5i92v、final-cli-snapshot-jiqbfz、final-native-fixture-snapshot-xw7bGT),约回收300MiB;源码备份、日志、当前工具和固定原料保留,删去的编译快照可重建。 -- 默认预检 `target/linux-ci/default/1790958354110646233` 在 Port target 失败(15通过、1失败),不是完整通过。此前双 CMS 6/6、native_entry 16/16、REST 12/12及CLI常规目标已通过;进程峰值约2.8GiB、无OOM。失败原因为旧测试直接编译无资源的external入口,未启用受验证bundle运行时。保留Port生成/清理检查,真实typed调用与每次shutdown验证合入既有external_resources打包用例,不增加邻接Worker回退。修正后的Port exact 1/1通过(`target/linux-ci-port-fix.log`);实际打包用例待复验。 -- 当前源码四profile归档、CLI/guard/静态init/压力客户端重建中,作者过程与源码摘要写 `target/linux-ci-author-build/`;临时内存盘仅缓存编译产物。自有PG16集群 `/tmp/dever-linux-ci-pg-AqF2Cz/cluster` 初始化通过,尚未启动;根临时setting声明loopback端口34889与专用库模板,结束后恢复原先不存在状态。 -- 为保留本次编译空间,进一步移除过时closure-current-compiler的runtime/cache/可执行文件、closure-verified-tools-ksA2Hn快照、未引用native-runtime/runtime-sandbox.a,以及回收站内六个旧ledger/LLVM诊断可执行文件。仅删除可重建编译产物,保留源码备份、固定原料、历史报告和摘要;回收站内这六项为永久删除,需重编恢复。 -- 修正CI配置接线:运行时严格拒绝未知顶层键,因此验收工具改用既有 `performance.linux_ci`,只把 `performance.network_peer/live_peer` 解析为peer路径,未放宽产品配置。gate Python14/14、Rust application_config6/6通过。此前失败清理疑点经metadata入口和文件时间核对属重跑生成文件,现有清理正常,没有额外修改。 -- 四优化runtime归档、当前CLI/guard/静态init及3个压力客户端最终构建确认通过,源码SHA `8c699b703e5ef689c076678f2d5ea9ed0cca5c986a5aa8ac245fb567d70e9716`,完整归档/编译器/peer摘要在 `target/linux-ci-author-final/provenance.json`。首轮因CI源码中途修正而拒绝最终通过,旧日志保留。`target/performance/cms-linux-ci-10-02`双CMS检查/构建成功,`protocols-linux-ci-10-02`协议产物构建成功;尚无本轮长测结果。 -- `target/linux-ci-preflight-closure/result.json` 定向通过:配置6/6、external_resources常规8/8及真实打包exact1/1(107.37秒),覆盖清空环境、两次typed返回7、每次新的shutdown确认和资源篡改拒绝。不是完整CI通过,也不是受限非root验收。构建后删除自有1.3GiB内存盘临时编译缓存;磁盘紧张继续删除未使用的 `target/go-cache` 与 `target/go-managed/cache` 旧可重建Go缓存,原runtime.pack/依赖/报告保留。 -- 正式inventory首轮因backend完整静态归档写满磁盘失败,日志 `target/linux-ci/inventory/1790962709158372077`。将整个可重建参考编译缓存逐文件核对后迁到 `/dev/shm/dever-ci-reference-cache-7Qn1JD/native-runtime`,原 `target/native-runtime` 暂时为指向它的链接,不修改编译器。每阶段从总4GiB额度扣除已有缓存页并保留32MiB开销,进程额度最高3400MiB。结束时须回收该链接/临时缓存。重跑inventory `1790963141083952733` 通过:108个实际target、217个ignored逐一分类,无缺项;期间无OOM。 -- 正式author首轮5/6通过,npm第6项因临时构建目录写满磁盘失败(`target/linux-ci/author/1790963610753874259`)。重跑只给本轮systemd临时unit配置私有 `/tmp` tmpfs(2GiB上限、仍计入总内存额度),只读映入托管脚本与PG原料;主机 `/tmp` 未变。`1790963918501049513` 6/6通过,含真实Go/Python依赖验证、工具pack制作、隔离PEP517及npm原生addon构建,输入/输出摘要一致,进程内存峰值1,963,769,856字节、无OOM。作者结果不是非root AppArmor验收;宿主策略仍未获得授权且未改动。 -- 正式static通过(`1790964267132478061`):全仓fmt及default/all-feature全target Clippy零警告。features通过(`1790964373302707758`):19个最小组合加CLI依赖树;Python85项(gate14/performance69/ecosystem2)通过;SDK `1790964628129189173` 三语言真实协议全部通过。新default矩阵 `1790964733321613886` 正在执行,随后all-features;这两个完整矩阵及真实PG/native/sandbox/长测仍未记为通过。 -- 上述default正式尝试最终在 `035.log` 的async_composition失败(6通过、1失败):旧fixture把零输出sleep赋给变量,当前checker正确报C005;此前Port16/16、REST12/12及CMS6/6已通过。进程峰值1,719,320,576字节、无OOM。仅将两处无用赋值改为action后,实际原生exact1/1通过(22.60秒,`target/linux-ci-async-composition-fix.log`)。 -- 同源测试漂移扫描修正async_stream/http_library/live_library/pooled_library/performance/differential/structured_concurrency七文件:按当前成功值与显式result捕获合同迁移调用,Read/Receive使用Done(state),保留独立行为及拒绝断言。七文件rustfmt通过;`target/linux-ci-diagnostics/1790966028853786940` 串行执行剩余all-feature目标并收集失败,仅为诊断。测试源码已改变,之前正式门不能视为当前版本全部通过;产品和固定runtime/peer字节未改。 -- 上述62目标诊断完成:20组失败、无OOM,进程峰值1,138,159,616字节。修复一处真实checker崩溃:结构类型深度超限时contract阶段未生成summaries,auth仍继续索引;改为返回致命C015,主检查和Port case均停止依赖阶段,普通合同诊断仍聚合。独立只读复核通过,256层原回归未修改,实际复验待完成。 -- 其余失败fixture迁移到当前App/Model目录、公开类型、显式result及main命名;差分仍精确比较原生/参考输出和完整错误JSON,ORM保留查询/迁移/回滚断言,HTTP非法response按现行请求边界500并验证后续请求健康,H2/时间codec补正式请求scope/metadata提交。sqlite_orm有一次磁盘不足,不修改产品规避。当前 `target/linux-ci-diagnostics/1790968164204229608` 复跑20失败组及Port,使用独立2GiB临时/tmp,仍受总4GiB预算约束;尚不记为正式CI通过。 -- 该定向复验已确认Port16/16、contract_semantics14/14(含原256层崩溃用例)、contract_execution11/11、原生SQL7/7通过;当前唯一再次失败组secure_contracts是fixture缺部署site绑定,已恢复原source-only合同检查并独立验证platform数据库,保留global及原匿名/事务断言,待再次执行。复验期间移除5份本次core修复前的过时rlib/rmeta(约238MiB);均为可重建缓存,保留报告/原料。 -- `1790968164204229608` 最终19/21组通过、无OOM(进程峰值973,602,816字节);含SQLite5/5、迁移10/10、差分13/13、HTTP/H2/live/入口/time codec。`1790969758624751556` 安全合同14/14通过,并发12/13失败。进一步保留精确liveness断言定位真实遗漏:CaptureResult未参与挂起点判定,且同源inline-blocking分支也只匹配Call。`1790970195428604455` 修改前11/13,实际证明捕获async sleep漏liveness、捕获sync sleep可绕过worker边界。现两处共用Call|CaptureResult原判定,加入同步capture正向及诊断span;独立只读复核确认根因,实际修复后复验正在进行。未重建验收程序或重跑正式质量门,前述正式结果仍为旧版证据。 -- CaptureResult修复后 `1790970325577979930` structured_concurrency 13/13实际通过,source前后一致、无OOM(峰值704,716,800字节);完整保留三个挂起点的精确liveness span、同步capture正向及捕获同步sleep的worker边界负向。继续评估直接受影响的既有fixture后冻结源码重跑正式门。 -- CaptureResult调用方独立有界审查未发现需迁移的正向用例;async_native及LLVM async/stream checker由后续正式门覆盖。当前 `/tmp/dever-linux-ci-refresh.py` 托管重建CLI/maker与双CMS/协议产物;四runtime归档和三个压力客户端源码未改,逐字节摘要核对后复用原 `linux-ci-author-final/provenance.json` 来源,新的provenance会明确记录复用,不冒充归档重编。 -- 新编译器/打包工具及双CMS/协议产物刷新4/4通过、无OOM(峰值1,046,528,000字节)。冻结源码 `900043ab2c819372ac22b1c8c44bf905d23a115c2f7a936eab0e38dbb04c86d0`,CLI SHA `c22b9fc622322d0b2456cd929533b9f0414c2a9ce48cb1a547fdf6582c078b61`;`target/linux-ci-author-current/provenance.json` 明确保留runtime/peer原构建来源。新 `cms-linux-ci-closure` 两源码分别47.71/47.90秒构建,8,324,776/8,327,016字节,SHA与原CMS一致。临时setting已指向新产物,准备后input SHA `cbdb39c8284c4a3685567c7417fb54eb0dadfe3ff92d7603f3d00b05347b9fc3`。`target/linux-ci-frozen-matrix.log` 串行启动inventory/author/static/features/python/sdk/default/all-features;仍未记为全部通过。宿主strict仍0/userns限制1,未安装profile/helper。 - -- 冻结版inventory `1790970867807152470` 在backend静态归档生成阶段因ENOSPC失败,尚未执行完整测试;峰值785,174,528字节、无OOM。停机后清理4个遗留测试可执行文件、3个旧CLI可执行文件及失败静态归档,约406MiB,均为可重建产物;当前CLI/输入原料/报告未删除。 - -- 冻结版inventory重跑 `1790971446868474214` 通过(108目标、217分类用例);author `1790971823437290546` 6/6通过,准备后完整input为 `d8657e37f743d4758bbcc6fc5c045dac032df62eedeea58556f824798b0eae87`;static `1790972018127138063` 格式/default与all-feature Clippy均通过,随后继续features/Python/SDK及完整矩阵。 -- 在同一受限control cgroup内逐字节核对旧performance ELF,将58个完全一致的单链接程序合并为硬链接,释放311,181,312字节;历史路径/字节/报告全部保留,当前两个closure输入目录未改。明细 `target/linux-ci-cache-dedup.json`。未删除其他项目或旧数据库。 - -- 冻结版features `1790972235115826233` 20命令通过(19最小组合及CLI树),Python `1790972375205452463` 85/85、SDK `1790972401999175653` 三生态协议通过。default `1790972457820456527` 在CMS5/6后因测试工具hard_link遇私有/tmp跨文件系统失败;CMS真实check/test/run/build/package链已通过,非产品错误。后续default/all-feature改用原盘临时目录,不改源码规避。另复核当前artifact后回收6个过期runtime/embedded bridge文件约141MiB;原候选中的fe5c5dcd75301ecf已被default重新使用,明确保留。 - -- 缓存清理纠正:上述bridge `9735e2773af0aacd` 虽旧时间戳,default仍复用,不应算过期;其约51MiB被误回收后由Cargo自动重建,源码和固定输入未受影响。其余4项约90MiB才是本次实际旧缓存回收,不将暂时消失的有效缓存计为净节省。 - -- 同盘/tmp的完整矩阵 `target/linux-ci-full-tests.log` 已启动;当前default目录 `1790972808956136476`,已通过CMS6/6、原生入口16/16、REST12/12、Port/异步/连接池/合同语义,仍在运行,尚不记为全门通过。 -- 根据实际inventory/default artifact联合图、当前作者工具fingerprint依赖闭包及固定inputs排除,独立核对377个单链接rmeta。主代理持有 `target/debug/.cargo-lock`、确认无writer,再复核最新artifact与dev/inode/size/mtime/blocks后回收361,652,224字节;明细 `target/linux-ci-rmeta-cleanup.json`。都是可重建元数据(含旧rlib配套metadata),不把它们一概称为check-only;未删除任何当前登记库、固定输入或源码。 - -- default `1790972808956136476` 全78目标/650测试实际通过,但阶段结束因固定input漂移拒绝通过;source仍为900043...、无OOM(进程峰值1,167,564,800字节)。精确重算确认唯一变化是 `target/debug/component-fixture`:其Cargo功能组合重链接由66743d...变为089a2d...;只替换该摘要即重现原input d8657e...。未放宽质量门、未将失效证据标pass。 -- 修正验收输入边界:两处显式LLVM Worker fixture改读 `target/native-release-inputs/component-fixture`,普通Worker测试仍读Cargo各自构建的bin;README/spec说明先准备并记录独立副本。临时setting同步固定路径;产品代码/编译器/runtime/已建CMS与协议程序未改。`target/linux-ci-immutable-fixture-matrix.log` 托管重新准备fixture、inventory/author/static/features/Python/SDK,随后须用同盘/tmp重跑default/all-feature。原650结果保留为诊断,未冒充新正式证据。 -- 新冻结源码 `fbe4a92970850e29b3561cc22af437bc1dbe2819d173af5ad32a4848145d4461` 的固定fixture准备通过,程序SHA `58a5a120104baabac29cc712358174b0a1573ca726744fab14168edf5e9bb802`,独立副本/provenance写在 `target/native-release-inputs`。inventory `1790975682052927294`(108目标/217分类)、author `1790976010020603166`(6用例)、static `1790976202296015153`、features `1790976561899757466`(20命令)、Python `1790976771445471337`(85项)、SDK `1790976798389126261` 均通过;准备后input为 `7d5ef87ea08c9ed8803b8c32733578d87b5b2fcc054c9f527fe27aa106077ce3`。受限进程峰值1,638,834,176字节、无OOM。`target/linux-ci-immutable-full-tests.log` 已按all-features→default启动,同盘/tmp;完整矩阵、PG/native/长测仍未记为通过。 -- 发行测试空间预审确认 optimized 安装时根盘同时保留两份约603MiB payload,当前余量不足。为避免必然ENOSPC,主动SIGINT结束all-features `1790976909411656631`,报告如实为KeyboardInterrupt,未记完成。复用已有 `machine_temporary_root` 配置,将 optimized machine、signed_core release/isolated、bootstrap downloaded 四处统一接入既有临时目录owner;author仍留同盘支持原料hardlink。独立审查确认所有hardlink同文件系统、安装仍真实copy、回收边界不变;两文件rustfmt通过,未改产品或验收断言。新源码 `3ca3f74e4696973e5dbde34efa188dda6ad103861c98a8576def3d6d31223254` 正在 `target/linux-ci-release-storage-matrix.log` 重跑inventory/author/static/features/Python/SDK,前版证据不算新门通过。 -- 3ca3版准备门全部通过:inventory `1790977493517800171`、author `1790977818442118586`、static `1790978011370964455`、features `1790978044513313008`、Python `1790978070742789549`、SDK `1790978097831556704`;准备后input为 `02c363bd03e50772acfefe2b59d2493a82665faa74616ef2d502b7d0bd4700da`,无OOM。再次基于新artifact/作者闭包清单、持锁复核368个旧rmeta并回收334,819,328字节(`target/linux-ci-rmeta-storage-cleanup.log`),根盘余量约702MiB。正式all-features→default运行日志为 `target/linux-ci-release-storage-full-tests.log`;此次复用未变的fixture/runtime/CMS及其原provenance,不将测试目录接线改动冒充产品重编。 - -## 2026-09-30 用户批准的最终交付顺序 - -范围固定为以下六个闭环,不再重新设计已稳定的语法、API、目录角色或 CMS 业务。单个模块或 fixture 通过不等于整个闭环完成;代码、正式资产、真实平台验收分别记录。 - -1. [x] Dever Package:版本/传递依赖、共享摘要缓存、安全安装/更新/移除/doctor、源码加载和传递 Lib 统一锁已完成。2026-10-02 已通过签名安装 → LLVM daemon 编译 → check/test/run/build → 停止 daemon 后独立执行的自有完整 fixture,没有私有缓存旁路。公开 registry 仍未发布,归入第 5 项正式发行。 -2. [ ] 正式 runtime/build packs 与 OS sandbox:可重复制作/签名/版本绑定,完整标准库与构建资源,以及真实拒绝未授权文件/网络/子进程操作的验收;不把 capability 回显当沙箱。 -3. [x] 完整 Lib(当前 Linux x86_64 实现):Go 自动 Worker 编译/链接与 sumdb、Python extras/sdist/PEP517 原生构建、npm 高级依赖与受控 hooks;官方 UUID、simplejson C 扩展及 bufferutil 原生 addon 已通过实际隔离构建、锁定重放与离线 Worker 运行。正式多平台包仍归第 2/5 项。 -4. [ ] 正式原生后端:完整 HIR 语义到 LLVM/LLD、稳定运行时 ABI、六目标资源,干净机器离线 check/run/build;不以隐藏 rustc 或子进程重命名替代。 -5. [ ] 共享编译与发行:deverd 编译 IPC、跨用户产物、签名目录/下载、平台权限与服务、升级回滚卸载,六宿主到六目标的真实验收。 -6. [ ] 最终质量:完整测试/CI、双源码与 PG/HTTP2/Job/上传组合、持续并发/故障恢复、体积/冷启动/延迟/RSS/64/128 MiB 容量报告。 - -验证继续从必要的最小定向检查开始。全量、服务级和正式发布步骤先说明并遵守用户授权;未经授权不提交、发布、安装全局服务或使用真实签名身份。每阶段完成后复核本节及原始验收合同,未完成项不得归档。 - -已接通 Package 配置/解析/锁/cache/source/exec、受管 Go 构建与 LLVM/LLD 连接桥。后续实现了同步强类型函数、受管值/集合、业务失败/Result、Bytes/File/同步 Stream 与真实协程的 Task/Group/Channel/sleep/blocking/parallel、AsyncStream/TCP/timeout/race/ParallelEach HIR→LLVM 和 runtime ABI;2026-10-01 又完成 CMD/wire/Dever Adapter 应用根,以及非租户 Model/双数据库 SQL/事务/DbError/Related/RowStream/schema/Seed 切片,证据分别见对应复验节。2026-09-30 用户批准的 unsafe 例外仍只在独立 `dever-backend-bridge` 的私有 `ffi.rs`,workspace 继续 forbid;runtime 本体、core、CLI 和 tests 不扩大例外,不开放 Dever 语言 FFI。私有默认 CLI 与 Linux 可信 daemon 已接 LLVM/LLD,不再调用 rustc;正式目标 runtime packs 和发行验收仍未完成。Go 保留环境变量禁令,采用固定目标受管工具路线,不引入 GOOS/GOARCH/GOCACHE/GOPATH 运行配置。 - -当前已完成 Linux 可信 daemon 编译、跨用户编译缓存及取消/断连/真实期限回收,真实三生态高级依赖和 Linux root 下的 OS sandbox 已通过定向验收。四个优化 runtime archive 已刷新;双 CMS/真实 PG/Job/API 与 LLVM 性能、64/128 MiB、HTTP/2 恢复矩阵均有独立报告。Linux签名首装、双项目/真实双UID共享使用、升级/篡改拒绝和移源执行通过。三生态最终签名安装、受管check/run/build、移除源码及机器目录后的无系统语言独立执行亦已通过,含Python/Node源码构建原生依赖及离线收据重放。2026-10-03已补齐受限AppArmor真实非root入口、三生态非root独立执行与本轮Linux质量门,证据及版本边界见顶部最终结果。仍缺其他平台产品实现和资产及正式公开发行,按用户要求暂缓;剩余长测免跑,尚未公开发布或安装全局服务。 - -以下保留原始任务的历史阶段编号;当前交付顺序以上述六个闭环为准。 - -## 阶段 0:任务基线与旧记录收口 - -- [x] 核对既有子任务实现与最新源码,标出“已实现但任务未归档”和“文档中已过时的未完成项”。 -- [x] 为每个子任务补充真实验证命令和阻塞项,不把历史记录当作当前缺口。 -- [x] 保持源码配置只走 `config/setting.json`,清理旧环境变量说明。 - -## 阶段 1:Production API 与真实 PostgreSQL - -- [x] 补真实 PostgreSQL fixture/配置入口,默认无配置不连接数据库。 -- [x] 完成 PostgreSQL 授权 Store 的权限目录、角色、跨站点、多角色和撤销验收,以及 CMS Owner HTTP/两个物理租户数据库验收。 -- [x] 完成同一真实 PostgreSQL HTTP 链路的非 Owner 多角色、跨站同名角色及撤销立即失效验收;使用仅注入临时 CMS 副本的成员 fixture,生产 CMS/Owner 保留角色规则未改。 -- [x] 完成请求、响应、Cookie/Header/Context、上传、取消、事务、HTTP/2 的已有定向回归;不代表所有 PostgreSQL/双源码组合已运行。 -- [x] 更新 `09-20-production-api` 和父任务;共享 ORM fixture 已迁移并通过真实 PostgreSQL,未完成的任务不归档。 - -## 阶段 2:大型 CMS - -- [x] 按当前组件目录约束实现账户/会话/权限、内容/版本/状态、媒体、发布、审计和清理 Job。 -- [x] 完成 Dever 与 Markdown 双源码行为合同和等价测试。 -- [x] 完成 `check/test/run/build` 与 `api/worker/all` 验收;CMS isolated `check/test/run/build/package/run` 双源码长链路已通过。 -- [x] 删除旧 demo-only 路径,更新 CMS 文档和示例;新增 `system.health.ping` 作为无数据库运行烟囱,不恢复旧 `news.article.demo` 兼容入口。 - -## 阶段 3:External Lib 生态 - -- [x] 完成离线 lock/resolver/cache/artifact 边界、Adapter 精确 Lib 请求接线,以及真实 PyPI wheel/npm registry/Go proxy 解析器;显式联网入口依赖已验证的安装版本及签名 runtime 描述,不访问宿主语言工具。 -- [x] 完成 Python、JavaScript、Go SDK 协议库和显式宿主验收。 -- [x] 支持 external pip/npm/go,三 SDK 共用 checked wire manifest;Python/JS 自动同名 entry 绑定、离线运行树和受控启动已有实现及定向 fixture 验收。 -- [x] 完成锁定 host-target build pack 的 Go compile/link、build tags、module ZIP、go:embed 和静态操作绑定,并验收源码移除后的独立 Worker。 -- [x] 完成 Dever Package 版本/传递依赖、源码加载、共用缓存与 Lib 锁、离线移除、失败回滚,以及真实安装到独立应用运行的自有 fixture 链路。 -- [x] 完成 Python extras/wheel/sdist/PEP517 原生构建、npm 高级安装/受控生命周期/native 输出和 Go sumdb;默认合同及真实第三方包定向验收通过,见 10-02 记录。 -- [ ] 交付正式签名语言 runtime/build packs,并在无宿主语言环境验收;复制宿主工具的自有 fixture 不代替发行验收。 -- [x] 完成 fixture run/build preparation、Worker 资源完整性、取消/超时/中断和并发协议回归。 -- [x] 完成 Linux x86_64 三生态程序的无宿主语言环境独立执行,包含Python/Node源码构建原生依赖和离线收据重放;Go官方UUID另有隔离构建/移源Worker证据。正式公开与跨平台交付仍属于上述未完成项。 - -## 阶段 4:共享工具链与发行版 - -- [x] 完成 Linux 开发态 `deverd` 认证 IPC、租约、并发发布、完整性校验和缓存状态/清理命令;跨平台 peer credential 与系统服务注册仍阻塞于发行层。 -- [ ] 完成 Linux/macOS/Windows 权限、服务注册、安装、升级、卸载和安全检查(跨平台发行层阻塞)。 -- [ ] 实现公开 HIR→LLVM/LLD 后端与六 target runtime ABI packs,再验证干净机器无 cargo/rustc;Rust bootstrap 不代替此项。 -- [x] 实现隔离的 LLVM 18/LLD 连接桥,验收六目标 object/link、输入拒绝、失败恢复、并发独占和私有输出目录;不是完整 HIR 后端或发行 SDK。 -- [x] 实现同步强类型函数 HIR→LLVM 内核及源位置/调用链,验证真实对象、本机执行、静态 handler、复合值和数值边界;不代表资源/异步/应用语义完成。 -- [x] 实现独立 runtime-abi staticlib 的数值/Text/Bytes 缓冲边界,并通过 canonical C header 和 LLVM object 的实际调用验收;复合资源/异步 ABI 和正式 target packs 未完成。 -- [x] 实现 Linux 内核 peer credential、跨用户 Lib artifact IPC、配额与有界 admission;真实不同 UID 的自有 fixture 已通过。 -- [x] 实现 Linux 可信 daemon build IPC、签名核心/pack 校验、跨用户编译缓存与取消/超时回收,恢复机器管理的 Package 完整执行合同。 -- [ ] 实现 macOS/Windows peer adapters、系统服务与正式发行;Linux 自有 fixture 不代替全平台验收。 - -## 阶段 5:最终质量门 - -- [x] 完成本轮 Linux 全量 workspace 矩阵和阶段定向测试;版本边界见顶部最终结果,其他平台延期。 -- [x] 完成本轮真实 PostgreSQL、CMS 服务级、External Lib 真实运行时和 Linux 签名发行验收;公开发行另行延期。 -- [x] 完成 LLVM 四 profile/双 CMS 体积、启动、并发、RSS、64/128 MiB 与共享编译缓存报告;HTTP/2 含一分钟稳态及 100 轮恢复,不把短测或私有 debug 编译耗时当生产饱和上限。 -- [x] 在私有临时目录准备同版本 rustfmt/clippy;core/runtime 与 CLI libs/bins 的 Clippy `-D warnings` 通过,不安装或替换全局命令。 -- [x] 完成源码全局格式及本轮 Linux CI 质量门;剩余长测按用户要求免跑,不计通过。 -- [ ] 更新规范、归档完成子任务和总任务(本轮规范和执行记录已更新;总任务因跨平台/正式公开发行延期继续in_progress,不归档未完成任务)。 - -## 2026-09-29 收口复验 - -- 通过:`cargo check --offline --locked --workspace`;API declarations 16/16;SQLite authorization 1/1;CMS parity 1/1;External Lib 6/6;shared toolchain 7/7;CLI Lib 单测 4/4;Dever CMS `check`(Dever/Markdown)及 Dever native build/package/run。 -- 通过:真实本机 PostgreSQL authorization ignored 1/1(记录在 `09-20-production-api/implement.md`)。 -- 修复:无租户 Job 的 tenant migration 未定义符号;CMS 打包验收的工作目录配置缺口;恢复 CMS 双源码测试入口。 -- 追加修复:无数据库的 application-test native 编译不再生成引用 `dever_runtime::database` 的 tenant Job 空实现;`application_testing` 8/8 已通过。 -- 追加修复:`deverc run` 在启动临时 native 程序前将项目 `config/` 安全复制到受保护的 build staging 目录,并拒绝配置目录符号链接;因此运行配置仍只来自 `config/setting.json`,不引入环境变量。 -- 阻塞/未运行:旧 `postgres_orm` fixture 在连接前因当前 Model 规则失败;真实 pip/npm/Go registry、受管 runtime/正式 SDK、跨平台服务注册与 peer credential、全量 workspace、64/128 MiB 压测、真实持久服务;rustfmt/clippy 组件未安装。 - -## 阶段 5 定向质量门记录 - -- 通过:workspace `cargo check --offline --locked`;`api_declarations` 16/16、`application_config` 6/6、`application_testing` 8/8、CMS parity 1/1、External Lib 6/6、shared toolchain 7/7、SQLite authorization 1/1。 -- 通过:CMS isolated 长链路 `cms_project_checks_runs_and_builds_from_an_isolated_copy` 1/1(Dever/Markdown 的 check、test、run、build、package、package-run);native stripped 产物约 6.3 MiB。 -- 通过:项目 formatter 对 Dever/Markdown CMS 的 `fmt --check`;`cargo fmt`/Clippy 仍因组件未安装不可用。 -- 保留阻塞:全量 workspace 测试、真实 registry/runtime、跨平台发行、旧 ORM fixture 迁移及性能/RSS/64/128 MiB 压测未纳入本地完成证据。 - -## 首个实施目标 - -优先启动阶段 1,使用现有 production-api 代码和测试作为基线,只补真实 PostgreSQL fixture/配置及最终组合验收;不先扩展新语法。 - -## 2026-09-30 实施与当前源码证据 - -任务仍为 `in_progress`,没有把五个阶段记为完成。上面的 09-29 数据是历史定向证据,不能代替当前源码的运行级/发行验收。 - -已实现并复验: - -- 共享 SQLite/PostgreSQL ORM fixture 迁移到当前 App/Model 结构,保留事务、CRUD、分页/游标/流、错误恢复及回滚断言。 -- Lib 配置统一为 `config/setting.json.lib`,拒绝旧独立配置文件;canonical v2 lock 绑定 checked Worker schema/操作/capability/Adapter/依赖闭包,允许不同 Worker 独立锁版本,拒绝同一环境冲突和完整 provider 元数据漂移。 -- run/build 自动嵌入全部 checked exec 候选,原子提取、Unix 私有权限/所有权和每次 Worker 启动的精确清单/摘要复验;不扫描其他 bundle。清空环境、不带源码 Worker 的重复运行与篡改拒绝实际通过。 -- 三语言 SDK 的实际协议、i64/JSON 预算、错误/取消/关闭;不合作取消一秒终止。显式宿主验收通过,不代表无宿主发行。 -- `deverd` 同所有者 token 校验、OS singleton 锁、断连/坏帧容错和固定线程/队列;缺 token、256 字节长度差、慢/坏客户端及重复实例/进程退出恢复回归通过。 -- base-only CMD/Job 不再引用未启用 database/tenant 模块;当前四 profile 均实际编译通过。 -- CMS 性能入口改为 stock 双源码的真实 bootstrap、tenant migrate/Owner、admin/front 登录、REST 创建/替换、发布、前台完整查询和重复发布 409;删除旧 `READY|3` fixture,不用无关记录数作为业务验收。 - -当前通过的定向检查: - -- `cargo check --offline --locked -p dever-core -p dever-cli -p dever-runtime --features 'dever-runtime/external dever-runtime/postgres dever-runtime/api'`。 -- `external_resources` 6/6;`native_entry` 15/15;`port_adapter` 15/15;CLI `external_libs` 14/14;`shared_toolchain` 10/10;`application_config` 6/6;`application_testing` 8/8;`cms_acceptance` 1/1。 -- `test/external-sdk/check.py` 的显式 Python/Node/Go 宿主协议验收通过。 -- 真实 PostgreSQL 16.15:`postgres_authorization_preserves_site_scoped_roles_and_catalog` 1/1、`postgres_orm_uses_the_configured_isolated_database` 1/1,后者约 398 秒。服务端 deb 仅解压到自有临时目录,使用现有低权限账号和专用 loopback 端口,不安装系统服务。配置写入临时根 `config/setting.json` 的 `postgres_test` URL 模板,全部结束后恢复原先文件不存在状态,关闭自有实例并删除测试库/下载包;服务日志保留在 `target/performance/postgres-acceptance-09-30-server.log`。此证据不是 PostgreSQL HTTP/租户完整组合验收。 -- CMS stock 双源码实际 `check/build`;产物 Dever 6,594,936 字节、Markdown 6,595,576 字节;每项 SHA 与构建日志在 `target/performance/cms-publish-09-30-v3/manifest.json`。 -- CMS 两套源码在 64 和 128 MiB 自有 cgroup 内各完成 16 篇顺序发布及完整输出核对,无 OOM;专属 cgroup 和服务进程全部清理。当前报告 `target/performance/cms-publish-64-09-30-v1/report.json`、`target/performance/cms-publish-128-09-30-v2/report.json`。峰值 RSS 约 33.3–33.7 MiB;64 MiB 下创建中位约 1.9–2.1 ms、发布约 2.2–2.4 ms,启动约 45–51 ms。这是 loopback/暖页、小规模顺序业务基线,非并发上限、冷缓存总内存或生产 p99。 -- 四 profile 体积:base 919,720、SQLite 2,901,400、PostgreSQL 2,920,488、both 4,884,760 字节,生产 fat LTO/strip 未放宽。报告 `target/performance/profile-cmd-09-30-v2/manifest.json` 与 `profile-report.json`,只构建不连接数据库。 - -失败及后续修复证据:首次 native 检查的开发 rustc PATH 缺失与旧测试合同已修正;发现真正的 base CMD database/tenant 引用缺陷并修复后复验通过。首次临时 PG 配置缺少必需 database.default,补正完整配置后两个实际测试通过。CMS v2 构建的 180 秒等待超时,v3 使用有界 900 秒构建并保留超时输出/关闭自有进程组,实际双源码构建通过。旧报告和失败目录未覆盖。 - -仍未完成的产品代码与验收,不混为“缺环境”: - -- Go 受管 compile/link、Python extras/sdist、npm 高级安装语义、Go sumdb、正式签名语言 runtime/build packs、无宿主发行验收,以及 Dever Package 安装与传递 Lib 集成;真实三生态 resolver、三 SDK typed manifest 和 Python/JS 自动 Worker 代码已补,见本轮追加。 -- OS capability sandbox;当前仅编译 effect 与握手 admission。 -- daemon build 服务、macOS/Windows peer adapters 和三平台正式安装/服务注册/升级/卸载;Linux 跨用户 artifact IPC 已补并通过实际不同 UID 验收。 -- HIR→LLVM/LLD 公开编译器和六 target ABI packs;无 Cargo/Rust 的公开项目构建仍未交付。 -- Markdown PostgreSQL/HTTP2 全组合、持续并发 CMS/全性能矩阵、全量质量门。当前相关的定向测试不代替这些;Dever CMS 的 PostgreSQL 非 Owner HTTP 授权组合已追加通过。 -- 全局工具未安装/替换;私有 rustfmt/Clippy 已可用且以下定向静态门通过。没有默认运行全量 workspace 测试。 - -### 2026-09-30 追加运行与质量复验 - -- PostgreSQL 16.15 的 `postgres_cms_http_isolates_two_tenant_databases` ignored 定向验收 1/1 通过:真实 CMS 原生程序、两个租户独立数据库、admin/front 登录、每租户两篇创建/替换/发布/查询、相同 slug 不同标题、重复发布 409、跨站 Cookie 和跨租户登录 401。报告 `target/performance/postgres-http-09-30-v1/report.json`;不包含非 Owner 授权撤销。Rust fixture 只复制 stock CMS 到自有临时项目,数据库清理失败也会使验收失败,配置 URL/密钥不写摘要。 -- 清理独立复核:PG 仅残留原有验收基库和 postgres,测试控制库/两个租户库均删除;停止本轮自有实例,临时根 `config/setting.json` 恢复为原先不存在,专属 cgroup 和服务进程回收。服务器日志 `target/performance/postgres-http-09-30-v1/server.log`;本轮 PG 临时目录移入回收站,可恢复,未注册系统服务。 -- PG 首次失败为工具在原位私有配置上使用独占创建,已修复为同目录原子替换并验证序列化失败不破坏原文件;第二次为 Rust wrapper 对含 `..` 的 workspace 路径判定错误,已 canonicalize 后第三次通过。独立复核进一步指出公开工具入口原位修改调用者配置,现已改为工具自身复制到 TemporaryDirectory,构建失败也保持源配置字节不变,副本自动清理。 -- SQLite ORM 实际 HTTP:64 MiB 自有 cgroup,128 行、短窗口 50 目标 QPS,25/25 正确响应、无错误/丢弃,实际约 49.91 QPS、请求 p50 约 1.056 ms、峰值 RSS 约 7.54 MiB;单连接事务断连后约 5.965 ms 回收、计数仍为 0。`target/performance/orm-runtime-64-09-30-v1/report.json`。仅短时合同基线,不是饱和吞吐或 p99。 -- typed App→Port→Adapter live TCP:64 MiB 下 8 次实际 echo 全部正确、RSS 约 4.77 MiB、无 OOM,`target/performance/live-tcp-64-09-30-v1/report.json`。不声称 TLS/WebSocket/SSE 压力已复验。 -- rustfmt/Clippy 使用 Rust 1.98.0 同版本的校验下载包,临时解压,不安装全局工具。core/runtime 与 api/postgres/external 组合 Clippy `-D warnings` 通过;CLI libs/bins 同样通过,日志 `target/performance/quality-09-30-v1/clippy-core-runtime-v3.log` 与 `clippy-cli-v3.log`。运行时数据库 open 改为具名 ConnectionOptions 并迁移所有调用点;不改变 setting.json 格式或连接语义。 -- 当前追加定向通过:`external_resources` 6/6、formatter 13/13、ORM performance fixture 4/4、ORM query 9/9、Port performance fixture 3/3、syntax/format 22/22、CLI external_libs 14/14、shared_toolchain 10/10、Python CMS/runner 55/55。 -- ORM query 的过时断言已迁移:事务内密码哈希保留 C014 拒绝,合法路径先哈希再进入短事务;空 create_many 从 owning-domain App 调用,公开名称不带 app 段;where 外 contains 仍拒绝,断言按当前 C004 诊断。没有放宽 checker 合同。formatter 测试补齐新 AST 声明,完整 13/13 通过。 - -### PostgreSQL 非 Owner HTTP 最终补验 - -- `postgres_api` 同一 exact ignored 目标当前 1/1 通过,约 41.29 秒;新摘要 `target/performance/postgres-http-09-30-v1/report-1968019-1790739069361983512.json`,日志 `test-rbac-final.log`,旧 Owner-only 报告保留。stock CMS 副本只追加 `test/dever-tests/fixtures/postgres_api/` 的普通成员 CMD/Reader membership,不修改生产源码或 Owner 不可撤销规则。 -- 真实会话成员 user_id=3,与两个 Owner 不同,三个权限来自各站点实际目录而非硬编码 key:授权前三个 GET 均 403;两个 admin 角色授权形成并集,front 同名角色独立;撤销首个 admin 角色后原会话对应 GET 立即 403,另一 admin GET 及 front GET 仍 200;继续撤销剩余角色后均 403。Rust 独立核对 ID/互异权限键/状态,且在数据库清理成功后才保存通过摘要,不记录密码、邮箱或 Cookie。 -- 两轮工具失败保留:首轮误从 admin 目录找 front 权限,现按当前 site 过滤合同分别读取;次轮 DELETE 发 JSON body,返回 400,现统一在 CmsClient 的 GET/DELETE 路径编码 query 且不发 body。没有放宽目录隔离或 API 输入规则。新增负向/编码回归;Python CMS/runner 最终 57/57,Rust 非 ignored 3/3,私有 rustfmt 对 postgres_api.rs 检查通过,CLI Clippy 最终复验 exit0(`clippy-cli-final.log`)。 -- 最终清理独立复核:仅保留本来就有的验收基库/postgres,client backend 数量 1 是核对自身;已停止本轮 PG,临时根配置再次恢复不存在,PG 临时目录再次移入回收站。`server-rbac.log` 保留完整服务器日志。 -- 真实 provider 诊断也同步事实:当前 resolver 只接 FixtureRegistry,错误明确说 provider integration 未实现,不再暗示安装一个尚未接线的 pack 就能解决。该诊断修正不算 pip/npm/Go resolver 完成;CLI external_libs 再次 14/14。 -- 私有 rustfmt/Clippy 下载与解压目录在复验后也移入回收站,可恢复;未改全局 Rust 工具链。PG 临时目录本次回收名称为 `dever-pg-http-JbyaSX.2`,最终根配置不存在、42209 无监听、自有 CMS/PG 进程及 cgroup 无残留。工作区原有 untracked 源码和用户删除未回退,未创建 commit。 - -### 2026-09-30 缺实现补齐:真实 resolver、typed Worker 与 Linux 共享资产 - -本轮实际产品代码: - -- 三生态共享 `RegistryResolver`/transport/lock/cache owner,实现 PyPI PEP 508/440 wheel、npm semver/SRI、Go proxy/MVS;只从当前已验证发行 core 的签名 runtime 元数据取 pack。拒绝代理、非协议允许的重定向、网络错误回退旧版本、坏归档、身份/工具链漂移,解析预算有界。Go ZIP 最多两跳手工转入固定 HTTPS GCS bucket,规范化目标检查在请求前完成,总 30 秒 deadline、循环/异常 Location 拒绝、签名 URL 日志脱敏;自有 loopback mirror 不成为项目配置。 -- Adapter contextual pip/npm/go 语法、生态/零 Lib runtime 锁定与 checked SDK manifest 接线。三 SDK 复用 setting/input/output/error 的 wire DAG;Python/JS runner 自动绑定 Port 同名导出,不增加业务注册表或第二套动态 App 调用。 -- Python/JS 离线展开 runtime/dependencies/owned source,生成 launch manifest,启动只接受精确资源树中的解释器/argv/cwd。Python 固定 `-I -S -B` 且先导入可信 SDK;Node 兼容 ESM/CommonJS。普通 Dever tests 继续 fake,不启动 Lib。 -- Linux SO_PEERCRED 跨用户 artifact 上传/下载、owner-only token/clean、metadata-only status (`verified:false`);64 MiB 单资产、2 GiB/4096 条总缓存配额,外部 UID 两连接/总量六连接,保留管理员容量。流式 exact-length/SHA staging、原子发布、操作租约和传输 deadline。 -- 原生资源使用独立二进制编译输入并按实际 SHA 共享一个静态 payload,编译前拒绝伪摘要,缓存身份仍含路径/摘要/长度/可执行位。移除 managed-only raw pack/archive 的重复嵌入;资源校验按 64 KiB 分块,不再额外读取整份解释器到堆。 - -已验收:CLI external_libs 最终 27/27(新增 Go ZIP 正常跳转、非法目标/异常 Location/循环/跳数、其他端点禁止跳转三项;主进程另独立复验 redirect 两项 2/2);shared_toolchain 14/14,另 actual UID=65534 ignored 1/1(含 token、clean、二连接 admission 和未校验摘要);external_resources 9/9(含独立 exec、重复资源、篡改和大文件);native_entry 资源生成定向 2/2;Port/Adapter 16/16、Worker protocol/lifecycle 1/1。Python/JS 默认 Worker 6 项通过/6 个宿主专项默认 ignored,其中最终 Native managed Node exact 用例单独执行 1/1(285.45 秒测试总墙钟,包含打包/编译,不是启动延迟)。三语言 SDK 协议已分别通过显式宿主路径验收,不等同于正式无宿主环境。最终 core/runtime api+postgres+external 与 CLI libs/bins/三项变更测试的 Clippy `-D warnings` 通过;Go 追加变更后的 CLI Clippy 也再次通过,修改的 Rust 文件私有 rustfmt check 通过。未安装全局工具、未默认全量测试。 - -失败及修复:独立资源生成测试首轮固定 32 KiB 总源码上限错误,改为相对不含资源的基线增量,1 MiB payload 不增长为数组且伪摘要拒绝通过。Python 隔离参数下的 SDK 导入顺序和业务同名模块遮蔽已修;Native managed npm 初次已编译但临时 fixture 缺 setting.json,补自有 Adapter 配置后实际独立产物返回 code=0/data=8(已移除原 entry、lock、raw pack 并清空继承环境)。复制宿主 Node 的 pack 只证明 bootstrap 链路,复制 Python 仍依赖宿主 stdlib;不能记成正式发行。最终协议复核发现全面禁跳会阻断 Go ZIP 的官方存储跳转,已按精确 bucket 增加受限跳转;规范化 URL 会抹掉空 userinfo,故同时检查原始 URI authority,负向测试确认不发第二次请求。 - -根因复盘(Trellis break-loop): - -1. 类别 E/D:小 exec/fake runtime 夹具隐含假设了大 runtime 也能作为数字数组生成,以及 Python script 目录会出现在隔离 sys.path;默认测试缺少真正的隔离启动和 SDK 遮蔽证据。 -2. 表面修复风险:仅减少 emitter 临时字符串不会消除重复 binary payload;只调整 Python source 路径而不先导入受信 SDK仍可能被同名模块替代。 -3. P0 防复发已实施:唯一内容输入/静态引用、差分源码大小/伪摘要回归、真实独立资源执行、固定隔离参数/SDK 导入优先级/同名模块用例,以及 actual UID 与缓存 quota/summary 测试。 -4. 扩展范围只覆盖同一资源打包/启动和 daemon 入口;没有改业务 API、真实配置或其他项目服务。 -5. 已同步 README、LANGUAGE、IMPLEMENTATION、compiler/toolchain specs 与三个相关任务的当前边界,不新增平行文档、commit 或归档;总任务保持 in_progress。 - -该轮结束时待做的 Package 集成和 Go compile/link 已在后续实现并复验,见下一节。当前仍未完成:高级生态安装规则/Go sumdb、OS sandbox、daemon build IPC、macOS/Windows peer/service adapters、完整 HIR→LLVM 与六 target runtime ABI packs、正式签名语言包/无宿主发行、持续并发/完整性能矩阵和全量质量门。连接桥已经有产品代码,不能再把它记为完全未实现,也不能把它记为完整编译器。 - -## 2026-09-30 Package、Go 与编译器连接桥复验 - -本轮已完成的实现边界: - -- `packages.rs` 复用现有 semver、ArtifactStore、Lib resolver 和原子锁:单版本传递闭包、精确归档/manifest 摘要、组件所有权、Package 源码注入普通 check/test/run/build、统一 Lib 锁、离线 remove 保留剩余版本、配置失败恢复原始字节。无本地 module 目录的 Package-only 项目也能加载。 -- exec 和受管 Worker 共用由 setting.json + canonical lock 决定的 Package 归属,不根据归档中是否有同名目录决定是否回退。真实 checker 的入口是 `module///`;原有组件碰撞已阻止本地同路径替换。新增实际 prepare 回归验证锁定入口缺失拒绝,以及本地组件碰撞拒绝,不声称证明了可利用漏洞。 -- Go 仅使用锁定 build pack 的 compile/link/analyzer/stdlib/importcfg,工具以绝对路径和空环境运行;生成 main 静态检查同名 handler 的签名,并复用 SDK typed manifest。编译后仅嵌入 Worker 与合同,删除展开后的 raw build pack/module archive。显式作者工具制作的 host-target fixture 压缩 55,785,046 字节,展开 203,288,946 字节/358 项,未放宽原有 64 MiB 单资产与 256 MiB 展开预算。 -- 新增 `dever-backend-bridge`,安全 API 显式选择 Linux/macOS/Windows 的 x86_64/aarch64 目标;LLVM 在进程内 parse/verify/O2/object,LLD 在进程内串行链接。所有 foreign buffer 同一 allocator 释放,输出只在当前用户私有且祖先可信的目录独占预留;失败清理不覆盖已有文件。不可恢复的 LLD 状态终止私有 compiler worker。私有 LLVM 18 开发 SDK 不做全局安装,当前 Linux 作者 SDK仍使用宿主 LLVM 动态库,不能记成自包含发行包。 - -主代理最终验证证据(不是仅采用子代理报告): - -- bridge `--features embedded --test backend_bridge`:5/5;六种真实对象和链接输出、IR/SSA/target/layout 拒绝、失败后重试、并发同输出唯一胜者、共享目录/可写祖先拒绝,Linux freestanding LLVM→LLD 程序在空环境实际退出 42。日志 `target/backend-bridge-test.log`。 -- Go ignored 专项单独执行:1/1,44.46 秒(整项编译+执行,不是启动延迟);包含 module ZIP、目标 tags、go:embed、typed call 与源码移除/空环境独立执行。日志 `target/closure-go-managed-final.log`。 -- 最终 Lib 27/27、默认 Worker 6 项通过/7 项 ignored、Package 10 项通过/1 个 signed child 入口按设计 ignored/1 个既有慢链路过滤;signed child 由父测试实际执行,覆盖真实 `workers::prepare`。日志 `target/closure-package-worker-final.log`。 -- 本轮之前已由主代理独立执行完整 Package 集合 9/9,其中安装→check/test/run/build→停止私有 daemon→独立运行链路通过,总 221.17 秒;最后的锁归属加强只重跑相关集合,没有重复这个慢链路。日志 `target/closure-package-go-regression.log`。 -- 配置/Port/源码回归:application_config 6/6、Port/Adapter 16/16、source_architecture 12/12、source_visibility 10/10。日志 `target/closure-source-package-regression.log`。 -- 最终 CLI/core/runtime/bridge offline locked check(runtime external/postgres/api)通过;CLI libs/bins 与三项变更测试、bridge embedded all-targets Clippy `-D warnings` 通过;本轮修改的 Rust 文件私有 rustfmt check 通过。日志分别为 `target/closure-current-cargo-check.log`、`target/closure-cli-final-clippy.log`、`target/backend-bridge-clippy.log`、`target/closure-final-rustfmt.log`。 - -没有新增应用环境变量、默认联网或宿主语言回退;未运行全量、真实数据库/CMS 服务级或新性能压测,未使用真实发行签名身份,未提交或归档。自有测试 daemon 已退出,无遗留服务;磁盘约 7.3 GiB 可用。总任务继续 `in_progress`:完整 HIR lowerer/稳定 runtime ABI、正式 packs/OS sandbox、高级生态安装、daemon build/跨平台发行和最终质量门仍需完成。 - -## 2026-09-30 强类型 LLVM 内核与首段 runtime ABI 复验 - -实现:`dever-core::llvm::emit_kernel` 复用 checked HIR、分句 Domain 和静态 specialization,直接产生 typed LLVM IR。当前覆盖 Int/Float/Bool/Nullable、普通 Record/Choice、多输出、分句绑定投影、值拷贝/字段修改、直接调用/静态 handler、左到右求值、短路和 checked 数值错误;故障保留 origin span 和逐层 caller spans,容量由无递归的可达实例图界定。所有可达但未支持的类型、资源、异步、失败、API/CMD/REST/Job 或 intrinsic 都明确带源码位置拒绝,不改默认 CLI 后端、不引入动态 Value 或 Rust fallback。 - -首段 runtime ABI 采用固定宽度标量/u32 status/显式输出指针,Decimal 使用原 runtime 的 LE 双 u64 位表示;Text/Bytes 返回带所有者的 Buffer,错误保留原数值/UTF-8 消息。`runtime-abi` feature 和 `embedded` 分离,前者独立构建的 staticlib 不含 LLVM/C++ SDK;所有 C 导出/原始指针操作仍在唯一私有 ffi.rs,runtime 本体保持 forbid。canonical 签名、借用、对齐、非重叠和释放合同位于 include/runtime.h。C++ compiler Reply 和 Rust Box ABI Buffer 分配器不混用。 - -主代理最终证据: - -- `llvm_lowering` 4/4:typed IR、源位置拒绝、完整调用链,以及仅嵌在表达式中的 nominal type 定义。日志 `target/closure-llvm-lowering-tests.log`。 -- `llvm_native` 9/9:简单内核六目标 object/link、复杂聚合六目标 object、本机分句/Nullable/Choice/record 值语义、静态 handler、Float NaN、多输出、短路、Int 极值/除零/溢出及实际 origin/caller span;其中 Windows 未提供 target runtime 时的显式拒绝是负向验收,不是 Windows 复杂链接成功。日志 `target/closure-llvm-runtime-tests.log`。 -- 原 bridge 回归 5/5、ABI safe 合同 2/2;同上日志。 -- 独立 `--no-default-features --features runtime-abi` archive 在 `target/native-runtime-abi` 离线制作;C header→实际库和 LLVM object→实际库 opt-in 2/2,owned 子进程 env_clear 并按 5 秒期限回收。开发 C/Rust 作者工具只用于夹具,不是产品启动依赖。日志 `target/closure-runtime-link-tests.log`。 -- core/runtime/CLI/bridge(runtime external/api/postgres)offline locked check、bridge/new tests 严格 Clippy(runtime/api feature)、core/IR tests 严格 Clippy及私有 rustfmt check通过。ABI-only 构建成功,但它单独的严格 Clippy 仍遇到旧 HTTP client_address 的 dead_code 警告;未改无关 HTTP 或添加抑制。 -- 双方独立只读审查没有剩余的当前 kernel/ABI milestone 阻断;不代替六目标运行或完整后端验收。 - -实测发现并处理:错误帧数组 GEP 原多一个索引,已在 owning emitter 修复;收集类型只看签名/locals 会漏临时 nominal 表达式,已复用 `check::visit` 全遍历并补最小回归。类别 D/E(IR 字符串通过不证明 LLVM 验证/执行、隐含类型会落地到 local 的假设),P0 防复发是当前真实对象/执行链及嵌套表达式回归。扩到 Windows 复杂聚合时,实际链接暴露 `__chkstk`/`_fltused` target runtime 缺失;没有提供 fixture 替代符号,此项仍归正式 target packs 未完成,已有负向失败/自有输出清理证据。已同步 canonical compiler/toolchain specs,仓库没有模板副本,无 commit/归档。 - -剩余:完整资源/集合/Decimal/Text/Bytes 的 HIR lowering、业务错误/async/Model/Port/Adapter/API/Job、全部 runtime ABI、六目标 CRT/stdlib/runtime assets和正式签名/无宿主发行;总任务及六阶段未完成项继续 in_progress。未运行全量、真实 PostgreSQL、CMS 服务级或新性能压测,未安装全局工具、改应用环境变量或使用真实发行身份。 - -## 2026-09-30 下一段:同步受管值与集合 - -范围:沿用当前任务推进 Decimal/Text/Id、基础 Bytes、List/Map 的 checked HIR→LLVM 与真实 runtime ABI 调用。不修改语法、默认 CLI 后端或配置方式;业务失败/捕获、Bytes Result-choice、资源、异步、Model/Port/Adapter/API/Job、正式目标 packs 仍未完成。 - -- [x] 复用现有 Text/Bytes/数值及 List/Map COW;固定 typed element 的布局、静态生命周期回调与消费式更新合同,原始指针操作仍只在私有 ffi.rs。 -- [x] LLVM 为受管局部、临时、嵌套 Record/Choice/Nullable 建立具体类型所有权;正常、短路和故障出口统一清理,成功输出移交调用者。 -- [x] runtime 原始错误 Buffer 移交 fault 尾槽,保留 source origin/caller stack,并提供调用者释放;不混用 C++ Reply 分配器。 -- [x] 从真实 checked Dever 源码生成对象、链接实际 runtime archive,定向验收集合/静态 handler、别名与字段替换、提前失败、根输出及重复执行分配平衡。 -- [x] 最小定向检查、格式/Clippy、独立审查并同步 canonical 合同;分别记录支持范围和仍明确拒绝的 HIR,不把该里程碑称为完整后端。 - -实现边界: - -- `runtime.h` 的 Text/Bytes/List/Map opaque owner、process-static DeverRtType 回调及消费式 cursor 接入现有 runtime。元素存储用对齐的 MaybeUninit,不复制/读取 padding;普通 Element 保留 PartialEq,只有合法 MapKey 包装实现 Eq/Hash。Text split 使用调用者的同一 Text descriptor。 -- LLVM 拆分到 abi/ownership/intrinsics/collections/traversal,复用 native last-use/字段替换分析。typed guard 在入口初始化,正常/失败统一清理;根输出与原始错误分别通过 `dever_outputs_release`/`dever_fault_release` 释放。无动态 Value/解释器或 Rust fallback。 -- 支持 List/Bytes 的静态 each/filter/find/reduce/reduce_until/sum;C ABI 已有 Bytes 转换/切片,但其 BytesToText/BytesFromInts/BytesSlice Result-choice 源码 lowering 仍明确拒绝,不能记为完整 Bytes 已交付。 -- 本轮所有永久测试都在根 test/。共享 checked-source→IR 辅助函数复用同一 SourceMap/check/emit 路径,不另建测试编译器。 - -主线程独立复验(全部离线,2026-09-30): - -- runtime-only staticlib 明确构建:`cargo build --offline --locked -p dever-backend-bridge --no-default-features --features runtime-abi --lib --target-dir target/native-runtime-abi`,通过;不含 embedded LLVM/C++ SDK。 -- `cargo test --offline --locked -p dever-backend-bridge --features embedded,runtime-abi --test llvm_managed_native --test llvm_native --test native_runtime_abi --test native_runtime_link -- --include-ignored`:**25/25**。其中 managed 10/10(一个六目标 object 用例,九个 Linux 实际执行用例)、原有 LLVM 9/9、运行时 ABI 4/4、真实 C/LLVM→archive 2/2。日志 `target/closure-managed-final-tests.log`。 -- `cargo test --offline --locked -p dever-tests --test llvm_lowering`:**5/5**,日志 `target/closure-managed-final-ir.log`。 -- core/runtime/CLI/bridge 的 offline cargo check(runtime api/external/postgres、bridge embedded/runtime-abi)通过,仅编译、不连接数据库;日志 `target/closure-managed-final-check.log`。 -- core/bridge 及上述四个 bridge 测试 target 的私有严格 Clippy `-D warnings` 通过,日志 `target/closure-managed-final-clippy.log`;root `llvm_lowering` 的严格 Clippy 也通过,日志 `target/closure-managed-final-ir-clippy.log`;本次改动 Rust 文件私有 rustfmt check 通过,日志 `target/closure-managed-final-fmt.log`。没有安装/替换全局组件。 -- canonical C driver 与 allocation driver 的语法检查通过。九个 managed 执行用例预热后各重复 64 次,结果与存活分配计数保持一致;这只是有界所有权回归,不是性能/RSS/64/128 MiB 容量报告。 -- 独立只读审查确认当前修复范围无剩余阻断;主线程验证关键执行证据,不以审查报告替代测试。 - -本轮实际失败与防复发:新增 `List`/`Map` 边界执行发现 First/Get 原按 nullable 结果的内层值分配 ABI out,而 ABI 写入完整 nullable 行;同时外层 present 覆盖内部 null。此前只读审查和普通集合用例漏掉该合同。修复统一在 `llvm/abi.rs::runtime_optional_row`:按真实 row_type 分配,status 成功后才读取 present,无行不读 out,有可空行整行转交而非双包装。First/Get 共用此 owner,Find 同型路径也覆盖;新增 IR 与真实 native 回归后整组通过。根因是把“行存在”与“值非 null”混为一层的布局假设(类别 D/E),防复发合同已写入现有 compiler/toolchain specs,不创建重复规范或模板。 - -剩余先补业务失败/Result-choice,再接资源/异步及应用语义;正式 CRT/stdlib/runtime assets、签名 packs、无宿主发行与父任务其他未勾选闭环继续 `in_progress`。测试仅执行自有有限生命周期进程,不启动数据库/CMS 服务,不增加应用环境变量或默认联网;没有运行全量测试、新性能压测或六目标实际运行,没有 commit/归档。 - -## 2026-09-30 下一段:业务失败与 Bytes 结果 - -沿用已有 Rust 后端合同补同步 LLVM 缺口,不修改语言语法、Checker、默认 CLI 后端或应用配置。业务失败保持 nominal identity 和 typed payload,`result` 仅捕获已检查的业务错误;溢出、除零和 ABI 故障继续传播。复用 specialize/capture 的失败集合及匹配规则、已有 runtime Bytes 接口和受管值清理,不建第二套错误系统。 - -- [x] 具体类型的业务失败载荷、默认传播、根释放和源位置/调用链;捕获前后不泄漏或重复释放。 -- [x] `result(named_call)` 的零/单/多输出成功、direct/wrapped error、显式 outer identity 及 static handler 传播。 -- [x] BytesToText/BytesFromInts/BytesSlice 的成功/Failed choice;普通标准库调用和显式 result 共用同一通道,非法 ABI 不伪装为业务错误。 -- [x] 真实 checked-source→LLVM→实际 archive 执行,包含受管载荷/提前失败、捕获后再次失败、运行故障不可捕获、Bytes 边界和重复分配平衡;保留上轮回归。 -- [x] 最小 offline check、私有 fmt/strict Clippy、独立检查及 canonical specs/任务证据。 - -实现代理负责 core LLVM 与 IR 回归;主线程负责根 test 的实际执行验收、整合及规范。资源/异步/应用入口/正式 packs 仍不在此段完成范围;仅执行自有有限生命周期进程,不启动数据库/CMS/HTTP 服务或进行全量/性能测试。 - -实现与复用:`llvm/failures.rs` 统一 ordinary invoke/fail/capture/write_variant,复用 `specialize::failures`、`capture::targets` 与已有 TypeOwner;不改 Checker、runtime/bridge ABI 源码或默认 CLI。fault 前五字段不变,追加 type_id+1(0 为无载荷)、variant、按可达错误 Choice 最大布局对齐的内联 typed payload;Business code=4,匹配捕获后转交并清空整个 fault,根释放静态分派原类型。Bytes 三项只将 ABI status1 转为标准 Failed(Text),status2 与数值/其他 runtime fault 继续传播。没有 Value/Any、错误字符串匹配、Rust fallback 或新 unsafe 边界。 - -主线程最终独立复验(离线,2026-09-30): - -- `cargo test --offline --locked -p dever-backend-bridge --features embedded,runtime-abi --test llvm_result_native --test llvm_managed_native --test llvm_native --test native_runtime_abi --test native_runtime_link -- --include-ignored`:**37/37**。新 Result target 12/12(1 checked-source/IR 合同检查、11 actual Linux LLVM native),旧 managed 10/10、原 LLVM 9/9、runtime ABI 4/4、真实 C/LLVM 链接 2/2。日志 `target/closure-results-final-native.log`。复用此前显式准备的 runtime-only archive,未在测试中递归构建。 -- `cargo test --offline --locked -p dever-tests --test llvm_lowering`:**7/7**,日志 `target/closure-results-final-ir.log`。 -- core/runtime/CLI/bridge offline check(api/external/postgres、embedded/runtime-abi)通过,日志 `target/closure-results-final-check.log`,仅编译不连接数据库。 -- core/bridge 及上述 targets、root llvm_lowering 的私有严格 Clippy `-D warnings` 通过,日志 `target/closure-results-final-clippy.log`;改动与相关 LLVM 文件私有 rustfmt check 通过,日志 `target/closure-results-final-fmt.log`。未安装或修改全局工具。 -- 新旧 managed native 共用 `test/dever-tests/tests/support/llvm_managed.rs` 原有 runner 与 C allocation driver:每次实际执行保持明确 output/fault 释放,预热后 64 次结果与存活分配平衡。新测试覆盖错误载荷 COW、原始 Bytes 文案、捕获后重失败、第二 variant 的根释放及精确 origin/两 caller spans。这是有界所有权回归,不是性能或容量报告。 -- 独立 trellis-check 只读对照 Rust native/capture 合同,无当前 milestone 阻断;主线程重新核验关键运行证据,不以子代理报告替代验收。README、LANGUAGE、IMPLEMENTATION 与现有 compiler/toolchain specs 已同步,不建重复设计文档。 - -质量修正:原验收 helper 曾同时认可“任意成功或失败”分支,零输出捕获可能被错误 Done 误判为通过。主线程读用例后加入逐次 wanted_success/预期内层错误标签,成功/失败及 Missing/Conflict 互斥;加强后整组复验通过。记录的是测试判定缺口,不是已观测到的 LLVM 实现故障。中途其余失败是 fixture 语法/类型上下文错误,均按现有合同修正,没有放宽 Checker。防复发要求写入 compiler-contracts 的 Required Tests/Wrong vs Correct。 - -下一段继续资源生命周期与异步语义,再接 Model/Port/Adapter/API/Job 应用入口和正式目标资源。父任务与六个闭环的未完成项仍 `in_progress`;没有全量/数据库服务/CMS/性能/跨平台运行验收,没有 commit 或归档。 - -## 2026-09-30 下一段:资源生命周期与真实协程 - -当前用户已确认继续;沿用父任务,不切换默认 CLI 后端,也不改变语言或配置语法。 - -- [x] File 的 create_new/open/read/write/close、共享别名关闭与最后 owner 释放;原始 I/O 失败进入标准 choice/fail 通道。 -- [x] 同步 Stream 的共享游标、文件 chunks、内部 pull/close 与静态 handler 遍历,EOF、最后错误项和提前释放保持 runtime 合同;不新增源码 pull/first(Stream)。 -- [x] LLVM18 switched-resume coroutine + runtime ForeignFuture:真实 Pending/恢复、owned 输入/局部量/输出与 typed fault,初始/pending/final destroy 配对清理;不是每函数 block_on。 -- [x] 基于现有单 runtime Scope/supervisor 的 Task、Group、Channel、sleep、checked 同步 blocking/parallel;取消和失败先排空后代,保留业务错误身份与来源。 -- [x] checked-source → LLVM object → 实际 runtime archive 的有界自有资源/进程验收、旧定向回归、offline check、私有 fmt/Clippy、独立检查与 canonical 规范同步。 - -归属:bridge 只在原 private ffi.rs/header 增加资源和 future ABI;core 在 llvm/ 中完成 typed lowering,复用现有 specialization、liveness、TypeOwner 与失败通道;测试仍在根 test。异步输入、输出和 fault 通过静态描述符的 typed move/drop 转交,禁止解释器/Any/Value、错误 String 化、raw padding copy 或同步线程冒充 async。LLVM 自有协程帧使用配对 runtime allocator,借用的 poll Context 只在当次 resume 有效,final suspend 后绝不再次 resume。 - -此段不启动数据库/CMS/HTTP 服务,不做全量或压力测试,不安装全局工具;AsyncStream、网络/系统族、Model/Port/Adapter/API/Job 入口及正式跨平台 packs 仍需后续接入,不能以 Task/Group/Channel 的定向验收代替完整应用后端。 - -### 2026-10-01 最终复验 - -- 显式离线构建 runtime-only archive(`target/native-runtime-abi/debug/libdever_backend_bridge.a`),含 File/Stream、异步与同步 time_sleep ABI;与 embedded LLVM/LLD 分离。测试没有递归 cargo 构建、宿主语言回退、联网或数据库连接。 -- `cargo test --offline --locked -p dever-backend-bridge --features embedded,runtime-abi --test llvm_async_source --test llvm_resource_native --test llvm_async_native --test llvm_result_native --test llvm_managed_native --test llvm_native --test native_runtime_abi --test native_runtime_link -- --include-ignored`:**70/70**。async_source 21/21(17 actual archive 执行、六目标 object、源码 Checker/两个原规则拒绝),resource 10/10、async ABI 2/2、旧 Result/managed/kernel/ABI/link 37/37。日志 `target/closure-resources-async-final-native.log`。 -- 源码覆盖大记录及 Text/List/Map/多输出跨 Pending、异步 each/reduce 静态 handler、同步/异步 Task、Group 容量和 Unit child、Channel 背压/Nullable/close/End、stop 与嵌套后代释放、blocking/parallel 的 owned 值和业务错误、capture/refail、默认业务错误的精确 origin/caller、负数 sleep 原始消息、数字 code2 与 ABI code3 原始 Buffer 不可捕获。受管运行 runner 用并发安全的原子 allocator ledger,一次预热后 64 次重复核验;不是 RSS/体积/性能测试。 -- 资源验证覆盖同次第二次 create_new 必须失败、不同内容不能覆盖、File 别名 close、read EOF、Stream 共享进度/提前关闭、reduce_until 未访问行、一次末尾 Failed 后 End、each 的 owned 业务错误、运行故障清理及 root File owner 移交。C 层无效输出在 I/O/cursor advance 前拒绝。 -- `llvm_lowering` **7/7**,日志 `target/closure-resources-async-ir.log`;原 runtime Stream 定向 **3/3**、File 定向 **1/1**,分别见 `target/closure-resource-reference-stream.log`、`target/closure-resource-reference-file.log`。 -- core/runtime/CLI/bridge 的 offline locked check(runtime api/external/postgres,bridge embedded/runtime-abi)通过,日志 `target/closure-resources-async-final-check.log`。postgres 仅编译,没有真实 PostgreSQL。 -- 私有工具对 core lib 与 bridge lib/上述 8 targets 的严格 `Clippy --no-deps -D warnings` 通过,日志 `target/closure-resources-async-core-clippy.log`、`target/closure-resources-async-bridge-clippy.log`。改动和相关 LLVM/ffi/根测试的 rustfmt check 通过,日志 `target/closure-resources-async-final-fmt.log`;没有安装全局工具,不代表全仓库质量门。 -- 独立只读检查已完成:发现并修正内部 Unit/Outputs ABI transferability、同步 sleep 符号、可达 async 临时值的 Send 验证;fresh review 未发现 typed fault、initial/pending/final cleanup 的剩余阻塞。主线程用实际最终日志确认关键证据。 -- 已同步 README/IMPLEMENTATION/LANGUAGE 与 compiler/toolchain canonical specs;父任务仍 `in_progress`,未 commit、未归档。磁盘约 4.9 GiB 可用,此段没有清理用户数据或旧目录。 - -质量复盘:内部 Unit/Outputs 的源码属性不可直接充当 ABI row 属性(跨层合同/隐含假设);修复归属在唯一 descriptor 生成器,不改 Checker,真实 sync Task/多输出/blocking 用例防回归。SyncFunction.invoke 只借用 runtime-owned input,避免双 drop。测试判定另有两处缺口:create_new 相同内容掩盖错误覆盖,以及以 RuntimeAbi 字符串 oracle 验证数字除零;已改互斥结果/不同内容、精确 code2/origin,并另验 code3 原始 Buffer。规范已记录字段转移、Scope/Send、状态映射和 exact oracle 要求;没有新增重复框架/错误系统或伪造成功分支。 - -后续仍需 AsyncStream/网络及其余系统 intrinsic(含 timeout/race)、Model/Port/Adapter/API/Job 的 LLVM 应用入口、默认 CLI 后端整合、正式六目标 runtime packs,以及父任务其余真实生态/发行/性能质量门。资源/协程这一段已验收,不以此标记整个阶段四或全部语言完成。 - -## 2026-10-01 下一段:AsyncStream、TCP 与 timeout/race - -用户已确认继续,沿用原 LLVM 后端阶段;本段不改变语法、Checker、默认 Rust bootstrap CLI 或配置协议。 - -- [x] AsyncStream 的 List/Bytes/Channel 来源、ticks、共享游标/close、静态 handler 遍历及当前合同允许的并行分派。 -- [x] Socket/Listener typed owner 和 TCP connect/connect_timeout/listen/accept/port/read/write/timeout/close/chunks/connections;复用 runtime net 的方向锁、期限及取消合同。 -- [x] timeout/race 消费同签名 Task,超时/胜出结果返回前排空被取消的工作;fallback 只在真正超时后运行,业务和 runtime fault 保持原始 typed 身份与来源。 -- [x] checked-source → LLVM object → runtime-only archive 的实际运行、六目标 object、旧定向回归、offline check、私有 fmt/Clippy 与独立合同检查。 - -改动归属在 core llvm/ 和 bridge 私有 ffi.rs/canonical runtime.h;永久用例仍在根 test。复用现有协程、typed move/drop、recoverable choice/fault 和单 runtime Scope,不增加第二套异步引擎、动态值或 fallback。验证只使用自有短生命周期 loopback、系统分配端口和有界等待,不接触真实服务或外部网络。HTTP/TLS/WebSocket、其余系统族及 Model/Port/Adapter/API/Job 应用入口不计为此段已完成;正式 packs、共享编译和最终质量门仍按父任务推进。 - -### 本段最终复验 - -- 主线程显式 offline/locked 构建 runtime-only staticlib,最终 archive 晚于最终 ffi 修改,不含 embedded LLVM SDK;日志 `target/closure-stream-network-final-archive.log`。 -- 9 个相关 LLVM/ABI targets 首次最终集合 **92/92**(旧 70 + 新 22),日志 `target/closure-stream-network-final-native.log`。随后追加「并行 handler 故障打断空闲 Channel producer,同时只关闭流别名而不关闭独立 Channel」精确回归;最新新 target **23/23**(21 个实际 archive 执行项、Checker、六目标 object),日志 `target/closure-stream-network-final-new-native.log`。当前独立覆盖共 **93 项通过**,不是将重复执行相加。 -- 新源码执行覆盖 nullable 流、Channel 背压/挂起 handler、ticks 和提前关闭别名、四类序列及同步/挂起 handler 的合法并行路径、同步 File Stream worker 的 owned 业务错误、timeout/race 受管记录及多输出/null/Unit、真正超时的 async fallback、业务错误不走 fallback、数值 code2 的原始来源、ticks/timeout 非法期限的原始 code3 文案。TCP 自有 loopback 验收 short read/完整 chunks/EOF/共享关闭、原始输入错误、chunks/connections 一次末尾 Failed 后 End;超时返回后对端 EOF 证明 pending 后代 Socket 已释放。 -- 沿用同一 atomic allocator ledger,实际 native 每个程序预热一次后重复 64 次,输出/fault 与资源释放平衡;这不是体积/RSS/延迟/64或128 MiB 性能报告。六目标只证明对象生成,本机 Linux x86_64 证明实际运行,没有六 OS 执行验收。 -- 原 runtime/IR 定向复验:`llvm_lowering` **7/7**、`async_network` **9/9**、`async_composition` **6/6**(明确过滤原 Rust native 慢链路);日志 `target/closure-stream-network-reference-ir.log`。覆盖原背压/空闲 producer 故障、读超时后继续使用、部分写取消先关闭、阻塞后代排空和规则拒绝;不启动现有服务。 -- 异步 poll 的非法输入状态最小修正为既有 canonical `4`,不再与 typed fault `2` 冲突;C driver 新断言实际 archive 执行 **2/2**,日志 `target/closure-stream-network-final-async-abi.log`,严格 C11 语法检查通过。 -- core/runtime/CLI/bridge offline locked check(runtime api/external/postgres、bridge embedded/runtime-abi)通过,日志 `target/closure-stream-network-final-check.log`;postgres 仅编译。core lib 与 bridge lib/9 targets 私有严格 `Clippy --no-deps -D warnings` 通过,日志 `target/closure-stream-network-core-clippy.log`、`target/closure-stream-network-bridge-clippy.log`;追加新 fixture 后再次 Clippy 通过,日志 `target/closure-stream-network-final-new-clippy.log`。相关 LLVM/ffi/新根测试的 rustfmt check 通过,日志 `target/closure-stream-network-final-fmt.log`。没有安装全局工具。 -- 按 Trellis 2.2 进行双向非本人代码审查:core 作者独立对照 bridge ABI,bridge 作者独立对照 core 与原 native/runtime;新 reviewer 线程额度不足时复用已完成线程,没有启动额外进程。最终未发现本段剩余阻断;主线程独立执行关键验收,不以作者 compile 或审查报告代替运行证据。 -- 已同步 README/IMPLEMENTATION/LANGUAGE 和现有 compiler/toolchain/directory specs。父任务仍 `in_progress`,六个闭环的未完成项不勾选;无全量测试、真实 PostgreSQL、CMS 服务、压力测试、正式签名发布、全局安装、commit 或归档。磁盘约 4.7 GiB 可用,未清理用户数据。 - -首轮失败均明确保留为未通过的迭代证据:fixture 的空比较缺类型上下文、named Outputs 跨 suspension、保留词 `other` 当局部名、Result 的 timer failure 集合不匹配;均按现有语言合同改 fixture,没有改 Checker 或降级错误类型。桥接中途一次 Result error 类型推断失败已加具体类型,最终 check/Clippy 通过。质量收尾还保证 race null 创建路径保留 caller owners、遍历关闭责任在 state/context 求值后建立,以及 ParallelHandler 只校验布局而不额外分配临时三份存储。 - -下一段仍需 HTTP/TLS/WebSocket 与其余系统 intrinsic,再接 Model/Port/Adapter/API/Job 应用入口、默认 CLI 后端与正式六目标 runtime packs;不得将这 93 项内核/ABI 定向证据记为整个阶段四或完整语言交付。 - -## 2026-10-01 LLVM HTTP/TLS/WebSocket 与系统 intrinsic(本段已验收) - -沿用当前 checked HIR、静态 specialization、强类型 fault/owner/coroutine 描述符及既有 runtime;不改语言语法、配置或默认 CLI 后端,不把本段内核验收计为完整应用/正式目标包验收。 - -- [x] 补 HTTP 单次/池化/流式请求与静态 server handler 的 typed ABI/lowering,复用 Hyper、原 HTTP/2 和连接/任务 Scope。 -- [x] 补 TLS client/server、live reply/SSE/WebSocket 与对应资源 retain/drop,保持背压、原始可恢复错误、取消和有界排空。 -- [x] 补剩余非应用系统 intrinsic(时间、进程参数、日志/stdout、UUID/Secret/crypto),保持敏感类型不可观察与既有阻塞工作边界;鉴权/上传/Job/Model 归属后续应用 lowering,不擅自合并。 -- [x] 根目录 checked-source→LLVM→真实 runtime archive 定向执行、无网络 Checker/六目标对象生成及必要旧覆盖复验;网络仅使用自有临时文件/有界 loopback peer,TLS 复用根目录 fixture。 -- [x] offline locked check、相关 fmt/Clippy、独立边界复核,并更新现有 canonical 合同与本记录。记录精确已验收范围和剩余项,父任务保持 in_progress。 - -实现所有权:bridge 工作线仅修改私有 `ffi.rs`、canonical `runtime.h` 及必要 runtime feature 接线;core 工作线仅修改 `llvm.rs`/`llvm/**`。主线程负责根测试、target 注册、验收和合同/任务记录;不互相覆盖,不运行全量或现有服务。 - -### 实现与复用 - -- 新 `llvm/http.rs`、`http_values.rs`、`http_handlers.rs` 复用原 Hyper/rustls/tungstenite 与 Scope,使用固定命名字段、opaque owner、静态 typed sync/async handler/context;不经过 JSON/Value。响应 owned 字段先注册再做可能失败的 header 转换。 -- `llvm/system.rs` 接日历/时钟、argv、stdout/log、Uuid/Secret/crypto,密码计算保留 blocking。Uuid 使用真实 UUID owner;敏感类型不新增 Render。`llvm/render.rs` 只在请求边界渲染可观察的终端 fault,保留原有日志+500/中止回复+服务器继续处理的行为。 -- 协议 async poll 在 I/O 前检查 output/presence/align;非法 metadata 返回 4,不改 sentinels 或操作状态,修正后可重试。原非协议 async 合同不扩大。 -- 纯日志探针定位到 runtime Logger 后,主线程明确扩展 bridge 的 owner 范围到 `log.rs`:单一预分配 128 槽队列配合 Mutex/Condvar,保留原过滤、截断、JSON、FIFO、低级别丢弃/高级别背压;串行固定 ACK,异常退出释放积压并唤醒等待者。没有新依赖或第二套 logger/队列。 -- 根 test 保留源码执行、C ABI 与队列回归;实际 native helper 共用原严格 allocation ledger,只增加明确的昂贵用例次数/期限与文件输出捕获,不建另一个执行器。 - -### 最终证据 - -- 显式 offline/locked 重建 runtime-only archive,最终 `2026-10-01 03:44:10 UTC` 晚于最终 ffi 与 log 修改,不含 embedded LLVM/C++ SDK;`target/closure-http-system-final-archive.log`。 -- 新 `llvm_http_system_source` 唯一覆盖 **25/25**:23 项 Linux checked-source→LLVM→实际 archive 执行;21 份源码 Checker;21 份源码×六目标 object。末批输出 fixture 的 Map 分隔修正后单独复验,未重复相加:`closure-http-system-native-final.log` 的 22 项已通过,修正后的三个检查见 `closure-http-system-output-final.log`、`closure-http-system-checker-final.log`、`closure-http-system-objects-final.log`。六目标 object 不等于六 OS 运行。 -- 实际执行覆盖独立 chunked wire/repeated headers、H1/H2/TLS 池化与流式上下行、live Reply/SSE、WS/WSS 文本/二进制/控制帧与共享关闭、owned context 最初挂起前克隆、owned handler 失败后 500 再正常处理、原始诊断、时间/UUID/Secret/密码/argv、stdout 与四级精确 JSON 日志。一般 ledger 每进程 warm 1+64 次;密码是 warm 1+2 次,45 秒边界。 -- C/header/archive **4/4**,含非法协议目的槽→原样保留→有效重试→完成后拒绝 repoll,以及纯 log flush 的严格 ledger;`closure-http-system-c-abi-final.log`。C 探针不假造成功的 WsReceive row,真实消息路径由源码执行覆盖。另同一纯 flush 探针在 **40 个独立进程**中全部通过。 -- 原 8 个相关资源/异步/集合/Result/ABI targets **91/91**;`closure-http-system-old-regression.log`。root IR **8/8**;`closure-http-system-ir-final.log`。原 Rust bootstrap 的 source logging **1/1**;`closure-http-system-bootstrap-log.log`。Logger 的 FIFO/dropcount、Warn/Error 背压、并发 flush、writer panic 四项 **4/4**;`closure-http-system-log-unit.log`。 -- core/runtime/CLI/bridge offline locked check(runtime api/external/postgres,bridge embedded/runtime-abi)通过;`closure-http-system-check-final.log`,postgres 仅编译。core lib、bridge lib/10 定向 targets 与 root IR 的私有严格 `Clippy --no-deps -D warnings` 通过;`closure-http-system-core-clippy.log`、`closure-http-system-bridge-clippy.log`、`closure-http-system-ir-clippy.log`。实际 `log.rs` 与根队列测试的独立 strict Clippy 通过;`closure-http-system-log-clippy.log`。相关文件私有 rustfmt check 与 C11 strict syntax 通过;`closure-http-system-fmt-final.log`。没有安装全局工具;不是全仓库 Clippy 门。 - -### 根因与防复发 - -首轮 native 为 15 通过、6 项 ledger 失败(+2/+1),返回值 oracle 没失败。只调用 flush 的 C 探针同样出现 +2,证明 owner 在 Logger,不能据此断言 LLVM/HTTP 泄漏。固定 ACK 通道仍失败;分配栈最终确认是 std mpsc receiver 首次阻塞的 48B Context 与 96B waiter Vec 持久初始化,发生在 ACK 后。最终修正整个单一队列等待 owner,而不是增加 warm、sleep 或放宽 ledger。此前关于「仅临时 ACK 析构 race 就解释全部失败」的初判过强,已纠正。纯探针、全部协议源码和旧回归共同复验通过;独立检查确认无丢唤醒、串 ACK、队列 owner 遗漏或新阻断。约束已写入 logging/toolchain/compiler canonical specs。 - -另修正 C async poll 的边界检查时机:先 poll 后检查目的槽会推进有副作用的操作,必须先验证 metadata,根 C fixture 固化可重试合同。测试维护同步迁移原「stdout 尚未支持」断言为真实支持检查,保留合法 App 内鉴权 intrinsic 的源码定位拒绝;没有放宽 Checker。Clippy 曾命中失败的 rustc 探测缓存,保留到 `target/closure-http-system-rustc-probe-failed.json` 后只重建该元数据,最终通过。 - -README/LANGUAGE/IMPLEMENTATION 与 backend compiler/toolchain/directory/logging/index 已同步。未运行全量、数据库连接、CMS 服务、新性能/RSS/64–128 MiB 压测或跨 OS 实际执行;没有 commit/归档。下一段继续 Model/Port/Adapter/API/CMD/Job 与鉴权/上传等 LLVM 应用语义,再接默认 CLI 和正式六目标 runtime packs;父任务其余生态/发行/最终质量门未因此变为完成。 - -## 2026-10-01 LLVM CMD/App/Dever Adapter 应用执行链(本批已验收) - -继续原生产化任务,不重定语言语法,不切换默认 CLI。应用合同不能只靠解除 kernel 拒绝:原 Rust 生成入口还拥有配置、事务、权限、租户、服务与清理。 - -本批先交付独立 `llvm::emit_application`:真实 CMD 参数 → shared checked wire schema → App → 配置选中的 Dever Port/Adapter → typed 输出 → 固定 JSON envelope。Wire 的 JSON 只留在输入/配置/输出边界,复用 runtime `wire::parse/Node/Encoder`;业务仍是具体 LLVM 类型和静态函数。选中 Setting 在应用 entry 生命周期内初始化并清理;未选中 Adapter 不要求其配置。同步/挂起 CMD 都必须保持原 source fault、typed business failure 和所有权。 - -主线程负责根测试、实际 archive 链接、文档和串行定向验证;原 core/bridge implement 线程分持 LLVM lowerer 和 canonical C ABI。普通 `emit_kernel` 不替代生成应用根。实际执行使用测试自有临时目录、明确离线 runtime archive 和严格 allocation ledger;不启动数据库、CMS、外部 Worker 或服务。 - -已完成: - -- [x] 独立 `llvm::emit_application` 与 compiler-owned CMD 根,标准 `dever_application_entry`/output/fault release;内部 run 不公开。完整 CMD 名与单个 JSON 对象使用原参数合同,同步/推导挂起 App 共用已有 Scope 和 typed fault。 -- [x] `llvm/wire.rs` 消费原 checked schema DAG,具体 scalar/record/List/nullable codec 复用 runtime Node/Encoder,不把 JSON/Value 引入业务。CMD 顶层复用原 `Inputs`,保留缺失/未知字段文案、重复键检测和字段错误优先级;嵌套 wire policy 不混用。 -- [x] `llvm/ports.rs` 的 closed Dever Adapter 选择与 selected Setting 初始化。配置仍只读 `config/setting.json`,未选中的 Adapter 不要求配置,单个无 Setting 的 Adapter 不要求配置文件。选中槽为模块私有,非阻塞原子 gate 拒绝重入/重叠,根 Scope 排空后清理/复位并释放 gate;部分初始化失败走同一清理。 -- [x] 私有 canonical wire/CMD/settings ABI,回调借用不越过同步调用,输出 metadata 校验在解析/取字段/选择之前。成功解码后若 trailing CMD input 或 Buffer 不合法,桥接 drop 完整 owner;失败回调由编译后的部分初始化 guard 清理。复用原 runtime wire/config owner,`runtime-abi` 只增加 wire feature,不依赖 LLVM/C++ SDK。 -- [x] 新应用根拒绝尚未接通的 Model/API/REST/Job/auth/permission/tenant 和 external Adapter,不按某个 CMD 当前未调用就跳过启动合同;普通 kernel 仍拒绝应用入口。 -- [x] 公共 native runner 下移到根测试 support,kernel/application 共用实际 archive、超时、owned process 和原 allocation ledger;没有平行测试执行器或放宽既有 fault oracle。 - -实际验收: - -- runtime-only archive 显式 offline/locked 重建通过,最终文件时间 `2026-10-01 05:12:48 UTC`,晚于 ffi/header 修改;不含 embedded SDK。core 后续 failure metadata 修正只改变 generated object,不要求重新构建 runtime archive。 -- 新 `llvm_application_source` **19/19**:15 项 Linux x86_64 checked-source→LLVM object→实际 archive 执行,另含原 Checker、六目标 object、kernel/app 边界及 source-located unsupported metadata 检查。实际执行保持 warm 1 + 64 次、严格原分配平衡与每次精确 JSON/fault oracle;覆盖 owned Unicode/大 Int/全部受支持 wire scalar/原始 Json、可空顶层/列表、异步输入、业务失败/result/数值错误、配置选择、部分 Secret/多 Adapter 初始化失败及 Task 读取 selected Setting。日志 `target/closure-llvm-application-source-final.log`。六目标 object 不是六 OS 运行。 -- 旧受影响回归 **43/43**:managed 10、Result 12、async source 21;runtime ABI **4/4**,C/LLVM 实际链接与 ledger **5/5**(含 wire/CMD callback/非法槽/成功后 finish 失败清理),日志 `target/closure-llvm-application-regressions.log`。IR **8/8**,日志 `target/closure-llvm-application-lowering.log`;没有重复相加早期运行。 -- core/runtime/CLI/bridge offline locked check(runtime api/external/postgres、bridge embedded/runtime-abi)通过,日志 `target/closure-llvm-application-check.log`;PostgreSQL 仅编译,未连接。 -- core lib 与 bridge lib/本批六个相关 test targets 私有 `Clippy --no-deps -D warnings` 通过,日志 `target/closure-llvm-application-core-clippy.log`、`target/closure-llvm-application-bridge-clippy.log`。相关文件私有 rustfmt check 通过,日志 `target/closure-llvm-application-fmt.log`;两个 C fixture 的 C11 `-Wall -Wextra -Werror` 检查通过。没有全局工具安装。 -- 本批独立 ABI/所有权交叉检查及最后的 failure metadata/runner 有界复核无阻断。主要风险分别由实际 fault、partial owner、重复 gate 复位和严格 ledger 用例覆盖;不把审查声明当作执行证据。 - -发现并修复的真实缺陷:扩展到 19 项时首轮为 18 通过、1 项 lowering panic。无配置同步 Adapter 声明了 `SleepResult`,实现并未实际构造它,但 fault 布局/drop 仍消费 `specialize::failures`;旧统一收集点遗漏仅声明的 failure nominal/owned 字段。现于 `validate_function`/`Module::new` 对同一 reachable failure 集做校验及递归类型收集,不注册无关类型、不加 fallback。单用例与最终 19 项、43 项旧回归均通过,canonical compiler spec 已记录此 invariant。最初关于「CMD 输入行缺描述符」的猜测已纠正。此前源 fixture 的字段换行、Int `//` 与 Port fails 合同,以及 C fixture 的 mandatory equal callback 修正是测试 fixture 修正,不是放宽语言/ABI。 - -README/LANGUAGE/IMPLEMENTATION 与 backend compiler/toolchain/directory specs 已同步。没有全量测试、数据库/CMS 服务、真实外部 Worker、新性能/RSS/64–128 MiB 压测或跨 OS 执行;没有 commit/归档。父任务仍为 `in_progress`。 - -完整 LLVM 应用阶段仍按依赖收口:① 本批入口/wire/CMD/Dever Adapter;② Model/双数据库 SQL plan/事务/DbError/Related/RowStream;③ API/auth/tenant/component/permission/REST/Upload;④ Job 与 compiler-owned Test;⑤ external Adapter 与准备好的资源集成。后续未支持族继续 source-located 硬拒绝,不用 Rust fallback、成功 stub 或放宽 checker。只有这些全部通过,才进入默认 CLI 和正式六目标 packs。 - -## 2026-10-01 LLVM Model/ORM 与事务(实现与定向验收通过) - -承接已验收的 CMD 应用根,本批实现静态 Model 操作、SQLite/PostgreSQL SQL/bind/row codecs、nested transaction 与精确 DbError、Related 批量加载、typed SQL、RowStream,以及 schema/migration/Seed 启动。沿用 checked QueryPlan 和原 driver,不修改语言语法、业务 CMS、默认 CLI,API/auth/tenant/Job/external 仍为后续边界。 - -代码归属:core implement 负责 `llvm/**` 和必要纯 SQL/schema helper 共享提取;bridge implement 负责私有 `ffi.rs`/`runtime.h`、独立数据库 ABI profiles,以及 runtime 数据库生命周期薄适配;主线程负责根测试、所有 Cargo/实际验收、canonical specs 和本记录。两个 implement 不运行 Cargo/真实数据库,不回滚对方或既有修改。 - -已经确认的结构风险:原 `config::bootstrap_scoped`、SQLite/PostgreSQL registry 都是 OnceLock,shutdown 后不能重复初始化或复用已关闭池。因此新 LLVM 根需要 owned `database::Session`,原 Rust native 仍保留现有 bootstrap;两个路径共享实际 driver 构造。事务普通/顺序调用继承隐藏 context,并发边界显式 detached;迁移和 SQL 仍使用原 owner。Session 在根 Scope 排空后、同一 runtime 销毁前关闭;必要 `task::run_entry_with_typed_cleanup` 只扩展这个生命周期,原入口委托它保持原语义。禁止新建池栈/SQL builder/反射业务 Value、成功 stub、tenant-to-global fallback,禁止新增环境变量配置。 - -验收先离线 Checker/objects/最小新根 target,再实际自有 SQLite 与严格所有权检查;PostgreSQL 只使用显式隔离 fixture,任何临时服务启动先说明。共享 helper/driver/task 改动必须复验受影响的原 Rust native/ORM/async 合同,不能只测新实现。未通过前不标记本批或父任务完成。 - -本批实现: - -- checked Model 的 CRUD、bulk/upsert、offset/cursor、nullable/scalar/private/choice codecs、typed SQL 和 bounded RowStream 均由 LLVM 降级到真实 runtime archive;ToOne nullable join 与 ToMany 按 998 个父键分批,保留每父条数限制。schema/migration/data migration/Seed 按实际数据库分组,先建全表再建外键。SQL/DDL 和 SQLite/PostgreSQL driver 复用原 owner,不复制 ORM 引擎、不通过 Rust fallback 执行。 -- 根 `database::Session` 持有本次 Settings/pools,根 Scope 排空后在同一 runtime 关闭,支持重复进入;没有给全局 OnceLock 重绑新池。数据库配置仍只来自程序旁 `config/setting.json`。本切片只支持普通非租户 Model,真实 tenant 配置硬拒绝,不回落平台数据库。 -- 顺序调用/handler 继承隐藏事务 context,Task/并发边界 detached;嵌套 transaction 共享 owner,不引入 savepoint。CMD 顺序为输入解码→开启事务→App→输出编码→commit→stdout;数值、业务、数据库或输出编码失败均 rollback,commit 前已初始化的输出有明确 typed drop。清理失败只追加 cause,不覆盖原故障。 -- `runtime-abi`、`runtime-sqlite`、`runtime-postgres` profiles 独立选择实际 driver,canonical C header 中的 DbError/Row/Rows/Related/RowStream ABI 只使用固定持久化边界值,业务字段保持具体类型。非法输出槽在 I/O、pull/next 或 clone 前拒绝。 - -实际验收(未将重复复验相加): - -- 最终双 driver runtime-only archive 重建通过,时间 `2026-10-01 08:56:03 UTC`,晚于最终 ffi/运行时机械修正;日志 `target/closure-llvm-database-archive-final.log`。 -- 最终 `llvm_database_source` **23/23**:19 项自有 SQLite 原生执行、1 项全部 fixture Checker、1 项六目标 object,以及共享 PostgreSQL fixture 的 2 项纯校验。每个原生 probe 为 checked source→LLVM object→实际 archive,warm 1 + 64 次,清空子进程环境,检查精确 stdout/fault 与原分配平衡;覆盖两版迁移、nullable/所有存储 scalar、cursor、ToOne/ToMany、stream full/early-close/cancel、单连接嵌套/顺序事务和 constraint/numeric/encoding rollback。日志 `target/closure-llvm-database-sqlite-final.log`;六目标 object 不等于六 OS 运行。 -- 真实自有 PostgreSQL **3/3 组**(共 19 个逻辑场景,迁移包含两版):CRUD/codec/query/relations/stream/transaction/schema/Seed,以及 encoding 和 uncaught constraint 回滚后重试/读取。日志 `target/closure-llvm-database-postgres-final.log`,运行 271.58 秒;这是依赖升级与最后 MSRV 机械修正前的实际验收,不声称之后又启动服务。仅连接自有 loopback fixture、随机 schema,未接触部署数据库。检查残留 schema 为 0 后停止服务,临时 `config/setting.json` 删除恢复原先不存在状态;PG fixture 移入可恢复目录 `/root/.local/share/Trash/files/dever-llvm-pg-ZQQmWO`,日志保留 `target/closure-llvm-database-postgres-server.log`。 -- 依赖修复后受影响旧应用/async/managed/Result 回归 **62/62**(19 + 21 + 10 + 12),日志 `target/closure-llvm-database-native-regressions.log`;最后 MSRV/ffi 机械修正后重跑 task-group 取消及后代 frame 释放关键用例 **1/1**,日志 `target/closure-llvm-database-async-critical-final.log`。 -- 最终原 runtime 定向回归 **24/24**:async composition 5、ORM migration 7、Seed 3、entry cleanup 3、SQLite runtime 6,日志 `target/closure-llvm-database-runtime-regressions-final.log`。覆盖 deferred constraint commit rollback、pool 未知状态丢弃、全部四种 decoder 的非法 UTF-8 列索引及后续连接替换。 -- 最终 C ABI probe **1/1**,十种 DbError/borrowed Text cause、Related Loaded(null)/Unloaded、非法/错位槽和不消费原 fault 的 rollback 校验通过;日志 `target/closure-llvm-database-c-abi-final.log`。C11 `-Wall -Wextra -Werror` 语法检查通过,日志 `target/closure-llvm-database-c-format-final.log`。 -- base ABI / SQLite / PostgreSQL / 双 driver 四 profile offline locked lib check 通过;core/runtime/CLI libs/bins、bridge lib/本批根 tests 与 cleanup/SQLite runtime tests 的严格 Clippy `-D warnings` 全通过,日志 `target/closure-llvm-database-profile-*.log`、`target/closure-llvm-database-clippy-{product,bridge,tests}-final.log`。本批 LLVM/bridge/database/task/config/driver/根测试相关文件私有 rustfmt check 通过,日志 `target/closure-llvm-database-rustfmt-final.log`;未声称原 `native/orm.rs` 等历史基线的全局格式门通过。工具私有运行,不安装/替换全局命令。 - -真实故障与根因修复:首轮 SQLite 21 项中 stream 用例超时,之后单用例重复暴露。两个 blocking-worker 栈定位到旧 bundled SQLite 3.51.1 的 WAL close/replacement-open VFS 锁反转(global→inode / inode→global),不是 Dever Scope 未清理。已升级既有精确依赖 `deadpool-sqlite` 0.13.0→0.14.0,锁定 `rusqlite` 0.40.2 / `libsqlite3-sys` 0.38.2 / `hashlink` 0.12.2,使用 bundled SQLite 3.53.2;没有改 registry 缓存、私有 SQLite fork、超时阈值或未知连接复用规则。四条 SQLite decoder 适配真实列索引,新增非法 UTF-8 回归。依赖要求作者 workspace 最低 Rust **1.95**(本机实际使用 1.98.0,未单独运行 1.95 toolchain);对应新 MSRV 触发的 let-chain/is_multiple_of/as_chunks 写法仅机械修正,独立复核短路/资源 drain/对齐/偶数长度 invariant 后严格 lint 与上述关键复验通过。临时栈探针和 thread-trace 源已移除,原 `managed-driver.c` 恢复,诊断日志保留。 - -另外纠正了测试 oracle:cursor `next = null` 传作 after 表示重新开始,不表示终点;PostgreSQL constraint 会使当前事务 aborted,不能沿用 SQLite 捕获 constraint 后继续 SQL 的测试预期。现 PostgreSQL 捕获 NotFound 独立验证错误身份,uncaught constraint 则验证整笔回滚和下一次入口读取。没有放宽 checker 或改变既有 driver 事务语义。 - -README/LANGUAGE/IMPLEMENTATION 与 compiler/toolchain/directory/database canonical specs 已同步,数据库 spec 保存锁顺序回归及清理 invariant。未运行全量 workspace、CMS/HTTP 服务、性能/RSS/64–128 MiB、其他 OS 或正式 packs。ToMany 的 998 分批静态路径已复核,实际 fixture 只覆盖少量父键;新 LLVM commit/Session-close 人为失败注入未做,原 Seed deferred-commit 回归不冒充新 ABI 注入。完整 log 配置、API/REST/auth/tenant/component/permission/Upload、Job/Test、external Adapter 与默认 CLI/正式发行仍在后续闭环,本批不重新设计这些已约定合同。父任务保持 `in_progress`,没有 commit 或归档。 - -## 2026-10-01 LLVM API/REST 与可信请求上下文(本切片已完成) - -用户在上一切片验收后批准继续本阶段。范围为已有 API/REST、站点目录映射、可信身份、自动权限、database-only 租户/组件状态、Cookie/Header/Upload 与 log 配置的 LLVM 应用接线;不改语法、权限 key 或 CMS 业务,不提前切换默认 CLI,也不加入 Job/Test/external/正式 packs。 - -最小行为差距:原 native 已生成完整 HTTP 路由与认证/授权链,LLVM 只生成 CMD root 并拒绝这些元数据。compiler 需统一所有 API/CMD/REST/verify/字段绑定执行根的 reachability、typed input/output/failure layouts;runtime 需让已存在的 config/auth/store/tenant/API/log owner 服务 invocation-owned Session,而不是重绑 OnceLock 或实现第二套 HTTP/RBAC/数据库。 - -分工:`llvm_api_core` 只改 core `llvm/**` 与确需复用的 native 纯 helper;`llvm_api_runtime` 只改 runtime 及 bridge ffi/header/features;主线程拥有根 tests、文档、所有串行 Cargo/实际验收。代理按项目 `.codex/agents/trellis-implement.toml` 的可用 `gpt-6-astra/high` 配置运行,因本环境内建角色的 `gpt-6.1-sol` 无法启动,显式上下文加载作为 native injection 的 fallback。双方不回滚彼此或既有修改。 - -实现约束:静态 route descriptor + 具体输入 decoder + compiled typed wrapper;runtime 只复用既有 request/auth/tenant scope、dispatch、envelope/metadata,App 无动态业务 Value。verify 使用固定 Claims/Identity pack/unpack,business failure 按精确已编译身份映射。REST 复用原 Model SQL/codecs;POST/PUT/DELETE 仍输入解码后开始事务,输出编码成功后提交。每 root 只加载一次 Settings;身份/租户/响应 metadata 的并发传播按原 caller 合同,不能把事务 detached 规则泛化到全部隐式 context。部分启动失败和最终清理保留原 fault,根任务与资源在同一 runtime 排空。 - -主要风险为:route-only/mixed root 选择、REST 字段绑定漏执行根、global settings/tenant OnceLock 串 owner、请求间身份或响应 metadata 串用、权限目录/多角色/跨站及禁用组件绕过、跨租户 fallback、Upload affine owner 取消泄漏,以及 shutdown 时先销毁 runtime。首轮先以现有 native 合同做 oracle,之后静态检查与本机 LLVM 实际对象/owned loopback 验收;服务或数据库启动在执行前说明,不使用部署服务。 - -资源准备:改动前已备份 `crates/`、`library/`、Cargo manifest/lock 到 `/tmp/dever-llvm-api-backup-AC4QeV`。磁盘约 430 MiB 不足后续构建,已核对无 Cargo/rustc 进程后仅删除 `target/debug/deps/` 内 9 个旧 bridge 静态 archive(旧 profile/hash);保留最后两版及 `target/native-runtime-abi/debug/libdever_backend_bridge.a`,后者摘要 `994ed15beb13da2856723ce73cc988bd688e931cd7857dfae8baca7111652703` 未改。可重建缓存回收约 0.9 GiB,剩余约 1.3 GiB;未删除源码、数据库、日志、SDK 或配置。 - -本批实现与复用边界: - -- `llvm/api.rs`、`api_context.rs`、`rest.rs` 和 `application_commands.rs` 接通 HTTP/CMD 混合根、REST 字段来源与 owner 过滤、Claims/Identity、Cookie/Header/Upload 及管理命令。仍由 checked HIR 生成具体输入、输出与业务失败布局,API/CMD 不经过 Rust fallback,也不引入动态业务 Value。SQL assignments、tenant fingerprint 与 wire query kind 从既有 owner 共享,原 Rust 后端继续使用同一合同。 -- runtime `application::Session` 统一持有本次配置、生命周期、平台库、tenant manager 和迁移池;Settings 每根加载一次,log-only CMD 也消费配置并在返回前 flush。根任务排空后在同一 runtime 关闭资源;部分迁移与租户池先登记 owner、验证成功才 ready,取消不遗失 pool。 -- `runtime-api` profile 与 canonical C ABI 接通真实 request/auth/store/tenant/upload owner。public 接口允许匿名并保留原 Bearer 校验规则;受保护接口按原配置选择站点/provider,执行可信 verify→租户/组件检查→精确角色权限→输入及业务。权限键仍为 component.domain.site.action,REST 保留 read/create/replace/delete;缺失认证或权限元数据在 lowerer/ABI 拒绝。禁用组件对 Tenant Owner 同样生效,不回落控制库。 -- POST/PUT/DELETE 保持输入解码→事务→App/Model→输出编码→commit→响应 metadata。public/private 错误映射、隐藏 500、跨站/过期会话、多角色撤销、租户物理隔离均沿用原合同。配置只在 `config/setting.json`,无环境变量入口。 - -实际发现并修复的根因: - -- 私有 HTTP 首轮 SIGSEGV 来自调试构建的嵌套 future poll 栈过大,发生在 verify 已成功之后。只在 compiled handler 的共同边界 `Box::pin(self.call(...))`,保留原 auth/tenant/cancel scope;没有扩大线程栈、到处装箱或重写 Identity ABI。 -- borrowed receiver clone 原先保存了新句柄却返回原 SSA 值。现在从真正 clone guard 取值后再释放来源,REST search 复用同一路径;新增 Channel 记录跨 Task 返回的实际回归,覆盖 clone 与原 owner 销毁顺序。 -- REST DELETE 的 `null` 响应原先由两个 guard 同时持有。改成只交给响应 wrapper 的唯一 owner,跨 commit 保留并正确转交。 -- 同时纠正测试 oracle:嵌套输入仍需 payload 对象、owner 不可见行是 404、禁用角色不会由 save 重新启用、max_page_size=4 时必须显式 size、PostgreSQL TLS 使用 disabled 且必须配置 default。没有为测试放宽语言或数据库合同。 -- 原 Rust `rest_model` 的三个编译 fixture 仍对无 settings 的 HIR 生成应用,权限注册为空却调用组件辅助函数,导致 E0425;相关 product 逻辑与本批备份一致。现复用一个本地 fixture,向实际编译阶段补齐 config/setting.json、站点/provider 和名义身份,通过 `check_with_settings` 绑定。原 SQL/owner/字段来源断言保留;没有禁用组件授权或补匿名 fallback。 - -验收证据(不把重复复验累计为不同用例): - -- `target/closure-llvm-api-final-native.log`:API 根 **14/14**,其中 6 项 Checker/六目标 objects/fixture 校验,8 项实际原生执行;HTTP、私有 REST、禁用组件、上传、混合 CMD、无认证 metadata、启动失败、log-only CMD 均检查 warm 1 + 64 次资源平衡。六目标 objects 不代表六 OS 实际运行。 -- `target/closure-llvm-api-postgres-native.log`:真实 PostgreSQL **1/1 组**,复用同一 private REST 场景,执行 3 次根;隔离的控制库与两个租户物理库覆盖可信身份、多角色/跨站权限、租户隔离、创建/更新/删除、字段绑定、owner 行过滤、并发身份、Cookie 与失败回滚。该验收在最后无行为变化的 Clippy 修正前执行,未声称修正后再次启动 PG。 -- `target/closure-llvm-api-upload-final.log`:最后 runtime-only archive 重建后,包含新增上传中途断开的用例 **1/1**,65 次根均确认文件实际开始写入,再断开连接并等待临时文件清零;正常存储与解码失败同时覆盖。 -- 原应用入口 **19/19**(`target/closure-llvm-api-owner-regressions.log`),最终异步 **22/22**、受管值 **10/10**(`target/closure-llvm-api-owner-regressions-final.log`)。首轮后 9 个异步用例在启动 cc/ELF 时遭遇 ENOENT,未进入业务断言;/bin/bash 同期也暂时无法启动。只读确认工具恢复后,22 项全量定向重跑通过,未更改全局工具或掩盖失败记录。 -- 原配置/请求上下文/鉴权/权限/声明 **36/36**,日志 `target/closure-llvm-api-runtime-regressions-final.log`;该日志保留三个旧 REST fixture 的失败。修正 fixture 后,REST **12/12**(含三条实际 Rust AOT 编译)、entry cleanup **3/3**、tenant database **3/3** 均通过,日志 `target/closure-llvm-api-runtime-rest-final.log`。共 54 项定向结果包含各 target 自带的 PostgreSQL fixture 纯校验,不代表这些 target 启动了 PG。 -- 最终双 driver/API archive 下,原 LLVM Model bulk/upsert 与单连接 RowStream 取消 **2/2**、canonical C header 实际链接运行 **1/1** 通过,日志 `target/closure-llvm-api-database-abi-final.log`。验证共享 SQL 及 API profile 没有破坏先前 Model 根和基础 ABI。 -- 最终 archive 重建通过:`target/closure-llvm-api-archive-final.log`;runtime-api base/SQLite/PostgreSQL/双 driver 的四 profile check 见 `target/closure-llvm-api-profiles.log`。本批文件 rustfmt、C11 `-Wall -Wextra -Werror` 与相对源码备份的 whitespace 检查通过,见 `target/closure-llvm-api-{rustfmt,c-header}-final.log`、`target/closure-llvm-api-diff-check.log`;历史 native 源码整体格式差异未全库重排。 -- 最终 core/runtime/CLI/bridge libs、三个 CLI bins、本批 API/async/REST tests 严格 Clippy `-D warnings` 通过,包含原 runtime external feature 的编译检查,见 `target/closure-llvm-api-clippy-final.log`。旧 REST diagnostic 的 `.err().expect()` 改为等价 `expect_err()` 后,9 项非 AOT 合同再验通过(`target/closure-llvm-api-rest-diagnostics-final.log`);三个 AOT 不为此机械测试写法重复构建。新 fixture 块 rustfmt check 通过,保留文件其余历史格式。 - -资源清理:真实 PostgreSQL 验收结束后核对随机库已由共享 fixture 清理、无其他连接,只删除本批创建的 `dever_llvm_llvm_api` 基础库,保留此前 `dever_llvm_llvm_database`;停止自有 loopback PostgreSQL,资产回到 `/root/.local/share/Trash/files/dever-llvm-pg-ZQQmWO`,服务日志在 `target/closure-llvm-api-postgres-server.log`。临时仓库 `config/setting.json` 已移除,恢复原先不存在;诊断用失败 fixture、临时 signal/backtrace/debug 标记已移除,原 C allocation ledger 恢复。源码备份保留。磁盘清理只针对已核实的旧 target archive,可重新构建;未删除源码、业务数据或 SDK。 - -最终复核没有本切片未解决的功能失败。README/LANGUAGE/IMPLEMENTATION 和 compiler/database/toolchain/directory/logging specs 已同步;共享 clone 值、DELETE 单 owner、请求 Future 栈边界、pool 取消归属及配置式 REST fixture 的规则已记录。没有运行全量 workspace、CMS 服务、性能/RSS/64–128 MiB 或其他 OS;新 LLVM commit/Session-close 人为故障注入、完整协议组合和容量仍属于最终验收矩阵,不由重复入口分配平衡代替。 - -父任务继续 `in_progress`,不提交、不归档。下一步按原合同完成 LLVM Job/Test 执行根及持久任务的身份重验、取消/重试/事务资源清理,再接 external Adapter、默认 CLI 和正式发行;不重设计语法或缩减既定外部生态/平台范围。 - -## 2026-10-01 LLVM Job/Test 执行根(本切片已完成) - -用户在 API/REST 切片完成后明确继续。当前边界是把现有持久 Job 与应用 Test 合同接到 LLVM;语法、默认 CLI、external Adapter 和发行工作保持各自原定阶段。复用 checked Job/Payload/Test metadata、case-local Port fake、队列 store/worker、Clock、可信身份和 application Session,不另建任务队列、测试解释器或全局可重绑状态。 - -编译器接通入队、调度、typed Job dispatch、User 每次执行的身份/精确权限重验、System 编译器入口、Job 数据库初始化/租户迁移及 api/worker/all 组合;Test 接通 filename entry、断言、每 case fake/数据库/虚拟时钟与资源清理。所有业务值保持具体类型,序列化仅用于既有持久 payload 和 ABI 边界;失败、取消、重试和 lease fencing 由现有 owner 承担。 - -分工:core implement 负责 `crates/dever-core/src/llvm*` 与必要纯 helper 共享;runtime implement 负责 runtime、bridge ffi/header/features。两者先协调共同 ABI,再分别修改;主线程负责根 tests、文档和串行 Cargo/实际运行,第三方独立复核后再收口。不得回滚彼此或既有用户改动。没有新的产品决策或任务批准等待。 - -改动前源码备份:`/tmp/dever-llvm-job-test-backup-spJueT`(crates、library、Cargo manifest/lock)。磁盘起始约 381 MiB,先核对无编译进程后清理必要的旧可重建产物;不清业务数据库、源码或私有工具。 - -验收:最小静态/六目标 object → 实际 archive + 隔离文件/SQLite → 持久 Job、Test fake/虚拟时钟、重复根/取消/错误清理 → 受影响旧 API/Model/task/Job/Test 合同。真实 PG/自有 worker/HTTP 的运行前说明;不访问部署服务,不用环境变量配置,不默认全量/性能测试。 - -### 实现与根因修复 - -- LLVM `jobs.rs` 接入具体类型 payload、入队/定时、handler 事务、Job-only 与 API/worker/all、租户队列迁移及每次执行的 User 身份/精确权限/组件重验。Session 持有本次 bindings/Clock,复用 store/worker/cron/lease fencing;同步 handler 复用 bounded blocking,异步 handler 复用既有协程。 -- `llvm::emit_test_suite` 复用 case-local `test_program`,单 IR/可执行文件按稳定 index 派发;导出 indexed fault size/render/release。只给已声明的 LLVM 内部符号加 case 前缀,不改字符串和 runtime ABI;不同 fake 的效果、失败类型、数据库与时钟互不串用。普通测试不启动真实 Lib 或服务;无数据库 case 不创建无关 Model。 -- 修复服务配置无条件校验:只有 `service_start` 才检查 Worker/HTTP 启动策略,普通入队 CMD/管理命令无需这些配置。修复无 tenant 配置的普通 Job 被要求 tenant ID:两后端共享 `job::require_components`,由实际部署配置决定是否隔离。 -- 实际 API User 入队首次报 500,根因是 LLVM 复用的 `auth::authorize_permission` 成功后未绑定权限,而原 native 已有 `job::bind_permission`。现在授权成功后由该 runtime owner 绑定精确 key,native 也委托同一实现;拒绝/错误不绑定,不伪造 System 身份。 -- 校正身份测试 oracle:空 subject、篡改物理归属会触发 store 的早期 fail-closed 错误,不是 dispatch-time blocked。现使用格式合法的失效 subject/session、已删除权限、与执行租户不符的 tenant claim 来验证重新授权,保持原存储合同。Job 不允许调用 HTTP/auth getter,fixture 的业务写入只读取 typed payload。 -- 更新原 LLVM 应用测试中过期的“Job 必须拒绝”断言,使用新 Job-only/CMD/服务回归证明支持;沿用原 C allocation ledger(warmup + 64 次),仅修正零次重复时的无符号循环警告。新增 case driver 和 SQLite 检查均在根 `test/`,复用原链接/子进程工具。 - -### 最终证据与边界 - -- 新增 Job/Test target **9/9**:2 个静态/六目标 object 项,7 个显式实际 archive 执行组。覆盖 4 个纯断言/业务失败 case、7 个 Job fake/虚拟时钟/重试/cron/事务 case、2 个同步 blocking/异步 fake case,以及入队 CMD、启动前策略拒绝、schema/payload/policy 阻断、超时子任务排空和回滚。纯用例与重复入口沿用 warmup + 64 次分配平衡,未降低 oracle。日志 `target/closure-llvm-job-suite-static.log`、`target/closure-llvm-job-test-native-final.log`;最终纯 suite 加入业务失败和字符串不被 namespace 改写的断言后,六目标复验见 `target/closure-llvm-job-api-suite-final.log`。 -- 新增 API User Job **2/2**:六目标 object(`target/closure-llvm-job-api-static.log`)及真实自有 loopback/两租户 SQLite。实际验证 api 入队、all 执行、worker-only、精确权限引用、撤权/会话失效/权限删除/账号失效/租户不匹配的 `blocked + identity_rejected + attempt=1`、组件禁用的 `component_disabled`,正常业务记录只落入各自租户库。最后与既有私有 REST(65 次根)共同复验 **2/2**,见 `target/closure-llvm-job-api-suite-final.log`。 -- 原后端 `durable_jobs` 选定 **4/4**:case-local SQLite/Clock/fake、撤权后禁止业务派发、SQLite durable state machine、租户业务/队列同库与仅恢复 tenant scope。日志 `target/closure-llvm-job-original-regression.log`。 -- 受影响 LLVM 应用/异步/受管值 **19 + 22 + 10 全通过**,日志 `target/closure-llvm-job-shared-regression.log`。基础 ABI **4/4**,canonical C header 与实际 archive 链接执行 **1/1**,日志 `target/closure-llvm-job-abi-final.log`。重复执行不重复累计新覆盖。 -- 最终 runtime archive 重建通过(`target/closure-llvm-job-permission-archive.log`);runtime-api base/SQLite/PostgreSQL/双 driver 四 profile offline/locked lib check 全通过(`target/closure-llvm-job-profiles.log`)。core/runtime/CLI libs/bins 与 bridge/lib/本批 tests 严格 Clippy `--no-deps -D warnings` 通过(`target/closure-llvm-job-clippy-product.log`、`target/closure-llvm-job-clippy-bridge.log`)。修改范围私有 rustfmt、C11 `-Wall -Wextra -Werror`、相对源码备份的 whitespace 检查通过(`target/closure-llvm-job-rustfmt.log`、`target/closure-llvm-job-c-driver.log`、`target/closure-llvm-job-diff-check.log`);没有全局安装工具或重排历史 native 源文件。 -- 独立 review 复核了 typed ABI、资源清理、原 backend 鉴权等价性与两次 shared-owner 修复,没有剩余 P1/P2。早期失败日志保留,最终通过证据如上;测试子进程和临时 SQLite 由 fixture 清理,仓库未新增 `config/setting.json`,源码备份保留。README/LANGUAGE/IMPLEMENTATION、相关 specs 和日志已同步。 - -本轮未运行真实 PostgreSQL Job、全量 workspace/CMS、性能/RSS/64–128 MiB 压测或其他 OS 实际运行;四 profile 和六目标 object 不代表这些已验收。默认 CLI 仍使用 Rust 引导后端。下一切片接现有 external Adapter/Worker 的 LLVM 执行链,再完成默认 CLI、正式 packs/全平台发行与最终容量门。父任务保持 `in_progress`,不提交、不归档。 - -## 2026-10-01 LLVM external Adapter/Worker 与内嵌资源(本切片已完成) - -- 本轮从现有 Worker 协议、生态解析和打包实现接入 LLVM;缺口是 LLVM 当前拒绝 external 函数,尚无 typed wire 调用及内嵌资源入口。备份:`/tmp/dever-llvm-external-backup-kI9I74`。 -- Core 负责 checked Adapter 候选、Setting 校验后启动、typed 输入/输出/声明业务错误、资源元数据与应用入口;runtime/bridge 复用现有 component supervisor、external 安全提取和 Scope,补 canonical ABI。原 Rust backend 的活跃调用者同步迁移,不能另写协议、解析器或进程管理器。 -- Worker 与资源归属于一次应用调用,重复进入不能复用已关闭实例或泄漏元数据。启动失败、取消、超时、未声明错误及清理失败保留原来源/故障语义;普通 Test 仍只走 fake。共享资源 hash/dedupe 算法只有一个 owner。 -- 验证覆盖六目标 IR/object、真实自有 fixture Worker 成功/业务错误/畸形响应/启动失败、连续 root 清理、独立可执行程序内嵌 Worker 与受管 launch 资源,并复验原 Worker、资源及受影响 LLVM 入口。主 agent 串行运行定向 Cargo/链接测试;实现 agent 不执行 Cargo,不清理缓存。当前磁盘约 733 MiB,构建前持续核对容量。 -- 本轮不切换默认 CLI 后端,不重做 pip/npm/go resolver,不访问生产服务、不下载语言环境、不增加配置环境变量;最终发行/容量门仍在父任务内。 - -### 实现与复用 - -- 新增 `llvm/external.rs` 和 `llvm::emit_application_with_resources`:复用 checked Port/Adapter、具名 wire codec、声明错误身份、原 native 摘要/资源去重和 runtime 安全提取。选中的 Setting 校验成功后才启动 Worker;缺失字段(包括可空字段)、额外字段、错类型与未声明错误保持来源位置并作为运行故障,不能伪装成可恢复业务错误。 -- `runtime-external` 独立于编译器 SDK。canonical ABI 明确元数据借用、输入复制、Reply 转移和资源清理;无新的协议、生态解析器、进程管理器或宿主环境查找。 -- 将进程级 Worker 注册表/资源缓存迁入 invocation-owned `component::Session`;显式传播到 Task、blocking 与 API。supervisor 属于根 Scope,短命子任务结束不关闭共享 Worker;启动前注册 owner,取消启动或 shutdown 仍由入口继续收尾。根先关闭 Worker,再排空子任务及应用/数据库 owner;保留原故障并附加清理原因。 -- 普通 Test 沿用 case fake 图,不启动真实 Lib;原 Rust backend 同步使用 owned Definition 和同一 Session。源码备份保留,未提交或归档父任务。 - -### 根因修复 - -- 共享 C 分配账本补计 `realpath(NULL)`:glibc 内部 malloc 绕过链接器包装,Rust 随后的 free 会被计数,原计数因此出现 -2/-1。独立探针验证修正前 -1、修正后 0(`target/closure-llvm-external-ledger-probe.log`);未放宽 warmup + 64 根的精确余额断言。临时探针与诊断源码已删除。 -- 原 Worker 生命周期测试暴露新嵌套 Future 的调试栈溢出。没有挂起点的 `task::run_in` 改为同步返回 Task,`component::scope_resources` 直接返回 task-local scope Future,去掉重复状态机;不增加线程栈或 Box,不吞错。最终原测试和共享异步回归均通过。 -- 修正新测试中 CMD 绑定多个/零 App 输出的非法 fixture:Port 仍测多/零输出,App 按既有规则返回单个记录/Bool。未修改语言合同。内嵌资源验收保留每根 SHA 校验,仅将外层进程限时调整到能覆盖 65 根的 120 秒;测试墙钟包含编译/链接/反复校验,不作为性能数据。 - -### 最终证据与边界 - -- 新 LLVM external 共 8 项均已有通过证据。四种 exec/pip/npm/go 内嵌 launch 组在 `target/closure-llvm-external-verified.log` 通过:只迁移可执行程序和 setting.json、删除构建目录、清空继承环境,各跑 65 根。该轮另外一项 CMD fixture 失败已修复,见 `target/closure-llvm-external-typed-final.log`。最后两个无挂起 helper 修正后重建 archive(`target/closure-llvm-external-archive-final.log`),其余 7 项全部复验通过(`target/closure-llvm-external-final.log`);四生态内嵌大组未为等价 helper 修正重复运行。 -- 最终原 Worker 生命周期/资源/入口清理 1+9+3 全通过,含真实启动/关闭取消检查点、短命 Task 调用和原 Rust backend 独立 exec 打包运行(`target/closure-llvm-external-original-final.log`)。 -- 最终共享 application 19、async 22、ABI 4 全通过(`target/closure-llvm-external-shared.log`);fake-only Test、HTTP 请求连续入口、canonical C 实际链接分别 1/1(`target/closure-llvm-external-{fake,http,c-link}-final.log`)。删除旧 external 拒绝断言后的 application 元数据测试 1/1(`target/closure-llvm-external-application-static-final.log`)。 -- 六 runtime profile 的 offline/locked lib check 通过(`target/closure-llvm-external-profile-*.log`);base ABI 保留备份中已存在的 `append_fault_cause` dead_code warning,不声称全 profile 无警告。修改范围 rustfmt、C11 strict syntax、相对备份 whitespace 检查通过(`target/closure-llvm-external-{rustfmt,header,diff-check}-final.log`)。 -- core/runtime/CLI libs/bins、bridge lib/受影响 LLVM tests 与原 Worker/资源/清理 tests、fixture binary 的私有严格 Clippy `--no-deps -D warnings` 全通过(`target/closure-llvm-external-clippy-{product,bridge,tests}-final.log`)。未安装或替换全局工具,未将定向检查称为全仓库质量门。 -- 本批原失败日志保留供追溯,以上述最后证据为准。受管 launch 使用自有合成 fixture,不能代替真实 Python/Node/Go SDK 的正式发行验收;六目标 object 也不等于六 OS/架构实际执行。本轮没有全量 workspace/CMS、真实 PostgreSQL、性能/RSS/64–128 MiB 或其他 OS 验收。 -- 独立 trellis-check 最终确认无剩余 P1/P2;复核了资源账本与 Future 层数修正,结论与上述准确测试范围一致。测试子进程无残留,父任务和用户原有工作区变更保留。 - -下一切片接默认 CLI 的 LLVM 编译/链接与 runtime pack 选择,再完成正式 packs、真实生态/共享发行及最终容量门;父任务保持 `in_progress`。 - -## 2026-10-01 LLVM 私有默认 CLI 与 runtime pack 接入(本切片已完成) - -- 差距:`deverc run/build/test` 仍读取 RUSTC 并生成 Rust;已有 LLVM 只导出 callable application/suite,还缺真实进程入口、pack 选择及编译/链接编排。继续现有父任务,不重新设计语言或 API。 -- 改动 owner:core 的 LLVM 入口/故障呈现与 native artifact 临时目录/cache;CLI 的 run/build/test、runtime pack 验证/选择;已有 LLVM/LLD bridge 只补实际链接所需的封闭选项。复用 checked HIR、测试逐case隔离、现有资源pack与输出create-new规则,不另写协议/进程管理或文件清理实现。 -- 默认应用命令不能调用 Rust/Cargo/cc 或通过环境变量/PATH选择后端;依赖显式准备且校验过的目标 runtime/CRT/library,缺失明确失败,不增加 Rust fallback。私有作者准备工具与产品执行严格区分;签名发行继续复用现有 release v1。 -- 源码核对发现 deverd 只有 artifact IPC,没有受信任编译入口。按既有共享缓存安全合同,本切片完成私有 `deverc` 默认 LLVM 并保留其作者缓存;managed `dever-core` 编译命令明确报告缺少共享编译入口,不能把失败降级成本地/无缓存编译。该部分留在已排定的共享编译/发行切片,不新增隐式旁路或用户环境变量。 -- 备份:`/tmp/dever-llvm-cli-backup-6mojiN`(crates/library/Cargo manifests)。磁盘低至153MiB,已删除逐个确认的旧 first-party rlib/LLVM test binary;所有源码、备份、设置、数据、SDK及当前runtime archive保留。主线程独占所有Cargo/链接验证,agent不运行构建或清缓存。 -- 本切片验证实际离线 CLI check/run/build/test、错误/失败继续、pack缺失/篡改、输出防覆盖/资源清理、cache身份与必要旧调用者;包括plain/Markdown、fake和最小数据库/外部Worker路径。六目标metadata/object与当前Linux实际执行分开记录,不将自有pack fixture声称为正式签名多平台发行。 -- 之后仍需正式packs、真实生态/共享编译发行、跨平台和最终性能容量;不在本次默认跑全量测试、CMS长链路或生产服务,不安装全局命令,不提交。 - -### 实现与根因修复 - -- `deverc` 私有 `compile.rs`/`compile/runtime.rs` 接通 checked HIR→LLVM→object→进程内 LLD。复用 `native::compile_artifact` 的临时目录、缓存完整性和 create-new 发布;旧 Rust 作者回归也委托同一 owner,不留产品 fallback。 -- pack 使用编译器同级 `runtime//manifest.json`,绑定 compiler version/ABI/target 与 base/sqlite/postgres/both。路径、大小、SHA 和 profile 引用均校验;缓存命中也复核选中输入。链接前复制并重验,仅接受显式 CRT object/普通静态 archive,拒绝 symlink、脚本、thin archive。缓存身份含编译器字节、完整 manifest/profile、IR 与资源。 -- `llvm/process_entry.rs` 在 callable application/suite 外生成 C main,复用 typed 故障呈现、原 logger 和资源释放。suite 参数严格检查单个十进制 index,size/run/render/drop 共用同一 index。实际 closed-pipe 探针发现原入口缺 Rust 启动的 SIGPIPE 策略(退出 -13、stderr 空),现在仅进程 main 调用统一 ABI 初始化;callable 根保持宿主策略,实际回归要求 code=1 与源码错误。 -- 新编译模块最初在共享 CLI lib,readelf 发现 launcher/daemon 因此误链接 LLVM。将 compile/pack 收回 binary 私有模块,最终 `dever`/`deverd` 不再有 LLVM/C++ DT_NEEDED,空环境真实入口回归通过。`deverc` 使用自身 `lib/` 的 LLVM;未安装或修改全局命令/服务。 -- debug 大 archive 的 SHA 校验造成每次 CLI 数十秒等待。共享 `sha256_file` 复用已有 ring 流式 SHA-256,测试 pack 删除重复摘要实现;每次完整校验仍保留,既有签名发行测试用独立 sha2 oracle 复验。没有新增密码库、缓存信任豁免或性能达标声称。 -- 首轮 CLI 5/6 通过,Test fixture 的损坏 JSON 在 Package 元数据读取时被拒绝。改用合法项目 JSON + 无法作为数据库打开的目录,验证测试执行只使用生成的临时 SQLite;缺失真实 Worker 仍由 fake 隔离。旧 RUSTC 失败注入用例已迁移为无 pack 的独占编译器,保留全部用例失败汇总和清理断言。 - -### 最终证据与边界 - -- 实际 CLI **7/7**:`target/closure-llvm-cli-execution-final.log`。覆盖无宿主编译器调用、Unicode/异步、typed 与运行故障/来源、build 防覆盖/搬迁、closed stdout、源码/manifest 缓存身份、坏缓存/命中后的 pack 篡改、Markdown CMD、SQLite/fake 逐 case 隔离、失败继续、非法 suite index,以及内嵌 exec Worker 在源码删除后独立运行。真实 Worker 只是协议 fixture,不代替 Python/npm/Go 生态发行。 -- 进程入口 **3/3** 与既有 bridge **5/5**:`target/closure-llvm-cli-entry-link-final.log`,含六目标 object、原简单内核六目标 link、失败后恢复/并发输出保护。当前实际独立应用仅验收 Linux x86_64。 -- canonical C header 与最终 runtime archive 实际链接 **1/1**:`target/closure-llvm-cli-c-abi-pack.log`,含新增进程参数/错误 ABI 与 SIGPIPE 初始化。最终 ABI version 改为复用同一个常量后 archive 再建、此项重验;其余实际 CLI 已在相同语义的 archive 上通过,没有重复计数。 -- artifact cache 新用例 **2/2**,原 Rust cache 编译回归 **1/1**:`target/closure-llvm-cli-cache.log`、`target/closure-llvm-cli-bootstrap-cache.log`。旧 CLI 编译失败汇总 **1/1**;签名版本安装/回滚、空环境多项目 launcher、自有 daemon IPC 各 **1/1**:`target/closure-llvm-cli-{test-failure,release,launcher,daemon}-final.log`。本切片合计 23 项不同定向用例通过。 -- CLI lib/bins/相关 tests/example、core lib、完整 bridge profile/相关 tests 和 cache test 严格 Clippy 均通过:`target/closure-llvm-cli-clippy-{product,core,bridge,cache}.log`。修改范围 rustfmt/C11/whitespace 检查通过;历史 native 文件未整库重排。base ABI 编译仍有此前已有的 `append_fault_cause` unused warning,不声称所有 profile 无警告。 -- 私有作者 pack 已准备于 `target/debug/runtime/linux-x86_64`,复用 root `test/native-runtime-pack.rs`/共享 fixture,日志 `target/closure-llvm-cli-author-pack.log`;重复准备明确拒绝,原 manifest 摘要未变。四 profile 在此夹具中复用完整 archive,不是四套正式裁剪包。最终动态依赖见 `target/closure-llvm-cli-dynamic-dependencies.log`。两套 CMS 仅在空环境做 check,通过并保留原 W001 建议,日志 `target/closure-llvm-cli-cms-check.log`。 -- 清理仅涉及逐个确认的旧可重建 target 产物,源码备份保留;临时 Worker/SQLite/daemon 由 fixture 回收,仓库未增加应用 setting.json。没有运行全量、完整 CMS、真实 PG、其他 OS、体积/性能/RSS/64–128 MiB 压测;没有提交、发布或安装全局工具。 - -父任务仍为 `in_progress`。下一步接可信 `deverd` 编译与正式签名 packs;managed `dever-core` 目前明确拒绝编译,因此此前 Package 的受管完整执行合同也需在该阶段复验,不能用私有旁路把它标为完成。真实生态高级能力、OS sandbox、跨平台发行及最终容量门仍按父计划实施。旧全 CMS mixed-suite fixture 的坏 JSON/历史用例计数未作为本切片通过证据,留在完整 CMS 验收中同步。 - -## 2026-10-02 可信共享编译与签名 pack 引用闭包(本切片完成) - -- 原始差距:managed core 拒绝 run/build/test,deverd 只有不透明 artifact IPC,不能把上传字节当作可信编译结果。本轮复用现有前端、LLVM、签名发行和 CacheStore 补齐了可信编译链路。 -- caller 保留 Package/Lib 准备、完整部署配置、API baseline 及最终程序运行;提交规范逻辑源码、无秘密编译绑定和资源字节。daemon 自行计算身份,只启动已验签 core 的编译 worker,不执行 App/Test/Lib Worker,不接受客户端 IR、cache key 或输出路径。 -- 改动 owner:core source/check/model 及 runtime config 的无秘密编译投影;binary-private compile/worker 与 NativeProgram 接收产物;toolchain service/cache/release 的 IPC、生命周期、版本共享锁及签名 runtime 引用闭包。LLVM 动态依赖仍不得进入 launcher/daemon。 -- 请求、响应、并发和编译时间有界;断连/取消/失败回收 child 与 staging。缓存命中仍验证签名资源,完整请求才可读编译产物,不能通过 artifact digest 读取编译缓存。复用现有 operation/read lease,安装/卸载持久独占锁与编译共享锁互斥。 -- 主线程独占 Cargo/native 验证。采用自有临时 daemon/签名 fixture,恢复受管 Package 最小完整链路;不启动现有服务,不做全量/CMS压测、全局安装、正式签名发布或其他平台执行。 -- 备份:`/tmp/dever-shared-compile-backup-udVyQC`(crates/library/test/Cargo manifests/父任务)。已确认无构建进程,清理旧可重建 `target/native-artifacts` 和 `target/native-runtime/inputs`,空闲由约417MiB恢复至1.1GiB;未删除源码、备份、SDK、当前LLVM archive/pack或数据库。 -- 本切片签名 fixture 证明安装/引用绑定,不把四 profile 共用 debug archive 当作正式裁剪六平台资产,不把受限编译子进程当作完整 OS sandbox。 - -### 实现与边界 - -- `CompilationBindings` 只携带数据库 driver/选择名、Provider verify 方法及 site path/auth;URL、密码、JWT/Cookie 等部署配置不进 daemon。普通配置和远端编译复用同一验证/数据库选择 owner。Test 不携带部署绑定,继续由 caller 逐例检查并执行隔离 SQLite/fake。 -- 规范请求限制为 64 MiB、4096/16 MiB 源码、4096/48 MiB 资源(单个32MiB),拒绝未知字段、重复/非规范编码、目录逃逸及伪摘要。严格 SourceMap/checker 在已验签核心里重建 HIR,缓存身份绑定完整请求及签名 manifest。 -- daemon 同时最多2个编译,180秒总期限;客户端190秒总接收期限。私有 worker 限制 CPU/地址空间/文件大小/FD/core dump,不运行应用或依赖脚本。取消、断连、失败、超时均 wait/reap 并回收 staging;缓存与安装版本租约持续到传输结束。编译缓存独立限制2GiB/4096条/单产物64MiB,artifact 上传及摘要读取不能访问它。 -- 每次请求包括命中缓存都复验签名、native manifest、全部 profile 的 CRT/archive 与 LLVM 库;安装/卸载用持久独占锁、编译用共享锁。worker 只接收自有0700目录中的0600请求,state/cache/socket祖先仍允许其他用户安全遍历。 -- 共享 runtime pack 校验不引用 bridge,LLVM 只由私有 binary 编译模块调用。修正安装锁误用公开权限验证、worker 对公开祖先误要求0700,以及相对 `--root .` 下切换 cwd 后找不到核心程序的问题;核心路径在验签及持锁后转换为绝对路径。 - -### 定向验收 - -- `packages --ignored --skip installed_managed_package_worker_guard --test-threads=1`:4/4,355.62秒。包含签名安装的 Package check/test/run/build/独立运行、两个实际 UID 跨目录复用、错误源码与缓存恢复、未签名 CRT/篡改 pack 命中拒绝,以及实际180秒超时、取消/断连回收与版本锁互斥。日志 `target/closure-shared-compile-managed-final.log`。 -- 最后将测试 daemon 改为 `--root .` 后,Package 完整执行及跨UID两项复验2/2,88.83秒(`closure-shared-compile-relative-root.log`)。Package Worker 锁定归属/本地碰撞父用例1/1,9秒(`closure-shared-compile-package-worker.log`),由它正确调用签名安装里的 child-only helper。 -- 无秘密源码快照 1/1;`shared_toolchain` 16/16(原独立 artifact 跨 UID 项保持默认 ignored,本轮编译跨 UID 已显式执行);私有 `llvm_cli` 含 ignored 7/7。日志分别为 `closure-shared-compile-snapshot.log`、`closure-shared-compile-toolchain.log`、`closure-shared-compile-private.log`。 -- `api_declarations` 16/16、`application_config` 6/6,日志 `target/closure-shared-compile-bindings.log`。上述共51个不同定向用例,不把重复复验或嵌套 helper 计入总数。 -- 双源码 CMS 仅清空环境 `check` 通过,既有W001建议保留;没有启动 CMS/数据库或压测。日志 `closure-shared-compile-cms-dever.log`、`closure-shared-compile-cms-md.log`。 -- CLI lib/bins/相关三个测试 target 与 core/runtime lib 的 Clippy `-D warnings` 均通过;本次独立/已格式化 Rust 文件的 rustfmt check、备份对比 whitespace 检查通过。历史大文件未做无关全局格式化。证据 `closure-shared-compile-clippy.log`、`closure-shared-compile-core-clippy.log`、`closure-shared-compile-rustfmt.log`。 -- `readelf -d` 确认 dever/deverd 不依赖 LLVM/libstdc++;deverc 保留固定 LLVM18依赖及 `$ORIGIN/lib`。证据 `target/closure-shared-compile-dynamic-dependencies.log`,不能只凭本机装有LLVM时能启动得出无依赖结论。 -- 首轮失败记录保留:fixture 配置字段/保留命名空间断言修正、祖先权限修复、跨UID fixture外层目录需0755,以及 child-only ignored helper 不应从仓库根独立运行。最终通过日志覆盖对应问题,未放宽语言或权限合同。 - -父任务保持 `in_progress`。下一步制作正式、可重复、裁剪 profile 的 native/runtime/build packs;六目标正式资产、真实生态高级能力、OS sandbox、跨平台发行以及完整性能/容量门仍未完成。本轮未运行全量、真实PG、全CMS、低内存/性能或其他OS验收,未安装全局服务或发布真实签名版本。 - -## 2026-10-02 原生发行包制作(本切片完成) - -- 实施前只有 `test/native-runtime-pack.rs` 的作者 fixture,四 profile 复用 debug archive;签名安装/运行时验证已存在,缺可重复的制作与签名入口。本轮补 Linux native release 的作者制作工具、四个真实优化 archive 和对应安装/LLVM链接验收。 -- 复用 `toolchain/runtime_pack` 的 manifest/引用/格式/摘要校验、`ReleaseManifest` 与 ring Ed25519;作者工具仅从自己根下 `config/setting.json` 读取显式文件/摘要/签名key路径,输出全新发行目录。禁止私钥进入产物、硬链接导致源文件变化污染产物、隐式联网、环境变量/宿主工具查找或覆盖已有发行目录。 -- 作者侧构建与应用 run/build 分离:共用一个 Cargo target 构建 base/sqlite/postgres/both,独立 feature 组合;发布材料记录实际 archive、编译版本/目标/选项和摘要。测试两次制作字节一致、错误输入无半成品、验签安装后实际编译/运行,并检查 profile 裁剪和应用产物体积。重复打包一致不冒充跨机器源码重建一致。 -- 代码 owner:CLI `toolchain` 制作/签名模块及私有 SDK 作者入口,根 Cargo 的 runtime pack profile/作者构建配置,root test 的定向制作/安装验收。产品编译与签名安装协议保持不变;改动原始 fixture 时必须复用同一个制作 owner。 -- 本轮不发布真实密钥签名版本、不安装全局服务;Python/Node/Go正式pack、OS sandbox、其他宿主实际运行与容量门仍按父任务另行验收。Linux本机构建不能充当六平台完成证据。 -- 修改前备份 `/tmp/dever-native-release-backup-u48cQl`,包含 crates/sdk/test/Cargo manifests/父任务。主线程独占 Cargo、实际构建、清理和运行验证;子代理负责边界内实现及检查。 - -### 实现与实际产物 - -- 新增 `toolchain::packaging::create` 和私有 `sdk/native-release.rs` 作者命令;使用现有 v1 manifest/验签合同,无新依赖和 lock 漂移。配置拒绝未知字段/路径逃逸/符号链接/错误摘要,私钥必须 owner-private,拒绝把相同私钥字节作为 payload。先复制再复核摘要,固定清单顺序并签名,以 Linux `RENAME_NOREPLACE` 发布;失败只清理自有 staging,并发不能覆盖输出。 -- 根 `runtime-pack` profile 保留链接符号,四次离线 locked 构建共用 `target/native-runtime-abi`。均启用 `runtime-api,runtime-external`,按 profile 分别启用 SQLite/PostgreSQL;未启用 `embedded`。作者工具与应用 run/build 分离,不引入产品环境变量、联网或宿主编译器查找。 -- 实际保存于 `target/native-release-inputs/`:base 78,568,584 字节,SQLite 93,357,820,PostgreSQL 99,502,804,both 106,926,902;全部 SHA-256 见 `target/closure-native-release-acceptance.json`。`nm` 检查证实 SQLite/PostgreSQL 驱动只在对应 archive 中出现,未包含 LLVMContextCreate。这些是供链接的库体积,不是应用体积。 -- 作者工具链为 rustc 1.98.0(88d9e12ae,内置 LLVM 22.1.8)/cargo 1.98.0(797e8a9bc);Dever 编译核心使用独立 LLVM 18/LLD,Linux x86_64 输入使用本机 glibc 2.39/GCC 13 CRT。未证明其他 libc/宿主/目标可用或跨机器源码构建一致。 -- 删除旧 `test/native-runtime-pack.rs` 作者入口(上述备份可恢复)。测试共享显式 SDK 输入及 daemon 生命周期,旧私有 pack fixture 保留作回归;没有复制第二套签名/manifest 校验。作者配置、制作与验收用法记录在 `sdk/native-release.md`。 - -### 定向验收 - -- 四个优化 archive 构建全部通过;日志 `target/closure-native-release-{base,sqlite,postgres,both}-build.log`,分别约 2m52s、4m47s、3m40s、3m35s。作者 executable 构建通过,日志 `closure-native-release-maker-build.log`。 -- `cargo test --offline --locked -p dever-cli --test native_release`:默认 5/5,通过重复制作/签名/独立副本、坏输入及 staging 回收、私钥和 symlink 拒绝、已有目录保护和并发单次发布。真实资产用例默认 ignored;日志 `target/closure-native-release-tests.log`。 -- 显式 `native_release acceptance::optimized_profiles_make_reproducible_signed_release_and_run_through_daemon -- --exact --ignored --nocapture`:1/1,97.42 秒。先库调用、再实际作者 CLI 制作,清单和签名字节一致;验签安装后四 profile 的 `check/run/build` 均通过,缓存恰好四条。关闭自有 daemon 并删除源码后,四个程序独立运行通过,SQLite/both 实际创建、计数和删除通过。日志 `target/closure-native-release-acceptance-final.log`,摘要/体积/边界见同前缀 JSON。 -- 该最小 CMD 的程序体积:base 2,088,488 字节,SQLite 5,082,504,PostgreSQL 2,269,832,both 7,592,744。base/postgres 执行异步 sleep,sqlite/both 执行 CRUD,不能直接作为同一业务的四 profile 性能对照;PostgreSQL 配置指向未使用地址,未连接服务,不宣称真实 PG 验收或驱动全部代码都进入最终程序。 -- 验收初轮 fixture 错把单输出 Bool 预期成对象,随后发现 `value/model.dever` 必须声明 `Value`;仅修正这两个测试合同,语言/输出规则未放宽。首次失败日志 `target/closure-native-release-acceptance.log` 保留;最终完整重跑通过。 -- 回归:`llvm_cli` 默认 4/4(3 个历史显式用例保持 ignored),签名版本安装/切换/回滚 1/1;日志 `closure-native-release-llvm-regression.log`、`closure-native-release-signature-regression.log`。连同制作器 5 项及实际发行 1 项,本轮共 11 个不同定向用例通过,不重复计算四 profile 和重复运行。 -- CLI lib/bins、作者 example 及 native_release/llvm_cli/packages/shared_toolchain test targets 的严格 Clippy `-D warnings` 通过,日志 `closure-native-release-clippy-final.log`。初轮暴露测试重复载入 temp 模块及新 Clippy 的定长切片建议,改为复用父级 TemporaryDirectory 和 `as_chunks`,不加 suppress;默认制作测试复验 5/5,日志 `closure-native-release-tests-final.log`。修改范围 rustfmt、备份对比 whitespace 通过,独立审核无确认阻塞。 -- `readelf -d` 复核 dever/deverd/作者制作器均无 LLVM/libstdc++ 依赖;deverc 保留 LLVM18 与 `$ORIGIN/lib`。日志 `target/closure-native-release-dynamic-dependencies.log`。这不证明核心及 LLVM 的其他系统库都已随发行打包,干净机器验收仍未完成。 -- 清理仅使用 Cargo clean 回收已确认的可重建旧 native cache/debug ABI/重复 runtime-pack bridge 输出;当前私有 debug archive 链接、四个优化输入、源码及所有备份保留。测试临时发行目录、密钥、daemon 与 SQLite 由 fixture 回收。收尾磁盘约 1.2 GiB 空闲。 - -父任务保持 `in_progress`。本切片证明 Linux x86_64 原生制作、安装和执行;签名密钥是测试临时身份,核心程序是当前开发构建,没有发布正式版本。Python/Node/Go packs、完整标准库/构建输入、OS sandbox、其他平台发行以及完整性能/容量门仍未完成。本轮未运行全量、真实 PG、CMS 服务、低内存/性能或其他 OS 验收,未安装全局服务或提交。 - -## 2026-10-02 外部生态发行包制作(Linux 定向验收完成) - -- 现有 Registry/Worker 已消费签名 `runtime///manifest.json` 与 `runtime.pack`,缺制作 owner;本轮扩展现有原生作者制作器,按显式文件/摘要生成确定性压缩包及 registry 描述,将 Python/Node/Go 材料统一纳入发行签名。Worker 与作者共用 runtime manifest/闭包验证,不再各写一份字段合同。 -- Python 必须携带标准库与扩展,Node 使用明确发行输入,Go 携带 compile/link/analyzer 与 stdlib importcfg。只在作者准备阶段获取/整理固定输入;产品 run/build 不联网、不读取环境变量或宿主工具。实际脱离源码/输入目录的执行用于证明迁移能力,临时签名不代表公开发行。 -- 已确认 Node 解释器约 118 MiB,超过上一轮共享编译的 32 MiB 单资源、48 MiB 总资源及64 MiB输出限制;本轮在实际编译协议/缓存 owner 修正相互冲突的有界预算,保持不透明 artifact 与可信编译产物隔离、2 GiB 总缓存限制和生命周期校验。避免只让制作器通过、受管 run/build 仍不可用。 -- owner:`toolchain/packaging` 与 Worker/runtime 描述共享校验、registry metadata;共享编译的资源/输出预算;根 test 的三生态签名制作及独立执行验收。语言语法、Provider、API/CMS 业务不变,extras/sdist/npm高级安装/Go sumdb 仍按父计划后续实现。 -- 备份 `/tmp/dever-ecosystem-release-backup-7jv8nj` 包含 crates/sdk/test/Cargo manifests/父任务。实现/审核子代理遵循明确文件边界;主线程独占 Cargo、输入准备和实际验收。 - -### 已落地与验证过程 - -- 继续追踪后确认,旧 LLVM emitter 把每个资源字节编码为三个字符,122,889,056 字节的 Node 会生成约 351.6 MiB 的 IR,不能通过 8 MiB IR 边界。本轮复用 `native::resource_inputs` 摘要去重,把 payload 作为有界二进制附件交给私有 LLVM bridge,在 verify/优化之前填入已声明的常量;IR 仍绑定路径、摘要、长度和执行位,8 MiB IR 限制保留。runtime C ABI 未变,因此不重建上一轮四个优化 archive。 -- 共享编译传输 384 MiB,资源最多 4096 项、单项128 MiB/总256 MiB,可信产物320 MiB;bridge保持对应附件边界。不透明 artifact 上传仍64 MiB,编译与 artifact 缓存分别2 GiB/4096条。canonical编码只排序引用,daemon及worker尽早释放已不需要的请求副本,保留原180/190秒编译与客户端期限。 -- 固定作者输入:python-build-standalone 20260901 CPython3.12.14完整可搬移标准库发行、Node24.15.0官方Linux发行,以及先前保存的Go1.26.3构建fixture。Python/Node下载分别核对GitHub资产摘要和官方SHASUMS;确切SHA及路径保存在 `test/ecosystem-release/prepare.py`,生成材料位于 `target/ecosystem-release-inputs/prepared/`。Go不是独立验证的公开上游pack,临时签名不替代供应链来源证明。 -- 默认 `native_release` 9/9、`external_workers` 6/6;bridge 7/7及LLVM external默认3/3,包括超旧限制的二进制附件实际链接与逐字节核对。共享编译输入/输出配额2/2,canonical无秘密快照1/1。日志前缀 `target/closure-ecosystem-release-`,实际三生态验收仍单独执行,默认ignored不算通过。 -- 实际验收初轮因debug作者准备完整语言材料超过测试夹具190秒而终止,未进入应用编译;日志 `closure-ecosystem-release-acceptance-author-timeout.log`。作者制作步骤独立设为900秒,其他命令及产品编译期限保持不变。 -- 新 fixture 曾遗漏 Port 必须声明 `fails Choice` 的合同,语法/合同检查先后拒绝了缺失body与普通空body;已复用现有Port测试的明确失败Choice声明,并把三生态源码预检查移至制作之前。没有放宽语言合同。失败证据为 `closure-ecosystem-release-acceptance-fixture.log` 与 `closure-ecosystem-release-acceptance-port-contract.log`。 -- 调试版客户端准备完整Python资源另触发一次190秒fixture超时,保留 `closure-ecosystem-release-acceptance-preparation-timeout.log`。只优化压缩依赖后仍慢;对自有客户端3秒CPU采样(297样本)定位约七成开销在未优化sha2软件实现,非共享Worker死锁。诊断后仅终止已确认PID的自有客户端,daemon/项目由fixture回收;证据 `closure-ecosystem-release-preparation-perf.log` 及 `closure-ecosystem-release-acceptance-sha-diagnostic.log`。最终作者构建及显式验收统一使用Cargo命令级 `profile.dev.package.{miniz_oxide,flate2,sha2}.opt-level=3`,不改产品Settings、校验或期限。运行性能/内存仍需另行验收。 -- 仅以 `cargo clean -p dever-tests` 回收确认可重建的旧测试产物约1.0 GiB;保留源码、备份、四个优化archive和本次发行输入。独立审核暂未确认其他阻塞;格式/whitespace及依赖锁不变检查通过。 - -### Go 缓存身份问题 - -- 根因属于跨层合同与覆盖缺口:Go编译器把每次随机stage目录写入调试/源位置,两个相同锁定输入产生不同Worker字节,进而改变Dever编译请求及缓存身份。完整三生态验收第一次跑通全部 `check/run/build` 后,明确得到4条缓存而非3条;日志 `closure-ecosystem-release-acceptance-go-cache.log`,未把它标为通过。 -- 既有Go用例只构建一次并验证移除源码后可运行,不能证明重复构建一致。共享缓存没有误判:不同字节应得到不同身份,因此修正owner为Go `Builder::compile`,SDK/Adapter/依赖共用 `-trimpath` 删除stage前缀,保留逻辑文件名/行号;不按生态绕过哈希或放宽缓存断言。依据为Go官方compile文档的trimpath合同。 -- 将现有真实Go fixture改为在两个新stage重复准备并比较全部资源身份,再执行无源码Worker;定向1/1通过(10.10秒),日志 `closure-ecosystem-release-go-determinism.log`。规范已固定该断言及三生态共享缓存恰好三条要求;最终完整验收已通过,不新增独立构建/缓存实现。 - -### 最终结果与未完成边界 - -- `closure-ecosystem-release-acceptance-final.log`:实际三生态验收1/1通过,573.56秒。签名制作/安装、runtime锁定、三个受管 `check/run/build`、共享缓存恰好三条均通过;停止自有daemon,删除整个机器安装与源码目录后,三程序在只有显式Linux OS ABI库及私有proc的chroot中执行成功,没有系统Python/Node/Go或包管理器。Python另核对全部导入路径在内嵌目录,并执行SQLite、SSL、压缩等标准库能力。 -- 产物证据 `target/closure-ecosystem-release-acceptance.json`:pip/npm/go压缩pack分别41,778,610 / 43,996,315 / 54,494,714字节;测试程序分别94,754,600 / 125,792,424 / 6,960,616字节,完整SHA-256见JSON。Python/Node程序包含解释器与标准库,Go只内嵌编译后的Worker。这是三个探针程序的大小,不代表CMS大小或吞吐/RSS性能。 -- 本轮共30个不同定向用例通过:bridge/LLVM资源10、默认制作/Worker合同15、共享编译配额2、canonical快照1、真实Go重复构建1、完整三生态1。最终默认复验日志 `closure-ecosystem-release-contracts-final.log`;历史ignored未运行项不计入通过。 -- CLI/core/bridge严格Clippy均通过,日志 `closure-ecosystem-release-{clippy-final,core-clippy,bridge-clippy}.log`;修改范围rustfmt、备份对比whitespace、依赖清单/锁不变检查通过。独立审核复核Go统一入口与真实日志,未发现确认阻塞。 -- 最终 `readelf` 日志 `closure-ecosystem-release-dynamic-dependencies-final.log`:launcher/daemon/maker没有LLVM或libstdc++依赖,deverc仍依赖LLVM18及现有系统库。自有进程、签名密钥、安装/项目目录与mount已随fixture回收;磁盘恢复约1.9 GiB,备份和输入保留。 - -父任务仍为 `in_progress`。本切片完成三生态pack制作与Linux无系统语言环境的执行链路;临时签名不等于公开发行,Go输入的正式来源闭环、完整核心动态依赖交付、其他平台资产/执行、sdist/extras/npm高级安装/Go sumdb、OS sandbox及最终性能/低内存门仍未完成。本轮未运行全量、真实PG、CMS服务、第三方包安装、低内存/吞吐或其他OS验收,未安装全局服务或提交。下一步按父任务继续真实生态高级解析/构建能力,之后处理发行平台与容量门。 - -## 2026-10-02 五项剩余收口(实施中) - -用户已明确授权实施高级Lib、OS沙箱、发行/跨平台、最终组合与性能容量五项;沿用本任务,不创建重复任务。源码备份 `/tmp/dever-closure-remaining-backup-EFQlXQ`,保留此前备份和无关删除。主线程串行构建/测试,独立研究与实现遵循不重叠归属。 - -执行依赖:先补不执行第三方代码的精确extras/依赖解析与sumdb;并行建立可复用的Linux隔离启动边界;再接源码包/受控hooks及正式构建输入;之后统一发行验收和质量/性能矩阵。源码包/hook不能靠删掉拒绝分支完成,必须有锁定工具、受控网络/文件/进程及真实包验收。 - -- 研究 `research/ecosystem-closure.md` 明确每生态缺口和锁/Worker隔离合同。Python extras沿用规范化Lib请求身份,不把一个Worker选择的extras泄漏到另一个Worker。主线程负责Worker归档路径与重复wheel去重接线。 -- Linux隔离设计复用显式签名打包的bubblewrap与safe Rust seccomp guard,共享namespace/PID生命周期、路径与固定syscall策略。保持workspace unsafe禁止,不在Tokio线程设置进程级限制,不调用宿主PATH工具,不缺资产裸跑。文件授权由setting.json明确授予,配置内容不发给Worker;未支持的平台必须明确拒绝。非特权用户、真实三生态和后代回收均需执行证据,方案不是完成证据。 -- 最终CMS夹具基线失败于Package元数据读取前的非法JSON。改为合法JSON但不可打开的部署数据库目录,继续证明应用Test使用隔离SQLite;混合用例保留bootstrap,准确要求4项。复用根process owner为所有夹具命令增加180秒期限、文件捕获与空环境,避免输出管道阻塞。`closure-final-cms-project.log` 6/6通过(143.32秒),涵盖双源码check/test/run/build/移除源码后的独立健康入口;服务、PG与性能组合另行验收。 -- Python extras已接解析、精确变体图、同包自激活/回溯、Worker隔离、单归档安装与大小统计。空extra被pep508规范化接受的问题已修;`closure-python-extras-final.log`中external_libs 32/32、`closure-python-extras-install.log`安装7/7与Package11/11通过,显式宿主/发行fixture未被计入。这是extras证据,不包含sdist/native wheel。 -- 沙箱新增`dever-sandbox`共享namespace启动/ELF闭包验证/seccomp helper,发行maker及运行时所有exec/managed启动正在整合;Go工具也改走相同隔离owner,源码只读、build目录独立可写。`closure-sandbox-isolation.log`、`closure-sandbox-missing-library.log`、`closure-sandbox-descendants.log`分别验证文件/网络/进程权限与线程、缺动态库拒绝宿主回退、杀死namespace后无存活后代;`closure-sandbox-component.log`真实协议/生命周期1/1通过(2.28秒,沿用命令级SHA优化)。独立审核指出ioctl参数宽度、DNS输入和动态库回退问题,均已修代码;ioctl高32位实际回归、完整三生态/ABI/发行复验仍待补。 -- `closure-sandbox-unprivileged.log`失败:宿主启用AppArmor非特权user namespace限制,临时签名资产的bwrap不能配置隔离loopback。保留fail-closed;未更改主机sysctl/profile,不能把root下通过说成非root验收通过。GPU/其他平台隔离仍待支持。 -- Go sumdb已接固定官方key、h1、MVS元数据、签名树/收录/一致性与lock v3证据;首轮`closure-sumdb-first.log`6个sumdb测试通过,含官方66321505叶树的离线vector。独立审核的ZIP目录条目、无Go更新锚保留、并发更新锚回退与整锁预算四项正在修复;尚未宣布sumdb收口。新sandbox要求导致的两个exec fixture预期正在同步。 - -本轮后续复验与修正: - -- sumdb四项审查修复和exec准备夹具已完成,`closure-sumdb-final.log` **45/45**通过(1项作者联网准备默认忽略)。真实官方`github.com/google/uuid@1.6.0`及sumdb证明已由显式作者入口获取、验证并存入`target/go-managed/dependency`,日志`closure-official-go-fixture-prepare.log`;这一步不等于实际Go构建/执行,后者正在接线。npm嵌套依赖/peer环境图继续实施,拟直接更新锁格式,不保留旧格式回退。 -- 沙箱独立安全复核的五项已修并复核闭合:执行缓存写授权、目录替换竞争、native配置快照漏接、宿主loader preload、Go输出符号链接。共享mount使用`openat2`和`command-fds`安全传递FD,不新增项目unsafe。`closure-sandbox-kernel-final.log` **6/6**真实kernel通过(含ioctl截断、FD目录替换、读写/网络/进程/线程与后代终止);`closure-sandbox-config.log` **1/1**;`closure-sandbox-runtime-final.log`协议/生命周期 **1/1**、资源 **8/8**(Rust bootstrap显式fixture1项未运行);`closure-sandbox-clippy.log`严格lint通过。 -- 当前ABI已重建。LLVM首次9项并发验收因磁盘不足出现5项链接失败,保留失败日志`closure-sandbox-llvm-external.log`;以`--test-threads=1`复验 **9/9通过**(774.66秒),日志`closure-sandbox-llvm-external-serial.log`。真实Python/Node在只读沙箱内完成标准库与线程操作,`closure-sandbox-python-node.log` **1/1通过**;runtime external/api/postgres严格lint通过`closure-sandbox-runtime-clippy-final.log`。这些不是三生态签名release与第三方包完整验收。 -- 已按Cargo包范围清理可恢复编译缓存,保留源码、备份、输入、报告以及`target/native-runtime/runtime-sandbox.a`当前归档;没有清理其他项目。所有大型LLVM夹具后续串行执行,避免低磁盘下并发链接。 -- 官方`google/uuid@1.6.0`已完成真实沙箱内Go编译两次、资源身份相同及移走适配源码后协议执行,`closure-sandbox-official-go-worker.log` **1/1通过**(13.52秒)。工具、依赖源码与importcfg只读,输出独立授权;编译与执行均使用共享隔离入口。 -- npm安装图迁移到lock v4(不保留旧格式回退)。首轮`closure-npm-graph-tests.log` 50项通过、1项失败、1项作者准备忽略;失败是手工夹具漏填精确npm环境,已迁移。bundled父来源、同名依赖优先级、循环孤儿删除、安装膨胀预算四项均修复并经独立复核关闭。`closure-npm-graph-final.log` 解析 **56/56**、Worker安装 **7/7**、Package **11/11**通过,另13项显式环境fixture未在此组运行。npm hooks/native仍另行实施,不混计为依赖图完成。 -- 当前沙箱四profile优化archive串行重建中;编译缓存再次仅按`dever-cli/dever-core/dever-runtime`包范围清理896.9MiB,日志`closure-core-dependency-cache-clean.log`。源码、备份、author SDK/生态输入与验收报告保留。 -- 发行实查确认此前仅复制LLVM不足:Linux编译器仍依赖14个非GNU OS ABI动态库,且核心RUNPATH不会向传递依赖继承。正在将author单`llvm`字段改为`core_libraries`完整声明、核心继承RPATH及制作/签名native发行验证共用闭包检查;追加仅声明GNU OS ABI的自有chroot内真实编译验收,不把原有仅独立程序chroot成功替代核心编译证据。 -- 六平台复核:Linux ARM64作者SDK multiarch路径硬编码已修源码,尚无ARM资产/宿主验收;macOS/Windows仍缺原生可执行链接与runtime协议、发行发布、跨用户认证服务及沙箱实现,不能只称“缺机器”。本轮不把六目标对象文件生成说成六平台产品交付。跨平台实际输入及运行宿主当前均不可用,Linux后续实施继续。 - -后续已完成的定向证据: - -- Linux核心动态库闭包已完成:maker和native发行安装/解析共用校验,核心改用可继承RPATH,严格拒绝unsigned lib/hwcaps目录、缺传递库及宿主preload。`closure-core-contracts-final.log` **12/12**,`closure-core-loader-acceptance.log` 最小OS根真实check/build/移除源码运行 **1/1**(18.62秒)。不是正式公开签名或其他平台交付。 -- wheel三项独立审查修复已闭合:候选阶段使用选定wheel的已验证METADATA,统一Python prefix/安装scheme/脚本,准确模拟RUNPATH和扩展祖先RPATH。`closure-wheel-contracts-reviewed.log` external_libs **63/63**、workers **7/7**、native_release **12/12**、packages **11/11**;18项显式fixture未计入。`closure-official-python-native-wheel-reviewed.log` 官方simplejson3.20.1真实扩展、同prefix资源和独立脚本导入、沙箱执行 **1/1**(16.55秒)。sdist/PEP517/npm生命周期仍在实现。 -- 四个sandbox runtime-pack archive已构建,随后sandbox抽出了已有的preload检查供核心闭包复用;最终构建沙箱修改稳定后仍需刷新四个归档。`target/closure-current-compiler/provenance.json`保存当前私有测量编译器、四archive、系统SDK和14库的准确摘要;不是签名发行。 -- 当前LLVM双CMS构建通过,Dever **8,323,880**字节、Markdown **8,326,120**字节。`cms-llvm-128-10-02`及`cms-llvm-64-10-02`各自双源码、顺序16篇真实登录/租户/CRUD/发布均通过且无OOM,RSS峰值28.20–28.33MiB、cgroup峰值23.48–23.91MiB、启动44.6–51.9ms。顺序发布约53.6–55.6篇/秒是完整登录及发布链基线,不是并发饱和QPS或p99。 -- 发现runtime/http/live性能构建器仍调用旧Rust backend;已迁到公开LLVM项目/CMD入口并移除无其他调用方的native_fixture_builder。每组构建一个多CMD应用,报告明确共享产物和生产默认调度,拒绝旧manifest充当当前证据。5项运行器定向合同已通过,真实协议测量尚未完成。 - -最终矩阵继续: - -- `profiles-llvm-10-02/profile-report.json`四profile同CMD实际大小base **2,083,880**、SQLite **4,139,976**、PostgreSQL **2,265,224**、both **4,238,568**字节;无数据库连接。`protocols-llvm-10-02`已通过公开LLVM构建runtime/http/live,各组共享多CMD产物,三个Rust参考由当前源码runtime-pack优化构建。 -- `memory-llvm-64-10-02`五种空闲/挂起服务和`async-llvm-64-10-02`六种任务/Channel/取消路径完成,均无OOM。`http-llvm-{64,128}-10-02`共24组2秒HTTP/HTTPS测量无请求错误或OOM;目标5000req/s下实际约4889–4980req/s,p99约0.7–3.2ms,少量负载端未派发请求保留在dropped,不能称持续饱和上限。新server owner统一检查OOM,HTTP warmup/measurement复用请求错误与成功计数门;runner合同 **47/47**通过,`closure-performance-runner-contracts.log`。 -- 当前CMS LLVM/PG验收 **1/1**(56.31秒),`closure-postgres-cms-configured.log`:Owner及非Owner多角色、跨站同名角色、原会话即时撤权、两个物理租户库与同slug数据隔离通过。原始首次fixture失败是根Settings缺default,不是产品失败;仅补临时合法default后重跑。专属PG16实例只监听owned 51183端口,结束已删除本轮两基准库、停止并移回原fixture位置,root config恢复原先不存在。测试内部创建的control/tenant库均由共享fixture清理,无其他库被删除。 -- LLVM API首轮17项中16通过,上传取消fixture失败:4KiB正文在头部独立TCP frame时不足以推动16KiB分块,等待写盘不成立。改夹具发送32KiB(声明64KiB,仍不完整),保留真实断连、temp文件与affine owner零残留断言;`closure-upload-cancellation-llvm-final.log` exact **1/1**(65轮生命周期),无运行时限制改动。组合证据覆盖17项,含真实PG权限/事务与排队Job重新鉴权;另9项Job suite单独继续,未因前target失败误记通过。 -- 共享build Stage与signed rootfs边界迁移后,官方Go UUID双构建/移源执行 **1/1**(13.58秒),`closure-shared-build-go-exact.log`。`closure-shared-build-go-regression.log`最初过滤名错误只运行0项,不计通过。独立只读复核固定RO/usr、network=false、普通Worker权限不变、kill/wait与工具依赖闭包,无确认阻塞;实际PEP517/npm工具执行仍待验证。 -- 作者工具叶准备 `test/ecosystem-release/build_inputs.py` 复用已验SHA的Python/Node提取owner,固定GNU工具/sysroot与同版本headers/npm;明确记录两份linker script的受控前缀转换,来源仅用于私有作者fixture,未冒充官方发行。源码包/receipt锁v5正在接线。 -- 又清理已保存archive对应的bridge optimized缓存622MiB、已完CLI验证缓存548.4MiB,并删除四profile manifest已不引用的旧191,253,848字节debug/runtime.a(SHA70022249…,可重建);当前四archive、私有compiler、SDK、报告与备份均保留。 -- Job独立LLVM定向 **9/9**(185.22秒),`closure-job-cancellation-llvm-final.log`:fake clock/cron、重试、事务、入参策略、CMD enqueue及超时后子任务回收与回滚通过,没有因之前API target失败漏跑却记通过。PEP517作者签名工具pack准备 **1/1**(26.50秒),`closure-pep517-author-tools-fixed.log`;实际sdist/native构建正在验收。 -- CMS增加显式可选并发读取负载,沿用真实登录cookie、查询与资源采样owner,每次校验完整列表,错误立即停止同组客户端并关闭连接;合同 **11/11**,`closure-cms-load-contracts.log`。`cms-read-llvm-{64,128}-10-02/report.json`双源码共四case,8并发、每组10秒,约 **1210.6–1322.2 QPS**、p99 **11.48–13.59ms**、峰值RSS **30.81–31.04MiB**,请求错误和OOM均零。负载端为Python闭环客户端,服务未绑单核,不能称生产容量上限或单核成绩。 -- HTTP/2单核校准 `http2-scan-llvm-64-10-02`:h2c/TLS、4物理连接×16流、3秒/档、1000/5000/15000目标。六case零请求错误/OOM且断连FD差均0;15000目标下h2c完整成功44741/45000,TLS44349/45000,后者不足99%派发成功门,因此不能直接用15k宣称持续容量,后续稳态降至10k。 -- HTTP/2正式一分钟稳态 `http2-steady-llvm-{64,128}-10-02`:单核、4连接×16流、目标10k,四case实际 **9971.6–9979.2 QPS**、成功/计划 **99.718–99.794%**、p99 **2.912–3.424ms**、峰值RSS **4.88–5.72MiB**,错误/OOM/断连FD差全部0,达到99%门。源码/编译器/产物摘要沿用当前protocols manifest;不是历史20k报告或跨主机生产容量。 -- 100轮恢复首次失败于runner每轮复制同一peer导致磁盘耗尽,保留`closure-http2-llvm-recovery.log`和未完成目录,不计通过。`stage_peer`改为同文件系统硬链接(EXDEV才独占复制),配置/日志仍独立;**48/48**合同通过。仅把确认同字节的本轮重复peer替换为共享硬链接,释放约0.8GiB,日志与报告未删;另清理完成后的Cargo缓存261.5+531.9+128.4MiB,已留存四archive/参考程序/SDK。PEP复验的磁盘失败与后续copytree/xattr真实失败均留日志,不能混记为通过。 -- HTTP/2恢复v2两种传输各100轮 **通过**,19,887完整成功、200次FD回落为0、错误/OOM为0;`closure-http2-llvm-recovery-shared.log`。TCP/WS/SSE单核64/128MiB、32/128连接、各10轮共 **12case通过**,120次断开FD差均0、完整消息及关闭计数一致、错误/OOM为0,`closure-live-llvm-capacity.log`。未运行小时级soak或外部网络故障。 -- PEP隔离hook回归 **1/1通过**(`closure-pep517-metadata-execution.log`),官方simplejson仍因原生扩展未生成失败。成功hook现在沿现有Inputs诊断边界输出有界stdout/stderr,定位到作者linker脚本将已有`/usr/lib`二次变成`/usr/usr/lib`;已修token改写且 **2/2**回归通过,已更新两生态工具叶摘要,等待重制pack及真实原生验收。只读xattr与资产执行位共享owner经独立定向复核关闭,实际C syscall probe已重建,kernel复验待运行。 -- 修正工具pack后,官方simplejson3.20.1源码经真实隔离PEP517/GCC构建出 `_speedups.cpython-312-x86_64-linux-gnu.so`,resolver/doctor与同session重放 **1/1通过**(23.55秒),`closure-pep517-native-corrected.log`。作者pack重制1/1通过27.28秒;构建C扩展不是Worker运行证明,后者及npm receipt字段最终冻结后复验仍待完成。Node runtime作者fixture已复用同一已验叶→确定性归档owner生成,`closure-npm-runtime-fixture.log`,未重取上游包或安装系统Node。 -- lock v5新字段接线后,默认四target分别 **68/7/12/11通过**(`closure-source-build-contracts.log`);显式官方源码解析 **1/1**(25秒)及源码构建产物实际沙箱Worker **1/1**(16.58秒)通过,见`closure-pep517-{lock,worker}-final.log`。只读xattr实际kernel probe **1/1**及资产路径/执行位合同 **2/2**通过,见`closure-sandbox-{metadata-kernel,asset-modes}.log`。 -- 共享编译跨真实UID和并发缓存 **2/2通过**(`closure-managed-compilation-final.log`),两个同步客户端相同新源码收敛为同一产物。取消夹具清空环境后cc找不到ld,在开始产品验证前失败;已补作者显式`-B/usr/bin/`,待重编复验。`closure-shared-compile-measurement.json`记录私有debug核心、热OS缓存下冷请求7.318秒、命中5.564秒、并发新请求7.463/7.838秒;包括签名输入校验和IPC,不能当纯编译速度。两份4,239,368字节产物占缓存8,478,736字节,零损坏条目。 -- npm作者pack **1/1通过**(34.68秒),修正主线程fixture缺空`python_wheel_tags`,见`closure-npm-author-tools-fixed.log`。首次真实bufferutil4.0.9构建在node-gyp配置之后、make运行printf时EPERM,`closure-npm-native-first.log`;尚不算native通过。独立审查另外确认可选依赖环失败传播及预构建addon入口完整性两项,正在同一owner修复。 -- npm失败实际strace确认是make的`POSIX_SPAWN_RESETIDS`重设有效身份被拒绝,clone3原有ENOSYS回退正常。共享filter仅在process授权时允许`setres{u,g}id(-1,当前真实身份,-1)`,三个参数按内核低32位比较;其他有效身份、real/saved修改及无process情况仍拒绝。更新C probe两个capability分支 **1/1通过**(0.36秒),`closure-sandbox-spawn-identity.log`;sandbox严格Clippy通过。作者SDK另补glibc的pthread/dl/rt/util链接占位文件,修复真实链接缺`-lpthread`,没有使用宿主工具回退。 -- node-gyp输出的内部硬链接经同一output owner按(dev,ino)核对完整别名数后转为独立字节,输出外别名仍拒绝;实际正反fixture **1/1通过**(38.27秒),`closure-npm-output-alias-final.log`。可选循环失败固定点、native成功/拒绝完整分区与Worker物理裁剪均经独立复核关闭;不是JS层可绕过的dlopen补丁。Stage增加250ms周期的可见scratch目录512MiB/65536项监控,不声称内核磁盘quota。 -- 最新默认四target **70/7/12/11通过**,`closure-native-build-contracts-final.log`。官方bufferutil4.0.9源码构建/锁定/重放 **1/1**(33.60秒),`closure-npm-native-final.log`:新编译Release及内部obj.target别名、现成Linux-x64 prebuild都经runtime-only实际加载;三个Darwin/Windows变体被分类拒绝。实际hooks/optional环/bin与离线remove **1/1**(38.38秒),scratch超限终止与清理 **1/1**(18.81秒),分别见`closure-npm-{hooks,scratch}-final.log`。 -- 官方npm产物离线Worker与worker_threads **1/1通过**(19.78秒),`closure-npm-worker-final.log`;直接调用生成addon的mask/unmask,移除原adapter后从资源恢复,两次prepare身份一致,所有拒绝项都未进入运行目录。不是纯JS fallback。源码收据到最终LLVM程序的集成仍在追加验收,暂不以Worker测试代替公开run/build。 -- base优化archive刷新完成(5分03秒),通过副本+rename替换作者输入,保留历史测量compiler的原hardlink字节及SHA。仅清理已保存的base桥接缓存与debug下7条已完成测试的原生编译缓存(约91MiB,可重建);报告/源码/备份/四profile输入未删除。其余三个archive及最终签名集成继续。 -- 最终v5收据下Python作者pack **1/1**(27.26秒)、源码解析/原生构建 **1/1**(23.97秒)、源码Worker **1/1**(16.24秒)通过,`closure-pep517-{final-author-pack,native-lock-v5-final,source-worker-v5-final}.log`。共享Stage新增budget后官方Go UUID双构建一致、移除源码与Go环境运行 **1/1**(13.81秒),`closure-go-final-build-budget.log`。 -- 共享编译取消/断连/版本租约/真实180秒deadline最终 **1/1通过**(196.27秒),`closure-managed-cancellation-final.log`;原夹具ld路径失败已经关闭,不缩短产品期限。结合先前跨UID及并发缓存两项,三项实际共享编译验收全部覆盖。 -- SQLite及PostgreSQL优化archive分别5分09秒、5分01秒刷新,both继续。CLI严格Clippy首次发现pack返回类型复杂度及npm可折叠分支,已在owner修正、等待复验,不使用allow。源码输出归档在managed Worker展开后重复嵌入的问题已在原prune owner修正,保留声明/exec/投影环境共享使用;独立复核通过,默认及最终签名运行证据继续。 -- 最终签名生态夹具已接入simplejson `_speedups.scanstring`和bufferutil原生mask/unmask,仍保留Python标准库路径、Go、三缓存条目及移源chroot。测试作者签名的是实际源码构建绑定的原runtime pack字节,未篡改收据SHA;依赖与npm输出通过公开artifact owner导入,run/build不重建或联网。此时只完成源码/独立复核,尚不计运行通过。 -- both 最终优化 archive 已完成(3分39秒),四份 SHA/大小均已核对;私有 debug runtime 清单同步刷新,历史测量 compiler 的硬链接输入保持原字节。最终默认合同 `closure-final-consumer-contracts-retry.log` **71/7/12/11通过**(101项);新 npm 收据输出裁剪覆盖 managed、declared、exec 和共享环境,不重复嵌入已展开归档。 -- 严格 CLI Clippy 最终 `closure-final-cli-clippy-clean.log` 通过;前两次暴露测试中三处多余分配和一处多余借用,已直接修复,不加 allow。最终 author example 重新构建通过。保留最终CLI/测试/SDK到 `target/final-cli-snapshot-jiqbfz` 硬链接快照后,仅清理已完成 dev 编译缓存(Cargo报告2.4GiB,实际磁盘可用由1.2增至2.8GiB),恢复原精确可执行路径;源码、日志、历史测量产物、作者输入和备份保留。 -- 最新四profile签名/确定性/受管及移源独立执行 **1/1**(126.43秒),`closure-final-signed-profiles.log`;最小OS核心编译 **1/1**(18.16秒),`closure-final-signed-core.log`。增强三生态最终链首轮 **失败**(752.34秒,`closure-final-signed-native-ecosystems.log`):managed三组均完成,移源后pip进入Worker前EOF,不能记为无宿主通过。 -- 根因复盘(D/E:组合覆盖缺口/隐含假设):旧fixture把chroot当成完整namespace根,Linux会拒绝在其中创建CLONE_NEWUSER;与simplejson本身无直接证据关联。静态C最小探针实际确认chroot→EPERM、真正pivot→成功,显式作者bwrap也成功,日志`closure-{owned-chroot,owned-pivot,prepared-pivot}-ns-probe.log`。没有尝试放宽产品seccomp/namespace限制。一次性C源码已删,证据保留。 -- P0防复发:core与生态验收复用`isolated_os_command`,仅挂载自有OS根、proc与synthetic设备,安装器验收也使用同一入口;已更新toolchain/quality规范。全链复验待重编,不以探针成功替代三生态运行。仓库无对应spec模板副本;遵守用户约束,不提交或归档。 -- 正式Linux bootstrap另有实际产品缺口:原maker没有公开launcher/daemon,二者还依赖宿主libgcc_s,原最小OS core验收不覆盖它们。已开始复用既有签名与机器安装owner补独立bootstrap闭包和首次安装事务,备份`/tmp/dever-bootstrap-backup-YRnulM`。只允许owned系统根验收,不安装/重启本机全局服务。 -- Linux bootstrap实现已接入独立签名的launcher/daemon/私有库、固定systemd资产、原子信任锚与五目标恢复journal。五项独立审查修复闭合:首次失败的服务恢复顺序、最终权限/目录树同步、旧签名模板兼容、绝对可信根、公钥中断恢复;额外覆盖通用旧版本`resolve_core`消费者,保留项目固定旧编译器的能力。`closure-bootstrap-contracts-clean.log`默认 **16/16通过**,`closure-bootstrap-trust-recovery-final.log`root信任/恢复 **2/2通过**,`closure-bootstrap-clippy-clean.log`严格Clippy通过。 -- 最终maker已重编;保存精确bin/test/lib/runtime到`target/bootstrap-cli-snapshot-s5i92v`后清理可重建dev缓存,日志`closure-bootstrap-dev-cache-clean.log`(Cargo报告1.5GiB,物理可用1.1→1.8GiB)。首装实际验收`closure-bootstrap-actual-first.log` **失败**(107.92秒):安装、旧模板升级和篡改包拒绝通过后,独立创建的客户端/daemon PID namespace令SO_PEERCRED的PID不可见。此为新夹具隔离边界不一致,产品认证不放宽;正在让客户端进入同一个owned namespace后复验。三生态pivot复验独立继续。 -- 三生态pivot首轮`closure-final-signed-native-ecosystems-pivot.log` **失败**(526.20秒):Python受管run/build通过,npm在复制已编译程序进入缓存时遇到ENOSPC;尚未进入最终移源阶段。根盘其后仅约1.5GiB空闲。验收临时机器目录改由显式作者`target/native-release-inputs/config/setting.json`选择`/dev/shm`,输入hardlink仍留在原文件系统,产品无改动/无TMPDIR变量。下一轮复用既有performance进程/cgroup owner,以4GiB上限运行自有测试,避免挤占根盘;结果另记。 -- 临时目录合同 **17/17默认通过**(`closure-bootstrap-fixture-contracts-final.log`),严格Clippy和scoped rustfmt通过;产品dever/deverc/deverd摘要与此前冻结版本完全一致。受4GiB预算的bootstrap实际复验`closure-bootstrap-actual-final/` **失败**(184.97秒):隔离根双项目check/run/build及缓存恰好1条通过,阶段切换时wrapper已退出而内部daemon尚持锁。峰值1,875,550,208字节、OOM为0;不是容量失败。夹具已用启动时固定的pidfd停止所属namespace,等待内部退出及同一daemon锁释放后再继续;显式停止失败终止验收,Drop不二次panic。产品认证/锁未修改,独立定向复核通过,实际重跑待完成。 - -- 三生态受4GiB预算的复验 `closure-signed-native-ecosystems-bounded/` **失败**(742.77秒):三种生态的受管check/run/build及3条缓存断言全部通过,移除机器目录和项目源码后,Python独立程序启动Worker收到协议early EOF。预算峰值2,804,113,408字节、OOM/预算触顶均0,磁盘无耗尽;不能把此前chroot修正记为最终通过。正在对真实namespace内层启动做最小探针定位,避免反复整链构建。 -- 最小探针确认上述EOF来自内层bwrap `Can't mount proc ... Operation not permitted`:外层bwrap的只读proc子挂载令内核拒绝嵌套user namespace重建proc。新增root/test下显式静态`native-acceptance-init`,只在已经pivot的owned namespace内覆盖完整private proc后exec;保留外层原能力,内层产品cap-drop/guard不变,不绑定宿主proc。实际Rust init嵌套Python/guard探针 `closure-static-init-nested-probe.log` 通过;所有可见PID的root inode均为owned根的独立探针亦通过。修正rustix信号常量后默认 **17/17** 通过(`closure-final-namespace-contracts.log`),新静态helper实际构建通过。最新fixture Cargo产物hash已改变;误选旧hash的 `closure-bootstrap-actual-private-proc/` 主动中止,不计证据,其5个owned临时目录和cgroup已清理;复验使用当前 `native_release-c3060e189a48ed83`。 - -- Linux首次安装完整验收 `closure-bootstrap-actual-current-init/` **1/1通过**(231.51秒),报告 `target/closure-linux-bootstrap-acceptance.json`:独立信任签名首装、旧签名模板升级、篡改拒绝不损坏原入口、最小OS根双项目check/run/build、单条共享编译缓存、真实UID65533/65534使用和管理拒绝、移除项目/机器目录后的两个独立程序均通过。仅自有image目录的systemd资产,未激活全局服务;4GiB预算峰值1,512,423,424字节,无OOM或预算触顶;所有自有daemon/namespace/cgroup已退出。不是公开发行或其他平台交付。 - -- 三生态最终 `closure-signed-native-ecosystems-current-init/` **1/1通过**(755.81秒),报告 `target/closure-sandbox-ecosystem-release-acceptance.json`:三种签名runtime身份、受管check/run/build、3条编译缓存、离线源码构建收据重放,以及删除全部项目源码/机器目录后的三个最小OS独立程序全部通过。Python实际加载simplejson3.20.1 C扩展,Node加载bufferutil4.0.9 addon;本项Go是标准库协议Worker,官方UUID第三方依赖另有前述真实隔离构建/移源执行证据,不混记。4GiB验收预算峰值3,276,374,016字节,OOM/预算触顶均0;这是编译和临时文件总预算,不是应用RSS。自有进程、namespace、临时机器目录与cgroup已清理。失败日志均保留,没有改动产品sandbox来绕过夹具失败。 - -- 最终静态质量:`closure-final-namespace-clippy.log` CLI lib/bins/native_release及静态test-init **Clippy -D warnings通过**,scoped rustfmt通过。没有运行或冒充全量workspace/完整CI;独立复核确认新init仅属于测试入口,未绑定宿主proc或修改产品sandbox。 -- 结束时将当前已验收bin/test/example、私有lib和四profile runtime以硬链接保存到 `target/closure-verified-tools-ksA2Hn`,清理本轮可重建dev缓存后恢复原路径;当前native_release为 `c3060e189a48ed83`,静态init亦保留。`closure-final-dev-cache-clean.log`记录2822文件/1.8GiB逻辑容量,实际根盘可用约1.1→2.1GiB。首装报告中的launcher/daemon SHA与恢复后完全一致;源码、SDK/作者输入、报告、既有备份和无关项目未清理。 - -## 风险文件/边界 - -- `crates/dever-runtime/**`、`crates/dever-cli/**`:API、数据库和运行时集成,需避免破坏已有协议。 -- `examples/cms/**`:双源码行为一致性,删除旧流程前先保留可恢复验证点。 -- `crates/dever-build/**`、`crates/dever-cli/**`:External Lib 和共享缓存构建边界。 -- `crates/dever-backend-bridge/**`:唯一授权的底层连接 unsafe 边界、foreign buffer 所有权、LLD 串行/恢复与私有输出目录。 -- `config/setting.json` 与测试 fixture:不得引入环境变量秘密或真实凭据。 - -## 验证命令 - -优先使用离线和定向检查,例如: - -```text -cargo test --offline --locked -p dever-tests --test application_testing -cargo test --offline --locked -p dever-tests --test native_cache -cargo test --offline --locked -p dever-cli --test cms_project -deverc check examples/cms/dever -deverc check examples/cms/md -``` - -真实 PostgreSQL、跨平台发行和性能命令必须在条件具备后单独执行并记录结果;不默认运行全量 build 或集成测试。 - -2026-10-04 范围更新:用户另行授权的 Linux x86_64 → ARM64 **应用交叉构建**已在 `linux-arm64-cross-build` 任务完成,最终证据为 `target/arm64-cross/acceptance.json`,包括四profile/缓存/SQLite与完整ARM内核下的三生态Worker及HTTP。此项完成不表示ARM原生编译器、其他平台或公开发行完成,原有延期范围保留。 diff --git a/.trellis/tasks/09-29-language-production-closure/prd.md b/.trellis/tasks/09-29-language-production-closure/prd.md deleted file mode 100644 index 7006d7d..0000000 --- a/.trellis/tasks/09-29-language-production-closure/prd.md +++ /dev/null @@ -1,93 +0,0 @@ -# Dever 语言生产化收口需求 - -## 2026-10-02 当前执行范围 - -用户最新确认先完成Linux的完整CI/长时间压力测试,以及受限AppArmor下非root第三方Worker;其他平台和公开发行暂不推进。下方保留完整产品目标,本次交付不以这些延期项阻塞已授权的Linux工作。 - -- 完整质量门覆盖当前workspace静态检查、默认测试、必要feature组合、Python运行器合同及有明确前提的Linux运行级验收;内部probe、作者准备与不可用条件必须逐项分类,禁止把跳过算通过。 -- 长压测复用现有CMS/HTTP2/连接恢复运行器,每个关键持续场景至少30分钟,覆盖64/128MiB预算、业务响应、OOM、RSS/FD趋势和退出回收;记录实际负载和限制,不把计划时长或短测说成完成。 -- 非root修复必须保留文件/网络/子进程隔离、签名资产和UID边界。不得关闭全局AppArmor限制、引入setuid绕过、依赖环境变量或系统PATH碰巧存在的语言/沙箱程序。若需要安装或加载宿主专用profile,先完成可审查的产品改动及策略,再单独取得操作确认。 -- 用户此次明确授权完整CI和上述长压测;仍只使用自有临时目录、loopback服务/数据库和受限资源,不改动现有业务服务。 - -## 目标 - -把 Dever 从“语言核心和部分生产能力已实现”收口到“可以用来开发、验证、打包并交付大型项目”的状态。收口必须建立在现有实现上,不重复实现已经完成的编译器、运行时、API、Job、Port/Adapter、测试运行器和缓存治理能力。 - -## 背景与已确认事实 - -- Dever 的语言核心、Native 编译链、主要运行时、Model/ORM、Context、API 基础、权限基础、Job、Port/Adapter、应用测试运行器和构建缓存已有定向实现。 -- 生产 API 源码大部分已经实现,但真实 PostgreSQL、真实 HTTP 组合链路和最终任务状态尚未收口。 -- CMS 目前是基础示例和部分能力验证,尚未完成大型项目级双源码验收。 -- External Lib 已有统一协议和 Worker 基础,但 pip/npm/Go 真实生态解析、运行时打包、Package 传递依赖和独立运行尚未完成。 -- 当前发行路径仍主要依赖本地 Rust/Cargo 开发工具链,正式跨平台发行、机器级共享工具链和认证缓存服务尚未完成。 -- 项目配置必须使用 `config/setting.json`;不恢复环境变量配置方案。 -- 当前租户隔离只承诺 database 模式;FFI、front 和表/字段隔离不纳入本轮收口。 - -## 范围 - -### A. 生产 API 与数据库验收 - -1. 完成生产 API 的最终合同检查,清理已被后续实现覆盖的旧任务项。 -2. 使用 `config/setting.json` 提供隔离的真实 PostgreSQL 配置和可重复验收入口。 -3. 验证权限目录、角色、跨站点同名角色、多角色、撤销权限和租户数据库隔离。 -4. 验证请求解析、响应错误映射、Cookie/Header/Context、上传、取消、事务和 HTTP/2 组合行为。 - -### B. 大型 CMS 双源码验收 - -1. 完成 Dever 和 Markdown 两套 CMS 的 Model、业务规则、权限、会话、媒体、发布、审计和 Job。 -2. 两套源码使用同一份行为合同,测试结果和关键输出保持一致。 -3. 验证 `check/test/run/build` 及 `api/worker/all` 配置模式。 -4. 删除或隔离旧 demo-only 流程、旧种子和不符合当前目录约束的代码。 - -### C. External Lib 生态 - -1. 完成统一 external Adapter/Worker 协议的生产错误、取消、超时、capability 和生命周期行为。 -2. 完成 pip、npm、Go Modules 的真实解析、锁定、缓存和运行时准备。 -3. 完成 Python、JavaScript、Go SDK 和 `Adapter -> Lib` 依赖映射。 -4. 完成 Dever Package 的传递 Lib 依赖、run/build 集成和无系统运行时执行。 -5. `run/build` 不隐式联网;所有解析和下载均由显式命令及锁文件驱动。 - -### D. 发行版与共享工具链 - -1. 完成 `deverd` 机器级共享工具链、认证 IPC、并发发布、租约、完整性校验和安全缓存边界。 -2. 支持在无 cargo/rustc 的干净机器上安装、运行和构建公开项目。 -3. 完成 Linux、Windows、macOS 的发行物、安装/升级/卸载边界和平台安全检查。 - -### E. 最终质量验收 - -1. 完成相关定向测试、全量 workspace 测试和真实 PostgreSQL 验收。 -2. 完成 CMS、外部 Lib、发行版的运行级检查。 -3. 完成二进制体积、启动时间、并发、RSS、64/128 MiB 内存压力和缓存占用报告。 -4. 在工具可安装时启用 rustfmt、clippy 和 CI 检查。 - -## 不在本轮范围 - -- FFI。 -- front 产品能力。 -- table/field 租户隔离;只实现 database 模式。 -- 通过环境变量配置 PostgreSQL 或其它运行参数。 -- 重新设计已稳定的语言语法和 API 协议。 - -## 验收标准 - -- 真实 PostgreSQL 下 API、权限、角色、租户和事务链路通过;无配置时不会连接外部数据库。 -- Dever/Markdown CMS 的同一验收矩阵全部通过,并能完成 check、test、run、build。 -- pip/npm/Go Lib 可锁定、准备、打包并通过 Worker 调用;运行不依赖宿主机对应语言环境。 -- 干净机器安装后不需要 cargo/rustc 才能执行公开 Dever 项目。 -- Linux、Windows、macOS 的发行边界和未支持项有可执行检查,不泄漏私有 Rust/Trellis 源码。 -- 全量、定向、性能和安全检查的状态均有明确记录:通过、失败、跳过或阻塞,不以计划代替证据。 - -## 既有任务关系 - -本任务是收口总任务,不复制已有实现,直接复用并收口以下任务: - -- `09-20-production-api` -- `09-20-large-cms-acceptance` -- `09-29-external-libs` 及其三个子任务 -- `09-06-private-compiler-distribution` 与 `09-28-shared-toolchain` -- `09-19-application-testing` -- `09-29-build-cache-storage` - -## 当前无阻塞产品决策 - -本轮按以上范围执行,不再等待新的产品语法或权限设计决定。若平台供应商或真实 PostgreSQL 不可用,只能将对应验收标记为 blocked/skipped,并保留可重复入口,不得伪造通过。 diff --git a/.trellis/tasks/09-29-language-production-closure/research/apparmor-nonroot.md b/.trellis/tasks/09-29-language-production-closure/research/apparmor-nonroot.md deleted file mode 100644 index 13de868..0000000 --- a/.trellis/tasks/09-29-language-production-closure/research/apparmor-nonroot.md +++ /dev/null @@ -1,40 +0,0 @@ -# 受限 AppArmor 非 root Worker - -2026-10-02,只读安全调查;未加载策略、改 sysctl 或安装全局程序。 - -## 已证实根因 - -旧失败 PID 4087980/4087981 的内核 audit:实际首个 exec 是私有 `ld-linux-x86-64`,创建 user namespace 后进入默认 `unprivileged_userns`,拒绝 capability 8/setpcap 与 12/net_admin,对应 `RTM_NEWADDR: Operation not permitted`。当前 `dever-sandbox/src/lib.rs` 把 bwrap 当 loader 参数,给 bwrap 路径添加 attachment 不会生效。 - -宿主 `apparmor_restrict_unprivileged_userns=1`、`apparmor_restrict_unprivileged_unconfined=0`,没有 Dever/bwrap profile;parser 4.0.1、ABI 4.0 可用。这些只证明环境条件,尚未证明专用 profile 兼容或非 root 验收通过。 - -## 最小实现 - -1. 签名 bwrap 采用静态 ELF(无 PT_INTERP/DT_NEEDED),直接 exec;内部 guard/语言继续使用私有 loader/libs。避免给动态 loader 授予 userns,也防止宿主 preload 先于可信入口运行。 -2. 受限机器 helper 固定 `/opt/dever/sandbox//bwrap`,复用现有发行签名安装 owner。整条目录链 root-owned,不可组/其他用户写,无符号链接。普通 0755,不加 setuid/filecaps。独立应用只选择与嵌入签名资产摘要相同者,旧版本并存,无 PATH/env/系统 bwrap 回退。 -3. 专用 AppArmor ABI 4.0 profile 复用上游 bwrap 的 namespace 设置与 exec 子程序 deny-capabilities 堆叠,attachment 只覆盖受信目录。禁止简化为宽泛 unconfined+userns。现有 FD pin、只读挂载、grant、seccomp、后代回收保留。 -4. 作者机缺 libcap.a,需制作固定来源静态 bwrap 资产;不能要求客户机安装编译依赖。规则文件可打包/离线验证,宿主加载须管理员明确确认。 - -## 验收 - -### 安全复核补充:专用 profile 的宿主前提 - -本机 `apparmor_restrict_unprivileged_unconfined=0` 是部署阻塞:Linux 对当前 unconfined 源直接允许显式 change_profile/change_onexec,目标的路径 attachment 不能拒绝这次进入。攻击程序可直接进入允许 capability/userns 的父 profile,尚未执行下一次 exec 时不会叠加 deny-capabilities 子 profile。不能加载当前规则后再补救,也不能仅在目标规则加 deny change_profile。 - -Ubuntu 官方要求管理员启用 `kernel.apparmor_restrict_unprivileged_unconfined=1`。产品非 root 受限启动必须只读检查此前提,实际 `/` 安装在发布 `/etc/apparmor.d` 文件前也必须检查(系统 reload 可能自动加载)。离线镜像可制作,但不是宿主验收。产品不自行改全局设置;主代理完成可审查代码后单独请求临时加强保护及加载新规则的验证授权,其他CI继续。回滚时先卸载本轮 profile,再恢复原严格项,避免留下可进入的宽松窗口。 - -依据:Linux `security/apparmor/domain.c` 的 `change_profile_perms`、`profile_onexec`;https://discourse.ubuntu.com/t/understanding-apparmor-user-namespace-restriction/58007 的 profile changes 节。此结论替代“只要静态 helper+专用规则就足够”的初始假设。 - -- 限制仍为 1 的非零 UID 运行真实三生态 Worker;audit 不再进入默认 unprivileged_userns。 -- 源码/编译服务移除后独立程序仍可运行,只需匹配的受信 helper/profile 和系统 ABI。 -- 默认拒绝未授权文件/网络/fork,声明 grant 各自生效;禁止 namespace/ptrace/capability;取消/超时不留后代。 -- NNP 堆叠及直接 aa-exec 进入规则不能把 capability 带入任意程序。此项必须真实加载后验证,不能凭上游 profile 推断。 -- 缺 helper/hash 错/可写祖先/symlink/profile 缺失失败关闭;多 UID/多版本互不污染;安装恢复保留既有版本。 - -## 上游依据 - -- https://discourse.ubuntu.com/t/understanding-apparmor-user-namespace-restriction/58007 -- https://raw.githubusercontent.com/containers/bubblewrap/main/meson.build -- https://gitlab.com/apparmor/apparmor/-/raw/apparmor-4.0/profiles/apparmor/profiles/extras/bwrap-userns-restrict - -文件 owners:`dever-sandbox/src/assets.rs` 与 `lib.rs`;CLI `toolchain/packaging/sandbox.rs` 与 `bootstrap{,/transaction,/service}.rs`;SDK 作者输入说明;根 `test/dever-sandbox-tests`、`native_release`。不新增自写 namespace helper、通用代理或新签名协议。 diff --git a/.trellis/tasks/09-29-language-production-closure/research/ecosystem-closure.md b/.trellis/tasks/09-29-language-production-closure/research/ecosystem-closure.md deleted file mode 100644 index d1a1b48..0000000 --- a/.trellis/tasks/09-29-language-production-closure/research/ecosystem-closure.md +++ /dev/null @@ -1,125 +0,0 @@ -# Research: External ecosystem closure - -- Query: Identify remaining pip/npm/Go implementation owners, contract changes, reusable paths, and independently executable slices. -- Scope: mixed; read-only source and primary protocol documentation; no Cargo, package installation or service tests. -- Date: 2026-10-02 -- Task: parent explicitly supplied this task directory; `task.py current --source` returned none in the child session. No task pointer changed. - -## Findings - -### Existing implementation is substantial - -Signed Python/Node/Go pack authoring, immutable runtime identities, Worker preparation, Go compilation, shared compilation and no-host-language Linux standard-library execution already exist. Latest acceptance is recorded in implement.md:660. These are not new implementation gaps. - -| Owner | Current behavior and relevant source | -| --- | --- | -| `crates/dever-cli/src/libs.rs` | `LibSpec` at 118, canonical lock v2 at 198/244, independent Worker resolution at 487, graph doctor at 1343, explicit commands at 1461. | -| `crates/dever-cli/src/libs/registry.rs` | Bounded official transport at 98; Python/npm solver at 357–628; archive locking at 725; Go MVS at 773; extraction at 1155. | -| `crates/dever-cli/src/workers.rs` | Dependency closure at 460; Python installation at 529; npm installation at 567; shared resource Tree at 620. | -| `crates/dever-cli/src/workers/runtime.rs` | Shared author/consumer runtime manifest and file-closure validation. Interpreter descriptors cannot currently declare build tools. | -| `crates/dever-cli/src/workers/go_build.rs` | Private owned staging, exact packed tools, transitive package compile/link, cancellation/deadline. `Builder::compile` at 346 includes deterministic trimpath. | -| `crates/dever-cli/src/packages.rs` | Package Lib declarations use the same `LibSpec` parser at 274, 601, 672, 953; no second ecosystem resolver is needed. | -| `crates/dever-core/src/check/ports.rs:333` | External Lib declarations receive shape checks; quoted `name[extra]@version` already fits the syntax. Semantic extras checking belongs in the CLI library contract. | -| `test/dever-cli-tests/external_libs.rs` | Injected `LocalRegistry`, real archive fixtures, exact provider metadata, independent Worker versions, canonical lock, offline remove, real loopback redirect rules. | -| `test/dever-cli-tests/external_workers.rs` | Prepared resource inspection, native Python rejection, npm hook rejection, real optional managed execution. | -| `test/go-managed/analyze/main.go` | Go build tag/source analyzer; deliberately rejects cgo/assembly/native source. Not a general Go build frontend. | - -### First independently executable slice: Python extras - -Actual missing behavior: - -- `LibSpec` has only ecosystem/name/version. Parsing name as `PackageName` rejects brackets (`libs.rs:130`). -- `python_dependencies` evaluates markers with an empty extras list and rejects dependency extras (`registry.rs:920–947`). -- The bounded solver chooses versions by base name; extras need monotone dependency activation, including newly activated extras on already-selected nodes and after backtracking (`registry.rs:445–573`). - -Smallest useful design: - -1. Extend the existing Lib identity/parser with sorted, normalized Python extra names using installed `pep508_rs::ExtraName`. Keep `name` the canonical distribution name. Serialize `pip:name[a,b]@version` through the single `key()` owner. Reject extras on npm/go, malformed or empty brackets and noncanonical serialized identities. -2. Use explicit lock format v3 if selected-extra or dependency-edge semantics change; directly migrate repository callers/fixtures. Do not add a permissive v2 compatibility path. Package source manifests can continue storing the same strings. -3. Reuse `Requirement::evaluate_markers(markers, extras)` and existing PEP440 constraints. Maintain extras per requested distribution inside each search branch; activating an extra must re-evaluate that selected distribution's metadata until stable. Do not mutate sibling branches or silently ignore unknown declared extras. -4. Preserve the exact requested extra variant on Worker roots and dependency edges. A single package version may have base and extra variants sharing the same archive. Do not union all Workers' extras globally: `resolve_workers` intentionally solves each Worker separately before merging. -5. During materialization, deduplicate identical distribution/version/artifact installations; conflicting bytes remain an error. Do not change runtime imports or introduce per-extra runtime modules. - -Important graph caveat: storing only one union-extra `LockedLib` per base package is insufficient. A plain Worker and an extras Worker could then share expanded edges, violating isolation or triggering `inconsistent resolved metadata` in `resolve_workers`. Either retain explicitly requested variants as distinct lock nodes (while selecting one version per base name per Worker) or introduce an explicit resolved-context identity. The former is the smaller extension. Existing cross-context version-selection conflicts must remain explicit, never overwritten. A `foo -> foo[feature]` relationship is not a package version cycle; avoid accidental self-edge rejection from treating expansion as an ordinary recursive package edge. - -Acceptance for this slice: - -- Normalize case/separators, duplicate extras, deterministic ordering; round-trip and malformed non-Python rejection. -- Base request excludes extra-only dependencies; extra request includes them. -- Transitive `a -> b[x]`; two parents request disjoint extras on the same b; late activation on an already-selected b; backtracking selects compatible versions without leaking failed-branch extra state. -- Different Workers requesting plain versus extra variants preserve exact roots/edges and installation closure. -- Package-provided extra declarations, lib remove/update, stale/corrupt lock rejection, offline preparation and one physical wheel installation. -- Focused default targets: external_libs, affected external_workers and packages. No interpreter/network required for resolver tests. - -### Python platform wheels and source distributions are separate slices - -`lock_python` only selects `bdist_wheel` matching signed runtime tags (`registry.rs:630–692`). Worker installation then rejects every `.so/.pyd/.dll/.dylib`, `.data/platlib` and `Root-Is-Purelib: false` (`workers.rs:537–557`). Thus tags alone do not establish native-wheel support. - -Platform-wheel slice should first make signed pack tags describe actual ABI/platform compatibility, check WHEEL identity/tag and RECORD/file integrity rules, install purelib/platlib through the existing bounded Tree and verify native dependencies against a packaged OS ABI baseline. Keep `.pth` executable hooks a distinct policy. Test an actual compatible extension and missing/wrong ELF/ABI dependencies in the no-host execution fixture. Merely allowing filename suffixes is not enough. - -Sdist requires a real PEP517 build frontend: acquire and lock source plus build-system requirements; resolve dynamic `get_requires_for_build_wheel`; run backend in a private no-network build sandbox; validate and publish the generated wheel with build provenance. `run/build` then consume only locked outputs, never call an online package manager. Existing `archive_files` supports zip and gzip tar, with bounded no-link extraction; reuse it for admitted sdists instead of unrestricted host extraction. - -The current pack has an interpreter/stdlib only and deliberately strips development inputs. It does not include setuptools/build backends, Python development headers, C/C++/Rust compiler toolchains, sysroot, or arbitrary external system libraries. Source/native builds need signed explicit build packs and locks, not discovery of host cc/cmake/rustc. A deterministic source-build lock must bind source digest, backend+build dependency closure, target/runtime ABI, selected signed toolchain, explicit args/config and output digest. Add that structured provenance to the same lock owner, not a loose per-project cache flag. - -### npm advanced dependency graph - -`npm_dependencies` rejects nonempty optionalDependencies, peerDependencies, bundledDependencies and bundleDependencies (`registry.rs:959`). Existing search and `doctor` enforce one version per name per Worker; installation is flat `node_modules/` (`workers.rs:608`). - -- First add typed metadata/edge kinds and target eligibility. Optional dependencies override same-named regular entries. Optional peers are constraints when present, not auto-installed dependencies. Record omitted optional nodes with a reproducible reason; checksum/signature/protocol failures must not become optional-success fallback. -- Required peers need resolution in their consumer context. A one-version flat graph supports only the compatible subset. Full npm semantics require package-instance identity and installation path ownership, since independent branches legitimately select incompatible versions. Do not claim complete npm support by promoting every peer/optional edge to an ordinary mandatory edge. -- Bundled dependencies are already bytes in the parent tarball. Validate declared bundled package names, package.json identities and nested closures; bind them to the signed parent artifact rather than downloading or flattening them. Reject undeclared/colliding injected trees. -- Keep one extraction/publication owner. Extend lock graph and installer together, with exact instance references and safe relative installation paths if nested graphs are introduced. - -Minimal units: optional/peer metadata+graph tests; bundled archive installation tests; nested package-instance graph+layout if required; then controlled hooks/native builds. Scope claims must distinguish these. - -### npm hooks/native compilation - -`workers.rs:583` rejects lifecycle scripts and gypfile, and 606 rejects `.node`/binding.gyp. Removing these checks would execute or accept unverified install behavior without a build owner. - -Use the same isolated explicit build-artifact owner as Python. npm lifecycle scripts are shell strings, not safely interchangeable with a simplistic `split_whitespace` Node command. Supporting their existing ecosystem semantics requires a signed known shell/tool set, limited filesystem/network/process capabilities, declared Node/ABI/toolchain/headers, bounded capture and complete descendant cleanup. That internal fixed build environment must not read user PATH/env. If only direct JavaScript entry hooks are supported, name it as a restricted contract rather than general npm lifecycle support. Product user configuration stays in setting.json. - -Lock completed outputs and source/script/tool/target provenance during explicit lib preparation. Runtime preparation must not rerun hooks or consult the network. Test hostile output paths/links, timeout descendants, denied network, native ABI mismatch and cached replay. - -### Go sumdb - -Current `go_mod` fetches unverified .mod bytes, and `resolve_go` fetches ZIP then immediately calls `lock_archive` (`registry.rs:831–839`). Local archive SHA verifies cached bytes later but does not authenticate registry content. Both .mod and ZIP must be sumdb-verified before use/publication. - -Required owner: a bounded `libs/registry` sumdb module behind the existing transport, with fixed official key/origin, explicit injected fixture key/transport for tests, not GOSUMDB/GOPRIVATE environment variables. Existing ring SHA/Ed25519, sha2, base64 are available. Either implement the small checked protocol against upstream vectors or supply a signed verifier with a narrow offline API; do not invoke a host Go command. - -Full contract: Go dirhash h1 for the uncompressed logical module file tree (not raw ZIP SHA), separate go.mod h1; lookup record framing/module/version identity; signed checkpoint note verification; inclusion proofs; consistency against previously trusted checkpoints; bounded authenticated tile cache. Verified lock provenance must include enough checkpoint/record evidence or immutable digest binding for offline install. Do not trust HTTPS lookup text alone. Verify every .mod consulted for MVS, including versions not in the final build graph. Retain raw artifact SHA for Dever cache identity alongside upstream h1. - -Tests: official independent dirhash/tlog/note vectors; ZIP order/recompression same h1; changed file/go.mod rejected before publication; invalid key/signature/wrong record/inclusion/consistency/rollback; uppercase path escaping; offline verified replay; transport limits. Then one real public pure-Go package rebuilt and executed with existing signed pack. Existing cgo/assembly exclusion is a separate documented boundary, not a missing sumdb feature. - -### Order and shared contracts - -1. Python extras is executable without adding runtime/build assets or changing sandbox policy. -2. npm metadata and graph semantics can follow independently; preserve claims about nested versions. -3. Go sumdb is a security-critical independent resolver slice and needs dedicated protocol review. -4. Platform-wheel/native-loader acceptance can precede arbitrary source builds. -5. Finish shared OS-enforced build sandbox and signed tool/header/backend assets, then Python sdist/npm hooks through one owned artifact preparation boundary. -6. Finally extend the actual signed-release acceptance with pinned third-party inputs, offline reconstruction and no-host execution; do not reuse standard-library probes as evidence for third-party installation. - -## External references - -Primary sources inspected on 2026-10-02: - -- https://packaging.python.org/en/latest/specifications/pyproject-toml/ — build-system dependencies and dynamic project metadata. Build requirements belong to preparation, not runtime imports. -- https://peps.python.org/pep-0517/ — backend hooks and isolated build requirements; confirms sdist support is a build frontend, not archive copying. -- https://docs.npmjs.com/cli/v11/configuring-npm/package-json/ — npm v11 optional/peer/bundled contracts. Optional peers are not auto-installed; optionalDependencies override regular same-named entries. -- https://go.dev/ref/mod#authenticating — Go checksum database requires inclusion and consistency verification before accepting lookup data; h1 differs from ZIP archive digest. -- https://pkg.go.dev/golang.org/x/mod/sumdb/tlog — canonical transparent-log API and formats useful for independent conformance vectors. - -## Related specs - -- `.trellis/spec/backend/toolchain-and-library.md`: signed packs, no PATH/env/network fallback, resource budgets, independent Worker lifecycle, immutable cache and focused tests. -- `.trellis/spec/backend/error-handling.md`: explicit errors, no secret-bearing protocol diagnostics, owned cleanup and offline preparation failures. -- `.trellis/spec/backend/directory-structure.md`: core/CLI/runtime ownership and root test layout. -- Parent `prd.md` C/D/E and `design.md` External Lib boundary; `implement.md` records existing evidence and retained gaps. - -## Caveats / Not Found - -- Research only; no product code or acceptance was changed or executed. -- Current optional/peer/sdist policies deliberately fail closed. They are missing supported behaviors, not justification to delete validation. -- No signed general native build-tool pack or controlled package-hook executor found. Interpreter runtime packs do not provide those by implication. -- Full npm multi-version context resolution and Python extras cross-Worker identity need explicit lock semantics. A broad lock bump should cover changed semantics coherently, without speculative unused fields. -- Existing author/CLI tests are canonical reusable fixtures; public network package tests should remain explicit rather than become ordinary unit-test dependencies. diff --git a/.trellis/tasks/09-29-language-production-closure/research/ecosystem-pack-inputs.md b/.trellis/tasks/09-29-language-production-closure/research/ecosystem-pack-inputs.md deleted file mode 100644 index f72b555..0000000 --- a/.trellis/tasks/09-29-language-production-closure/research/ecosystem-pack-inputs.md +++ /dev/null @@ -1,95 +0,0 @@ -# Research: ecosystem pack author inputs and acceptance reuse - -- Query: Identify available real Python/Node/Go inputs, reusable acceptance, relocation limitations, and disk costs for signed ecosystem packs. -- Scope: internal; read-only source/filesystem inspection and executable version queries; no builds, tests, downloads or services. -- Date: 2026-10-02 - -## Findings - -### Available inputs - -| Ecosystem | Explicit input | Observed identity / size | Evidence limit | -|---|---|---|---| -| Python | `/usr/bin/python3.12`, `/usr/lib/python3.12` | Python 3.12.3 (Aug 31 2026 local build), executable 8,020,928 bytes; stdlib directory 54 MiB | Distribution configured for `/usr`, not verified relocatable. | -| Node | `/root/.nvm/versions/node/v24.15.0/bin/node` | v24.15.0, 122,889,056 bytes | Actual runtime, but needs OS dynamic libraries. Whole nvm version tree is 991 MiB and includes unrelated global dependencies. | -| Go | `target/go-managed/runtime.pack` | 55,785,046 compressed bytes, 203,288,938 extracted bytes, 358 regular entries; manifest says go1.26.3 linux/amd64 | Existing private fixed-target build pack, not an independently verified published release. | - -`df -h /data/project/dever` reported 2.0 GiB free during inspection. `target/go-managed/cache` is 50 MiB; preserve it unless the parent explicitly needs reclaimable build caches. Serial acceptance avoids duplicating multiple 194 MiB extracted Go trees and signed release copies concurrently. - -Python `-I -S -B` currently reports `/usr/lib/python312.zip`, `/usr/lib/python3.12`, `/usr/lib/python3.12/lib-dynload` in `sys.path`. `sysconfig` records `--prefix=/usr`, system expat and system SSL. `readelf` shows executable dependencies on libm, libz, libexpat and libc. Extension modules add libssl/libcrypto, sqlite3, ffi, bz2, lzma, crypt, ncurses/tinfo/panel, db/gdbm and readline. Therefore copying only python3.12 is definitively insufficient for independent Python operation. Copying stdlib alone also does not close the extension native dependency set. - -Python directory contains symlinks: `_sysconfigdata__linux_x86_64-linux-gnu.py` is a sibling alias, `sitecustomize.py` points outside to `/etc/python3.12/sitecustomize.py`, and config libpython points outside the directory. Prepared author inputs must be explicit regular files; do not blindly archive this tree or copy developer sitecustomize. No isolated relocation probe was run in this research; relocating executable plus `lib/python3.12` must be verified rather than assumed. A complete stdlib claim also needs extension loading and filesystem path assertions, not just a JSON echo. - -Node `readelf` NEEDED entries are libdl, libstdc++, libm, libgcc_s, libpthread, libc and ld-linux-x86-64. There is no RPATH/RUNPATH entry. No external JavaScript stdlib directory is referenced by the current SDK/runner; only the runtime binary plus SDK/adapter/dependencies is needed for existing fixtures. This is a practical runtime input, but host-copy execution does not prove the declared OS ABI baseline or a clean machine lacking these shared libraries. - -The Go pack already bundles compiler, linker, analyzer, a complete generated stdlib importcfg and archives. Its manifest does not declare a runtime interpreter. A bounded search did not find an active Go installation at `/usr/local/go`, `/usr/bin/go`, `/usr/local/bin/go`, `/root/go` or `/root/.local`; the retained pack suffices for existing build acceptance without locating/rebuilding host Go. - -### Existing owners and tests - -- `crates/dever-cli/src/libs.rs:631`: installed registry provider reads signed `runtime///manifest.json` and adjacent runtime.pack; verifies target, metadata requirements, pack SHA and 256 MiB compressed bound. Reuse this chain rather than introducing a second trusted-runtime loader. -- `crates/dever-cli/src/libs/registry.rs:30`: `InstalledRegistryPack` / `RegistryRuntime` own registry metadata and Python markers/wheel tags. -- `crates/dever-cli/src/workers.rs:58`: existing `dever-worker-runtime-v1` parser; `prepare_worker` at 151 validates lock identity, then archive and inner manifest. Tree bound at 17 is 256 MiB uncompressed and 65,536 files. The retained Go pack fits with about 53 MiB remaining for related generated content. -- `crates/dever-cli/src/workers/go_build.rs:27`: fixed-target build descriptor; line 452 uses environment-cleared absolute tool execution. No new Go launcher needed. -- `test/go-managed/make_pack.go:22`: existing private maker builds source selector, lists all stdlib exports, copies tools and writes sorted tar entries. It is explicitly a private fixture maker, not a signed production author tool; its Go build environment is author-side only. -- `test/dever-cli-tests/external_workers.rs:287`: ignored real Go test consumes retained pack, locked module ZIP, target build tags and go:embed, compiles SDK/runner, removes original adapter source, and runs standalone Worker with cleared environment. Asserts generated resources do not retain build/source trees. Reuse this behavioral coverage for produced Go pack acceptance. -- `test/dever-cli-tests/external_workers.rs:647`: real Node fixture run; 653 Python host fixture run; 660/677 CommonJS/ESM export binding; 691 packaged Python SDK shadow protection. Several intentionally override generated executable with a host path. These prove protocol/binding, not release relocation. -- `test/dever-cli-tests/external_workers.rs:706`: relocates an embedded Node Worker after removing source, lock and raw pack. It still compiles via old explicit Rust author helper. New signed-release acceptance should use current LLVM path rather than duplicate this old harness. -- `test/dever-cli-tests/support/daemon.rs`: shared owned-daemon lifecycle helper from native acceptance; use for signed managed execution rather than another child owner. -- `sdk/python/dever_component.py:8`: SDK imports asyncio/json/math/re/struct/sys/threading/uuid/dataclasses/typing and therefore real Python stdlib availability is required before worker startup. -- `sdk/javascript/dever_component.mjs`: checked wire/protocol implementation to embed; current generated runner in workers.rs uses `node:console` and `node:fs`. - -### Concrete acceptance recommendations - -1. Keep maker consumption deterministic and offline: prepare explicit digest-bound regular-file ecosystem inputs separately, then include registry manifest + inner runtime.pack in the same signed release manifest. Do not discover Python/Node/Go through PATH or add application environment configuration. -2. Reuse retained Go pack immediately for signed-install → lock-bound prepare → worker execution. Preserve target/stdlib contract and assert executable output only; source/compiler archives must not survive in final Go Worker resources. -3. For Node, stage only the explicit binary and existing SDK/fixtures, not the 991 MiB nvm tree. Verify CommonJS and ESM, relocation, empty environment, removed original source/pack and tampered signed artifact rejection. -4. For Python, provide an explicit prepared stdlib tree and reject symlink/escaping input; test `sys.prefix`, `sys.path` and imported modules' `__file__` all point inside the relocated runtime where applicable. Exercise asyncio plus SSL/sqlite/ctypes/compression if advertising their availability. A bare executable test can falsely pass by reading `/usr/lib/python3.12`. -5. Distinguish same-host relocation from a no-system-runtime OS image. Neither `env_clear()` nor deleting the project source hides `/usr/lib/python3.12` or host shared libraries. Do not label same-host copied interpreter checks as clean-machine release acceptance. Do not rename/hide global host directories to simulate this. - -## Related specs - -- `.trellis/spec/backend/index.md`: focused offline compiler checks and root test ownership. -- `.trellis/spec/backend/toolchain-and-library.md:173`: verified installed signed registry runtimes and explicit network boundaries. -- `.trellis/spec/backend/toolchain-and-library.md:175`: one lock-bound pack protocol, Python isolation, Go fixed-target tools, no host language lookup. -- `.trellis/tasks/09-29-language-production-closure/{prd,design}.md`: actual ecological independence remains a required outcome, unavailable evidence must be marked honestly. - -## External references - -No external browsing was performed: this topic inventories local prepared inputs and existing code only. Version numbers above came from explicit binaries or retained manifest, not current upstream release claims. - -## Caveats / Not Found - -- Sub-agent `task.py current --source` returned none because its session pointer is absent; parent explicitly supplied this output task directory, so no task selection was guessed or changed. -- No ready signed Python/Node ecosystem release pack was found in the bounded target/tmp paths inspected. -- No clean-machine container/rootfs, official upstream signature, source-build reproducibility, license aggregation or alternate target runtime was verified here. -- No modifications outside this research file; no Cargo, Go compilation, downloads, tests, service startup or destructive action performed. - -## Follow-up: shared compilation size and LLVM representation - -- Query: Are proposed 128 MiB single / 256 MiB total resources, 384 MiB request and 320 MiB compiled output enough for the real Node binary? -- Date: 2026-10-02. Read-only inspection, no measurements or tests. - -### Definite blocker beyond IPC limits - -`crates/dever-core/src/llvm/external.rs:128` emits every resource byte as a three-character `\\XX` escaped LLVM string. The 122,889,056-byte Node executable becomes 368,667,168 textual bytes (351.6 MiB) before other code. `crates/dever-backend-bridge/src/lib.rs:57` rejects IR larger than 8 MiB. Raising only IPC/cache limits is therefore insufficient. - -`crates/dever-backend-bridge/src/bridge.cpp:59` additionally copies all textual IR into an LLVM MemoryBuffer before parsing; parsing then materializes the actual constant. `worker.rs:75` imposes CPU 120 seconds, address space 2 GiB, file size 1 GiB, 128 FDs and no core dump. Raising the IR cap to accept 256 MiB of escaped resources would admit 768 MiB text plus its C++ copy, decoded request/resources, LLVM objects and object-output copies; this conflicts with the existing 2 GiB worker budget before realistic linking overhead. - -Smallest coherent direction: keep bounded textual code IR and move resource payloads to a separate dense bridge input. IR declares named external byte-array constants; the existing private LLVM bridge defines them with dense ConstantDataArray initializers before verification/emission, or emits one separately linked data object. Reuse `native::resource_inputs` digest deduplication and the exact existing symbols/descriptors. Validate missing/extra resources, symbol shape/length/collision and raw SHA at the existing owner. Do not introduce an independent archive/decoder in application runtime merely to solve compile transport. - -Compression of IPC bytes is not necessary to admit this actual Node case: base64 expands it to 163,852,076 bytes, within proposed 384 MiB. It also would not solve the current LLVM expansion. Compression would add another protocol plus decompression limits; defer unless measured transport costs warrant it after dense resource emission. Existing encoded cap remains an independent cap: 256 MiB resources consume about 341.3 MiB base64, leaving about 42.7 MiB for text/metadata; pathological escaping of the permitted 16 MiB source can exceed that, which should remain an explicit encoded-limit rejection rather than an allocation assumption. - -### Limit consumers and preserved ownership - -- `toolchain/compilation.rs:12,117,136,174,194,292`: encoded cap, resource count/total, single decoded cap, canonical encode/decode and base64 deserializer encoded bound must move together; use named constants to avoid mismatched limits. -- `toolchain/service/compile_request.rs:45`: returned executable receipt needs compiled-specific validation before allocating output. -- `toolchain/service/compile.rs:97,144`: output regular-file metadata and outgoing receipt need the same compiled-specific limit. -- `toolchain/cache.rs:293`: `publish` is trusted compiled-output owner; change only this limit, preserve 2 GiB quota and 4096 entries. -- `toolchain/cache.rs:462`: `inspect_entry` currently checks format/key and file length/hash but no compiled byte bound. Apply compiled receipt/size validation before `restore` reads entire file (`cache.rs:356`), including status and quota inspection paths. -- Keep ordinary `ArtifactReceipt::validate` (cache.rs:86), publish_artifact/artifact/artifact_path, service artifact_put/get and ArtifactPut dispatch at 64 MiB. Do not weaken generic user-upload quota to admit trusted compiled output. - -### Memory/lifecycle cleanup worth doing with caps - -`CompileRequest::new` clones resource bytes; `encode` deep-clones the full request to sort; `decode` re-encodes to verify canonical representation. The daemon retains its upload buffer, decoded request and canonical payload while running the worker; `worker.rs` retains encoded input through lowering, while `request.embedded_resources()` clones decoded bytes again. At the proposed limits these create substantial avoidable overlapping allocations. Drop encoded input after canonical decode, release daemon decoded request before long worker execution once identity/version are retained, and avoid cloning payloads merely to sort serialization. Prefer existing ownership moves/borrowed sorted references; do not add compression as a substitute for fixing live owners. - -Daemon admission allows two active compilations (`service/compile.rs:27`); service transfer reader caps upload at 60 seconds (`service.rs:580`), individual socket read/write timeout is 5 seconds, total compilation including upload/link/download is 180 seconds, and client response/download is 190 seconds. Keep these limits initially and measure real Node acceptance. CPU/address-space limits constrain the child only, not daemon/client copies. Raw object output is also copied by bridge reply ownership, so dense inputs remove a major expansion but do not by themselves prove maximum-limit memory acceptance. diff --git a/.trellis/tasks/09-29-language-production-closure/research/linux-ci-scope.md b/.trellis/tasks/09-29-language-production-closure/research/linux-ci-scope.md deleted file mode 100644 index 02dc3a7..0000000 --- a/.trellis/tasks/09-29-language-production-closure/research/linux-ci-scope.md +++ /dev/null @@ -1,147 +0,0 @@ -# Research: Linux CI 与持续压力验收范围 - -- Query: 根据当前源码设计完整 Linux 质量门;区分默认合同、显式验收、作者准备与内部探针;复用现有长测 runner。 -- Scope: internal;仅调查 `/data/project/dever` Rust 语言仓库,不适用 Go Dever 的 Model/Page/Service 开发流程。 -- Date: 2026-10-02 -- Task: 主代理明确指定本任务;child session 的 `task.py current --source` 返回 none,主代理确认父会话 active=in_progress,因此不创建或切换任务。 - -## Findings - -### 代码与规范入口 - -| 文件 | 用途 | -| --- | --- | -| `Cargo.toml` | 六个 workspace member、Rust 1.95/edition 2024、dev/test 禁用 debug 与 incremental、release/runtime-pack 优化 | -| `crates/*/Cargo.toml`、`test/dever-tests/Cargo.toml` | target 与 feature 真实注册来源;不能按 test 文件名猜测 Cargo target | -| `crates/dever-backend-bridge/build.rs:12` | embedded 需要 `target/backend-sdk/usr/lib/llvm-18` LLD headers/static archives 与系统 LLVM-18 | -| `test/dever-cli-tests/support/llvm_inputs.rs:4` | GNU 作者夹具的 LLVM 18、glibc 2.39、GCC 13 路径与动态依赖闭包 | -| `sdk/native-release.md`、`sdk/native-release.rs` | 四 profile、作者打包工具、签名安装与三生态验收规范 | -| `test/dever-cli-tests/native_release/acceptance.rs:120` | 正式验收读取 `target/native-release-inputs/{base,sqlite,postgres,both}.a` | -| `test/ecosystem-release/{prepare,build_inputs}.py` | 固定摘要的显式作者输入准备;不是默认联网安装器 | -| `test/dever-tests/tests/support/postgres.rs` | `{case}` 数据库模板、唯一 schema/tenant 数据库、失败清理 | -| `test/performance/{run,build,process,live,cms,settings}.py` | 已有构建、隔离进程、cgroup、协议负载、CMS、报告 owners | -| `test/external-sdk/check.py:192` | 三 SDK wire/typed 合同,必须显式给绝对解释器路径 | -| `test/dever-sandbox-tests/isolation.rs` | 正式 sandbox 测试与内部 helper probe;不能全量 `--ignored` | - -相关规范:`.trellis/spec/backend/index.md`、`quality-guidelines.md`、`directory-structure.md`、`error-handling.md`,以及 `toolchain-and-library.md` 的独立 runtime/embedded、作者输入与发行验收合同,`database-guidelines.md` 的隔离数据库合同。任务旧 PRD 仍含跨平台目标与历史“未完成”背景;本轮采用父代理转述的最新授权:完整 Linux CI/长测、AppArmor 非 root Worker;其他 OS 暂缓。历史 TODO 不是本研究的当前实现判断。 - -### 最小复用设计 - -建议只有一个根 `test/` 下的 Linux gate runner 和一个声明式阶段/ignored 用例分类表;`.github/workflows/` 仅负责安装确定工具/启动该 runner/保存日志,不复制测试矩阵。当前 `.github` 不存在。长测继续调用 `test/performance`,不另写负载发生器。每阶段保存命令、开始/结束、退出状态、实际测试数、输入指纹;失败要 fail closed,blocked/skipped 不能计入通过。 - -由 `cargo metadata --offline --locked --no-deps --format-version 1` 获取注册 target/required-features;从编译后的 libtest `--list` / `--ignored --list` 获得精确用例清单。审计分类表与清单的差集:新 ignored 必须明确分类;不能简单 `cargo test --workspace --all-features -- --ignored`。Python `unittest discover` 默认是否递归不能当覆盖证明,应分别指定现有目录。 - -### Cargo 覆盖与顺序 - -workspace 成员:dever-core、dever-runtime、dever-cli、dever-backend-bridge、dever-sandbox、dever-tests。 - -- core 只有 `reference`(启用 runtime crypto);生产 CLI 不应启用它。 -- runtime 默认空;独立能力 `auth-crypto,crypto,wire,external,api,database,sqlite,postgres`。上层依赖的 feature unification 会掩盖最小 feature 编译错误。 -- bridge 默认空;`embedded` 与 `runtime-abi` 必须独立;其余 `runtime-database,runtime-api,runtime-external,runtime-sqlite,runtime-postgres`。`--all-features` 是合同覆盖,不是可交付 archive 的构建方式。 -- dever-tests 默认空;`reference,sqlite,postgres,api,crypto,component,external`,许多 target 有 required-features。 -- CLI:lib,deverc/dever/deverd 三 bin,llvm_cli/native_release/cms_project/shared_toolchain/external_libs/external_workers/packages 七 integration targets,native-release/native-acceptance-init 两个 `test=false` example。 -- sandbox:lib/guard bin/isolation target。bridge 有 16 个显式 integration targets;dever-tests 设置 `autotests=false`,只测 manifest 注册者。`test/runtime_logging.rs`、安全 cases 等路径还可能被其他 target `#[path]` 引入,不能据未注册就判遗漏。 -- Rust peers `network_bench/live_bench/async_bench` 是 dever-tests 自动 example;`--all-targets` 静态门检查它们,真实运行另由 Python 使用。 - -主代理统一 Cargo `-j1 --offline --locked`。建议阶段命令(并非本研究执行结果): - -```sh -cargo fmt --all --check -cargo clippy --offline --locked -j1 --workspace --all-targets -- -D warnings -cargo clippy --offline --locked -j1 --workspace --all-targets --all-features -- -D warnings -cargo test --offline --locked -j1 --workspace -- --test-threads=1 -cargo test --offline --locked -j1 --workspace --all-features -- --test-threads=1 -cargo check --offline --locked -j1 -p dever-runtime --lib --no-default-features -cargo check --offline --locked -j1 -p dever-backend-bridge --lib --no-default-features -cargo check --offline --locked -j1 -p dever-backend-bridge --lib --no-default-features --features embedded -cargo tree --offline --locked -p dever-cli --edges features -``` - -还需按上述 runtime 八个能力逐一 `cargo check -p dever-runtime --lib --no-default-features --features `;bridge 分别 runtime-abi/runtime-database/runtime-api/runtime-external/runtime-sqlite/runtime-postgres 与两驱动组合。不能在这些最小能力命令上加 `--workspace`,否则 workspace feature 合并消除隔离意义。四个正式 profile 构建可以覆盖相应 release 组合,但不能替代 runtime-only 最小能力。生产 CLI 的 feature-tree 检查不得从 all-features 测试解析结果推出 reference 不进入生产。 - -默认与 all-features 会有意重复部分合同,这是覆盖不同配置的证据;无需再对每个 feature 重跑全套功能测试。按 target 串行执行可以降低一次留存的链接产物,仍需记录全 workspace 默认和全特性两个集合的总结果,doctest/lib/bin 不能被 integration-only 循环漏掉。 - -### 作者准备与显式运行 - -SDK 输入必须先检查存在、版本与摘要:Rust>=1.95;LLVM/LLD 18;GNU x86_64 夹具固定 GCC 13/glibc2.39 位置;sandbox bwrap bind-fd/guard/loader 闭包;三生态固定发行与源码构建夹具。`prepare.py` 不负责下载,脚本常量固定 CPython3.12.14、Node24.15.0 下载档及 Go pack 摘要;以源码当前摘要为准。现存文件不证明由当前源码构建,记录 provenance。 - -独立正式 profile 用同一个 `target/native-runtime-abi`: - -```sh -cargo build --offline --locked -j1 -p dever-backend-bridge --lib --profile runtime-pack --no-default-features --features runtime-api,runtime-external --target x86_64-unknown-linux-gnu --target-dir target/native-runtime-abi -``` - -分别增加 `runtime-sqlite`、`runtime-postgres`、两者;每次立即独立保存 archive 到 `target/native-release-inputs/.a` 后再构建下一个。禁止 all-features/embedded、把 both 复制四份、原地 strip 已硬链文件。许多 LLVM helper 另读取 `target/native-runtime-abi/debug/libdever_backend_bridge.a`,需要显式完整 runtime 测试 archive;不能以正式 profile 名义蒙混。构建 author example(sdk/native-release.md 给 miniz_oxide/flate2/sha2 opt-level3 配置)、三 CLI bin、guard、component-fixture、静态 native-acceptance-init,之后再运行验收。 - -正式 ignored 分类: - -1. bridge native LLVM targets 中依赖 runtime archive 的源码执行、资源/异步/错误/HTTP/Job/API/外部 Worker 全部属于显式运行;`llvm_database_source` 与 `llvm_api_source` 含 PostgreSQL 分支,使用包含 runtime-postgres 的 target build。不能用 object-only/非 ignored 结果替代。 -2. PG:`postgres_orm_uses_the_configured_isolated_database`、`postgres_authorization_preserves_site_scoped_roles_and_catalog`、`postgres_cms_http_isolates_two_tenant_databases`,及 LLVM API/database 的 PG ignored。用 `cargo test -p dever-tests --all-features --test postgres_orm --test postgres_api --test authorization_postgres -- --ignored --test-threads=1`,并运行 bridge 对应 targets 的 ignored。只有目标内全为验收用例时才整体 ignored。 -3. `native_release` 的四个真实链路:`acceptance::optimized_profiles_make_reproducible_signed_release_and_run_through_daemon`、`acceptance::signed_core_builds_without_host_compiler_libraries_or_tools`、`acceptance::bootstrap::signed_bootstrap_installs_and_serves_two_projects_without_host_libraries`、`acceptance::ecosystems::signed_ecosystems_build_and_run_without_system_language_installations`(最终模块名请以 libtest --list 确认)。另外 bootstrap trust/crash-recovery ignored 必须执行。 -4. `packages` 的 installed package check/test/run/build/standalone、managed_compile 的成功/不同 UID/取消清理;shared_toolchain 不同 UID;external_workers 的官方 Go/Python wheel/PEP517/npm、直接 Node/Python adapter 和独立运行;external_libs 的 managed lifecycle/越界/alias/PEP517 合同;native_cache 新鲜 CLI ignored。这些是显式验收,不是可忽略的“可选测试”。 -5. sandbox 的 `enforces_files_network_process_and_threads`、`pins_grants_against_directory_replacement`、`rejects_writable_aliases_of_executable_inputs`、`prepared_python_and_node_run_without_host_files_or_process_creation`、`enforces_unprivileged_namespace`、`terminates_detached_descendants_on_kill`、`rejects_missing_dependency_before_host_loader_can_supply_it`、`kernel_rejects_namespace_ptrace_and_truncated_ioctl_requests` 精确执行。C syscall probe 需提前显式编译至 fixture 指定位置。 -6. `performance` 两个 native kernel/large-map 基准、`concurrency` 调度基准是单独 bounded perf;真实长压测在下节,不互相替代。 - -不要直接运行内部 probe:isolation 的 `pinned_grant_probe/restricted_probe/tree_probe/descendant_probe/granted_probe`,packages 的 `installed_managed_package_worker_guard`。它们由父用例在签名/namespace 环境内 `--exact --ignored` 调用。 - -作者 preparation 用例单独列状态,避免无意联网与重复下载:external_libs wheel 官方 fetch、sumdb 官方 proxy fetch、build.rs/native-build-inputs、npm_build.rs/hashed 输入组装与官方源码构建;它们准备下游执行需要的固定锁定输入。已有内容摘要与合同匹配则复用,但真实 registry 解析/官方源码构建若属于本轮 CI 要求,应在显式 author 阶段执行一次,不能因为下游 fixture 已存在就声称该阶段通过。 - -### Python、SDK 与 PostgreSQL 假通过防线 - -```sh -python3 -B -m unittest discover -s test/performance -p 'test_*.py' -v -python3 -B -m unittest discover -s test/ecosystem-release -p 'test_*.py' -v -python3 -B test/external-sdk/check.py --python /absolute/python --node /absolute/node --go /absolute/go -``` - -performance 的 network/live 测试会启动自有 loopback;必须事先准备 release peers,并在根 setting.json 的 `performance.network_peer/live_peer` 配置路径。SDK checker 没给解释器时打印 unavailable 后继续,甚至三个都没给仍可零退出;CI 必须强制三个路径并断言三生态结果,不只检查退出码。 - -Rust PG helper `load_setting` 强制 `database.postgres_test` 和数据库名中恰好一个 `{case}`,拒绝 query dbname 覆盖;schema 用唯一 PID/time/counter,tenant 用本轮唯一前缀并仅删除规范正整数 ID。schema fixture 不创建基础数据库,需提前准备 `postgres_orm/authorization_postgres/llvm_database` 等每个调用 case 所需数据库;tenant fixture 会创建控制库和租户库,配置角色需要对应权限。全部连接必须指向本次自有 PostgreSQL instance。owned cluster 在 runner finally 停止并清理;失败原始信息与清理错误都要保留。 - -性能 `build.load_postgres_setting` 没配置会返回 None,run orm 自动退化为 SQLite-only;CI PG 阶段先检查配置,报告必须包含 postgres driver。其 Python URL validator 没有 Rust helper 的 query dbname 禁止规则,推荐 fixture 创建者只输出固定安全 URL,不接受任意外部 override。 - -### 长压测:可直接复用的命令与界限 - -构建 `run.py build --selection protocols` 准备 protocols,`--selection cms-profiles` 准备双源码 CMS/四 profile;ORM 需 all 构建并已配置 PG。Rust peers 单次 release 构建后复制指纹,run 阶段不运行 Cargo。记录 `application_configuration=llvm-cmd-v1`、`peer_configuration=setting-json-v1` 与所有实际二进制 hash;旧 manifest 被拒绝。 - -下面每组分别在 memory=64、128 执行,output 用新的独占目录;`CGROUP` 必须是已经委派且有 memory controller 的自有父组。每个子场景是真实持续至少1800秒。CPU affinity 从允许 CPU 集合选,server/client 不重叠;没有隔离不声明独占 CPU。 - -```sh -python3 test/performance/run.py run --artifacts "$ARTIFACTS" --output "$OUT_HTTP" --suite http --implementations dever --duration 1800 --warmup 5 --rates 1000 --paths /plain,/json,/bytes --repeats 1 --concurrency 16 --connection-mode reuse --memory-mib "$MEMORY" --cgroup-parent "$CGROUP" -python3 test/performance/run.py run --artifacts "$ARTIFACTS" --output "$OUT_H2" --suite http2 --implementations dever --duration 1800 --warmup 5 --rates 1000 --paths /plain,/json,/bytes --http2-connections 1 --repeats 1 --memory-mib "$MEMORY" --cgroup-parent "$CGROUP" -python3 test/performance/run.py run --artifacts "$ARTIFACTS" --output "$OUT_RECOVERY" --suite http2-recovery --implementations dever --duration 30 --cycles 60 --recovery-rate 1000 --recovery-connections 1 --repeats 1 --memory-mib "$MEMORY" --cgroup-parent "$CGROUP" -python3 test/performance/run.py run --artifacts "$ARTIFACTS" --output "$OUT_LIVE" --suite live --duration 30 --cycles 60 --connection-tiers 32 --repeats 1 --interval 0.1 --memory-mib "$MEMORY" --cgroup-parent "$CGROUP" -python3 test/performance/cms.py run --manifest "$CMS_MANIFEST" --output "$OUT_CMS" --concurrency 16 --read-seconds 1800 --memory-mib "$MEMORY" --cgroup-parent "$CGROUP" -``` - -1000 req/s 是保守起点而非宣称性能阈值;先独立短时 calibration,长测要求 errors=0、OOM=0、非零成功,建议 >=99% scheduled 成功作为该次目标负载验收,失败需降低目标后重新完整跑并保留失败数据。不要把历史 20k 短测当当前机器长测门槛。 - -runner 当前 profile lifetime=3600000ms(build.py:121),live duration 限制0.3..60、cycles<=100(run.py:1161);所以 live 不能传1800,可用60×30秒的真实连续同一进程生命周期。HTTP2 recovery 同理,周期总量需小于1h。HTTP/H2 各两种 transport×3 paths,64/128 合计各6小时;recovery 两 transport 两预算约2小时;live 三协议两预算约3小时;CMS 双源码两预算约2小时。以上完整路径矩阵约19小时加准备;若只选一个代表 body 路径,HTTP/H2合计缩为4小时,总约11小时,但必须显式记录未长测另两路径,短合同测试继续覆盖它们。 - -`run --suite cms` 只顺序发布16篇,与 --duration 无关;长测用独立 cms.py 的 read-seconds。`memory` parked fixture 只有3秒窗口,`async` 与 ORM CRUD/list/cursor/stream/pool 是有限操作,给 duration1800也不是长测。ORM 的 HTTP entry 使用 duration 可测30分钟,但有限项需在同一进程内重复 workload 才证明长期资源稳定;单纯外层重复短进程会掩盖泄漏。现有 CMS postgres-case 是验收,不自动成为长压测。若用户要求这些也长测,需在现有 runner owner 上增添持续模式,不冒称现有参数已覆盖。 - -资源/失败判定:run.py server context 最终检查 cgroup OOM;HTTP/2 `observe_disconnected` 要求 FD 精确恢复;live.py 验证 phase 顺序、连接计数、payload 和 heartbeat,run.py:627 当前只记录 FD/RSS delta,不强制 delta=0。必须加报告 gate 或局部 owner 校验 live FD 恢复。RSS 保存每周期基线、断开后值、末段范围/趋势;allocator 稳定保留不等于泄漏,不要求绝对回到首次 RSS,但持续增长、OOM、资源无法回收应判失败。完整进程组 terminate/reap、cgroup 清空/删除、失败也保留 cases.jsonl/report 已完成部分;还应验证控制器缺失明确失败、错误 payload 失败、超时/中断清理的测试。`status=complete` 不单独代表无错误。 - -### 2.1 GiB 空间下的串行策略与耗时 - -只读 df 已确认根分区可用2.1GiB。单个 Cargo -j1 控制编译并发但不限制产物总量;不要承诺完整 all-targets 全量链接可装进2.1GiB。优先共享当前 target/dependency cache,先静态,再默认/全特性按 target 执行并保存结果,只清理本轮可重建的精确输出,不能删作者输入、其他任务缓存或整个 target。任何安全清理计划由主代理解析实际路径/所有权后实施。 - -原生 ABI 四次 release 编译共享一个 target,保存成品后再切 feature;大三生态/安装验收串行且不和 Cargo/PG压力同跑。sdk/native-release.md 已支持 `target/native-release-inputs/config/setting.json` 的 `machine_temporary_root`,只移动 owned image/machine;可选较大且可执行的文件系统。若用 /dev/shm,必须同时预算真实 RAM/该进程 cgroup,不能把磁盘问题变成宿主 OOM。报告只需小量 JSON/日志;live 0.1s采样每30分钟约18000点,多 raw 副本占用需计入预算。run.py stage_case_binary 对 Dever 每case复制,settings.stage_peer 对 immutable peer用硬链;不要假定所有 binaries 都已零复制。 - -耗时只能估计:已准备依赖的静态/合同门数十分钟至数小时;冷四profile fat-LTO每个数分钟到数十分钟,必须实际记录;三生态重打包/源码构建数分钟至数十分钟,临时空间数GiB;19小时长测是按明确场景串行计算的下限,不能用并行负载污染CPU测量或拿超短烟测替代。新增 runner 可提供阶段选择用于重跑失败阶段,但 full gate 必须验证所有必选阶段拥有同一源码/输入版本的通过证据。 - -### 主代理补充限制:总2 CPU / 4GiB - -`process.py:47` 的 Budget 接受任意显式 parent,在其下建唯一子组,并设置 memory.max/swap.max/cpu.max;`Process:105` 只把自有被启动 child迁入所给Budget。现有 server 的预算仅覆盖服务,HTTP/live负载端没有server Budget,默认继承 Python runner 的cgroup。因此支持统一上层限额,但必须由外部CI入口先把 runner/作者准备/Cargo/自有PG都放入共同的4GiB/2 CPU父组,不能只传server的 `--cpu-quota 2` 冒称全局2 CPU。 - -推荐结构:owned parent设置 `memory.max=4294967296`、swap.max=0、`cpu.max=200000 100000`,空父组启用memory/cpu controllers;其下 `control` 放CI/Python/Cargo/负载端,自有 `postgres` 放PG,再传该空父组给performance让其创建server64/128MiB兄弟组。这满足cgroup v2 no-internal-process约束;不要把runner放在已启用domain controller且还要建子组的父组本身。所占CPU可在允许affinity里挑2个,server/client各1个,总quota仍统一2。PG与server受父级内存合计限制,/dev/shm作者验收同样计入4GiB;必须预估并保留headroom,不能假设搬到tmpfs无限可用。 - -主代理报告格式门已实际失败,`target/linux-ci-initial-format.log`有1174处Diff位置(不是1174个文件)。这是待实施的格式修复前置证据;本research未亲自执行格式化,不把其当通过。主代理可将HTTP2正式稳定负载选5000/s并先做短calibration;长测仍需完整30分钟,不能宣称该速率是吞吐上限。 - -## Caveats / Not Found - -- 本研究未运行任何 Cargo、编译、测试、服务、下载或 Git 命令;上述命令是实现建议,不是执行证据。 -- 系统 AppArmor 实际策略与非 root Worker 修改由另一工作流负责;现有 `enforces_unprivileged_namespace` 在root时降为65534,只证明当前 host策略下该夹具的执行,不等价正式部署 profile 的路径覆盖。禁止以 root pass替代非root;禁止通过全局关限制获得绿色。 -- CI 配置当前不存在;作者/fixture paths有明确 Linux GNU x86_64/GCC13/glibc2.39 依赖,不能把普通ubuntu-latest或跨平台可用当事实。 -- ignored 全量精确模块名应由实际 libtest inventory确认;本文件列源码 owners和明确名称,不替代机器可审计清单。 -- PG、SDK缺配置、finite runner duration未生效、内部probe被错误执行、仅all-features验证profiles,是主要 false-pass 风险。 diff --git a/.trellis/tasks/09-29-language-production-closure/research/native-pack-production-inputs.md b/.trellis/tasks/09-29-language-production-closure/research/native-pack-production-inputs.md deleted file mode 100644 index 5eb58f6..0000000 --- a/.trellis/tasks/09-29-language-production-closure/research/native-pack-production-inputs.md +++ /dev/null @@ -1,71 +0,0 @@ -# Research: native runtime pack 制作与 profile 裁剪 - -- Query: 既有制作入口是否仅 fixture;四 profile 的真实 archive 制作、裁剪、复用及本机资源边界。 -- Scope: internal;只读源码与本机工具元数据,不构建、不测试、不下载、不研究签名/CLI owner。 -- Date: 2026-10-02 - -## Findings - -### 文件与当前证据 - -- `test/native-runtime-pack.rs:1` 明示 private Linux author fixture;main 仅调用 `llvm_pack::prepare`。 -- `test/dever-cli-tests/support/llvm_pack.rs:56` 的 `native_inputs` 固定引用 `target/native-runtime-abi/debug/libdever_backend_bridge.a` 和本机 glibc/GCC CRT/static libs;没有 Cargo 调用。 -- 同文件 `document`(88–101)把 base/sqlite/postgres/both 全映射至同一个 `runtime.a`。`prepare`(107–150)只是检查输入、独占创建目录、硬链接并记录 SHA/大小;不是四 profile 发行构建器。`compiler_library`(153)硬链接本机 LLVM 动态库。 -- `target/debug/runtime/linux-x86_64/manifest.json` 当前 runtime.a 为 **191253848 bytes**,摘要 `7002224967cfbc3609b304f964e911d2f03fe204d5b58c07e90dc35d71c4b84c`。源码 archive 的 stat 相符;本次未重复计算其 SHA。此 archive 为三硬链接之一,严禁原地 strip,否则会修改现有 fixture。 -- `crates/dever-backend-bridge/Cargo.toml:9` 输出 rlib/staticlib;17–25 已有独立 features,无需新 runtime crate。 -- `crates/dever-backend-bridge/build.rs:1` 只有 embedded feature 才编 C++/链接 LLVM;runtime-only archive 必须禁用 embedded。私有 SDK 位于 `target/backend-sdk/usr/lib/llvm-18`(12),LLD 静态库、LLVM18/z 动态库、zstd 静态库是 compiler 侧依赖(39–44)。 -- `crates/dever-runtime/Cargo.toml:11` 已有 api/external/sqlite/postgres 独立 feature owner;SQLite bundled engine 固定于 workspace dependency,不能依赖宿主动态 SQLite。 -- `Cargo.toml:46` release 为 fat LTO、codegen-units=1;dev/test debug=0、incremental=false。现有 debug archive 不能靠 strip 冒充 release 优化。 - -### 四 profile 的最小 feature 映射 - -| profile | bridge features(每次只构建 bridge lib) | -| --- | --- | -| base | runtime-abi,runtime-api,runtime-external | -| sqlite | 上述 + runtime-sqlite | -| postgres | 上述 + runtime-postgres | -| both | 上述 + runtime-sqlite,runtime-postgres | - -profile 的区别只在真实数据库 driver。base 不是仅 runtime-abi:否则缺失 API/external 应用能力。证据:ffi.rs:4319 的 Worker 实现由 runtime-external 门控,ffi.rs:5196/5333 等应用路径由 runtime-api 门控,ffi.rs:5476–5477 按两个数据库 feature 声明 driver 能力。不要在 workspace-wide build 中无意通过 CLI dev-dependencies 合并 embedded/全数据库 features。 - -建议作者构建步骤(未执行):用显式 Cargo/Rust 工具路径,`cargo build --offline --locked -p dever-backend-bridge --lib --release --no-default-features --features --target x86_64-unknown-linux-gnu --target-dir `,每次将结果复制为独立 profile archive 后再构建下一个。四个 profile 共用一个 Cargo target,避免四份依赖树;不用环境变量/PATH作为产品配置。 - -### 裁剪与可重复制作的最小交付 - -1. 作者工具接受显式输入:目标、四份真实 release archive、CRT/static lib 清单及工具路径;记录工具版本、输入摘要与制作参数。将 profile 映射保存在单一配置表,manifest 仍使用既有 v1 协议。 -2. 对**新副本**进行确定性 archive debug 裁剪;本机 GNU strip 支持 `--strip-debug --enable-deterministic-archives -o `。不要使用 `--strip-all`,它移除重定位/符号,会损坏可继续链接的 archive。不要凭文件名任意删除 Rust/C ABI object member;真正 driver 裁剪由 Cargo features 完成。 -3. 保留 ABI 导出、链接符号及故障来源字符串;检查普通 archive、目标架构与输入完整性,生成每个 profile 独立 runtime 路径。可共享真正相同的 CRT/libs,但不可拿同一 all-features archive 冒充四包。 -4. 对同一批输入重复制作两次并比对文件/manifest 摘要,证明“pack 制作确定性”。若要声称从源码可重复,还须固定完整 Rust/CRT/SDK 版本、构建路径映射等并实际重建比较;仅重复复制不证明源码 bit-reproducibility。 -5. 将完成后的字节集合交给既有 release 签名 owner(主线程负责),签名之后不得再 strip。定向验收应覆盖四档链接/执行、driver 分离、缺失/篡改及安装后消费;没有实际 PG 服务只能证明 postgres 构建/链接,不能声称真实 PG 执行通过。 - -复用点:`sha256_file` 已为流式摘要 owner(llvm_pack.rs:5);现有 runtime v1 manifest/校验及 release v1 签名闭包由主线程复用,不新造协议;fixture 的 CRT 顺序与 archive 清单可作为 Linux GNU 输入模板,但其绝对路径与硬链接行为不能直接当通用发布接口。 - -### 对作者工具是否亲自调用 Cargo 的建议 - -**不必让签名/制作器亲自调 Cargo 才算完整交付**。更小且边界清楚的链路是:一个有真实执行证据的统一 `runtime-pack` Cargo profile + 四条固定 feature 构建命令,输出四份真实 archive;作者 maker 只读 `/config/setting.json` 的明确输入、验证/裁剪副本、生成 manifest 并交既有签名 owner。如此制作器不依赖源码树、Cargo 缓存或编译工具,不把“签名已准备资产”与“编译源码”混成一个职责。构建配方与制作配置共同构成可重复链,文档应区分两层,不能仅交付 maker 而省略真实四 archive 构建。 - -若当前验收明确要求“一条作者命令从源码生成四包”,才给 maker 增加独立 build 子流程;不要通过扫描 PATH 或环境变量选择工具。现有需求是可重复制作/裁剪/签名,未见必须单命令从源码构建的约束。显式 Cargo/Rust/C 工具输入可属于作者构建配方;避免在产品 setting 中新增这些实现细节。 - -统一 runtime-pack profile 应继承 release 的 fat LTO/单 codegen unit,保持 debug 信息策略明确。先实际构建一次检查 archive/link/尺寸,再决定是否需要额外 strip 步骤;不为缩小时间或磁盘而悄悄降低既有生产优化合同。共享 target + 顺序构建四档即可,不需要泛化跨平台构建框架。 - -### 本机现有资源(只读检查) - -- `/root/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/{cargo,rustc}` 存在;rustlib 只发现 x86_64-unknown-linux-gnu 标准库,没有其他目标 std。 -- `/usr/bin/{ar,strip}` 是 GNU Binutils 2.42;另有 `/usr/bin/x86_64-linux-gnu-objcopy`。其 strip help 列出确定性 archive 支持;未验证对新 release archive 的实际处理结果。 -- `/usr/bin/llvm-ar*`、`llvm-strip*`、`llvm-objcopy*` 和 `/usr/lib/llvm-18/bin` 不存在;私有 SDK 有 LLVM/LLD headers/static libraries,不能由此推定已安装完整跨平台裁剪工具。 -- `/usr/lib/llvm-18/lib/libLLVM.so.1` 为 123215144 bytes;当前 fixture 指定 glibc 2.39、GCC13。正式交付须明确该 Linux GNU 工具链基线,不能声称兼容所有 Linux。 -- `target/native-runtime-abi` 约1.3 GiB;文件系统可用718 MiB。只有主线程可构建/清理;研究未移动或删除任何产物。 - -### 相关规范 / 外部参考 - -- `.trellis/spec/backend/index.md`、`directory-structure.md`、`error-handling.md`、`quality-guidelines.md:5`(共享 Cargo target、release优化、定向验收)。 -- `.trellis/spec/backend/toolchain-and-library.md:7–19`(Rust≥1.95、feature边界、runtime v1与不可伪称六目标发行)。 -- 当前任务 `implement.md` 的 2026-10-02 节明确下一步是正式可重复裁剪 packs,现有签名 fixture 不代表正式资产。 -- 外部网页未访问;工具选项证据直接来自本机 GNU strip 2.42 `--help` 和 ar/strip `--version`。 - -## Caveats / Not Found - -- 子代理运行 task.py current --source 返回 none;输出路径使用父代理明确给出的 Active task,未猜测/改动任务指针。 -- 检查了 shemic-dever SKILL.md;实际仓库 AGENTS.md 明确这是 Rust 语言编译器,不适用 Go Model/Page/Service 规则。 -- 未找到正式四 profile maker;现有入口清楚标记 fixture。本结论不覆盖主线程正在编辑的文件。 -- 本次没有 Cargo/build/test、下载、全局安装、git 操作及真实发布;没有验证 release archive 大小、跨平台运行、签名真实性或源码重建一致性。 diff --git a/.trellis/tasks/09-29-language-production-closure/task.json b/.trellis/tasks/09-29-language-production-closure/task.json deleted file mode 100644 index 55ec6c9..0000000 --- a/.trellis/tasks/09-29-language-production-closure/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "language-production-closure", - "name": "language-production-closure", - "title": "Dever 语言生产化收口", - "description": "完成 Dever 语言从大型项目可用到可验收、可复用外部生态和可发行产品的收口工作", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P0", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-29", - "completedAt": null, - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [], - "notes": "2026-10-03本轮Linux CI及受限AppArmor非root Worker已收口。source7310a568/e40b7f16:native1791040913590327459为185/185,sandbox1791040885539823828为9/9,Python1791040504277745773为92/92,inventory108目标/217分类通过。宿主报告target/linux-ci-apparmor/1791040870463419164/result.json通过且完整恢复;4种负面探针均实际被内核拒绝,签名三生态pip/npm/go在真实UID65534独立执行全部通过。只修父子libtest计数和std mpmc晚初始化TLS缓存的测试误报,固定20/20复验与真实泄漏/错误返回负面回归通过。恢复4个原测试文件并排除2个新增回归可精确重算90245dd9,产品与固定输入未改;保留默认651/651、全功能873/873、静态、19组合、三SDK、PG7/7、性能3/3的原指纹证据,不冒称同新指纹全阶段重跑。最终队列1小时3分28秒,预算内、OOM0;自有unit/cgroup/PG退出,helper及AppArmor文件/profile移除,sysctl恢复strict=0/userns=1。临时根config/setting.json核验后移到target/linux-ci-session-BrZ5t3/setting-final.json,恢复根配置原先不存在。CMS64/128及HTTP2-64长测0错误/0 OOM;HTTP2-128中止、recovery/live64/128未跑,用户免跑且未标通过。父任务因其他平台/公开发行暂缓继续in_progress,不提交不归档;本轮Linux交付无剩余阻塞。", - "meta": {} -} diff --git a/.trellis/tasks/10-05-install-entry/check.jsonl b/.trellis/tasks/10-05-install-entry/check.jsonl deleted file mode 100644 index 805da9a..0000000 --- a/.trellis/tasks/10-05-install-entry/check.jsonl +++ /dev/null @@ -1,2 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Signed install and source contract"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Validation boundaries and meaningful tests"} diff --git a/.trellis/tasks/10-05-install-entry/design.md b/.trellis/tasks/10-05-install-entry/design.md deleted file mode 100644 index 781e975..0000000 --- a/.trellis/tasks/10-05-install-entry/design.md +++ /dev/null @@ -1,19 +0,0 @@ -# 设计 - -## 唯一安装实现 - -2026-10-05 用户在合仓后明确要求只保留根 install,取代之前的 skill安装器加生成器方案。根 install 直接维护既有下载、签名校验、raw launcher 校验与 Rust 解压/bootstrap 调用链。Bash 只负责 Python 前提检查、必要的 sudo 和把内嵌 Python 程序通过引用 heredoc 交给 /usr/bin/python3 -I -,参数原样转发。完整函数定义在最后调用前解析,截断的主体不执行安装。 - -根脚本内嵌独立固定公钥,不从下载包取公钥;显式 --trusted-key 仍支持已独立确认的自有签名包。删除双入口专用的生成包装和skill相对路径。普通测试与发行验收统一消费根 install;测试用加载器只读取实际内嵌源码,不保存第二份安装实现、不成为生产依赖。 - -默认版本 latest;元数据为 dist/latest/dever-.manifest.json 与 .sig;验签后只从 dist// 获取基础 archive、raw blobs 和扩展。Rust ReleaseSource 与 Python 使用同一静态协议。只允许官方 HTTPS 同站重定向,禁止凭据、非 443、fragment 和外站。没有环境变量/项目配置覆盖和旧源 fallback。 - -## 行为与验证边界 - -机器布局与 bootstrap 事务不变,解压保持在 Rust owner,不增加 shell tar/zstd 解析。帮助不联网、不提权;非 root 安装使用系统 sudo,保留退出状态。沿用 --release、--trusted-key、--system-root、--no-start 做离线镜像验收。 - -现有真实 0.1.1 split assets 可验证新入口和安装生命周期;旧二进制内部仍指向 GitHub,不能据此声称新源线上 update 已通过。新版本构建发布属后续步骤。服务器须显式映射 /shemic/dever/install 到纯脚本;Git 页面或 raw 登录跳转不是安装脚本。 - -## 资源 - -磁盘不足 1 GiB,隔离镜像优先放 /dev/shm 自有临时目录并及时清理,仅保留报告。源码备份 target/install-before.WTVfLC。不得删除其他缓存、改变系统服务或修改 AppArmor 全局状态。仅修改安装、发行源、相关测试和必要文档,不做语言与 skill 约束的邻接改造。 diff --git a/.trellis/tasks/10-05-install-entry/implement.jsonl b/.trellis/tasks/10-05-install-entry/implement.jsonl deleted file mode 100644 index c8a4ef8..0000000 --- a/.trellis/tasks/10-05-install-entry/implement.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/index.md","reason":"Rust compiler scope and checklist"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Signed distribution, bootstrap and single ownership"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused offline testing and temporary ownership"} diff --git a/.trellis/tasks/10-05-install-entry/implement.md b/.trellis/tasks/10-05-install-entry/implement.md deleted file mode 100644 index ed149bd..0000000 --- a/.trellis/tasks/10-05-install-entry/implement.md +++ /dev/null @@ -1,83 +0,0 @@ -# 执行与证据 - -## 授权与起点 - -- 已在方案与「先实现 install、统一新源」说明之后授权实施并同意任务登记,不重复询问。 -- 主仓库 a2e0436、skill 27ac8f2 起点均 clean。 -- 备份 target/install-before.WTVfLC/core.tar.gz 与 skills.tar.gz。 - -## 顺序与所有权 - -1. [x] trellis-implement:Python 安装器、生成器、根 install、Rust ReleaseSource、根 test/ 定向测试及既有验收 harness 路由。不修改文档、spec、Git 元数据、版本号。 -2. [x] 主会话:README、安装说明、SDK 发布说明与规范;真实签名包的新入口自有镜像验收,不修改全局服务。 -3. [x] trellis-check:独立检查完整 diff,修复确有的安装/边界/测试缺陷,核验生成物一致性。 -4. [x] 主会话:关键证据、必要复验、diff/资源清理、实现验收收口;准确说明线上端点与新包未发布。提交归档随后续迁移统一处理。 - -## 定向验证 - -- bash -n install;实际 Bash 文件/管道帮助和失败路径。 -- Python onboarding installer 与新增入口定向测试。 -- cargo test --offline -p dever-cli --lib toolchain::release_source;修改文件格式检查,不跑全量。 -- 真实旧 0.1.1 签名基础包,通过 bash install --release ... --system-root ... --no-start 安装自有镜像。旧二进制不证明新源线上 update。 -- 生成器 --check、git diff --check、skill 文档检查。 - -## 结果 - -- Python 定向 `python3 -B -m unittest discover -s test/onboarding -p 'test_install*.py' -v`:19/19 通过。包含实际 Bash、真实 Ed25519、独立公钥、字面参数与退出状态、非 root UID help 和进程内 sudo 拦截;没有实际提权/全局服务操作。 -- Rust `cargo test --offline -p dever-cli --lib toolchain::release_source`:10/10 通过。实际本地 HTTP 传输断言 latest 两份元数据后从签名准确版本取 archive。复用 target/debug,未跑全量。 -- 原有作者 rustfmt 对修改 Rust 文件检查通过。主会话复核生成 --check、bash -n、主/skill diff --check 和 skill quick_validate 均通过。 -- `test/onboarding/verify_install_entry.py` 真实 0.1.1 签名资产验收 4/4 通过,报告 `target/install-entry-acceptance.json`:Rust 验签解包准备、独立 Bash 首装且 core/skill 对应、管道重装保持核心与选择、坏签名拒绝且原 journal/core/bootstrap 不变。自有 /dev/shm 临时目录已清理,没有启动全局服务。 -- 初次验收报告保留为 `target/install-entry-acceptance-initial.json`。首装通过后,重复安装因测试误要求 active-version 字节完全相同失败;实际 `bootstrap/transaction.rs` 明确追加激活记录。仅修正验收:重复安装比较实际选中版本与负载字节,失败安装仍严格比较 journal 字节。生产安装行为未放宽,重跑完整4阶段通过。 -- 根 install 为 13,938 字节,摘要 `3cab983b5093c4a7075f28707042c672a00ce754888ac3e7c9f85853d40ae7eb`;真实验收使用旧版负载,不表示新版本构建、线上安装或线上 update。 -- 任务分支 `feat/install-entry`;未提交、推送、改 Git remote 或合并 skills 子仓库。后续迁移发布需新版本 core/launcher/daemon 与完整配套 skill,部署匿名 HTTPS 安装/资产路由。 -- 独立 trellis-check 最终无阻塞、未修改产品文件;再次核对生成脚本与真实验收报告 SHA 完全一致,认可 bootstrap 同版本激活记录的测试边界。全部本次验收已满足,未跑全量 clippy、全量 CI 或线上安装。 - -## 合仓与发行阶段(2026-10-05) - -用户已批准前述后续交付方案,继续使用本任务记录,不重复请求创建任务或实施批准。 - -- [x] 主会话:当前源码和 Git 历史备份;skills 普通目录化;新远端核验、提交推送;同步安装/源码文档。 -- [x] 发行 worker:准备新版本精简发行,复用既有制作和验收脚本,报告实际包体;不操作 Git、全局安装或服务。 -- [x] 主会话:核对新包及匹配 skill,准备完整静态部署目录,完成隔离本地安装验收。 -- [ ] 发布静态端点并完成真实 HTTPS 首装/update 验收;缺少站点部署接入,不能用本地结果代替。 -- [ ] 线上验收完成后归档;当前保持 in_progress。 - -初始只读证据:新 SSH 仓库 ls-remote 成功且无 refs;HTTPS /shemic/dever/install 返回 404。已询问站点部署方式,等待期间继续合仓与可离线完成的新包准备。系统盘剩约 368 MiB,/dev/shm 约 2.4 GiB,优先复用资产和缓存,不能删除其它项目或部署数据。 - -### 当前证据 - -- 备份目录 `target/migration-backup.pBIq3U`:当前源码 tar.gz(不含构建物、Git元数据、密钥与本地配置)、完整 `core.bundle` 和 `skills.bundle` 均验证通过;原 `skills/.git` 移入此目录,保留本地历史和配置。 -- `skills/` 已从 gitlink 改成主仓库 21 个普通文件,删除唯一 `.gitmodules` 及本地 submodule 配置。`origin` 已切至新 SSH 地址,旧远端以 `github` 保留;没有向旧远端推送。 -- 生成 install `--check`、Bash语法、skill结构和diff检查通过;同仓说明、模板和新源文档已同步。 -- 此前 skill约束和CLI接线一并进入本版:`check/run/build` 共用 C016;CLI新增5项及既有1项定向回归通过,CMS普通/Markdown静态check均通过(各7条既有W001)。不扩大冗余判定、不声称所有CRUD包装都可识别。 -- 发行版本设为0.1.2,core/launcher/daemon在自有tmpfs目录串行离线重建;不重编未改的runtime。为本轮发行空间,Cargo仅清理本地dever-cli dev构建产物,释放236.7MiB,可从源码恢复;旧release、作者输入和备份保留。 - -### 0.1.2 合仓、构建与验收结果 - -- 产品提交 `19f122b4b4f7cf977059d127db6971c5dfc07b1d` 已推送新 `origin/main`,远端默认分支为 main;保留 v0.1.0、v0.1.1 标签。从新 SSH 地址重新克隆,未使用 submodule 即获得全部 skill,生成入口、Bash语法及skill结构检查通过;临时克隆已清理。 -- core/launcher/daemon 真正离线 release 重编完成,源码和skill固定在上述提交;依赖与runtime实现未改。已核对8116项作者输入,8份未变扩展与0.1.1字节相同并硬链接复用,ARM应用target按0.1.2重新组包。这仍是 Linux x86_64 编译器发行,宿主要求 glibc >= 2.39。 -- 基础包 `target/release-0.1.2/assets/dever-linux-x86_64.tar.zst` 为 **117,507,272字节(112.064MiB)**,仅比0.1.1增加26,064字节(25.45KiB)。解压600,851,668字节。基础包SHA256为 `d8e7628d42688628b5d3007fa074e3aad75607917bc34cb34fbebed62b40ee75`。 -- 主会话复核新二进制摘要与构建记录一致,启动器和daemon内嵌新官方源;core增4,288字节,启动器和daemon分别减256及320字节,未添加新依赖。 -- `target/release-0.1.2/acceptance.json`:8/8通过。真实签名包隔离首装、基础包排除可选扩展、版本入口、普通和Markdown模板的new/fmt/check/最小test/CMD/build、skill同步、缺target离线报错,以及移除源码/机器目录后的独立程序运行。 -- `check-acceptance.json`:2/2通过,发行包check实际拒绝不可达app并返回C016,新建项目模板与冻结skill一致。 -- `install-entry-acceptance.json`:4/4通过,实际生成的Bash首装、管道重装、坏签名拒绝且保留已有安装。此处为本地官方签名资产验收,未声称真实HTTPS或线上update通过。 -- 主会话使用独立公钥重新验证manifest签名,流式复算全部14份发行文件的大小和SHA256;manifest中21份skill文件与本仓源码逐一一致。可部署目录 `target/release-0.1.2/public/` 包含 `install`、`dist/0.1.2/` 全部资产及 `dist/latest/` 两份匹配元数据;资产用硬链接,不额外复制约597MiB。 -- 构建输入、实际体积、构建日志分别保存在同目录 `provenance.json`、`sizes.json`、`build.json`。自有daemon、tmpfs挂载、临时私钥副本与本轮Cargo目录已清理。未运行全量CI、三生态重验、长测或宿主全局服务操作。 -- 独立发行复核无新增阻塞:源码提交、manifest、安装脚本与验收报告一致,public目录无私钥、作者配置、测试记录或符号链接。`v0.1.2` 注释标签已固定到产品提交19f122b并推送新origin;Git标签不代表HTTPS端点已部署。 - -### 待上线的唯一交付阻塞 - -2026-10-05最后复核,`https://git.dever.cc/shemic/dever/install` 与 `/shemic/dever/dist/latest/dever-linux-x86_64.manifest.json` 均为HTTP404。已向用户询问SSH主机、端口、账号与静态目录,或既有部署配置位置;目前仅有Git SSH访问,不能据此推定服务器shell/路由配置。发布时将上述public目录映射至 `/shemic/dever/`,然后在自有隔离安装中验收真实HTTPS首装与update。部署完成前不归档、不标为全部交付完成。 - -### 合仓后的安装入口清理(用户新增授权) - -用户确认只保留根install。旧设计中skill安装器作为源码、根入口作为生成物的约定被替代;前述发行验收是历史证据,不能据此宣称本次改动已验证。 - -- 实现边界:根install成为唯一安装源码,删除 `skills/scripts/install.py` 和 `sdk/install-entry.py`,迁移根test/onboarding内的测试和发行验收调用,更新当前安装指引与规范。 -- 保持固定下载源、独立公钥、验签/路径/摘要校验、Rust解压及bootstrap、失败清理、Bash参数传递/提权/截断保护。仅移除双入口专用逻辑,不修改Rust或已签名0.1.2发行资产,不运行全量或全局服务验证。 -- trellis-implement负责安装脚本和测试;主会话负责指引、规范、任务记录,完成后独立检查实际diff与定向证据。 -- 原19项安装定向测试19/19通过,无跳过;保留文件/管道help、字面参数与退出码、隔离Python、真实非root UID的sudo截获、截断不执行、默认官方公钥拒绝自签包、显式可信key接受及篡改拒绝/清理。三个发行验收脚本的导入/help、Bash语法、skill结构、diff和旧活动引用扫描通过。 -- 主会话补验真实Bash签名/清理1/1通过。首次补验因根盘满在fixture创建阶段失败,改为仅本测试进程的 `/dev/shm` 临时目录后通过,未修改产品环境或增加环境变量配置。 -- 删除旧安装器的Python缓存及空 `skills/scripts/` 目录;源码可从Git历史恢复。为提交空间删除本轮 `target/release-0.1.2/tools/dever-core` 编译器副本(16,956,160字节,摘要已核对);完整同字节核心仍保存在签名基础包,可由已有解包器恢复,其余工具与签名资产保留。 -- 新根install为13,632字节,SHA256 `2b07829c7c7c7d76b8fd257239b4ab44816e064951f66e33ffd6e2bdcfce92ef`。已制作的0.1.2版本/tag及签名包仍固定在原产品提交19f122b;本次未重新发行,不把旧安装验收报告当成新脚本的验收报告。 -- 待部署的 `target/release-0.1.2/public/install` 已同步新根入口并逐字节核对;dist签名资产未改。独立检查确认下载/验签等函数与原版本AST一致、Bash包装参数及尾部调用保持,未引入第二套生产安装实现;已清理规范中最后一处generator检查要求。 diff --git a/.trellis/tasks/10-05-install-entry/prd.md b/.trellis/tasks/10-05-install-entry/prd.md deleted file mode 100644 index d719d80..0000000 --- a/.trellis/tasks/10-05-install-entry/prd.md +++ /dev/null @@ -1,38 +0,0 @@ -# Dever 单命令安装入口与官方源迁移 - -## Goal - -实现自包含 Bash install,复用签名安装器并统一 git.dever.cc 下载源,完成隔离定向验证 - -## 背景与授权 - -用户要求先实现 install,再处理新 Git 的迁移发布;已收到方案后明确要求实施,并于 2026-10-05 同意任务登记。已有签名 Python 安装器、Rust 解压/bootstrap 和配套 skill 打包可以复用。新 Git SSH 已可访问,远端尚无 refs;HTTPS /install 与公开发行资产尚未部署。 - -## Requirements - -- R1:根 install 可直接通过 Bash 文件或管道执行,无需克隆源码或先安装 skill;支持现有版本选择、本地发行目录、自有镜像和不启动服务选项。 -- R2:复用唯一签名安装器和 Rust 解压/bootstrap。独立公钥、签名、摘要、长度、路径验证和失败恢复不得削弱;非 root 使用 sudo,帮助不需要管理员权限。 -- R3:首次安装、机器 install/update、按需扩展统一使用 https://git.dever.cc/shemic/dever/dist;latest 只选择签名版本,负载取准确版本目录;不从业务配置或环境变量选择官方源。 -- R4:普通 run/build 仍离线,机器共享布局、按需扩展、版本与 skill 同步保持原有合同。安装前检查必要 OS/ABI/工具,清晰报告不支持或未发布。 -- R5:安装说明准确区分代码完成与服务器发布;源码下载源迁移不代表已有 0.1.1 二进制已更改。 - -## Acceptance Criteria - -- [x] Bash 语法、直接/管道 help、参数转发、退出状态、非 root 提权与截断脚本行为有最小定向验证。 -- [x] 根 install 是唯一安装源码;删除skill安装器与生成器、迁移相关测试及验收调用,保留独立固定公钥和既有安装行为。(2026-10-05 合仓后用户修订) -- [x] Python/Rust 新源 latest/精确版本/扩展地址一致,拒绝非法重定向。 -- [x] 真实 Ed25519 校验、损坏拒绝、临时文件清理保持通过;实际签名包可通过新入口安装到自有镜像,不启动宿主服务。 -- [x] 必要定向测试和 diff 检查通过,文档说明命令、发布目录、旧版迁移和线上未验证边界。 - -## 本次边界 - -先完成 install 及必需下载链路,不执行 Git 迁移/提交/push、skills 子仓库并入、全局安装、Web 服务配置、全量 CI 或正式新版本构建发布。后续必须重建包含新源的二进制,不能将旧包重新标号。源仓库访问限制不变,安装端点与资产需要匿名 HTTPS。 - -## 2026-10-05 后续交付授权 - -用户在合仓、Git 迁移、精简发行和线上安装更新验收方案后回复「可以」,本阶段继续实施以下交付。上一阶段的 Git/发布排除仅描述当时范围,不再阻止本阶段工作;仍不运行全量测试、不替换作者机全局服务或安装。 - -- [x] 备份当前源码与 skills Git 历史,将 skills 作为普通目录并入主仓库,保留当前约束和模板。 -- [x] 主仓库迁移至 ssh://git@git.dever.cc:2222/shemic/dever.git,提交并推送;不覆盖远端已有历史。 -- [x] 用新版本重建 core/launcher/daemon,复用未改变的已验证 runtime 输入,制作精简基础包、匹配 skill 与可选扩展,记录体积与摘要。 -- [ ] 发布安装脚本和签名资产,验证真实 HTTPS 首装与 update 的版本/skill 一致性;若部署接入缺失,保留可发布资产并明确缺失信息,不把本地验收当作上线成功。 diff --git a/.trellis/tasks/10-05-install-entry/task.json b/.trellis/tasks/10-05-install-entry/task.json deleted file mode 100644 index 75c0fe9..0000000 --- a/.trellis/tasks/10-05-install-entry/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "install-entry", - "name": "install-entry", - "title": "Dever 单命令安装入口与官方源迁移", - "description": "实现自包含 Bash install,复用签名安装器并统一 git.dever.cc 下载源,完成隔离定向验证", - "status": "in_progress", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-10-05", - "completedAt": null, - "branch": "feat/install-entry", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-09/00-bootstrap-guidelines/prd.md b/.trellis/tasks/archive/2026-09/00-bootstrap-guidelines/prd.md deleted file mode 100644 index 408d0d1..0000000 --- a/.trellis/tasks/archive/2026-09/00-bootstrap-guidelines/prd.md +++ /dev/null @@ -1,19 +0,0 @@ -# Bootstrap project guidelines - -## Scope - -This repository is a Rust workspace for the Dever language compiler, runtime, -CLI and repository-root tests. `AGENTS.md` and the actual implementation are -the source of truth for `.trellis/spec/backend/`. There is no frontend package -or UI source in this repository; frontend scaffolding from `trellis init` is -not applicable and must not prescribe hypothetical conventions. - -## Completion - -- [x] Document compiler/runtime/CLI ownership and real source examples in - `.trellis/spec/backend/directory-structure.md`. -- [x] Document compiler contracts, ORM, errors, logging, toolchain and focused - checks in `.trellis/spec/backend/`, backed by source and tests. -- [x] Remove unused frontend template specs; no frontend rules are claimed. -- [x] Keep the backend index in sync and verify no template placeholders remain - in applicable backend specs. diff --git a/.trellis/tasks/archive/2026-09/00-bootstrap-guidelines/task.json b/.trellis/tasks/archive/2026-09/00-bootstrap-guidelines/task.json deleted file mode 100644 index 97d53f0..0000000 --- a/.trellis/tasks/archive/2026-09/00-bootstrap-guidelines/task.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "id": "00-bootstrap-guidelines", - "name": "00-bootstrap-guidelines", - "title": "Bootstrap Guidelines", - "description": "Fill in project development guidelines for AI agents", - "status": "completed", - "dev_type": "docs", - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-04", - "completedAt": "2026-09-18", - "branch": null, - "base_branch": null, - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [ - ".trellis/spec/backend/" - ], - "notes": "Rust compiler workspace; frontend template specs are not applicable.", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-09/09-09-markdown-source/check.jsonl b/.trellis/tasks/archive/2026-09/09-09-markdown-source/check.jsonl deleted file mode 100644 index f93cbc8..0000000 --- a/.trellis/tasks/archive/2026-09/09-09-markdown-source/check.jsonl +++ /dev/null @@ -1 +0,0 @@ -{"file": ".trellis/spec/backend/quality-guidelines.md", "reason": "Focused checks"} diff --git a/.trellis/tasks/archive/2026-09/09-09-markdown-source/design.md b/.trellis/tasks/archive/2026-09/09-09-markdown-source/design.md deleted file mode 100644 index d3b4bf3..0000000 --- a/.trellis/tasks/archive/2026-09/09-09-markdown-source/design.md +++ /dev/null @@ -1,17 +0,0 @@ -# 设计 - -## 归属与复用 - -源码格式和 Markdown 内容区间由 core 拥有。使用 CommonMark 解析库识别真实顶层围栏,避免自造解析器误执行列表、HTML 或外层示例内的伪代码。新依赖仅用于编译器,不进入最小运行时。 - -SourceFile 保留原文,词法 token span 使用原字节位置。Markdown 提取不能让缓存、诊断、运行故障指向合成文件。词法/格式化共用程序区间;语义包路径接受 `.dever.md`,重复检测沿用声明注册。 - -## 格式化 - -先解析全包,验证完整声明不跨围栏。复用 AST 格式化方法,按块选择包头/声明/注释生成内容,原位替换内部文本。不能合并代码块或移动说明。CLI 快照检查与 staging 原样复用。 - -## 分工与契约 - -主代理负责 CLI 文案、实际 CLI 验证、示例、文档、规范与任务记录。实现代理负责 core/加载/解析/格式化、必要依赖和 core 定向测试。完成后独立审查,主代理复核关键证据。 - -程序围栏须顶层、闭合,信息字符串为 `dever`;无标记及其他语言只展示。每个类型、函数分句和 package 头完整位于一块内。若不支持缩进围栏,应明确诊断,不静默改变归属。 diff --git a/.trellis/tasks/archive/2026-09/09-09-markdown-source/implement.jsonl b/.trellis/tasks/archive/2026-09/09-09-markdown-source/implement.jsonl deleted file mode 100644 index a710497..0000000 --- a/.trellis/tasks/archive/2026-09/09-09-markdown-source/implement.jsonl +++ /dev/null @@ -1 +0,0 @@ -{"file": ".trellis/spec/backend/index.md", "reason": "Compiler conventions"} diff --git a/.trellis/tasks/archive/2026-09/09-09-markdown-source/implement.md b/.trellis/tasks/archive/2026-09/09-09-markdown-source/implement.md deleted file mode 100644 index 065c391..0000000 --- a/.trellis/tasks/archive/2026-09/09-09-markdown-source/implement.md +++ /dev/null @@ -1,24 +0,0 @@ -# 执行与验证 - -用户已在双格式方案后确认并选择 `.dever.md`,无需重复请求实施授权。 - -- [x] Core:程序块识别、原文位置、加载与包路径、共用解析和格式化。 -- [x] 定向测试:提取/拒绝边界、中文换行定位、混用/重复包/契约、格式化保留说明和幂等。 -- [x] 示例和 CLI:结算示例、空源码提示、实际 check/fmt/run/build 的隔离定向验证。 -- [x] 文档规范:语言说明、实现说明、过时草案、AGENTS 源码规则。 -- [x] 检查:相关 Rust 格式、定向 Clippy/Markdown/formatter 测试及独立复核。 - -`/root/.cargo/bin` 不在 PATH 时只设置命令级 PATH。持久测试放根 `test/`,临时程序归测试所有;无服务或网络操作,无全量/集成测试,无提交。仓库大部分文件原本未跟踪,diff 以本轮前快照为准。 - -## 完成证据(2026-09-09) - -- `cargo test --offline -p dever-tests --test markdown_source --test formatter --test syntax_and_format`:45 项通过(12 + 11 + 22)。主代理已检查原始日志 `/tmp/dever-markdown-checks.log`。 -- 同目标 `cargo-clippy clippy --offline ... -- -D warnings` 通过;CLI 单独 `-p dever-cli --bin deverc -- -D warnings` 通过。10 个修改 Rust 文件的定向 rustfmt 检查通过。 -- 实际 CLI 对 `examples/markdown` 的 check/fmt/run 通过,输出 `customer = 小明`、`subtotal = 47.5`、`discount = 4.75`、`payable = 42.75`。普通 `.dever` 计价包被 Markdown 包调用。 -- 根 test/ 下临时程序验证:无 rustc 时 check 仍可用、两种格式的 API 相同、普通 README 忽略、fmt --check 不写、第二文件错误阻止所有改写、CRLF/说明/围栏保持及幂等、run/build、PATH 不含工具链时独立运行、已有输出不覆盖、重复包 C002、C005 精确到 Markdown 第 11 行第 20 列、运行除零定位 Markdown 第 11 行。临时文件和二进制已清理。 -- 最终 core 的实际 CLI 裸 CR/缩进围栏验证通过:中文原文 C005 第 10 行第 31 列、格式化无新增 LF、说明保持、check 和 fmt --check 通过。首次手写列号预期少算一列,按原文核对修正,非实现缺陷。 -- 独立只读审查无阻塞。补充验证包头前后独立注释块、跨块 Bool 分句、同一文件各块 LF/CRLF/CR、围栏/正文保持和幂等通过。 -- 新编译器依赖 `pulldown-cmark = 0.13.4`(关闭默认特性)及三个传递依赖已获取并锁定;不进入运行时,验证全部离线。复用已有 target/verification-tools 中的 rustfmt/Clippy,未安装全局组件。 -- 更新过时标题语法草案、当前说明和旧主任务源码格式限制。28 个实现/文档变更文件空白检查通过;未修改现有无关删除项。 - -无未解决阻塞。未运行全量、集成或服务测试,未提交 Git;开发工作区改动保留供审查。 diff --git a/.trellis/tasks/archive/2026-09/09-09-markdown-source/prd.md b/.trellis/tasks/archive/2026-09/09-09-markdown-source/prd.md deleted file mode 100644 index a347b29..0000000 --- a/.trellis/tasks/archive/2026-09/09-09-markdown-source/prd.md +++ /dev/null @@ -1,25 +0,0 @@ -# Dever Markdown 程序源码支持 - -## 目标与确认决定 - -用户希望用 Markdown 组织易读的 AI 程序,继续由 Dever 类型与契约约束执行。2026-09-09 用户批准同时保留 `.dever` 和 Markdown 源码,并明确选择 `.dever.md` 后缀。 - -- `.dever` 行为兼容;`account/user.dever.md` 对应 `account.user` 包。 -- 标题、说明、表格不参与程序定义;只有标为 `dever` 的顶层围栏代码块属于程序,按顺序处理。代码保留完整 Dever 包、类型和函数声明。 -- 一个文件拥有一个包;格式可跨包混用,同包重复必须报错。 -- 复用现有语法、语义、契约、API 与原生编译路径。 -- 诊断和运行故障定位到原 `.dever.md` 文件及准确行列。 -- `fmt` 只格式化程序代码块,保留其它 Markdown 和围栏;整批检查后逐文件原子写入规则不变。 - -## 验收 - -1. 只加载 `.dever`/`.dever.md`,普通 `.md` 中的示例忽略。 -2. 同一程序两种格式的执行结果一致;混用包可调用,重复包、类型错误、分句缺失、失败义务仍拒绝。 -3. 多代码块、中文、不同换行、注释和原生故障位置正确;普通示例、嵌套围栏、引用、列表与 HTML 内的伪程序不执行。 -4. 程序围栏闭合,各块包含完整顶层声明(允许纯注释或空块);无程序块、跨块声明报错,避免格式化移动代码跨说明。 -5. 格式化只更新代码块内部、幂等;语法或程序结构错误时无文件改写。 -6. 提供可读的结算 Markdown 示例,更新语言说明和过时草案。 - -## 范围与验证限制 - -不增加新语言语法、浏览器运行时、编辑器扩展或多语言执行。不改无关文件,不提交或安装全局命令。只跑离线定向检查和自有临时程序,不跑全量、集成测试或现有服务。开发依赖获取明确记录,最终程序编译保持离线。 diff --git a/.trellis/tasks/archive/2026-09/09-09-markdown-source/research/source-flow.md b/.trellis/tasks/archive/2026-09/09-09-markdown-source/research/source-flow.md deleted file mode 100644 index 10a93c1..0000000 --- a/.trellis/tasks/archive/2026-09/09-09-markdown-source/research/source-flow.md +++ /dev/null @@ -1,8 +0,0 @@ -# 源码事实 - -- source.rs 只收集 `.dever`,保存原文、SourceId 和行开始位置;符号链接全部拒绝。 -- lib.rs 的 parse_uncached 共用 lexer→parser;lexer 当前读取 SourceFile.text()。 -- check.rs 的 check_package 固定 `.dever` 路径;注册阶段已有重复包检测。 -- format.rs 从 token 注释和 AST 生成整个包;CLI 先准备全部字符串,再快照核验和逐文件原子替换。 -- check/cache.rs 键含源码全文/路径,文档改动仍需重新建立准确诊断位置。 -- pulldown-cmark 提供带偏移的块事件:https://docs.rs/pulldown-cmark/0.13.4/pulldown_cmark/struct.Parser.html 。当前未缓存,新增这一个编译器依赖用于避免不完整的 Markdown 自制解析器。 diff --git a/.trellis/tasks/archive/2026-09/09-09-markdown-source/task.json b/.trellis/tasks/archive/2026-09/09-09-markdown-source/task.json deleted file mode 100644 index a45f193..0000000 --- a/.trellis/tasks/archive/2026-09/09-09-markdown-source/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "markdown-source", - "name": "markdown-source", - "title": "Dever Markdown 程序源码支持", - "description": "保留 .dever,新增 .dever.md 源码加载、原文诊断、保留文档的格式化与定向验证", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-09", - "completedAt": "2026-09-09", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/check.jsonl b/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/check.jsonl deleted file mode 100644 index 9c0f7cd..0000000 --- a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/error-handling.md","reason":"检查错误、OOM、计数和进程退出都显式传播"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"核对 CPU 隔离、测量矩阵、最小测试和结果边界"} -{"file":".trellis/tasks/09-13-http2-ceiling-soak/research/client-bottleneck.md","reason":"检查实现没有引入重复负载器或错误分位数聚合"} diff --git a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/design.md b/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/design.md deleted file mode 100644 index 4cba455..0000000 --- a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/design.md +++ /dev/null @@ -1,70 +0,0 @@ -# 设计 - -## 1. 最小改动边界 - -本阶段只扩展 `test/performance` 的负载进程配置和测量文档。现有 Rust `network_bench` 已具备多线程 runtime、固定 HTTP/2 连接拓扑、速率调度、完整响应校验和延迟直方图,因此不修改 Rust 负载器,更不修改生产运行时。 - -多进程客户端会产生多组独立直方图。只合并 p99 会得到错误分位数,输出全部 4096 个桶再聚合又会扩大协议和实现范围。一个多线程进程已经能把请求 worker 分布到多个 CPU,同时保留单一调度和精确的进程内直方图,因此采用该方案。 - -## 2. CPU 与 worker 合同 - -`Process` 的亲和性参数从单个 `cpu` 改为可空的 `cpus` 集合,并在 fork 后、exec 前一次性调用: - -```text -os.sched_setaffinity(0, cpus) -``` - -服务端仍把 `--server-cpu` 转为单元素集合。运行器将 `--client-cpu` 直接迁移为 `--client-cpus`,接受无重复的逗号分隔非负整数;新增 `--client-workers`,默认 1。运行前集中校验: - -- 所有指定 CPU 必须属于当前进程允许集合; -- 服务 CPU 不得出现在客户端 CPU 集合; -- 正式压测显式使用 `--client-workers 4 --client-cpus 1,2,3,4`。 - -不强制 worker 数等于 CPU 数,避免把合理的欠订阅/超订阅变成运行器错误;报告必须同时记录两者,使结果可解释。HTTP `load()` 和 `live.load_live()` 都把 `BENCH_WORKERS` 设置为同一个 `args.client_workers`,并把同一个 CPU 集合交给 `Process`。 - -## 3. 数据流与复用 - -```text -run.py 参数与集中校验 - -> Process(cpus=client_cpus) - -> BENCH_WORKERS=client_workers - -> 现有 network_bench 单进程 Tokio runtime - -> 现有 H2 连接/请求槽、调度、校验、Histogram - -> 现有 load JSON、进程采样、case/report 汇总 -``` - -`Process` 继续只负责子进程生命周期、亲和性和采样;它不解释 server/client 角色。`run.py` 负责参数合同与服务/客户端隔离。`live.py` 只消费已经校验的参数,不新增一套 CPU 解析逻辑。 - -## 4. 测量阶段 - -所有正式场景只测 Dever,服务绑定 CPU 0、1 worker、1 CPU quota、swap 0;客户端绑定 CPU 1–4、4 workers,位于服务 cgroup 之外。使用现存 `typed-orm-build-v2` 指纹产物和 16 流配置;先验证其 HTTP/2 二进制、TLS 文件和清单,不重建生产产物。 - -### 饱和扫描 - -- 预算:128 MiB -- 路径:`/plain` -- 传输:h2c、TLS+h2 -- 拓扑:16x16(256 请求槽) -- offered rate:30000、45000、60000、90000 req/s -- 每 case:1 秒预热、5 秒测量、2 个 repeat - -若 90000 仍未出现平台,则只报告“扫描上界不足”,不继续无界提高负载。观测平台取成功 QPS 不再随 offered rate 近似线性增长的区间,不把容量丢弃计为服务错误。 - -### 60 秒稳态 - -从扫描得到的 h2c/TLS+h2 较低平台值向下取整到不高于 80% 的明确整数 rate,确保两种传输使用相同负载。128 MiB 和 64 MiB 各运行 h2c/TLS+h2 一个 60 秒 case。99% 成功率门槛只用于证明选定 rate 可持续,不用于定义服务极限。 - -### 连接恢复耐久 - -128 MiB 下,h2c/TLS+h2 各在同一服务进程运行 100 轮;每轮 16 条物理连接、每连接 16 流、0.1 秒、1000 req/s,随后使用既有 0.3 秒断开观测。每轮校验握手、请求错误和 FD 回落,整组检查 cgroup OOM 与 RSS 序列。 - -## 5. 风险与解释 - -- 多线程负载器仍有单一速率调度协程。如果扫描中客户端 CPU 未扩展、dispatch expired 显著而服务端未满 1 核,本阶段应如实判定压测器仍受调度器限制;是否实现分片调度另建任务,不能伪称服务端平台。 -- 客户端和服务端仍共享同一虚拟机,只是 CPU 集合隔离;缓存、内存带宽和宿主机噪声仍然共享。 -- 64 MiB cgroup 的文件页计费受热缓存影响,继续同时报告进程 RSS/PSS 和 cgroup peak,不以任一单值替代另一个。 -- 100 轮是分钟级重复回收证据,不是小时级泄漏或生产网络稳定性证明。 - -## 6. 回退 - -改动不涉及生产代码。若 CPU 集合支持造成回归,回退 Python 运行器、测试和文档即可;已有构建产物和历史报告不修改,新测量始终写入新输出目录。 diff --git a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/implement.jsonl b/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/implement.jsonl deleted file mode 100644 index 63e1bee..0000000 --- a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/implement.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/directory-structure.md","reason":"保持 Python runner、进程采样和 Rust 协议负载的职责边界"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"遵守性能测量公平性、资源预算、报告和最小验证要求"} -{"file":".trellis/tasks/09-13-http2-ceiling-soak/research/client-bottleneck.md","reason":"复用已有多线程能力并避免不可合并的多进程分位数"} diff --git a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/implement.md b/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/implement.md deleted file mode 100644 index 034d3ce..0000000 --- a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/implement.md +++ /dev/null @@ -1,32 +0,0 @@ -# 执行计划 - -## 1. 启动与上下文 - -- [x] 用户确认后运行 `task.py start`;启动前不修改基准源码。 -- [x] 使用 `trellis-before-dev` 重新加载 backend 规范,核对当前 diff、磁盘、CPU、cgroup 和正式构建产物;`build-http2-final` 已不在工作树,改用参数满足需求的 `typed-orm-build-v2`,仍须校验指纹。 - -## 2. 客户端并行配置 - -- [x] 将 `Process(cpu=...)` 收敛为 `Process(cpus=...)`,所有调用者一次性迁移;保持亲和性只作用于自有子进程。 -- [x] 在 `run.py` 增加 CPU 集合解析、集中分配校验、`--client-cpus` 和 `--client-workers`,删除旧 `--client-cpu`。 -- [x] 让 HTTP/HTTP2 与 live 客户端共同使用相同 worker 数和 CPU 集合;更新 report environment/arguments。 -- [x] 清理重复解析与分支,确保进程生命周期、运行器合同和协议负载职责仍分离。 - -## 3. 定向验证 - -- [x] 扩展 `test_runner.py`,覆盖 CPU 集合解析、重复/越界/重叠拒绝、子进程实际亲和性和报告配置。 -- [x] Python 语法解析与 runner 34/34 通过;HTTP/2 产物指纹校验通过,未运行全量测试。 -- [x] `http2-ceiling-smoke-09-18`:h2c/TLS+h2 各 30/30 成功、16/16 握手、FD 差 0、OOM 0,报告确认 4 workers、CPU 1–4、客户端 5 线程。 - -## 4. 有界正式测量 - -- [x] `http2-ceiling-scan-09-18`:128 MiB、16x16、30k/45k/60k/90k、h2c/TLS+h2、5 秒、2 repeats 共 16/16 完成,错误/OOM/FD 差为 0。 -- [x] 30k 档 h2c/TLS+h2 吞吐约 29.9k/29.8k;45k 以上 h2c 约 34–40k、TLS+h2 约 37–39k,服务端接近 1 核、客户端 1.4–2.0 核,请求槽丢弃主导,调度过期很少。28k 的 60 秒首轮分别只有 98.68%/97.91% 成功;24k 的 10 秒校准 TLS+h2 只有 99.18%。20k 的 10 秒校准分别为 99.96%/99.92%,据此将正式共同稳态输入定为 20,000 req/s(低于较低观测平台的 80%)。 -- [x] `http2-ceiling-steady-128m-20k-09-18` 与 `http2-ceiling-steady-64m-20k-09-18`:h2c/TLS+h2 各 60 秒,成功率依次为 99.77%/99.92% 和 99.94%/99.80%,吞吐约 19.95k–19.99k req/s;全部零错误/OOM、FD 差 0。28k 首轮两项不足 99%,保留该报告为探索证据。 -- [x] `http2-ceiling-recovery-09-18`:128 MiB 下 h2c/TLS+h2 各 100/100 轮,分别成功 9,944/10,000 请求,余下 56 次/组为调度过期;每轮至少成功 95/98 个,16 次握手、FD 差 0,请求错误/OOM 为 0。首末轮断开后 RSS 为 4,845,568→5,357,568 B / 5,959,680→6,647,808 B,完整逐轮序列保留。 - -## 5. 收尾 - -- [x] 更新 `test/performance/README.md` 与 backend 性能规范中的 CLI、测量结果和限制;HTTP/HTTPS 30/30、TCP/WS/SSE 16/16 最小相邻入口回归通过。 -- [x] 检查了入口到子进程的 CPU/worker 传递、重复、职责、命名和无关改动;未改生产运行时或覆盖历史报告,空 frontend 模板是单独已归档的 bootstrap 任务。 -- [x] `trellis-check`:runner 定向单测 34/34、Python AST、构建清单指纹、扫描/稳态/恢复报告计数与 OOM/FD/握手不变量、空白检查均通过;HTTP/HTTPS 与 TCP/WS/SSE 最小回归通过。未运行全量测试、Cargo build、rustfmt/clippy;未提交 Git。 diff --git a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/prd.md b/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/prd.md deleted file mode 100644 index 71e4082..0000000 --- a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/prd.md +++ /dev/null @@ -1,42 +0,0 @@ -# HTTP/2 饱和边界与耐久压测 - -## 目标 - -解除现有 HTTP/2 压测客户端的单核限制,在服务端固定 1 CPU、128 MiB/64 MiB、无 swap 的条件下,测量 Dever HTTP/2 小响应的本机饱和边界、60 秒稳态表现和重复连接恢复表现。结果用于判断后续是否存在值得单独优化的生产热路径,不把本机 loopback 数字外推为跨机器或生产环境上限。 - -## 已确认事实 - -- `network_bench` 已使用 Tokio 多线程 runtime,并通过 `BENCH_WORKERS` 控制 worker 数;HTTP/2 请求调度、响应校验、计数守恒和延迟直方图已有单一实现。 -- `test/performance/run.py:258` 把负载端 `BENCH_WORKERS` 固定为 1,`test/performance/process.py:104` 只允许子进程绑定一个 CPU。此前 30000 req/s 的 Dever 4x16 场景中,服务端和客户端均约占 0.9 核,因此现有数据不能区分两端上限。 -- 已构建清单允许 32 条物理连接、每连接 16 流、任务容量 272;16x16 需要 272 个服务任务,正好落在已有容量内,无需重新配置生产运行时。 -- Rust 负载结果只有一个进程内的完整直方图。拆成多个客户端进程后,现有 p50/p95/p99 摘要无法无损合并;使用一个多线程负载进程可以保留现有统计合同。 -- 当前机器允许 CPU 0–4;正式测量可将服务绑定 CPU 0,将负载端限制到 CPU 1–4。现有构建产物生命周期为 3600 秒,足以完成单个 60 秒场景和 100 轮恢复场景。 - -## 需求 - -- 将基准进程的单 CPU 亲和性扩展为明确的 CPU 集合;服务端继续使用单 CPU,客户端可使用多个互不重复且不与服务 CPU 重叠的 CPU。 -- 运行器新增明确的客户端 worker 数和客户端 CPU 集合参数,统一用于 HTTP、HTTP/2 和长连接负载;报告记录实际 worker 数和 CPU 集合。 -- 仓库内调用者一次性迁移到新的客户端 CPU 集合参数,不保留旧 `--client-cpu` 别名或兼容分支。 -- 多线程客户端继续复用一个 `network_bench` 进程、一套请求调度和一组原始直方图;不新增协议实现,不增加多进程结果拼接器。 -- 使用现存 `typed-orm-build-v2` 指纹产物(原 `build-http2-final` 已不在工作树,HTTP/2 配置仍为 32 连接、16 流、272 任务),先对 Dever `/plain`、h2c 和 TLS+h2、16x16 拓扑扫描多个 offered rate,区分客户端限制、请求槽限制和服务端饱和。 -- 根据扫描结果选择不高于观测平台 80% 的整数 offered rate,分别完成 h2c 和 TLS+h2 的 60 秒稳态测量;128 MiB 与 64 MiB 服务预算均覆盖,服务 CPU 固定为 1 核,swap 为 0。 -- 在同一 Dever 服务进程上对 h2c 和 TLS+h2 分别完成 100 轮 16x16 建连、请求、断开,逐轮保留计数、FD 和 RSS 回落数据。 -- 所有正式 case 必须保留请求计数、延迟、服务端/客户端 CPU 与内存、cgroup peak/OOM、握手数和断开后 FD 数据;失败时保留已完成结果与日志。 - -## 验收标准 - -- [x] 定向测试证明进程可绑定 CPU 集合,CPU 参数拒绝空值、重复值、越界值以及与服务 CPU 重叠的配置。 -- [x] 报告中的 `client_workers` 与 `client_cpus` 等于实际配置;负载进程采样可报告超过单核的总 CPU 使用率,且服务端仍只绑定一个 CPU。 -- [x] HTTP/1、HTTP/2 和长连接负载共用同一客户端并行配置入口;现有协议调度、响应校验和直方图实现未复制。 -- [x] 16x16 饱和扫描覆盖 h2c/TLS+h2 和至少四个递增 rate;全部请求计数守恒、请求错误为 0、握手数等于物理连接数、无 OOM,报告能识别吞吐平台或确认扫描上界仍不足。 -- [x] 128 MiB 与 64 MiB 下各完成 h2c/TLS+h2 的 60 秒稳态 case;请求错误和 OOM 为 0,成功率不低于计划请求的 99%,结束后 FD 回到 READY 基线。 -- [x] h2c/TLS+h2 各完成 100 轮 16x16 恢复;每轮至少有成功请求、错误为 0、握手数正确、FD 回到 READY 基线,RSS 序列如实记录且不把短时平台误称为无泄漏证明。 -- [x] 文档记录命令、机器约束、扫描结果、稳态/恢复结果和限制;明确区分本机观测饱和点、可持续负载与跨机器性能。 -- [x] 只运行受影响的 Python 单元测试、最小 loopback smoke、现有产物指纹校验和显式有界压测;不运行全量测试,不接触已有服务,不提交 Git。 - -## 排除项 - -- 修改 `crates/dever-runtime`、编译器、语言 API 或 HTTP/2 生产协议路径。 -- 多进程客户端、跨进程直方图合并、新压测依赖或第二套结果格式。 -- 跨主机、公网、丢包/限速注入、HTTP/3、RFC 8441 或小时级 soak。 -- 预设固定 QPS 门槛、与 Go/Fiber 的跨机器数字比较,或根据一次短测直接修改生产热路径。 diff --git a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/research/client-bottleneck.md b/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/research/client-bottleneck.md deleted file mode 100644 index 719e3d8..0000000 --- a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/research/client-bottleneck.md +++ /dev/null @@ -1,27 +0,0 @@ -# 客户端瓶颈证据 - -## 现有实现 - -- `test/dever-tests/examples/network_bench/load.rs` 从 `BENCH_WORKERS` 创建 Tokio multi-thread runtime,范围为 1–64。HTTP/2 的物理连接、请求 worker、速率调度、响应校验和三组 Histogram 均在该进程内完成。 -- `test/performance/run.py` 的 `load()` 无条件写入 `BENCH_WORKERS=1`,并通过 `args.client_cpu` 把负载进程绑定到一个 CPU;`live.py` 使用相同单 worker/单 CPU 方式。 -- `test/performance/process.py` 的 `Process` 已集中拥有 fork 后亲和性设置,只需把单元素集合推广为调用方提供的集合,不需要新增进程封装。 - -## 现有结果 - -`target/performance/http2-plain-128m/report.json` 中,Dever 4x16、30000 req/s 的三轮结果为: - -- h2c 成功 QPS 29506–29804,服务端约 0.87–0.92 CPU,客户端约 0.89–0.91 CPU; -- TLS+h2 成功 QPS 28673–29865,服务端约 0.91–0.93 CPU,客户端约 0.92 CPU; -- 请求错误均为 0,但存在容量丢弃,因此该档位不能确定是哪一端首先饱和。 - -## 方案比较 - -| 方案 | 优点 | 问题 | 结论 | -| --- | --- | --- | --- | -| 多进程客户端 | 调度器天然分片,可跨多个 CPU | 每进程独立直方图,现有分位数无法正确合并;还需拆分 rate、连接和生命周期 | 本阶段不采用 | -| 单进程多线程 | 已有 Tokio 支持;保留单一计数、校验和直方图;改动只在 Python 配置 | 单一调度协程仍可能成为更高档位瓶颈 | 先采用并用结果验证 | -| 引入 h2load 等外部工具 | 成熟、高吞吐 | 新依赖、响应合同和报告格式不同,破坏现有可比性 | 不采用 | - -## 结论 - -当前最小实验不是重写负载器,而是解除 Python 对已有多线程能力的限制。只有在多 CPU 客户端仍显示调度端瓶颈时,才有证据支持后续分片调度或多进程直方图协议。 diff --git a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/task.json b/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/task.json deleted file mode 100644 index 2613f29..0000000 --- a/.trellis/tasks/archive/2026-09/09-13-http2-ceiling-soak/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "http2-ceiling-soak", - "name": "http2-ceiling-soak", - "title": "HTTP/2 ceiling and soak", - "description": "解除 HTTP/2 压测客户端单核限制,测量单核小内存服务的饱和边界、稳态表现与连接恢复耐久性。", - "status": "completed", - "dev_type": null, - "scope": "test/performance + performance docs/spec; reuse existing network_bench and production runtime unchanged", - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-13", - "completedAt": "2026-09-18", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-04-dever-language-mvp", - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/check.jsonl b/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/check.jsonl deleted file mode 100644 index 34a1998..0000000 --- a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"定向验收与代码审查"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"配置、Model、事务和迁移不变量"} -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"双源码和错误合同"} diff --git a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/design.md b/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/design.md deleted file mode 100644 index d8f815f..0000000 --- a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/design.md +++ /dev/null @@ -1,26 +0,0 @@ -# 设计边界 - -- 复用同一 source/parser/check/native 流程;Markdown 只负责抽取及文档合同,不另建 ORM。 -- Model 字面量约束收敛在已有 normalize_value 所有者;覆盖 default/seed 两种调用者。 -- ORM 错误复用现有 choice/error 隐式失败机制;数据库错误身份不得通过文本猜测,非数据库故障仍走 Fault。 -- 标准库 `dever.database.Error` 对应 runtime ErrorKind 的十个 error 分支,每个保留 message。调用方结果类型可用一个 error-only choice 载荷包装原错误,例如 `error Failed(error: dever.database.Error)`;checker/native/reference 共用捕获映射,显式抛出的外层错误仍保留名义身份,重叠包装及不匹配错误集合均拒绝。 -- 数据迁移扩展已有命名 migration 与参数化 SQL 校验/运行流程,不新增迁移框架。 -- CMS 两套源文件具有相同包名和声明,Markdown 补充所需中文文档;共同测试防漂移。普通 CRUD 直接调用 Model,业务状态校验留在 service。 -- CMS 演示管理员 Seed、编辑注册与文章发布;注册规范化邮箱/显示名并检查必填数据,单次 create 不增加空事务包装。发布事务验证作者 Active,再按 slug upsert。入口首次注册编辑、重复运行复用编辑,稳定输出 users=2/news=1;哈希仅为演示值,不实现登录或密码算法。 -- 旧 examples/dever/cms 移至 examples/cms/dever;其余 dever/markdown 示例整体放 examples/old 下。更新维护中的路径,历史日志保留事实。 -- 基准 Python 驱动按受控测试目录写 config/setting.json,Rust peers 使用统一读取规则;工具链配置不混入业务配置。 -- 不触及 HTTP API 设计、路由、认证协议或新增 API 配置。现有编译器 dever.api 合同快照仍是编译器能力,并非用户延期的业务接口。 - -实现分工:Model/Markdown 与基准配置分别独立处理;主线程负责错误链、迁移、CMS 与集成。相邻文件修改前明确交接。 - -## 命名数据迁移 - -`migrate name` 保留 `drop field`,增加可重复的 `before { sqlite = "..."; postgres = "..."; parameters = [...] }` 与 `after { ... }` 块;这里的分号仅表示文档分隔,实际源码使用换行。每块必须显式给出两个方言与参数列表,参数用现有绑定编码,不做字符串插值。 - -- SQL 只接受一条 INSERT、UPDATE 或 DELETE;扫描器跳过引号/注释后检查首关键字及语句终止符,拒绝多语句、事务控制、DDL、PRAGMA。占位符继续复用现有方言扫描与连续参数覆盖检查。 -- `_dever_`、`sqlite_`、`pg_` 前缀及 `information_schema` 是保留对象,普通、引用和 SQLite 单引号名称都不能出现在迁移 SQL 中;同名业务文本使用绑定参数。PostgreSQL Unicode 转义标识符不接受,防止绕开保留名称检查。 -- 无类型上下文的绑定常量支持 Bool、Int、Text、null 和指数形式 Float;无指数小数属于 Decimal,缺少目标精度/scale 时拒绝,不隐式改为 Float。 -- 已有表先校验已应用迁移与实际 catalog,再按源码中迁移/块的顺序执行全部未应用 before,执行自动结构变更,再执行全部未应用 after,最后 Seed/history。所有步骤在现有单 Model 迁移事务中完成;失败整体回滚。 -- 新表直接建立最终结构和 Seed,登记迁移已应用,不重放旧数据转换。无 SQL 的 drop-only revision 保持原算法;包含 SQL 的 revision 纳入名字、drop、方言文本、参数类型/值、phase 与块顺序,以有边界的规范表示计算,避免拼接歧义。修改或删除已应用迁移继续拒绝。 -- 运行语句放 `Model.data_migrations`,历史 Schema 仍保存声明名、revision、drop;复用 `orm::Value` 和数据库绑定,不新增通用值系统。 -- 事务边界是同一数据库中的单 Model 初始化;跨表变换只能引用届时已存在的表。编译器现有 Model 初始化顺序不变,不承诺跨 Model 原子升级、任意对象拓扑或跨数据库迁移。 diff --git a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/implement.jsonl b/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/implement.jsonl deleted file mode 100644 index efafdc9..0000000 --- a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/implement.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"定向离线验证及测试目录"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"Model、事务、配置与迁移合同"} -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"源码格式、错误和效应一致性"} diff --git a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/implement.md b/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/implement.md deleted file mode 100644 index 903b4d7..0000000 --- a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/implement.md +++ /dev/null @@ -1,38 +0,0 @@ -# 执行记录 - -用户已授权实施;API 明确延期。沿用上一轮审查已验证的缺口。 - -## 顺序 - -- [x] Model 字面量与 Markdown 声明合同、对应定向测试。 -- [x] 基准配置迁移到 config/setting.json,Python/Rust 定向检查。 -- [x] ORM 恢复错误的类型/效应/生成器贯通及事务捕获回归。 -- [x] 命名数据迁移扩展及历史/事务定向回归。 -- [x] examples 重排、CMS 双源码业务实现、路径与文档同步。 -- [x] 双源码 check/run/build 与打包定向验证、独立审查、规范更新。 - -## 验证边界 - -仅当前合同及示例的离线定向测试。SQLite 数据库使用测试临时目录。若需要 loopback 短时 peer 验证,运行前说明;不连接外部数据库、不运行全量集成或压力测试。未安装的 lint 工具如实记录。 - -## 当前证据 - -- Model default/Seed 定向 3/3;Markdown 静态/格式化 18/18(包括新 Model 声明支持)。 -- 基准 runner 37/37;network/live 无网络配置测试 2/2;Rust peers offline check/build 通过。现有根 setting.json 未修改。构建产物协议标记 setting-json-v1,旧产物必须重建。 -- error_effects 原有 8 项通过;新增共享错误包装/native+reference 1 项通过(含显式外层错误身份保持)。 -- SQLite 共享 ORM fixture 通过;新增 NotFound/Constraint 经任务和事务回滚捕获通过,最终记录 0 条。 -- 所有迁移后示例统一合同检查通过。两套 CMS 声明、Model、API、配置 parity 通过。 -- CMS 实际 native 首次运行发现 first() 行解码裸块的 ?/return 错误边界问题,已在共用 decode_included_row 修复;关联查询 native 回归 1/1,通过。 -- CMS CLI/打包验收 1/1(392.43 秒):两格式各 check、2 次 CLI run、build、2 次无 module 独立打包运行,均 users=2/news=1。业务 probe 确认邮箱/显示名规范化,重复注册 Constraint 后数据不增加,禁用作者后发布 AuthorDisabled 且文章不增加。临时项目和 SQLite 已清理。 -- 两套 CMS 经 deverc fmt 整理后,fmt --check 和 parity 再次通过。CMS 基准 fixture 与当前业务入口的静态检查 1/1;旧 system 示例移除配置环境变量后的 native 检查 1/1。 -- 命名数据迁移 7/7(包括真实 native 双版本 SQLite 升级);既有 orm_migration 7/7;最后增加 dollar-quote 回归后,静态/SQLite 7/7、共享 typed SQL 3/3 通过。native 升级未因纯扫描器边界修正重复运行。 -- 默认 core 及 core + PostgreSQL runtime cargo check 通过;最终扫描器修正后再次通过。 -- 独立审查确认 1 项 P2:PostgreSQL SQL 以未闭合 $tag 结束时,then_some 急切切片越界。最小回归先复现 panic,再修正共用扫描器;未闭合 delimiter/body 均给出 C014,合法 Unicode tag 和含 $ 的标识符保留。修复已独立复核,无剩余阻塞。 -- rustfmt/clippy 未安装。性能没有重测,旧 CMS 报告对应旧业务入口,不能替代新实现验收。 - -## 收口 - -- examples 仅保留 cms、old 两个目录:cms/dever 与 cms/md 同步;历史示例位于 old/dever、old/markdown。正式测试仍在 test/。 -- README、LANGUAGE、MARKDOWN-SYNTAX、示例说明和 backend specs 已同步。维护中的路径及配置环境变量搜索无旧入口;历史任务/日志保留原始事实。 -- 本次验收完成。业务 HTTP API 等用户重新设计;真实 PostgreSQL、性能/体积/64/128 MiB 压测不属于本轮验收。命名迁移只保证单 Model 事务,不承诺跨 Model 原子升级。 -- 本地任务未关联 PR;按项目要求不创建 commit,归档和日志均使用 no-commit。 diff --git a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/prd.md b/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/prd.md deleted file mode 100644 index f387625..0000000 --- a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/prd.md +++ /dev/null @@ -1,18 +0,0 @@ -# 双源码 CMS 与语言合同修正 - -## 需求 - -用户要求 examples 最终只有 cms、old 两个目录;cms/md 与 cms/dever 同步实现同一 CMS,旧示例移到 old。API 留待用户重新设计,本任务不实现 HTTP API。 - -承接源码审查:修复 Markdown Model 识别/声明合同、Model 默认值与 Seed 字面量校验、ORM 可恢复错误传播与捕获;补齐命名迁移的数据变换能力;示例与基准配置统一从 config/setting.json 读取;同步过期的语言返回值说明。 - -## 验收 - -- 两套 CMS 执行相同的注册、发布业务,数据库结构和可观察结果等价;重复执行可预测,禁用作者不能发布。 -- 所有旧示例移动到 examples/old;正式测试留在 test;当前代码与文档没有悬空路径。 -- Markdown Model 支持普通 Model 的声明,仍执行文档合同校验。 -- 不合法 Int/Float/Decimal/Text 默认值与 Seed 在编译期拒绝,不推迟到 Rust 编译或生成器 panic。 -- ORM 故障保留错误类别,进入既有隐式失败传播与 result 捕获合同;事务边界不抹掉错误。 -- 命名迁移支持参数化、按数据库方言选择的数据变换;事务、历史一致性约束不降级。 -- 无应用/基准配置环境变量入口;保留构建工具自身环境及通用 process.environment 语言能力。 -- 定向离线检查与最小测试通过,明确未运行的验证。不做全量测试或性能重测,不改全局工具、不提交 Git。 diff --git a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/task.json b/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/task.json deleted file mode 100644 index 3ad2c02..0000000 --- a/.trellis/tasks/archive/2026-09/09-18-cms-dual-source-contracts/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "cms-dual-source-contracts", - "name": "cms-dual-source-contracts", - "title": "双源码 CMS 与语言合同修正", - "description": "CMS 的 Dever/Markdown 双实现、旧示例归档和已确认语言合同问题;API 延后", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-18", - "completedAt": "2026-09-18", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-04-dever-language-mvp", - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/check.jsonl b/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/check.jsonl deleted file mode 100644 index 1cb58ac..0000000 --- a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused CMS/compiler/runtime verification"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"No junk layers and dual-source ownership"} -{"file":".trellis/spec/backend/error-handling.md","reason":"Business/API/Job failure flow review"} diff --git a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/design.md b/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/design.md deleted file mode 100644 index c962ea0..0000000 --- a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/design.md +++ /dev/null @@ -1,24 +0,0 @@ -# CMS 业务闭环设计 - -## 复用与依赖 -保留路径角色、生成入口与核心 RBAC。认证走配置站点/account.verify,权限目录自动生成,不新增身份注入。跨领域只调用 App。 -依赖单向:content.revision、publishing.schedule 调用 news.article;news.article 可依赖 content.category、media.asset、audit.operation,不反向调用 revision/schedule。修订拥有编辑编排,文章拥有作者、状态和版本规则。普通 CRUD 保留生成 REST。 - -## 数据与行为 -文章增加可空分类/媒体引用及受保护版本;关联校验复用叶领域 App。修订调用文章受约束更新再保存快照,复用同一租户事务;使用现有条件 update 的 affected rows 判断竞争,不用 count+1 分配版本。 -手动与定时发布共用内聚实现;手动重复保持冲突,任务在已完成状态幂等成功。定时创建验证真实作者,保存必要业务引用并使用 enqueue_at。Worker 仍由核心重新验证可信身份和权限,payload 不能成为认证来源。 -API/Job 保持薄适配。数据库回滚不等于任意文件回滚;区分 Upload 临时资源与已提交存储文件。 - -## 测试分层 -- 应用源码测试验证 App/Domain 和正常存储结果,用例由运行器隔离;错误、权限和会话失效通过真实 HTTP 验证。Test/Job 不能调用身份 getter,不增加后门。 -- 自有 HTTP 验收使用复制的 CMS、临时 SQLite/配置、随机 loopback 端口、真实登录与角色及正常 Worker。 -- 复用 test/performance/cms.py 客户端与现有过程 owner;业务验收留在根 test/,不启动压测。 -- 等价检查覆盖声明、Model/API/Job/Port 和设置,Markdown 保留真实文档合同。 - -## 变更边界 -主要修改 examples/cms 双源码与测试、根 test/ 相关验收和 examples/README.md;复用编译器/runtime,默认不重建发行包或升级依赖。 -改前备份:target/cms-workflows-before.v1FzWO/source.tar.gz。 - -## 已证实的核心阻塞 -- SQL 返回同领域 App View,复用既有行解码;拒绝非存储类型、private 字段和未经解码证明的字段 bounds。仅两个方言均为完整单表简单投影时证明只读,其他 SQL 保持 write 效果。 -- 可信用户/租户 ID 可在明确 nullable ModelId 上下文中保持名义类型,API 与 REST 均按当前 Provider 的 verify 字段验证,不把 Int 任意转换成 ID。CMS 直接读取已验证身份,避免租户写入链重读全局 Session;保留跨库事务禁止规则。 diff --git a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/implement.jsonl b/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/implement.jsonl deleted file mode 100644 index 2bcf7df..0000000 --- a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Final application role/API/Job/visibility contract"} -{"file":".trellis/spec/backend/database-guidelines.md","reason":"CMS Models, transactions, migrations and test isolation"} -{"file":".trellis/spec/backend/logging-guidelines.md","reason":"Audit and secret-free request logging"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Runtime modes, Port/Job/API standard packages"} diff --git a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/implement.md b/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/implement.md deleted file mode 100644 index 8140170..0000000 --- a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/implement.md +++ /dev/null @@ -1,40 +0,0 @@ -# CMS 业务闭环实施记录 - -## 2026-10-04 基线 -用户批准本轮实施。旧勾选不代表当前业务验收完成:每套45个生产文件/12领域,3个应用测试中2个固定字符串断言;cms_acceptance只比较API/Model。定时发布用了enqueue而不是enqueue_at,修订版本用count+1。此前真实PG/RBAC/租户和核心Job验收有效,但不代替CMS业务用例。 - -## 执行顺序 -- [x] 更新要求/设计/上下文,保存改前备份。 -- [x] 分类/媒体关联、文章版本竞争、修订事务。 -- [x] 到期入队、共享发布和任务幂等。 -- [x] 替换空测试、同步Markdown、完善等价与CLI预期。 -- [x] 有界HTTP验收:身份权限、编辑冲突、上传、到期/重试/回滚。 -- [x] 两套check/fmt/test、相关Rust/Python检查和真实验收。 -- [x] 独立复核,修复阻塞,更新示例与记录。 - -## 验证约束 -磁盘约462MiB空闲,复用target/debug/dever和runtime pack,Cargo单并发。自有HTTP/Worker前说明;不连真实数据库,不运行全量测试/压测,不变更全局命令/服务。配置只在自有临时项目写config/setting.json;子进程有超时与清理,分别记录通过/失败/未运行。 - -## 结果 -本轮业务闭环已完成。真实HTTP、CLI、核心约束回归、独立复核和静态质量门均通过;未执行范围外的全量CI、真实PG或压测,不将当前结果当作这些验证的替代。所有改动保留在工作区,未创建Git提交。 - -## 已完成的定向证据与直接阻塞 -- 两套源改为46个生产文件+5个真实应用测试;51对源码声明一致,check/fmt及各5/5应用测试已通过。源测试验证正常业务输出,拒绝和失效放在真实HTTP验证,不伪造认证上下文。 -- Python CMS调用迁移单测12/12;SQL View/字段范围/跨域约束4/4;API声明与GET只读SQL规则18/18;CMS语义/配置/测试等价2/2通过。 -- HTTP第1轮在build发现published_detail误删既有业务校验,已恢复;第2轮构建成功,但bootstrap启动拒绝global Session读取与tenant Article写入同一事务。日志保存在target/cms-business-acceptance-{1,2}/,尚未进入HTTP业务断言。 -- 直接语言修复:SQL可返回同领域App View,普通SQL结果record拒绝未经数据库解码证明的bounds;仅完整自有表简单投影可证明只读,两方言都通过才允许GET,其他SQL保留write效果。复用现有类型/行解码/事务,不增依赖和运行时ABI。 -- 已修可信身份的名义ModelId取值,以已验证的auth metadata替代业务重复读取global Session;不放宽跨库事务,不将模型ID改成Int。 -- 第3轮真实HTTP/Worker验收10组全部通过,report在target/cms-business-acceptance-3/report.json:真实登录/角色拒绝、上传清理、关联/非作者/过期版本、修订晚失败回滚、两请求单胜者、发布快照与晚失败回滚、未来到期/同刻任务、完成任务重放、失败重试、撤权阻断任务、会话注销/过期与站点隔离。fixture程序8,465,384 bytes,临时配置/DB和进程已清理;非压测。 -- 独立审查确证REST字段create/replace也可产生typed身份getter,原新增validator只遍历显式API;现已用同一IdentityContext校验API、REST create/replace/search与名义ID owner。新增正反例、跨站点provider错配、native/LLVM生成验证。完整API目标26/26通过,原错误fixture被CLI明确C006拒绝后已清理。普通Int和nullable边界保留。 -- 最终源码等价2/2、typed_sql 4/4、Python CMS调用单测12/12。CLI精确用例2/2:双格式各5个应用测试各运行两次(故意阻断部署DB,证明测试隔离),check/run/build及无源码打包运行;混合6用例验证仅数据库用例初始化临时DB。更新了该混合用例残留的旧3测试预期。 -- HTTP最终运行器显式关闭SQLite连接;复用已构建程序复验10组全部通过,最终报告target/cms-business-acceptance-final/report.json。不改源码/部署配置,不遗留HTTP/Worker/测试进程。此结果不覆盖真实PG、浏览器HTTPS或性能/长压测。 -- 两套最终check/fmt通过,check各有7条W001未读取返回值提示,非错误;语言只允许零输出调用作为动作语句,未用虚假读取或抑制消除提示。Rust改动文件rustfmt --check通过。 -- 定向clippy通过(dever-core/dever-tests/dever-cli,lib、dever bin及api_declarations/orm_native_sql/contract_execution/cms_acceptance/cms_project,sqlite feature,-D warnings)。最终diff检查通过。独立复核指出的SQL bounds和REST身份绑定缺口均修复并保留回归;主线程确认实际测试输出。任务直接在既有main工作区完成、没有PR分支,归档使用skip-branch-validation且no-commit。 -- 磁盘紧张时暂移的可再生成target/native-artifacts已压缩为target/cms-workflows-before.v1FzWO/native-artifacts-cache.tar.xz(约190MiB)。先逐文件比较,再验证重压缩前后tar SHA256一致(675338b0d4af58b76689ae3ec9bc2c7202a1b5aa3e3f117d0df5930f7e88a7d0);原路径恢复普通空缓存目录,软链和自有内存盘临时副本均已清理。源码、数据库和其他服务未动。 - -## Bug Analysis: SQL投影与业务集成边界 -1. 根因:跨层合同与测试覆盖缺口。私有Model不能穿越App边界,但SQL结果又只能是Model内部record;查询不能直接返回已定义的App View。数据库decoder也不会证明源级bounds。 -2. 失败尝试:只开放同域私有record引用仍会触发公开App签名约束;把Session重新读进文章调用链则实际触发跨库事务限制。不能通过放宽隐私或事务检查解决。 -3. 防止复发:共享SQL result检查同时验证归属、字段类型/可见性和bounds;GET效果采用完整受限语法证明,保留反例;HTTP按正常入口启动、验证完整提交与回滚。 -4. 扩展核对:双源码、旧CMS性能/PG调用方及CLI测试预期同步迁移;原SQL私有record同样拒绝未证明bounds。 -5. 已更新backend/database-guidelines.md和LANGUAGE.md;本仓库无对应spec模板副本,不创建;按用户约束不提交Git。 diff --git a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/prd.md b/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/prd.md deleted file mode 100644 index 811bb80..0000000 --- a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/prd.md +++ /dev/null @@ -1,25 +0,0 @@ -# 双源码 CMS 业务闭环验收 - -## 当前目标与授权 -2026-10-04 用户批准继续完善 CMS:替换空断言,贯通分类、文章、修订、媒体和定时发布,验证权限拒绝、并发冲突、重试与回滚。沿用本任务;旧规划中的手写 main、Principal 入参、业务 RBAC 和旧命令名已被后续语言合同取代,不恢复旧实现。 - -## 要求 -- 两套示例保持业务声明、Model/API/Job/Port 和测试等价。 -- 复用现有 ORM、自动权限、database-only 租户、Upload/Storage Port 和延时 Job;业务规则留在 App/Domain,不绕过真实身份。 -- 分类与媒体可关联文章,创建/编辑时校验。修订快照与文章更新同租户事务;过期版本或并发竞争明确冲突,不丢失更新。 -- 手动发布保持作者校验;定时创建验证作者和文章状态,按真实到期时间执行;重复任务不重复发布/审计,失败不留下部分完成状态。 -- 普通应用测试只用运行器临时 SQLite、结果捕获和 fake,不加身份后门、不读部署配置。认证、租户、上传与 Worker 由自有 HTTP 验收覆盖。 -- 两个固定字符串断言必须删除或改为真实业务测试;check、健康接口、快照不代表业务验收。 -- 配置只用 config/setting.json,不增加环境变量、权限表或框架层。 - -## 验收 -- [x] 两套 check/fmt、应用测试和语义等价通过。 -- [x] 分类/媒体关联、修订编辑、发布快照形成完整链路。 -- [x] 未授权/非作者请求失败且无写入,保留即时撤权。 -- [x] 并发/过期修订只有合法更新成功;失败回滚文章和修订/审计。 -- [x] 任务不提前运行,到期发布、重复执行、失败回滚/重试有真实断言。 -- [x] 上传成功与受限/失败路径验证文件、临时资源归属。 -- [x] 定向 build、自有临时 HTTP/Worker 验收通过,记录范围和限制。 - -## 范围外 -前端、富文本/搜索产品、外部云服务、公开发行、ARM、全量 CI 和长压测。仅确证阻止本任务的缺陷才修改语言核心。 diff --git a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/task.json b/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/task.json deleted file mode 100644 index 2de2244..0000000 --- a/.trellis/tasks/archive/2026-10/09-20-large-cms-acceptance/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "large-cms-acceptance", - "name": "large-cms-acceptance", - "title": "Dever 大型双源码 CMS 验收", - "description": "扩展 Dever 与 Markdown CMS,验证大型项目的安全、Port、Job、API 和测试合同", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P1", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-09-20", - "completedAt": "2026-10-04", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": "09-20-production-application-language", - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/check.jsonl b/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/check.jsonl deleted file mode 100644 index 2f6fc4f..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/check.jsonl +++ /dev/null @@ -1 +0,0 @@ -{"file": ".trellis/spec/backend/quality-guidelines.md", "reason": "定向离线验证与临时目录边界"} diff --git a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/design.md b/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/design.md deleted file mode 100644 index 99043d1..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/design.md +++ /dev/null @@ -1,9 +0,0 @@ -# 设计 - -- `skills/` 为可独立复制/后续建 Git 的 skill 根目录,包含 SKILL.md、按需语言/安装参考、共享模板资源。名称 dever-language,避免与 shemic-dever Go skill 混淆。 -- CLI 复用该目录的模板字节,生成器拥有文件系统发布边界;新项目使用 app + cmd API + 零输入测试,不生成 main/package/expose 或无用业务分层。 -- new 属于非项目命令,机器启动器使用活动核心;模板与发行核心版本一致。 -- skill 纳入发行签名清单并由版本库管理。安装和更新沿用现有机器权限、锁、暂存、校验和恢复机制;可发现路径必须随活动版本切换,不要求每个项目复制或手动更新技能。 -- 明确区分独立 skill 安装、机器 Dever 安装、应用依赖准备。官方发行源内置为 GitHub shemic/dever-main Releases,不读取业务配置或环境变量。Git 仓库和公开二进制资产区分,未发布资产时明确报错。 -- 安装到 AI 的稳定 skill 入口先执行绝对机器启动器的 `skill path`,再加载活动版本的完整 skill。继续保留唯一 active-version journal 提交点,避免核心和 skill 双指针更新撕裂。 -- 实施前保存涉及源码的自有备份;并行任务按文件归属分工,Cargo 验证由主代理串行执行以控制磁盘。 diff --git a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/implement.jsonl b/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/implement.jsonl deleted file mode 100644 index e70eb0d..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/implement.jsonl +++ /dev/null @@ -1 +0,0 @@ -{"file": ".trellis/spec/backend/toolchain-and-library.md", "reason": "CLI、发行与共享机器契约"} diff --git a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/implement.md b/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/implement.md deleted file mode 100644 index 7eabd79..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/implement.md +++ /dev/null @@ -1,34 +0,0 @@ -# 实施记录 - -状态:实现与定向验证完成。核心工作提交 ac458ff,独立 skill 提交 9fd78fc;本任务按用户授权向两个指定仓库发布源码。 - -1. CLI 新建项目与共享模板。 -2. 独立开发 skill、安装/更新引导和语言参考。 -3. 发行包携带 skill,机器安装与同步更新集成。 -4. 定向测试、真实模板 CLI 验证、失败保护和独立 skill 校验。 - -实施前现状:机器 update 仅消费本地 downloads/latest,当时尚无 new 和发布 skill;磁盘约213MiB可用,因此本次Cargo验证串行执行。 - -## 已完成 - -- CLI `new [--markdown]`、单一模板资源和两种等价源码格式;新目录原子发布,拒绝已有目录/文件/链接,覆盖并发失败保护。 -- 独立 dever-language skill,含语言/架构/接口/数据/权限/租户/库/Markdown/安装参考,项目 AI 指引,官方源安装脚本。SKILL 元数据校验通过。 -- core 主仓库和 skills 独立仓库采用用户指定 SSH remote;主仓库固定 skill submodule。官方更新地址内置 GitHub Releases,已撤销放入配置文件的早期提议。 -- 发行 maker 将完整 skill 加入签名清单;`skill path [project-root]` 按活动/固定版本只读校验;`skill install` 安装永久薄入口,不单独维护可失配的技能版本指针。 -- 官方下载先验签,限制源/重定向/大小/归档成员,校验完整包后发布;更新和安装不读取业务配置或环境变量。损坏包保留旧活动版本。 -- Python 首装助手复用已有 bootstrap,官方资源制作工具发布三个确定性资源,Linux NOREPLACE 防止覆盖并发目标。测试仅在自有目录,首装脚本的最终 bootstrap 为 mock,未触碰宿主安装/服务。 - -## 验证 - -- Rust new_project:4/4;release_source:7/7(含自有 loopback 下载/坏签名/坏内容);shared_toolchain 定向:3/3(完整版本切换、坏skill、真实降低UID读取)。 -- native_release 两项 maker 定向:2/2(缺skill/超限拒绝,确定性完整签名)。共16项Rust定向通过。 -- Python安装/资产定向:8/8;包含独立临时密钥签名、拒绝缺skill、归档坏尾/重复/链接/unsigned、镜像配置/清理和发布竞态。 -- 独立按skill执行普通/Markdown项目14项new/check/fmt/test/run/build/独立程序命令全部成功;各1个应用测试通过,4次原生执行JSON为code=0、data=Hello, Dever。主代理再次生成Markdown项目并原生run得到相同结果。 -- rustfmt已应用;定向clippy对lib、core/launcher、新项目/共享工具链/发行测试通过 -D warnings;skill validator通过。 -- 未跑全量CI、压测、真实数据库或全局安装;未发布正式二进制资产,不能将源码push当作发行完成。官方GitHub两个仓库初始为空,core仓库已确认public。 - -## 本机保留 - -- 改前源码备份:target/onboarding-before.Vgoy97/source.tar.gz。 -- 新官方发行公钥仅公开pub,私钥留在被忽略的本机目录;已验证PKCS#8 v2符合maker并匹配skill公钥,不打印/提交私钥。 -- 为有限磁盘验证临时移走的6份旧CLI缓存已归档为 target/onboarding-before.Vgoy97/superseded-cli-cache.tar.gz(约21MiB),可恢复;本次自有临时目录已清理,未删除业务数据。 diff --git a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/prd.md b/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/prd.md deleted file mode 100644 index 3dca818..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/prd.md +++ /dev/null @@ -1,16 +0,0 @@ -# Dever 开发入口 - -用户已授权实施:独立 `/data/project/dever/skills`、开发指引、新项目模板、`dever new`、安装引导以及 `dever update` 同步更新语言和 skill。 - -## 验收 - -- skill 根目录可独立分发,名称 `dever-language`,不依赖本机源码绝对路径,不混入 Go 框架规范;指导 AI 安装、编写、检查、测试和构建 Dever 应用。 -- `dever new [--markdown]` 生成最小可运行 CMD 项目、配置、项目 AI 指引和定向应用测试;两种源码格式共享语义,无数据库、鉴权或第三方工具前提。 -- 新项目目录不得覆盖已有内容;机器启动器创建新项目不读取尚不存在的项目配置。 -- 语言和 skill 共用版本发行、完整性校验及更新失败保护;支持一次安装后持续获取活动版本的 skill。 -- 应用配置只来自 `config/setting.json`,不用环境变量。用户已指定官方核心仓库 `git@github.com:shemic/dever-main.git` 和独立 skill 仓库 `git@github.com:shemic/dever-main-skills.git`。发行地址是工具内置元数据,禁止写入业务项目配置。 -- 定向验证模板 check/fmt/test/run/build、安装/更新后 core 与 skill 一致、损坏输入不破坏旧版本。仅使用自有临时目录/安装镜像,不安装全局服务、不替换全局命令。用户已授权两个指定仓库提交并 push;skill 是独立 Git,核心使用 submodule 固定对应提交。 - -## 现有缺口与边界 - -复用 CLI、共享机器版本库、签名发行作者、既有 bootstrap 安装和项目命令分派。当前没有 new;update 仅选择 downloads/latest 的核心,不交付 skill。普通应用配置、语言语义、Go front、其它平台发行、全量 CI 和压测不在本任务范围内。 diff --git a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/task.json b/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/task.json deleted file mode 100644 index 4db7b6d..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-developer-onboarding/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "developer-onboarding", - "name": "developer-onboarding", - "title": "Dever 开发 skill、新项目模板与统一更新", - "description": "实现独立 Dever language skill、可验证新项目模板、dever new,以及沿用共享机器安装的 core/skill 成套更新和安装指引。", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-10-04", - "completedAt": "2026-10-04", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-10/10-04-external-command/check.jsonl b/.trellis/tasks/archive/2026-10/10-04-external-command/check.jsonl deleted file mode 100644 index 696b7ce..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-external-command/check.jsonl +++ /dev/null @@ -1,3 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"定向验证、真实执行和资源所有权"} -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"命令合同不得扩散到API和Worker"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"打包闭包与沙箱完整性"} diff --git a/.trellis/tasks/archive/2026-10/10-04-external-command/design.md b/.trellis/tasks/archive/2026-10/10-04-external-command/design.md deleted file mode 100644 index e22fe93..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-external-command/design.md +++ /dev/null @@ -1,36 +0,0 @@ -# 普通二进制调用设计 - -## 源码合同 - -Adapter:`external command "bin/tool" { allow file }`,路径沿用领域相对资源路径,allow 沿用现有能力名。不接受 setting/lib;部署配置和授权沿用已有 adapter 节点。 - -每个 command Adapter 对应一个只有一个操作的 Port,操作名按业务自定:`execute(args: List, stdin: Bytes?) (output: dever.process.Output) fails dever.process.Error`。第二个 stdin 参数允许整项省略(仅 args),传 null 表示立即关闭 stdin。固定字段名防止增加映射 DSL。标准 Output 是 `{code: Int, stdout: Bytes, stderr: Bytes}`;标准 Error 是 `error Failed(message: Text)`,满足现有 Port failure 合同。命令非零退出按沙箱传播的退出码返回,不猜测 signal;启动/超时/超限继续作为源位置 runtime fault。 - -## 编译器与进程边界 - -新增 ExternalEcosystem::Command,保留现有 external 合成函数、Port fake、effect 和 suspends 链路。共享 wire 增加仅 Command policy 可用的 Bytes/base64;API/Job/真实 Worker 原有 wire policy 不变。两个后端仍用同一 external start/call/reply ABI,只给 Bytes wire 增加最小桥接函数。 - -HIR 共用合同构造实现,但 external_worker_contracts 只返回 exec/pip/npm/go,external_command_contracts 返回 command,避免 Lib lock/resolver 散落 command 特判。command 不需要 dever.lock;有真实生态依赖的同项目仍保持原 lock 行为。 - -## 运行时 - -复用 invocation Session、Managed、registry、bounded requests 和 structured Scope。command supervisor 启动不执行二进制或协议握手;收到每个请求才启动一个独立沙箱进程,并发写 stdin、读 stdout/stderr 和等待退出。不追加 --dever-component,不重放命令。超时、调用取消和关闭均 kill/wait,再返回结果;空闲 supervisor 可继续服务后续请求,不为正常多次调用套用 Worker crash restart 次数。 - -复用 verified extraction、launch manifest owner 和 sandbox Launch。内部资源 argv 继续映射,动态调用 argv 作为普通数据追加,不当宿主路径重写。保留只读程序树、grant、namespace/seccomp 与空环境。沙箱 PID namespace 负责后代收束,测试必须观察真实后代清理。 - -限额来自 config/setting.json 的 `adapter..command`:timeout_ms(默认30000,最大3600000)、output_limit(默认1048576,最大8388608,两路输出合计)。argv 总量最多65536字节,stdin最多8388608字节;拒绝NUL。base64膨胀及JSON包装不得超过已有16MiB wire上限。Worker Adapter 不使用这组命令限额。 - -## 离线打包 - -CLI 专门 command packager 接受一个 ELF 文件及同目录 lib/ 中的普通库文件;只采集所属项目/Package 的显式资源,不扫描宿主或调用 ldd。静态 ELF 可直接运行。动态 ELF 复用签名 sandbox GNU loader/OS库,递归解析 DT_NEEDED、验证目标、SONAME和版本需求,私有库按随附 lib/ 查找,缺少依赖构建期报错。共享已有 Python native ELF 闭包校验算法,不复制第三套解析器。使用固定私有 loader 参数关闭系统 cache,库搜索受打包树与sandbox库限制。 - -资源沿用SHA、私有原子提取、缓存/签名和Package归属验证;每次启动重新校验。具体 launch manifest 字段按既有owner扩展,不能从运行配置接受任意可执行路径。 - -## 改动边界 - -- core syntax/parser/check/ports/hir/wire/native/llvm,library/dever/process.dever,以及 wire runtime/bridge:一条类型与调用合同。 -- runtime component/command/external/config 与 sandbox:一次调用的进程和资源生命周期。 -- CLI workers command/ELF依赖、libs资源准备:离线可执行资源闭包。 -- 根test、LANGUAGE/README和已有规范:真实证据和可用示例。 - -不增加通用执行注册中心、新依赖、第二套SDK/JSON引擎,不改CMS业务。回滚按上述拥有者整体撤销本任务差异,保留开始前源码备份与用户已有改动。 diff --git a/.trellis/tasks/archive/2026-10/10-04-external-command/implement.jsonl b/.trellis/tasks/archive/2026-10/10-04-external-command/implement.jsonl deleted file mode 100644 index 3b4915d..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-external-command/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/index.md","reason":"Rust语言仓库开发边界"} -{"file":".trellis/spec/backend/compiler-contracts.md","reason":"Port/Adapter和两后端的类型与失败合同"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"外部资源、沙箱、目标与生命周期"} -{"file":".trellis/spec/backend/error-handling.md","reason":"源位置错误和资源清理"} diff --git a/.trellis/tasks/archive/2026-10/10-04-external-command/implement.md b/.trellis/tasks/archive/2026-10/10-04-external-command/implement.md deleted file mode 100644 index 19138e3..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-external-command/implement.md +++ /dev/null @@ -1,56 +0,0 @@ -# 实施与验证 - -## 执行顺序 - -1. [x] 读取规范、调查编译/运行/沙箱/打包,固定用户已确认范围和合同。 -2. [x] 备份当前源码;并行实施编译器合同及runtime进程执行,主线程实现CLI资源打包。 -3. [x] 串行运行必要offline Cargo检查和定向测试;修复真实失败。 -4. [x] 用独立ELF与真实Dever源码验证check/run/build、移除源码运行、动态库、取消和完整性;验证ARM目标。 -5. [x] 独立Trellis复核、清理本任务冗余、更新语言规范及验证证据,归档;不提交Git。 - -## 所有权 - -- 编译代理:core、library/dever/process.dever、runtime/wire.rs、bridge ffi/runtime.h、对应编译/codec测试。 -- runtime代理:runtime component/command/external/config、sandbox及进程测试,不改wire.rs和CLI。 -- 主代理:CLI workers/libs/ELF闭包/Package必要集成及测试、任务/文档、全部Cargo和重资源验证。 - -代理不并行运行Cargo,不覆盖其他代理或用户改动。涉及共同合同先沟通。 - -## 验证原则 - -仅本任务所需定向检查,无全量测试/业务服务/长测;提前说明自有沙箱进程测试。先check与轻量测试,后更新实际runtime ABI再运行真实源码,不能用旧archive验证新codec。开始可用磁盘约3.3GiB,复用现有目标目录,串行构建。 - -预期目标:port_adapter、command专用runtime/CLI测试、external_workers/resources、llvm_external_source中command案例;原Worker回归按实际共享代码影响选择。fmt/clippy只覆盖改动所属目标。错误、跳过和未运行独立记录。 - -## 最终证据 - -- 改动前备份:`target/external-command-before.lBL9wU/source.tar.gz`。 -- CLI/core/runtime 初次 offline check 已通过;command 编译/codec/format/fake 5项通过。 -- external_workers 当前13项通过,10项需特定资产的旧真实生态测试未运行。command 打包4项通过,后续新增越界 RPATH 回归需复验。 -- runtime 首轮3过5失败为未优化debug哈希耗时超过fixture启动等待;作者构建为sha2/miniz_oxide/flate2指定opt-level=3,测试等待与命令deadline分离。随后即时文件锁断言揭示真实namespace清理竞态:管道EOF早于内核后代回收。最终改为info-fd + block-fd门禁,在放行guard前pin namespace pidfd并核验PPid,取消等待pidfd readiness后回收wrapper。9/9定向测试通过(17.86s),包括启动错误、无FD泄露、非零1/127、输入输出、限额、取消/超时/root close/queued/explicit shutdown。 -- 独立复核发现启动失败与非零退出混淆、RPATH越出程序树两项问题;已修复,复核确认无剩余阻塞。新增RPATH回归4/4及共用Python ELF闭包2/2通过。 -- 旧 Port 原生测试先因测试作者 rustc 路径缺失中断;指定作者工具路径后相关测试运行,期间新增sandbox直接依赖导致 --locked 拒绝。Cargo offline check已增量更新锁,不升级第三方包;最终21/21复验已关闭这些失败。 -- 新runtime ABI archive已离线重建(runtime-api/external/sqlite/postgres,3m25s),真实LLVM/CLI验收使用该新档案;未连接任何数据库。改动Rust格式检查及C fixture语法检查通过。 -- LLVM command对象+真实调用2/2通过(102.33s);六目标对象生成,预热+64轮每轮3次普通程序调用,二进制/EOF/退出7和allocation ledger全通过。初次60s fixture预算仅完成42轮,给command probe单独180s预算后保留全部65轮与相同断言;原Worker预算不变。 -- native_runtime_link 的Bytes wire C ABI验收1/1通过(7.18s)。 -- signed_cli_runs_and_packages_ordinary_command_with_private_library 1/1通过(172.02s):当前核心和新ABI、真实C动态工具+私有.so、check/run/build、无Lib锁、Package锁定资源、删除项目/作者/机器目录后两种产物独立运行、篡改.so拒绝。所有daemon/程序均为自有临时fixture,未安装全局命令。 -- 最终旧Worker生命周期1/1、external_resources 8/8通过;1项旧Rust bootstrap打包用例维持ignored,本次已有新的真实LLVM/签名CLI独立打包证据。 -- 最终Port/Adapter(包含普通/fake实际原生执行)21/21通过(103.41s),此前作者路径/锁文件导致的失败已全部关闭。 -- Linux ARM64 runtime-api/runtime-external桥接库、runtime、sandbox/guard 交叉cargo check通过(65s);结合六目标LLVM对象生成与CLI跨目标打包/拒绝错架构验证。未重发四个ARM发行profile、未运行ARM实机/虚拟机验收,不能将这些检查表述为ARM执行通过。 -- 所有改动所属库、guard及6个相关测试target的clippy `-D warnings`通过(45.21s);Rust定向fmt和C语法检查通过。git diff --check通过但本仓库核心文件为untracked,实际差异还通过改动前tar对比、逐文件检查与独立复核覆盖。 - -## 最终检查入口 - -Cargo均为offline、单并发,不使用全量测试。作者工具路径仅影响构建/验证进程,未加入应用环境配置。作者测试使用`profile.dev.package.{sha2,miniz_oxide,flate2}.opt-level=3`减少大量重复资源校验耗时。 - -- `dever-tests --features external --test port_adapter`:21通过。 -- `dever-tests --features external --test external_command`:9通过。 -- `dever-tests --features external --test external_component --test external_resources`:1+8通过,1旧bootstrap用例ignored。 -- `dever-cli --test external_workers`:13通过、10个旧真实生态fixture ignored;最终command过滤4通过。 -- `dever-cli --test external_libs wheel_tests::native_`:2通过。 -- `dever-backend-bridge --features embedded,runtime-external --test llvm_external_source command_ -- --include-ignored`:2通过。 -- `dever-backend-bridge --features embedded,runtime-external --test native_runtime_link wire_codecs_validate_slots_before_callback_and_release_partial_values -- --ignored --exact`:1通过。 -- `dever-cli --test native_release signed_cli_runs_and_packages_ordinary_command_with_private_library -- --ignored`:1通过。 -- ARM交叉check使用现有`target/arm64-cross`作者sysroot/工具,profile runtime-pack,target aarch64-unknown-linux-gnu;检查sandbox和bridge runtime-api/runtime-external。 - -未运行:全量测试、长压测、真实数据库、ARM目标执行及Windows;未替换全局安装或修改主机策略。当前无已知本任务阻塞。原有两篇tracked文档删除及其他既存任务保持原状。 diff --git a/.trellis/tasks/archive/2026-10/10-04-external-command/prd.md b/.trellis/tasks/archive/2026-10/10-04-external-command/prd.md deleted file mode 100644 index 5bddc0d..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-external-command/prd.md +++ /dev/null @@ -1,33 +0,0 @@ -# Linux 普通二进制调用 - -## Goal - -在 Port/Adapter 下直接执行现成 Linux 二进制,支持参数、标准输入输出、退出状态、超时取消及独立打包 - -## 已确认范围 - -用户已在上一轮审阅普通命令调用、Port/Adapter、参数数组、可选标准输入、两路输出、退出码、超时取消、二进制与动态库打包、Linux x86_64/ARM64、无 shell/env 的方案,并批准创建任务、规划和实施。本任务不再次请求相同授权。 - -## 需求 - -- R1:直接调用现成 Linux ELF,无需程序实现 Dever 协议或用户编写其他语言包装;Port/Adapter 保留唯一外部调用边界。 -- R2:参数按数组原样传递,标准输入可省略;输出不丢失非 UTF-8 字节,正常非零退出码属于结果。 -- R3:启动失败、超时、取消、输出超限明确处理;每次调用均回收自有进程及沙箱后代,不自动重试命令。 -- R4:run/build 离线准备并嵌入程序和显式随附的必要动态库;检查目标架构、依赖闭包和完整性,部署不依赖源码/机器缓存/宿主语言工具。 -- R5:继续使用 config/setting.json 管理部署文件授权和调用限额,不添加环境变量或 PATH/shell 查找。复用现有沙箱,不修改宿主策略。 -- R6:保持现有 exec/pip/npm/go Worker 合同;普通 Dever 测试继续 Port fake,不执行真实命令。兼容 Package 资源与 Markdown 源码。 - -## 验收 - -- [x] 编译检查并格式化合法 command Adapter;拒绝错误 Port 签名、额外操作、setting/lib 和非法路径;其他 wire 边界仍拒绝 Bytes。 -- [x] 真实无协议 ELF 收到空格、引号、shell 元字符和绝对沙箱路径原文;stdin EOF、二进制输入输出、两路并发大输出、正常非零退出正确。 -- [x] 超时/调用取消/根关闭/输出超限均有界完成并回收沙箱进程树;后续调用仍可执行,无自动重放。 -- [x] 打包拒绝错架构、缺库、错误 SONAME/ABI、越界路径和篡改;完整动态程序在移除原始源码后运行。 -- [x] 真实 Dever check/run/build 和独立产物覆盖完整路径;Package 资源与现有 Worker 定向回归通过。 -- [x] Linux ARM64 构建与目标校验覆盖;目标运行证据单独报告,不能由 ELF 标签推导运行通过。 - -ARM64本次证据为Rust交叉检查、LLVM目标对象生成及打包目标校验;实际普通命令与独立产物运行证据来自Linux x86_64。完整验证命令、失败修复及未运行项见implement.md。 - -## 非目标 - -Windows/macOS、FFI、shell/管道语法、后台守护进程/交互式终端、隐式下载或宿主库扫描、全量测试和长压测。 diff --git a/.trellis/tasks/archive/2026-10/10-04-external-command/task.json b/.trellis/tasks/archive/2026-10/10-04-external-command/task.json deleted file mode 100644 index a62fcd1..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-external-command/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "external-command", - "name": "external-command", - "title": "Linux 普通二进制调用", - "description": "在 Port/Adapter 下直接执行现成 Linux 二进制,支持参数、标准输入输出、退出状态、超时取消及独立打包", - "status": "completed", - "dev_type": null, - "scope": "external-command", - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-10-04", - "completedAt": "2026-10-04", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [], - "notes": "Linux普通二进制调用已实现并完成定向及真实打包验收;ARM证据为交叉检查/对象生成/目标校验,不含目标执行。备份与完整证据见implement.md。不提交Git、不替换全局安装。", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/check.jsonl b/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/check.jsonl deleted file mode 100644 index 63d97b4..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/check.jsonl +++ /dev/null @@ -1,2 +0,0 @@ -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"目标贯穿、共享缓存、安全闭包、Worker部署一致性"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"真实跨目标执行证据与最小回归边界"} diff --git a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/design.md b/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/design.md deleted file mode 100644 index a5e5a5b..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/design.md +++ /dev/null @@ -1,25 +0,0 @@ -# Linux ARM64 应用交叉构建设计 - -## 边界与复用 - -只有应用部署目标变化,编译器/daemon/build tools 仍在当前 x86 宿主运行。复用 LLVM bridge 的 Target、现有 pack 清单/签名验证、NativeProgram 发布、Lib resolver/lock/Worker 以及 CacheStore,不建立平行流水线。主机平台身份继续用于 launcher/daemon 验证;新增独立、封闭的构建目标值,不能全局替换 platform_identity。 - -## 目标数据流 - -CLI build 参数 → 明确的 BuildTarget → 目标 Lib 资源准备 → CompileRequest → daemon 验证目标 pack 与缓存 → worker 加载目标 runtime → LLVM object/LLD → 独立程序。私有编译走同一目标与 pack owner。run/test 在入口固定使用 host;应用配置不保存编译器状态。 - -toolchain/target.rs 拥有 BuildTarget(LinuxX86_64、LinuxAarch64),严格解析 linux-x86_64/linux-aarch64,提供 host/platform/triple 映射。共享库不引用 bridge,避免 launcher/deverd 引入 LLVM。原始六目标 bridge 保持独立。 - -每个 runtime//manifest.json 验证实际目标与 compiler_version/ABI;所选目标的整个输入闭包必须纳入安装签名,缓存键包含目标和该 pack 身份。pack 制作器接受显式准备的目标运行输入,同时只验证/打包 x86 宿主核心,不要求构建 ARM 核心。 - -## Lib 与宿主执行 - -资源路径、runtime/构建收据和 ELF 校验使用部署目标;实际启动的编译工具使用构建宿主。Go 交叉编译工具必须在 x86 执行且输出 ARM,标准库/importcfg 和源码 tags 选择 ARM。Python wheel 与 npm addon 遵守目标 ABI;跨目标源码构建不能把 ARM 工具直接作为 x86 可执行文件启动,也不能无条件接受宿主生成的收据。共用现有显式 Lib 准备入口传递目标,离线 build 只消费完整、已校验的目标材料。lock 模式如需变化直接迁移仓库合同/fixture,不增加旧格式回退。 - -源项目与 Dever Package 的业务声明不增加架构分支。只有明确的部署目标选择和作者工具输入区分架构。缺少目标资产给出明确准备错误,不能退回宿主资源或无沙箱执行。 - -## 验证与运维 - -作者资源/模拟器解包到本任务专用目录,使用绝对工具路径与校验摘要,不全局安装。所有 Cargo/原生构建由主代理串行执行,优先复用现有缓存,开工前检查磁盘与内存预算。跨编译测试验证 ELF、执行结果及坏输入拒绝;共享编译验证目标隔离和命中前完整性校验。模拟 ARM 内核只在任务自有进程/镜像内运行,不修改主机 AppArmor 或已有服务。 - -ARM 真机吞吐和不同硬件/内核兼容性不从模拟结果推导。本次不重新跑既有全量矩阵或长压测。 diff --git a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/implement.jsonl b/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/implement.jsonl deleted file mode 100644 index f80d992..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/implement.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"file":".trellis/spec/backend/directory-structure.md","reason":"编译/运行库/Lib/资源的唯一owner和根test归属"} -{"file":".trellis/spec/backend/error-handling.md","reason":"显式目标错误与资源/发布清理"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"离线定向验证和资源预算"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"运行输入、签名闭包、daemon/cache与生态宿主/目标合同"} diff --git a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/implement.md b/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/implement.md deleted file mode 100644 index 4c1a555..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/implement.md +++ /dev/null @@ -1,61 +0,0 @@ -# 执行记录 - -## 已确认范围 - -用户已批准 x86 构建 ARM 应用及创建任务继续实施。最终方案沿用已确认目标,没有 ARM 开发工具链/公开发行/长压测。旧生产化父任务的其他平台延期范围,仅为本任务的 Linux ARM 应用部署这一项解除延期。 - -## 收口结果 - -本任务范围全部通过。最终汇总为 `target/arm64-cross/acceptance.json`,逐项绑定构建日志、运行日志和当前产物SHA。最终完整ARM内核模拟日志为 `target/arm64-cross/logs/guest-1791082810005965465.log`:Python、JavaScript、Go各自成功/故障/恢复/清理全部通过,HTTP返回`arm-http`,guest退出0,222.57s,无超时。四profile、私有/共享编译、缓存隔离/篡改拒绝和SQLite真实CRUD由此前独立验收覆盖。 - -本机构建、41项初始定向回归、Lib 73项、Worker 9项、迁移后的真实Go构建运行1项、Python/JavaScript SDK合同、作者Python输入2项及相关Clippy/格式检查通过;这些测试集有交集,不相加成独立总数。最新Python签名构建201.28s通过,包已包含最终reader及completion清理修复。 - -没有ARM真机;未运行ARM真机性能/长测、真实PostgreSQL服务器或全工作区CI。模拟器验证功能,不推导真机吞吐。Python sdist/npm hook跨目标仍需事先准备匹配目标的输出和完整收据;纯Python/npm与Go交叉构建已实际覆盖。产品仍不隐式联网或从环境变量/PATH读取语言工具。未安装/替换全局命令、修改主机AppArmor/sysctl或业务服务,未提交Git。 - -## 实施 - -1. [x] 调查 CLI、runtime pack、daemon/cache、Lib/Worker 目标链路,建立可审查任务。 -2. [x] 编译链路:BuildTarget、build 参数、CompileRequest、runtime/签名/缓存及打包者,配套回归。 -3. [x] Lib 链路:显式目标准备、lock/resource/runtime/Worker/build pack 的宿主与目标分离,错架构拒绝与回归。 -4. [x] 准备可复现 ARM 运行输入与模拟器;构建四 runtime profile 和所需生态资源。 -5. [x] 串行定向检查,执行 ARM 真实应用/三生态模拟验收及 x86 最小回归。 -6. [x] 独立复核、修复实际问题,更新规范/CLI 文档/执行证据,清理自有进程与临时配置,不提交。 - -## 所有权 - -- 编译实施代理:CLI main/compile/worker、toolchain target/runtime_pack/compilation/service/release/cache、packaging.rs 主文件与编译相关根 test。 -- Lib 实施代理:libs.rs 与 libs/**、workers.rs 与 workers/**、packages 的传递 Lib 必需接线、packaging/{ecosystems,builds,sandbox}.rs、生态相关根 test。CLI 参数集成通过主代理/编译代理协调,禁止重写对方文件。 -- 主代理:任务/规范/SDK/README、作者 ARM 资源和模拟验收 owner、所有 Cargo 和重资源命令、最终集成。 - -## 检查原则 - -先参数/目标映射/清单/缓存/锁的定向测试,再用真实 ARM 产物执行。编译命令明确 offline/locked 和单作业;不让子代理并行 Cargo。真实业务服务仅在自有临时项目/端口或模拟机里启动,提前说明。失败保存证据,不放宽断言、不能将未准备目标或模拟器缺失标成通过。 - -初始磁盘可用约8.2GiB;现有 debug 3.1GiB、参考 runtime 948MiB 均保留。准备资源前重新核算,不删除用户不明文件、不恢复旧长测。 - -## 过程与证据(按执行顺序保留) - -- 编译与 Lib 两条接线已实施,新增 BuildTarget、请求/缓存目标绑定、显式目标 Lib 准备及 ELF/Go archive 检查;尚待 Cargo 与真实产物验收,未将代理报告记成通过。 -- 作者工具均在 `target/arm64-cross/`:Rust 1.98 ARM std、GCC 13 ARM cross、QEMU user/system、同版本私有 rustfmt/clippy。未安装全局工具。Ubuntu 包按现有受信 metadata 的 SHA256 验证,ARM OS 库索引另外通过 Ubuntu InRelease 签名验证。 -- ARM base 和 sqlite 已使用 `runtime-pack` 串行构建成功,保存到 `archives/`;postgres/both 仍在构建。初次失败是私有 cross as 找不到同目录 libopcodes,已仅在作者 Cargo 子进程设置私有库路径修复,未加入产品环境变量。 -- Python 3.12.14 ARM standalone 和 Node 24.15.0 ARM 已按上游发布摘要下载并生成目标 pack;真实 six/is-number 包及 Google UUID 现有官方校验证据供后续 Worker 验收。 -- Alpine 3.22.6 ARM 内核完整系统模拟启动成功,日志 `target/arm64-cross/logs/guest-1791077299508695065.log`:`aarch64`、user namespace 存在、`DEVER_ARM_GUEST_EXIT=0`。这只是模拟机准备,不是 Dever/Worker 验收。 -- author native release helper 增加目标参数复用现有 Python/npm选取/manifest;Go author fixture通过私有 Go overlay 固定交叉工具默认目标(源码未改全局SDK),待实际构建与执行。 - -- 四份 ARM runtime 全部通过:base 311.91s/81,418,028B、sqlite 362.84s/96,034,088B、postgres 338.03s/102,287,968B、both 237.84s/109,661,934B。总作者构建20m52s,峰值1.9GiB、无swap/OOM;每份SHA和命令在对应log JSON。`target/debug/runtime/linux-aarch64`已按真实输入准备,未改原x86 pack。 -- 新host工具构建通过;定向测试39项通过:CLI参数3、native maker24、请求目标2、LLVM CLI5、共享缓存1、resolver目标1、exec架构1、managed runtime目标2。未执行的ignored项未算通过。作者Python输入测试2项通过。 -- `trellis-check`独立复核修复1处多余借用,17个生产Rust文件格式检查通过;未发现目标数据流/签名/缓存的功能性阻塞。主代理继续负责实际测试,不以复核替代执行。 -- 实际签名安装/shared+private ARM构建验收1/1通过(177.32s):4共享profile + 私有base均在删除源码与机器目录后由QEMU执行成功;SQLite真实CRUD、ARM/x86缓存隔离、重复命中、命中前篡改拒绝通过。结果 `target/arm64-cross/compile-acceptance.json`,HTTP应用已导出但尚待完整guest运行。未运行真实PG服务器。 -- ARM guard已按私有sysroot成功链接,sandbox OS assets准备完成;前两次作者链接失败(缺libgcc_s、GNU脚本绝对sysroot)均保留日志,修复只在私有作者输入/链接参数,不改变产品配置。Go交叉pack正在构建。 - -- Go交叉pack已成功(144.86s);签名安装后的三生态ARM应用离线构建1/1通过(453.51s),各应用导出后删除源码和机器目录。完整guest运行尚未通过,构建成功不算Worker执行成功。 -- 完整模拟定位两个独立问题:fixture直接从initramfs rootfs运行导致bwrap `pivot_root: EINVAL`,已改为switch_root到正常tmpfs根;随后日志 `guest-1791080132703634001.log`明确显示ARM loader为0600,guard启动Permission denied。 -- 根因属隐含宿主假设/跨层传播与测试缺口:`asset_executable`只识别宿主loader,ELF架构校验正确但打包和嵌入权限错误;首轮复核未覆盖这条权限数据流。已在共享owner精确识别两种目标loader,并增加真实pack权限回归(输入0600→loader/guard/bwrap0755、库0644)和负例。目标架构校验、guard和沙箱策略未放宽;规范已补齐。主代理正在重建host工具及全部三生态产物复验,旧产物不能作为修复证据。 -- loader修复后host工具重建通过,定向测试41/41通过(原39项加sandbox默认2项);三生态应用重新生成通过(461.13s,日志 `ecosystems-1791080644145693595.log`)。旧失败应用保存在 `target/arm64-cross/failed-loader-mode/`,当前guest/apps均是修复后产物。 -- 完整系统验收脚本固化在根test下 `test/ecosystem-release/arm64/{simulate.py,init.sh,bootstrap.sh,guest.sh}`;独立复核补上源码定位的预期错误、每次调用后 `/worker/*` 进程检查、流水线子进程回收,语法检查通过。完整guest正在运行。 -- 四ARM静态runtime/guard沿用前述已验证构建:本次最后修复的`asset_executable`仅由宿主作者/CLI打包与嵌入路径调用,ARM运行期不调用它;重新构建host core并重生成应用资源标记即覆盖实际修复,不重复20分钟runtime构建。 -- `guest-1791081118958747964.log`已得到Python `data:true`,随后Worker以134退出,验收正确判失败。宿主SDK合同用例保持stdin打开后稳定复现 `_enter_buffered_busy`:daemon读线程持有BufferedReader锁,之前测试先关stdin掩盖了退出竞争。SDK已改用asyncio管道与有界队列,finally取消并等待reader、关闭transport;修改后的整个Python SDK握手/调用/业务错误/取消/关闭/拒绝检查通过。只需重嵌入Python SDK,ARM runtime/Node/Go源字节未变;共用原签名构建fixture增加Python定向入口,不复制构建流程。 -- SDK复核补齐有界队列中completion通知任务的取消/等待,`test/external-sdk/check.py`新增Python队列满时关闭、保留stdin等待退出且stderr为空的回归。Python完整合同与JavaScript原合同检查均通过。该保留stdin回归针对CPython退出竞争;JavaScript继续遵循原测试/真实host在shutdown应答后关闭stdin的流程。 -- `guest-1791081776953594061.log`完整通过Python成功/故障/恢复/清理,但整个三生态模拟在180s总上限时被停止,记为未通过。模拟器需反复读取校验大型独立程序,后续有限总预算改为600s并增加每步marker;这是9次调用加HTTP的功能验收,不是长压测。 -- 旧host Go fixture缺少新增的`build.host`,已校验原SHA及358个leaf,保留工具/stdlib原字节和mode,仅重封装descriptor并同步6个作者文件、锁及prepared摘要;原文件完整备份在 `target/arm64-cross/host-go/backup`。新固定SHA `8818a1eccb510948a55f63088c01678391a5e0c2236e6eacadfe45d0a5edbb43`,prepare.py和SDK文档同步,未改其他语言收据和UUID/sumdb。实际host Go重复编译/移除源码后运行回归1/1通过(18.06s)。 -- 静态检查修复沙箱条件嵌套、Go编译参数过多(组合现有构建输入)、共享ELF测试fixture在两个新消费者中的未用辅助方法告警;CLI相关bin/test及sandbox全部target的Clippy `-D warnings`通过。受影响Lib默认73/73、Worker默认9/9通过;各10项ignored未算通过。最后改动Rust格式检查通过,作者Python输入2/2通过。 diff --git a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/prd.md b/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/prd.md deleted file mode 100644 index 90eabd1..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/prd.md +++ /dev/null @@ -1,33 +0,0 @@ -# Linux ARM64 应用交叉构建 - -## 目标 - -在现有 Linux x86_64 开发机执行 Dever build,得到能在 Linux ARM64 独立运行的应用。部署端不安装 Dever 编译器、Rust、Cargo 或 LLVM。用户已确认上述范围及创建任务、继续实施;不重复要求实施确认。 - -## 实施前基线 - -- LLVM bridge 已有 LinuxAarch64 对象生成和链接;CLI compile.rs、toolchain/runtime_pack.rs 仍按 host 选 pack。 -- toolchain/compilation.rs 的请求未携带产物目标;service/compile.rs 的缓存目标固定为 host。 -- libs.rs、workers.rs 与 Go/build pack 的验证多处把运行目标视为开发机;不能仅改最终主程序而混入 x86 资源。 -- 启动本任务时没有 ARM 真机及模拟器。准备作者工具与 ARM 资源属于本任务,模拟通过不等于真机性能验收。 - -## 要求 - -1. `dever build --target linux-aarch64 --output ` 选择产物目标;省略目标保持本机构建。run/test 继续本机执行,未知/重复参数明确失败。 -2. 私有 CLI 与机器共享编译均传递同一目标;验证正确版本、ABI、目标 pack 和签名闭包,缓存按目标隔离。不能用宿主 pack 替代缺失 ARM pack。 -3. 制作并验证 ARM64 的 base/sqlite/postgres/both 运行库及必要 CRT/静态库;构建端保持 x86_64。 -4. Lib 准备/锁定/离线打包区分构建宿主与部署目标,Python/Node 解释器、Go/exec Worker、原生扩展和沙箱资产不得混入错误架构。复用原协议、resolver 和资源 owner,不另建跨编译框架。 -5. 产品配置只用 config/setting.json;run/build 不联网、不读取环境变量或系统 PATH 获取语言工具。准备目标依赖必须显式进行。 -6. 用模拟环境运行生成的真实应用与目标 Worker,验证输出、失败和清理;涉及 namespace/seccomp 的验收使用带 ARM 内核的完整系统模拟,不能拿用户态模拟结果替代沙箱证据。 - -## 验收 - -- [x] 默认本机 check/run/build 行为及参数拒绝定向回归通过。 -- [x] x86 构建的应用 ELF 标记 AArch64,模拟器中执行实际 CMD/HTTP/数据库路径并得到预期输出。 -- [x] 四 profile 都使用真实 ARM 输入;私有与共享构建命中正确目标缓存,缺失/错误/篡改目标输入均拒绝。 -- [x] pip/npm/go 与 exec 的目标资源选择、锁定和错架构拒绝有回归;准备的 ARM 三生态应用能在模拟环境独立运行。 -- [x] 产物不依赖 ARM 编译器或源项目,构建不隐式联网;最终日志明确记录通过、未运行和阻塞。 - -## 不在范围 - -ARM 上开发/编译 Dever、macOS/Windows、公开发行/新签名体系、真机性能及长压测。保留现有 x86 验收证据,不重复全量 CI;不改宿主 AppArmor、业务服务或全局工具。 diff --git a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/task.json b/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/task.json deleted file mode 100644 index 9a7c9d4..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-linux-arm64-cross-build/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "linux-arm64-cross-build", - "name": "linux-arm64-cross-build", - "title": "Linux ARM64 应用交叉构建", - "description": "在Linux x86_64开发机生成可在Linux ARM64运行的应用二进制,覆盖目标运行库、Lib资源、共享缓存和模拟验收;不移植ARM开发工具链。", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-10-04", - "completedAt": "2026-10-04", - "branch": "main", - "base_branch": "main", - "worktree_path": null, - "commit": null, - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [], - "notes": "", - "meta": {} -} \ No newline at end of file diff --git a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/check.jsonl b/.trellis/tasks/archive/2026-10/10-04-slim-distribution/check.jsonl deleted file mode 100644 index 318f4ed..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/check.jsonl +++ /dev/null @@ -1,5 +0,0 @@ -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused checks and actual CLI verification"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Distribution security and offline invariants"} -{"file":".trellis/tasks/10-04-slim-distribution/prd.md","reason":"Required deliverables and acceptance criteria"} -{"file":".trellis/tasks/10-04-slim-distribution/design.md","reason":"Implementation boundaries and exact restore contract"} -{"file":".trellis/tasks/10-04-slim-distribution/implement.md","reason":"Verification evidence and ownership"} diff --git a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/design.md b/.trellis/tasks/archive/2026-10/10-04-slim-distribution/design.md deleted file mode 100644 index c6de8f2..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/design.md +++ /dev/null @@ -1,37 +0,0 @@ -# 精简发行设计 - -## 修改边界与复用 - -现有 `packaging` 统一签名全部资源,`release_source` 下载单一 gzip,`MachineManager` 原子安装版本,daemon 保护共享缓存,`InstalledRegistry` 从安装版本取工具。改动必须落在这些 owner:不向 App/业务配置加入安装概念,不重复实现每种生态的下载器/进程监督器,不把 Rust 源码编译要求转给使用者。 - -保留源码签名、路径/类型/摘要校验、四种数据库 profile、系统服务权限范围、离线编译、失败前置和版本 journal 的既有语义。CLI/安装/缓存/SDK/skill 的改变属于已确认五项方案;语言语法、模型、业务运行时与其他宿主平台不变。 - -## 发行目录与认证 - -- 升级当前发行 schema:签名根 manifest 包含基础 `artifacts` 和封闭类型的扩展目录 `extensions`。每个扩展绑定 kind、target 和完整 artifact 列表,身份由根 manifest 精确字节摘要与扩展 ID 共同确定。单一根签名认证全部描述,不能信任单独下载的无绑定元数据。 -- 基础包包含 host native runtime 四 profile、core/lib、bootstrap、host sandbox、skill;Runtime(pip/npm/go)、Build(pip/npm)、Target(linux-aarch64 native+target sandbox) 分开发布。纯 Python/npm 包不触发 Build。 -- author maker 继续只复制/校验/签名显式输入。预备发行目录可同时包含待发布扩展,SDK publisher 输出 base `.tar.zst` 与每种扩展 `.tar.zst`,文件列表来自同一签名目录。既有 v0.1.0 tag 不覆盖,正式新产物使用新版本。 -- Zstandard 固定长窗口上限 27、流式解压、压缩/解压/文件数/单文件/尾部边界仍受限;不以签名成功替代归档检查。Rust 使用维护中的 codec 库安全接口,不手写 codec 或新增 workspace unsafe。 -- Python 首装沿用独立发行公钥+OpenSSL 认证根目录,再下载并逐字节校验 raw bootstrap launcher 及其已声明私有动态库到独立 scratch。使用已认证 launcher 的隐藏 extraction 入口解压 `.tar.zst`,然后运行现有 bootstrap;使用者无需系统 zstd。完整解压/路径规则复用 Rust owner,避免保留两套 TAR 安全实现。SDK 发布上述 raw blob 供引导,所有可执行字节必须在执行前经独立密钥和摘要验证。 - -## 扩展安装、读取与更新 - -- 资源存储位于现有 service 可写的 `cache/extensions` 下,按已安装签名 manifest 身份与扩展 ID 建立不可变目录;不扩大 systemd 写范围,不写用户家目录,不修改版本 core 树或签名数据。 -- 新 IPC 只接收 `version + ExtensionId(kind,target)` 封闭枚举,不接受 URL、路径、脚本或解压参数。官方 HTTPS origin、redirect allowlist、字节/时限/并发限额由工具链固定。外部用户复用现有 peer authentication/admission,只能准备已安装可信版本目录里声明的扩展。 -- 复用持久 install 锁,下载在私有 staging,验证完整列表和字节后原子 no-replace 发布;竞态仅在完整同身份校验通过后复用。缺失是准备提示,损坏必须拒绝,不能悄悄掩盖成 cache miss。 -- 单一只读资源视图统一 base 与已安装扩展路径,所有 worker runtime/build/sandbox 和目标 runtime 读取共用它;编译和缓存命中不得触发下载。源 manifest 不被拼接改写成伪造签名数据。 -- `target add linux-aarch64` 对当前 active 版本显式准备 target 扩展;Lib preparation 额外准备实际使用生态对应 target。目标是应用 ARM,不要求 ARM 宿主编译器。 -- `update` 准备新 base,并把当前 active 版本已经安装的扩展选择全部准备到新版本身份下,再写同一个 active journal。任何前置失败保留旧 active/core/skill/扩展,已安装资源不重复下载;未使用扩展不被顺带安装。 - -## Lib 恢复 - -- 显式 add/update/install 及 Package 中真正准备 Lib 的动作进入同一 preparation scope。先取得未绑定 Worker 声明,按需准备 Runtime,然后通过现有 owner 绑定和解析;普通 check/doctor/remove/run/build 保持只读或既有离线语义。 -- Build 仅在 resolver 已确认 sdist 或 npm hook 必需后由统一 build-input owner 准备,不能根据生态名称一律下载。 -- `lib install` 消费当前格式准确锁:验证项目、Package 传递依赖与 checked Worker binding;缓存命中验证完整 bytes/hash;缺失时按锁定精确版本/源定位下载,不选择新版本。完成后 setting/lock 字节保持一致。 -- 为原生构建收据补全准确源 locator/文件名、固定 build requirement closure、原始 npm 执行图和编译输入身份;当前格式一并迁移仓库 fixtures,不引入旧格式 fallback。重放只能使用锁定输入;最终产物必须符合原收据 bytes/hash,不能用不同产物改写原锁。不可重现明确失败。 - -## 质量与操作边界 - -主任务串行协调 Cargo,worker 不并发创建新 target。测试只选择发行/资源/Lib/安装路径,真实验收使用 owned 镜像和进程,不修改宿主服务、安全策略或真实数据库。正式优化构建与四种 runtime 档案来源分开记录。压缩收益不与重复内容字节直接相减;实际发布前报告 base download/install、raw bootstrap 开销及扩展增量。 - -公开 Release 和线上更新独立于本地签名包验收。若缺 GitHub API 登录,先完成可审查的源码与产物,再报告唯一外部阻塞,不能以 tag/源码 push 代替 Release。 diff --git a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/implement.jsonl b/.trellis/tasks/archive/2026-10/10-04-slim-distribution/implement.jsonl deleted file mode 100644 index 6951c22..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/implement.jsonl +++ /dev/null @@ -1,8 +0,0 @@ -{"file":".trellis/spec/backend/index.md","reason":"Rust compiler scope and check routing"} -{"file":".trellis/spec/backend/directory-structure.md","reason":"Module ownership and root test placement"} -{"file":".trellis/spec/backend/quality-guidelines.md","reason":"Focused validation and safe Rust"} -{"file":".trellis/spec/backend/error-handling.md","reason":"Explicit errors and resource cleanup"} -{"file":".trellis/spec/backend/toolchain-and-library.md","reason":"Signed toolchain, offline resources and Lib contracts"} -{"file":".trellis/tasks/10-04-slim-distribution/design.md","reason":"Approved scope and cross-owner contracts"} -{"file":".trellis/tasks/10-04-slim-distribution/research/release.md","reason":"Release call chain and security invariants"} -{"file":".trellis/tasks/10-04-slim-distribution/research/libs.md","reason":"Lock restore and preparation call chain"} diff --git a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/implement.md b/.trellis/tasks/archive/2026-10/10-04-slim-distribution/implement.md deleted file mode 100644 index 40a8148..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/implement.md +++ /dev/null @@ -1,57 +0,0 @@ -# 实施记录 - -## 已确认 - -- 用户已批准完整五项方案及任务创建/继续实施,无需重复确认相同范围。 -- [x] 工作区起点核查和备份,`target/distribution-before.10dsis`,gzip 校验通过。 -- [x] PRD 记录用户要求、范围、回滚和验收,非语言迁移任务。 -- [x] research/release.md 和 research/libs.md 完成,按实际 owner 完成 API 对接。 -- [x] 实施上下文配置、任务进入 in_progress。 - -## 实施顺序与责任 - -1. 发行/扩展 worker:根 catalog schema、Zstandard Rust owner、资源视图、共享扩展安装 IPC、target 命令、installed-extension update、Rust 隐藏 extraction 入口;拥有 toolchain 下相关模块、launcher binary、CLI Cargo dependency 和对应定向测试。不要修改 author packaging、SDK Python、skills 或 Lib resolver owner。 -2. Lib worker:锁/收据当前格式与精确恢复、add/update/install/Package preparation scope、InstalledRegistry 资源读取接线、CLI lib help 与相关测试;拥有 libs/**、必要 workers 资源消费/Package 路径及 main.rs。与发行 worker对接 typed extension API,不重复实现下载/安装。 -3. 主会话:author packaging 接 catalog、SDK asset publisher、Python 首装、skill/docs、最终构建及真实发行验收。三个 owner 先固定接口,避免同文件改动;若遇所有权交叉先沟通。 -4. trellis-check 独立检查整个改动范围并修复;主会话核验关键结果,更新 canonical spec 和记录,然后按已有授权处理 Git 与可用的发行发布。 - -## 验证清单 - -- [x] codec/manifest:10 定向通过;bootstrap执行位另有断言。 -- [x] install/cache/update:4 定向通过(并发/损坏/更新失败/已装集合/closedIPC/typedmiss);实际 UID65533/65534 共享扩展通过。 -- [x] lib install:4 cold restore、2 npm cache/projection、1 Package exact closure、PEP517 nested replay、npm optional replay 定向通过;实际安装版三生态无 Lib Worker 的锁恢复/运行/构建通过。 -- [x] 运行/构建缺资源只提示,不联网;target add 支持 ARM,实际 ARM64 ELF 交叉构建通过。 -- [x] SDK/Python bootstrap 10/10、skill quick_validate、全部修改/新增 Rust 文件 rustfmt check、CLI lib/bins/author examples clippy -D warnings/type check 通过。 -- [x] 正式 release 构建、core/launcher/daemon ELF closure、保留 runtime 档案链接符号。 -- [x] 实际签名包基础首装:普通/Markdown new/fmt/check/test/run/build;不含可选生态和 ARM 文件。 -- [x] 实际扩展准备/锁恢复/跨项目复用、ARM 构建、已准备资源离线和独立应用执行。 -- [x] 安装/更新失败恢复和成功更新:定向回归通过;真实负载本地后继 catalog 的 4 阶段更新事务验收通过。公开网络单独阻塞,不混同。 -- [x] 清理本次 owned 临时产物,保留 durable assets、hash、验收 JSON 和源码备份。 -- [x] 最终 diff/self review、任务进度、Git 提交/push 和 Release 状态准确记录。实现与本地验收完成;公开 Release 条件未满足,仍属既有公开发行待办。 - -## 构建资源 - -起始磁盘约 0.78 GiB 空闲,/dev/shm 约 1.4 GiB 空闲。必要时可回收上一轮由本会话创建的隔离安装镜像(正式包与验收记录已持久保存且先复核),不可删除其他项目、源码、keys、未知 cache 或实验。使用显式 Rust toolchain 路径,保留现有共享 target,Cargo 串行 -j1;不因磁盘不足跳过必要验收或宣称完成。 - -## 当前证据 - -- 首轮 SDK/Python installer 定向 10/10,通过基础/扩展资产分离、真实 Ed25519 验签、raw bootstrap 摘要/长度/私有库、发布竞态、流量边界。Rust 接管的归档拒绝测试由发行 worker 补齐,未以 Python mock 代替实际安装验收。 -- Cargo 新增静态 zstd 0.13.3;工作区版本 0.1.1,release strip=symbols,runtime-pack 仍显式 strip=debuginfo。正式串行构建目录 `/dev/shm/dever-slim-cargo.PvjPZZ`,未运行全量 CI。 -- 旧 v0.1.0 完整 archive SHA-256 重新核对为 `7b56e825fb2b0468a271276bffbd84775e9dd9ae219f7e16097d1ff3df22b1cc` 后回收 owned 1.5 GiB 临时镜像。正式旧包/验收记录/源码备份均保留。 -- Cargo 自有 `clean -p dever-cli -p dever-core --profile dev --target-dir target` 回收 898.3 MiB 旧编译产物;仅 native-acceptance-init 验收助手另存 `target/release-0.1.1/tools/`。源码/依赖缓存/其它项目/全局服务未清理。 -- 真实本地 sandbox PEP517 nested replay 142.15s、npm optional replay 61.70s,均通过。原生maker 25/25默认定向通过,10个独立重验收未在这条命令启动。旧cross sandbox fixture已补齐同组native input;不是删除失败检查。 -- trellis-check 独立审查未发现其他Rust合同问题;主会话修复其SDK bounded metadata/path长度/namespace/hostTarget差异,补文件/目录重叠拒绝。主会话另修复解压bootstrap执行位。clippy唯一is_multiple_of诊断已修复并复验通过。 -- 原正式build先完成了全部依赖和CLI类型检查;在最终ELF链接前因上述代码修正主动停止(exit130)。最终源码 release 构建已成功(6m39s),产物保存到 `target/release-0.1.1/tools/`。core 16,951,872 字节,launcher 3,330,288 字节,daemon 3,310,296 字节;ELF 已 strip,launcher/daemon 仅需私有 libgcc_s 和 OS ABI,core 的 LLVM/private closure 随包提供。 - -## 真实 0.1.1 产物与验收 - -- 已制作实际签名 v2 目录与全部 split assets。基础 `.tar.zst` 为 117,481,208 字节(112.04 MiB),SHA-256 `fbf04562012b40038c8d845dcf528070606b4fd8374edec34c6516ea4afdf167`;基础文件解压合计约 573 MiB。首装另有 raw helper 3,513,312 字节(3.35 MiB)和约 22 KiB 元数据。全部可选资产合计约 596.59 MiB,不代表默认下载这些资源。 -- `target/release-0.1.1/sizes.json` 记录每个资产的字节数/摘要;`provenance.json` 记录显式输入及未修改 runtime 档案复用。host glibc 最低 2.39,ARM64 为应用交叉目标。 -- 首次实包验收到普通/Markdown 项目和缺 ARM 资源提示均通过;跨 UID 步骤因 outer bwrap 单 UID 映射不能 setgid65534 而失败。修复的是验收夹具:使用既有测试模式,在私有 machine 启动独立 daemon,以真实 UID65533/65534 检查共享资源。产品代码/签名资产未改;重新从 durable assets 验收。 -- 更新验收另用真实负载签署仅供本地测试的后继版本,传输指向本地真实扩展。Ed25519 PKCS#8 v2 由与 maker 相同的 ring 签署,不再使用不支持该作者密钥格式的 OpenSSL 私钥读取;正式安装的 OpenSSL 公钥验证未变。最终 `update-acceptance.json` 为 passed,4 阶段通过:安装/扩展基线、失败保留旧活动版本且项目可运行、成功激活核心/skill/恰好已装扩展、切回真实版本后项目继续运行。仅供验收的 0.1.2 catalog 不能冒充 0.1.2 编译器,托管编译器严格拒绝目录版本与编译版本不同;没有关闭这项产品校验,也不声称虚拟后继版本执行通过。 -- 实包从 durable assets 复验最终 `acceptance.json` 为 passed,13 阶段全部通过:签名首装、可选资源排除、公共入口/版本、普通与 Markdown 各自完整新项目流程、skill、离线缺资源、ARM64、三生态、双 UID、五个程序脱离源码/机器目录且清空 Worker 缓存后执行。全程未启动全局服务、未替换全局命令;本地传输不表示线上更新通过。 -- 独立 trellis-check 对新增验收夹具/作者助手再次限定复核,无阻塞。产品验证合计 Rust 48 项、Python 10 项;正式实包 13 阶段、更新事务 4 阶段通过。fmt/clippy/skill 检查通过;未运行无关全量 CI/压力测试。 -- 仅为回收本轮已完成的测试产物,Cargo clean CLI dev profile 再释放 376.8 MiB;正式包、作者输入、源码备份保留。 -- 所有本轮隔离安装镜像均已卸载,自有 daemon/namespace 已退出;空临时目录已移除。正式构建临时目录核对仅含本轮 Rust 缓存/产物,保留工具与正式资产后清理约 556 MiB tmpfs。该目录没有新版 Cargo clean 要求的 CACHEDIR.TAG,未补造标记,核对归属后按精确目录移除;可从源码重建。 -- 核心提交 `4fda7c8c1a33b843e2fca219cb3bc95c09471716`、skill 提交 `27ac8f21c2e82458e00161154e277eb742c6a231` 已分别推送到两个官方仓库 main;`v0.1.1` 标签已推送并指向核心工作提交。发布包不包含后续仅记录/归档提交的变化。GitHub API 未登录,Release 资产尚未上传,线上首次下载/更新未运行;不能将已推送标签等同于发布完成。 -- GitHub SSH 源码访问可用;GitHub Release API 尚未登录。不能把源码/tag push 或本地模拟传输当作公开发布及线上更新。 diff --git a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/prd.md b/.trellis/tasks/archive/2026-10/10-04-slim-distribution/prd.md deleted file mode 100644 index c6ba386..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/prd.md +++ /dev/null @@ -1,33 +0,0 @@ -# Dever 精简发行与按需工具安装 - -## 目标与已确认范围 - -用户已确认五项实施方案,并于本轮确认创建任务和继续实施。默认 Linux x86_64 基础包目标约 120 MiB,功能保持完整:编译器、LLVM、四种本机运行库(base/sqlite/postgres/both)、CLI、sandbox、skill 与模板。Python/Node/Go、原生扩展构建工具和 ARM 应用交叉编译资源改为显式命令触发、自动判断的按需安装。整台机器多用户、多项目共享同版本资源。 - -## 事实与约束 - -- 当前完整发行压缩包 714.7 MiB;同一基础文件集 gzip 为 181.6 MiB,Zstandard 长窗口(128 MiB)为 118.0 MiB,解压约 624 MiB。这是压缩试算,实际正式构建与完整安装验证仍需执行。 -- 源码备份:`target/distribution-before.10dsis/source.tar.gz`;独立 skill 备份 `skills.tar.gz`;发行记录备份 `release-records.tar.gz`,均已 gzip 完整性校验。工作起点主仓库 `83b78a0`、skill `9fd78fc`,工作区干净。 -- 编译器、launcher、daemon 应改为正式优化构建,清理非必要符号;保持 runtime 链接需要的符号。 -- 应用配置仅 `config/setting.json`;官方源属于工具链内置元数据,不能放进项目配置或新增环境变量配置。不得依赖系统 PATH 的 Python/Node/Go/Rust 来构建用户应用。 -- `run/build` 保持离线,缺资源提供准确准备命令;Dever Package 保持源码发布,底层 Rust 运行库保持预编译,FFI、自举和其他宿主平台不在本任务内。 -- 当前 v0.1.0 源码 tag 已推送但二进制 Release 未发布;不得覆盖已有 tag。用户已授权相关仓库 commit/push。公开发布需完整验收和可用 GitHub API 授权,不能把本地包或 tag 当作已发布。 -- 不改宿主 AppArmor/sysctl/全局服务,不替换机器全局命令;验收使用隔离安装镜像和自有进程。磁盘有限,复用现有工具输入并避免重复 Cargo target。 - -## 需求 - -1. 正式基础发行包采用 Zstandard,安装器和更新器具备所需解压能力,用户无需手动安装 zstd。完整性校验、边界限制、拒绝路径逃逸与原子发布继续成立。 -2. 扩展按 Dever 版本、目标平台和内容身份绑定;按需签名下载、原子安装、并发安全、缓存复用,扩展失败不破坏已有可用版本。 -3. `dever lib add/update` 自动准备声明所需生态环境,只有确有必要才准备原生构建工具;`dever lib install ` 按现有锁文件恢复,不更新版本、不改 setting/lock。 -4. `dever target add linux-aarch64` 为当前选定版本准备 ARM 交叉编译资源;使用第三方 Lib 的 ARM 项目仍显式准备目标依赖。既有 ARM 能力与离线构建保持。 -5. `dever update` 同步核心、skill 和已安装扩展;新增版本准备失败时旧 active 版本可继续使用,不能隐式安装所有可选扩展。 -6. 同步 SDK 发行工具、安装脚本、CLI 帮助、开发 skill 和文档,命令行为只有一套实现,不新增兼容别名或重复路径。 - -## 验收 - -- 实际正式构建,报告压缩包大小与安装占用;约 120 MiB 为基于已有内容的目标,超出时必须报告准确实测和原因。 -- 基础安装不包含 Python/Node/Go、原生扩展构建工具或 ARM 专用资源;普通与 Markdown 项目 new/check/test/run/build 通过隔离的定向验收。 -- 需要什么下载什么;已有资源复用;锁文件恢复前后字节不变;无锁、锁与声明不符、资源损坏与下载失败均明确失败。 -- 全新机器式隔离环境验证首次安装、扩展安装、多项目共享、已装扩展随更新和失败恢复;资源准备后断网构建,最终程序脱离工具链可执行。 -- 定向恶意/损坏元数据和压缩边界回归通过;ARM 至少验证交叉构建及既有适用的隔离证据,不能把构建成功当作物理 ARM 性能测试。 -- 公开上传和线上更新单独记录为完成或具体阻塞,不混同本地验收;不运行无关全量测试/长测。 diff --git a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/research/libs.md b/.trellis/tasks/archive/2026-10/10-04-slim-distribution/research/libs.md deleted file mode 100644 index 0d4ef64..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/research/libs.md +++ /dev/null @@ -1,159 +0,0 @@ -# Research: Lib 按需准备与精确锁恢复 - -- Query: 追踪 Lib、Worker、Package 的准备/离线消费路径,设计 `dever lib install ` 与扩展管理器接点。 -- Scope: internal;仅源码阅读,无测试、构建、下载、Git 操作。 -- Date: 2026-10-04 - -## Findings - -### 归属与已读规范 - -实际研究仓库为 `/data/project/dever`,独立 Rust 语言编译器,不是 `/data/project/shemic` 的 Go 应用。已读仓库 `AGENTS.md`、`.trellis/workflow.md`、当前 `prd.md`、backend index 与 toolchain-and-library 中目标、生态、锁、缓存和 Worker 合同,以及仓库 `skills/SKILL.md`。全局 shemic-dever/framework reference 描述 Go 项目,不能覆盖本仓库事实。 - -`task.py current --source` 返回 none;输出目录由主代理明确指定,未建立/修改会话指针。 - -### Files found - -| 文件 | 作用 | -| --- | --- | -| `crates/dever-cli/src/libs.rs` | 锁结构、显式命令、已安装 runtime 读取、校验与离线嵌入 | -| `crates/dever-cli/src/libs/mutation.rs` | 稳定 inode 的项目依赖互斥锁 | -| `crates/dever-cli/src/libs/registry.rs` | 官方源安全传输、PyPI/npm/Go 解析及产物缓存发布 | -| `crates/dever-cli/src/libs/registry/npm.rs` | 独立 npm 环境、精确实例图、归档展开与需构建判断 | -| `crates/dever-cli/src/libs/registry/sumdb.rs` | Go 已锁透明日志证据与 ZIP 校验 | -| `crates/dever-cli/src/libs/build.rs` | 构建 Inputs、Session、完整 Receipt、离线收据校验 | -| `crates/dever-cli/src/libs/build/python.rs` | sdist 解包、PEP517 build 依赖解析与隔离执行 | -| `crates/dever-cli/src/libs/build/npm.rs` | npm 生命周期执行、optional 剪枝、最终安装归档 | -| `crates/dever-cli/src/libs/build/npm/environment.rs` | Node/Python/native 工具与 sandbox 环境 | -| `crates/dever-cli/src/workers/runtime.rs` | maker/consumer 共享 runtime descriptor 校验 | -| `crates/dever-cli/src/workers/go_build.rs` | 已准备 host Go 工具编译 target Worker | -| `crates/dever-cli/src/packages.rs` | Package 解析、精确 ZIP、源码/Worker/Lib 汇入公共锁 | -| `crates/dever-cli/src/toolchain/service.rs` | daemon ArtifactGet/Put IPC | -| `crates/dever-cli/src/toolchain/launcher.rs`、`src/main.rs` | 选版本与公共参数路由 | - -### 现有调用链与准备入口 - -1. `libs::execute_for_target` (`libs.rs:1870`) 在 add/update 中先读声明、`source_workers`、Package libs,再 `resolve_project`,最后写 setting/lock。不能将 install 实现为 add/update 别名。 -2. `source_workers_with_packages` (`libs.rs:2173`) 加载源码、check,再 `bound_program_workers` (`1236`)。后者立即调用 `InstalledRegistry::runtime` 绑定每个非 exec Worker 的 runtime。因此只在 `resolve_project` (`612`) 加 ensure 太晚:全新精简安装会先失败。无 Lib 的 managed Worker 也需要 runtime。 -3. `resolve_project` 为实际生态调用 `InstalledRegistry::runtime` (`648`),创建 `HttpRegistry::official`、sumdb、`build::Session`,交给 resolver。fixture 全 exec 分支完全离线,不应强制要求 managed 安装。 -4. `packages::execute_locked` (`1109`) 的 add/update 解析 Package closure,然后 `source_workers_with_packages` (`1173 附近`) 和 `resolve_project` (`1193 附近`)。Package 的传递 Lib 与 Worker 必须享有同一显式准备能力;remove 则 `retain_locked_libs`,不得顺便安装扩展。 -5. `prepare` (`libs.rs:1139`) 名称易误导:它只校验声明是否在锁中并统计大小,不下载、不校验缓存完整性。 -6. `embedded_resources_for_target` (`1268`) 在离线路径核对 runtime identity、目标、每个归档摘要/长度和 Go sumdb,再把字节作为资源。`prepare_resources` (`1418`) 追加目标 sandbox,Go 另外需要 host sandbox,随后 `workers::prepare_for_target`。 -7. `workers/go_build.rs:61` 的 `compile_worker` 是离线构建;Go 编译器/链接器/selector/target stdlib 目前在 Go **runtime pack** 中,非 `build/go` 原生扩展包。保持 host 工具 + target 输出区分。 - -### 扩展管理器最小 API 接点 - -主代理提出使用 daemon 可写的不可变 `cache/extensions`,catalog 绑定已签名核心。Lib 层可保留当前逻辑路径,无需另一份生态业务实现: - -- `ensure_extension(version, kind, target)`:仅显式准备阶段调用;kind 至少 runtime(pip/npm/go)、build(pip/npm)、target。目标 extension 包含 native runtime/target sandbox;生态 target runtime 单独选取。 -- `read_verified_extension_artifact(version, kind, target, relative)` 与有界 artifact listing:只读验证已安装 extension,返回缺资源的准确准备命令。`InstalledRegistry::runtime` (`791`)、`build::Inputs::tools` (`726`)、`sandbox_resources` (`839`) 共用这个验证 owner,避免保留各自手写签名读取。当前 `signed_artifact` (`817`) 仅从 core manifest.artifacts 查叶子,需切换到合并后的已验证资源读取。 -- 显式 preparation wrapper 实现 `build::Inputs`,runtime/tools 可先 ensure 再读。普通 InstalledRegistry 永远只读;或者使用显式、不可隐式默认的 preparation policy,并沿 worker 绑定路径传递。 -- `source_workers_with_packages` 保持只读供 doctor/remove/run/build;新增同一底层源码扫描的显式准备入口,先收集未绑定 Worker,再 ensure、绑定。Package add/update 必须走该入口。不要复制 SourceMap/check 逻辑。 -- npm build environment 自身请求辅助 Python (`build/npm/environment.rs:57`);按需准备需覆盖此调用,不能只看顶层 npm 声明。 -- cross target 的本机 runtime、sandbox 与目标资源由类型化 target 选择,不能全局修改 host identity。 - -### 何时真的需要 build extension - -- Python:优先兼容 wheel;只有进入 `RegistryResolver::python_source_candidate` (`registry.rs:933`) 的 sdist 分支才调用 Session.python。`Environment::new` (`build/python.rs:239`) 读取 build/pip;提前为每个 pip 根都安装 build/pip 不合理。 -- npm:`Session::npm` (`build/npm.rs:15`) 先展开户籍归档,`npm::requires_build` 为 false 在第 43 行前后返回。只有确需生命周期/native 检查才创建 Environment,读取 build/npm。 -- 当前 npm 的任何需执行 hook 路径都加载 Python + native build pack;当前 Python 的任何 sdist 也加载完整 build/pip。若 PRD 的“确有必要”要求进一步区分纯 JS hook / 纯 Python sdist 与 native 编译,需要收紧现有 environment 合同,而不仅加 lazy ensure;不能声称已做到逐个原生编译器按需。 - -### 当前锁记录什么、未记录什么 - -| 记录 | 源码依据 | 能力/缺口 | -| --- | --- | --- | -| LockedArtifact | `libs.rs:238` | target/path/bytes/sha256;path 是生成的逻辑路径,不是下载 URL | -| RuntimePack | `libs.rs:247` | name/version/sha256;运行时元数据从已签名版本读取 | -| LockedLib | `libs.rs:255` | 精确 spec、依赖、runtime、artifacts、schema、build receipt identity | -| LockFile | `libs.rs:267` | libs/workers/go_sumdb/npm/builds/packages;decode 要求规范字节与当前 TOOLCHAIN (`353`) | -| npm Environment | `registry/npm.rs:73` | 每个 Worker 独立 roots、实例路径、owner archive/prefix、edges、omission、build id | -| build Receipt | `build.rs:52` | roots/sources/graph/runtime/aux runtime/tools/frontend/Python backend/dynamic deps/递归依赖锁/output | -| LockedPackage | `packages.rs:75` | name/version/zip sha256/bytes/精确依赖/manifest sha256;来源在 setting 中已有 registry | - -普通 PyPI wheel filename/URL 在解析后丢失(`registry.rs:905`);npm dist URL/SRI 未持久化(`988`);Go ZIP 地址可由已锁 spec 按现有 go_path 规则导出(`1121` 附近)。不改锁格式的恢复可查询**已锁精确版本**的 metadata 并仅选匹配锁 SHA/长度的文件,绝不重新选择版本或依赖;若文件撤下或变字节,明确失败。下载仍通过现有官方源/redirect/长度策略。 - -构建产物不是远端 registry 文件,必须优先从共享 cache 恢复;缺失时用固定 receipt 重放并比对锁定输出 SHA/长度,不能把新输出写回锁。 - -### 锁恢复的完整最小流程 - -1. install 参数禁止 specs,保留明确 target 选择。读且保存原始 setting/lock 字节;无锁立即报错;`LockFile::decode` + `doctor` 校验。将 install 纳入 `ProjectMutation::for_command` 的稳定互斥锁 (`mutation.rs:13`),不调用 setting 或 lock writer。 -2. Package 必须先恢复:从已有 registry 的 `/v1/packages//.zip`(`packages.rs:467` 的现有格式)取**锁定** ZIP,以 lock 摘要/长度验证并发布共享 artifact cache;不读版本索引、不选版本。然后复用 `owned_files_with` (`726`)、`validate_locked_roots` (`811`) 核对 manifests、依赖、源码归属和本地冲突。 -3. 收集 config Lib、Package manifest Lib、源码 Worker 合同,验证锁 roots/closure;现有 `prepare` 只查声明包含性,不拒绝无主锁 libs。可借 `retain_locked_libs` (`2072`) 的闭包投影与原锁比较(不发布),同时核对 workers;注意 npm receipt 的原始图与 remove 后视图允许不同,不误判合法离线 remove 结果。 -4. 仅为锁中实际 runtime 及 Worker ensure 对应版本/target 扩展,然后比对 RuntimePack;目标错配先报错,不替用户切换锁。对 fixture 条目复用内置字节与完整 metadata 校验。 -5. 实现 `restore_locked` 的精确归档恢复,接受 `RegistryTransport`、`ArtifactStore`、build Inputs,便于 fixture 注入。按 SHA/bytes 查缓存,真实 miss 才取精确版本 metadata/归档。Go 使用锁中 `go_sumdb` 验 ZIP,不调用新的 MVS/checkpoint 解析。 -6. 对缺失的构建产物递归恢复 receipt.sources 和 receipt.dependencies;验证 frontend、tools、runtime identity;通过同一个 sandbox/environment 实现固定重放。Python 重放使用锁定 backend/static+dynamic 依赖,不调用 `build_requirements`;npm 使用锁定实例图与已记录 optional 结果,不再进行 semver 解析。 -7. 恢复后复用 `embedded_resources_for_target` 验最终产物,确认 setting/lock 原字节未变。任何失败保留已存在可用数据;新增正确 cache 项可留作重试复用。 - -### 必须正视的重放缺口 - -- `Session::python` (`build/python.rs:37`) 在 73/94 行调用 resolver.build_requirements,直接重用会重新解析,违反 install 合同。应提取固定依赖的执行阶段,供首次解析和锁重放共用。 -- Python receipt source 被写成 `build/source//source` (`python.rs:144`),没有 filename/格式;`source_files` (`196`) 需要 `.tar.gz` 或 `.zip`。可用 receipt 根的精确 PyPI metadata 按 source hash 找回文件名,但若 metadata 不再包含该源,必须报缺失。 -- npm `sources` 在 optional 构建失败剪枝**前**采集 (`build/npm.rs:46`),receipt.graph 在 `prune_failed` **后**保存 (`72/87`)。失败节点 spec/owner 可能已丢,sources 只有散列路径,故当前 receipt 不保证可以完整重放原环境;不能凭摘要路径猜原包名。 -- 若需要对新生成锁完整恢复,应在首次解析时保存 source locator/filename 与 npm 原始执行图(不同于最终消费图),并在 doctor/identity 中校验。不要添加旧格式兼容分支;按仓库“新语言直接迁移合同”规则迁移 fixtures/callers。已有锁缺最终产物且缺恢复信息时,明确说明不可恢复,不能静默 resolve。 -- 即使输入齐全,任意第三方 hook/wheel 打包不保证字节确定性。重放输出必须匹配原 SHA,否则明确失败;没有远端保存原产物的机制就不能保证所有第三方构建永远能在全新机器复现。PRD 的精确恢复应以这一合同验证,不能以“版本相同”代替“字节相同”。 -- `ManagedArtifactStore::get_exact` (`libs.rs:893`) 调 `artifact_get(...).map(Some)`;当前 miss、损坏、IPC 失败都 Err。`service.rs:327/515` 未提供 typed miss。必须增加明确 absence 结果或专用有界 existence/read 协议,不能 `Err => 下载`、不能匹配错误文本。缓存损坏和 service 不可达应继续失败。 - -### target add 与 CLI - -`main.rs:435` 的 Lib operation 白名单和两个 USAGE 都需 install;launcher `project_root` (`launcher.rs:174`) 已识别任意 lib operation,可原样按项目版本转发。 - -`dever target add linux-aarch64` 没有 root 参数,应在 launcher dispatch 使用当前选定的 active 版本并调用 extension owner;若期望 cwd pin,则需要与主设计明确一致,不能悄悄扩大既有 project_root 行为。它仅准备 target runtime/sandbox;第三方 ARM Lib 仍 `lib ... --target linux-aarch64`。 - -Python sdist/npm hook 在非 host target 上由 `build::require_execution_target` (`build.rs:13`) 明确拒绝,需要匹配隔离执行环境或完整目标产物。target add 不能解除这个约束。Go runtime 则支持 host tools + target stdlib。 - -### 最近的测试夹具(本次未执行) - -- `test/dever-cli-tests/external_libs.rs:331/400/418`:LocalRegistry、FixtureArtifactStore、三生态精确归档;`:451` 目标选择;`:1333` 离线确定性;`:1397` setting 不变;`:1469` 错配配置;`:1508` Worker 合同;`:1649` 无 Lib Worker。 -- `test/dever-cli-tests/external_libs/build.rs:241`:不兼容 sdist 在装工具前拒绝;`:260/359` backend fixture / PEP517 hooks;`:422` 官方 sdist 为显式重测试,不默认运行。 -- `test/dever-cli-tests/external_libs/npm_build.rs:68`:完整固定 receipt;`:264` 不重跑 hooks 的锁图投影;`:421` optional 失败/bin/offline remove;可增加记录请求次数的精确 install 用例。 -- `test/dever-cli-tests/packages.rs:121/174`:注入 transport/store、传递 Package→Lib;`:621` 移除不请求 registry;`:725` 原 setting 字节回滚;`:909` signed managed 全链路(重验收,不默认执行)。 -- 新定向验收应覆盖冷 cache install 后锁字节不变、metadata 新增更高版本仍不选、Package→managed Worker、空 specs/无锁/声明漂移、typed miss 与损坏差异、固定 Python build deps、npm optional 原执行图、输出摘要不一致失败、ARM mismatch、已缓存构建输出不加载 build extension,以及普通 run/build 绝不发 ensure/download。 - -### 建议定稿的数据合同与实施所有权 - -当前源码实际是 `LOCK_FORMAT = "dever-lock-v5"` (`libs.rs:25`),部分 spec 文案仍写 v2;本次直接升级 **dever-lock-v6**,无旧格式 fallback。建议单一、最小模式: - -```text -LockedArtifact += source: Option -RegistrySource = { ecosystem: Ecosystem, locator: String, filename: String } -Receipt.dependencies -> Receipt.inputs: Box -``` - -`source` 对 registry 原始归档必填,对最终本地构建 output/fixture 可为 None;locator 是受现有 RegistryTransport 官方 origin/path 策略约束的精确地址,filename 只允许单文件名并承担解包格式选择,不从 URL query 猜格式。SHA/长度/target 沿用同一 LockedArtifact,不引入第二份内容身份。既然只接受 v6,source 必须成为已知字段,不需要兼容性 serde default;可序列化为 null。receipt 没有独立外部文件,**锁 v6 就是其 schema 版本**,不要再加无独立生命周期的 receipt 格式版本。 - -`inputs` 复用现有 LockFile:Python 为固定 build requirements 的精确递归锁;npm 为剪枝前 `libraries + npm graph`,图中 build=None,inputs.builds 为空,彻底避免自身 receipt 环。当前 receipt.graph 继续保存完整构建结束后的结果图(包括 prune 结果),供离线消费者与 `remove` 后投影使用。`sources` 保留为执行输入摘要列表并由 doctor 确认等于 inputs 的原始归档集合(Python 为单 sdist,build requirements 另在 inputs)。npm receipt.input 图不可被 remove 剪枝;最终 lock.npm 可以投影,原 receipt 保持不变。 - -实施所有权建议: - -| Owner | 文件/API | 验证责任 | -| --- | --- | --- | -| extension/cache worker | toolchain extension owner、service/cache;ensure/read/list 与 `artifact_get_optional` typed miss | 签名、只读缺失/损坏区分、跨 UID、并发、失败原子性 | -| libs integration worker | libs.rs、main.rs、packages.rs、mutation.rs;明确 preparation policy、`install_locked`、Package exact restoration | 公共命令、Package 先恢复、Worker 提前准备、锁字节不变、离线边界 | -| registry/receipt worker | libs/registry.rs、build.rs、build/python.rs、build/npm.rs;v6 source、`restore_locked_artifacts`、`Session::replay` | 固定来源/输入、拒绝重新解析、嵌套依赖、输出 hash 不同失败 | - -这些是逻辑所有权,可由同一 implementer 串行完成;`libs.rs` 类型/API 应由主实现者统一修改,避免多个 worker 同写。 - -具体公共/内部接点建议: - -```text -toolchain::artifact_get_optional(layout, sha256, bytes) -> Result>, String> -packages::restore_locked(project_root, lock, transport, store) -> Result<(), String> -libs::restore::install(project_root, target, preparation_inputs, transport, store) - -> Result -registry::restore_artifact(source, artifact, transport, store) -> Result<(), String> -build::Session::replay(receipt, store, signed_runtimes) -> Result<(), String> -``` - -`Session::replay` 绝不接收可解析版本的 RegistryResolver;将 Environment.run 中只用到的 store/runtime 提取成参数,首次 resolve 与 replay 共用原隔离执行器。Python inspect/requires 若执行,只用来比对已锁 backend/requirements,不能更新 inputs;metadata/wheel 阶段沿用现有检查。npm 执行 input 图,验证产出的 optional outcomes/native entries/rejections/结果图及 output SHA 与 receipt 相等后 publish。先完成全部验证再发布最终 output,不能先 publish 后发现不一致。 - -最小可测直接路径:现有 `build.rs:260` 的内联 backend fixture 无网络包管理器,验证固定动态 build requirements;`npm_build.rs:68` 固定安装收据与 `:421` optional 生命周期 fixture 验证原始图;在内存/目录 ArtifactStore 清空最终 output 后重放,两次字节一致。另加 hook 有意生成变化输出的 fixture,要求明确失败且锁字节保持。真实 C extension/node-gyp 仍复用现有显式 native fixture,不能把纯脚本 replay 通过报告成原生编译验收。 - -### External references - -未查外部网络;本研究以仓库实现为准。协议事实来自现有代码:PyPI PEP440/508 + wheel、npm semver/SRI/实例图、Go proxy/MVS/sumdb、PEP517。版本绑定以 lock.TOOLCHAIN 和 signed RuntimePack/pack::Descriptor 为准,不假定系统 Python/Node/Go 版本。 - -## Caveats / Not Found - -- 未实现任何功能、未运行测试/build/download、未修改产品或 specs。 -- Extension catalog/IPC 的最终结构由发行路径研究和主代理决定;本文提供实际 caller 需求,不重复设计签名/安装 owner。 -- 现有锁可精确获取大多数普通 registry 归档,但并非所有构建收据都包含完整重放信息;这是当前实现完整性的实际缺口,不是通过更多 retry 可解决的问题。 diff --git a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/research/release.md b/.trellis/tasks/archive/2026-10/10-04-slim-distribution/research/release.md deleted file mode 100644 index 2727cd2..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/research/release.md +++ /dev/null @@ -1,101 +0,0 @@ -# Research: 精简发行、签名扩展与机器更新 - -- Query: 核对现有签名发行、bootstrap、共享机器资源与更新契约,给出最小完整拆分方案。 -- Scope: mixed;源码只读,外部仅查解码 API 文档。 -- Date: 2026-10-04 - -## Findings - -### 现状与文件归属 - -| 文件 | 归属与证据 | -| --- | --- | -| `crates/dever-cli/src/toolchain/release.rs` | `ReleaseManifest`(74)只有 format/version/platform/artifacts;`MachineManager` 安装(293)、更新(310)、只读 core(437)、编译租约(470)、签名验证(579)、文件验证(616)、安装权限(968);稳定 `install.lock` inode(713)。 | -| `crates/dever-cli/src/toolchain/release_source.rs` | 官方 URL/重定向白名单(16、119)、元数据先验签(184)、同版本清单字节不变(213)、有界 gzip 下载(223)、catalog(250)、严格 USTAR 文件白名单(280)、NOREPLACE 发布(343)。 | -| `crates/dever-cli/src/toolchain/packaging.rs` | 固定 author 输入与签名;assemble(141)将 native、生态、sandbox、build 全部加入同一清单(202–234);必须在此按语义分类,不在压缩脚本根据随机路径猜测归属。 | -| `toolchain/packaging/{ecosystems,builds,sandbox,bootstrap}.rs` | 各类资源本身的语义校验与打包复用点;bootstrap(18)已有独立 ELF loader closure。 | -| `sdk/release-assets.py` | 所有清单 artifact 输出一个 deterministic gzip USTAR(create);目录发布使用 renameat2 NOREPLACE(publish)。 | -| `skills/scripts/install.py` | Python/OpenSSL 独立锚定公钥;authenticate(79)先验签,copy_artifact(129)精确字节/SHA 校验,payload(148)严格 tar 流,最后执行 bootstrap/dever。 | -| `toolchain/bootstrap.rs` 与 `bootstrap/transaction.rs` | 固定 bootstrap 系统落点、可信 key pin、崩溃恢复;SERVICE(19)仅允许写 state/cache/run,不允许服务写 versions 或新顶层目录。 | -| `toolchain/service.rs` | IPC Operation(100)只有 Status/Clean/ArtifactPut/ArtifactGet/Compile;内核 UID 认证(440),外 UID 可编译/资源缓存,不能 Clean;socket 0666、8 workers(34–36、154)。 | -| `toolchain/service/compile.rs` | compilation 租约、cache identity(74–86)、verify_pack(120)逐项验证所选 runtime 文件属于签名 manifest,cache hit 前也检查。 | -| `toolchain/runtime_pack.rs` | load_manifest(99)接受资源根目录,内部追加 runtime/;公开 validate(142)、RuntimePack::load(173)。 | -| `crates/dever-cli/src/compile.rs` | daemon 子进程依然在 worker(149)用 compiler_directory 加载 runtime;仅改 daemon 的 verify_pack 不够。 | -| `crates/dever-cli/src/libs.rs` | InstalledRegistry(709);tools(726)、runtime(797)、signed_artifact(823)、sandbox_resources(841)直接读版本根与根清单。 | -| `toolchain/cache.rs` | CacheStore 根实际为 cache/native(118),其中 ArtifactPut 单文件上限 64 MiB(81);不能用此 opaque artifact 上传接口安装 256 MiB 运行包。 | -| `toolchain/launcher.rs` | install/update 先下载后调用 MachineManager(27);当前 update 仅 core+skill,target 命令尚不存在。 | - -现有清单并非全目录严格白名单:verify_artifacts 验证声明文件,core_libraries 对 lib 目录另有精确 closure 检查。拆分后不能把“目录存在”或只读 root metadata 当作签名证明。所有消费者仍需验证所属声明和文件字节。 - -### 建议的数据契约:一个签名根清单 - -将现有根清单明确升级新格式,保留 `version/platform/artifacts`,增加有界 `extensions`。`artifacts` 仅基础必需项;`extensions` 每项为 `{kind, target, artifacts}`。enum `ExtensionKind = Runtime(Ecosystem) | Build(Ecosystem) | Target`;身份为 `(version, host_platform, kind, deployment_target, signed_catalog_sha256)`,内容身份可对该项规范化完整描述计算 SHA-256。根签名覆盖所有扩展文件完整 path/bytes/sha256,不需要第二套扩展密钥或可变 unsigned receipt 作为信任来源。 - -基础内容:core、LLVM 完整 private closure、本机四 profile runtime、host sandbox、bootstrap、skill/templates。Target(ARM) 包含 ARM native 四 profile/CRT 与 ARM sandbox。Runtime(pip/npm/go,target) 与 Build(pip/npm,target) 独立;Go runtime 已包含 host 工具和 target stdlib,不强造 build/go。无基础文件与扩展间路径重叠,也无扩展互相路径重叠。 - -根清单 validator 统一校验版本/host、枚举目标组合、重复 ID、规范路径、lowercase SHA、数量/字节溢出、每包上限与全部描述上限。按固定类型限制 logical path:runtime//、build//、Target 对应 runtime/ 与 sandbox/。防止扩展声明覆盖 core、lib、bootstrap、skill 或另一个 target。元数据顶层需 deny_unknown_fields;Python 同步语义,不维持兼容分叉。 - -外部 asset 名从固定 enum 计算;客户端与 manifest 不传任意 URL。每包一个 tar.zst;基础清单和签名单独发布;bootstrap 解码器作为原始文件单独发布并由根清单绑定。先签名固定原始内容,再压缩;确定性 USTAR 排序、mtime/uid/gid 和完整文件集继续成立。 - -### 扩展存储、接口与权限 - -推荐 `/opt/dever/cache/extensions////`;位于当前 service 可写范围内,和 `cache/native` 的可清理缓存分开。扩展先在专用 owner-private staging 中完全解压/验签/校验语义,fsync 文件和子目录,再 NOREPLACE rename 到最终路径。终态目录 0755、数据 0644,root-owned、不可被组/其他用户写;无需把 /opt/dever/cache 或 state 改成 0700。终态存在时重验内容而不是静默覆盖;失败仅清理自己 staging。manifest 摘要不同但版本相同必须失败,不创建并行“修正版”身份。 - -```rust -enum Operation { - // 现有操作…… - EnsureExtension { version: Version, extension: ExtensionId }, -} -struct ExtensionId { kind: ExtensionKind, target: BuildTarget } -// 网络/落盘仅 daemon 或拥有机器写权限的更新 owner 调用。 -fn ensure_extension(layout: &Layout, version: &Version, id: &ExtensionId) -> Result<(), String>; -// 只读;不得打开 root-only install.lock,也不得下载。 -fn resolve_extension(layout: &Layout, version: &Version, id: &ExtensionId) -> Result; -``` - -IPC 只接受已安装版本与其已验签目录声明的有限扩展,返回成功/内容身份而非用户指定路径。复用内核 UID/admission 和严格官方 HTTPS 下载,按请求限时、压缩/解压字节和数量限额;拒绝 caller 提供 URL、任意 filesystem path、payload 或 trust key。没有资源时 readonly resolve 返回准确 `dever lib install ...` 或 `dever target add linux-aarch64` 准备命令;run/build/check 不隐式进入 ensure。 - -采用一个 `SignedResources` 只读 owner,负责 root catalog、路径归属和已安装 extension 定位,供 InstalledRegistry 与 native pack 共用。`read_artifact(logical_path)` 与 `artifacts(prefix)` 只看到选定基础/扩展文件;避免构造 unsigned merged ReleaseManifest。RuntimePack::load 接收其实际资源根(base root 或 Target extension root),保留 logical path 到签名 artifacts 的逐项绑定。 - -SignedResources 需同时接入 libs.rs runtime/tools/sandbox_resources、service/compile.rs verify_pack、compile.rs worker RuntimePack::load。LLVM 动态库仍从 core 根加载。daemon BuildIdentity 必须包含所选 target pack 的签名/内容身份;不要让未使用扩展改变本机编译 cache identity。cache hit 仍重验所选 target pack。 - -### 更新与原子性 - -在同一个安装事务 owner 下读取 active 版本和其已安装扩展 ID 集合,验证新根清单有对应完整定义,下载并准备新 core+skill+这些扩展,最终重验后才 append active-version。失败保持旧 journal、旧 core 和扩展;已完整准备的新 immutable bytes 可留待重试复用,不声称更新成功。不自动安装新清单里所有扩展。 - -扩展选择直接由严格校验后的已发布目录集合导出,无需增加一个独立可漂移 selection pointer。若更新期间允许并行 ensure,必须在提交前锁内重新读取旧 active 扩展集合并补齐;更简单是将 ensure 与 update 的集合采样/发布串行化,避免丢失更新期间新增的扩展。沿用现有持久 inode lock,但不能在持有 exclusive lock 时递归调用再次 acquire 的公用 API;拆 locked 内部路径。当前锁为 try_lock,冲突会明确失败;如需“并发两项目都成功”应有限等待并在获锁后重验,不引入无限等待。 - -私有 staging 与 release.cleanup_staging 的全目录清扫不能冲突:若沿用 cache/staging,所有操作必须持同一安装锁;独立下载阶段则必须独占子树并禁止被旧 cleanup 删除。cache clean 目前只清 cache/native,保持其不删除 installed extensions。卸载版本时同安装锁删除对应扩展命名空间,active 保护不变。 - -当前 `dever update` 不更新机器 `/opt/dever/bin/dever[d]`,只更新版本目录/active。新资源 IPC 必須在首装 bootstrap launcher/daemon 中就存在;后续若改变 IPC,旧 daemon 兼容性是单独的 bootstrap 生命周期问题,不能假设 active core 更新自动重启了新服务。 - -### Zstandard:统一 Rust 解码,Python 验证后执行已有 launcher - -推荐 zstd crate 的安全 streaming wrapper,静态编入发行时所需 decoder library;不要手写 C FFI 或 ctypes 依赖宿主 libzstd。Rust release downloader 与 launcher 隐藏 extraction 入口复用一个 codec/archive 模块:固定 `window_log_max(27)` 对应 128 MiB、压缩输入上限、解压输出上限、精确 frame 结束与 EOF 检查。不得仅 tar 遍历到结束标记就成功,必须排空/校验 zstd frame 尾部,拒绝截断与尾随额外数据;默认 Decoder 会连续解多个 frame,单 frame 策略需显式实施。 - -首装 Python 保留 OpenSSL 签名锚:下载/验证根 manifest → 从基础 artifacts 的固定 bootstrap/dever 与 bootstrap/lib/* 集合,按 digest 命名的 raw assets 下载全部 launcher closure → 精确大小与 SHA 验证、权限落盘 → 以空环境、绝对路径执行隐藏 `--dever-extract ` → launcher 再验证根清单签名并调用共享 Rust USTAR 解包 → 完整已校验后执行 bootstrap 安装。配置与 trust key 仅放 root-owned scratch,不从应用读取。raw helper 文件与 payload 目标必须是两个目录,避免 create_new 冲突。需要 subprocess timeout 与失败后 kill/wait,不能把解包失败当成可继续安装。 - -现有 staged manifest 声明 `bootstrap/lib/libgcc_s.so.1`(`target/release-0.1.0/assets/dever-linux-x86_64.manifest.json:27`)。因此直接下载裸 launcher 不成立;但按主 agent 收敛方案,额外发布已签名 raw launcher + 完整小型私有 lib closure 后,复用 launcher 优于新 decoder bin:没有额外执行文件/第二套 tar validator。raw asset 文件名由既有 SHA 推导,不能由远端任意 URL 或目录控制。作者阶段仍需验证 ELF DT_NEEDED、RPATH、完整私有 closure,确保 zstd 为静态且 LLVM 不被引入 launcher/daemon;Linux libc/loader 为已声明 OS ABI。Python 在执行前只能信赖独立签名和已固定路径规则,签名发行 maker 对 closure 的检查仍是必要发行门槛。 - -Python SDK maker 可以使用作者提供的 zstd 工具或编码库完成 deterministic streaming tar.zst;这属于 author 工具链,不把系统 zstd 加成最终用户前提。公共资产总大小应单独计入 raw bootstrap closure,而不是只报告主 tar.zst。 - -### External references - -- [zstd Decoder API](https://docs.rs/zstd/latest/zstd/stream/read/struct.Decoder.html),本次页面为 0.14.0:Read streaming、single_frame、window_log_max;finish_frame 错误需要显式处理。版本选型应核对仓库 MSRV 并固定 Cargo.lock,本次没有安装或锁定依赖。 -- 本地 SDK `target/backend-sdk/usr/include/zstd.h:107` 为 1.5.5;`:606` 说明 streaming window 上限控制、`:648` 提供 DCtx 参数 API。这是本地已有头文件证据,不代表最终打包采用此版本。 -- GitHub zstd-sys Cargo.toml 页面读取失败;静态链接需在实施中核对选定 crate build 配置与产物 ELF,不能将本研究当作已验证链接证据。 - -### Related specs - -- `.trellis/spec/backend/toolchain-and-library.md:23` compiler-relative runtime 与 daemon 签名闭包;`:27` bootstrap;`:84–96` release/skill/author/ELF closure;`:337–343` onboarding、native release、shared toolchain 定向验收。 -- `.trellis/spec/backend/index.md`:本仓库是 Rust 语言编译器,不采用 Go Dever Model/Page/Service 规则。 -- `.trellis/tasks/10-04-slim-distribution/prd.md`:离线 run/build、多用户共享、按需自动生态、target 命令、core+已装扩展更新、不改宿主服务。 - -## Caveats / Not Found - -- 子 agent `task.py current --source` 返回 none;主 agent 已明确指定此任务与写入位置,未修改任务状态。 -- 本次未下载发行/依赖、未运行构建/测试、未改产品文件/服务,也未读取私钥或授权凭据。仅查看公开解码 API 文档。 -- 120 MiB 目标是已有压缩估算;codec 与新正式优化 core 会改变最终数字,尚无本次测量。 -- 精简需同时调整 package/Lib 显式准备策略:另一研究分支已发现 `source_workers_with_packages` 在 resolve_project 前读 runtime;不能只在 resolver 内 ensure。remove/doctor/check/run/build 必须 readonly。 -- 更新携带范围建议 active 版本已安装选择;若产品要求机器所有历史 pinned 版本的 union,应在设计明确,不应默默给新版本安装历史上任何扩展。 -- 大包首次安装、损坏重试、多 UID 同时 ensure、更新失败仍运行旧版、ARM cache hit 校验、decoder 超大 window/截断/尾随数据均需定向验收;本研究没有执行验证。 diff --git a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/task.json b/.trellis/tasks/archive/2026-10/10-04-slim-distribution/task.json deleted file mode 100644 index 65af244..0000000 --- a/.trellis/tasks/archive/2026-10/10-04-slim-distribution/task.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "slim-distribution", - "name": "slim-distribution", - "title": "Dever 精简发行与按需工具安装", - "description": "将基础包缩至约 120 MiB,拆分签名扩展并完成 lib install、target add、更新及实际发行验收", - "status": "completed", - "dev_type": null, - "scope": null, - "package": null, - "priority": "P2", - "creator": "Antigravity", - "assignee": "Antigravity", - "createdAt": "2026-10-04", - "completedAt": "2026-10-05", - "branch": "codex/slim-distribution", - "base_branch": "main", - "worktree_path": null, - "commit": "4fda7c8c1a33b843e2fca219cb3bc95c09471716", - "pr_url": null, - "subtasks": [], - "children": [], - "parent": null, - "relatedFiles": [], - "notes": "精简发行实现和本地验收完成:112.04 MiB基础包,58项定向、13阶段实包、4阶段本地更新事务通过。核心4fda7c8、skill27ac8f2及v0.1.1标签已推送。GitHub API未登录,二进制Release未上传、线上更新未跑;该外部发布待办不标为通过,详见implement.md与target/release-0.1.1/release-state.json。", - "meta": {} -} \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index bcaf762..9305692 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -24,7 +24,7 @@ Managed by Trellis. Edits outside this block are preserved; edits inside may be - This repository develops a new Rust bootstrap compiler, not the existing Go Dever application framework. Do not introduce Model, Page JSON or Service scaffolding here. - This is a new language under active design: change source contracts directly and migrate repository callers together. Do not add legacy aliases, compatibility modes, fallback implementations or speculative defensive branches. Keep required type/protocol validation, explicit errors and resource lifecycle semantics. -- Program source is `.dever` or `.dever.md`; the latter compiles only top-level fenced `dever` blocks and keeps Markdown headings/prose nonsemantic. One file owns one package; both formats share language/contract checks. The language contract is `.trellis/tasks/09-04-dever-language-mvp/prd.md`; Markdown source rules are in `LANGUAGE.md` and `.trellis/spec/backend/toolchain-and-library.md`. +- Program source is `.dever` or `.dever.md`; the latter compiles only top-level fenced `dever` blocks and keeps Markdown headings/prose nonsemantic. Both formats share language/contract checks. The public language contract is `LANGUAGE.md`; Markdown source rules are in `MARKDOWN-SYNTAX.md` and `.trellis/spec/backend/toolchain-and-library.md`. Internal tasks and journals stay local and are not required to build or test a checkout. - Compiler phases belong to `crates/dever-core`. Add the native runtime and CLI when their implementation stages need them; avoid empty crates and placeholder commands. - Read `.trellis/spec/backend/index.md` before editing. All permanent tests belong under repository-root `test/`. - Parser success means syntax success only. Do not present it as name resolution, type checking or executable language support. diff --git a/Cargo.lock b/Cargo.lock index 96c48a3..43ae7c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -430,7 +430,7 @@ dependencies = [ [[package]] name = "dever-backend-bridge" -version = "0.1.2" +version = "0.1.3" dependencies = [ "cc", "dever-core", @@ -443,7 +443,7 @@ dependencies = [ [[package]] name = "dever-cli" -version = "0.1.2" +version = "0.1.3" dependencies = [ "base64 0.22.1", "csv", @@ -471,7 +471,7 @@ dependencies = [ [[package]] name = "dever-core" -version = "0.1.2" +version = "0.1.3" dependencies = [ "dever-runtime", "pulldown-cmark", @@ -481,7 +481,7 @@ dependencies = [ [[package]] name = "dever-runtime" -version = "0.1.2" +version = "0.1.3" dependencies = [ "argon2", "base64 0.22.1", @@ -514,7 +514,7 @@ dependencies = [ [[package]] name = "dever-sandbox" -version = "0.1.2" +version = "0.1.3" dependencies = [ "command-fds", "goblin", @@ -527,7 +527,7 @@ dependencies = [ [[package]] name = "dever-tests" -version = "0.1.2" +version = "0.1.3" dependencies = [ "bytes", "dever-core", diff --git a/Cargo.toml b/Cargo.toml index da4c2ae..4a60d96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/dever-core", "crates/dever-runtime", "crates/dever-cli", "cra resolver = "3" [workspace.package] -version = "0.1.2" +version = "0.1.3" edition = "2024" rust-version = "1.95" publish = false diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md index 0635fc7..29d9884 100644 --- a/IMPLEMENTATION.md +++ b/IMPLEMENTATION.md @@ -489,7 +489,7 @@ File 的 create_new/open/read/write/close 与共享别名、同步 Stream 的共 Linux `deverd` 已接可信编译 IPC。managed core 提交逻辑源码、无秘密编译绑定及资源;daemon 验证签名版本与完整 pack 引用后,启动受限核心 worker 重新检查并编译。只由 daemon 发布缓存,不能通过普通 artifact 上传污染它;App/Test/Lib 准备与运行留在 caller。服务缺失明确失败。 -原生发行包作者入口 `sdk/native-release.rs` 从独立作者根的 `config/setting.json` 读取显式输入及摘要,复用既有 runtime manifest、验证器和 Ed25519 发行协议。制作器复制并复核四 profile、CRT 和核心/LLVM 文件,在私有 staging 中签名,再以不覆盖方式原子发布;私钥不进入产物。`runtime-pack` Cargo profile 为 base/sqlite/postgres/both 分别生成保留链接符号的优化 archive,共享一个构建缓存。相同输入和密钥的重复打包一致,不等同于跨机器源码构建一致。作者流程见 [native release SDK](sdk/native-release.md)。 +原生发行包作者入口 `sdk/native-release.rs` 从独立作者根的 `config/setting.json` 读取显式输入及摘要,复用既有 runtime manifest、验证器和 Ed25519 发行协议。制作器复制并复核四 profile、CRT 和核心/LLVM 文件,在私有 staging 中签名,再以不覆盖方式原子发布;私钥不进入产物。`runtime-pack` Cargo profile 为 base/sqlite/postgres/both 分别生成保留链接符号的优化 archive,共享一个构建缓存。相同输入和密钥的重复打包一致,不等同于跨机器源码构建一致。 作者配置的可选 `runtimes` 已接 Python/Node/Go 完整运行/构建输入,制作器与 Worker 共用 manifest 和文件闭包校验。排序且固定元数据的 gzip/tar、registry 描述统一进入顶层发行签名;Go SDK、Adapter 和依赖的编译共用 `-trimpath`,避免随机临时目录改变 Worker 与共享缓存身份。LLVM 的二进制资源附件复用既有摘要去重,在 verify 前初始化常量,IR 仍限8 MiB;附件最多4096项、单项128 MiB/总256 MiB,共享编译请求384 MiB、产物320 MiB,不透明 artifact 仍64 MiB。Linux x86_64 三生态签名安装、受管 `check/run/build`、三条共享缓存及移除源码/机器安装后无系统语言环境的独立执行已通过,包含Python/Node源码构建原生依赖与离线收据重放。Linux签名首装、旧签名模板升级、篡改拒绝、双项目及真实双UID共享核心亦已通过自有完整验收。Linux root 沙箱、真实第三方高级依赖、双 CMS/PG 和 LLVM 容量报告已补齐;公开首次安装包、六平台产品代码/资产、受限 AppArmor 非 root 入口与完整质量门仍未完成。各阶段证据及限制见当前生产化任务。 diff --git a/LANGUAGE.md b/LANGUAGE.md index a2f4880..782b012 100644 --- a/LANGUAGE.md +++ b/LANGUAGE.md @@ -53,7 +53,7 @@ cmd greet = app.greet 模板不需要数据库或 HTTP 配置。添加 HTTP 时再完整配置站点与身份,不能只添加 get 而遗漏 sites/auth。配置不会编译进二进制。`run` 使用项目目录中的配置;独立二进制启动时使用可执行文件同级的 `config/setting.json`,相对数据路径也以该目录为基准。 -语言在开发和安装后的命令名均为 `dever`,Go 框架使用 `dever-go`。开发仓库生成 `target/debug/dever`;机器版启动器根据 `config/setting.json` 中可选的精确 `dever.version` 选择已安装版本,未锁定项目使用机器活动版本,再把项目命令和退出码原样分派。启动器的内部构建名为 `dever-launcher`,安装后仍叫 `dever`,版本核心为 `dever-core`。Linux 安装制作与机器共享已实现;公开发行资产尚未发布。源码构建不会替换机器上已有的全局命令。 +语言在开发和安装后的命令名均为 `dever`,Go 框架使用 `dever-go`。开发仓库生成 `target/debug/dever`;机器版启动器根据 `config/setting.json` 中可选的精确 `dever.version` 选择已安装版本,未锁定项目使用机器活动版本,再把项目命令和退出码原样分派。启动器的内部构建名为 `dever-launcher`,安装后仍叫 `dever`,版本核心为 `dever-core`。Linux 机器安装由多个项目共享。源码构建不会替换机器上已有的全局命令。 以下命令在已经提供 `dever` 的开发环境中执行: @@ -72,7 +72,7 @@ Linux 开发环境运行构建产物: ``` - `new`:从随版本验证的模板原子创建新项目,不覆盖已有目录;`--markdown` 生成等价 Markdown 源码。 -- 机器版 `update`:从内置的 `https://git.dever.cc/shemic/dever/dist` 显式下载并校验,统一更新活动核心与对应 skill;不修改业务配置。`skill path [project-root]` 返回经验证的配套指引,`skill install ` 安装稳定的 AI 加载入口。项目可锁定 dever.version,普通项目命令不会触发更新。 +- 机器版 `update`:从官方仓库的 Releases 显式下载并校验,统一更新活动核心与对应 skill;不修改业务配置。`skill path [project-root]` 返回经验证的配套指引,`skill install ` 安装稳定的 AI 加载入口。项目可锁定 dever.version,普通项目命令不会触发更新。 - `check`:加载生产源码,完成语法、名称、类型、分句及应用入口可达性和冗余硬检查;不执行应用或准备运行资源。 - `fmt --check`:只检查格式,不修改文件。 - `fmt`:统一格式化项目 `module/` 和存在的 `test/`;需要修复格式时单独执行 `dever fmt my_app`。 @@ -255,7 +255,7 @@ my_app/module/news/article/app/query.dever ### 2.1 Markdown 程序源码 -使用 `.dever.md` 可以把程序和面向人的用途说明放在一起。Dever 代码仍写在顶层 `dever` 或 `typescript dever` 围栏中;`typescript dever` 让编辑器尝试使用 TypeScript 高亮,第二个标记用于确认其中仍是 Dever 源码。普通 `.md` 文档不参与编译。 +使用 `.dever.md` 可以把程序和面向人的用途说明放在一起。Dever 代码仍写在顶层 `dever` 或 `typescript dever` 围栏中;未安装 Dever 编辑器插件时,`typescript dever` 可让编辑器尝试使用 TypeScript 高亮,第二个标记用于确认其中仍是 Dever 源码。普通 `.md` 文档不参与编译。 Markdown 结构也是编译契约:一个一级标题说明包,一个二级标题说明一个 type 或一个逻辑函数。标题使用自然语言,技术名称、公开清单、输入输出和类型结构使用固定列表,并由编译器与代码核对。 @@ -295,7 +295,7 @@ get greeting = app.greet - 函数输入输出、条件分句、类型、失败义务、`pure` 和依赖边界都按现有 Dever 规则检查,说明文字不能代替正式契约。 - `check/api/run/build` 命令不变,并强制检查 Markdown 契约;错误显示 `.dever.md` 原文中的行列并关联对应代码。`fmt` 检查结构并仅更新程序块内部,保留说明、围栏和展示代码块。 -固定列表的完整格式见 [Dever Markdown 源码规范](MARKDOWN-SYNTAX.md),完整接口示例见 [Markdown CMS](examples/cms/md/module/news/article/api/admin/manage.dever.md)。`typescript dever` 只复用现有高亮规则;精确的 Dever 高亮、补全和语言服务仍需编辑器扩展。 +固定列表的完整格式见 [Dever Markdown 源码规范](MARKDOWN-SYNTAX.md),完整接口示例见 [Markdown CMS](examples/cms/md/module/news/article/api/admin/manage.dever.md)。安装 [VS Code 语法插件](editor/vscode/README.md) 后,两种围栏都使用与 `.dever` 相同的 Dever 高亮规则,`.dever.md` 保持 Markdown 语言模式。插件不提供补全、跳转或实时编译诊断;契约与语言合法性仍由编译器检查。 ### 2.2 应用测试 diff --git a/README.md b/README.md index 9d25a2f..7673608 100644 --- a/README.md +++ b/README.md @@ -1,173 +1,79 @@ # Dever -Dever 语言编译器。基础类型、表达式、命名输出、条件分句、集合、Stream 和值/资源语义已经接通语义检查与原生执行。提供源码格式化、基础标准库、JSON、HTTP/1.1 连接池、HTTP/2 多路复用、流式传输、SSE、WebSocket、TLS、可配置的有界并发,以及 SQLite/PostgreSQL 类型安全 ORM。Linux 机器安装、共享工具链与 ARM64 应用交叉构建已有实现;公开二进制发行资产、其它平台发行和自举仍需单独交付。 +Dever 是面向应用开发的编译型语言,提供类型检查、命名输出、穷尽分句、值与资源语义、结构化并发,以及 JSON、HTTP/1.1、HTTP/2、SSE、WebSocket、TLS 和 SQLite/PostgreSQL 类型安全 ORM。源码支持 `.dever` 和带说明的 `.dever.md`,两者使用相同语言规则。 -面向 Dever 程序开发者的完整语法、标准包和示例说明见 [Dever 语言开发指南](LANGUAGE.md);编译器的长期架构和语义实现见 [Dever 语言实现原理](IMPLEMENTATION.md)。 +## 安装与开始 -应用开发从 [安装指引](skills/references/install.md) 和配套 [dever-language skill](skills/SKILL.md) 开始。根目录 [install](install) 是自包含 Bash 安装入口,无需先克隆源码或安装 skill。服务器部署脚本和发行资产后,使用: - -```sh -curl -fsSL https://git.dever.cc/shemic/dever/install | bash -``` - -源码中的入口不等于线上已发布:该 URL 需要服务器返回纯脚本,配套签名资产放在同站 `dist/`。发布与旧安装迁移步骤见 [发行说明](sdk/native-release.md#public-installer-and-static-distribution)。 +当前开发机支持 Linux x86_64,要求 glibc 2.39 或更新版本。首次安装需要 Bash、curl、`/usr/bin/python3` 3.9+、支持 Ed25519 的 `/usr/bin/openssl` 和管理员权限;非 root 用户通过 `/usr/bin/sudo` 提权。 ```sh +curl -fsSL https://git.dever.cc/shemic/dever/raw/branch/main/install | bash dever new my_app +dever fmt my_app --check dever check my_app dever test my_app dever run my_app -- hello.greeting.greet '{"name":"Dever"}' dever build my_app --output my_app/program +./my_app/program hello.greeting.greet '{"name":"Dever"}' ``` -`new my_app --markdown` 生成等价 Markdown 项目,包含配置、AI 指引和应用测试。机器版 `dever update` 显式从内置官方发行源更新核心与配套 skill;`dever skill path [project-root]` 读取对应版本,`dever skill install ` 安装持续跟随机器版本的 AI 入口。地址不写入业务 `config/setting.json`,普通 run/build 不联网。多个项目共享 `/opt/dever`,无需在每个项目复制核心;`crates/` 与 `library/` 是编译器和标准库维护目录。源码统一位于 `ssh://git@git.dever.cc:2222/shemic/dever.git`,`skills/` 与核心同仓维护,无需额外克隆或初始化子模块。 +发行包可从 [Releases](https://git.dever.cc/shemic/dever/releases) 下载。安装使用 `/opt/dever` 和 `/usr/local/bin/dever`,并安装共享服务;详情见 [安装与更新](skills/references/install.md)。应用开发无需克隆编译器源码或安装 Rust、LLVM、Python、Node、Go 开发环境。 -[示例索引](examples/README.md) 以 CMS 为当前业务示例:[Dever 实现](examples/cms/dever/module/news/article/api/admin/manage.dever)和 [Markdown 实现](examples/cms/md/module/news/article/api/admin/manage.dever.md)同步维护。旧示例及编译拒绝反例归档在 `examples/old/`,正式回归测试保留在根目录 `test/`。 +`dever new my_app --markdown` 创建等价的 Markdown 项目。项目目录必须是新目录;`build` 输出必须是新文件,父目录必须存在。生成程序从可执行文件同级的 `config/setting.json` 读取配置,部署时保留这个目录结构。独立程序无需 Dever 编译器或应用源码;使用外部 Lib 时,所需运行资源随程序嵌入。 -源码同时支持 `.dever` 和 `.dever.md`。应用固定使用 `module///` 结构,role 为 App、Domain、Model、Port、Adapter、API 或 Job;源码不写 package 或 import,`public` 只允许修饰单条匿名 HTTP 声明。跨领域只能调用 `..` 形式的 App 能力,其他 role 保持领域私有。编译器从 API、CMD 和 Job 声明生成入口,不再使用 `module/main.dever`。应用测试放在 `test///`,由文件名选择同名零输入、零输出函数。Markdown 合同见 [Markdown 源码规范](MARKDOWN-SYNTAX.md)。CMS 展示账号、成员、会话、admin/front 站点以及平台库与租户库分离。 - -例如 `module/news/article/api/admin/manage.dever` 只声明入口,业务组合留在 App;`examples/old/` 保存旧合同回归材料,不是当前应用目录示例。 - -```dever -rest model -post publish = app.publish +```sh +sudo dever update +dever version +dever skill install <新的AI技能目录>/dever-language ``` -## 运行 +核心与配套 AI skill 一起更新。已有项目可在 `config/setting.json` 的 `dever.version` 锁定准确版本,并用 `dever skill path ` 查找对应指引。普通 `check/test/run/build` 不检查更新、不隐式联网。 -这是编译器开发仓库,构建编译器自身需要 Rust 1.95 或以上、锁定的 Cargo 依赖和显式准备的 LLVM 18/LLD 作者 SDK。私有 `dever run/build/test` 默认将 checked HIR 编译为 LLVM object,再通过内置 LLD 链接;不调用 Rust/Cargo/cc,不通过环境变量选择后端,也不隐式下载依赖。CLI 参数是项目根,源码固定放在项目根的 `module/` 中,运行配置固定为 `config/setting.json`。 +## 应用开发 -编译器同级必须有 `runtime//manifest.json` 声明的 runtime、CRT 和静态库。作者侧使用独立的 base、SQLite、PostgreSQL、双数据库优化 archive,通过 [原生发行包制作流程](sdk/native-release.md) 生成带签名清单的新目录;输入固定写在作者根下的 `config/setting.json`。 +应用按 `module///` 组织;role 为 App、Domain、Model、Port、Adapter、API 或 Job。API 声明入口,App 编排业务,Domain 表达内聚规则,Model 定义持久化合同,Port/Adapter 接入外部能力。跨领域只调用目标 App,其他角色保持领域私有。 -```bash -cargo build --offline --locked -p dever-cli --bin dever -cargo build --offline --locked -p dever-cli --example native-release -target/debug/examples/native-release --output +源码不写 `package`、`import` 或 `main`,入口由 API、CMD 和 Job 声明生成。HTTP 默认要求认证和权限,仅单条 `public` HTTP 声明允许匿名访问。配置集中在 `config/setting.json`,不从环境变量读取。应用测试放在 `test///`。 + +- [语言开发指南](LANGUAGE.md):语法、标准包、并发、Model、权限、租户、Job 和外部调用。 +- [应用开发规范](skills/references/development.md):目录、函数职责、复用、配置、测试和交付。 +- [dever-language skill](skills/SKILL.md):面向 AI 的应用开发指引。 +- [Markdown 源码规范](MARKDOWN-SYNTAX.md):说明与代码的一致性要求。 +- [CMS 示例](examples/README.md):同步维护的普通源码和 Markdown 实现。 +- [External Worker SDK](sdk/README.md):Python、JavaScript 和 Go Adapter 开发。 + +`dever fmt --check` 检查格式;`dever check ` 静态检查语言、目录、配置、API 基线及生产入口可达性,不执行应用。`dever test ` 执行项目全部应用测试,没有筛选参数;按改动选择验证,不默认运行大型项目的完整套件、真实数据库或性能测试。 + +## 依赖与应用目标 + +Dever Package 复用业务组件;Python、JavaScript、Go 生态依赖称为 Lib。通过显式 `dever package` 或 `dever lib` 命令准备依赖并写入 `dever.lock`,后续运行和构建使用锁定结果。已有锁的项目在新机器用 `dever lib install ` 恢复,不重新选择版本。相同版本的工具和资源由多个用户、项目共享。 + +Linux x86_64 开发机可以生成 Linux ARM64 应用: + +```sh +dever target add linux-aarch64 +dever lib update my_app --target linux-aarch64 +dever build my_app --target linux-aarch64 --output my_app/program-arm64 ``` -制作器离线工作,不覆盖已有目录;它复用安装端的格式/摘要校验,复制完成后签名,私钥不进入产物。私有调试可按制作说明将该 `runtime/`、`lib/` 放到匹配的 `dever` 同级。六目标正式发行仍需各自资产和平台验收。缺失或损坏的 pack 会明确报错;`check/fmt` 和零用例 `test` 不需要 runtime pack。 +没有外部依赖时省略 `lib update`;已有匹配目标的锁时改用 `lib install`。依赖及原生扩展必须支持目标架构。省略 `--target` 时使用本机目标,`run/test` 也在本机执行。ARM64 应用目标不代表提供 ARM64 宿主编译器;macOS、Windows 宿主安装暂未提供。 -现成 Linux 二进制可通过 Port 的 `external command "bin/tool" {}` 直接调用,传参数数组及可选 Bytes 输入,得到退出码与两路 Bytes 输出;不用实现 Worker 协议或编写包装脚本。`run/build` 自动嵌入程序和显式随附的动态库,限额与文件授权仍在 `config/setting.json`,不使用 shell、环境变量或 PATH。单独的 command 不需要 Lib 锁;完整写法见 [语言说明](LANGUAGE.md)。 +Linux 外部调用使用 OS 沙箱,需要系统允许所需 namespace 和 `openat2`;受限 AppArmor 环境还需要安装器配置的专用策略。系统策略不满足要求时明确失败,不退回无沙箱执行。HTTP/2 暂不支持 WebSocket-over-HTTP/2、CONNECT 或服务端推送。完整能力及限制见语言指南。 -外部 Lib 通过显式命令解析,项目声明写入 `config/setting.json` 的根 `lib` 数组,例如 `"lib": ["pip:fixture@1.0.0"]`,锁定结果写入 `dever.lock`;`run/build` 只消费已有锁,不联网、不读取环境变量或系统 PATH。旧 `config/lib.json` 不再接受: +## 编辑器 -```bash -dever lib add pip:fixture@1.0.0 -dever lib list -dever lib install -dever lib doctor -dever lib update -dever lib remove pip:fixture@1.0.0 -``` +[VS Code 语法插件](editor/vscode/README.md) 通过独立 VSIX 安装,支持 `.dever` 和 Markdown 中的 Dever 代码块、括号配对、自动闭合、缩进及 `#` 注释。无需先安装编译器;目前不提供补全、跳转、格式化或实时诊断。`dever update` 不负责更新编辑器插件。 -当前仓库已接入 PyPI、npm registry 和 Go proxy 解析、校验下载及机器共享缓存。真实 provider 只从已验证的机器资源读取签名 runtime 描述和 pack;缺少资源明确报错,不使用宿主语言环境。v6 锁绑定 Worker 合同、Python extras、npm 嵌套实例、Go sumdb 证据、准确源文件与完整构建输入。`lib install` 按已有锁恢复,配置和锁文件字节不变;第三方构建无法重现锁定摘要时明确失败。不同 Worker 独立解析依赖。显式 Lib 准备可使用签名工具包构建 PEP 517 sdist、执行 npm 安装钩子及原生 addon 编译;`run/build` 只复用已锁定输出。SDK 自动绑定 Port 同名操作并校验输入、结果与错误,见 `sdk/README.md` 和 `LANGUAGE.md`。Go Worker 使用锁定工具离线编译/链接,支持目标文件选择与 `go:embed`,启动不需要系统 Go。 +## 编译器源码开发 -发行包分为基础包和可选扩展。基础包保留 Dever 编译器、本机四种数据库运行库和配套 skill;Python/Node/Go 由 `lib add/update/install` 按实际需要准备,源码构建路径再准备构建工具。`dever target add linux-aarch64` 准备 ARM 应用目标。同版本资源在机器上共享,普通 `run/build` 不下载;`dever update` 更新核心、skill 和当前已安装的扩展,全部准备成功后才切换活动版本。基础与扩展均采用 Zstandard,首装无需系统 zstd。 +[源码仓库](https://git.dever.cc/shemic/dever) 使用 Rust;`crates/dever-core` 负责语言检查与编译,`crates/dever-runtime` 提供运行时,`crates/dever-cli` 提供命令,`library/` 保存标准 Dever 源码。架构及语义实现见 [实现原理](IMPLEMENTATION.md)。 -原生制作器已支持 Python/Node/Go runtime/build pack 的确定性打包与统一签名;Linux x86_64 三生态的签名安装、受管 `check/run/build` 和移除源码/机器目录后的无系统语言独立执行已通过,包含 Python/Node 原生依赖。Python sdist/extras/原生扩展、npm 高级依赖/安装钩子/native addon 和 Go sumdb 均已有实现及真实第三方依赖定向证据。Linux 签名首装、升级保护和两个项目/真实用户共享核心也已通过自有完整验收。Linux Worker 使用 OS 沙箱;当前 root 验收不代表受限 AppArmor 下非 root 部署通过。输入仍是私有作者资产和临时签名,尚未交付公开首次安装包或其他平台发行。具体流程见 [原生发行包制作流程](sdk/native-release.md)。 +构建编译器需要 Rust 1.95+、锁定的 Cargo 依赖和准备好的 LLVM 18/LLD SDK;仅构建 CLI 不足以运行应用,还需要匹配的应用编译资源。生产应用编译使用 LLVM/LLD,不调用系统 Rust/Cargo/cc。 -Dever Package 用 `config/setting.json.package` 声明,例如 `"package": {"registry": "https://packages.example.test", "use": ["catalog@^1.0.0"]}`。`dever package add/update/remove/list/doctor ` 共用机器摘要缓存;版本和传递依赖、Package 摘要及其 Lib 闭包统一写入 `dever.lock`。`check/test/run/build` 加载锁定的 Package 源码,不隐式解析或下载,不允许 Package 覆盖本地同名组件;离线移除保留剩余 Package 的锁定版本。这里的 registry 地址只是配置格式示例,不是已发布服务。 +永久测试位于根目录 `test/`,按修改选择最小定向检查,例如: -编译器底层已有 LLVM 18/LLD 连接桥和强类型 HIR→LLVM 转换,覆盖数值(含 Decimal)、Text/Id、Bytes、集合、嵌套记录/选择型/可空值、静态 handler、遍历、Result 和原始错误调用链。文件/流、真实协程、Task/Group/Channel、blocking/parallel、TCP/HTTP/TLS/SSE/WebSocket 及系统能力复用原 runtime 和同一 typed ABI。受管值通过具体生命周期回调转移,业务不经过解释器或动态 Value。简单内核已验证六目标链接,复杂内核已验证六目标对象及 Linux x86_64 实际执行;Windows 复杂链接仍需正式 runtime 支持。Rust unsafe 例外仅限桥接 crate 的私有 `ffi.rs`,不是语言 FFI。 - -独立 LLVM 应用入口已接通 CMD→App→配置选中的 Dever/external Port/Adapter、SQLite/PostgreSQL Model/事务,以及 HTTP/REST、可信身份、自动权限、database-only 租户/组件状态、Cookie/Header、Upload 存储和日志配置。持久 Job 复用现有队列、重试、调度、权限重验和事务;应用 Test 保持整套一次编译、稳定用例编号、每用例独立进程及 fake/数据库/时钟隔离。external 调用沿用统一 Worker 协议,支持具名类型化输入/输出、声明的业务错误和校验后提取的内嵌资源;只在边界编码 JSON。Worker 属于本次运行,退出时先关闭 Worker,再排空子任务和关闭其他资源;配置仍只读取 `config/setting.json`。私有 CLI 和 Linux 可信 daemon 编译已接 LLVM,正式目标包和跨平台发行仍未交付;本机定向验收不等于性能或正式发行验收。 - -```bash -cargo run --offline --quiet -p dever-cli --bin dever -- check examples/cms/dever -cargo run --offline --quiet -p dever-cli --bin dever -- test examples/cms/dever -cargo run --offline --quiet -p dever-cli --bin dever -- fmt examples/cms/dever --check -cargo run --offline --quiet -p dever-cli --bin dever -- run examples/cms/dever -- user.account.bootstrap '{"tenant_key":"tenant-one","tenant_name":"Tenant One","email":"owner@example.com","display_name":"Owner","password":"change-me-now"}' -cargo run --offline --quiet -p dever-cli --bin dever -- tenant migrate examples/cms/dever 1 -cargo run --offline --quiet -p dever-cli --bin dever -- tenant owner examples/cms/dever 1 admin 1 -cargo run --offline --quiet -p dever-cli --bin dever -- tenant owner examples/cms/dever 1 front 1 -cargo run --offline --quiet -p dever-cli --bin dever -- check examples/cms/md -cargo run --offline --quiet -p dever-cli --bin dever -- test examples/cms/md -cargo run --offline --quiet -p dever-cli --bin dever -- clean examples/cms/dever -``` - -`tenant migrate` 和两条 `tenant owner` 中的租户 `1` 应替换为 bootstrap 响应中的 `tenant_id`,Owner 命令最后的用户 `1` 应替换为响应中的 `user_id`。迁移先建立租户物理库和私有 Job/授权 schema,再分别为 admin/front 站点建立核心 RBAC Owner,完成后才能启动受保护 API/Worker。bootstrap 中的 Owner membership 是业务成员身份,不代替核心接口授权。两套 CMS 源码具有相同的 Model 与 App 合同。编译器开发入口是 `target/debug/dever`,也是 `cargo run -p dever-cli -- ...` 的默认目标。机器版启动器的内部构建名是 `dever-launcher`,发行时安装为 `dever`,版本核心仍安装为 `dever-core`。Go 框架使用独立的 `dever-go`;本仓库构建不会安装或替换全局命令。 - -正式工具链只公开一个安装在机器级 `bin/` 下的 `dever`。它从签名版本仓库选择版本:项目可在 `config/setting.json` 写精确的 `{"dever":{"version":"0.1.0"}}`,未写时使用机器活动版本。`install/update/use/uninstall/version/cache status/cache clean` 属于机器管理命令。`dever clean ` 只回收当前用户超过 24 小时且所属进程已经退出的 Dever 临时构建目录和旧 `.dever-run-*` 文件,不删除 build 输出、源码、配置、data、Lib 或 Cargo 缓存。Linux `deverd` 已用内核 peer credential 接受其他机器用户的状态查询和按 SHA-256 传输的共享 Lib 资产,非服务所有者不能清缓存或读取管理 token;普通查询返回 `verified:false` 的元数据摘要,完整校验与清理由管理员执行。服务不可用明确失败,不会本地回退。开发 fixture 可用 `deverd --root ` 启动服务。编译器贡献者清理本仓库 `target/` 时使用 Cargo 自己的 `cargo clean`。Linux daemon 编译提交规范源码和无秘密配置绑定,签名核心重新检查并编译;完整相同输入可跨项目、跨用户复用产物。App/Test 仍由调用者运行。macOS/Windows 跨用户认证、系统服务注册和正式原生发行仍未交付,开发态 socket 不等于完整跨平台安装。 - -保留一个可独立运行的程序: - -```bash -cargo run --offline --quiet -p dever-cli --bin dever -- build examples/cms/dever --output examples/cms/dever/cms-app -./examples/cms/dever/cms-app user.account.bootstrap '{"tenant_key":"tenant-one","tenant_name":"Tenant One","email":"owner@example.com","display_name":"Owner","password":"change-me-now"}' -``` - -`build` 的输出路径必须是新文件,父目录必须存在;已有文件不会被覆盖。独立程序从可执行文件同级的 `config/setting.json` 加载配置,因此正式产物放在项目根或保持相同的部署目录结构。编译和运行使用同一 LLVM 路径;`run` 直接执行编译器持有的临时程序,临时 object、链接输入快照和程序在执行后清理。私有作者缓存位于编译器同级 `cache/native`,绑定编译器、pack/profile 和完整 IR;命中仍检查 pack 和程序完整性。独立程序无需 LLVM、Cargo、Rust 工具链或 `.dever` 源码即可运行。机器管理的 `dever-core` 通过可信 daemon 编译;服务缺失明确失败,不降级到私有缓存。签名版本必须覆盖 native manifest、全部链接输入和编译器动态库,命中缓存也重新校验。 - -## 已支持 - -Linux x86_64 开发机可用 `dever build <项目目录> --target linux-aarch64 --output <新文件>` 生成 ARM64 应用;部署端不需要 Dever 编译器、Rust 或 LLVM。工具链须已包含对应 ARM 运行库,第三方 Lib 用 `dever lib update <项目目录> --target linux-aarch64` 显式准备。省略目标继续本机构建,`run/test` 也保持本机执行。构建不隐式联网、不读取环境变量选择工具;作者输入及 Go 宿主工具与目标标准库的区别见 [发行制作说明](sdk/native-release.md)。 - -- 应用源码使用路径推导的 component/domain/role;App 自动成为跨领域能力,其他 role 仅在所属领域内可见。Model/API 主文件可与同 role 主题目录共存;其余 role 的主文件与目录互斥,单个非 Model/API 主题应并回主文件。 -- Bool、Int、Decimal、Float、Text、Id;字段型、选择型、可空值、List、Map、MapEntry、Bytes 和 `Stream`。 -- 构造、字段读写、算术、比较、布尔短路、单个及多个命名输出;初始化检查、稳定类型和值语义。 -- Int/Decimal 字段与输出范围、`private` 字段、`error` 失败义务、默认错误传播、`result(call)` 主动捕获、`fail(...)`、显式 `recover("reason")` 和传递式 `pure` 检查;API 基线约束公开契约变化,保守建议提示重复判断和包装。用法见 [指南第 18 节](LANGUAGE.md#18-编译器约束与公开接口)及 `examples/old/dever/contracts/`。 -- 分句是唯一条件分派方式,检查重叠、遗漏、不可达和多输入组合;`other` 是所在输入位置全部明确模式的补集,不依赖书写顺序。 -- `each`、`reduce`、`reduce_until`、`filter`、`find`、`sum`、`append`、`first`、`get`、`put`、`remove`、`entries`、`length`。List、Bytes 和 Stream 共用静态 handler 检查,handler 参数可跨函数转发但不是运行时值。Map 保留插入顺序,可空返回不产生嵌套可空类型。 -- `parallel_each(handler, sequence, workers[, context])` 接受 List、Bytes、Stream 或 AsyncStream,并根据序列与 handler 的挂起 effect 选择作用域线程、共享 blocking worker 或有界 Group。并发数始终有上限,返回前清理已启动工作;副作用完成顺序不保证。 -- 普通调用自动等待其完整调用链;源码不声明 `async`,也不写 `await`。`run`、`wait`、`stop`、`timeout`、`race`、有界 `Group`、`parallel`、`blocking` 和有界 `Channel` 构成结构化并发基础。Task/Group 必须在父作用域消费,超时和竞争都会清理剩余任务。 -- `run/build` 的应用入口由 API、CMD 和 Job 声明生成;CMD 以稳定名称和一个 JSON 对象选中。HTTP API 按 `config/setting.json` 的 `sites..path` 归属站点,浏览器 Cookie 使用配置的外部 `sites..origin` 做精确同源校验;默认需要认证,只有单条 `public get/post/put/delete` 可匿名。函数、用户类型和 package 依赖不能形成循环。 -- `dever test ` 按名称串行执行 `test/` 中的应用测试。`assert(Bool)` 与同类型可比较值的 `assert_eq(actual, expected)` 只在测试源码可用;每个用例使用独立进程,涉及 Model 时使用运行器生成的临时 SQLite 配置,不读取部署数据库配置,也不从环境变量接收数据库覆盖。 -- `library/` 中的核心和官方 package 都是正常检查的 `.dever` 源码。Text 提供 Unicode 标量索引/切片、字符编码转换、查找、切分、替换与连接;Int/Decimal/Float 提供解析与文本转换。解析失败或索引越界返回 `null`,不截断或默认为零。 -- Bytes 与文件/TCP 资源原语;可恢复错误使用选择型结果,数值故障和标准输出失败定位到 `.dever` 源码。 -- Model role 提供隐式 ID/创建时间、静态 CRUD、分页/游标/Stream、关联、迁移、Seed、事务和参数化 typed native SQL;Model 操作只能由所属领域 App 调用,SQLite 与 PostgreSQL 共享 Model、QueryPlan 和 schema 语义。 -- `dever.auth` 通过配置引用的只读 App verify 建立三字段隐藏身份;所有非 `public` HTTP API 自动按 `component.domain.site.action` 查询核心 RBAC,源码不写权限字符串。权限目录、角色、角色权限和用户角色由 Dever 私有表维护;用户 Job 只保存入口权限键,执行前重新验证身份、组件状态和当前角色。多租户只支持 `tenant.database` 选择控制连接;`global type` 留在平台库,其他 Model 使用独立租户数据库,租户组件从 Model/Job 自动推导并可由受控 CLI 禁用或恢复。未迁移、未就绪、组件禁用或缺少租户上下文都直接失败,不回退平台库。 -- 自动 REST 支持 `owner` 行范围及字段级 `create/replace/search` 纯绑定;上传使用有界 multipart spool 和 affine `Upload`,只允许 POST App 直接接收,并经 Port/Adapter 调用 `dever.storage.put` 或显式关闭。 - -## 格式化与官方库 - -`dever fmt ` 统一规范化 `module/` 和存在的 `test/` 中的两空格缩进、换行和空白,保留注释、表达式分组及 record 字段的求值顺序。`--check` 只列出需格式化的文件并返回非零。格式化不要求语义检查通过;整批源码先通过语法检查和写入准备,才逐文件原子替换,不能把操作系统中途故障视为跨文件事务。 - -`.dever.md` 先检查标题、说明列表和代码块的一对一结构,再只格式化 Dever 代码块内部;说明文字、标题、围栏和其它代码块保持原样。语义检查还会拒绝与代码名称、类型、数量或顺序不一致的说明。 - -- `dever.process.arguments()` 读取应用参数(不含可执行文件路径);应用配置只读 `config/setting.json`。`dever.time` 提供 Unix 毫秒、单调纳秒和显式等待,均返回源码定义的结果类型。 -- `dever.task.sleep(milliseconds)` 提供非阻塞等待,`ticks(milliseconds)` 提供不积压的周期流;调用链是否挂起由编译器推断。同步 `dever.time.sleep` 保持阻塞语义。 -- `dever.json.parse(text)` / `stringify(document)` 使用普通分句、reduce 和 Map 完成 JSON 解析与编码。`dever.json.value` 定义公共结果、文档和节点类型,节点以整数链接表示嵌套;数字保留原文。重复键、非法转义、未配对代理项和多余输入明确失败。深度最多 256 层;编码最多 16,777,216 个 Unicode 标量,并验证手工构造的文档引用。 -- `dever.http` 复用 Hyper 的 HTTP/1 与 HTTP/2 引擎,支持持久连接、逐块响应和 SSE;HTTP/1 支持流水线、chunked 和 WebSocket 升级。`client/request/open/open_stream` 提供固定目标的有界连接池和流式上传/下载,支持 DNS。设置 `limits.http2 = dever.http.default_http2_limits()` 开启 HTTP/2 多路复用,独立限制连接数、流数和接收窗口。TLS 复用 rustls/tokio-rustls,校验证书并为 HTTP/2 协商 ALPN h2;关闭 Listener 后通过 GOAWAY 排空。静态 handler 可携带类型化 Context。WebSocket-over-HTTP/2、CONNECT、推送与其他协议扩展仍未交付。 - -JSON 算法和官方接口位于 `library/dever/`;HTTP 的协议状态机复用运行时中的 Hyper,业务 handler 直接编译执行。精确限制见 [LANGUAGE.md](LANGUAGE.md)。 - -`examples/old/` 保留旧语言合同、网络和运行时回归材料;它们不代表当前应用目录结构。[CMS 示例](examples/cms/dever/module/news/article/api/admin/manage.dever) 展示 App/Domain/Model 边界、站点认证、平台/租户数据分离和发布事务。 - -## 资源边界 - -普通值复制后独立修改;资源句柄和 Stream 别名共享资源状态。关闭文件或连接任一别名后,其他别名的操作会得到 `Failed`;关闭 Stream 任一别名后,全部别名结束,重复关闭无副作用。`dever.io.create` 只创建新文件,不覆盖已有文件;`open` 只读打开。`read` 和 `chunks` 接受正数大小上限,允许短读;Stream 在自然 EOF 后结束,终止错误只产生一个 `Failed` 项。 - -TCP 的连接、监听、接收、读写会被推断为挂起并复用一个 Tokio runtime;`connect_timeout` 要求数值 IP。连接流和字节流为 `AsyncStream`,按需拉取;`parallel_each` 使用有界任务组,先等待容量再拉取。Socket 支持同时读写,关闭唤醒等待方,取消部分写入会关闭连接。HTTP、SSE、WebSocket 共用现有任务作用域和连接限额;停止服务会排空升级后的会话。文件 I/O 仍需通过 `blocking(...)` 与调度线程隔离。 - -HTTP 池的连接上限包含空闲连接;响应体读完才归还连接,提前关闭则丢弃该连接。流式传输按块限制并复用 Bytes 存储,不收集整条长连接。TLS 配置共享信任材料,并使用小容量的有界会话缓存。线程、任务、连接和块大小上限共同约束运行资源,应用保留的数据和操作系统缓冲仍需单独计入内存。 - -这是全新语言,接口直接迭代,仓库源码同步迁移,不提供旧源码兼容别名或回退后端。TCP 用法见 [异步 TCP 示例](examples/old/dever/async_tcp/module/main.dever);流的关闭、限流和取消契约见 [LANGUAGE.md](LANGUAGE.md)。 - -编译器通过最后使用分析移动普通值;含文件、Socket、Listener 或 Stream 的值保留到源码作用域结束,避免优化提前关闭外部资源。基准解释器仅通过 `reference` feature 启用,用于与原生结果和故障位置进行差分验证;CLI 的默认 `build/run` 不使用解释器。 - -记录字段更新、独占列表消费、直接字符遍历和可证明安全的集合融合由编译器自动优化。HTTP 复用 Hyper 增量协议处理,Bytes 共享消息缓冲区;List/Bytes 并行动作按有限批次分发。私有 LLVM CLI 复用编译器同级 `cache/native` 的原生产物,命中时仍检查源码、API 基线、pack 和程序完整性;Lib 资产和 Linux 编译产物通过 `deverd` 共享;编译缓存按完整请求复用,不能仅凭产物摘要读取。大型 Worker 资源随原生产物内嵌;启动校验按块读取。前端检查结果仅在同进程内缓存。实现与边界见 [IMPLEMENTATION.md](IMPLEMENTATION.md)。 - -## 定向验证 - -按当前修改选择定向测试,不默认运行全部测试。原生测试会执行本地小程序;资源测试只使用自身临时目录、临时 SQLite 数据库及 `127.0.0.1` 随机端口。真实 PostgreSQL 测试默认忽略,只有仓库根 `config/setting.json` 明确配置 `database.postgres_test` 后才手动运行,不接受环境变量或命令行连接覆盖。可复制 `config/setting.example.json` 后按本机 PostgreSQL 凭据修改;测试 URL 的数据库名必须保留 `{case}` 占位符。 - -```bash +```sh cargo test --offline -p dever-tests --test core_semantics -cargo test --offline -p dever-tests --test core_native -cargo test --offline -p dever-tests --test runtime_foundations -cargo test --offline -p dever-tests --test hello_native -cargo test --offline -p dever-tests --test structured_concurrency -cargo test --offline -p dever-tests --test async_runtime -cargo test --offline -p dever-tests --test async_native -cargo test --offline -p dever-tests --test async_composition -cargo test --offline -p dever-tests --test pooled_network -cargo test --offline -p dever-tests --test pooled_library ``` -新增工具和库按需选择 `formatter`、`standard_library`、`native_ownership`、`concurrency`、`json_library`、`http_library`、`http_engine`;差分验证使用 `cargo test --offline -p dever-tests --features reference --test differential`。 - -`performance` 默认忽略,只在明确进行有界性能验证时运行:`cargo test --offline -p dever-tests --test performance -- --ignored --nocapture`。它比较 Int、Float、List、Decimal、Map 五个本地计算内核,排除构建、文件读取和进程启动,构建耗时单独记录。双方交错运行五个独立进程,每个进程预热后取九次测量,以各自全部样本的中位数比较,目标不超过对应基线的 1.15 倍。结果只代表该环境和这些内核,不代表 HTTP 吞吐或整个语言的性能。 - -同一目标还包含 `allocation_sensitive_source_scenarios`,运行 `test/dever-tests/fixtures/performance` 的记录文本、列表、JSON 和 16,384 个不同键用例。`concurrency` 的 `parallel_task_granularity_measurement` 也默认忽略,用于有限任务调度测量,不启动服务。耗时、内存与验证范围见任务实施记录。 - -独立二进制的常驻内存、异步调度和 HTTP/HTTPS 基准位于 [test/performance](test/performance/README.md)。构建和运行分开,支持专属 cgroup 预算及 Rust runtime/Hyper 对照,保存原始计数、延迟与资源采样。文档包含首轮 1 worker/128 MiB 短时结果及 64 MiB 空闲验证;这些结果不代表吞吐上限或长期稳定性。基准必须显式运行,不进入默认测试。 +语言接口直接迭代,源码调用方须同步更新。旧语法回归材料位于 `examples/old/`,不要用作新项目模板。 diff --git a/crates/dever-cli/src/toolchain/launcher.rs b/crates/dever-cli/src/toolchain/launcher.rs index 7f13abd..8a2aada 100644 --- a/crates/dever-cli/src/toolchain/launcher.rs +++ b/crates/dever-cli/src/toolchain/launcher.rs @@ -46,13 +46,14 @@ pub fn execute_in(layout: &Layout, arguments: &[OsString]) -> Result { let requested = utf8(requested, "version")?; - super::release_source::prepare(layout, requested)?; - let version = manager.install_requested(requested)?; + let version = super::release_source::prepare(layout, requested)?; + let version = manager.install_requested(version.as_str())?; Ok(CommandResult::Message(format!("installed Dever {version}"))) } [command] if command == "update" => { - super::release_source::prepare(layout, "latest")?; - let version = manager.update()?; + let source = super::release_source::ReleaseSource::official(); + let version = super::release_source::prepare_from(layout, "latest", &source)?; + let version = manager.update_version_with(&version, &source)?; Ok(CommandResult::Message(format!( "updated Dever and dever-language skill to {version}" ))) diff --git a/crates/dever-cli/src/toolchain/release.rs b/crates/dever-cli/src/toolchain/release.rs index 684ec25..ed8f6ac 100644 --- a/crates/dever-cli/src/toolchain/release.rs +++ b/crates/dever-cli/src/toolchain/release.rs @@ -318,27 +318,35 @@ impl MachineManager { /// Uses the ordinary install transaction with an explicitly supplied author transport. pub fn update_with(&self, source: &dyn super::ExtensionSource) -> Result { let version = self.releases.latest()?; + self.update_version_with(&version, source) + } + + pub(super) fn update_version_with( + &self, + version: &Version, + source: &dyn super::ExtensionSource, + ) -> Result { let _lock = InstallLock::acquire(&self.layout)?; #[cfg(target_os = "linux")] super::bootstrap::require_no_pending(&self.layout)?; if self .active_version()? - .is_some_and(|active| version < active) + .is_some_and(|active| version < &active) { return Err(format!( "refusing to downgrade active Dever with 'dever update' to {version}; use 'dever use {version}' for an explicit installed-version switch" )); } self.cleanup_staging()?; - self.install_locked(&version)?; + self.install_locked(version)?; if let Some(active) = self.active_version()? { let resources = super::extensions::SignedResources::load(&self.layout, &active)?; for extension in resources.installed_extensions()? { - super::extensions::ensure_locked(&self.layout, &version, &extension, source)?; + super::extensions::ensure_locked(&self.layout, version, &extension, source)?; } } - self.activate_locked(&version)?; - Ok(version) + self.activate_locked(version)?; + Ok(version.clone()) } pub fn activate(&self, version: &Version) -> Result<(), String> { diff --git a/crates/dever-cli/src/toolchain/release_source.rs b/crates/dever-cli/src/toolchain/release_source.rs index 522a827..bb38c5d 100644 --- a/crates/dever-cli/src/toolchain/release_source.rs +++ b/crates/dever-cli/src/toolchain/release_source.rs @@ -1,13 +1,15 @@ //! Explicit installation/update downloads. Project commands never enter here. +use std::cell::RefCell; +use std::collections::{BTreeMap, BTreeSet}; use std::fs::{self, File, OpenOptions}; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; +use std::rc::Rc; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::{Duration, Instant}; use super::extensions::Extension; -#[cfg(test)] use super::extensions::PAYLOAD_LIMIT as RELEASE_LIMIT; #[cfg(test)] use super::release::ReleaseManifest; @@ -18,14 +20,87 @@ use super::release::{ }; use super::validate_catalog; -const OFFICIAL_RELEASES: &str = "https://git.dever.cc/shemic/dever/dist"; +const OFFICIAL_RELEASES: &str = "https://git.dever.cc/api/v1/repos/shemic/dever/releases"; const DOWNLOAD_TIMEOUT: Duration = Duration::from_secs(300); const METADATA_LIMIT: u64 = 2 * 1024 * 1024; +const ASSET_LIMIT: usize = 512; static NEXT_DOWNLOAD: AtomicU64 = AtomicU64::new(0); pub(super) struct ReleaseSource { - base: String, + base: url::Url, agent: ureq::Agent, + releases: RefCell>>, +} + +#[derive(serde::Deserialize)] +struct ReleaseMetadata { + tag_name: String, + draft: bool, + prerelease: bool, + assets: Vec, +} + +#[derive(serde::Deserialize)] +struct ReleaseAsset { + name: String, + browser_download_url: String, + size: u64, +} + +struct ResolvedRelease { + version: Version, + assets: Vec, +} + +impl ResolvedRelease { + fn parse(bytes: &[u8], requested: &str) -> Result { + let metadata: ReleaseMetadata = + serde_json::from_slice(bytes).map_err(|_| "invalid official release metadata")?; + if metadata.draft || metadata.prerelease { + return Err("official release must be published and stable".into()); + } + let version = Version::parse( + metadata + .tag_name + .strip_prefix('v') + .ok_or("invalid official release tag")?, + )?; + if requested != "latest" && version.as_str() != requested { + return Err("official release tag does not match the requested version".into()); + } + if metadata.assets.is_empty() || metadata.assets.len() > ASSET_LIMIT { + return Err("official release asset count is outside its limits".into()); + } + let mut names = BTreeSet::new(); + for asset in &metadata.assets { + if asset.name.is_empty() + || asset.name.len() > 255 + || !asset + .name + .bytes() + .all(|byte| byte.is_ascii_alphanumeric() || b"-_.".contains(&byte)) + || asset.size == 0 + || asset.size > RELEASE_LIMIT + { + return Err("invalid official release asset metadata".into()); + } + if !names.insert(&asset.name) { + return Err("official release contains duplicate asset names".into()); + } + } + Ok(Self { + version, + assets: metadata.assets, + }) + } + + fn asset(&self, suffix: &str) -> Result<&ReleaseAsset, String> { + let name = format!("dever-{}.{suffix}", platform_identity()); + self.assets + .iter() + .find(|asset| asset.name == name) + .ok_or_else(|| format!("official release is missing required asset '{name}'")) + } } impl ReleaseSource { @@ -35,7 +110,8 @@ impl ReleaseSource { fn new(base: String) -> Self { Self { - base, + base: url::Url::parse(&base).expect("release API origin is compiled in"), + releases: RefCell::new(BTreeMap::new()), agent: ureq::Agent::new_with_config( ureq::Agent::config_builder() .proxy(None) @@ -46,19 +122,33 @@ impl ReleaseSource { } } - fn asset(&self, requested: &str, suffix: &str) -> String { - format!( - "{}/{requested}/dever-{}.{suffix}", - self.base, - platform_identity() - ) + fn resolve(&self, requested: &str, started: Instant) -> Result, String> { + let selection = if requested == "latest" { + "latest".to_owned() + } else { + Version::parse(requested)?; + format!("tags/v{requested}") + }; + if let Some(release) = self.releases.borrow().get(requested) { + return Ok(Rc::clone(release)); + } + let bytes = self.read_metadata(format!("{}/{selection}", self.base), started)?; + let release = Rc::new(ResolvedRelease::parse(&bytes, requested)?); + for asset in &release.assets { + validate_download_url(&asset.browser_download_url, &self.base)?; + } + let mut releases = self.releases.borrow_mut(); + releases.insert(release.version.to_string(), Rc::clone(&release)); + releases.insert(requested.to_owned(), Rc::clone(&release)); + Ok(release) } fn response( &self, - mut address: String, + address: String, started: Instant, ) -> Result, String> { + let mut address: String = validate_download_url(&address, &self.base)?.into(); for _ in 0..=5 { let remaining = DOWNLOAD_TIMEOUT .checked_sub(started.elapsed()) @@ -94,19 +184,13 @@ impl ReleaseSource { if locations.next().is_some() { return Err("release redirect has multiple Locations".into()); } - address = redirect(&address, location)?; + address = redirect(&address, location, &self.base)?; } Err("official release download exceeded its redirect limit".into()) } - fn metadata( - &self, - requested: &str, - suffix: &str, - path: &Path, - started: Instant, - ) -> Result<(), String> { - let mut response = self.response(self.asset(requested, suffix), started)?; + fn read_metadata(&self, address: String, started: Instant) -> Result, String> { + let mut response = self.response(address, started)?; let mut bytes = Vec::new(); response .body_mut() @@ -117,8 +201,27 @@ impl ReleaseSource { if bytes.len() as u64 > METADATA_LIMIT { return Err("official release metadata exceeds its size limit".into()); } + Ok(bytes) + } + + fn metadata(&self, asset: &ReleaseAsset, path: &Path, started: Instant) -> Result<(), String> { + if asset.size > METADATA_LIMIT { + return Err("official release metadata exceeds its size limit".into()); + } + let bytes = self.read_metadata(asset.browser_download_url.clone(), started)?; + if bytes.len() as u64 != asset.size { + return Err("official release asset size does not match its metadata".into()); + } write_new(path, &bytes) } + + fn open_asset(&self, asset: &ReleaseAsset, started: Instant) -> Result, String> { + let response = self.response(asset.browser_download_url.clone(), started)?; + Ok(Box::new(AssetReader { + reader: response.into_body().into_reader(), + remaining: asset.size, + })) + } } impl super::ExtensionSource for ReleaseSource { @@ -127,30 +230,58 @@ impl super::ExtensionSource for ReleaseSource { version: &Version, extension: &super::ExtensionId, ) -> Result, String> { - Ok(Box::new( - self.response( - self.asset(version.as_str(), &extension.asset_suffix()), - Instant::now(), - )? - .into_body() - .into_reader(), - )) + let started = Instant::now(); + let release = self.resolve(version.as_str(), started)?; + self.open_asset(release.asset(&extension.asset_suffix())?, started) } } -fn redirect(current: &str, location: &str) -> Result { +struct AssetReader { + reader: R, + remaining: u64, +} + +impl Read for AssetReader { + fn read(&mut self, buffer: &mut [u8]) -> io::Result { + if buffer.is_empty() { + return Ok(0); + } + if self.remaining == 0 { + if self.reader.read(&mut [0])? != 0 { + return Err(io::Error::other("release asset exceeds its declared size")); + } + return Ok(0); + } + let limit = self.remaining.min(buffer.len() as u64) as usize; + let count = self.reader.read(&mut buffer[..limit])?; + if count == 0 { + return Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "release asset is shorter than its declared size", + )); + } + self.remaining -= count as u64; + Ok(count) + } +} + +fn validate_download_url(address: &str, origin: &url::Url) -> Result { + let next = url::Url::parse(address).map_err(|_| "invalid release asset URL")?; + if next.origin() != origin.origin() + || !next.username().is_empty() + || next.password().is_some() + || next.fragment().is_some() + { + return Err("release download must remain on the official HTTPS asset origin".into()); + } + Ok(next) +} + +fn redirect(current: &str, location: &str, origin: &url::Url) -> Result { let next = url::Url::parse(current) .and_then(|base| base.join(location)) .map_err(|_| "invalid release redirect")?; - if next.scheme() != "https" - || !next.username().is_empty() - || next.password().is_some() - || next.port_or_known_default() != Some(443) - || next.fragment().is_some() - || next.host_str() != Some("git.dever.cc") - { - return Err("release redirect must remain on the official HTTPS asset hosts".into()); - } + validate_download_url(next.as_str(), origin)?; Ok(next.into()) } @@ -158,7 +289,7 @@ pub(super) fn prepare(layout: &Layout, requested: &str) -> Result { - let mut response = - source.response(source.asset(version.as_str(), "tar.zst"), started)?; super::release_archive::extract( - response.body_mut().as_reader(), + source.open_asset(archive, started)?, &staging.0, &manifest.artifacts, )?; diff --git a/editor/vscode/.gitignore b/editor/vscode/.gitignore new file mode 100644 index 0000000..28a78a7 --- /dev/null +++ b/editor/vscode/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +*.vsix diff --git a/editor/vscode/.vscodeignore b/editor/vscode/.vscodeignore new file mode 100644 index 0000000..5d40ead --- /dev/null +++ b/editor/vscode/.vscodeignore @@ -0,0 +1,5 @@ +**/* +!package.json +!README.md +!language-configuration.json +!syntaxes/** diff --git a/editor/vscode/README.md b/editor/vscode/README.md new file mode 100644 index 0000000..d39f286 --- /dev/null +++ b/editor/vscode/README.md @@ -0,0 +1,32 @@ +# Dever Language for VS Code + +支持 `.dever` 语法高亮、括号配对、自动闭合、缩进和 `#` 快捷键注释。 +Markdown 正文保留原有编辑体验,`dever` 和 `typescript dever` 围栏共用 Dever 高亮规则;支持反引号、波浪号及更长的关闭围栏。无需先安装 Dever 编译器。 + +## 安装 + +从 [Gitea Releases](https://git.dever.cc/shemic/dever/releases) 下载 VSIX,在 VS Code 的扩展视图中选择“从 VSIX 安装”,或执行(将文件名替换为下载的版本): + +```sh +code --install-extension dever-language-0.1.0.vsix +``` + +`.dever.md` 继续使用 Markdown 语言模式,不要切换为普通 Dever。已有纯 TypeScript 围栏不会被接管。 +插件随 VSIX 单独分发,不包含编译器、skills、依赖或构建缓存;`dever update` 不负责安装或更新编辑器插件。 + +这是纯语法插件,不提供补全、跳转、格式化或实时编译诊断。最终颜色由 VS Code 主题决定;Markdown 着色依赖 VS Code 的宿主语法,不等同于编译器的程序块抽取。语言合法性、Markdown 说明契约和业务约束仍由 `dever check` 判断。 +插件暂未发布到插件市场,扩展标识为 `shemic.dever-language`。 + +## 开发与打包 + +维护者需要 Node.js 22 或更新版本。用户安装 VSIX 不需要 Node.js、npm 或 Rust。 +在本目录运行 `npm ci --ignore-scripts` 准备锁定的开发依赖,再运行 `npm run package` 生成 VSIX。 +插件没有运行时依赖或激活代码,不读取应用配置、环境变量,也不执行用户程序。 + +正式测试放在仓库根的 `test/editor-vscode/`。使用 VS Code 随附的 `extensions/markdown-basics/syntaxes/markdown.tmLanguage.json` 作为真实宿主语法: + +```sh +npm test -- --markdown-grammar /absolute/path/to/markdown.tmLanguage.json +``` + +测试用实际 TextMate/Oniguruma 引擎校验作用域与嵌入语言标识,覆盖两种 Markdown 围栏、关闭边界、注释/字符串、整数除法、声明以及仓库维护中的 CMS 双实现。没有宿主 Markdown 语法时明确报错,不以仿造语法代替。 diff --git a/editor/vscode/language-configuration.json b/editor/vscode/language-configuration.json new file mode 100644 index 0000000..16d730b --- /dev/null +++ b/editor/vscode/language-configuration.json @@ -0,0 +1,18 @@ +{ + "comments": { + "lineComment": "#" + }, + "brackets": [["{", "}"], ["[", "]"], ["(", ")"]], + "autoClosingPairs": [ + { "open": "{", "close": "}", "notIn": ["string", "comment"] }, + { "open": "[", "close": "]", "notIn": ["string", "comment"] }, + { "open": "(", "close": ")", "notIn": ["string", "comment"] }, + { "open": "\"", "close": "\"", "notIn": ["string", "comment"] } + ], + "surroundingPairs": [["{", "}"], ["[", "]"], ["(", ")"], ["\"", "\""]], + "wordPattern": "[A-Za-z_][A-Za-z0-9_]*", + "indentationRules": { + "increaseIndentPattern": "^\\s*(?!#)(?:[^\"#]|\"(?:\\\\.|[^\"\\\\])*\")*[({\\[]\\s*(?:#.*)?$", + "decreaseIndentPattern": "^\\s*[})\\]]" + } +} diff --git a/editor/vscode/package-lock.json b/editor/vscode/package-lock.json new file mode 100644 index 0000000..c0b71c5 --- /dev/null +++ b/editor/vscode/package-lock.json @@ -0,0 +1,1872 @@ +{ + "name": "dever-language", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dever-language", + "version": "0.1.0", + "license": "UNLICENSED", + "devDependencies": { + "@vscode/vsce": "4.0.0", + "vscode-oniguruma": "2.0.1", + "vscode-textmate": "9.2.0" + }, + "engines": { + "vscode": "^1.85.0" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.2.0.tgz", + "integrity": "sha512-fNAjWnA/nZ2jz31kxR/AqRaUT8ewHBw/WuBIosK0moMy1C9e5ValbDfFdIxJzVOOYaYkV/b2F1S4H/aHiqfVQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.11.0.tgz", + "integrity": "sha512-IUZydyTUkDnYdstOW9pFOOUQlBjAepK5teihDE3x6yxsPJs/hsAaaYpeGxdxrgtOiJbBKSjKW7MDk7AEhb4LRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.11.1.tgz", + "integrity": "sha512-2QygG2F76ZpMP2eMztiJvAiFMu71M9rDeU7vO/QKg5Css7MgM4frUOslFjhVjRhbGaCNPtz/S8M6y46/fFKVuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-process": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@azure/core-process/-/core-process-1.0.0.tgz", + "integrity": "sha512-/shnJ+ooO8WPxDhPEeI/2oRQuubn16gZ6CvlbpWbEswZfzwI9tI/sMAHmF3x1LuQ9yZYXfLW3TjzGMLEC5blKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.25.0.tgz", + "integrity": "sha512-bMs8ekJLjX8wPV+9IPBges1SLPyuDtE9g5gLDWOpxzKcoOFQnpLGkbcT1tdw3FaAmDS1gnPmMmJ6y/T5B96kIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.4.0.tgz", + "integrity": "sha512-eGwxD0AtncrxeBM4tG8R55Pc3rdX1hNW2WibJAgYpCVA6E93mvvVH+LcssoVjOBrSKWS55yEIHsk0X8ctHmfOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.14.0.tgz", + "integrity": "sha512-9n2pWK61veAuN0V20t9lOuoV4CFMdyAZ1ygZzvBGk/pBBJRib/PjL9PLXa/aI2CcPpyHfqVsxxqLCYl6uZlfDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.13.3", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.3.tgz", + "integrity": "sha512-zGQPtqvXPgSA8yfV2CkIQ1qirqk0p9AIVpC5uEkdXQYcKl07QHvyaGYRnZOk0AsQUmxNb4wfkcwY5di8Z5xa9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-process": "^1.0.0", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^6.0.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.4.0.tgz", + "integrity": "sha512-rbAE25KUfjU/s3XHUdJgceoCP5dEOpMx85J04kF+QMdta73XkuG9JGHHinch+XIoKpBdqljin+KqURpJriSzLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.24.0.tgz", + "integrity": "sha512-jS1stt81tslcVZi7fqVD+g6vr8w/IWqFl/vAB2dx/6EOroQDuCR4+z0o3C+d6a/GpLATvdoO+kwnDcYzsBXKQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.14.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "16.14.2", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.14.2.tgz", + "integrity": "sha512-HOBR0Gfo39TMrkxNG8k6cfjRkrRjXZc3JQs3ebMWQc9S4cihuknMYra3sgmzbZB752oQBqBN9+WF7c826p2vIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-6.0.1.tgz", + "integrity": "sha512-ixSO1Y/kCVRthRs+hSx/5qkwaunX1/RAePhlMN0wIpIQ4WEZ6AREGGnGd1AP0qspHVsAwzWQKGubpjh50JyJIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.14.1", + "jsonwebtoken": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@azure/msal-node/node_modules/@azure/msal-common": { + "version": "16.14.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.14.1.tgz", + "integrity": "sha512-Or6xhPNyi4zHW25158yxBoyxuCqNSPa5YBVqfF1J5Ks4MJWBo/USXdp05DQIPu1Zli00YZu6t0+h6KvHJealxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@napi-rs/keyring": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring/-/keyring-1.3.0.tgz", + "integrity": "sha512-WrOw/bcXm0f9qHkumlT1QlArXSTWqaY9sunsDpOk+yCCorCKMxvWT/a3xko4EYHVdeZoh00yI2TydXn6eyICDA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/keyring-darwin-arm64": "1.3.0", + "@napi-rs/keyring-darwin-x64": "1.3.0", + "@napi-rs/keyring-freebsd-x64": "1.3.0", + "@napi-rs/keyring-linux-arm-gnueabihf": "1.3.0", + "@napi-rs/keyring-linux-arm64-gnu": "1.3.0", + "@napi-rs/keyring-linux-arm64-musl": "1.3.0", + "@napi-rs/keyring-linux-riscv64-gnu": "1.3.0", + "@napi-rs/keyring-linux-x64-gnu": "1.3.0", + "@napi-rs/keyring-linux-x64-musl": "1.3.0", + "@napi-rs/keyring-win32-arm64-msvc": "1.3.0", + "@napi-rs/keyring-win32-ia32-msvc": "1.3.0", + "@napi-rs/keyring-win32-x64-msvc": "1.3.0" + } + }, + "node_modules/@napi-rs/keyring-darwin-arm64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-darwin-arm64/-/keyring-darwin-arm64-1.3.0.tgz", + "integrity": "sha512-pl76hJvdYUBn6I24bXiOBMA9nbDapo3I5B+f3OorjDU4dUMSypXeKbOVehJe8fhgTiH24flMyTS3aAIy43xegQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-darwin-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-darwin-x64/-/keyring-darwin-x64-1.3.0.tgz", + "integrity": "sha512-YcJtEV5LA3cvA4z3BurgxH5IhTsW1JfIvcAAcqcecwk06Si9F9NqkxbZVIfDwQ8oRHgaBmT3zZJnLAotCrVahw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-freebsd-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-freebsd-x64/-/keyring-freebsd-x64-1.3.0.tgz", + "integrity": "sha512-vlLf31TGhfRAaxLDBhg8b89ss0HHD/lyNmL5F3UjSaz5CUXElsJmKYq9fqA/B+cZKUEUcLHHGhF0I/CqcFdaVw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-linux-arm-gnueabihf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-linux-arm-gnueabihf/-/keyring-linux-arm-gnueabihf-1.3.0.tgz", + "integrity": "sha512-KiWdMMu/Inz/bHHIAGrnF7r54FZDYXuHO6UFF/rhIrshUsxbMG1Rl9lEymNtqqsVo927G0VYcb02FzWQ3iBQRQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-linux-arm64-gnu": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-linux-arm64-gnu/-/keyring-linux-arm64-gnu-1.3.0.tgz", + "integrity": "sha512-eyKGpY40lm9Jvs1aD294XRH4y7+TlJM0YVAryZeXA6TX0mb4gMkxVXwSQv7MCwgah7raeUd0dKUb4BPAYIgcMg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-linux-arm64-musl": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-linux-arm64-musl/-/keyring-linux-arm64-musl-1.3.0.tgz", + "integrity": "sha512-iIK6JWHXAJqDrEyLY3TmswwloVyt2vj+04TZnew+uSJ9gnDO8EwRbp3/iw3LpWaXiDO7VomGO6y8I0Id8uBZSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-linux-riscv64-gnu": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-linux-riscv64-gnu/-/keyring-linux-riscv64-gnu-1.3.0.tgz", + "integrity": "sha512-/PGqrwn6EwgtK6vccASSXJRfOSP4vN1F4ASsIQ+7MdrK6hNvAJ1FZPrIuD5gGGdxezo3F++To2Wq7DbuGIeuNQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-linux-x64-gnu": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-linux-x64-gnu/-/keyring-linux-x64-gnu-1.3.0.tgz", + "integrity": "sha512-2PDK1WKWTu9lBGq9VvNEkSlQD3O7YwVpmnyN2M3cy4v7NJ/8gDMd9GXv3G+FVXN13uhp4gnnPBS+ScefmEeD2A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-linux-x64-musl": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-linux-x64-musl/-/keyring-linux-x64-musl-1.3.0.tgz", + "integrity": "sha512-oJ2HkX8YUo46QBkn0pG+HuIKQNqr523q6vBobCn+P95s4C4K6/kLBqHY/1bg5J4ap31DzsznhnFKcfBNBsjCnw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-win32-arm64-msvc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-win32-arm64-msvc/-/keyring-win32-arm64-msvc-1.3.0.tgz", + "integrity": "sha512-tOd3c/uAaeoE4ycVlmAdSvygz0Zt3zdca6Y7gokBeIbaRDWpjDIUOpU3MvML59XAaqyuKGsVVu0F/DZb1lHPmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-win32-ia32-msvc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-win32-ia32-msvc/-/keyring-win32-ia32-msvc-1.3.0.tgz", + "integrity": "sha512-sPSqeAFZMGqP1R++M2JTza7GQJJ/TpCo6JU6Vcd4jnebvOaEDs9b7eipakU1PJdSvhpC2yXMCNRk9gXfrhuwHQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/keyring-win32-x64-msvc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@napi-rs/keyring-win32-x64-msvc/-/keyring-win32-x64-msvc-1.3.0.tgz", + "integrity": "sha512-4DnCWXwDc0HRKwyRlG5y0VhKZW2tNRQfKKfyj6IX/KWfDNyq9hn4n+GL1auyDcOO/v8PwnhmYo2+rOOqCkvvOg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@secretlint/core": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/core/-/core-10.2.2.tgz", + "integrity": "sha512-6rdwBwLP9+TO3rRjMVW1tX+lQeo5gBbxl1I5F8nh8bgGtKwdlCMhMKsBWzWg1ostxx/tIG7OjZI0/BxsP8bUgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/profiler": "^10.2.2", + "@secretlint/types": "^10.2.2", + "debug": "^4.4.1", + "structured-source": "^4.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/profiler": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/profiler/-/profiler-10.2.2.tgz", + "integrity": "sha512-qm9rWfkh/o8OvzMIfY8a5bCmgIniSpltbVlUVl983zDG1bUuQNd1/5lUEeWx5o/WJ99bXxS7yNI4/KIXfHexig==", + "dev": true, + "license": "MIT" + }, + "node_modules/@secretlint/secretlint-rule-no-dotenv": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-no-dotenv/-/secretlint-rule-no-dotenv-10.2.2.tgz", + "integrity": "sha512-KJRbIShA9DVc5Va3yArtJ6QDzGjg3PRa1uYp9As4RsyKtKSSZjI64jVca57FZ8gbuk4em0/0Jq+uy6485wxIdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/secretlint-rule-preset-recommend": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/secretlint-rule-preset-recommend/-/secretlint-rule-preset-recommend-10.2.2.tgz", + "integrity": "sha512-K3jPqjva8bQndDKJqctnGfwuAxU2n9XNCPtbXVI5JvC7FnQiNg/yWlQPbMUlBXtBoBGFYp08A94m6fvtc9v+zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/source-creator": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/source-creator/-/source-creator-10.2.2.tgz", + "integrity": "sha512-h6I87xJfwfUTgQ7irWq7UTdq/Bm1RuQ/fYhA3dtTIAop5BwSFmZyrchph4WcoEvbN460BWKmk4RYSvPElIIvxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@secretlint/types": "^10.2.2", + "istextorbinary": "^9.5.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@secretlint/types": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@secretlint/types/-/types-10.2.2.tgz", + "integrity": "sha512-Nqc90v4lWCXyakD6xNyNACBJNJ0tNCwj2WNk/7ivyacYHxiITVgmLUFXTBOeCdy79iz6HtN9Y31uw/jbLrdOAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.9.tgz", + "integrity": "sha512-edSdeAqkdxBVzA1yL1LrLCml1YjyCVvPMtMqJpbF+6K609tHe8V6sQUzFQSGcYNhcuhOceZtjvN32+mpIth30A==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@vscode/vsce": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-4.0.0.tgz", + "integrity": "sha512-NImwuLaenMmb5D5Jer9/lzi/F9ZQUBOp8Azhj/BVYcTFgixv8KehFXqEUDjQlD2tAiw2E6dDGyjTuAB//di60A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.13.2", + "@napi-rs/keyring": "^1.3.0", + "@secretlint/core": "^10.2.2", + "@secretlint/secretlint-rule-no-dotenv": "^10.2.2", + "@secretlint/secretlint-rule-preset-recommend": "^10.2.2", + "@secretlint/source-creator": "^10.2.2", + "@secretlint/types": "^10.2.2", + "@vscode/vsce-sign": "^2.1.0", + "azure-devops-node-api": "^12.5.0", + "cockatiel": "^3.2.1", + "commander": "^12.1.0", + "hosted-git-info": "^4.1.0", + "jsonc-parser": "^3.3.1", + "marked": "^18.0.11", + "mime": "^1.6.0", + "minimatch": "^10.2.6", + "parse5": "^8.0.1", + "proper-lockfile": "^4.1.2", + "read": "^1.0.7", + "semver": "^7.8.5", + "tinyglobby": "^0.2.17", + "typed-rest-client": "^1.8.11", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^3.4.0", + "yazl": "^2.5.1" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 22" + } + }, + "node_modules/@vscode/vsce-sign": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.1.0.tgz", + "integrity": "sha512-9AQrqazrBgTgRSuwleLVXUrIUphY02/SFCh2TKYoLV/xifJAdblhdmEmw5gUrYSPQ3sRwNs9iyCMD14sATEE6g==", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.6", + "@vscode/vsce-sign-alpine-x64": "2.0.6", + "@vscode/vsce-sign-darwin-arm64": "2.0.6", + "@vscode/vsce-sign-darwin-x64": "2.0.6", + "@vscode/vsce-sign-linux-arm": "2.0.6", + "@vscode/vsce-sign-linux-arm64": "2.0.6", + "@vscode/vsce-sign-linux-x64": "2.0.6", + "@vscode/vsce-sign-win32-arm64": "2.0.6", + "@vscode/vsce-sign-win32-x64": "2.0.6" + } + }, + "node_modules/@vscode/vsce-sign-alpine-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-arm64/-/vsce-sign-alpine-arm64-2.0.6.tgz", + "integrity": "sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-alpine-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-alpine-x64/-/vsce-sign-alpine-x64-2.0.6.tgz", + "integrity": "sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "alpine" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-arm64/-/vsce-sign-darwin-arm64-2.0.6.tgz", + "integrity": "sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-darwin-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-darwin-x64/-/vsce-sign-darwin-x64-2.0.6.tgz", + "integrity": "sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm/-/vsce-sign-linux-arm-2.0.6.tgz", + "integrity": "sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-arm64/-/vsce-sign-linux-arm64-2.0.6.tgz", + "integrity": "sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-linux-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", + "integrity": "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@vscode/vsce-sign-win32-arm64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-arm64/-/vsce-sign-win32-arm64-2.0.6.tgz", + "integrity": "sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vscode/vsce-sign-win32-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-win32-x64/-/vsce-sign-win32-x64-2.0.6.tgz", + "integrity": "sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/binaryextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-6.11.0.tgz", + "integrity": "sha512-sXnYK/Ij80TO3lcqZVV2YgfKN5QjUWIRk/XSm2J/4bd/lPko3lvk0O4ZppH6m+6hB2/GTu+ptNwVFe1xh+QLQw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/boundary": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", + "integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/brace-expansion": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/bundle-name": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.1.tgz", + "integrity": "sha512-DdH81/zPLVS11EUgWq3tEu/xn+EzljlMYooDNdzWEnFha3R3NBMpMV1UqYIpjYHV/SgpFKMIX1Oh7o06SjM/oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/default-browser": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.1.tgz", + "integrity": "sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" + }, + "engines": { + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/entities": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz", + "integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/marked": { + "version": "18.0.14", + "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.14.tgz", + "integrity": "sha512-mBHK6FBHuBAlhgRe88w9F0O1AbwwXJUcQibUbC/QcdTbVGAD7aWza+xt3N6oT/jCZx3/OMeS+8rnuiHZcQ9s7A==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/qs": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz", + "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boundary": "^2.0.0" + } + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "dev": true, + "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "dev": true, + "license": "Artistic-2.0", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vscode-oniguruma": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-2.0.1.tgz", + "integrity": "sha512-poJU8iHIWnC3vgphJnrLZyI3YdqRlR27xzqDmpPXYzA93R4Gk8z7T6oqDzDoHjoikA2aS82crdXFkjELCdJsjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-textmate": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-9.2.0.tgz", + "integrity": "sha512-rkvG4SraZQaPSN/5XjwKswdU0OP9MF28QjrYzUBbhb8QyG3ljB1Ky996m++jiI7KdiAP2CkBiQZd9pqEDTClqA==", + "dev": true, + "license": "MIT" + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz", + "integrity": "sha512-jIH9yLR9wqr0wOS0TpBvo/g/2UgZH5qePVbjgRliiF0BYvOZyaBknKsF+x9Iht0O6sqgnB93rCICdOZFecJuDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + } + } +} diff --git a/editor/vscode/package.json b/editor/vscode/package.json new file mode 100644 index 0000000..5437c77 --- /dev/null +++ b/editor/vscode/package.json @@ -0,0 +1,56 @@ +{ + "name": "dever-language", + "displayName": "Dever Language", + "description": "Dever syntax highlighting and editing support, including Markdown code blocks.", + "version": "0.1.0", + "publisher": "shemic", + "private": true, + "license": "UNLICENSED", + "engines": { + "vscode": "^1.85.0" + }, + "categories": ["Programming Languages"], + "keywords": ["dever", "markdown", "syntax highlighting"], + "repository": { + "type": "git", + "url": "ssh://git@git.dever.cc:2222/shemic/dever.git", + "directory": "editor/vscode" + }, + "contributes": { + "languages": [ + { + "id": "dever", + "aliases": ["Dever", "dever"], + "extensions": [".dever"], + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "dever", + "scopeName": "source.dever", + "path": "./syntaxes/dever.tmLanguage.json" + }, + { + "scopeName": "markdown.dever.codeblock", + "path": "./syntaxes/dever-markdown.tmLanguage.json", + "injectTo": ["text.html.markdown"], + "embeddedLanguages": { + "meta.embedded.block.dever": "dever" + }, + "tokenTypes": { + "meta.embedded.block.dever": "other" + } + } + ] + }, + "scripts": { + "test": "node ../../test/editor-vscode/highlight.test.cjs", + "package": "vsce package --no-dependencies --skip-license" + }, + "devDependencies": { + "@vscode/vsce": "4.0.0", + "vscode-oniguruma": "2.0.1", + "vscode-textmate": "9.2.0" + } +} diff --git a/editor/vscode/syntaxes/dever-markdown.tmLanguage.json b/editor/vscode/syntaxes/dever-markdown.tmLanguage.json new file mode 100644 index 0000000..a74eb03 --- /dev/null +++ b/editor/vscode/syntaxes/dever-markdown.tmLanguage.json @@ -0,0 +1,31 @@ +{ + "name": "Dever Markdown blocks", + "scopeName": "markdown.dever.codeblock", + "injectionSelector": "L:text.html.markdown -markup.fenced_code.block -markup.raw.block -markup.quote -markup.list -meta.embedded.block -comment", + "patterns": [ + { + "name": "markup.fenced_code.block.markdown", + "contentName": "meta.embedded.block.dever source.dever", + "begin": "^ {0,3}(`{3,})[ \\t]*(dever|typescript dever)[ \\t]*$", + "end": "^ {0,3}\\1`* *$", + "beginCaptures": { + "1": { "name": "punctuation.definition.markdown.dever" }, + "2": { "name": "fenced_code.block.language.markdown" } + }, + "endCaptures": { "0": { "name": "punctuation.definition.markdown.dever" } }, + "patterns": [{ "include": "source.dever" }] + }, + { + "name": "markup.fenced_code.block.markdown", + "contentName": "meta.embedded.block.dever source.dever", + "begin": "^ {0,3}(~{3,})[ \\t]*(dever|typescript dever)[ \\t]*$", + "end": "^ {0,3}\\1~* *$", + "beginCaptures": { + "1": { "name": "punctuation.definition.markdown.dever" }, + "2": { "name": "fenced_code.block.language.markdown" } + }, + "endCaptures": { "0": { "name": "punctuation.definition.markdown.dever" } }, + "patterns": [{ "include": "source.dever" }] + } + ] +} diff --git a/editor/vscode/syntaxes/dever.tmLanguage.json b/editor/vscode/syntaxes/dever.tmLanguage.json new file mode 100644 index 0000000..194eabd --- /dev/null +++ b/editor/vscode/syntaxes/dever.tmLanguage.json @@ -0,0 +1,95 @@ +{ + "name": "Dever", + "scopeName": "source.dever", + "patterns": [ + { "include": "#comments" }, + { "include": "#strings" }, + { "include": "#unsupported" }, + { "include": "#declarations" }, + { "include": "#constants" }, + { "include": "#numbers" }, + { "include": "#names" }, + { "include": "#keywords" }, + { "include": "#operators" } + ], + "repository": { + "comments": { + "name": "comment.line.number-sign.dever", + "begin": "#", + "end": "$" + }, + "strings": { + "name": "string.quoted.double.dever", + "begin": "\"", + "end": "\"|$", + "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.dever" } }, + "endCaptures": { "0": { "name": "punctuation.definition.string.end.dever" } }, + "patterns": [ + { "name": "constant.character.escape.dever", "match": "\\\\(?:[\"\\\\nrt]|u\\{[0-9A-Fa-f]{1,6}\\})" }, + { "name": "invalid.illegal.escape.dever", "match": "\\\\." } + ] + }, + "declarations": { + "patterns": [ + { + "match": "\\b(type)\\s+([A-Z][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.dever" }, + "2": { "name": "entity.name.type.dever" } + } + }, + { + "match": "^\\s*(?:(public)\\s+)?(get|post|put|delete|cmd|rest)\\b", + "captures": { + "1": { "name": "storage.modifier.dever" }, + "2": { "name": "keyword.control.api.dever" } + } + }, + { + "match": "^\\s*(external)\\s+(command|exec|pip|npm|go)\\b", + "captures": { + "1": { "name": "storage.modifier.external.dever" }, + "2": { "name": "keyword.other.external.dever" } + } + }, + { "name": "keyword.other.declaration.dever", "match": "^\\s*(database|relation|seed|migrate|sql|index|unique|schedule)\\b" } + ] + }, + "constants": { + "name": "constant.language.dever", + "match": "\\b(true|false|null|other)\\b" + }, + "unsupported": { + "name": "invalid.illegal.keyword.dever", + "match": "\\b(package|exposes|if|else|switch|match|when|by|for|while|break|continue|iterate|recur|repeat|return|function|throw|catch|try|import|use|class|interface|unsafe|macro)\\b" + }, + "numbers": { + "name": "constant.numeric.dever", + "match": "(?=|[=+*/%<>?-]" }, + { "name": "punctuation.section.dever", "match": "[{}()\\[\\]]" }, + { "name": "punctuation.separator.dever", "match": "[,:.]" } + ] + } + } +} diff --git a/install b/install index dc9e78f..c86b640 100755 --- a/install +++ b/install @@ -36,24 +36,30 @@ import urllib.error import urllib.parse import urllib.request -RELEASES = "https://git.dever.cc/shemic/dever/dist" +RELEASES = "https://git.dever.cc/api/v1/repos/shemic/dever/releases" MAX_METADATA = 2 * 1024 * 1024 MAX_RELEASE = 2 * 1024 * 1024 * 1024 ASSET_HOSTS = {"git.dever.cc"} DEFAULT_PUBLIC_KEY = "7889e0edaf5fbf1060bef4ad6e27106128485c8412a6f6cd4457dc67e112986e" +def official_address(address): + target = urllib.parse.urlsplit(address) + if (target.scheme != "https" or target.hostname not in ASSET_HOSTS + or target.username or target.password or target.port not in (None, 443) + or target.fragment): + raise ValueError("发行下载地址必须位于官方 HTTPS 站点") + return address + + class OfficialRedirect(urllib.request.HTTPRedirectHandler): def redirect_request(self, request, stream, code, message, headers, address): - target = urllib.parse.urlsplit(address) - if (target.scheme != "https" or target.hostname not in ASSET_HOSTS - or target.username or target.password or target.port not in (None, 443) - or target.fragment): - raise ValueError("发行下载重定向离开官方 HTTPS 站点") + official_address(address) return super().redirect_request(request, stream, code, message, headers, address) def download(address): + official_address(address) # Installation does not inherit HTTP proxy/environment configuration. client = urllib.request.build_opener( urllib.request.ProxyHandler({}), OfficialRedirect(), @@ -99,15 +105,61 @@ def read_bounded(path, limit): return contents -def metadata(release, source, selection, platform): +def resolve_release(selection): + endpoint = "latest" if selection == "latest" else f"tags/v{selection}" + with download(f"{RELEASES}/{endpoint}") as stream: + contents = stream.read(MAX_METADATA + 1) + if len(contents) > MAX_METADATA: + raise ValueError("发行元数据超过大小限制") + record = json.loads(contents) + if (not isinstance(record, dict) or record.get("draft") is not False + or record.get("prerelease") is not False): + raise ValueError("需要已发布的稳定发行版本") + tag = record.get("tag_name") + if not isinstance(tag, str) or not re.fullmatch( + r"v(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)", tag): + raise ValueError("发行标签不是准确的 v") + version = tag[1:] + if selection != "latest" and version != selection: + raise ValueError("发行版本与请求不匹配") + entries = record.get("assets") + if not isinstance(entries, list) or not 1 <= len(entries) <= 512: + raise ValueError("发行附件列表缺失或超限") + attachments = {} + for entry in entries: + if not isinstance(entry, dict): + raise ValueError("发行附件元数据错误") + name, size, address = (entry.get(key) for key in ("name", "size", "browser_download_url")) + if (not isinstance(name, str) or not name or name in attachments + or type(size) is not int or size <= 0 or size > MAX_RELEASE + or not isinstance(address, str)): + raise ValueError("发行附件名称重复、长度或地址错误") + attachments[name] = {"address": official_address(address), "bytes": size} + return version, attachments + + +def asset(attachments, platform, suffix, limit=MAX_RELEASE): + name = f"dever-{platform}.{suffix}" + entry = attachments.get(name) + if entry is None: + raise ValueError(f"该发行版本缺少附件:{name}") + if entry["bytes"] > limit: + raise ValueError("发行附件超过大小限制") + return entry + + +def metadata(release, source, attachments, platform): for filename in ("manifest.json", "manifest.sig"): if source: contents = read_bounded(source / filename, MAX_METADATA) else: - with download(f"{RELEASES}/{selection}/dever-{platform}.{filename}") as stream: + entry = asset(attachments, platform, filename, MAX_METADATA) + with download(entry["address"]) as stream: contents = stream.read(MAX_METADATA + 1) if len(contents) > MAX_METADATA: raise ValueError("发行元数据超过大小限制") + if len(contents) != entry["bytes"]: + raise ValueError("发行元数据长度不匹配") (release / filename).write_bytes(contents) @@ -181,7 +233,7 @@ def copy_artifact(stream, destination, artifact): destination.chmod(0o755 if executable else 0o644) -def payload(release, source, version, platform, catalog, trusted_key=None): +def payload(release, source, platform, catalog, trusted_key=None, attachments=None): if source: for name, artifact in catalog.items(): path = source / name @@ -202,15 +254,20 @@ def payload(release, source, version, platform, catalog, trusted_key=None): with tempfile.TemporaryDirectory(prefix=".extract-", dir=release.parent) as directory: scratch = Path(directory) helper = scratch / "helper" - base = f"{RELEASES}/{version}/dever-{platform}" for name, artifact in catalog.items(): if name == "bootstrap/dever" or name.startswith("bootstrap/lib/"): - with download(f"{base}.blob-{artifact['sha256']}") as stream: + entry = asset(attachments, platform, f"blob-{artifact['sha256']}") + if entry["bytes"] != artifact["bytes"]: + raise ValueError("bootstrap 附件长度与签名不匹配") + with download(entry["address"]) as stream: copy_artifact(stream, helper / name, artifact) if stream.read(1): raise ValueError("bootstrap 下载超过签名长度") compressed = scratch / "base.tar.zst" - download_archive(f"{base}.tar.zst", compressed) + entry = asset(attachments, platform, "tar.zst") + download_archive(entry["address"], compressed) + if compressed.stat().st_size != entry["bytes"]: + raise ValueError("发行附件长度不匹配") configuration = scratch / "extract.json" configuration.write_text(json.dumps({ "release": str(release), "archive": str(compressed), @@ -235,7 +292,8 @@ def install(arguments): raise ValueError("机器安装需要管理员权限;请通过根 install 入口执行") platform = platform_name() prerequisites(platform) - if arguments.version != "latest" and not re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", arguments.version): + if arguments.version != "latest" and not re.fullmatch( + r"(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)", arguments.version): raise ValueError("--version 需要 latest 或准确版本") system_root = arguments.system_root.absolute() if not system_root.is_dir() or system_root.is_symlink(): @@ -248,15 +306,17 @@ def install(arguments): scratch = Path(directory) release = scratch / "release" release.mkdir() - metadata(release, source, arguments.version, platform) + selection, attachments = ((arguments.version, None) if source + else resolve_release(arguments.version)) + metadata(release, source, attachments, platform) key_path = arguments.trusted_key if key_path is None: key_path = scratch / "independent-release.pub" key_path.write_text(DEFAULT_PUBLIC_KEY) - version, catalog, key = authenticate(release, key_path, scratch, platform, arguments.version) + version, catalog, key = authenticate(release, key_path, scratch, platform, selection) trusted = scratch / "release.pub" trusted.write_text(key.hex() + "\n") - payload(release, source, version, platform, catalog, trusted) + payload(release, source, platform, catalog, trusted, attachments) configuration = scratch / "config" configuration.mkdir() (configuration / "setting.json").write_text(json.dumps({ diff --git a/sdk/README.md b/sdk/README.md index 1145e7f..4329ceb 100644 --- a/sdk/README.md +++ b/sdk/README.md @@ -1,7 +1,5 @@ # External Worker SDKs -Compiler authors: the private [native release workflow](native-release.md) builds and signs Dever runtime packs. It is separate from these external-language Worker SDKs and from application configuration. - These are stdio Worker libraries for Python, JavaScript (Node), and Go. The compiler remains the sole owner of Port schemas. Each checked external Adapter exposes `ExternalWorkerContract::sdk_manifest()`, including the exact identity and recursive setting, input, output and declared-error types. The managed Python and JavaScript runners package this manifest and bind each Port operation to a same-named function exported by the Adapter entry; JavaScript accepts ESM named exports or CommonJS `module.exports` properties. Application code does not maintain a second registration table. Python uses `Worker.from_manifest(manifest, handlers)`, JavaScript uses `Worker.fromManifest(manifest, handlers)`, and Go uses `NewFromManifest(manifest)` followed by `RegisterHandlers(handlers)`. These paths decode inputs and validate results and declared business-error payloads from the same compiler-generated contract. The SDK checks the identity during `hello` and never adopts a schema supplied by the supervisor. The lower-level `Contract`/`Worker` registration API remains available for protocol fixtures. The setting decoder runs before `ready`; it receives only the `hello.setting` value. Handlers return JSON-compatible values or a declared `BusinessError`. Python handlers are async; JavaScript handlers receive an `AbortSignal`; Go handlers receive a `context.Context`. A cooperative cancellation receives one `dever.cancelled` protocol error and discards its handler result. If a handler ignores cancellation for one second, the Worker fails and admits no further calls. The supervisor owns the Worker process and its stdin lifetime; an in-process Go `Serve` caller must close or unblock its own `io.Reader` when returning. diff --git a/sdk/native-release.md b/sdk/native-release.md deleted file mode 100644 index 99f3472..0000000 --- a/sdk/native-release.md +++ /dev/null @@ -1,303 +0,0 @@ -# Native release authoring - -This is the private compiler-author workflow. Application projects continue to use `dever run/build`; they do not need Cargo, a signing key or author settings. A Linux x86_64 compiler release can contain both native x86_64 and cross-compiled ARM64 application packs. The compiler and its LLVM libraries remain host binaries. - -Build the four runtime archives separately, then assemble and sign a new directory. The maker never builds source, downloads dependencies, searches `PATH`, reads configuration from environment variables, or modifies its inputs. It reuses the runtime manifest and signed release formats consumed by `deverd` and `MachineManager`. - -## Build inputs - -Build the compiler with `cargo build --release --offline --locked -p dever-cli --bin dever`; its author input becomes the installed `dever-core`. Build the stable machine launcher with `--bin dever-launcher` and the daemon with `--bin deverd` in the same release profile. Use `target/release/dever-launcher` for the bootstrap launcher input, which the maker publishes as `bootstrap/dever`. The release profile uses fat LTO, one codegen unit and symbol stripping; `runtime-pack` overrides stripping to retain linkable archive symbols. The installed public command remains `dever`; `dever-launcher` is only an author build name. - -Prepare the pinned Rust dependencies and compiler LLVM 18/LLD SDK explicitly. Use an explicitly selected Cargo/Rust toolchain for author builds. The root `runtime-pack` Cargo profile inherits the release optimization settings, uses one codegen unit and removes debug information while retaining archive symbols needed by LLD. It must not enable the bridge's `embedded` feature. - -All profiles include `runtime-api,runtime-external`; their dependencies enable `runtime-abi`. Database drivers vary: - -| Profile | Additional features | Saved archive | -| --- | --- | --- | -| base | none | `base.a` | -| sqlite | `runtime-sqlite` | `sqlite.a` | -| postgres | `runtime-postgres` | `postgres.a` | -| both | `runtime-sqlite,runtime-postgres` | `both.a` | - -For example, build base for Linux x86_64: - -```sh -cargo build --offline --locked -p dever-backend-bridge --lib \ - --profile runtime-pack --no-default-features \ - --features runtime-api,runtime-external \ - --target x86_64-unknown-linux-gnu --target-dir target/native-runtime-abi -``` - -Copy `target/native-runtime-abi/x86_64-unknown-linux-gnu/runtime-pack/libdever_backend_bridge.a` to a new `base.a` input, then repeat with each row's features and save its archive before the next build. Share this one Cargo target directory; do not create four dependency caches. Do not copy the both archive into all four inputs or strip a hard-linked fixture in place. Do not use `strip --strip-all` on link inputs. - -Prepare a matching compiler core, `libLLVM.so.18.1`, target CRT objects and genuine static libraries. Linux GNU link order is explicit: start objects, runtime, static libraries, end objects. Linker scripts and thin archives are rejected. Preserve the compiler version and the exact compiler/CRT/SDK versions and input hashes in build records; the maker does not infer feature content or compiler versions from filenames. - -## Author settings - -Application authors first prepare `dever target add linux-aarch64`, then select `dever build --target linux-aarch64 --output `; omitted targets, `run`, and `test` use the host. This selects application output, not an ARM compiler installation. Missing target packs are errors with a preparation command. Product commands do not discover cross tools or download packs while building. - -For an additional application target, add `native_targets.linux-aarch64` to the author settings. Its value has the same `profiles`, `start`, `libraries`, and `end` fields as the host inputs below. Build all four archives with Rust target `aarch64-unknown-linux-gnu` and an explicitly prepared cross linker/sysroot. Use ARM CRT and static libraries, never host files or linker scripts. Both standalone object and archive member ELF headers are checked against the declared target before publishing and on cache access. - -The parallel maps `ecosystem_targets.linux-aarch64`, `sandbox_targets.linux-aarch64`, and `build_targets.linux-aarch64` use the corresponding host `runtimes`, `sandbox`, and `builds` shapes. Python/Node interpreters, native wheel/addon files, the sandbox guard, static bwrap, and its OS libraries must match the application target. Go is different: `build.host` identifies the host executable tools; `build.goos` and `build.goarch` identify the output and standard-library archives. The compiler/linker must produce that target with a cleared environment. The private fixture maker supports `go run test/go-managed/make_pack.go linux-aarch64`; it uses an author-only Go overlay to bake ARM defaults into x86 tools without changing the installed Go SDK. - -Prepare project Libs explicitly with `dever lib update --target linux-aarch64` (or `lib add` with the same option). The resulting lock and cached resources bind the selected target. Offline `build` verifies that binding. Pure Python wheels/npm packages and Go cross compilation use this path; Python source distributions or npm lifecycle builds require already prepared matching target outputs and complete build receipts. An x86 tool must never silently produce a native extension labeled ARM. - -The opt-in ARM acceptance uses explicit inputs under `target/arm64-cross/`: four archives/CRT libraries, target ecosystem and sandbox packs, locked upstream dependencies, and private QEMU/Alpine kernel/initramfs files. `native_release::acceptance::cross` exports independent applications under `guest/apps/` after deleting its source and machine store. Run `python3 -B test/ecosystem-release/arm64/simulate.py` to rebuild only the owned guest images and execute Python, Node, Go and HTTP under the complete ARM kernel. It requires all success/failure/cleanup markers and writes serial logs plus a result JSON under `logs/`. The VM has no external network or system language installations. Its initramfs switches into a normal root mount so bubblewrap can use `pivot_root`. This is functional emulation, not physical ARM performance or a universal kernel compatibility result. - -Use a separate author root, not a Dever application's configuration. Place its explicit input files and private Ed25519 PKCS#8 key below that root. `config/setting.json` has this shape; replace every illustrative digest with the file's actual lowercase SHA-256: - -```json -{ - "format": "dever-native-release-input-v1", - "version": "0.1.0", - "target": "x86_64-unknown-linux-gnu", - "signing_key": "private/release.pk8", - "core": {"source": "inputs/dever-core", "sha256": ""}, - "skill": [ - {"source": "inputs/skills/SKILL.md", "path": "SKILL.md", "sha256": ""}, - {"source": "inputs/skills/references/development.md", "path": "references/development.md", "sha256": ""} - ], - "core_libraries": [ - {"source": "inputs/libLLVM.so.18.1", "path": "libLLVM.so.18.1", "sha256": ""}, - {"source": "inputs/libstdc++.so.6", "path": "libstdc++.so.6", "sha256": ""} - ], - "profiles": { - "base": {"source": "inputs/base.a", "sha256": ""}, - "sqlite": {"source": "inputs/sqlite.a", "sha256": ""}, - "postgres": {"source": "inputs/postgres.a", "sha256": ""}, - "both": {"source": "inputs/both.a", "sha256": ""} - }, - "start": [ - {"source": "inputs/crt1.o", "path": "crt1.o", "sha256": ""}, - {"source": "inputs/crti.o", "path": "crti.o", "sha256": ""}, - {"source": "inputs/crtbeginT.o", "path": "crtbeginT.o", "sha256": ""} - ], - "libraries": [ - {"source": "inputs/libc.a", "path": "libc.a", "sha256": ""}, - {"source": "inputs/libm.a", "path": "libm.a", "sha256": ""}, - {"source": "inputs/libmvec.a", "path": "libmvec.a", "sha256": ""}, - {"source": "inputs/libgcc.a", "path": "libgcc.a", "sha256": ""}, - {"source": "inputs/libgcc_eh.a", "path": "libgcc_eh.a", "sha256": ""} - ], - "end": [ - {"source": "inputs/crtend.o", "path": "crtend.o", "sha256": ""}, - {"source": "inputs/crtn.o", "path": "crtn.o", "sha256": ""} - ] -} -``` - -`source` and `signing_key` are normalized relative paths below the author root, without symlinks. Link-input `path` is relative to the output's `runtime/` directory; reserved and duplicate destinations fail. The key must be owner-private on Unix. Unknown fields, missing profiles, invalid targets or digests fail explicitly. The key and author configuration are never included in the output. - -`core_libraries` must list the full dynamic dependency closure, not just the two illustrative entries above. These `path` values are plain SONAMEs published under `lib/`. Current Linux x86_64 inputs additionally require gcc_s, z, ffi, edit, zstd, tinfo, xml2, bsd, md, icuuc, icudata and lzma. The compiler declares inherited `RPATH=$ORIGIN/lib`; library search entries may only name that same private directory (`$ORIGIN` or upstream LLVM's `$ORIGIN/../lib`). Maker and signed native installation reject missing dependencies, mismatched SONAME/architecture, unused libraries and escaping search paths. The declared system baseline is GNU libc and its companion libraries; the current prepared compiler requires glibc 2.39. The pack must not replace that system ABI. This replaces the single `llvm` author field directly. - -## Versioned AI skill and public release assets - -`skill` is required. Copy the complete `skills/` directory from the same main-repository revision as the compiler into the author inputs, excluding Git metadata and temporary files, and list every skill file as `{source,path,sha256}`. It is an ordinary repository directory, not a separate checkout or submodule. Paths are relative to its skill root; the maker publishes them under `skills/dever-language/` in the signed manifest. The two entries above illustrate the shape, not the complete file list. `SKILL.md` is mandatory; at most 256 files, 1 MiB per file and 8 MiB total are allowed. - -`dever skill path [project-root]` validates and returns the skill belonging to the selected compiler. `dever skill install ` installs a small AI entry that resolves the active signed skill on each task. It refuses existing directories. `dever update` and `dever use` change the one active-version journal used by both core and skill; they do not rewrite every user's AI directory. Ordinary users can read the signed skill without the install lock or administrator permissions. - -Publish official assets under `https://git.dever.cc/shemic/dever/dist//`, independently of Git source access. Git tags may remain `v`; HTTP asset directories use the exact numeric version without `v`. The v2 signed root catalog separates base `artifacts` from `extensions`. Base includes core/private libraries, bootstrap, host native profiles/sandbox and skill. Each extension declares `{kind,target,artifacts}`; `kind` is `{"type":"runtime","ecosystem":"pip|npm|go"}`, `{"type":"build","ecosystem":"pip|npm"}` or `{"type":"target"}`. Target combines that target's native profiles/CRT and sandbox. Paths and identities cannot overlap. No extension has an independent unsigned manifest or can override base files. - -`python3 sdk/release-assets.py --output --zstd /absolute/author/zstd` writes `dever-.manifest.json`, `.manifest.sig`, `.tar.zst`, plus `.ext--.tar.zst`. Each USTAR contains exactly its signed ordinary artifact files, no directory headers or embedded root metadata. Zstandard uses a checksummed single frame with a maximum 128 MiB window. The publisher also emits `.blob-` for bootstrap/dever and every bootstrap/lib dependency. First installation authenticates these raw helpers before executing the launcher's bounded extractor; end users do not need a system zstd executable. Report helper bytes separately from base archive size. - -Only explicit install/update, target add and dependency preparation download official resources. The source address is compiled into the toolchain, not application configuration or environment variables. Extension preparation uses closed typed IPC and the existing machine service, storing immutable version/catalog-bound resources under `cache/extensions`. Multiple projects/users share one verified tree. `run/build` and resource reads never download. `update` prepares the new core/skill and the active version's already installed extension selection before publishing the active-version journal; failure keeps the old selection usable. The stable machine launcher/daemon are provisioned by bootstrap, so changes to that protocol require a matching trusted bootstrap installation. - -## Public installer and static distribution - -Root `install` is the sole installer source. Maintain its Bash entry and embedded Python directly; there is no generator or separate skill installer. It embeds the independently provisioned public key, so `curl -fsSL https://git.dever.cc/shemic/dever/install | bash` needs neither a Git checkout nor a separate skill download. Keep archive extraction and machine activation in their existing Rust owners. Validate changes with `bash -n install` and the focused `python3 -B -m unittest discover -s test/onboarding -p 'test_install*.py' -v` suite; the tests load the actual root entry instead of copying its implementation. - -Configure the web server to serve these anonymous HTTPS paths: - -```text -/shemic/dever/install root install Bash script -/shemic/dever/dist/latest/dever-.manifest.json -/shemic/dever/dist/latest/dever-.manifest.sig -/shemic/dever/dist//dever-.* all matching immutable assets -``` - -These are explicit static routes, not assumed Git web UI or GitHub-compatible release URLs. Do not return a login page or HTML file viewer. Source repositories can retain their existing access restrictions. Publish the complete immutable version directory first, then switch the latest catalog selection together. Installers authenticate the latest catalog and download payloads only from its signed exact version. Keep old version directories for pinned installations; do not replace a published version's bytes. Release assets are outside Git source history. - -For the GitHub-to-new-origin migration, rebuild the core, launcher and daemon with the new compiled origin and a new version before publishing. Already installed old launchers still contain GitHub addresses, and ordinary update does not replace the stable bootstrap pair. Run the new `install` once to provision that pair through the existing bootstrap transaction, then use normal `dever update`. A successful test using older signed bytes proves installation behavior only; it does not prove a newly built release or online migration. - -## Linux first installation - -Include the stable launcher and daemon in the same signed release by adding this author field: - -```json -"bootstrap": { - "launcher": {"source":"inputs/dever", "sha256":""}, - "daemon": {"source":"inputs/deverd", "sha256":""}, - "libraries": [ - {"source":"inputs/libgcc_s.so.1", "path":"libgcc_s.so.1", "sha256":""} - ] -} -``` - -Both Rust entry points must be built with their private `$ORIGIN/lib` RPATH. The maker verifies their separate ELF dependency closure and adds `bootstrap/dever`, `bootstrap/deverd`, `bootstrap/lib/*` and the fixed `bootstrap/deverd.service` to the existing signed manifest. Core-only releases may omit this field; first installation requires it. - -An administrator must independently authenticate the first installer executable, its private libraries, and the release public key. A key shipped inside a downloaded release is not a trust source. Place the following configuration under an absolute, root-owned installer directory, in `config/setting.json`: - -```json -{ - "release": "/prepared/release", - "system_root": "/owned/system-image", - "trusted_key": "/independently-provisioned/release.pub", - "activate_service": false -} -``` - -Run the independently trusted launcher with `--dever-install /absolute/installer-root`. It installs the signed compiler version, `/opt/dever/bin` bootstrap closure, `/usr/local/bin/dever` symlink, root-owned systemd unit and its enable link below `system_root`. The root daemon owns the shared machine store; ordinary projects and users share it through the existing authenticated service protocol. `install`, `update` and `use` retain their version-management contracts. - -Offline image installation never invokes systemctl. `activate_service: true` is accepted only for the real `/` system root and explicitly performs daemon reload, restart and readiness checking. This session's acceptance uses owned image roots and manually started owned daemons; it does not activate any global service. - -The initial key is written to a checked temporary file, synced, then published without replacing an existing key. A bounded journal records seven fixed destinations: bootstrap directory, sandbox helper store, AppArmor policy file, service unit, public entry, enable link and active version. File modes and child directories are persisted before publication. Interrupted uncommitted installs restore their recorded predecessors; committed installs finish cleanup without undoing publication. Rerun the explicit installer to recover. Normal launcher/version operations refuse an unfinished journal. A cleanup failure remains an explicit error with the journal retained. Existing service/policy ownership is checked against its previously signed template, allowing legitimate template upgrades while rejecting unrelated files. These ordering guarantees and interruption tests are not a claim of hardware power-loss testing. - -## Ecosystem inputs - -The same author configuration accepts an optional `runtimes` object with `pip`, `npm` and `go` entries. Each entry declares `name`, `version` and `files`: normalized archive `path`, author-root `source`, and exact `sha256`. Include `dever-runtime.json` in that list. Python additionally requires `python_markers` and nonempty `python_wheel_tags` matching the prepared interpreter; these are registry resolution metadata, not settings supplied by an application. - -Python packs must contain a relocatable interpreter, its standard library, native extensions and their non-OS dependencies, with fixed `-I -S -B` arguments. Node packs include the interpreter with its embedded standard library. Go build packs contain `compile`, `link`, the Dever source analyzer and every standard-library archive referenced by their `importcfg`; applications embed only the resulting Go Worker. Interpreter portability must be tested against an explicit OS baseline. A copied host executable alone does not establish a complete pack. - -The maker and Worker builder share descriptor, path and file-closure validation. Packs are deterministic gzip/tar files with sorted entries, fixed archive metadata and executable modes derived from the descriptor. Every runtime input is copied and rehashed; the private-key exclusion applies to these files too. The maker calculates the pack digest and emits `runtime///{runtime.pack,manifest.json}`. Both files enter the existing top-level release signature. No new lock, installation or signature protocol is introduced. - -Node registry metadata may declare `npm_libc` as `glibc` or `musl`, matching the explicitly prepared interpreter and target. This is signed author metadata for package eligibility, never host probing. The pinned GNU Node fixture declares `glibc`. - -## Sandbox inputs - -External Workers, including `exec`, require the installed release's sandbox assets. Add a `sandbox` array to author settings using the same `{source, path, sha256}` entries as other leaf inputs. Its paths are `bin/bwrap`, `bin/guard`, and flat `lib/` libraries, including the platform loader. Build `dever-sandbox-guard` from the current source with the explicit author toolchain. The bwrap input must support bind-fd and be a static target ELF with neither PT_INTERP nor DT_NEEDED; runtime executes it directly. The guard and language runtimes retain their complete private loader/library closure. The maker validates every asset before publishing `sandbox//` under the existing release signature. The asset budget is 128 files / 32 MiB. Inputs must not use RPATH/RUNPATH to escape the supplied bootstrap library set. - -The Linux backend requires user, mount, PID and network namespace permission, seccomp and `openat2`. An active host loader preload configuration is rejected. When `apparmor_restrict_unprivileged_userns=1`, a non-root launch selects only `/opt/dever/sandbox//bwrap`. Every ancestor must be a real root-owned directory without group/other write permission; the regular executable must have no setuid/setgid or file capabilities, and its digest must equal the embedded verified asset. Missing or invalid helpers produce an installation error before spawning. Other launches execute the same static embedded bwrap directly; there is no PATH, environment, dynamic-loader or system-bwrap fallback. - -The signed bootstrap includes `bootstrap/dever-sandbox`, copied to `/etc/apparmor.d/dever-sandbox` by the same installation transaction. The source is [sdk/apparmor/dever-sandbox](apparmor/dever-sandbox), derived from the [AppArmor 4.0 bwrap restriction profile](https://gitlab.com/apparmor/apparmor/-/raw/apparmor-4.0/profiles/apparmor/profiles/extras/bwrap-userns-restrict). Its attachment permits only 64-lowercase-hex directories below the trusted store. bwrap creates namespaces under the parent policy and exec stacks the capability-denying child policy, including under no-new-privileges. Attachment paths do not restrict an explicit profile transition from an unconfined process: on hosts with user namespace restriction enabled, `kernel.apparmor_restrict_unprivileged_unconfined=1` is therefore mandatory before installation or loading. See [Ubuntu's explanation of strict profile changes](https://discourse.ubuntu.com/t/understanding-apparmor-user-namespace-restriction/58007). Non-root launches check this flag before selecting a helper; a missing, disabled or unreadable flag fails closed. The real-host installer checks the same prerequisite before any installation changes and again before publishing the policy file, because an independent system policy reload could load even an initially inactive file. Offline image preparation does not change or require the author's host settings; the deployed image must satisfy this prerequisite before its policy becomes loadable. - -The runtime also requires both named profiles in enforce mode using the read-only AppArmor policy filesystem; absent or inaccessible policy metadata is an explicit deployment error. No launch changes sysctl or loads policy. A container or restricted mount namespace must expose this policy metadata if it runs such non-root Workers. Hosts without the user namespace restriction do not require the strict-profile sysctl to exist. - -Administrator order is explicit: first review and approve the host-wide effect of strict profile transitions, record the original sysctl value, and establish `kernel.apparmor_restrict_unprivileged_unconfined=1`; then install the matching signed helper/policy; only then load with `apparmor_parser -r -K /etc/apparmor.d/dever-sandbox`. Dever never changes this global setting automatically. Review and offline validation use `apparmor_parser -Q -K -j 1 sdk/apparmor/dever-sandbox`, which does not load policy or write its cache. First-install rollback must unload this exact policy with `apparmor_parser -R -K /etc/apparmor.d/dever-sandbox` and remove the newly installed policy file from reload discovery before restoring the original strict-profile sysctl value. For an upgrade, restore the previously approved policy instead, retaining strict mode for any policy that requires it. Keep all helpers needed by deployed applications. Each host operation requires authorization; never disable the user namespace restriction. Real non-root, NNP/aa-exec (including immediate mode) and capability-denial acceptance must follow loading; offline parsing and root-only acceptance do not establish those results. - -The installer preserves at most 24 helper identities, each with its original signed manifest/signature, independently of compiler version directories. Unknown entries, incorrect signatures and digest mismatches fail without overwriting that store. The existing transaction's 128-entry/80-MiB tree budget also applies. Retained hashes support independently deployed applications after source or compiler-version removal. A new compiler version selecting different bwrap bytes requires the explicit trusted bootstrap installation before affected non-root Workers can start. Other OS backends and GPU device isolation are not currently supported. - -For approved profile-transition acceptance, `test/dever-sandbox-tests/apparmor_transition.c` is a standalone negative probe: compile it statically with the explicit author C toolchain, then invoke it as a nonzero UID through `aa-exec -p dever-bwrap`, immediate `aa-exec -i -p dever-bwrap`, and no-new-privileges variants. It never executes another program; it attempts only its own user/network namespaces, UID/GID maps and loopback capability operation. Record aa-exec rejection separately from a probe result. Exit 0 reports a denied operation, exit 1 reports unsafe access and exit 2 means unavailable setup. Creating the network namespace already proves a capability check succeeded, so the probe returns 1 even if a later loopback operation fails. Preserve the initial label and exact denial stage for each case. - -### Static Linux x86_64 author input - -The current private fixture uses upstream [bubblewrap v0.11.0](https://github.com/containers/bubblewrap/tree/v0.11.0), SHA-256 `cfeeb15fcc47d177d195f06fdf0847e93ee3aa6bf46f6ac0a141fa142759e2c3` for `https://codeload.github.com/containers/bubblewrap/tar.gz/refs/tags/v0.11.0`, and Ubuntu Noble's `libcap-dev_2.66-5ubuntu2.4_amd64.deb`, SHA-256 `07f2462867569a2119a2ad0f1593232663f2d1612b791c230d22a8d73a15abee` from the authenticated apt package index. Its download URL is `https://archive.ubuntu.com/ubuntu/pool/main/libc/libcap2/libcap-dev_2.66-5ubuntu2.4_amd64.deb`. Extract with `dpkg-deb -x` into the author directory; do not install packages on the target host. Retain upstream `COPYING`, the libcap package's `usr/share/doc/libcap-dev/copyright`, sources and the exact build recipe with author inputs. - -Below, `target/sandbox-author-inputs/` contains the extracted `bubblewrap-0.11.0/` and `libcap/`. Its source-local `config.h` contains only `#define PACKAGE_STRING "bubblewrap 0.11.0"` and `#define ENABLE_REQUIRE_USERNS 1`. Build with the explicitly selected author GNU C toolchain and static libc; no customer build tools are needed: - -```sh -/usr/bin/cc -static -O2 -D_GNU_SOURCE \ - -I target/sandbox-author-inputs/libcap/usr/include \ - -I target/sandbox-author-inputs/bubblewrap-0.11.0 \ - target/sandbox-author-inputs/bubblewrap-0.11.0/bubblewrap.c \ - target/sandbox-author-inputs/bubblewrap-0.11.0/bind-mount.c \ - target/sandbox-author-inputs/bubblewrap-0.11.0/network.c \ - target/sandbox-author-inputs/bubblewrap-0.11.0/utils.c \ - target/sandbox-author-inputs/libcap/usr/lib/x86_64-linux-gnu/libcap.a \ - -o target/sandbox-author-inputs/bwrap-static -readelf -l target/sandbox-author-inputs/bwrap-static -readelf -d target/sandbox-author-inputs/bwrap-static -sha256sum target/sandbox-author-inputs/bwrap-static -``` - -The 2026-10-02 private author build is 1,099,016 bytes with SHA-256 `c9e8bd758c2d01ca6668a842bad7b020bf700436e87b666cfaae3803be0be1b3`; readelf confirms no interpreter and no dynamic section. A different author compiler/libc may produce a different digest: sign the actual validated bytes and deploy their matching content-addressed helper. The current policy source SHA-256 is `a6d2ef490d12914e90a96272a197b8b78667403702b1324bae661a10b78125ec`; AppArmor parser 4.0.1 accepted it offline with the command above. These are input/parse results, not evidence that host policy has been loaded. - -Application file access is explicit in `config/setting.json`, for example `adapter.notification.delivery.files.uploads = {"path":"data/upload", "write":true}` with checked `allow file`. The Worker sees `/data/uploads`. Grant paths cannot write the executable cache or other execution inputs; no environment configuration is introduced. - -## Make and consume - -Build the private author executable once, then run it directly. The command optimizes existing compression and digest dependencies even in a development build, so complete language distributions do not spend minutes in unoptimized byte loops. These author/test options do not change application configuration or compile-service limits. - -```sh -cargo build --offline --locked -p dever-cli --example native-release \ - --config 'profile.dev.package.miniz_oxide.opt-level=3' \ - --config 'profile.dev.package.flate2.opt-level=3' \ - --config 'profile.dev.package.sha2.opt-level=3' -target/debug/examples/native-release --output -``` - -The output parent must exist. A private sibling staging directory holds copied inputs until the existing runtime validator succeeds and the manifest is signed. Publication atomically requires an absent destination, including under concurrent makers. Failures remove only owned staging. Output artifacts are independent copies; subsequent source changes do not change a completed pack. - -The result contains `dever-core`, `lib/libLLVM.so.18.1`, `runtime//manifest.json`, four `archives/.a` files, the configured link inputs, and top-level `manifest.json`/`manifest.sig`. The signed manifest covers the complete native closure. Place this version directory in the existing machine download store and use the established installer; trusted public-key provisioning remains explicit and separate. The maker does not trust a key merely because it accompanies a release, install a service, publish a catalog or update a global command. - -For private `dever` development, the same verified `runtime/` and `lib/` trees may be copied beside a matching private compiler in a new directory. An executable named `dever-core` still requires the managed installation layout and authenticated daemon. This is not a service-unavailable fallback. - -## Acceptance - -Default `native_release` tests use synthetic input and temporary keys. The explicit Linux acceptance additionally consumes the four optimized archives in `target/native-release-inputs/`, the prepared native SDK and the built author executable: - -Real ecosystem acceptance temporarily holds the signed release, installed version, compiler cache and Worker bundles simultaneously. Allow several GiB of free storage in addition to author inputs and Cargo artifacts. When the system temporary filesystem is too small, an optional author-only `target/native-release-inputs/config/setting.json` can select an existing executable filesystem: - -```json -{"machine_temporary_root":"/dev/shm"} -``` - -The path must be absolute; unknown configuration fields are rejected. Only the ecosystem machine directory and bootstrap image use this setting. Author inputs remain on the normal temporary filesystem so their immutable hard links stay on the source filesystem. With no configuration, the existing temporary-directory behavior is unchanged. No environment variable is read for this setting. A memory-backed filesystem consumes real memory: provide both sufficient free capacity and an explicit acceptance-process memory budget, and run these large acceptances serially. - -Before the no-host checks, build their test-only static init explicitly: - -```sh -cargo rustc --offline --locked -j1 -p dever-cli --example native-acceptance-init -- -C target-feature=+crt-static -``` - -```sh -cargo test --offline --locked -p dever-cli --test native_release -cargo test --offline --locked -p dever-cli --test native_release \ - acceptance::optimized_profiles_make_reproducible_signed_release_and_run_through_daemon \ - -- --exact --ignored --nocapture -cargo test --offline --locked -p dever-cli --test native_release \ - acceptance::signed_core_builds_without_host_compiler_libraries_or_tools \ - -- --exact --ignored --nocapture -``` - -The second command starts only a test-owned daemon and SQLite databases. It checks actual driver symbols, identical manifests/signatures for repeated packaging, signed installation, four profile executions through the daemon, and independent programs after source removal and daemon shutdown. PostgreSQL server behavior is a separate acceptance, not implied by linking the PostgreSQL profile. - -The third command requires root and namespace permission for a test-owned mount namespace root. It checks source and builds a SQLite program inside a root containing only the signed compiler closure, selected native archives and named GNU OS ABI libraries, then executes the program after removing its source. No host LLVM, C++ library, language tool, compiler SDK or package manager is visible there. The harness uses the explicitly prepared bwrap/loader assets to pivot into that root. - -The harness rejects a dynamically linked init. Inside the already pivoted namespace, it replaces bwrap's proc submounts with a complete private proc mount so the nested Worker can mount its own proc. It keeps the outer root fixture's existing capabilities; the product's inner namespace, capability removal and guard remain unchanged. It never binds the host proc into the final root. This private compiler test complements the managed daemon test; it does not install a machine service. - -To accept an already prepared official release (including its real signing identity), use the owned-image verifier. `--assets` feeds the exact split download files through the real installer using local transport; signature checks, extraction and bootstrap execution are unchanged. The `prepare-extensions` author example replaces only extension transport with actual local assets; it uses the product owner for validation and installation. Supply it with `--extension-helper` to exercise ARM preparation, CLI reuse and cross compilation. The verifier requires explicit static bwrap/init fixtures, creates a new image, starts only its own daemon and records each passed stage. Online update and real-host service activation remain separate checks. - -```sh -python3 -B test/onboarding/verify_prepared_release.py \ - --release /prepared/release --assets /prepared/download-assets \ - --init /prepared/native-acceptance-init --extension-helper /prepared/prepare-extensions \ - --image /new/owned-image --report /owned-records/acceptance.json -``` - -The image and its owned ancestor directories must be traversable by the two test UIDs (65533 and 65534). Their resource-reuse check starts a separate private-machine daemon with real kernel identities, because the minimal OS fixture's single-UID user namespace cannot represent another user. It does not touch the global service. - -`test/onboarding/verify_release_update.py` accepts the same asset/init/helper paths plus `--key `. It re-signs the real payload catalog as an acceptance-only next version, verifies that a missing extension preserves the old working selection, then verifies that a successful update activates core/skill and exactly the installed extension set. That fixture version is never published; this is local update-transaction evidence, not an online Release acceptance. - -The existing fixture-based bootstrap regression additionally requires the built `dever` and `deverd` binaries: - -```sh -cargo test --offline --locked -p dever-cli --test native_release \ - acceptance::bootstrap::signed_bootstrap_installs_and_serves_two_projects_without_host_libraries \ - -- --exact --ignored --nocapture -``` - -It installs only into a new owned image, verifies stable entry and systemd assets, exercises a legitimate older signed unit upgrade and rejects tampering, then runs two projects through the installed daemon in the minimal OS root. Separate clients retain two real kernel UIDs to check shared-cache use and denied machine mutation. Finally the independently built programs run after source and machine-store removal. Neither the global service nor a public signing identity is involved. - -Identical prepared inputs and signing key produce identical payloads, manifests and signatures. This establishes deterministic packaging, not reproducible source builds across different machines, CRTs or Rust toolchains. Temporary test signatures and Linux execution do not establish public release, six-platform delivery, an OS sandbox or performance capacity. - -The explicit three-ecosystem acceptance uses fixed upstream archives and the retained Go build fixture listed with exact digests in `test/ecosystem-release/prepare.py`. Supply those inputs explicitly, then prepare a new directory: - -| Input | Explicit source | -| --- | --- | -| `downloads/cpython-3.12.14.tar.gz` | [python-build-standalone 20260901, Linux x86_64 install-only stripped](https://github.com/astral-sh/python-build-standalone/releases/download/20260901/cpython-3.12.14%2B20260901-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz) | -| `downloads/node-v24.15.0-linux-x64.tar.xz` | [Node v24.15.0 Linux x64](https://nodejs.org/dist/v24.15.0/node-v24.15.0-linux-x64.tar.xz), verified against the release's `SHASUMS256.txt` | -| `target/go-managed/runtime.pack` | Go 1.26.3 private host fixture with explicit `build.host=linux-x86_64`; the pinned archive preserves the original tools/stdlib and repacks the updated descriptor. New fixtures use `test/go-managed/make_pack.go`; this is not an upstream published pack. | - -The two download paths are below `target/ecosystem-release-inputs/`. No command here performs implicit downloads; the preparation script rejects different digests. - -```sh -/usr/bin/python3 test/ecosystem-release/prepare.py target/ecosystem-release-inputs/prepared -cargo test --offline --locked -p dever-cli --test native_release \ - --config 'profile.dev.package.miniz_oxide.opt-level=3' \ - --config 'profile.dev.package.flate2.opt-level=3' \ - --config 'profile.dev.package.sha2.opt-level=3' \ - acceptance::ecosystems::signed_ecosystems_build_and_run_without_system_language_installations \ - -- --exact --ignored --nocapture -``` - -This opt-in test requires Linux root and mount/PID/user namespace capability. It signs and installs an owned release, uses the managed daemon for each ecosystem's lock/check/run/build, then removes project sources and the entire machine store. The resulting programs run inside an owned mount namespace root containing only named Linux OS ABI libraries, a private proc mount and synthetic devices. Python checks bundle-local imports, standard-library native modules and the source-built simplejson C extension; Node loads the source-built bufferutil addon; Go retains its managed probe. The already prepared source-build locks and exact output artifacts come from `target/source-build/dependency` and `target/npm-build/dependency`; this acceptance never rebuilds hooks or downloads dependencies. It signs the exact runtime-pack bytes bound by those build receipts, so this test's author signature differs from the separate deterministic-maker evidence. No system Python, Node, Go, compiler, SDK or package manager is visible there. Other operating systems and a public release identity remain separate acceptance. diff --git a/skills/SKILL.md b/skills/SKILL.md index 4924ed5..ff53528 100644 --- a/skills/SKILL.md +++ b/skills/SKILL.md @@ -11,7 +11,7 @@ Dever 是独立语言。应用源码使用 `.dever` 或 `.dever.md`,不沿用 1. 读取用户项目的 `AGENTS.md`、现有目录和 `config/setting.json`。回答、分析、诊断只做只读检查;用户要求修改时再实施,不擅自安装软件、改服务或改全局命令。 2. 若已安装机器版 Dever,新项目运行 `dever skill path`,已有项目运行 `dever skill path `,读取返回目录中的 `SKILL.md` 与本次需要的参考文件。已经在那个目录读取本 skill 时不再递归加载。它由 `dever update` 与核心一起更新;已有项目按其可选 dever.version 选择对应指引,不能把活动版本新增语法强加给旧项目。 -3. 尚无 `dever` 时按 [安装与更新](references/install.md) 引导安装;不能把 `dever-go` 当作 Dever 语言命令。公开发行包缺失时如实说明,不编造成功、不自动编译一套缺少 runtime 的开发二进制。 +3. 尚无 `dever` 时按 [安装与更新](references/install.md) 引导安装;不能把 `dever-go` 当作 Dever 语言命令。先核对主机平台和安装前提,安装失败时保留真实错误,不用缺少运行资源的源码开发二进制冒充完整安装。 4. 新项目使用 `dever new `;Markdown 项目加 `--markdown`。不要手工猜模板,不覆盖已有目录。项目模板的用途和检查命令见 [项目开发](references/development.md)。 开发、重构或审查应用代码前,必须读取 [项目开发](references/development.md) 中的文件与函数组织、配置与硬编码、禁止绕过检查、验证范围。安装或纯语法问答只加载与请求相关的参考。 diff --git a/skills/assets/template/README.md b/skills/assets/template/README.md index d829c2b..1044c05 100644 --- a/skills/assets/template/README.md +++ b/skills/assets/template/README.md @@ -19,6 +19,6 @@ dever build . --output hello-app AI 开发规范见本项目 `AGENTS.md`。运行 `dever skill path .` 获取项目对应版本的完整 `dever-language` skill,开发前读取其中 `references/development.md`。AI 的稳定 skill 入口可用 `dever skill install <新的AI技能目录>/dever-language` 安装;核心与配套 skill 通过 `dever update` 同步更新,已锁定版本的项目仍使用自己的版本。 -首次安装入口为 `https://git.dever.cc/shemic/dever/install`,源码仓库为 `ssh://git@git.dever.cc:2222/shemic/dever.git`。安装前确认该站已发布对应平台的脚本和签名包;部署完成后可用 `curl -fsSL https://git.dever.cc/shemic/dever/install | bash`,机器安装需要管理员权限。仓库可访问不代表二进制已经发布。 +首次安装使用 `curl -fsSL https://git.dever.cc/shemic/dever/raw/branch/main/install | bash`。开发机须为 Linux x86_64、glibc 2.39+,并具备 Bash、curl、Python 3.9+、支持 Ed25519 的 OpenSSL 和管理员权限;非 root 用户需要 sudo。完整条件见 [安装指引](https://git.dever.cc/shemic/dever/src/branch/main/skills/references/install.md)。下载安装无需 token 或项目配置。 普通 `.dever` 与 Markdown `.dever.md` 共享语言规则。用 `dever new <新目录> --markdown` 创建 Markdown 项目。目录必须不存在,生成器不会覆盖已有项目。 diff --git a/skills/references/development.md b/skills/references/development.md index ec21225..e6110ba 100644 --- a/skills/references/development.md +++ b/skills/references/development.md @@ -123,6 +123,6 @@ W001–W005 等诊断包含未使用赋值、部分冗余条件、相同私有 ## 核心与业务的区别 -统一源码仓库地址为 `ssh://git@git.dever.cc:2222/shemic/dever.git`,迁移与发行状态见 [安装指引](install.md)。`crates/dever-core` 负责语言检查/编译,`crates/dever-runtime` 负责运行时,`crates/dever-cli` 负责命令,`library/` 是随版本提供的标准 Dever 源码。维护中的完整业务示例是 `examples/cms/dever` 与 `examples/cms/md`;`examples/old` 是历史回归,不作新项目模板。 +[源码仓库](https://git.dever.cc/shemic/dever) 中,`crates/dever-core` 负责语言检查/编译,`crates/dever-runtime` 负责运行时,`crates/dever-cli` 负责命令,`library/` 是随版本提供的标准 Dever 源码。维护中的完整业务示例是 `examples/cms/dever` 与 `examples/cms/md`;`examples/old` 是历史回归,不作新项目模板。 开发普通应用无需复制或修改这些核心目录。可复用业务组件作为 Dever Package;外部 Python/JS/Go 生态称 Lib。多个项目共享机器安装的 Dever。 diff --git a/skills/references/install.md b/skills/references/install.md index 07555d3..0b265ea 100644 --- a/skills/references/install.md +++ b/skills/references/install.md @@ -1,24 +1,24 @@ # 安装与更新 -安装入口为 `https://git.dever.cc/shemic/dever/install`,官方二进制源为同站 `/shemic/dever/dist`。这些地址由发行工具固定,不写入业务项目配置,不通过环境变量选择。Git 源码可访问不代表安装端点或二进制已发布;服务器尚未部署时如实报告,不能把登录 HTML 当作脚本。 +Dever 安装包和编辑器插件从 [Releases](https://git.dever.cc/shemic/dever/releases) 下载。 ## 安装 dever -先检查 `dever --help`。机器版提供 new、install、update、target、version、skill;仅源码开发二进制不管理机器安装。不要把已有同名命令直接删掉或覆盖,先识别归属。 +先检查 `dever --help`,确认已有同名命令的归属,不直接删除或覆盖。Dever 语言与 Go 框架的 `dever-go` 是不同工具。 -初次安装需要 Linux、Bash、Python 3.9 或更新版本的 `/usr/bin/python3` 和支持 Ed25519 的 `/usr/bin/openssl`;管道下载还需要 curl。非 root 安装通过 `/usr/bin/sudo` 提权,帮助不提权。这些工具用于校验和安装,生成的应用不依赖系统 Python、Node、Go 或 Rust。检查安装脚本并取得机器安装授权后执行: +当前开发机支持 Linux x86_64,要求 glibc 2.39 或更新版本。首次安装还需要 Bash、`/usr/bin/python3` 3.9+、支持 Ed25519 的 `/usr/bin/openssl`;管道下载需要 curl。安装使用管理员权限,非 root 用户通过 `/usr/bin/sudo` 提权,查看帮助不提权。 -还须满足所选发行包的主机 ABI 要求;当前准备的 Linux x86_64 编译器要求 glibc 2.39。ARM64 应用交叉构建可在 x86_64 主机使用,不能据此宣称 ARM64 宿主编译器包已经发布。 +取得机器安装授权后执行: ```sh -curl -fsSL https://git.dever.cc/shemic/dever/install | bash +curl -fsSL https://git.dever.cc/shemic/dever/raw/branch/main/install | bash ``` -无需先克隆源码或安装 skill。查看参数用 `bash -s -- --help`;固定版本用 `bash -s -- --version <准确版本>`,替换上面命令尾部的 `bash` 即可。本地已下载脚本可用 `bash install --help` 检查。 +无需先克隆源码或安装 skill。安装器下载最新正式版本,安装到 `/opt/dever`,提供 `/usr/local/bin/dever`,并安装、启动机器共享服务及必要的沙箱策略。无需系统 zstd。没有匹配平台的发行包或下载校验失败时明确报错。 -该命令下载当前平台最新已签名基础包。脚本包含独立固定公钥,先校验发行元数据,再验证引导程序及其私有库摘要,由引导程序解压 Zstandard 包;无需系统 zstd。安装 `/opt/dever`、`/usr/local/bin/dever`、机器共享服务和必要沙箱策略,默认启动服务。`--no-start` 可仅安装。没有对应正式资产时明确失败,不修改已安装版本。 +将命令尾部的 `bash` 换为 `bash -s -- --help` 可查看参数,换为 `bash -s -- --version <准确版本>` 可指定版本。`--no-start` 只安装、不启动服务;应用编译仍需要共享服务可用。已下载脚本也可用 `bash install --help` 查看帮助。 -基础包包含 Dever 编译器、本机应用编译资源、四种数据库运行库和配套 skill。Python、Node、Go、第三方原生构建工具与 ARM 应用目标按需安装,保存在机器共享资源目录;同一版本的多个用户和项目共用一份。 +基础安装包含编译器、应用编译资源、数据库运行库和配套 skill。Python、Node、Go 及第三方构建工具按实际依赖准备,同一版本由多个用户和项目共享。生成的应用不依赖系统 Python、Node、Go、Rust 或 Dever 编译器。 ## 将 skill 接入 AI @@ -28,35 +28,29 @@ curl -fsSL https://git.dever.cc/shemic/dever/install | bash dever skill install <新的AI技能目录>/dever-language ``` -目录必须尚不存在,不能覆盖已有 skill。入口每次解析与核心配套的完整 skill,重载 AI 工具的技能列表后使用。这是 Dever 语言的 `dever-language`,不是 Go 框架的 `shemic-dever`。不自动修改机器上其他用户的 AI 目录。 +目标目录必须尚不存在,不覆盖已有 skill,也不把入口嵌套进现有完整 skill 目录。重载 AI 工具的技能列表后使用;入口解析与核心版本配套的完整 skill。它名为 `dever-language`,不是 Go 框架的 `shemic-dever`,不会自动修改其他用户的 AI 目录。 -## 按需准备资源 +新项目用 `dever skill path`,已有项目用 `dever skill path ` 查看对应版本的指引。 -首次添加或更新 Lib 时,`dever lib add/update ...` 自动准备相应生态,只有进入源码构建流程时才准备构建工具。已有 `dever.lock` 的项目在新机器运行 `dever lib install `,按锁恢复依赖,保持配置和锁文件不变;没有 Lib 的 Python/JS/Go Adapter 也可通过该命令准备环境。缺少锁时先显式 `dever lib update ` 生成锁。不要把 install 当作重新选版本的 update。 +## 按需准备依赖和 ARM64 应用目标 -在 x86_64 机器准备 ARM64 应用目标: +显式 `dever lib add/update ...` 按需准备对应生态,只有依赖需要源码构建时才准备构建工具。已有 `dever.lock` 的项目在新机器运行 `dever lib install `,按锁恢复,保持配置与锁文件不变;没有 Lib 的 Python/JS/Go Adapter 也可通过该命令准备环境。缺锁时先用 `dever lib update ` 生成锁,不把 install 当作重新选版本的 update。 + +Linux x86_64 开发机可准备 Linux ARM64 应用目标: ```sh dever target add linux-aarch64 -dever lib install --target linux-aarch64 +dever lib update --target linux-aarch64 dever build --target linux-aarch64 --output <新文件> ``` -只用 Dever、没有外部依赖的项目省略 lib install。目标 Lib 必须已有匹配目标的锁;首次生成 ARM 锁使用 lib add/update 的同名 target 参数。准备会显式联网,后续 run/build 离线;缺资源时执行提示的准备命令,不改用系统解释器。target add 准备当前活动版本,锁定其它编译器版本的项目先准备并选择对应版本。 +没有外部依赖时省略 lib update;已有匹配目标的锁时使用 lib install。目标依赖和原生扩展必须支持 ARM64。target add 准备当前活动版本,锁定其他编译器版本的项目先安装并选择对应版本。 -已准备本地发行包时: +依赖和目标准备会显式联网,后续 run/build 离线;缺资源时按提示准备,不扫描宿主 Python、Node、Go 或 PATH 充当运行环境。省略目标时使用本机架构,run/test 始终在本机执行。ARM64 应用目标不表示提供 ARM64 宿主编译器,macOS、Windows 宿主安装暂未提供。 -```sh -bash install --release /可信发行目录 --trusted-key /独立确认的公钥文件 -``` +Linux 外部调用要求系统支持所需 namespace 与 openat2。受限 AppArmor 环境需要安装器配置的专用策略;策略不满足要求时明确失败,不关闭沙箱继续执行。 -测试或镜像制作增加 `--system-root /已有的自有镜像目录`;不会启动宿主服务。安装器生成的临时 `config/setting.json` 仅供机器 bootstrap 使用,包含本地发行路径、安装根和公钥路径;不是业务配置,不写发行仓库地址或环境变量。 - -公钥可公开提交;签名私钥绝不能进 skill、源码仓库或发行包。只有已独立确认的公钥才可作为 `--trusted-key`,不能从未知下载包顺手取一把钥匙作为信任依据。 - -skills 只提供安装指引,不携带独立安装器;首次安装统一使用上述 `install` 入口。 - -## 一条命令更新核心与 skill +## 更新与选择版本 ```sh sudo dever update @@ -64,16 +58,8 @@ dever version dever skill path ``` -update 只访问内置官方发行源,先准备核心、同版本完整 skill,以及当前活动版本已安装的扩展,再切换活动版本。未使用的扩展不会一起下载;任一准备失败保留原活动版本。普通 check/test/run/build 不检查更新、不隐式联网。 +update 同步准备核心、配套 skill 和当前已安装的可选扩展,全部成功后才切换活动版本;未使用的扩展不下载,失败保留原活动版本。普通 check/test/run/build 不检查更新、不隐式联网。更新不改业务项目文件或数据库。 -从旧 GitHub 发行源迁移时,需要在新源正式包发布后执行一次新的 `install`。旧启动器和守护进程内置旧地址,普通 update 不负责替换这两个稳定程序;只修改仓库 remote 或重新发布旧包不能完成迁移。新 install 成功后再用 `dever update`。 +项目可在 `config/setting.json` 的 `dever.version` 锁定准确 `major.minor.patch`,未锁定时使用机器活动版本。`sudo dever install <版本>` 准备指定版本,`sudo dever use <版本>` 切换活动版本;项目锁定仍优先于活动版本。已有项目用 `dever skill path ` 读取对应指引,不仅凭最新指南采用新语法。 -本仓库直接安装的 skill 在开始开发时先运行 `dever skill path` 并加载该版本的完整 skill,不必每个项目 git pull。也可以用 `dever skill install <新的AI技能目录>/dever-language` 安装稳定的薄入口,之后每次自动解析当前机器版本;已有目录不会被覆盖。不要把新入口嵌套装进已经存在的完整 skill 目录。 - -项目可选 `config/setting.json` 的 `dever.version` 锁定准确 `major.minor.patch`,未锁定时使用机器活动版本。`dever install 版本` 准备指定版本;`dever use 版本` 显式切换活动版本。update 不改业务项目文件或数据库。锁定项目用 `dever skill path ` 读取对应指引,不能仅凭活动版指南采用新语法。 - -## 源码维护者 - -统一源码仓库为 `ssh://git@git.dever.cc:2222/shemic/dever.git`。`skills/` 是主仓库中的普通目录,与核心、模板和安装器一起提交、校验及发行;无需初始化 submodule 或另行克隆 skill 仓库。普通应用开发者无需克隆核心或编译 Rust。 - -根 `install` 是唯一安装源码,直接维护其中的 Bash 入口和内嵌 Python 实现,无需生成步骤。独立固定公钥不得来自下载包;修改后检查 `bash -n install`,并运行 `python3 -B -m unittest discover -s test/onboarding -p 'test_install*.py' -v` 验证参数传递、验签和失败清理。首个新源发行包发布前,默认下载会明确失败;使用真实签名本地包可验证安装,但不能代表线上安装或更新已经通过。 +旧安装若仍访问已停用的下载地址,重新执行上述安装命令,再使用正常 update。该操作需要同样的机器安装权限。 diff --git a/test/ci/README.md b/test/ci/README.md index 51fc06d..746ba22 100644 --- a/test/ci/README.md +++ b/test/ci/README.md @@ -44,7 +44,7 @@ 替换路径,勿直接复制示例运行。下文 CI 字段均位于 `performance.linux_ci`。`inputs` 列出固定原始作者输入及准备好的资产文件/目录,逐文件计 SHA-256;工具、协议产物、CMS manifest/可执行文件/配置和 `performance.network_peer/live_peer` 也自动计摘要,`linux_ci` 对象不作为 peer 路径解析。输出目录不得包含在 inputs 中。报告只存摘要,不复制数据库密码。 -`required_inputs` 为 `author`、`native`、`postgres`、`sandbox`、`bounded-perf`、`soak` 各提供非空绝对路径列表,必须落在 `inputs` 声明范围内。缺路径记录 blocked,不算 pass。作者 fixture 的具体固定路径/准备命令仍以 `sdk/native-release.md`、`test/ecosystem-release/prepare.py`、`test/ecosystem-release/build_inputs.py` 和对应 ignored 原因文本为准;gate 不把现存文件冒充由当前源码重建的 provenance。 +`required_inputs` 为 `author`、`native`、`postgres`、`sandbox`、`bounded-perf`、`soak` 各提供非空绝对路径列表,必须落在 `inputs` 声明范围内。缺路径记录 blocked,不算 pass。作者 fixture 的具体固定路径/准备命令仍以 `test/ecosystem-release/prepare.py`、`test/ecosystem-release/build_inputs.py` 和对应 ignored 原因文本为准;gate 不把现存文件冒充由当前源码重建的 provenance。 显式 LLVM Worker 验收读取 `target/native-release-inputs/component-fixture`:先用当前源码构建 `dever-tests` 的 `component-fixture` bin,再将程序复制到该准备目录,记录源码/程序摘要,并把固定副本列入 `inputs` 和 `required_inputs.native`。不能将 `target/debug/component-fixture` 当作不可变输入:Cargo 在 default/all-feature 组合间会重新链接这个输出。普通 Worker 测试仍使用 Cargo 为各自组合生成的 `CARGO_BIN_EXE_component-fixture`,不改质量门的输入变更拒绝规则。 diff --git a/test/dever-cli-tests/release_source.rs b/test/dever-cli-tests/release_source.rs index d3f4337..d1e14d7 100644 --- a/test/dever-cli-tests/release_source.rs +++ b/test/dever-cli-tests/release_source.rs @@ -108,15 +108,17 @@ fn signed_catalog_paths_and_total_size_are_bounded_before_extraction() { #[test] fn official_redirects_reject_http_credentials_ports_and_foreign_hosts() { - let current = "https://git.dever.cc/shemic/dever/dist/latest/a"; + let current = "https://git.dever.cc/attachments/a"; + let origin = url::Url::parse(OFFICIAL_RELEASES).unwrap(); assert!( redirect( current, - "https://git.dever.cc/shemic/dever/dist/1.2.3/a?token=opaque" + "https://git.dever.cc/attachments/b?token=opaque", + &origin, ) .is_ok() ); - assert!(redirect(current, "/shemic/dever/dist/1.2.3/a").is_ok()); + assert!(redirect(current, "/attachments/b", &origin).is_ok()); for address in [ "http://git.dever.cc/a", "https://evil.example/a", @@ -127,34 +129,109 @@ fn official_redirects_reject_http_credentials_ports_and_foreign_hosts() { "https://github.com/a", "https://release-assets.githubusercontent.com/a", ] { - assert!(redirect(current, address).is_err(), "{address}"); + assert!(redirect(current, address, &origin).is_err(), "{address}"); + assert!( + validate_download_url(address, &origin).is_err(), + "{address}" + ); + } + assert!(validate_download_url("/attachments/b", &origin).is_err()); +} + +#[test] +fn official_assets_use_exact_platform_names_and_return_the_published_url() { + let suffix = "ext-runtime-pip-linux-x86_64.tar.zst"; + let metadata = release_metadata("https://git.dever.cc", "v1.2.3", &[(suffix, b"archive")]); + let release = ResolvedRelease::parse(&metadata, "latest").unwrap(); + assert_eq!(release.version.as_str(), "1.2.3"); + assert_eq!( + release.asset(suffix).unwrap().browser_download_url, + "https://git.dever.cc/attachments/0" + ); + assert!(release.asset("manifest.json").is_err()); + assert!( + release + .asset("ext-runtime-pip-linux-aarch64.tar.zst") + .is_err() + ); +} + +#[test] +fn release_metadata_rejects_unstable_tags_mismatched_versions_and_malformed_assets() { + let good: serde_json::Value = serde_json::from_slice(&release_metadata( + "https://git.dever.cc", + "v1.2.3", + &[("tar.zst", b"archive")], + )) + .unwrap(); + for tag in [ + "1.2.3", + "v01.2.3", + "v1.2", + "v1.2.3-rc.1", + "v1.2.3+build", + "v../escape", + ] { + let mut metadata = good.clone(); + metadata["tag_name"] = tag.into(); + assert!( + ResolvedRelease::parse(&serde_json::to_vec(&metadata).unwrap(), "latest").is_err(), + "{tag}" + ); + } + assert!(ResolvedRelease::parse(&serde_json::to_vec(&good).unwrap(), "1.2.4").is_err()); + for field in ["draft", "prerelease"] { + let mut metadata = good.clone(); + metadata[field] = true.into(); + assert!(ResolvedRelease::parse(&serde_json::to_vec(&metadata).unwrap(), "latest").is_err()); + metadata.as_object_mut().unwrap().remove(field); + assert!(ResolvedRelease::parse(&serde_json::to_vec(&metadata).unwrap(), "latest").is_err()); + } + let asset = good["assets"][0].clone(); + for assets in [ + serde_json::json!([]), + serde_json::json!([asset, asset]), + serde_json::json!(vec![asset.clone(); ASSET_LIMIT + 1]), + ] { + let mut metadata = good.clone(); + metadata["assets"] = assets; + assert!(ResolvedRelease::parse(&serde_json::to_vec(&metadata).unwrap(), "latest").is_err()); + } + for size in [ + serde_json::json!(0), + serde_json::json!(-1), + serde_json::json!(1.5), + serde_json::json!(RELEASE_LIMIT + 1), + serde_json::json!("7"), + ] { + let mut metadata = good.clone(); + metadata["assets"][0]["size"] = size; + assert!(ResolvedRelease::parse(&serde_json::to_vec(&metadata).unwrap(), "latest").is_err()); + } + for name in ["", "../asset", "a/b", "a\\b"] { + let mut metadata = good.clone(); + metadata["assets"][0]["name"] = name.into(); + assert!(ResolvedRelease::parse(&serde_json::to_vec(&metadata).unwrap(), "latest").is_err()); } } #[test] -fn official_asset_names_are_versioned_and_platform_specific() { - let source = ReleaseSource::official(); - assert_eq!( - source.asset("latest", "manifest.json"), - format!( - "https://git.dever.cc/shemic/dever/dist/latest/dever-{}.manifest.json", - platform_identity() - ) - ); - assert_eq!( - source.asset("1.2.3", "tar.zst"), - format!( - "https://git.dever.cc/shemic/dever/dist/1.2.3/dever-{}.tar.zst", - platform_identity() - ) - ); - assert_eq!( - source.asset("1.2.3", "ext-runtime-pip-linux-x86_64.tar.zst"), - format!( - "https://git.dever.cc/shemic/dever/dist/1.2.3/dever-{}.ext-runtime-pip-linux-x86_64.tar.zst", - platform_identity() - ) - ); +fn release_asset_reader_requires_the_exact_declared_size() { + for size in [2, 4] { + let mut reader = AssetReader { + reader: io::Cursor::new(b"abc"), + remaining: size, + }; + assert!(reader.read_to_end(&mut Vec::new()).is_err()); + } + let mut reader = AssetReader { + reader: io::Cursor::new(b"abc"), + remaining: 3, + }; + assert_eq!(reader.read(&mut []).unwrap(), 0); + let mut bytes = Vec::new(); + reader.read_to_end(&mut bytes).unwrap(); + assert_eq!(bytes, b"abc"); } fn signed_release() -> (ReleaseManifest, Vec, Vec, Vec) { @@ -177,13 +254,57 @@ fn signed_release() -> (ReleaseManifest, Vec, Vec, Vec) { } fn server(responses: Vec>) -> (ReleaseSource, std::thread::JoinHandle<()>) { + release_server("latest", "v1.2.3", responses) +} + +fn release_metadata(base: &str, tag: &str, assets: &[(&str, &[u8])]) -> Vec { + serde_json::to_vec(&serde_json::json!({ + "tag_name": tag, + "draft": false, + "prerelease": false, + "assets": assets.iter().enumerate().map(|(index, (suffix, bytes))| serde_json::json!({ + "name": format!("dever-{}.{suffix}", platform_identity()), + "browser_download_url": format!("{base}/attachments/{index}"), + "size": bytes.len(), + })).collect::>(), + })) + .unwrap() +} + +fn release_server( + selection: &str, + tag: &str, + responses: Vec>, +) -> (ReleaseSource, std::thread::JoinHandle<()>) { + serve(|base| { + let assets: Vec<_> = ["manifest.json", "manifest.sig", "tar.zst"] + .into_iter() + .zip(&responses) + .map(|(suffix, bytes)| (suffix, bytes.as_slice())) + .collect(); + let metadata = release_metadata(base, tag, &assets); + std::iter::once((format!("/releases/{selection}"), metadata)) + .chain( + responses + .into_iter() + .enumerate() + .map(|(index, bytes)| (format!("/attachments/{index}"), bytes)), + ) + .collect() + }) +} + +fn serve( + responses: impl FnOnce(&str) -> Vec<(String, Vec)>, +) -> (ReleaseSource, std::thread::JoinHandle<()>) { use std::io::BufRead; let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); listener.set_nonblocking(true).unwrap(); - let base = format!("http://{}/releases", listener.local_addr().unwrap()); + let base = format!("http://{}", listener.local_addr().unwrap()); + let responses = responses(&base); let worker = std::thread::spawn(move || { let deadline = Instant::now() + Duration::from_secs(5); - for (index, response) in responses.into_iter().enumerate() { + for (path, response) in responses { let mut stream = loop { match listener.accept() { Ok((stream, _)) => break stream, @@ -203,18 +324,7 @@ fn server(responses: Vec>) -> (ReleaseSource, std::thread::JoinHandle<() let mut reader = io::BufReader::new(stream.try_clone().unwrap()); let mut request = String::new(); reader.read_line(&mut request).unwrap(); - let (selection, suffix) = [ - ("latest", "manifest.json"), - ("latest", "manifest.sig"), - ("1.2.3", "tar.zst"), - ][index]; - assert_eq!( - request, - format!( - "GET /releases/{selection}/dever-{}.{suffix} HTTP/1.1\r\n", - platform_identity() - ) - ); + assert_eq!(request, format!("GET {path} HTTP/1.1\r\n")); loop { let mut line = String::new(); reader.read_line(&mut line).unwrap(); @@ -231,7 +341,123 @@ fn server(responses: Vec>) -> (ReleaseSource, std::thread::JoinHandle<() stream.write_all(&response).unwrap(); } }); - (ReleaseSource::new(base), worker) + (ReleaseSource::new(format!("{base}/releases")), worker) +} + +#[test] +fn latest_and_extensions_share_one_release_snapshot() { + use super::super::{BuildTarget, ExtensionId, ExtensionKind, ExtensionSource}; + use crate::libs::Ecosystem; + let extension = ExtensionId { + kind: ExtensionKind::Runtime(Ecosystem::Pip), + target: BuildTarget::LinuxX86_64, + }; + let (source, worker) = serve(|base| { + vec![ + ( + "/releases/latest".into(), + release_metadata(base, "v1.2.3", &[(&extension.asset_suffix(), b"extension")]), + ), + ("/attachments/0".into(), b"extension".to_vec()), + ("/attachments/0".into(), b"extension".to_vec()), + ] + }); + let selected = source.resolve("latest", Instant::now()).unwrap(); + assert!(Rc::ptr_eq( + &selected, + &source.resolve("latest", Instant::now()).unwrap() + )); + assert!(Rc::ptr_eq( + &selected, + &source.resolve("1.2.3", Instant::now()).unwrap() + )); + for _ in 0..2 { + let mut contents = Vec::new(); + source + .open(&selected.version, &extension) + .unwrap() + .read_to_end(&mut contents) + .unwrap(); + assert_eq!(contents, b"extension"); + } + worker.join().unwrap(); +} + +#[test] +fn exact_versions_resolve_the_tag_endpoint_and_missing_or_foreign_assets_fail() { + let (source, worker) = serve(|base| { + vec![( + "/releases/tags/v1.2.3".into(), + release_metadata(base, "v1.2.3", &[("tar.zst", b"archive")]), + )] + }); + let selected = source.resolve("1.2.3", Instant::now()).unwrap(); + worker.join().unwrap(); + assert!(selected.asset("manifest.sig").is_err()); + let foreign = ReleaseAsset { + name: "asset".into(), + browser_download_url: "https://evil.example/archive".into(), + size: 7, + }; + assert!( + source + .open_asset(&foreign, Instant::now()) + .err() + .unwrap() + .contains("origin") + ); + for version in ["../latest", "v1.2.3", "1.2.3-rc.1"] { + assert!(source.resolve(version, Instant::now()).is_err()); + } + let (source, worker) = serve(|_| { + vec![( + "/releases/latest".into(), + release_metadata("https://evil.example", "v1.2.3", &[("tar.zst", b"archive")]), + )] + }); + assert!( + source + .resolve("latest", Instant::now()) + .err() + .unwrap() + .contains("origin") + ); + worker.join().unwrap(); +} + +#[test] +fn release_metadata_downloads_are_bounded_and_asset_lengths_are_checked() { + let (source, worker) = serve(|_| { + vec![( + "/releases/latest".into(), + vec![b' '; METADATA_LIMIT as usize + 1], + )] + }); + assert!( + source + .resolve("latest", Instant::now()) + .err() + .unwrap() + .contains("size limit") + ); + worker.join().unwrap(); + let root = Download::new(&std::env::temp_dir()).unwrap(); + for size in [2, 4] { + let (source, worker) = serve(|_| vec![("/attachments/manifest".into(), b"abc".to_vec())]); + let asset = ReleaseAsset { + name: "asset".into(), + browser_download_url: source.base.join("/attachments/manifest").unwrap().into(), + size, + }; + assert!( + source + .metadata(&asset, &root.0.join("manifest.json"), Instant::now()) + .unwrap_err() + .contains("size") + ); + worker.join().unwrap(); + assert!(!root.0.join("manifest.json").exists()); + } } fn compressed_release(core: &[u8]) -> Vec { @@ -396,6 +622,31 @@ fn explicit_download_verifies_the_complete_bundle_before_publishing_catalog() { assert_eq!(fs::read_dir(layout.staging()).unwrap().count(), 0); } +#[test] +fn latest_manifest_must_match_the_selected_tag_before_publication() { + let root = Download::new(&std::env::temp_dir()).unwrap(); + let layout = Layout::new(root.0.join("machine")); + layout.initialize().unwrap(); + let (_, bytes, signature, key) = signed_release(); + fs::write( + layout.state().join("trusted-release-key"), + super::super::release::hex(&key), + ) + .unwrap(); + fs::write(layout.downloads().join("latest"), "0.9.0\n").unwrap(); + let (source, worker) = release_server("latest", "v1.2.4", vec![bytes, signature]); + let error = prepare_from(&layout, "latest", &source).unwrap_err(); + worker.join().unwrap(); + assert!(error.contains("selected release tag"), "{error}"); + assert_eq!( + fs::read_to_string(layout.downloads().join("latest")).unwrap(), + "0.9.0\n" + ); + assert!(!layout.downloads().join("1.2.3").exists()); + assert!(!layout.downloads().join("1.2.4").exists()); + assert_eq!(fs::read_dir(layout.staging()).unwrap().count(), 0); +} + #[test] fn bad_signatures_and_corrupt_payloads_preserve_the_previous_catalog_and_active_version() { for bad_signature in [true, false] { diff --git a/test/dever-tests/fixtures/core/complete_package.dever b/test/dever-tests/fixtures/core/complete_package.dever new file mode 100644 index 0000000..8476379 --- /dev/null +++ b/test/dever-tests/fixtures/core/complete_package.dever @@ -0,0 +1,150 @@ +public type UserStatus { + Pending + Active + Disabled(reason: Text) +} + +public type CreateInput { + id: Id + name: Text + email: Text + phone: Text? + score: Int + labels: Map +} + +public type CreateResult { + Created(user: User) + InvalidName(reason: Text) + InvalidEmail(reason: Text) +} + +public type User { + id: Id + name: Text + email: Text + phone: Text? + score: Int + labels: Map + status: UserStatus +} + +public type UserView { + id: Id + name: Text + email: Text + phone: Text + score: Int + can_sign_in: Bool +} + +public create(input: CreateInput) (result: CreateResult) { + normalized = normalize(input) + result = create_name(normalized, normalized.name) +} + +normalize(input: CreateInput) (result: CreateInput) { + result = input + result.name = text.trim(input.name) + result.email = text.lower(text.trim(input.email)) +} + +create_name(input: CreateInput, name: "") (result: CreateResult) { + result = CreateResult.InvalidName("name is required") +} + +create_name(input: CreateInput, name: other) (result: CreateResult) { + result = create_email(input, name, input.email) +} + +create_email(input: CreateInput, name: Text, email: "") (result: CreateResult) { + result = CreateResult.InvalidEmail("email is required") +} + +create_email(input: CreateInput, name: Text, email: other) (result: CreateResult) { + user = User { + id = input.id + name = name + email = email + phone = input.phone + score = input.score + labels = input.labels + status = UserStatus.Pending + } + result = CreateResult.Created(user) +} + +public activate(user: User) (result: User) { + result = user + result.status = UserStatus.Active +} + +public disable(user: User, reason: Text) (result: User) { + result = user + result.status = UserStatus.Disabled(reason) +} + +public can_sign_in(status: UserStatus.Active) (allowed: Bool) { + allowed = true +} + +public can_sign_in(status: other) (allowed: Bool) { + allowed = false +} + +phone_text(phone: Text) (result: Text) { + result = phone +} + +phone_text(phone: null) (result: Text) { + result = "Not provided" +} + +public to_view(user: User) (view: UserView) { + view = UserView { + id = user.id + name = user.name + email = user.email + phone = phone_text(user.phone) + score = user.score + can_sign_in = can_sign_in(user.status) + } +} + +public to_views(users: List) (views: List) { + views = each(to_view, users) +} + +is_active(user: User) (result: Bool) { + result = can_sign_in(user.status) +} + +public active_views(users: List) (views: List) { + active = filter(is_active, users) + views = each(to_view, active) +} + +has_id(user: User, expected: Id) (matches: Bool) { + matches = user.id == expected +} + +public find_user(users: List, id: Id) (user: User?) { + user = find(has_id, users, id) +} + +public put_label(user: User, key: Text, value: Text) (result: User) { + result = user + result.labels = put(user.labels, key, value) +} + +public label(user: User, key: Text) (value: Text?) { + value = get(user.labels, key) +} + +score_bonus(user: User, rate: Decimal) (amount: Decimal) { + amount = user.score * rate +} + +public total_score_bonus(users: List, rate: Decimal) (total: Decimal) { + total = sum(score_bonus, users, rate) +} \ No newline at end of file diff --git a/test/dever-tests/tests/core_semantics.rs b/test/dever-tests/tests/core_semantics.rs index 5897774..1d8be46 100644 --- a/test/dever-tests/tests/core_semantics.rs +++ b/test/dever-tests/tests/core_semantics.rs @@ -4,17 +4,7 @@ use support::{checked, rejected, sources}; #[test] fn full_language_contract_package_checks_with_the_official_sources() { - let prd = include_str!("../../../.trellis/tasks/09-04-dever-language-mvp/prd.md"); - let source = prd - .split_once("## Complete Package Example\n") - .unwrap() - .1 - .split_once("```dever\n") - .unwrap() - .1 - .split_once("\n```") - .unwrap() - .0; + let source = include_str!("../fixtures/core/complete_package.dever"); let mut sources = dever_core::source::SourceMap::default(); sources.add("account/user.dever", source); checked(&sources); diff --git a/test/dever-tests/tests/formatter.rs b/test/dever-tests/tests/formatter.rs index 6ee1ee2..7cd83b5 100644 --- a/test/dever-tests/tests/formatter.rs +++ b/test/dever-tests/tests/formatter.rs @@ -189,10 +189,7 @@ fn current_examples_official_packages_and_complete_contract_roundtrip() { assert_roundtrip_at(&path, source.text()); } } - let prd = include_str!("../../../.trellis/tasks/09-04-dever-language-mvp/prd.md"); - let (_, example) = prd.split_once("## Complete Package Example\n").unwrap(); - let (_, fenced) = example.split_once("```dever\n").unwrap(); - assert_roundtrip(fenced.split_once("\n```").unwrap().0); + assert_roundtrip(include_str!("../fixtures/core/complete_package.dever")); } fn source_root_relative(path: &FilePath) -> PathBuf { diff --git a/test/dever-tests/tests/syntax_and_format.rs b/test/dever-tests/tests/syntax_and_format.rs index 671fd7f..4364baf 100644 --- a/test/dever-tests/tests/syntax_and_format.rs +++ b/test/dever-tests/tests/syntax_and_format.rs @@ -47,10 +47,7 @@ fn assigned(expression: &str) -> Expression { #[test] fn parses_the_complete_package_from_the_product_contract() { - let prd = include_str!("../../../.trellis/tasks/09-04-dever-language-mvp/prd.md"); - let (_, example_section) = prd.split_once("## Complete Package Example\n").unwrap(); - let (_, fenced) = example_section.split_once("```dever\n").unwrap(); - let (source, _) = fenced.split_once("\n```").unwrap(); + let source = include_str!("../fixtures/core/complete_package.dever"); let package = parsed(source); assert_eq!( package diff --git a/test/editor-vscode/highlight.test.cjs b/test/editor-vscode/highlight.test.cjs new file mode 100644 index 0000000..a8adb05 --- /dev/null +++ b/test/editor-vscode/highlight.test.cjs @@ -0,0 +1,264 @@ +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const { createRequire } = require('node:module'); +const test = require('node:test'); + +const root = path.resolve(__dirname, '../..'); +const extension = path.join(root, 'editor/vscode'); +const extensionRequire = createRequire(path.join(extension, 'package.json')); +const textmate = extensionRequire('vscode-textmate'); +const oniguruma = extensionRequire('vscode-oniguruma'); +const cliArguments = process.argv.slice(2); +assert.equal(cliArguments.length, 2, 'pass --markdown-grammar followed by the real VS Code grammar path'); +assert.equal(cliArguments[0], '--markdown-grammar'); +const markdownPath = path.resolve(cliArguments[1]); +const manifest = JSON.parse(fs.readFileSync(path.join(extension, 'package.json'), 'utf8')); +const configuration = JSON.parse(fs.readFileSync(path.join(extension, 'language-configuration.json'), 'utf8')); + +async function loadGrammars() { + const wasm = fs.readFileSync(extensionRequire.resolve('vscode-oniguruma/release/onig.wasm')); + await oniguruma.loadWASM(wasm.buffer.slice(wasm.byteOffset, wasm.byteOffset + wasm.byteLength)); + const catalog = new Map(); + for (const contribution of manifest.contributes.grammars) { + const filename = path.join(extension, contribution.path); + catalog.set(contribution.scopeName, textmate.parseRawGrammar(fs.readFileSync(filename, 'utf8'), filename)); + } + const markdown = textmate.parseRawGrammar(fs.readFileSync(markdownPath, 'utf8'), markdownPath); + assert.equal(markdown.scopeName, 'text.html.markdown'); + catalog.set(markdown.scopeName, markdown); + const registry = new textmate.Registry({ + onigLib: Promise.resolve({ + createOnigScanner: patterns => new oniguruma.OnigScanner(patterns), + createOnigString: value => new oniguruma.OnigString(value) + }), + loadGrammar: scope => catalog.get(scope) || null, + getInjections: scope => manifest.contributes.grammars + .filter(contribution => contribution.injectTo?.includes(scope)) + .map(contribution => contribution.scopeName) + }); + return { + source: await registry.loadGrammarWithConfiguration('source.dever', 1, {}), + markdown: await registry.loadGrammarWithConfiguration('text.html.markdown', 2, { + embeddedLanguages: { 'meta.embedded.block.dever': 1 }, + tokenTypes: { 'meta.embedded.block.dever': 0 } + }) + }; +} + +const grammars = loadGrammars(); + +function tokenize(grammar, document) { + let state = textmate.INITIAL; + return document.split(/\r\n|\r|\n/).map(line => { + const encoded = grammar.tokenizeLine2(line, state); + const result = grammar.tokenizeLine(line, state); + state = result.ruleStack; + return { line, tokens: result.tokens, encoded: encoded.tokens }; + }); +} + +function tokenAt(rows, line, fragment) { + const row = rows[line]; + const offset = row.line.indexOf(fragment); + assert.ok(offset >= 0, `line ${line + 1} does not contain ${fragment}`); + const token = row.tokens.find(candidate => candidate.startIndex <= offset && candidate.endIndex > offset); + assert.ok(token, `no token for ${fragment} on line ${line + 1}`); + return token; +} + +function hasScope(rows, line, fragment, scope) { + const actual = tokenAt(rows, line, fragment).scopes; + assert.ok(actual.includes(scope), `${fragment}: expected ${scope}, received ${actual.join(' ')}`); +} + +function sourceFiles(directory, suffix) { + return fs.readdirSync(directory, { withFileTypes: true }).flatMap(entry => { + const filename = path.join(directory, entry.name); + return entry.isDirectory() ? sourceFiles(filename, suffix) : filename.endsWith(suffix) ? [filename] : []; + }); +} + +test('types, fields and named function inputs/outputs receive Dever scopes', async () => { + const rows = tokenize((await grammars).source, [ + 'type Profile {', + ' id: Int?', + ' name: Text', + '}', + 'greet(name: Text) (message: Text) {', + ' message = app.format(name)', + '}' + ].join('\n')); + hasScope(rows, 0, 'type', 'storage.type.dever'); + hasScope(rows, 0, 'Profile', 'entity.name.type.dever'); + hasScope(rows, 1, 'id', 'variable.other.member.dever'); + hasScope(rows, 1, 'Int', 'support.type.dever'); + hasScope(rows, 4, 'greet', 'entity.name.function.dever'); + hasScope(rows, 4, 'name', 'variable.other.member.dever'); + hasScope(rows, 4, 'message', 'variable.other.member.dever'); + hasScope(rows, 5, 'app', 'entity.name.namespace.dever'); + hasScope(rows, 5, 'format', 'entity.name.function.dever'); +}); + +test('API, Model, Job and external Adapter declarations are covered', async () => { + const source = (await grammars).source; + for (const method of ['get', 'post', 'put', 'delete', 'cmd', 'rest']) { + const rows = tokenize(source, `${method} profile = app.profile`); + hasScope(rows, 0, method, 'keyword.control.api.dever'); + } + const rows = tokenize(source, [ + 'public get profile = app.profile', + ' private owner user_id: user.account.model.id = dever.auth.user_id()', + 'index(user_id, created_at)', + 'sql owned_articles(id: Int) (articles: List
) {', + 'job send(message: Text) () fails app.Error {', + 'schedule send_every_minute {', + 'external npm "worker.js" {}' + ].join('\n')); + hasScope(rows, 0, 'public', 'storage.modifier.dever'); + hasScope(rows, 1, 'owner', 'storage.modifier.dever'); + hasScope(rows, 2, 'index', 'keyword.other.declaration.dever'); + hasScope(rows, 3, 'sql', 'keyword.other.declaration.dever'); + hasScope(rows, 4, 'job', 'storage.modifier.dever'); + hasScope(rows, 4, 'fails', 'storage.modifier.dever'); + hasScope(rows, 5, 'schedule', 'keyword.other.declaration.dever'); + hasScope(rows, 6, 'npm', 'keyword.other.external.dever'); +}); + +test('hash comments, quoted text and escapes do not leak into subsequent lines', async () => { + const rows = tokenize((await grammars).source, [ + '# type Fake and return', + String.raw`message = "中文 # and type \n \u{4E2D} \""`, + String.raw`invalid = "\q"`, + 'broken = "unfinished', + 'type Next { value: Text }' + ].join('\n')); + hasScope(rows, 0, 'type', 'comment.line.number-sign.dever'); + hasScope(rows, 1, '#', 'string.quoted.double.dever'); + hasScope(rows, 1, '\\n', 'constant.character.escape.dever'); + hasScope(rows, 1, '\\u{4E2D}', 'constant.character.escape.dever'); + hasScope(rows, 2, '\\q', 'invalid.illegal.escape.dever'); + hasScope(rows, 4, 'type', 'storage.type.dever'); + assert.ok(!tokenAt(rows, 4, 'type').scopes.includes('string.quoted.double.dever')); +}); + +test('integer division is an operator, not a JavaScript line comment', async () => { + const rows = tokenize((await grammars).source, 'count = 12 // 3\namount = 1.25e-2\nvalid = true and not false'); + hasScope(rows, 0, '//', 'keyword.operator.dever'); + hasScope(rows, 0, '3', 'constant.numeric.dever'); + assert.ok(!tokenAt(rows, 0, '3').scopes.some(scope => scope.startsWith('comment.'))); + hasScope(rows, 1, '1.25e-2', 'constant.numeric.dever'); + hasScope(rows, 2, 'true', 'constant.language.dever'); + hasScope(rows, 2, 'and', 'keyword.operator.logical.dever'); +}); + +test('excluded control-flow syntax is not presented as a valid function', async () => { + const rows = tokenize((await grammars).source, 'if(value)\nreturn value\nimport other\npackage main'); + for (const [line, keyword] of ['if', 'return', 'import', 'package'].entries()) { + hasScope(rows, line, keyword, 'invalid.illegal.keyword.dever'); + } +}); + +test('Markdown fences reuse source.dever while prose keeps Markdown scopes', async () => { + for (const marker of ['```', '~~~']) { + for (const language of ['dever', 'typescript dever']) { + const rows = tokenize((await grammars).markdown, [ + '# 文档', '', '## 类型', `${marker}${language}`, + 'type Profile { name: Text }', marker, '', '正文 type Profile' + ].join('\n')); + hasScope(rows, 4, 'type', 'storage.type.dever'); + hasScope(rows, 4, 'Text', 'support.type.dever'); + hasScope(rows, 4, 'Profile', 'meta.embedded.block.dever'); + assert.ok(!tokenAt(rows, 7, 'type').scopes.includes('source.dever')); + } + } +}); + +test('embedded tokens carry the Dever language ID and are not string tokens', async () => { + const rows = tokenize((await grammars).markdown, '```dever\ntype Profile {}\n```'); + const metadata = rows[1].encoded[1]; + assert.equal(metadata & 0xff, 1); + assert.equal((metadata >>> 8) & 3, 0); +}); + +test('fence closing honors its character and minimum opening length', async () => { + const rows = tokenize((await grammars).markdown, [ + '````dever', 'type First {}', '```', 'type Second {}', + '~~~~', 'type Third {}', '`````', '正文 type Outside' + ].join('\n')); + for (const line of [1, 3, 5]) hasScope(rows, line, 'type', 'storage.type.dever'); + assert.ok(!tokenAt(rows, 7, 'type').scopes.includes('source.dever')); + const waves = tokenize((await grammars).markdown, '~~~dever\ntype Inside {}\n~~~~\n正文 type Outside'); + assert.ok(!tokenAt(waves, 3, 'type').scopes.includes('source.dever')); +}); + +test('valid indentation and CRLF work without taking over other language fences', async () => { + const rows = tokenize((await grammars).markdown, ' ```dever\r\ntype Profile {}\r\n ```\r\n正文'); + hasScope(rows, 1, 'type', 'storage.type.dever'); + for (const language of ['typescript', 'javascript', 'dever extra', 'typescript dever']) { + const other = tokenize((await grammars).markdown, `\`\`\`${language}\ntype Profile {}\n\`\`\``); + assert.ok(!tokenAt(other, 1, 'type').scopes.includes('source.dever'), language); + } +}); + +test('quotes, lists, showcase fences, indented code and comments retain Markdown scopes', async () => { + for (const [document, line] of [ + ['> ```dever\n> type Quoted {}\n> ```', 1], + ['- 示例\n\n ```dever\n type Nested {}\n ```', 3], + ['````markdown\n```dever\ntype Showcase {}\n```\n````', 2], + [' ```dever\n type Indented {}\n ```', 1], + ['', 2] + ]) { + const rows = tokenize((await grammars).markdown, document); + assert.ok(!tokenAt(rows, line, 'type').scopes.includes('source.dever'), document); + } +}); + +test('language configuration uses Dever comments, pairs and indentation', () => { + assert.equal(configuration.comments.lineComment, '#'); + assert.equal(configuration.comments.blockComment, undefined); + assert.deepEqual(configuration.brackets, [['{', '}'], ['[', ']'], ['(', ')']]); + const increase = new RegExp(configuration.indentationRules.increaseIndentPattern); + const decrease = new RegExp(configuration.indentationRules.decreaseIndentPattern); + for (const line of ['greet(name: Text) (message: Text) {', ' values = [', 'type Profile { # 字段']) { + assert.ok(increase.test(line), line); + } + for (const line of ['# example {', 'message = "literal {"', 'message = "value" # {']) { + assert.ok(!increase.test(line), line); + } + assert.ok(decrease.test(' }')); + assert.ok(decrease.test(' ]')); + assert.ok(configuration.autoClosingPairs.every(pair => pair.notIn.includes('string') && pair.notIn.includes('comment'))); + assert.deepEqual(manifest.contributes.languages[0].extensions, ['.dever']); + const injection = manifest.contributes.grammars.find(contribution => contribution.injectTo?.includes('text.html.markdown')); + assert.deepEqual(injection.embeddedLanguages, { 'meta.embedded.block.dever': 'dever' }); + assert.deepEqual(injection.tokenTypes, { 'meta.embedded.block.dever': 'other' }); + assert.equal(manifest.main, undefined); + assert.equal(manifest.dependencies, undefined); +}); + +test('maintained plain and Markdown CMS files tokenize without illegal tokens', async () => { + const loaded = await grammars; + for (const [directory, suffix, grammar] of [ + ['examples/cms/dever', '.dever', loaded.source], + ['examples/cms/md', '.dever.md', loaded.markdown] + ]) { + const files = sourceFiles(path.join(root, directory), suffix); + assert.ok(files.length > 0, directory); + let highlighted = 0; + for (const filename of files) { + const rows = tokenize(grammar, fs.readFileSync(filename, 'utf8')); + let fileHighlighted = 0; + for (const row of rows) { + for (const token of row.tokens) { + assert.ok(!token.scopes.some(scope => scope.startsWith('invalid.illegal.')), `${filename}: ${row.line}`); + if (token.scopes.includes('source.dever')) fileHighlighted += 1; + } + } + assert.ok(fileHighlighted > 0, `${filename} must actually enter the Dever grammar`); + highlighted += fileHighlighted; + } + assert.ok(highlighted > files.length, `${directory} must actually enter the Dever grammar`); + process.stdout.write(`CMS ${directory}: ${files.length} files, ${highlighted} Dever tokens\n`); + } +}); diff --git a/test/onboarding/test_installer.py b/test/onboarding/test_installer.py index 390d27a..18b71e1 100644 --- a/test/onboarding/test_installer.py +++ b/test/onboarding/test_installer.py @@ -88,6 +88,15 @@ class InstallerTests(unittest.TestCase): def create_assets(self, output): return assets.create(self.release, output, Path("/usr/bin/zstd")) + def release_record(self, directory, version="1.2.3"): + return { + "tag_name": f"v{version}", "draft": False, "prerelease": False, + "assets": [{"name": path.name, "size": path.stat().st_size, + "browser_download_url": + f"https://git.dever.cc/shemic/dever/releases/download/v{version}/{path.name}"} + for path in sorted(directory.iterdir())], + } + def archive_payloads(self, path): contents = subprocess.run(["/usr/bin/zstd", "-q", "-d", "-c", str(path)], env={}, capture_output=True, check=True, timeout=15).stdout @@ -212,10 +221,14 @@ class InstallerTests(unittest.TestCase): assets_path = self.root / "assets" self.create_assets(assets_path) calls = [] + record = self.release_record(assets_path) + with mock.patch.object(installer, "download", return_value=io.BytesIO(json.dumps(record).encode())): + version, attachments = installer.resolve_release("latest") + self.assertEqual(version, "1.2.3") def download(address): self.assertTrue(address.startswith( - f"https://git.dever.cc/shemic/dever/dist/1.2.3/dever-{self.platform}.")) + f"https://git.dever.cc/shemic/dever/releases/download/v1.2.3/dever-{self.platform}.")) return (assets_path / address.rsplit("/", 1)[-1]).open("rb") def extract(command, **kwargs): @@ -233,8 +246,8 @@ class InstallerTests(unittest.TestCase): with mock.patch.object(installer, "download", side_effect=download), \ mock.patch.object(installer.subprocess, "run", side_effect=extract): - installer.payload(self.directory("network"), None, "1.2.3", self.platform, - self.catalog, self.public) + installer.payload(self.directory("network"), None, self.platform, + self.catalog, self.public, attachments) self.assertEqual(len(calls), 1) self.assertEqual(list(self.root.glob(".extract-*")), []) @@ -244,7 +257,7 @@ class InstallerTests(unittest.TestCase): with mock.patch.object(installer, "download", side_effect=download), \ mock.patch.object(installer.subprocess, "run") as execute, \ self.assertRaises(ValueError): - installer.payload(self.release, None, "1.2.3", self.platform, self.catalog, self.public) + installer.payload(self.release, None, self.platform, self.catalog, self.public, attachments) execute.assert_not_called() def test_download_archive_is_bounded(self): @@ -255,19 +268,19 @@ class InstallerTests(unittest.TestCase): def test_local_payload_rejects_symlink_and_source_directory(self): copied = self.directory("copied") - installer.payload(copied, self.release, "1.2.3", self.platform, self.catalog) + installer.payload(copied, self.release, self.platform, self.catalog) self.assertEqual((copied / "dever-core").read_bytes(), self.payloads["dever-core"]) core = self.release / "dever-core" core.unlink() core.symlink_to(self.public) with self.assertRaisesRegex(ValueError, "符号链接"): - installer.payload(self.directory("symlink"), self.release, "1.2.3", self.platform, self.catalog) + installer.payload(self.directory("symlink"), self.release, self.platform, self.catalog) with self.assertRaisesRegex(ValueError, "symlinks"): self.create_assets(self.root / "invalid-assets") core.unlink() core.mkdir() with self.assertRaisesRegex(ValueError, "类型"): - installer.payload(self.directory("directory"), self.release, "1.2.3", self.platform, self.catalog) + installer.payload(self.directory("directory"), self.release, self.platform, self.catalog) def test_image_install_authenticates_before_mock_bootstrap_and_cleans_owned_staging(self): image = self.directory("image") @@ -302,27 +315,83 @@ class InstallerTests(unittest.TestCase): self.assertEqual(len(calls), 1) self.assertEqual(list(image.iterdir()), []) - def test_metadata_uses_latest_or_exact_directory_and_never_a_github_fallback(self): - for version in ("latest", "1.2.3"): - destination = self.directory(version) + def test_metadata_pins_latest_or_exact_release_before_downloading_matching_assets(self): + assets_path = self.root / "assets" + self.create_assets(assets_path) + record = self.release_record(assets_path) + for requested, endpoint in (("latest", "latest"), ("1.2.3", "tags/v1.2.3")): + destination = self.directory(requested) addresses = [] def download(address): addresses.append(address) - return io.BytesIO(b"metadata") + if address == f"{installer.RELEASES}/{endpoint}": + return io.BytesIO(json.dumps(record).encode()) + return (assets_path / address.rsplit("/", 1)[-1]).open("rb") with mock.patch.object(installer, "download", side_effect=download): - installer.metadata(destination, None, version, self.platform) - self.assertEqual(addresses, [ - f"https://git.dever.cc/shemic/dever/dist/{version}/dever-{self.platform}.{suffix}" + selected, attachments = installer.resolve_release(requested) + installer.metadata(destination, None, attachments, self.platform) + authenticated, _, _ = installer.authenticate(destination, self.public, self.scratch, + self.platform, selected) + self.assertEqual(authenticated, "1.2.3") + self.assertEqual(addresses, [f"{installer.RELEASES}/{endpoint}"] + [ + f"https://git.dever.cc/shemic/dever/releases/download/v1.2.3/dever-{self.platform}.{suffix}" for suffix in ("manifest.json", "manifest.sig") ]) + def test_release_metadata_rejects_unpublished_ambiguous_and_foreign_assets(self): + directory = self.root / "assets" + self.create_assets(directory) + valid = self.release_record(directory) + mutations = [ + lambda record: record.update(draft=True), + lambda record: record.update(prerelease=True), + lambda record: record.update(tag_name="v01.2.3"), + lambda record: record.update(tag_name="v1.2.4"), + lambda record: record["assets"].append(record["assets"][0]), + lambda record: record["assets"][0].update(size=True), + lambda record: record["assets"][0].update(browser_download_url="https://evil.example/asset"), + lambda record: record.update(assets=[]), + lambda record: record.update(assets=[record["assets"][0]] * 513), + ] + for mutate in mutations: + record = json.loads(json.dumps(valid)) + mutate(record) + with self.subTest(record=record["tag_name"]), \ + mock.patch.object(installer, "download", return_value=io.BytesIO(json.dumps(record).encode())), \ + self.assertRaises(ValueError): + installer.resolve_release("1.2.3") + with mock.patch.object(installer, "MAX_METADATA", 10), \ + mock.patch.object(installer, "download", return_value=io.BytesIO(b" " * 11)), \ + self.assertRaisesRegex(ValueError, "大小限制"): + installer.resolve_release("latest") + + def test_latest_tag_must_match_signed_manifest_and_required_assets_must_exist(self): + directory = self.root / "assets" + self.create_assets(directory) + record = self.release_record(directory, "1.2.4") + with mock.patch.object(installer, "download", return_value=io.BytesIO(json.dumps(record).encode())): + selected, attachments = installer.resolve_release("latest") + with self.assertRaisesRegex(ValueError, "版本与请求不匹配"): + installer.authenticate(self.release, self.public, self.scratch, self.platform, selected) + with self.assertRaisesRegex(ValueError, "缺少附件"): + installer.asset(attachments, self.platform, "missing.tar.zst") + with self.assertRaisesRegex(ValueError, "大小限制"): + installer.asset(attachments, self.platform, "manifest.json", 1) + + def test_metadata_rejects_truncated_api_attachment(self): + name = f"dever-{self.platform}.manifest.json" + attachments = {name: {"address": "https://git.dever.cc/asset", "bytes": 20}} + with mock.patch.object(installer, "download", return_value=io.BytesIO(b"short")), \ + self.assertRaisesRegex(ValueError, "长度不匹配"): + installer.metadata(self.directory("truncated"), None, attachments, self.platform) + def test_redirects_remain_on_the_official_https_site(self): handler = installer.OfficialRedirect() - current = "https://git.dever.cc/shemic/dever/dist/latest/a" + current = "https://git.dever.cc/shemic/dever/releases/download/v1.2.3/a" request = installer.urllib.request.Request(current) - allowed = "https://git.dever.cc/shemic/dever/dist/1.2.3/a" + allowed = "https://git.dever.cc/attachments/fixture" redirected = handler.redirect_request(request, None, 302, "Found", {}, allowed) self.assertEqual(redirected.full_url, allowed) for address in ( diff --git a/test/onboarding/verify_prepared_release.py b/test/onboarding/verify_prepared_release.py index 25a5d11..60785de 100644 --- a/test/onboarding/verify_prepared_release.py +++ b/test/onboarding/verify_prepared_release.py @@ -3,6 +3,7 @@ import argparse import hashlib +import io import json import os from pathlib import Path @@ -198,18 +199,20 @@ def install_assets(assets, image, manifest): # Only transport is local: signature verification, full tar extraction and # the final bootstrap executable are the real first-install implementation. installer = load_installer() - stem = f"dever-{manifest['platform']}" - base = installer.RELEASES - routes = { - f"{base}/latest/{stem}.manifest.json": assets / f"{stem}.manifest.json", - f"{base}/latest/{stem}.manifest.sig": assets / f"{stem}.manifest.sig", - f"{base}/{manifest['version']}/{stem}.tar.zst": assets / f"{stem}.tar.zst", + base = f"https://git.dever.cc/shemic/dever/releases/download/v{manifest['version']}" + routes = {f"{base}/{path.name}": path for path in assets.iterdir() if path.is_file()} + record = { + "tag_name": f"v{manifest['version']}", "draft": False, "prerelease": False, + "assets": [{"name": path.name, "size": path.stat().st_size, + "browser_download_url": address} for address, path in routes.items()], } - for artifact in manifest["artifacts"]: - if artifact["path"] == "bootstrap/dever" or artifact["path"].startswith("bootstrap/lib/"): - name = f"{stem}.blob-{artifact['sha256']}" - routes[f"{base}/{manifest['version']}/{name}"] = assets / name - installer.download = lambda address: routes[address].open("rb") + + def download(address): + if address == f"{installer.RELEASES}/latest": + return io.BytesIO(json.dumps(record).encode()) + return routes[address].open("rb") + + installer.download = download installer.install(argparse.Namespace( version="latest", release=None, system_root=image, no_start=True, trusted_key=WORKSPACE / "skills/assets/release.pub",