generated from john/python-template
gpt-5.3-codesx review: Phase 5 Release Readiness & Contract Enforcement
Quality Gate / gate (push) Failing after 10s
Quality Gate / gate (push) Failing after 10s
This commit is contained in:
@@ -1,253 +0,0 @@
|
|||||||
# Phase 4: Implementation Task Specifications
|
|
||||||
|
|
||||||
## Objective
|
|
||||||
|
|
||||||
Convert the canonical V4 baseline into executable, worker-ready implementation tasks that close remaining drift risk and harden enforcement.
|
|
||||||
|
|
||||||
Canonical authority for all tasks:
|
|
||||||
|
|
||||||
- `docs/ver4/*`
|
|
||||||
- `.github/instructions/services.instructions.md`
|
|
||||||
- `.github/instructions/ui.instructions.md`
|
|
||||||
- `.github/instructions/error-handling.instructions.md`
|
|
||||||
- `.github/skills/python-code-reviewer/skill.md`
|
|
||||||
- `.github/skills/evidence-provenance-auditor/skill.md`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Dependency-Ordered Task Graph
|
|
||||||
|
|
||||||
| Task ID | Title | Depends On | Priority |
|
|
||||||
| :--- | :--- | :--- | :--- |
|
|
||||||
| P4-01 | Meta-contract regression guards | - | P0 |
|
|
||||||
| P4-02 | Error taxonomy and translation conformance | P4-01 | P0 |
|
|
||||||
| P4-03 | Evidence append-only write-path hardening | P4-01 | P0 |
|
|
||||||
| P4-04 | Job/Page lifecycle consistency hardening | P4-02, P4-03 | P0 |
|
|
||||||
| P4-05 | Eager-loading and `lazy="raise"` conformance sweep | P4-01 | P1 |
|
|
||||||
| P4-06 | Media route/path safety enforcement sweep | P4-01 | P1 |
|
|
||||||
| P4-07 | Duration semantics split for telemetry correctness | P4-04 | P1 |
|
|
||||||
| P4-08 | Reviewer/instruction enforcement tests in CI path | P4-01..P4-07 | P1 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Task Specifications
|
|
||||||
|
|
||||||
## P4-01 — Meta-contract regression guards
|
|
||||||
|
|
||||||
**Goal:** Add deterministic tests preventing drift from canonical docs/instructions/skills contracts.
|
|
||||||
|
|
||||||
**Scope:**
|
|
||||||
|
|
||||||
- `tests/` (new focused tests)
|
|
||||||
- optionally small helper in `tests/conftest.py` if needed
|
|
||||||
|
|
||||||
**Required changes:**
|
|
||||||
|
|
||||||
1. Add a test that fails if active docs/instructions/skills reference removed V4 revision paths.
|
|
||||||
2. Add a test that asserts canonical authority references exist where required (services/ui/error-handling instructions and reviewer skills).
|
|
||||||
3. Keep checks text-based and stable; avoid brittle full-document snapshots.
|
|
||||||
|
|
||||||
**Acceptance criteria:**
|
|
||||||
|
|
||||||
- Test suite fails on any reintroduction of legacy-path authority references.
|
|
||||||
- Test suite passes with current baseline.
|
|
||||||
|
|
||||||
**Validation command:** `uv run pytest tests -k "contract or instruction or skill"`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## P4-02 — Error taxonomy and translation conformance
|
|
||||||
|
|
||||||
**Goal:** Ensure service/API/UI error translation matches canonical categories and boundaries.
|
|
||||||
|
|
||||||
**Scope:**
|
|
||||||
|
|
||||||
- `src/transcription/services/**/*.py`
|
|
||||||
- `src/transcription/api/**/*.py`
|
|
||||||
- `src/transcription/ui/**/*.py`
|
|
||||||
- related tests under `tests/services`, `tests/api`, `tests/ui`
|
|
||||||
|
|
||||||
**Required changes:**
|
|
||||||
|
|
||||||
1. Normalize service-edge exceptions to canonical categories:
|
|
||||||
- `validation`, `not_found`, `conflict`, `external`, `timeout`, `internal`.
|
|
||||||
2. Ensure causal chain preservation (`raise ... from ...`) on translation.
|
|
||||||
3. Ensure UI/API emits user-safe envelopes/messages without stack/path/secret leakage.
|
|
||||||
4. Add/adjust tests for category mapping and envelope shape.
|
|
||||||
|
|
||||||
**Acceptance criteria:**
|
|
||||||
|
|
||||||
- No ad hoc category values in user/API-facing error envelopes.
|
|
||||||
- Translation boundaries are deterministic and test-covered.
|
|
||||||
|
|
||||||
**Validation command:** `uv run pytest tests/services tests/api tests/ui -k "error or envelope or category"`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## P4-03 — Evidence append-only write-path hardening
|
|
||||||
|
|
||||||
**Goal:** Guarantee each provider call appends new `ExecutionAttempt` evidence and never rewrites attempt history.
|
|
||||||
|
|
||||||
**Scope:**
|
|
||||||
|
|
||||||
- `src/transcription/services/sources.py`
|
|
||||||
- `src/transcription/services/workflows.py`
|
|
||||||
- `src/transcription/services/evidence.py`
|
|
||||||
- `src/transcription/db/models.py` (only if required for bug fix)
|
|
||||||
- tests under `tests/services`
|
|
||||||
|
|
||||||
**Required changes:**
|
|
||||||
|
|
||||||
1. Audit all attempt-write paths for accidental update/overwrite behavior.
|
|
||||||
2. Enforce append-only semantics for retries and reprocessing.
|
|
||||||
3. Keep `Source.raw_transcription` and preferred pointers as projection-only mutation surfaces.
|
|
||||||
4. Add/strengthen tests proving historical attempts are unchanged across retries/promotions.
|
|
||||||
|
|
||||||
**Acceptance criteria:**
|
|
||||||
|
|
||||||
- Reprocessing/retry produces new attempts, never history rewrite.
|
|
||||||
- Projection changes do not mutate prior attempt evidence.
|
|
||||||
|
|
||||||
**Validation command:** `uv run pytest tests/services -k "attempt or evidence or retry or promotion"`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## P4-04 — Job/Page lifecycle consistency hardening
|
|
||||||
|
|
||||||
**Goal:** Enforce coherent status transitions and cancellation semantics across `Job` and `JobSource`.
|
|
||||||
|
|
||||||
**Scope:**
|
|
||||||
|
|
||||||
- `src/transcription/services/jobs.py`
|
|
||||||
- `src/transcription/services/workflows.py`
|
|
||||||
- related tests under `tests/services`
|
|
||||||
|
|
||||||
**Required changes:**
|
|
||||||
|
|
||||||
1. Verify terminal `Job.status` resolution from page outcomes only:
|
|
||||||
- `transcribed`, `partial_success`, `failed`.
|
|
||||||
2. Ensure cancellation transitions remaining `pending` pages to `cancelled`.
|
|
||||||
3. Ensure lifecycle language and emitted behavior never reintroduce legacy `completed` semantics.
|
|
||||||
4. Add/adjust reliability tests for mixed outcomes and cancel/retry edges.
|
|
||||||
|
|
||||||
**Acceptance criteria:**
|
|
||||||
|
|
||||||
- Job and page-level transitions remain consistent under success/failure/partial/cancel paths.
|
|
||||||
- No legacy terminal vocabulary in behavior contracts or emitted statuses.
|
|
||||||
|
|
||||||
**Validation command:** `uv run pytest tests/services/test_workflows_reliability.py tests/services -k "job or cancel or partial_success"`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## P4-05 — Eager-loading and `lazy="raise"` conformance sweep
|
|
||||||
|
|
||||||
**Goal:** Eliminate hidden lazy-load access in service/UI read paths.
|
|
||||||
|
|
||||||
**Scope:**
|
|
||||||
|
|
||||||
- `src/transcription/services/**/*.py`
|
|
||||||
- `src/transcription/ui/pages/**/*.py`
|
|
||||||
- `src/transcription/ui/components/**/*.py`
|
|
||||||
|
|
||||||
**Required changes:**
|
|
||||||
|
|
||||||
1. Audit relationship access sites and ensure explicit eager-loads where needed.
|
|
||||||
2. Fix any read-path assumptions that rely on implicit lazy loading.
|
|
||||||
3. Add targeted tests for high-risk rendering/read paths.
|
|
||||||
|
|
||||||
**Acceptance criteria:**
|
|
||||||
|
|
||||||
- Read paths that touch relationships function with `lazy="raise"` constraints intact.
|
|
||||||
|
|
||||||
**Validation command:** `uv run pytest tests/services tests/ui -k "boundary or lazy or load"`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## P4-06 — Media route/path safety enforcement sweep
|
|
||||||
|
|
||||||
**Goal:** Ensure all UI/print media flows use approved record-validated or controlled resolver patterns.
|
|
||||||
|
|
||||||
**Scope:**
|
|
||||||
|
|
||||||
- `src/transcription/api/v4_print.py`
|
|
||||||
- `src/transcription/ui/components/media_urls.py`
|
|
||||||
- `src/transcription/ui/pages/**/*.py`
|
|
||||||
- `src/transcription/ui/components/**/*.py`
|
|
||||||
- tests in `tests/ui` and `tests/api` where applicable
|
|
||||||
|
|
||||||
**Required changes:**
|
|
||||||
|
|
||||||
1. Remove any direct filesystem path exposure to clients.
|
|
||||||
2. Ensure print/export media access is record-validated.
|
|
||||||
3. Ensure UI media URL construction uses resolver helper only.
|
|
||||||
4. Add tests that fail on unsafe URL/path construction patterns.
|
|
||||||
|
|
||||||
**Acceptance criteria:**
|
|
||||||
|
|
||||||
- No `file://` usage or raw absolute-path emission in UI/API responses.
|
|
||||||
- Media links resolve through approved paths only.
|
|
||||||
|
|
||||||
**Validation command:** `uv run pytest tests/ui tests/api -k "media or print or path"`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## P4-07 — Duration semantics split for telemetry correctness
|
|
||||||
|
|
||||||
**Goal:** Separate provider-call latency from end-to-end processing duration so model rollups are not misleading.
|
|
||||||
|
|
||||||
**Scope:**
|
|
||||||
|
|
||||||
- `src/transcription/services/workflows.py`
|
|
||||||
- `src/transcription/db/models.py` and migration surface if schema needs extension
|
|
||||||
- `docs/ver4/schema_v4.md` (same change if model fields evolve)
|
|
||||||
- tests in `tests/services`
|
|
||||||
|
|
||||||
**Required changes:**
|
|
||||||
|
|
||||||
1. Introduce explicit timing fields or calculation paths that distinguish:
|
|
||||||
- provider call duration
|
|
||||||
- full processing duration
|
|
||||||
2. Keep existing invariants and backward compatibility behavior explicit.
|
|
||||||
3. Add tests covering success, timeout, and failure timing writes.
|
|
||||||
4. Update schema docs if persistence contract changes.
|
|
||||||
|
|
||||||
**Acceptance criteria:**
|
|
||||||
|
|
||||||
- Telemetry consumers can compute provider performance without preprocessing/commit skew.
|
|
||||||
- Timing semantics are test-backed and documented.
|
|
||||||
|
|
||||||
**Validation command:** `uv run pytest tests/services -k "duration or timeout or workflow"`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## P4-08 — Enforcement coverage in CI path
|
|
||||||
|
|
||||||
**Goal:** Ensure critical invariant checks run in the normal validation path.
|
|
||||||
|
|
||||||
**Scope:**
|
|
||||||
|
|
||||||
- existing test organization and runner configs only
|
|
||||||
|
|
||||||
**Required changes:**
|
|
||||||
|
|
||||||
1. Ensure boundary/provenance/contract tests are discoverable by default `pytest` runs.
|
|
||||||
2. Add grouping markers only if already consistent with project test conventions.
|
|
||||||
3. Avoid introducing new tooling; reuse existing test stack.
|
|
||||||
|
|
||||||
**Acceptance criteria:**
|
|
||||||
|
|
||||||
- A standard repo test run exercises meta-contract, boundary, and provenance guards.
|
|
||||||
|
|
||||||
**Validation command:** `uv run pytest`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Worker Handoff Contract (apply to every task)
|
|
||||||
|
|
||||||
Each worker delivery must include:
|
|
||||||
|
|
||||||
1. Files changed.
|
|
||||||
2. Behavior change summary.
|
|
||||||
3. Why the change satisfies the invariant/contract.
|
|
||||||
4. Targeted test command(s) and result summary.
|
|
||||||
5. Explicit note if `docs/ver4/schema_v4.md` was updated due to model/persistence changes.
|
|
||||||
@@ -6,6 +6,7 @@ from nicegui import ui
|
|||||||
|
|
||||||
from transcription.errors import AppError
|
from transcription.errors import AppError
|
||||||
from transcription.errors import ErrorCategory
|
from transcription.errors import ErrorCategory
|
||||||
|
from transcription.errors import canonical_error_category
|
||||||
from transcription.errors import classify_unexpected_error
|
from transcription.errors import classify_unexpected_error
|
||||||
|
|
||||||
|
|
||||||
@@ -31,7 +32,12 @@ def show_error(exc: Exception, *, title: str, operation: str) -> None:
|
|||||||
ui.label(error.message)
|
ui.label(error.message)
|
||||||
ui.label(f"Suggested action: {error.suggestion}").classes("text-weight-medium")
|
ui.label(f"Suggested action: {error.suggestion}").classes("text-weight-medium")
|
||||||
ui.label(f"Error reference: {error.error_id}").classes("text-caption")
|
ui.label(f"Error reference: {error.error_id}").classes("text-caption")
|
||||||
ui.label(f"Category: {error.category.value}").classes("text-caption")
|
ui.label(f"Category: {display_error_category(error)}").classes("text-caption")
|
||||||
|
|
||||||
|
|
||||||
|
def display_error_category(error: AppError) -> str:
|
||||||
|
"""Return the canonical UI-facing category label for an AppError."""
|
||||||
|
return canonical_error_category(error)
|
||||||
|
|
||||||
|
|
||||||
def summarize_error(exc: Exception, *, operation: str) -> str:
|
def summarize_error(exc: Exception, *, operation: str) -> str:
|
||||||
|
|||||||
@@ -2,41 +2,16 @@ source: Book Two - page 02.jpg
|
|||||||
provider: openrouter
|
provider: openrouter
|
||||||
model: google/gemini-2.5-flash
|
model: google/gemini-2.5-flash
|
||||||
---
|
---
|
||||||
|
[document body typewritten]
|
||||||
BY WAY OF INTRODUCTION:-
|
BY WAY OF INTRODUCTION:-
|
||||||
|
|
||||||
These few paragraphs of introduction may help you read BOOK 2 which covers a
|
These few paragraphs of introduction may help you read BOOK 2 which covers a wider range than did BOOK 1 (Pioneer Days).
|
||||||
wider range than did BOOK 1 (Pioneer Days).
|
|
||||||
|
|
||||||
BOOK 1 had 54 pages; 14 chapters. BOOK 2 has 70 pages; 18 chapters. BOOK 1 con-
|
BOOK 1 had 54 pages; 14 chapters. BOOK 2 has 70 pages; 18 chapters. BOOK 1 consisted largely of first generation family history. BOOK 2 throws more light on the second generation. Sidney promises a BOOK 3 and that may begin to do justice to the third generation. We suggest that Sidney get the help of Louis Shinn who has a chapter in this book (Chapter 16 - The Last 25 Years on the Doumecq Plains. Louis has the gift of seeing, recalling and telling. One sentence in his chapter gives a great tribute to the Doumecqers--so far as he knows no one on the Doumecq Plains went on relief during the depression. That in a nutshell shows the sturdy character of the residents of the Doumecq Plains.
|
||||||
sisted largely of first generation family history. BOOK 2 throws more light on
|
|
||||||
the second generation. Sidney promises a BOOK 3 and that may begin to do justice
|
|
||||||
to the third generation. We suggest that Sidney get the help of Louis Shinn
|
|
||||||
who has a chapter in this book (Chapter 16 - The Last 25 Years on the Doumecq
|
|
||||||
Plains. Louis has the gift of seeing, recalling and telling. One sentence in
|
|
||||||
his chapter gives a great tribute to the Doumeccqers--so [sic] far as he knows no one
|
|
||||||
on the Doumecq Plains went on relief during the depression. That in a nutshell
|
|
||||||
shows the sturdy character of the residents of the Doumecq Plains.
|
|
||||||
|
|
||||||
We promised in BOOK 1 that in BOOK 2 we would give the story of the trip of
|
We promised in BOOK 1 that in BOOK 2 we would give the story of the trip of John E. Cochran and wife to Tennessee, Cuba and the Panama Canal. You will see by the Table of Contents that the first four chapters have been given to those trips. Those chapters are worth reading and re-reading. Mr. Cochran has eyes to see and a pen to tell. We think the people in Tennessee will read with great pleasure the comments he makes on conditions today.
|
||||||
John E. Cochran and wife to Tennessee, Cuba and the Panama Canal. You will see
|
|
||||||
by the Table of Contents that the first four chapters have been given to those
|
|
||||||
trips. Those chapters are worth reading and re-reading. Mr. Cochran has eyes
|
|
||||||
to see and a pen to tell. We think the people in Tennessee will read with
|
|
||||||
great pleasure the comments he makes on conditions today.
|
|
||||||
|
|
||||||
Some who get this book will consider the group picture the best thing in the
|
Some who get this book will consider the group picture the best thing in the book. It took a lot of preliminary photographing to reduce some pictures, enlarge others and bring out the tin types. We wish that instead of 44 faces we could have given 88. Do not blame Ethel Cochran-Shinn for the selection. She furnished enough pictures but we had to take only part of them. We think there are great possibilities in reproducing old pictures. We wish we had a Pickard group. Some Pickard descendant may wish to make a collection.
|
||||||
book. It took a lot of preliminary photographing to reduce some pictures, enlarge
|
|
||||||
others and bring out the tin types. We wish that instead of 44 faces we could
|
|
||||||
have given 88. Do not blame Ethel Cochran-Shinn for the selection. She furnished
|
|
||||||
enough pictures but we had to take only part of them. We think there are great
|
|
||||||
possibilities in reproducing old pictures. We wish we had a Pickard group. Some
|
|
||||||
Pickard descendant may wish to make a collection.
|
|
||||||
|
|
||||||
We are much impressed with the future possibilities of getting a complete geneol-
|
|
||||||
ogy of the Pickard family. Mr. Cochran has a fine chapter on the Pickards but
|
|
||||||
to date we have not had the pleasure of finding all of the family dates. We had
|
|
||||||
intended to give more family data in this book but it takes time to get the
|
|
||||||
correct dates. Often times it requires trips to cemeteries to get dates on the
|
|
||||||
tombstones. Winter is no time to collect dates on tombstones.
|
|
||||||
|
|
||||||
|
We are much impressed with the future possibilities of getting a complete geneol-ogy of the Pickard family. Mr. Cochran has a fine chapter on the Pickards but to date we have not had the pleasure of finding all of the family dates. We had intended to give more family data in this book but it takes time to get the correct dates. Often times it requires trips to cemeteries to get dates on the tombstones. Winter is no time to collect dates on tombstones.
|
||||||
-2-
|
-2-
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ source: Omie Writes Home.pdf
|
|||||||
provider: openrouter
|
provider: openrouter
|
||||||
model: google/gemini-2.5-flash
|
model: google/gemini-2.5-flash
|
||||||
---
|
---
|
||||||
|
[document body mixed]
|
||||||
JOHN E. COCHRAN
|
JOHN E. COCHRAN
|
||||||
FAMILY ASSOCIATION
|
FAMILY ASSOCIATION
|
||||||
Family Only
|
Family Only
|
||||||
Home | Sibling's Stories | 1st Cousins | Ancestor's Stories | Reunion History | Next Reunion | JECMEF
|
[handwritten: Home | Sibling's Stories | 1st Cousins | Ancestor's Stories | Reunion History | Next Reunion | JECMEF]
|
||||||
|
|
||||||
OMIE WRITES HOME
|
OMIE WRITES HOME
|
||||||
|
|
||||||
Ed. Note: The following letter was written by Omie Cochran in Nome, Alaska and sent to her
|
Ed. Note: The following letter was written by Omie Cochran in Nome, Alaska and sent to her
|
||||||
sister, Ethel Shinn, in Canfield, Idaho in 1923. It has been stored away these 63 years in the
|
sister, Ethel Shinn, in Canfield, Idaho in 1923. It has been stored away these 63 years in the
|
||||||
original envelope with its 2 cent stamp. The letter has a number of references to the Shinn
|
original envelope with its 2 cent stamp. The letter has a number of references to the Shinn
|
||||||
@@ -26,6 +25,9 @@ and Polly sit up and listen and that little black
|
|||||||
rascal of yours would fairly sparkle with
|
rascal of yours would fairly sparkle with
|
||||||
listening. Can't I see him listening now to all the
|
listening. Can't I see him listening now to all the
|
||||||
yarns we told last summer?
|
yarns we told last summer?
|
||||||
|
|
||||||
|
[photo: Five people, appearing to be native Alaskan, in winter clothing, standing on a beach with a dog sled in front of them and a boat in the background]
|
||||||
|
|
||||||
You see, we-Miss Saville and I, took a trip north
|
You see, we-Miss Saville and I, took a trip north
|
||||||
on the Buford and it was very interesting. We
|
on the Buford and it was very interesting. We
|
||||||
went north thru the Bering Strait into the Arctic and as far as the Ice Pack. There the captain
|
went north thru the Bering Strait into the Arctic and as far as the Ice Pack. There the captain
|
||||||
@@ -33,82 +35,4 @@ of our craft and some other mighty hunters went out first in kayaks and later in
|
|||||||
shot seven walrus. When they also took a movie man and camera, so you will likely see all
|
shot seven walrus. When they also took a movie man and camera, so you will likely see all
|
||||||
this in the movies before I get to tell you. They came back on board and the ship went up
|
this in the movies before I get to tell you. They came back on board and the ship went up
|
||||||
along the icebergs and the walrus were 'heisted' on board by the use of the crane which loads
|
along the icebergs and the walrus were 'heisted' on board by the use of the crane which loads
|
||||||
tons of freight and the beasts were so huge that they made the pulleys just creak. They were
|
tons of freight and the beasts were
|
||||||
over 12 feet long, as big around as three cows, had no feet but toenails on their flippers or
|
|
||||||
flappers, no head but their body just suddenly ended with a hole for a mouth and big bristles
|
|
||||||
|
|
||||||
all around it similar to a currycomb in coarseness; no ears but huge tusks of ivory. They are
|
|
||||||
the most repulsive looking animals imaginable and tho I have always read about them I never
|
|
||||||
expect such disagreeable looking creatures. They had a rough brown hairy skin and some of
|
|
||||||
them looked warty. They must have weighed two ton at least. Ere we got them back to Nome
|
|
||||||
to the natives they were getting extremely odiferous—in fact, you could scarcely stay on the
|
|
||||||
ship with any degree of comfort unless you had per chance lost your sense of smell.
|
|
||||||
|
|
||||||
Then we went north to a few minutes beyond the 70th degree of latitude and thot for awhile
|
|
||||||
we would go to Wrangell Island where some men from Steffonsons ship were supposed to be
|
|
||||||
stranded but we didn't get there and instead stopped at a small native village at Cape Serdz in
|
|
||||||
Siberia. These Eskimo were very primitive. One white squaw man lived there and had for 23
|
|
||||||
years. He was a Swede--who else could. Their houses were circular and built up with dirt 2 or
|
|
||||||
3 feet and then skins were stretched over it and weighted down with rocks. Inside, the room
|
|
||||||
was partitioned off at the sides with skins for sleeping quarters. In the main part they had the
|
|
||||||
fire on the ground and the fish drying on lines and the skins hanging around and the dogs and
|
|
||||||
babies and children. They wore skin clothes entirely. The women's were made like bloomers
|
|
||||||
and were heavily padded for warmth. They wore high mukluks and really looked very
|
|
||||||
comfortable. The babies were in fur skins with the fur inside and they looked like little Teddy
|
|
||||||
bears with faces. I guess they had never seen white women, not so many at one time anyway.
|
|
||||||
We went ashore in 2 life boats and a launch pulling them. On the launch was a six piece band
|
|
||||||
playing and the rear of the last life boat was the movie man. 'Twas very thrilling.
|
|
||||||
|
|
||||||
The other place we stopped was at Whalen, a trading post in Siberia. There these 'towerists'
|
|
||||||
went wild. They rushed helter-skelter, hither and thither, here and there, trying to find
|
|
||||||
something to buy. Prices raised right before your eyes. One would but something for $1.00
|
|
||||||
and the next might have to pay $2.00, $4.00 or $10.00. That made no difference. They had to
|
|
||||||
have it. One man I was sort of taking care of, tho he had his son along for the purpose,
|
|
||||||
bought 2 ivory tusks, 1 pup, 2 moccasins, 3 or 4 billikens, 6 or 8 ivory and silver rings, one
|
|
||||||
fishing line, hooks, floats, etc. and two bird slings. The slings have rocks at the end and the
|
|
||||||
little natives throw them at the flocks of geese and ducks which fly close over the village and
|
|
||||||
the slings entangle their wings and legs, sometimes more than one, and they can't fly. They
|
|
||||||
come down and the natives capture them. There was more junk brot aboard than baggage, I
|
|
||||||
do believe. And they say that at the first stop it was worse than here. The red flag was flying
|
|
||||||
over Whalen and the Russian soldiers were there—a few, one or two or three, I forget the
|
|
||||||
number.
|
|
||||||
|
|
||||||
We got home yesterday morning at 5 a.m. but missed the first lighter in so had to stay out
|
|
||||||
until 2:30. The girls had prepared a big meal for us and invited up the Hartfords and then let
|
|
||||||
us talk. Miss Saville talked quite a bit. Any how if you folks don't like this I don't care, it is
|
|
||||||
all I had to write about and I know Buster'ud listen anyway and I'd soak ole Peter's head if he
|
|
||||||
didn't and Polly would in my lap and I don't know much about the youngest one of yours so
|
|
||||||
likely he would be squawling. But we did surely enjoy our trip and were gone just long enuf.
|
|
||||||
|
|
||||||
I expect there were 150 passengers on board and almost or more of the crew and helpers. We
|
|
||||||
had a stateroom down next to the kitchen and 'twas pretty fierce for odor at times.
|
|
||||||
|
|
||||||
I have had jobs nearly all summer but not very much in them. Next week, September 4,
|
|
||||||
school opens. I wish they would wait for a week but you know these school men. Wouldn't
|
|
||||||
make any special difference I suppose for I would just fritter away the time but still one likes
|
|
||||||
to postpone the inevitable.
|
|
||||||
|
|
||||||
I just now stopped and re-read your letter and it sure was a bird. I don't especially blame Ray
|
|
||||||
for reading over your shoulder. It would seem, then that you have bright children. Maybe
|
|
||||||
they do know something about Geography. But it is ridiculous to speak of Louis finishing the
|
|
||||||
eighth grade. Why you and I were grown children when we finished and he is only a baby. I
|
|
||||||
am rather afraid he doesn't know much. I quite remember your little timid Maurice and how
|
|
||||||
he shifted his affection from his Aunt Om and yelled and howled and screamed steadily for a
|
|
||||||
week while his mother went to S.S. Ask him is he recalls this little interview. Do you suppose
|
|
||||||
he does?
|
|
||||||
|
|
||||||
Ever hear from Zen? or Inez? They don't seem to be very writing inclined tho Zen has done
|
|
||||||
well this year. Even sent me a telegram a few weeks ago. Well, if anything else ever happens,
|
|
||||||
I'll write again. Don't suppose it ever will, tho.
|
|
||||||
|
|
||||||
Lots of love to all,
|
|
||||||
|
|
||||||
Ome
|
|
||||||
|
|
||||||
Reprinted from Cochran Chronicles, Volume 9, Number 1, November 1986
|
|
||||||
|
|
||||||
© JECFA 1986
|
|
||||||
|
|
||||||
Up
|
|
||||||
|
|
||||||
jecochranclan.org ~ Contact webmaster
|
|
||||||
|
|||||||
@@ -2,29 +2,30 @@ source: Rod Moser Letter - p1.jpg
|
|||||||
provider: openrouter
|
provider: openrouter
|
||||||
model: google/gemini-2.5-flash
|
model: google/gemini-2.5-flash
|
||||||
---
|
---
|
||||||
|
[document body mixed]
|
||||||
JOHN ISBILL
|
JOHN ISBILL
|
||||||
R. T. MOSER
|
R. T. MOSER
|
||||||
ISBILL & MOSER
|
ISBILL & MOSER
|
||||||
DEALERS IN
|
DEALERS IN
|
||||||
GENERAL MERCHANDISE
|
GENERAL MERCHANDISE
|
||||||
|
[handwritten: Vonore, Tenn. Jan'y 27 - 1913]
|
||||||
|
|
||||||
Vonore, Tenn. Jany 27- 1913
|
[handwritten: Dear Much Aunt Louing
|
||||||
Dear Much Aunt Adeline
|
I was at home a
|
||||||
Was at home a
|
|
||||||
few nights ago & saw a
|
few nights ago & saw a
|
||||||
letter from your folks. So
|
letter from you folks, so
|
||||||
I decided to write you
|
I decided to write you
|
||||||
a few lines myself ok
|
a few lines myself &
|
||||||
I am contemplateing [sic] a
|
I am contemplating a
|
||||||
trip out west next summer
|
trip out west next summer
|
||||||
& [inserted: I] want some of them to go
|
& would like of [illegible] to go
|
||||||
when I am [inserted: a] them.
|
where I am from.
|
||||||
Am getting
|
Am getting
|
||||||
up in years & unmarried
|
up in years & unmarried
|
||||||
so you see the object of
|
so you see the object of
|
||||||
my trip, is to get a wife
|
my trip, is to get a wife
|
||||||
& if there is any old maids
|
of there is any old maids
|
||||||
or widows out there, I
|
or widows out there, I
|
||||||
want you to kiss them
|
want you to kiss them
|
||||||
at my [hand?] me at there
|
at my [illegible] for me at home
|
||||||
as soon as I get there.
|
as soon as I get there]
|
||||||
|
|||||||
@@ -7,7 +7,25 @@ import pytest
|
|||||||
|
|
||||||
from transcription.services.sources import transcribe_document_image
|
from transcription.services.sources import transcribe_document_image
|
||||||
|
|
||||||
HAS_OPENROUTER_KEY = bool(os.getenv("OPENROUTER_API_KEY"))
|
|
||||||
|
def _load_openrouter_key_from_dotenv() -> str | None:
|
||||||
|
"""Best-effort read of OPENROUTER_API_KEY from local .env without printing it."""
|
||||||
|
env_path = Path(__file__).resolve().parents[2] / ".env"
|
||||||
|
if not env_path.exists():
|
||||||
|
return None
|
||||||
|
for raw_line in env_path.read_text(encoding="utf-8").splitlines():
|
||||||
|
line = raw_line.strip()
|
||||||
|
if not line or line.startswith("#") or "=" not in line:
|
||||||
|
continue
|
||||||
|
key, value = line.split("=", 1)
|
||||||
|
if key.strip() != "OPENROUTER_API_KEY":
|
||||||
|
continue
|
||||||
|
resolved = value.strip().strip('"').strip("'")
|
||||||
|
return resolved or None
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
HAS_OPENROUTER_KEY = bool(os.getenv("OPENROUTER_API_KEY") or _load_openrouter_key_from_dotenv())
|
||||||
|
|
||||||
REAL_IMAGES_DIR = Path(__file__).resolve().parents[1] / "fixtures" / "images" / "real"
|
REAL_IMAGES_DIR = Path(__file__).resolve().parents[1] / "fixtures" / "images" / "real"
|
||||||
ARTIFACTS_DIR = Path(__file__).resolve().parents[1] / "artifacts" / "transcriptions"
|
ARTIFACTS_DIR = Path(__file__).resolve().parents[1] / "artifacts" / "transcriptions"
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from transcription.errors import AppError
|
||||||
|
from transcription.errors import ErrorCategory
|
||||||
|
from transcription.ui.components.error_presenter import display_error_category
|
||||||
|
|
||||||
|
|
||||||
|
def test_display_error_category_uses_canonical_taxonomy():
|
||||||
|
assert display_error_category(AppError("x", category=ErrorCategory.USER_INPUT)) == "validation"
|
||||||
|
assert display_error_category(AppError("x", category=ErrorCategory.NOT_FOUND)) == "not_found"
|
||||||
|
assert display_error_category(AppError("x", category=ErrorCategory.CONFLICT)) == "conflict"
|
||||||
|
assert display_error_category(AppError("x", category=ErrorCategory.EXTERNAL_PROVIDER)) == "external"
|
||||||
|
assert display_error_category(AppError("x", category=ErrorCategory.INFRA_TRANSIENT)) == "timeout"
|
||||||
|
assert display_error_category(AppError("x", category=ErrorCategory.INFRA_PERSISTENT)) == "internal"
|
||||||
Reference in New Issue
Block a user