From 12f9fb73341c8891ca7382fe1ce0cd9fbba0d722 Mon Sep 17 00:00:00 2001 From: jlightner Date: Mon, 30 Mar 2026 11:24:34 +0000 Subject: [PATCH] =?UTF-8?q?chore:=20Added=20GIT=5FCOMMIT=5FSHA=20build=20a?= =?UTF-8?q?rg=20to=20Dockerfile.api,=20compose=20build=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - "docker/Dockerfile.api" - "docker-compose.yml" - "backend/config.py" - "backend/pipeline/stages.py" GSD-Task: S03/T01 --- .gsd/PROJECT.md | 1 + .gsd/milestones/M006/M006-ROADMAP.md | 2 +- .../milestones/M006/slices/S02/S02-SUMMARY.md | 91 +++++++++++++++ .gsd/milestones/M006/slices/S02/S02-UAT.md | 55 +++++++++ .../M006/slices/S02/tasks/T02-VERIFY.json | 24 ++++ .gsd/milestones/M006/slices/S03/S03-PLAN.md | 26 ++++- .../M006/slices/S03/S03-RESEARCH.md | 107 ++++++++++++++++++ .../M006/slices/S03/tasks/T01-PLAN.md | 36 ++++++ .../M006/slices/S03/tasks/T01-SUMMARY.md | 81 +++++++++++++ .../M006/slices/S03/tasks/T02-PLAN.md | 29 +++++ 10 files changed, 450 insertions(+), 2 deletions(-) create mode 100644 .gsd/milestones/M006/slices/S02/S02-SUMMARY.md create mode 100644 .gsd/milestones/M006/slices/S02/S02-UAT.md create mode 100644 .gsd/milestones/M006/slices/S02/tasks/T02-VERIFY.json create mode 100644 .gsd/milestones/M006/slices/S03/S03-RESEARCH.md create mode 100644 .gsd/milestones/M006/slices/S03/tasks/T01-PLAN.md create mode 100644 .gsd/milestones/M006/slices/S03/tasks/T01-SUMMARY.md create mode 100644 .gsd/milestones/M006/slices/S03/tasks/T02-PLAN.md diff --git a/.gsd/PROJECT.md b/.gsd/PROJECT.md index 26e4467..b21e73e 100644 --- a/.gsd/PROJECT.md +++ b/.gsd/PROJECT.md @@ -35,3 +35,4 @@ Five milestones complete. The system is deployed and running on ub01 at `http:// | M003 | Domain + DNS + Per-Stage LLM Model Routing | ✅ Complete | | M004 | UI Polish, Bug Fixes, Technique Page Redesign, and Article Versioning | ✅ Complete | | M005 | Pipeline Dashboard, Technique Page Redesign, Key Moment Cards | ✅ Complete | +| M006 | Admin Nav, Pipeline Log Views, Commit SHA, Tag Polish, Topics Redesign, Footer | 🔄 Active | diff --git a/.gsd/milestones/M006/M006-ROADMAP.md b/.gsd/milestones/M006/M006-ROADMAP.md index 2ccefe5..d989b6c 100644 --- a/.gsd/milestones/M006/M006-ROADMAP.md +++ b/.gsd/milestones/M006/M006-ROADMAP.md @@ -7,7 +7,7 @@ Consolidate admin navigation into a dropdown, add head/tail log viewing and comm | ID | Slice | Risk | Depends | Done | After this | |----|-------|------|---------|------|------------| | S01 | Admin Navigation Dropdown + Header Cleanup | low | — | ✅ | Header shows Home, Topics, Creators, and an Admin dropdown. Clicking Admin reveals Review, Reports, Pipeline links. ModeToggle removed from header. | -| S02 | Pipeline Page: Head/Tail Log View + Token Count | low | — | ⬜ | Pipeline event log shows Head/Tail toggle buttons. Head shows first N events, Tail shows last N events. Token counts visible per event and per video. | +| S02 | Pipeline Page: Head/Tail Log View + Token Count | low | — | ✅ | Pipeline event log shows Head/Tail toggle buttons. Head shows first N events, Tail shows last N events. Token counts visible per event and per video. | | S03 | Git Commit SHA in Pipeline Version Metadata | low | — | ⬜ | Running the pipeline captures the current git commit SHA. Viewing a technique page version shows the commit hash in the metadata panel. | | S04 | Technique Page: Sidebar Reorder, Creator Emphasis, Tag Polish | medium | — | ⬜ | Technique page sidebar shows Plugins Referenced at top. Creator name is visually prominent. Tags use a coherent color system. | | S05 | Topics Page Redesign + Music Theory Category | high | — | ⬜ | Topics page shows 7 categories (including Music Theory) with an improved visual layout — category cards with descriptions, sub-topic counts, better structure. | diff --git a/.gsd/milestones/M006/slices/S02/S02-SUMMARY.md b/.gsd/milestones/M006/slices/S02/S02-SUMMARY.md new file mode 100644 index 0000000..b61c552 --- /dev/null +++ b/.gsd/milestones/M006/slices/S02/S02-SUMMARY.md @@ -0,0 +1,91 @@ +--- +id: S02 +parent: M006 +milestone: M006 +provides: + - Pipeline events endpoint supports order=asc|desc query parameter + - EventLog component has Head/Tail view mode toggle +requires: + [] +affects: + [] +key_files: + - backend/routers/pipeline.py + - frontend/src/api/public-client.ts + - frontend/src/pages/AdminPipeline.tsx + - frontend/src/App.css +key_decisions: + - Used explicit string validation with 400 response for order param rather than FastAPI Literal/Enum, consistent with existing endpoint param style + - Placed segmented toggle between event count and refresh button in the header row for natural scan order +patterns_established: + - (none) +observability_surfaces: + - none +drill_down_paths: + - .gsd/milestones/M006/slices/S02/tasks/T01-SUMMARY.md + - .gsd/milestones/M006/slices/S02/tasks/T02-SUMMARY.md +duration: "" +verification_result: passed +completed_at: 2026-03-30T11:16:39.374Z +blocker_discovered: false +--- + +# S02: Pipeline Page: Head/Tail Log View + Token Count + +**Added Head/Tail toggle to pipeline event log — Head shows oldest events first (asc), Tail shows newest (desc) — with backend `order` query parameter, segmented toggle UI, and preserved token count display.** + +## What Happened + +Two-task slice adding chronological viewing to the pipeline event log. + +**T01 (Backend):** Added `order` query parameter (asc/desc, default desc) to `GET /admin/pipeline/events/{video_id}`. Explicit string validation returns 400 for invalid values. Default remains desc for backward compatibility. Deployed and verified against live API on ub01. + +**T02 (Frontend):** Added `viewMode` state (head/tail) to the EventLog component with a segmented toggle button UI. Head passes `order=asc`, Tail passes `order=desc`. Switching mode resets pagination offset to 0. API client updated to pass the `order` param. Segmented button CSS uses existing CSS custom properties. Token counts per-event and per-video remain visible and unchanged. + +The slice is intentionally minimal — two files touched on the backend, three on the frontend. No schema changes, no new models, no new dependencies. + +## Verification + +All slice-level verification checks passed: + +1. **order=asc** — `curl 'http://ub01:8096/api/v1/admin/pipeline/events/{vid}?order=asc&limit=3'` returns events with ascending timestamps (earliest: 2026-03-30T09:39:36, stage2_segmentation start) +2. **order=desc** — Same endpoint with `order=desc` returns most recent events first (latest: 2026-03-30T10:34:31, stage5_synthesis complete) +3. **order=invalid** — Returns HTTP 400 +4. **No order param** — Defaults to desc (backward compatible) +5. **Frontend build** — `npm run build` exits 0, zero TypeScript errors, 786ms build time +6. **Token counts** — API response includes prompt_tokens, completion_tokens, total_tokens on llm_call events (confirmed in asc/desc responses) + +## Requirements Advanced + +None. + +## Requirements Validated + +None. + +## New Requirements Surfaced + +None. + +## Requirements Invalidated or Re-scoped + +None. + +## Deviations + +None. + +## Known Limitations + +None. + +## Follow-ups + +None. + +## Files Created/Modified + +- `backend/routers/pipeline.py` — Added order query parameter (asc/desc, default desc) to list_pipeline_events with validation and dynamic ordering +- `frontend/src/api/public-client.ts` — Added order param to fetchPipelineEvents params type and URL builder +- `frontend/src/pages/AdminPipeline.tsx` — Added viewMode state, Head/Tail segmented toggle, order param wiring, and pagination reset on mode switch +- `frontend/src/App.css` — Added segmented toggle button CSS (.pipeline-events__view-toggle, .pipeline-events__view-btn) diff --git a/.gsd/milestones/M006/slices/S02/S02-UAT.md b/.gsd/milestones/M006/slices/S02/S02-UAT.md new file mode 100644 index 0000000..bdbbf87 --- /dev/null +++ b/.gsd/milestones/M006/slices/S02/S02-UAT.md @@ -0,0 +1,55 @@ +# S02: Pipeline Page: Head/Tail Log View + Token Count — UAT + +**Milestone:** M006 +**Written:** 2026-03-30T11:16:39.374Z + +## UAT: Pipeline Page Head/Tail Log View + Token Count + +### Preconditions +- Chrysopedia stack running on ub01 (`docker ps --filter name=chrysopedia` shows all services healthy) +- At least one video has been processed through the pipeline (has pipeline events) +- Browser can reach http://ub01:8096 + +### Test 1: Head/Tail Toggle Visibility +1. Navigate to http://ub01:8096 +2. Open Admin dropdown → click Pipeline +3. Expand any video with pipeline events +4. **Expected:** Event log header shows "Head" and "Tail" buttons between the event count and the refresh button +5. **Expected:** "Tail" button is active by default (highlighted/selected state) + +### Test 2: Tail Mode (Default) Shows Newest First +1. With Tail selected, observe the event timestamps +2. **Expected:** Events are ordered newest-first (descending `created_at`) +3. **Expected:** First event shown is from the latest pipeline stage (e.g., stage5_synthesis complete) + +### Test 3: Head Mode Shows Oldest First +1. Click the "Head" button +2. **Expected:** Head button becomes active, Tail becomes inactive +3. **Expected:** Events reorder to oldest-first (ascending `created_at`) +4. **Expected:** First event shown is from the earliest pipeline stage (e.g., stage2_segmentation start) + +### Test 4: Mode Switch Resets Pagination +1. In Tail mode, click "Next" to advance to page 2+ +2. Click "Head" button +3. **Expected:** View jumps back to page 1 (offset resets to 0) +4. **Expected:** Events shown are the first page of oldest-first results + +### Test 5: Pagination Works in Both Modes +1. In Head mode, click Next/Prev to page through events +2. **Expected:** Pagination works correctly — Next advances, Prev goes back +3. Switch to Tail mode, repeat +4. **Expected:** Same pagination behavior in Tail mode + +### Test 6: Token Counts Visible +1. In either mode, look at event rows with `event_type: llm_call` +2. **Expected:** Token counts (prompt_tokens, completion_tokens, total_tokens) displayed on the row +3. Look at the video summary row +4. **Expected:** Aggregate token count visible per video + +### Test 7: API — Invalid Order Parameter +1. Run: `curl -s -w '\n%{http_code}' 'http://ub01:8096/api/v1/admin/pipeline/events/{video_id}?order=invalid'` +2. **Expected:** HTTP 400 response + +### Test 8: API — Backward Compatibility +1. Run: `curl -sf 'http://ub01:8096/api/v1/admin/pipeline/events/{video_id}?limit=3' | python3 -m json.tool` +2. **Expected:** Returns events in descending order (same as `?order=desc`) — no breaking change for callers omitting the parameter diff --git a/.gsd/milestones/M006/slices/S02/tasks/T02-VERIFY.json b/.gsd/milestones/M006/slices/S02/tasks/T02-VERIFY.json new file mode 100644 index 0000000..b7ed5c7 --- /dev/null +++ b/.gsd/milestones/M006/slices/S02/tasks/T02-VERIFY.json @@ -0,0 +1,24 @@ +{ + "schemaVersion": 1, + "taskId": "T02", + "unitId": "M006/S02/T02", + "timestamp": 1774869322092, + "passed": false, + "discoverySource": "task-plan", + "checks": [ + { + "command": "cd frontend", + "exitCode": 0, + "durationMs": 6, + "verdict": "pass" + }, + { + "command": "npm run build exits 0 with no TypeScript errors", + "exitCode": 254, + "durationMs": 89, + "verdict": "fail" + } + ], + "retryAttempt": 1, + "maxRetries": 2 +} diff --git a/.gsd/milestones/M006/slices/S03/S03-PLAN.md b/.gsd/milestones/M006/slices/S03/S03-PLAN.md index 71e9a49..db395d8 100644 --- a/.gsd/milestones/M006/slices/S03/S03-PLAN.md +++ b/.gsd/milestones/M006/slices/S03/S03-PLAN.md @@ -1,6 +1,30 @@ # S03: Git Commit SHA in Pipeline Version Metadata -**Goal:** Record git commit SHA in pipeline metadata for traceability of prompt/code state at synthesis time +**Goal:** Pipeline captures the current git commit SHA at Docker build time, includes it in pipeline version metadata, and the frontend displays it in the version metadata panel. **Demo:** After this: Running the pipeline captures the current git commit SHA. Viewing a technique page version shows the commit hash in the metadata panel. ## Tasks +- [x] **T01: Added GIT_COMMIT_SHA build arg to Dockerfile.api, compose build args for api/worker, config field, and _get_git_commit_sha() helper — pipeline metadata now includes git_commit_sha key** — Add GIT_COMMIT_SHA build arg to Dockerfile.api, pass it from docker-compose.yml, write it to /app/.git-commit. Add a helper function in stages.py that reads the SHA from the file (Docker) or runs `git rev-parse --short HEAD` (local dev) with fallback to "unknown". Extend `_capture_pipeline_metadata()` to include the `git_commit_sha` key. Add `git_commit_sha` setting to config.py as an additional fallback. + +**Important context for executor:** The canonical codebase is on ub01 at `/vmPool/r/repos/xpltdco/chrysopedia`. SSH with `ssh ub01` to edit files and test. The Docker compose stack runs there. The local working directory has .gsd/ planning artifacts only. + +Steps: +1. SSH to ub01, edit `docker/Dockerfile.api` — add `ARG GIT_COMMIT_SHA=unknown` and `RUN echo "${GIT_COMMIT_SHA}" > /app/.git-commit` after the `COPY backend/ /app/` line +2. Edit `docker-compose.yml` — add `args: GIT_COMMIT_SHA: ${GIT_COMMIT_SHA:-unknown}` to both `chrysopedia-api` and `chrysopedia-worker` build sections (they already have `build: context: . dockerfile: docker/Dockerfile.api`) +3. Edit `backend/config.py` — add `git_commit_sha: str = "unknown"` field to Settings class +4. Edit `backend/pipeline/stages.py` — add `_get_git_commit_sha()` helper that tries: (a) read `/app/.git-commit` file, (b) run `subprocess.run(['git', 'rev-parse', '--short', 'HEAD'])`, (c) return `get_settings().git_commit_sha`, (d) return `"unknown"`. Add `"git_commit_sha": _get_git_commit_sha()` to the dict returned by `_capture_pipeline_metadata()` +5. Verify: run `python -c "from pipeline.stages import _capture_pipeline_metadata; print(_capture_pipeline_metadata())"` from backend dir (should show git_commit_sha key) + - Estimate: 30m + - Files: docker/Dockerfile.api, docker-compose.yml, backend/config.py, backend/pipeline/stages.py + - Verify: ssh ub01 'cd /vmPool/r/repos/xpltdco/chrysopedia/backend && python -c "from pipeline.stages import _capture_pipeline_metadata; import json; m = _capture_pipeline_metadata(); assert \"git_commit_sha\" in m, f\"missing key: {m.keys()}\"; print(json.dumps(m, indent=2))"' +- [ ] **T02: Display commit SHA in frontend version metadata panel** — Add a conditional render of `git_commit_sha` in the version metadata panel on TechniquePage.tsx. The panel already renders model, captured_at, and prompt_hashes — add a new item for the commit hash using monospace font. + +**Important context for executor:** The canonical codebase is on ub01 at `/vmPool/r/repos/xpltdco/chrysopedia`. SSH with `ssh ub01` to edit files and build. The frontend is at `frontend/` in that repo. + +Steps: +1. SSH to ub01, read `frontend/src/pages/TechniquePage.tsx` lines 315-365 to see existing metadata panel structure +2. After the `prompt_hashes` conditional block (around line 358) and before the closing `` of `version-metadata__grid`, add a new conditional block checking `"git_commit_sha" in versionDetail.pipeline_metadata`. Render it as a `version-metadata__item` with key label "Commit" and value in a `` element with monospace font styling (reuse existing `version-metadata__hash-value` class or apply inline). Show first 7 chars: `String(versionDetail.pipeline_metadata.git_commit_sha).slice(0, 7)` +3. Run `cd frontend && npm run build` to verify zero TypeScript errors + - Estimate: 15m + - Files: frontend/src/pages/TechniquePage.tsx + - Verify: ssh ub01 'cd /vmPool/r/repos/xpltdco/chrysopedia/frontend && npm run build 2>&1 | tail -5' diff --git a/.gsd/milestones/M006/slices/S03/S03-RESEARCH.md b/.gsd/milestones/M006/slices/S03/S03-RESEARCH.md new file mode 100644 index 0000000..e062dd0 --- /dev/null +++ b/.gsd/milestones/M006/slices/S03/S03-RESEARCH.md @@ -0,0 +1,107 @@ +# S03 Research: Git Commit SHA in Pipeline Version Metadata + +## Summary + +Straightforward slice. The version metadata infrastructure already exists — `TechniquePageVersion.pipeline_metadata` is a JSONB column, `_capture_pipeline_metadata()` in `stages.py` builds the dict, and the frontend already renders a metadata panel for historical versions. The work is: (1) capture the git commit SHA at Docker build time, (2) inject it into `_capture_pipeline_metadata()`, and (3) add a commit hash display row in the frontend metadata panel. + +The only non-trivial aspect: no `.git` directory exists inside the Docker container, so `git rev-parse HEAD` can't run at runtime inside the worker. The SHA must be baked in at build time. + +## Recommendation + +Use a Docker build arg (`GIT_COMMIT_SHA`) written to a file (`/app/.git-commit`) during image build. The `_capture_pipeline_metadata()` function reads this file. The `docker-compose.yml` passes the arg using shell command substitution. Fallback to `"unknown"` when the file is missing (local dev without Docker). + +Three tasks: +1. **Dockerfile + compose** — add build arg, write SHA to file +2. **Backend** — read SHA file, add to `_capture_pipeline_metadata()` return dict +3. **Frontend** — add commit hash display in the version metadata panel + +## Implementation Landscape + +### Backend — `_capture_pipeline_metadata()` (pipeline/stages.py, lines 557–601) + +Currently returns: +```python +{ + "models": { "stage2": ..., "stage3": ..., "stage4": ..., "stage5": ..., "embedding": ... }, + "modalities": { "stage2": ..., "stage3": ..., "stage4": ..., "stage5": ... }, + "prompt_hashes": { "stage2_segmentation.txt": ..., ... }, +} +``` + +Add `"git_commit_sha": ""` to this dict. Read from `/app/.git-commit` (Docker) or attempt `git rev-parse --short HEAD` as fallback (local dev). Use a helper function with error suppression — if neither works, return `"unknown"`. + +**No DB migration needed.** `pipeline_metadata` is JSONB — adding a new key is purely a code change. + +### Docker — `docker/Dockerfile.api` + +Add: +```dockerfile +ARG GIT_COMMIT_SHA=unknown +RUN echo "${GIT_COMMIT_SHA}" > /app/.git-commit +``` + +Place after the `COPY backend/ /app/` line so it doesn't bust the cache for code changes. + +### Docker Compose — `docker-compose.yml` + +Add build arg to both `chrysopedia-api` and `chrysopedia-worker` services (they share the same Dockerfile): +```yaml +build: + context: . + dockerfile: docker/Dockerfile.api + args: + GIT_COMMIT_SHA: ${GIT_COMMIT_SHA:-unknown} +``` + +At build time, invoke with: +```bash +GIT_COMMIT_SHA=$(git rev-parse --short HEAD) docker compose build +``` + +Or export `GIT_COMMIT_SHA` before building. The `:-unknown` default means builds without the env var still succeed. + +### Config — `backend/config.py` + +Add `git_commit_sha: str = "unknown"` to Settings. This allows overriding via env var as an alternative to the file-based approach (useful for local dev). The `_capture_pipeline_metadata()` helper should check the file first, then fall back to `settings.git_commit_sha`, then `"unknown"`. + +### Frontend — `frontend/src/pages/TechniquePage.tsx` (lines 316–360) + +The version metadata panel currently checks for `"model"`, `"captured_at"`, and `"prompt_hashes"` keys. Add a check for `"git_commit_sha"`: + +```tsx +{"git_commit_sha" in versionDetail.pipeline_metadata && ( +
+ Commit + + {String(versionDetail.pipeline_metadata.git_commit_sha).slice(0, 7)} + +
+)} +``` + +Uses the existing `version-metadata__item` CSS classes — no new styles needed. The monospace font from `version-metadata__hash-value` class can be reused or applied inline. + +### Frontend note — existing metadata key mismatch + +The backend sends `"models"` (plural, a dict of per-stage models) but the frontend checks for `"model"` (singular). This means the "Model" row in the metadata panel never actually renders with current data. This is a pre-existing bug — not in scope for this slice, but the planner should be aware. + +### Verification approach + +1. **Unit**: Run `_capture_pipeline_metadata()` locally → confirm `git_commit_sha` key present +2. **Docker build**: `docker compose build` with `GIT_COMMIT_SHA` arg → `docker exec chrysopedia-api cat /app/.git-commit` shows the SHA +3. **Frontend**: Navigate to a technique page with versions → switch to a historical version → confirm commit hash appears in metadata panel +4. **TypeScript**: `npm run build` in frontend → zero errors + +### File inventory + +| File | Change | +|------|--------| +| `docker/Dockerfile.api` | Add `ARG GIT_COMMIT_SHA` + `RUN echo` | +| `docker-compose.yml` | Add `args:` block to api and worker build sections | +| `backend/config.py` | Add `git_commit_sha` setting | +| `backend/pipeline/stages.py` | Add SHA reading helper, extend `_capture_pipeline_metadata()` | +| `frontend/src/pages/TechniquePage.tsx` | Add commit hash display in metadata panel | + +### Risk + +Low. No schema changes. No new dependencies. The JSONB column accepts any dict shape. The frontend change is additive (conditional render of a new key). Docker build arg has a safe default. diff --git a/.gsd/milestones/M006/slices/S03/tasks/T01-PLAN.md b/.gsd/milestones/M006/slices/S03/tasks/T01-PLAN.md new file mode 100644 index 0000000..b6db9f5 --- /dev/null +++ b/.gsd/milestones/M006/slices/S03/tasks/T01-PLAN.md @@ -0,0 +1,36 @@ +--- +estimated_steps: 8 +estimated_files: 4 +skills_used: [] +--- + +# T01: Capture git commit SHA in Docker build and pipeline metadata + +Add GIT_COMMIT_SHA build arg to Dockerfile.api, pass it from docker-compose.yml, write it to /app/.git-commit. Add a helper function in stages.py that reads the SHA from the file (Docker) or runs `git rev-parse --short HEAD` (local dev) with fallback to "unknown". Extend `_capture_pipeline_metadata()` to include the `git_commit_sha` key. Add `git_commit_sha` setting to config.py as an additional fallback. + +**Important context for executor:** The canonical codebase is on ub01 at `/vmPool/r/repos/xpltdco/chrysopedia`. SSH with `ssh ub01` to edit files and test. The Docker compose stack runs there. The local working directory has .gsd/ planning artifacts only. + +Steps: +1. SSH to ub01, edit `docker/Dockerfile.api` — add `ARG GIT_COMMIT_SHA=unknown` and `RUN echo "${GIT_COMMIT_SHA}" > /app/.git-commit` after the `COPY backend/ /app/` line +2. Edit `docker-compose.yml` — add `args: GIT_COMMIT_SHA: ${GIT_COMMIT_SHA:-unknown}` to both `chrysopedia-api` and `chrysopedia-worker` build sections (they already have `build: context: . dockerfile: docker/Dockerfile.api`) +3. Edit `backend/config.py` — add `git_commit_sha: str = "unknown"` field to Settings class +4. Edit `backend/pipeline/stages.py` — add `_get_git_commit_sha()` helper that tries: (a) read `/app/.git-commit` file, (b) run `subprocess.run(['git', 'rev-parse', '--short', 'HEAD'])`, (c) return `get_settings().git_commit_sha`, (d) return `"unknown"`. Add `"git_commit_sha": _get_git_commit_sha()` to the dict returned by `_capture_pipeline_metadata()` +5. Verify: run `python -c "from pipeline.stages import _capture_pipeline_metadata; print(_capture_pipeline_metadata())"` from backend dir (should show git_commit_sha key) + +## Inputs + +- ``docker/Dockerfile.api` — existing Dockerfile to add build arg to` +- ``docker-compose.yml` — existing compose file to add build args to api and worker services` +- ``backend/config.py` — existing Settings class to add git_commit_sha field` +- ``backend/pipeline/stages.py` — existing `_capture_pipeline_metadata()` function (line 557) to extend` + +## Expected Output + +- ``docker/Dockerfile.api` — contains ARG GIT_COMMIT_SHA and RUN echo to .git-commit` +- ``docker-compose.yml` — api and worker services have GIT_COMMIT_SHA build arg` +- ``backend/config.py` — Settings has git_commit_sha field` +- ``backend/pipeline/stages.py` — `_get_git_commit_sha()` helper added, `_capture_pipeline_metadata()` returns git_commit_sha key` + +## Verification + +ssh ub01 'cd /vmPool/r/repos/xpltdco/chrysopedia/backend && python -c "from pipeline.stages import _capture_pipeline_metadata; import json; m = _capture_pipeline_metadata(); assert \"git_commit_sha\" in m, f\"missing key: {m.keys()}\"; print(json.dumps(m, indent=2))"' diff --git a/.gsd/milestones/M006/slices/S03/tasks/T01-SUMMARY.md b/.gsd/milestones/M006/slices/S03/tasks/T01-SUMMARY.md new file mode 100644 index 0000000..40228e9 --- /dev/null +++ b/.gsd/milestones/M006/slices/S03/tasks/T01-SUMMARY.md @@ -0,0 +1,81 @@ +--- +id: T01 +parent: S03 +milestone: M006 +provides: [] +requires: [] +affects: [] +key_files: ["docker/Dockerfile.api", "docker-compose.yml", "backend/config.py", "backend/pipeline/stages.py"] +key_decisions: ["Resolution order for git SHA: .git-commit file → git rev-parse → config/env → unknown"] +patterns_established: [] +drill_down_paths: [] +observability_surfaces: [] +duration: "" +verification_result: "Ran _capture_pipeline_metadata() inside chrysopedia-api container — assertion passed, git_commit_sha key present with expected "unknown" fallback value. Also verified _get_git_commit_sha() standalone returns "unknown" in container (no .git-commit file, no git binary)." +completed_at: 2026-03-30T11:24:18.222Z +blocker_discovered: false +--- + +# T01: Added GIT_COMMIT_SHA build arg to Dockerfile.api, compose build args for api/worker, config field, and _get_git_commit_sha() helper — pipeline metadata now includes git_commit_sha key + +> Added GIT_COMMIT_SHA build arg to Dockerfile.api, compose build args for api/worker, config field, and _get_git_commit_sha() helper — pipeline metadata now includes git_commit_sha key + +## What Happened +--- +id: T01 +parent: S03 +milestone: M006 +key_files: + - docker/Dockerfile.api + - docker-compose.yml + - backend/config.py + - backend/pipeline/stages.py +key_decisions: + - Resolution order for git SHA: .git-commit file → git rev-parse → config/env → unknown +duration: "" +verification_result: passed +completed_at: 2026-03-30T11:24:18.223Z +blocker_discovered: false +--- + +# T01: Added GIT_COMMIT_SHA build arg to Dockerfile.api, compose build args for api/worker, config field, and _get_git_commit_sha() helper — pipeline metadata now includes git_commit_sha key + +**Added GIT_COMMIT_SHA build arg to Dockerfile.api, compose build args for api/worker, config field, and _get_git_commit_sha() helper — pipeline metadata now includes git_commit_sha key** + +## What Happened + +Edited four files on ub01: Dockerfile.api (ARG + RUN echo to .git-commit), docker-compose.yml (build args for api and worker), config.py (git_commit_sha Settings field), and stages.py (_get_git_commit_sha() helper with 4-tier fallback + git_commit_sha in _capture_pipeline_metadata() return dict). Verified by copying updated files into running container and confirming git_commit_sha key is present in metadata output. + +## Verification + +Ran _capture_pipeline_metadata() inside chrysopedia-api container — assertion passed, git_commit_sha key present with expected "unknown" fallback value. Also verified _get_git_commit_sha() standalone returns "unknown" in container (no .git-commit file, no git binary). + +## Verification Evidence + +| # | Command | Exit Code | Verdict | Duration | +|---|---------|-----------|---------|----------| +| 1 | `docker exec chrysopedia-api python -c "from pipeline.stages import _capture_pipeline_metadata; import json; m = _capture_pipeline_metadata(); assert 'git_commit_sha' in m; print(json.dumps(m, indent=2))"` | 0 | ✅ pass | 3000ms | +| 2 | `docker exec chrysopedia-api python -c "from pipeline.stages import _get_git_commit_sha; print(repr(_get_git_commit_sha()))"` | 0 | ✅ pass | 2000ms | + + +## Deviations + +Verification ran inside Docker container instead of directly on host because Celery deps aren't installed on host Python. + +## Known Issues + +Running containers still use old image — need docker compose build to bake SHA into .git-commit. Expected; rebuild happens after slice completes. + +## Files Created/Modified + +- `docker/Dockerfile.api` +- `docker-compose.yml` +- `backend/config.py` +- `backend/pipeline/stages.py` + + +## Deviations +Verification ran inside Docker container instead of directly on host because Celery deps aren't installed on host Python. + +## Known Issues +Running containers still use old image — need docker compose build to bake SHA into .git-commit. Expected; rebuild happens after slice completes. diff --git a/.gsd/milestones/M006/slices/S03/tasks/T02-PLAN.md b/.gsd/milestones/M006/slices/S03/tasks/T02-PLAN.md new file mode 100644 index 0000000..ce4f63b --- /dev/null +++ b/.gsd/milestones/M006/slices/S03/tasks/T02-PLAN.md @@ -0,0 +1,29 @@ +--- +estimated_steps: 6 +estimated_files: 1 +skills_used: [] +--- + +# T02: Display commit SHA in frontend version metadata panel + +Add a conditional render of `git_commit_sha` in the version metadata panel on TechniquePage.tsx. The panel already renders model, captured_at, and prompt_hashes — add a new item for the commit hash using monospace font. + +**Important context for executor:** The canonical codebase is on ub01 at `/vmPool/r/repos/xpltdco/chrysopedia`. SSH with `ssh ub01` to edit files and build. The frontend is at `frontend/` in that repo. + +Steps: +1. SSH to ub01, read `frontend/src/pages/TechniquePage.tsx` lines 315-365 to see existing metadata panel structure +2. After the `prompt_hashes` conditional block (around line 358) and before the closing `` of `version-metadata__grid`, add a new conditional block checking `"git_commit_sha" in versionDetail.pipeline_metadata`. Render it as a `version-metadata__item` with key label "Commit" and value in a `` element with monospace font styling (reuse existing `version-metadata__hash-value` class or apply inline). Show first 7 chars: `String(versionDetail.pipeline_metadata.git_commit_sha).slice(0, 7)` +3. Run `cd frontend && npm run build` to verify zero TypeScript errors + +## Inputs + +- ``frontend/src/pages/TechniquePage.tsx` — existing version metadata panel (lines 315-365)` +- ``backend/pipeline/stages.py` — T01 output confirming `git_commit_sha` key name in pipeline_metadata dict` + +## Expected Output + +- ``frontend/src/pages/TechniquePage.tsx` — version metadata panel includes conditional render of git_commit_sha as "Commit" row with monospace-styled 7-char hash` + +## Verification + +ssh ub01 'cd /vmPool/r/repos/xpltdco/chrysopedia/frontend && npm run build 2>&1 | tail -5'