You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[AI] Define module boundaries, safety policy, and first vertical slice
Why this issue gates the others
#34 (natural-language job specs), #48 (generative UI), #58 (pull quote details from scanned specs), #59 (suggest job title), and any statistical component of #36 all depend on decisions that belong here. Until this closes, each of those would invent its own answer to the same questions — and the answers would differ.
Nothing AI-facing should ship before this issue concludes.
Part 1 — The boundary questions to decide
1.1 Where does inference run?
Does the feature require a model?
├─ Local only (bundled or user-supplied)
│ + preserves the local-first exit criteria (#197)
│ + no document content leaves the machine
│ − model size in the installer; CPU cost; weaker capability
├─ Remote, opt-in, off by default
│ + capability
│ − document content leaves the machine → needs consent, and
│ cannot sit on the path of any core workflow
└─ Either, per deployment
− two code paths, two failure modes, two test matrices
The hard constraint: #197's exit criteria require reports exportable without network access, and preflight is local-first by design. So any remote option is opt-in, off by default, absent from the release profile unless explicitly enabled, and never required by a core workflow.
1.2 What may an AI component touch?
Recommended default, to be confirmed here:
Data
Permitted
Document metadata (title, dimensions, page count)
yes
Extracted text
only with explicit consent per document
Rendered page images
only with explicit consent per document
Preflight findings (structured)
yes
Customer/job data
no
Anything, to a remote endpoint, by default
no
Customer artwork is confidential — often under NDA before a product launch. Treat "may the model see the artwork?" as the default-deny question it is.
1.3 What may an AI component do?
This is the one that matters most.
Can the output be reviewed by a human before it takes effect?
├─ NO → the feature must not exist in that form. Redesign it.
└─ YES → what is the blast radius if it is wrong?
├─ Cosmetic (a suggested title) → suggest inline, easily dismissed
├─ Configuration (a job spec) → draft + explicit confirmation
└─ Document mutation → FORBIDDEN as a direct action.
Must produce a PDFRepairPlan reviewed through the normal
transaction/preview path like every other operation.
No AI component ever mutates a document directly. Everything goes through PDFRepairTransaction — plan, preview, candidate, revalidate — exactly like a fixup. There is no AI-specific execution path. This single rule makes the safety story tractable, because the existing review machinery already covers it.
1.4 Determinism and reproducibility
Preflight's value rests on determinism: same input, same profile, same result. An AI component that varies run to run cannot participate in that guarantee.
Therefore AI output is never an input to a preflight finding, a pass/fail decision, a certificate (#133), or a profile digest (#132). AI may help an operator decide; it may not compute technical truth.
Part 2 — Module boundary
Pdf4QtLibCore ────────────── no AI dependency, ever.
Deterministic technical truth lives here.
▲
│ structured data only (findings, metadata, text)
│
LoupeAI module ───────────── optional, feature-flagged, separable.
│ Produces SUGGESTIONS and DRAFTS only.
▼
Editor / PdfTool surfaces ── operator reviews and confirms.
Core never links an AI dependency. A build with AI disabled must be byte-identical in Core.
The module is gated like the OCR plugin: PDF4QT_MODULE_AI, defaulting OFF in PDF4QT_LOUPE_DISTRIBUTION — the same pattern already proven for PDF4QT_PLUGIN_OCR (CMakeLists.txt:81).
All AI output crosses back as typed, validated structures — never as text interpolated into a command.
Part 3 — First vertical slice
Pick the smallest feature that exercises the whole boundary without risking anything. #59 (suggest job title from live text and metadata) is the right candidate:
cosmetic blast radius — a wrong title costs nothing;
exercises consent (reads document text), the suggest-not-act pattern, the feature flag, and the disabled-build path;
ships value independent of everything else.
Explicitly not first: #58 (pull quote details from scanned specs), because wrong extracted numbers flow into pricing, and #34's NL parsing, whose blast radius is configuration.
Acceptance criteria
An ADR under docs/adr/ records decisions for 1.1–1.4 with rationale.
A documented module boundary showing Core has no AI dependency.
PDF4QT_MODULE_AI exists, defaults OFF in the release profile, and a disabled build is byte-identical in Core — asserted by test.
A written data policy stating what AI components may access and what requires per-document consent.
A written rule, enforced by test, that no AI path reaches document mutation without a reviewed PDFRepairPlan.
AI output is excluded from findings, pass/fail, certificates, and profile digests.
Any remote option is off by default, requires explicit consent, and is absent from the release profile.
Test strategy
Build-isolation test: PDF4QT_MODULE_AI=OFF produces Core binaries identical to a build where the module does not exist.
Mutation guard: static check plus a runtime test asserting no AI code path calls PDFRepairTransaction::apply() without an operator confirmation step.
Determinism guard: assert no PreflightResult field is influenced by AI output — run preflight with the module enabled and disabled; results must be byte-identical.
Consent: with consent withheld, assert no document text or page image reaches the module.
Offline: with the module enabled and networking disabled, assert core workflows are unaffected.
[AI] Define module boundaries, safety policy, and first vertical slice
Why this issue gates the others
#34 (natural-language job specs), #48 (generative UI), #58 (pull quote details from scanned specs), #59 (suggest job title), and any statistical component of #36 all depend on decisions that belong here. Until this closes, each of those would invent its own answer to the same questions — and the answers would differ.
Nothing AI-facing should ship before this issue concludes.
Part 1 — The boundary questions to decide
1.1 Where does inference run?
The hard constraint: #197's exit criteria require reports exportable without network access, and preflight is local-first by design. So any remote option is opt-in, off by default, absent from the release profile unless explicitly enabled, and never required by a core workflow.
1.2 What may an AI component touch?
Recommended default, to be confirmed here:
Customer artwork is confidential — often under NDA before a product launch. Treat "may the model see the artwork?" as the default-deny question it is.
1.3 What may an AI component do?
This is the one that matters most.
No AI component ever mutates a document directly. Everything goes through
PDFRepairTransaction— plan, preview, candidate, revalidate — exactly like a fixup. There is no AI-specific execution path. This single rule makes the safety story tractable, because the existing review machinery already covers it.1.4 Determinism and reproducibility
Preflight's value rests on determinism: same input, same profile, same result. An AI component that varies run to run cannot participate in that guarantee.
Therefore AI output is never an input to a preflight finding, a pass/fail decision, a certificate (#133), or a profile digest (#132). AI may help an operator decide; it may not compute technical truth.
Part 2 — Module boundary
PDF4QT_MODULE_AI, defaulting OFF inPDF4QT_LOUPE_DISTRIBUTION— the same pattern already proven forPDF4QT_PLUGIN_OCR(CMakeLists.txt:81).Part 3 — First vertical slice
Pick the smallest feature that exercises the whole boundary without risking anything. #59 (suggest job title from live text and metadata) is the right candidate:
Explicitly not first: #58 (pull quote details from scanned specs), because wrong extracted numbers flow into pricing, and #34's NL parsing, whose blast radius is configuration.
Acceptance criteria
docs/adr/records decisions for 1.1–1.4 with rationale.PDF4QT_MODULE_AIexists, defaults OFF in the release profile, and a disabled build is byte-identical in Core — asserted by test.PDFRepairPlan.Test strategy
PDF4QT_MODULE_AI=OFFproduces Core binaries identical to a build where the module does not exist.PDFRepairTransaction::apply()without an operator confirmation step.PreflightResultfield is influenced by AI output — run preflight with the module enabled and disabled; results must be byte-identical.Dependencies
CMakeLists.txt:81— the OCR plugin gating pattern to copy.Migration provenance (imported record)
Labels: enhancement, P1-high, audit:still-open
Source: mberrys/Frisket-pdf#119 (created 2026-08-06T19:14:41Z)