| status | ACTIVE |
|---|
Generated by /plan-ceo-review on 2026-04-21 Branch: (no git repo yet) | Mode: SELECTIVE EXPANSION Repo: /Users/siraj/Print CMS (slug: PrintCMS) Approach: A (build brief as written)
This is a CEO-level decision summary. It captures:
- Accepted scope additions on top of the brief (5 items, below)
- Deferred items and why
- Blocking preconditions that must be answered before Phase 2 implementation begins
It is NOT an engineering spec. Detailed acceptance criteria, tool choices (exact diff tool, file-lock mechanism, CSV parser, measurement pipeline), and test matrices live in /plan-eng-review, which runs after this document and Phase 1 verification.
The source of truth for product scope is the original product brief (52-template inventory, 12 classified types, 11 ad slots, 13-phase build order, print-readiness checklist, out-of-scope list, open questions).
A single non-technical operator produces print-ready magazine issues (.pptx → PDF in PowerPoint) for an Indian regional publisher. A4 + A5, English + Hindi + bilingual, classifieds, ads, covers, auto-fit, auto-versioning, offline-first. Eventually SaaS.
AI-assisted editorial copilot: raw transcript → proposed headline + deck + pull quote + cover lines; Whisper+LLM classifieds intake; image crop suggestions; per-issue copyedit. MVP preserves the architectural hooks for this (structured templates, content types, content-addressable assets) but implements none of it.
Pretext is confirmed real (https://github.com/chenglou/pretext). Pure JS/TS, uses Canvas 2D measureText() as ground truth via the browser's font engine. Runs in the Electron renderer (browser context). Server-side support is still "soon."
Pretext gives pixel-perfect measurement of the web/Electron editor preview. That preview is the source of truth. The architecture question the harness answers: how faithfully can we map Pretext's measured layout into a PPTX such that PowerPoint renders it identically?
PowerPoint must be constrained to a display surface, not allowed to re-typeset. OOXML mechanisms available to us:
- EMU-precise positioning (914400 units/inch) for text box placement (
<a:off>/<a:ext>). - Explicit pre-computed line breaks (
<a:br/>or paragraph-per-line) so PowerPoint's line-break algorithm never runs. - Disabled autofit (
<a:normAutofit/>off) so PowerPoint doesn't rescale. - Precise leading via
<a:lnSpc>values matching Pretext's output. - Run-level explicit positioning for fine kerning control where needed.
- Embedded font subsets so PowerPoint uses the same glyph outlines Pretext measured against.
Harness job: take a representative template × content pair, render the editor preview (Pretext), generate PPTX, open in PowerPoint, compare. Acceptance: every line in the PPTX appears at the same pixel coordinate as the Pretext preview, within a defined tolerance. Tolerance, measurement method, and automation tooling are /plan-eng-review work.
Phase 2 gate: at least the Standard Feature A4 English Editorial Serif template must pass the mapping fidelity test. Subsequent templates in Phase 4+ each pass the same harness before merging.
Gate failure consequence: the mapping approach is revisited. Likely fallbacks (decided at the time by engineering + user):
- Tighter pre-breaking (paragraph-per-line instead of paragraph-per-block).
- Single-text-box-per-line at explicit EMU coordinates (loses editability in PowerPoint, which is fine per brief).
- SVG embedding for problem text blocks (loses text selection; last resort).
A full architectural pivot (Paged.js + HTML export) is NOT in MVP scope.
Target platforms for MVP gate: whichever PowerPoint versions the pilot publisher's operator actually uses (resolved by Blocking Precondition #2, "Pilot publisher OS target," below). MVP gate covers exactly those; additional platforms are out of scope.
Coverage: sample Hindi articles exercising shirorekha, conjuncts, matra stacking, nukta forms, mixed-script with English brand names and Arabic numerals, and Devanagari poetry (left-aligned).
Gate pass criterion: operator reviews rendered PPTX on the target platforms; no glyph drops, no conjunct breakage, no overflow. Manual review with tooling assistance (diff tool choice is /plan-eng-review work).
Gate failure consequence: Hindi release blocked. Two options to choose between:
- 2a: Engineering addresses the specific rendering issue (font substitution, template spacing adjustment, pptxgenjs configuration).
- 2b: Hindi ships in v1.1 instead of MVP, English-only MVP proceeds.
This is a DEFERRED CEO DECISION, not a deferred engineering detail. When Phase 3 starts and a specific failure type is known, the user decides between 2a and 2b based on the estimated fix cost and the project timeline at that moment. Do not start Phase 3 work without a committed fallback choice. A third option — rearchitecting to Paged.js + HTML export just for Hindi — is NOT in MVP scope. If Hindi doesn't work in PPTX, it's deferred, not rearchitected.
Standalone screen runs brief Section 21 checks without generating a PPTX. Shared library between this screen and export — no duplicated logic. Warnings are non-blocking (no per-issue ignore list). Errors block export until fixed.
In scope at decision altitude:
- Detect prior-unclean-exit on Electron startup.
- Offer a non-technical "Recover / Discard / Open-Fresh" prompt referencing the last auto-save time.
- Integrity check runs in background and does not block startup.
- Operator sees an understandable remediation flow if any image is corrupted (replace / continue / restore-from-backup), with "restore from backup" being the operator's own external backup, not an in-system recovery of content-addressed bytes.
Implementation details (exact lock mechanism, integrity cadence, hash-verification strategy, dialog wording, remediation flow UI) are /plan-eng-review work.
- Per-type CSV template matching the field set of each of the 12 classified types.
- Accept UTF-8 with or without BOM. Reject non-UTF-8 with a clear error. (Hindi CSV content is UTF-8 regardless; the BOM is a Windows Excel artifact we tolerate.)
- Preview grid shows parsed rows with validation errors highlighted. Operator imports only-valid-rows, fixes and re-uploads, or cancels.
- Size cap: 1000 rows per CSV, reject larger with a suggestion to split.
- Duplicate detection on (phone number + billing reference) — ASCII-safe fields only to avoid Hindi-name normalization complexity. Duplicates shown in preview with per-row import-anyway / skip.
- Image-attached classifieds reference images by filename; images must already be in the Content Library.
Note on estimate: this is M (≈ 1 week CC) because of 12 per-type schemas × validation × preview UI × duplicate handling. Could be de-risked further by cutting to the 3 highest-volume classified types for MVP (matrimonial with photo, public notice, obituary) and expanding later, but not recommended since form entry already covers all 12 and CSV is the scale tool.
- Voice intake for classifieds via local Whisper + LLM extraction.
- Font substitution safety check.
- Typography pairing preview page.
- Cover variant thumbnails.
- Classifieds deduplication beyond phone+billing-ref.
- Template style tokens (per-issue accent color, etc.).
- Issue-to-web HTML export.
- Printer profile upload.
- Backup-as-ZIP export.
- Issue structure duplication ("clone last issue's skeleton").
- Crash recovery thumbnail previews.
- Per-issue ignore list for pre-export warnings.
Defer entirely to brief Section 22.
The brief says "do not preclude multi-tenancy." To meet that promise with minimum scope creep:
- Issue-level tenant scoping: SQLite issues table carries a
tenant_idcolumn, constantpublisher_defaultin MVP. Other tables reference issues (FK); they don't need their own tenant_id — it cascades through the issue relationship. Migration to real multi-tenancy is a schema change, not a re-architecture. - Asset storage prefix:
assets/{tenant-id}/{...}, tenant-id hardcoded topublisher_defaultin MVP.
That's the complete list. No template_overrides table, no tenant-scoped font override table, no tenant-specific fonts directory. Multi-tenancy UI surface, RBAC, admin tooling — all deferred.
Per user direction (Temporal 1 answer): pilot-publisher-specific inputs are dynamic config inside the app, not hardcoded assumptions in the brief or code. A "Publisher Profile" is the first-run configuration screen the operator fills out:
- Publication name
- Masthead logo (upload)
- House-style accent color (picker; applies to section dividers, pull quotes if templates support)
- Typography pairing default (pick one of the four; overridable per issue)
- Primary language default (en / hi / bilingual)
- Default page size (A4 / A5)
- Default issue cadence (weekly / fortnightly / monthly) — informs "next issue" date suggestions
- Printer contact info + delivery method (email / courier / portal URL) — free-text, displayed at export time
- Ad position label list (operator types their own, brief Section 15.2 is default suggestion)
- Classifieds "billing reference" label (operator types their own term, e.g., "Invoice #")
This means none of the brief's pilot-publisher-driven open questions need to be answered before Phase 1 — they become user-settable config. The product ships usable to any publisher. This is also how the SaaS future works naturally.
macOS-only for dev and first deploy. Windows is a roadmap pathway, not a Phase-1 concurrent target. Specifically:
- Phase 1-13 implementation on macOS.
- Installer built for macOS (.dmg, signed + notarized).
- Devanagari Phase 3 gate tests on Office 365 macOS only for MVP.
- Code is kept Windows-portable (no macOS-specific APIs outside well-scoped modules) so Windows build is a later deliverable.
- Windows installer + Windows PowerPoint testing is a named post-MVP milestone, NOT a gate or dependency.
This simplifies the Pretext harness (no Windows VM needed for MVP), the Devanagari QA suite (one OS), and the installer work.
Definition of "Phase 1 complete": 3 technical blockers. Everything else is Publisher Profile config (first-run UI, no engineering dependency).
- Pretext → PPTX mapping probe. Pretext confirmed real. Phase 1 builds a minimal template, runs it through Pretext measurement, generates PPTX with explicit pre-breaks (approach options listed in Accepted Scope #1), opens in Office 365 macOS, measures the rendering drift. If tolerance is met, proceed to Phase 2. If not, try the next fallback mapping approach until tolerance is met. Phase 2 cannot begin until at least one mapping approach passes.
- PowerPoint scripting probe (macOS). Can we drive Office 365 macOS via AppleScript (or alternative: LibreOffice headless, or convert-to-PDF-and-measure) well enough to automate the mapping harness? If no path works, the harness is manual; update timelines.
- Font subset embedding verification. Confirm
pptxgenjs(or a direct OOXML writer if needed) can embed Google Font subsets that render correctly in Office 365 macOS. Non-trivial because PowerPoint's font embedding preferences have changed over versions.
These are no longer Phase-1 blockers; they surface in the Publisher Profile first-run UI.
- Publication name and house style.
- First-issue content mix (informs which templates the operator opens first; doesn't gate development).
- Lite mode toggle for fewer templates.
- Ad position label list.
- Backup workflow guidance text.
- Printer contact info + delivery method.
- Image pathway (informational; operator may upload from wherever).
- Existing publication assets (upload-as-needed at first run).
- Network context (informational; product works offline regardless).
- Framework choice (React vs Svelte vs Solid).
- Styling approach (Tailwind vs vanilla CSS vs CSS-in-JS).
These remain open deliberately — resolution belongs in Phase 1 or /plan-eng-review:
- PowerPoint scripting feasibility (macOS). Phase 1 probe.
- Devanagari rendering diff tool + tolerance.
/plan-eng-reviewwork. - CSV parser + encoding edge cases.
/plan-eng-reviewwork. - File-lock mechanism for crash recovery.
/plan-eng-reviewwork. - Pretext → PPTX mapping approach selection (paragraph-per-line vs. text-box-per-line vs. SVG fallback).
/plan-eng-reviewlocks, Phase 1 probe validates.
| Section | Decision # | Topic | Choice |
|---|---|---|---|
| 1 | 1H | Re-export rollback UX | B — default to current editor state, operator can override via history panel |
| 1 | 1I | Silent font-load fallback | A — block editor with "fonts missing" error if required font unavailable |
| 2 | 2A+2B | Data-loss protections (OOXML validation + SQLite backup) | A — both in scope for MVP |
| 2 | 2C | Classified entry too tall for column | A — Extended Notice page (dedicated full-width) |
| 3 | 3C | Electron security update mechanism | B — no update mechanism in MVP; operator manually reinstalls |
| 4 | 4B | Article already placed, dragged to another page | A — move with confirmation |
| 4 | 4C | Bulk import partial failure UX | A — review screen shows success + failure, operator proceeds with successful |
| 4 | 4F | Form idempotency vs double-click | A — debounce 500ms + client-side dedup check |
| 8 | 8A+8E | Local logging + Diagnostics menu | A — structured local logs (7-day rotation) + Diagnostics export-as-zip button |
| 9 | 9C+9F | First-run wizard + rollback doc | A — first-run wizard in scope; rollback via prior .dmg install |
| 11 | 11A | IA structure | A — 8-tab structure (Issue Board / Articles / Classifieds / Ads / Images / Templates / History / Settings) |
Nine findings, three presented as decisions:
| OV # | Topic | User choice |
|---|---|---|
| OV1 | Phase 2 gate framing (pixel-identical vs. tolerance) | B — Keep pixel-identical framing; accept risk. User takes conviction position: the mapping IS solvable with the right OOXML approach. |
| OV2 | Precondition sequencing (#3 before #1?) | B — Run #1 and #3 in parallel. Moderate-risk, faster Phase 1. |
| OV3 | Pilot commitment + Hindi positioning | B — Proceed without pilot; Publisher Profile generics are enough. |
Outside voice findings not translated to decisions (flagged as background risk):
- OV #1 (rasterizer mismatch Canvas vs CoreText): real and needs Phase 1 empirical validation. If the probe shows drift > tolerance, this re-surfaces as a hard decision.
- OV #4 (paragraph-per-line is a product change, not an engineering detail): if fallback hits, operator UX changes. Worth documenting in the help text.
- OV #5 (Phase 2 harness needs ground-truth renderer): AppleScript flakiness is Reviewer Concern; LibreOffice is not a proxy.
/plan-eng-reviewpicks the path. - OV #6 (InDesign/Affinity alternative at 10x less work): explicitly rejected via Approach A commitment. Named here for archaeology.
- OV #7 (template bundle hardens from guesswork without pilot): risk accepted per OV3B. First-issue feedback from the eventual pilot will cause template rework.
- OV #8 (Hindi-in-v1.1 = positioning change): risk accepted per OV3B. If the Phase 3 Hindi gate fails, re-review positioning before committing to 2b.
- OV #9 (Office point-release rendering breakage): no rollback mechanism in MVP. Reviewer Concern; needs v1.1 monitoring.