# Add agent-shell-quote-reply and DWIM context prefill for queue-compose #125
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, dev] | |
| pull_request: | |
| branches: [main] | |
| jobs: | |
| readme-updated: | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check README.org updated when code changes | |
| run: | | |
| base="${{ github.event.pull_request.base.sha }}" | |
| head="${{ github.event.pull_request.head.sha }}" | |
| changed_files=$(git diff --name-only "$base" "$head") | |
| has_code_changes=false | |
| for f in $changed_files; do | |
| case "$f" in | |
| *.el|tests/*) has_code_changes=true; break ;; | |
| esac | |
| done | |
| if "$has_code_changes"; then | |
| if ! echo "$changed_files" | grep -q '^README\.org$'; then | |
| echo "::error::Code or test files changed but README.org was not updated." | |
| echo "Please update the soft-fork features list in README.org." | |
| exit 1 | |
| fi | |
| fi | |
| agent-symlinks: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Verify agent config symlinks | |
| run: | | |
| ok=true | |
| for dir in .claude .codex .gemini; do | |
| target=$(readlink "${dir}" 2>/dev/null) | |
| if [[ "${target}" != ".agents" ]]; then | |
| echo "::error::${dir} should symlink to .agents but points to '${target:-<missing>}'" | |
| ok=false | |
| fi | |
| done | |
| for md in CLAUDE.md CODEX.md GEMINI.md; do | |
| target=$(readlink "${md}" 2>/dev/null) | |
| if [[ "${target}" != "AGENTS.md" ]]; then | |
| echo "::error::${md} should symlink to AGENTS.md but points to '${target:-<missing>}'" | |
| ok=false | |
| fi | |
| done | |
| if ! [[ -d .agents/commands ]]; then | |
| echo "::error::.agents/commands/ directory missing" | |
| ok=false | |
| fi | |
| if [[ "${ok}" != "true" ]]; then | |
| exit 1 | |
| fi | |
| echo "All agent config symlinks verified." | |
| dependency-dag: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Verify require graph is a DAG (no cycles) | |
| run: | | |
| # Build the set of project-internal modules from *.el filenames. | |
| declare -A project_modules | |
| for f in *.el; do | |
| mod="${f%.el}" | |
| project_modules["${mod}"]=1 | |
| done | |
| # Parse (require 'foo) from each file and build an adjacency list. | |
| # Only track edges where both ends are project-internal. | |
| # The regex anchors the (require to whitespace-only line prefix | |
| # so semicolon comments and strings can't fake an edge. It | |
| # captures only the first require per line; multi-require lines | |
| # are not used in this codebase. | |
| declare -A edges # edges["a"]="b c" means a requires b and c | |
| for f in *.el; do | |
| mod="${f%.el}" | |
| deps="" | |
| while IFS= read -r dep; do | |
| if [[ -n "${project_modules[$dep]+x}" ]]; then | |
| deps="${deps} ${dep}" | |
| fi | |
| done < <(sed -nE "s/^[[:space:]]*\\(require '([a-zA-Z0-9_-]+)\\).*/\\1/p" "$f") | |
| edges["${mod}"]="${deps}" | |
| done | |
| # DFS cycle detection. | |
| declare -A color # white=unvisited, gray=in-stack, black=done | |
| found_cycle="" | |
| cycle_path="" | |
| dfs() { | |
| local node="$1" | |
| local path="$2" | |
| color["${node}"]="gray" | |
| for neighbor in ${edges["${node}"]}; do | |
| if [[ "${color[$neighbor]:-white}" == "gray" ]]; then | |
| found_cycle=1 | |
| cycle_path="${path} -> ${neighbor}" | |
| return | |
| fi | |
| if [[ "${color[$neighbor]:-white}" == "white" ]]; then | |
| dfs "${neighbor}" "${path} -> ${neighbor}" | |
| if [[ -n "${found_cycle}" ]]; then | |
| return | |
| fi | |
| fi | |
| done | |
| color["${node}"]="black" | |
| } | |
| for mod in "${!project_modules[@]}"; do | |
| if [[ "${color[$mod]:-white}" == "white" ]]; then | |
| dfs "${mod}" "${mod}" | |
| if [[ -n "${found_cycle}" ]]; then | |
| echo "::error::Dependency cycle detected: ${cycle_path}" | |
| exit 1 | |
| fi | |
| fi | |
| done | |
| echo "Dependency graph is a DAG — no cycles found." | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/checkout@v4 | |
| with: | |
| repository: timvisher-dd/acp.el-plus | |
| path: deps/acp.el | |
| - uses: actions/checkout@v4 | |
| with: | |
| repository: xenodium/shell-maker | |
| path: deps/shell-maker | |
| # Pin to the Package-Requires floor (v2.5) so CI catches code that | |
| # silently depends on a newer markdown-mode. bin/test auto-discovers | |
| # whatever's installed locally and may pick up something newer. | |
| - uses: actions/checkout@v4 | |
| with: | |
| repository: jrblevin/markdown-mode | |
| ref: v2.5 | |
| path: deps/markdown-mode | |
| - uses: purcell/setup-emacs@master | |
| with: | |
| version: 29.4 | |
| - name: Remove stale .elc files | |
| run: find . deps -follow -name '*.elc' -print0 | xargs -0 rm -f | |
| - name: Byte-compile | |
| run: | | |
| compile_files=() | |
| for f in *.el; do | |
| case "$f" in x.*|y.*|z.*) ;; *) compile_files+=("$f") ;; esac | |
| done | |
| emacs -Q --batch \ | |
| -L . -L deps/acp.el -L deps/shell-maker -L deps/markdown-mode \ | |
| -f batch-byte-compile \ | |
| "${compile_files[@]}" | |
| - name: Run ERT tests | |
| run: | | |
| test_args=() | |
| for f in tests/*-tests.el; do | |
| test_args+=(-l "$f") | |
| done | |
| emacs -Q --batch \ | |
| -L . -L deps/acp.el -L deps/shell-maker -L deps/markdown-mode -L tests \ | |
| "${test_args[@]}" \ | |
| -f ert-run-tests-batch-and-exit |