Skip to content

refactor(domains): MOVE migration complete β€” 360 specs β†’ 32 standalon… #1100

refactor(domains): MOVE migration complete β€” 360 specs β†’ 32 standalon…

refactor(domains): MOVE migration complete β€” 360 specs β†’ 32 standalon… #1100

Workflow file for this run

# ═══════════════════════════════════════════════════════════════
# CDO Troubleshooting:
# .shared/ μ‹¬λ§ν¬λŠ” 폐기됨 (TECS-L 흑수 μ™„λ£Œ, canon 단일 톡합).
# CI μ—μ„œ .shared/ λ‚΄μš©μ— μ˜μ‘΄ν•˜μ§€ 말 것.
# CDO JSON 검증은 인라인 Python μ‚¬μš©.
# ═══════════════════════════════════════════════════════════════
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# ── Job 1: Python syntax check + tests ──────────────────────
python-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install test dependencies
run: |
pip install pytest numpy 2>/dev/null || pip install pytest
- name: py_compile (syntax check)
run: |
exitcode=0
for f in tools/*.py techniques/*.py engine/*.py *.py; do
if [ -f "$f" ]; then
python3 -m py_compile "$f" || exitcode=1
fi
done
exit $exitcode
- name: pytest (unit tests)
run: |
if compgen -G "tests/test_*.py" > /dev/null 2>&1; then
python3 -m pytest tests/ -q --tb=short
else
echo "No test files in tests/ β€” skipping pytest"
fi
# ── Job 2: Rust cargo check + test β€” REMOVED 2026-04-24 ─────
# Rationale: tools/nexus/Cargo.toml path was stale (removed long ago).
# No Cargo.toml exists anywhere in this repo; .own rule #10 bans .rs files
# in canon. Rust testing belongs to the nexus/ sister repo's own CI.
# ── Job 3b: Stage A preflight β€” shared constants generator-clean + flatten ──
# Stage A consolidation (proposals/dup_derivation_consolidation_phase2_2026_04_24.md).
# SSOT relocated 2026-05-08: n6_core_constants.hexa now lives in the nexus
# sister repo (~/core/nexus/n6/n6_core_constants.hexa). Drift check is skipped
# in canon CI because the upstream SSOT is not checked out here. nexus CI
# owns the regen check; canon only consumes the auto-generated derivative.
n6-shared-constants:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Stage-A SSOT relocation note
run: |
echo "Stage A SSOT (n6_core_constants.hexa) relocated to nexus 2026-05-08."
echo "canonshared/_shared_constants.hexa is now hand-maintained until a"
echo "cross-repo sync workflow lands. Skipping --check."
- name: Flatten-preflight β€” Stage A migrated verify files
# hexa-lang toolchain is not provisioned on the runner; we use the pure-python
# fallback (scripts/flatten_imports_py.hexa thin-shim β†’ legacy.py) which has the same `use` resolution
# contract. This validates that every migrated file flattens cleanly.
run: |
set -e
MIGRATED=(
domains/cognitive/brain-computer-interface/verify_brain-computer-interface.hexa
domains/energy/room-temp-sc/tabletop-fusion-verify.hexa
domains/physics/millennium-riemann/verify_millennium-riemann.hexa
)
for f in "${MIGRATED[@]}"; do
if [ ! -f "$f" ]; then
echo "MISSING: $f"; exit 1
fi
out=$(mktemp --suffix=.hexa)
hexa scripts/flatten_imports_py.hexa "$f" "$out"
# Sanity: the flattened file must contain the SSOT block.
grep -q "let SIGMA = 12" "$out" || { echo "FAIL: SSOT block not inlined in $f"; exit 1; }
grep -q "let sigma = SIGMA" "$out" || { echo "FAIL: lowercase aliases not inlined in $f"; exit 1; }
done
echo "[n6-shared-constants] flatten preflight OK on ${#MIGRATED[@]} files"
# ── Job 3: CDO JSON validation ──────────────────────────────
cdo-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate CDO JSON structure
run: |
python3 - <<'PYEOF'
import json, glob, sys
CDO_REQUIRED = {"_meta"} # minimum CDO field
errors = []
json_files = glob.glob("canonshared/**/*.json", recursive=True) + \
glob.glob("experiments/**/*.json", recursive=True)
if not json_files:
print("No JSON files found to validate")
sys.exit(0)
for path in sorted(json_files):
try:
with open(path) as f:
data = json.load(f)
except json.JSONDecodeError as e:
errors.append(f" INVALID JSON: {path} ({e})")
continue
if not isinstance(data, dict):
continue # arrays are OK, skip CDO check
# CDO check: if file has _meta, validate its structure
if "_meta" in data:
meta = data["_meta"]
if not isinstance(meta, dict):
errors.append(f" BAD _meta (not dict): {path}")
elif "description" not in meta:
errors.append(f" _meta missing 'description': {path}")
print(f" OK (CDO): {path}")
else:
print(f" OK (plain): {path}")
if errors:
print("\nCDO validation errors:")
for e in errors:
print(e)
sys.exit(1)
else:
print(f"\nAll {len(json_files)} JSON files valid.")
PYEOF
# ── Job 4: own#17 β€” Public README English-only audit (HARD block) ──
# Enforces .own rule #17 (doc-english-required) across the 5-repo org.
# Tool: hexa-lang/tool/readme_english_audit.hexa (sister repo).
# Strategy: checkout hexa-lang alongside canon into a
# layout that mirrors $HOME/core/{repo}/ β€” the audit tool reads
# README.md from that fixed prefix (see tool header TARGETS block).
# hexa CLI is bootstrapped from hexa-lang source (same chain as
# hexa-lang/.github/workflows/bootstrap.yml Stage 0/1).
readme-english-audit:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout canon
uses: actions/checkout@v4
with:
path: canon
- name: Checkout hexa-lang (sister repo, tool source)
id: checkout-hexa
uses: actions/checkout@v4
with:
repository: dancinlab/hexa-lang
path: hexa-lang
continue-on-error: true
- name: Guard β€” hexa-lang checkout result
shell: bash
run: |
if [ ! -d hexa-lang/self ]; then
echo "::warning::hexa-lang checkout unavailable β€” readme-english-audit will SOFT-skip."
echo "HEXA_LANG_AVAILABLE=0" >> "$GITHUB_ENV"
else
echo "HEXA_LANG_AVAILABLE=1" >> "$GITHUB_ENV"
fi
- name: Checkout nexus (audit target)
uses: actions/checkout@v4
with:
repository: dancinlab/nexus
path: nexus
continue-on-error: true
- name: Checkout anima (audit target)
uses: actions/checkout@v4
with:
repository: dancinlab/anima
path: anima
continue-on-error: true
- name: Checkout papers (audit target)
uses: actions/checkout@v4
with:
repository: dancinlab/papers
path: papers
continue-on-error: true
- name: Cache hexa CLI binary
if: env.HEXA_LANG_AVAILABLE == '1'
uses: actions/cache@v4
id: hexa-cache
with:
path: |
${{ github.workspace }}/hexa-lang/hexa
${{ github.workspace }}/hexa-lang/self/native/hexa_v2
${{ github.workspace }}/hexa-lang/build
key: hexa-cli-${{ runner.os }}-${{ hashFiles('hexa-lang/self/**') }}
restore-keys: |
hexa-cli-${{ runner.os }}-
- name: Bootstrap hexa CLI (from hexa-lang source)
if: env.HEXA_LANG_AVAILABLE == '1' && steps.hexa-cache.outputs.cache-hit != 'true'
shell: bash
working-directory: hexa-lang
run: |
set -euo pipefail
mkdir -p self/native build/stage1
gcc -O2 -std=gnu11 -D_GNU_SOURCE -Wno-trigraphs \
-I self self/native/hexa_cc.c \
-o self/native/hexa_v2 \
-lm -ldl
./self/native/hexa_v2 self/main.hexa build/stage1/main.c
gcc -O2 -std=gnu11 -D_GNU_SOURCE -Wno-trigraphs \
-I self build/stage1/main.c \
-o hexa \
-lm -ldl
- name: Expose hexa CLI on PATH
if: env.HEXA_LANG_AVAILABLE == '1'
shell: bash
working-directory: hexa-lang
run: |
set -euo pipefail
test -x ./hexa || { echo "::error::hexa binary missing after cache+bootstrap"; exit 1; }
echo "$GITHUB_WORKSPACE/hexa-lang" >> "$GITHUB_PATH"
- name: Expose $HOME/core layout expected by audit tool
if: env.HEXA_LANG_AVAILABLE == '1'
shell: bash
run: |
set -euo pipefail
mkdir -p "$HOME/core"
ln -sfn "$GITHUB_WORKSPACE/canon" "$HOME/core/canon"
ln -sfn "$GITHUB_WORKSPACE/hexa-lang" "$HOME/core/hexa-lang"
[ -d "$GITHUB_WORKSPACE/nexus" ] && ln -sfn "$GITHUB_WORKSPACE/nexus" "$HOME/core/nexus" || true
[ -d "$GITHUB_WORKSPACE/anima" ] && ln -sfn "$GITHUB_WORKSPACE/anima" "$HOME/core/anima" || true
[ -d "$GITHUB_WORKSPACE/papers" ] && ln -sfn "$GITHUB_WORKSPACE/papers" "$HOME/core/papers" || true
ls -la "$HOME/core"
- name: Public README English-only audit (own#17)
if: env.HEXA_LANG_AVAILABLE == '1'
shell: bash
working-directory: hexa-lang
run: hexa tool/readme_english_audit.hexa
- name: SOFT-skip notice (hexa-lang unavailable)
if: env.HEXA_LANG_AVAILABLE != '1'
shell: bash
run: |
echo "::warning::readme-english-audit SOFT-skipped because hexa-lang checkout was unavailable."
echo "This is a graceful-degradation path; re-run once hexa-lang is reachable for HARD enforcement."
# ── Job 5: own#20 β€” .own drift detection (SOFT warn) ──
# Enforces .own rule #20 (drift-tracked). Tool: hexa-lang/tool/own_runner.hexa.
# SOFT: continue-on-error: true β€” drift is a lagging signal, not a merge
# blocker. Failure surfaces in Actions UI for triage.
own-drift-daily:
runs-on: ubuntu-latest
timeout-minutes: 15
continue-on-error: true
steps:
- name: Checkout canon
uses: actions/checkout@v4
with:
path: canon
- name: Checkout hexa-lang (tool source)
id: checkout-hexa
uses: actions/checkout@v4
with:
repository: dancinlab/hexa-lang
path: hexa-lang
continue-on-error: true
- name: Guard β€” hexa-lang checkout result
shell: bash
run: |
if [ ! -d hexa-lang/self ]; then
echo "::warning::hexa-lang checkout unavailable β€” own#20 drift detection will SOFT-skip."
echo "HEXA_LANG_AVAILABLE=0" >> "$GITHUB_ENV"
else
echo "HEXA_LANG_AVAILABLE=1" >> "$GITHUB_ENV"
fi
- name: Cache hexa CLI binary
if: env.HEXA_LANG_AVAILABLE == '1'
uses: actions/cache@v4
id: hexa-cache
with:
path: |
${{ github.workspace }}/hexa-lang/hexa
${{ github.workspace }}/hexa-lang/self/native/hexa_v2
${{ github.workspace }}/hexa-lang/build
key: hexa-cli-${{ runner.os }}-${{ hashFiles('hexa-lang/self/**') }}
restore-keys: |
hexa-cli-${{ runner.os }}-
- name: Bootstrap hexa CLI (from hexa-lang source)
if: env.HEXA_LANG_AVAILABLE == '1' && steps.hexa-cache.outputs.cache-hit != 'true'
shell: bash
working-directory: hexa-lang
run: |
set -euo pipefail
mkdir -p self/native build/stage1
gcc -O2 -std=gnu11 -D_GNU_SOURCE -Wno-trigraphs \
-I self self/native/hexa_cc.c \
-o self/native/hexa_v2 \
-lm -ldl
./self/native/hexa_v2 self/main.hexa build/stage1/main.c
gcc -O2 -std=gnu11 -D_GNU_SOURCE -Wno-trigraphs \
-I self build/stage1/main.c \
-o hexa \
-lm -ldl
- name: Expose hexa CLI on PATH
if: env.HEXA_LANG_AVAILABLE == '1'
shell: bash
working-directory: hexa-lang
run: |
set -euo pipefail
test -x ./hexa || { echo "::error::hexa binary missing after cache+bootstrap"; exit 1; }
echo "$GITHUB_WORKSPACE/hexa-lang" >> "$GITHUB_PATH"
- name: Drift detection β€” techniques + tests count (own#20)
if: env.HEXA_LANG_AVAILABLE == '1'
shell: bash
working-directory: canon
# own_runner.hexa lives in hexa-lang; invoked by absolute path.
# Runs from canon PWD so raw_loader picks up the local .own.
run: hexa "$GITHUB_WORKSPACE/hexa-lang/tool/own_runner.hexa" drift-all
- name: README nexus6 tests count drift (own#21)
if: always()
shell: bash
working-directory: canon
continue-on-error: true # SOFT β€” .own own#21 on_fail=warn
# Hexa comparator (raw 9 hexa-only): authoritative count from
# reports/n6_selftest.json#total vs README.md 'tests: N' tokens.
# Emits reports/n6_own21_drift.json for post-run triage.
run: hexa tool/own_nexus6_tests_drift.hexa --verbose
# ── Job 6: own#13 β€” OUROBOROS CRITICAL=0 enforcement (HARD block) ──
# Enforces .own rule #13 (R14 atlas acyclicity for CRITICAL prefixes).
# Tool: scripts/monotone/ouroboros_detector_v2.hexa.
# The script exits 1 when any CRITICAL cycle is detected and exits 0
# otherwise (ADVISORY cycles are warn-only); no --exit-on-critical
# flag is needed β€” that behaviour is the default contract.
# Pre-flight existence check prevents silent-pass if the script is
# absent on a branch (e.g., not yet merged from a worktree).
ouroboros-integrity:
runs-on: ubuntu-latest
timeout-minutes: 15
env:
HEXA_LOCAL: "1"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Detector existence precheck
shell: bash
run: |
set -euo pipefail
if [ ! -f scripts/monotone/ouroboros_detector_v2.hexa ]; then
echo "::error::scripts/monotone/ouroboros_detector_v2.hexa missing β€” cannot enforce own#13"
exit 1
fi
- name: Setup hexa CLI
uses: ./.github/actions/setup-hexa
- name: OUROBOROS CRITICAL=0 enforcement (own#13)
if: env.HEXA_AVAILABLE == '1'
run: hexa scripts/monotone/ouroboros_detector_v2.hexa
- name: SOFT-skip notice (hexa CLI unavailable)
if: env.HEXA_AVAILABLE != '1'
shell: bash
run: echo "::warning::own#13 SOFT-skipped because hexa CLI bootstrap was unavailable."
# ── Job 7: own#14 β€” README sealed-hash enforcement (HARD block) ──
# Enforces .own rule #14 (readme-sealed-required).
# Tool: tool/readme_sealed_check.hexa. README.md SHA-256 must match the
# value stored in README.md.sealed.hash. Drift β†’ exit 1 (merge blocked).
# Re-seal locally via: hexa tool/readme_sealed_check.hexa --update
readme-sealed-hash:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
HEXA_LOCAL: "1"
steps:
- uses: actions/checkout@v4
- name: Setup hexa CLI
uses: ./.github/actions/setup-hexa
- name: Verify README sealed hash (own#14)
if: env.HEXA_AVAILABLE == '1'
run: hexa tool/readme_sealed_check.hexa
- name: SOFT-skip notice (hexa CLI unavailable)
if: env.HEXA_AVAILABLE != '1'
shell: bash
run: echo "::warning::own#14 SOFT-skipped because hexa CLI bootstrap was unavailable."
# ── Job 7b: own#29 β€” readme-friendly-toolkit-required (HARD block) ──
# Closes README FU-4. Enforces .own rule #29 (readme-friendly-toolkit-
# required) β€” alien-grade alignment SSOT (P0). Dispatcher tool/own_doc_lint
# .hexa --rule 29 chains both:
# - tool/own29_readme_friendly_toolkit_lint.hexa (biology-only table)
# - tool/own29_multi_section_lint.hexa (multi-section, 32 rows)
# Drift β†’ exit 1 (merge blocked). HEXA_LOCAL=1 invokes bare-host REAL_HEXA
# via ~/.hx/bin/hexa resolver (avoids docker-daemon dependency on runner).
# Pure read-files / count-strings / exit workload β€” no darwin-specific
# _to_lower or shell ops; ubuntu-latest is sufficient (matches own#1 job).
# Active-enforcement: hexa CLI is bootstrapped via the .github/actions/
# setup-hexa composite action (sparse-checkout hexa-lang sister repo +
# 2-stage gcc bootstrap, mirrors own#17/own#20 jobs). SOFT-skip remains
# as graceful-degradation fallback when hexa-lang checkout is unreachable
# (e.g. private fork PR) β€” caller gates on env.HEXA_AVAILABLE == '1'.
readme-friendly-toolkit-29:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
HEXA_LOCAL: "1"
steps:
- uses: actions/checkout@v4
- name: Setup hexa CLI
uses: ./.github/actions/setup-hexa
- name: own#29 readme-friendly-toolkit-required (HARD)
if: env.HEXA_AVAILABLE == '1'
shell: bash
working-directory: ${{ github.workspace }}
run: |
set -euo pipefail
if hexa tool/own_doc_lint.hexa --rule 29; then
echo "own#29 lint PASS (biology-only + multi-section)"
else
rc=$?
echo "::error::own#29 readme-friendly-toolkit lint FAILED (exit ${rc}) β€” see log above for failing section/row."
exit "${rc}"
fi
- name: SOFT-skip notice (hexa CLI unavailable)
if: env.HEXA_AVAILABLE != '1'
shell: bash
run: |
echo "::warning::own#29 SOFT-skipped because hexa CLI is not installed on this runner."
# ── Job 8: own#1 β€” doc-english-required HARD block ──
# Hexa-native (raw 9): tool/own1_doc_english_lint.hexa via dispatcher --rule 1.
# Scope: domains/, theory/, reports/, experiments/, papers/, bridge/, canonshared/
# .md files. Legacy CJK files grandfathered via tool/own1_legacy_allowlist.json
# (frozen sidecar, 1050+ entries). New CJK content in any .md under decl scope
# fails the check and blocks merge.
own1-doc-english-hard:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
HEXA_LOCAL: "1"
steps:
- uses: actions/checkout@v4
- name: Setup hexa CLI
uses: ./.github/actions/setup-hexa
- name: own#1 doc-english-required (HARD)
if: env.HEXA_AVAILABLE == '1'
run: hexa tool/own_doc_lint.hexa --rule 1
- name: SOFT-skip notice (hexa CLI unavailable)
if: env.HEXA_AVAILABLE != '1'
shell: bash
run: echo "::warning::own#1 SOFT-skipped because hexa CLI bootstrap was unavailable."
# ── Job 9: own#2/#3/#4/#5/#6/#7/#8/#9/#10/#11/#12/#16/#29 β€” HARD (all auto) ──
# Hexa-native (raw 9, 14/14 dispatcher coverage). All auto-verifiable rules
# run in one linter pass. Pre-existing violations grandfathered via inline
# OWN{4,6,12}_LEGACY_ALLOWLIST sets in their respective per-rule hexa lints.
own-all-hard:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
HEXA_LOCAL: "1"
steps:
- uses: actions/checkout@v4
- name: Setup hexa CLI
uses: ./.github/actions/setup-hexa
- name: own#all auto-rules dispatcher (HARD)
if: env.HEXA_AVAILABLE == '1'
run: hexa tool/own_doc_lint.hexa
- name: SOFT-skip notice (hexa CLI unavailable)
if: env.HEXA_AVAILABLE != '1'
shell: bash
run: echo "::warning::own#all SOFT-skipped because hexa CLI bootstrap was unavailable."