From d1ef33c25a704be5f54c0ff1b34aa61ab7515054 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 12 Mar 2026 00:56:57 +0800 Subject: [PATCH] first commit --- .gitignore | 32 +++ .planning/codebase/ARCHITECTURE.md | 116 ++++++++++ .planning/codebase/CONCERNS.md | 186 ++++++++++++++++ .planning/codebase/CONVENTIONS.md | 239 ++++++++++++++++++++ .planning/codebase/INTEGRATIONS.md | 190 ++++++++++++++++ .planning/codebase/STACK.md | 137 ++++++++++++ .planning/codebase/STRUCTURE.md | 148 +++++++++++++ .planning/codebase/TESTING.md | 345 +++++++++++++++++++++++++++++ README.md | 0 9 files changed, 1393 insertions(+) create mode 100644 .gitignore create mode 100644 .planning/codebase/ARCHITECTURE.md create mode 100644 .planning/codebase/CONCERNS.md create mode 100644 .planning/codebase/CONVENTIONS.md create mode 100644 .planning/codebase/INTEGRATIONS.md create mode 100644 .planning/codebase/STACK.md create mode 100644 .planning/codebase/STRUCTURE.md create mode 100644 .planning/codebase/TESTING.md create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..0e18415d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ + +# ── GSD baseline (auto-generated) ── +.gsd/activity/ +.gsd/runtime/ +.gsd/auto.lock +.gsd/metrics.json +.gsd/STATE.md +.DS_Store +Thumbs.db +*.swp +*.swo +*~ +.idea/ +.vscode/ +*.code-workspace +.env +.env.* +!.env.example +node_modules/ +.next/ +dist/ +build/ +__pycache__/ +*.pyc +.venv/ +venv/ +target/ +vendor/ +*.log +coverage/ +.cache/ +tmp/ diff --git a/.planning/codebase/ARCHITECTURE.md b/.planning/codebase/ARCHITECTURE.md new file mode 100644 index 000000000..235f902ae --- /dev/null +++ b/.planning/codebase/ARCHITECTURE.md @@ -0,0 +1,116 @@ +# Architecture + +**Analysis Date:** 2026-03-12 + +## Pattern Overview + +**Overall:** Agent-based task automation framework built on OpenCode + +**Key Characteristics:** +- Modular command/agent system with specialized agents for different phases +- Workflow-driven execution with named phases (discovery, research, plan, execute, verify) +- Direct file output pattern - agents write to `.planning/codebase/` directly +- Subagent spawning for parallel exploration tasks + +## Layers + +**Commands Layer:** +- Purpose: User-facing entry points for GSD operations +- Location: `.opencode/commands/gsd/` +- Contains: Markdown command definitions with YAML frontmatter +- Files: 33 command files (gsd-*.md) +- Used by: OpenCode CLI when user invokes `/gsd-*` commands + +**Agents Layer:** +- Purpose: Specialized AI agents for focused tasks +- Location: `.opencode/agents/` +- Contains: Agent role definitions with tools and skills +- Files: 12 agent definitions (gsd-*.md) +- Used by: Commands that need parallel or complex task execution + +**Workflows Layer:** +- Purpose: Execution logic connecting commands and agents +- Location: `.opencode/get-shit-done/workflows/` +- Contains: Step-by-step workflow definitions +- Files: 36 workflow files +- Depends on: Commands layer (referenced in command execution_context) +- Used by: Command execution context + +**Supporting Layers:** +- Skills: `.opencode/skills/` - Specialized skills (e.g., model selection) +- Rules: `.opencode/rules/` - Behavior rules (e.g., work-hard rule) +- Configuration: `.opencode/package.json`, `bun.lock` - Dependencies and lockfile + +## Data Flow + +**Command Invocation Flow:** +1. User invokes `/gsd-*` command +2. Command definition loads execution_context (workflow) +3. Workflow orchestrates agent spawning and task execution +4. Agents write outputs directly to `.planning/` directories +5. Confirmation returned to orchestrator (not full content) + +**Parallel Agent Pattern:** +- map-codebase spawns 4 parallel mapper agents (tech, arch, quality, concerns) +- Each agent explores focus area and writes specific documents +- Agents return confirmations only to minimize context load + +## Key Abstractions + +**Command Pattern:** +- Format: Markdown with YAML frontmatter +- Structure: name, description, argument-hint, permissions, objective, execution_context, context, when_to_use, process, success_criteria +- Location: `.opencode/commands/gsd/gsd-{name}.md` + +**Agent Pattern:** +- Format: Markdown with YAML frontmatter +- Structure: name, description, mode, tools, color, skills +- Location: `.opencode/agents/gsd-{name}.md` +- Types: orchestrator agents (main), subagents (parallel workers) + +**Workflow Pattern:** +- Format: Markdown with step-by-step instructions +- Location: `.opencode/get-shit-done/workflows/{name}.md` +- Called from: Command's `` directive + +## Entry Points + +**Primary Entry Point:** +- Location: `.opencode/commands/gsd/gsd-*.md` (33 commands) +- Triggers: OpenCode CLI `/gsd-*` invocation +- Responsibilities: Define command interface, load workflow, return success criteria + +**Command Categories:** +- Project management: new-project, new-milestone, resume-work, pause-work +- Phase management: add-phase, remove-phase, insert-phase, list-phase-assumptions +- Execution: plan-phase, execute-phase, verify-phase, validate-phase +- Discovery: research-phase, map-codebase, discuss-phase, quick +- Verification: audit-milestone, complete-milestone, verify-work, health +- Debugging: debug, diagnose-issues, reapply-patches +- Utilities: add-todo, add-tests, set-profile, settings, help + +## Error Handling + +**Workflow Error Handling:** +- Phase failures trigger diagnosis workflows +- verify-work performs health checks on each phase +- audit-milestone catches incomplete work before completion + +**Agent Error Patterns:** +- Subagent failures reported to orchestrator with error details +- Parallel agents - one failure doesn't cascade to others + +## Cross-Cutting Concerns + +**State Management:** +- Project state stored in `.planning/STATE.md` +- Milestone data in `.gsd/milestones/` +- Codebase docs in `.planning/codebase/` + +**Permissions System:** +- Commands declare required permissions (read, bash, glob, grep, write, task) +- Agents declare tools they can use + +--- + +*Architecture analysis: 2026-03-12* \ No newline at end of file diff --git a/.planning/codebase/CONCERNS.md b/.planning/codebase/CONCERNS.md new file mode 100644 index 000000000..2c870b528 --- /dev/null +++ b/.planning/codebase/CONCERNS.md @@ -0,0 +1,186 @@ +# Codebase Concerns + +**Analysis Date:** 2026-03-12 + +## Project Status: Greenfield + +**Critical Finding:** This is a greenfield project with no actual implementation code. The repository contains only: + +- `THE_IDEA.md` - Requirements specification document +- `.opencode/` - OpenCode/GSD framework configuration + +**Impact:** There are no code-level technical concerns to document because nothing has been built yet. This document outlines concerns for the future implementation. + +--- + +## Implementation Concerns + +### No Source Code Exists + +**Issue:** No application code has been implemented +- Files: None (project has not been initialized with source code) +- Impact: Cannot assess code quality, patterns, or technical debt +- Fix approach: Initialize project with proper scaffolding before implementation begins + +### Missing Project Initialization + +**Issue:** No package.json, build configuration, or source directories at project root +- Files: `package.json`, `tsconfig.json`, `src/` missing +- Impact: No standard development workflow established +- Fix approach: Run project initialization to create proper project structure + +--- + +## Hardware-Specific Concerns + +### Low-Power Device Targeting + +**Issue:** Target hardware is Raspberry Pi Zero 2W (limited resources) +- Device: Pi Zero 2 W with 512MB RAM, single-core ARMv8 +- Concern: UI must be lightweight to run smoothly in Chromium Kiosk Mode +- Mitigation needed: + - Minimal JavaScript bundle size + - Efficient rendering (avoid heavy frameworks if possible) + - Consider static HTML/CSS over SPA for main interface + - Lazy-load any heavy components + +### Dual Display Resolution Support + +**Issue:** Must support two different display modes +- 7-inch touchscreen: 1024x600 resolution +- Full HD remote access: 1920x1080 resolution +- Concern: Responsive design complexity +- Mitigation needed: + - Clear responsive breakpoints + - Different layouts for touch vs desktop + - Performance testing on actual hardware + +--- + +## Requirements Complexity + +### Feature Scope (3 Milestones) + +**Issue:** Large feature set across three milestones +- Milestone 1: Modern compact UI +- Milestone 2: CSV processing and workflow +- Milestone 3: Network stack +- Concern: Scope creep and milestone creep +- Priority: High + +### Data Types and Processing + +**Issue:** Multiple sensor data types require handling +- Rainfall (today, hourly, MAR, yearly) +- Battery voltage +- Solar voltage +- Water level sensors (4-20mA, 0-10vDC) +- GPS coordinates +- Mobile network status +- Concern: Data normalization and storage complexity + +### Network Protocol Support + +**Issue:** Multiple transfer protocols specified in requirements +- FTP, SCP, SFTP, WEBDAV +- TCP socket connections +- Concern: Implementation complexity and security +- Mitigation: Start with simplest protocol (HTTP), add others as needed + +--- + +## Dependencies at Risk + +### OpenCode Framework Dependency + +**Issue:** Project configured to use OpenCode/GSD workflow +- Package: `@opencode-ai/plugin` v1.2.24 +- Location: `.opencode/package.json` +- Risk: Vendor lock-in to specific workflow tool +- Mitigation: Document standard development practices that work independently + +### Zod in node_modules + +**Issue:** Zod library present in `.opencode/node_modules/` +- Purpose: Likely used for configuration validation +- Concern: Not yet integrated into project (in .) +- Recommendation: If validationopencode only needed, use zod; otherwise remove dependency + +--- + +## Missing Infrastructure + +### No Testing Framework + +**Issue:** No test files or configuration detected +- No `jest.config.*`, `vitest.config.*`, or similar +- No `*.test.*` or `*.spec.*` files +- Impact: No test coverage for future implementation +- Priority: High - Testing should be established before implementation + +### No Linting/Formatting + +**Issue:** No ESLint, Prettier, or biome configuration +- Impact: Inconsistent code style as team grows +- Priority: Medium + +### No CI/CD Configuration + +**Issue:** No GitHub Actions, GitLab CI, or similar +- Impact: No automated testing or deployment +- Priority: Low (can be added later) + +--- + +## Security Considerations (Future) + +### Network Credentials Storage + +**Issue:** Requirements mention FTP/SCP credentials +- Files referenced: `THE_IDEA.md` lines 175-184 +- Concern: Plain-text credentials in configuration +- Future mitigation: + - Use environment variables, not config files + - Consider OAuth/API keys over username/password + - Encrypt any stored credentials + +### GPRS/Mobile Network + +**Issue:** Mobile settings stored in system +- Location: `THE_IDEA.md` section 1.7 +- Concern: Phone numbers and device IDs stored +- Future mitigation: Encrypt sensitive station data + +--- + +## Performance Targets + +### Startup Time + +**Target:** Fast enough for Pi Zero 2W Chromium Kiosk +- Concern: Cold start must be under 3 seconds +- Mitigation: Minimize JavaScript, use progressive loading + +### Memory Usage + +**Target:** Stay within 256MB RAM for UI +- Concern: Chromium + web app + system services +- Mitigation: Avoid large in-memory data structures + +--- + +## Summary of Priorities + +| Concern | Priority | Status | +|---------|----------|--------| +| No source code exists | Critical | Not started | +| No testing framework | High | Not started | +| No project initialization | High | Not started | +| Hardware performance | High | Future | +| Requirements scope | Medium | Planned | +| No CI/CD | Low | Not started | +| Security hardening | Medium | Future | + +--- + +*Concerns audit: 2026-03-12* diff --git a/.planning/codebase/CONVENTIONS.md b/.planning/codebase/CONVENTIONS.md new file mode 100644 index 000000000..4e97f1a17 --- /dev/null +++ b/.planning/codebase/CONVENTIONS.md @@ -0,0 +1,239 @@ +# Coding Conventions + +**Analysis Date:** 2026-03-12 + +## Language + +**Primary:** JavaScript (Node.js) +- All source files use CommonJS (`.cjs` extension) +- ESM imports used in test files with `.test.cjs` extension + +## File Naming + +**Pattern:** kebab-case +- Commands: `allow-read-config.cjs`, `get-profile.cjs`, `set-profile.cjs` +- Libraries: `oc-core.cjs`, `oc-config.cjs`, `oc-models.cjs` +- Tests: `get-profile.test.cjs`, `allow-read-config.test.cjs` + +**Directories:** +- Commands: `bin/gsd-oc-commands/` +- Libraries: `bin/gsd-oc-lib/` or `bin/lib/` +- Tests: `bin/test/` + +## Code Style + +### Formatting + +**No explicit formatter configured.** Code uses: +- 2-space indentation +- Consistent brace placement +- Max line length ~100 characters + +**Example from `bin/gsd-oc-commands/get-profile.cjs`:** +```javascript +function getProfile(cwd, args) { + const verbose = args.includes('--verbose'); + const raw = args.includes('--raw'); + const log = verbose ? (...args) => console.error('[get-profile]', ...args) : () => {}; + // ... +} +``` + +### Linting + +**No ESLint or Prettier configuration detected.** + +## Import Organization + +**Order in source files:** +1. Node.js built-ins (`fs`, `path`, `os`) +2. Local modules relative paths + +**Example from `bin/gsd-oc-commands/allow-read-config.cjs`:** +```javascript +const fs = require('fs'); +const path = require('path'); +const os = require('os'); +const { output, error, createBackup } = require('../gsd-oc-lib/oc-core.cjs'); +``` + +## Function Design + +### Naming + +- Commands: lowercase with hyphens (e.g., `getProfile`, `allowReadConfig`) +- Helper functions: camelCase +- Error code constants: UPPER_SNAKE_CASE + +### Documentation + +**Every file includes a JSDoc-style header:** +```javascript +/** + * get-profile.cjs — Retrieve profile definitions from oc_config.json + * + * Command module that exports getProfile(cwd, args) function with two operation modes: + * 1. No parameters: Returns current profile definition + * 2. Profile name parameter: Returns specified profile definition + * + * Output format: JSON envelope {success: true, data: {...}} + * Flags: --raw (output raw JSON without envelope), --verbose (output diagnostics to stderr) + * + * Usage: node get-profile.cjs [profile-name] [--raw] [--verbose] + */ +``` + +**Function JSDoc:** +```javascript +/** + * Main command function + * + * @param {string} cwd - Current working directory + * @param {string[]} args - Command line arguments + */ +function getProfile(cwd, args) { +``` + +## Error Handling + +### Error Codes + +**Pattern:** Constant object with error codes, used with custom error function + +From `bin/gsd-oc-lib/oc-profile-config.cjs`: +```javascript +const ERROR_CODES = { + CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND', + INVALID_JSON: 'INVALID_JSON', + PROFILE_NOT_FOUND: 'PROFILE_NOT_FOUND', + INVALID_MODELS: 'INVALID_MODELS', + INCOMPLETE_PROFILE: 'INCOMPLETE_PROFILE', + WRITE_FAILED: 'WRITE_FAILED', + APPLY_FAILED: 'APPLY_FAILED', + ROLLBACK_FAILED: 'ROLLBACK_FAILED' +}; +``` + +### Output Pattern + +**Success output:** JSON envelope with `success: true` and `data` +```javascript +output({ success: true, data: result }); +``` + +**Error output:** Uses centralized `error()` function from `oc-core.cjs` +```javascript +error('current_oc_profile not set in oc_config.json', 'MISSING_CURRENT_PROFILE'); +``` + +From `bin/gsd-oc-lib/oc-core.cjs`: +```javascript +function error(message, code = 'UNKNOWN_ERROR') { + const errorEnvelope = { + success: false, + error: { + code, + message + } + }; + console.error(JSON.stringify(errorEnvelope, null, 2)); + process.exit(1); +} +``` + +## Return Patterns + +### Result Objects + +**Pattern:** Return object with `success: boolean` and either `data` or `error` + +From `bin/gsd-oc-lib/oc-profile-config.cjs`: +```javascript +function loadOcProfileConfig(cwd) { + try { + const configPath = path.join(cwd, '.planning', 'oc_config.json'); + if (!fs.existsSync(configPath)) { + return { + success: false, + error: { + code: ERROR_CODES.CONFIG_NOT_FOUND, + message: `.planning/oc_config.json not found at ${configPath}` + } + }; + } + return { success: true, config, configPath }; + } catch (err) { + // ... + } +} +``` + +## Module Design + +### Exports + +**Pattern:** Single function export via `module.exports` +```javascript +module.exports = getProfile; +``` + +### Command Module Structure + +1. JSDoc header with description +2. Require statements +3. Error code constants +4. Helper functions +5. Main command function +6. `module.exports` + +## CLI Patterns + +### Flag Handling + +**Pattern:** Simple array filtering +```javascript +const verbose = args.includes('--verbose'); +const raw = args.includes('--raw'); +const profileArgs = args.filter(arg => !arg.startsWith('--')); +``` + +### Output Functions + +From `bin/gsd-oc-lib/oc-core.cjs`: +```javascript +function output(result, raw = false, rawValue = null) { + let outputStr; + if (raw && rawValue !== null) { + outputStr = rawValue; + } else { + outputStr = JSON.stringify(result, null, 2); + } + // Large payload handling (>50KB) + if (outputStr.length > 50 * 1024) { + const tempFile = path.join(require('os').tmpdir(), `gsd-oc-${Date.now()}.json`); + fs.writeFileSync(tempFile, outputStr, 'utf8'); + console.log(`@file:${tempFile}`); + } else { + console.log(outputStr); + } +} +``` + +## Logging + +### Verbose Logging Pattern + +**Conditional logging based on flag:** +```javascript +const log = verbose ? (...args) => console.error('[get-profile]', ...args) : () => {}; +log('Loading oc_config.json'); +log(`Config loaded from ${configPath}`); +``` + +## Testing Conventions + +Tests co-located in `bin/test/` directory with `.test.cjs` suffix. + +--- + +*Convention analysis: 2026-03-12* diff --git a/.planning/codebase/INTEGRATIONS.md b/.planning/codebase/INTEGRATIONS.md new file mode 100644 index 000000000..e83193639 --- /dev/null +++ b/.planning/codebase/INTEGRATIONS.md @@ -0,0 +1,190 @@ +# External Integrations + +**Analysis Date:** 2026-03-12 + +## Project Status + +This is a **greenfield project** - no implementation code exists yet. The following analysis is based on the requirements defined in `THE_IDEA.md`. + +--- + +## Hardware Interfaces + +### Sensors + +**Rainfall Sensors:** +- Rainfall-1 ID (RF) - Primary rainfall sensor (e.g., `123456RF`) +- Rainfall-2 ID - Secondary rainfall sensor +- Tip bucket counting for rainfall accumulation + +**Water Level Sensors:** +- 4-20mA type sensors (Channels 1-2) +- 0-10vDC type sensors (Channels 3-4) +- SDI-12 interface for additional sensors + +**Environmental Sensors:** +- Solar voltage monitoring +- Battery voltage monitoring +- Soil moisture sensors (SDI-12) +- Evapotranspiration sensors + +### GPS Module + +- USB GPS module for location data +- Latitude/longitude retrieval +- Manual coordinate setting as fallback + +--- + +## Data Storage + +### Local Storage + +**CSV Files:** +- Data logging to local filesystem +- File naming: `SP8020_FTP.txt`, `SP8021_FTP.txt`, etc. +- Flash memory management for stored files +- File operations: Navigate, View, Delete, Save + +**Data Types Logged:** +- Rainfall (today, hourly, monthly accumulated, yearly) +- Water levels +- Battery voltage +- Solar voltage +- Sensor readings (ADC channels) + +--- + +## Network & External Services + +### Data Server (myvscada) + +**Server Details:** +- Remote server for receiving CSV data +- Location: Configurable IP address +- Protocol: FTP, SCP, SFTP, or WEBDAV + +**Transfer Flow:** +``` +RTU → CSV file → myvscada server → received folder → processed/error folder +``` + +### Mobile Network (GPRS) + +**GPRS Module:** +- Mobile network connectivity for remote transmission +- RTU Mobile number configuration +- Referenced in "Mobile Setting" submenu (THE_IDEA.md section 1.7) + +### Protocols Supported + +| Protocol | Purpose | Reference | +|----------|---------|-----------| +| FTP | CSV file transfer | Primary protocol mentioned | +| SCP | Secure copy | Section 1.6 | +| SFTP | Secure FTP | Section 1.6 | +| WebDAV | Web-based file access | Section 1.6 | +| TCP Socket | Real-time data requests | Section 1.6 | + +--- + +## Authentication & Identity + +**Station Configuration:** +- Station ID (e.g., `D007`) +- Device version number (e.g., `v4.0.4`) +- Login status for remote access + +**Network Credentials:** +- FTP/SCP username and password +- Referenced in THE_IDEA.md section 1.6 (Protocol Setting) +- **Note:** Credentials should be stored securely (env vars, not plain config) + +--- + +## Alert Systems + +### SMS/Call Alerts + +**Contact Types:** +- Master phones (2 numbers) +- SubMaster phones (2 numbers) +- Engineer phones (up to 10 numbers) +- RTU Mobile number + +**Alert Triggers:** +- Danger rainfall threshold (configurable mm per hour) +- Warning rainfall threshold +- Water level thresholds (Danger, Warning, Alert, Normal) + +--- + +## Display Interfaces + +### Local Touchscreen + +- **Resolution:** 1024x600 +- **Connection:** Direct video output (HDMI/CSI) +- **Browser:** Chromium Kiosk Mode +- **URL:** `http://pihostname:8080` + +### Remote Web Access + +- **Resolution:** Full HD (1920x1080) +- **Authentication:** Login required +- **URL:** `http://pihostname:9090/` + +--- + +## Communication Status + +**Monitoring Data:** +- Communication status display (e.g., `0ASU/-113dBm(0%)`) +- Signal strength (dBm) +- Connection percentage + +--- + +## Environment Configuration + +### Required Configuration Items + +**Network:** +- Local IP Address +- Subnet Mask +- Gateway +- DNS Server +- MAC Address +- Transfer Protocol (FTP/SCP/SFTP/WEBDAV) + +**Server:** +- Server IP Address +- TCP Port +- File Directory (e.g., `/myvscada/stationA`) + +**Sensors:** +- ADC channel types (4-20mA, 0-10vDC) +- Sensor datum offsets +- Sensor ranges and units + +--- + +## Data Flow Summary + +``` +Sensors (ADC, RF, WL) + ↓ +Python Backend (data collection) + ↓ +CSV File Generation + ↓ +Transfer Protocol (FTP/SCP/SFTP/WebDAV) + ↓ +myvscada Server + ↓ +Processed/Error folder handling +``` + +--- + +*Integration audit: 2026-03-12* \ No newline at end of file diff --git a/.planning/codebase/STACK.md b/.planning/codebase/STACK.md new file mode 100644 index 000000000..3585ef01b --- /dev/null +++ b/.planning/codebase/STACK.md @@ -0,0 +1,137 @@ +# Technology Stack + +**Analysis Date:** 2026-03-12 + +## Project Status + +This is a **greenfield project** - no implementation code exists yet. The repository currently contains only: +- `THE_IDEA.md` - Requirements specification document +- `.opencode/` - OpenCode/GSD framework configuration + +The following stack analysis is based on the requirements defined in `THE_IDEA.md`. + +--- + +## Languages + +**Primary:** +- **HTML/CSS/JavaScript** - Web-based UI for the 7-inch touchscreen and remote full HD interface + - Expected to run in Chromium Kiosk Mode on Raspberry Pi + - Must support dual resolution: 1024x600 (touchscreen) and 1920x1080 (remote) + +**Secondary:** +- **Python** (likely) - Backend for sensor data collection, CSV processing, and network operations + - Raspberry Pi standard runtime + - Used for serial communication with sensors (ADC, rainfall sensors) + - CSV file generation and management + +--- + +## Runtime + +**Environment:** +- **Raspberry Pi OS** - Primary runtime on Pi Zero 2 W and Pi 3B + - Pi Zero 2 W: ARMv8 single-core, 512MB RAM + - Pi 3B: ARMv7 quad-core, 1GB RAM + +**Browser:** +- **Chromium** - Kiosk mode for touchscreen interface + - Target URL: `http://pihostname:8080` (touchscreen) + - Target URL: `http://pihostname:9090/` (remote full HD) + +**Package Manager:** +- Not yet established (pending project initialization) + +--- + +## Frameworks + +**Core:** +- **Lightweight web framework** (TBD) - For serving the UI + - Options: Flask, FastAPI (Python), or simple HTTP server + - Must be performant on low-power Pi Zero 2 W +- **Frontend** - Plain HTML/CSS or lightweight framework + - Recommendation: Static HTML/CSS for main interface (performance) + - Avoid heavy SPA frameworks to minimize memory footprint + +**Sensor Interfaces:** +- **Serial communication** - For ADC, rainfall sensors, GPS +- **SDI-12** - For soil moisture and evapotranspiration sensors (referenced in requirements) + +**Data Handling:** +- **CSV processing** - For data logging and transfer (per flowchart in THE_IDEA.md) + +**Build/Dev:** +- Not yet established (pending project initialization) + +--- + +## Key Dependencies + +**Hardware Interfaces:** +- Serial port communication (Python pyserial or similar) +- ADC reading libraries +- GPS module support (USB) + +**Network:** +- FTP client (for data transfer to myvscada server) +- SCP/SFTP client +- WebDAV client +- TCP socket libraries + +**Data Processing:** +- CSV generation and parsing libraries +- Data validation utilities + +--- + +## Configuration + +**Network Settings:** +- Local IP configuration (static IP) +- Subnet mask, gateway, DNS +- MAC address +- Transfer protocol selection (FTP/SCP/SFTP/WEBDAV) + +**Sensor Configuration:** +- ADC channels (4-20mA, 0-10vDC types) +- Rainfall sensor settings +- Water level thresholds +- Evapotranspiration settings + +**Server Settings:** +- Server IP and TCP port +- Tide data hours +- GPS coordinates (manual or USB GPS) + +**Mobile Settings:** +- Phone numbers for alerts (Master, SubMaster, Engineer contacts) + +--- + +## Platform Requirements + +**Development:** +- Standard web development tools (editor, browser) +- Python development environment +- Git for version control + +**Production:** +- Raspberry Pi Zero 2 W or 3B +- 7-inch capacitive touchscreen (1024x600) +- Chromium browser (Kiosk mode) +- Network connectivity (Ethernet or mobile/GPRS) + +--- + +## Performance Constraints + +| Resource | Target | Concern | +|----------|--------|---------| +| RAM | <256MB for UI | Pi Zero 2 W has only 512MB total | +| Startup time | <3 seconds | Cold start in Chromium Kiosk | +| Bundle size | Minimal | Optimize for low-power device | + +--- + +*Stack analysis: 2026-03-12* \ No newline at end of file diff --git a/.planning/codebase/STRUCTURE.md b/.planning/codebase/STRUCTURE.md new file mode 100644 index 000000000..72cb50148 --- /dev/null +++ b/.planning/codebase/STRUCTURE.md @@ -0,0 +1,148 @@ +# Codebase Structure + +**Analysis Date:** 2026-03-12 + +## Directory Layout + +``` +/root/tckuiyo/ +├── THE_IDEA.md # Project concept documentation +├── .gitignore # Git ignore rules +├── .bg-shell/ # Background shell config (manifest.json) +├── .gsd/ # GSD project data +│ └── milestones/ # Milestone definitions (empty) +├── .opencode/ # GSD Framework (main project code) +│ ├── package.json # Dependencies (OpenCode plugin) +│ ├── bun.lock # Dependency lockfile +│ ├── opencode.db # OpenCode database +│ ├── commands/ # User-facing commands +│ ├── agents/ # AI agent definitions +│ ├── get-shit-done/ # Workflows +│ │ └── workflows/ # Execution logic +│ ├── skills/ # Specialized skills +│ ├── rules/ # Behavior rules +│ ├── node_modules/ # Dependencies +│ └── .gitignore # OpenCode-specific ignores +├── .planning/ # Project planning output +│ └── codebase/ # Codebase analysis docs (where mappers write) +└── (empty directories for future use) +``` + +## Directory Purposes + +**`.opencode/`:** +- Purpose: Core GSD framework configuration +- Contains: Commands, agents, workflows, skills, rules +- Key files: All 33 command files, 12 agent files, 36 workflow files + +**`.opencode/commands/gsd/`:** +- Purpose: User-invokable GSD commands +- Contains: Markdown command definitions with YAML frontmatter +- Key files: `gsd-new-project.md`, `gsd-map-codebase.md`, `gsd-plan-phase.md`, `gsd-execute-phase.md` + +**`.opencode/agents/`:** +- Purpose: AI agent role definitions +- Contains: Agent configurations with tools and skills +- Key files: `gsd-codebase-mapper.md`, `gsd-planner.md`, `gsd-executor.md`, `gsd-verifier.md` + +**`.opencode/get-shit-done/workflows/`:** +- Purpose: Execution logic for commands +- Contains: Step-by-step workflow instructions +- Key files: `map-codebase.md`, `new-project.md`, `plan-phase.md`, `execute-phase.md` + +**`.opencode/skills/`:** +- Purpose: Specialized capability modules +- Contains: Skill definitions with scripts +- Key files: `gsd-oc-select-model/` (model selection skill) + +**`.opencode/rules/`:** +- Purpose: Global behavior rules +- Contains: Rule definitions for agent behavior +- Key files: `gsd-oc-work-hard.md` + +**`.planning/codebase/`:** +- Purpose: Output location for codebase mapper agents +- Contains: Analysis documents written by mapper agents +- Target files: STACK.md, INTEGRATIONS.md, ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md, CONCERNS.md + +**`.gsd/milestones/`:** +- Purpose: Milestone definitions for projects +- Contains: Milestone JSON files (currently empty) +- Used by: new-milestone, complete-milestone commands + +## Key File Locations + +**Entry Points:** +- `.opencode/commands/gsd/gsd-*.md`: Command definitions invoked via `/gsd-*` + +**Configuration:** +- `.opencode/package.json`: Dependencies - `@opencode-ai/plugin: 1.2.24` +- `.opencode/bun.lock`: Dependency lockfile +- `.gitignore`: Excludes node_modules, .opencode/, .gsd/, .planning/, *.swp + +**Core Logic:** +- All logic in `.opencode/` - this IS the application (OpenCode configuration) + +**Testing:** +- No separate test directory - OpenCode handles testing via verify-work workflow + +## Naming Conventions + +**Files:** +- Commands: `gsd-{command-name}.md` (kebab-case) +- Agents: `gsd-{agent-name}.md` (kebab-case) +- Workflows: `{workflow-name}.md` (kebab-case) +- Skills: `{skill-name}/` directory with SKILL.md inside + +**Directories:** +- `.opencode/commands/gsd/`: GSD commands group +- `.opencode/agents/`: Agent definitions +- `.opencode/get-shit-done/workflows/`: Workflow definitions +- `.opencode/skills/`: Skill packages +- `.opencode/node_modules/`: npm dependencies +- `.planning/codebase/`: Codebase analysis outputs + +## Where to Add New Code + +**New Command:** +- Implementation: `.opencode/commands/gsd/gsd-{name}.md` +- Workflow: Add corresponding `.opencode/get-shit-done/workflows/{name}.md` + +**New Agent:** +- Implementation: `.opencode/agents/gsd-{name}.md` + +**New Workflow:** +- Implementation: `.opencode/get-shit-done/workflows/{name}.md` +- Referenced by: Command's `` tag + +**New Skill:** +- Implementation: `.opencode/skills/{skill-name}/SKILL.md` + +**Codebase Analysis Output:** +- Location: `.planning/codebase/` (written by gsd-codebase-mapper agents) + +## Special Directories + +**`.opencode/`:** +- Purpose: OpenCode project root - contains all project code +- Generated: No - this IS the codebase +- Committed: Yes - core project files + +**`.opencode/node_modules/`:** +- Purpose: Dependencies for OpenCode plugin +- Generated: Yes (via bun install) +- Committed: No (in .gitignore) + +**`.planning/`:** +- Purpose: Planning output and project state +- Generated: Yes (by GSD commands) +- Committed: Yes (project state is versioned) + +**`.gsd/`:** +- Purpose: Project milestone and tracking data +- Generated: Yes (by GSD commands) +- Committed: Yes (project progress is versioned) + +--- + +*Structure analysis: 2026-03-12* \ No newline at end of file diff --git a/.planning/codebase/TESTING.md b/.planning/codebase/TESTING.md new file mode 100644 index 000000000..815e39fdb --- /dev/null +++ b/.planning/codebase/TESTING.md @@ -0,0 +1,345 @@ +# Testing Patterns + +**Analysis Date:** 2026-03-12 + +## Test Framework + +**Mixed approach detected:** + +### Primary: Node.js built-in `node:test` +- Used in `bin/gsd-tools.test.cjs` +- Version: Node.js built-in (no package needed) +- Config: None detected + +### Secondary: Vitest +- Used in `bin/test/*.test.cjs` files +- Version: `^3.2.4` (from package.json) +- Config: None detected (uses defaults) + +**Run Commands:** +```bash +npm test # Run all tests (vitest run) +npm run test:watch # Watch mode (vitest) +``` + +## Test File Organization + +**Location:** `bin/test/` + +**Naming:** `{command-name}.test.cjs` + +**Example files:** +- `bin/test/get-profile.test.cjs` +- `bin/test/set-profile.test.cjs` +- `bin/test/allow-read-config.test.cjs` +- `bin/test/oc-profile-config.test.cjs` +- `bin/test/pivot-profile.test.cjs` + +## Test Structure + +### Vitest Style (Recommended) + +From `bin/test/get-profile.test.cjs`: + +```javascript +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import fs from 'fs'; +import path from 'path'; +import os from 'os'; + +describe('get-profile.cjs', () => { + let testDir; + let planningDir; + let configPath; + let capturedLog; + let capturedError; + let exitCode; + + beforeEach(() => { + // Create isolated test directory + testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'get-profile-test-')); + planningDir = path.join(testDir, '.planning'); + configPath = path.join(planningDir, 'oc_config.json'); + fs.mkdirSync(planningDir, { recursive: true }); + + // Reset captured output + capturedLog = null; + capturedError = null; + exitCode = null; + + // Mock console.log to capture all output + console.log = (msg) => { + allLogs.push(msg); + capturedLog = msg; + }; + console.error = (msg) => { + allErrors.push(msg); + capturedError = msg; + }; + process.exit = (code) => { + exitCode = code; + throw new Error(`process.exit(${code})`); + }; + }); + + afterEach(() => { + // Restore original functions + console.log = originalLog; + console.error = originalError; + process.exit = originalExit; + + // Cleanup test directory + try { + fs.rmSync(testDir, { recursive: true, force: true }); + } catch (err) { + // Ignore cleanup errors + } + }); + + it('returns current profile when current_oc_profile is set', () => { + fs.writeFileSync(configPath, JSON.stringify(VALID_CONFIG_WITH_CURRENT, null, 2)); + const getProfile = importGetProfile(); + + try { + getProfile(testDir, []); + } catch (err) { + // Expected to throw due to process.exit mock + } + + expect(exitCode).toBe(0); + const output = JSON.parse(capturedLog); + expect(output.success).toBe(true); + }); +}); +``` + +### Node:test Style + +From `bin/gsd-tools.test.cjs`: + +```javascript +const { test, describe, beforeEach, afterEach } = require('node:test'); +const assert = require('node:assert'); +const fs = require('fs'); +const path = require('path'); + +describe('history-digest command', () => { + let tmpDir; + + beforeEach(() => { + tmpDir = createTempProject(); + }); + + afterEach(() => { + cleanup(tmpDir); + }); + + test('empty phases directory returns valid schema', () => { + const result = runGsdTools('history-digest', tmpDir); + assert.ok(result.success, `Command failed: ${result.error}`); + + const digest = JSON.parse(result.output); + assert.deepStrictEqual(digest.phases, {}, 'phases should be empty object'); + }); +}); +``` + +### Manual Test Runner Style + +From `bin/test/allow-read-config.test.cjs`: + +```javascript +function testCreatePermission() { + console.log('Test: Create new opencode.json with permission...'); + + const testDir = createTestDir(); + + try { + const result = runCLI(testDir, []); + + if (!result.success) { + throw new Error(`Expected success, got: ${JSON.stringify(result)}`); + } + + // Verify opencode.json was created + const opencodePath = path.join(testDir, 'opencode.json'); + if (!fs.existsSync(opencodePath)) { + throw new Error('opencode.json was not created'); + } + + console.log('✓ PASS: Create permission\n'); + return true; + } catch (err) { + console.error('✗ FAIL:', err.message, '\n'); + return false; + } finally { + cleanupTestDir(testDir); + } +} + +function runTests() { + console.log('Running allow-read-config tests...\n'); + + const results = [ + testCreatePermission(), + testIdempotency(), + testDryRun(), + ]; + + const passed = results.filter(r => r).length; + console.log(`Results: ${passed}/${total} tests passed`); + + if (passed === total) { + process.exit(0); + } else { + process.exit(1); + } +} + +runTests(); +``` + +## Mocking Patterns + +### Console/Process Mocking + +**Vitest approach:** +```javascript +const originalLog = console.log; +const originalError = console.error; +const originalExit = process.exit; + +beforeEach(() => { + console.log = (msg) => { + allLogs.push(msg); + capturedLog = msg; + }; + console.error = (msg) => { + allErrors.push(msg); + capturedError = msg; + }; + process.exit = (code) => { + exitCode = code; + throw new Error(`process.exit(${code})`); + }; +}); + +afterEach(() => { + console.log = originalLog; + console.error = originalError; + process.exit = originalExit; +}); +``` + +### Require Cache Clearing + +```javascript +const importGetProfile = () => { + const modulePath = '../gsd-oc-commands/get-profile.cjs'; + delete require.cache[require.resolve(modulePath)]; + return require(modulePath); +}; +``` + +## Test Fixtures + +**Location:** `bin/test/fixtures/` + +**Pattern:** In-file constants + +```javascript +const VALID_CONFIG_WITH_CURRENT = { + current_oc_profile: 'smart', + profiles: { + presets: { + simple: { + planning: 'bailian-coding-plan/qwen3.5-plus', + execution: 'bailian-coding-plan/qwen3.5-plus', + verification: 'bailian-coding-plan/qwen3.5-plus' + }, + smart: { /* ... */ } + } + } +}; +``` + +## Test Helpers + +### CLI Execution + +```javascript +function runCLI(testDir, args) { + const cmd = `node ${TOOLS_PATH} allow-read-config ${args.join(' ')}`; + const output = execSync(cmd, { cwd: testDir, encoding: 'utf8' }); + return JSON.parse(output); +} +``` + +### Temp Directory Creation + +```javascript +function createTestDir() { + const testDir = path.join(os.tmpdir(), `gsd-oc-test-${Date.now()}`); + fs.mkdirSync(testDir, { recursive: true }); + return testDir; +} + +function cleanupTestDir(testDir) { + if (fs.existsSync(testDir)) { + fs.rmSync(testDir, { recursive: true, force: true }); + } +} +``` + +## Assertion Patterns + +### Vitest +```javascript +expect(exitCode).toBe(0); +expect(output.success).toBe(true); +expect(output.data).toHaveProperty('smart'); +expect(output.data.smart).toEqual(VALID_CONFIG_WITH_CURRENT.profiles.presets.smart); +``` + +### Node.js assert +```javascript +assert.ok(result.success, `Command failed: ${result.error}`); +assert.deepStrictEqual(digest.phases, {}, 'phases should be empty object'); +``` + +## Coverage + +**No coverage configuration detected.** No enforcement of coverage thresholds. + +## Test Types + +### Unit Tests +- Individual function testing +- Use mocking for dependencies +- Test isolated behavior + +### Integration/CLI Tests +- Execute CLI commands via `execSync` +- Test with real temporary directories +- Verify file creation/state changes + +### Patterns +- Test both success and error paths +- Test flag combinations (--verbose, --dry-run) +- Test idempotency (running same command twice) + +## Common Issues + +### Inconsistent Test Frameworks +- Some tests use Vitest, others use Node.js built-in `node:test` +- Some tests use manual test runner (no framework) +- **Recommendation:** Standardize on one framework + +### Missing Test Config +- No `vitest.config.js` found +- No `jest.config.js` found +- **Recommendation:** Add configuration file + +--- + +*Testing analysis: 2026-03-12* diff --git a/README.md b/README.md new file mode 100644 index 000000000..e69de29bb