chore: Added GIT_COMMIT_SHA build arg to Dockerfile.api, compose build…

- "docker/Dockerfile.api"
- "docker-compose.yml"
- "backend/config.py"
- "backend/pipeline/stages.py"

GSD-Task: S03/T01
This commit is contained in:
jlightner 2026-03-30 11:24:34 +00:00
parent ee24731e59
commit 12f9fb7334
10 changed files with 450 additions and 2 deletions

View file

@ -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 |

View file

@ -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. |

View file

@ -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)

View file

@ -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

View file

@ -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
}

View file

@ -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 `</div>` 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 `<code>` 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'

View file

@ -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 557601)
Currently returns:
```python
{
"models": { "stage2": ..., "stage3": ..., "stage4": ..., "stage5": ..., "embedding": ... },
"modalities": { "stage2": ..., "stage3": ..., "stage4": ..., "stage5": ... },
"prompt_hashes": { "stage2_segmentation.txt": ..., ... },
}
```
Add `"git_commit_sha": "<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 316360)
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 && (
<div className="version-metadata__item">
<span className="version-metadata__key">Commit</span>
<code className="version-metadata__value" style={{ fontFamily: '"SF Mono", "Fira Code", monospace' }}>
{String(versionDetail.pipeline_metadata.git_commit_sha).slice(0, 7)}
</code>
</div>
)}
```
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.

View file

@ -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))"'

View file

@ -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.

View file

@ -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 `</div>` 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 `<code>` 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'