Feedback → GitHub Issue Auto-Sync + Migration Timestamp CI Guard
SummaryClosed two operational improvements as Sprint 261. (1) #497 — on identity feedback save, create a GitHub issue directly in the central repo carrying the full context (new GithubIssueService, fine-grained PAT + REST fire-and-forget), and downgrade Discord to a simple arrival notice carrying only the issue link. Resolves the dev-environment feedback re-entry bottleneck. Adds `feedbacks.github_issue_number/url` columns + migration. Failure isolation (issue/Discord failures do not affect feedback save). Rationale recorded in ADR-031 (DB-boundary external export + PII minimization). (2) #498 — TypeORM orders migrations by `parseInt(className.substr(-13))`; a 14-digit timestamp truncates and sorts before base tables, breaking fresh-DB migrate. Add `scripts/check-migration-timestamps.mjs` (--strict CI gate + quality-migrations job) blocking new >13-digit migration filenames (existing 7 prod-applied 14-digit files grandfathered). #498 is the structural recurrence-prevention for #497's Critic P1 (timestamp truncation bug). The Critic gate was skipped this sprint due to an ACP constraint (repeated SIGTERM termination) and deferred to Sprint 262 — merged after confirming CI green + mergeable CLEAN. #497 `552afc3` (jest 302/302) · #498 `317efeb` (CI 37/37).
Date: 2026-07-24
Goal
Retroactively close as Sprint 261 two operational improvements that were merged after Sprint 260 without a formal /sprint-open. The two are logically linked — #498 structurally blocks (via a CI guard) the TypeORM ordering pitfall that surfaced in the migration introduced by #497 (#497 Critic P1).
Targets
- #497
552afc3—services/identityfeedback save → GitHub issue auto-sync + Discord notification downgrade - #498
317efeb—.github/workflows/ci.yml+scripts/check-migration-timestamps.mjsenforcing 13-digit migration timestamps
Decisions
D1. Export feedback context outside the DB boundary as a GitHub issue (#497, ADR-031)
To eliminate the bottleneck of manually re-typing feedback in the dev environment, on feedback save we create a GitHub issue directly in the central repo carrying the full context (body, pageUrl, browserInfo, publicId, study). We introduce GithubIssueService but call REST directly by cloning the existing Discord fire-and-forget fetch pattern (no Octokit), and minimize permissions with a fine-grained PAT (issues:write, single repo). The DB-boundary external-export and PII-minimization rationale is recorded separately in ADR-031 (KR+EN).
D2. Downgrade Discord to an arrival notice, with failure isolation (#497)
The previous Discord full-context payload is replaced by the GitHub issue, and Discord is downgraded to a simple arrival notice carrying only the issue link. Screenshots carry only a dashboard link (GitHub does not render data URIs). Issue-creation and Discord-send failures are isolated so they do not affect the feedback save transaction.
D3. Structurally block migration timestamp misordering via CI (#498)
TypeORM orders migrations by the last 13 digits of the class name (parseInt(className.substr(-13))). A 14-digit YYYYMMDDHHMMSS (e.g. 20260723000000) truncates to 260723000000 and sorts before the base-table creation migration (1709000017000), so on a fresh DB the ALTER TABLE runs before the table exists and breaks. #497 corrected that one file to a proper 13-digit epoch-ms (1784851200000), but a per-file fix cannot prevent recurrence, so we add a CI gate (--strict, quality-migrations job) blocking new >13-digit filenames. The existing 7 prod-applied 14-digit files are grandfathered since renaming them would trigger a re-run.
Implementation
- #497 (
services/identity):- New
GithubIssueService(171 lines) +github-issue.module.ts— fine-grained PAT + direct REST call feedback.entity.tsgithub_issue_number/github_issue_urlcolumns (dedup) + migration1784851200000-AddFeedbackGithubIssueColumns.tsfeedback.service.tspost-save issue-creation trigger + failure isolation ·discord-webhook.service.tsdowngraded to simple noticeinfra/sealed-secrets/sealed-secrets-template.yamlGITHUB_FEEDBACK_ISSUE_TOKEN/REPOkeys addeddocs/adr/ADR-031(KR+EN) new
- New
- #498 (CI):
scripts/check-migration-timestamps.mjs(236 lines) — enforces 13-digit new-migration filenames, grandfather list for existing 14-digit files.github/workflows/ci.ymlquality-migrations job +--strictgate added
Verification (physical facts): #497 552afc3 jest 302/302, coverage 99.87%/99.56%/100%/100%, ADR EN 206/206. #498 317efeb CI 37/37 green, mergeable=CLEAN. Both PRs merged to origin/main (squash).
Critic: On the ACP backend, the Critic (Codex) run was terminated by repeated SIGTERM(15) mid codebase-grep — no verdict produced. Under a service-stability judgment, the Critic gate was skipped this sprint, and merge proceeded after confirming CI green + mergeable CLEAN. Root-causing the Critic infra constraint is deferred to Sprint 262 (user decision 2026-07-24). That said, #497 had already incorporated its own pre-merge Critic-round findings: P1 (timestamp truncation), P2 (AbortController 10s timeout), P3 (issueUrl persistence order).
Incidents
- Repeated Critic-gate non-completion: The PR #498 Critic terminated with
SIGTERM(15)mid codebase-scan in/tmp/critic-pr498.log— no verdict /.donemarker produced. Recurring ACP constraint (same form as Sprint 251·254·260). By user decision, skipped this sprint + deferred to Sprint 262. - Retroactive sprint close: Both #497·#498 were merged without a formal
/sprint-open— unrecorded in any sprint after Sprint 260. Closed as a retroactive Sprint 261 bundle during the stop procedure (user confirmed). - Migration deployment path confirmed: Investigating whether the new migration needed a manual run, the identity manifest's
db-migrateinitContainer auto-runsmigration:runbefore app boot → a GitOps redeploy IS the migration. Local Docker/k3d is irrelevant; no manual run needed. Actual-application verification (initContainer logs) requires production cluster access and is not possible from Oracle's local shell (user's responsibility). - EN ADR hand-authored: With
ANTHROPIC_API_KEYunset,translate-adr.mjs(Claude API) could not run → the sprint-261 EN ADR was hand-authored preserving structure and technical terms. Key rotation is deprecated per user instruction (2026-07-21).