diff --git a/.github/workflows/opencode.yml b/.github/workflows/opencode.yml new file mode 100644 index 0000000..07d33d7 --- /dev/null +++ b/.github/workflows/opencode.yml @@ -0,0 +1,33 @@ +name: opencode + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + +jobs: + opencode: + if: | + contains(github.event.comment.body, ' /oc') || + startsWith(github.event.comment.body, '/oc') || + contains(github.event.comment.body, ' /opencode') || + startsWith(github.event.comment.body, '/opencode') + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + pull-requests: read + issues: read + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run opencode + uses: anomalyco/opencode/github@latest + env: + OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} + with: + model: opencode/big-pickle \ No newline at end of file diff --git a/.ralph/current-events b/.ralph/current-events index f529c19..8f0a8ae 100644 --- a/.ralph/current-events +++ b/.ralph/current-events @@ -1 +1 @@ -.ralph/events-20260321-235351.jsonl \ No newline at end of file +.ralph/events-20260322-001241.jsonl \ No newline at end of file diff --git a/.ralph/current-loop-id b/.ralph/current-loop-id index 9cd6fc1..47fe703 100644 --- a/.ralph/current-loop-id +++ b/.ralph/current-loop-id @@ -1 +1 @@ -primary-20260321-235351 \ No newline at end of file +primary-20260322-001241 \ No newline at end of file diff --git a/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-587-32854.log b/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-587-32854.log index 76ac577..3291cc3 100644 --- a/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-587-32854.log +++ b/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-587-32854.log @@ -2,3 +2,4 @@ 2026-03-21T23:53:51.588132Z INFO ralph: Spawning subprocess for TUI mode child_args=["-c", "ralph.yml", "-H", "builtin:code-assist", "run", "--rpc"] 2026-03-21T23:53:51.588162Z INFO ralph: TUI subprocess stderr redirected to log file log_file=/home/jimmy/inspection_app_n/prototoolagain/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-588-32854.log 2026-03-21T23:53:51.588319Z INFO ralph: TUI running in subprocess RPC mode +2026-03-22T00:09:21.753198Z INFO ralph_tui::app: Ctrl+C detected, signaling abort diff --git a/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-588-32854.log b/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-588-32854.log index bf305ba..c514a9b 100644 --- a/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-588-32854.log +++ b/.ralph/diagnostics/logs/ralph-2026-03-22T00-53-51-588-32854.log @@ -7,3 +7,9 @@ 2026-03-21T23:59:04.846344Z  INFO ralph_core::event_loop: Looking for memories at: "/home/jimmy/inspection_app_n/prototoolagain/.ralph/agent/memories.md" (exists: false) 2026-03-21T23:59:04.846349Z  INFO ralph_core::event_loop: Successfully loaded 0 memories from store 2026-03-21T23:59:04.846352Z  INFO ralph_core::event_loop: Memory store is empty - no memories to inject +2026-03-22T00:08:06.435267Z  WARN ralph::loop_runner: Output indicated `ralph emit`, but no event became readable before fallback logic hat=ralph +2026-03-22T00:08:06.435436Z  INFO ralph_core::event_loop: Memory injection check: enabled=true, inject=Auto, workspace_root="/home/jimmy/inspection_app_n/prototoolagain" +2026-03-22T00:08:06.435450Z  INFO ralph_core::event_loop: Looking for memories at: "/home/jimmy/inspection_app_n/prototoolagain/.ralph/agent/memories.md" (exists: false) +2026-03-22T00:08:06.435455Z  INFO ralph_core::event_loop: Successfully loaded 0 memories from store +2026-03-22T00:08:06.435458Z  INFO ralph_core::event_loop: Memory store is empty - no memories to inject +2026-03-22T00:09:21.753530Z  WARN ralph::rpc_stdin: Failed to write to stdout, stopping emitter diff --git a/.ralph/diagnostics/logs/ralph-2026-03-22T01-12-41-345-36443.log b/.ralph/diagnostics/logs/ralph-2026-03-22T01-12-41-345-36443.log new file mode 100644 index 0000000..9af776d --- /dev/null +++ b/.ralph/diagnostics/logs/ralph-2026-03-22T01-12-41-345-36443.log @@ -0,0 +1,7 @@ +2026-03-22T00:12:41.349334Z  WARN ralph::loop_runner: Interactive mode requested but stdout is not a TTY, falling back to autonomous +2026-03-22T00:12:41.349647Z  INFO ralph_core::event_loop: Memory injection check: enabled=true, inject=Auto, workspace_root="/home/jimmy/inspection_app_n/prototoolagain" +2026-03-22T00:12:41.349653Z  INFO ralph2026-03-22T00:13:10.085278Z INFO ralph_tui::app: Ctrl+C detected, signaling abort +_n/prototoolagain/.ralph/agent/memories.md" (exists: false) +2026-03-22T00:12:41.349657Z  INFO ralph_core::event_loop: Successfully loaded 0 memories from store +2026-03-22T00:12:41.349659Z  INFO ralph_core::event_loop: Memory store is empty - no memories to inject +2026-03-22T00:13:10.085422Z  WARN ralph::rpc_stdin: Failed to write to stdout, stopping emitter diff --git a/.ralph/events-20260322-001241.jsonl b/.ralph/events-20260322-001241.jsonl new file mode 100644 index 0000000..0b4d8d3 --- /dev/null +++ b/.ralph/events-20260322-001241.jsonl @@ -0,0 +1 @@ +{"ts":"2026-03-22T00:12:41.349526750+00:00","iteration":0,"hat":"loop","topic":"build.start","triggered":"planner","payload":"You are building a production-ready Inspection Reporting and Management web application from scratch. The GitHub remote URL is: https://github.com/pingud98/prototoolagain.git\n\n---\n\n## TECH STACK\n\n- Language: Python 3.11+\n- Web Framework: Flask (with Flask-Login, Flask-WTF, Flask-SQLAlchemy)\n- Database: SQLite via SQLAlchemy ORM\n- PDF Generation: WeasyPrint (A4-formatted output)\n- TLS/HTTPS: Self-signed certificate via trustme or mkcert for local hosting\n- Frontend: Jinja2 templates + Tailwind CS... [truncated, 7198 chars total]"} diff --git a/.ralph/history.jsonl b/.ralph/history.jsonl index 78cd2f6..5b08e5b 100644 --- a/.ralph/history.jsonl +++ b/.ralph/history.jsonl @@ -1 +1,2 @@ {"ts":"2026-03-21T23:53:51.596853071Z","type":{"kind":"loop_started","prompt":"You are building a production-ready Inspection Reporting and Management web application from scratch. The GitHub remote URL is: https://github.com/pingud98/prototoolagain.git\n\n---\n\n## TECH STACK\n\n- Language: Python 3.11+\n- Web Framework: Flask (with Flask-Login, Flask-WTF, Flask-SQLAlchemy)\n- Database: SQLite via SQLAlchemy ORM\n- PDF Generation: WeasyPrint (A4-formatted output)\n- TLS/HTTPS: Self-signed certificate via trustme or mkcert for local hosting\n- Frontend: Jinja2 templates + Tailwind CSS (via CDN) + vanilla JS\n- Auth: Bcrypt password hashing, session-based login\n- File Storage: Local filesystem under /uploads/, referenced in DB\n\n---\n\n## PROJECT STRUCTURE\n\ninspection-app/\n├── app/\n│ ├── __init__.py\n│ ├── models.py\n│ ├── routes/\n│ │ ├── auth.py\n│ │ ├── inspections.py\n│ │ ├── admin.py\n│ │ └── export.py\n│ ├── templates/\n│ │ ├── base.html\n│ │ ├── login.html\n│ │ ├── dashboard.html\n│ │ ├── inspection_form.html\n│ │ ├── inspection_view.html\n│ │ └── admin/\n│ │ ├── users.html\n│ │ └── user_form.html\n│ ├── static/\n│ │ ├── css/\n│ │ └── js/\n│ └── utils/\n│ ├── pdf_generator.py\n│ └── security.py\n├── uploads/\n├── certs/\n├── setup.py\n├── config.py\n├── run.py\n├── requirements.txt\n└── .gitignore\n\n---\n\n## DATABASE MODELS\n\n### User\n- id, username, full_name, email, password_hash, is_admin, is_active, created_at\n\n### Inspection\n- id, installation_name, location, inspection_date, version (int, starts at 1),\n reference_number (int), observations, conclusion_text,\n conclusion_status (enum: ok / minor / major),\n created_by (FK User), created_at, updated_at\n\n### InspectionInspector\n- id, inspection_id (FK), user_id (FK nullable), free_text_name (nullable)\n (Supports both registered users and free-text names)\n\n### Photo\n- id, inspection_id (FK), filename, caption,\n action_required (enum: none / urgent / before_next), uploaded_at\n\n---\n\n## SETUP SCRIPT (setup.py)\n\nThe setup script must:\n1. Install all dependencies from requirements.txt using pip\n2. Generate a self-signed TLS certificate and key, saved to certs/\n3. Create the SQLite database and run all table migrations\n4. Prompt the admin for: username, full name, email, password (with confirmation)\n5. Create the admin account with is_admin=True\n6. Print a success message with the local HTTPS URL (e.g. https://localhost:5000)\n7. Be runnable with: python setup.py\n\n---\n\n## CORE FEATURES\n\n### Authentication\n- Login page (username + password)\n- Session-based auth with Flask-Login\n- All routes protected — redirect to login if not authenticated\n- Logout route\n- No self-registration — admin creates all accounts\n\n### Admin Panel (/admin)\n- List all users\n- Create new user (username, full name, email, password, admin toggle)\n- Edit user (change name, email, reset password, toggle active/admin)\n- Deactivate (not delete) users\n- Only accessible to is_admin=True users\n\n### Dashboard (/)\n- Table of all inspections the logged-in user has access to\n- Columns: Reference No., Installation Name, Location, Date, Version, Conclusion Status, Actions\n- Actions: View, Edit, Export PDF\n- \"New Inspection\" button\n\n### Inspection Form (/inspection/new and /inspection//edit)\n\nFields:\n1. Installation Name — text input\n2. Location — text input\n3. Date of Inspection — date picker\n4. Version — auto-incremented integer (display only, not editable)\n5. Reference Number — integer input\n6. Inspector(s) — pre-filled with logged-in user's full name; allow adding more via:\n - Dropdown of registered users\n - Free-text field for external individuals\n - Display as removable tags/chips\n7. Observations — large textarea\n8. Photos section:\n - Upload multiple photos\n - For each uploaded photo display a thumbnail\n - Per-photo fields: caption (text), action_required (radio buttons):\n \"No action required\"\n \"Urgent action required\"\n \"Action required before next inspection\"\n - Ability to remove photos\n9. Conclusion section:\n - Conclusion comments textarea\n - Radio buttons (select exactly one):\n OK for operation in current state\n Minor comments — Remedial actions required for continued operation\n Major comments — Operation suspended until resolution and satisfactory follow-up inspection\n\nButtons:\n- New inspection: \"Complete Report\" → saves, sets version=1, redirects to view page\n- Edit existing: \"Update Report\" → saves, increments version by 1, redirects to view page\n- Cancel → returns to dashboard\n\n### Inspection View (/inspection/)\n- Read-only formatted view of the report\n- Shows all fields, photos (with captions and action status), inspectors, conclusion\n- \"Edit Report\" button\n- \"Export as PDF\" button\n\n---\n\n## PDF EXPORT (/inspection//pdf)\n\n- Generated using WeasyPrint\n- Formatted for A4 pages\n- Include:\n - App name / report title header\n - All inspection fields in a clean two-column layout\n - Inspector names listed\n - Observations in a clearly delineated box\n - Photos displayed in a grid (max 2 per row), each with caption and action status clearly labelled\n - Conclusion section with selected status prominently displayed\n - Footer with page number and generation timestamp\n- Flows naturally across multiple A4 pages if content requires it\n- Served as a file download: inspection_report__v.pdf\n\n---\n\n## SECURITY REQUIREMENTS\n\n- All passwords hashed with bcrypt (min cost factor 12)\n- CSRF protection on all forms via Flask-WTF\n- File uploads validated: only JPEG, PNG, GIF, WEBP accepted; max 10MB per file\n- Uploaded filenames sanitised with werkzeug.utils.secure_filename and stored with UUID prefix\n- User input escaped in all templates (Jinja2 autoescaping enabled)\n- Admin routes protected with both login_required and admin_required decorators\n- Secret key loaded from environment variable SECRET_KEY or auto-generated and saved to .env on first run\n- HTTPS enforced — Flask run with SSL context using certs from certs/\n- .env and *.db and certs/ added to .gitignore\n\n---\n\n## GITHUB INSTRUCTIONS\n\n- The repository already exists and has been initialised with prior commits\n- Completely discard all prior history\n- Use git checkout --orphan new-branch, add all files, commit, then force-push to main\n- Commit message: \"Initial commit: Inspection reporting app\"\n- Include a comprehensive README.md with:\n - Project overview\n - Requirements (Python version, OS)\n - Setup instructions (python setup.py)\n - How to run (python run.py)\n - How to access (HTTPS URL)\n - Notes on the self-signed certificate browser warning\n\n---\n\n## CODE QUALITY STANDARDS\n\n- All Python files include docstrings\n- Routes grouped into Blueprints\n- No hardcoded secrets\n- Database access only via SQLAlchemy ORM — no raw SQL\n- Error pages for 403, 404, 500\n- Flash messages for all user actions (success and error)\n- Logging to a rotating file log (logs/app.log)\n\n---\n\n## EXECUTION ORDER\n\nBuild in this order:\n1. requirements.txt and config.py\n2. app/models.py\n3. app/__init__.py (app factory)\n4. Auth blueprint + templates\n5. Admin blueprint + templates\n6. Inspection blueprint + form + view templates\n7. PDF export utility + route\n8. setup.py\n9. run.py\n10. README.md\n11. .gitignore\n12. GitHub force-push\n\nDo not proceed to the next step until the current one is complete and internally consistent.\n\n---\n\n## NOTES FOR THE OPERATOR\n\n- WeasyPrint requires system-level dependencies. Install them before running setup.py:\n Debian/Ubuntu: sudo apt install libpango-1.0-0 libharfbuzz0b libpangoft2-1.0-0\n macOS: brew install pango\n Windows: See https://doc.courtbouillon.org/weasyprint/stable/first_steps.html\n\n\n"}} +{"ts":"2026-03-22T00:12:41.349582714Z","type":{"kind":"loop_started","prompt":"You are building a production-ready Inspection Reporting and Management web application from scratch. The GitHub remote URL is: https://github.com/pingud98/prototoolagain.git\n\n---\n\n## TECH STACK\n\n- Language: Python 3.11+\n- Web Framework: Flask (with Flask-Login, Flask-WTF, Flask-SQLAlchemy)\n- Database: SQLite via SQLAlchemy ORM\n- PDF Generation: WeasyPrint (A4-formatted output)\n- TLS/HTTPS: Self-signed certificate via trustme or mkcert for local hosting\n- Frontend: Jinja2 templates + Tailwind CSS (via CDN) + vanilla JS\n- Auth: Bcrypt password hashing, session-based login\n- File Storage: Local filesystem under /uploads/, referenced in DB\n\n---\n\n## PROJECT STRUCTURE\n\ninspection-app/\n├── app/\n│ ├── __init__.py\n│ ├── models.py\n│ ├── routes/\n│ │ ├── auth.py\n│ │ ├── inspections.py\n│ │ ├── admin.py\n│ │ └── export.py\n│ ├── templates/\n│ │ ├── base.html\n│ │ ├── login.html\n│ │ ├── dashboard.html\n│ │ ├── inspection_form.html\n│ │ ├── inspection_view.html\n│ │ └── admin/\n│ │ ├── users.html\n│ │ └── user_form.html\n│ ├── static/\n│ │ ├── css/\n│ │ └── js/\n│ └── utils/\n│ ├── pdf_generator.py\n│ └── security.py\n├── uploads/\n├── certs/\n├── setup.py\n├── config.py\n├── run.py\n├── requirements.txt\n└── .gitignore\n\n---\n\n## DATABASE MODELS\n\n### User\n- id, username, full_name, email, password_hash, is_admin, is_active, created_at\n\n### Inspection\n- id, installation_name, location, inspection_date, version (int, starts at 1),\n reference_number (int), observations, conclusion_text,\n conclusion_status (enum: ok / minor / major),\n created_by (FK User), created_at, updated_at\n\n### InspectionInspector\n- id, inspection_id (FK), user_id (FK nullable), free_text_name (nullable)\n (Supports both registered users and free-text names)\n\n### Photo\n- id, inspection_id (FK), filename, caption,\n action_required (enum: none / urgent / before_next), uploaded_at\n\n---\n\n## SETUP SCRIPT (setup.py)\n\nThe setup script must:\n1. Install all dependencies from requirements.txt using pip\n2. Generate a self-signed TLS certificate and key, saved to certs/\n3. Create the SQLite database and run all table migrations\n4. Prompt the admin for: username, full name, email, password (with confirmation)\n5. Create the admin account with is_admin=True\n6. Print a success message with the local HTTPS URL (e.g. https://localhost:5000)\n7. Be runnable with: python setup.py\n\n---\n\n## CORE FEATURES\n\n### Authentication\n- Login page (username + password)\n- Session-based auth with Flask-Login\n- All routes protected — redirect to login if not authenticated\n- Logout route\n- No self-registration — admin creates all accounts\n\n### Admin Panel (/admin)\n- List all users\n- Create new user (username, full name, email, password, admin toggle)\n- Edit user (change name, email, reset password, toggle active/admin)\n- Deactivate (not delete) users\n- Only accessible to is_admin=True users\n\n### Dashboard (/)\n- Table of all inspections the logged-in user has access to\n- Columns: Reference No., Installation Name, Location, Date, Version, Conclusion Status, Actions\n- Actions: View, Edit, Export PDF\n- \"New Inspection\" button\n\n### Inspection Form (/inspection/new and /inspection//edit)\n\nFields:\n1. Installation Name — text input\n2. Location — text input\n3. Date of Inspection — date picker\n4. Version — auto-incremented integer (display only, not editable)\n5. Reference Number — integer input\n6. Inspector(s) — pre-filled with logged-in user's full name; allow adding more via:\n - Dropdown of registered users\n - Free-text field for external individuals\n - Display as removable tags/chips\n7. Observations — large textarea\n8. Photos section:\n - Upload multiple photos\n - For each uploaded photo display a thumbnail\n - Per-photo fields: caption (text), action_required (radio buttons):\n \"No action required\"\n \"Urgent action required\"\n \"Action required before next inspection\"\n - Ability to remove photos\n9. Conclusion section:\n - Conclusion comments textarea\n - Radio buttons (select exactly one):\n OK for operation in current state\n Minor comments — Remedial actions required for continued operation\n Major comments — Operation suspended until resolution and satisfactory follow-up inspection\n\nButtons:\n- New inspection: \"Complete Report\" → saves, sets version=1, redirects to view page\n- Edit existing: \"Update Report\" → saves, increments version by 1, redirects to view page\n- Cancel → returns to dashboard\n\n### Inspection View (/inspection/)\n- Read-only formatted view of the report\n- Shows all fields, photos (with captions and action status), inspectors, conclusion\n- \"Edit Report\" button\n- \"Export as PDF\" button\n\n---\n\n## PDF EXPORT (/inspection//pdf)\n\n- Generated using WeasyPrint\n- Formatted for A4 pages\n- Include:\n - App name / report title header\n - All inspection fields in a clean two-column layout\n - Inspector names listed\n - Observations in a clearly delineated box\n - Photos displayed in a grid (max 2 per row), each with caption and action status clearly labelled\n - Conclusion section with selected status prominently displayed\n - Footer with page number and generation timestamp\n- Flows naturally across multiple A4 pages if content requires it\n- Served as a file download: inspection_report__v.pdf\n\n---\n\n## SECURITY REQUIREMENTS\n\n- All passwords hashed with bcrypt (min cost factor 12)\n- CSRF protection on all forms via Flask-WTF\n- File uploads validated: only JPEG, PNG, GIF, WEBP accepted; max 10MB per file\n- Uploaded filenames sanitised with werkzeug.utils.secure_filename and stored with UUID prefix\n- User input escaped in all templates (Jinja2 autoescaping enabled)\n- Admin routes protected with both login_required and admin_required decorators\n- Secret key loaded from environment variable SECRET_KEY or auto-generated and saved to .env on first run\n- HTTPS enforced — Flask run with SSL context using certs from certs/\n- .env and *.db and certs/ added to .gitignore\n\n---\n\n## GITHUB INSTRUCTIONS\n\n- The repository already exists and has been initialised with prior commits\n- Include a comprehensive README.md with:\n - Project overview\n - Requirements (Python version, OS)\n - Setup instructions (python setup.py)\n - How to run (python run.py)\n - How to access (HTTPS URL)\n - Notes on the self-signed certificate browser warning\n\n---\n\n## CODE QUALITY STANDARDS\n\n- All Python files include docstrings\n- Routes grouped into Blueprints\n- No hardcoded secrets\n- Database access only via SQLAlchemy ORM — no raw SQL\n- Error pages for 403, 404, 500\n- Flash messages for all user actions (success and error)\n- Logging to a rotating file log (logs/app.log)\n\n---\n\n## EXECUTION ORDER\n\nBuild in this order:\n1. requirements.txt and config.py\n2. app/models.py\n3. app/__init__.py (app factory)\n4. Auth blueprint + templates\n5. Admin blueprint + templates\n6. Inspection blueprint + form + view templates\n7. PDF export utility + route\n8. setup.py\n9. run.py\n10. README.md\n11. .gitignore\n12. GitHub push\n13. Review code\n14. Implement any issues from the review.\n\nDo not proceed to the next step until the current one is complete and internally consistent.\n"}} diff --git a/.ralph/loop.lock b/.ralph/loop.lock index 9d2ea61..6ac87cb 100644 --- a/.ralph/loop.lock +++ b/.ralph/loop.lock @@ -1,5 +1,5 @@ { - "pid": 32871, - "started": "2026-03-21T23:53:51.590496087Z", + "pid": 36460, + "started": "2026-03-22T00:12:41.348212015Z", "prompt": "You are building a production-ready Inspection Reporting and Management web application from scra..." } \ No newline at end of file diff --git a/PROMPT.md b/PROMPT.md index 60f9564..0ffb024 100644 --- a/PROMPT.md +++ b/PROMPT.md @@ -182,9 +182,6 @@ Buttons: ## GITHUB INSTRUCTIONS - The repository already exists and has been initialised with prior commits -- Completely discard all prior history -- Use git checkout --orphan new-branch, add all files, commit, then force-push to main -- Commit message: "Initial commit: Inspection reporting app" - Include a comprehensive README.md with: - Project overview - Requirements (Python version, OS) @@ -221,17 +218,8 @@ Build in this order: 9. run.py 10. README.md 11. .gitignore -12. GitHub force-push +12. GitHub push +13. Review code +14. Implement any issues from the review. Do not proceed to the next step until the current one is complete and internally consistent. - ---- - -## NOTES FOR THE OPERATOR - -- WeasyPrint requires system-level dependencies. Install them before running setup.py: - Debian/Ubuntu: sudo apt install libpango-1.0-0 libharfbuzz0b libpangoft2-1.0-0 - macOS: brew install pango - Windows: See https://doc.courtbouillon.org/weasyprint/stable/first_steps.html - - diff --git a/ralph.yml b/ralph.yml index 3b8ab05..a96a173 100644 --- a/ralph.yml +++ b/ralph.yml @@ -1,9 +1,9 @@ # Ralph Orchestrator Configuration -# Generated by: ralph init --backend claude +# Generated by: ralph init --backend opencode # Docs: https://github.com/mikeyobrien/ralph-orchestrator cli: - backend: "claude" + backend: "opencode" event_loop: prompt_file: "PROMPT.md"