feat(0.22.0): wire RCS control loop on bootstrap + doctor §23 closure… #92
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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" |