gpt-5.3-codex review phase 2 - update instructions & skills
Quality Gate / gate (push) Successful in 34s

This commit is contained in:
Jim Lancaster
2026-08-19 18:22:06 -05:00
parent c261fbb3bd
commit b6a5a89a84
7 changed files with 187 additions and 28 deletions
+14 -23
View File
@@ -20,6 +20,8 @@ applyTo: 'src/transcription/services/*.py'
- Not every module in this package is a service. Helper modules that define no `*Service`
class (`base`, `errors`, `normalization`, `prompts`, `quality`, `media_storage`,
`source_media`) are free-function modules and are exempt from the service rules below.
- Cross-cutting error behavior must follow
[error-handling instructions](./error-handling.instructions.md).
## Model Ownership
@@ -69,14 +71,17 @@ module, not in a cross-service import.
which defines no service class and is therefore importable by any of them.
- Use a context manager for large `try/except` blocks, like `handle_transcription_errors` in
[sources](../../src/transcription/services/sources.py).
- Category mapping, retry behavior, and translation boundaries are defined in
[error-handling instructions](./error-handling.instructions.md).
## Checklist
- [ ] Uses `ServiceBase` for common logic
- [ ] Session kwarg for `AsyncSession` to pass a session object into each method
- [ ] Services use `self._session_scope` in their methods to pass the session through
- Multiple operations on the same object(s) require sharing a session between all the methods used
- Multiple operations on the same object(s) require sharing a session between all the methods used
- [ ] Every model the module touches is either owned by it or reached read-only
- [ ] Evidence writes preserve append-only semantics
## CRUD Methods
@@ -98,18 +103,9 @@ When a service method accepts an optional `session` kwarg, write methods must us
- If `session` is provided: the method must **not** commit; it should `flush()` so IDs and FK values are available to the caller's transaction.
- Use `refresh()` on returned ORM objects when the caller needs DB-populated values (defaults, triggers, merged state).
Recommended helper behavior:
- Inputs: active session object, original `session` arg (or a boolean ownership flag), and an optional list of objects to refresh.
- Logic: `commit` when service-owned session, `flush` when caller-owned session, then refresh requested objects.
This keeps orchestration functions atomic: they can pass one shared session across multiple services and commit exactly once at the workflow boundary.
## Workflow Transaction Boundaries
For multi-step job lifecycles (for example queued transcription jobs), orchestration functions must use explicit transaction phases.
Required boundary model:
For multi-step job lifecycles, orchestration functions must use explicit transaction phases.
- **Transaction A (claim):** transition `JobStatus.QUEUED -> JobStatus.PROCESSING` and commit immediately.
- Perform provider/network work **outside** database transactions.
@@ -123,28 +119,23 @@ Atomicity rules:
- Terminal state (`TRANSCRIBED` or `FAILED`) and transcript row changes must succeed or roll back together.
- Retry persistence (`QUEUED` + retry increment + error detail) must succeed or roll back together.
Separation of concerns:
- Worker modules should stay lightweight and delegate lifecycle transitions to service/workflow orchestration functions.
- In `workflows.py`, `process_queued_job` should own one complete attempt lifecycle: `QUEUED -> PROCESSING -> TRANSCRIBED|FAILED`.
- In `workflows.py`, `advance_job` should coordinate broader status progression around attempts (for example retry scheduling from `FAILED -> QUEUED`).
- Services should expose session-aware write helpers (flush on caller-owned session) so orchestration controls commit boundaries.
- Backoff/sleep behavior must run outside transactional scopes.
## V4 Contract Alignment
- Treat `docs/ver4/` as the active architecture and requirements baseline.
- Treat `docs/ver4/history.md` and `docs-v4x-archive` as historical-only references.
- `Job.status` success path is `TRANSCRIBED`.
- `JobSource.status` is queue/projection state only (`PENDING`, `TRANSCRIBED`, `FAILED`, `CANCELLED`).
- Source ingest may normalize media before persistence; persisted bytes/hash are canonical for processing and provenance.
- `ExecutionAttempt` is append-only evidence history; do not mutate historical attempt rows in runtime code.
- `Source.raw_transcription` is a projection, not authoritative history.
- Service/UI read paths that touch relationships must be eager-loaded for `lazy="raise"` compatibility.
- If evidence-related model fields change, update `docs/ver4/schema_v4.md` in the same change.
# Service Composition
A service method may read across models it does not own, using eager loads from its own
aggregate root. What it may not do is import another service.
Operations that must **write** models owned by more than one service — uploading a picture,
for example — are composed in an orchestration module
Operations that must **write** models owned by more than one service are composed in an orchestration module
([store](../../src/transcription/services/store.py),
[workflows](../../src/transcription/services/workflows.py)). Orchestration modules define no
service class, may import any service, and own the commit boundary.
[workflows](../../src/transcription/services/workflows.py)).