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. 26
      .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. 22
      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. 669
      doc/notification-system-implementation.md
  16. 613
      doc/notification-system-plan.md
  17. 3
      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. Where to apply this knowledge next.
``` ```
- [ ] Integration tests - [ ] Integration tests
- [ ] E2E tests - [ ] E2E tests

26
.cursor/rules/harbor_pilot_universal.mdc

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

2
.cursor/rules/meta_bug_diagnosis.mdc

@ -82,6 +82,7 @@ common investigation pitfalls.
### **Safe Diagnosis Commands** ### **Safe Diagnosis Commands**
✅ **Safe to use during diagnosis:** ✅ **Safe to use during diagnosis:**
- `npm run lint-fix` - Syntax and style checking - `npm run lint-fix` - Syntax and style checking
- `npm run type-check` - TypeScript validation (if available) - `npm run type-check` - TypeScript validation (if available)
- `git status` - Version control status - `git status` - Version control status
@ -90,6 +91,7 @@ common investigation pitfalls.
- `grep_search` - Text pattern searching - `grep_search` - Text pattern searching
❌ **Never use during diagnosis:** ❌ **Never use during diagnosis:**
- `npm run build:web` - Blocks chat - `npm run build:web` - Blocks chat
- `npm run build:electron` - Blocks chat - `npm run build:electron` - Blocks chat
- `npm run build:capacitor` - 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:** **This meta-rule enforces current workflow mode constraints for all interactions:**
### **Current Workflow State** ### **Current Workflow State**
```json ```json
{ {
"workflowState": { "workflowState": {
@ -62,26 +63,31 @@ that are essential for all AI interactions.
### **Mode-Specific Enforcement** ### **Mode-Specific Enforcement**
**Diagnosis Mode (read_only):** **Diagnosis Mode (read_only):**
- ❌ **Forbidden**: File modification, code creation, build commands, git commits - ❌ **Forbidden**: File modification, code creation, build commands, git commits
- ✅ **Allowed**: File reading, code analysis, investigation, documentation - ✅ **Allowed**: File reading, code analysis, investigation, documentation
- **Response**: Guide user toward investigation and analysis, not implementation - **Response**: Guide user toward investigation and analysis, not implementation
**Fixing Mode (implementation):** **Fixing Mode (implementation):**
- ✅ **Allowed**: File modification, code creation, build commands, testing, git commits - ✅ **Allowed**: File modification, code creation, build commands, testing, git commits
- ❌ **Forbidden**: None (full implementation mode) - ❌ **Forbidden**: None (full implementation mode)
- **Response**: Proceed with implementation and testing - **Response**: Proceed with implementation and testing
**Planning Mode (design_only):** **Planning Mode (design_only):**
- ❌ **Forbidden**: Implementation, coding, building, deployment - ❌ **Forbidden**: Implementation, coding, building, deployment
- ✅ **Allowed**: Analysis, design, estimation, documentation, architecture - ✅ **Allowed**: Analysis, design, estimation, documentation, architecture
- **Response**: Focus on planning and design, not implementation - **Response**: Focus on planning and design, not implementation
**Research Mode (investigation):** **Research Mode (investigation):**
- ❌ **Forbidden**: File modification, implementation, deployment - ❌ **Forbidden**: File modification, implementation, deployment
- ✅ **Allowed**: Investigation, analysis, research, documentation - ✅ **Allowed**: Investigation, analysis, research, documentation
- **Response**: Focus on investigation and analysis - **Response**: Focus on investigation and analysis
**Documentation Mode (writing_only):** **Documentation Mode (writing_only):**
- ❌ **Forbidden**: Implementation, coding, building, deployment - ❌ **Forbidden**: Implementation, coding, building, deployment
- ✅ **Allowed**: Writing, editing, formatting, structuring, reviewing - ✅ **Allowed**: Writing, editing, formatting, structuring, reviewing
- **Response**: Focus on documentation creation and improvement - **Response**: Focus on documentation creation and improvement

9
.cursor/rules/meta_documentation.mdc

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

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

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

22
BUILDING.md

@ -93,6 +93,7 @@ The Build Architecture Guard protects your build system by enforcing documentati
#### Protected File Patterns #### Protected File Patterns
The guard monitors these sensitive paths: The guard monitors these sensitive paths:
- `vite.config.*` - Build configuration - `vite.config.*` - Build configuration
- `scripts/**` - Build and utility scripts - `scripts/**` - Build and utility scripts
- `electron/**` - Desktop application code - `electron/**` - Desktop application code
@ -132,6 +133,7 @@ npm run guard:setup
#### Troubleshooting #### Troubleshooting
If you encounter `mapfile: command not found` errors: If you encounter `mapfile: command not found` errors:
```bash ```bash
# Ensure script is executable # Ensure script is executable
chmod +x scripts/build-arch-guard.sh 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) 3. To test the production build locally, use `npm run build:web:serve` (builds then serves)
**Why Use `serve`?** **Why Use `serve`?**
- **Production Testing**: Test your optimized production build locally before deployment - **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`) - **SPA Routing Validation**: Verify deep linking and navigation work correctly (handles routes like `/discover`, `/account`)
- **Performance Testing**: Test the minified and optimized build locally - **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: The `serve` functionality provides a local HTTP server for testing production builds:
**What It Does:** **What It Does:**
1. **Builds** the application using Vite 1. **Builds** the application using Vite
2. **Serves** the built files from the `dist/` directory 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.) 3. **Handles SPA Routing** - serves `index.html` for all routes (fixes 404s on `/discover`, `/account`, etc.)
**Server Options:** **Server Options:**
- **Primary**: `npx serve -s dist -l 8080` (recommended - full SPA support) - **Primary**: `npx serve -s dist -l 8080` (recommended - full SPA support)
- **Fallback**: Python HTTP server (limited SPA routing support) - **Fallback**: Python HTTP server (limited SPA routing support)
**Use Cases:** **Use Cases:**
- Testing production builds before deployment - Testing production builds before deployment
- Validating SPA routing behavior - Validating SPA routing behavior
- Performance testing of optimized builds - Performance testing of optimized builds
@ -1257,11 +1263,13 @@ npm run assets:validate
##### What Gets Validated ##### What Gets Validated
**Source Assets (Required):** **Source Assets (Required):**
- `resources/icon.png` - App icon source - `resources/icon.png` - App icon source
- `resources/splash.png` - Splash screen source - `resources/splash.png` - Splash screen source
- `resources/splash_dark.png` - Dark mode splash source - `resources/splash_dark.png` - Dark mode splash source
**Android Resources (Generated):** **Android Resources (Generated):**
- `android/app/src/main/res/drawable/splash.png` - Splash screen drawable - `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.png` - App icons for all densities
- `android/app/src/main/res/mipmap-*/ic_launcher_round.png` - Round 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 ### 2025-08-21 - Cursor Rules Refactoring and Build System Updates
#### Package Dependencies Updated #### Package Dependencies Updated
- **Added**: `markdownlint-cli2` v0.18.1 - Modern markdown linting with improved performance - **Added**: `markdownlint-cli2` v0.18.1 - Modern markdown linting with improved performance
- **Added**: `@commitlint/cli` v18.6.1 - Conventional commit message validation - **Added**: `@commitlint/cli` v18.6.1 - Conventional commit message validation
- **Added**: `@commitlint/config-conventional` v18.6.2 - Conventional commit standards - **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 - **Updated**: `lint-staged` v15.2.2 - Pre-commit linting automation
#### Build Script Improvements #### Build Script Improvements
- **Markdown Linting**: Replaced custom markdown scripts with `markdownlint-cli2` - **Markdown Linting**: Replaced custom markdown scripts with `markdownlint-cli2`
- **Before**: `./scripts/fix-markdown.sh` and `./scripts/validate-markdown.sh` - **Before**: `./scripts/fix-markdown.sh` and `./scripts/validate-markdown.sh`
- **After**: `markdownlint-cli2 --fix` and `markdownlint-cli2` - **After**: `markdownlint-cli2 --fix` and `markdownlint-cli2`
- **Benefits**: Faster execution, better error reporting, modern markdown standards - **Benefits**: Faster execution, better error reporting, modern markdown standards
#### Lint-Staged Configuration Enhanced #### Lint-Staged Configuration Enhanced
- **Added**: Markdown file linting to pre-commit hooks - **Added**: Markdown file linting to pre-commit hooks
- **Pattern**: `*.{md,markdown,mdc}` files now automatically formatted - **Pattern**: `*.{md,markdown,mdc}` files now automatically formatted
- **Command**: `markdownlint-cli2 --fix` runs before each commit - **Command**: `markdownlint-cli2 --fix` runs before each commit
- **Coverage**: All markdown files including `.mdc` cursor rules - **Coverage**: All markdown files including `.mdc` cursor rules
#### Commit Message Standards #### Commit Message Standards
- **Added**: Conventional commit validation via commitlint - **Added**: Conventional commit validation via commitlint
- **Configuration**: Extends `@commitlint/config-conventional` - **Configuration**: Extends `@commitlint/config-conventional`
- **Enforcement**: Ensures consistent commit message format across the project - **Enforcement**: Ensures consistent commit message format across the project
#### Node.js Version Requirements #### Node.js Version Requirements
- **Updated**: Minimum Node.js version requirements for new dependencies - **Updated**: Minimum Node.js version requirements for new dependencies
- **markdownlint-cli2**: Requires Node.js >=20 - **markdownlint-cli2**: Requires Node.js >=20
- **Various utilities**: Require Node.js >=18 for modern ES features - **Various utilities**: Require Node.js >=18 for modern ES features
#### Build Process Impact #### Build Process Impact
- **No Breaking Changes**: All existing build commands continue to work - **No Breaking Changes**: All existing build commands continue to work
- **Improved Quality**: Better markdown formatting and commit message standards - **Improved Quality**: Better markdown formatting and commit message standards
- **Enhanced Automation**: More comprehensive pre-commit validation - **Enhanced Automation**: More comprehensive pre-commit validation
@ -2745,6 +2759,7 @@ configuration files in the repository.
### 2025-08-21 - Commitlint Configuration Refinement ### 2025-08-21 - Commitlint Configuration Refinement
#### Commit Message Validation Improvements #### Commit Message Validation Improvements
- **Modified**: Commitlint configuration moved from `package.json` to dedicated `commitlint.config.js` - **Modified**: Commitlint configuration moved from `package.json` to dedicated `commitlint.config.js`
- **Enhanced**: Strict validation rules downgraded from errors to warnings - **Enhanced**: Strict validation rules downgraded from errors to warnings
- **Before**: `subject-case` and `subject-full-stop` rules caused red error messages - **Before**: `subject-case` and `subject-full-stop` rules caused red error messages
@ -2752,6 +2767,7 @@ configuration files in the repository.
- **Benefit**: Eliminates confusing red error messages while maintaining commit quality guidance - **Benefit**: Eliminates confusing red error messages while maintaining commit quality guidance
#### Configuration Structure #### Configuration Structure
- **File**: `commitlint.config.js` - Dedicated commitlint configuration - **File**: `commitlint.config.js` - Dedicated commitlint configuration
- **Extends**: `@commitlint/config-conventional` - Standard conventional commit rules - **Extends**: `@commitlint/config-conventional` - Standard conventional commit rules
- **Custom Rules**: - **Custom Rules**:
@ -2762,6 +2778,7 @@ configuration files in the repository.
- Current: Problematic rules set to warning level (1) - Current: Problematic rules set to warning level (1)
#### User Experience Impact #### User Experience Impact
- **Before**: Red error messages on every push with strict commit rules - **Before**: Red error messages on every push with strict commit rules
- **After**: Yellow warning messages that provide guidance without disruption - **After**: Yellow warning messages that provide guidance without disruption
- **Workflow**: Commits and pushes continue to work while maintaining quality standards - **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 ### 2025-08-26 - Capacitor Plugin Additions
#### New Capacitor Plugins Added #### New Capacitor Plugins Added
- **Added**: `@capacitor/clipboard` v6.0.2 - Clipboard functionality for mobile platforms - **Added**: `@capacitor/clipboard` v6.0.2 - Clipboard functionality for mobile platforms
- **Purpose**: Enable copy/paste operations on mobile devices - **Purpose**: Enable copy/paste operations on mobile devices
- **Platforms**: iOS and Android - **Platforms**: iOS and Android
@ -2785,23 +2803,27 @@ configuration files in the repository.
- **Integration**: Automatically included in mobile builds - **Integration**: Automatically included in mobile builds
#### Android Build System Updates #### Android Build System Updates
- **Modified**: `android/capacitor.settings.gradle` - Added new plugin project includes - **Modified**: `android/capacitor.settings.gradle` - Added new plugin project includes
- **Added**: `:capacitor-clipboard` project directory mapping - **Added**: `:capacitor-clipboard` project directory mapping
- **Added**: `:capacitor-status-bar` project directory mapping - **Added**: `:capacitor-status-bar` project directory mapping
- **Impact**: New plugins now properly integrated into Android build process - **Impact**: New plugins now properly integrated into Android build process
#### Package Dependencies #### Package Dependencies
- **Updated**: `package.json` - Added new Capacitor plugin dependencies - **Updated**: `package.json` - Added new Capacitor plugin dependencies
- **Updated**: `package-lock.json` - Locked dependency versions for consistency - **Updated**: `package-lock.json` - Locked dependency versions for consistency
- **Version**: All new plugins use Capacitor 6.x compatible versions - **Version**: All new plugins use Capacitor 6.x compatible versions
#### Build Process Impact #### Build Process Impact
- **No Breaking Changes**: Existing build commands continue to work unchanged - **No Breaking Changes**: Existing build commands continue to work unchanged
- **Enhanced Mobile Features**: New clipboard and status bar capabilities available - **Enhanced Mobile Features**: New clipboard and status bar capabilities available
- **Automatic Integration**: Plugins automatically included in mobile builds - **Automatic Integration**: Plugins automatically included in mobile builds
- **Platform Support**: Both iOS and Android builds now include new functionality - **Platform Support**: Both iOS and Android builds now include new functionality
#### Testing Requirements #### Testing Requirements
- **Mobile Builds**: Verify new plugins integrate correctly in iOS and Android builds - **Mobile Builds**: Verify new plugins integrate correctly in iOS and Android builds
- **Functionality**: Test clipboard operations and status bar management on devices - **Functionality**: Test clipboard operations and status bar management on devices
- **Fallback**: Ensure graceful degradation when plugins are unavailable - **Fallback**: Ensure graceful degradation when plugins are unavailable

3
README-PR-TEMPLATE.md

@ -66,14 +66,17 @@ test-image.tar a1b2c3d4e5f6...
``` ```
### Docs ### Docs
- [x] **BUILDING.md** updated (sections): Docker deployment - [x] **BUILDING.md** updated (sections): Docker deployment
- [x] Troubleshooting updated: Added Docker troubleshooting section - [x] Troubleshooting updated: Added Docker troubleshooting section
### Rollback ### Rollback
- [x] Verified steps to restore previous behavior: - [x] Verified steps to restore previous behavior:
1. `git revert HEAD` 1. `git revert HEAD`
2. `docker rmi test-image` 2. `docker rmi test-image`
3. Restore previous BUILDING.md 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: 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 ```bash
npm install npm install
@ -90,6 +90,7 @@ VITE_LOG_LEVEL=debug npm run dev
See [Logging Configuration Guide](doc/logging-configuration.md) for complete details. See [Logging Configuration Guide](doc/logging-configuration.md) for complete details.
### Quick Usage ### Quick Usage
```bash ```bash
# Run the database clearing script # Run the database clearing script
./scripts/clear-database.sh ./scripts/clear-database.sh
@ -102,16 +103,19 @@ npm run build:web:dev # For Web
### What It Does ### What It Does
#### **Electron (Desktop App)** #### **Electron (Desktop App)**
- Automatically finds and clears the SQLite database files - Automatically finds and clears the SQLite database files
- Works on Linux, macOS, and Windows - Works on Linux, macOS, and Windows
- Clears all data and forces fresh migrations on next startup - Clears all data and forces fresh migrations on next startup
#### **Web Browser** #### **Web Browser**
- Provides instructions for using custom browser data directories - Provides instructions for using custom browser data directories
- Shows manual clearing via browser DevTools - Shows manual clearing via browser DevTools
- Ensures reliable database clearing without browser complications - Ensures reliable database clearing without browser complications
### Safety Features ### Safety Features
- ✅ **Interactive Script**: Guides you through the process - ✅ **Interactive Script**: Guides you through the process
- ✅ **Platform Detection**: Automatically detects your OS - ✅ **Platform Detection**: Automatically detects your OS
- ✅ **Clear Instructions**: Step-by-step guidance for each platform - ✅ **Clear Instructions**: Step-by-step guidance for each platform
@ -120,6 +124,7 @@ npm run build:web:dev # For Web
### Manual Commands (if needed) ### Manual Commands (if needed)
#### **Electron Database Location** #### **Electron Database Location**
```bash ```bash
# Linux # Linux
rm -rf ~/.config/TimeSafari/* rm -rf ~/.config/TimeSafari/*
@ -132,6 +137,7 @@ rmdir /s /q %APPDATA%\TimeSafari
``` ```
#### **Web Browser (Custom Data Directory)** #### **Web Browser (Custom Data Directory)**
```bash ```bash
# Create isolated browser profile # Create isolated browser profile
mkdir ~/timesafari-dev-data mkdir ~/timesafari-dev-data
@ -144,6 +150,7 @@ URL generation across all environments. This prevents localhost URLs from
appearing in shared links during development. appearing in shared links during development.
### Key Features ### Key Features
- ✅ **Production URLs for Sharing**: All copy link buttons use production domain - ✅ **Production URLs for Sharing**: All copy link buttons use production domain
- ✅ **Environment-Specific Internal URLs**: Internal operations use appropriate - ✅ **Environment-Specific Internal URLs**: Internal operations use appropriate
environment URLs environment URLs
@ -227,6 +234,7 @@ npm run test:prerequisites
- **Build failures**: Run `npm run check:dependencies` to diagnose environment issues - **Build failures**: Run `npm run check:dependencies` to diagnose environment issues
**Required Versions**: **Required Versions**:
- Node.js: 18+ (LTS recommended) - Node.js: 18+ (LTS recommended)
- npm: 8+ (comes with Node.js) - npm: 8+ (comes with Node.js)
- Platform-specific tools: Android Studio, Xcode (for mobile builds) - 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 ### 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. 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 ### Code Organization
The project uses a centralized approach to type definitions and interfaces: The project uses a centralized approach to type definitions and interfaces:
* `src/interfaces/` - Contains all TypeScript interfaces and type definitions - `src/interfaces/` - Contains all TypeScript interfaces and type definitions
* `deepLinks.ts` - Deep linking type system and Zod validation schemas - `deepLinks.ts` - Deep linking type system and Zod validation schemas
* `give.ts` - Give-related interfaces and type definitions - `give.ts` - Give-related interfaces and type definitions
* `claims.ts` - Claim-related interfaces and verifiable credentials - `claims.ts` - Claim-related interfaces and verifiable credentials
* `common.ts` - Shared interfaces and utility types - `common.ts` - Shared interfaces and utility types
* Other domain-specific interface files - Other domain-specific interface files
Key principles: Key principles:
- All interfaces and types are defined in the interfaces folder - All interfaces and types are defined in the interfaces folder
- Zod schemas are used for runtime validation and type generation - Zod schemas are used for runtime validation and type generation
- Domain-specific interfaces are separated into their own files - 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: The application uses a platform-agnostic database layer with Vue mixins for service access:
* `src/services/PlatformService.ts` - Database interface definition - `src/services/PlatformService.ts` - Database interface definition
* `src/services/PlatformServiceFactory.ts` - Platform-specific service factory - `src/services/PlatformServiceFactory.ts` - Platform-specific service factory
* `src/services/AbsurdSqlDatabaseService.ts` - SQLite implementation - `src/services/AbsurdSqlDatabaseService.ts` - SQLite implementation
* `src/utils/PlatformServiceMixin.ts` - Vue mixin for database access with caching - `src/utils/PlatformServiceMixin.ts` - Vue mixin for database access with caching
* `src/db/` - Legacy Dexie database (migration in progress) - `src/db/` - Legacy Dexie database (migration in progress)
**Development Guidelines**: **Development Guidelines**:
@ -316,11 +325,11 @@ timesafari/
Gifts make the world go 'round! Gifts make the world go 'round!
* [WebStorm by JetBrains](https://www.jetbrains.com/webstorm/) for the free open-source license - [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) - [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 - [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) - [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) - [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) - 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 - [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/) - 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. 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. Also, with sensitive data, the accounts info should be encrypted.
# Options # 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 # 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 # Current method calls

1
doc/README-BUILD-GUARD.md

@ -330,6 +330,7 @@ Track the effectiveness of your Build Architecture Guard:
## 📝 **Changelog** ## 📝 **Changelog**
### 2025-08-22 - Shell Compatibility Fix ### 2025-08-22 - Shell Compatibility Fix
- **Fixed**: Replaced `mapfile` command with portable alternative for cross-shell compatibility - **Fixed**: Replaced `mapfile` command with portable alternative for cross-shell compatibility
- **Impact**: Resolves "mapfile: command not found" errors in pre-commit hooks - **Impact**: Resolves "mapfile: command not found" errors in pre-commit hooks
- **Files**: `scripts/build-arch-guard.sh` - **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 ## Problem Solved
Previously, Android builds would fail with errors like: Previously, Android builds would fail with errors like:
``` ```
error: resource drawable/splash (aka app.timesafari.app:drawable/splash) not found. 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. error: resource mipmap/ic_launcher (aka app.timesafari.app:mipmap/ic_launcher) not found.
``` ```
This happened when: This happened when:
- Source assets existed but weren't generated into Android resources - Source assets existed but weren't generated into Android resources
- Android resource directories were missing - Android resource directories were missing
- Asset generation tools weren't run before building - Asset generation tools weren't run before building
@ -45,16 +47,19 @@ npm run build:android:studio
### What Gets Validated ### What Gets Validated
#### Source Assets (Required) #### Source Assets (Required)
- `resources/icon.png` - App icon source - `resources/icon.png` - App icon source
- `resources/splash.png` - Splash screen source - `resources/splash.png` - Splash screen source
- `resources/splash_dark.png` - Dark mode splash source - `resources/splash_dark.png` - Dark mode splash source
#### Android Resources (Generated) #### Android Resources (Generated)
- `android/app/src/main/res/drawable/splash.png` - Splash screen drawable - `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.png` - App icons for all densities
- `android/app/src/main/res/mipmap-*/ic_launcher_round.png` - Round app icons for all densities - `android/app/src/main/res/mipmap-*/ic_launcher_round.png` - Round app icons for all densities
### Density Levels Checked ### Density Levels Checked
- `mipmap-mdpi` (1x) - `mipmap-mdpi` (1x)
- `mipmap-hdpi` (1.5x) - `mipmap-hdpi` (1.5x)
- `mipmap-xhdpi` (2x) - `mipmap-xhdpi` (2x)
@ -64,6 +69,7 @@ npm run build:android:studio
## Usage ## Usage
### Automatic Validation (Recommended) ### Automatic Validation (Recommended)
The validation runs automatically during all Android builds: The validation runs automatically during all Android builds:
```bash ```bash
@ -78,6 +84,7 @@ npm run build:android:debug
``` ```
### Manual Validation ### Manual Validation
Run validation only to check/fix assets: Run validation only to check/fix assets:
```bash ```bash
@ -89,6 +96,7 @@ npm run assets:validate:android
``` ```
### Validation Only (No Regeneration) ### Validation Only (No Regeneration)
Check configuration without fixing: Check configuration without fixing:
```bash ```bash
@ -98,6 +106,7 @@ npm run assets:validate
## Error Handling ## Error Handling
### Missing Source Assets ### Missing Source Assets
If source assets are missing, the build fails with clear error messages: 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 ### Missing Generated Resources
If generated resources are missing, they're automatically regenerated: If generated resources are missing, they're automatically regenerated:
``` ```
@ -119,6 +129,7 @@ If generated resources are missing, they're automatically regenerated:
``` ```
### Generation Failure ### Generation Failure
If regeneration fails, helpful guidance is provided: If regeneration fails, helpful guidance is provided:
``` ```
@ -131,6 +142,7 @@ If regeneration fails, helpful guidance is provided:
## Integration Points ## Integration Points
### Build Script Integration ### Build Script Integration
The validation is integrated into the main build process: The validation is integrated into the main build process:
```bash ```bash
@ -143,6 +155,7 @@ validate_android_assets || {
``` ```
### NPM Scripts ### NPM Scripts
New npm scripts for asset management: New npm scripts for asset management:
```json ```json
@ -156,17 +169,20 @@ New npm scripts for asset management:
## Benefits ## Benefits
### For Developers ### For Developers
- **No More Build Failures**: Automatic detection and fixing of missing resources - **No More Build Failures**: Automatic detection and fixing of missing resources
- **Faster Development**: No need to manually run asset generation tools - **Faster Development**: No need to manually run asset generation tools
- **Clear Error Messages**: Helpful guidance when issues occur - **Clear Error Messages**: Helpful guidance when issues occur
- **Consistent Results**: Same validation on all development machines - **Consistent Results**: Same validation on all development machines
### For CI/CD ### For CI/CD
- **Reliable Builds**: Consistent asset validation across environments - **Reliable Builds**: Consistent asset validation across environments
- **Early Detection**: Catches issues before they reach production - **Early Detection**: Catches issues before they reach production
- **Automated Fixes**: Self-healing builds when possible - **Automated Fixes**: Self-healing builds when possible
### For Project Maintenance ### For Project Maintenance
- **Reduced Support**: Fewer "build doesn't work" issues - **Reduced Support**: Fewer "build doesn't work" issues
- **Documentation**: Clear requirements for required assets - **Documentation**: Clear requirements for required assets
- **Standardization**: Consistent asset structure across the project - **Standardization**: Consistent asset structure across the project
@ -176,21 +192,27 @@ New npm scripts for asset management:
### Common Issues ### Common Issues
#### "No assets found in the asset path" #### "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. This occurs when the `assets/` directory is empty. The validation system automatically copies source assets and regenerates them.
#### "Failed to generate Android assets" #### "Failed to generate Android assets"
Check that: Check that:
- Source assets exist in `resources/` - Source assets exist in `resources/`
- `@capacitor/assets` is installed - `@capacitor/assets` is installed
- You have write permissions to the Android directories - You have write permissions to the Android directories
#### "Asset generation completed but some resources are still missing" #### "Asset generation completed but some resources are still missing"
This indicates a problem with the asset generation tool. Try: This indicates a problem with the asset generation tool. Try:
1. Running `npm install` to ensure dependencies are up to date 1. Running `npm install` to ensure dependencies are up to date
2. Manually running `npx @capacitor/assets generate` 2. Manually running `npx @capacitor/assets generate`
3. Checking the asset generation logs for specific errors 3. Checking the asset generation logs for specific errors
### Manual Recovery ### Manual Recovery
If automatic regeneration fails, you can manually create the missing resources: If automatic regeneration fails, you can manually create the missing resources:
```bash ```bash
@ -213,12 +235,14 @@ rm assets/icon.png assets/splash.png assets/splash_dark.png
## Future Enhancements ## Future Enhancements
### Planned Improvements ### Planned Improvements
- **iOS Asset Validation**: Extend validation to iOS assets - **iOS Asset Validation**: Extend validation to iOS assets
- **Asset Quality Checks**: Validate image dimensions and formats - **Asset Quality Checks**: Validate image dimensions and formats
- **Performance Optimization**: Cache validation results - **Performance Optimization**: Cache validation results
- **CI/CD Integration**: Add validation to GitHub Actions - **CI/CD Integration**: Add validation to GitHub Actions
### Configuration Options ### Configuration Options
- **Custom Asset Paths**: Support for different asset directory structures - **Custom Asset Paths**: Support for different asset directory structures
- **Validation Rules**: Configurable validation requirements - **Validation Rules**: Configurable validation requirements
- **Skip Options**: Ability to skip validation for specific scenarios - **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** ### **Step 1: Always Start with Core Always-On**
**Every single interaction** starts with: **Every single interaction** starts with:
``` ```
meta_core_always_on.mdc 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: **Important**: Meta-rules represent **workflow phases**, not a rigid sequence. You can:
### **Jump Between Phases Freely** ### **Jump Between Phases Freely**
- **Start with diagnosis** if you already know the problem - **Start with diagnosis** if you already know the problem
- **Go back to research** if your fix reveals new issues - **Go back to research** if your fix reveals new issues
- **Switch to planning** mid-implementation if scope changes - **Switch to planning** mid-implementation if scope changes
- **Document at any phase** - not just at the end - **Document at any phase** - not just at the end
### **Mode Switching by Invoking Meta-Rules** ### **Mode Switching by Invoking Meta-Rules**
Each meta-rule invocation **automatically switches your workflow mode**: 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** ### **Phase Constraints, Not Sequence Constraints**
- **Within each phase**: Clear constraints on what you can/cannot do - **Within each phase**: Clear constraints on what you can/cannot do
- **Between phases**: Complete freedom to move as needed - **Between phases**: Complete freedom to move as needed
- **No forced order**: Choose the phase that matches your current need - **No forced order**: Choose the phase that matches your current need
### **Example of Flexible Workflow** ### **Example of Flexible Workflow**
``` ```
1. Start with @meta_research (investigation mode) 1. Start with @meta_research (investigation mode)
2. Jump to @meta_bug_diagnosis (diagnosis 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 **Scenario**: User reports that the contact list isn't loading properly
**Initial Meta-Rule Selection**: **Initial Meta-Rule Selection**:
``` ```
meta_core_always_on + meta_research + meta_bug_diagnosis meta_core_always_on + meta_research + meta_bug_diagnosis
``` ```
**What This Gives You**: **What This Gives You**:
- **Core Always-On**: Human competence focus, time standards, context - **Core Always-On**: Human competence focus, time standards, context
- **Research**: Systematic investigation methodology, evidence collection - **Research**: Systematic investigation methodology, evidence collection
- **Bug Diagnosis**: Defect analysis framework, root cause identification - **Bug Diagnosis**: Defect analysis framework, root cause identification
**Flexible Workflow**: **Flexible Workflow**:
1. Apply core always-on for foundation 1. Apply core always-on for foundation
2. Use research meta-rule for systematic investigation 2. Use research meta-rule for systematic investigation
3. Switch to bug diagnosis when you have enough evidence 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 **Scenario**: Building a new contact search feature
**Meta-Rule Selection**: **Meta-Rule Selection**:
``` ```
meta_core_always_on + meta_feature_planning + meta_feature_implementation meta_core_always_on + meta_feature_planning + meta_feature_implementation
``` ```
**What This Gives You**: **What This Gives You**:
- **Core Always-On**: Foundation principles and context - **Core Always-On**: Foundation principles and context
- **Feature Planning**: Requirements analysis, architecture planning - **Feature Planning**: Requirements analysis, architecture planning
- **Feature Implementation**: Development workflow, testing strategy - **Feature Implementation**: Development workflow, testing strategy
**Iterative Workflow**: **Iterative Workflow**:
1. Start with core always-on 1. Start with core always-on
2. Use feature planning for design and requirements 2. Use feature planning for design and requirements
3. Switch to feature implementation for coding and testing 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 **Scenario**: Writing a migration guide for the new database system
**Meta-Rule Selection**: **Meta-Rule Selection**:
``` ```
meta_core_always_on + meta_documentation meta_core_always_on + meta_documentation
``` ```
**What This Gives You**: **What This Gives You**:
- **Core Always-On**: Foundation and context - **Core Always-On**: Foundation and context
- **Documentation**: Educational focus, templates, quality standards - **Documentation**: Educational focus, templates, quality standards
**Parallel Workflow**: **Parallel Workflow**:
1. Apply core always-on for foundation 1. Apply core always-on for foundation
2. Use documentation meta-rule for educational content creation 2. Use documentation meta-rule for educational content creation
3. **Can research** while documenting if you need more information 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 ## Common Meta-Rule Combinations
### **Research + Diagnosis** ### **Research + Diagnosis**
``` ```
meta_core_always_on + meta_research + meta_bug_diagnosis meta_core_always_on + meta_research + meta_bug_diagnosis
``` ```
**Use for**: Complex bug investigations requiring systematic analysis **Use for**: Complex bug investigations requiring systematic analysis
### **Planning + Implementation** ### **Planning + Implementation**
``` ```
meta_core_always_on + meta_feature_planning + meta_feature_implementation meta_core_always_on + meta_feature_planning + meta_feature_implementation
``` ```
**Use for**: End-to-end feature development from concept to deployment **Use for**: End-to-end feature development from concept to deployment
### **Research + Planning** ### **Research + Planning**
``` ```
meta_core_always_on + meta_research + meta_feature_planning meta_core_always_on + meta_research + meta_feature_planning
``` ```
**Use for**: Feasibility research and solution design **Use for**: Feasibility research and solution design
### **Documentation + Context** ### **Documentation + Context**
``` ```
meta_core_always_on + meta_documentation + [context-specific] meta_core_always_on + meta_documentation + [context-specific]
``` ```
**Use for**: Creating comprehensive, educational documentation **Use for**: Creating comprehensive, educational documentation
## Best Practices ## 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.*

669
doc/notification-system-implementation.md

File diff suppressed because it is too large

613
doc/notification-system-plan.md

@ -4,31 +4,52 @@
**Date:** 2025-09-05T05:09Z (UTC) **Date:** 2025-09-05T05:09Z (UTC)
**Author:** Matthew Raymer **Author:** Matthew Raymer
**Scope:** v1 (in‑app orchestrator) now; path to v2 (native plugin) next **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. **Goal:** We **will deliver** 1..M local notifications/day with content
**prefetched** so messages **will display offline**. We **will support**
> **Implementation Details:** See `notification-system-implementation.md` for detailed code, database schemas, and integration specifics. online‑first (API→DB→Schedule) with offline‑first fallback. The system
> **Canonical Ownership:** This document owns Goals, Tenets, Platform behaviors, Acceptance criteria, and Test cases. **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 ## 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. - **v1 (In‑App Orchestrator):** We **will implement** multi‑daily local
- **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**. 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 ## 2) Design Tenets
- **Reliability:** OS‑level delivery once scheduled; no reliance on JS being alive at fire time. - **Reliability:** OS‑level delivery once scheduled; no reliance on JS being alive
- **Freshness:** Prefer online‑first within a short prefetch window; degrade gracefully to cached content with TTL. at fire time.
- **Extractable:** Clean interfaces (Scheduler, DataStore, Callbacks) so v2 **will swap** adapters without API changes. - **Freshness:** Prefer online‑first within a short prefetch window; degrade
- **Simplicity:** One‑shot notifications per slot; rolling window scheduling to respect platform caps. gracefully to cached content with TTL.
- **Observability:** Persist deliveries and errors; surface minimal metrics; enable ACKs. - **Extractable:** Clean interfaces (Scheduler, DataStore, Callbacks) so v2
- **Privacy-First:** Follow TimeSafari's privacy-preserving architecture; user-controlled visibility and data sovereignty. **will swap** adapters without API changes.
- **Community-Focused:** Enhance TimeSafari's mission of connecting people through gratitude, gifts, and collaborative projects. - **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,6 +67,8 @@ Adapters
├─ V1: SchedulerCapacitor, DataStoreSqlite, CallbacksHttp ├─ V1: SchedulerCapacitor, DataStoreSqlite, CallbacksHttp
└─ V2: SchedulerNative, DataStoreNativeSqlite, CallbacksNativeHttp └─ 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 Platform
├─ iOS/Android: LocalNotifications (+ native bridges later) ├─ iOS/Android: LocalNotifications (+ native bridges later)
├─ Web: Service Worker + Push (kept) ├─ Web: Service Worker + Push (kept)
@ -53,149 +76,229 @@ Platform
``` ```
**Execution modes (concise):** **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). - **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) ## 4) Public API (Shared by v1 & v2)
```ts **Core Types & Interface:** See Implementation document for complete API
export type NotificationTime = { hour: number; minute: number }; // local wall-clock definitions, type interfaces, and design decisions.
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.)
> **Storage semantics:** `'shared'` = app DB; `'private'` = plugin-owned/native
> DB (v2). (No functional difference in v1.)
> **Slot Identity & Scheduling Policy** > **Slot Identity & Scheduling Policy**
> • **SlotId** uses canonical `HHmm` and remains stable across timezone changes. > • **SlotId** uses canonical `HHmm` and remains stable across timezone
> • **Lead window:** default `prefetchLeadMinutes = 20`; no retries once inside the lead. > changes.
> • **TTL policy:** When offline and content is beyond TTL, **we will skip** the notification (no "(cached)" suffix). > • **Lead window:** default `prefetchLeadMinutes = 20`; no retries once inside
> • **Idempotency:** Duplicate "scheduled" deliveries are prevented by a unique index on `(slot_id, fire_at, status='scheduled')`. the lead.
> • **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. > • **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) ## 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 ## 6) Scheduling Policy & Slot Math
- **One‑shot per slot** per day (non‑repeating). - **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. - **Rolling window:** today's remaining slots; seed tomorrow where platform
- **TZ/DST safe:** We **will recompute** local wall‑times on app resume and whenever timezone/offset changes; then **reschedule**. limits allow.
- **Android exactness:** If exact alarms are unavailable or denied, we **will use** `setWindow` semantics via the scheduler adapter. - **TZ/DST safe:** We **will recompute** local wall‑times on app resume and
- **iOS pending cap:** We **will keep** pending locals within typical caps (~64) by limiting the window and canceling/re‑arming as needed. whenever timezone/offset changes; then **reschedule**.
- **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. - **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** **iOS**
- Local notifications **will** fire without background runtime once scheduled. NSE **will not** mutate locals; delivery-time enrichment requires remote push (future).
- 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 - **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)**. - **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.** - **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) - **Channel defaults**: ID `timesafari.daily`, name "TimeSafari Daily",
- Receivers for reboot/time change **will be handled** by v2 (plugin); in v1, re‑arming **will occur** on app start/resume. 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)**. - **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** **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. - Requires registered Service Worker + permission; can deliver with browser closed.
- 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). **Web will not offline-schedule**.
- **Note**: Service workers are **intentionally disabled** in Electron (`src/main.electron.ts`) and web uses VitePWA plugin for minimal implementation. - 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.
**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)** **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): 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 ## 8) Template Engine Contract
**Supported tokens:** `{{headline}}`, `{{summary}}`, `{{date}}` (YYYY-MM-DD), `{{time}}` (HH:MM). **Supported tokens:** `{{headline}}`, `{{summary}}`, `{{date}}` (YYYY-MM-DD),
`{{time}}` (HH:MM).
**Escaping:** HTML-escape all injected values. **Escaping:** HTML-escape all injected values.
**Limits:** Title ≤ 50 chars; Body ≤ 200 chars; truncate with ellipsis. **Limits:** Title ≤ 50 chars; Body ≤ 200 chars; truncate with ellipsis.
**Fallback:** Missing token → `"[Content]"`. **Fallback:** Missing token → `"[Content]"`.
**Mutation:** We **will** render templates **before** scheduling; no mutation at delivery time on iOS locals. **Mutation:** We **will** render templates **before** scheduling; no mutation at
delivery time on iOS locals.
## 9) Integration with Existing TimeSafari Infrastructure ## 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 **Database:** We **will integrate** with existing migration system in
**Settings:** We **will extend** existing Settings type in `src/db/tables/settings.ts` following the established type extension pattern `src/db-sql/migration.ts` following the established `MIGRATIONS` array pattern
**Platform Service:** We **will leverage** existing PlatformServiceMixin database utilities following the established mixin pattern **Settings:** We **will extend** existing Settings type in
**Service Factory:** We **will follow** the existing `PlatformServiceFactory` singleton pattern for notification service creation `src/db/tables/settings.ts` following the established type extension pattern
**Capacitor:** We **will integrate** with existing deep link system in `src/main.capacitor.ts` following the established initialization pattern **Platform Service:** We **will leverage** existing PlatformServiceMixin database
**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) utilities following the established mixin pattern
**API:** We **will use** existing error handling from `src/services/api.ts` following the established `handleApiError` pattern **Service Factory:** We **will follow** the existing `PlatformServiceFactory`
**Logging:** We **will use** existing logger from `src/utils/logger` following the established logging patterns singleton pattern for notification service creation
**Platform Detection:** We **will use** existing `process.env.VITE_PLATFORM` patterns (`web`, `capacitor`, `electron`) **Capacitor:** We **will integrate** with existing deep link system in
**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) `src/main.capacitor.ts` following the established initialization pattern
**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) **Service Worker:** We **will extend** existing service worker infrastructure
**Identity System:** We **will integrate** with existing `did:ethr:` (Ethereum-based DID) system for user context 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 **Testing:** We **will follow** Playwright E2E testing patterns established in TimeSafari
**Database Architecture:** We **will support** platform-specific database backends: **Database Architecture:** We **will support** platform-specific database backends:
- **Web**: Absurd SQL (SQLite via IndexedDB) via `WebPlatformService` with worker pattern - **Web**: Absurd SQL (SQLite via IndexedDB) via `WebPlatformService` with worker pattern
- **Capacitor**: Native SQLite via `CapacitorPlatformService` - **Capacitor**: Native SQLite via `CapacitorPlatformService`
- **Electron**: Native SQLite via `ElectronPlatformService` (extends CapacitorPlatformService) - **Electron**: Native SQLite via `ElectronPlatformService` (extends CapacitorPlatformService)
@ -204,129 +307,157 @@ We **will deliver** desktop notifications while the Electron app is running. Tru
## 10) Error Taxonomy & Telemetry ## 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 ## 11) Permission UX & Channels/Categories
- We **will request** notification permission **after** user intent (e.g., settings screen), not on first render. - We **will request** notification permission **after** user intent (e.g.,
- **Android:** We **will create** a stable channel ID (e.g., `timesafari.daily`) and **will set** importance appropriately. settings screen), not on first render.
- **iOS:** We **will register** categories for optional actions; grouping may use `threadIdentifier` per slot/day. - **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 ## 12) Eventing & Telemetry
### Error Taxonomy **Error Codes:** `FETCH_TIMEOUT`, `ETAG_NOT_MODIFIED`, `SCHEDULE_DENIED`,
**Finite error code set:** `EXACT_ALARM_MISSING`, `STORAGE_BUSY`, `TEMPLATE_MISSING_TOKEN`, `PERMISSION_DENIED`.
- `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
}
```
### ACK Payload Format **Event Envelope:** `code, slotId, whenMs, attempt, networkState, tzOffset,
```ts appState, timestamp`.
{
slotId: string,
fireAt: number, // Scheduled time
deliveredAt: number, // Actual delivery time
deviceTz: string, // Device timezone
appVersion: string, // App version
buildId: string // Build identifier
}
```
- **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. **Implementation:** See Implementation document for complete error taxonomy,
- **Callbacks (optional):** `ackDelivery`, `reportError`, `heartbeat` **will post** to server endpoints when configured. event logging envelope, ACK payload format, and telemetry events.
- **Minimal metrics:** pending count, last fetch, last delivery, next occurrences.
--- ---
## 13) Feature Flags & Config ## 13) Feature Flags & Config
### Feature Flags Table **Key Flags:** `scheduler`, `mode`, `prefetchLeadMinutes`, `ttlSeconds`,
| Flag | Default | Description | Location | `iosCategoryIdentifier`, `androidChannelId`, `prefetchRunner`, `runnerRearm`.
|------|---------|-------------|----------|
| `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 |
**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 ## 14) Acceptance (Definition of Done) → Test Cases
### Explicit Test Checks ### 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 - **App killed → locals fire**: Configure slots at 8:00, 12:00, 18:00; kill
- **ETag 200 path**: Server returns 200 → update content and re-arm locals with fresh payload app; verify notifications fire at each slot on iOS/Android
- **Offline + beyond TTL**: When offline and content > 24h old → skip notification (no "(cached)" suffix) - **ETag 304 path**: Server returns 304 → keep previous content; locals fire
- **iOS pending cap**: Respect ~64 pending limit; cancel/re-arm as needed within rolling window with cached payload
- **Exact-alarm denied**: Android permission absent → windowed schedule (±10m) activates; UI shows fallback hint - **ETag 200 path**: Server returns 200 → update content and re-arm locals with
- **Permissions disabled** → we will record `SCHEDULE_DENIED` and refrain from queuing locals. fresh payload
- **Window fallback** → when exact alarm is absent on Android, verify target fires within **±10m** of slot time (document as an E2E expectation). - **Offline + beyond TTL**: When offline and content > 24h old → skip notification
- **Timezone change**: On TZ/DST change → recompute wall-clock times; cancel & re-arm all slots (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 - **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 - **Cooldown guard**: `deliverStoredNow()` has 60s cooldown to prevent double-firing
### Electron-Specific Test Checks ### 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) - **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 - **Template limits honored** (Title ≤ 50, Body ≤ 200) on Electron notifications
- **SW scope** not used for Electron (click handlers are **web only**) - **SW scope** not used for Electron (click handlers are **web only**)
- **Windows appUserModelId** set correctly for toast attribution - **Windows appUserModelId** set correctly for toast attribution
- **macOS notification permission** requested on first use - **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) ## 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. - **Android:** exact vs inexact branch, Doze/App Standby behavior, reboot/time
- **iOS:** BG fetch budget limits, pending cap windowing, local notification delivery with app terminated, category actions. change, permission denial path, deep‑link to exact‑alarm settings.
- **Web:** SW lifecycle, push delivery with app closed, click handling, no offline scheduling. - **iOS:** BG fetch budget limits, pending cap windowing, local notification
- **Cross‑cutting:** ETag/304 behavior, TTL policy, templating correctness, event queue drain, SQLite retention job. 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 ## 16) Migration & Rollout Notes
- We **will keep** existing web push flows intact. - 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 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 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 document** platform caveats inside user‑visible settings (e.g.,
Android exact alarms, iOS cap).
--- ---
## 17) Security & Privacy ## 17) Security & Privacy
- Tokens **will reside** in Keystore/Keychain (mobile) and **will be injected** at request time; they **will not** be stored in SQLite. - Tokens **will reside** in Keystore/Keychain (mobile) and **will be injected**
- Optionally, SQLCipher at rest for mobile; redaction of PII in logs; payload size caps. 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. - Content **will be** minimal (title/body); sensitive data **will not be** embedded.
--- ---
@ -342,116 +473,66 @@ We **will deliver** desktop notifications while the Electron app is running. Tru
## 19) Cross-Doc Sync Hygiene ## 19) Cross-Doc Sync Hygiene
### Canonical Ownership ### 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 ### PR Checklist
When changing notification system behavior, update both documents: When changing notification system behavior, update both documents:
- [ ] **API changes**: Update types/interfaces in both Plan §4 and Implementation §3 - [ ] **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 - [ ] **Slot/TTL changes**: Update Plan §4 semantics and Implementation §6 logic
- [ ] **Template changes**: Update Plan §9 contract and Implementation examples - [ ] **Template changes**: Update Plan §9 contract and Implementation examples
- [ ] **Error codes**: Update Plan §11 taxonomy and Implementation error handling - [ ] **Error codes**: Update Plan §11 taxonomy and Implementation error handling
### Synchronization Points - **API code blocks**: Must be identical between Plan §4 and Implementation §3
- **API code blocks**: Must be identical between Plan §4 and Implementation §3 (Public API (Shared)) (Public API (Shared))
- **Feature flags**: Must match between Plan §12 table and Implementation defaults - **Feature flags**: Must match between Plan §12 table and Implementation defaults
- **Test cases**: Plan §13 acceptance criteria must align with Implementation test examples - **Test cases**: Plan §13 acceptance criteria must align with Implementation
- **Slot/TTL/Lead policies**: Must be identical between Plan §4 policy and Implementation §3 policy test examples
- **Slot/TTL/Lead policies**: Must be identical between Plan §4 policy and
Implementation §3 policy
--- ---
## 21) Privacy & Security Alignment ## Sync Checklist
### 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 item | Plan | Impl | Status |
## 24) TimeSafari Architecture Compliance | ------------------------------ | --------------------- | --------------------- | ------ |
| Public API block identical | §4 | §3 | ✅ |
### Design Pattern Adherence | `getState()` fields present | §4 | §8 Orchestrator | ✅ |
- **Factory Pattern:** Notification service follows `PlatformServiceFactory` singleton pattern | Capacitor action handlers | §7 (iOS/Android note) | §9 Bootstrap | ✅ |
- **Mixin Pattern:** Database access uses existing `PlatformServiceMixin` pattern | Electron fetch prereq/polyfill | §7 | §9 Electron | ✅ |
- **Migration Pattern:** Database changes follow existing `MIGRATIONS` array pattern | Android ±10m fallback | §7 | §7 SchedulerCapacitor | ✅ |
- **Error Handling:** Uses existing `handleApiError` from `src/services/api.ts` | Retention (no VACUUM v1) | §5 | `$pruneNotifData` | ✅ |
- **Logging:** Uses existing logger from `src/utils/logger` with established patterns | Runner described as **opportunistic prefetch**, not scheduler | §7 | §9 | ✅ |
- **Platform Detection:** Uses existing `Capacitor.isNativePlatform()` and `VITE_PLATFORM` patterns | Feature flag `prefetchRunner` (default `'none'`) | §13 | §15 | ✅ |
| Capabilities `networkWake: 'opportunistic' | 'none'` | §7 | Scheduler.capabilities | ✅ |
### File Organization Compliance | Runner tick handler bounded to ≤12s | §7 | BackgroundRunnerPrefetch | ✅ |
- **Services:** Follows existing `src/services/` organization with factory and adapters | Optional `runnerRearm` flag & behavior | §7 | Orchestrator + Runner | ✅ |
- **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 Checklist ## Sync Checklist
| Sync item | Plan | Impl | Status | | Sync item | Plan | Impl | Status |
| ------------------------------ | --------------------- | --------------------- | --------- | | ------------------------------ | --------------------- | --------------------- | ------ |
| Public API block identical | §4 | §3 | ✅ | | Public API block identical | §4 | §3 | ✅ |
| `getState()` fields present | §4 | §8 Orchestrator | ✅ | | `getState()` fields present | §4 | §8 Orchestrator | ✅ |
| Capacitor action handlers | §7 (iOS/Android note) | §9 Bootstrap | ✅ | | Capacitor action handlers | §7 (iOS/Android note) | §9 Bootstrap | ✅ |
| Electron fetch prereq/polyfill | §7 | §9 Electron | ✅ | | Electron fetch prereq/polyfill | §7 | §9 Electron | ✅ |
| Android ±10m fallback | §7 | §7 SchedulerCapacitor | ✅ | | Android ±10m fallback | §7 | §7 SchedulerCapacitor | ✅ |
| Retention (no VACUUM v1) | §5 | `$pruneNotifData` | ✅ | | 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`.*

3
doc/z-index-guide.md

@ -5,12 +5,15 @@
**Status**: 🎯 **ACTIVE** - Z-index layering standards **Status**: 🎯 **ACTIVE** - Z-index layering standards
## Objective ## Objective
Establish consistent z-index values across the TimeSafari application to ensure proper layering of UI elements. Establish consistent z-index values across the TimeSafari application to ensure proper layering of UI elements.
## Result ## Result
This document defines the z-index hierarchy for all UI components. This document defines the z-index hierarchy for all UI components.
## Use/Run ## Use/Run
Reference these values when implementing new components or modifying existing ones to maintain consistent layering. Reference these values when implementing new components or modifying existing ones to maintain consistent layering.
## Z-Index Hierarchy ## Z-Index Hierarchy

Loading…
Cancel
Save