Phase 1: CLI Restructure
- Purpose: Reorganize command parsing, add new commands, normalize flags
T-001 - Refactor CLI argument parser
Add support for month ranges (1-3), case-insensitive entity/unit, and new --type flag.
- Status: completed
- Priority: P0
- Dependencies: none
Acceptance
-
parseMonth("2")returns{ start: 2, end: 2 } -
parseMonth("1-3")returns{ start: 1, end: 3 } -
--entity ionsnormalized toIONS -
--unit tmnormalized toTM -
--typeflag parsed for report command - Unit tests pass
Notes
- Month range validation: start <= end, both 1-12
- Type values:
monthly,quarterly,yearly
Files
- @packages/pipeline/@source/index.ts
- @packages/pipeline/@source/cli.ts (new, extract parsing logic)
T-002 - Add sync command
Create unified sync command that runs extract → load → validate → transform.
- Status: completed
- Priority: P0
- Dependencies: T-001, T-005
Acceptance
-
pnpm pipeline -- sync --entity IONS --year 2026executes full chain -
pnpm pipeline -- sync --entity IONS --year 2026 --month 2filters load to single month - Each stage logs start/completion
- Pipeline run recorded in
_pipeline_runs
Notes
- Replaces current
runcommand behavior - Transform step added (T-005 dependency)
Files
- @packages/pipeline/@source/index.ts
- @packages/pipeline/@source/commands/sync.ts (new)
T-003 - Update root package.json scripts
Add new root-level shortcuts for seed, sync, publish, report.
- Status: completed
- Priority: P1
- Dependencies: T-002, T-006, T-007
Acceptance
-
pnpm seed --entity IONSworks -
pnpm sync --entity IONS --year 2026works -
pnpm publish --entity IONS --year 2026 --month 2works -
pnpm report --entity IONS --year 2026 --month 2 --type monthlyworks - Existing scripts still work (backward compatible)
Notes
- Keep existing
extract,validate,format,presentas dev/debug commands
Files
- package.json
Phase 2: Transform & Publish
- Purpose: Implement missing pipeline stages
T-004 - Create _pipeline_runs table
Add DuckDB metadata table for tracking pipeline executions.
- Status: completed
- Priority: P0
- Dependencies: none
Acceptance
- Table created on first pipeline run if not exists
- Schema includes: id, entity, year, month, stage, started_at, completed_at, status, error_message, source_file_hash, row_count
- Index on (entity, year, stage, completed_at)
- Helper functions:
recordPipelineStart(),recordPipelineComplete(),getLastRun()
Notes
- Use DuckDB sequences for auto-increment id
Files
- @packages/pipeline/@source/meta.ts (new)
- @packages/pipeline/@source/duck.ts (add table setup)
T-005 - Add transform command
Create wrapper for uv run dbt run execution.
- Status: completed
- Priority: P0
- Dependencies: T-004
Acceptance
-
pnpm pipeline -- transform --entity IONSruns dbt - Shells out to
uv run dbt runin@python/analyticsdirectory - Captures exit code and stderr
- Records run in
_pipeline_runs - Supports
--selectpassthrough for dbt model selection
Notes
- dbt doesn't filter by entity at runtime (all data processed)
- Entity param used for metadata tracking only
Files
- @packages/pipeline/@source/commands/transform.ts (new)
- @packages/pipeline/@source/index.ts
T-006 - Add publish command
Create DuckDB → LibSQL sync for operational tables.
- Status: completed
- Priority: P0
- Dependencies: T-004
Acceptance
-
pnpm pipeline -- publish --entity IONS --year 2026 --month 2syncs data - Reads from DuckDB
int_orders,int_enrollments - Writes to LibSQL
commerce_order,finance_transaction,db_person - Uses transaction (BEGIN → DELETE → INSERT → COMMIT)
- Delete scoped to entity + year + month
- Records run in
_pipeline_runs - Handles FK resolution (lookup/create dimension records)
Notes
- Delete + insert strategy (not upsert)
- Must resolve: organization_name → db_organization, student_name → db_person
Files
- @packages/pipeline/@source/commands/publish.ts (new)
- @packages/pipeline/@source/publish/orders.ts (new)
- @packages/pipeline/@source/publish/dimensions.ts (new)
- @packages/pipeline/@source/index.ts
Phase 3: Report Unification
- Purpose: Combine format + present into unified report command
T-007 - Create unified report command
Combine format and present into single report command with --type flag.
- Status: completed
- Priority: P0
- Dependencies: T-001, T-004
Acceptance
-
pnpm pipeline -- report --entity IONS --year 2026 --month 2 --type monthlyworks - Runs format → present in sequence
- Supports
--type monthly,--type quarterly,--type yearly - Output paths:
IONS-2026-02.json,IONS-2026-Q1.json,IONS-2026.json - Records run in
_pipeline_runs
Notes
- Monthly is default if
--typenot specified - Quarterly requires month range (
--month 1-3)
Files
- @packages/pipeline/@source/commands/report.ts (new)
- @packages/pipeline/@source/index.ts
T-008 - Implement quarterly report aggregation
Extend format logic to aggregate multiple months for quarterly reports.
- Status: completed
- Priority: P1
- Dependencies: T-007
Acceptance
-
--type quarterlywith--month 1-3aggregates Jan-Mar data - Revenue comparison shows quarter totals
- Program progress shows quarter totals
- Output file named
IONS-2026-Q1.json - Quarter label derived from month range (1-3=Q1, 4-6=Q2, 7-9=Q3, 10-12=Q4)
Notes
- Non-standard ranges (e.g.,
--month 2-4) should use "range" label, not quarter
Files
- @packages/pipeline/@source/format/report.ts
- @packages/pipeline/@source/format/types.ts
T-009 - Add staleness check
Implement data freshness check before report generation.
- Status: completed
- Priority: P1
- Dependencies: T-004, T-007
Acceptance
- Before format, check
_pipeline_runsfor last transform - Warn if source file modified since last extract
- Warn if no transform found for entity/year
-
--forceflag skips staleness check - Warning is info-only (does not block)
Notes
- Hash source files for change detection
- Warnings printed to stderr
Files
- @packages/pipeline/@source/staleness.ts (new)
- @packages/pipeline/@source/commands/report.ts
Phase 4: FK Resolution for Publish
- Purpose: Handle dimension table lookups/creation during publish
T-010 - Implement dimension resolver for db_person
Lookup or create person records during publish.
- Status: completed
- Priority: P0
- Dependencies: T-006
Acceptance
- Given student_name from int_orders, find or create db_person
- Use entity_id scoping
- Return person_id for commerce_order FK
- Handle duplicates gracefully (same name = same person within entity)
- Cache lookups within publish transaction
Notes
- Student names are denormalized in dbt output
- May need fuzzy matching for name variations (future)
Files
- @packages/pipeline/@source/publish/dimensions.ts
T-011 - Implement dimension resolver for db_organization
Lookup or create organization records during publish.
- Status: completed
- Priority: P0
- Dependencies: T-006
Acceptance
- Given organization_name from int_orders, find or create db_organization
- Use entity_id scoping
- Return organization_id for db_person FK
- Cache lookups within publish transaction
Notes
- Organizations come from REFERENSI sheet (already seeded as lookups?)
- May need to verify seed coverage
Files
- @packages/pipeline/@source/publish/dimensions.ts
T-012 - Implement db_account creation for orders
Create account records linking person to organization.
- Status: completed
- Priority: P1
- Dependencies: T-010, T-011
Acceptance
- Each commerce_order needs account_id FK
- Account links person + organization
- Find existing or create new account
- Cache within publish transaction
Notes
- Account represents a person's enrollment at an organization
Files
- @packages/pipeline/@source/publish/dimensions.ts
Phase 5: Documentation & Cleanup
- Purpose: Update docs, deprecate old commands
T-013 - Update AGENTS.md pipeline commands
Document new command structure in AGENTS.md.
- Status: completed
- Priority: P1
- Dependencies: T-002, T-003, T-006, T-007
Acceptance
-
seed,sync,publish,reportdocumented - Individual stage commands documented as dev/debug
- Example workflows shown (bootstrap, monthly refresh, report generation)
- Old command aliases noted if kept
Files
- .ai/SYSTEM.md (source of truth)
- AGENTS.md (generated)
- CLAUDE.md (generated)
T-014 - Update architecture.md deployment section
Update deployment workflow to reflect new commands.
- Status: completed
- Priority: P1
- Dependencies: T-013
Acceptance
- Phase 1 (Local) section uses new commands
- Clear separation: bootstrap vs recurring vs on-demand
- Pipeline diagram updated if needed
Files
- @plan/architecture.md
T-015 - Update @packages/pipeline AGENTS.md
Update package-level documentation.
- Status: completed
- Priority: P2
- Dependencies: T-013
Acceptance
- Commands section reflects new structure
- Examples updated
- File structure section updated with new files
Files
- @packages/pipeline/AGENTS.md
T-016 - Deprecate old run command
Mark run as deprecated, alias to sync.
- Status: completed
- Priority: P2
- Dependencies: T-002
Acceptance
-
runcommand still works but prints deprecation warning - Warning suggests using
syncinstead - Behavior identical to
sync
Notes
- Keep for backward compatibility during transition
Files
- @packages/pipeline/@source/index.ts