Release 1.0.0-beta.24 package manifest discipline
This commit is contained in:
parent
05ff5be5c5
commit
b241a8a812
@ -0,0 +1,79 @@
|
||||
# 1.0.0-beta.24 Package Manifest Identity And Dependency Discipline
|
||||
|
||||
## Scope
|
||||
|
||||
`1.0.0-beta.24` is a package/workspace discipline hardening slice for local
|
||||
manifest diagnostics. It tightens how package manifest identity and local
|
||||
dependency tables are reported when users write ambiguous or invalid manifest
|
||||
keys.
|
||||
|
||||
This release changes diagnostics only. It does not change the Slovo source
|
||||
language, typed core, runtime behavior, standard-library helper surface,
|
||||
compiler-known runtime names, package graph semantics, ABI/layout policy, or
|
||||
artifact/Markdown schema stability guarantees.
|
||||
|
||||
## Contract
|
||||
|
||||
The beta package model remains a closed local workspace model:
|
||||
|
||||
- package manifests declare `[package]` identity metadata and optional
|
||||
`[dependencies]` local path records
|
||||
- dependency keys name local packages and must match the target package name
|
||||
- dependency paths remain local path records under the existing workspace and
|
||||
package boundary checks
|
||||
|
||||
The beta24 diagnostic hardening makes these manifest errors explicit:
|
||||
|
||||
- duplicate keys in package manifests report `PackageManifestInvalid`
|
||||
- invalid dependency keys report `InvalidPackageDependencyName`
|
||||
- duplicate dependency keys report `DuplicatePackageDependencyName`
|
||||
|
||||
These diagnostics are part of the beta package/workspace discipline surface.
|
||||
They do not promote a package manager, resolver, lockfile, registry, publish
|
||||
flow, or stable package ABI/layout.
|
||||
|
||||
## Non-Scope
|
||||
|
||||
This scope does not add:
|
||||
|
||||
- remote registry behavior
|
||||
- lockfiles
|
||||
- semantic-version solving
|
||||
- package publishing
|
||||
- optional, dev, target, or feature-gated dependencies
|
||||
- build scripts or package archives
|
||||
- stable package ABI/layout
|
||||
- stable package manager behavior
|
||||
- source-language syntax or semantics
|
||||
- runtime behavior or runtime C capabilities
|
||||
- standard-library helpers or stdlib behavior
|
||||
- compiler-known `std.*` runtime names
|
||||
- stable artifact-manifest or Markdown schema guarantees
|
||||
- performance claims
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `docs/language/PACKAGES.md` documents duplicate package-manifest keys,
|
||||
invalid dependency keys, and duplicate dependency keys as explicit beta
|
||||
diagnostics.
|
||||
- Language and compiler release notes describe beta24 as package manifest
|
||||
identity/dependency diagnostic hardening only.
|
||||
- Language and compiler roadmaps record beta24 as a local package/workspace
|
||||
diagnostics slice with all registry, lockfile, semver, publishing,
|
||||
optional/dev/target dependency, ABI/layout, language, runtime, and stdlib
|
||||
work deferred.
|
||||
- README and the post-beta roadmap identify `1.0.0-beta.24` as the current
|
||||
package/workspace discipline hardening slice.
|
||||
- Glagol is versioned as `1.0.0-beta.24`.
|
||||
- `compiler/tests/package_workspace_discipline_beta24.rs` covers the focused
|
||||
package manifest/dependency diagnostics and a positive local dependency
|
||||
workspace.
|
||||
- `scripts/release-gate.sh` runs the focused beta24 test.
|
||||
|
||||
## Suggested Gates
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
cargo fmt --check
|
||||
cargo test --test package_workspace_discipline_beta24
|
||||
```
|
||||
66
.llm/reviews/BETA_24_RELEASE_REVIEW.md
Normal file
66
.llm/reviews/BETA_24_RELEASE_REVIEW.md
Normal file
@ -0,0 +1,66 @@
|
||||
# Beta24 Release Review
|
||||
|
||||
Verdict: PASS.
|
||||
|
||||
## Findings
|
||||
|
||||
No blocking or non-blocking findings in the reviewed scope.
|
||||
|
||||
## Scope Reviewed
|
||||
|
||||
- `compiler/src/project.rs` package manifest diagnostics.
|
||||
- `compiler/tests/package_workspace_discipline_beta24.rs`.
|
||||
- `scripts/release-gate.sh` beta24 focused gate entry.
|
||||
- `compiler/Cargo.toml` and `compiler/Cargo.lock` version bump.
|
||||
- `.llm/BETA_24_PACKAGE_MANIFEST_IDENTITY_AND_DEPENDENCY_DISCIPLINE.md`.
|
||||
- README, language package/diagnostic/release/roadmap docs, compiler release/roadmap docs, and post-beta roadmap updates.
|
||||
|
||||
## Acceptance Checklist
|
||||
|
||||
- PASS: Duplicate package manifest keys now use package-scoped diagnostics through `set_manifest_key(..., "PackageManifestInvalid", "package")` for package identity keys. See `compiler/src/project.rs:1505` through `compiler/src/project.rs:1545` and `compiler/src/project.rs:1752` through `compiler/src/project.rs:1771`.
|
||||
- PASS: Invalid dependency keys are rejected before graph validation with `InvalidPackageDependencyName`. See `compiler/src/project.rs:1556` through `compiler/src/project.rs:1572`.
|
||||
- PASS: Duplicate dependency keys are rejected before graph validation with `DuplicatePackageDependencyName`, and invalid/duplicate dependency records are not added to the dependency graph. See `compiler/src/project.rs:1573` through `compiler/src/project.rs:1593`.
|
||||
- PASS: Existing local-path-only dependency parsing and later dependency key/name matching remain in place. See `compiler/src/project.rs:1594` through `compiler/src/project.rs:1601`, `compiler/src/project.rs:1743` through `compiler/src/project.rs:1749`, and `compiler/src/project.rs:2970` through `compiler/src/project.rs:3005`.
|
||||
- PASS: Focused tests cover duplicate package keys, invalid dependency keys, duplicate dependency keys, and a clean local dependency workspace. See `compiler/tests/package_workspace_discipline_beta24.rs:11` through `compiler/tests/package_workspace_discipline_beta24.rs:109`.
|
||||
- PASS: `scripts/release-gate.sh` runs the beta24 focused test before full `cargo test`. See `scripts/release-gate.sh:68` through `scripts/release-gate.sh:82`.
|
||||
- PASS: The compiler package version is aligned to `1.0.0-beta.24` in both Cargo files. See `compiler/Cargo.toml:3` and `compiler/Cargo.lock:7`.
|
||||
- PASS: The beta24 contract defines diagnostics-only scope, explicit non-scope, acceptance criteria, and focused gates. See `.llm/BETA_24_PACKAGE_MANIFEST_IDENTITY_AND_DEPENDENCY_DISCIPLINE.md:5` through `.llm/BETA_24_PACKAGE_MANIFEST_IDENTITY_AND_DEPENDENCY_DISCIPLINE.md:79`.
|
||||
- PASS: README identifies `1.0.0-beta.24` as current and describes the package manifest/dependency diagnostic hardening scope without claiming package-manager, runtime, language, or stdlib changes. See `README.md:9` and `README.md:27` through `README.md:50`.
|
||||
- PASS: `docs/language/PACKAGES.md` documents duplicate package manifest keys, invalid dependency keys, and duplicate dependency keys as beta package/workspace diagnostics. See `docs/language/PACKAGES.md:59` through `docs/language/PACKAGES.md:73` and `docs/language/PACKAGES.md:111` through `docs/language/PACKAGES.md:130`.
|
||||
- PASS: `docs/language/DIAGNOSTICS.md` includes the new package/workspace diagnostic codes in the project/workspace catalog. See `docs/language/DIAGNOSTICS.md:240` through `docs/language/DIAGNOSTICS.md:279`.
|
||||
- PASS: Language and compiler release notes describe beta24 as package manifest identity/dependency diagnostic hardening only. See `docs/language/RELEASE_NOTES.md:44` through `docs/language/RELEASE_NOTES.md:68` and `docs/compiler/RELEASE_NOTES.md:15` through `docs/compiler/RELEASE_NOTES.md:42`.
|
||||
- PASS: Language/compiler roadmaps and post-beta roadmap mark beta24 as the current local package/workspace diagnostics slice with registry, lockfile, semver, publishing, optional/dev/target dependencies, ABI/layout, language, runtime, and stdlib work deferred. See `docs/language/ROADMAP.md:11` through `docs/language/ROADMAP.md:33`, `docs/compiler/ROADMAP.md:24` through `docs/compiler/ROADMAP.md:38`, `docs/compiler/ROADMAP.md:722` through `docs/compiler/ROADMAP.md:728`, and `docs/POST_BETA_ROADMAP.md:185` through `docs/POST_BETA_ROADMAP.md:191`.
|
||||
|
||||
## Verification Commands
|
||||
|
||||
Ran:
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
cargo fmt --check
|
||||
cargo test --test package_workspace_discipline_beta24
|
||||
cargo test --test project_mode workspace_package_boundaries_are_diagnostics
|
||||
cargo test --test project_mode
|
||||
rg -n "beta\\.23|beta23|beta\\.24|beta24|1\\.0\\.0-beta\\.2[0-9]|current|Release state|Last updated" README.md docs/language/PACKAGES.md docs/language/DIAGNOSTICS.md docs/language/RELEASE_NOTES.md docs/language/ROADMAP.md docs/compiler/RELEASE_NOTES.md docs/compiler/ROADMAP.md docs/POST_BETA_ROADMAP.md .llm/BETA_24_PACKAGE_MANIFEST_IDENTITY_AND_DEPENDENCY_DISCIPLINE.md compiler/Cargo.toml compiler/Cargo.lock scripts/release-gate.sh
|
||||
```
|
||||
|
||||
Result: all executed checks passed. The focused beta24 test reported 4 passed tests. The full `project_mode` suite reported 36 passed tests.
|
||||
|
||||
## Final Gate Disposition
|
||||
|
||||
After this review, the controller ran the full release gate:
|
||||
|
||||
```bash
|
||||
./scripts/release-gate.sh
|
||||
```
|
||||
|
||||
Result: PASS. The gate completed docs/catalog checks, focused beta13-beta24
|
||||
tests, full `cargo test`, ignored promotion smoke, ignored binary smoke, and
|
||||
ignored LLVM smoke.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- No release-blocking residual risks remain. The release gate regenerated and
|
||||
checked the standard-library API catalog; publication PDFs were not
|
||||
regenerated because this slice does not touch paper sources, and the gate
|
||||
verified that the required PDF artifacts are present.
|
||||
28
README.md
28
README.md
@ -6,7 +6,7 @@ This repository is the canonical public monorepo for the language design,
|
||||
standard library source, compiler, runtime, examples, benchmarks, and technical
|
||||
documents.
|
||||
|
||||
Current release: `1.0.0-beta.23`.
|
||||
Current release: `1.0.0-beta.24`.
|
||||
|
||||
## Repository Layout
|
||||
|
||||
@ -24,7 +24,7 @@ scripts/ local release and document tooling
|
||||
|
||||
## Beta Scope
|
||||
|
||||
`1.0.0-beta.23` keeps the `1.0.0-beta` language baseline, includes the
|
||||
`1.0.0-beta.24` keeps the `1.0.0-beta` language baseline, includes the
|
||||
`1.0.0-beta.1` tooling/install hardening slice, the `1.0.0-beta.2`
|
||||
runtime/resource foundation bundle, the `1.0.0-beta.3` standard-library
|
||||
stabilization bundle, the `1.0.0-beta.4` language-usability diagnostics
|
||||
@ -46,7 +46,9 @@ the `1.0.0-beta.17` JSON primitive scalar parsing foundation, the
|
||||
`1.0.0-beta.21` JSON document scalar parsing foundation, plus the
|
||||
`1.0.0-beta.22` run manifest and execution report hardening slice, and the
|
||||
`1.0.0-beta.23` standard-library stability tier ledger and catalog alignment
|
||||
slice.
|
||||
slice, and the `1.0.0-beta.24` package manifest identity and local dependency
|
||||
diagnostic hardening slice.
|
||||
|
||||
The language baseline supports practical local command-line, file, and
|
||||
loopback-network programs with:
|
||||
|
||||
@ -196,6 +198,14 @@ schema, stable Markdown schema, stable ABI/layout, or stable stdlib/API freeze
|
||||
changes. The generated catalog and release gate now expose and check tier
|
||||
metadata.
|
||||
|
||||
The `1.0.0-beta.24` package manifest identity and local dependency discipline
|
||||
slice tightens local manifest diagnostics only: duplicate package manifest
|
||||
keys, invalid dependency keys, and duplicate dependency keys are explicit beta
|
||||
package/workspace diagnostics. It does not add remote registries, lockfiles,
|
||||
semantic-version solving, package publishing, optional/dev/target
|
||||
dependencies, stable package ABI/layout, source-language changes, runtime
|
||||
changes, or standard-library changes.
|
||||
|
||||
Still deferred before stable: executable generics, generic aliases, maps/sets,
|
||||
broad package registry semantics, stable artifact-manifest schema, stable
|
||||
Markdown schema, stable stdlib/API compatibility freeze, DNS/TLS/async
|
||||
@ -330,6 +340,18 @@ package/dependency summary, new workspace templates declare
|
||||
local-package rules. Remote registries, lockfiles, semantic-version solving,
|
||||
package publishing, and stable package ABI/layout remain deferred.
|
||||
|
||||
## 1.0.0-beta.24 Package Manifest Identity And Dependency Discipline
|
||||
|
||||
The `1.0.0-beta.24` release keeps the local package model closed and local. It
|
||||
hardens diagnostics for manifest identity/dependency mistakes only: duplicate
|
||||
package manifest keys, invalid dependency keys, and duplicate dependency keys
|
||||
are reported explicitly.
|
||||
|
||||
This scope does not add a remote registry, lockfile, semantic-version solver,
|
||||
package publishing flow, optional/dev/target dependencies, stable package
|
||||
ABI/layout, source-language behavior, runtime behavior, or standard-library
|
||||
behavior.
|
||||
|
||||
## 1.0.0-beta.6 Networking Foundation
|
||||
|
||||
The `1.0.0-beta.6` release adds a narrow blocking loopback TCP foundation:
|
||||
|
||||
2
compiler/Cargo.lock
generated
2
compiler/Cargo.lock
generated
@ -4,4 +4,4 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "glagol"
|
||||
version = "1.0.0-beta.23"
|
||||
version = "1.0.0-beta.24"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "glagol"
|
||||
version = "1.0.0-beta.23"
|
||||
version = "1.0.0-beta.24"
|
||||
edition = "2021"
|
||||
description = "Glagol, the first compiler for the Slovo language"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
@ -1124,7 +1124,16 @@ fn parse_manifest(path: PathBuf, source: String) -> Result<Manifest, Vec<Diagnos
|
||||
};
|
||||
|
||||
match key {
|
||||
"name" => set_manifest_key(&file, &mut errors, &mut name, parsed, line.span, "name"),
|
||||
"name" => set_manifest_key(
|
||||
&file,
|
||||
&mut errors,
|
||||
&mut name,
|
||||
parsed,
|
||||
line.span,
|
||||
"name",
|
||||
"ProjectManifestInvalid",
|
||||
"project",
|
||||
),
|
||||
"source_root" => set_manifest_key(
|
||||
&file,
|
||||
&mut errors,
|
||||
@ -1132,8 +1141,19 @@ fn parse_manifest(path: PathBuf, source: String) -> Result<Manifest, Vec<Diagnos
|
||||
parsed,
|
||||
line.span,
|
||||
"source_root",
|
||||
"ProjectManifestInvalid",
|
||||
"project",
|
||||
),
|
||||
"entry" => set_manifest_key(
|
||||
&file,
|
||||
&mut errors,
|
||||
&mut entry,
|
||||
parsed,
|
||||
line.span,
|
||||
"entry",
|
||||
"ProjectManifestInvalid",
|
||||
"project",
|
||||
),
|
||||
"entry" => set_manifest_key(&file, &mut errors, &mut entry, parsed, line.span, "entry"),
|
||||
_ => errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
@ -1412,6 +1432,7 @@ fn parse_package_manifest(
|
||||
let mut source_root = None::<String>;
|
||||
let mut entry = None::<String>;
|
||||
let mut dependencies = Vec::new();
|
||||
let mut dependency_keys = BTreeSet::<String>::new();
|
||||
|
||||
for line in manifest_lines(&source) {
|
||||
let trimmed = line.text.trim();
|
||||
@ -1489,6 +1510,8 @@ fn parse_package_manifest(
|
||||
parsed,
|
||||
line.span,
|
||||
"name",
|
||||
"PackageManifestInvalid",
|
||||
"package",
|
||||
),
|
||||
"version" => set_manifest_key(
|
||||
&file,
|
||||
@ -1497,6 +1520,8 @@ fn parse_package_manifest(
|
||||
parsed,
|
||||
line.span,
|
||||
"version",
|
||||
"PackageManifestInvalid",
|
||||
"package",
|
||||
),
|
||||
"source_root" => set_manifest_key(
|
||||
&file,
|
||||
@ -1505,6 +1530,8 @@ fn parse_package_manifest(
|
||||
parsed,
|
||||
line.span,
|
||||
"source_root",
|
||||
"PackageManifestInvalid",
|
||||
"package",
|
||||
),
|
||||
"entry" => set_manifest_key(
|
||||
&file,
|
||||
@ -1513,6 +1540,8 @@ fn parse_package_manifest(
|
||||
parsed,
|
||||
line.span,
|
||||
"entry",
|
||||
"PackageManifestInvalid",
|
||||
"package",
|
||||
),
|
||||
other => errors.push(
|
||||
Diagnostic::new(
|
||||
@ -1524,12 +1553,44 @@ fn parse_package_manifest(
|
||||
),
|
||||
}
|
||||
}
|
||||
"dependencies" => match parse_dependency_path(value) {
|
||||
Some(path) => dependencies.push(PackageDependency {
|
||||
"dependencies" => {
|
||||
let valid_key = if is_project_name(key) {
|
||||
true
|
||||
} else {
|
||||
errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
"InvalidPackageDependencyName",
|
||||
format!(
|
||||
"package dependency name `{}` must start with `a-z` and contain only `a-z`, `0-9`, and `-`",
|
||||
key
|
||||
),
|
||||
)
|
||||
.with_span(line.span),
|
||||
);
|
||||
false
|
||||
};
|
||||
let unique_key = if dependency_keys.insert(key.to_string()) {
|
||||
true
|
||||
} else {
|
||||
errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
"DuplicatePackageDependencyName",
|
||||
format!("duplicate package dependency name `{}`", key),
|
||||
)
|
||||
.with_span(line.span),
|
||||
);
|
||||
false
|
||||
};
|
||||
|
||||
match parse_dependency_path(value) {
|
||||
Some(path) if valid_key && unique_key => dependencies.push(PackageDependency {
|
||||
key: key.to_string(),
|
||||
path,
|
||||
span: line.span,
|
||||
}),
|
||||
Some(_) => {}
|
||||
None => errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
@ -1538,7 +1599,8 @@ fn parse_package_manifest(
|
||||
)
|
||||
.with_span(line.span),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
"" | "project" => errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
@ -1694,13 +1756,15 @@ fn set_manifest_key(
|
||||
value: String,
|
||||
span: Span,
|
||||
key: &str,
|
||||
code: &'static str,
|
||||
manifest_kind: &str,
|
||||
) {
|
||||
if slot.replace(value).is_some() {
|
||||
errors.push(
|
||||
Diagnostic::new(
|
||||
file,
|
||||
"ProjectManifestInvalid",
|
||||
format!("duplicate project manifest key `{}`", key),
|
||||
code,
|
||||
format!("duplicate {} manifest key `{}`", manifest_kind, key),
|
||||
)
|
||||
.with_span(span),
|
||||
);
|
||||
|
||||
229
compiler/tests/package_workspace_discipline_beta24.rs
Normal file
229
compiler/tests/package_workspace_discipline_beta24.rs
Normal file
@ -0,0 +1,229 @@
|
||||
use std::{
|
||||
fs,
|
||||
path::PathBuf,
|
||||
process::{Command, Output},
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
static NEXT_WORKSPACE_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[test]
|
||||
fn duplicate_package_keys_report_package_manifest_invalid() {
|
||||
let workspace = write_workspace(
|
||||
"duplicate-package-key",
|
||||
"[workspace]\nmembers = [\"packages/app\"]\n",
|
||||
&[WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nname = \"other\"\nversion = \"0.1.0\"\n",
|
||||
modules: &[("main", "(module main)\n\n(fn main () -> i32\n 0)\n")],
|
||||
}],
|
||||
);
|
||||
|
||||
let output = run_glagol([
|
||||
"--json-diagnostics".as_ref(),
|
||||
"check".as_ref(),
|
||||
workspace.as_os_str(),
|
||||
]);
|
||||
assert_exit_code("duplicate package key", &output, 1);
|
||||
assert_json_diagnostic_code("duplicate package key", &output, "PackageManifestInvalid");
|
||||
assert_json_diagnostic_code_absent("duplicate package key", &output, "ProjectManifestInvalid");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_dependency_key_reports_invalid_package_dependency_name() {
|
||||
let workspace = write_workspace(
|
||||
"invalid-dependency-key",
|
||||
"[workspace]\nmembers = [\"packages/app\"]\n",
|
||||
&[WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nversion = \"0.1.0\"\n\n[dependencies]\nBad_Name = { path = \"../util\" }\n",
|
||||
modules: &[("main", "(module main)\n\n(fn main () -> i32\n 0)\n")],
|
||||
}],
|
||||
);
|
||||
|
||||
let output = run_glagol([
|
||||
"--json-diagnostics".as_ref(),
|
||||
"check".as_ref(),
|
||||
workspace.as_os_str(),
|
||||
]);
|
||||
assert_exit_code("invalid dependency key", &output, 1);
|
||||
assert_json_diagnostic_code(
|
||||
"invalid dependency key",
|
||||
&output,
|
||||
"InvalidPackageDependencyName",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_dependency_keys_report_duplicate_package_dependency_name() {
|
||||
let workspace = write_workspace(
|
||||
"duplicate-dependency-key",
|
||||
"[workspace]\nmembers = [\"packages/app\"]\n",
|
||||
&[WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nversion = \"0.1.0\"\n\n[dependencies]\nutil = { path = \"../util\" }\nutil = { path = \"../util-again\" }\n",
|
||||
modules: &[("main", "(module main)\n\n(fn main () -> i32\n 0)\n")],
|
||||
}],
|
||||
);
|
||||
|
||||
let output = run_glagol([
|
||||
"--json-diagnostics".as_ref(),
|
||||
"check".as_ref(),
|
||||
workspace.as_os_str(),
|
||||
]);
|
||||
assert_exit_code("duplicate dependency key", &output, 1);
|
||||
assert_json_diagnostic_code(
|
||||
"duplicate dependency key",
|
||||
&output,
|
||||
"DuplicatePackageDependencyName",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_dependency_identity_checks_cleanly() {
|
||||
let workspace = write_workspace(
|
||||
"valid-dependency-identity",
|
||||
"[workspace]\nmembers = [\"packages/app\", \"packages/util\"]\n",
|
||||
&[
|
||||
WorkspacePackageSpec {
|
||||
member: "packages/util",
|
||||
manifest: "[package]\nname = \"util\"\nversion = \"0.1.0\"\n",
|
||||
modules: &[(
|
||||
"util",
|
||||
"(module util (export answer))\n\n(fn answer () -> i32\n 42)\n",
|
||||
)],
|
||||
},
|
||||
WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nversion = \"0.1.0\"\n\n[dependencies]\nutil = { path = \"../util\" }\n",
|
||||
modules: &[(
|
||||
"main",
|
||||
"(module main)\n\n(import util.util (answer))\n\n(fn main () -> i32\n (answer))\n",
|
||||
)],
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
let output = run_glagol(["check".as_ref(), workspace.as_os_str()]);
|
||||
assert_success_stdout("valid dependency identity", output, "");
|
||||
}
|
||||
|
||||
struct WorkspacePackageSpec<'a> {
|
||||
member: &'a str,
|
||||
manifest: &'a str,
|
||||
modules: &'a [(&'a str, &'a str)],
|
||||
}
|
||||
|
||||
fn write_workspace(
|
||||
name: &str,
|
||||
workspace_manifest: &str,
|
||||
packages: &[WorkspacePackageSpec<'_>],
|
||||
) -> PathBuf {
|
||||
let root = unique_path(name);
|
||||
fs::create_dir_all(&root).expect("create workspace root");
|
||||
fs::write(root.join("slovo.toml"), workspace_manifest).expect("write workspace manifest");
|
||||
|
||||
for package in packages {
|
||||
let package_root = root.join(package.member);
|
||||
let src = package_root.join("src");
|
||||
fs::create_dir_all(&src).expect("create workspace package src");
|
||||
fs::write(package_root.join("slovo.toml"), package.manifest)
|
||||
.expect("write workspace package manifest");
|
||||
for (module, source) in package.modules {
|
||||
fs::write(src.join(format!("{}.slo", module)), source)
|
||||
.expect("write workspace package module");
|
||||
}
|
||||
}
|
||||
|
||||
root
|
||||
}
|
||||
|
||||
fn unique_path(name: &str) -> PathBuf {
|
||||
let id = NEXT_WORKSPACE_ID.fetch_add(1, Ordering::SeqCst);
|
||||
let nanos = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|duration| duration.as_nanos())
|
||||
.unwrap_or(0);
|
||||
std::env::temp_dir().join(format!(
|
||||
"glagol-package-workspace-discipline-beta24-{}-{}-{}-{}",
|
||||
std::process::id(),
|
||||
nanos,
|
||||
id,
|
||||
name
|
||||
))
|
||||
}
|
||||
|
||||
fn run_glagol<I, S>(args: I) -> Output
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<std::ffi::OsStr>,
|
||||
{
|
||||
Command::new(env!("CARGO_BIN_EXE_glagol"))
|
||||
.args(args)
|
||||
.output()
|
||||
.expect("run glagol")
|
||||
}
|
||||
|
||||
fn assert_success_stdout(context: &str, output: Output, expected: &str) {
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"{} failed\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
expected,
|
||||
"{} stdout mismatch",
|
||||
context
|
||||
);
|
||||
assert!(
|
||||
output.stderr.is_empty(),
|
||||
"{} wrote stderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_exit_code(context: &str, output: &Output, expected: i32) {
|
||||
assert_eq!(
|
||||
output.status.code(),
|
||||
Some(expected),
|
||||
"{} exit code mismatch\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_json_diagnostic_code(context: &str, output: &Output, expected: &str) {
|
||||
let diagnostics = diagnostic_text(output);
|
||||
assert!(
|
||||
diagnostics.contains(&format!(r#""code":"{}""#, expected)),
|
||||
"{} did not report `{}`:\n{}",
|
||||
context,
|
||||
expected,
|
||||
diagnostics
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_json_diagnostic_code_absent(context: &str, output: &Output, unexpected: &str) {
|
||||
let diagnostics = diagnostic_text(output);
|
||||
assert!(
|
||||
!diagnostics.contains(&format!(r#""code":"{}""#, unexpected)),
|
||||
"{} unexpectedly reported `{}`:\n{}",
|
||||
context,
|
||||
unexpected,
|
||||
diagnostics
|
||||
);
|
||||
}
|
||||
|
||||
fn diagnostic_text(output: &Output) -> String {
|
||||
format!(
|
||||
"{}{}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
)
|
||||
}
|
||||
@ -182,6 +182,14 @@ local-package rules. Lockfiles, remote registries, semver solving, publishing,
|
||||
optional/dev/target dependencies, and stable package ABI/layout remain out of
|
||||
scope.
|
||||
|
||||
Released in `1.0.0-beta.24`: package manifest identity and dependency
|
||||
diagnostics are tightened without changing the package model. Duplicate
|
||||
package manifest keys, invalid dependency keys, and duplicate dependency keys
|
||||
are explicit diagnostics. The slice adds no remote registry, lockfile,
|
||||
semantic-version solving, package publishing, optional/dev/target
|
||||
dependencies, stable package ABI/layout, source-language change, runtime
|
||||
change, or standard-library change.
|
||||
|
||||
Why fifth: stable package rules are a prerequisite for a usable public language,
|
||||
but remote publishing can wait.
|
||||
|
||||
@ -557,6 +565,8 @@ Slovo should not become stable until all of these are true:
|
||||
- `lib/std` has explicit beta-supported, experimental, and internal tiers plus
|
||||
a later stable-tier/deprecation policy before `1.0.0`
|
||||
- package/workspace behavior is deterministic
|
||||
- package manifest identity and dependency-key failures have explicit
|
||||
diagnostics
|
||||
- conformance tests cover user-shaped projects
|
||||
- release gates are reproducible on a clean checkout
|
||||
- diagnostics and formatter output are stable for promoted features
|
||||
|
||||
@ -12,6 +12,37 @@ integration/readiness release, not the first real beta.
|
||||
|
||||
No active unreleased compiler scope is documented here yet.
|
||||
|
||||
## 1.0.0-beta.24
|
||||
|
||||
Release label: `1.0.0-beta.24`
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Release state: package manifest identity and local dependency diagnostic
|
||||
hardening
|
||||
|
||||
### Summary
|
||||
|
||||
The beta.24 compiler/tooling slice tightens local package manifest diagnostics
|
||||
without changing the language, runtime, stdlib, or package graph model:
|
||||
|
||||
- Bump the `glagol` compiler package version to `1.0.0-beta.24`.
|
||||
- Diagnose duplicate package manifest keys explicitly.
|
||||
- Diagnose invalid dependency keys explicitly.
|
||||
- Diagnose duplicate dependency keys explicitly.
|
||||
- Keep dependency records local-path-only and require dependency keys to match
|
||||
target package names.
|
||||
|
||||
### Explicit Deferrals
|
||||
|
||||
This release does not implement remote registries, lockfiles,
|
||||
semantic-version solving, package publishing, optional/dev/target
|
||||
dependencies, feature flags, build scripts, package archives, stable package
|
||||
ABI/layout, source-language syntax, runtime C capabilities, standard-library
|
||||
helpers, compiler-known `std.*` runtime names, stable artifact-manifest schema
|
||||
guarantees, stable Markdown schemas, LSP/watch/SARIF/daemon protocols, or
|
||||
performance claims.
|
||||
|
||||
## 1.0.0-beta.23
|
||||
|
||||
Release label: `1.0.0-beta.23`
|
||||
|
||||
@ -21,8 +21,8 @@ general-purpose beta release.
|
||||
|
||||
A Glagol feature is done only when it has parser/lowerer support, checker behavior, diagnostics for invalid forms, backend behavior or explicit unsupported diagnostics, and tests.
|
||||
|
||||
Current stage: `1.0.0-beta.23`, released on 2026-05-23 as standard-library
|
||||
stability tier ledger and catalog alignment. It keeps the
|
||||
Current stage: `1.0.0-beta.24`, released on 2026-05-23 as package manifest
|
||||
identity and local dependency diagnostic hardening. It keeps the
|
||||
`1.0.0-beta` language/compiler support baseline and includes the
|
||||
`1.0.0-beta.1` tooling hardening release, the `1.0.0-beta.2` runtime/resource
|
||||
foundation release, the `1.0.0-beta.3` standard-library stabilization release,
|
||||
@ -131,6 +131,14 @@ experimental, and keeps concrete vector modules beta-supported concrete lanes
|
||||
without claiming generic collection stability. It adds no source-language,
|
||||
runtime, package, or standard-library helper surface.
|
||||
|
||||
The beta.24 compiler/tooling slice bumps the package version and tightens
|
||||
local package manifest diagnostics. Duplicate package manifest keys, invalid
|
||||
dependency keys, and duplicate dependency keys are explicit diagnostics. It
|
||||
keeps the existing closed local workspace model and adds no remote registry,
|
||||
lockfile, semantic-version solving, package publishing, optional/dev/target
|
||||
dependencies, stable package ABI/layout, source-language behavior, runtime
|
||||
behavior, or standard-library behavior.
|
||||
|
||||
Generic vectors, generic collections, maps, sets, generic stdlib dispatch,
|
||||
runtime collection changes, collection unification, stable human diagnostic
|
||||
text, stable artifact-manifest or Markdown schema freezes, LSP/watch
|
||||
@ -714,6 +722,8 @@ Alpha is the latest compiler semantic/runtime-operation support slice.
|
||||
- [x] Diagnose missing packages, duplicate package names, dependency cycles,
|
||||
path escapes, invalid package names, invalid package versions, private
|
||||
visibility, and dependency key mismatches.
|
||||
- [x] Diagnose duplicate package manifest keys, invalid dependency keys, and
|
||||
duplicate dependency keys explicitly.
|
||||
- [x] Keep registries, lockfiles, semver solving, aliases/globs/re-exports,
|
||||
generated code, build scripts, publishing, optional/dev/target
|
||||
dependencies, stable package ABI, and remote dependencies deferred.
|
||||
|
||||
@ -237,6 +237,47 @@ Future releases may add codes or split broad codes when the release scope
|
||||
requires more precise tooling behavior. Such changes must be documented using
|
||||
the compatibility classes above.
|
||||
|
||||
## Project And Workspace Codes
|
||||
|
||||
Project, package, and workspace diagnostics are covered by integration tests
|
||||
because they often require multiple files, manifests, or generated temporary
|
||||
directories rather than a single `.slo` golden fixture. These codes still use
|
||||
the same `slovo.diagnostic` version `1` schema and PascalCase code policy.
|
||||
|
||||
Current package/workspace loader and graph diagnostics include:
|
||||
|
||||
- `DependencyNameMismatch`
|
||||
- `DependencyPathEscape`
|
||||
- `DuplicatePackageDependencyName`
|
||||
- `DuplicatePackageName`
|
||||
- `DuplicateWorkspaceMember`
|
||||
- `InvalidPackageDependencyName`
|
||||
- `InvalidPackageName`
|
||||
- `InvalidPackageVersion`
|
||||
- `MissingPackageDependency`
|
||||
- `MissingPackageModule`
|
||||
- `PackageDependencyCycle`
|
||||
- `PackageImportNotDependency`
|
||||
- `PackageManifestInvalid`
|
||||
- `PackageSourceReadFailed`
|
||||
- `PackageSourceRootEscape`
|
||||
- `PackageSourceRootMissing`
|
||||
- `ProjectEntryMainInvalidSignature`
|
||||
- `ProjectEntryMainMissing`
|
||||
- `ProjectManifestInvalid`
|
||||
- `ProjectManifestReadFailed`
|
||||
- `ProjectSourceReadFailed`
|
||||
- `ProjectSourceRootMissing`
|
||||
- `UnsupportedDependency`
|
||||
- `WorkspaceBuildAmbiguousEntryPackage`
|
||||
- `WorkspaceDefaultPackageEntryMissing`
|
||||
- `WorkspaceDefaultPackageMissing`
|
||||
- `WorkspaceEntryMainInvalidSignature`
|
||||
- `WorkspaceEntryMainMissing`
|
||||
- `WorkspaceManifestInvalid`
|
||||
- `WorkspaceMemberManifestMissing`
|
||||
- `WorkspaceMemberPathEscape`
|
||||
|
||||
## Explicit Deferrals
|
||||
|
||||
`1.0.0-beta.13` does not define:
|
||||
|
||||
@ -56,6 +56,10 @@ used for solving dependency constraints.
|
||||
dependency paths must stay inside the workspace/package boundary after
|
||||
normalization and canonical path checks.
|
||||
|
||||
Duplicate keys in package manifests are `PackageManifestInvalid` diagnostics.
|
||||
The manifest loader does not silently choose one spelling for repeated package
|
||||
identity or dependency entries.
|
||||
|
||||
Dependencies are local path records only. The dependency key must match the
|
||||
target package name:
|
||||
|
||||
@ -63,6 +67,11 @@ target package name:
|
||||
mathlib = { path = "../mathlib" }
|
||||
```
|
||||
|
||||
Dependency keys use the same package-name shape as package identities. Invalid
|
||||
dependency keys are `InvalidPackageDependencyName` diagnostics, and duplicate
|
||||
dependency keys are `DuplicatePackageDependencyName` diagnostics before the
|
||||
local dependency graph is accepted.
|
||||
|
||||
## Imports
|
||||
|
||||
Within a workspace, a package imports a dependency module through the package
|
||||
@ -106,9 +115,12 @@ The package/workspace gate covers these user-facing error families:
|
||||
- missing member manifests
|
||||
- duplicate normalized workspace members
|
||||
- invalid member or dependency paths
|
||||
- duplicate package manifest keys
|
||||
- invalid package names and versions
|
||||
- duplicate package names
|
||||
- missing local path dependencies
|
||||
- invalid dependency keys
|
||||
- duplicate dependency keys
|
||||
- dependency key/name mismatches
|
||||
- package dependency cycles
|
||||
- private cross-package imports
|
||||
|
||||
@ -8,7 +8,7 @@ Historical `exp-*` releases listed here are experimental maturity milestones.
|
||||
The pushed tag `v2.0.0-beta.1` is historical. It is now documented as an
|
||||
experimental integration/readiness release, not as a beta maturity claim.
|
||||
|
||||
The current release is `1.0.0-beta.23`, published on 2026-05-23. It keeps the
|
||||
The current release is `1.0.0-beta.24`, published on 2026-05-23. It keeps the
|
||||
`1.0.0-beta` language surface, includes the first post-beta tooling/install
|
||||
hardening bundle from `1.0.0-beta.1`, and adds the first runtime/resource
|
||||
foundation bundle from `1.0.0-beta.2` plus the first standard-library
|
||||
@ -33,12 +33,40 @@ conformance foundation from `1.0.0-beta.19`, and the string search and ASCII
|
||||
trim foundation from `1.0.0-beta.20`, plus the JSON document scalar parsing
|
||||
foundation from `1.0.0-beta.21`, and the run manifest execution-report
|
||||
hardening slice from `1.0.0-beta.22`, plus the standard-library stability tier
|
||||
ledger and catalog alignment slice from `1.0.0-beta.23`.
|
||||
ledger and catalog alignment slice from `1.0.0-beta.23`, and the package
|
||||
manifest identity and local dependency diagnostic hardening slice from
|
||||
`1.0.0-beta.24`.
|
||||
|
||||
## Unreleased
|
||||
|
||||
No active unreleased language scope is documented here yet.
|
||||
|
||||
## 1.0.0-beta.24
|
||||
|
||||
Release label: `1.0.0-beta.24`
|
||||
|
||||
Release name: Package Manifest Identity And Dependency Discipline
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Status: released beta package/workspace diagnostic hardening on the
|
||||
`1.0.0-beta` language baseline.
|
||||
|
||||
This release tightens diagnostics for local package manifests only. Duplicate
|
||||
package manifest keys, invalid dependency keys, and duplicate dependency keys
|
||||
are explicit beta package/workspace diagnostics.
|
||||
|
||||
The package model remains the existing closed local workspace model:
|
||||
dependencies are local path records, dependency keys must match target package
|
||||
names, and package-qualified imports still resolve through the local workspace
|
||||
graph.
|
||||
|
||||
This release adds no remote registry, lockfile, semantic-version solving,
|
||||
package publishing, optional/dev/target dependencies, stable package
|
||||
ABI/layout, source-language syntax or semantics, runtime behavior,
|
||||
standard-library helpers, compiler-known runtime names, stable manifest schema,
|
||||
stable Markdown schema, or performance claim.
|
||||
|
||||
## 1.0.0-beta.23
|
||||
|
||||
Release label: `1.0.0-beta.23`
|
||||
|
||||
@ -8,10 +8,10 @@ Guiding rule: the manifest wins. A feature is not accepted until it has surface
|
||||
Long-horizon planning lives in `.llm/ROADMAP_TO_STABLE.md`. It defines the
|
||||
release train beyond the first real general-purpose beta Slovo contract.
|
||||
|
||||
Current stage: `1.0.0-beta.23`, released on 2026-05-23 as post-beta
|
||||
standard-library stability tier ledger and catalog alignment. It keeps the
|
||||
`1.0.0-beta` language
|
||||
contract and includes the `1.0.0-beta.1` tooling hardening release, the
|
||||
Current stage: `1.0.0-beta.24`, released on 2026-05-23 as post-beta
|
||||
package manifest identity and local dependency diagnostic hardening. It keeps
|
||||
the `1.0.0-beta` language contract and includes the `1.0.0-beta.1` tooling
|
||||
hardening release, the
|
||||
`1.0.0-beta.2` runtime/resource foundation release, the `1.0.0-beta.3`
|
||||
standard-library stabilization release, the `1.0.0-beta.4`
|
||||
language-usability diagnostics release, the `1.0.0-beta.5` package/workspace
|
||||
@ -29,7 +29,8 @@ scalar token parsing, `1.0.0-beta.18` JSON string token parsing,
|
||||
`1.0.0-beta.20` string search and ASCII trim helpers, plus
|
||||
`1.0.0-beta.21` JSON document scalar parsing helpers, and
|
||||
`1.0.0-beta.22` run manifest execution-report hardening, plus
|
||||
`1.0.0-beta.23` standard-library stability tier documentation.
|
||||
`1.0.0-beta.23` standard-library stability tier documentation, and
|
||||
`1.0.0-beta.24` package manifest/dependency diagnostic hardening.
|
||||
|
||||
`1.0.0-beta.16` adds `std.string` source facades and examples for
|
||||
`byte_at_result`, `slice_result`, `starts_with`, and `ends_with`. These helpers
|
||||
@ -118,6 +119,14 @@ behavior, stable manifest schema, stable Markdown schema, stable ABI/layout,
|
||||
or stable stdlib/API freeze. It does update generated catalog output and the
|
||||
release gate so tier metadata is visible and checked.
|
||||
|
||||
`1.0.0-beta.24` is package/workspace diagnostic hardening, not a language,
|
||||
runtime, package-manager, or stdlib behavior feature. It makes duplicate
|
||||
package manifest keys, invalid dependency keys, and duplicate dependency keys
|
||||
explicit diagnostics while keeping the existing closed local workspace model.
|
||||
It adds no remote registry, lockfile, semantic-version solving, package
|
||||
publishing, optional/dev/target dependencies, stable package ABI/layout,
|
||||
source-language change, runtime change, or stdlib change.
|
||||
|
||||
The final experimental precursor scope is `exp-125`, defined in
|
||||
`.llm/EXP_125_UNSIGNED_U32_U64_NUMERIC_AND_STDLIB_BREADTH_ALPHA.md`. Its
|
||||
unsigned direct-value flow, parse/format runtime lanes, and matching staged
|
||||
|
||||
@ -6,7 +6,7 @@ Do not edit this file by hand.
|
||||
## Stability Tiers
|
||||
|
||||
- `beta-supported`: exported from `lib/std` and covered by source-search, promotion, or facade gates in the current beta line.
|
||||
- `experimental`: exported from `lib/std` in `1.0.0-beta.23`, but still has beta caveats around host behavior, resource handles, or API shape.
|
||||
- `experimental`: exported from `lib/std` in `1.0.0-beta.24`, but still has beta caveats around host behavior, resource handles, or API shape.
|
||||
- `internal`: helper names that are not exported from their module; they are intentionally omitted from this catalog.
|
||||
|
||||
The catalog is a beta API discovery aid, not a stable `1.0.0` standard-library freeze.
|
||||
|
||||
@ -76,6 +76,7 @@ cargo test --test test_discovery_beta19
|
||||
cargo test --test standard_string_search_trim_beta20
|
||||
cargo test --test standard_json_document_scalar_parsing_beta21
|
||||
cargo test --test run_manifest_beta22
|
||||
cargo test --test package_workspace_discipline_beta24
|
||||
# Full cargo test includes unignored integration gates such as dx_v1_7,
|
||||
# beta_v2_0_0_beta_1, and beta_1_0_0.
|
||||
cargo test
|
||||
|
||||
Loading…
Reference in New Issue
Block a user