Adds .github/workflows/quality-gate.yml, running the gate on push and pull
request. CI invokes `pre-commit run --all-files` rather than restating the
`ruff check` and `ty check` commands, so the checks keep a single definition
in .pre-commit-config.yaml and local and CI cannot drift (plan task 2).
The workflow writes a .env file rather than exporting an environment
variable. The two are not equivalent here: Settings reads the .env file,
while the external-test skip guard reads os.getenv, so an exported variable
un-skips the external tests and sends them to the network. Measured in CI:
no .env gave 115 failures and 18 errors, an exported dummy key gave 3
failures, and a written .env file reproduced the local baseline exactly.
Negative-tested on a scratch branch: a deliberate lint error failed the run
at `ruff check` with exactly the planted errors, confirming the gate blocks
rather than merely reporting (plan task 4). The subsequent clean run passed
ruff and ty and reported 295 passed, 4 skipped, matching local and
confirming the four credential-gated tests skip cleanly (plan task 3).
That first green run caught a real platform-dependent defect. PromptStore
rejected non-direct-child names via `Path(name).name != name`, which is
platform-dependent: on POSIX a backslash is an ordinary filename character,
so "nested\prompt.md" passed the guard and failed later as NOT_FOUND rather
than VALIDATION. Windows cannot reproduce it. No traversal was possible,
since the path.parent != root check still held, so the impact was a wrong
error category and a red gate. Both separators are now rejected explicitly,
matching the ^[^/\\]+$ pattern config.PromptFilename already used.
Also exports docs/ver4.7/review_log_v4_7.md, the working record kept across
all six phases: 50 entries, 1 still open. The open entry is a pre-existing
/ui redirect defect found during the Phase 3 UI walk and deliberately left
unfixed as outside the V4.7 scope boundary.
Co-authored-by: Copilot App <[email protected]>
Preserves the traceability the V4.7 plan depends on ahead of starting
implementation in a fresh session. Documentation only.
The V4.6 review log was maintained in a session-scoped database and cited
by number throughout the V4.6, V4.7, and V4.8 planning documents as
"review log [N]". Those citations were unresolvable outside the session
that produced them. The log is now exported verbatim to
docs/ver4.6/review_log_v4_6.md: 70 entries, of which 8 remain open, each
mapped to its disposition (V4.7 phase, accepted risk, or operator
judgement).
The architecture review report is retained rather than deleted. It is the
canonical registry of the 32 finding IDs cited across six documents, so
removing it would orphan every CRIT/HIGH/MED/LOW reference in the planning
corpus. Instead it now carries a status banner marking it as a pre-V4.6
snapshot, warning that its paths, line numbers, and baseline metrics are
stale, recording that all 32 findings were dispositioned in V4.6 with only
MED-14 and HIGH-06 carrying into V4.7, and noting the two recommendations
later revised on evidence - the cancelled services/artifacts.py extraction
and the assumption that job_source and execution_attempt were
complementary rather than duplicated.
Co-authored-by: Copilot App <[email protected]>
Plans the next two releases following the V4.6 architecture remediation.
Documentation only - no code or schema changes.
V4.7 is an architectural cleanup and evidence-model re-alignment release,
scoped from measurements taken against the live database:
- job_source and execution_attempt duplicate the same evidence. Measured
77/77 identical on raw_transcription, ai_metadata vs normalized_metadata,
and raw_api_response vs sdk_response_snapshot. job_source is stripped to
its original junction role plus queue state (9 columns -> 4); all evidence
reads move to execution_attempt.
- job_source is stripped rather than deleted because it is also the work
queue: rows are created PENDING before any provider call, and cancellation
writes a terminal state with no provider call at all. An append-only
evidence table cannot express either.
- JobSourceStatus.CANCELLED is added so cancellation stops overloading
FAILED plus free text, which retires job_source.error_detail. This absorbs
the dual-spelling fix [45], since both rewrite the same persistence.
- ProcessingArtifact is removed. Two rows exist against 77 successful
transcriptions, so the subsystem has effectively never run. Orientation
normalization moves to ingest, where it is applied once and needs no
derivative.
- Orientation normalization itself is retained: 58 of 79 stored images carry
EXIF orientation 3, and their raw decoded pixels are genuinely inverted.
Rotation switches to quantization-table reuse, measured better than the
current quality=95 settings on both fidelity (51.5-55.0 dB PSNR vs
50.0-53.5) and size (-6% vs +38%).
- The planned services/artifacts.py extraction is cancelled. The cluster is
deleted rather than moved, establishing a delete-before-refactor ordering.
V4.8 parks feature work: pan and zoom, homepage gallery, multi-portrait
support, image descriptions, and the model-performance rollup, which stays
gated on the V4.7 run-time measurement fix.
Co-authored-by: Copilot App <[email protected]>