111 changed files with 8529 additions and 3328 deletions
@ -1,316 +1,181 @@ |
|||||
--- |
|
||||
description: |
|
||||
globs: |
|
||||
alwaysApply: true |
|
||||
--- |
|
||||
# Time Safari Context |
# Time Safari Context |
||||
|
|
||||
|
**Author**: Matthew Raymer |
||||
|
**Date**: 2025-08-19 |
||||
|
**Status**: 🎯 **ACTIVE** - Core application context |
||||
|
|
||||
## Project Overview |
## Project Overview |
||||
|
|
||||
Time Safari is an application designed to foster community building through gifts, |
Time Safari is an application designed to foster community building through |
||||
gratitude, and collaborative projects. The app should make it extremely easy and |
gifts, gratitude, and collaborative projects. The app makes it easy and |
||||
intuitive for users of any age and capability to recognize contributions, build |
intuitive for users of any age and capability to recognize contributions, |
||||
trust networks, and organize collective action. It is built on services that |
build trust networks, and organize collective action. It is built on services |
||||
preserve privacy and data sovereignty. |
that preserve privacy and data sovereignty. |
||||
|
|
||||
The ultimate goals of Time Safari are two-fold: |
## Core Goals |
||||
|
|
||||
1. **Connect** Make it easy, rewarding, and non-threatening for people to |
1. **Connect**: Make it easy, rewarding, and non-threatening for people to |
||||
connect with others who have similar interests, and to initiate activities |
connect with others who have similar interests, and to initiate activities |
||||
together. This helps people accomplish and learn from other individuals in |
together. |
||||
less-structured environments; moreover, it helps them discover who they want |
|
||||
to continue to support and with whom they want to maintain relationships. |
|
||||
|
|
||||
2. **Reveal** Widely advertise the great support and rewards that are being |
2. **Reveal**: Widely advertise the great support and rewards that are being |
||||
given and accepted freely, especially non-monetary ones. Using visuals and text, |
given and accepted freely, especially non-monetary ones, showing the impact |
||||
display the kind of impact that gifts are making in the lives of others. Also |
gifts make in people's lives. |
||||
show useful and engaging reports of project statistics and personal accomplishments. |
|
||||
|
|
||||
|
## Technical Foundation |
||||
|
|
||||
## Core Approaches |
### Architecture |
||||
|
|
||||
Time Safari should help everyday users build meaningful connections and organize |
- **Privacy-preserving claims architecture** via endorser.ch |
||||
collective efforts by: |
- **Decentralized Identifiers (DIDs)**: User identities based on |
||||
|
public/private key pairs stored on devices |
||||
|
- **Cryptographic Verification**: All claims and confirmations are |
||||
|
cryptographically signed |
||||
|
- **User-Controlled Visibility**: Users explicitly control who can see their |
||||
|
identifiers and data |
||||
|
- **Cross-Platform**: Web (PWA), Mobile (Capacitor), Desktop (Electron) |
||||
|
|
||||
1. **Recognizing Contributions**: Creating permanent, verifiable records of gifts |
### Current Database State |
||||
and contributions people give to each other and their communities. |
|
||||
|
|
||||
2. **Facilitating Collaboration**: Making it ridiculously easy for people to ask |
- **Database**: SQLite via Absurd SQL (browser) and native SQLite |
||||
for or propose help on projects and interests that matter to them. |
(mobile/desktop) |
||||
|
- **Legacy Support**: IndexedDB (Dexie) for backward compatibility |
||||
|
- **Status**: Modern database architecture fully implemented |
||||
|
|
||||
3. **Building Trust Networks**: Enabling users to maintain their network and activity |
### Core Technologies |
||||
visibility. Developing reputation through verified contributions and references, |
|
||||
which can be selectively shown to others outside the network. |
|
||||
|
|
||||
4. **Preserving Privacy**: Ensuring personal identifiers are only shared with |
- **Frontend**: Vue 3 + TypeScript + vue-facing-decorator |
||||
explicitly authorized contacts, allowing private individuals including children |
- **Styling**: TailwindCSS |
||||
to participate safely. |
- **Build**: Vite with platform-specific configs |
||||
|
- **Testing**: Playwright E2E, Jest unit tests |
||||
|
- **Database**: SQLite (Absurd SQL in browser), IndexedDB (legacy) |
||||
|
- **State**: Pinia stores |
||||
|
- **Platform Services**: Abstracted behind interfaces with factory pattern |
||||
|
|
||||
5. **Engaging Content**: Displaying people's records in compelling stories, and |
## Development Principles |
||||
highlighting those projects that are lifting people's lives long-term, both in |
|
||||
physical support and in emotional-spiritual-creative thriving. |
|
||||
|
|
||||
|
### Code Organization |
||||
|
|
||||
## Technical Foundation |
- **Platform Services**: Abstract platform-specific code behind interfaces |
||||
|
- **Service Factory**: Use `PlatformServiceFactory` for platform selection |
||||
|
- **Type Safety**: Strict TypeScript, no `any` types, use type guards |
||||
|
- **Modern Architecture**: Use current platform service patterns |
||||
|
|
||||
This application is built on a privacy-preserving claims architecture (via |
### Architecture Patterns |
||||
endorser.ch) with these key characteristics: |
|
||||
|
|
||||
- **Decentralized Identifiers (DIDs)**: User identities are based on public/private |
- **Dependency Injection**: Services injected via mixins and factory pattern |
||||
key pairs stored on their devices |
- **Interface Segregation**: Small, focused interfaces over large ones |
||||
- **Cryptographic Verification**: All claims and confirmations are |
- **Composition over Inheritance**: Prefer mixins and composition |
||||
cryptographically signed |
- **Single Responsibility**: Each component/service has one clear purpose |
||||
- **User-Controlled Visibility**: Users explicitly control who can see their |
|
||||
identifiers and data |
|
||||
- **Merkle-Chained Claims**: Claims are cryptographically chained for verification |
|
||||
and integrity |
|
||||
- **Native and Web App**: Works on Capacitor (iOS, Android), Desktop (Electron |
|
||||
and CEFPython), and web browsers |
|
||||
|
|
||||
## User Journey |
### Testing Strategy |
||||
|
|
||||
The typical progression of usage follows these stages: |
- **E2E**: Playwright for critical user journeys |
||||
|
- **Unit**: Jest with F.I.R.S.T. principles |
||||
|
- **Platform Coverage**: Web + Capacitor (Pixel 5) in CI |
||||
|
- **Quality Assurance**: Comprehensive testing and validation |
||||
|
|
||||
1. **Gratitude & Recognition**: Users begin by expressing and recording gratitude |
## Current Development Focus |
||||
for gifts received, building a foundation of acknowledgment. |
|
||||
|
|
||||
2. **Project Proposals**: Users propose projects and ideas, reaching out to connect |
### Active Development |
||||
with others who share similar interests. |
|
||||
|
|
||||
3. **Action Triggers**: Offers of help serve as triggers and motivations to execute |
- **Feature Development**: Build new functionality using modern platform |
||||
proposed projects, moving from ideas to action. |
services |
||||
|
- **Performance Optimization**: Improve app performance and user experience |
||||
|
- **Platform Enhancement**: Leverage platform-specific capabilities |
||||
|
- **Code Quality**: Maintain high standards and best practices |
||||
|
|
||||
## Context for LLM Development |
### Development Metrics |
||||
|
|
||||
When developing new functionality for Time Safari, consider these design principles: |
- **Code Quality**: High standards maintained across all platforms |
||||
|
- **Performance**: Optimized for all target devices |
||||
|
- **Testing**: Comprehensive coverage maintained |
||||
|
- **User Experience**: Focus on intuitive, accessible interfaces |
||||
|
|
||||
1. **Accessibility First**: Features should be usable by non-technical users with |
## Platform-Specific Considerations |
||||
minimal learning curve. |
|
||||
|
|
||||
2. **Privacy by Design**: All features must respect user privacy and data sovereignty. |
### Web (PWA) |
||||
|
|
||||
3. **Progressive Enhancement**: Core functionality should work across all devices, |
- **QR Scanning**: WebInlineQRScanner |
||||
with richer experiences where supported. |
- **Deep Linking**: URL parameters |
||||
|
- **File System**: Limited browser APIs |
||||
|
- **Build**: `npm run build:web` (development build) |
||||
|
|
||||
4. **Voluntary Collaboration**: The system should enable but never coerce participation. |
### Mobile (Capacitor) |
||||
|
|
||||
5. **Trust Building**: Features should help build verifiable trust between users. |
- **QR Scanning**: @capacitor-mlkit/barcode-scanning |
||||
|
- **Deep Linking**: App URL open events |
||||
|
- **File System**: Capacitor Filesystem |
||||
|
- **Build**: `npm run build:capacitor` |
||||
|
|
||||
6. **Network Effects**: Consider how features scale as more users join the platform. |
### Desktop (Electron) |
||||
|
|
||||
7. **Low Resource Requirements**: The system should be lightweight enough to run |
- **File System**: Node.js fs |
||||
on inexpensive devices users already own. |
- **Build**: `npm run build:electron` |
||||
|
- **Distribution**: AppImage, DEB, DMG packages |
||||
|
|
||||
## Use Cases to Support |
## Development Workflow |
||||
|
|
||||
|
### Build Commands |
||||
|
|
||||
LLM development should focus on enhancing these key use cases: |
```bash |
||||
|
# Web (development) |
||||
|
npm run build:web |
||||
|
|
||||
1. **Community Building**: Tools that help people find others with shared |
# Mobile |
||||
interests and values. |
npm run build:capacitor |
||||
|
npm run build:native |
||||
|
|
||||
2. **Project Coordination**: Features that make it easy to propose collaborative |
# Desktop |
||||
projects and to submit suggestions and offers to existing ones. |
npm run build:electron |
||||
|
npm run build:electron:appimage |
||||
|
npm run build:electron:deb |
||||
|
npm run build:electron:dmg |
||||
|
``` |
||||
|
|
||||
3. **Reputation Building**: Methods for users to showcase their contributions |
### Testing Commands |
||||
and reliability, in contexts where they explicitly reveal that information. |
|
||||
|
|
||||
4. **Governance Experimentation**: Features that facilitate decision-making and |
```bash |
||||
collective governance. |
# Web E2E |
||||
|
npm run test:web |
||||
|
|
||||
## Constraints |
# Mobile |
||||
|
npm run test:mobile |
||||
When developing new features, be mindful of these constraints: |
npm run test:android |
||||
|
npm run test:ios |
||||
|
|
||||
|
# Type checking |
||||
|
npm run type-check |
||||
|
npm run lint-fix |
||||
|
``` |
||||
|
|
||||
|
## Key Constraints |
||||
|
|
||||
|
1. **Privacy First**: User identifiers remain private except when explicitly |
||||
|
shared |
||||
|
2. **Platform Compatibility**: Features must work across all target platforms |
||||
|
3. **Performance**: Must remain performant on older/simpler devices |
||||
|
4. **Modern Architecture**: New features should use current platform services |
||||
|
5. **Offline Capability**: Key functionality should work offline when feasible |
||||
|
|
||||
|
## Use Cases to Support |
||||
|
|
||||
|
1. **Community Building**: Tools for finding others with shared interests |
||||
|
2. **Project Coordination**: Easy proposal and collaboration on projects |
||||
|
3. **Reputation Building**: Showcasing contributions and reliability |
||||
|
4. **Governance**: Facilitating decision-making and collective governance |
||||
|
|
||||
|
## Resources |
||||
|
|
||||
|
- **Testing**: `docs/migration-testing/` |
||||
|
- **Architecture**: `docs/architecture-decisions.md` |
||||
|
- **Build Context**: `docs/build-modernization-context.md` |
||||
|
|
||||
|
--- |
||||
|
|
||||
1. **Privacy Preservation**: User identifiers must remain private except when |
## Status: Active application context |
||||
explicitly shared. |
|
||||
|
|
||||
2. **Platform Limitations**: Features must work within the constraints of the target |
- **Priority**: Critical |
||||
app platforms, while aiming to leverage the best platform technology available. |
- **Estimated Effort**: Ongoing reference |
||||
|
- **Dependencies**: Vue 3, TypeScript, SQLite, Capacitor, Electron |
||||
3. **Endorser API Limitations**: Backend features are constrained by the endorser.ch |
- **Stakeholders**: Development team, Product team |
||||
API capabilities. |
|
||||
|
|
||||
4. **Performance on Low-End Devices**: The application should remain performant |
|
||||
on older/simpler devices. |
|
||||
|
|
||||
5. **Offline-First When Possible**: Key functionality should work offline when feasible. |
|
||||
|
|
||||
## Project Technologies |
|
||||
|
|
||||
- Typescript using ES6 classes using vue-facing-decorator |
|
||||
- TailwindCSS |
|
||||
- Vite Build Tool |
|
||||
- Playwright E2E testing |
|
||||
- IndexDB |
|
||||
- Camera, Image uploads, QR Code reader, ... |
|
||||
|
|
||||
## Mobile Features |
|
||||
|
|
||||
- Deep Linking |
|
||||
- Local Notifications via a custom Capacitor plugin |
|
||||
|
|
||||
## Project Architecture |
|
||||
|
|
||||
- The application must work on web browser, PWA (Progressive Web Application), |
|
||||
desktop via Electron, and mobile via Capacitor |
|
||||
- Building for each platform is managed via Vite |
|
||||
|
|
||||
## Core Development Principles |
|
||||
|
|
||||
### DRY development |
|
||||
|
|
||||
- **Code Reuse** |
|
||||
- Extract common functionality into utility functions |
|
||||
- Create reusable components for UI patterns |
|
||||
- Implement service classes for shared business logic |
|
||||
- Use mixins for cross-cutting concerns |
|
||||
- Leverage TypeScript interfaces for shared type definitions |
|
||||
|
|
||||
- **Component Patterns** |
|
||||
- Create base components for common UI elements |
|
||||
- Implement higher-order components for shared behavior |
|
||||
- Use slot patterns for flexible component composition |
|
||||
- Create composable services for business logic |
|
||||
- Implement factory patterns for component creation |
|
||||
|
|
||||
- **State Management** |
|
||||
- Centralize state in Pinia stores |
|
||||
- Use computed properties for derived state |
|
||||
- Implement shared state selectors |
|
||||
- Create reusable state mutations |
|
||||
- Use action creators for common operations |
|
||||
|
|
||||
- **Error Handling** |
|
||||
- Implement centralized error handling |
|
||||
- Create reusable error components |
|
||||
- Use error boundary components |
|
||||
- Implement consistent error logging |
|
||||
- Create error type definitions |
|
||||
|
|
||||
- **Type Definitions** |
|
||||
- Create shared interfaces for common data structures |
|
||||
- Use type aliases for complex types |
|
||||
- Implement generic types for reusable components |
|
||||
- Create utility types for common patterns |
|
||||
- Use discriminated unions for state management |
|
||||
|
|
||||
- **API Integration** |
|
||||
- Create reusable API client classes |
|
||||
- Implement request/response interceptors |
|
||||
- Use consistent error handling patterns |
|
||||
- Create type-safe API endpoints |
|
||||
- Implement caching strategies |
|
||||
|
|
||||
- **Platform Services** |
|
||||
- Abstract platform-specific code behind interfaces |
|
||||
- Create platform-agnostic service layers |
|
||||
- Implement feature detection |
|
||||
- Use dependency injection for services |
|
||||
- Create service factories |
|
||||
|
|
||||
- **Testing** |
|
||||
- Create reusable test utilities |
|
||||
- Implement test factories |
|
||||
- Use shared test configurations |
|
||||
- Create reusable test helpers |
|
||||
- Implement consistent test patterns |
|
||||
- F.I.R.S.T. (for Unit Tests) |
|
||||
F – Fast |
|
||||
I – Independent |
|
||||
R – Repeatable |
|
||||
S – Self-validating |
|
||||
T – Timely |
|
||||
|
|
||||
### SOLID Principles |
|
||||
|
|
||||
- **Single Responsibility**: Each class/component should have only one reason to |
|
||||
change |
|
||||
- Components should focus on one specific feature (e.g., QR scanning, DID management) |
|
||||
- Services should handle one type of functionality (e.g., platform services, |
|
||||
crypto services) |
|
||||
- Utilities should provide focused helper functions |
|
||||
|
|
||||
- **Open/Closed**: Software entities should be open for extension but closed for |
|
||||
modification |
|
||||
- Use interfaces for service definitions |
|
||||
- Implement plugin architecture for platform-specific features |
|
||||
- Allow component behavior extension through props and events |
|
||||
|
|
||||
- **Liskov Substitution**: Objects should be replaceable with their subtypes |
|
||||
- Platform services should work consistently across web/mobile |
|
||||
- Authentication providers should be interchangeable |
|
||||
- Storage implementations should be swappable |
|
||||
|
|
||||
- **Interface Segregation**: Clients shouldn't depend on interfaces they don't use |
|
||||
- Break down large service interfaces into smaller, focused ones |
|
||||
- Component props should be minimal and purposeful |
|
||||
- Event emissions should be specific and targeted |
|
||||
|
|
||||
- **Dependency Inversion**: High-level modules shouldn't depend on low-level modules |
|
||||
- Use dependency injection for services |
|
||||
- Abstract platform-specific code behind interfaces |
|
||||
- Implement factory patterns for component creation |
|
||||
|
|
||||
### Law of Demeter |
|
||||
|
|
||||
- Components should only communicate with immediate dependencies |
|
||||
- Avoid chaining method calls (e.g., `this.service.getUser().getProfile().getName()`) |
|
||||
- Use mediator patterns for complex component interactions |
|
||||
- Implement facade patterns for subsystem access |
|
||||
- Keep component communication through defined events and props |
|
||||
|
|
||||
### Composition over Inheritance |
|
||||
|
|
||||
- Prefer building components through composition |
|
||||
- Use mixins for shared functionality |
|
||||
- Implement feature toggles through props |
|
||||
- Create higher-order components for common patterns |
|
||||
- Use service composition for complex features |
|
||||
|
|
||||
### Interface Segregation |
|
||||
|
|
||||
- Define clear interfaces for services |
|
||||
- Keep component APIs minimal and focused |
|
||||
- Split large interfaces into smaller, specific ones |
|
||||
- Use TypeScript interfaces for type definitions |
|
||||
- Implement role-based interfaces for different use cases |
|
||||
|
|
||||
### Fail Fast |
|
||||
|
|
||||
- Validate inputs early in the process |
|
||||
- Use TypeScript strict mode |
|
||||
- Implement comprehensive error handling |
|
||||
- Add runtime checks for critical operations |
|
||||
- Use assertions for development-time validation |
|
||||
|
|
||||
### Principle of Least Astonishment |
|
||||
|
|
||||
- Follow Vue.js conventions consistently |
|
||||
- Use familiar naming patterns |
|
||||
- Implement predictable component behaviors |
|
||||
- Maintain consistent error handling |
|
||||
- Keep UI interactions intuitive |
|
||||
|
|
||||
### Information Hiding |
|
||||
|
|
||||
- Encapsulate implementation details |
|
||||
- Use private class members |
|
||||
- Implement proper access modifiers |
|
||||
- Hide complex logic behind simple interfaces |
|
||||
- Use TypeScript's access modifiers effectively |
|
||||
|
|
||||
### Single Source of Truth |
|
||||
|
|
||||
- Use Pinia for state management |
|
||||
- Maintain one source for user data |
|
||||
- Centralize configuration management |
|
||||
- Use computed properties for derived state |
|
||||
- Implement proper state synchronization |
|
||||
|
|
||||
### Principle of Least Privilege |
|
||||
|
|
||||
- Implement proper access control |
|
||||
- Use minimal required permissions |
|
||||
- Follow privacy-by-design principles |
|
||||
- Restrict component access to necessary data |
|
||||
- Implement proper authentication/authorization |
|
||||
|
@ -0,0 +1,75 @@ |
|||||
|
# Architecture Rules Directory |
||||
|
|
||||
|
**Author**: Matthew Raymer |
||||
|
**Date**: 2025-08-20 |
||||
|
**Status**: 🎯 **ACTIVE** - Architecture protection guidelines |
||||
|
|
||||
|
## Overview |
||||
|
|
||||
|
This directory contains MDC (Model Directive Configuration) rules that protect |
||||
|
critical architectural components of the TimeSafari project. These rules ensure |
||||
|
that changes to system architecture follow proper review, testing, and |
||||
|
documentation procedures. |
||||
|
|
||||
|
## Available Rules |
||||
|
|
||||
|
### Build Architecture Guard (`build_architecture_guard.mdc`) |
||||
|
|
||||
|
Protects the multi-platform build system including: |
||||
|
|
||||
|
- Vite configuration files |
||||
|
- Build scripts and automation |
||||
|
- Platform-specific configurations (iOS, Android, Electron, Web) |
||||
|
- Docker and deployment infrastructure |
||||
|
- CI/CD pipeline components |
||||
|
|
||||
|
**When to use**: Any time you're modifying build scripts, configuration files, |
||||
|
or deployment processes. |
||||
|
|
||||
|
**Authorization levels**: |
||||
|
|
||||
|
- **Level 1**: Minor changes (review required) |
||||
|
- **Level 2**: Moderate changes (testing required) |
||||
|
- **Level 3**: Major changes (ADR required) |
||||
|
|
||||
|
## Usage Guidelines |
||||
|
|
||||
|
### For Developers |
||||
|
|
||||
|
1. **Check the rule**: Before making architectural changes, review the relevant |
||||
|
rule |
||||
|
2. **Follow the process**: Use the appropriate authorization level |
||||
|
3. **Complete validation**: Run through the required checklist |
||||
|
4. **Update documentation**: Keep BUILDING.md and related docs current |
||||
|
|
||||
|
### For Reviewers |
||||
|
|
||||
|
1. **Verify authorization**: Ensure changes match the required level |
||||
|
2. **Check testing**: Confirm appropriate testing has been completed |
||||
|
3. **Validate documentation**: Ensure BUILDING.md reflects changes |
||||
|
4. **Assess risk**: Consider impact on other platforms and systems |
||||
|
|
||||
|
## Integration with Other Rules |
||||
|
|
||||
|
- **Version Control**: Works with `workflow/version_control.mdc` |
||||
|
- **Research & Diagnostic**: Supports `research_diagnostic.mdc` for |
||||
|
investigations |
||||
|
- **Software Development**: Aligns with development best practices |
||||
|
- **Markdown Automation**: Integrates with `docs/markdown-automation.mdc` for |
||||
|
consistent documentation formatting |
||||
|
|
||||
|
## Emergency Procedures |
||||
|
|
||||
|
If architectural changes cause system failures: |
||||
|
|
||||
|
1. **Immediate rollback** to last known working state |
||||
|
2. **Document the failure** with full error details |
||||
|
3. **Investigate root cause** using diagnostic workflows |
||||
|
4. **Update procedures** to prevent future failures |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Status**: Active architecture protection |
||||
|
**Priority**: Critical |
||||
|
**Maintainer**: Development team |
||||
|
**Next Review**: 2025-09-20 |
@ -0,0 +1,295 @@ |
|||||
|
--- |
||||
|
description: Guards against unauthorized changes to the TimeSafari building |
||||
|
architecture |
||||
|
alwaysApply: false |
||||
|
--- |
||||
|
|
||||
|
# Build Architecture Guard Directive |
||||
|
|
||||
|
**Author**: Matthew Raymer |
||||
|
**Date**: 2025-08-20 |
||||
|
**Status**: 🎯 **ACTIVE** - Build system protection guidelines |
||||
|
|
||||
|
## Purpose |
||||
|
|
||||
|
Protect the TimeSafari building architecture from unauthorized changes that |
||||
|
could break the multi-platform build pipeline, deployment processes, or |
||||
|
development workflow. This directive ensures all build system modifications |
||||
|
follow proper review, testing, and documentation procedures. |
||||
|
|
||||
|
## Protected Architecture Components |
||||
|
|
||||
|
### Core Build Infrastructure |
||||
|
|
||||
|
- **Vite Configuration Files**: `vite.config.*.mts` files |
||||
|
- **Build Scripts**: All scripts in `scripts/` directory |
||||
|
- **Package Scripts**: `package.json` build-related scripts |
||||
|
- **Platform Configs**: `capacitor.config.ts`, `electron/`, `android/`, |
||||
|
`ios/` |
||||
|
- **Docker Configuration**: `Dockerfile`, `docker-compose.yml` |
||||
|
- **Environment Files**: `.env.*`, `.nvmrc`, `.node-version` |
||||
|
|
||||
|
### Critical Build Dependencies |
||||
|
|
||||
|
- **Build Tools**: Vite, Capacitor, Electron, Android SDK, Xcode |
||||
|
- **Asset Management**: `capacitor-assets.config.json`, asset scripts |
||||
|
- **Testing Infrastructure**: Playwright, Jest, mobile test scripts |
||||
|
- **CI/CD Pipeline**: GitHub Actions, build validation scripts |
||||
|
- **Service Worker Assembly**: `sw_scripts/`, `sw_combine.js`, WASM copy steps |
||||
|
|
||||
|
## Change Authorization Requirements |
||||
|
|
||||
|
### Level 1: Minor Changes (Requires Review) |
||||
|
|
||||
|
- Documentation updates to `BUILDING.md` |
||||
|
- Non-breaking script improvements |
||||
|
- Test additions or improvements |
||||
|
- Asset configuration updates |
||||
|
|
||||
|
**Process**: Code review + basic testing |
||||
|
|
||||
|
### Level 2: Moderate Changes (Requires Testing) |
||||
|
|
||||
|
- New build script additions |
||||
|
- Environment variable changes |
||||
|
- Dependency version updates |
||||
|
- Platform-specific optimizations |
||||
|
|
||||
|
**Process**: Code review + platform testing + documentation update |
||||
|
|
||||
|
### Level 3: Major Changes (Requires ADR) |
||||
|
|
||||
|
- Build system architecture changes |
||||
|
- New platform support |
||||
|
- Breaking changes to build scripts |
||||
|
- Major dependency migrations |
||||
|
|
||||
|
**Process**: ADR creation + comprehensive testing + team review |
||||
|
|
||||
|
## Prohibited Actions |
||||
|
|
||||
|
### ❌ Never Allow Without ADR |
||||
|
|
||||
|
- **Delete or rename** core build scripts |
||||
|
- **Modify** `package.json` build script names |
||||
|
- **Change** Vite configuration structure |
||||
|
- **Remove** platform-specific build targets |
||||
|
- **Alter** Docker build process |
||||
|
- **Modify** CI/CD pipeline without testing |
||||
|
|
||||
|
### ❌ Never Allow Without Testing |
||||
|
|
||||
|
- **Update** build dependencies |
||||
|
- **Change** environment configurations |
||||
|
- **Modify** asset generation scripts |
||||
|
- **Alter** test infrastructure |
||||
|
- **Update** platform SDK versions |
||||
|
|
||||
|
## Required Validation Checklist |
||||
|
|
||||
|
### Before Any Build System Change |
||||
|
|
||||
|
- [ ] **Impact Assessment**: Which platforms are affected? |
||||
|
- [ ] **Testing Plan**: How will this be tested across platforms? |
||||
|
- [ ] **Rollback Plan**: How can this be reverted if it breaks? |
||||
|
- [ ] **Documentation**: Will `BUILDING.md` need updates? |
||||
|
- [ ] **Dependencies**: Are all required tools available? |
||||
|
|
||||
|
### After Build System Change |
||||
|
|
||||
|
- [ ] **Web Platform**: Does `npm run build:web:dev` work? |
||||
|
- [ ] **Mobile Platforms**: Do iOS/Android builds succeed? |
||||
|
- [ ] **Desktop Platform**: Does Electron build and run? |
||||
|
- [ ] **Tests Pass**: Do all build-related tests pass? |
||||
|
- [ ] **Documentation Updated**: Is `BUILDING.md` current? |
||||
|
|
||||
|
## Specific Test Commands (Minimum Required) |
||||
|
|
||||
|
### Web Platform |
||||
|
|
||||
|
- **Development**: `npm run build:web:dev` - serve and load app |
||||
|
- **Production**: `npm run build:web:prod` - verify SW and WASM present |
||||
|
|
||||
|
### Mobile Platforms |
||||
|
|
||||
|
- **Android**: `npm run build:android:test` or `:prod` - confirm assets copied |
||||
|
- **iOS**: `npm run build:ios:test` or `:prod` - verify build succeeds |
||||
|
|
||||
|
### Desktop Platform |
||||
|
|
||||
|
- **Electron**: `npm run build:electron:dev` and packaging for target OS |
||||
|
- **Verify**: Single-instance behavior and app boot |
||||
|
|
||||
|
### Auto-run (if affected) |
||||
|
|
||||
|
- **Test Mode**: `npm run auto-run:test` and platform variants |
||||
|
- **Production Mode**: `npm run auto-run:prod` and platform variants |
||||
|
|
||||
|
### Clean and Rebuild |
||||
|
|
||||
|
- Run relevant `clean:*` scripts and ensure re-build works |
||||
|
|
||||
|
## Emergency Procedures |
||||
|
|
||||
|
### Build System Broken |
||||
|
|
||||
|
1. **Immediate**: Revert to last known working commit |
||||
|
2. **Investigation**: Create issue with full error details |
||||
|
3. **Testing**: Verify all platforms work after revert |
||||
|
4. **Documentation**: Update `BUILDING.md` with failure notes |
||||
|
|
||||
|
### Platform-Specific Failure |
||||
|
|
||||
|
1. **Isolate**: Identify which platform is affected |
||||
|
2. **Test Others**: Verify other platforms still work |
||||
|
3. **Rollback**: Revert platform-specific changes |
||||
|
4. **Investigation**: Debug in isolated environment |
||||
|
|
||||
|
## Integration Points |
||||
|
|
||||
|
### With Version Control |
||||
|
|
||||
|
- **Branch Protection**: Require reviews for build script changes |
||||
|
- **Commit Messages**: Must reference ADR for major changes |
||||
|
- **Testing**: All build changes must pass CI/CD pipeline |
||||
|
|
||||
|
### With Documentation |
||||
|
|
||||
|
- **BUILDING.md**: Must be updated for any script changes |
||||
|
- **README.md**: Must reflect new build requirements |
||||
|
- **CHANGELOG.md**: Must document breaking build changes |
||||
|
|
||||
|
### With Testing |
||||
|
|
||||
|
- **Pre-commit**: Run basic build validation |
||||
|
- **CI/CD**: Full platform build testing |
||||
|
- **Manual Testing**: Human verification of critical paths |
||||
|
|
||||
|
## Risk Matrix & Required Validation |
||||
|
|
||||
|
### Environment Handling |
||||
|
|
||||
|
- **Trigger**: Change to `.env.*` loading / variable names |
||||
|
- **Validation**: Prove `dev/test/prod` builds; show environment echo in logs |
||||
|
|
||||
|
### Script Flow |
||||
|
|
||||
|
- **Trigger**: Reorder steps (prebuild → build → package), new flags |
||||
|
- **Validation**: Dry-run + normal run, show exit codes & timing |
||||
|
|
||||
|
### Platform Packaging |
||||
|
|
||||
|
- **Trigger**: Electron NSIS/DMG/AppImage, Android/iOS bundle |
||||
|
- **Validation**: Produce installer/artifact and open it; verify single-instance, |
||||
|
icons, signing |
||||
|
|
||||
|
### Service Worker / WASM |
||||
|
|
||||
|
- **Trigger**: `sw_combine.js`, WASM copy path |
||||
|
- **Validation**: Verify combined SW exists and is injected; page loads offline; |
||||
|
WASM present |
||||
|
|
||||
|
### Docker |
||||
|
|
||||
|
- **Trigger**: New base image, build args |
||||
|
- **Validation**: Build image locally; run container; list produced `/dist` |
||||
|
|
||||
|
### Signing/Notarization |
||||
|
|
||||
|
- **Trigger**: Cert path/profiles |
||||
|
- **Validation**: Show signing logs + verify on target OS |
||||
|
|
||||
|
## PR Template (Paste into Description) |
||||
|
|
||||
|
- [ ] **Level**: L1 / L2 / L3 + justification |
||||
|
- [ ] **Files & platforms touched**: |
||||
|
- [ ] **Risk triggers & mitigations**: |
||||
|
- [ ] **Commands run (paste logs)**: |
||||
|
- [ ] **Artifacts (names + sha256)**: |
||||
|
- [ ] **Docs updated (sections/links)**: |
||||
|
- [ ] **Rollback steps verified**: |
||||
|
- [ ] **CI**: Jobs passing and artifacts uploaded |
||||
|
|
||||
|
## Rollback Playbook |
||||
|
|
||||
|
### Immediate Rollback |
||||
|
|
||||
|
1. `git revert` or `git reset --hard <prev>`; restore prior `scripts/` or config |
||||
|
files |
||||
|
2. Rebuild affected targets; verify old behavior returns |
||||
|
3. Post-mortem notes → update this guard and `BUILDING.md` if gaps found |
||||
|
|
||||
|
### Rollback Verification |
||||
|
|
||||
|
- **Web**: `npm run build:web:dev` and `npm run build:web:prod` |
||||
|
- **Mobile**: `npm run build:android:test` and `npm run build:ios:test` |
||||
|
- **Desktop**: `npm run build:electron:dev` and packaging commands |
||||
|
- **Clean**: Run relevant `clean:*` scripts and verify re-build works |
||||
|
|
||||
|
## ADR Trigger List |
||||
|
|
||||
|
Raise an ADR when you propose any of: |
||||
|
|
||||
|
- **New build stage** or reorder of canonical stages |
||||
|
- **Replacement of packager** / packaging format |
||||
|
- **New environment model** or secure secret handling scheme |
||||
|
- **New service worker assembly** strategy or cache policy |
||||
|
- **New Docker base** or multi-stage pipeline |
||||
|
- **Relocation of build outputs** or directory conventions |
||||
|
|
||||
|
**ADR must include**: motivation, alternatives, risks, validation plan, rollback, |
||||
|
doc diffs. |
||||
|
|
||||
|
## Competence Hooks |
||||
|
|
||||
|
### Why This Works |
||||
|
|
||||
|
- **Prevents Build Failures**: Catches issues before they reach production |
||||
|
- **Maintains Consistency**: Ensures all platforms build identically |
||||
|
- **Reduces Debugging Time**: Prevents build system regressions |
||||
|
|
||||
|
### Common Pitfalls |
||||
|
|
||||
|
- **Silent Failures**: Changes that work on one platform but break others |
||||
|
- **Dependency Conflicts**: Updates that create version incompatibilities |
||||
|
- **Documentation Drift**: Build scripts that don't match documentation |
||||
|
|
||||
|
### Next Skill Unlock |
||||
|
|
||||
|
- Learn to test build changes across all platforms simultaneously |
||||
|
|
||||
|
### Teach-back |
||||
|
|
||||
|
- "What three platforms must I test before committing a build script change?" |
||||
|
|
||||
|
## Collaboration Hooks |
||||
|
|
||||
|
### Team Review Requirements |
||||
|
|
||||
|
- **Platform Owners**: iOS, Android, Electron, Web specialists |
||||
|
- **DevOps**: CI/CD pipeline maintainers |
||||
|
- **QA**: Testing infrastructure owners |
||||
|
|
||||
|
### Discussion Prompts |
||||
|
|
||||
|
- "Which platforms will be affected by this build change?" |
||||
|
- "How can we test this change without breaking existing builds?" |
||||
|
- "What's our rollback plan if this change fails?" |
||||
|
|
||||
|
## Self-Check (Before Allowing Changes) |
||||
|
|
||||
|
- [ ] **Authorization Level**: Is this change appropriate for the level? |
||||
|
- [ ] **Testing Plan**: Is there a comprehensive testing strategy? |
||||
|
- [ ] **Documentation**: Will BUILDING.md be updated? |
||||
|
- [ ] **Rollback**: Is there a safe rollback mechanism? |
||||
|
- [ ] **Team Review**: Have appropriate stakeholders been consulted? |
||||
|
- [ ] **CI/CD**: Will this pass the build pipeline? |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Status**: Active build system protection |
||||
|
**Priority**: Critical |
||||
|
**Estimated Effort**: Ongoing vigilance |
||||
|
**Dependencies**: All build system components |
||||
|
**Stakeholders**: Development team, DevOps, Platform owners |
||||
|
**Next Review**: 2025-09-20 |
@ -1,32 +1,61 @@ |
|||||
--- |
--- |
||||
alwaysApply: true |
description: when doing anything with capacitor assets |
||||
|
alwaysApply: false |
||||
--- |
--- |
||||
# Asset Configuration Directive |
# Asset Configuration Directive |
||||
*Scope: Assets Only (icons, splashes, image pipelines) — not overall build orchestration* |
|
||||
|
**Author**: Matthew Raymer |
||||
|
**Date**: 2025-08-19 |
||||
|
**Status**: 🎯 **ACTIVE** - Asset management guidelines |
||||
|
|
||||
|
*Scope: Assets Only (icons, splashes, image pipelines) — not overall build |
||||
|
orchestration* |
||||
|
|
||||
## Intent |
## Intent |
||||
|
|
||||
- Version **asset configuration files** (optionally dev-time generated). |
- Version **asset configuration files** (optionally dev-time generated). |
||||
- **Do not** version platform asset outputs (Android/iOS/Electron); generate them **at build-time** with standard tools. |
- **Do not** version platform asset outputs (Android/iOS/Electron); generate |
||||
|
them **at build-time** with standard tools. |
||||
- Keep existing per-platform build scripts unchanged. |
- Keep existing per-platform build scripts unchanged. |
||||
|
|
||||
## Source of Truth |
## Source of Truth |
||||
|
|
||||
- **Preferred (Capacitor default):** `resources/` as the single master source. |
- **Preferred (Capacitor default):** `resources/` as the single master source. |
||||
- **Alternative:** `assets/` is acceptable **only** if `capacitor-assets` is explicitly configured to read from it. |
- **Alternative:** `assets/` is acceptable **only** if `capacitor-assets` is |
||||
- **Never** maintain both `resources/` and `assets/` as parallel sources. Migrate and delete the redundant folder. |
explicitly configured to read from it. |
||||
|
- **Never** maintain both `resources/` and `assets/` as parallel sources. |
||||
|
Migrate and delete the redundant folder. |
||||
|
|
||||
## Config Files |
## Config Files |
||||
|
|
||||
- Live under: `config/assets/` (committed). |
- Live under: `config/assets/` (committed). |
||||
- Examples: |
- Examples: |
||||
- `config/assets/capacitor-assets.config.json` (or the path the tool expects) |
- `config/assets/capacitor-assets.config.json` (or the path the tool |
||||
|
expects) |
||||
- `config/assets/android.assets.json` |
- `config/assets/android.assets.json` |
||||
- `config/assets/ios.assets.json` |
- `config/assets/ios.assets.json` |
||||
- `config/assets/common.assets.yaml` (optional shared layer) |
- `config/assets/common.assets.yaml` (optional shared layer) |
||||
- **Dev-time generation allowed** for these configs; **build-time generation is forbidden**. |
- **Dev-time generation allowed** for these configs; **build-time |
||||
|
generation is forbidden**. |
||||
|
|
||||
## Build-Time Behavior |
## Build-Time Behavior |
||||
|
|
||||
- Build generates platform assets (not configs) using the standard chain: |
- Build generates platform assets (not configs) using the standard chain: |
||||
```bash |
|
||||
npm run build:capacitor # web build via Vite (.mts) |
```bash |
||||
npx cap sync |
npm run build:capacitor # web build via Vite (.mts) |
||||
|
npx cap sync |
||||
|
npx capacitor-assets generate # produces platform assets; not committed |
||||
|
# then platform-specific build steps |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Status**: Active asset management directive |
||||
|
**Priority**: Medium |
||||
|
**Estimated Effort**: Ongoing reference |
||||
|
**Dependencies**: capacitor-assets toolchain |
||||
|
**Stakeholders**: Development team, Build team |
||||
|
|
||||
npx capacitor-assets generate # produces platform assets; not committed |
npx capacitor-assets generate # produces platform assets; not committed |
||||
# then platform-specific build steps |
# then platform-specific build steps |
||||
|
@ -0,0 +1,79 @@ |
|||||
|
--- |
||||
|
alwaysApply: true |
||||
|
--- |
||||
|
|
||||
|
# Markdown Automation System |
||||
|
|
||||
|
**Author**: Matthew Raymer |
||||
|
**Date**: 2025-08-20 |
||||
|
**Status**: 🎯 **ACTIVE** - Markdown formatting automation |
||||
|
|
||||
|
## Overview |
||||
|
|
||||
|
The Markdown Automation System ensures your markdown formatting standards are |
||||
|
followed **during content generation** by AI agents, not just applied after the |
||||
|
fact. |
||||
|
|
||||
|
## AI-First Approach |
||||
|
|
||||
|
### **Primary Method**: AI Agent Compliance |
||||
|
|
||||
|
- **AI agents follow markdown rules** while generating content |
||||
|
- **No post-generation fixes needed** - content is compliant from creation |
||||
|
- **Consistent formatting** across all generated documentation |
||||
|
|
||||
|
### **Secondary Method**: Automated Validation |
||||
|
|
||||
|
- **Pre-commit hooks** catch any remaining issues |
||||
|
- **GitHub Actions** validate formatting before merge |
||||
|
- **Manual tools** for bulk fixes when needed |
||||
|
|
||||
|
## How It Works |
||||
|
|
||||
|
### 1. **AI Agent Compliance** (Primary) |
||||
|
|
||||
|
- **When**: Every time AI generates markdown content |
||||
|
- **What**: AI follows markdown rules during generation |
||||
|
- **Result**: Content is properly formatted from creation |
||||
|
|
||||
|
### 2. **Pre-commit Hooks** (Backup) |
||||
|
|
||||
|
- **When**: Every time you commit |
||||
|
- **What**: Catches any remaining formatting issues |
||||
|
- **Result**: Clean, properly formatted markdown files |
||||
|
|
||||
|
### 3. **GitHub Actions** (Pre-merge) |
||||
|
|
||||
|
- **When**: Every pull request |
||||
|
- **What**: Validates markdown formatting across all files |
||||
|
- **Result**: Blocks merge if formatting issues exist |
||||
|
|
||||
|
## AI Agent Rules Integration |
||||
|
|
||||
|
The AI agent follows markdown rules defined in `.cursor/rules/docs/markdown.mdc`: |
||||
|
|
||||
|
- **alwaysApply: true** - Rules are enforced during generation |
||||
|
- **Line Length**: AI never generates lines > 80 characters |
||||
|
- **Blank Lines**: AI adds proper spacing around all elements |
||||
|
- **Structure**: AI uses established templates and patterns |
||||
|
|
||||
|
## Available Commands |
||||
|
|
||||
|
### NPM Scripts |
||||
|
|
||||
|
- **`npm run markdown:setup`** - Install the automation system |
||||
|
- **`npm run markdown:fix`** - Fix formatting in all markdown files |
||||
|
- **`npm run markdown:check`** - Validate formatting without fixing |
||||
|
|
||||
|
## Benefits |
||||
|
|
||||
|
- **No more manual fixes** - AI generates compliant content from start |
||||
|
- **Consistent style** - All files follow same standards |
||||
|
- **Faster development** - No need to fix formatting manually |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Status**: Active automation system |
||||
|
**Priority**: High |
||||
|
**Maintainer**: Development team |
||||
|
**Next Review**: 2025-09-20 |
@ -0,0 +1,206 @@ |
|||||
|
--- |
||||
|
alwaysApply: true |
||||
|
inherits: base_context.mdc |
||||
|
--- |
||||
|
```json |
||||
|
{ |
||||
|
"coaching_level": "standard", |
||||
|
"socratic_max_questions": 2, |
||||
|
"verbosity": "concise", |
||||
|
"timebox_minutes": 10, |
||||
|
"format_enforcement": "strict" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
# Harbor Pilot — Universal Directive for Human-Facing Technical Guides |
||||
|
|
||||
|
**Author**: System/Shared |
||||
|
**Date**: 2025-08-21 (UTC) |
||||
|
**Status**: 🚢 ACTIVE — General ruleset extending *Base Context — Human Competence First* |
||||
|
|
||||
|
> **Alignment with Base Context** |
||||
|
> - **Purpose fit**: Prioritizes human competence and collaboration while delivering reproducible artifacts. |
||||
|
> - **Output Contract**: This directive **adds universal constraints** for any technical topic while **inheriting** the Base Context contract sections. |
||||
|
> - **Toggles honored**: Uses the same toggle semantics; defaults above can be overridden by the caller. |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## Objective |
||||
|
Produce a **developer-grade, reproducible guide** for any technical topic that onboards a competent practitioner **without meta narration** and **with evidence-backed steps**. |
||||
|
|
||||
|
## Scope & Constraints |
||||
|
- **One Markdown document** as the deliverable. |
||||
|
- Use **absolute dates** in **UTC** (e.g., `2025-08-21T14:22Z`) — avoid “today/yesterday”. |
||||
|
- Include at least **one diagram** (Mermaid preferred). Choose the most fitting type: |
||||
|
- `sequenceDiagram` (protocols/flows), `flowchart`, `stateDiagram`, `gantt` (timelines), or `classDiagram` (schemas). |
||||
|
- Provide runnable examples where applicable: |
||||
|
- **APIs**: `curl` + one client library (e.g., `httpx` for Python). |
||||
|
- **CLIs**: literal command blocks and expected output snippets. |
||||
|
- **Code**: minimal, self-contained samples (language appropriate). |
||||
|
- Cite **evidence** for *Works/Doesn’t* items (timestamps, filenames, line numbers, IDs/status codes, or logs). |
||||
|
- If something is unknown, output `TODO:<missing>` — **never invent**. |
||||
|
|
||||
|
## Required Sections (extends Base Output Contract) |
||||
|
Follow this exact order **after** the Base Contract’s **Objective → Result → Use/Run** headers: |
||||
|
|
||||
|
1. **Context & Scope** |
||||
|
- Problem statement, audience, in/out-of-scope bullets. |
||||
|
2. **Artifacts & Links** |
||||
|
- Repos/PRs, design docs, datasets/HARs/pcaps, scripts/tools, dashboards. |
||||
|
3. **Environment & Preconditions** |
||||
|
- OS/runtime, versions/build IDs, services/endpoints/URLs, credentials/auth mode (describe acquisition, do not expose secrets). |
||||
|
4. **Architecture / Process Overview** |
||||
|
- Short prose + **one diagram** selected from the list above. |
||||
|
5. **Interfaces & Contracts (choose one)** |
||||
|
- **API-based**: Endpoint table (*Step, Method, Path/URL, Auth, Key Headers/Params, Sample Req/Resp ref*). |
||||
|
- **Data/Files**: I/O contract table (*Source, Format, Schema/Columns, Size, Validation rules*). |
||||
|
- **Systems/Hardware**: Interfaces table (*Port/Bus, Protocol, Voltage/Timing, Constraints*). |
||||
|
6. **Repro: End-to-End Procedure** |
||||
|
- Minimal copy-paste steps with code/commands and **expected outputs**. |
||||
|
7. **What Works (with Evidence)** |
||||
|
- Each item: **Time (UTC)** • **Artifact/Req IDs** • **Status/Result** • **Where to verify**. |
||||
|
8. **What Doesn’t (Evidence & Hypotheses)** |
||||
|
- Each failure: locus (file/endpoint/module), evidence snippet; short hypothesis and **next probe**. |
||||
|
9. **Risks, Limits, Assumptions** |
||||
|
- SLOs/limits, rate/size caps, security boundaries (CORS/CSRF/ACLs), retries/backoff/idempotency patterns. |
||||
|
10. **Next Steps (Owner • Exit Criteria • Target Date)** |
||||
|
- Actionable, assigned, and time-bound. |
||||
|
11. **References** |
||||
|
- Canonical docs, specs, tickets, prior analyses. |
||||
|
|
||||
|
> **Competence Hooks (per Base Context; keep lightweight):** |
||||
|
> - *Why this works* (≤3 bullets) — core invariants or guarantees. |
||||
|
> - *Common pitfalls* (≤3 bullets) — the traps we saw in evidence. |
||||
|
> - *Next skill unlock* (1 line) — the next capability to implement/learn. |
||||
|
> - *Teach-back* (1 line) — prompt the reader to restate the flow/architecture. |
||||
|
|
||||
|
> **Collaboration Hooks (per Base Context):** |
||||
|
> - Name reviewers for **Interfaces & Contracts** and the **diagram**. |
||||
|
> - Short **sign-off checklist** before merging/publishing the guide. |
||||
|
|
||||
|
## Do / Don’t (Base-aligned) |
||||
|
- **Do** quantify progress only against a defined scope with acceptance criteria. |
||||
|
- **Do** include minimal sample payloads/headers or I/O schemas; redact sensitive values. |
||||
|
- **Do** keep commentary lean; if timeboxed, move depth to **Deferred for depth**. |
||||
|
- **Don’t** use marketing language or meta narration (“Perfect!”, “tool called”, “new chat”). |
||||
|
- **Don’t** include IDE-specific chatter or internal rules unrelated to the task. |
||||
|
|
||||
|
## Validation Checklist (self-check before returning) |
||||
|
- [ ] All Required Sections present and ordered. |
||||
|
- [ ] Diagram compiles (basic Mermaid syntax) and fits the problem. |
||||
|
- [ ] If API-based, **Auth** and **Key Headers/Params** are listed for each endpoint. |
||||
|
- [ ] Repro section includes commands/code **and expected outputs**. |
||||
|
- [ ] Every Works/Doesn’t item has **UTC timestamp**, **status/result**, and **verifiable evidence**. |
||||
|
- [ ] Next Steps include **Owner**, **Exit Criteria**, **Target Date**. |
||||
|
- [ ] Unknowns are `TODO:<missing>` — no fabrication. |
||||
|
- [ ] Base **Output Contract** sections satisfied (Objective/Result/Use/Run/Competence/Collaboration/Assumptions/References). |
||||
|
|
||||
|
## Universal Template (fill-in) |
||||
|
```markdown |
||||
|
# <Title> — Working Notes (As of YYYY-MM-DDTHH:MMZ) |
||||
|
|
||||
|
## Objective |
||||
|
<one line> |
||||
|
|
||||
|
## Result |
||||
|
<link to the produced guide file or say “this document”> |
||||
|
|
||||
|
## Use/Run |
||||
|
<how to apply/test and where to run samples> |
||||
|
|
||||
|
## Context & Scope |
||||
|
- Audience: <role(s)> |
||||
|
- In scope: <bullets> |
||||
|
- Out of scope: <bullets> |
||||
|
|
||||
|
## Artifacts & Links |
||||
|
- Repo/PR: <link> |
||||
|
- Data/Logs: <paths or links> |
||||
|
- Scripts/Tools: <paths> |
||||
|
- Dashboards: <links> |
||||
|
|
||||
|
## Environment & Preconditions |
||||
|
- OS/Runtime: <details> |
||||
|
- Versions/Builds: <list> |
||||
|
- Services/Endpoints: <list> |
||||
|
- Auth mode: <Bearer/Session/Keys + how acquired> |
||||
|
|
||||
|
## Architecture / Process Overview |
||||
|
<short prose> |
||||
|
```mermaid |
||||
|
<one suitable diagram: sequenceDiagram | flowchart | stateDiagram | gantt | classDiagram> |
||||
|
``` |
||||
|
|
||||
|
## Interfaces & Contracts |
||||
|
### If API-based |
||||
|
| Step | Method | Path/URL | Auth | Key Headers/Params | Sample | |
||||
|
|---|---|---|---|---|---| |
||||
|
| <…> | <…> | <…> | <…> | <…> | below | |
||||
|
|
||||
|
### If Data/Files |
||||
|
| Source | Format | Schema/Columns | Size | Validation | |
||||
|
|---|---|---|---|---| |
||||
|
| <…> | <…> | <…> | <…> | <…> | |
||||
|
|
||||
|
### If Systems/Hardware |
||||
|
| Interface | Protocol | Timing/Voltage | Constraints | Notes | |
||||
|
|---|---|---|---|---| |
||||
|
| <…> | <…> | <…> | <…> | <…> | |
||||
|
|
||||
|
## Repro: End-to-End Procedure |
||||
|
```bash |
||||
|
# commands / curl examples (redacted where necessary) |
||||
|
``` |
||||
|
```python |
||||
|
# minimal client library example (language appropriate) |
||||
|
``` |
||||
|
> Expected output: <snippet/checks> |
||||
|
|
||||
|
## What Works (Evidence) |
||||
|
- ✅ <short statement> |
||||
|
- **Time**: <YYYY-MM-DDTHH:MMZ> |
||||
|
- **Evidence**: file/line/log or request id/status |
||||
|
- **Verify at**: <where> |
||||
|
|
||||
|
## What Doesn’t (Evidence & Hypotheses) |
||||
|
- ❌ <short failure> at `<component/endpoint/file>` |
||||
|
- **Time**: <YYYY-MM-DDTHH:MMZ> |
||||
|
- **Evidence**: <snippet/id/status> |
||||
|
- **Hypothesis**: <short> |
||||
|
- **Next probe**: <short> |
||||
|
|
||||
|
## Risks, Limits, Assumptions |
||||
|
<bullets: limits, security boundaries, retries/backoff, idempotency, SLOs> |
||||
|
|
||||
|
## Next Steps |
||||
|
| Owner | Task | Exit Criteria | Target Date (UTC) | |
||||
|
|---|---|---|---| |
||||
|
| <name> | <action> | <measurable outcome> | <YYYY-MM-DD> | |
||||
|
|
||||
|
## References |
||||
|
<links/titles> |
||||
|
|
||||
|
## Competence Hooks |
||||
|
- *Why this works*: <≤3 bullets> |
||||
|
- *Common pitfalls*: <≤3 bullets> |
||||
|
- *Next skill unlock*: <1 line> |
||||
|
- *Teach-back*: <1 line> |
||||
|
|
||||
|
## Collaboration Hooks |
||||
|
- Reviewers: <names/roles> |
||||
|
- Sign-off checklist: <≤5 checks> |
||||
|
|
||||
|
## Assumptions & Limits |
||||
|
<bullets> |
||||
|
|
||||
|
## Deferred for depth |
||||
|
<park deeper material here to respect timeboxing> |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Notes for Implementers:** |
||||
|
- Respect Base *Do-Not* (no filler, no invented facts, no censorship). |
||||
|
- Prefer clarity over completeness when timeboxed; capture unknowns explicitly. |
||||
|
- Apply historical comment management rules (see `.cursor/rules/historical_comment_management.mdc`) |
||||
|
- Apply realistic time estimation rules (see `.cursor/rules/realistic_time_estimation.mdc`) |
@ -0,0 +1,236 @@ |
|||||
|
--- |
||||
|
description: when comments are generated by the model |
||||
|
alwaysApply: false |
||||
|
--- |
||||
|
# Historical Comment Management — Harbor Pilot Directive |
||||
|
|
||||
|
> **Agent role**: When encountering historical comments about removed methods, deprecated patterns, or architectural changes, apply these guidelines to maintain code clarity and developer guidance. |
||||
|
|
||||
|
## 🎯 Purpose |
||||
|
|
||||
|
Historical comments should either be **removed entirely** or **transformed into actionable guidance** for future developers. Avoid keeping comments that merely state what was removed without explaining why or what to do instead. |
||||
|
|
||||
|
## 📋 Decision Framework |
||||
|
|
||||
|
### Remove Historical Comments When: |
||||
|
- **Obsolete Information**: Comment describes functionality that no longer exists |
||||
|
- **No Action Required**: Comment doesn't help future developers make decisions |
||||
|
- **Outdated Context**: Comment refers to old patterns that are no longer relevant |
||||
|
- **Self-Evident**: The current code clearly shows the current approach |
||||
|
|
||||
|
### Transform Historical Comments When: |
||||
|
- **Architectural Context**: The change represents a significant pattern shift |
||||
|
- **Migration Guidance**: Future developers might need to understand the evolution |
||||
|
- **Decision Rationale**: The "why" behind the change is still relevant |
||||
|
- **Alternative Approaches**: The comment can guide future implementation choices |
||||
|
|
||||
|
## 🔄 Transformation Patterns |
||||
|
|
||||
|
### 1. From Removal Notice to Migration Note |
||||
|
```typescript |
||||
|
// ❌ REMOVE THIS |
||||
|
// turnOffNotifyingFlags method removed - notification state is now managed by NotificationSection component |
||||
|
|
||||
|
// ✅ TRANSFORM TO THIS |
||||
|
// Note: Notification state management has been migrated to NotificationSection component |
||||
|
// which handles its own lifecycle and persistence via PlatformServiceMixin |
||||
|
``` |
||||
|
|
||||
|
### 2. From Deprecation Notice to Implementation Guide |
||||
|
```typescript |
||||
|
// ❌ REMOVE THIS |
||||
|
// This will be handled by the NewComponent now |
||||
|
// No need to call oldMethod() as it's no longer needed |
||||
|
|
||||
|
// ✅ TRANSFORM TO THIS |
||||
|
// Note: This functionality has been migrated to NewComponent |
||||
|
// which provides better separation of concerns and testability |
||||
|
``` |
||||
|
|
||||
|
### 3. From Historical Note to Architectural Context |
||||
|
```typescript |
||||
|
// ❌ REMOVE THIS |
||||
|
// Old approach: used direct database calls |
||||
|
// New approach: uses service layer |
||||
|
|
||||
|
// ✅ TRANSFORM TO THIS |
||||
|
// Note: Database access has been abstracted through service layer |
||||
|
// for better testability and platform independence |
||||
|
``` |
||||
|
|
||||
|
## 🚫 Anti-Patterns to Remove |
||||
|
|
||||
|
- Comments that only state what was removed |
||||
|
- Comments that don't explain the current approach |
||||
|
- Comments that reference non-existent methods |
||||
|
- Comments that are self-evident from the code |
||||
|
- Comments that don't help future decision-making |
||||
|
|
||||
|
## ✅ Best Practices |
||||
|
|
||||
|
### When Keeping Historical Context: |
||||
|
1. **Explain the "Why"**: Why was the change made? |
||||
|
2. **Describe the "What"**: What is the current approach? |
||||
|
3. **Provide Context**: When might this information be useful? |
||||
|
4. **Use Actionable Language**: Guide future decisions, not just document history |
||||
|
|
||||
|
### When Removing Historical Context: |
||||
|
1. **Verify Obsoleteness**: Ensure the information is truly outdated |
||||
|
2. **Check for Dependencies**: Ensure no other code references the old approach |
||||
|
3. **Update Related Docs**: If removing from code, consider adding to documentation |
||||
|
4. **Preserve in Git History**: The change is preserved in version control |
||||
|
|
||||
|
## 🔍 Implementation Checklist |
||||
|
|
||||
|
- [ ] Identify historical comments about removed/deprecated functionality |
||||
|
- [ ] Determine if comment provides actionable guidance |
||||
|
- [ ] Transform useful comments into migration notes or architectural context |
||||
|
- [ ] Remove comments that are purely historical without guidance value |
||||
|
- [ ] Ensure remaining comments explain current approach and rationale |
||||
|
- [ ] Update related documentation if significant context is removed |
||||
|
|
||||
|
## 📚 Examples |
||||
|
|
||||
|
### Good Historical Comment (Keep & Transform) |
||||
|
```typescript |
||||
|
// Note: Database access has been migrated from direct IndexedDB calls to PlatformServiceMixin |
||||
|
// This provides better platform abstraction and consistent error handling across web/mobile/desktop |
||||
|
// When adding new database operations, use this.$getContact(), this.$saveSettings(), etc. |
||||
|
``` |
||||
|
|
||||
|
### Bad Historical Comment (Remove) |
||||
|
```typescript |
||||
|
// Old method getContactFromDB() removed - now handled by PlatformServiceMixin |
||||
|
// No need to call the old method anymore |
||||
|
``` |
||||
|
|
||||
|
## 🎯 Integration with Harbor Pilot |
||||
|
|
||||
|
This rule works in conjunction with: |
||||
|
- **Component Creation Ideals**: Maintains architectural consistency |
||||
|
- **Migration Patterns**: Documents evolution of patterns |
||||
|
- **Code Review Guidelines**: Ensures comments provide value |
||||
|
|
||||
|
## 📝 Version History |
||||
|
|
||||
|
### v1.0.0 (2025-08-21) |
||||
|
- Initial creation based on notification system cleanup |
||||
|
- Established decision framework for historical comment management |
||||
|
- Added transformation patterns and anti-patterns |
||||
|
- Integrated with existing Harbor Pilot architecture rules |
||||
|
# Historical Comment Management — Harbor Pilot Directive |
||||
|
|
||||
|
> **Agent role**: When encountering historical comments about removed methods, deprecated patterns, or architectural changes, apply these guidelines to maintain code clarity and developer guidance. |
||||
|
|
||||
|
## 🎯 Purpose |
||||
|
|
||||
|
Historical comments should either be **removed entirely** or **transformed into actionable guidance** for future developers. Avoid keeping comments that merely state what was removed without explaining why or what to do instead. |
||||
|
|
||||
|
## 📋 Decision Framework |
||||
|
|
||||
|
### Remove Historical Comments When: |
||||
|
- **Obsolete Information**: Comment describes functionality that no longer exists |
||||
|
- **No Action Required**: Comment doesn't help future developers make decisions |
||||
|
- **Outdated Context**: Comment refers to old patterns that are no longer relevant |
||||
|
- **Self-Evident**: The current code clearly shows the current approach |
||||
|
|
||||
|
### Transform Historical Comments When: |
||||
|
- **Architectural Context**: The change represents a significant pattern shift |
||||
|
- **Migration Guidance**: Future developers might need to understand the evolution |
||||
|
- **Decision Rationale**: The "why" behind the change is still relevant |
||||
|
- **Alternative Approaches**: The comment can guide future implementation choices |
||||
|
|
||||
|
## 🔄 Transformation Patterns |
||||
|
|
||||
|
### 1. From Removal Notice to Migration Note |
||||
|
```typescript |
||||
|
// ❌ REMOVE THIS |
||||
|
// turnOffNotifyingFlags method removed - notification state is now managed by NotificationSection component |
||||
|
|
||||
|
// ✅ TRANSFORM TO THIS |
||||
|
// Note: Notification state management has been migrated to NotificationSection component |
||||
|
// which handles its own lifecycle and persistence via PlatformServiceMixin |
||||
|
``` |
||||
|
|
||||
|
### 2. From Deprecation Notice to Implementation Guide |
||||
|
```typescript |
||||
|
// ❌ REMOVE THIS |
||||
|
// This will be handled by the NewComponent now |
||||
|
// No need to call oldMethod() as it's no longer needed |
||||
|
|
||||
|
// ✅ TRANSFORM TO THIS |
||||
|
// Note: This functionality has been migrated to NewComponent |
||||
|
// which provides better separation of concerns and testability |
||||
|
``` |
||||
|
|
||||
|
### 3. From Historical Note to Architectural Context |
||||
|
```typescript |
||||
|
// ❌ REMOVE THIS |
||||
|
// Old approach: used direct database calls |
||||
|
// New approach: uses service layer |
||||
|
|
||||
|
// ✅ TRANSFORM TO THIS |
||||
|
// Note: Database access has been abstracted through service layer |
||||
|
// for better testability and platform independence |
||||
|
``` |
||||
|
|
||||
|
## 🚫 Anti-Patterns to Remove |
||||
|
|
||||
|
- Comments that only state what was removed |
||||
|
- Comments that don't explain the current approach |
||||
|
- Comments that reference non-existent methods |
||||
|
- Comments that are self-evident from the code |
||||
|
- Comments that don't help future decision-making |
||||
|
|
||||
|
## ✅ Best Practices |
||||
|
|
||||
|
### When Keeping Historical Context: |
||||
|
1. **Explain the "Why"**: Why was the change made? |
||||
|
2. **Describe the "What"**: What is the current approach? |
||||
|
3. **Provide Context**: When might this information be useful? |
||||
|
4. **Use Actionable Language**: Guide future decisions, not just document history |
||||
|
|
||||
|
### When Removing Historical Context: |
||||
|
1. **Verify Obsoleteness**: Ensure the information is truly outdated |
||||
|
2. **Check for Dependencies**: Ensure no other code references the old approach |
||||
|
3. **Update Related Docs**: If removing from code, consider adding to documentation |
||||
|
4. **Preserve in Git History**: The change is preserved in version control |
||||
|
|
||||
|
## 🔍 Implementation Checklist |
||||
|
|
||||
|
- [ ] Identify historical comments about removed/deprecated functionality |
||||
|
- [ ] Determine if comment provides actionable guidance |
||||
|
- [ ] Transform useful comments into migration notes or architectural context |
||||
|
- [ ] Remove comments that are purely historical without guidance value |
||||
|
- [ ] Ensure remaining comments explain current approach and rationale |
||||
|
- [ ] Update related documentation if significant context is removed |
||||
|
|
||||
|
## 📚 Examples |
||||
|
|
||||
|
### Good Historical Comment (Keep & Transform) |
||||
|
```typescript |
||||
|
// Note: Database access has been migrated from direct IndexedDB calls to PlatformServiceMixin |
||||
|
// This provides better platform abstraction and consistent error handling across web/mobile/desktop |
||||
|
// When adding new database operations, use this.$getContact(), this.$saveSettings(), etc. |
||||
|
``` |
||||
|
|
||||
|
### Bad Historical Comment (Remove) |
||||
|
```typescript |
||||
|
// Old method getContactFromDB() removed - now handled by PlatformServiceMixin |
||||
|
// No need to call the old method anymore |
||||
|
``` |
||||
|
|
||||
|
## 🎯 Integration with Harbor Pilot |
||||
|
|
||||
|
This rule works in conjunction with: |
||||
|
- **Component Creation Ideals**: Maintains architectural consistency |
||||
|
- **Migration Patterns**: Documents evolution of patterns |
||||
|
- **Code Review Guidelines**: Ensures comments provide value |
||||
|
|
||||
|
## 📝 Version History |
||||
|
|
||||
|
### v1.0.0 (2025-08-21) |
||||
|
- Initial creation based on notification system cleanup |
||||
|
- Established decision framework for historical comment management |
||||
|
- Added transformation patterns and anti-patterns |
||||
|
- Integrated with existing Harbor Pilot architecture rules |
@ -1,76 +1,117 @@ |
|||||
# Investigation Report Example |
# Investigation Report Example |
||||
|
|
||||
|
**Author**: Matthew Raymer |
||||
|
**Date**: 2025-08-19 |
||||
|
**Status**: 🎯 **ACTIVE** - Investigation methodology example |
||||
|
|
||||
## Investigation — Registration Dialog Test Flakiness |
## Investigation — Registration Dialog Test Flakiness |
||||
|
|
||||
## Objective |
## Objective |
||||
Identify root cause of flaky tests related to registration dialogs in contact import scenarios. |
|
||||
|
Identify root cause of flaky tests related to registration dialogs in contact |
||||
|
import scenarios. |
||||
|
|
||||
## System Map |
## System Map |
||||
- User action → ContactInputForm → ContactsView.addContact() → handleRegistrationPrompt() |
|
||||
|
- User action → ContactInputForm → ContactsView.addContact() → |
||||
|
handleRegistrationPrompt() |
||||
- setTimeout(1000ms) → Modal dialog → User response → Registration API call |
- setTimeout(1000ms) → Modal dialog → User response → Registration API call |
||||
- Test execution → Wait for dialog → Assert dialog content → Click response button |
- Test execution → Wait for dialog → Assert dialog content → Click response |
||||
|
button |
||||
|
|
||||
## Findings (Evidence) |
## Findings (Evidence) |
||||
- **1-second timeout causes flakiness** — evidence: `src/views/ContactsView.vue:971-1000`; setTimeout(..., 1000) in handleRegistrationPrompt() |
|
||||
- **Import flow bypasses dialogs** — evidence: `src/views/ContactImportView.vue:500-520`; importContacts() calls $insertContact() directly, no handleRegistrationPrompt() |
- **1-second timeout causes flakiness** — evidence: |
||||
- **Dialog only appears in direct add flow** — evidence: `src/views/ContactsView.vue:774-800`; addContact() calls handleRegistrationPrompt() after database insert |
`src/views/ContactsView.vue:971-1000`; setTimeout(..., 1000) in |
||||
|
handleRegistrationPrompt() |
||||
|
- **Import flow bypasses dialogs** — evidence: |
||||
|
`src/views/ContactImportView.vue:500-520`; importContacts() calls |
||||
|
$insertContact() directly, no handleRegistrationPrompt() |
||||
|
- **Dialog only appears in direct add flow** — evidence: |
||||
|
`src/views/ContactsView.vue:774-800`; addContact() calls |
||||
|
handleRegistrationPrompt() after database insert |
||||
|
|
||||
## Hypotheses & Failure Modes |
## Hypotheses & Failure Modes |
||||
- H1: 1-second timeout makes dialog appearance unpredictable; would fail when tests run faster than 1000ms |
|
||||
- H2: Test environment timing differs from development; watch for CI vs local test differences |
- H1: 1-second timeout makes dialog appearance unpredictable; would fail when |
||||
|
tests run faster than 1000ms |
||||
|
- H2: Test environment timing differs from development; watch for CI vs local |
||||
|
test differences |
||||
|
|
||||
## Corrections |
## Corrections |
||||
- Updated: "Multiple dialogs interfere with imports" → "Import flow never triggers dialogs - they only appear in direct contact addition" |
|
||||
- Updated: "Complex batch registration needed" → "Simple timeout removal and test mode flag sufficient" |
- Updated: "Multiple dialogs interfere with imports" → "Import flow never |
||||
|
triggers dialogs - they only appear in direct contact addition" |
||||
|
- Updated: "Complex batch registration needed" → "Simple timeout removal and |
||||
|
test mode flag sufficient" |
||||
|
|
||||
## Diagnostics (Next Checks) |
## Diagnostics (Next Checks) |
||||
|
|
||||
- [ ] Repro on CI environment vs local |
- [ ] Repro on CI environment vs local |
||||
- [ ] Measure actual dialog appearance timing |
- [ ] Measure actual dialog appearance timing |
||||
- [ ] Test with setTimeout removed |
- [ ] Test with setTimeout removed |
||||
- [ ] Verify import flow doesn't call handleRegistrationPrompt |
- [ ] Verify import flow doesn't call handleRegistrationPrompt |
||||
|
|
||||
## Risks & Scope |
## Risks & Scope |
||||
- Impacted: Contact addition tests, registration workflow tests; Data: None; Users: Test suite reliability |
|
||||
|
- Impacted: Contact addition tests, registration workflow tests; Data: None; |
||||
|
Users: Test suite reliability |
||||
|
|
||||
## Decision / Next Steps |
## Decision / Next Steps |
||||
|
|
||||
- Owner: Development Team; By: 2025-01-28 |
- Owner: Development Team; By: 2025-01-28 |
||||
- Action: Remove 1-second timeout + add test mode flag; Exit criteria: Tests pass consistently |
- Action: Remove 1-second timeout + add test mode flag; Exit criteria: Tests |
||||
|
pass consistently |
||||
|
|
||||
## References |
## References |
||||
|
|
||||
- `src/views/ContactsView.vue:971-1000` |
- `src/views/ContactsView.vue:971-1000` |
||||
- `src/views/ContactImportView.vue:500-520` |
- `src/views/ContactImportView.vue:500-520` |
||||
- `src/views/ContactsView.vue:774-800` |
- `src/views/ContactsView.vue:774-800` |
||||
|
|
||||
## Competence Hooks |
## Competence Hooks |
||||
- Why this works: Code path tracing revealed separate execution flows, evidence disproved initial assumptions |
|
||||
- Common pitfalls: Assuming related functionality without tracing execution paths, over-engineering solutions to imaginary problems |
|
||||
- Next skill: Learn to trace code execution before proposing architectural changes |
|
||||
- Teach-back: "What evidence shows that contact imports bypass registration dialogs?" |
|
||||
|
|
||||
--- |
- Why this works: Code path tracing revealed separate execution flows, |
||||
|
evidence disproved initial assumptions |
||||
|
- Common pitfalls: Assuming related functionality without tracing execution |
||||
|
paths, over-engineering solutions to imaginary problems |
||||
|
- Next skill: Learn to trace code execution before proposing architectural |
||||
|
changes |
||||
|
- Teach-back: "What evidence shows that contact imports bypass registration |
||||
|
dialogs?" |
||||
|
|
||||
## Key Learning Points |
## Key Learning Points |
||||
|
|
||||
### Evidence-First Approach |
### Evidence-First Approach |
||||
|
|
||||
This investigation demonstrates the importance of: |
This investigation demonstrates the importance of: |
||||
|
|
||||
1. **Tracing actual code execution** rather than making assumptions |
1. **Tracing actual code execution** rather than making assumptions |
||||
2. **Citing specific evidence** with file:line references |
2. **Citing specific evidence** with file:line references |
||||
3. **Validating problem scope** before proposing solutions |
3. **Validating problem scope** before proposing solutions |
||||
4. **Considering simpler alternatives** before complex architectural changes |
4. **Considering simpler alternatives** before complex architectural changes |
||||
|
|
||||
### Code Path Tracing Value |
### Code Path Tracing Value |
||||
|
|
||||
By tracing the execution paths, we discovered: |
By tracing the execution paths, we discovered: |
||||
|
|
||||
- Import flow and direct add flow are completely separate |
- Import flow and direct add flow are completely separate |
||||
- The "multiple dialog interference" problem didn't exist |
- The "multiple dialog interference" problem didn't exist |
||||
- A simple timeout removal would solve the actual issue |
- A simple timeout removal would solve the actual issue |
||||
|
|
||||
### Prevention of Over-Engineering |
### Prevention of Over-Engineering |
||||
|
|
||||
The investigation prevented: |
The investigation prevented: |
||||
|
|
||||
- Unnecessary database schema changes |
- Unnecessary database schema changes |
||||
- Complex batch registration systems |
- Complex batch registration systems |
||||
- Migration scripts for non-existent problems |
- Migration scripts for non-existent problems |
||||
- Architectural changes based on assumptions |
- Architectural changes based on assumptions |
||||
description: |
|
||||
globs: |
|
||||
alwaysApply: false |
|
||||
--- |
--- |
||||
|
|
||||
|
**Status**: Active investigation methodology |
||||
|
**Priority**: High |
||||
|
**Estimated Effort**: Ongoing reference |
||||
|
**Dependencies**: software_development.mdc |
||||
|
**Stakeholders**: Development team, QA team |
||||
|
@ -0,0 +1,222 @@ |
|||||
|
# Agent Contract — TimeSafari Logging (Unified, MANDATORY) |
||||
|
|
||||
|
**Author**: Matthew Raymer |
||||
|
**Date**: 2025-08-19 |
||||
|
**Status**: 🎯 **ACTIVE** - Mandatory logging standards |
||||
|
|
||||
|
## Overview |
||||
|
|
||||
|
This document defines unified logging standards for the TimeSafari project, |
||||
|
ensuring consistent, rest-parameter logging style using the project logger. |
||||
|
No `console.*` methods are allowed in production code. |
||||
|
|
||||
|
## Scope and Goals |
||||
|
|
||||
|
**Scope**: Applies to all diffs and generated code in this workspace unless |
||||
|
explicitly exempted below. |
||||
|
|
||||
|
**Goal**: One consistent, rest-parameter logging style using the project |
||||
|
logger; no `console.*` in production code. |
||||
|
|
||||
|
## Non‑Negotiables (DO THIS) |
||||
|
|
||||
|
- You **MUST** use the project logger; **DO NOT** use any `console.*` |
||||
|
methods. |
||||
|
- Import exactly as: |
||||
|
- `import { logger } from '@/utils/logger'` |
||||
|
- If `@` alias is unavailable, compute the correct relative path (do not |
||||
|
fail). |
||||
|
- Call signatures use **rest parameters**: `logger.info(message, ...args)` |
||||
|
- Prefer primitives/IDs and small objects in `...args`; **never build a |
||||
|
throwaway object** just to "wrap context". |
||||
|
- Production defaults: Web = `warn+`, Electron = `error`, Dev/Capacitor = |
||||
|
`info+` (override via `VITE_LOG_LEVEL`). |
||||
|
- **Database persistence**: `info|warn|error` are persisted; `debug` is not. |
||||
|
Use `logger.toDb(msg, level?)` for DB-only. |
||||
|
|
||||
|
## Available Logger API (Authoritative) |
||||
|
|
||||
|
- `logger.debug(message, ...args)` — verbose internals, timings, input/output |
||||
|
shapes |
||||
|
- `logger.log(message, ...args)` — synonym of `info` for general info |
||||
|
- `logger.info(message, ...args)` — lifecycle, state changes, success paths |
||||
|
- `logger.warn(message, ...args)` — recoverable issues, retries, degraded mode |
||||
|
- `logger.error(message, ...args)` — failures, thrown exceptions, aborts |
||||
|
- `logger.toDb(message, level?)` — DB-only entry (default level = `info`) |
||||
|
- `logger.toConsoleAndDb(message, isError)` — console + DB (use sparingly) |
||||
|
- `logger.withContext(componentName)` — returns a scoped logger |
||||
|
|
||||
|
## Level Guidelines (Use These Heuristics) |
||||
|
|
||||
|
### DEBUG |
||||
|
|
||||
|
Use for method entry/exit, computed values, filters, loops, retries, and |
||||
|
external call payload sizes. |
||||
|
|
||||
|
```typescript |
||||
|
logger.debug('[HomeView] reloadFeedOnChange() called'); |
||||
|
logger.debug('[HomeView] Current filter settings', |
||||
|
settings.filterFeedByVisible, |
||||
|
settings.filterFeedByNearby, |
||||
|
settings.searchBoxes?.length ?? 0); |
||||
|
logger.debug('[FeedFilters] Toggling nearby filter', |
||||
|
this.isNearby, this.settingChanged, this.activeDid); |
||||
|
``` |
||||
|
|
||||
|
**Avoid**: Vague messages (`'Processing data'`). |
||||
|
|
||||
|
### INFO |
||||
|
|
||||
|
Use for user-visible lifecycle and completed operations. |
||||
|
|
||||
|
```typescript |
||||
|
logger.info('[StartView] Component mounted', process.env.VITE_PLATFORM); |
||||
|
logger.info('[StartView] User selected new seed generation'); |
||||
|
logger.info('[SearchAreaView] Search box stored', |
||||
|
searchBox.name, searchBox.bbox); |
||||
|
logger.info('[ContactQRScanShowView] Contact registration OK', |
||||
|
contact.did); |
||||
|
``` |
||||
|
|
||||
|
**Avoid**: Diagnostic details that belong in `debug`. |
||||
|
|
||||
|
### WARN |
||||
|
|
||||
|
Use for recoverable issues, fallbacks, unexpected-but-handled conditions. |
||||
|
|
||||
|
```typescript |
||||
|
logger.warn('[ContactQRScanShowView] Invalid scan result – no value', |
||||
|
resultType); |
||||
|
logger.warn('[ContactQRScanShowView] Invalid QR format – no JWT in URL'); |
||||
|
logger.warn('[ContactQRScanShowView] JWT missing "own" field'); |
||||
|
``` |
||||
|
|
||||
|
**Avoid**: Hard failures (those are `error`). |
||||
|
|
||||
|
### ERROR |
||||
|
|
||||
|
Use for unrecoverable failures, data integrity issues, and thrown |
||||
|
exceptions. |
||||
|
|
||||
|
```typescript |
||||
|
logger.error('[HomeView Settings] initializeIdentity() failed', err); |
||||
|
logger.error('[StartView] Failed to load initialization data', error); |
||||
|
logger.error('[ContactQRScanShowView] Error processing contact QR', |
||||
|
error, rawValue); |
||||
|
``` |
||||
|
|
||||
|
**Avoid**: Expected user cancels (use `info`/`debug`). |
||||
|
|
||||
|
## Context Hygiene (Consistent, Minimal, Helpful) |
||||
|
|
||||
|
- **Component context**: Prefer scoped logger. |
||||
|
|
||||
|
```typescript |
||||
|
const log = logger.withContext('UserService'); |
||||
|
log.info('User created', userId); |
||||
|
log.error('Failed to create user', error); |
||||
|
``` |
||||
|
|
||||
|
If not using `withContext`, prefix message with `[ComponentName]`. |
||||
|
|
||||
|
- **Emojis**: Optional and minimal for visual scanning. Recommended set: |
||||
|
- Start/finish: 🚀 / ✅ |
||||
|
- Retry/loop: 🔄 |
||||
|
- External call: 📡 |
||||
|
- Data/metrics: 📊 |
||||
|
- Inspection: 🔍 |
||||
|
|
||||
|
- **Sensitive data**: Never log secrets (tokens, keys, passwords) or |
||||
|
payloads >10KB. Prefer IDs over objects; redact/hash when needed. |
||||
|
|
||||
|
## Migration — Auto‑Rewrites (Apply Every Time) |
||||
|
|
||||
|
- Exact transforms: |
||||
|
- `console.debug(...)` → `logger.debug(...)` |
||||
|
- `console.log(...)` → `logger.log(...)` (or `logger.info(...)` when |
||||
|
clearly stateful) |
||||
|
- `console.info(...)` → `logger.info(...)` |
||||
|
- `console.warn(...)` → `logger.warn(...)` |
||||
|
- `console.error(...)` → `logger.error(...)` |
||||
|
|
||||
|
- Multi-arg handling: |
||||
|
- First arg becomes `message` (stringify safely if non-string). |
||||
|
- Remaining args map 1:1 to `...args`: |
||||
|
`console.info(msg, a, b)` → `logger.info(String(msg), a, b)` |
||||
|
|
||||
|
- Sole `Error`: |
||||
|
- `console.error(err)` → `logger.error(err.message, err)` |
||||
|
|
||||
|
- **Object-wrapping cleanup**: Replace `{{ userId, meta }}` wrappers with |
||||
|
separate args: |
||||
|
`logger.info('User signed in', userId, meta)` |
||||
|
|
||||
|
## DB Logging Rules |
||||
|
|
||||
|
- `debug` **never** persists automatically. |
||||
|
- `info|warn|error` persist automatically. |
||||
|
- For DB-only events (no console), call `logger.toDb('Message', |
||||
|
'info'|'warn'|'error')`. |
||||
|
|
||||
|
## Exceptions (Tightly Scoped) |
||||
|
|
||||
|
Allowed paths (still prefer logger): |
||||
|
|
||||
|
- `**/*.test.*`, `**/*.spec.*` |
||||
|
- `scripts/dev/**`, `scripts/migrate/**` |
||||
|
|
||||
|
To intentionally keep `console.*`, add a pragma on the previous line: |
||||
|
|
||||
|
```typescript |
||||
|
// cursor:allow-console reason="short justification" |
||||
|
console.log('temporary output'); |
||||
|
``` |
||||
|
|
||||
|
Without the pragma, rewrite to `logger.*`. |
||||
|
|
||||
|
## CI & Diff Enforcement |
||||
|
|
||||
|
- Do not introduce `console.*` anywhere outside allowed, pragma'd spots. |
||||
|
- If an import is missing, insert it and resolve alias/relative path |
||||
|
correctly. |
||||
|
- Enforce rest-parameter call shape in reviews; replace object-wrapped |
||||
|
context. |
||||
|
- Ensure environment log level rules remain intact (`VITE_LOG_LEVEL` |
||||
|
respected). |
||||
|
|
||||
|
## Quick Before/After |
||||
|
|
||||
|
### **Before** |
||||
|
|
||||
|
```typescript |
||||
|
console.log('User signed in', user.id, meta); |
||||
|
console.error('Failed to update profile', err); |
||||
|
console.info('Filter toggled', this.hasVisibleDid); |
||||
|
``` |
||||
|
|
||||
|
### **After** |
||||
|
|
||||
|
```typescript |
||||
|
import { logger } from '@/utils/logger'; |
||||
|
|
||||
|
logger.info('User signed in', user.id, meta); |
||||
|
logger.error('Failed to update profile', err); |
||||
|
logger.debug('[FeedFilters] Filter toggled', this.hasVisibleDid); |
||||
|
``` |
||||
|
|
||||
|
## Checklist (for every PR) |
||||
|
|
||||
|
- [ ] No `console.*` (or properly pragma'd in the allowed locations) |
||||
|
- [ ] Correct import path for `logger` |
||||
|
- [ ] Rest-parameter call shape (`message, ...args`) |
||||
|
- [ ] Right level chosen (debug/info/warn/error) |
||||
|
- [ ] No secrets / oversized payloads / throwaway context objects |
||||
|
- [ ] Component context provided (scoped logger or `[Component]` prefix) |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Status**: Active and enforced |
||||
|
**Priority**: Critical |
||||
|
**Estimated Effort**: Ongoing reference |
||||
|
**Dependencies**: TimeSafari logger utility |
||||
|
**Stakeholders**: Development team, Code review team |
@ -0,0 +1,348 @@ |
|||||
|
--- |
||||
|
description: when generating text that has project task work estimates |
||||
|
alwaysApply: false |
||||
|
--- |
||||
|
# No Time Estimates — Harbor Pilot Directive |
||||
|
|
||||
|
> **Agent role**: **DO NOT MAKE TIME ESTIMATES**. Instead, use phases, milestones, and complexity levels. Time estimates are consistently wrong and create unrealistic expectations. |
||||
|
|
||||
|
## 🎯 Purpose |
||||
|
|
||||
|
Development time estimates are consistently wrong and create unrealistic expectations. This rule ensures we focus on phases, milestones, and complexity rather than trying to predict specific timeframes. |
||||
|
|
||||
|
## 🚨 Critical Rule |
||||
|
|
||||
|
**DO NOT MAKE TIME ESTIMATES** |
||||
|
- **Never provide specific time estimates** - they are always wrong |
||||
|
- **Use phases and milestones** instead of days/weeks |
||||
|
- **Focus on complexity and dependencies** rather than time |
||||
|
- **Set expectations based on progress, not deadlines** |
||||
|
|
||||
|
## 📊 Planning Framework (Not Time Estimates) |
||||
|
|
||||
|
### **Complexity Categories** |
||||
|
- **Simple**: Text changes, styling updates, minor bug fixes |
||||
|
- **Medium**: New features, refactoring, component updates |
||||
|
- **Complex**: Architecture changes, integrations, cross-platform work |
||||
|
- **Unknown**: New technologies, APIs, or approaches |
||||
|
|
||||
|
### **Platform Complexity** |
||||
|
- **Single platform**: Web-only or mobile-only changes |
||||
|
- **Two platforms**: Web + mobile or web + desktop |
||||
|
- **Three platforms**: Web + mobile + desktop |
||||
|
- **Cross-platform consistency**: Ensuring behavior matches across all platforms |
||||
|
|
||||
|
### **Testing Complexity** |
||||
|
- **Basic**: Unit tests for new functionality |
||||
|
- **Comprehensive**: Integration tests, cross-platform testing |
||||
|
- **User acceptance**: User testing, feedback integration |
||||
|
|
||||
|
## 🔍 Planning Process (No Time Estimates) |
||||
|
|
||||
|
### **Step 1: Break Down the Work** |
||||
|
- Identify all subtasks and dependencies |
||||
|
- Group related work into logical phases |
||||
|
- Identify critical path and blockers |
||||
|
|
||||
|
### **Step 2: Define Phases and Milestones** |
||||
|
- **Phase 1**: Foundation work (basic fixes, core functionality) |
||||
|
- **Phase 2**: Enhancement work (new features, integrations) |
||||
|
- **Phase 3**: Polish work (testing, user experience, edge cases) |
||||
|
|
||||
|
### **Step 3: Identify Dependencies** |
||||
|
- **Technical dependencies**: What must be built first |
||||
|
- **Platform dependencies**: What works on which platforms |
||||
|
- **Testing dependencies**: What can be tested when |
||||
|
|
||||
|
### **Step 4: Set Progress Milestones** |
||||
|
- **Milestone 1**: Basic functionality working |
||||
|
- **Milestone 2**: All platforms supported |
||||
|
- **Milestone 3**: Fully tested and polished |
||||
|
|
||||
|
## 📋 Planning Checklist (No Time Estimates) |
||||
|
|
||||
|
- [ ] Work broken down into logical phases |
||||
|
- [ ] Dependencies identified and mapped |
||||
|
- [ ] Milestones defined with clear criteria |
||||
|
- [ ] Complexity levels assigned to each phase |
||||
|
- [ ] Platform requirements identified |
||||
|
- [ ] Testing strategy planned |
||||
|
- [ ] Risk factors identified |
||||
|
- [ ] Success criteria defined |
||||
|
|
||||
|
## 🎯 Example Planning (No Time Estimates) |
||||
|
|
||||
|
### **Example 1: Simple Feature** |
||||
|
``` |
||||
|
Phase 1: Core implementation |
||||
|
- Basic functionality |
||||
|
- Single platform support |
||||
|
- Unit tests |
||||
|
|
||||
|
Phase 2: Platform expansion |
||||
|
- Multi-platform support |
||||
|
- Integration tests |
||||
|
|
||||
|
Phase 3: Polish |
||||
|
- User testing |
||||
|
- Edge case handling |
||||
|
``` |
||||
|
|
||||
|
### **Example 2: Complex Cross-Platform Feature** |
||||
|
``` |
||||
|
Phase 1: Foundation |
||||
|
- Architecture design |
||||
|
- Core service implementation |
||||
|
- Basic web platform support |
||||
|
|
||||
|
Phase 2: Platform Integration |
||||
|
- Mobile platform support |
||||
|
- Desktop platform support |
||||
|
- Cross-platform consistency |
||||
|
|
||||
|
Phase 3: Testing & Polish |
||||
|
- Comprehensive testing |
||||
|
- Error handling |
||||
|
- User experience refinement |
||||
|
``` |
||||
|
|
||||
|
## 🚫 Anti-Patterns to Avoid |
||||
|
|
||||
|
- **"This should take X days"** - Red flag for time estimation |
||||
|
- **"Just a few hours"** - Ignores complexity and testing |
||||
|
- **"Similar to X"** - Without considering differences |
||||
|
- **"Quick fix"** - Nothing is ever quick in software |
||||
|
- **"No testing needed"** - Testing always takes effort |
||||
|
|
||||
|
## ✅ Best Practices |
||||
|
|
||||
|
### **When Planning:** |
||||
|
1. **Break down everything** - no work is too small to plan |
||||
|
2. **Consider all platforms** - web, mobile, desktop differences |
||||
|
3. **Include testing strategy** - unit, integration, and user testing |
||||
|
4. **Account for unknowns** - there are always surprises |
||||
|
5. **Focus on dependencies** - what blocks what |
||||
|
|
||||
|
### **When Presenting Plans:** |
||||
|
1. **Show the phases** - explain the logical progression |
||||
|
2. **Highlight dependencies** - what could block progress |
||||
|
3. **Define milestones** - clear success criteria |
||||
|
4. **Identify risks** - what could go wrong |
||||
|
5. **Suggest alternatives** - ways to reduce scope or complexity |
||||
|
|
||||
|
## 🔄 Continuous Improvement |
||||
|
|
||||
|
### **Track Progress** |
||||
|
- Record planned vs. actual phases completed |
||||
|
- Identify what took longer than expected |
||||
|
- Learn from complexity misjudgments |
||||
|
- Adjust planning process based on experience |
||||
|
|
||||
|
### **Learn from Experience** |
||||
|
- **Underestimated complexity**: Increase complexity categories |
||||
|
- **Missed dependencies**: Improve dependency mapping |
||||
|
- **Platform surprises**: Better platform research upfront |
||||
|
|
||||
|
## 🎯 Integration with Harbor Pilot |
||||
|
|
||||
|
This rule works in conjunction with: |
||||
|
- **Project Planning**: Focuses on phases and milestones |
||||
|
- **Resource Allocation**: Based on complexity, not time |
||||
|
- **Risk Management**: Identifies blockers and dependencies |
||||
|
- **Stakeholder Communication**: Sets progress-based expectations |
||||
|
|
||||
|
## 📝 Version History |
||||
|
|
||||
|
### v2.0.0 (2025-08-21) |
||||
|
- **Major Change**: Completely removed time estimation approach |
||||
|
- **New Focus**: Phases, milestones, and complexity-based planning |
||||
|
- **Eliminated**: All time multipliers, estimates, and calculations |
||||
|
- **Added**: Dependency mapping and progress milestone framework |
||||
|
|
||||
|
### v1.0.0 (2025-08-21) |
||||
|
- Initial creation based on user feedback about estimation accuracy |
||||
|
- ~~Established realistic estimation multipliers and process~~ |
||||
|
- ~~Added comprehensive estimation checklist and examples~~ |
||||
|
- Integrated with Harbor Pilot planning and risk management |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 🚨 Remember |
||||
|
|
||||
|
**DO NOT MAKE TIME ESTIMATES. Use phases, milestones, and complexity instead. Focus on progress, not deadlines.** |
||||
|
|
||||
|
## 🚨 Remember |
||||
|
|
||||
|
**Your first estimate is wrong. Your second estimate is probably still wrong. Focus on progress, not deadlines.** |
||||
|
# No Time Estimates — Harbor Pilot Directive |
||||
|
|
||||
|
> **Agent role**: **DO NOT MAKE TIME ESTIMATES**. Instead, use phases, milestones, and complexity levels. Time estimates are consistently wrong and create unrealistic expectations. |
||||
|
|
||||
|
## 🎯 Purpose |
||||
|
|
||||
|
Development time estimates are consistently wrong and create unrealistic expectations. This rule ensures we focus on phases, milestones, and complexity rather than trying to predict specific timeframes. |
||||
|
|
||||
|
## 🚨 Critical Rule |
||||
|
|
||||
|
**DO NOT MAKE TIME ESTIMATES** |
||||
|
- **Never provide specific time estimates** - they are always wrong |
||||
|
- **Use phases and milestones** instead of days/weeks |
||||
|
- **Focus on complexity and dependencies** rather than time |
||||
|
- **Set expectations based on progress, not deadlines** |
||||
|
|
||||
|
## 📊 Planning Framework (Not Time Estimates) |
||||
|
|
||||
|
### **Complexity Categories** |
||||
|
- **Simple**: Text changes, styling updates, minor bug fixes |
||||
|
- **Medium**: New features, refactoring, component updates |
||||
|
- **Complex**: Architecture changes, integrations, cross-platform work |
||||
|
- **Unknown**: New technologies, APIs, or approaches |
||||
|
|
||||
|
### **Platform Complexity** |
||||
|
- **Single platform**: Web-only or mobile-only changes |
||||
|
- **Two platforms**: Web + mobile or web + desktop |
||||
|
- **Three platforms**: Web + mobile + desktop |
||||
|
- **Cross-platform consistency**: Ensuring behavior matches across all platforms |
||||
|
|
||||
|
### **Testing Complexity** |
||||
|
- **Basic**: Unit tests for new functionality |
||||
|
- **Comprehensive**: Integration tests, cross-platform testing |
||||
|
- **User acceptance**: User testing, feedback integration |
||||
|
|
||||
|
## 🔍 Planning Process (No Time Estimates) |
||||
|
|
||||
|
### **Step 1: Break Down the Work** |
||||
|
- Identify all subtasks and dependencies |
||||
|
- Group related work into logical phases |
||||
|
- Identify critical path and blockers |
||||
|
|
||||
|
### **Step 2: Define Phases and Milestones** |
||||
|
- **Phase 1**: Foundation work (basic fixes, core functionality) |
||||
|
- **Phase 2**: Enhancement work (new features, integrations) |
||||
|
- **Phase 3**: Polish work (testing, user experience, edge cases) |
||||
|
|
||||
|
### **Step 3: Identify Dependencies** |
||||
|
- **Technical dependencies**: What must be built first |
||||
|
- **Platform dependencies**: What works on which platforms |
||||
|
- **Testing dependencies**: What can be tested when |
||||
|
|
||||
|
### **Step 4: Set Progress Milestones** |
||||
|
- **Milestone 1**: Basic functionality working |
||||
|
- **Milestone 2**: All platforms supported |
||||
|
- **Milestone 3**: Fully tested and polished |
||||
|
|
||||
|
## 📋 Planning Checklist (No Time Estimates) |
||||
|
|
||||
|
- [ ] Work broken down into logical phases |
||||
|
- [ ] Dependencies identified and mapped |
||||
|
- [ ] Milestones defined with clear criteria |
||||
|
- [ ] Complexity levels assigned to each phase |
||||
|
- [ ] Platform requirements identified |
||||
|
- [ ] Testing strategy planned |
||||
|
- [ ] Risk factors identified |
||||
|
- [ ] Success criteria defined |
||||
|
|
||||
|
## 🎯 Example Planning (No Time Estimates) |
||||
|
|
||||
|
### **Example 1: Simple Feature** |
||||
|
``` |
||||
|
Phase 1: Core implementation |
||||
|
- Basic functionality |
||||
|
- Single platform support |
||||
|
- Unit tests |
||||
|
|
||||
|
Phase 2: Platform expansion |
||||
|
- Multi-platform support |
||||
|
- Integration tests |
||||
|
|
||||
|
Phase 3: Polish |
||||
|
- User testing |
||||
|
- Edge case handling |
||||
|
``` |
||||
|
|
||||
|
### **Example 2: Complex Cross-Platform Feature** |
||||
|
``` |
||||
|
Phase 1: Foundation |
||||
|
- Architecture design |
||||
|
- Core service implementation |
||||
|
- Basic web platform support |
||||
|
|
||||
|
Phase 2: Platform Integration |
||||
|
- Mobile platform support |
||||
|
- Desktop platform support |
||||
|
- Cross-platform consistency |
||||
|
|
||||
|
Phase 3: Testing & Polish |
||||
|
- Comprehensive testing |
||||
|
- Error handling |
||||
|
- User experience refinement |
||||
|
``` |
||||
|
|
||||
|
## 🚫 Anti-Patterns to Avoid |
||||
|
|
||||
|
- **"This should take X days"** - Red flag for time estimation |
||||
|
- **"Just a few hours"** - Ignores complexity and testing |
||||
|
- **"Similar to X"** - Without considering differences |
||||
|
- **"Quick fix"** - Nothing is ever quick in software |
||||
|
- **"No testing needed"** - Testing always takes effort |
||||
|
|
||||
|
## ✅ Best Practices |
||||
|
|
||||
|
### **When Planning:** |
||||
|
1. **Break down everything** - no work is too small to plan |
||||
|
2. **Consider all platforms** - web, mobile, desktop differences |
||||
|
3. **Include testing strategy** - unit, integration, and user testing |
||||
|
4. **Account for unknowns** - there are always surprises |
||||
|
5. **Focus on dependencies** - what blocks what |
||||
|
|
||||
|
### **When Presenting Plans:** |
||||
|
1. **Show the phases** - explain the logical progression |
||||
|
2. **Highlight dependencies** - what could block progress |
||||
|
3. **Define milestones** - clear success criteria |
||||
|
4. **Identify risks** - what could go wrong |
||||
|
5. **Suggest alternatives** - ways to reduce scope or complexity |
||||
|
|
||||
|
## 🔄 Continuous Improvement |
||||
|
|
||||
|
### **Track Progress** |
||||
|
- Record planned vs. actual phases completed |
||||
|
- Identify what took longer than expected |
||||
|
- Learn from complexity misjudgments |
||||
|
- Adjust planning process based on experience |
||||
|
|
||||
|
### **Learn from Experience** |
||||
|
- **Underestimated complexity**: Increase complexity categories |
||||
|
- **Missed dependencies**: Improve dependency mapping |
||||
|
- **Platform surprises**: Better platform research upfront |
||||
|
|
||||
|
## 🎯 Integration with Harbor Pilot |
||||
|
|
||||
|
This rule works in conjunction with: |
||||
|
- **Project Planning**: Focuses on phases and milestones |
||||
|
- **Resource Allocation**: Based on complexity, not time |
||||
|
- **Risk Management**: Identifies blockers and dependencies |
||||
|
- **Stakeholder Communication**: Sets progress-based expectations |
||||
|
|
||||
|
## 📝 Version History |
||||
|
|
||||
|
### v2.0.0 (2025-08-21) |
||||
|
- **Major Change**: Completely removed time estimation approach |
||||
|
- **New Focus**: Phases, milestones, and complexity-based planning |
||||
|
- **Eliminated**: All time multipliers, estimates, and calculations |
||||
|
- **Added**: Dependency mapping and progress milestone framework |
||||
|
|
||||
|
### v1.0.0 (2025-08-21) |
||||
|
- Initial creation based on user feedback about estimation accuracy |
||||
|
- ~~Established realistic estimation multipliers and process~~ |
||||
|
- ~~Added comprehensive estimation checklist and examples~~ |
||||
|
- Integrated with Harbor Pilot planning and risk management |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 🚨 Remember |
||||
|
|
||||
|
**DO NOT MAKE TIME ESTIMATES. Use phases, milestones, and complexity instead. Focus on progress, not deadlines.** |
||||
|
|
||||
|
## 🚨 Remember |
||||
|
|
||||
|
**Your first estimate is wrong. Your second estimate is probably still wrong. Focus on progress, not deadlines.** |
@ -0,0 +1,329 @@ |
|||||
|
--- |
||||
|
alwaysApply: true |
||||
|
--- |
||||
|
# Time Handling in Development Workflow |
||||
|
|
||||
|
**Author**: Matthew Raymer |
||||
|
**Date**: 2025-08-17 |
||||
|
**Status**: 🎯 **ACTIVE** - Production Ready |
||||
|
|
||||
|
## Overview |
||||
|
|
||||
|
This guide establishes **how time should be referenced and used** across the |
||||
|
development workflow. It is not tied to any one project, but applies to **all |
||||
|
feature development, issue investigations, ADRs, and documentation**. |
||||
|
|
||||
|
## General Principles |
||||
|
|
||||
|
- **Explicit over relative**: Always prefer absolute dates (`2025-08-17`) over |
||||
|
relative references like "last week." |
||||
|
- **ISO 8601 Standard**: Use `YYYY-MM-DD` format for all date references in |
||||
|
docs, issues, ADRs, and commits. |
||||
|
- **Time zones**: Default to **UTC** unless explicitly tied to user-facing |
||||
|
behavior. |
||||
|
- **Precision**: Only specify as much precision as needed (date vs. datetime vs. |
||||
|
timestamp). |
||||
|
- **Consistency**: Align time references across ADRs, commits, and investigation |
||||
|
reports. |
||||
|
|
||||
|
## In Documentation & ADRs |
||||
|
|
||||
|
- Record decision dates using **absolute ISO dates**. |
||||
|
- For ongoing timelines, state start and end explicitly (e.g., `2025-08-01` → |
||||
|
`2025-08-17`). |
||||
|
- Avoid ambiguous terms like *recently*, *last month*, or *soon*. |
||||
|
- For time-based experiments (e.g., A/B tests), always include: |
||||
|
|
||||
|
- Start date |
||||
|
- Expected duration |
||||
|
- Review date checkpoint |
||||
|
|
||||
|
## In Code & Commits |
||||
|
|
||||
|
- Use **UTC timestamps** in logs, DB migrations, and serialized formats. |
||||
|
- In commits, link changes to **date-bound ADRs or investigation docs**. |
||||
|
- For migrations, include both **applied date** and **intended version window**. |
||||
|
- Use constants for known fixed dates; avoid hardcoding arbitrary strings. |
||||
|
|
||||
|
## In Investigations & Research |
||||
|
|
||||
|
- Capture **when** an issue occurred (absolute time or version tag). |
||||
|
- When describing failures: note whether they are **time-sensitive** (e.g., after |
||||
|
migrations, cache expirations). |
||||
|
- Record diagnostic timelines in ISO format (not relative). |
||||
|
- For performance regressions, annotate both **baseline timeframe** and |
||||
|
**measurement timeframe**. |
||||
|
|
||||
|
## Collaboration Hooks |
||||
|
|
||||
|
- During reviews, verify **time references are clear, absolute, and |
||||
|
standardized**. |
||||
|
- In syncs, reframe relative terms ("this week") into shared absolute |
||||
|
references. |
||||
|
- Tag ADRs with both **date created** and **review by** checkpoints. |
||||
|
|
||||
|
## Self-Check Before Submitting |
||||
|
|
||||
|
- [ ] Did I check the time using the **developer's actual system time and |
||||
|
timezone**? |
||||
|
- [ ] Am I using absolute ISO dates? |
||||
|
- [ ] Is UTC assumed unless specified otherwise? |
||||
|
- [ ] Did I avoid ambiguous relative terms? |
||||
|
- [ ] If duration matters, did I specify both start and end? |
||||
|
- [ ] For future work, did I include a review/revisit date? |
||||
|
|
||||
|
## Real-Time Context in Developer Interactions |
||||
|
|
||||
|
- The model must always resolve **"current time"** using the **developer's |
||||
|
actual system time and timezone**. |
||||
|
- When generating timestamps (e.g., in investigation logs, ADRs, or examples), |
||||
|
the model should: |
||||
|
|
||||
|
- Use the **developer's current local time** by default. |
||||
|
- Indicate the timezone explicitly (e.g., `2025-08-17T10:32-05:00`). |
||||
|
- Optionally provide UTC alongside if context requires cross-team clarity. |
||||
|
|
||||
|
- When interpreting relative terms like *now*, *today*, *last week*: |
||||
|
|
||||
|
- Resolve them against the **developer's current time**. |
||||
|
- Convert them into **absolute ISO-8601 values** in the output. |
||||
|
|
||||
|
## LLM Time Checking Instructions |
||||
|
|
||||
|
**CRITICAL**: The LLM must actively query the system for current time rather |
||||
|
than assuming or inventing times. |
||||
|
|
||||
|
### How to Check Current Time |
||||
|
|
||||
|
#### 1. **Query System Time (Required)** |
||||
|
|
||||
|
- **Always start** by querying the current system time using available tools |
||||
|
- **Never assume** what the current time is |
||||
|
- **Never use** placeholder values like "current time" or "now" |
||||
|
|
||||
|
#### 2. **Available Time Query Methods** |
||||
|
|
||||
|
- **System Clock**: Use `date` command or equivalent system time function |
||||
|
- **Programming Language**: Use language-specific time functions (e.g., |
||||
|
`Date.now()`, `datetime.now()`) |
||||
|
- **Environment Variables**: Check for time-related environment variables |
||||
|
- **API Calls**: Use time service APIs if available |
||||
|
|
||||
|
#### 3. **Required Time Information** |
||||
|
|
||||
|
When querying time, always obtain: |
||||
|
|
||||
|
- **Current Date**: YYYY-MM-DD format |
||||
|
- **Current Time**: HH:MM:SS format (24-hour) |
||||
|
- **Timezone**: Current system timezone or UTC offset |
||||
|
- **UTC Equivalent**: Convert local time to UTC for cross-team clarity |
||||
|
|
||||
|
#### 4. **Time Query Examples** |
||||
|
|
||||
|
```bash |
||||
|
# Example: Query system time |
||||
|
$ date |
||||
|
# Expected output: Mon Aug 17 10:32:45 EDT 2025 |
||||
|
|
||||
|
# Example: Query UTC time |
||||
|
$ date -u |
||||
|
# Expected output: Mon Aug 17 14:32:45 UTC 2025 |
||||
|
``` |
||||
|
|
||||
|
```python |
||||
|
# Example: Python time query |
||||
|
import datetime |
||||
|
current_time = datetime.datetime.now() |
||||
|
utc_time = datetime.datetime.utcnow() |
||||
|
print(f"Local: {current_time}") |
||||
|
print(f"UTC: {utc_time}") |
||||
|
``` |
||||
|
|
||||
|
```javascript |
||||
|
// Example: JavaScript time query |
||||
|
const now = new Date(); |
||||
|
const utc = new Date().toISOString(); |
||||
|
console.log(`Local: ${now}`); |
||||
|
console.log(`UTC: ${utc}`); |
||||
|
``` |
||||
|
|
||||
|
#### 5. **LLM Time Checking Workflow** |
||||
|
|
||||
|
1. **Query**: Actively query system for current time |
||||
|
2. **Validate**: Confirm time data is reasonable and current |
||||
|
3. **Format**: Convert to ISO 8601 format |
||||
|
4. **Context**: Provide both local and UTC times when helpful |
||||
|
5. **Document**: Show the source of time information |
||||
|
|
||||
|
#### 6. **Error Handling for Time Queries** |
||||
|
|
||||
|
- **If time query fails**: Ask user for current time or use "unknown time" |
||||
|
with explanation |
||||
|
- **If timezone unclear**: Default to UTC and ask for clarification |
||||
|
- **If time seems wrong**: Verify with user before proceeding |
||||
|
- **Always log**: Record when and how time was obtained |
||||
|
|
||||
|
#### 7. **Time Query Verification** |
||||
|
|
||||
|
Before using queried time, verify: |
||||
|
|
||||
|
- [ ] Time is recent (within last few minutes) |
||||
|
- [ ] Timezone information is available |
||||
|
- [ ] UTC conversion is accurate |
||||
|
- [ ] Format follows ISO 8601 standard |
||||
|
|
||||
|
## Model Behavior Rules |
||||
|
|
||||
|
- **Never invent a "fake now"**: All "current time" references must come from |
||||
|
the real system clock available at runtime. |
||||
|
- **Check developer time zone**: If ambiguous, ask for clarification (e.g., |
||||
|
"Should I use UTC or your local timezone?"). |
||||
|
- **Format for clarity**: |
||||
|
|
||||
|
- Local time: `YYYY-MM-DDTHH:mm±hh:mm` |
||||
|
- UTC equivalent (if needed): `YYYY-MM-DDTHH:mmZ` |
||||
|
|
||||
|
## Examples |
||||
|
|
||||
|
### Good |
||||
|
|
||||
|
- "Feature flag rollout started on `2025-08-01` and will be reviewed on |
||||
|
`2025-08-21`." |
||||
|
- "Migration applied on `2025-07-15T14:00Z`." |
||||
|
- "Issue reproduced on `2025-08-17T09:00-05:00 (local)` / |
||||
|
`2025-08-17T14:00Z (UTC)`." |
||||
|
|
||||
|
### Bad |
||||
|
|
||||
|
- "Feature flag rolled out last week." |
||||
|
- "Migration applied recently." |
||||
|
- "Now is August, so we assume this was last month." |
||||
|
|
||||
|
### More Examples |
||||
|
|
||||
|
#### Issue Reports |
||||
|
|
||||
|
- ✅ **Good**: "User reported login failure at `2025-08-17T14:30:00Z`. Issue |
||||
|
persisted until `2025-08-17T15:45:00Z`." |
||||
|
- ❌ **Bad**: "User reported login failure earlier today. Issue lasted for a |
||||
|
while." |
||||
|
|
||||
|
#### Release Planning |
||||
|
|
||||
|
- ✅ **Good**: "Feature X scheduled for release on `2025-08-25`. Testing |
||||
|
window: `2025-08-20` to `2025-08-24`." |
||||
|
- ❌ **Bad**: "Feature X will be released next week after testing." |
||||
|
|
||||
|
#### Performance Monitoring |
||||
|
|
||||
|
- ✅ **Good**: "Baseline performance measured on `2025-08-10T09:00:00Z`. |
||||
|
Regression detected on `2025-08-15T14:00:00Z`." |
||||
|
- ❌ **Bad**: "Performance was good last week but got worse this week." |
||||
|
|
||||
|
## Technical Implementation Notes |
||||
|
|
||||
|
### UTC Storage Principle |
||||
|
|
||||
|
- **Store all timestamps in UTC** in databases, logs, and serialized formats |
||||
|
- **Convert to local time only for user display** |
||||
|
- **Use ISO 8601 format** for all storage: `YYYY-MM-DDTHH:mm:ss.sssZ` |
||||
|
|
||||
|
### Common Implementation Patterns |
||||
|
|
||||
|
#### Database Storage |
||||
|
|
||||
|
```sql |
||||
|
-- ✅ Good: Store in UTC |
||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
|
|
||||
|
-- ❌ Bad: Store in local time |
||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP |
||||
|
``` |
||||
|
|
||||
|
#### API Responses |
||||
|
|
||||
|
```json |
||||
|
// ✅ Good: Include both UTC and local time |
||||
|
{ |
||||
|
"eventTime": "2025-08-17T14:00:00Z", |
||||
|
"localTime": "2025-08-17T10:00:00-04:00", |
||||
|
"timezone": "America/New_York" |
||||
|
} |
||||
|
|
||||
|
// ❌ Bad: Only local time |
||||
|
{ |
||||
|
"eventTime": "2025-08-17T10:00:00-04:00" |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
#### Logging |
||||
|
|
||||
|
```python |
||||
|
# ✅ Good: Log in UTC with timezone info |
||||
|
logger.info(f"User action at {datetime.utcnow().isoformat()}Z (UTC)") |
||||
|
|
||||
|
# ❌ Bad: Log in local time |
||||
|
logger.info(f"User action at {datetime.now()}") |
||||
|
``` |
||||
|
|
||||
|
### Timezone Handling Best Practices |
||||
|
|
||||
|
#### 1. Always Store Timezone Information |
||||
|
|
||||
|
- Include IANA timezone identifier (e.g., `America/New_York`) |
||||
|
- Store UTC offset at time of creation |
||||
|
- Handle daylight saving time transitions automatically |
||||
|
|
||||
|
#### 2. User Display Considerations |
||||
|
|
||||
|
- Convert UTC to user's preferred timezone |
||||
|
- Show timezone abbreviation when helpful |
||||
|
- Use relative time for recent events ("2 hours ago") |
||||
|
|
||||
|
#### 3. Edge Case Handling |
||||
|
|
||||
|
- **Daylight Saving Time**: Use timezone-aware libraries |
||||
|
- **Leap Seconds**: Handle gracefully (rare but important) |
||||
|
- **Invalid Times**: Validate before processing |
||||
|
|
||||
|
### Common Mistakes to Avoid |
||||
|
|
||||
|
#### 1. Timezone Confusion |
||||
|
|
||||
|
- ❌ **Don't**: Assume server timezone is user timezone |
||||
|
- ✅ **Do**: Always convert UTC to user's local time for display |
||||
|
|
||||
|
#### 2. Format Inconsistency |
||||
|
|
||||
|
- ❌ **Don't**: Mix different time formats in the same system |
||||
|
- ✅ **Do**: Standardize on ISO 8601 for all storage |
||||
|
|
||||
|
#### 3. Relative Time References |
||||
|
|
||||
|
- ❌ **Don't**: Use relative terms in persistent storage |
||||
|
- ✅ **Do**: Convert relative terms to absolute timestamps immediately |
||||
|
|
||||
|
## References |
||||
|
|
||||
|
- [ISO 8601 Date and Time Standard](https://en.wikipedia.org/wiki/ISO_8601) |
||||
|
- [IANA Timezone Database](https://www.iana.org/time-zones) |
||||
|
- [ADR Template](./adr_template.md) |
||||
|
- [Research & Diagnostic Workflow](./research_diagnostic.mdc) |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Rule of Thumb**: Every time reference in development artifacts should be |
||||
|
**clear in 6 months without context**, and aligned to the **developer's actual |
||||
|
current time**. |
||||
|
|
||||
|
**Technical Rule of Thumb**: **Store in UTC, display in local time, always |
||||
|
include timezone context.** |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Status**: Active |
||||
|
**Version**: 1.0 |
||||
|
**Maintainer**: Matthew Raymer |
||||
|
**Next Review**: 2025-09-17 |
@ -1,142 +0,0 @@ |
|||||
name: Asset Validation & CI Safeguards |
|
||||
|
|
||||
on: |
|
||||
pull_request: |
|
||||
paths: |
|
||||
- 'resources/**' |
|
||||
- 'config/assets/**' |
|
||||
- 'capacitor-assets.config.json' |
|
||||
- 'capacitor.config.ts' |
|
||||
- 'capacitor.config.json' |
|
||||
push: |
|
||||
branches: [main, develop] |
|
||||
paths: |
|
||||
- 'resources/**' |
|
||||
- 'config/assets/**' |
|
||||
- 'capacitor-assets.config.json' |
|
||||
- 'capacitor.config.ts' |
|
||||
- 'capacitor.config.json' |
|
||||
|
|
||||
jobs: |
|
||||
asset-validation: |
|
||||
runs-on: ubuntu-latest |
|
||||
steps: |
|
||||
- name: Checkout code |
|
||||
uses: actions/checkout@v4 |
|
||||
|
|
||||
- name: Setup Node.js |
|
||||
uses: actions/setup-node@v4 |
|
||||
with: |
|
||||
node-version-file: '.nvmrc' |
|
||||
cache: 'npm' |
|
||||
|
|
||||
- name: Install dependencies |
|
||||
run: npm ci |
|
||||
|
|
||||
- name: Validate asset configuration |
|
||||
run: npm run assets:validate |
|
||||
|
|
||||
- name: Check for committed platform assets (Android) |
|
||||
run: | |
|
||||
if git ls-files -z android/app/src/main/res | grep -E '(AppIcon.*\.png|Splash.*\.png|mipmap-.*/ic_launcher.*\.png)' > /dev/null; then |
|
||||
echo "❌ Android platform assets found in VCS - these should be generated at build-time" |
|
||||
git ls-files -z android/app/src/main/res | grep -E '(AppIcon.*\.png|Splash.*\.png|mipmap-.*/ic_launcher.*\.png)' |
|
||||
exit 1 |
|
||||
fi |
|
||||
echo "✅ No Android platform assets committed" |
|
||||
|
|
||||
- name: Check for committed platform assets (iOS) |
|
||||
run: | |
|
||||
if git ls-files -z ios/App/App/Assets.xcassets | grep -E '(AppIcon.*\.png|Splash.*\.png)' > /dev/null; then |
|
||||
echo "❌ iOS platform assets found in VCS - these should be generated at build-time" |
|
||||
git ls-files -z ios/App/App/Assets.xcassets | grep -E '(AppIcon.*\.png|Splash.*\.png)' |
|
||||
exit 1 |
|
||||
fi |
|
||||
echo "✅ No iOS platform assets committed" |
|
||||
|
|
||||
- name: Test asset generation |
|
||||
run: | |
|
||||
echo "🧪 Testing asset generation workflow..." |
|
||||
npm run build:capacitor |
|
||||
npx cap sync |
|
||||
npx capacitor-assets generate --dry-run || npx capacitor-assets generate |
|
||||
echo "✅ Asset generation test completed" |
|
||||
|
|
||||
- name: Verify clean tree after build |
|
||||
run: | |
|
||||
if [ -n "$(git status --porcelain)" ]; then |
|
||||
echo "❌ Dirty tree after build - asset configs were modified" |
|
||||
git status |
|
||||
git diff |
|
||||
exit 1 |
|
||||
fi |
|
||||
echo "✅ Build completed with clean tree" |
|
||||
|
|
||||
schema-validation: |
|
||||
runs-on: ubuntu-latest |
|
||||
steps: |
|
||||
- name: Checkout code |
|
||||
uses: actions/checkout@v4 |
|
||||
|
|
||||
- name: Setup Node.js |
|
||||
uses: actions/setup-node@v4 |
|
||||
with: |
|
||||
node-version-file: '.nvmrc' |
|
||||
cache: 'npm' |
|
||||
|
|
||||
- name: Install dependencies |
|
||||
run: npm ci |
|
||||
|
|
||||
- name: Validate schema compliance |
|
||||
run: | |
|
||||
echo "🔍 Validating schema compliance..." |
|
||||
node -e " |
|
||||
const fs = require('fs'); |
|
||||
const config = JSON.parse(fs.readFileSync('capacitor-assets.config.json', 'utf8')); |
|
||||
const schema = JSON.parse(fs.readFileSync('config/assets/schema.json', 'utf8')); |
|
||||
|
|
||||
// Basic schema validation |
|
||||
if (!config.icon || !config.splash) { |
|
||||
throw new Error('Missing required sections: icon and splash'); |
|
||||
} |
|
||||
|
|
||||
if (!config.icon.source || !config.splash.source) { |
|
||||
throw new Error('Missing required source fields'); |
|
||||
} |
|
||||
|
|
||||
if (!/^resources\/.*\.(png|svg)$/.test(config.icon.source)) { |
|
||||
throw new Error('Icon source must be in resources/ directory'); |
|
||||
} |
|
||||
|
|
||||
if (!/^resources\/.*\.(png|svg)$/.test(config.splash.source)) { |
|
||||
throw new Error('Splash source must be in resources/ directory'); |
|
||||
} |
|
||||
|
|
||||
console.log('✅ Schema validation passed'); |
|
||||
" |
|
||||
|
|
||||
- name: Check source file existence |
|
||||
run: | |
|
||||
echo "📁 Checking source file existence..." |
|
||||
node -e " |
|
||||
const fs = require('fs'); |
|
||||
const config = JSON.parse(fs.readFileSync('capacitor-assets.config.json', 'utf8')); |
|
||||
|
|
||||
const requiredFiles = [ |
|
||||
config.icon.source, |
|
||||
config.splash.source |
|
||||
]; |
|
||||
|
|
||||
if (config.splash.darkSource) { |
|
||||
requiredFiles.push(config.splash.darkSource); |
|
||||
} |
|
||||
|
|
||||
const missingFiles = requiredFiles.filter(file => !fs.existsSync(file)); |
|
||||
|
|
||||
if (missingFiles.length > 0) { |
|
||||
console.error('❌ Missing source files:', missingFiles); |
|
||||
process.exit(1); |
|
||||
} |
|
||||
|
|
||||
console.log('✅ All source files exist'); |
|
||||
" |
|
@ -1,27 +0,0 @@ |
|||||
name: Playwright Tests |
|
||||
on: |
|
||||
push: |
|
||||
branches: [ main, master ] |
|
||||
pull_request: |
|
||||
branches: [ main, master ] |
|
||||
jobs: |
|
||||
test: |
|
||||
timeout-minutes: 60 |
|
||||
runs-on: ubuntu-latest |
|
||||
steps: |
|
||||
- uses: actions/checkout@v4 |
|
||||
- uses: actions/setup-node@v4 |
|
||||
with: |
|
||||
node-version: lts/* |
|
||||
- name: Install dependencies |
|
||||
run: npm ci |
|
||||
- name: Install Playwright Browsers |
|
||||
run: npx playwright install --with-deps |
|
||||
- name: Run Playwright tests |
|
||||
run: npx playwright test |
|
||||
- uses: actions/upload-artifact@v4 |
|
||||
if: always() |
|
||||
with: |
|
||||
name: playwright-report |
|
||||
path: playwright-report/ |
|
||||
retention-days: 30 |
|
@ -0,0 +1,40 @@ |
|||||
|
#!/usr/bin/env sh |
||||
|
# |
||||
|
# Husky Helper Script |
||||
|
# This file is sourced by all Husky hooks |
||||
|
# |
||||
|
if [ -z "$husky_skip_init" ]; then |
||||
|
debug () { |
||||
|
if [ "$HUSKY_DEBUG" = "1" ]; then |
||||
|
echo "husky (debug) - $1" |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
readonly hook_name="$(basename -- "$0")" |
||||
|
debug "starting $hook_name..." |
||||
|
|
||||
|
if [ "$HUSKY" = "0" ]; then |
||||
|
debug "HUSKY env variable is set to 0, skipping hook" |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
if [ -f ~/.huskyrc ]; then |
||||
|
debug "sourcing ~/.huskyrc" |
||||
|
. ~/.huskyrc |
||||
|
fi |
||||
|
|
||||
|
readonly husky_skip_init=1 |
||||
|
export husky_skip_init |
||||
|
sh -e "$0" "$@" |
||||
|
exitCode="$?" |
||||
|
|
||||
|
if [ $exitCode != 0 ]; then |
||||
|
echo "husky - $hook_name hook exited with code $exitCode (error)" |
||||
|
fi |
||||
|
|
||||
|
if [ $exitCode = 127 ]; then |
||||
|
echo "husky - command not found in PATH=$PATH" |
||||
|
fi |
||||
|
|
||||
|
exit $exitCode |
||||
|
fi |
@ -0,0 +1,10 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
# |
||||
|
# Husky Commit Message Hook |
||||
|
# Validates commit message format using commitlint |
||||
|
# |
||||
|
. "$(dirname -- "$0")/_/husky.sh" |
||||
|
|
||||
|
# Run commitlint but don't fail the commit (|| true) |
||||
|
# This provides helpful feedback without blocking commits |
||||
|
npx commitlint --edit "$1" || true |
@ -0,0 +1,15 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
# |
||||
|
# Husky Pre-commit Hook |
||||
|
# Runs Build Architecture Guard to check staged files |
||||
|
# |
||||
|
. "$(dirname -- "$0")/_/husky.sh" |
||||
|
|
||||
|
echo "🔍 Running Build Architecture Guard (pre-commit)..." |
||||
|
bash ./scripts/build-arch-guard.sh --staged || { |
||||
|
echo |
||||
|
echo "💡 To bypass this check for emergency commits, use:" |
||||
|
echo " git commit --no-verify" |
||||
|
echo |
||||
|
exit 1 |
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
# |
||||
|
# Husky Pre-push Hook |
||||
|
# Runs Build Architecture Guard to check commits being pushed |
||||
|
# |
||||
|
. "$(dirname -- "$0")/_/husky.sh" |
||||
|
|
||||
|
echo "🔍 Running Build Architecture Guard (pre-push)..." |
||||
|
|
||||
|
# Get the remote branch we're pushing to |
||||
|
REMOTE_BRANCH="origin/$(git rev-parse --abbrev-ref HEAD)" |
||||
|
|
||||
|
# Check if remote branch exists |
||||
|
if git show-ref --verify --quiet "refs/remotes/$REMOTE_BRANCH"; then |
||||
|
RANGE="$REMOTE_BRANCH...HEAD" |
||||
|
else |
||||
|
# If remote branch doesn't exist, check last commit |
||||
|
RANGE="HEAD~1..HEAD" |
||||
|
fi |
||||
|
|
||||
|
bash ./scripts/build-arch-guard.sh --range "$RANGE" || { |
||||
|
echo |
||||
|
echo "💡 To bypass this check for emergency pushes, use:" |
||||
|
echo " git push --no-verify" |
||||
|
echo |
||||
|
exit 1 |
||||
|
} |
File diff suppressed because it is too large
@ -0,0 +1,290 @@ |
|||||
|
# Build Architecture Guard - Husky Implementation |
||||
|
|
||||
|
## Overview |
||||
|
|
||||
|
The Build Architecture Guard protects your build system by enforcing |
||||
|
documentation requirements through **Git hooks**. When you modify |
||||
|
build-critical files, the system automatically blocks commits/pushes |
||||
|
until you update `BUILDING.md`. |
||||
|
|
||||
|
## 🎯 **Why Husky-Only?** |
||||
|
|
||||
|
**Advantages:** |
||||
|
|
||||
|
- ✅ **Immediate feedback** - Hooks run before commit/push |
||||
|
- ✅ **Works everywhere** - No server-side CI/CD required |
||||
|
- ✅ **Simple setup** - One tool, one configuration |
||||
|
- ✅ **Fast execution** - No network delays or server queues |
||||
|
- ✅ **Offline support** - Works without internet connection |
||||
|
|
||||
|
**Trade-offs:** |
||||
|
|
||||
|
- ⚠️ **Can be bypassed** - `git commit --no-verify` or `git push --no-verify` |
||||
|
- ⚠️ **Developer discipline** - Relies on team following the rules |
||||
|
|
||||
|
## 🏗️ **Architecture** |
||||
|
|
||||
|
```bash |
||||
|
Developer Workflow: |
||||
|
1. Modify build files (scripts/, vite.config.*, etc.) |
||||
|
2. Try to commit → Husky pre-commit hook runs |
||||
|
3. Guard script checks if BUILDING.md was updated |
||||
|
4. ✅ Commit succeeds if docs updated |
||||
|
5. ❌ Commit blocked if docs missing |
||||
|
``` |
||||
|
|
||||
|
## 🚀 **Quick Start** |
||||
|
|
||||
|
### 1. Install Dependencies |
||||
|
|
||||
|
```bash |
||||
|
npm install |
||||
|
npm run prepare # Sets up Husky hooks |
||||
|
``` |
||||
|
|
||||
|
### 2. Test the System |
||||
|
|
||||
|
```bash |
||||
|
# Modify a build file without updating BUILDING.md |
||||
|
echo "# test" >> scripts/test.sh |
||||
|
|
||||
|
# Try to commit (should be blocked) |
||||
|
git add scripts/test.sh |
||||
|
git commit -m "test: add build script" |
||||
|
# ❌ Hook blocks commit with helpful message |
||||
|
``` |
||||
|
|
||||
|
### 3. Fix and Retry |
||||
|
|
||||
|
```bash |
||||
|
# Update BUILDING.md with your changes |
||||
|
echo "## New Build Script" >> BUILDING.md |
||||
|
echo "Added test.sh for testing purposes" >> BUILDING.md |
||||
|
|
||||
|
# Now commit should succeed |
||||
|
git add BUILDING.md |
||||
|
git commit -m "feat: add test build script with docs" |
||||
|
# ✅ Commit succeeds |
||||
|
``` |
||||
|
|
||||
|
## 🔧 **How It Works** |
||||
|
|
||||
|
### Pre-commit Hook (`.husky/pre-commit`) |
||||
|
|
||||
|
- **When**: Every `git commit` |
||||
|
- **What**: Runs `./scripts/build-arch-guard.sh --staged` |
||||
|
- **Result**: Blocks commit if build files changed without BUILDING.md update |
||||
|
|
||||
|
### Pre-push Hook (`.husky/pre-push`) |
||||
|
|
||||
|
- **When**: Every `git push` |
||||
|
- **What**: Runs `./scripts/build-arch-guard.sh --range` |
||||
|
- **Result**: Blocks push if commits contain undocumented build changes |
||||
|
|
||||
|
### Guard Script (`scripts/build-arch-guard.sh`) |
||||
|
|
||||
|
- **Detects**: Changes to build-sensitive file patterns |
||||
|
- **Validates**: BUILDING.md was updated alongside changes |
||||
|
- **Reports**: Clear error messages with guidance |
||||
|
|
||||
|
## 📁 **Protected File Patterns** |
||||
|
|
||||
|
The guard script monitors these paths for changes: |
||||
|
|
||||
|
```text |
||||
|
Build Configuration: |
||||
|
├── vite.config.* # Vite configuration |
||||
|
├── capacitor.config.ts # Capacitor configuration |
||||
|
├── package.json # Package configuration |
||||
|
├── package-lock.json # Lock files |
||||
|
├── yarn.lock |
||||
|
└── pnpm-lock.yaml |
||||
|
|
||||
|
Build Scripts: |
||||
|
├── scripts/** # All build and automation scripts |
||||
|
├── electron/** # Electron build files |
||||
|
├── android/** # Android build configuration |
||||
|
├── ios/** # iOS build configuration |
||||
|
├── sw_scripts/** # Service worker scripts |
||||
|
└── sw_combine.js # Service worker combination |
||||
|
|
||||
|
Deployment: |
||||
|
├── Dockerfile # Docker configuration |
||||
|
└── docker/** # Docker services |
||||
|
``` |
||||
|
|
||||
|
## 🎭 **Usage Scenarios** |
||||
|
|
||||
|
### Scenario 1: Adding a New Build Script |
||||
|
|
||||
|
```bash |
||||
|
# ❌ This will be blocked |
||||
|
echo '#!/bin/bash' > scripts/new-build.sh |
||||
|
git add scripts/new-build.sh |
||||
|
git commit -m "feat: add new build script" |
||||
|
# Hook blocks: "Build-sensitive files changed but BUILDING.md not updated" |
||||
|
|
||||
|
# ✅ This will succeed |
||||
|
echo '#!/bin/bash' > scripts/new-build.sh |
||||
|
echo '## New Build Script' >> BUILDING.md |
||||
|
echo 'Added new-build.sh for feature X' >> BUILDING.md |
||||
|
git add scripts/new-build.sh BUILDING.md |
||||
|
git commit -m "feat: add new build script with docs" |
||||
|
# ✅ Commit succeeds |
||||
|
``` |
||||
|
|
||||
|
### Scenario 2: Updating Vite Configuration |
||||
|
|
||||
|
```bash |
||||
|
# ❌ This will be blocked |
||||
|
echo 'export default { newOption: true }' >> vite.config.ts |
||||
|
git add vite.config.ts |
||||
|
git commit -m "config: add new vite option" |
||||
|
# Hook blocks: "Build-sensitive files changed but BUILDING.md not updated" |
||||
|
|
||||
|
# ✅ This will succeed |
||||
|
echo 'export default { newOption: true }' >> vite.config.ts |
||||
|
echo '### New Vite Option' >> BUILDING.md |
||||
|
echo 'Added newOption for improved performance' >> BUILDING.md |
||||
|
git add vite.config.ts BUILDING.md |
||||
|
git commit -m "config: add new vite option with docs" |
||||
|
# ✅ Commit succeeds |
||||
|
``` |
||||
|
|
||||
|
## 🚨 **Emergency Bypass** |
||||
|
|
||||
|
**⚠️ Use sparingly and only for emergencies:** |
||||
|
|
||||
|
```bash |
||||
|
# Skip pre-commit hook |
||||
|
git commit -m "emergency: critical fix" --no-verify |
||||
|
|
||||
|
# Skip pre-push hook |
||||
|
git push --no-verify |
||||
|
|
||||
|
# Remember to update BUILDING.md later! |
||||
|
``` |
||||
|
|
||||
|
## 🔍 **Troubleshooting** |
||||
|
|
||||
|
### Hooks Not Running |
||||
|
|
||||
|
```bash |
||||
|
# Reinstall hooks |
||||
|
npm run prepare |
||||
|
|
||||
|
# Check hook files exist and are executable |
||||
|
ls -la .husky/ |
||||
|
chmod +x .husky/* |
||||
|
|
||||
|
# Verify Git hooks path |
||||
|
git config core.hooksPath |
||||
|
# Should show: .husky |
||||
|
``` |
||||
|
|
||||
|
### Guard Script Issues |
||||
|
|
||||
|
```bash |
||||
|
# Test guard script manually |
||||
|
./scripts/build-arch-guard.sh --help |
||||
|
|
||||
|
# Check script permissions |
||||
|
chmod +x scripts/build-arch-guard.sh |
||||
|
|
||||
|
# Test with specific files |
||||
|
./scripts/build-arch-guard.sh --staged |
||||
|
``` |
||||
|
|
||||
|
### False Positives |
||||
|
|
||||
|
```bash |
||||
|
# If guard blocks legitimate changes, check: |
||||
|
# 1. Are you modifying a protected file pattern? |
||||
|
# 2. Did you update BUILDING.md? |
||||
|
# 3. Is BUILDING.md staged for commit? |
||||
|
|
||||
|
# View what the guard sees |
||||
|
git diff --name-only --cached |
||||
|
``` |
||||
|
|
||||
|
## 📋 **Best Practices** |
||||
|
|
||||
|
### For Developers |
||||
|
|
||||
|
1. **Update BUILDING.md first** - Document changes before implementing |
||||
|
2. **Test locally** - Run `./scripts/build-arch-guard.sh --staged` before committing |
||||
|
3. **Use descriptive commits** - Include context about build changes |
||||
|
4. **Don't bypass lightly** - Only use `--no-verify` for true emergencies |
||||
|
|
||||
|
### For Teams |
||||
|
|
||||
|
1. **Document the system** - Ensure everyone understands the guard |
||||
|
2. **Review BUILDING.md updates** - Verify documentation quality |
||||
|
3. **Monitor bypass usage** - Track when hooks are skipped |
||||
|
4. **Regular audits** - Check that BUILDING.md stays current |
||||
|
|
||||
|
### For Maintainers |
||||
|
|
||||
|
1. **Update protected patterns** - Modify `scripts/build-arch-guard.sh` as needed |
||||
|
2. **Monitor effectiveness** - Track how often the guard catches issues |
||||
|
3. **Team training** - Help developers understand the system |
||||
|
4. **Continuous improvement** - Refine patterns and error messages |
||||
|
|
||||
|
## 🔄 **Customization** |
||||
|
|
||||
|
### Adding New Protected Paths |
||||
|
|
||||
|
Edit `scripts/build-arch-guard.sh`: |
||||
|
|
||||
|
```bash |
||||
|
SENSITIVE=( |
||||
|
# ... existing patterns ... |
||||
|
"new-pattern/**" # Add your new pattern |
||||
|
"*.config.js" # Add file extensions |
||||
|
) |
||||
|
``` |
||||
|
|
||||
|
### Modifying Error Messages |
||||
|
|
||||
|
Edit the guard script to customize: |
||||
|
|
||||
|
- Error message content |
||||
|
- File pattern matching |
||||
|
- Documentation requirements |
||||
|
- Bypass instructions |
||||
|
|
||||
|
### Adding New Validation Rules |
||||
|
|
||||
|
Extend the guard script to check for: |
||||
|
|
||||
|
- Specific file content patterns |
||||
|
- Required documentation sections |
||||
|
- Commit message formats |
||||
|
- Branch naming conventions |
||||
|
|
||||
|
## 📚 **Integration with PR Template** |
||||
|
|
||||
|
The `pull_request_template.md` works with this system by: |
||||
|
|
||||
|
- **Guiding developers** through required documentation |
||||
|
- **Ensuring consistency** across all build changes |
||||
|
- **Providing checklist** for comprehensive updates |
||||
|
- **Supporting L1/L2/L3** change classification |
||||
|
|
||||
|
## 🎯 **Success Metrics** |
||||
|
|
||||
|
Track the effectiveness of your Build Architecture Guard: |
||||
|
|
||||
|
- **Hook execution rate** - How often hooks run successfully |
||||
|
- **Bypass frequency** - How often `--no-verify` is used |
||||
|
- **Documentation quality** - BUILDING.md stays current |
||||
|
- **Build failures** - Fewer issues from undocumented changes |
||||
|
- **Team adoption** - Developers follow the process |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Status**: Active protection system |
||||
|
**Architecture**: Client-side Git hooks only |
||||
|
**Dependencies**: Husky, Git, Bash |
||||
|
**Maintainer**: Development team |
||||
|
**Related**: `pull_request_template.md`, `scripts/build-arch-guard.sh` |
@ -0,0 +1,82 @@ |
|||||
|
# Pull Request Template |
||||
|
|
||||
|
## Location |
||||
|
|
||||
|
The Build Architecture Guard PR template is located at: |
||||
|
|
||||
|
- **`pull_request_template.md`** (root directory) |
||||
|
|
||||
|
## Usage |
||||
|
|
||||
|
When creating a pull request in Gitea, this template will automatically populate the PR description with the required checklist. |
||||
|
|
||||
|
## Template Features |
||||
|
|
||||
|
### Change Level Classification |
||||
|
|
||||
|
- **L1**: Minor changes, documentation updates |
||||
|
- **L2**: Moderate changes, new features, environment changes |
||||
|
- **L3**: Major changes, architecture changes, new platforms |
||||
|
|
||||
|
### Required Fields for All Levels |
||||
|
|
||||
|
- Change level selection |
||||
|
- Scope and impact description |
||||
|
- Commands executed and their output |
||||
|
- Documentation updates (BUILDING.md) |
||||
|
- Rollback verification steps |
||||
|
|
||||
|
### Additional Requirements for L3 |
||||
|
|
||||
|
- **ADR link**: Must provide URL to Architectural Decision Record |
||||
|
- **Artifacts with SHA256**: Must list artifacts with cryptographic hashes |
||||
|
|
||||
|
## Integration |
||||
|
|
||||
|
This template works with: |
||||
|
|
||||
|
- **Gitea Actions**: `.gitea/workflows/build-guard.yml` |
||||
|
- **Client-side hooks**: `.husky/` pre-commit and pre-push hooks |
||||
|
- **Guard script**: `scripts/build-arch-guard.sh` |
||||
|
|
||||
|
## Example Usage |
||||
|
|
||||
|
```markdown |
||||
|
### Change Level |
||||
|
- [x] Level: **L2** |
||||
|
|
||||
|
**Why:** Adding new build script for Docker deployment |
||||
|
|
||||
|
### Scope & Impact |
||||
|
- [x] Files & platforms touched: scripts/build-docker.sh, |
||||
|
BUILDING.md |
||||
|
- [x] Risk triggers: Docker build process changes |
||||
|
- [x] Mitigations/validation done: Tested on local Docker environment |
||||
|
|
||||
|
### Commands Run |
||||
|
- [x] Web: `npm run build:web:docker` ✅ |
||||
|
- [x] Docker: `docker build -t test-image .` ✅ |
||||
|
|
||||
|
### Artifacts |
||||
|
- [x] Names + **sha256** of artifacts/installers: |
||||
|
|
||||
|
Artifacts: |
||||
|
```text |
||||
|
test-image.tar a1b2c3d4e5f6... |
||||
|
``` |
||||
|
|
||||
|
### Docs |
||||
|
- [x] **BUILDING.md** updated (sections): Docker deployment |
||||
|
- [x] Troubleshooting updated: Added Docker troubleshooting section |
||||
|
|
||||
|
### Rollback |
||||
|
- [x] Verified steps to restore previous behavior: |
||||
|
1. `git revert HEAD` |
||||
|
2. `docker rmi test-image` |
||||
|
3. Restore previous BUILDING.md |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Note**: This template is enforced by the Build Architecture Guard |
||||
|
system. Complete all required fields to ensure your PR can be merged. |
@ -1,243 +1,118 @@ |
|||||
# TimeSafari.app - Crowd-Funder for Time - PWA |
# Time Safari Application |
||||
|
|
||||
[Time Safari](https://timesafari.org/) allows people to ease into collaboration: start with expressions of gratitude |
**Author**: Matthew Raymer |
||||
and expand to crowd-fund with time & money, then record and see the impact of contributions. |
**Version**: 1.0.8-beta |
||||
|
**Description**: Time Safari Application |
||||
|
|
||||
## Roadmap |
## 🛡️ Build Architecture Guard |
||||
|
|
||||
See [ClickUp](https://sharing.clickup.com/9014278710/l/h/8cmnyhp-174/10573fec74e2ba0) for current priorities. |
This project uses **Husky Git hooks** to protect the build system |
||||
|
architecture. When you modify build-critical files, the system |
||||
|
automatically blocks commits until you update `BUILDING.md`. |
||||
|
|
||||
## Setup & Building |
### Quick Setup |
||||
|
|
||||
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. |
|
||||
|
|
||||
```bash |
|
||||
npm install |
|
||||
npm run build:web:serve -- --test |
|
||||
``` |
|
||||
|
|
||||
To be able to make submissions: go to "profile" (bottom left), go to the bottom and expand "Show Advanced Settings", go to the bottom and to the "Test Page", and finally "Become User 0" to see all the functionality. |
|
||||
|
|
||||
See [BUILDING.md](BUILDING.md) for comprehensive build instructions for all platforms (Web, Electron, iOS, Android, Docker). |
|
||||
|
|
||||
## Development Database Clearing |
|
||||
|
|
||||
TimeSafari provides a simple script-based approach to clear the local database (not the claim server) for development purposes. |
|
||||
|
|
||||
## Logging Configuration |
|
||||
|
|
||||
TimeSafari supports configurable logging levels via the `VITE_LOG_LEVEL` environment variable. This allows developers to control console output verbosity without modifying code. |
|
||||
|
|
||||
### Quick Usage |
|
||||
|
|
||||
```bash |
```bash |
||||
# Show only errors |
npm run guard:setup # Install and activate the guard |
||||
VITE_LOG_LEVEL=error npm run dev |
|
||||
|
|
||||
# Show warnings and errors |
|
||||
VITE_LOG_LEVEL=warn npm run dev |
|
||||
|
|
||||
# Show info, warnings, and errors (default) |
|
||||
VITE_LOG_LEVEL=info npm run dev |
|
||||
|
|
||||
# Show all log levels including debug |
|
||||
VITE_LOG_LEVEL=debug npm run dev |
|
||||
``` |
``` |
||||
|
|
||||
### Available Levels |
### How It Works |
||||
|
|
||||
- **`error`**: Critical errors only |
- **Pre-commit**: Blocks commits if build files changed without |
||||
- **`warn`**: Warnings and errors (default for production web) |
BUILDING.md updates |
||||
- **`info`**: Info, warnings, and errors (default for development/capacitor) |
- **Pre-push**: Blocks pushes if commits contain undocumented build |
||||
- **`debug`**: All log levels including verbose debugging |
changes |
||||
|
- **Protected paths**: `scripts/`, `vite.config.*`, `electron/`, |
||||
|
`android/`, `ios/`, etc. |
||||
|
|
||||
See [Logging Configuration Guide](doc/logging-configuration.md) for complete details. |
### Usage |
||||
|
|
||||
### Quick Usage |
|
||||
```bash |
```bash |
||||
# Run the database clearing script |
# Test the guard manually |
||||
./scripts/clear-database.sh |
npm run guard:test |
||||
|
|
||||
# Then restart your development server |
# Emergency bypass (use sparingly) |
||||
npm run build:electron:dev # For Electron |
git commit --no-verify |
||||
npm run build:web:dev # For Web |
git push --no-verify |
||||
``` |
``` |
||||
|
|
||||
### What It Does |
**📚 Full documentation**: See `README-BUILD-GUARD.md` |
||||
|
|
||||
#### **Electron (Desktop App)** |
## 🚀 Quick Start |
||||
- Automatically finds and clears the SQLite database files |
|
||||
- Works on Linux, macOS, and Windows |
|
||||
- Clears all data and forces fresh migrations on next startup |
|
||||
|
|
||||
#### **Web Browser** |
### Prerequisites |
||||
- Provides instructions for using custom browser data directories |
|
||||
- Shows manual clearing via browser DevTools |
|
||||
- Ensures reliable database clearing without browser complications |
|
||||
|
|
||||
### Safety Features |
- Node.js 18+ |
||||
- ✅ **Interactive Script**: Guides you through the process |
- npm, yarn, or pnpm |
||||
- ✅ **Platform Detection**: Automatically detects your OS |
- Git |
||||
- ✅ **Clear Instructions**: Step-by-step guidance for each platform |
|
||||
- ✅ **Safe Paths**: Only clears TimeSafari-specific data |
|
||||
|
|
||||
### Manual Commands (if needed) |
### Installation |
||||
|
|
||||
#### **Electron Database Location** |
|
||||
```bash |
```bash |
||||
# Linux |
npm install |
||||
rm -rf ~/.config/TimeSafari/* |
npm run guard:setup # Sets up Build Architecture Guard |
||||
|
|
||||
# macOS |
|
||||
rm -rf ~/Library/Application\ Support/TimeSafari/* |
|
||||
|
|
||||
# Windows |
|
||||
rmdir /s /q %APPDATA%\TimeSafari |
|
||||
``` |
|
||||
|
|
||||
#### **Web Browser (Custom Data Directory)** |
|
||||
```bash |
|
||||
# Create isolated browser profile |
|
||||
mkdir ~/timesafari-dev-data |
|
||||
``` |
``` |
||||
|
|
||||
## Domain Configuration |
### Development |
||||
|
|
||||
TimeSafari uses a centralized domain configuration system to ensure consistent |
|
||||
URL generation across all environments. This prevents localhost URLs from |
|
||||
appearing in shared links during development. |
|
||||
|
|
||||
### Key Features |
|
||||
- ✅ **Production URLs for Sharing**: All copy link buttons use production domain |
|
||||
- ✅ **Environment-Specific Internal URLs**: Internal operations use appropriate |
|
||||
environment URLs |
|
||||
- ✅ **Single Point of Control**: Change domain in one place for entire app |
|
||||
- ✅ **Type-Safe Configuration**: Full TypeScript support |
|
||||
|
|
||||
### Quick Reference |
|
||||
|
|
||||
```typescript |
|
||||
// For sharing functionality (environment-specific) |
|
||||
import { APP_SERVER } from "@/constants/app"; |
|
||||
const shareLink = `${APP_SERVER}/deep-link/claim/123`; |
|
||||
|
|
||||
// For internal operations (environment-specific) |
```bash |
||||
import { APP_SERVER } from "@/constants/app"; |
npm run build:web:dev # Build web version |
||||
const apiUrl = `${APP_SERVER}/api/claim/123`; |
npm run build:ios:test # Build iOS test version |
||||
|
npm run build:android:test # Build Android test version |
||||
|
npm run build:electron:dev # Build Electron dev version |
||||
``` |
``` |
||||
|
|
||||
### Documentation |
### Testing |
||||
|
|
||||
- [Constants and Configuration](src/constants/app.ts) - Core constants |
|
||||
|
|
||||
## Tests |
|
||||
|
|
||||
See [TESTING.md](test-playwright/TESTING.md) for detailed test instructions. |
|
||||
|
|
||||
## Asset Management |
|
||||
|
|
||||
TimeSafari uses a standardized asset configuration system for consistent |
|
||||
icon and splash screen generation across all platforms. |
|
||||
|
|
||||
### Asset Sources |
|
||||
|
|
||||
- **Single source of truth**: `resources/` directory (Capacitor default) |
|
||||
- **Source files**: `icon.png`, `splash.png`, `splash_dark.png` |
|
||||
- **Format**: PNG or SVG files for optimal quality |
|
||||
|
|
||||
### Asset Generation |
|
||||
|
|
||||
- **Configuration**: `config/assets/capacitor-assets.config.json` |
|
||||
- **Schema validation**: `config/assets/schema.json` |
|
||||
- **Build-time generation**: Platform assets generated via `capacitor-assets` |
|
||||
- **No VCS commits**: Generated assets are never committed to version control |
|
||||
|
|
||||
### Development Commands |
|
||||
|
|
||||
```bash |
```bash |
||||
# Generate/update asset configurations |
npm run test:web # Run web tests |
||||
npm run assets:config |
npm run test:mobile # Run mobile tests |
||||
|
npm run test:all # Run all tests |
||||
# Validate asset configurations |
|
||||
npm run assets:validate |
|
||||
|
|
||||
# Clean generated platform assets (local dev only) |
|
||||
npm run assets:clean |
|
||||
|
|
||||
# Build with asset generation |
|
||||
npm run build:native |
|
||||
``` |
``` |
||||
|
|
||||
### Platform Support |
## 📁 Project Structure |
||||
|
|
||||
- **Android**: Adaptive icons with foreground/background, monochrome support |
```text |
||||
- **iOS**: LaunchScreen storyboard preferred, splash assets when needed |
timesafari/ |
||||
- **Web**: PWA icons generated during build to `dist/` (not committed) |
├── 📁 src/ # Source code |
||||
|
├── 📁 scripts/ # Build and automation scripts |
||||
### Font Awesome Icons |
├── 📁 electron/ # Electron configuration |
||||
|
├── 📁 android/ # Android configuration |
||||
To add a Font Awesome icon, add to `fontawesome.ts` and reference with |
├── 📁 ios/ # iOS configuration |
||||
`font-awesome` element and `icon` attribute with the hyphenated name. |
├── 📁 .husky/ # Git hooks (Build Architecture Guard) |
||||
|
├── 📄 BUILDING.md # Build system documentation |
||||
## Other |
├── 📄 pull_request_template.md # PR template |
||||
|
└── 📄 README-BUILD-GUARD.md # Guard system documentation |
||||
### Reference Material |
``` |
||||
|
|
||||
* Notifications can be type of `toast` (self-dismiss), `info`, `success`, `warning`, and `danger`. |
|
||||
They are done via [notiwind](https://www.npmjs.com/package/notiwind) and set up in App.vue. |
|
||||
|
|
||||
* [Customize Vue configuration](https://cli.vuejs.org/config/). |
|
||||
|
|
||||
* If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js, eg: `publicPath: "/app/time-tracker/",` |
|
||||
|
|
||||
### Code Organization |
|
||||
|
|
||||
The project uses a centralized approach to type definitions and interfaces: |
|
||||
|
|
||||
* `src/interfaces/` - Contains all TypeScript interfaces and type definitions |
## 🔧 Build System |
||||
* `deepLinks.ts` - Deep linking type system and Zod validation schemas |
|
||||
* `give.ts` - Give-related interfaces and type definitions |
|
||||
* `claims.ts` - Claim-related interfaces and verifiable credentials |
|
||||
* `common.ts` - Shared interfaces and utility types |
|
||||
* Other domain-specific interface files |
|
||||
|
|
||||
Key principles: |
This project supports multiple platforms: |
||||
- All interfaces and types are defined in the interfaces folder |
|
||||
- Zod schemas are used for runtime validation and type generation |
|
||||
- Domain-specific interfaces are separated into their own files |
|
||||
- Common interfaces are shared through `common.ts` |
|
||||
- Type definitions are generated from Zod schemas where possible |
|
||||
|
|
||||
### Database Architecture |
- **Web**: Vite-based build with service worker support |
||||
|
- **Mobile**: Capacitor-based iOS and Android builds |
||||
|
- **Desktop**: Electron-based cross-platform desktop app |
||||
|
- **Docker**: Containerized deployment options |
||||
|
|
||||
The application uses a platform-agnostic database layer with Vue mixins for service access: |
## 📚 Documentation |
||||
|
|
||||
* `src/services/PlatformService.ts` - Database interface definition |
- **`BUILDING.md`** - Complete build system guide |
||||
* `src/services/PlatformServiceFactory.ts` - Platform-specific service factory |
- **`README-BUILD-GUARD.md`** - Build Architecture Guard documentation |
||||
* `src/services/AbsurdSqlDatabaseService.ts` - SQLite implementation |
- **`pull_request_template.md`** - PR template for build changes |
||||
* `src/utils/PlatformServiceMixin.ts` - Vue mixin for database access with caching |
|
||||
* `src/db/` - Legacy Dexie database (migration in progress) |
|
||||
|
|
||||
**Development Guidelines**: |
## 🤝 Contributing |
||||
|
|
||||
- Always use `PlatformServiceMixin` for database operations in components |
1. **Follow the Build Architecture Guard** - Update BUILDING.md when modifying build files |
||||
- Test with PlatformServiceMixin for new features |
2. **Use the PR template** - Complete the checklist for build-related changes |
||||
- Use migration tools for data transfer between systems |
3. **Test your changes** - Ensure builds work on affected platforms |
||||
- Leverage mixin's ultra-concise methods: `$db()`, `$exec()`, `$one()`, `$contacts()`, `$settings()` |
4. **Document updates** - Keep BUILDING.md current and accurate |
||||
|
|
||||
**Architecture Decision**: The project uses Vue mixins over Composition API composables for platform service access. See [Architecture Decisions](doc/architecture-decisions.md) for detailed rationale. |
## 📄 License |
||||
|
|
||||
### Kudos |
[Add your license information here] |
||||
|
|
||||
Gifts make the world go 'round! |
--- |
||||
|
|
||||
* [WebStorm by JetBrains](https://www.jetbrains.com/webstorm/) for the free open-source license |
**Note**: The Build Architecture Guard is active and will block |
||||
* [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) |
commits/pushes that modify build files without proper documentation |
||||
* [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 |
updates. See `README-BUILD-GUARD.md` for complete details. |
||||
* [Bush 3D model](https://sketchfab.com/3d-models/lupine-plant-bf30f1110c174d4baedda0ed63778439) |
|
||||
* [Forest floor image](https://www.goodfreephotos.com/albums/textures/leafy-autumn-forest-floor.jpg) |
|
||||
* Time Safari logo assisted by [DALL-E in ChatGPT](https://chat.openai.com/g/g-2fkFE8rbu-dall-e) |
|
||||
* [DiceBear](https://www.dicebear.com/licenses/) and [Avataaars](https://www.dicebear.com/styles/avataaars/#details) for human-looking identicons |
|
||||
* Some gratitude prompts thanks to [Develop Good Habits](https://www.developgoodhabits.com/gratitude-journal-prompts/) |
|
||||
|
@ -0,0 +1,187 @@ |
|||||
|
# TimeSafari Debug Hook Guide |
||||
|
|
||||
|
**Complete Guide for Team Members** |
||||
|
|
||||
|
**Date**: 2025-01-27 |
||||
|
**Author**: Matthew Raymer |
||||
|
**Status**: ✅ **ACTIVE** - Ready for production use |
||||
|
|
||||
|
## 🎯 Overview |
||||
|
|
||||
|
A pre-commit hook that automatically detects and prevents debug code from reaching protected branches (master, main, production, release, stable). This ensures production code remains clean while allowing free development on feature branches. |
||||
|
|
||||
|
## 🚀 Quick Installation |
||||
|
|
||||
|
**From within the TimeSafari repository:** |
||||
|
|
||||
|
```bash |
||||
|
./scripts/install-debug-hook.sh |
||||
|
``` |
||||
|
|
||||
|
This automatically installs, updates, and verifies the hook in your current |
||||
|
repository. **Note**: Hooks are not automatically installed - you must run this |
||||
|
script deliberately to enable debug code checking. |
||||
|
|
||||
|
## 🔧 Manual Installation |
||||
|
|
||||
|
**Copy files manually:** |
||||
|
|
||||
|
```bash |
||||
|
cp scripts/git-hooks/pre-commit /path/to/your/repo/.git/hooks/ |
||||
|
cp scripts/git-hooks/debug-checker.config /path/to/your/repo/.git/hooks/ |
||||
|
chmod +x /path/to/your/repo/.git/hooks/pre-commit |
||||
|
``` |
||||
|
|
||||
|
## 📋 What Gets Installed |
||||
|
|
||||
|
- **`pre-commit`** - Main hook script (executable) |
||||
|
- **`debug-checker.config`** - Configuration file |
||||
|
- **`README.md`** - Documentation and troubleshooting |
||||
|
|
||||
|
**Note**: Hooks are stored in `scripts/git-hooks/` and must be deliberately |
||||
|
installed by each developer. They are not automatically active. |
||||
|
|
||||
|
## 🎯 How It Works |
||||
|
|
||||
|
1. **Deliberate Installation**: Hooks must be explicitly installed by each |
||||
|
developer |
||||
|
2. **Branch Detection**: Only runs on protected branches |
||||
|
3. **File Filtering**: Automatically skips tests, scripts, and documentation |
||||
|
4. **Pattern Matching**: Detects debug code using regex patterns |
||||
|
5. **Commit Prevention**: Blocks commits containing debug code |
||||
|
|
||||
|
## 🔒 Installation Philosophy |
||||
|
|
||||
|
**Why deliberate installation?** |
||||
|
|
||||
|
- **Developer choice**: Each developer decides whether to use the hook |
||||
|
- **No forced behavior**: Hooks don't interfere with existing workflows |
||||
|
- **Local control**: Hooks are installed locally, not globally |
||||
|
- **Easy removal**: Can be uninstalled at any time |
||||
|
- **Team flexibility**: Some developers may prefer different tools |
||||
|
|
||||
|
## 🌿 Branch Behavior |
||||
|
|
||||
|
- **Protected branches** (master, main, production, release, stable): Hook runs automatically |
||||
|
- **Feature branches**: Hook is skipped, allowing free development with debug code |
||||
|
|
||||
|
## 🔍 Debug Patterns Detected |
||||
|
|
||||
|
- **Console statements**: `console.log`, `console.debug`, `console.error` |
||||
|
- **Template debug**: `Debug:`, `debug:` in Vue templates |
||||
|
- **Debug constants**: `DEBUG_`, `debug_` variables |
||||
|
- **HTML debug**: `<!-- debug` comments |
||||
|
- **Debug attributes**: `debug="true"` attributes |
||||
|
- **Vue debug**: `v-if="debug"`, `v-show="debug"` |
||||
|
- **Debug TODOs**: `TODO debug`, `FIXME debug` |
||||
|
|
||||
|
## 📁 Files Automatically Skipped |
||||
|
|
||||
|
- Test files: `*.test.js`, `*.spec.ts`, `*.test.vue` |
||||
|
- Scripts: `scripts/` directory |
||||
|
- Test directories: `test-*` directories |
||||
|
- Documentation: `docs/`, `*.md`, `*.txt` |
||||
|
- Config files: `*.json`, `*.yml`, `*.yaml` |
||||
|
- IDE files: `.cursor/` directory |
||||
|
|
||||
|
## ✅ Verification |
||||
|
|
||||
|
**After installation, verify it's working:** |
||||
|
|
||||
|
```bash |
||||
|
# Check if files exist |
||||
|
ls -la .git/hooks/pre-commit |
||||
|
ls -la .git/hooks/debug-checker.config |
||||
|
|
||||
|
# Test the hook manually |
||||
|
.git/hooks/pre-commit |
||||
|
|
||||
|
# Test with actual commit |
||||
|
echo "console.log('test')" > test.vue |
||||
|
git add test.vue |
||||
|
git commit -m "test" # Should be blocked |
||||
|
``` |
||||
|
|
||||
|
## 📊 Example Output |
||||
|
|
||||
|
``` |
||||
|
❌ Debug code detected in staged files! |
||||
|
Branch: master |
||||
|
Files checked: 1 |
||||
|
Errors found: 3 |
||||
|
|
||||
|
🚨 AccountViewView.vue: Found debug pattern 'console\.' |
||||
|
🚨 AccountViewView.vue: Found debug pattern 'Debug:' |
||||
|
🚨 AccountViewView.vue: Found debug pattern 'DEBUG_' |
||||
|
|
||||
|
💡 Please remove debug code before committing to master |
||||
|
``` |
||||
|
|
||||
|
## ⚙️ Configuration |
||||
|
|
||||
|
Edit `.git/hooks/debug-checker.config` to customize: |
||||
|
|
||||
|
- **Protected branches**: Add/remove branches as needed |
||||
|
- **Debug patterns**: Customize what gets detected |
||||
|
- **Skip patterns**: Adjust file filtering rules |
||||
|
|
||||
|
## 🚨 Emergency Bypass |
||||
|
|
||||
|
If you absolutely need to commit debug code to a protected branch: |
||||
|
|
||||
|
```bash |
||||
|
git commit --no-verify -m "emergency: debug code needed" |
||||
|
``` |
||||
|
|
||||
|
⚠️ **Warning**: This bypasses all pre-commit hooks. Use sparingly. |
||||
|
|
||||
|
## 🔄 Updates |
||||
|
|
||||
|
When the hook is updated in the main repository: |
||||
|
|
||||
|
```bash |
||||
|
./scripts/install-debug-hook.sh |
||||
|
``` |
||||
|
|
||||
|
## 🚨 Troubleshooting |
||||
|
|
||||
|
| Issue | Solution | |
||||
|
|-------|----------| |
||||
|
| Hook not running | Check if on protected branch, verify permissions | |
||||
|
| Permission denied | Run `chmod +x .git/hooks/pre-commit` | |
||||
|
| Files not found | Ensure you're copying from TimeSafari repo | |
||||
|
| False positives | Edit `debug-checker.config` to customize patterns | |
||||
|
|
||||
|
## 🧪 Testing |
||||
|
|
||||
|
A test script is available at `scripts/test-debug-hook.sh` to verify the hook works correctly. |
||||
|
|
||||
|
## 💡 Best Practices |
||||
|
|
||||
|
1. **Use feature branches** for development with debug code |
||||
|
2. **Use proper logging** instead of console statements (`logger.info`, `logger.debug`) |
||||
|
3. **Test thoroughly** before merging to protected branches |
||||
|
4. **Review commits** to ensure no debug code slips through |
||||
|
5. **Keep hooks updated** across all repositories |
||||
|
|
||||
|
## 📚 Additional Resources |
||||
|
|
||||
|
- **Hook documentation**: `scripts/git-hooks/README.md` |
||||
|
- **Configuration**: `scripts/git-hooks/debug-checker.config` |
||||
|
- **Test script**: `scripts/test-debug-hook.sh` |
||||
|
- **Installation script**: `scripts/install-debug-hook.sh` |
||||
|
|
||||
|
## 🎯 Team Workflow |
||||
|
|
||||
|
**Recommended setup:** |
||||
|
|
||||
|
1. **Repository setup**: Include hook files in `.githooks/` directory |
||||
|
2. **Team onboarding**: Run installation script in each repo |
||||
|
3. **Updates**: Re-run installation script when hooks are updated |
||||
|
4. **Documentation**: Keep this guide updated |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
**Status**: Active and enforced |
||||
|
**Last Updated**: 2025-01-27 |
||||
|
**Maintainer**: Matthew Raymer |
File diff suppressed because it is too large
@ -0,0 +1,47 @@ |
|||||
|
# Build Architecture Guard PR Template |
||||
|
|
||||
|
## Change Level |
||||
|
|
||||
|
- [ ] Level: **L1** / **L2** / **L3** (pick one) |
||||
|
|
||||
|
**Why:** … |
||||
|
|
||||
|
## Scope & Impact |
||||
|
|
||||
|
- [ ] Files & platforms touched: … |
||||
|
- [ ] Risk triggers (env / script flow / packaging / SW+WASM / |
||||
|
Docker / signing): … |
||||
|
- [ ] Mitigations/validation done: … |
||||
|
|
||||
|
## Commands Run (paste exact logs/snips) |
||||
|
|
||||
|
- [ ] Web: `npm run build:web` / `:prod` |
||||
|
- [ ] Electron: `npm run build:electron:dev` / package step |
||||
|
- [ ] Mobile: `npm run build:android:test` / iOS equivalent |
||||
|
- [ ] Clean/auto-run impacted scripts |
||||
|
|
||||
|
## Artifacts |
||||
|
|
||||
|
- [ ] Names + **sha256** of artifacts/installers: |
||||
|
|
||||
|
Artifacts: |
||||
|
|
||||
|
```text |
||||
|
<name-1> <sha256-1> |
||||
|
<name-2> <sha256-2> |
||||
|
``` |
||||
|
|
||||
|
## Docs |
||||
|
|
||||
|
- [ ] **BUILDING.md** updated (sections): … |
||||
|
- [ ] Troubleshooting updated (if applicable) |
||||
|
|
||||
|
## Rollback |
||||
|
|
||||
|
- [ ] Verified steps (1–3 cmds) to restore previous behavior |
||||
|
|
||||
|
## L3 only |
||||
|
|
||||
|
- [ ] ADR link: |
||||
|
|
||||
|
ADR: https://… |
@ -0,0 +1,187 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
# |
||||
|
# Build Architecture Guard Script |
||||
|
# |
||||
|
# Author: Matthew Raymer |
||||
|
# Date: 2025-08-20 |
||||
|
# Purpose: Protects build-critical files by requiring BUILDING.md updates |
||||
|
# |
||||
|
# Usage: |
||||
|
# ./scripts/build-arch-guard.sh --staged # Check staged files (pre-commit) |
||||
|
# ./scripts/build-arch-guard.sh --range # Check range (pre-push) |
||||
|
# ./scripts/build-arch-guard.sh # Check working directory |
||||
|
# |
||||
|
|
||||
|
set -euo pipefail |
||||
|
|
||||
|
# Sensitive paths that require BUILDING.md updates when modified |
||||
|
SENSITIVE=( |
||||
|
"vite.config.*" |
||||
|
"scripts/**" |
||||
|
"electron/**" |
||||
|
"android/**" |
||||
|
"ios/**" |
||||
|
"sw_scripts/**" |
||||
|
"sw_combine.js" |
||||
|
"Dockerfile" |
||||
|
"docker/**" |
||||
|
"capacitor.config.ts" |
||||
|
"package.json" |
||||
|
"package-lock.json" |
||||
|
"yarn.lock" |
||||
|
"pnpm-lock.yaml" |
||||
|
) |
||||
|
|
||||
|
# Documentation files that must be updated alongside sensitive changes |
||||
|
DOCS_REQUIRED=("BUILDING.md") |
||||
|
|
||||
|
# Colors for output |
||||
|
RED='\033[0;31m' |
||||
|
GREEN='\033[0;32m' |
||||
|
YELLOW='\033[1;33m' |
||||
|
BLUE='\033[0;34m' |
||||
|
NC='\033[0m' # No Color |
||||
|
|
||||
|
log_info() { |
||||
|
echo -e "${BLUE}[guard]${NC} $1" |
||||
|
} |
||||
|
|
||||
|
log_warn() { |
||||
|
echo -e "${YELLOW}[guard]${NC} $1" |
||||
|
} |
||||
|
|
||||
|
log_error() { |
||||
|
echo -e "${RED}[guard]${NC} $1" |
||||
|
} |
||||
|
|
||||
|
log_success() { |
||||
|
echo -e "${GREEN}[guard]${NC} $1" |
||||
|
} |
||||
|
|
||||
|
# Collect files based on mode |
||||
|
collect_files() { |
||||
|
if [[ "${1:-}" == "--staged" ]]; then |
||||
|
# Pre-commit: check staged files |
||||
|
git diff --name-only --cached |
||||
|
elif [[ "${1:-}" == "--range" ]]; then |
||||
|
# Pre-push: check commits being pushed |
||||
|
RANGE="${2:-HEAD~1..HEAD}" |
||||
|
git diff --name-only "$RANGE" |
||||
|
else |
||||
|
# Default: check working directory changes |
||||
|
git diff --name-only HEAD |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# Check if a file matches any sensitive pattern |
||||
|
matches_sensitive() { |
||||
|
local f="$1" |
||||
|
for pat in "${SENSITIVE[@]}"; do |
||||
|
# Convert glob pattern to regex |
||||
|
local rx="^${pat//\./\.}$" |
||||
|
rx="${rx//\*\*/.*}" |
||||
|
rx="${rx//\*/[^/]*}" |
||||
|
|
||||
|
if [[ "$f" =~ $rx ]]; then |
||||
|
return 0 |
||||
|
fi |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
# Check if documentation was updated |
||||
|
check_docs_updated() { |
||||
|
local changed_files=("$@") |
||||
|
|
||||
|
for changed_file in "${changed_files[@]}"; do |
||||
|
for required_doc in "${DOCS_REQUIRED[@]}"; do |
||||
|
if [[ "$changed_file" == "$required_doc" ]]; then |
||||
|
return 0 |
||||
|
fi |
||||
|
done |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
# Main guard logic |
||||
|
main() { |
||||
|
local mode="${1:-}" |
||||
|
local arg="${2:-}" |
||||
|
|
||||
|
log_info "Running Build Architecture Guard..." |
||||
|
|
||||
|
# Collect changed files |
||||
|
mapfile -t changed_files < <(collect_files "$mode" "$arg") |
||||
|
|
||||
|
if [[ ${#changed_files[@]} -eq 0 ]]; then |
||||
|
log_info "No files changed, guard check passed" |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
log_info "Checking ${#changed_files[@]} changed files..." |
||||
|
|
||||
|
# Find sensitive files that were touched |
||||
|
sensitive_touched=() |
||||
|
for file in "${changed_files[@]}"; do |
||||
|
if matches_sensitive "$file"; then |
||||
|
sensitive_touched+=("$file") |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
# If no sensitive files were touched, allow the change |
||||
|
if [[ ${#sensitive_touched[@]} -eq 0 ]]; then |
||||
|
log_success "No build-sensitive files changed, guard check passed" |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
# Sensitive files were touched, log them |
||||
|
log_warn "Build-sensitive paths changed:" |
||||
|
for file in "${sensitive_touched[@]}"; do |
||||
|
echo " - $file" |
||||
|
done |
||||
|
|
||||
|
# Check if required documentation was updated |
||||
|
if check_docs_updated "${changed_files[@]}"; then |
||||
|
log_success "BUILDING.md updated alongside build changes, guard check passed" |
||||
|
exit 0 |
||||
|
else |
||||
|
log_error "Build-sensitive files changed but BUILDING.md was not updated!" |
||||
|
echo |
||||
|
echo "The following build-sensitive files were modified:" |
||||
|
for file in "${sensitive_touched[@]}"; do |
||||
|
echo " - $file" |
||||
|
done |
||||
|
echo |
||||
|
echo "When modifying build-critical files, you must also update BUILDING.md" |
||||
|
echo "to document any changes to the build process." |
||||
|
echo |
||||
|
echo "Please:" |
||||
|
echo " 1. Update BUILDING.md with relevant changes" |
||||
|
echo " 2. Stage the BUILDING.md changes: git add BUILDING.md" |
||||
|
echo " 3. Retry your commit/push" |
||||
|
echo |
||||
|
exit 2 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# Handle help flag |
||||
|
if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then |
||||
|
echo "Build Architecture Guard Script" |
||||
|
echo |
||||
|
echo "Usage:" |
||||
|
echo " $0 [--staged|--range [RANGE]]" |
||||
|
echo |
||||
|
echo "Options:" |
||||
|
echo " --staged Check staged files (for pre-commit hook)" |
||||
|
echo " --range [RANGE] Check git range (for pre-push hook)" |
||||
|
echo " Default range: HEAD~1..HEAD" |
||||
|
echo " (no args) Check working directory changes" |
||||
|
echo |
||||
|
echo "Examples:" |
||||
|
echo " $0 --staged # Pre-commit check" |
||||
|
echo " $0 --range origin/main..HEAD # Pre-push check" |
||||
|
echo " $0 # Working directory check" |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
main "$@" |
@ -0,0 +1,110 @@ |
|||||
|
#!/bin/bash |
||||
|
# check-dependencies.sh |
||||
|
# Author: Matthew Raymer |
||||
|
# Date: 2025-08-19 |
||||
|
# Description: Dependency validation script for TimeSafari development environment |
||||
|
# This script checks for critical dependencies required for building the application. |
||||
|
|
||||
|
# Exit on any error |
||||
|
set -e |
||||
|
|
||||
|
# Source common utilities |
||||
|
source "$(dirname "$0")/common.sh" |
||||
|
|
||||
|
print_header "TimeSafari Dependency Validation" |
||||
|
|
||||
|
log_info "Checking development environment dependencies..." |
||||
|
|
||||
|
# Check Node.js version |
||||
|
if command -v node &> /dev/null; then |
||||
|
NODE_VERSION=$(node --version) |
||||
|
log_info "Node.js version: $NODE_VERSION" |
||||
|
|
||||
|
# Extract major version number |
||||
|
MAJOR_VERSION=$(echo $NODE_VERSION | sed 's/v\([0-9]*\)\..*/\1/') |
||||
|
if [ "$MAJOR_VERSION" -lt 18 ]; then |
||||
|
log_error "Node.js version $NODE_VERSION is too old. Please upgrade to Node.js 18 or later." |
||||
|
exit 1 |
||||
|
fi |
||||
|
else |
||||
|
log_error "Node.js is not installed. Please install Node.js 18 or later." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Check npm version |
||||
|
if command -v npm &> /dev/null; then |
||||
|
NPM_VERSION=$(npm --version) |
||||
|
log_info "npm version: $NPM_VERSION" |
||||
|
else |
||||
|
log_error "npm is not installed. Please install npm." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Check if node_modules exists |
||||
|
if [ ! -d "node_modules" ]; then |
||||
|
log_error "node_modules directory not found." |
||||
|
log_info "Please run: npm install" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Check critical dependencies |
||||
|
log_info "Validating critical packages..." |
||||
|
|
||||
|
CRITICAL_DEPS=("tsx" "capacitor-assets" "vite") |
||||
|
|
||||
|
for dep in "${CRITICAL_DEPS[@]}"; do |
||||
|
if [ -f "node_modules/.bin/$dep" ]; then |
||||
|
log_success "✓ $dep found" |
||||
|
else |
||||
|
log_error "✗ $dep not found in node_modules/.bin" |
||||
|
log_info "This usually means the package wasn't installed properly." |
||||
|
log_info "Try running: npm install" |
||||
|
exit 1 |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
# Check TypeScript via npx |
||||
|
if npx tsc --version &> /dev/null; then |
||||
|
TSC_VERSION=$(npx tsc --version) |
||||
|
log_success "✓ TypeScript found: $TSC_VERSION" |
||||
|
else |
||||
|
log_error "✗ TypeScript not accessible via npx" |
||||
|
log_info "Try running: npm install" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Check Capacitor CLI |
||||
|
if command -v npx &> /dev/null; then |
||||
|
if npx cap --version &> /dev/null; then |
||||
|
CAP_VERSION=$(npx cap --version) |
||||
|
log_success "✓ Capacitor CLI version: $CAP_VERSION" |
||||
|
else |
||||
|
log_error "✗ Capacitor CLI not accessible via npx" |
||||
|
log_info "Try running: npm install @capacitor/cli" |
||||
|
exit 1 |
||||
|
fi |
||||
|
else |
||||
|
log_error "npx is not available. Please ensure npm is properly installed." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Check Android development tools |
||||
|
if command -v adb &> /dev/null; then |
||||
|
log_success "✓ Android Debug Bridge (adb) found" |
||||
|
else |
||||
|
log_warn "⚠ Android Debug Bridge (adb) not found" |
||||
|
log_info "This is only needed for Android development and testing." |
||||
|
fi |
||||
|
|
||||
|
if command -v gradle &> /dev/null; then |
||||
|
GRADLE_VERSION=$(gradle --version | head -n 1) |
||||
|
log_success "✓ Gradle found: $GRADLE_VERSION" |
||||
|
else |
||||
|
log_warn "⚠ Gradle not found in PATH" |
||||
|
log_info "This is only needed if building outside of Android Studio." |
||||
|
fi |
||||
|
|
||||
|
log_success "Dependency validation completed successfully!" |
||||
|
log_info "Your development environment is ready for TimeSafari development." |
||||
|
|
||||
|
print_footer "Dependency Validation" |
@ -0,0 +1,62 @@ |
|||||
|
#!/bin/bash |
||||
|
# clean-android.sh |
||||
|
# Author: Matthew Raymer |
||||
|
# Date: 2025-08-19 |
||||
|
# Description: Clean Android app with timeout protection to prevent hanging |
||||
|
# This script safely uninstalls the TimeSafari app from connected Android devices |
||||
|
# with a 30-second timeout to prevent indefinite hanging. |
||||
|
|
||||
|
# Exit on any error |
||||
|
set -e |
||||
|
|
||||
|
# Source common utilities |
||||
|
source "$(dirname "$0")/common.sh" |
||||
|
|
||||
|
# Function to implement timeout for systems without timeout command |
||||
|
timeout_command() { |
||||
|
local timeout_seconds="$1" |
||||
|
shift |
||||
|
|
||||
|
# Check if timeout command exists |
||||
|
if command -v timeout &> /dev/null; then |
||||
|
timeout "$timeout_seconds" "$@" |
||||
|
else |
||||
|
# Fallback for systems without timeout (like macOS) |
||||
|
# Use perl to implement timeout |
||||
|
perl -e ' |
||||
|
eval { |
||||
|
local $SIG{ALRM} = sub { die "timeout" }; |
||||
|
alarm shift; |
||||
|
system @ARGV; |
||||
|
alarm 0; |
||||
|
}; |
||||
|
if ($@) { exit 1; } |
||||
|
' "$timeout_seconds" "$@" |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
log_info "Starting Android cleanup process..." |
||||
|
|
||||
|
# Check if adb is available |
||||
|
if ! command -v adb &> /dev/null; then |
||||
|
log_error "adb command not found. Please install Android SDK Platform Tools." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Check for connected devices |
||||
|
log_info "Checking for connected Android devices..." |
||||
|
if adb devices | grep -q 'device$'; then |
||||
|
log_info "Android device(s) found. Attempting to uninstall app..." |
||||
|
|
||||
|
# Try to uninstall with timeout |
||||
|
if timeout_command 30 adb uninstall app.timesafari.app; then |
||||
|
log_success "Successfully uninstalled TimeSafari app" |
||||
|
else |
||||
|
log_warn "Uninstall failed or timed out after 30 seconds" |
||||
|
log_info "This is normal if the app wasn't installed or device is unresponsive" |
||||
|
fi |
||||
|
else |
||||
|
log_info "No Android devices connected. Skipping uninstall." |
||||
|
fi |
||||
|
|
||||
|
log_success "Android cleanup process completed" |
@ -0,0 +1,19 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
set -euo pipefail |
||||
|
|
||||
|
echo "🔧 Auto-fixing markdown formatting..." |
||||
|
|
||||
|
# Check if markdownlint is available |
||||
|
if ! command -v npx &> /dev/null; then |
||||
|
echo "❌ npx not found. Please install Node.js and npm first." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Run markdownlint with auto-fix on project markdown files (exclude node_modules) |
||||
|
echo "📝 Fixing project markdown files..." |
||||
|
npx markdownlint "*.md" "*.mdc" "scripts/**/*.md" "src/**/*.md" "test-playwright/**/*.md" "resources/**/*.md" --config .markdownlint.json --fix 2>/dev/null || { |
||||
|
echo "⚠️ Some issues could not be auto-fixed. Check manually." |
||||
|
} |
||||
|
|
||||
|
echo "✅ Markdown auto-fix complete!" |
||||
|
echo "💡 Run 'npm run markdown:check' to verify all issues are resolved." |
@ -0,0 +1,124 @@ |
|||||
|
# TimeSafari Git Hooks |
||||
|
|
||||
|
This directory contains custom Git hooks for the TimeSafari project. |
||||
|
|
||||
|
## Debug Code Checker Hook |
||||
|
|
||||
|
### Overview |
||||
|
|
||||
|
The `pre-commit` hook automatically checks for debug code when committing to protected branches (master, main, production, release). This prevents debug statements from accidentally reaching production code. |
||||
|
|
||||
|
### How It Works |
||||
|
|
||||
|
1. **Branch Detection**: Only runs on protected branches (configurable) |
||||
|
2. **File Filtering**: Automatically skips test files, scripts, and documentation |
||||
|
3. **Pattern Matching**: Detects common debug patterns using regex |
||||
|
4. **Commit Prevention**: Blocks commits containing debug code |
||||
|
|
||||
|
### Protected Branches (Default) |
||||
|
|
||||
|
- `master` |
||||
|
- `main` |
||||
|
- `production` |
||||
|
- `release` |
||||
|
- `stable` |
||||
|
|
||||
|
### Debug Patterns Detected |
||||
|
|
||||
|
- **Console statements**: `console.log`, `console.debug`, `console.error` |
||||
|
- **Template debug**: `Debug:`, `debug:` in Vue templates |
||||
|
- **Debug constants**: `DEBUG_`, `debug_` variables |
||||
|
- **HTML debug**: `<!-- debug` comments |
||||
|
- **Debug attributes**: `debug="true"` attributes |
||||
|
- **Vue debug**: `v-if="debug"`, `v-show="debug"` |
||||
|
- **Debug TODOs**: `TODO debug`, `FIXME debug` |
||||
|
|
||||
|
### Files Automatically Skipped |
||||
|
|
||||
|
- Test files: `*.test.js`, `*.spec.ts`, `*.test.vue` |
||||
|
- Scripts: `scripts/` directory |
||||
|
- Test directories: `test-*` directories |
||||
|
- Documentation: `docs/`, `*.md`, `*.txt` |
||||
|
- Config files: `*.json`, `*.yml`, `*.yaml` |
||||
|
- IDE files: `.cursor/` directory |
||||
|
|
||||
|
### Configuration |
||||
|
|
||||
|
Edit `.git/hooks/debug-checker.config` to customize: |
||||
|
|
||||
|
- Protected branches |
||||
|
- Debug patterns |
||||
|
- Skip patterns |
||||
|
- Logging level |
||||
|
|
||||
|
### Testing the Hook |
||||
|
|
||||
|
Run the test script to verify the hook works: |
||||
|
|
||||
|
```bash |
||||
|
./scripts/test-debug-hook.sh |
||||
|
``` |
||||
|
|
||||
|
### Manual Testing |
||||
|
|
||||
|
1. Make changes to a file with debug code |
||||
|
2. Stage the file: `git add <filename>` |
||||
|
3. Try to commit: `git commit -m 'test'` |
||||
|
4. Hook should prevent commit if debug code is found |
||||
|
|
||||
|
### Bypassing the Hook (Emergency) |
||||
|
|
||||
|
If you absolutely need to commit debug code to a protected branch: |
||||
|
|
||||
|
```bash |
||||
|
git commit --no-verify -m "emergency: debug code needed" |
||||
|
``` |
||||
|
|
||||
|
⚠️ **Warning**: This bypasses all pre-commit hooks. Use sparingly and only in emergencies. |
||||
|
|
||||
|
### Troubleshooting |
||||
|
|
||||
|
#### Hook not running |
||||
|
|
||||
|
- Ensure the hook is executable: `chmod +x .git/hooks/pre-commit` |
||||
|
- Check if you're on a protected branch |
||||
|
- Verify the hook file exists and has correct permissions |
||||
|
|
||||
|
#### False positives |
||||
|
|
||||
|
- Add legitimate debug patterns to skip patterns in config |
||||
|
- Use proper logging levels (`logger.info`, `logger.debug`) instead of console |
||||
|
- Move debug code to feature branches first |
||||
|
|
||||
|
#### Hook too strict |
||||
|
|
||||
|
- Modify debug patterns in config file |
||||
|
- Add more file types to skip patterns |
||||
|
- Adjust protected branch list |
||||
|
|
||||
|
### Best Practices |
||||
|
|
||||
|
1. **Use feature branches** for development with debug code |
||||
|
2. **Use proper logging** instead of console statements |
||||
|
3. **Test thoroughly** before merging to protected branches |
||||
|
4. **Review commits** to ensure no debug code slips through |
||||
|
5. **Keep config updated** as project needs change |
||||
|
|
||||
|
### Integration with CI/CD |
||||
|
|
||||
|
This hook works locally. For CI/CD pipelines, consider: |
||||
|
|
||||
|
- Running the same checks in your build process |
||||
|
- Adding ESLint rules for console statements |
||||
|
- Using TypeScript strict mode |
||||
|
- Adding debug code detection to PR checks |
||||
|
|
||||
|
### Support |
||||
|
|
||||
|
If you encounter issues: |
||||
|
|
||||
|
1. Check the hook output for specific error messages |
||||
|
2. Verify your branch is in the protected list |
||||
|
3. Review the configuration file |
||||
|
4. Test with the provided test script |
||||
|
5. Check file permissions and git setup |
@ -0,0 +1,86 @@ |
|||||
|
# TimeSafari Debug Checker Configuration |
||||
|
# Edit this file to customize protected branches and debug patterns |
||||
|
|
||||
|
# Protected branches where debug code checking is enforced |
||||
|
# Add or remove branches as needed |
||||
|
PROTECTED_BRANCHES=( |
||||
|
"master" |
||||
|
"main" |
||||
|
"production" |
||||
|
"release" |
||||
|
"stable" |
||||
|
) |
||||
|
|
||||
|
# Debug patterns to detect (regex patterns) |
||||
|
# Add or remove patterns as needed |
||||
|
DEBUG_PATTERNS=( |
||||
|
# Console statements |
||||
|
"console\." |
||||
|
|
||||
|
# Template debug text |
||||
|
"Debug:" |
||||
|
"debug:" |
||||
|
|
||||
|
# Debug constants and variables |
||||
|
"DEBUG_" |
||||
|
"debug_" |
||||
|
|
||||
|
# HTML debug comments |
||||
|
"<!-- debug" |
||||
|
|
||||
|
# Debug attributes |
||||
|
"debug.*=" |
||||
|
|
||||
|
# Vue debug patterns |
||||
|
"v-if.*debug" |
||||
|
"v-show.*debug" |
||||
|
|
||||
|
# Common debug text |
||||
|
"TODO.*debug" |
||||
|
"FIXME.*debug" |
||||
|
|
||||
|
# Debug imports (uncomment if you want to catch these) |
||||
|
# "import.*debug" |
||||
|
# "require.*debug" |
||||
|
) |
||||
|
|
||||
|
# Files and directories to skip during checking |
||||
|
# Add patterns to exclude from debug checking |
||||
|
SKIP_PATTERNS=( |
||||
|
"\.(test|spec)\.(js|ts|vue)$" # Test files (must have .test. or .spec.) |
||||
|
"^scripts/" # Scripts directory |
||||
|
"^test-.*/" # Test directories (must end with /) |
||||
|
"^\.git/" # Git directory |
||||
|
"^node_modules/" # Dependencies |
||||
|
"^docs/" # Documentation |
||||
|
"^\.cursor/" # Cursor IDE files |
||||
|
"\.md$" # Markdown files |
||||
|
"\.txt$" # Text files |
||||
|
"\.json$" # JSON config files |
||||
|
"\.yml$" # YAML config files |
||||
|
"\.yaml$" # YAML config files |
||||
|
) |
||||
|
|
||||
|
# Files that are whitelisted for console statements |
||||
|
# These files may contain intentional console.log statements that are |
||||
|
# properly whitelisted with eslint-disable-next-line no-console comments |
||||
|
WHITELIST_FILES=( |
||||
|
"src/services/platforms/WebPlatformService.ts" # Worker context logging |
||||
|
"src/services/platforms/CapacitorPlatformService.ts" # Platform-specific logging |
||||
|
"src/services/platforms/ElectronPlatformService.ts" # Electron-specific logging |
||||
|
"src/services/QRScanner/.*" # QR Scanner services |
||||
|
"src/utils/logger.ts" # Logger utility itself |
||||
|
"src/utils/LogCollector.ts" # Log collection utilities |
||||
|
"scripts/.*" # Build and utility scripts |
||||
|
"test-.*/.*" # Test directories |
||||
|
".*\.test\..*" # Test files |
||||
|
".*\.spec\..*" # Spec files |
||||
|
) |
||||
|
|
||||
|
# Logging level (debug, info, warn, error) |
||||
|
LOG_LEVEL="info" |
||||
|
|
||||
|
# Exit codes |
||||
|
EXIT_SUCCESS=0 |
||||
|
EXIT_DEBUG_FOUND=1 |
||||
|
EXIT_ERROR=2 |
@ -0,0 +1,252 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
# TimeSafari Pre-commit Hook - Debug Code Checker |
||||
|
# Only runs on master or specified branches to catch debug code before it reaches production |
||||
|
|
||||
|
# Hook directory |
||||
|
HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
||||
|
CONFIG_FILE="$HOOK_DIR/debug-checker.config" |
||||
|
|
||||
|
# Default configuration (fallback if config file is missing) |
||||
|
DEFAULT_PROTECTED_BRANCHES=("master" "main" "production" "release") |
||||
|
DEFAULT_DEBUG_PATTERNS=( |
||||
|
"console\." |
||||
|
"Debug:" |
||||
|
"debug:" |
||||
|
"DEBUG_" |
||||
|
"debug_" |
||||
|
"<!-- debug" |
||||
|
"debug.*=" |
||||
|
) |
||||
|
DEFAULT_WHITELIST_FILES=( |
||||
|
"src/services/platforms/WebPlatformService.ts" |
||||
|
"src/services/platforms/CapacitorPlatformService.ts" |
||||
|
"src/services/platforms/ElectronPlatformService.ts" |
||||
|
) |
||||
|
|
||||
|
# Load configuration from file if it exists |
||||
|
load_config() { |
||||
|
if [[ -f "$CONFIG_FILE" ]]; then |
||||
|
# Source the config file to load variables |
||||
|
# We'll use a safer approach by reading and parsing |
||||
|
PROTECTED_BRANCHES=() |
||||
|
DEBUG_PATTERNS=() |
||||
|
SKIP_PATTERNS=() |
||||
|
WHITELIST_FILES=() |
||||
|
|
||||
|
# Read protected branches |
||||
|
while IFS= read -r line; do |
||||
|
if [[ "$line" =~ ^PROTECTED_BRANCHES=\( ]]; then |
||||
|
# Start reading array |
||||
|
while IFS= read -r line; do |
||||
|
if [[ "$line" =~ ^\)$ ]]; then |
||||
|
break |
||||
|
fi |
||||
|
if [[ "$line" =~ \"([^\"]+)\" ]]; then |
||||
|
PROTECTED_BRANCHES+=("${BASH_REMATCH[1]}") |
||||
|
fi |
||||
|
done |
||||
|
fi |
||||
|
done < "$CONFIG_FILE" |
||||
|
|
||||
|
# Read debug patterns |
||||
|
while IFS= read -r line; do |
||||
|
if [[ "$line" =~ ^DEBUG_PATTERNS=\( ]]; then |
||||
|
while IFS= read -r line; do |
||||
|
if [[ "$line" =~ ^\)$ ]]; then |
||||
|
break |
||||
|
fi |
||||
|
if [[ "$line" =~ \"([^\"]+)\" ]]; then |
||||
|
DEBUG_PATTERNS+=("${BASH_REMATCH[1]}") |
||||
|
fi |
||||
|
done |
||||
|
fi |
||||
|
done < "$CONFIG_FILE" |
||||
|
|
||||
|
# Read skip patterns |
||||
|
while IFS= read -r line; do |
||||
|
if [[ "$line" =~ ^SKIP_PATTERNS=\( ]]; then |
||||
|
while IFS= read -r line; do |
||||
|
if [[ "$line" =~ ^\)$ ]]; then |
||||
|
break |
||||
|
fi |
||||
|
if [[ "$line" =~ \"([^\"]+)\" ]]; then |
||||
|
SKIP_PATTERNS+=("${BASH_REMATCH[1]}") |
||||
|
fi |
||||
|
done |
||||
|
fi |
||||
|
done < "$CONFIG_FILE" |
||||
|
|
||||
|
# Read whitelist files |
||||
|
while IFS= read -r line; do |
||||
|
if [[ "$line" =~ ^WHITELIST_FILES=\( ]]; then |
||||
|
while IFS= read -r line; do |
||||
|
if [[ "$line" =~ ^\)$ ]]; then |
||||
|
break |
||||
|
fi |
||||
|
if [[ "$line" =~ \"([^\"]+)\" ]]; then |
||||
|
WHITELIST_FILES+=("${BASH_REMATCH[1]}") |
||||
|
fi |
||||
|
done |
||||
|
fi |
||||
|
done < "$CONFIG_FILE" |
||||
|
fi |
||||
|
|
||||
|
# Use defaults if config loading failed |
||||
|
if [[ ${#PROTECTED_BRANCHES[@]} -eq 0 ]]; then |
||||
|
PROTECTED_BRANCHES=("${DEFAULT_PROTECTED_BRANCHES[@]}") |
||||
|
fi |
||||
|
|
||||
|
if [[ ${#DEBUG_PATTERNS[@]} -eq 0 ]]; then |
||||
|
DEBUG_PATTERNS=("${DEFAULT_DEBUG_PATTERNS[@]}") |
||||
|
fi |
||||
|
|
||||
|
if [[ ${#SKIP_PATTERNS[@]} -eq 0 ]]; then |
||||
|
SKIP_PATTERNS=("${DEFAULT_SKIP_PATTERNS[@]}") |
||||
|
fi |
||||
|
|
||||
|
if [[ ${#WHITELIST_FILES[@]} -eq 0 ]]; then |
||||
|
WHITELIST_FILES=("${DEFAULT_WHITELIST_FILES[@]}") |
||||
|
fi |
||||
|
|
||||
|
} |
||||
|
|
||||
|
# Check if current branch is protected |
||||
|
is_protected_branch() { |
||||
|
local branch="$1" |
||||
|
for protected in "${PROTECTED_BRANCHES[@]}"; do |
||||
|
if [[ "$branch" == "$protected" ]]; then |
||||
|
return 0 |
||||
|
fi |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
# Check if file should be skipped |
||||
|
should_skip_file() { |
||||
|
local file="$1" |
||||
|
for pattern in "${SKIP_PATTERNS[@]}"; do |
||||
|
if [[ "$file" =~ $pattern ]]; then |
||||
|
return 0 |
||||
|
fi |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
# Check if file is whitelisted for console statements |
||||
|
is_whitelisted_file() { |
||||
|
local file="$1" |
||||
|
for whitelisted in "${WHITELIST_FILES[@]}"; do |
||||
|
if [[ "$file" =~ $whitelisted ]]; then |
||||
|
return 0 |
||||
|
fi |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
|
||||
|
# Main execution |
||||
|
main() { |
||||
|
# Load configuration |
||||
|
load_config |
||||
|
|
||||
|
# Get current branch name |
||||
|
CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null) |
||||
|
|
||||
|
if [[ -z "$CURRENT_BRANCH" ]]; then |
||||
|
echo "⚠️ Could not determine current branch, skipping debug check" |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
# Check if we should run the hook |
||||
|
if ! is_protected_branch "$CURRENT_BRANCH"; then |
||||
|
echo "🔒 Pre-commit hook skipped - not on protected branch ($CURRENT_BRANCH)" |
||||
|
echo " Protected branches: ${PROTECTED_BRANCHES[*]}" |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
echo "🔍 Running debug code check on protected branch: $CURRENT_BRANCH" |
||||
|
echo " Using config: $CONFIG_FILE" |
||||
|
|
||||
|
# Get all staged files (modified, added, copied, merged) |
||||
|
ALL_STAGED_FILES=$(git diff --cached --name-only) |
||||
|
|
||||
|
|
||||
|
|
||||
|
if [ -z "$ALL_STAGED_FILES" ]; then |
||||
|
echo "✅ No staged files to check" |
||||
|
exit 0 |
||||
|
fi |
||||
|
|
||||
|
# Initialize error tracking |
||||
|
ERRORS_FOUND=0 |
||||
|
ERROR_MESSAGES=() |
||||
|
FILES_CHECKED=0 |
||||
|
|
||||
|
# Check each staged file for debug patterns |
||||
|
for file in $ALL_STAGED_FILES; do |
||||
|
# Skip files that should be ignored |
||||
|
if should_skip_file "$file"; then |
||||
|
continue |
||||
|
fi |
||||
|
|
||||
|
FILES_CHECKED=$((FILES_CHECKED + 1)) |
||||
|
|
||||
|
# Check for debug patterns in the file |
||||
|
for pattern in "${DEBUG_PATTERNS[@]}"; do |
||||
|
# Skip console pattern checks for whitelisted files |
||||
|
if [[ "$pattern" == "console\." ]] && is_whitelisted_file "$file"; then |
||||
|
continue |
||||
|
fi |
||||
|
|
||||
|
# For new files, check the file content directly |
||||
|
# For modified files, check the staged diff |
||||
|
if [[ -f "$file" ]]; then |
||||
|
# New file - check content directly |
||||
|
if grep -E "$pattern" "$file" > /dev/null; then |
||||
|
ERRORS_FOUND=$((ERRORS_FOUND + 1)) |
||||
|
ERROR_MESSAGES+=("🚨 $file: Found debug pattern '$pattern'") |
||||
|
fi |
||||
|
else |
||||
|
# Modified file - check staged diff |
||||
|
if git diff --cached "$file" | grep -E "$pattern" > /dev/null; then |
||||
|
ERRORS_FOUND=$((ERRORS_FOUND + 1)) |
||||
|
ERROR_MESSAGES+=("🚨 $file: Found debug pattern '$pattern'") |
||||
|
fi |
||||
|
fi |
||||
|
done |
||||
|
done |
||||
|
|
||||
|
# Report results |
||||
|
if [ $ERRORS_FOUND -gt 0 ]; then |
||||
|
echo "" |
||||
|
echo "❌ Debug code detected in staged files!" |
||||
|
echo " Branch: $CURRENT_BRANCH" |
||||
|
echo " Files checked: $FILES_CHECKED" |
||||
|
echo " Errors found: $ERRORS_FOUND" |
||||
|
echo "" |
||||
|
for msg in "${ERROR_MESSAGES[@]}"; do |
||||
|
echo " $msg" |
||||
|
done |
||||
|
echo "" |
||||
|
echo "💡 Please remove debug code before committing to $CURRENT_BRANCH" |
||||
|
echo " Common debug patterns to check:" |
||||
|
echo " - console.log, console.debug, console.error" |
||||
|
echo " - Debug: or debug: in templates" |
||||
|
echo " - DEBUG_ constants" |
||||
|
echo " - HTML comments with debug" |
||||
|
echo "" |
||||
|
echo " If debug code is intentional, consider:" |
||||
|
echo " - Moving to a feature branch first" |
||||
|
echo " - Using proper logging levels (logger.info, logger.debug)" |
||||
|
echo " - Adding debug code to .gitignore or .debugignore" |
||||
|
echo "" |
||||
|
echo " Configuration file: $CONFIG_FILE" |
||||
|
exit 1 |
||||
|
else |
||||
|
echo "✅ No debug code found in $FILES_CHECKED staged files" |
||||
|
exit 0 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# Run main function |
||||
|
main "$@" |
@ -0,0 +1,171 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
# TimeSafari Debug Hook Installer |
||||
|
# Run this script in any repository to install the debug pre-commit hook |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
# Colors for output |
||||
|
RED='\033[0;31m' |
||||
|
GREEN='\033[0;32m' |
||||
|
YELLOW='\033[1;33m' |
||||
|
BLUE='\033[0;34m' |
||||
|
NC='\033[0m' # No Color |
||||
|
|
||||
|
echo -e "${BLUE}🔧 TimeSafari Debug Hook Installer${NC}" |
||||
|
echo "=============================================" |
||||
|
|
||||
|
# Check if we're in a git repository |
||||
|
if ! git rev-parse --git-dir > /dev/null 2>&1; then |
||||
|
echo -e "${RED}❌ Error: Not in a git repository${NC}" |
||||
|
echo "Please run this script from within a git repository" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Get repository root |
||||
|
REPO_ROOT=$(git rev-parse --show-toplevel) |
||||
|
HOOKS_DIR="$REPO_ROOT/.git/hooks" |
||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
||||
|
|
||||
|
echo -e "${BLUE}Repository:${NC} $REPO_ROOT" |
||||
|
echo -e "${BLUE}Hooks directory:${NC} $HOOKS_DIR" |
||||
|
echo -e "${BLUE}Script directory:${NC} $SCRIPT_DIR" |
||||
|
|
||||
|
# Check if hooks directory exists |
||||
|
if [[ ! -d "$HOOKS_DIR" ]]; then |
||||
|
echo -e "${RED}❌ Error: Hooks directory not found${NC}" |
||||
|
echo "This repository may not be properly initialized" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Check if we have the hook files in the repository |
||||
|
HOOK_SCRIPT="$SCRIPT_DIR/git-hooks/pre-commit" |
||||
|
CONFIG_FILE="$SCRIPT_DIR/git-hooks/debug-checker.config" |
||||
|
|
||||
|
if [[ ! -f "$HOOK_SCRIPT" ]]; then |
||||
|
echo -e "${RED}❌ Error: Pre-commit hook script not found${NC}" |
||||
|
echo "Expected location: $HOOK_SCRIPT" |
||||
|
echo "Make sure you're running this from the TimeSafari repository" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
if [[ ! -f "$CONFIG_FILE" ]]; then |
||||
|
echo -e "${RED}❌ Error: Debug checker config not found${NC}" |
||||
|
echo "Expected location: $CONFIG_FILE" |
||||
|
echo "Make sure you're running this from the TimeSafari repository" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Check if already installed |
||||
|
if [[ -f "$HOOKS_DIR/pre-commit" && -f "$HOOKS_DIR/debug-checker.config" ]]; then |
||||
|
echo -e "${YELLOW}⚠️ Debug hook already appears to be installed${NC}" |
||||
|
echo -e " Checking if update is needed..." |
||||
|
|
||||
|
# Check if files are different |
||||
|
if diff "$HOOK_SCRIPT" "$HOOKS_DIR/pre-commit" > /dev/null 2>&1; then |
||||
|
echo -e " ${GREEN}✅${NC} Hook script is up to date" |
||||
|
HOOK_UP_TO_DATE=true |
||||
|
else |
||||
|
echo -e " ${YELLOW}⚠️ Hook script differs - will update${NC}" |
||||
|
HOOK_UP_TO_DATE=false |
||||
|
fi |
||||
|
|
||||
|
if diff "$CONFIG_FILE" "$HOOKS_DIR/debug-checker.config" > /dev/null 2>&1; then |
||||
|
echo -e " ${GREEN}✅${NC} Config file is up to date" |
||||
|
CONFIG_UP_TO_DATE=true |
||||
|
else |
||||
|
echo -e " ${YELLOW}⚠️ Config file differs - will update${NC}" |
||||
|
CONFIG_UP_TO_DATE=false |
||||
|
fi |
||||
|
|
||||
|
if [[ "$HOOK_UP_TO_DATE" == true && "$CONFIG_UP_TO_DATE" == true ]]; then |
||||
|
echo -e "\n${GREEN}✅ Debug hook is already up to date!${NC}" |
||||
|
echo -e " No installation needed" |
||||
|
else |
||||
|
echo -e "\n${BLUE}Updating existing installation...${NC}" |
||||
|
fi |
||||
|
else |
||||
|
echo -e "\n${BLUE}Installing debug hook...${NC}" |
||||
|
fi |
||||
|
|
||||
|
# Copy/update the hook script if needed |
||||
|
if [[ "$HOOK_UP_TO_DATE" != true ]]; then |
||||
|
cp "$HOOK_SCRIPT" "$HOOKS_DIR/pre-commit" |
||||
|
chmod +x "$HOOKS_DIR/pre-commit" |
||||
|
echo -e " ${GREEN}✅${NC} Pre-commit hook installed/updated" |
||||
|
fi |
||||
|
|
||||
|
# Copy/update the config file if needed |
||||
|
if [[ "$CONFIG_UP_TO_DATE" != true ]]; then |
||||
|
cp "$CONFIG_FILE" "$HOOKS_DIR/debug-checker.config" |
||||
|
echo -e " ${GREEN}✅${NC} Configuration file installed/updated" |
||||
|
fi |
||||
|
|
||||
|
# Copy/update the README if needed |
||||
|
README_FILE="$SCRIPT_DIR/git-hooks/README.md" |
||||
|
if [[ -f "$README_FILE" ]]; then |
||||
|
if [[ ! -f "$HOOKS_DIR/README.md" ]] || ! diff "$README_FILE" "$HOOKS_DIR/README.md" > /dev/null 2>&1; then |
||||
|
cp "$README_FILE" "$HOOKS_DIR/README.md" |
||||
|
echo -e " ${GREEN}✅${NC} Documentation installed/updated" |
||||
|
else |
||||
|
echo -e " ${GREEN}✅${NC} Documentation is up to date" |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
echo -e "\n${GREEN}🎉 Debug hook installation complete!${NC}" |
||||
|
|
||||
|
# Test the installation |
||||
|
echo -e "\n${BLUE}Testing installation...${NC}" |
||||
|
if [[ -x "$HOOKS_DIR/pre-commit" ]]; then |
||||
|
echo -e " ${GREEN}✅${NC} Hook is executable" |
||||
|
else |
||||
|
echo -e " ${RED}❌${NC} Hook is not executable" |
||||
|
fi |
||||
|
|
||||
|
if [[ -f "$HOOKS_DIR/debug-checker.config" ]]; then |
||||
|
echo -e " ${GREEN}✅${NC} Config file exists" |
||||
|
else |
||||
|
echo -e " ${RED}❌${NC} Config file missing" |
||||
|
fi |
||||
|
|
||||
|
# Show current branch status |
||||
|
CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "detached") |
||||
|
echo -e "\n${BLUE}Current branch:${NC} $CURRENT_BRANCH" |
||||
|
|
||||
|
# Check if this is a protected branch |
||||
|
PROTECTED_BRANCHES=("master" "main" "production" "release" "stable") |
||||
|
IS_PROTECTED=false |
||||
|
|
||||
|
for branch in "${PROTECTED_BRANCHES[@]}"; do |
||||
|
if [[ "$CURRENT_BRANCH" == "$branch" ]]; then |
||||
|
IS_PROTECTED=true |
||||
|
break |
||||
|
fi |
||||
|
done |
||||
|
|
||||
|
if [[ "$IS_PROTECTED" == true ]]; then |
||||
|
echo -e "${YELLOW}⚠️ You're on a protected branch ($CURRENT_BRANCH)${NC}" |
||||
|
echo -e " The debug hook will now run on all commits to this branch" |
||||
|
echo -e " Consider switching to a feature branch for development" |
||||
|
else |
||||
|
echo -e "${GREEN}✅ You're on a feature branch ($CURRENT_BRANCH)${NC}" |
||||
|
echo -e " The debug hook will be skipped on this branch" |
||||
|
echo -e " You can develop with debug code freely" |
||||
|
fi |
||||
|
|
||||
|
echo -e "\n${BLUE}Next steps:${NC}" |
||||
|
echo "1. The hook will now run automatically on protected branches" |
||||
|
echo "2. Test it by trying to commit a file with debug code" |
||||
|
echo "3. Use feature branches for development with debug code" |
||||
|
echo "4. Check the README.md in .git/hooks/ for more information" |
||||
|
|
||||
|
echo -e "\n${BLUE}To test the hook:${NC}" |
||||
|
echo "1. Create a test file with debug code (e.g., console.log('test'))" |
||||
|
echo "2. Stage it: git add <filename>" |
||||
|
echo "3. Try to commit: git commit -m 'test'" |
||||
|
echo "4. The hook should prevent the commit if debug code is found" |
||||
|
|
||||
|
echo -e "\n${BLUE}To uninstall:${NC}" |
||||
|
echo "rm $HOOKS_DIR/pre-commit" |
||||
|
echo "rm $HOOKS_DIR/debug-checker.config" |
||||
|
echo "rm $HOOKS_DIR/README.md" |
@ -0,0 +1,214 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
# Setup Markdown Pre-commit Hooks |
||||
|
# This script installs pre-commit hooks that automatically fix markdown formatting |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
echo "🔧 Setting up Markdown Pre-commit Hooks..." |
||||
|
|
||||
|
# Check if pre-commit is installed |
||||
|
if ! command -v pre-commit &> /dev/null; then |
||||
|
echo "📦 Installing pre-commit..." |
||||
|
pip install pre-commit |
||||
|
else |
||||
|
echo "✅ pre-commit already installed" |
||||
|
fi |
||||
|
|
||||
|
# Create .pre-commit-config.yaml if it doesn't exist |
||||
|
if [ ! -f .pre-commit-config.yaml ]; then |
||||
|
echo "📝 Creating .pre-commit-config.yaml..." |
||||
|
cat > .pre-commit-config.yaml << 'EOF' |
||||
|
repos: |
||||
|
- repo: https://github.com/igorshubovych/markdownlint-cli |
||||
|
rev: v0.38.0 |
||||
|
hooks: |
||||
|
- id: markdownlint |
||||
|
args: [--fix, --config, .markdownlint.json] |
||||
|
files: \.(md|mdc)$ |
||||
|
description: "Auto-fix markdown formatting issues" |
||||
|
stages: [commit] |
||||
|
additional_dependencies: [markdownlint-cli] |
||||
|
|
||||
|
- repo: local |
||||
|
hooks: |
||||
|
- id: markdown-format-check |
||||
|
name: Markdown Format Validation |
||||
|
entry: bash -c 'echo "Checking markdown files..." && npx markdownlint --config .markdownlint.json "$@"' |
||||
|
language: system |
||||
|
files: \.(md|mdc)$ |
||||
|
stages: [commit] |
||||
|
description: "Validate markdown formatting" |
||||
|
pass_filenames: true |
||||
|
|
||||
|
- repo: local |
||||
|
hooks: |
||||
|
- id: markdown-line-length |
||||
|
name: Markdown Line Length Check |
||||
|
entry: bash -c ' |
||||
|
for file in "$@"; do |
||||
|
if [[ "$file" =~ \.(md|mdc)$ ]]; then |
||||
|
echo "Checking line length in $file..." |
||||
|
if grep -q ".\{81,\}" "$file"; then |
||||
|
echo "❌ Line length violations found in $file" |
||||
|
echo "Lines exceeding 80 characters:" |
||||
|
grep -n ".\{81,\}" "$file" | head -5 |
||||
|
exit 1 |
||||
|
fi |
||||
|
fi |
||||
|
done |
||||
|
' |
||||
|
language: system |
||||
|
files: \.(md|mdc)$ |
||||
|
stages: [commit] |
||||
|
description: "Check markdown line length (80 chars max)" |
||||
|
pass_filenames: true |
||||
|
|
||||
|
- repo: local |
||||
|
hooks: |
||||
|
- id: markdown-blank-lines |
||||
|
name: Markdown Blank Line Validation |
||||
|
entry: bash -c ' |
||||
|
for file in "$@"; do |
||||
|
if [[ "$file" =~ \.(md|mdc)$ ]]; then |
||||
|
echo "Checking blank lines in $file..." |
||||
|
# Check for multiple consecutive blank lines |
||||
|
if grep -q "^$" "$file" && grep -A1 "^$" "$file" | grep -q "^$"; then |
||||
|
echo "❌ Multiple consecutive blank lines found in $file" |
||||
|
exit 1 |
||||
|
fi |
||||
|
# Check for missing blank lines around headings |
||||
|
if grep -B1 "^##" "$file" | grep -v "^##" | grep -v "^$" | grep -v "^--"; then |
||||
|
echo "❌ Missing blank line before heading in $file" |
||||
|
exit 1 |
||||
|
fi |
||||
|
fi |
||||
|
done |
||||
|
' |
||||
|
language: system |
||||
|
files: \.(md|mdc)$ |
||||
|
stages: [commit] |
||||
|
description: "Validate markdown blank line formatting" |
||||
|
pass_filenames: true |
||||
|
EOF |
||||
|
echo "✅ Created .pre-commit-config.yaml" |
||||
|
else |
||||
|
echo "✅ .pre-commit-config.yaml already exists" |
||||
|
fi |
||||
|
|
||||
|
# Install the pre-commit hooks |
||||
|
echo "🔗 Installing pre-commit hooks..." |
||||
|
pre-commit install |
||||
|
|
||||
|
# Install markdownlint if not present |
||||
|
if ! command -v npx &> /dev/null; then |
||||
|
echo "📦 Installing Node.js dependencies..." |
||||
|
npm install --save-dev markdownlint-cli |
||||
|
else |
||||
|
if ! npx markdownlint --version &> /dev/null; then |
||||
|
echo "📦 Installing markdownlint-cli..." |
||||
|
npm install --save-dev markdownlint-cli |
||||
|
else |
||||
|
echo "✅ markdownlint-cli already available" |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
# Create a markdown auto-fix script |
||||
|
echo "📝 Creating markdown auto-fix script..." |
||||
|
cat > scripts/fix-markdown.sh << 'EOF' |
||||
|
#!/bin/bash |
||||
|
|
||||
|
# Auto-fix markdown formatting issues |
||||
|
# Usage: ./scripts/fix-markdown.sh [file_or_directory] |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
FIX_MARKDOWN() { |
||||
|
local target="$1" |
||||
|
|
||||
|
if [ -f "$target" ]; then |
||||
|
# Fix single file |
||||
|
if [[ "$target" =~ \.(md|mdc)$ ]]; then |
||||
|
echo "🔧 Fixing markdown formatting in $target..." |
||||
|
npx markdownlint --fix "$target" || true |
||||
|
fi |
||||
|
elif [ -d "$target" ]; then |
||||
|
# Fix all markdown files in directory |
||||
|
echo "🔧 Fixing markdown formatting in $target..." |
||||
|
find "$target" -name "*.md" -o -name "*.mdc" | while read -r file; do |
||||
|
echo " Processing $file..." |
||||
|
npx markdownlint --fix "$file" || true |
||||
|
done |
||||
|
else |
||||
|
echo "❌ Target $target not found" |
||||
|
exit 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# Default to current directory if no target specified |
||||
|
TARGET="${1:-.}" |
||||
|
FIX_MARKDOWN "$TARGET" |
||||
|
|
||||
|
echo "✅ Markdown formatting fixes applied!" |
||||
|
echo "💡 Run 'git diff' to see what was changed" |
||||
|
EOF |
||||
|
|
||||
|
chmod +x scripts/fix-markdown.sh |
||||
|
|
||||
|
# Create a markdown validation script |
||||
|
echo "📝 Creating markdown validation script..." |
||||
|
cat > scripts/validate-markdown.sh << 'EOF' |
||||
|
#!/bin/bash |
||||
|
|
||||
|
# Validate markdown formatting without auto-fixing |
||||
|
# Usage: ./scripts/validate-markdown.sh [file_or_directory] |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
VALIDATE_MARKDOWN() { |
||||
|
local target="$1" |
||||
|
|
||||
|
if [ -f "$target" ]; then |
||||
|
# Validate single file |
||||
|
if [[ "$target" =~ \.(md|mdc)$ ]]; then |
||||
|
echo "🔍 Validating markdown formatting in $target..." |
||||
|
npx markdownlint "$target" |
||||
|
fi |
||||
|
elif [ -d "$target" ]; then |
||||
|
# Validate all markdown files in directory |
||||
|
echo "🔍 Validating markdown formatting in $target..." |
||||
|
find "$target" -name "*.md" -o -name "*.mdc" | while read -r file; do |
||||
|
echo " Checking $file..." |
||||
|
npx markdownlint "$file" || true |
||||
|
done |
||||
|
else |
||||
|
echo "❌ Target $target not found" |
||||
|
exit 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
# Default to current directory if no target specified |
||||
|
TARGET="${1:-.}" |
||||
|
VALIDATE_MARKDOWN "$TARGET" |
||||
|
|
||||
|
echo "✅ Markdown validation complete!" |
||||
|
EOF |
||||
|
|
||||
|
chmod +x scripts/validate-markdown.sh |
||||
|
|
||||
|
echo "" |
||||
|
echo "🎉 Markdown Pre-commit Hooks Setup Complete!" |
||||
|
echo "" |
||||
|
echo "📋 What was installed:" |
||||
|
echo " ✅ pre-commit hooks for automatic markdown formatting" |
||||
|
echo " ✅ .pre-commit-config.yaml with markdown rules" |
||||
|
echo " ✅ scripts/fix-markdown.sh for manual fixes" |
||||
|
echo " ✅ scripts/validate-markdown.sh for validation" |
||||
|
echo "" |
||||
|
echo "🚀 Usage:" |
||||
|
echo " • Hooks run automatically on commit" |
||||
|
echo " • Manual fix: ./scripts/fix-markdown.sh [file/dir]" |
||||
|
echo " • Manual check: ./scripts/validate-markdown.sh [file/dir]" |
||||
|
echo " • Test hooks: pre-commit run --all-files" |
||||
|
echo "" |
||||
|
echo "💡 The hooks will now automatically fix markdown issues before commits!" |
@ -0,0 +1,117 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
# Test script for the debug pre-commit hook |
||||
|
# This script helps verify that the hook is working correctly |
||||
|
|
||||
|
set -e |
||||
|
|
||||
|
echo "🧪 Testing TimeSafari Debug Pre-commit Hook" |
||||
|
echo "=============================================" |
||||
|
|
||||
|
# Colors for output |
||||
|
RED='\033[0;31m' |
||||
|
GREEN='\033[0;32m' |
||||
|
YELLOW='\033[1;33m' |
||||
|
BLUE='\033[0;34m' |
||||
|
NC='\033[0m' # No Color |
||||
|
|
||||
|
# Test directory |
||||
|
TEST_DIR="$(mktemp -d)" |
||||
|
echo -e "${BLUE}Created test directory: $TEST_DIR${NC}" |
||||
|
|
||||
|
# Function to cleanup |
||||
|
cleanup() { |
||||
|
echo -e "${YELLOW}Cleaning up test directory...${NC}" |
||||
|
rm -rf "$TEST_DIR" |
||||
|
} |
||||
|
|
||||
|
# Set trap to cleanup on exit |
||||
|
trap cleanup EXIT |
||||
|
|
||||
|
# Function to run test |
||||
|
run_test() { |
||||
|
local test_name="$1" |
||||
|
local test_file="$2" |
||||
|
local expected_exit="$3" |
||||
|
|
||||
|
echo -e "\n${BLUE}Running test: $test_name${NC}" |
||||
|
|
||||
|
# Create test file |
||||
|
echo "$test_file" > "$TEST_DIR/test.vue" |
||||
|
|
||||
|
# Stage the file |
||||
|
cd "$TEST_DIR" |
||||
|
git init > /dev/null 2>&1 |
||||
|
git add test.vue > /dev/null 2>&1 |
||||
|
|
||||
|
# Run the hook |
||||
|
if bash ../../.git/hooks/pre-commit > hook_output.txt 2>&1; then |
||||
|
exit_code=0 |
||||
|
else |
||||
|
exit_code=$? |
||||
|
fi |
||||
|
|
||||
|
# Check result |
||||
|
if [[ $exit_code -eq $expected_exit ]]; then |
||||
|
echo -e " ${GREEN}✅ PASS${NC} - Exit code: $exit_code (expected: $expected_exit)" |
||||
|
else |
||||
|
echo -e " ${RED}❌ FAIL${NC} - Exit code: $exit_code (expected: $expected_exit)" |
||||
|
echo -e " ${YELLOW}Hook output:${NC}" |
||||
|
cat hook_output.txt |
||||
|
fi |
||||
|
|
||||
|
# Cleanup git |
||||
|
rm -rf .git |
||||
|
rm -f hook_output.txt |
||||
|
} |
||||
|
|
||||
|
# Test cases |
||||
|
echo -e "\n${BLUE}Test Case 1: Clean file (should pass)${NC}" |
||||
|
run_test "Clean file" "// No debug code here" 0 |
||||
|
|
||||
|
echo -e "\n${BLUE}Test Case 2: Console statement (should fail)${NC}" |
||||
|
run_test "Console statement" "console.log('debug info')" 1 |
||||
|
|
||||
|
echo -e "\n${BLUE}Test Case 3: Debug template (should fail)${NC}" |
||||
|
run_test "Debug template" "Debug: {{ isMapReady ? 'Map Ready' : 'Map Loading' }}" 1 |
||||
|
|
||||
|
echo -e "\n${BLUE}Test Case 4: Debug constant (should fail)${NC}" |
||||
|
run_test "Debug constant" "const DEBUG_MODE = true" 1 |
||||
|
|
||||
|
echo -e "\n${BLUE}Test Case 5: Mixed content (should fail)${NC}" |
||||
|
run_test "Mixed content" "// Some normal code\nconsole.debug('test')\n// More normal code" 1 |
||||
|
|
||||
|
echo -e "\n${BLUE}Test Case 6: HTML debug comment (should fail)${NC}" |
||||
|
run_test "HTML debug comment" "<!-- debug: this is debug info -->" 1 |
||||
|
|
||||
|
echo -e "\n${BLUE}Test Case 7: Debug attribute (should fail)${NC}" |
||||
|
run_test "Debug attribute" "<div debug='true'>content</div>" 1 |
||||
|
|
||||
|
echo -e "\n${BLUE}Test Case 8: Test file (should be skipped)${NC}" |
||||
|
run_test "Test file" "console.log('this should be skipped')" 0 |
||||
|
|
||||
|
# Test branch detection |
||||
|
echo -e "\n${BLUE}Testing branch detection...${NC}" |
||||
|
cd "$TEST_DIR" |
||||
|
git init > /dev/null 2>&1 |
||||
|
git checkout -b feature-branch > /dev/null 2>&1 |
||||
|
echo "console.log('debug')" > test.vue |
||||
|
git add test.vue > /dev/null 2>&1 |
||||
|
|
||||
|
if bash ../../.git/hooks/pre-commit > hook_output.txt 2>&1; then |
||||
|
echo -e " ${GREEN}✅ PASS${NC} - Hook skipped on feature branch" |
||||
|
else |
||||
|
echo -e " ${RED}❌ FAIL${NC} - Hook should have been skipped on feature branch" |
||||
|
echo -e " ${YELLOW}Hook output:${NC}" |
||||
|
cat hook_output.txt |
||||
|
fi |
||||
|
|
||||
|
rm -rf .git |
||||
|
rm -f hook_output.txt |
||||
|
|
||||
|
echo -e "\n${GREEN}🎉 All tests completed!${NC}" |
||||
|
echo -e "\n${BLUE}To test manually:${NC}" |
||||
|
echo "1. Make changes to a file with debug code" |
||||
|
echo "2. Stage the file: git add <filename>" |
||||
|
echo "3. Try to commit: git commit -m 'test'" |
||||
|
echo "4. The hook should prevent the commit if debug code is found" |
@ -0,0 +1,19 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
set -euo pipefail |
||||
|
|
||||
|
echo "🔍 Validating markdown formatting..." |
||||
|
|
||||
|
# Check if markdownlint is available |
||||
|
if ! command -v npx &> /dev/null; then |
||||
|
echo "❌ npx not found. Please install Node.js and npm first." |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
# Run markdownlint on project markdown files (exclude node_modules) |
||||
|
echo "📝 Checking project markdown files..." |
||||
|
npx markdownlint "*.md" "*.mdc" "scripts/**/*.md" "src/**/*.md" "test-playwright/**/*.md" "resources/**/*.md" --config .markdownlint.json 2>/dev/null || { |
||||
|
echo "❌ Markdown validation failed. Run 'npm run markdown:fix' to auto-fix issues." |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
echo "✅ All markdown files pass validation!" |
@ -0,0 +1,26 @@ |
|||||
|
/** |
||||
|
* @file Dynamic Main Entry Point |
||||
|
* @author Matthew Raymer |
||||
|
* |
||||
|
* This file dynamically loads the appropriate platform-specific main entry point |
||||
|
* based on the current environment and build configuration. |
||||
|
*/ |
||||
|
|
||||
|
import { logger } from "./utils/logger"; |
||||
|
|
||||
|
// Check the platform from environment variables
|
||||
|
const platform = process.env.VITE_PLATFORM || "web"; |
||||
|
|
||||
|
logger.info(`[Main] 🚀 Loading TimeSafari for platform: ${platform}`); |
||||
|
|
||||
|
// Dynamically import the appropriate main entry point
|
||||
|
if (platform === "capacitor") { |
||||
|
logger.info(`[Main] 📱 Loading Capacitor-specific entry point`); |
||||
|
import("./main.capacitor"); |
||||
|
} else if (platform === "electron") { |
||||
|
logger.info(`[Main] 💻 Loading Electron-specific entry point`); |
||||
|
import("./main.electron"); |
||||
|
} else { |
||||
|
logger.info(`[Main] 🌐 Loading Web-specific entry point`); |
||||
|
import("./main.web"); |
||||
|
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue