# Feature detail: Ticket sync foundation **Parent roadmap:** [[../features-for-redmine_tickets-sync]] **Status:** largely implemented (2026-07-14); cron wiring still open **Primary script:** `redmine_tickets.py` **Target project (first):** `customer-service` ## Intent Durable, incremental local mirror of Redmine issues so humans and agents can work offline-first, cron-refresh frequently, and not re-pull full payloads for unchanged tickets. ## Requirements - Sync tickets updated within a window (e.g. past 30 days) into a **stable** cache path (not timestamped per run). - Skip full fetch when cached `updated_on` still matches the list stub. - Support frequent refresh (every few minutes / couple times per hour) using a tight remote window after the initial warm-up. - Never delete old ticket JSON unless explicitly asked. - Optional small run-stats ring buffer for cron observability. ## Cache locations | Environment | Path | |-------------|------| | Production (`https://rm.ldrprep.com`) | `/home/jason/projects/redmine/cache/redmine_tickets` | | Dev / LAN (`http://192.168.50.170`) | `/home/jason/projects/redmine/cache-dev/redmine_tickets` | Layout: ```text / manifest.json run-stats.json # optional, with --run-log / .json ``` ## Server-side vs local filters (sync) | Flag | Side | Meaning | |------|------|---------| | `--status-id` / `--remote-status-id` | **remote** | Redmine API `status_id` (`*`, `open`, `closed`, numeric) | | `--remote-updated-on` | **remote** | Raw Redmine syntax: `>=2026-06-14`, `>=2014-01-02T08:12:32Z`, `>=...` (YYYY-MM-DD, ISO, `30d`, `2 days ago`, …) | | `--remote-updated-before` | **remote** | Convenience → `<=...`; with since → `>/run-stats.json`, keep last N (`--run-log-keep`, default 3). ## Recommended commands ```bash cd /home/jason/projects/redmine # Initial 30-day window (server-side) ./redmine_tickets.py \ --base-url https://rm.ldrprep.com \ --project customer-service \ --cache-dir /home/jason/projects/redmine/cache/redmine_tickets \ sync \ --remote-status-id '*' \ --remote-updated-since 30d \ --run-log # Frequent refresh ./redmine_tickets.py \ --base-url https://rm.ldrprep.com \ --project customer-service \ --cache-dir /home/jason/projects/redmine/cache/redmine_tickets \ sync \ --remote-status-id '*' \ --remote-updated-since 2h \ --run-log \ --quiet ``` Raw Redmine form: ```bash ./redmine_tickets.py ... sync --remote-updated-on '>=2026-06-14' --status-id '*' ``` ## Open - [x] Scripts under `cron-scripts/` installed + crontab running (live + dev) - [ ] **ADJUST LATER (do not forget):** cron still uses `--remote-updated-since 30d` on a few-minute cadence. Fine while validating (~3–4s/run after warm cache) but should tighten to `2h`/`6h` (or marker-based since-last-success) so list pages stay cheap long-term. `run-log-keep 20` is already set. - [ ] Optional: master storage + symlink organization of JSON (see parent roadmap)