Skip to content

feat(0.19.0): Closure Contract — arcs.yaml + composite-ω drift trend … #55

feat(0.19.0): Closure Contract — arcs.yaml + composite-ω drift trend …

feat(0.19.0): Closure Contract — arcs.yaml + composite-ω drift trend … #55

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
lint:
name: Lint shell + JSON templates
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: ShellCheck (scripts + bin)
run: |
# Only lint files that have a shebang we recognize.
set -euo pipefail
mapfile -t targets < <(
find scripts bin -type f \( -name "*.sh" -o ! -name "*.*" \) 2>/dev/null \
| xargs -I {} sh -c 'head -n1 "{}" | grep -q "^#!.*sh" && echo "{}"' \
| sort -u
)
if [ "${#targets[@]}" -eq 0 ]; then
echo "No shell scripts found to lint."
exit 0
fi
printf ' • %s\n' "${targets[@]}"
# Excluded checks (bstack's defensive shell style accepts these):
# SC1091 — don't follow sourced files.
# SC2155 — declare-and-assign masks return code (intentional).
# SC2034 — unused variable. Several scripts intentionally name
# variables that are only used in conditional branches
# shellcheck can't see. Suppressed at the lint gate;
# per-file SC2034 audit is a follow-up.
shellcheck --severity=warning \
--exclude=SC1091,SC2155,SC2034 \
"${targets[@]}"
- name: Validate JSON templates
run: |
set -euo pipefail
shopt -s nullglob
fail=0
for f in assets/templates/*.snippet; do
if ! jq -e . "$f" >/dev/null 2>&1; then
echo "::error file=$f::invalid JSON shape"
fail=1
else
echo " • $f — valid JSON"
fi
done
exit "$fail"
doctor:
name: bstack doctor (primitive-contract lint)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run doctor against templates
run: |
set -euo pipefail
mkdir -p .control
cp assets/templates/CLAUDE.md.template ./CLAUDE.md 2>/dev/null || true
cp assets/templates/AGENTS.md.template ./AGENTS.md 2>/dev/null || true
cp assets/templates/policy.yaml.template .control/policy.yaml 2>/dev/null || true
bash scripts/doctor.sh --quiet
tests:
name: tests/*.test.sh
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run all tests/*.test.sh
# As of v0.8.0 (Phase 5 of substrate completion) the pre-existing
# tests/template_lockstep.test.sh and tests/onboard.test.sh are
# fixed (case-insensitive lockstep assertion + BSTACK_SKIP_SKILLS=1
# env override for the bootstrap skill-install loop). The full
# `tests/*.test.sh` suite now runs on every PR — no more vetted
# allowlist.
run: |
set -euo pipefail
shopt -s nullglob
fail=0
for t in tests/*.test.sh; do
echo ""
echo "=== $t ==="
if ! bash "$t"; then
echo "::error file=$t::test failed"
fail=1
fi
done
exit "$fail"
canary:
name: bstack canary suite (substrate invariants)
runs-on: ubuntu-latest
needs: [lint, doctor]
steps:
- uses: actions/checkout@v4
- name: Install jq + python deps for canary
run: |
set -euo pipefail
sudo apt-get update -qq && sudo apt-get install -y jq
python3 -m pip install --quiet jsonschema PyYAML
- name: Run canary suite (substrate invariants on fresh install)
# The canary suite verifies that the substrate's load-bearing
# contracts hold on a fresh install (no companion skills, no
# workspace state). Each canary covers one phase's deliverables:
# 01 — fresh bootstrap (Plant Contract)
# 02 — metrics pipeline (Phase 1 v0.4.0)
# 03 — status surface (Phase 2 v0.5.0)
# 04 — schemas validate (Phase 3 v0.6.0)
# 05 — crystallize detector (Phase 7 v0.9.5)
run: |
set -euo pipefail
shopt -s nullglob
fail=0
for t in tests/canary/*.test.sh; do
echo ""
echo "=== $t ==="
if ! bash "$t"; then
echo "::error file=$t::canary failed"
fail=1
fi
done
exit "$fail"