Phase 1: Package Scaffold + Adapter Interface
- Purpose: Create the workspace package and define the PresentAdapter contract
T-001 - Scaffold @services/present package
Create package.json, tsconfig.json, eslint.config.mjs for @services/present.
- Status: pending
- Priority: P0
- Dependencies: none
Acceptance
-
@services/present/package.jsonwith name@services/present, scripts (build/dev/lint/test:type), deps:pptxgenjs,@packages/format(workspace:*) -
@services/present/tsconfig.jsonextending@repo/typescript/lib -
@services/present/eslint.config.mjsusingbase()from@repo/lint/base - Root
package.jsoncatalogs extended withpptxgenjsif not present
Files
- @services/present/package.json
- @services/present/tsconfig.json
- @services/present/eslint.config.mjs
T-002 - Define PresentAdapter interface and output types
Define the PresentAdapter interface, OutputOptions, PresentResult types, and add stub implementations for future adapters.
- Status: pending
- Priority: P0
- Dependencies: T-001
Acceptance
-
PresentAdapterinterface:{ name: string; render(report: Report, options: OutputOptions): Promise<PresentResult> } -
OutputOptions:{ outputDir: string; filename: string } -
PresentResult:{ pptxPath?: string; pdfPath?: string; } -
GoogleSlidesAdapterstub: implementsPresentAdapter, throwsError('Not implemented') -
NotebookLMAdapterstub: implementsPresentAdapter, throwsError('Not implemented') - All exported from
@source/adapters/index.ts
Files
- @services/present/@source/adapters/base.ts
- @services/present/@source/adapters/google-slides.ts
- @services/present/@source/adapters/notebooklm.ts
- @services/present/@source/adapters/index.ts
Phase 2: PptxAdapter
- Purpose: Implement the pptxgenjs-based PPTX renderer
T-003 - Implement PptxAdapter
The main pptxgenjs adapter. Creates a PptxGenJS instance, calls all slide generators, saves the PPTX file.
- Status: pending
- Priority: P0
- Dependencies: T-002
Acceptance
-
PptxAdapterimplementsPresentAdapter - Creates
pptxinstance with slide dimensions 13.33" × 7.5" (widescreen) - Iterates report units, calls appropriate slide generators in order
- Saves to
options.outputDir/options.filename.pptx - Returns
PresentResultwithpptxPath
Notes
- Slide order per unit: revenue-comparison → key-comparison → program-progress → school-progress
- Channel marketing slide comes after all per-unit slides (combined view)
Files
- @services/present/@source/adapters/pptx.ts
Phase 3: Slide Implementations
- Purpose: Implement all 6 slide types matching the reference PDF
T-004 - slides/cover.ts
Cover slide: gradient background (dark blue → teal), bold report title, date, and brand logos.
- Status: pending
- Priority: P0
- Dependencies: T-003
Acceptance
- Background: gradient fill from
#0d47a1to#006064(left to right) - Title: "PLAN [MONTH] [YEAR]" in bold white, large font
- Date line: formatted date in white, smaller font
- Brand logo placeholders (or actual logo images if available in
@services/present/assets/) - Matches reference PDF page 1 layout
Files
- @services/present/@source/slides/cover.ts
T-005 - slides/revenue-comparison.ts
Revenue comparison slide per unit: summary table (last month, last year, all-time best, target, actuals) + bar chart below.
- Status: pending
- Priority: P0
- Dependencies: T-003
Acceptance
- Slide number badge (e.g. "1") and title "Perbandingan Target Revenue – [Unit]" with unit brand color
- Summary table: 5 columns (Bulan Sebelumnya, Tahun Sebelumnya, Pencapaian Tertinggi, Target, Realisasi), 2 rows (header + values)
- Bar chart: 5 bars (Last Month, Last Year, Highest, Target, Current) in unit brand color
- Realisasi column highlighted in green if met/exceeded target, red if below
- Matches reference PDF pages 2–3
Files
- @services/present/@source/slides/revenue-comparison.ts
T-006 - slides/key-comparison.ts
Key comparison slide per unit: table comparing last year, target, actuals, gap%, and status for revenue + student types.
- Status: pending
- Priority: P0
- Dependencies: T-003
Acceptance
- Slide number badge "2" and title "Komparasi Utama" with unit brand color
- Table rows: Total Revenue, Total Siswa Baru, Total Siswa Lanjut, Total Siswa Alumni
- Columns: Parameter, Realisasi [Last Year] (Full), Target [Current Period], Realisasi [Current Period] (Ongoing), Gap to Goal (%), Status
- Status cell color: Completed=green bg, On Track=light blue bg, Needs Attention=salmon bg
- Matches reference PDF pages 4–5
Files
- @services/present/@source/slides/key-comparison.ts
T-007 - slides/program-progress.ts
Program progress slide per unit: per-program table with last year, target, actuals, and status.
- Status: pending
- Priority: P0
- Dependencies: T-003
Acceptance
- Slide number badge "3" and title "Progres Program" with unit brand color
- Table rows: one per program (product_name)
- Columns: Parameter (program name), Realisasi [Last Year], Target [Current Period], Realisasi [Current Period], Status
- Status cell color coding matching reference PDF
- Matches reference PDF pages 6–7
Files
- @services/present/@source/slides/program-progress.ts
T-008 - slides/school-progress.ts
School progress slide per unit: dense matrix table of organizations × years.
- Status: pending
- Priority: P0
- Dependencies: T-003
Acceptance
- Slide number badge "4" and title "Progres Sekolah" with unit brand color
- Organizations as rows, years as columns (sorted ascending: 2021, 2022, 2023, 2024, 2025, 2026)
- Cells with non-zero student count show the count; empty cells show blank
- Organizations grouped by education level (Perguruan Tinggi, SMA, SMP, SD) with section headers
- Two marketing channel checkbox columns (KON, DIG) as in reference
- Highlighted rows (yellow/cyan) for schools active in current year
- Matches reference PDF pages 8–9
Notes
- School progress slide is the most complex — the reference shows dense tables with hundreds of rows; may need font size 6–7pt for dense tables
Files
- @services/present/@source/slides/school-progress.ts
T-009 - slides/channel-marketing.ts
Channel marketing slide: combined across units, showing leads/follow-ups/closings/contribution per channel.
- Status: pending
- Priority: P0
- Dependencies: T-003
Acceptance
- Slide number badge "5" and title "Progres Channel Marketing"
- One table per unit on the same slide (or separate slides if more than 2 units)
- Columns: Channel Marketing, Jml Respon Masuk, Jml Follow Up, Jumlah Siswa (Closing), Kontribusi (%), Status, Strategi
- Status color coding: High Performer=green, Solid=blue, Potensial=yellow, Needs Improv...=salmon
- Matches reference PDF page 10
Files
- @services/present/@source/slides/channel-marketing.ts
Phase 4: Generator + PDF Conversion
- Purpose: Orchestrate slide order and produce both PPTX and PDF outputs
T-010 - generator.ts — Slide orchestrator
Calls all slide generators in the correct order for each unit, assembles the full deck.
- Status: pending
- Priority: P0
- Dependencies: T-004, T-005, T-006, T-007, T-008, T-009
Acceptance
-
generate(pptx, report, options)function - Slide order: cover → for each unit [revenue-comparison, key-comparison, program-progress, school-progress] → channel-marketing
- Per-unit brand color resolved from unit code:
WLC_ENGLISHandWLC_NON_ENGLISH→#1565c0,TM→#7b1111, others →#1565c0
Files
- @services/present/@source/generator.ts
T-011 - PDF conversion via LibreOffice CLI
Implement the PDF conversion step that invokes libreoffice --headless --convert-to pdf.
- Status: pending
- Priority: P1
- Dependencies: T-010
Acceptance
-
convertToPdf(pptxPath, outputDir)usesBun.spawnto run LibreOffice CLI - Detects if LibreOffice is not installed and warns rather than hard-fails
- Returns path to generated PDF file
- Exported from
@source/pdf.ts
Files
- @services/present/@source/pdf.ts
Phase 5: CLI + Verification
- Purpose: Wire the CLI and verify end-to-end output
T-012 - index.ts — CLI entry point
Wire the CLI with --report or --entity + --period flags.
- Status: pending
- Priority: P0
- Dependencies: T-010, T-011
Acceptance
-
--report path/to/report.jsonreads the JSON directly -
--entity IONS --period 2026-02callsassembleReportfrom@packages/formatfirst, then renders -
--adapter pptx|google-slides|notebooklm(default: pptx) - Outputs paths of generated PPTX and PDF files
- Exits 0 on success
Files
- @services/present/@source/index.ts
T-013 - Add root scripts and NETWORK.yml entry
Add present script to root package.json and update AGENTS.md.
- Status: pending
- Priority: P1
- Dependencies: T-012
Acceptance
- Root
package.jsonhas"present": "bun run --filter @services/present start"(or equivalent) -
AGENTS.mdcommit scopes list includespresent -
AGENTS.mdCLI usage updated with present commands
Files
- package.json
- AGENTS.md
T-014 - bun install + type-check
Install and verify type-check.
- Status: pending
- Priority: P0
- Dependencies: T-001, T-002, T-003, T-012, T-013
Acceptance
-
bun installcompletes -
bun run test:type --filter @services/presentpasses
Files
- bun.lock
T-015 - End-to-end verification
Run the CLI against real 2026-02 report.json and verify both output files.
- Status: pending
- Priority: P0
- Dependencies: T-014
Acceptance
-
bun run present --entity IONS --period 2026-02exits 0 -
output/monthly/2026-02.pptxexists and is a valid PPTX file (>10KB) -
output/monthly/2026-02.pdfexists (if LibreOffice installed) - PPTX contains slides for WLC and TM units with correct colors
- Revenue comparison slides match data in report.json