Browse Source

chore: update plan and rulesets

pull/196/head
Matthew Raymer 2 weeks ago
parent
commit
74e4a20ef9
  1. 1
      .cursor/rules/docs/markdown_templates.mdc
  2. 28
      .cursor/rules/harbor_pilot_universal.mdc
  3. 2
      .cursor/rules/meta_bug_diagnosis.mdc
  4. 6
      .cursor/rules/meta_core_always_on.mdc
  5. 9
      .cursor/rules/meta_documentation.mdc
  6. 39
      .cursor/rules/playwright-test-investigation.mdc
  7. 34
      BUILDING.md
  8. 3
      README-PR-TEMPLATE.md
  9. 55
      README.md
  10. 22
      TASK_storage.md
  11. 1
      doc/README-BUILD-GUARD.md
  12. 24
      doc/android-asset-validation.md
  13. 22
      doc/meta_rule_usage_guide.md
  14. 131
      doc/notification-system-executive-summary.md
  15. 861
      doc/notification-system-implementation.md
  16. 657
      doc/notification-system-plan.md
  17. 5
      doc/z-index-guide.md

1
.cursor/rules/docs/markdown_templates.mdc

@ -192,6 +192,7 @@ Summary of key concepts and skills.
Where to apply this knowledge next.
```
- [ ] Integration tests
- [ ] E2E tests

28
.cursor/rules/harbor_pilot_universal.mdc

@ -19,6 +19,7 @@ inherits: base_context.mdc
**Status**: 🚢 ACTIVE — General ruleset extending *Base Context — Human Competence First*
> **Alignment with Base Context**
>
> - **Purpose fit**: Prioritizes human competence and collaboration while delivering reproducible artifacts.
> - **Output Contract**: This directive **adds universal constraints** for any technical topic while **inheriting** the Base Context contract sections.
> - **Toggles honored**: Uses the same toggle semantics; defaults above can be overridden by the caller.
@ -26,9 +27,11 @@ inherits: base_context.mdc
---
## Objective
Produce a **developer-grade, reproducible guide** for any technical topic that onboards a competent practitioner **without meta narration** and **with evidence-backed steps**.
## Scope & Constraints
- **One Markdown document** as the deliverable.
- Use **absolute dates** in **UTC** (e.g., `2025-08-21T14:22Z`) — avoid “today/yesterday”.
- Include at least **one diagram** (Mermaid preferred). Choose the most fitting type:
@ -41,6 +44,7 @@ Produce a **developer-grade, reproducible guide** for any technical topic that o
- If something is unknown, output `TODO:<missing>` — **never invent**.
## Required Sections (extends Base Output Contract)
Follow this exact order **after** the Base Contract’s **Objective → Result → Use/Run** headers:
1. **Context & Scope**
@ -69,16 +73,19 @@ Follow this exact order **after** the Base Contract’s **Objective → Result
- Canonical docs, specs, tickets, prior analyses.
> **Competence Hooks (per Base Context; keep lightweight):**
>
> - *Why this works* (≤3 bullets) — core invariants or guarantees.
> - *Common pitfalls* (≤3 bullets) — the traps we saw in evidence.
> - *Next skill unlock* (1 line) — the next capability to implement/learn.
> - *Teach-back* (1 line) — prompt the reader to restate the flow/architecture.
> **Collaboration Hooks (per Base Context):**
>
> - Name reviewers for **Interfaces & Contracts** and the **diagram**.
> - Short **sign-off checklist** before merging/publishing the guide.
## Do / Don’t (Base-aligned)
- **Do** quantify progress only against a defined scope with acceptance criteria.
- **Do** include minimal sample payloads/headers or I/O schemas; redact sensitive values.
- **Do** keep commentary lean; if timeboxed, move depth to **Deferred for depth**.
@ -86,6 +93,7 @@ Follow this exact order **after** the Base Contract’s **Objective → Result
- **Don’t** include IDE-specific chatter or internal rules unrelated to the task.
## Validation Checklist (self-check before returning)
- [ ] All Required Sections present and ordered.
- [ ] Diagram compiles (basic Mermaid syntax) and fits the problem.
- [ ] If API-based, **Auth** and **Key Headers/Params** are listed for each endpoint.
@ -96,6 +104,7 @@ Follow this exact order **after** the Base Contract’s **Objective → Result
- [ ] Base **Output Contract** sections satisfied (Objective/Result/Use/Run/Competence/Collaboration/Assumptions/References).
## Universal Template (fill-in)
```markdown
# <Title> — Working Notes (As of YYYY-MM-DDTHH:MMZ)
@ -132,37 +141,46 @@ Follow this exact order **after** the Base Contract’s **Objective → Result
```
## Interfaces & Contracts
### If API-based
| Step | Method | Path/URL | Auth | Key Headers/Params | Sample |
|---|---|---|---|---|---|
| <…> | <…> | <…> | <…> | <…> | below |
### If Data/Files
| Source | Format | Schema/Columns | Size | Validation |
|---|---|---|---|---|
| <…> | <…> | <…> | <…> | <…> |
### If Systems/Hardware
| Interface | Protocol | Timing/Voltage | Constraints | Notes |
|---|---|---|---|---|
| <…> | <…> | <…> | <…> | <…> |
## Repro: End-to-End Procedure
```bash
# commands / curl examples (redacted where necessary)
```
```python
# minimal client library example (language appropriate)
```
> Expected output: <snippet/checks>
## What Works (Evidence)
- ✅ <short statement>
- **Time**: <YYYY-MM-DDTHH:MMZ>
- **Evidence**: file/line/log or request id/status
- **Verify at**: <where>
## What Doesn’t (Evidence & Hypotheses)
- ❌ <short failure> at `<component/endpoint/file>`
- **Time**: <YYYY-MM-DDTHH:MMZ>
- **Evidence**: <snippet/id/status>
@ -170,38 +188,46 @@ Follow this exact order **after** the Base Contract’s **Objective → Result
- **Next probe**: <short>
## Risks, Limits, Assumptions
<bullets: limits, security boundaries, retries/backoff, idempotency, SLOs>
## Next Steps
| Owner | Task | Exit Criteria | Target Date (UTC) |
|---|---|---|---|
| <name> | <action> | <measurable outcome> | <YYYY-MM-DD> |
## References
<links/titles>
## Competence Hooks
- *Why this works*: <≤3 bullets>
- *Common pitfalls*: <≤3 bullets>
- *Next skill unlock*: <1 line>
- *Teach-back*: <1 line>
## Collaboration Hooks
- Reviewers: <names/roles>
- Sign-off checklist: <≤5 checks>
## Assumptions & Limits
<bullets>
## Deferred for depth
<park deeper material here to respect timeboxing>
```
---
**Notes for Implementers:**
- Respect Base *Do-Not* (no filler, no invented facts, no censorship).
- Prefer clarity over completeness when timeboxed; capture unknowns explicitly.
- Apply historical comment management rules (see `.cursor/rules/historical_comment_management.mdc`)
- Apply realistic time estimation rules (see `.cursor/rules/realistic_time_estimation.mdc`)
- Apply Playwright test investigation rules (see `.cursor/rules/playwright_test_investigation.mdc`)
- Apply Playwright test investigation rules (see `.cursor/rules/playwright_test_investigation.mdc`)

2
.cursor/rules/meta_bug_diagnosis.mdc

@ -82,6 +82,7 @@ common investigation pitfalls.
### **Safe Diagnosis Commands**
✅ **Safe to use during diagnosis:**
- `npm run lint-fix` - Syntax and style checking
- `npm run type-check` - TypeScript validation (if available)
- `git status` - Version control status
@ -90,6 +91,7 @@ common investigation pitfalls.
- `grep_search` - Text pattern searching
❌ **Never use during diagnosis:**
- `npm run build:web` - Blocks chat
- `npm run build:electron` - Blocks chat
- `npm run build:capacitor` - Blocks chat

6
.cursor/rules/meta_core_always_on.mdc

@ -36,6 +36,7 @@ that are essential for all AI interactions.
**This meta-rule enforces current workflow mode constraints for all interactions:**
### **Current Workflow State**
```json
{
"workflowState": {
@ -62,26 +63,31 @@ that are essential for all AI interactions.
### **Mode-Specific Enforcement**
**Diagnosis Mode (read_only):**
- ❌ **Forbidden**: File modification, code creation, build commands, git commits
- ✅ **Allowed**: File reading, code analysis, investigation, documentation
- **Response**: Guide user toward investigation and analysis, not implementation
**Fixing Mode (implementation):**
- ✅ **Allowed**: File modification, code creation, build commands, testing, git commits
- ❌ **Forbidden**: None (full implementation mode)
- **Response**: Proceed with implementation and testing
**Planning Mode (design_only):**
- ❌ **Forbidden**: Implementation, coding, building, deployment
- ✅ **Allowed**: Analysis, design, estimation, documentation, architecture
- **Response**: Focus on planning and design, not implementation
**Research Mode (investigation):**
- ❌ **Forbidden**: File modification, implementation, deployment
- ✅ **Allowed**: Investigation, analysis, research, documentation
- **Response**: Focus on investigation and analysis
**Documentation Mode (writing_only):**
- ❌ **Forbidden**: Implementation, coding, building, deployment
- ✅ **Allowed**: Writing, editing, formatting, structuring, reviewing
- **Response**: Focus on documentation creation and improvement

9
.cursor/rules/meta_documentation.mdc

@ -51,6 +51,7 @@ providing technical descriptions.
## When to Use
**Use this meta-rule when**:
- Writing new documentation
- Updating existing documentation
- Creating technical guides
@ -107,6 +108,7 @@ providing technical descriptions.
### **Document Structure**
**Mandatory Sections**:
- **Overview**: Clear purpose and scope with educational context
- **Why This Matters**: Business value and user benefit explanation
- **Core Concepts**: Fundamental understanding before implementation
@ -116,6 +118,7 @@ providing technical descriptions.
- **Next Steps**: Where to go from here
**Optional Sections**:
- **Background**: Historical context and evolution
- **Alternatives**: Other approaches and trade-offs
- **Advanced Topics**: Deep dive into complex scenarios
@ -124,6 +127,7 @@ providing technical descriptions.
### **Writing Style**
**Educational Approach**:
- **Conversational tone**: Write as if explaining to a colleague
- **Progressive disclosure**: Start simple, add complexity gradually
- **Active voice**: "You can do this" not "This can be done"
@ -131,6 +135,7 @@ providing technical descriptions.
- **Analogies**: Use familiar concepts to explain complex ideas
**Technical Accuracy**:
- **Precise language**: Use exact technical terms consistently
- **Code examples**: Working, tested code snippets
- **Version information**: Specify applicable versions and platforms
@ -139,6 +144,7 @@ providing technical descriptions.
### **Content Quality Standards**
**Educational Value**:
- [ ] **Concept clarity**: Reader understands the fundamental idea
- [ ] **Context relevance**: Reader knows when to apply the knowledge
- [ ] **Practical application**: Reader can implement the solution
@ -146,6 +152,7 @@ providing technical descriptions.
- [ ] **Next steps**: Reader knows where to continue learning
**Technical Accuracy**:
- [ ] **Fact verification**: All technical details are correct
- [ ] **Code validation**: Examples compile and run correctly
- [ ] **Version compatibility**: Platform and version requirements clear
@ -183,6 +190,7 @@ providing technical descriptions.
### **Review Checklist**
**Educational Quality**:
- [ ] **Clear learning objective**: What will the reader learn?
- [ ] **Appropriate complexity**: Matches target audience knowledge
- [ ] **Progressive disclosure**: Information builds logically
@ -190,6 +198,7 @@ providing technical descriptions.
- [ ] **Common questions**: Anticipates and answers reader questions
**Technical Quality**:
- [ ] **Accuracy**: All technical details verified
- [ ] **Completeness**: Covers all necessary information
- [ ] **Consistency**: Terminology and formatting consistent

39
.cursor/rules/playwright-test-investigation.mdc

@ -9,26 +9,31 @@ alwaysApply: false
**Status**: 🎯 **ACTIVE** - Playwright test debugging guidelines
## Objective
Provide systematic approach for investigating Playwright test failures with focus on UI element conflicts, timing issues, and selector ambiguity.
## Context & Scope
- **Audience**: Developers debugging Playwright test failures
- **In scope**: Test failure analysis, selector conflicts, UI state investigation, timing issues
- **Out of scope**: Test writing best practices, CI/CD configuration
## Artifacts & Links
- Test results: `test-results/` directory
- Error context: `error-context.md` files with page snapshots
- Trace files: `trace.zip` files for failed tests
- HTML reports: Interactive test reports with screenshots
## Environment & Preconditions
- OS/Runtime: Linux/Windows/macOS with Node.js
- Versions: Playwright test framework, browser drivers
- Services: Local test server (localhost:8080), test data setup
- Auth mode: None required for test investigation
## Architecture / Process Overview
Playwright test investigation follows a systematic diagnostic workflow that leverages built-in debugging tools and error context analysis.
```mermaid
@ -57,6 +62,7 @@ flowchart TD
## Interfaces & Contracts
### Test Results Structure
| Component | Format | Content | Validation |
|---|---|---|---|
| Error Context | Markdown | Page snapshot in YAML | Verify DOM state matches test expectations |
@ -65,6 +71,7 @@ flowchart TD
| JSON Results | JSON | Machine-readable results | Parse for automated analysis |
### Investigation Commands
| Step | Command | Expected Output | Notes |
|---|---|---|---|
| Locate failed tests | `find test-results -name "*test-name*"` | Test result directories | Use exact test name patterns |
@ -74,6 +81,7 @@ flowchart TD
## Repro: End-to-End Investigation Procedure
### 1. Locate Failed Test Results
```bash
# Find all results for a specific test
find test-results -name "*test-name*" -type d
@ -83,6 +91,7 @@ find test-results -name "error-context.md" | head -5
```
### 2. Analyze Error Context
```bash
# Read error context for specific test
cat test-results/test-name-test-description-browser/error-context.md
@ -92,6 +101,7 @@ grep -A 10 -B 5 "button.*Yes\|button.*No" test-results/*/error-context.md
```
### 3. Check Trace Files
```bash
# List available trace files
find test-results -name "*.zip" | grep trace
@ -101,6 +111,7 @@ npx playwright show-trace test-results/test-name/trace.zip
```
### 4. Investigate Selector Issues
```typescript
// Check for multiple elements with same text
await page.locator('button:has-text("Yes")').count(); // Should be 1
@ -110,6 +121,7 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
```
## What Works (Evidence)
- ✅ **Error context files** provide page snapshots showing exact DOM state at failure
- **Time**: 2025-08-21T14:22Z
- **Evidence**: `test-results/60-new-activity-New-offers-for-another-user-chromium/error-context.md` shows both alerts visible
@ -126,6 +138,7 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
- **Verify at**: Error context markdown files
## What Doesn't (Evidence & Hypotheses)
- ❌ **Generic selectors** fail with multiple similar elements at `test-playwright/testUtils.ts:161`
- **Time**: 2025-08-21T14:22Z
- **Evidence**: `button:has-text("Yes")` matches both "Yes" and "Yes, Export Data"
@ -139,12 +152,14 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
- **Next probe**: Implement alert queuing or prevent overlapping alerts
## Risks, Limits, Assumptions
- **Trace file size**: Large trace files may impact storage and analysis time
- **Browser compatibility**: Trace viewer requires specific browser support
- **Test isolation**: Shared state between tests may affect investigation results
- **Timing sensitivity**: Tests may pass/fail based on system performance
## Next Steps
| Owner | Task | Exit Criteria | Target Date (UTC) |
|---|---|---|---|
| Development Team | Fix test selectors for multiple alerts | All tests pass consistently | 2025-08-22 |
@ -152,21 +167,25 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
| Development Team | Add test IDs to alert buttons | Unique selectors for all UI elements | 2025-08-28 |
## References
- [Playwright Trace Viewer Documentation](https://playwright.dev/docs/trace-viewer)
- [Playwright Test Results](https://playwright.dev/docs/test-reporters)
- [Test Investigation Workflow](./research_diagnostic.mdc)
## Competence Hooks
- **Why this works**: Systematic investigation leverages Playwright's built-in debugging tools to identify root causes
- **Common pitfalls**: Generic selectors fail with multiple similar elements; timing issues create race conditions; alert stacking causes UI conflicts
- **Next skill unlock**: Implement unique test IDs and handle alert dismissal order in test flows
- **Teach-back**: "How would you investigate a Playwright test failure using error context, trace files, and page snapshots?"
## Collaboration Hooks
- **Reviewers**: QA team, test automation engineers
- **Sign-off checklist**: Error context analyzed, trace files reviewed, root cause identified, fix implemented and tested
## Assumptions & Limits
- Test results directory structure follows Playwright conventions
- Trace files are enabled in configuration (`trace: "retain-on-failure"`)
- Error context files contain valid YAML page snapshots
@ -178,6 +197,7 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
**Priority**: High
**Maintainer**: Development team
**Next Review**: 2025-09-21
# Playwright Test Investigation — Harbor Pilot Directive
**Author**: Matthew Raymer
@ -185,26 +205,31 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
**Status**: 🎯 **ACTIVE** - Playwright test debugging guidelines
## Objective
Provide systematic approach for investigating Playwright test failures with focus on UI element conflicts, timing issues, and selector ambiguity.
## Context & Scope
- **Audience**: Developers debugging Playwright test failures
- **In scope**: Test failure analysis, selector conflicts, UI state investigation, timing issues
- **Out of scope**: Test writing best practices, CI/CD configuration
## Artifacts & Links
- Test results: `test-results/` directory
- Error context: `error-context.md` files with page snapshots
- Trace files: `trace.zip` files for failed tests
- HTML reports: Interactive test reports with screenshots
## Environment & Preconditions
- OS/Runtime: Linux/Windows/macOS with Node.js
- Versions: Playwright test framework, browser drivers
- Services: Local test server (localhost:8080), test data setup
- Auth mode: None required for test investigation
## Architecture / Process Overview
Playwright test investigation follows a systematic diagnostic workflow that leverages built-in debugging tools and error context analysis.
```mermaid
@ -233,6 +258,7 @@ flowchart TD
## Interfaces & Contracts
### Test Results Structure
| Component | Format | Content | Validation |
|---|---|---|---|
| Error Context | Markdown | Page snapshot in YAML | Verify DOM state matches test expectations |
@ -241,6 +267,7 @@ flowchart TD
| JSON Results | JSON | Machine-readable results | Parse for automated analysis |
### Investigation Commands
| Step | Command | Expected Output | Notes |
|---|---|---|---|
| Locate failed tests | `find test-results -name "*test-name*"` | Test result directories | Use exact test name patterns |
@ -250,6 +277,7 @@ flowchart TD
## Repro: End-to-End Investigation Procedure
### 1. Locate Failed Test Results
```bash
# Find all results for a specific test
find test-results -name "*test-name*" -type d
@ -259,6 +287,7 @@ find test-results -name "error-context.md" | head -5
```
### 2. Analyze Error Context
```bash
# Read error context for specific test
cat test-results/test-name-test-description-browser/error-context.md
@ -268,6 +297,7 @@ grep -A 10 -B 5 "button.*Yes\|button.*No" test-results/*/error-context.md
```
### 3. Check Trace Files
```bash
# List available trace files
find test-results -name "*.zip" | grep trace
@ -277,6 +307,7 @@ npx playwright show-trace test-results/test-name/trace.zip
```
### 4. Investigate Selector Issues
```typescript
// Check for multiple elements with same text
await page.locator('button:has-text("Yes")').count(); // Should be 1
@ -286,6 +317,7 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
```
## What Works (Evidence)
- ✅ **Error context files** provide page snapshots showing exact DOM state at failure
- **Time**: 2025-08-21T14:22Z
- **Evidence**: `test-results/60-new-activity-New-offers-for-another-user-chromium/error-context.md` shows both alerts visible
@ -302,6 +334,7 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
- **Verify at**: Error context markdown files
## What Doesn't (Evidence & Hypotheses)
- ❌ **Generic selectors** fail with multiple similar elements at `test-playwright/testUtils.ts:161`
- **Time**: 2025-08-21T14:22Z
- **Evidence**: `button:has-text("Yes")` matches both "Yes" and "Yes, Export Data"
@ -315,12 +348,14 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
- **Next probe**: Implement alert queuing or prevent overlapping alerts
## Risks, Limits, Assumptions
- **Trace file size**: Large trace files may impact storage and analysis time
- **Browser compatibility**: Trace viewer requires specific browser support
- **Test isolation**: Shared state between tests may affect investigation results
- **Timing sensitivity**: Tests may pass/fail based on system performance
## Next Steps
| Owner | Task | Exit Criteria | Target Date (UTC) |
|---|---|---|---|
| Development Team | Fix test selectors for multiple alerts | All tests pass consistently | 2025-08-22 |
@ -328,21 +363,25 @@ await page.locator('div[role="alert"]:has-text("Register") button:has-text("Yes"
| Development Team | Add test IDs to alert buttons | Unique selectors for all UI elements | 2025-08-28 |
## References
- [Playwright Trace Viewer Documentation](https://playwright.dev/docs/trace-viewer)
- [Playwright Test Results](https://playwright.dev/docs/test-reporters)
- [Test Investigation Workflow](./research_diagnostic.mdc)
## Competence Hooks
- **Why this works**: Systematic investigation leverages Playwright's built-in debugging tools to identify root causes
- **Common pitfalls**: Generic selectors fail with multiple similar elements; timing issues create race conditions; alert stacking causes UI conflicts
- **Next skill unlock**: Implement unique test IDs and handle alert dismissal order in test flows
- **Teach-back**: "How would you investigate a Playwright test failure using error context, trace files, and page snapshots?"
## Collaboration Hooks
- **Reviewers**: QA team, test automation engineers
- **Sign-off checklist**: Error context analyzed, trace files reviewed, root cause identified, fix implemented and tested
## Assumptions & Limits
- Test results directory structure follows Playwright conventions
- Trace files are enabled in configuration (`trace: "retain-on-failure"`)
- Error context files contain valid YAML page snapshots

34
BUILDING.md

@ -93,6 +93,7 @@ The Build Architecture Guard protects your build system by enforcing documentati
#### Protected File Patterns
The guard monitors these sensitive paths:
- `vite.config.*` - Build configuration
- `scripts/**` - Build and utility scripts
- `electron/**` - Desktop application code
@ -132,6 +133,7 @@ npm run guard:setup
#### Troubleshooting
If you encounter `mapfile: command not found` errors:
```bash
# Ensure script is executable
chmod +x scripts/build-arch-guard.sh
@ -270,6 +272,7 @@ Start the development server using `npm run build:web:dev` or `npm run build:web
3. To test the production build locally, use `npm run build:web:serve` (builds then serves)
**Why Use `serve`?**
- **Production Testing**: Test your optimized production build locally before deployment
- **SPA Routing Validation**: Verify deep linking and navigation work correctly (handles routes like `/discover`, `/account`)
- **Performance Testing**: Test the minified and optimized build locally
@ -335,15 +338,18 @@ All web build commands use the `./scripts/build-web.sh` script, which provides:
The `serve` functionality provides a local HTTP server for testing production builds:
**What It Does:**
1. **Builds** the application using Vite
2. **Serves** the built files from the `dist/` directory
3. **Handles SPA Routing** - serves `index.html` for all routes (fixes 404s on `/discover`, `/account`, etc.)
**Server Options:**
- **Primary**: `npx serve -s dist -l 8080` (recommended - full SPA support)
- **Fallback**: Python HTTP server (limited SPA routing support)
**Use Cases:**
- Testing production builds before deployment
- Validating SPA routing behavior
- Performance testing of optimized builds
@ -365,8 +371,8 @@ current version to test DB migrations.
- Put the commit hash in the changelog (which will help you remember to bump the
version in the step later).
- Tag with the new version,
[online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or
- Tag with the new version,
[online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or
`git tag 1.0.2 && git push origin 1.0.2`.
- For test, build the app:
@ -1185,14 +1191,14 @@ If you need to build manually or want to understand the individual steps:
- Choose Product -> Archive
- This will trigger a build and take time, needing user's "login" keychain
password (user's login password), repeatedly.
- If it fails with `building for 'iOS', but linking in dylib
- If it fails with `building for 'iOS', but linking in dylib
(.../.pkgx/zlib.net/v1.3.0/lib/libz.1.3.dylib) built for 'macOS'` then run
XCode outside that terminal (ie. not with `npx cap open ios`).
- Click Distribute -> App Store Connect
- In AppStoreConnect, add the build to the distribution. You may have to remove
the current build with the "-" when you hover over it, then "Add Build" with the
new build.
- May have to go to App Review, click Submission, then hover over the build
- May have to go to App Review, click Submission, then hover over the build
and click "-".
- It can take 15 minutes for the build to show up in the list of builds.
- You'll probably have to "Manage" something about encryption, disallowed in France.
@ -1257,11 +1263,13 @@ npm run assets:validate
##### What Gets Validated
**Source Assets (Required):**
- `resources/icon.png` - App icon source
- `resources/splash.png` - Splash screen source
- `resources/splash_dark.png` - Dark mode splash source
**Android Resources (Generated):**
- `android/app/src/main/res/drawable/splash.png` - Splash screen drawable
- `android/app/src/main/res/mipmap-*/ic_launcher.png` - App icons for all densities
- `android/app/src/main/res/mipmap-*/ic_launcher_round.png` - Round app icons for all densities
@ -2706,6 +2714,7 @@ configuration files in the repository.
### 2025-08-21 - Cursor Rules Refactoring and Build System Updates
#### Package Dependencies Updated
- **Added**: `markdownlint-cli2` v0.18.1 - Modern markdown linting with improved performance
- **Added**: `@commitlint/cli` v18.6.1 - Conventional commit message validation
- **Added**: `@commitlint/config-conventional` v18.6.2 - Conventional commit standards
@ -2713,28 +2722,33 @@ configuration files in the repository.
- **Updated**: `lint-staged` v15.2.2 - Pre-commit linting automation
#### Build Script Improvements
- **Markdown Linting**: Replaced custom markdown scripts with `markdownlint-cli2`
- **Before**: `./scripts/fix-markdown.sh` and `./scripts/validate-markdown.sh`
- **After**: `markdownlint-cli2 --fix` and `markdownlint-cli2`
- **Benefits**: Faster execution, better error reporting, modern markdown standards
#### Lint-Staged Configuration Enhanced
- **Added**: Markdown file linting to pre-commit hooks
- **Pattern**: `*.{md,markdown,mdc}` files now automatically formatted
- **Command**: `markdownlint-cli2 --fix` runs before each commit
- **Coverage**: All markdown files including `.mdc` cursor rules
#### Commit Message Standards
- **Added**: Conventional commit validation via commitlint
- **Configuration**: Extends `@commitlint/config-conventional`
- **Enforcement**: Ensures consistent commit message format across the project
#### Node.js Version Requirements
- **Updated**: Minimum Node.js version requirements for new dependencies
- **markdownlint-cli2**: Requires Node.js >=20
- **Various utilities**: Require Node.js >=18 for modern ES features
#### Build Process Impact
- **No Breaking Changes**: All existing build commands continue to work
- **Improved Quality**: Better markdown formatting and commit message standards
- **Enhanced Automation**: More comprehensive pre-commit validation
@ -2745,6 +2759,7 @@ configuration files in the repository.
### 2025-08-21 - Commitlint Configuration Refinement
#### Commit Message Validation Improvements
- **Modified**: Commitlint configuration moved from `package.json` to dedicated `commitlint.config.js`
- **Enhanced**: Strict validation rules downgraded from errors to warnings
- **Before**: `subject-case` and `subject-full-stop` rules caused red error messages
@ -2752,16 +2767,18 @@ configuration files in the repository.
- **Benefit**: Eliminates confusing red error messages while maintaining commit quality guidance
#### Configuration Structure
- **File**: `commitlint.config.js` - Dedicated commitlint configuration
- **Extends**: `@commitlint/config-conventional` - Standard conventional commit rules
- **Custom Rules**:
- **Custom Rules**:
- `subject-case: [1, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']]`
- `subject-full-stop: [1, 'never', '.']`
- **Levels**:
- **Levels**:
- `0` = Disabled, `1` = Warning, `2` = Error
- Current: Problematic rules set to warning level (1)
#### User Experience Impact
- **Before**: Red error messages on every push with strict commit rules
- **After**: Yellow warning messages that provide guidance without disruption
- **Workflow**: Commits and pushes continue to work while maintaining quality standards
@ -2772,6 +2789,7 @@ configuration files in the repository.
### 2025-08-26 - Capacitor Plugin Additions
#### New Capacitor Plugins Added
- **Added**: `@capacitor/clipboard` v6.0.2 - Clipboard functionality for mobile platforms
- **Purpose**: Enable copy/paste operations on mobile devices
- **Platforms**: iOS and Android
@ -2785,23 +2803,27 @@ configuration files in the repository.
- **Integration**: Automatically included in mobile builds
#### Android Build System Updates
- **Modified**: `android/capacitor.settings.gradle` - Added new plugin project includes
- **Added**: `:capacitor-clipboard` project directory mapping
- **Added**: `:capacitor-status-bar` project directory mapping
- **Impact**: New plugins now properly integrated into Android build process
#### Package Dependencies
- **Updated**: `package.json` - Added new Capacitor plugin dependencies
- **Updated**: `package-lock.json` - Locked dependency versions for consistency
- **Version**: All new plugins use Capacitor 6.x compatible versions
#### Build Process Impact
- **No Breaking Changes**: Existing build commands continue to work unchanged
- **Enhanced Mobile Features**: New clipboard and status bar capabilities available
- **Automatic Integration**: Plugins automatically included in mobile builds
- **Platform Support**: Both iOS and Android builds now include new functionality
#### Testing Requirements
- **Mobile Builds**: Verify new plugins integrate correctly in iOS and Android builds
- **Functionality**: Test clipboard operations and status bar management on devices
- **Fallback**: Ensure graceful degradation when plugins are unavailable

3
README-PR-TEMPLATE.md

@ -66,14 +66,17 @@ test-image.tar a1b2c3d4e5f6...
```
### Docs
- [x] **BUILDING.md** updated (sections): Docker deployment
- [x] Troubleshooting updated: Added Docker troubleshooting section
### Rollback
- [x] Verified steps to restore previous behavior:
1. `git revert HEAD`
2. `docker rmi test-image`
3. Restore previous BUILDING.md
```
---

55
README.md

@ -11,7 +11,7 @@ See [ClickUp](https://sharing.clickup.com/9014278710/l/h/8cmnyhp-174/10573fec74e
Quick start:
* For setup, we recommend [pkgx](https://pkgx.dev), which installs what you need (either automatically or with the `dev` command). Core dependencies are typescript & npm; when building for other platforms, you'll need other things such as those in the pkgx.yaml & BUILDING.md files.
- For setup, we recommend [pkgx](https://pkgx.dev), which installs what you need (either automatically or with the `dev` command). Core dependencies are typescript & npm; when building for other platforms, you'll need other things such as those in the pkgx.yaml & BUILDING.md files.
```bash
npm install
@ -90,6 +90,7 @@ VITE_LOG_LEVEL=debug npm run dev
See [Logging Configuration Guide](doc/logging-configuration.md) for complete details.
### Quick Usage
```bash
# Run the database clearing script
./scripts/clear-database.sh
@ -102,16 +103,19 @@ npm run build:web:dev # For Web
### What It Does
#### **Electron (Desktop App)**
- Automatically finds and clears the SQLite database files
- Works on Linux, macOS, and Windows
- Clears all data and forces fresh migrations on next startup
#### **Web Browser**
- Provides instructions for using custom browser data directories
- Shows manual clearing via browser DevTools
- Ensures reliable database clearing without browser complications
### Safety Features
- ✅ **Interactive Script**: Guides you through the process
- ✅ **Platform Detection**: Automatically detects your OS
- ✅ **Clear Instructions**: Step-by-step guidance for each platform
@ -120,6 +124,7 @@ npm run build:web:dev # For Web
### Manual Commands (if needed)
#### **Electron Database Location**
```bash
# Linux
rm -rf ~/.config/TimeSafari/*
@ -132,6 +137,7 @@ rmdir /s /q %APPDATA%\TimeSafari
```
#### **Web Browser (Custom Data Directory)**
```bash
# Create isolated browser profile
mkdir ~/timesafari-dev-data
@ -144,6 +150,7 @@ URL generation across all environments. This prevents localhost URLs from
appearing in shared links during development.
### Key Features
- ✅ **Production URLs for Sharing**: All copy link buttons use production domain
- ✅ **Environment-Specific Internal URLs**: Internal operations use appropriate
environment URLs
@ -227,6 +234,7 @@ npm run test:prerequisites
- **Build failures**: Run `npm run check:dependencies` to diagnose environment issues
**Required Versions**:
- Node.js: 18+ (LTS recommended)
- npm: 8+ (comes with Node.js)
- Platform-specific tools: Android Studio, Xcode (for mobile builds)
@ -246,25 +254,26 @@ To add a Font Awesome icon, add to `fontawesome.ts` and reference with
### Reference Material
* Notifications can be type of `toast` (self-dismiss), `info`, `success`, `warning`, and `danger`.
- Notifications can be type of `toast` (self-dismiss), `info`, `success`, `warning`, and `danger`.
They are done via [notiwind](https://www.npmjs.com/package/notiwind) and set up in App.vue.
* [Customize Vue configuration](https://cli.vuejs.org/config/).
- [Customize Vue configuration](https://cli.vuejs.org/config/).
* If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js, eg: `publicPath: "/app/time-tracker/",`
- If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js, eg: `publicPath: "/app/time-tracker/",`
### Code Organization
The project uses a centralized approach to type definitions and interfaces:
* `src/interfaces/` - Contains all TypeScript interfaces and type definitions
* `deepLinks.ts` - Deep linking type system and Zod validation schemas
* `give.ts` - Give-related interfaces and type definitions
* `claims.ts` - Claim-related interfaces and verifiable credentials
* `common.ts` - Shared interfaces and utility types
* Other domain-specific interface files
- `src/interfaces/` - Contains all TypeScript interfaces and type definitions
- `deepLinks.ts` - Deep linking type system and Zod validation schemas
- `give.ts` - Give-related interfaces and type definitions
- `claims.ts` - Claim-related interfaces and verifiable credentials
- `common.ts` - Shared interfaces and utility types
- Other domain-specific interface files
Key principles:
- All interfaces and types are defined in the interfaces folder
- Zod schemas are used for runtime validation and type generation
- Domain-specific interfaces are separated into their own files
@ -275,11 +284,11 @@ Key principles:
The application uses a platform-agnostic database layer with Vue mixins for service access:
* `src/services/PlatformService.ts` - Database interface definition
* `src/services/PlatformServiceFactory.ts` - Platform-specific service factory
* `src/services/AbsurdSqlDatabaseService.ts` - SQLite implementation
* `src/utils/PlatformServiceMixin.ts` - Vue mixin for database access with caching
* `src/db/` - Legacy Dexie database (migration in progress)
- `src/services/PlatformService.ts` - Database interface definition
- `src/services/PlatformServiceFactory.ts` - Platform-specific service factory
- `src/services/AbsurdSqlDatabaseService.ts` - SQLite implementation
- `src/utils/PlatformServiceMixin.ts` - Vue mixin for database access with caching
- `src/db/` - Legacy Dexie database (migration in progress)
**Development Guidelines**:
@ -316,11 +325,11 @@ timesafari/
Gifts make the world go 'round!
* [WebStorm by JetBrains](https://www.jetbrains.com/webstorm/) for the free open-source license
* [Máximo Fernández](https://medium.com/@maxfarenas) for the 3D [code](https://github.com/maxfer03/vue-three-ns) and [explanatory post](https://medium.com/nicasource/building-an-interactive-web-portfolio-with-vue-three-js-part-three-implementing-three-js-452cb375ef80)
* [Many tools & libraries](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/src/branch/master/package.json#L10) such as Nodejs.org, IntelliJ Idea, Veramo.io, Vuejs.org, threejs.org
* [Bush 3D model](https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439)
* [Forest floor image](https://www.goodfreephotos.com/albums/textures/leafy-autumn-forest-floor.jpg)
* Time Safari logo assisted by [DALL-E in ChatGPT](https://chat.openai.com/g/g-2fkFE8rbu-dall-e)
* [DiceBear](https://www.dicebear.com/licenses/) and [Avataaars](https://www.dicebear.com/styles/avataaars/#details) for human-looking identicons
* Some gratitude prompts thanks to [Develop Good Habits](https://www.developgoodhabits.com/gratitude-journal-prompts/)
- [WebStorm by JetBrains](https://www.jetbrains.com/webstorm/) for the free open-source license
- [Máximo Fernández](https://medium.com/@maxfarenas) for the 3D [code](https://github.com/maxfer03/vue-three-ns) and [explanatory post](https://medium.com/nicasource/building-an-interactive-web-portfolio-with-vue-three-js-part-three-implementing-three-js-452cb375ef80)
- [Many tools & libraries](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/src/branch/master/package.json#L10) such as Nodejs.org, IntelliJ Idea, Veramo.io, Vuejs.org, threejs.org
- [Bush 3D model](https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439)
- [Forest floor image](https://www.goodfreephotos.com/albums/textures/leafy-autumn-forest-floor.jpg)
- Time Safari logo assisted by [DALL-E in ChatGPT](https://chat.openai.com/g/g-2fkFE8rbu-dall-e)
- [DiceBear](https://www.dicebear.com/licenses/) and [Avataaars](https://www.dicebear.com/styles/avataaars/#details) for human-looking identicons
- Some gratitude prompts thanks to [Develop Good Habits](https://www.developgoodhabits.com/gratitude-journal-prompts/)

22
TASK_storage.md

@ -5,33 +5,33 @@
We can't trust iOS IndexedDB to persist. I want to start delivering an app to people now, in preparation for presentations mid-June: Rotary on June 12 and Porcfest on June 17.
* Apple WebKit puts a [7-day cap on IndexedDB](https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/).
- Apple WebKit puts a [7-day cap on IndexedDB](https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/).
* The web standards expose a `persist` method to mark memory as persistent, and [supposedly WebView supports it](https://developer.mozilla.org/en-US/docs/Web/API/StorageManager/persisted), but too many other things indicate it's not reliable. I've talked with [ChatGPT](https://chatgpt.com/share/68322f40-84c8-8007-b213-855f7962989a) & Venice & Claude (in Cursor); [this answer from Perplexity](https://www.perplexity.ai/search/which-platforms-prompt-the-use-HUQLqy4qQD2cRbkmO4CgHg) says that most platforms don't prompt and Safari doesn't support it; I don't know if that means WebKit as well.
- The web standards expose a `persist` method to mark memory as persistent, and [supposedly WebView supports it](https://developer.mozilla.org/en-US/docs/Web/API/StorageManager/persisted), but too many other things indicate it's not reliable. I've talked with [ChatGPT](https://chatgpt.com/share/68322f40-84c8-8007-b213-855f7962989a) & Venice & Claude (in Cursor); [this answer from Perplexity](https://www.perplexity.ai/search/which-platforms-prompt-the-use-HUQLqy4qQD2cRbkmO4CgHg) says that most platforms don't prompt and Safari doesn't support it; I don't know if that means WebKit as well.
* Capacitor says [not to trust it on iOS](https://capacitorjs.com/docs/v6/guides/storage).
- Capacitor says [not to trust it on iOS](https://capacitorjs.com/docs/v6/guides/storage).
Also, with sensitive data, the accounts info should be encrypted.
# Options
* There is a community [SQLite plugin for Capacitor](https://github.com/capacitor-community/sqlite) with encryption by [SQLCipher](https://github.com/sqlcipher/sqlcipher).
- There is a community [SQLite plugin for Capacitor](https://github.com/capacitor-community/sqlite) with encryption by [SQLCipher](https://github.com/sqlcipher/sqlcipher).
* [This tutorial](https://jepiqueau.github.io/2023/09/05/Ionic7Vue-SQLite-CRUD-App.html#part-1---web---table-of-contents) shows how that plugin works for web as well as native.
- [This tutorial](https://jepiqueau.github.io/2023/09/05/Ionic7Vue-SQLite-CRUD-App.html#part-1---web---table-of-contents) shows how that plugin works for web as well as native.
* Capacitor abstracts [user preferences in an API](https://capacitorjs.com/docs/apis/preferences), which uses different underlying libraries on iOS & Android. Unfortunately, it won't do any filtering or searching, and is only meant for small amounts of data. (It could be used for settings and for identifiers, but contacts will grow and image blobs won't work.)
- Capacitor abstracts [user preferences in an API](https://capacitorjs.com/docs/apis/preferences), which uses different underlying libraries on iOS & Android. Unfortunately, it won't do any filtering or searching, and is only meant for small amounts of data. (It could be used for settings and for identifiers, but contacts will grow and image blobs won't work.)
* There are hints that Capacitor offers another custom storage API but all I could find was that Preferences API.
- There are hints that Capacitor offers another custom storage API but all I could find was that Preferences API.
* [Ionic Storage](https://ionic.io/docs/secure-storage) is an enterprise solution, which also supports encryption.
- [Ionic Storage](https://ionic.io/docs/secure-storage) is an enterprise solution, which also supports encryption.
* Not an option yet: Dexie may support SQLite in [a future version](https://dexie.org/roadmap/dexie5.0).
- Not an option yet: Dexie may support SQLite in [a future version](https://dexie.org/roadmap/dexie5.0).
# Current Plan
* Implement SQLite for Capacitor & web, with encryption. That will allow us to test quickly and keep the same interface for native & web, but we don't deal with migrations for current web users.
- Implement SQLite for Capacitor & web, with encryption. That will allow us to test quickly and keep the same interface for native & web, but we don't deal with migrations for current web users.
* After that is delivered, write a migration for current web users from IndexedDB to SQLite.
- After that is delivered, write a migration for current web users from IndexedDB to SQLite.
# Current method calls

1
doc/README-BUILD-GUARD.md

@ -330,6 +330,7 @@ Track the effectiveness of your Build Architecture Guard:
## 📝 **Changelog**
### 2025-08-22 - Shell Compatibility Fix
- **Fixed**: Replaced `mapfile` command with portable alternative for cross-shell compatibility
- **Impact**: Resolves "mapfile: command not found" errors in pre-commit hooks
- **Files**: `scripts/build-arch-guard.sh`

24
doc/android-asset-validation.md

@ -11,12 +11,14 @@ The Android Asset Validation System automatically detects and fixes missing Andr
## Problem Solved
Previously, Android builds would fail with errors like:
```
error: resource drawable/splash (aka app.timesafari.app:drawable/splash) not found.
error: resource mipmap/ic_launcher (aka app.timesafari.app:mipmap/ic_launcher) not found.
```
This happened when:
- Source assets existed but weren't generated into Android resources
- Android resource directories were missing
- Asset generation tools weren't run before building
@ -45,16 +47,19 @@ npm run build:android:studio
### What Gets Validated
#### Source Assets (Required)
- `resources/icon.png` - App icon source
- `resources/splash.png` - Splash screen source
- `resources/splash_dark.png` - Dark mode splash source
#### Android Resources (Generated)
- `android/app/src/main/res/drawable/splash.png` - Splash screen drawable
- `android/app/src/main/res/mipmap-*/ic_launcher.png` - App icons for all densities
- `android/app/src/main/res/mipmap-*/ic_launcher_round.png` - Round app icons for all densities
### Density Levels Checked
- `mipmap-mdpi` (1x)
- `mipmap-hdpi` (1.5x)
- `mipmap-xhdpi` (2x)
@ -64,6 +69,7 @@ npm run build:android:studio
## Usage
### Automatic Validation (Recommended)
The validation runs automatically during all Android builds:
```bash
@ -78,6 +84,7 @@ npm run build:android:debug
```
### Manual Validation
Run validation only to check/fix assets:
```bash
@ -89,6 +96,7 @@ npm run assets:validate:android
```
### Validation Only (No Regeneration)
Check configuration without fixing:
```bash
@ -98,6 +106,7 @@ npm run assets:validate
## Error Handling
### Missing Source Assets
If source assets are missing, the build fails with clear error messages:
```
@ -108,6 +117,7 @@ If source assets are missing, the build fails with clear error messages:
```
### Missing Generated Resources
If generated resources are missing, they're automatically regenerated:
```
@ -119,6 +129,7 @@ If generated resources are missing, they're automatically regenerated:
```
### Generation Failure
If regeneration fails, helpful guidance is provided:
```
@ -131,6 +142,7 @@ If regeneration fails, helpful guidance is provided:
## Integration Points
### Build Script Integration
The validation is integrated into the main build process:
```bash
@ -143,6 +155,7 @@ validate_android_assets || {
```
### NPM Scripts
New npm scripts for asset management:
```json
@ -156,17 +169,20 @@ New npm scripts for asset management:
## Benefits
### For Developers
- **No More Build Failures**: Automatic detection and fixing of missing resources
- **Faster Development**: No need to manually run asset generation tools
- **Clear Error Messages**: Helpful guidance when issues occur
- **Consistent Results**: Same validation on all development machines
### For CI/CD
- **Reliable Builds**: Consistent asset validation across environments
- **Early Detection**: Catches issues before they reach production
- **Automated Fixes**: Self-healing builds when possible
### For Project Maintenance
- **Reduced Support**: Fewer "build doesn't work" issues
- **Documentation**: Clear requirements for required assets
- **Standardization**: Consistent asset structure across the project
@ -176,21 +192,27 @@ New npm scripts for asset management:
### Common Issues
#### "No assets found in the asset path"
This occurs when the `assets/` directory is empty. The validation system automatically copies source assets and regenerates them.
#### "Failed to generate Android assets"
Check that:
- Source assets exist in `resources/`
- `@capacitor/assets` is installed
- You have write permissions to the Android directories
#### "Asset generation completed but some resources are still missing"
This indicates a problem with the asset generation tool. Try:
1. Running `npm install` to ensure dependencies are up to date
2. Manually running `npx @capacitor/assets generate`
3. Checking the asset generation logs for specific errors
### Manual Recovery
If automatic regeneration fails, you can manually create the missing resources:
```bash
@ -213,12 +235,14 @@ rm assets/icon.png assets/splash.png assets/splash_dark.png
## Future Enhancements
### Planned Improvements
- **iOS Asset Validation**: Extend validation to iOS assets
- **Asset Quality Checks**: Validate image dimensions and formats
- **Performance Optimization**: Cache validation results
- **CI/CD Integration**: Add validation to GitHub Actions
### Configuration Options
- **Custom Asset Paths**: Support for different asset directory structures
- **Validation Rules**: Configurable validation requirements
- **Skip Options**: Ability to skip validation for specific scenarios

22
doc/meta_rule_usage_guide.md

@ -32,6 +32,7 @@ you apply 1-3 meta-rules that automatically include everything you need.
### **Step 1: Always Start with Core Always-On**
**Every single interaction** starts with:
```
meta_core_always_on.mdc
```
@ -65,12 +66,14 @@ meta_core_always_on + meta_research + meta_bug_diagnosis
**Important**: Meta-rules represent **workflow phases**, not a rigid sequence. You can:
### **Jump Between Phases Freely**
- **Start with diagnosis** if you already know the problem
- **Go back to research** if your fix reveals new issues
- **Switch to planning** mid-implementation if scope changes
- **Document at any phase** - not just at the end
### **Mode Switching by Invoking Meta-Rules**
Each meta-rule invocation **automatically switches your workflow mode**:
```
@ -80,11 +83,13 @@ Planning Mode → Invoke @meta_feature_implementation → Implementation Mode
```
### **Phase Constraints, Not Sequence Constraints**
- **Within each phase**: Clear constraints on what you can/cannot do
- **Between phases**: Complete freedom to move as needed
- **No forced order**: Choose the phase that matches your current need
### **Example of Flexible Workflow**
```
1. Start with @meta_research (investigation mode)
2. Jump to @meta_bug_diagnosis (diagnosis mode)
@ -103,16 +108,19 @@ Planning Mode → Invoke @meta_feature_implementation → Implementation Mode
**Scenario**: User reports that the contact list isn't loading properly
**Initial Meta-Rule Selection**:
```
meta_core_always_on + meta_research + meta_bug_diagnosis
```
**What This Gives You**:
- **Core Always-On**: Human competence focus, time standards, context
- **Research**: Systematic investigation methodology, evidence collection
- **Bug Diagnosis**: Defect analysis framework, root cause identification
**Flexible Workflow**:
1. Apply core always-on for foundation
2. Use research meta-rule for systematic investigation
3. Switch to bug diagnosis when you have enough evidence
@ -125,16 +133,19 @@ meta_core_always_on + meta_research + meta_bug_diagnosis
**Scenario**: Building a new contact search feature
**Meta-Rule Selection**:
```
meta_core_always_on + meta_feature_planning + meta_feature_implementation
```
**What This Gives You**:
- **Core Always-On**: Foundation principles and context
- **Feature Planning**: Requirements analysis, architecture planning
- **Feature Implementation**: Development workflow, testing strategy
**Iterative Workflow**:
1. Start with core always-on
2. Use feature planning for design and requirements
3. Switch to feature implementation for coding and testing
@ -147,15 +158,18 @@ meta_core_always_on + meta_feature_planning + meta_feature_implementation
**Scenario**: Writing a migration guide for the new database system
**Meta-Rule Selection**:
```
meta_core_always_on + meta_documentation
```
**What This Gives You**:
- **Core Always-On**: Foundation and context
- **Documentation**: Educational focus, templates, quality standards
**Parallel Workflow**:
1. Apply core always-on for foundation
2. Use documentation meta-rule for educational content creation
3. **Can research** while documenting if you need more information
@ -198,27 +212,35 @@ Each meta-rule includes success criteria. Use these to validate your work:
## Common Meta-Rule Combinations
### **Research + Diagnosis**
```
meta_core_always_on + meta_research + meta_bug_diagnosis
```
**Use for**: Complex bug investigations requiring systematic analysis
### **Planning + Implementation**
```
meta_core_always_on + meta_feature_planning + meta_feature_implementation
```
**Use for**: End-to-end feature development from concept to deployment
### **Research + Planning**
```
meta_core_always_on + meta_research + meta_feature_planning
```
**Use for**: Feasibility research and solution design
### **Documentation + Context**
```
meta_core_always_on + meta_documentation + [context-specific]
```
**Use for**: Creating comprehensive, educational documentation
## Best Practices

131
doc/notification-system-executive-summary.md

@ -0,0 +1,131 @@
# TimeSafari Notification System — Executive Summary
**Status:** 🚀 Ready for Implementation
**Date:** 2025-01-27T14:30Z (UTC)
**Author:** Matthew Raymer
**Audience:** Executive Leadership, Product Management, Engineering Leadership
---
## Executive Overview
TimeSafari will implement a **multi-platform notification system** that
delivers **1-3 daily notifications** to keep users connected to gratitude, gifts,
and collaborative projects. The system will work across **iOS, Android, Web,
and Electron** platforms with **offline-first reliability** and
**privacy-preserving architecture**.
### Business Value
- **User Engagement:** Daily touchpoints to maintain community connections
- **Platform Coverage:** Unified experience across all TimeSafari platforms
- **Privacy-First:** User-controlled data with no external tracking
- **Reliability:** Offline notifications that work even when app is closed
---
## Strategic Approach
### Phase 1 (v1): In-App Orchestrator
**Scope:** Multi-daily local notifications with online/offline flows
**Key Capabilities:**
- **Local Notifications:** OS-level delivery on mobile/desktop
- **Web Push:** Service Worker-based notifications for web
- **Offline Reliability:** Notifications fire even when app is closed
- **Content Prefetching:** Fresh content fetched when app is active
- **Cross-Platform:** Same user experience across all platforms
### Phase 2 (v2): Native Plugin
**Timeline:** Future enhancement
**Scope:** Native background scheduling and enhanced capabilities
**Key Capabilities:**
- **Native Background Work:** OS-level background tasks
- **Enhanced Scheduling:** More precise timing and reliability
- **Advanced Features:** Rich media and complex actions
- **Performance Optimization:** Native SQLite and HTTP
---
## Platform Strategy
| Platform | v1 Approach | v2 Enhancement |
|----------|-------------|----------------|
| **iOS** | Local notifications + Background Runner (optional) | Native BGTaskScheduler |
| **Android** | Local notifications + Background Runner (optional) | WorkManager + AlarmManager |
| **Web** | Service Worker push notifications | Enhanced push capabilities |
| **Electron** | OS notifications while app running | Native background services |
---
## Technical Architecture
### Core Components
- **Notification Orchestrator:** Central coordination and state management
- **Platform Adapters:** Platform-specific notification delivery
- **Database Integration:** SQLite persistence with TimeSafari's existing infrastructure
- **Content Management:** Template-based notification content with ETag caching
### Integration Points
- **Existing Database:** Extends TimeSafari's SQLite migration system
- **Platform Services:** Uses established PlatformServiceMixin patterns
- **Settings System:** Integrates with existing user preferences
- **Web Push:** Leverages existing Service Worker infrastructure
---
## Implementation Plan
### Phase 1 Deliverables (v1)
1. **Database Schema:** New notification tables integrated with existing migration system
2. **Core Service:** Notification orchestrator with platform adapters
3. **User Interface:** Settings integration for notification preferences
4. **Testing:** Cross-platform test suite with Playwright
5. **Documentation:** Complete implementation guide and API reference
### Success Metrics
- **Reliability:** 95%+ notification delivery rate across platforms
- **Performance:** <2s notification rendering time
- **User Adoption:** 80%+ opt-in rate for daily notifications
- **Platform Coverage:** 100% feature parity across iOS/Android/Web/Electron
---
## Risk Mitigation
### Technical Risks
- **Platform Limitations:** Mitigated by graceful degradation and fallback strategies
- **Permission Denials:** User education and deep-linking to system settings
- **Background Restrictions:** Conservative approach with offline-first design
### Business Risks
- **User Fatigue:** Configurable frequency and user-controlled preferences
- **Privacy Concerns:** Privacy-first architecture with local data storage
- **Platform Changes:** Abstraction layer protects against OS updates
---
## Document References
- **Strategic Plan:** `notification-system-plan.md` - Goals, tenets, platform
behaviors, acceptance criteria
- **Implementation Guide:** `notification-system-implementation.md` - Complete
code, database schemas, integration specifics
- **This Summary:** High-level overview for executive decision-making
---
*This executive summary provides the essential business context and strategic
direction for TimeSafari's notification system. For detailed technical
specifications and implementation guidance, refer to the referenced documents.*

861
doc/notification-system-implementation.md

File diff suppressed because it is too large

657
doc/notification-system-plan.md

@ -1,34 +1,55 @@
# TimeSafari Notification System — Strategic Plan
**Status:** 🚀 Active plan
**Date:** 2025-09-05T05:09Z (UTC)
**Author:** Matthew Raymer
**Scope:** v1 (in‑app orchestrator) now; path to v2 (native plugin) next
**Goal:** We **will deliver** 1..M local notifications/day with content **prefetched** so messages **will display offline**. We **will support** online‑first (API→DB→Schedule) with offline‑first fallback. The system **will enhance** TimeSafari's community-building mission by keeping users connected to gratitude, gifts, and collaborative projects through timely, relevant notifications.
> **Implementation Details:** See `notification-system-implementation.md` for detailed code, database schemas, and integration specifics.
> **Canonical Ownership:** This document owns Goals, Tenets, Platform behaviors, Acceptance criteria, and Test cases.
**Status:** 🚀 Active plan
**Date:** 2025-09-05T05:09Z (UTC)
**Author:** Matthew Raymer
**Scope:** v1 (in‑app orchestrator) now; path to v2 (native plugin) next
**Goal:** We **will deliver** 1..M local notifications/day with content
**prefetched** so messages **will display offline**. We **will support**
online‑first (API→DB→Schedule) with offline‑first fallback. The system
**will enhance** TimeSafari's community-building mission by keeping users
connected to gratitude, gifts, and collaborative projects through timely,
relevant notifications.
> **Implementation Details:** See `notification-system-implementation.md` for
detailed code, database schemas, and integration specifics.
> **Canonical Ownership:** This document owns Goals, Tenets, Platform
> behaviors, Acceptance criteria, and Test cases.
---
## 1) Versioning & Intent
- **v1 (In‑App Orchestrator):** We **will implement** multi‑daily local notifications, online/offline flows, templating, SQLite persistence, and eventing **inside the app** using Capacitor Local Notifications.
- **v2 (Plugin):** We **will extract** adapters to a Capacitor/Native plugin to gain native schedulers (WorkManager/AlarmManager; BGTask+UNUserNotificationCenter), native HTTP, and native SQLite **with the same TypeScript API**.
- **v1 (In‑App Orchestrator):** We **will implement** multi‑daily local
notifications, online/offline flows, templating, SQLite persistence, and
eventing **inside the app** using Capacitor Local Notifications.
- **v2 (Plugin):** We **will extract** adapters to a Capacitor/Native plugin
to gain native schedulers (WorkManager/AlarmManager;
BGTask+UNUserNotificationCenter), native HTTP, and native SQLite **with the
same TypeScript API**.
> We **will retain** the existing web push + Service Worker foundation; the system **will add** reliable local scheduling on mobile and a unified API across platforms.
> We **will retain** the existing web push + Service Worker foundation; the
> system **will add** reliable local scheduling on mobile and a unified API
> across platforms.
---
## 2) Design Tenets
- **Reliability:** OS‑level delivery once scheduled; no reliance on JS being alive at fire time.
- **Freshness:** Prefer online‑first within a short prefetch window; degrade gracefully to cached content with TTL.
- **Extractable:** Clean interfaces (Scheduler, DataStore, Callbacks) so v2 **will swap** adapters without API changes.
- **Simplicity:** One‑shot notifications per slot; rolling window scheduling to respect platform caps.
- **Observability:** Persist deliveries and errors; surface minimal metrics; enable ACKs.
- **Privacy-First:** Follow TimeSafari's privacy-preserving architecture; user-controlled visibility and data sovereignty.
- **Community-Focused:** Enhance TimeSafari's mission of connecting people through gratitude, gifts, and collaborative projects.
- **Reliability:** OS‑level delivery once scheduled; no reliance on JS being alive
at fire time.
- **Freshness:** Prefer online‑first within a short prefetch window; degrade
gracefully to cached content with TTL.
- **Extractable:** Clean interfaces (Scheduler, DataStore, Callbacks) so v2
**will swap** adapters without API changes.
- **Simplicity:** One‑shot notifications per slot; rolling window scheduling to
respect platform caps.
- **Observability:** Persist deliveries and errors; surface minimal metrics;
enable ACKs.
- **Privacy-First:** Follow TimeSafari's privacy-preserving architecture;
user-controlled visibility and data sovereignty.
- **Community-Focused:** Enhance TimeSafari's mission of connecting people through
gratitude, gifts, and collaborative projects.
---
@ -46,295 +67,405 @@ Adapters
├─ V1: SchedulerCapacitor, DataStoreSqlite, CallbacksHttp
└─ V2: SchedulerNative, DataStoreNativeSqlite, CallbacksNativeHttp
**Scheduler Adapter:** All notification arming must go through the Scheduler adapter to honor platform timing semantics (exact alarms vs. windowed fallback).
Platform
├─ iOS/Android: LocalNotifications (+ native bridges later)
├─ Web: Service Worker + Push (kept)
└─ Electron: OS notifications (thin adapter)
```
**Execution modes (concise):**
- **Online‑First:** wake near slot → fetch (ETag, timeout) → persist → schedule; on failure → Offline‑First.
- **Offline‑First:** read last good payload from SQLite; if beyond TTL → skip notification (no retry).
**Execution modes (concise):**
- **Online‑First:** wake near slot → fetch (ETag, timeout) → persist → schedule;
on failure → Offline‑First.
- **Offline‑First:** read last good payload from SQLite; if beyond TTL → skip
notification (no retry).
---
## 4) Public API (Shared by v1 & v2)
```ts
export type NotificationTime = { hour: number; minute: number }; // local wall-clock
export type SlotId = string; // Format: "HHmm" (e.g., "0800", "1200", "1800") - stable across TZ changes
export type FetchSpec = {
method: 'GET'|'POST';
url: string;
headers?: Record<string,string>;
bodyJson?: Record<string,unknown>;
timeoutMs?: number;
};
export type CallbackProfile = {
fetchContent: FetchSpec;
ackDelivery?: Omit<FetchSpec,'bodyJson'|'timeoutMs'>;
reportError?: Omit<FetchSpec,'bodyJson'|'timeoutMs'>;
heartbeat?: Omit<FetchSpec,'bodyJson'> & { intervalMinutes?: number };
};
export type ConfigureOptions = {
times: NotificationTime[]; // 1..M daily
timezone?: string; // Default: system timezone
ttlSeconds?: number; // Default: 86400 (24h)
prefetchLeadMinutes?: number; // Default: 20
storage: 'shared'|'private'; // Required
contentTemplate: { title: string; body: string }; // Required
callbackProfile?: CallbackProfile; // Optional
};
export interface MultiDailyNotification {
requestPermissions(): Promise<void>;
configure(o: ConfigureOptions): Promise<void>;
runFullPipelineNow(): Promise<void>; // API→DB→Schedule (today's remaining)
deliverStoredNow(slotId?: SlotId): Promise<void>; // 60s cooldown guard
reschedule(): Promise<void>;
getState(): Promise<{
nextOccurrences: Array<{ slotId: SlotId; when: string }>; // ISO
lastFetchAt?: string; lastDeliveryAt?: string;
pendingCount: number; exactAlarmCapable?: boolean;
}>;
}
```
> **Storage semantics:** `'shared'` = app DB; `'private'` = plugin-owned/native DB (v2). (No functional difference in v1.)
**Core Types & Interface:** See Implementation document for complete API
definitions, type interfaces, and design decisions.
> **Storage semantics:** `'shared'` = app DB; `'private'` = plugin-owned/native
> DB (v2). (No functional difference in v1.)
> **Slot Identity & Scheduling Policy**
> • **SlotId** uses canonical `HHmm` and remains stable across timezone changes.
> • **Lead window:** default `prefetchLeadMinutes = 20`; no retries once inside the lead.
> • **TTL policy:** When offline and content is beyond TTL, **we will skip** the notification (no "(cached)" suffix).
> • **Idempotency:** Duplicate "scheduled" deliveries are prevented by a unique index on `(slot_id, fire_at, status='scheduled')`.
> • **Time handling:** Slots will follow **local wall-clock** time across TZ/DST; `slotId=HHmm` stays constant and we will **recompute fire times** on offset change.
> • **SlotId** uses canonical `HHmm` and remains stable across timezone
> changes.
> • **Lead window:** default `prefetchLeadMinutes = 20`; no retries once inside
the lead.
> • **TTL policy:** When offline and content is beyond TTL, **we will skip** the
notification (no "(cached)" suffix).
> • **Idempotency:** Duplicate "scheduled" deliveries are prevented by a unique
index on `(slot_id, fire_at, status='scheduled')`.
> • **Time handling:** Slots will follow **local wall-clock** time across TZ/DST;
`slotId=HHmm` stays constant and we will **recompute fire times** on offset change.
---
## 5) Data Model & Retention (SQLite)
**Tables:** `notif_contents`, `notif_deliveries`, `notif_config`
**Tables:** `notif_contents`, `notif_deliveries`, `notif_config` (see
Implementation document for complete schema)
**Retention:** We **will keep** ~14 days of contents/deliveries (configurable) and **will prune** via a simple daily job that runs on app start/resume. We **will prune** daily but **will not** VACUUM by default on mobile; disk compaction is deferred.
**Retention:** We **will keep** ~14 days of contents/deliveries (configurable)
and **will prune** via a simple daily job that runs on app start/resume. We
**will prune** daily but **will not** VACUUM by default on mobile; disk
compaction is deferred.
**Payload handling:** We **will template** `{title, body}` **before** scheduling; we **will not** mutate at delivery time.
**Payload handling:** We **will template** `{title, body}` **before** scheduling;
we **will not** mutate at delivery time.
---
## 6) Scheduling Policy & Slot Math
- **One‑shot per slot** per day (non‑repeating).
- **Rolling window:** today's remaining slots; seed tomorrow where platform limits allow. v1 will schedule **the next occurrence per slot** by default; a **configurable depth** (0=today, 1=today+tomorrow) may be enabled as long as the iOS pending cap is respected.
- **TZ/DST safe:** We **will recompute** local wall‑times on app resume and whenever timezone/offset changes; then **reschedule**.
- **Android exactness:** If exact alarms are unavailable or denied, we **will use** `setWindow` semantics via the scheduler adapter.
- **iOS pending cap:** We **will keep** pending locals within typical caps (~64) by limiting the window and canceling/re‑arming as needed.
- **Electron rolling window:** On Electron we **will schedule** the **next occurrence per slot** by default; depth (today+tomorrow) **will be** enabled only when auto-launch is on, to avoid drift while the app is closed.
- **One‑shot per slot** per day (non‑repeating).
- **Rolling window:** today's remaining slots; seed tomorrow where platform
limits allow.
- **TZ/DST safe:** We **will recompute** local wall‑times on app resume and
whenever timezone/offset changes; then **reschedule**.
- **Android exactness:** If exact alarms are unavailable or denied, we
**will use** `setWindow` semantics via the scheduler adapter.
- **iOS pending cap:** We **will keep** pending locals within typical caps (~64)
by limiting the window and canceling/re‑arming as needed.
- **Electron rolling window:** On Electron we **will schedule** the **next
occurrence per slot** by default; depth (today+tomorrow) **will be** enabled only
when auto-launch is on, to avoid drift while the app is closed.
---
## 7) Timing & Network Requirements
**Summary:** The notification system uses lightweight, ETag-aware content
fetching with single attempts inside lead windows. All timing constants and
detailed network policies are defined in the Implementation document.
**Key Policies:**
- **Lead policy:** The lead window governs **online-first fetch attempts**, not
arming. We **will arm** locals **whenever the app runs**, using the freshest
available payload.
- **TTL policy:** If offline and content is beyond TTL, we will **skip** the
notification (no "cached" suffix).
- **Idempotency:** Duplicate "scheduled" rows are prevented by a unique index on
`(slot_id, fire_at, status='scheduled')`.
- **Wall-clock rule:** Slots will follow **local wall-clock** across TZ/DST;
`slotId=HHmm` stays constant and we will **recompute fire times** on offset change.
- **Resume debounce:** On app resume/open we will **debounce** pipeline
entry points by **30s** per app session to avoid burst fetches.
- **No scheduled background network in v1 (mobile):** Local notifications
**will deliver offline once armed**, but **we will not** run timed network jobs
when the app is terminated. **Network prefetch will occur only while the app is
running** (launch/resume/inside lead). Server-driven push (Web SW) and OS
background schedulers are a **v2** capability.
**Platform-Specific Network Access:**
- **iOS:** Foreground/recently backgrounded only; no JS wake when app is killed
- **Android:** Exact alarms vs. windowed triggers based on permissions
- **Web:** Service Worker for push notifications only
- **Electron:** App-running only; no background network access
**Optional Background Prefetch (v1):**
- **Background Runner (optional, v1):** We **will integrate** Capacitor's
Background Runner to **opportunistically prefetch** content on iOS/Android when
the OS grants background time. This **will not** provide clock-precise execution
and **will not** run after user-terminate on iOS. It **will not** be treated as
a scheduler. We **will continue** to *arm* local notifications via our rolling
window regardless of Runner availability. When Runner fires near a slot (inside
`prefetchLeadMinutes`), it **will** refresh content (ETag, 12s timeout) and,
behind a flag, **may** cancel & re-arm that slot with the fresh template if within
TTL. If no budget or failure, the previously armed local **will** still deliver.
**Implementation Details:** See Implementation document for complete timing
constants table, network request profiles, and platform-specific enforcement.
---
## 7) Platform Essentials
## 8) Platform Essentials
**iOS**
- Local notifications **will** fire without background runtime once scheduled. NSE **will not** mutate locals; delivery-time enrichment requires remote push (future).
**iOS**
- Local notifications **will** fire without background runtime once scheduled.
NSE **will not** mutate locals; delivery-time enrichment requires remote push (future).
- **Category ID**: `TS_DAILY` with default `OPEN` action
- **Background budget** is short and OS‑managed; any prefetch work **will complete** promptly.
- **Background budget** is short and OS‑managed; any prefetch work
**will complete** promptly.
- **Mobile local notifications will route via action listeners (not the service worker)**.
- Background Runner **will** offer **opportunistic** network wake (no guarantees;
short runtime; iOS will not run after force-quit). Locals **will** still deliver
offline once armed.
**Android**
**Android**
- Exact alarms on **API 31+** may require `SCHEDULE_EXACT_ALARM`. If exact access is missing on API 31+, we will use a **windowed trigger (default ±10m)** and surface a settings deep-link.
- Exact alarms on **API 31+** may require `SCHEDULE_EXACT_ALARM`. If exact access
is missing on API 31+, we will use a **windowed trigger (default ±10m)** and
surface a settings deep-link.
- **We will deep-link users to the exact-alarm settings when we detect denials.**
- **Channel defaults**: ID `timesafari.daily`, name "TimeSafari Daily", importance=high (IDs never change)
- Receivers for reboot/time change **will be handled** by v2 (plugin); in v1, re‑arming **will occur** on app start/resume.
- **Channel defaults**: ID `timesafari.daily`, name "TimeSafari Daily",
importance=high (IDs never change)
- Receivers for reboot/time change **will be handled** by v2 (plugin); in v1,
re‑arming **will occur** on app start/resume.
- **Mobile local notifications will route via action listeners (not the service worker)**.
- Background Runner **will** offer **opportunistic** network wake (no guarantees;
short runtime; iOS will not run after force-quit). Locals **will** still deliver
offline once armed.
**Web**
- Requires registered Service Worker + permission; can deliver with browser closed.
**Web will not offline-schedule**.
- Service Worker click handlers are for **web push only**;
**mobile locals bypass the SW**.
- SW examples use `/sw.js` as a placeholder; **wire this to your actual build
output path** (e.g., `sw_scripts/notification-click.js` or your combined bundle).
- **Note**: Service workers are **intentionally disabled** in Electron
(`src/main.electron.ts`) and web uses VitePWA plugin for minimal implementation.
**Web**
- Requires registered Service Worker + permission; can deliver with browser closed. **Web will not offline-schedule**.
- Service worker click handlers apply to **web push only**; local notifications on mobile do **not** pass through the SW.
- SW examples use `/sw.js` as a placeholder; **wire this to your actual build output path** (e.g., `sw_scripts/notification-click.js` or your combined bundle).
- **Note**: Service workers are **intentionally disabled** in Electron (`src/main.electron.ts`) and web uses VitePWA plugin for minimal implementation.
**Electron**
**Electron**
- We **will use** native OS notifications with **best-effort scheduling while the app is running**; true background scheduling will be addressed in v2 (native bridges).
- We **will use** native OS notifications with **best-effort scheduling while the
app is running**; true background scheduling will be addressed in v2 (native bridges).
**Electron delivery strategy (v1 reality + v2 path)**
We **will deliver** desktop notifications while the Electron app is running. True **background scheduling when the app is closed** is **out of scope for v1** and **will be addressed** in v2 via native bridges. We **will adopt** one of the following options (in order of fit to our codebase):
**Electron delivery strategy (v1 reality + v2 path)**
We **will deliver** desktop notifications while the Electron app is running. True
**background scheduling when the app is closed** is **out of scope for v1** and
**will be addressed** in v2 via native bridges. We **will adopt** one of the
following options (in order of fit to our codebase):
**In-app scheduler + auto-launch (recommended now):** Keep the orchestrator in the main process, **start on login** (tray app, hidden window), and use the **Electron `Notification` API** for delivery. This requires no new OS services and aligns with our PlatformServiceFactory/mixin patterns.
**In-app scheduler + auto-launch (recommended now):** Keep the orchestrator in
the main process, **start on login** (tray app, hidden window), and use the
**Electron `Notification` API** for delivery. This requires no new OS services
and aligns with our PlatformServiceFactory/mixin patterns.
**Policy (v1):** If the app is **not running**, Electron will **not** deliver scheduled locals. With **auto-launch enabled**, we **will achieve** near-mobile parity while respecting OS sleep/idle behavior.
**Policy (v1):** If the app is **not running**, Electron will **not** deliver
scheduled locals. With **auto-launch enabled**, we **will achieve** near-mobile
parity while respecting OS sleep/idle behavior.
**UX notes:** On Windows we **will set** `appUserModelId` so toasts are attributed correctly; on macOS we **will request** notification permission on first use.
**UX notes:** On Windows we **will set** `appUserModelId` so toasts are
attributed correctly; on macOS we **will request** notification permission on
first use.
**Prerequisites:** We **will require** Node 18+ (global `fetch`) or we **will polyfill** via `undici` for content fetching in the main process.
**Prerequisites:** We **will require** Node 18+ (global `fetch`) or we
**will polyfill** via `undici` for content fetching in the main process.
---
## 8) Template Engine Contract
**Supported tokens:** `{{headline}}`, `{{summary}}`, `{{date}}` (YYYY-MM-DD), `{{time}}` (HH:MM).
**Escaping:** HTML-escape all injected values.
**Limits:** Title ≤ 50 chars; Body ≤ 200 chars; truncate with ellipsis.
**Fallback:** Missing token → `"[Content]"`.
**Mutation:** We **will** render templates **before** scheduling; no mutation at delivery time on iOS locals.
**Supported tokens:** `{{headline}}`, `{{summary}}`, `{{date}}` (YYYY-MM-DD),
`{{time}}` (HH:MM).
**Escaping:** HTML-escape all injected values.
**Limits:** Title ≤ 50 chars; Body ≤ 200 chars; truncate with ellipsis.
**Fallback:** Missing token → `"[Content]"`.
**Mutation:** We **will** render templates **before** scheduling; no mutation at
delivery time on iOS locals.
## 9) Integration with Existing TimeSafari Infrastructure
**Database:** We **will integrate** with existing migration system in `src/db-sql/migration.ts` following the established `MIGRATIONS` array pattern
**Settings:** We **will extend** existing Settings type in `src/db/tables/settings.ts` following the established type extension pattern
**Platform Service:** We **will leverage** existing PlatformServiceMixin database utilities following the established mixin pattern
**Service Factory:** We **will follow** the existing `PlatformServiceFactory` singleton pattern for notification service creation
**Capacitor:** We **will integrate** with existing deep link system in `src/main.capacitor.ts` following the established initialization pattern
**Service Worker:** We **will extend** existing service worker infrastructure following the established `sw_scripts/` pattern (Note: Service workers are intentionally disabled in Electron and have minimal web implementation via VitePWA plugin)
**API:** We **will use** existing error handling from `src/services/api.ts` following the established `handleApiError` pattern
**Logging:** We **will use** existing logger from `src/utils/logger` following the established logging patterns
**Platform Detection:** We **will use** existing `process.env.VITE_PLATFORM` patterns (`web`, `capacitor`, `electron`)
**Vue Architecture:** We **will follow** Vue 3 + vue-facing-decorator patterns for component integration (Note: The existing `useNotifications` composable in `src/composables/useNotifications.ts` is currently stub functions with eslint-disable comments and needs implementation)
**State Management:** We **will integrate** with existing settings system via `PlatformServiceMixin.$saveSettings()` for notification preferences (Note: TimeSafari uses PlatformServiceMixin for all state management, not Pinia stores)
**Identity System:** We **will integrate** with existing `did:ethr:` (Ethereum-based DID) system for user context
**Testing:** We **will follow** Playwright E2E testing patterns established in TimeSafari
**Database:** We **will integrate** with existing migration system in
`src/db-sql/migration.ts` following the established `MIGRATIONS` array pattern
**Settings:** We **will extend** existing Settings type in
`src/db/tables/settings.ts` following the established type extension pattern
**Platform Service:** We **will leverage** existing PlatformServiceMixin database
utilities following the established mixin pattern
**Service Factory:** We **will follow** the existing `PlatformServiceFactory`
singleton pattern for notification service creation
**Capacitor:** We **will integrate** with existing deep link system in
`src/main.capacitor.ts` following the established initialization pattern
**Service Worker:** We **will extend** existing service worker infrastructure
following the established `sw_scripts/` pattern (Note: Service workers are
intentionally disabled in Electron and have minimal web implementation via
VitePWA plugin)
**API:** We **will use** existing error handling from `src/services/api.ts`
following the established `handleApiError` pattern
**Logging:** We **will use** existing logger from `src/utils/logger` following
the established logging patterns
**Platform Detection:** We **will use** existing `process.env.VITE_PLATFORM`
patterns (`web`, `capacitor`, `electron`)
**Vue Architecture:** We **will follow** Vue 3 + vue-facing-decorator patterns
for component integration (Note: The existing `useNotifications` composable in
`src/composables/useNotifications.ts` is currently stub functions with
eslint-disable comments and needs implementation)
**State Management:** We **will integrate** with existing settings system via
`PlatformServiceMixin.$saveSettings()` for notification preferences (Note:
TimeSafari uses PlatformServiceMixin for all state management, not Pinia stores)
**Identity System:** We **will integrate** with existing `did:ethr:`
(Ethereum-based DID) system for user context
**Testing:** We **will follow** Playwright E2E testing patterns established in TimeSafari
**Database Architecture:** We **will support** platform-specific database backends:
- **Web**: Absurd SQL (SQLite via IndexedDB) via `WebPlatformService` with worker pattern
- **Capacitor**: Native SQLite via `CapacitorPlatformService`
- **Electron**: Native SQLite via `ElectronPlatformService` (extends CapacitorPlatformService)
- **Capacitor**: Native SQLite via `CapacitorPlatformService`
- **Electron**: Native SQLite via `ElectronPlatformService` (extends CapacitorPlatformService)
---
## 10) Error Taxonomy & Telemetry
**Error Codes:** `FETCH_TIMEOUT`, `ETAG_NOT_MODIFIED`, `SCHEDULE_DENIED`, `EXACT_ALARM_MISSING`, `STORAGE_BUSY`, `TEMPLATE_MISSING_TOKEN`, `PERMISSION_DENIED`.
**Error Codes:** `FETCH_TIMEOUT`, `ETAG_NOT_MODIFIED`, `SCHEDULE_DENIED`,
`EXACT_ALARM_MISSING`, `STORAGE_BUSY`, `TEMPLATE_MISSING_TOKEN`, `PERMISSION_DENIED`.
**Event Envelope:** `code, slotId, whenMs, attempt, networkState, tzOffset, appState, timestamp`.
**Event Envelope:** `code, slotId, whenMs, attempt, networkState, tzOffset,
appState, timestamp`.
---
## 11) Permission UX & Channels/Categories
- We **will request** notification permission **after** user intent (e.g., settings screen), not on first render.
- **Android:** We **will create** a stable channel ID (e.g., `timesafari.daily`) and **will set** importance appropriately.
- **iOS:** We **will register** categories for optional actions; grouping may use `threadIdentifier` per slot/day.
- We **will request** notification permission **after** user intent (e.g.,
settings screen), not on first render.
- **Android:** We **will create** a stable channel ID (e.g., `timesafari.daily`)
and **will set** importance appropriately.
- **iOS:** We **will register** categories for optional actions; grouping may
use `threadIdentifier` per slot/day.
---
## 12) Eventing & Telemetry
### Error Taxonomy
**Finite error code set:**
- `FETCH_TIMEOUT` - Network request exceeded timeout
- `ETAG_NOT_MODIFIED` - Server returned 304 (expected)
- `SCHEDULE_DENIED` - OS denied notification scheduling
- `EXACT_ALARM_MISSING` - Android exact alarm permission absent
- `STORAGE_BUSY` - Database locked or unavailable
- `TEMPLATE_MISSING_TOKEN` - Required template variable not found
- `PERMISSION_DENIED` - User denied notification permissions
### Event Logging Envelope
```ts
{
code: string, // Error code from taxonomy
slotId: string, // Affected slot
whenMs: number, // Scheduled time
attempt: number, // Retry attempt (1-based)
networkState: string, // 'online' | 'offline'
tzOffset: number, // Current timezone offset
appState: string, // 'foreground' | 'background' | 'killed'
timestamp: number // UTC timestamp
}
```
**Error Codes:** `FETCH_TIMEOUT`, `ETAG_NOT_MODIFIED`, `SCHEDULE_DENIED`,
`EXACT_ALARM_MISSING`, `STORAGE_BUSY`, `TEMPLATE_MISSING_TOKEN`, `PERMISSION_DENIED`.
### ACK Payload Format
```ts
{
slotId: string,
fireAt: number, // Scheduled time
deliveredAt: number, // Actual delivery time
deviceTz: string, // Device timezone
appVersion: string, // App version
buildId: string // Build identifier
}
```
**Event Envelope:** `code, slotId, whenMs, attempt, networkState, tzOffset,
appState, timestamp`.
- **Event queue (v1):** In-memory queue for `delivery`, `error`, `heartbeat` events. Background/native work **will enqueue**; foreground **will drain** and publish to the UI. **v2 will migrate** to SQLite-backed queue for persistence.
- **Callbacks (optional):** `ackDelivery`, `reportError`, `heartbeat` **will post** to server endpoints when configured.
- **Minimal metrics:** pending count, last fetch, last delivery, next occurrences.
**Implementation:** See Implementation document for complete error taxonomy,
event logging envelope, ACK payload format, and telemetry events.
---
## 13) Feature Flags & Config
### Feature Flags Table
| Flag | Default | Description | Location |
|------|---------|-------------|----------|
| `scheduler` | `'capacitor'` | Scheduler implementation | `notif_config` table |
| `mode` | `'auto'` | Online-first inside lead, else offline-first | `notif_config` table |
| `prefetchLeadMinutes` | `20` | Lead time for prefetch attempts | `notif_config` table |
| `ttlSeconds` | `86400` | Content staleness threshold (24h) | `notif_config` table |
| `iosCategoryIdentifier` | `'TS_DAILY'` | iOS notification category | `notif_config` table |
| `androidChannelId` | `'timesafari.daily'` | Android channel ID (never changes) | `notif_config` table |
**Key Flags:** `scheduler`, `mode`, `prefetchLeadMinutes`, `ttlSeconds`,
`iosCategoryIdentifier`, `androidChannelId`, `prefetchRunner`, `runnerRearm`.
**Storage:** Feature flags **will reside** in `notif_config` table as key-value pairs, separate from user settings.
**Storage:** Feature flags **will reside** in `notif_config` table as key-value
pairs, separate from user settings.
**Implementation:** See Implementation document for complete feature flags table
with defaults and descriptions.
---
## 14) Acceptance (Definition of Done) → Test Cases
### Explicit Test Checks
- **App killed → locals fire**: Configure slots at 8:00, 12:00, 18:00; kill app; verify notifications fire at each slot on iOS/Android
- **ETag 304 path**: Server returns 304 → keep previous content; locals fire with cached payload
- **ETag 200 path**: Server returns 200 → update content and re-arm locals with fresh payload
- **Offline + beyond TTL**: When offline and content > 24h old → skip notification (no "(cached)" suffix)
- **iOS pending cap**: Respect ~64 pending limit; cancel/re-arm as needed within rolling window
- **Exact-alarm denied**: Android permission absent → windowed schedule (±10m) activates; UI shows fallback hint
- **Permissions disabled** → we will record `SCHEDULE_DENIED` and refrain from queuing locals.
- **Window fallback** → when exact alarm is absent on Android, verify target fires within **±10m** of slot time (document as an E2E expectation).
- **Timezone change**: On TZ/DST change → recompute wall-clock times; cancel & re-arm all slots
- **App killed → locals fire**: Configure slots at 8:00, 12:00, 18:00; kill
app; verify notifications fire at each slot on iOS/Android
- **ETag 304 path**: Server returns 304 → keep previous content; locals fire
with cached payload
- **ETag 200 path**: Server returns 200 → update content and re-arm locals with
fresh payload
- **Offline + beyond TTL**: When offline and content > 24h old → skip notification
(no "(cached)" suffix)
- **iOS pending cap**: Respect ~64 pending limit; cancel/re-arm as needed within
rolling window
- **Exact-alarm denied**: Android permission absent → windowed schedule (±10m)
activates; UI shows fallback hint
- **Permissions disabled** → we will record `SCHEDULE_DENIED` and refrain from
queuing locals.
- **Window fallback** → when exact alarm is absent on Android, verify target
fires within **±10m** of slot time (document as an E2E expectation).
- **Timezone change**: On TZ/DST change → recompute wall-clock times; cancel &
re-arm all slots
- **Lead window respect**: No retries attempted once inside 20min lead window
- **Idempotency**: Multiple `runFullPipelineNow()` calls don't create duplicate scheduled deliveries
- **Idempotency**: Multiple `runFullPipelineNow()` calls don't create duplicate
scheduled deliveries
- **Cooldown guard**: `deliverStoredNow()` has 60s cooldown to prevent double-firing
### Electron-Specific Test Checks
- **Electron running (tray or window) → notifications fire** at configured slots using Electron `Notification`
- **Electron running (tray or window) → notifications fire** at configured slots
using Electron `Notification`
- **Electron not running →** no delivery (documented limitation for v1)
- **Start on Login enabled →** after reboot + login, orchestrator **will re-arm** slots and deliver
- **Start on Login enabled →** after reboot + login, orchestrator **will re-arm**
slots and deliver
- **Template limits honored** (Title ≤ 50, Body ≤ 200) on Electron notifications
- **SW scope** not used for Electron (click handlers are **web only**)
- **Windows appUserModelId** set correctly for toast attribution
- **macOS notification permission** requested on first use
### Timing-Verifiable Test Checks
- **iOS/Android (app killed):** locals will fire at their slots; no network
activity at delivery time.
- **iOS/Android (resume inside lead):** exactly **one** online-first attempt
occurs; if fetch completes within **12s** → content updated; otherwise offline
policy applies.
- **Android (no exact access):** observed delivery is within **±10 min** of slot
time.
- **Web push:** SW push event fetch runs once with **12s** timeout; if it times
out, the push still displays (from payload).
- **Electron (app running):** timer-based locals fire on time; on reboot with
**Start on Login**, orchestrator re-arms on first run.
- **TTL behavior:** offline & stale → **skip** (no notification posted).
- **ETag path:** with `304`, last payload remains; no duplicate scheduling rows
(unique index enforced).
- **Cooldown:** calling `deliverStoredNow` twice within **60s** for same slot
doesn't produce two notifications.
- **Closed app, armed earlier** → locals fire at slot; title/body match last
rendered content (proves "render at schedule time" + adapter API).
- **Closed app, timezone change before slot** → on next resume, app recomputes
and re-arms; already armed notifications will still fire on original wall-time
- **Mobile closed-app, no background network:** Arm at T–hours; kill app; verify
locals fire with last rendered text; confirm **no** network egress at delivery.
- **Web push as network scheduler:** Send push with empty payload → SW fetches
within 12s timeout → shows correct text; confirm behavior with browser closed.
- **Electron app not running:** No delivery; with **Start on Login**, after
reboot first run fetches and re-arms; subsequent slots fire.
- **Runner fires in background (Android/iOS):** With Runner enabled and app
backgrounded for ≥30 min, at least one prefetch **will** occur; content cache
**will** update; already-armed locals **will** still fire on time.
- **Runner re-arm (flagged):** If `runnerRearm=true` and Runner fires inside lead
with fresh content + within TTL, the system **will** cancel & re-arm the next
slot; delivered text **will** match fresh template.
---
## 15) Test Matrix (Essentials)
- **Android:** exact vs inexact branch, Doze/App Standby behavior, reboot/time change, permission denial path, deep‑link to exact‑alarm settings.
- **iOS:** BG fetch budget limits, pending cap windowing, local notification delivery with app terminated, category actions.
- **Web:** SW lifecycle, push delivery with app closed, click handling, no offline scheduling.
- **Cross‑cutting:** ETag/304 behavior, TTL policy, templating correctness, event queue drain, SQLite retention job.
- **Android:** exact vs inexact branch, Doze/App Standby behavior, reboot/time
change, permission denial path, deep‑link to exact‑alarm settings.
- **iOS:** BG fetch budget limits, pending cap windowing, local notification
delivery with app terminated, category actions.
- **Web:** SW lifecycle, push delivery with app closed, click handling, no
offline scheduling.
- **Cross‑cutting:** ETag/304 behavior, TTL policy, templating correctness, event
queue drain, SQLite retention job.
---
## 16) Migration & Rollout Notes
- We **will keep** existing web push flows intact.
- We **will introduce** the orchestrator behind a feature flag, initially with a small number of slots.
- We **will migrate** settings to accept multiple times per day.
- We **will document** platform caveats inside user‑visible settings (e.g., Android exact alarms, iOS cap).
- We **will keep** existing web push flows intact.
- We **will introduce** the orchestrator behind a feature flag, initially with
a small number of slots.
- We **will migrate** settings to accept multiple times per day.
- We **will document** platform caveats inside user‑visible settings (e.g.,
Android exact alarms, iOS cap).
---
## 17) Security & Privacy
- Tokens **will reside** in Keystore/Keychain (mobile) and **will be injected** at request time; they **will not** be stored in SQLite.
- Optionally, SQLCipher at rest for mobile; redaction of PII in logs; payload size caps.
- Tokens **will reside** in Keystore/Keychain (mobile) and **will be injected**
at request time; they **will not** be stored in SQLite.
- Optionally, SQLCipher at rest for mobile; redaction of PII in logs; payload
size caps.
- Content **will be** minimal (title/body); sensitive data **will not be** embedded.
---
## 18) Non‑Goals (Now)
- Complex action sets and rich media on locals (kept minimal).
- Delivery‑time mutation of local notifications on iOS (NSE is for remote).
- Complex action sets and rich media on locals (kept minimal).
- Delivery‑time mutation of local notifications on iOS (NSE is for remote).
- Full analytics pipeline (future enhancement).
---
@ -342,116 +473,66 @@ We **will deliver** desktop notifications while the Electron app is running. Tru
## 19) Cross-Doc Sync Hygiene
### Canonical Ownership
- **This document (Plan)**: Canonical for Goals, Tenets, Platform behaviors, Acceptance criteria, Test cases
- **Implementation document**: Canonical for API definitions, Database schemas, Adapter implementations, Code examples
- **This document (Plan)**: Canonical for Goals, Tenets, Platform behaviors,
Acceptance criteria, Test cases
- **Implementation document**: Canonical for API definitions, Database schemas,
Adapter implementations, Code examples
### PR Checklist
When changing notification system behavior, update both documents:
- [ ] **API changes**: Update types/interfaces in both Plan §4 and Implementation §3
- [ ] **Schema changes**: Update Plan §5 and Implementation §2
- [ ] **Schema changes**: Update Plan §5 and Implementation §2
- [ ] **Slot/TTL changes**: Update Plan §4 semantics and Implementation §6 logic
- [ ] **Template changes**: Update Plan §9 contract and Implementation examples
- [ ] **Error codes**: Update Plan §11 taxonomy and Implementation error handling
### Synchronization Points
- **API code blocks**: Must be identical between Plan §4 and Implementation §3 (Public API (Shared))
- **API code blocks**: Must be identical between Plan §4 and Implementation §3
(Public API (Shared))
- **Feature flags**: Must match between Plan §12 table and Implementation defaults
- **Test cases**: Plan §13 acceptance criteria must align with Implementation test examples
- **Slot/TTL/Lead policies**: Must be identical between Plan §4 policy and Implementation §3 policy
- **Test cases**: Plan §13 acceptance criteria must align with Implementation
test examples
- **Slot/TTL/Lead policies**: Must be identical between Plan §4 policy and
Implementation §3 policy
---
## 21) Privacy & Security Alignment
### Privacy-First Architecture
- **User-Controlled Visibility:** Notification preferences **will be** user-controlled with explicit opt-in/opt-out
- **Data Sovereignty:** All notification data **will reside** on user's device; no external tracking or analytics
- **Minimal Data Collection:** We **will collect** only essential data for notification delivery (slot times, content templates)
- **DID Integration:** Notifications **will be** associated with user's Decentralized Identifier (DID) for privacy-preserving identity
### Security Considerations
- **Content Encryption:** Sensitive notification content **will be** encrypted at rest using device keystore
- **Secure Transmission:** All API calls **will use** HTTPS with proper certificate validation
- **Input Validation:** All notification content **will be** validated and sanitized before storage
- **Access Control:** Notification settings **will be** protected by user authentication
### Compliance with TimeSafari Principles
- **Privacy-Preserving:** Follows TimeSafari's privacy-preserving claims architecture
- **User Agency:** Users maintain full control over their notification experience
- **Transparency:** Clear communication about what data is collected and how it's used
- **Minimal Footprint:** Notification system **will have** minimal impact on user privacy
---
## 23) Platform-Specific Implementation Details
### Web Platform (`VITE_PLATFORM=web`)
- **Database:** Uses Absurd SQL (SQLite via IndexedDB) via `WebPlatformService` with worker pattern
- **Notifications:** Web push notifications via Service Worker (minimal implementation)
- **Local Scheduling:** **Not supported** - web cannot schedule local notifications offline
- **API Integration:** Direct HTTP calls for content fetching
- **Storage:** Notification preferences stored in Absurd SQL database
- **Testing:** Playwright E2E tests run on web platform
### Capacitor Platform (`VITE_PLATFORM=capacitor`)
- **Database:** Uses native SQLite via `CapacitorPlatformService`
- **Notifications:** Local notifications via `@capacitor/local-notifications`
- **Local Scheduling:** **Fully supported** - OS-level notification scheduling
- **API Integration:** HTTP calls with mobile-optimized timeouts and retry logic
- **Storage:** Notification preferences stored in native SQLite database
- **Testing:** Playwright E2E tests run on mobile devices (Android/iOS)
### Electron Platform (`VITE_PLATFORM=electron`)
- **Database:** Uses native SQLite via `ElectronPlatformService` (extends CapacitorPlatformService)
- **Notifications:** OS-level notifications via Electron's notification API
- **Local Scheduling:** **Supported** - desktop OS notification scheduling
- **API Integration:** Same as Capacitor platform
- **Storage:** Same as Capacitor platform (via inherited service)
- **Testing:** Same as Capacitor platform
### Cross-Platform Considerations
- **Feature Detection:** Use `process.env.VITE_PLATFORM` for platform-specific behavior
- **Database Abstraction:** PlatformServiceMixin handles database differences transparently
- **API Consistency:** Same TypeScript API across all platforms
- **Fallback Behavior:** Web platform gracefully degrades to push-only notifications
## Sync Checklist
---
## 24) TimeSafari Architecture Compliance
### Design Pattern Adherence
- **Factory Pattern:** Notification service follows `PlatformServiceFactory` singleton pattern
- **Mixin Pattern:** Database access uses existing `PlatformServiceMixin` pattern
- **Migration Pattern:** Database changes follow existing `MIGRATIONS` array pattern
- **Error Handling:** Uses existing `handleApiError` from `src/services/api.ts`
- **Logging:** Uses existing logger from `src/utils/logger` with established patterns
- **Platform Detection:** Uses existing `Capacitor.isNativePlatform()` and `VITE_PLATFORM` patterns
### File Organization Compliance
- **Services:** Follows existing `src/services/` organization with factory and adapters
- **Database:** Extends existing `src/db-sql/migration.ts` and `src/db/tables/settings.ts`
- **Utils:** Extends existing `src/utils/PlatformServiceMixin.ts`
- **Main Entry:** Integrates with existing `src/main.capacitor.ts` initialization
- **Service Workers:** Follows existing `sw_scripts/` organization
### Type Safety Compliance
- **Settings Extension:** Follows existing Settings type extension pattern
- **Interface Definitions:** Uses existing TypeScript interface patterns
- **Error Types:** Follows existing error handling type patterns
- **Platform Types:** Uses existing platform detection type patterns
| Sync item | Plan | Impl | Status |
| ------------------------------ | --------------------- | --------------------- | ------ |
| Public API block identical | §4 | §3 | ✅ |
| `getState()` fields present | §4 | §8 Orchestrator | ✅ |
| Capacitor action handlers | §7 (iOS/Android note) | §9 Bootstrap | ✅ |
| Electron fetch prereq/polyfill | §7 | §9 Electron | ✅ |
| Android ±10m fallback | §7 | §7 SchedulerCapacitor | ✅ |
| Retention (no VACUUM v1) | §5 | `$pruneNotifData` | ✅ |
| Runner described as **opportunistic prefetch**, not scheduler | §7 | §9 | ✅ |
| Feature flag `prefetchRunner` (default `'none'`) | §13 | §15 | ✅ |
| Capabilities `networkWake: 'opportunistic' | 'none'` | §7 | Scheduler.capabilities | ✅ |
| Runner tick handler bounded to ≤12s | §7 | BackgroundRunnerPrefetch | ✅ |
| Optional `runnerRearm` flag & behavior | §7 | Orchestrator + Runner | ✅ |
---
## Sync Checklist
| Sync item | Plan | Impl | Status |
| ------------------------------ | --------------------- | --------------------- | --------- |
| Public API block identical | §4 | §3 | ✅ |
| `getState()` fields present | §4 | §8 Orchestrator | ✅ |
| Capacitor action handlers | §7 (iOS/Android note) | §9 Bootstrap | ✅ |
| Electron fetch prereq/polyfill | §7 | §9 Electron | ✅ |
| Android ±10m fallback | §7 | §7 SchedulerCapacitor | ✅ |
| Retention (no VACUUM v1) | §5 | `$pruneNotifData` | ✅ |
| Sync item | Plan | Impl | Status |
| ------------------------------ | --------------------- | --------------------- | ------ |
| Public API block identical | §4 | §3 | ✅ |
| `getState()` fields present | §4 | §8 Orchestrator | ✅ |
| Capacitor action handlers | §7 (iOS/Android note) | §9 Bootstrap | ✅ |
| Electron fetch prereq/polyfill | §7 | §9 Electron | ✅ |
| Android ±10m fallback | §7 | §7 SchedulerCapacitor | ✅ |
| Retention (no VACUUM v1) | §5 | `$pruneNotifData` | ✅ |
| Runner described as **opportunistic prefetch**, not scheduler | §7 | §9 | ✅ |
| Feature flag `prefetchRunner` (default `'none'`) | §13 | §15 | ✅ |
| Capabilities `networkWake: 'opportunistic' | 'none'` | §7 | Scheduler.capabilities | ✅ |
| Runner tick handler bounded to ≤12s | §7 | BackgroundRunnerPrefetch | ✅ |
| Optional `runnerRearm` flag & behavior | §7 | Orchestrator + Runner | ✅ |
---
*This strategic plan focuses on features and future‑tense deliverables, avoids implementation details, and preserves a clear path from the in‑app implementation (v1) to the native plugin (v2). For detailed implementation specifics, see `notification-system-implementation.md`.*
*This strategic plan focuses on features and future‑tense deliverables, avoids implementation details, and preserves a clear path from the in‑app orchestrator (v1) to native plugin (v2). For executive overview, see `notification-system-executive-summary.md`. For complete implementation details, see `notification-system-implementation.md`.*

5
doc/z-index-guide.md

@ -5,12 +5,15 @@
**Status**: 🎯 **ACTIVE** - Z-index layering standards
## Objective
Establish consistent z-index values across the TimeSafari application to ensure proper layering of UI elements.
## Result
This document defines the z-index hierarchy for all UI components.
## Use/Run
Reference these values when implementing new components or modifying existing ones to maintain consistent layering.
## Z-Index Hierarchy
@ -51,7 +54,7 @@ Reference these values when implementing new components or modifying existing on
## Collaboration Hooks
- **Reviewers**: Frontend team, UI/UX designers
- **Sign-off checklist**:
- **Sign-off checklist**:
- [ ] All new components follow z-index guidelines
- [ ] Existing components updated to use defined values
- [ ] Cross-browser testing completed

Loading…
Cancel
Save