generated from john/python-template
gpt-5.3-codex review phase 2 - update instructions & skills
Quality Gate / gate (push) Successful in 34s
Quality Gate / gate (push) Successful in 34s
This commit is contained in:
@@ -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)).
|
||||
|
||||
Reference in New Issue
Block a user