From 6be515f87f5e2a5f341707f192fac9b824872214 Mon Sep 17 00:00:00 2001 From: Zzackllack Date: Mon, 15 Jun 2026 00:09:44 +0200 Subject: [PATCH 1/4] ci: improve pull request feedback workflows Add contributor-aware CODEOWNERS notices, detailed conventional title diagnostics, and formatted pytest and pylint failure comments. Fix application CODEOWNERS paths and document the revised CI behavior. --- .github/CODEOWNERS | 4 +- .github/CONTRIBUTING.md | 8 +- .github/workflows/codeowners-review.yml | 131 ++++++++++---------- .github/workflows/pr-test-feedback.yml | 40 +++--- .github/workflows/pr-title-conventional.yml | 46 +++++-- .github/workflows/pylint-quality.yml | 17 ++- internal/agents/change-log.md | 4 + internal/agents/release-ci.md | 18 +-- 8 files changed, 162 insertions(+), 106 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 05dba532..271fbee2 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -18,8 +18,8 @@ /docker-compose*.yaml @Zzackllack # Application code and tests -/app/ @Zzackllack -/tests/ @Zzackllack +/apps/api/app/ @Zzackllack +/apps/api/tests/ @Zzackllack # Cloudflare Worker /src/ @Zzackllack diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index fe40cd5c..132ecd12 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -78,7 +78,10 @@ We follow the Conventional Commits specification: https://www.conventionalcommit ## Codeowners -The codeowners for this repository are listed in the [CODEOWNERS](/.github/CODEOWNERS) file. Please update it as necessary when making changes to the codebase. +The codeowners for this repository are listed in the [CODEOWNERS](/.github/CODEOWNERS) file. +CODEOWNERS records ongoing review responsibility; it is not a list of every contributor. +Do not add yourself only because you opened a pull request. Maintainers may add recurring +contributors when they take ownership of an area. Conventions and tips you should follow when editing the CODEOWNERS file: @@ -87,6 +90,9 @@ Conventions and tips you should follow when editing the CODEOWNERS file: - Only `CODEOWNERS`, `.github/CODEOWNERS`, or `docs/CODEOWNERS` are recognized by GitHub. - Use @org/team for teams. +External contributors who are not listed receive an informational pull request comment. The +CODEOWNERS check only blocks malformed rules or owner references that GitHub cannot resolve. + ## Pull Request Process 1. Fork the repository and create a new branch. diff --git a/.github/workflows/codeowners-review.yml b/.github/workflows/codeowners-review.yml index f93ca6bb..841e7002 100644 --- a/.github/workflows/codeowners-review.yml +++ b/.github/workflows/codeowners-review.yml @@ -30,11 +30,10 @@ jobs: continue-on-error: true uses: actions/github-script@v9 env: - COMMENT_MARKER: "" + COMMENT_MARKER: "" with: script: | const fs = require('node:fs'); - const path = require('node:path'); const { owner, repo } = context.repo; const issue_number = context.payload.pull_request.number; const candidates = ['.github/CODEOWNERS', 'CODEOWNERS', 'docs/CODEOWNERS']; @@ -141,58 +140,6 @@ jobs: } } - const globToRegex = (pattern) => { - let result = '^'; - for (let i = 0; i < pattern.length; i += 1) { - const char = pattern[i]; - const next = pattern[i + 1]; - if (char === '*' && next === '*') { - result += '.*'; - i += 1; - } else if (char === '*') { - result += '[^/]*'; - } else if (char === '?') { - result += '[^/]'; - } else if ('\\.[]{}()+-^$|'.includes(char)) { - result += `\\${char}`; - } else { - result += char; - } - } - result += '$'; - return new RegExp(result); - }; - - const matches = (pattern, file) => { - if (pattern === '*') { - return true; - } - - const normalized = pattern.replace(/^\/+/, ''); - if (normalized.endsWith('/')) { - return file.startsWith(normalized); - } - - return globToRegex(normalized).test(file); - }; - - const files = await github.paginate(github.rest.pulls.listFiles, { - owner, - repo, - pull_number: issue_number, - per_page: 100, - }); - - const candidatePaths = files - .filter((file) => ['added', 'renamed', 'copied'].includes(file.status)) - .map((file) => file.filename); - - const fallbackOnly = candidatePaths.filter((filename) => { - const matchedRules = rules.filter((rule) => matches(rule.pattern, filename)); - const hasSpecificRule = matchedRules.some((rule) => rule.pattern !== '*'); - return matchedRules.length > 0 && !hasSpecificRule; - }); - const findings = []; if (invalidLines.length > 0) { findings.push( @@ -211,15 +158,6 @@ jobs: findings.push(` - \`${entry.owner}\` on line ${entry.lineNumber}`); } } - if (fallbackOnly.length > 0) { - findings.push( - '- The following added or renamed paths are only covered by the global `*` fallback:', - ); - for (const filename of fallbackOnly) { - findings.push(` - \`${filename}\``); - } - } - if (findings.length === 0) { return; } @@ -231,7 +169,7 @@ jobs: '', ...findings, '', - 'If the fallback ownership is intentional, update `CODEOWNERS` to add an explicit rule or adjust this check.', + 'This check only blocks malformed or unresolved ownership rules.', ].join('\n'); fs.writeFileSync('codeowners-comment.md', `${body}\n`, 'utf8'); @@ -241,7 +179,7 @@ jobs: if: always() uses: actions/github-script@v9 env: - COMMENT_MARKER: "" + COMMENT_MARKER: "" with: script: | const fs = require('node:fs'); @@ -298,6 +236,69 @@ jobs: ); } + - name: Sync new contributor ownership notice + if: always() && steps.validate.outcome == 'success' + uses: actions/github-script@v9 + env: + COMMENT_MARKER: "" + with: + script: | + const fs = require('node:fs'); + const { owner, repo } = context.repo; + const issue_number = context.payload.pull_request.number; + const marker = process.env.COMMENT_MARKER; + const author = context.payload.pull_request.user.login; + const association = context.payload.pull_request.author_association; + const trustedAssociations = new Set(['OWNER', 'MEMBER', 'COLLABORATOR']); + const candidates = ['.github/CODEOWNERS', 'CODEOWNERS', 'docs/CODEOWNERS']; + const codeownersPath = candidates.find((candidate) => fs.existsSync(candidate)); + const raw = codeownersPath ? fs.readFileSync(codeownersPath, 'utf8') : ''; + const authorRef = `@${author}`.toLowerCase(); + const listedAsOwner = raw + .split(/\r?\n/) + .filter((line) => line.trim() && !line.trim().startsWith('#')) + .some((line) => + line.trim().split(/\s+/).slice(1).some((entry) => entry.toLowerCase() === authorRef), + ); + const files = await github.paginate(github.rest.pulls.listFiles, { + owner, + repo, + pull_number: issue_number, + per_page: 100, + }); + const changedCodeowners = files.some((file) => file.filename === codeownersPath); + const shouldComment = + !trustedAssociations.has(association) && !listedAsOwner && !changedCodeowners; + const body = [ + marker, + `### CODEOWNERS note for @${author}`, + '', + `Thanks for contributing. You are not currently listed in \`${codeownersPath}\`.`, + '', + 'You do **not** need to add yourself for this pull request. CODEOWNERS represents ongoing review responsibility, not a list of everyone who has contributed.', + '', + 'A maintainer can add you later if you take recurring ownership of an area.', + ].join('\n'); + + try { + const comments = await github.paginate(github.rest.issues.listComments, { + owner, repo, issue_number, per_page: 100, + }); + const existing = comments.find((comment) => + comment.user?.type === 'Bot' && comment.body?.includes(marker), + ); + + if (shouldComment && existing) { + await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body }); + } else if (shouldComment) { + await github.rest.issues.createComment({ owner, repo, issue_number, body }); + } else if (existing) { + await github.rest.issues.deleteComment({ owner, repo, comment_id: existing.id }); + } + } catch (error) { + core.warning(`Skipping contributor ownership notice: ${error.message}`); + } + - name: Enforce CODEOWNERS validation if: steps.validate.outcome == 'failure' run: exit 1 diff --git a/.github/workflows/pr-test-feedback.yml b/.github/workflows/pr-test-feedback.yml index 409b0d8b..caffb3da 100644 --- a/.github/workflows/pr-test-feedback.yml +++ b/.github/workflows/pr-test-feedback.yml @@ -1,9 +1,10 @@ -name: QA / PR Test Feedback +name: QA / PR Feedback on: workflow_run: workflows: - QA / Tests + - QA / Pylint Score types: - completed @@ -17,8 +18,8 @@ concurrency: cancel-in-progress: false jobs: - sync-pytest-feedback: - name: Sync Pytest Feedback + sync-qa-feedback: + name: Sync QA Feedback if: github.event.workflow_run.event == 'pull_request' runs-on: ubuntu-latest steps: @@ -31,6 +32,9 @@ jobs: core.setOutput('pr_number', pullRequest ? String(pullRequest.number) : ''); core.setOutput('conclusion', context.payload.workflow_run.conclusion || ''); core.setOutput('run_url', context.payload.workflow_run.html_url || ''); + const isPylint = context.payload.workflow_run.name === 'QA / Pylint Score'; + core.setOutput('tool', isPylint ? 'Pylint' : 'Pytest'); + core.setOutput('marker', ``); if (!pullRequest) { core.setOutput('artifact_id', ''); @@ -39,7 +43,7 @@ jobs: const { owner, repo } = context.repo; const run_id = context.payload.workflow_run.id; - const artifactName = `pytest-output-pr-${pullRequest.number}`; + const artifactName = `${isPylint ? 'pylint' : 'pytest'}-output-pr-${pullRequest.number}`; const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, { owner, repo, @@ -49,7 +53,7 @@ jobs: const artifact = artifacts.find((item) => item.name === artifactName); core.setOutput('artifact_id', artifact ? String(artifact.id) : ''); - - name: Download pytest output artifact + - name: Download QA output artifact if: steps.context.outputs.conclusion == 'failure' && steps.context.outputs.artifact_id != '' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -60,37 +64,39 @@ jobs: set -euo pipefail gh api \ -H "Accept: application/vnd.github+json" \ - "/repos/${REPO}/actions/artifacts/${ARTIFACT_ID}/zip" > pytest-output.zip - unzip -p pytest-output.zip pytest-output.txt > pytest-output.raw.txt - mv pytest-output.raw.txt pytest-output.txt + "/repos/${REPO}/actions/artifacts/${ARTIFACT_ID}/zip" > qa-output.zip + unzip -p qa-output.zip > qa-output.txt - name: Build pull request feedback body if: steps.context.outputs.pr_number != '' env: CONCLUSION: ${{ steps.context.outputs.conclusion }} RUN_URL: ${{ steps.context.outputs.run_url }} + TOOL: ${{ steps.context.outputs.tool }} + MARKER: ${{ steps.context.outputs.marker }} shell: bash run: | set -euo pipefail - marker='' { - echo "${marker}" + echo "${MARKER}" + echo "### ${TOOL} check failed" + echo if [ "${CONCLUSION}" = "failure" ]; then - echo "Pytest failed for this pull request." + echo "${TOOL} failed for this pull request. The relevant output is included below." else - echo "Pytest passed for this pull request." + echo "${TOOL} passed for this pull request." fi echo - echo "Run details: ${RUN_URL}" - if [ "${CONCLUSION}" = "failure" ] && [ -s pytest-output.txt ]; then + echo "[Open the full workflow run](${RUN_URL})" + if [ "${CONCLUSION}" = "failure" ] && [ -s qa-output.txt ]; then echo - echo "
Pytest output" + echo "
${TOOL} output" echo echo '```text' python - <<'PY' from pathlib import Path - output = Path("pytest-output.txt").read_text(encoding="utf-8", errors="replace") + output = Path("qa-output.txt").read_text(encoding="utf-8", errors="replace") max_chars = 50000 if len(output) > max_chars: print("(truncated to the last 50000 characters)") @@ -108,7 +114,7 @@ jobs: if: steps.context.outputs.pr_number != '' uses: actions/github-script@v9 env: - COMMENT_MARKER: "" + COMMENT_MARKER: ${{ steps.context.outputs.marker }} PR_NUMBER: ${{ steps.context.outputs.pr_number }} CONCLUSION: ${{ steps.context.outputs.conclusion }} with: diff --git a/.github/workflows/pr-title-conventional.yml b/.github/workflows/pr-title-conventional.yml index 28d1602b..2c603911 100644 --- a/.github/workflows/pr-title-conventional.yml +++ b/.github/workflows/pr-title-conventional.yml @@ -33,9 +33,21 @@ jobs: if [[ "${PR_TITLE}" =~ ${pattern} ]]; then echo "PR title is valid: ${PR_TITLE}" + echo "reason=" >> "${GITHUB_OUTPUT}" exit 0 fi + reason="The title does not match \`type(scope): description\`." + invalid_scope_pattern='^[a-z]+\([^)]*[,[:space:]][^)]*\)' + if [[ ! "${PR_TITLE}" =~ ^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test) ]]; then + reason="The title must start with an allowed lowercase type." + elif [[ "${PR_TITLE}" =~ ${invalid_scope_pattern} ]]; then + reason="The scope must be one lowercase token; commas and spaces are not allowed." + elif [[ ! "${PR_TITLE}" =~ ^[^:]+:\ .+ ]]; then + reason="The header must contain a colon followed by one space and a description." + fi + echo "reason=${reason}" >> "${GITHUB_OUTPUT}" + echo "Pull request title must follow Conventional Commits." echo "Received: ${PR_TITLE}" echo @@ -58,23 +70,33 @@ jobs: uses: actions/github-script@v9 env: COMMENT_MARKER: "" - COMMENT_BODY: | - - Please update this pull request title to follow the Conventional Commits specification. - - Examples: - - `feat(api): add torrent health endpoint` - - `fix: handle missing provider aliases` - - `refactor(parser)!: remove legacy AniWorld slug fallback` - - Reference: - - https://www.conventionalcommits.org/en/v1.0.0/ + PR_TITLE: ${{ github.event.pull_request.title }} + FAILURE_REASON: ${{ steps.validate.outputs.reason }} with: script: | const { owner, repo } = context.repo; const issue_number = context.payload.pull_request.number; const marker = process.env.COMMENT_MARKER; - const body = process.env.COMMENT_BODY; + const safeTitle = process.env.PR_TITLE.replaceAll('`', '\\`'); + const body = [ + marker, + '### Pull request title needs attention', + '', + `**Received:** \`${safeTitle}\``, + '', + `**Why it failed:** ${process.env.FAILURE_REASON}`, + '', + '**Expected:** `type(scope): description` or `type: description`', + '', + 'Allowed types: `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test`.', + '', + 'Examples:', + '- `feat(api): add torrent health endpoint`', + '- `fix: handle missing provider aliases`', + '- `refactor(parser)!: remove legacy AniWorld slug fallback`', + '', + '[Conventional Commits reference](https://www.conventionalcommits.org/en/v1.0.0/)', + ].join('\n'); const shouldComment = '${{ steps.validate.outcome }}' === 'failure'; const { data: comments } = await github.rest.issues.listComments({ diff --git a/.github/workflows/pylint-quality.yml b/.github/workflows/pylint-quality.yml index 7f71565f..c6d71884 100644 --- a/.github/workflows/pylint-quality.yml +++ b/.github/workflows/pylint-quality.yml @@ -48,9 +48,11 @@ jobs: working-directory: apps/api/app run: | set -o pipefail - uv run pylint . | tee ../pylint-output.txt || true + uv run pylint . 2>&1 | tee ../pylint-output.txt || true - name: Enforce minimum pylint score + id: score + continue-on-error: true run: | set -euo pipefail SCORE=$(sed -nE 's/.*rated at ([0-9]+\.[0-9]+)\/10.*/\1/p' apps/api/pylint-output.txt | tail -n1) @@ -68,3 +70,16 @@ jobs: } echo "pylint score gate passed: score $SCORE > 7.5" + + - name: Upload pylint failure output + if: github.event_name == 'pull_request' && steps.score.outcome == 'failure' + uses: actions/upload-artifact@v7 + with: + name: pylint-output-pr-${{ github.event.pull_request.number }} + path: apps/api/pylint-output.txt + if-no-files-found: error + retention-days: 7 + + - name: Enforce pylint success + if: steps.score.outcome == 'failure' + run: exit 1 diff --git a/internal/agents/change-log.md b/internal/agents/change-log.md index 7a7430d6..69eb21ae 100644 --- a/internal/agents/change-log.md +++ b/internal/agents/change-log.md @@ -1,5 +1,9 @@ # Change Log +- 2026-06-15: Revised PR feedback automation so CODEOWNERS distinguishes + structural failures from contributor notices, pytest and pylint failures + receive formatted output comments, and PR title failures explain the rejected + format. - 2026-04-13: Documented the new `app/hosts` package and clarified the naming split between catalogue-site providers and direct video hosts. - 2026-03-22: Documented automatic Serienstream Turnstile handling for protected diff --git a/internal/agents/release-ci.md b/internal/agents/release-ci.md index af620e44..bfa6b603 100644 --- a/internal/agents/release-ci.md +++ b/internal/agents/release-ci.md @@ -54,16 +54,18 @@ For Pull Request preview links in Cloudflare's native PR status comment, use - `tests.yml`: runs `cd apps/api && uv sync --frozen`, executes pytest, and uploads captured failure output for pull request feedback. It ignores `v*` release-tag pushes. -- `pr-test-feedback.yml`: posts or updates a pull request comment when - `tests.yml` fails on a PR, including the pytest output in a collapsed Markdown - details block, and removes the comment automatically once the test run passes. -- `codeowners-review.yml`: checks pull requests for malformed `CODEOWNERS` - rules, invalid or unresolved owner references, and newly added or renamed - paths that are covered only by the global fallback rule, then posts or - refreshes a remediation comment on the PR. +- `pr-test-feedback.yml`: posts or updates tool-specific pull request comments + when `tests.yml` or `pylint-quality.yml` fails, includes captured output in a + collapsed Markdown details block, and removes each comment once its check + passes. +- `codeowners-review.yml`: blocks malformed `CODEOWNERS` rules and invalid or + unresolved owner references. It separately posts an informational notice for + external contributors who are not listed as recurring code owners; fallback + ownership alone is not treated as a failure. - `format-and-run.yml`: runs `cd apps/api && ruff format app tests` and auto-commits formatting changes. - `pylint-quality.yml`: enforces the pylint score gate on branch pushes and pull - requests, but ignores `v*` release-tag pushes. + requests, captures failure output for PR feedback, and ignores `v*` + release-tag pushes. - `format-and-run.yml`: runs `cd apps/api && ruff format app tests` and auto-commits formatting changes on branch pushes and pull requests, but ignores `v*` release-tag pushes. From f1b590ae7f4154647f6ae617a2c0f3d2ca2718cf Mon Sep 17 00:00:00 2001 From: Zzackllack Date: Mon, 15 Jun 2026 00:11:26 +0200 Subject: [PATCH 2/4] chore: remove change log file - not needed, see git history for changes --- internal/agents/change-log.md | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 internal/agents/change-log.md diff --git a/internal/agents/change-log.md b/internal/agents/change-log.md deleted file mode 100644 index 69eb21ae..00000000 --- a/internal/agents/change-log.md +++ /dev/null @@ -1,22 +0,0 @@ -# Change Log - -- 2026-06-15: Revised PR feedback automation so CODEOWNERS distinguishes - structural failures from contributor notices, pytest and pylint failures - receive formatted output comments, and PR title failures explain the rejected - format. -- 2026-04-13: Documented the new `app/hosts` package and clarified the naming - split between catalogue-site providers and direct video hosts. -- 2026-03-22: Documented automatic Serienstream Turnstile handling for protected - `/r?t=...` redirect tokens, including browser-like headers and configurable - backoff via `PROVIDER_CHALLENGE_BACKOFF_SECONDS`. -- 2026-03-22: Documented provider redirect retry/timeout controls for slow - `s.to` -> `VOE` resolution and noted the Sonarr `qBittorrent is reporting an - error` symptom when redirect resolution fails before download start. -- 2026-03-19: Documented the `aniworld` 4.1.1 migration, including the new - site-specific episode model split and the removal of `SpeedFiles` from the - default provider order. -- 2026-02-23: Documented Cloudflare PR preview URL requirements and enabled - `preview_urls` in `wrangler.toml`. -- 2026-01-25: Refactored AGENTS.md into progressive disclosure files under `internal/agents/`. -- 2025-12-21: Added uv guidance, improved formatting/phrasing, added `.env.example` reference, added Context7 reference, removed unused sections and optional pre-commit step. -- 2025-09-21: Rebuilt AGENTS.md to >=1000 lines, documented constitution alignment, added Cloudflare Workers/VitePress/CI/CD details, expanded env var catalog and file index. From 15fd33ef6f30dfd2c23dcaa65dd808166de83c84 Mon Sep 17 00:00:00 2001 From: Zzackllack Date: Mon, 15 Jun 2026 00:12:29 +0200 Subject: [PATCH 3/4] chore: remove stale, non-functional setup scripts --- scripts/setup-codex-overlay.sh | 476 --------------------------------- scripts/startup-script.sh | 67 ----- 2 files changed, 543 deletions(-) delete mode 100644 scripts/setup-codex-overlay.sh delete mode 100644 scripts/startup-script.sh diff --git a/scripts/setup-codex-overlay.sh b/scripts/setup-codex-overlay.sh deleted file mode 100644 index 8fd38ab9..00000000 --- a/scripts/setup-codex-overlay.sh +++ /dev/null @@ -1,476 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# ========================= -# UI helpers -# ========================= -color() { printf "\033[%sm%s\033[0m" "${1:-0}" "${2:-}"; } -info() { echo "$(color '1;36' '›')" "$@"; } -warn() { echo "$(color '1;33' '⚠')" "$@"; } -ok() { echo "$(color '1;32' '✓')" "$@"; } -err() { echo "$(color '1;31' '✗')" "$@"; } - -ask_yn() { # ask_yn "Question" default(no|yes) - local q="${1:-Proceed?}" d="${2:-no}" ans - case "$d" in - y|Y|yes) read -rp "$q [Y/n] " ans || true; [[ -z "${ans:-}" || "$ans" =~ ^[Yy]$ ]];; - *) read -rp "$q [y/N] " ans || true; [[ "$ans" =~ ^[Yy]$ ]];; - esac -} - -need_cmd() { command -v "$1" >/dev/null 2>&1 || { err "Required command '$1' not found in PATH."; return 1; }; } - -# ========================= -# Environment / detection -# ========================= -need_cmd ln -need_cmd awk -need_cmd sed -need_cmd date - -if ! command -v git >/dev/null 2>&1; then - warn "git not found — .gitignore guard can still work later via shell hooks." -fi - -if ! command -v codex >/dev/null 2>&1; then - warn "The 'codex' CLI was not found." - ask_yn "Continue anyway (you can install codex later)?" no || exit 1 -else - ok "codex found: $(command -v codex)" -fi - -DEFAULT_SHELL="${SHELL:-}" -[[ -z "$DEFAULT_SHELL" ]] && DEFAULT_SHELL="$(ps -p ${PPID:-$$} -o comm= 2>/dev/null || true)" -DEFAULT_SHELL_BASENAME="${DEFAULT_SHELL##*/}" - -choose_shells() { - local choices=() pick - command -v zsh >/dev/null 2>&1 && choices+=("zsh") - command -v bash >/dev/null 2>&1 && choices+=("bash") - if ((${#choices[@]}==0)); then - err "Neither zsh nor bash available. Aborting." - exit 1 - fi - info "Detected shells: ${choices[*]}" - if [[ " ${choices[*]} " == *" zsh "* ]]; then - pick="zsh" - else - pick="${choices[0]}" - fi - echo "$pick" -} - -PRIMARY_SHELL="$(choose_shells)" -info "Primary target shell: $PRIMARY_SHELL" - -RC_ZSH="${ZDOTDIR:-$HOME}/.zshrc" -RC_BASH="$HOME/.bashrc" -[[ -f "$HOME/.bashrc" || ! -f "$HOME/.bash_profile" ]] || RC_BASH="$HOME/.bash_profile" - -ZSH_SNIPPET="$HOME/.codex_overlay.zsh" -BASH_SNIPPET="$HOME/.codex_overlay.bash" -GLOBAL_HOME="$HOME/.codex" - -# ========================= -# Write snippets -# ========================= -write_zsh() { -cat >"$ZSH_SNIPPET" <<"ZSH_SNIP" -# --- Codex per-project overlay (zsh) ----------------------------------------- -# Keeps auth/logs/sessions in ~/.codex and overlays them into PROJECT/.codex -# while letting .codex/prompts (and optionally .codex/commands) stay local. - -export CODX_GLOBAL_HOME="$HOME/.codex" - -_codx_find_project_root() { - local dir="$PWD" - while [[ "$dir" != "/" ]]; do - [[ -d "$dir/.codex" || -d "$dir/.codex/prompts" || -d "$dir/.codex/commands" ]] && { print -r -- "$dir"; return 0; } - dir="${dir:h}" - done - return 1 -} - -_codx_overlay_global_into_project() { - local proj_codex="$1" - [[ -n "$proj_codex" ]] || return 1 - mkdir -p "$proj_codex" - mkdir -p "$proj_codex/prompts" - # mkdir -p "$proj_codex/commands" # uncomment if you want a local commands dir - - setopt local_options null_glob extended_glob - local src base dest - for src in "$CODX_GLOBAL_HOME"/^(prompts|commands)(N); do - base="${src:t}" - dest="$proj_codex/$base" - if [[ -e "$dest" && ! -L "$dest" ]]; then - continue - fi - ln -sfn -- "$src" "$dest" - done -} - -typeset -ga _CODX_GI_HEADER=( - "# Codex overlay: keep auth/logs in ~/.codex; only track per-project prompts/commands" - "# Ignore .codex/* but re-include .codex/prompts and .codex/commands below" -) - -typeset -ga _CODX_GI_RULES=( - ".codex/*" - "!.codex/prompts/" - "!.codex/prompts/**" - "!.codex/commands/" - "!.codex/commands/**" -) - -_codx_in_git_repo() { - command -v git >/dev/null 2>&1 || return 1 - git -C "$1" rev-parse --is-inside-work-tree >/dev/null 2>&1 -} - -_codx_gitignore_ensure_trailing_blankline() { - local gi="$1" - [[ -f "$gi" ]] || return 0 - if [[ -n "$(tail -c1 "$gi" 2>/dev/null)" ]]; then echo >> "$gi"; fi - if [[ -n "$(tail -n1 "$gi" | tr -d ' \t\r')" ]]; then echo >> "$gi"; fi -} - -_codx_gitignore_append_missing() { - local gi="$1" ; shift - [[ -f "$gi" ]] || : > "$gi" - _codx_gitignore_ensure_trailing_blankline "$gi" - local line missing=() - for line in "$@"; do - grep -Fqx -- "$line" "$gi" || missing+=("$line") - done - [[ ${#missing[@]} -eq 0 ]] && return 0 - if ! grep -Fqx -- "${_CODX_GI_HEADER[1]}" "$gi"; then - printf "%s\n" "${_CODX_GI_HEADER[@]}" >> "$gi" - echo >> "$gi" - print -u2 -- "✅ Inserted Codex header at end of $gi" - fi - for line in "${missing[@]}"; do - print -r -- "$line" >> "$gi" - done -} - -_codx_ensure_gitignore() { - local proj_root="$1" gi="$proj_root/.gitignore" - _codx_in_git_repo "$proj_root" || return 0 - local has_broad="" - if [[ -f "$gi" ]] && grep -Eq '^[[:space:]]*\.codex/?[[:space:]]*$' "$gi"; then - has_broad=1 - fi - local missing=() r - for r in "${_CODX_GI_RULES[@]}"; do - if [[ ! -f "$gi" ]] || ! grep -Fqx -- "$r" "$gi"; then - missing+=("$r") - fi - done - [[ -z "$has_broad" && ${#missing[@]} -eq 0 ]] && return 0 - - print -u2 -- "⚠️ Codex: .gitignore at $gi needs attention." - [[ -n "$has_broad" ]] && print -u2 -- " - Found a broad \".codex\" rule that prevents re-including prompts/commands." - (( ${#missing[@]} )) && print -u2 -- " - Missing recommended rules: ${missing[*]}" - - local reply - if [[ ! -f "$gi" ]]; then - read -q "reply?Create .gitignore with Codex header and rules now? [y/N] "; echo - if [[ "$reply" == [yY] ]]; then - : > "$gi" - _codx_gitignore_append_missing "$gi" "${_CODX_GI_RULES[@]}" - print -u2 -- "✅ Created $gi with Codex header and rules." - fi - return 0 - fi - - read -q "reply?Patch .gitignore (add Codex header, remove broad rule, append safe rules)? [y/N] "; echo - if [[ "$reply" == [yY] ]]; then - local ts backup tmp - ts=$(date +%Y%m%d-%H%M%S) - backup="$gi.bak_codex_$ts" - cp -p -- "$gi" "$backup" 2>/dev/null || cp -p "$gi" "$backup" - if [[ -n "$has_broad" ]]; then - tmp="$gi.tmp_codex_$ts" - awk '!/^[[:space:]]*\.codex\/?[[:space:]]*$/' "$gi" > "$tmp" && mv "$tmp" "$gi" - fi - _codx_gitignore_append_missing "$gi" "${_CODX_GI_RULES[@]}" - print -u2 -- "✅ Updated $gi (backup: $backup)" - else - print -u2 -- "ℹ️ Skipped updating $gi. Broad \".codex\" rules will hide prompts/commands from Git." - fi -} - -_codx_switch_codex_home() { - local proj_root proj_codex - if proj_root="$(_codx_find_project_root)"; then - proj_codex="$proj_root/.codex" - export CODEX_HOME="$proj_codex" - _codx_overlay_global_into_project "$proj_codex" - _codx_ensure_gitignore "$proj_root" - else - export CODEX_HOME="$CODX_GLOBAL_HOME" - fi -} - -autoload -Uz add-zsh-hook -add-zsh-hook chpwd _codx_switch_codex_home -_codx_switch_codex_home -# --- end Codex overlay (zsh) ------------------------------------------------ -ZSH_SNIP -} - -write_bash() { -cat >"$BASH_SNIPPET" <<"BASH_SNIP" -# --- Codex per-project overlay (bash) ---------------------------------------- -# Uses PROMPT_COMMAND to update CODEX_HOME on directory changes. - -export CODX_GLOBAL_HOME="$HOME/.codex" - -_codx_find_project_root() { - local dir="$PWD" - while [[ "$dir" != "/" ]]; do - if [[ -d "$dir/.codex" || -d "$dir/.codex/prompts" || -d "$dir/.codex/commands" ]]; then - printf '%s\n' "$dir"; return 0 - fi - dir="$(dirname "$dir")" - done - return 1 -} - -_codx_overlay_global_into_project() { - local proj_codex="$1" - [[ -n "$proj_codex" ]] || return 1 - mkdir -p "$proj_codex" - mkdir -p "$proj_codex/prompts" - # mkdir -p "$proj_codex/commands" # uncomment if you want a local commands dir - - shopt -s nullglob extglob - local src base dest - for src in "$CODX_GLOBAL_HOME"/!(prompts|commands); do - base="$(basename "$src")" - dest="$proj_codex/$base" - if [[ -e "$dest" && ! -L "$dest" ]]; then - continue - fi - ln -sfn -- "$src" "$dest" - done - shopt -u nullglob extglob -} - -_CODX_GI_HEADER_1="# Codex overlay: keep auth/logs in ~/.codex; only track per-project prompts/commands" -_CODX_GI_HEADER_2="# Ignore .codex/* but re-include .codex/prompts and .codex/commands below" - -declare -a _CODX_GI_RULES=( - ".codex/*" - "!.codex/prompts/" - "!.codex/prompts/**" - "!.codex/commands/" - "!.codex/commands/**" -) - -_codx_in_git_repo() { - command -v git >/dev/null 2>&1 || return 1 - git -C "$1" rev-parse --is-inside-work-tree >/dev/null 2>&1 -} - -_codx_gitignore_ensure_trailing_blankline() { - local gi="$1" - [[ -f "$gi" ]] || return 0 - if [[ -n "$(tail -c1 "$gi" 2>/dev/null || true)" ]]; then echo >> "$gi"; fi - if [[ -n "$(tail -n1 "$gi" | tr -d ' \t\r')" ]]; then echo >> "$gi"; fi -} - -_codx_gitignore_append_missing() { - local gi="$1"; shift - [[ -f "$gi" ]] || : > "$gi" - _codx_gitignore_ensure_trailing_blankline "$gi" - - local line missing=() - for line in "$@"; do - if ! grep -Fqx -- "$line" "$gi" 2>/dev/null; then - missing+=("$line") - fi - done - [[ ${#missing[@]} -eq 0 ]] && return 0 - - if ! grep -Fqx -- "$_CODX_GI_HEADER_1" "$gi" 2>/dev/null; then - printf "%s\n" "$_CODX_GI_HEADER_1" "$_CODX_GI_HEADER_2" >> "$gi" - echo >> "$gi" - >&2 echo "✅ Inserted Codex header at end of $gi" - fi - - for line in "${missing[@]}"; do - printf "%s\n" "$line" >> "$gi" - done -} - -_codx_ensure_gitignore() { - local proj_root="$1" gi="$proj_root/.gitignore" - _codx_in_git_repo "$proj_root" || return 0 - - local has_broad="" - if [[ -f "$gi" ]] && grep -Eq '^[[:space:]]*\.codex/?[[:space:]]*$' "$gi"; then - has_broad=1 - fi - - local missing=() r - for r in "${_CODX_GI_RULES[@]}"; do - if [[ ! -f "$gi" ]] || ! grep -Fqx -- "$r" "$gi"; then - missing+=("$r") - fi - done - - [[ -z "$has_broad" && ${#missing[@]} -eq 0 ]] && return 0 - - >&2 echo "⚠️ Codex: .gitignore at $gi needs attention." - [[ -n "$has_broad" ]] && >&2 echo " - Found a broad \".codex\" rule that prevents re-including prompts/commands." - (( ${#missing[@]} )) && >&2 echo " - Missing recommended rules: ${missing[*]}" - - local reply - if [[ ! -f "$gi" ]]; then - read -r -p "Create .gitignore with Codex header and rules now? [y/N] " reply - if [[ "$reply" =~ ^[Yy]$ ]]; then - : > "$gi" - _codx_gitignore_append_missing "$gi" "${_CODX_GI_RULES[@]}" - >&2 echo "✅ Created $gi with Codex header and rules." - fi - return 0 - fi - - read -r -p "Patch .gitignore (add Codex header, remove broad rule, append safe rules)? [y/N] " reply - if [[ "$reply" =~ ^[Yy]$ ]]; then - local ts backup tmp - ts="$(date +%Y%m%d-%H%M%S)" - backup="$gi.bak_codex_$ts" - cp -p -- "$gi" "$backup" 2>/dev/null || cp -p "$gi" "$backup" - if [[ -n "$has_broad" ]]; then - tmp="$gi.tmp_codex_$ts" - awk '!/^[[:space:]]*\.codex\/?[[:space:]]*$/' "$gi" > "$tmp" && mv "$tmp" "$gi" - fi - _codx_gitignore_append_missing "$gi" "${_CODX_GI_RULES[@]}" - >&2 echo "✅ Updated $gi (backup: $backup)" - else - >&2 echo "ℹ️ Skipped updating $gi. Broad \".codex\" rules will hide prompts/commands from Git." - fi -} - -_codx_switch_codex_home() { - local proj_root proj_codex - if proj_root="$(_codx_find_project_root)"; then - proj_codex="$proj_root/.codex" - export CODEX_HOME="$proj_codex" - _codx_overlay_global_into_project "$proj_codex" - _codx_ensure_gitignore "$proj_root" - else - export CODEX_HOME="$CODX_GLOBAL_HOME" - fi -} - -# Install PROMPT_COMMAND hook once -case "${PROMPT_COMMAND:-}" in - *_codx_switch_codex_home*) :;; - "") PROMPT_COMMAND="_codx_switch_codex_home";; - *) PROMPT_COMMAND="_codx_switch_codex_home; $PROMPT_COMMAND";; -esac - -# Run once for current shell -_codx_switch_codex_home -# --- end Codex overlay (bash) ----------------------------------------------- -BASH_SNIP -} - -mkdir -p "$GLOBAL_HOME" - -# Write/overwrite snippets only with consent -if [[ -f "$ZSH_SNIPPET" ]]; then - info "zsh snippet exists at $ZSH_SNIPPET" - if ask_yn "Overwrite zsh snippet with latest version?" no; then - write_zsh; ok "Updated $ZSH_SNIPPET" - fi -else - write_zsh; ok "Wrote $ZSH_SNIPPET" -fi - -if [[ -f "$BASH_SNIPPET" ]]; then - info "bash snippet exists at $BASH_SNIPPET" - if ask_yn "Overwrite bash snippet with latest version?" no; then - write_bash; ok "Updated $BASH_SNIPPET" - fi -else - write_bash; ok "Wrote $BASH_SNIPPET" -fi - -# ========================= -# Wire into RC files (ask!) -# ========================= -wire_rc() { - local rc="$1" snippet="$2" shellname="$3" - [[ -n "$rc" && -n "$snippet" ]] || return 0 - [[ -f "$snippet" ]] || return 0 - [[ -f "$rc" ]] || touch "$rc" - - # If RC already references our snippet, skip or offer to re-add - if grep -Fq "$snippet" "$rc"; then - info "$shellname RC already sources $snippet" - return 0 - fi - - # Heuristic: if RC already contains our function name (inline setup), - # warn and offer to skip adding another hook. - if grep -Fq "_codx_switch_codex_home" "$rc"; then - warn "$shellname RC already seems to contain a Codex overlay (inline)." - ask_yn "Add snippet sourcing anyway?" no || return 0 - else - ask_yn "Append snippet sourcing to $rc for $shellname?" yes || return 0 - fi - - local backup="${rc}.bak_codex_$(date +%Y%m%d-%H%M%S)" - cp -p "$rc" "$backup" 2>/dev/null || true - { - echo - echo "# Load Codex per-project overlay (installed by setup-codex-overlay.sh)" - if [[ "$shellname" == "zsh" ]]; then - echo "if [[ -f \"$snippet\" ]]; then source \"$snippet\"; fi" - else - echo "[ -f \"$snippet\" ] && source \"$snippet\"" - fi - } >> "$rc" - ok "Added source line to $rc (backup: $backup)" -} - -# Ask which shells to wire -TARGET_ZSH=false -TARGET_BASH=false - -if [[ "$PRIMARY_SHELL" == "zsh" ]]; then - TARGET_ZSH=true - ask_yn "Also install for bash RC?" no && TARGET_BASH=true -else - TARGET_BASH=true - ask_yn "Also install for zsh RC?" yes && TARGET_ZSH=true -fi - -$TARGET_ZSH && wire_rc "$RC_ZSH" "$ZSH_SNIPPET" "zsh" -$TARGET_BASH && wire_rc "$RC_BASH" "$BASH_SNIPPET" "bash" - -# ========================= -# Optional one-shot run now -# ========================= -echo -if ask_yn "Run a one-shot overlay + .gitignore check for THIS directory now?" yes; then - if [[ "$PRIMARY_SHELL" == "zsh" && $(command -v zsh) ]]; then - # Run in a separate zsh to avoid sourcing zsh code into bash - zsh -c "source '$ZSH_SNIPPET'; _codx_switch_codex_home" || true - elif [[ "$PRIMARY_SHELL" == "bash" && $(command -v bash) ]]; then - bash -c "source '$BASH_SNIPPET'; _codx_switch_codex_home" || true - else - warn "Primary shell not available for one-shot. Skipping." - fi -fi - -echo -ok "Codex per-project overlay setup finished." -info "To activate hooks in new terminals:" -echo " - zsh : run 'source \"$RC_ZSH\"' or open a new shell" -echo " - bash: run 'source \"$RC_BASH\"' or open a new shell" \ No newline at end of file diff --git a/scripts/startup-script.sh b/scripts/startup-script.sh deleted file mode 100644 index 38fa2b56..00000000 --- a/scripts/startup-script.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash -set -e - -echo "🚀 AniBridge Startup Script – Initializing Environment..." -echo "--------------------------------------------" - -# Check Python -if ! command -v python3 >/dev/null 2>&1; then - echo "❌ Python3 not found. Please install Python 3.11+" - exit 1 -fi -if ! command -v uv >/dev/null 2>&1; then - echo "❌ uv not found. Install it first: https://docs.astral.sh/uv/getting-started/installation/" - exit 1 -fi - -echo "✅ Python3 detected: $(python3 --version)" - -REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -API_DIR="$(cd "$(dirname "$0")/../apps/api" && pwd)" - -# Ensure Python version is >= 3.14 to match apps/api/pyproject.toml requires-python. -PYTHON_VERSION_OK=$(python3 -c 'import sys; print(int(sys.version_info >= (3, 14)))' || echo "0") -if [ "$PYTHON_VERSION_OK" != "1" ]; then - echo "❌ Python 3.14+ is required, but found: $(python3 --version 2>&1 || echo "unknown version")" - exit 1 -fi - -# Create virtual environment -echo "📦 Creating virtual environment..." -( - cd "$API_DIR" - uv venv -) - -# Install dependencies -echo "📦 Installing dependencies..." -( - cd "$API_DIR" - uv sync --frozen -) - -echo "✅ Dependencies installed." - -# Export environment variables -echo "⚙️ Setting environment variables..." -export LOG_LEVEL=DEBUG -export INDEXER_API_KEY="devkey" -export INDEXER_NAME="AniBridge" -export TORZNAB_CAT_ANIME=5070 -export DATA_DIR="$REPO_ROOT/data" -export DOWNLOAD_DIR="$REPO_ROOT/data/downloads" - -echo "✅ Environment variables set." - -# Startup message to Codex / LLM -echo "💡 Hey Codex, the environment is ready." -echo "💡 Python venv is active." -echo "💡 All dependencies are installed." -echo "💡 You can now start the AniBridge FastAPI server." - -# Start FastAPI -echo "🚀 Launching AniBridge..." -( - cd "$API_DIR" - uv run python -m app.main -) From 2236808dde34b339caf8e7c8bb98dfec3847b2d7 Mon Sep 17 00:00:00 2001 From: Zzackllack Date: Mon, 15 Jun 2026 00:47:20 +0200 Subject: [PATCH 4/4] fix(ci): address pull request workflow review feedback Improve QA artifact handling and comment messaging, harden PR title rendering, pin reviewed actions, and clean stale CI documentation. --- .github/workflows/codeowners-review.yml | 8 ++++---- .github/workflows/pr-test-feedback.yml | 15 ++++++++++++--- .github/workflows/pr-title-conventional.yml | 6 ++++-- .github/workflows/pylint-quality.yml | 2 +- AGENTS.md | 1 - internal/agents/release-ci.md | 3 --- internal/agents/repo-map.md | 2 -- 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/.github/workflows/codeowners-review.yml b/.github/workflows/codeowners-review.yml index 841e7002..4a4641d4 100644 --- a/.github/workflows/codeowners-review.yml +++ b/.github/workflows/codeowners-review.yml @@ -11,7 +11,7 @@ on: permissions: contents: read issues: write - pull-requests: write + pull-requests: read concurrency: group: codeowners-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -28,7 +28,7 @@ jobs: - name: Validate CODEOWNERS coverage id: validate continue-on-error: true - uses: actions/github-script@v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 env: COMMENT_MARKER: "" with: @@ -177,7 +177,7 @@ jobs: - name: Sync pull request CODEOWNERS comment if: always() - uses: actions/github-script@v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 env: COMMENT_MARKER: "" with: @@ -238,7 +238,7 @@ jobs: - name: Sync new contributor ownership notice if: always() && steps.validate.outcome == 'success' - uses: actions/github-script@v9 + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 env: COMMENT_MARKER: "" with: diff --git a/.github/workflows/pr-test-feedback.yml b/.github/workflows/pr-test-feedback.yml index caffb3da..c64c6b61 100644 --- a/.github/workflows/pr-test-feedback.yml +++ b/.github/workflows/pr-test-feedback.yml @@ -32,7 +32,12 @@ jobs: core.setOutput('pr_number', pullRequest ? String(pullRequest.number) : ''); core.setOutput('conclusion', context.payload.workflow_run.conclusion || ''); core.setOutput('run_url', context.payload.workflow_run.html_url || ''); - const isPylint = context.payload.workflow_run.name === 'QA / Pylint Score'; + const workflowName = context.payload.workflow_run.name; + const isPylint = workflowName === 'QA / Pylint Score'; + const isPytest = workflowName === 'QA / Tests'; + if (!isPylint && !isPytest) { + throw new Error(`Unsupported QA workflow: ${workflowName}`); + } core.setOutput('tool', isPylint ? 'Pylint' : 'Pytest'); core.setOutput('marker', ``); @@ -59,13 +64,17 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: ${{ github.repository }} ARTIFACT_ID: ${{ steps.context.outputs.artifact_id }} + TOOL: ${{ steps.context.outputs.tool }} shell: bash run: | set -euo pipefail gh api \ -H "Accept: application/vnd.github+json" \ "/repos/${REPO}/actions/artifacts/${ARTIFACT_ID}/zip" > qa-output.zip - unzip -p qa-output.zip > qa-output.txt + output_file="$(printf '%s' "${TOOL}" | tr '[:upper:]' '[:lower:]')-output.txt" + if ! unzip -p qa-output.zip "apps/api/${output_file}" > qa-output.txt; then + unzip -p qa-output.zip "${output_file}" > qa-output.txt + fi - name: Build pull request feedback body if: steps.context.outputs.pr_number != '' @@ -79,7 +88,7 @@ jobs: set -euo pipefail { echo "${MARKER}" - echo "### ${TOOL} check failed" + echo "### ${TOOL} check ${CONCLUSION}" echo if [ "${CONCLUSION}" = "failure" ]; then echo "${TOOL} failed for this pull request. The relevant output is included below." diff --git a/.github/workflows/pr-title-conventional.yml b/.github/workflows/pr-title-conventional.yml index 2c603911..ad49a652 100644 --- a/.github/workflows/pr-title-conventional.yml +++ b/.github/workflows/pr-title-conventional.yml @@ -77,12 +77,14 @@ jobs: const { owner, repo } = context.repo; const issue_number = context.payload.pull_request.number; const marker = process.env.COMMENT_MARKER; - const safeTitle = process.env.PR_TITLE.replaceAll('`', '\\`'); const body = [ marker, '### Pull request title needs attention', '', - `**Received:** \`${safeTitle}\``, + '**Received:**', + '```text', + process.env.PR_TITLE, + '```', '', `**Why it failed:** ${process.env.FAILURE_REASON}`, '', diff --git a/.github/workflows/pylint-quality.yml b/.github/workflows/pylint-quality.yml index c6d71884..17e1688b 100644 --- a/.github/workflows/pylint-quality.yml +++ b/.github/workflows/pylint-quality.yml @@ -73,7 +73,7 @@ jobs: - name: Upload pylint failure output if: github.event_name == 'pull_request' && steps.score.outcome == 'failure' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: pylint-output-pr-${{ github.event.pull_request.number }} path: apps/api/pylint-output.txt diff --git a/AGENTS.md b/AGENTS.md index 51fb890e..47058ddc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,7 +42,6 @@ More guidance - [Security & Legal](internal/agents/security-legal.md) - [Onboarding & Collaboration](internal/agents/onboarding-collaboration.md) - [References](internal/agents/references.md) -- [Change Log](internal/agents/change-log.md) Maintenance notice diff --git a/internal/agents/release-ci.md b/internal/agents/release-ci.md index bfa6b603..80c7dbb4 100644 --- a/internal/agents/release-ci.md +++ b/internal/agents/release-ci.md @@ -5,8 +5,6 @@ - `scripts/local_build_release.sh` — local artifact build helper. - `scripts/local_build_release.ps1` — PowerShell equivalent. - `scripts/release/cut_release.py` — authoritative semver bump helper used by CI. -- `scripts/setup-codex-overlay.sh` — agent overlay helper. -- `scripts/startup-script.sh` — example startup script. ## Build and Release @@ -62,7 +60,6 @@ For Pull Request preview links in Cloudflare's native PR status comment, use unresolved owner references. It separately posts an informational notice for external contributors who are not listed as recurring code owners; fallback ownership alone is not treated as a failure. -- `format-and-run.yml`: runs `cd apps/api && ruff format app tests` and auto-commits formatting changes. - `pylint-quality.yml`: enforces the pylint score gate on branch pushes and pull requests, captures failure output for PR feedback, and ignores `v*` release-tag pushes. diff --git a/internal/agents/repo-map.md b/internal/agents/repo-map.md index e2b7fc6d..b9efe983 100644 --- a/internal/agents/repo-map.md +++ b/internal/agents/repo-map.md @@ -56,8 +56,6 @@ - `local_build_release.sh` — local artifact build helper. - `local_build_release.ps1` — PowerShell equivalent. -- `setup-codex-overlay.sh` — agent overlay helper. -- `startup-script.sh` — example startup script. ## File Reference Index