Carry-Over Automation Seeds Cleanup — Trivy/Dependabot/Envelope (Critic Self-Contradiction Detection)
Key Decisions
Split into 4 PRs
Phase A/B/C/D each one-PR-one-responsibility — minimize regression risk. No single-PR compression
Close Phase A + defer redesign to Sprint 165
After Critic R1 P1 essential defect detection, immediately close. Avoid compressing essential redesign (build job load: true + multi-arch) into a single sprint. Apply priority (service stability > development speed)
Apply Critic R1 P2 fix immediately (Phase B)
Add equal coverage for blog Dockerfile — resolve the self-contradiction (blog is also CI-built + Trivy-scanned but not covered by dependabot) immediately
Envelope simplification (Phase C)
group has no score regex extraction pattern → always return status="failed" (simplified single envelope, consistency justified)
New PII/secret mock raw token leakage test
Introduce test_group_response_fallback_no_raw_exposure — explicitly verify all string values in envelope never contain raw tokens
Goal
- Clean up the top 3 carry-over automation seeds (#new1/#new2/#new3) accumulated in Sprint 157~163
- Seed #new1 — Enable Trivy scan at the PR stage (attempt to land Sprint 160 lesson #6)
- Seed #new2 — Add 5 docker entries to dependabot.yml (block the Sprint 159 missing base image refresh causal chain)
- Seed #new3 — Apply envelope to
_parse_group_response(recover Sprint 159 single-analysis envelope on the group side) - 5 user-facing UAT guides (visual validation of Sprint 161~163 new behaviors)
Decisions
- Split into 4 PRs: Phase A/B/C/D each one-PR-one-responsibility — minimize regression risk. No single-PR compression
- Close Phase A + defer redesign to Sprint 165: After Critic R1 P1 essential defect detection, immediately close. Avoid compressing essential redesign (build job
load: true+ multi-arch) into a single sprint. Apply priority (service stability > development speed) - Apply Critic R1 P2 fix immediately (Phase B): Add equal coverage for blog Dockerfile — resolve the self-contradiction (blog is also CI-built + Trivy-scanned but not covered by dependabot) immediately
- Envelope simplification (Phase C): group has no score regex extraction pattern → always return
status="failed"(simplified single envelope, consistency justified) - New PII/secret mock raw token leakage test: Introduce
test_group_response_fallback_no_raw_exposure— explicitly verify all string values in envelope never contain raw tokens
Implementation (4 PRs, 32 sprints consecutive branch discipline)
| PR | Phase | Branch | Result |
|---|---|---|---|
| #280 | A — Enable PR Trivy | chore/sprint-164-pr-trivy-enable | ❌ Closed (Critic R1 P1 essential defect → Sprint 165 redesign) |
| #281 | B — dependabot docker x6 | chore/sprint-164-dependabot-docker | ✅ Squash merge b13e6c5 |
| #282 | C — group envelope | fix/sprint-164-ai-analysis-group-envelope | ✅ Squash merge 12eb347 |
| #TBD | D — Sprint 164 ADR | docs/sprint-164-adr | This PR (architect + scribe) |
Phase A — PR-stage Trivy scan activation attempt (closed)
- Change:
.github/workflows/ci.yml:781if: github.ref == 'refs/heads/main' && !cancelled()→if: "!cancelled()" - Goal: Trivy SARIF upload on both PR + main → 1st-stage PR security regression detection (Sprint 160 lesson #6)
- Critic R1 P1 detected (codex review --commit 1e2e3c2):
Avoid scanning registry tags that PR builds never push (ci.yml:784). On
pull_request, build jobs still usepush: ${{ github.ref == 'refs/heads/main' }}, so they do not publishghcr.io/...:main-${{ github.sha }}. With this job now running for PRs, any changed service that reaches Trivy will try to pull a tag that was never pushed and fail before producing a useful security result. - Essential defect: PR build doesn't push to GHCR → Trivy tries to pull missing tag → fail. This PR produces noisy CI red, not a security gate = sprint goal self-contradiction
- Decision: Close PR + defer to Sprint 165 redesign (need 3-option comparison: build job
load: true+ Trivy local image scan, or PR-specific tag push, or buildx artifact + fs scan) - Lesson: A seemingly-simple 1-line
ifchange can require essential redesign when interacting with image registry policy
Phase B — dependabot.yml docker x6 additions
- Change:
.github/dependabot.ymldocker entries 2 → 8- Existing:
/services/gateway,/services/ai-analysis - New:
/services/identity,/services/submission,/services/problem,/services/github-worker,/frontend,/blog
- Existing:
- Common config: weekly Monday Asia/Seoul, labels
["dependencies", "docker"], commit prefixchore(docker), semver-major ignore - Critic R1 P2 detected (codex review --commit cdec0a2, session
019e3f46-4dad-73c0-911f-09066d212f60):Include the blog Dockerfile in Docker updates. CI builds and Trivy-scans a
blogimage from/blog/Dockerfile, but this new Docker coverage still omits/blog. If the blog image'snginxbase tag goes stale or vulnerable, the same Trivy failures this change is meant to prevent can still recur for blog. - Immediate fix (commit
0f81fb1): Add/blogdocker entry — resolve self-contradicting omission against this PR's causal-chain blocking goal - Critic R2 PASS ✅ — "No breaking or actionable issues were identified in the change"
- Merge: squash sha
b13e6c5
Phase C — _parse_group_response envelope application
- Change:
services/ai-analysis/src/claude_client.py:476-490(envelope pattern)- Before:
fallback = raw_text.strip()+ backtick strip +comparison: fallback[:50000](50KB raw exposure) - After:
comparison: "AI 그룹 분석 결과 파싱에 일시적 오류가 발생했습니다. 잠시 후 다시 시도해주세요."(zero raw body exposure) - logger.warning extra: only
raw_lengthrecorded (no raw body) - group has no score regex extraction pattern → always
status="failed"(simplified single envelope)
- Before:
- Tests (
services/ai-analysis/tests/test_claude_client.py):- 4 existing tests converted to envelope verification:
test_parse_group_response_invalid_json+test_parse_group_response_empty_string+test_group_response_fallback_backtick_no_closing+test_group_response_fallback_backtick_with_closing - 1 new:
test_group_response_fallback_no_raw_exposure— verify with PII/secret mock raw (hunter2/123-45-6789/sk-abc123def456/user_id=42) that no raw tokens leak into envelope string values
- 4 existing tests converted to envelope verification:
- Critic R1 PASS ✅ (codex review --commit, session
019e3f4a-92d5-7503-8dd3-e92f5ae18c78): "I did not find a discrete regression introduced by this commit" - Verification: pytest 79 PASS, claude_client.py coverage 99% maintained
Phase D — Sprint 164 ADR (this PR)
docs/adr/sprints/sprint-164.md(KR) +docs/adr-en/sprints/sprint-164.md(EN, this file, 1:1 mapping)docs/adr/README.mdupdate — count 103 → 104, range 62163 → 62164
Verification
| Item | Result |
|---|---|
| Phase B YAML syntax | ✅ docker entries 8 (2→8) |
| Phase B CI | 29 checks SUCCESS + SKIPPED |
| Phase B Critic R1 P2 → R2 | PASS ✅ |
| Phase C pytest | 79 PASS (5 group included) |
| Phase C claude_client.py coverage | 99% maintained |
| Phase C Critic R1 | PASS ✅ |
| check-adr-en-coverage --strict | 113/113 (100.0%) PASS (post Phase D) |
| check-doc-refs | 0 broken refs (post Phase D) |
| Branch discipline | ✅ 32 sprints consecutive, 0 direct main commits, 0 --no-verify |
Branch Discipline ✅ 32 Sprints Consecutive
- All 4 PRs use new branches + Squash merge (Phase A closed + branch deleted)
- 0 direct main commits, 0
--no-verify
New Patterns
- Critic R1 self-contradiction detection 2× per single sprint (Sprint 155/159/160 pattern reinforced) — Phase A essential defect (image tag missing) + Phase B blog equal coverage omission. Codex cross-validation's sprint consistency-guard effect confirmed 2× in this sprint
- PR close + Sprint 165 redesign deferral pattern — Even seemingly-simple 1-line change requires immediate close + separate sprint split when essential redesign is required. Avoid single-sprint compression (continues Sprint 161~163 3-sprint split policy)
- Cross-service envelope pattern recovery — Apply Sprint 159 single-analysis envelope to group side. Score regex extraction difference → simplification (group: always
status="failed"). Difference justification required when same pattern applied to different functions - PII/secret mock raw token leakage explicit verification — Strengthen envelope pattern's core promise (zero raw body exposure) via unit test. Regression-blocking gate (supplements Sprint 159 envelope's partial verification limitation)
- stash + branch switching multi-PR parallel handling — When Phase B Critic R1 P2 fix occurred, stash Phase C work → switch to Phase B → push fix → stash pop Phase C. Safe handling in multi-PR within single session
- codex CLI direct call backgrounding — Run
codex review --commit <sha>in background and proceed with next Phase in parallel. Hide Critic cycle processing time