Twenty-four of the last sixty staging pushes were pure documentation, yet each
one ran (and cancelled) the full gate and image publish. Introduce
deploy/gated-paths.txt as the single source of truth for what must rerun the
gate: every Dockerfile COPY source, the Python package inputs, the workflow and
build-context files, and the repository files frontend/tests read at gate time.
Both triggers of backend-quality-gate.yml now carry that exact list; pushes
that touch none of it neither run the gate nor cancel a running code gate.
Because staging head may then legitimately sit ahead of the last tested SHA,
add deploy/is-docs-only-range.sh: it proves <base> is an ancestor of <head>
and that no changed path matches a gated glob, from local history when it is
available and otherwise from the Gitea compare API (per-commit `files`, parent
walk for ancestry, total_commits cross-checked). The publish dispatch and the
deploy-staging head checks accept an advanced head only when that script
succeeds; diverged, older, or code-bearing heads are still refused. In
deploy-staging the check runs after the gate-attested controller bundle is
extracted so only the tested checker and path list are ever executed; the
manual rollback branch is unchanged.
AGENTS.md §6.3/§6.4 describe the new contract: `.deployment.gitCommit` must
equal the latest staging commit that touched a gated path, not staging head.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VawU7Xfd5jS9wUEXz1XYmS
deploy/reclaim-runner-disk.sh ran `docker builder prune --force --all` at the
start of every gate job, so each publish rebuilt the Dockerfile `npm ci` layer
from scratch behind the registry mirror (7-minute image builds became 47).
Reclaim build cache in tiers instead: prune entries unused for 72h, re-measure
free space, and escalate to `--all` only while still below MINIMUM_FREE_GIB.
The final threshold check and the "only unheld resources" rules are unchanged.
Contract test asserts the aged prune runs first and that `--all` is only
reachable inside the re-measured conditional.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VawU7Xfd5jS9wUEXz1XYmS
Gitea (git.copse.top) is the only CI/CD control plane; GitHub is a
read-only mirror whose Actions are being disabled in repository settings.
- Delete all 11 `.github/workflows/*.yml` (stale copies of the old design).
- Delete unused Gitea manual workflows `ci.yml`, `test.yml`,
`publish-pypi.yml`, `apply-supabase-profile-migrations.yml`
(0-1 historical runs, no remaining target).
- Fold the full `python -m pytest` tree and `tests/run_all.py` into
`release-quality-gate.yml`, which previously only ran the curated
release profile; update the `run_quality_gate.py` comment accordingly.
- Port `reset-staging-account.yml` to Gitea: `runs-on: xiaoxin`, bounded
exact-SHA checkout, `refs/heads/staging` only, `staging-mutation`
concurrency, same email/confirmation/host/port/user/path assertions.
- Repoint frontend workflow tests at `.gitea/workflows/`, drop the
GitHub-only assertions, add coverage for the new reset workflow, and
remove `tests/test_supabase_profile_migration_workflow.py`.
- Update AGENTS.md §6.8, README.md, and deploy/README.md to the current
production/mirror facts and document the staging account reset.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VawU7Xfd5jS9wUEXz1XYmS
Keep async job and chart-cache files across API recreates, freeze jyotish_api_server.py growth, and fail fast with 429 when rectification or high-rigor compute is saturated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Homepage bootstrap never escaped the loading shell when a new web image changed chunk hashes. Stamp deploymentId, stop caching chat HTML, and hard-reload failed chunk loads once.
Co-authored-by: Cursor <cursoragent@cursor.com>
Staging publish failed resolving python:3.12-slim through m.daocloud.io; the web image already uses the reachable SWR docker.io/library path.
Co-authored-by: Cursor <cursoragent@cursor.com>
Manual SKILL.md updates were blocked by registry sha256 and a byte-equal versions/ gate. Consult now loads the operator-maintained tree; rectification and personal-report stay hashed.
Co-authored-by: Cursor <cursoragent@cursor.com>
xiaoxin's 20-core npm test opened one Docker network per database file and exhausted default address pools. Limit concurrent fixtures and remove unused jyotisha-postgres networks before the gate.
Co-authored-by: Cursor <cursoragent@cursor.com>
Next's output file tracing pulls skills/ into .next/standalone with symlinks
resolved into real directories. The final stage copies the standalone bundle
into /app first, so the later explicit `COPY skills /app/skills` tries to put
the tracked symlink skills/jyotish-vedic-astrology/assets -> ../../assets on
top of a real directory. Whether that is fatal depends on the BuildKit
snapshotter: GitHub's runners tolerate it, Docker 29.1.3 with
containerd-overlayfs refuses with "cannot replace to directory ... with file".
Dropping the traced copy after the build lets the explicit COPY own that tree
deterministically. /app/assets still comes from the standalone bundle, which
outputFileTracingIncludes guarantees, so the symlink resolves.
Verified by building the image and inspecting it: skills/ complete at 1208
files, assets still a symlink that resolves, container boots on Next.js
16.3.1 and serves / with HTTP 200. Reproduced the original failure on the
pre-upgrade commit too, so it predates the Next 16.3.1 upgrade.
Co-authored-by: Cursor <cursoragent@cursor.com>
The staging host currently has .state/deployed-revision unreadable by the
deploy user, so the forward-only revision check failed with 'Permission
denied' before it could compare revisions. Treat an unreadable state file
like a missing one and discover the running revision from the web
container's GITHUB_SHA, in both the workflow step and the server-side
deploy/migration scripts.
- IDENTITY_TEST_OTP env: when set to a 6-digit code, no real email is
delivered; login page surfaces the fixed code so testers can register
and sign in without a mailbox. Opt-in, never set in production.
- email-otp-login: test-channel notice with the pinned code.
- Rectification candidate list restyled with the project design system
(warm canvas, action color, display serif, soft shadow, hover lift).
- Regression tests for config parsing, pinned OTP generation, login UI
notice, and candidate card styles.