Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ dated release section after the final merged commit is selected. -->

### Fixed

- Preserved literal PATH entries during `base_std_*` PATH deduplication.
- Rejected non-root Git update paths so `base_git_update_repo` cannot update an
ancestor repository from a plain child directory.
- Preserved exact string and list semantics under Bash `nocasematch`.
- Validated integer ranges before arithmetic so out-of-range configuration
values are rejected instead of being narrowed by conversion.
- Fixed nested configuration and validator state leaking across application
loads and nested CLI traversals.
- Fixed generated completion handling at the cursor/end-of-array boundary and
Expand Down
17 changes: 15 additions & 2 deletions docs/consumer-validation-status.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Consumer validation status

Last validated: 2026-09-02
Ledger reconciled: 2026-10-07

The v2.0.0 rows below are historical GA evidence. The current canary snapshot
is recorded separately and must not be read as a new first-party release or
consumer pin.

This is an internal readiness ledger for the #239 adoption work. It records
what can be reproduced from the current local checkouts; it is not a public
Expand All @@ -10,13 +14,22 @@ has approved publication.

## Framework reference

The release gate used the immutable `base-bash-libs` v2.0.0 GA at merge commit
Historical GA release gate: immutable `base-bash-libs` v2.0.0 at merge commit
`b4243765726c133499feeabdc50154f99c0fec12`. The
[v2.0.0 release](https://github.com/basefoundry/base-bash-libs/releases/tag/v2.0.0)
archive, SHA256SUMS, SPDX SBOM, and provenance assets were downloaded and
verified. The canonical archive SHA256 is
`73d6f92fab8f1a8ded7f3b4312ebbe51aa8ec0c16eacf18c2d8fa23fb5664333`.

## Current canary snapshot

On 2026-10-05, the scheduled [Framework Compatibility run
#37327900680](https://github.com/basefoundry/base-bash-libs-demo/actions/runs/37327900680)
passed all four candidate jobs: the immutable v2.0.0 baseline and current
supported v2.1.0 release on Ubuntu 24.04 and macOS 14. This validates the demo's
black-box compatibility path; it does not change the committed v2.0.0 vendor
pin or promote the historical GA rows below.

## Consumer matrix

| Checkout | Relationship | Reference | Deployment exercised | Result | Classification |
Expand Down
11 changes: 6 additions & 5 deletions docs/discovery/awesome-bash.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ deliberately not a claim that the project has been accepted upstream.

## Submission gate

Submit only after the v2.0.0 release has a canonical immutable asset and the
following links are public and stable:
Submit only after a published v2 release has a canonical immutable asset and
the following links are public and stable. This record was last reviewed on
2026-10-07 against v2.1.0:

1. the five-minute adoption path in [`docs/v2/quickstart.md`](../v2/quickstart.md);
2. the support and security policies in [`docs/support-policy.md`](../support-policy.md);
Expand All @@ -25,8 +26,8 @@ following links are public and stable:

## Maintainer checklist

- [ ] v2.0.0 release URL and SHA-256 added to this record
- [ ] release asset, bundle, and provenance links resolve without credentials
- [ ] reference-app and benchmark links resolve on the default branch
- [ ] v2.0.0 release URL and SHA-256 are recorded in this submission record
- [ ] release asset, bundle, and provenance links are independently verified here
- [ ] reference-app and benchmark links are independently verified here
- [ ] submission PR URL recorded here
- [ ] upstream acceptance or rejection recorded here
14 changes: 10 additions & 4 deletions docs/first-party-cutover.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# First-party v2 cutover
# Historical first-party v2.0.0 cutover record

Record scope: historical GA handoff completed on 2026-08-15. This page and its
machine-readable inventory describe the v2.0.0 cutover; they are not the
current Base or Base Bash release status.

Issue #240 records the first-party promotion handoff. The exact v2 GA asset,
checksum, and provenance exist, and Base, Base Demo, and Homebrew now point at
Expand Down Expand Up @@ -37,8 +41,10 @@ the v2 asset/tag unchanged. Never retag a different commit or silently fall
back to a moving branch. Record the failure and corrected checksums in the
release notes, then resume from the failed consumer after a reviewed fix.

## Current state
## Historical state at v2.0.0 GA

Base's `basectl help` integration defect is fixed in the merged issue-backed PR
above and validated locally against the v2 API. Base v1.8.0, Base Demo, and the
Homebrew `base-v1.8.0` bottle release consume the verified v2.0.0 GA asset.
above and validated locally against the v2 API. At the 2026-08-15 GA cutover,
Base v1.8.0, Base Demo, and the Homebrew `base-v1.8.0` bottle release consumed
the verified v2.0.0 GA asset. Later releases and pins belong in their own
release records.
9 changes: 5 additions & 4 deletions docs/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ in CI rather than making them runtime dependencies.
## Package channels

`integrations/package-managers/registry.yaml` is an intentionally conservative
registry. bpkg, Basher, and Basalt entries remain `planned-after-v2-ga` until an
immutable v2 asset, checksum, provenance, and a maintained update path exist.
No package-manager URL in this repository is presented as an official install
source before those gates pass.
registry. bpkg, Basher, and Basalt entries remain
`deferred-until-maintained-update-path`: the immutable v2 asset, checksum, and
provenance gates have passed, but no maintained owner and update path has been
verified. No package-manager URL in this repository is presented as an official
install source before that remaining gate passes.

The exact upstream revisions reviewed for the adapters and project tools are
recorded in [`integrations/compatibility.yaml`](../integrations/compatibility.yaml).
Expand Down
7 changes: 4 additions & 3 deletions examples/reference-apps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ examples/reference-apps/release-rehearsal.sh \
```

The required evidence schema and platform matrix live in
[`release-evidence.yaml`](release-evidence.yaml). It records the verified
canonical `v2.0.0` asset, checksum, and provenance; the repository never treats
a moving checkout as release evidence.
[`release-evidence.yaml`](release-evidence.yaml). That file is a historical
v2.0.0 GA baseline, reviewed on 2026-10-07; it records the verified canonical
asset, checksum, and provenance, and the repository never treats a moving
checkout as release evidence.
2 changes: 2 additions & 0 deletions examples/reference-apps/release-evidence.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
schema_version: 1
record_scope: historical-v2.0.0-ga-baseline
last_reviewed: 2026-10-07
release_line: v2.0.0
status: verified

Expand Down
3 changes: 3 additions & 0 deletions first-party-cutover.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
schema_version: 1
record_scope: historical-v2.0.0-ga-cutover
record_date: 2026-08-15
last_reconciled: 2026-10-07
target_release: 2.0.0
release_status: published
required_asset:
Expand Down
2 changes: 2 additions & 0 deletions integrations/compatibility.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
schema_version: 1
record_scope: historical-v2.0.0-ga-baseline
last_reviewed: 2026-10-07
framework_release_line: v2.0.0
update_policy: review-pins-on-every-upstream-release

Expand Down
6 changes: 3 additions & 3 deletions integrations/package-managers/registry.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ artifact: base-bash-libs
release_policy: immutable-v2-asset-and-sha256
entries:
- name: bpkg
status: planned-after-v2-ga
status: deferred-until-maintained-update-path
install_metadata: publish-only-after-verified-release-asset
verification: release-asset-sha256-and-provenance
maintenance: explicit-owner-and-update-path-required
- name: basher
status: planned-after-v2-ga
status: deferred-until-maintained-update-path
install_metadata: publish-only-after-verified-release-asset
verification: release-asset-sha256-and-provenance
maintenance: explicit-owner-and-update-path-required
- name: basalt
status: planned-after-v2-ga
status: deferred-until-maintained-update-path
install_metadata: publish-only-after-verified-release-asset
verification: release-asset-sha256-and-provenance
maintenance: explicit-owner-and-update-path-required
96 changes: 78 additions & 18 deletions scripts/first-party-cutover
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,69 @@ usage() {

while (($#)); do
case "$1" in
check) ;;
--allow-pending) allow_pending=1 ;;
--base-dir) [[ -n "${2-}" ]] || { usage >&2; exit 2; }; base_dir="$2"; shift ;;
--base-demo-dir) [[ -n "${2-}" ]] || { usage >&2; exit 2; }; base_demo_dir="$2"; shift ;;
--homebrew-dir) [[ -n "${2-}" ]] || { usage >&2; exit 2; }; homebrew_dir="$2"; shift ;;
-h|--help) usage; exit 0 ;;
*) printf 'Unknown cutover option: %s\n' "$1" >&2; usage >&2; exit 2 ;;
check) ;;
--allow-pending) allow_pending=1 ;;
--base-dir)
[[ -n "${2-}" ]] || {
usage >&2
exit 2
}
base_dir="$2"
shift
;;
--base-demo-dir)
[[ -n "${2-}" ]] || {
usage >&2
exit 2
}
base_demo_dir="$2"
shift
;;
--homebrew-dir)
[[ -n "${2-}" ]] || {
usage >&2
exit 2
}
homebrew_dir="$2"
shift
;;
-h | --help)
usage
exit 0
;;
*)
printf 'Unknown cutover option: %s\n' "$1" >&2
usage >&2
exit 2
;;
esac
shift
done

[[ -f "$manifest" ]] || { printf 'Missing cutover manifest: %s\n' "$manifest" >&2; exit 1; }
grep -F 'target_release: 2.0.0' "$manifest" >/dev/null || { printf 'Cutover target must be 2.0.0.\n' >&2; exit 1; }
grep -F 'tag: v2.0.0' "$manifest" >/dev/null || { printf 'Cutover tag must be v2.0.0.\n' >&2; exit 1; }
[[ -f "$manifest" ]] || {
printf 'Missing cutover manifest: %s\n' "$manifest" >&2
exit 1
}
grep -F 'record_scope: historical-v2.0.0-ga-cutover' "$manifest" > /dev/null || {
printf 'Cutover manifest must identify its historical record scope.\n' >&2
exit 1
}
grep -F 'record_date: 2026-08-15' "$manifest" > /dev/null || {
printf 'Cutover manifest must identify the v2.0.0 GA record date.\n' >&2
exit 1
}
grep -Eq '^last_reconciled: [0-9]{4}-[0-9]{2}-[0-9]{2}$' "$manifest" || {
printf 'Cutover manifest reconciliation date is missing or malformed.\n' >&2
exit 1
}
grep -F 'target_release: 2.0.0' "$manifest" > /dev/null || {
printf 'Cutover target must be 2.0.0.\n' >&2
exit 1
}
grep -F 'tag: v2.0.0' "$manifest" > /dev/null || {
printf 'Cutover tag must be v2.0.0.\n' >&2
exit 1
}

release_status="$(sed -n 's/^release_status:[[:space:]]*//p' "$manifest" | sed -n '1p')"
if [[ "$release_status" != published ]]; then
Expand All @@ -44,26 +93,37 @@ check_no_legacy() {
local directory="$1"
[[ -n "$directory" && -d "$directory" ]] || return 0
if grep -R -n -E 'base_bash_libs_(require_version|std_|file_|git_|gh_|str_|arg_|list_)' \
"$directory" --include='*.sh' --include='*.bash' --include='*.bats' 2>/dev/null; then
"$directory" --include='*.sh' --include='*.bash' --include='*.bats' 2> /dev/null; then
printf 'Legacy base-bash-libs symbols remain under %s.\n' "$directory" >&2
return 1
fi
}

if [[ -n "$base_dir" ]]; then
[[ -f "$base_dir/base_init.sh" ]] || { printf 'Base directory lacks base_init.sh: %s\n' "$base_dir" >&2; exit 1; }
grep -F 'base_require_version' "$base_dir/base_init.sh" >/dev/null || {
printf 'Base does not call the v2 version helper.\n' >&2; exit 1;
[[ -f "$base_dir/base_init.sh" ]] || {
printf 'Base directory lacks base_init.sh: %s\n' "$base_dir" >&2
exit 1
}
grep -F 'base_require_version' "$base_dir/base_init.sh" > /dev/null || {
printf 'Base does not call the v2 version helper.\n' >&2
exit 1
}
check_no_legacy "$base_dir" || exit $?
fi
check_no_legacy "$base_demo_dir" || exit $?
if [[ -n "$homebrew_dir" ]]; then
formula="$homebrew_dir/Formula/base-bash-libs.rb"
[[ -f "$formula" ]] || { printf 'Homebrew formula is missing: %s\n' "$formula" >&2; exit 1; }
grep -F 'v2.0.0' "$formula" >/dev/null || { printf 'Homebrew formula is not pinned to v2.0.0.\n' >&2; exit 1; }
grep -E 'type -t (std_run|update_file_section|git_get_current_branch|gh_run)' "$formula" >/dev/null && {
printf 'Homebrew formula still tests legacy generic symbols.\n' >&2; exit 1;
[[ -f "$formula" ]] || {
printf 'Homebrew formula is missing: %s\n' "$formula" >&2
exit 1
}
grep -F 'v2.0.0' "$formula" > /dev/null || {
printf 'Homebrew formula is not pinned to v2.0.0.\n' >&2
exit 1
}
grep -E 'type -t (std_run|update_file_section|git_get_current_branch|gh_run)' "$formula" > /dev/null && {
printf 'Homebrew formula still tests legacy generic symbols.\n' >&2
exit 1
}
fi

Expand Down
14 changes: 9 additions & 5 deletions tests/docs-contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,15 @@ readme_pin="$(sed -n '/^Pin the checkout to the full current release commit/,/^`
printf 'README current-release pin does not match the expected v2.1.0 commit.\n' >&2
exit 1
}
resolved_current_release="$(git rev-parse --verify "${readme_current_release}^{commit}" 2> /dev/null || true)"
[[ "$resolved_current_release" == "$readme_pin" ]] || {
printf 'README current-release pin does not match its tag.\n' >&2
exit 1
}
if resolved_current_release="$(git rev-parse --verify "${readme_current_release}^{commit}" 2> /dev/null)"; then
[[ "$resolved_current_release" == "$readme_pin" ]] || {
printf 'README current-release pin does not match its tag.\n' >&2
exit 1
}
else
printf 'Skipping README current-release tag comparison: tag %s is unavailable in this checkout.\n' \
"$readme_current_release" >&2
fi
grep -F 'framework_launcher' docs/v2/quickstart.md > /dev/null || {
printf "The v2 quickstart must use the verified launcher path.\n" >&2
exit 1
Expand Down
8 changes: 6 additions & 2 deletions tests/integration-release-contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ integration_fail() {
[[ -f "$integration_manifest" ]] || integration_fail "missing compatibility manifest"
grep -Fx 'schema_version: 1' "$integration_manifest" > /dev/null ||
integration_fail 'schema version is not 1'
grep -Fx 'record_scope: historical-v2.0.0-ga-baseline' "$integration_manifest" > /dev/null ||
integration_fail 'compatibility manifest must identify its historical baseline scope'
grep -Eq '^last_reviewed: [0-9]{4}-[0-9]{2}-[0-9]{2}$' "$integration_manifest" ||
integration_fail 'compatibility manifest review date is missing or malformed'
grep -Fx 'framework_release_line: v2.0.0' "$integration_manifest" > /dev/null ||
integration_fail 'framework release line is not v2.0.0'

Expand All @@ -37,8 +41,8 @@ done

for channel in bpkg basher basalt; do
grep -A2 -E "^ - name: ${channel}$" "$integration_repo_root/integrations/package-managers/registry.yaml" |
grep -F 'status: planned-after-v2-ga' > /dev/null ||
integration_fail "package channel ${channel} must remain fail-closed before GA"
grep -F 'status: deferred-until-maintained-update-path' > /dev/null ||
integration_fail "package channel ${channel} must remain deferred until a maintained update path exists"
done

printf 'Integration release contract passed: pins=%s package_channels=3.\n' "$pin_count"
6 changes: 3 additions & 3 deletions tests/integrations.bats
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ setup() {
[[ "$output" == *"release=candidate"* ]]
}

@test "integration recipes remain optional and package registry stays pre-GA" {
run grep -F 'status: planned-after-v2-ga' "$repo_root/integrations/package-managers/registry.yaml"
@test "integration recipes remain optional and package registry records its remaining gate" {
run grep -F 'status: deferred-until-maintained-update-path' "$repo_root/integrations/package-managers/registry.yaml"

[ "$status" -eq 0 ]
[ "$(grep -c 'status: planned-after-v2-ga' "$repo_root/integrations/package-managers/registry.yaml")" -eq 3 ]
[ "$(grep -c 'status: deferred-until-maintained-update-path' "$repo_root/integrations/package-managers/registry.yaml")" -eq 3 ]
}

@test "project kit declares Bash-aware static-analysis policy" {
Expand Down
4 changes: 4 additions & 0 deletions tests/reference-release-contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ reference_release_fail() {
[[ -f "$reference_release_evidence" ]] || reference_release_fail 'evidence manifest is missing'
grep -Fx 'schema_version: 1' "$reference_release_evidence" > /dev/null ||
reference_release_fail 'schema version is not 1'
grep -Fx 'record_scope: historical-v2.0.0-ga-baseline' "$reference_release_evidence" > /dev/null ||
reference_release_fail 'release evidence must identify its historical baseline scope'
grep -Eq '^last_reviewed: [0-9]{4}-[0-9]{2}-[0-9]{2}$' "$reference_release_evidence" ||
reference_release_fail 'release evidence review date is missing or malformed'
grep -Fx 'release_line: v2.0.0' "$reference_release_evidence" > /dev/null ||
reference_release_fail 'release line is not v2.0.0'
grep -Fx 'rehearsal_command: examples/reference-apps/release-rehearsal.sh' \
Expand Down
Loading