optimal-cli 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +18 -0
- package/.claude-plugin/plugin.json +10 -0
- package/.env.example +17 -0
- package/CLAUDE.md +67 -0
- package/COMMANDS.md +264 -0
- package/PUBLISH.md +70 -0
- package/agents/content-ops.md +2 -2
- package/agents/financial-ops.md +2 -2
- package/agents/infra-ops.md +2 -2
- package/apps/.gitkeep +0 -0
- package/bin/optimal.ts +1418 -0
- package/docs/MIGRATION_NEEDED.md +37 -0
- package/docs/plans/.gitkeep +0 -0
- package/docs/plans/optimal-cli-config-registry-v1.md +71 -0
- package/hooks/.gitkeep +0 -0
- package/lib/budget/projections.ts +561 -0
- package/lib/budget/scenarios.ts +312 -0
- package/lib/cms/publish-blog.ts +129 -0
- package/lib/cms/strapi-client.ts +302 -0
- package/lib/config/registry.ts +229 -0
- package/lib/config/schema.ts +58 -0
- package/lib/config.ts +247 -0
- package/lib/infra/.gitkeep +0 -0
- package/lib/infra/deploy.ts +70 -0
- package/lib/infra/migrate.ts +141 -0
- package/lib/kanban-obsidian.ts +232 -0
- package/lib/kanban-sync.ts +258 -0
- package/lib/kanban.ts +239 -0
- package/lib/newsletter/.gitkeep +0 -0
- package/lib/newsletter/distribute.ts +256 -0
- package/{dist/lib/newsletter/generate-insurance.d.ts → lib/newsletter/generate-insurance.ts} +24 -7
- package/lib/newsletter/generate.ts +735 -0
- package/lib/obsidian-tasks.ts +231 -0
- package/lib/returnpro/.gitkeep +0 -0
- package/lib/returnpro/anomalies.ts +258 -0
- package/lib/returnpro/audit.ts +194 -0
- package/lib/returnpro/diagnose.ts +400 -0
- package/lib/returnpro/kpis.ts +255 -0
- package/lib/returnpro/templates.ts +323 -0
- package/lib/returnpro/upload-income.ts +311 -0
- package/lib/returnpro/upload-netsuite.ts +696 -0
- package/lib/returnpro/upload-r1.ts +563 -0
- package/lib/social/post-generator.ts +468 -0
- package/lib/social/publish.ts +301 -0
- package/lib/social/scraper.ts +503 -0
- package/lib/supabase.ts +25 -0
- package/lib/transactions/delete-batch.ts +258 -0
- package/lib/transactions/ingest.ts +659 -0
- package/lib/transactions/stamp.ts +654 -0
- package/package.json +5 -18
- package/pnpm-workspace.yaml +3 -0
- package/scripts/check-table.ts +24 -0
- package/scripts/create-tables.ts +94 -0
- package/scripts/migrate-kanban.sh +28 -0
- package/scripts/migrate-v2.ts +78 -0
- package/scripts/migrate.ts +79 -0
- package/scripts/run-migration.ts +59 -0
- package/scripts/seed-board.ts +203 -0
- package/scripts/test-kanban.ts +21 -0
- package/skills/audit-financials/SKILL.md +33 -0
- package/skills/board-create/SKILL.md +28 -0
- package/skills/board-update/SKILL.md +27 -0
- package/skills/board-view/SKILL.md +27 -0
- package/skills/delete-batch/SKILL.md +77 -0
- package/skills/deploy/SKILL.md +40 -0
- package/skills/diagnose-months/SKILL.md +68 -0
- package/skills/distribute-newsletter/SKILL.md +58 -0
- package/skills/export-budget/SKILL.md +44 -0
- package/skills/export-kpis/SKILL.md +52 -0
- package/skills/generate-netsuite-template/SKILL.md +51 -0
- package/skills/generate-newsletter/SKILL.md +53 -0
- package/skills/generate-newsletter-insurance/SKILL.md +59 -0
- package/skills/generate-social-posts/SKILL.md +67 -0
- package/skills/health-check/SKILL.md +42 -0
- package/skills/ingest-transactions/SKILL.md +51 -0
- package/skills/manage-cms/SKILL.md +50 -0
- package/skills/manage-scenarios/SKILL.md +83 -0
- package/skills/migrate-db/SKILL.md +79 -0
- package/skills/preview-newsletter/SKILL.md +50 -0
- package/skills/project-budget/SKILL.md +60 -0
- package/skills/publish-blog/SKILL.md +70 -0
- package/skills/publish-social-posts/SKILL.md +70 -0
- package/skills/rate-anomalies/SKILL.md +62 -0
- package/skills/scrape-ads/SKILL.md +49 -0
- package/skills/stamp-transactions/SKILL.md +62 -0
- package/skills/upload-income-statements/SKILL.md +54 -0
- package/skills/upload-netsuite/SKILL.md +56 -0
- package/skills/upload-r1/SKILL.md +45 -0
- package/supabase/.temp/cli-latest +1 -0
- package/supabase/migrations/.gitkeep +0 -0
- package/supabase/migrations/20250305000001_create_agent_configs.sql +36 -0
- package/supabase/migrations/20260305111300_create_cli_config_registry.sql +22 -0
- package/supabase/migrations/20260306195000_create_kanban_tables.sql +97 -0
- package/tests/config-command-smoke.test.ts +395 -0
- package/tests/config-registry.test.ts +173 -0
- package/tsconfig.json +19 -0
- package/agents/profiles.json +0 -5
- package/dist/bin/optimal.d.ts +0 -2
- package/dist/bin/optimal.js +0 -1590
- package/dist/lib/assets/index.d.ts +0 -79
- package/dist/lib/assets/index.js +0 -153
- package/dist/lib/assets.d.ts +0 -20
- package/dist/lib/assets.js +0 -112
- package/dist/lib/auth/index.d.ts +0 -83
- package/dist/lib/auth/index.js +0 -146
- package/dist/lib/board/index.d.ts +0 -39
- package/dist/lib/board/index.js +0 -285
- package/dist/lib/board/types.d.ts +0 -111
- package/dist/lib/board/types.js +0 -1
- package/dist/lib/bot/claim.d.ts +0 -3
- package/dist/lib/bot/claim.js +0 -20
- package/dist/lib/bot/coordinator.d.ts +0 -27
- package/dist/lib/bot/coordinator.js +0 -178
- package/dist/lib/bot/heartbeat.d.ts +0 -6
- package/dist/lib/bot/heartbeat.js +0 -30
- package/dist/lib/bot/index.d.ts +0 -9
- package/dist/lib/bot/index.js +0 -6
- package/dist/lib/bot/protocol.d.ts +0 -12
- package/dist/lib/bot/protocol.js +0 -74
- package/dist/lib/bot/reporter.d.ts +0 -3
- package/dist/lib/bot/reporter.js +0 -27
- package/dist/lib/bot/skills.d.ts +0 -26
- package/dist/lib/bot/skills.js +0 -69
- package/dist/lib/budget/projections.d.ts +0 -115
- package/dist/lib/budget/projections.js +0 -384
- package/dist/lib/budget/scenarios.d.ts +0 -93
- package/dist/lib/budget/scenarios.js +0 -214
- package/dist/lib/cms/publish-blog.d.ts +0 -62
- package/dist/lib/cms/publish-blog.js +0 -74
- package/dist/lib/cms/strapi-client.d.ts +0 -123
- package/dist/lib/cms/strapi-client.js +0 -213
- package/dist/lib/config/registry.d.ts +0 -17
- package/dist/lib/config/registry.js +0 -182
- package/dist/lib/config/schema.d.ts +0 -31
- package/dist/lib/config/schema.js +0 -25
- package/dist/lib/config.d.ts +0 -55
- package/dist/lib/config.js +0 -206
- package/dist/lib/errors.d.ts +0 -25
- package/dist/lib/errors.js +0 -91
- package/dist/lib/format.d.ts +0 -28
- package/dist/lib/format.js +0 -98
- package/dist/lib/infra/deploy.d.ts +0 -29
- package/dist/lib/infra/deploy.js +0 -58
- package/dist/lib/infra/migrate.d.ts +0 -34
- package/dist/lib/infra/migrate.js +0 -103
- package/dist/lib/newsletter/distribute.d.ts +0 -52
- package/dist/lib/newsletter/distribute.js +0 -193
- package/dist/lib/newsletter/generate-insurance.js +0 -36
- package/dist/lib/newsletter/generate.d.ts +0 -104
- package/dist/lib/newsletter/generate.js +0 -571
- package/dist/lib/returnpro/anomalies.d.ts +0 -64
- package/dist/lib/returnpro/anomalies.js +0 -166
- package/dist/lib/returnpro/audit.d.ts +0 -32
- package/dist/lib/returnpro/audit.js +0 -147
- package/dist/lib/returnpro/diagnose.d.ts +0 -52
- package/dist/lib/returnpro/diagnose.js +0 -281
- package/dist/lib/returnpro/kpis.d.ts +0 -32
- package/dist/lib/returnpro/kpis.js +0 -192
- package/dist/lib/returnpro/templates.d.ts +0 -48
- package/dist/lib/returnpro/templates.js +0 -229
- package/dist/lib/returnpro/upload-income.d.ts +0 -25
- package/dist/lib/returnpro/upload-income.js +0 -235
- package/dist/lib/returnpro/upload-netsuite.d.ts +0 -37
- package/dist/lib/returnpro/upload-netsuite.js +0 -566
- package/dist/lib/returnpro/upload-r1.d.ts +0 -48
- package/dist/lib/returnpro/upload-r1.js +0 -398
- package/dist/lib/returnpro/validate.d.ts +0 -37
- package/dist/lib/returnpro/validate.js +0 -124
- package/dist/lib/social/meta.d.ts +0 -90
- package/dist/lib/social/meta.js +0 -160
- package/dist/lib/social/post-generator.d.ts +0 -83
- package/dist/lib/social/post-generator.js +0 -333
- package/dist/lib/social/publish.d.ts +0 -66
- package/dist/lib/social/publish.js +0 -226
- package/dist/lib/social/scraper.d.ts +0 -67
- package/dist/lib/social/scraper.js +0 -361
- package/dist/lib/supabase.d.ts +0 -4
- package/dist/lib/supabase.js +0 -20
- package/dist/lib/transactions/delete-batch.d.ts +0 -60
- package/dist/lib/transactions/delete-batch.js +0 -203
- package/dist/lib/transactions/ingest.d.ts +0 -43
- package/dist/lib/transactions/ingest.js +0 -555
- package/dist/lib/transactions/stamp.d.ts +0 -51
- package/dist/lib/transactions/stamp.js +0 -524
- package/docs/CLI-REFERENCE.md +0 -361
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stamp-transactions
|
|
3
|
+
description: Auto-categorize unclassified transactions using a 4-stage rule-based matching engine
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
Queries all unclassified transactions (where `provider IS NULL` or `category_id IS NULL`) for a given user and runs them through a 4-stage matching algorithm to assign provider names and categories. Optionally runs in dry-run mode to preview results without writing.
|
|
8
|
+
|
|
9
|
+
## Inputs
|
|
10
|
+
- **user-id** (required): Supabase user UUID whose transactions to stamp
|
|
11
|
+
- **dry-run** (optional): Preview matches without updating the database
|
|
12
|
+
|
|
13
|
+
## Matching Algorithm (4 stages)
|
|
14
|
+
| Stage | Name | Confidence | Method |
|
|
15
|
+
|-------|------|------------|--------|
|
|
16
|
+
| 1 | PATTERN | 100% | Regex patterns for transfers, Zelle, P2P, CC payments, payroll, ATM, fees |
|
|
17
|
+
| 2 | LEARNED | 80-99% | Description hash lookup in `learned_patterns` (weight determines confidence) |
|
|
18
|
+
| 3 | EXACT | 100% | Provider name (or variant) found as substring in description |
|
|
19
|
+
| 4 | FUZZY | 60-95% | Token overlap between description and provider names (threshold 0.6) |
|
|
20
|
+
| Fallback | CATEGORY_INFER | 50% | Map institution-specific category to standard category |
|
|
21
|
+
|
|
22
|
+
Transactions matching at >= 90% confidence are auto-confirmed. Below that, they remain `pending` for user review.
|
|
23
|
+
|
|
24
|
+
## Steps
|
|
25
|
+
1. Load matching rules from DB: `providers`, `learned_patterns`, `user_provider_overrides`
|
|
26
|
+
2. Fetch unclassified transactions for the user
|
|
27
|
+
3. Fetch `stamp_categories` and user `categories` for name-to-ID mapping
|
|
28
|
+
4. Run each transaction through the 4-stage pipeline
|
|
29
|
+
5. Update matched rows with `provider`, `provider_method`, `provider_confidence`, `category_id`
|
|
30
|
+
|
|
31
|
+
## Output
|
|
32
|
+
```
|
|
33
|
+
Matcher loaded: 342 providers, 89 learned patterns
|
|
34
|
+
Found 156 unclassified transactions
|
|
35
|
+
|
|
36
|
+
Stamped: 127 | Unmatched: 29 | Total: 156
|
|
37
|
+
By match type: PATTERN=18, LEARNED=34, EXACT=52, FUZZY=19, CATEGORY_INFER=4
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
In dry-run mode, no database writes occur — the output shows what would happen.
|
|
41
|
+
|
|
42
|
+
## CLI Usage
|
|
43
|
+
```bash
|
|
44
|
+
# Full stamp run
|
|
45
|
+
tsx bin/optimal.ts stamp-transactions --user-id <uuid>
|
|
46
|
+
|
|
47
|
+
# Preview only
|
|
48
|
+
tsx bin/optimal.ts stamp-transactions --user-id <uuid> --dry-run
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Environment
|
|
52
|
+
Requires: `OPTIMAL_SUPABASE_URL`, `OPTIMAL_SUPABASE_SERVICE_KEY`
|
|
53
|
+
|
|
54
|
+
## Tables Read
|
|
55
|
+
- `providers` — global provider-to-category mappings + aliases
|
|
56
|
+
- `learned_patterns` — user-confirmed description patterns
|
|
57
|
+
- `user_provider_overrides` — per-user category overrides
|
|
58
|
+
- `stamp_categories` — standard category definitions
|
|
59
|
+
- `categories` — user-specific categories
|
|
60
|
+
|
|
61
|
+
## Tables Written
|
|
62
|
+
- `transactions` — update `provider`, `provider_method`, `provider_confidence`, `provider_inferred_at`, `category_id`
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upload-income-statements
|
|
3
|
+
description: Load confirmed income statement CSVs into ReturnPro for accuracy auditing
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
Uploads confirmed income statement CSVs (exported from NetSuite) into `confirmed_income_statements`. These serve as the source of truth for financial accuracy auditing — the audit-financials skill compares staged data against these confirmed records. Maintaining accurate confirmed data is essential because ReturnPro targets 100% accuracy between staged and confirmed financials.
|
|
8
|
+
|
|
9
|
+
## Inputs
|
|
10
|
+
- **file** (required): Absolute path to the income statement CSV file on disk
|
|
11
|
+
- **month** (required): Target month as YYYY-MM (e.g., `2026-01`)
|
|
12
|
+
- **replace** (optional): If set, deletes existing confirmed rows for the target month before inserting. Default: false (append/upsert).
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
1. Call `lib/returnpro/upload-income.ts::uploadIncomeStatements(file, month, options?)` to orchestrate the upload
|
|
16
|
+
2. Read the CSV file and parse rows (account_code, account_name, total_amount, period)
|
|
17
|
+
3. Validate account codes against `dim_account`
|
|
18
|
+
4. If `--replace` flag is set, delete existing `confirmed_income_statements` rows for the target month
|
|
19
|
+
5. Batch-insert rows into `confirmed_income_statements`
|
|
20
|
+
6. Run a quick accuracy check against `stg_financials_raw` for the uploaded month (same logic as audit-financials)
|
|
21
|
+
7. Report accuracy inline so Carlos immediately knows the data state
|
|
22
|
+
8. Log execution via `lib/kanban.ts::logSkillExecution()`
|
|
23
|
+
|
|
24
|
+
## Output
|
|
25
|
+
```
|
|
26
|
+
Parsed income statement CSV: 189 accounts for 2026-01
|
|
27
|
+
Inserted: 189 | Replaced: 0
|
|
28
|
+
Quick accuracy check (2026-01): 91.2% (83/91 staged accounts match)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## CLI Usage
|
|
32
|
+
```bash
|
|
33
|
+
# Upload income statement
|
|
34
|
+
optimal upload-income-statements --file ~/Downloads/returnpro-data/IS-Jan-2026.csv --month 2026-01
|
|
35
|
+
|
|
36
|
+
# Replace existing month data
|
|
37
|
+
optimal upload-income-statements --file ~/Downloads/returnpro-data/IS-Jan-2026.csv --month 2026-01 --replace
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Environment
|
|
41
|
+
Requires: `RETURNPRO_SUPABASE_URL`, `RETURNPRO_SUPABASE_SERVICE_KEY`
|
|
42
|
+
|
|
43
|
+
## Tables Touched
|
|
44
|
+
- `confirmed_income_statements` — insert/replace confirmed GL account rows
|
|
45
|
+
- `stg_financials_raw` — read-only for post-upload accuracy check
|
|
46
|
+
- `dim_account` — validate account codes
|
|
47
|
+
|
|
48
|
+
## Gotchas
|
|
49
|
+
- **Coverage gap**: Confirmed data has ~185-193 accounts/month vs staging's ~88-93. The delta is GL accounts not in Solution7 (expected, but tracked).
|
|
50
|
+
- **Always run audit after upload**: The skill automatically runs a quick accuracy check, but a full audit-financials run is recommended for detailed investigation.
|
|
51
|
+
- **Upload via Admin Console**: Can also be done via the ReturnPro Admin Console UI (Income Statement tab).
|
|
52
|
+
|
|
53
|
+
## Status
|
|
54
|
+
Implementation status: Not yet implemented. Spec only. Lib function `lib/returnpro/upload-income.ts` to be extracted from dashboard-returnpro's `/api/admin/confirmed-income-statements` route.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upload-netsuite
|
|
3
|
+
description: Upload NetSuite XLSM or CSV financial data into ReturnPro staging tables
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
Uploads NetSuite financial exports (XLSM macro-enabled workbooks or CSV files) into `stg_financials_raw`. This is the primary data pipeline for ReturnPro FP&A staging. Handles both single-sheet CSV files and multi-sheet XLSM workbooks (auto-detects format). Supports Wes-style multi-sheet workbooks where each month tab contains that month's data.
|
|
8
|
+
|
|
9
|
+
## Inputs
|
|
10
|
+
- **file** (required): Absolute path to the NetSuite XLSM or CSV file on disk
|
|
11
|
+
- **month** (optional): Target month as YYYY-MM. Required for CSV files. For XLSM with monthly tabs, auto-detected from sheet names.
|
|
12
|
+
- **dry-run** (optional): Parse and validate without writing to Supabase.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
1. Call `lib/returnpro/upload-netsuite.ts::uploadNetsuite(file, month?, options?)` to orchestrate the upload
|
|
16
|
+
2. Detect file format by extension (.xlsm, .xlsx, .csv)
|
|
17
|
+
3. For XLSM/XLSX: check for multi-sheet layout using `hasMonthlySheets()` — if 3+ month-named sheets exist, read per-month tabs (NOT Summary)
|
|
18
|
+
4. For CSV: read single file, require `--month` parameter
|
|
19
|
+
5. Parse rows into staging format: `account_code`, `account_name`, `amount` (as TEXT), `period` (YYYY-MM), `source_file`
|
|
20
|
+
6. Resolve account codes against `dim_account` for validation
|
|
21
|
+
7. Batch-upsert into `stg_financials_raw` (keyed on account_code + period + master_program_id)
|
|
22
|
+
8. Log execution via `lib/kanban.ts::logSkillExecution()`
|
|
23
|
+
|
|
24
|
+
## Output
|
|
25
|
+
```
|
|
26
|
+
Format: NetSuite XLSM (multi-sheet: Jan, Feb, Mar)
|
|
27
|
+
Parsed 3 months: 2026-01 (91 rows), 2026-02 (89 rows), 2026-03 (93 rows)
|
|
28
|
+
Total inserted: 273 | Updated: 0 | Skipped: 0
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## CLI Usage
|
|
32
|
+
```bash
|
|
33
|
+
# XLSM with auto-detected monthly tabs
|
|
34
|
+
optimal upload-netsuite --file ~/Downloads/returnpro-data/Solution7-Q1-2026.xlsm
|
|
35
|
+
|
|
36
|
+
# CSV with explicit month
|
|
37
|
+
optimal upload-netsuite --file ~/Downloads/returnpro-data/netsuite-jan-2026.csv --month 2026-01
|
|
38
|
+
|
|
39
|
+
# Dry run to preview
|
|
40
|
+
optimal upload-netsuite --file ~/Downloads/returnpro-data/Solution7-Q1-2026.xlsm --dry-run
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Environment
|
|
44
|
+
Requires: `RETURNPRO_SUPABASE_URL`, `RETURNPRO_SUPABASE_SERVICE_KEY`
|
|
45
|
+
|
|
46
|
+
## Tables Touched
|
|
47
|
+
- `stg_financials_raw` — upsert parsed rows (amount stored as TEXT)
|
|
48
|
+
- `dim_account` — validate account codes
|
|
49
|
+
|
|
50
|
+
## Gotchas
|
|
51
|
+
- **amount is TEXT**: The `stg_financials_raw.amount` column is TEXT, not NUMERIC. Always CAST before numeric comparisons.
|
|
52
|
+
- **Multi-sheet detection**: `hasMonthlySheets()` triggers when 3+ sheets have month-like names. If present, reads individual month tabs and ignores Summary sheet.
|
|
53
|
+
- **Never run SQL manually**: Use migration files + `supabase db push --linked` for schema changes.
|
|
54
|
+
|
|
55
|
+
## Status
|
|
56
|
+
Implementation status: Not yet implemented. Spec only. Lib function `lib/returnpro/upload-netsuite.ts` to be extracted from dashboard-returnpro's `/api/staging/upload` route.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upload-r1
|
|
3
|
+
description: Upload R1 XLSX files parsed with WASM/calamine, aggregate by program, and load into ReturnPro staging
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Purpose
|
|
7
|
+
Uploads R1 reverse-logistics XLSX files into ReturnPro's financial staging tables. The R1 export is parsed using WASM-based calamine (fast XLSX parser without ExcelJS overhead), rows are aggregated by master program, and results are upserted into `stg_financials_raw`. This is one of the primary data ingestion paths for ReturnPro FP&A.
|
|
8
|
+
|
|
9
|
+
## Inputs
|
|
10
|
+
- **file** (required): Absolute path to the R1 XLSX file on disk
|
|
11
|
+
- **month** (required): Target month as YYYY-MM (e.g., `2026-01`). Used for the staging period column.
|
|
12
|
+
- **dry-run** (optional): Parse and aggregate without writing to Supabase. Useful for previewing row counts.
|
|
13
|
+
|
|
14
|
+
## Steps
|
|
15
|
+
1. Call `lib/returnpro/upload-r1.ts::uploadR1(file, month, options?)` to orchestrate the upload
|
|
16
|
+
2. Read the XLSX file with WASM/calamine parser (faster than ExcelJS for large files)
|
|
17
|
+
3. Normalize column headers — map R1-specific column names to standard staging fields (account_code, amount, description)
|
|
18
|
+
4. Aggregate rows by `master_program_id` + `account_code` within the target month
|
|
19
|
+
5. Resolve program names to `dim_master_program.id` via fuzzy match
|
|
20
|
+
6. Upsert aggregated rows into `stg_financials_raw` (keyed on account_code + month + master_program_id)
|
|
21
|
+
7. Log execution via `lib/kanban.ts::logSkillExecution()`
|
|
22
|
+
|
|
23
|
+
## Output
|
|
24
|
+
```
|
|
25
|
+
Parsed R1 XLSX: 1,842 rows across 47 programs
|
|
26
|
+
Aggregated to 312 staging rows for 2026-01
|
|
27
|
+
Inserted: 298 | Updated: 14 | Skipped: 0
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## CLI Usage
|
|
31
|
+
```bash
|
|
32
|
+
optimal upload-r1 --file ~/Downloads/returnpro-data/R1-January-2026.xlsx --month 2026-01
|
|
33
|
+
optimal upload-r1 --file ~/Downloads/returnpro-data/R1-January-2026.xlsx --month 2026-01 --dry-run
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Environment
|
|
37
|
+
Requires: `RETURNPRO_SUPABASE_URL`, `RETURNPRO_SUPABASE_SERVICE_KEY`
|
|
38
|
+
|
|
39
|
+
## Tables Touched
|
|
40
|
+
- `stg_financials_raw` — upsert aggregated rows (note: `amount` column is TEXT, not NUMERIC)
|
|
41
|
+
- `dim_master_program` — lookup for program name resolution
|
|
42
|
+
- `dim_account` — lookup for account code validation
|
|
43
|
+
|
|
44
|
+
## Status
|
|
45
|
+
Implementation status: Not yet implemented. Spec only. Lib function `lib/returnpro/upload-r1.ts` to be extracted from dashboard-returnpro's `/api/r1/` routes.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v2.75.0
|
|
File without changes
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- Create table for storing agent OpenClaw configs
|
|
2
|
+
CREATE TABLE IF NOT EXISTS agent_configs (
|
|
3
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4
|
+
agent_name TEXT NOT NULL UNIQUE,
|
|
5
|
+
config_json JSONB NOT NULL,
|
|
6
|
+
version TEXT NOT NULL,
|
|
7
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
8
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
-- Index for faster lookups
|
|
12
|
+
CREATE INDEX IF NOT EXISTS idx_agent_configs_name ON agent_configs(agent_name);
|
|
13
|
+
|
|
14
|
+
-- Enable RLS
|
|
15
|
+
ALTER TABLE agent_configs ENABLE ROW LEVEL SECURITY;
|
|
16
|
+
|
|
17
|
+
-- Allow service role full access
|
|
18
|
+
CREATE POLICY "Service role full access" ON agent_configs
|
|
19
|
+
FOR ALL
|
|
20
|
+
TO service_role
|
|
21
|
+
USING (true)
|
|
22
|
+
WITH CHECK (true);
|
|
23
|
+
|
|
24
|
+
-- Add updated_at trigger
|
|
25
|
+
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
26
|
+
RETURNS TRIGGER AS $$
|
|
27
|
+
BEGIN
|
|
28
|
+
NEW.updated_at = NOW();
|
|
29
|
+
RETURN NEW;
|
|
30
|
+
END;
|
|
31
|
+
$$ LANGUAGE plpgsql;
|
|
32
|
+
|
|
33
|
+
CREATE TRIGGER update_agent_configs_updated_at
|
|
34
|
+
BEFORE UPDATE ON agent_configs
|
|
35
|
+
FOR EACH ROW
|
|
36
|
+
EXECUTE FUNCTION update_updated_at_column();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
-- create shared config registry for optimal-cli profile sync
|
|
2
|
+
create table if not exists public.cli_config_registry (
|
|
3
|
+
id uuid primary key default gen_random_uuid(),
|
|
4
|
+
owner text not null,
|
|
5
|
+
profile text not null default 'default',
|
|
6
|
+
config_version text not null,
|
|
7
|
+
payload jsonb not null,
|
|
8
|
+
payload_hash text not null,
|
|
9
|
+
source text not null default 'optimal-cli',
|
|
10
|
+
updated_by text,
|
|
11
|
+
updated_at timestamptz not null default now(),
|
|
12
|
+
created_at timestamptz not null default now(),
|
|
13
|
+
unique (owner, profile)
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
create index if not exists idx_cli_config_registry_owner_profile
|
|
17
|
+
on public.cli_config_registry (owner, profile);
|
|
18
|
+
|
|
19
|
+
create index if not exists idx_cli_config_registry_updated_at
|
|
20
|
+
on public.cli_config_registry (updated_at desc);
|
|
21
|
+
|
|
22
|
+
-- note: rls policies intentionally deferred until auth model is finalized.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
-- Kanban tables for 3-way sync: supabase + obsidian + cli
|
|
2
|
+
|
|
3
|
+
-- Projects table
|
|
4
|
+
CREATE TABLE IF NOT EXISTS cli_projects (
|
|
5
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
6
|
+
slug TEXT UNIQUE NOT NULL,
|
|
7
|
+
name TEXT NOT NULL,
|
|
8
|
+
description TEXT,
|
|
9
|
+
status TEXT DEFAULT 'active' CHECK (status IN ('active', 'archived', 'on_hold')),
|
|
10
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
11
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- Tasks table
|
|
15
|
+
CREATE TABLE IF NOT EXISTS cli_tasks (
|
|
16
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
17
|
+
project_id UUID REFERENCES cli_projects(id) ON DELETE CASCADE,
|
|
18
|
+
task_id TEXT NOT NULL, -- from obsidian filename, e.g., "task__optimal-cli-shared-config-registry__b7c1d2e3"
|
|
19
|
+
title TEXT NOT NULL,
|
|
20
|
+
description TEXT,
|
|
21
|
+
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'in_progress', 'done', 'cancelled')),
|
|
22
|
+
priority INTEGER DEFAULT 3 CHECK (priority BETWEEN 1 AND 4),
|
|
23
|
+
owner TEXT, -- agent or person responsible
|
|
24
|
+
assignee TEXT,
|
|
25
|
+
tags JSONB DEFAULT '[]',
|
|
26
|
+
source TEXT, -- e.g., "chat:carlos:2026-03-04"
|
|
27
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
28
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
29
|
+
completed_at TIMESTAMPTZ,
|
|
30
|
+
completed_by TEXT,
|
|
31
|
+
metadata JSONB DEFAULT '{}',
|
|
32
|
+
UNIQUE(project_id, task_id)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
-- Sync log for tracking changes
|
|
36
|
+
CREATE TABLE IF NOT EXISTS cli_sync_log (
|
|
37
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
38
|
+
entity_type TEXT NOT NULL, -- 'project' or 'task'
|
|
39
|
+
entity_id UUID NOT NULL,
|
|
40
|
+
action TEXT NOT NULL, -- 'create', 'update', 'delete'
|
|
41
|
+
source TEXT NOT NULL, -- 'cli', 'obsidian', 'manual'
|
|
42
|
+
synced_at TIMESTAMPTZ DEFAULT NOW(),
|
|
43
|
+
payload JSONB
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
-- Indexes
|
|
47
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_project ON cli_tasks(project_id);
|
|
48
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_status ON cli_tasks(status);
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_owner ON cli_tasks(owner);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_tasks_assignee ON cli_tasks(assignee);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_sync_log_entity ON cli_sync_log(entity_type, entity_id);
|
|
52
|
+
|
|
53
|
+
-- Enable RLS
|
|
54
|
+
ALTER TABLE cli_projects ENABLE ROW LEVEL SECURITY;
|
|
55
|
+
ALTER TABLE cli_tasks ENABLE ROW LEVEL SECURITY;
|
|
56
|
+
ALTER TABLE cli_sync_log ENABLE ROW LEVEL SECURITY;
|
|
57
|
+
|
|
58
|
+
-- RLS policies (service role can do everything)
|
|
59
|
+
CREATE POLICY "service_role_full_access_projects" ON cli_projects FOR ALL USING (true) WITH CHECK (true);
|
|
60
|
+
CREATE POLICY "service_role_full_access_tasks" ON cli_tasks FOR ALL USING (true) WITH CHECK (true);
|
|
61
|
+
CREATE POLICY "service_role_full_access_sync_log" ON cli_sync_log FOR ALL USING (true) WITH CHECK (true);
|
|
62
|
+
|
|
63
|
+
-- Function to update updated_at
|
|
64
|
+
CREATE OR REPLACE FUNCTION update_updated_at()
|
|
65
|
+
RETURNS TRIGGER AS $$
|
|
66
|
+
BEGIN
|
|
67
|
+
NEW.updated_at = NOW();
|
|
68
|
+
RETURN NEW;
|
|
69
|
+
END;
|
|
70
|
+
$$ LANGUAGE plpgsql;
|
|
71
|
+
|
|
72
|
+
-- Triggers for updated_at
|
|
73
|
+
CREATE TRIGGER update_projects_updated_at BEFORE UPDATE ON cli_projects
|
|
74
|
+
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
|
|
75
|
+
|
|
76
|
+
CREATE TRIGGER update_tasks_updated_at BEFORE UPDATE ON cli_tasks
|
|
77
|
+
FOR EACH ROW EXECUTE FUNCTION update_updated_at();
|
|
78
|
+
|
|
79
|
+
-- Insert default project for optimal tasks
|
|
80
|
+
INSERT INTO cli_projects (slug, name, description)
|
|
81
|
+
VALUES ('optimal-tasks', 'Optimal Tasks', 'Main task tracking for optimal agents')
|
|
82
|
+
ON CONFLICT (slug) DO NOTHING;
|
|
83
|
+
|
|
84
|
+
-- Function to log sync
|
|
85
|
+
CREATE OR REPLACE FUNCTION log_sync(
|
|
86
|
+
p_entity_type TEXT,
|
|
87
|
+
p_entity_id UUID,
|
|
88
|
+
p_action TEXT,
|
|
89
|
+
p_source TEXT,
|
|
90
|
+
p_payload JSONB DEFAULT '{}'::JSONB
|
|
91
|
+
)
|
|
92
|
+
RETURNS VOID AS $$
|
|
93
|
+
BEGIN
|
|
94
|
+
INSERT INTO cli_sync_log (entity_type, entity_id, action, source, payload)
|
|
95
|
+
VALUES (p_entity_type, p_entity_id, p_action, p_source, p_payload);
|
|
96
|
+
END;
|
|
97
|
+
$$ LANGUAGE plpgsql;
|