chore: bootstrap rdb-discovery
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"project_name": "rdb-discovery",
|
||||||
|
"stage": "DISCOVERY",
|
||||||
|
"current_task": "TASK-000",
|
||||||
|
"next_task": "TASK-001"
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Agent Handoff
|
||||||
|
|
||||||
|
## Current Stage
|
||||||
|
|
||||||
|
DISCOVERY
|
||||||
|
|
||||||
|
## Current Task
|
||||||
|
|
||||||
|
TASK-000 — Bootstrap RDB project standards
|
||||||
|
|
||||||
|
## Instructions For Agent
|
||||||
|
|
||||||
|
- Complete one task only
|
||||||
|
- Make the smallest useful change
|
||||||
|
- Update documentation
|
||||||
|
- Run tests
|
||||||
|
- Commit changes
|
||||||
|
- Stop after task completion
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
# Project State
|
||||||
|
|
||||||
|
Current Stage: DISCOVERY
|
||||||
|
Previous Stage: NONE
|
||||||
|
Next Stage: BOOTSTRAP_READY
|
||||||
|
|
||||||
|
Current Task: TASK-000
|
||||||
|
Active Branch: main
|
||||||
|
|
||||||
|
Last Updated: 2026-06-01
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# rdb-discovery
|
||||||
|
|
||||||
|
A small CLI-first tool for repeatable software project discovery and delivery.
|
||||||
|
|
||||||
|
It creates markdown files that help humans and AI coding agents understand:
|
||||||
|
|
||||||
|
- what is being built
|
||||||
|
- why it exists
|
||||||
|
- what questions remain open
|
||||||
|
- what task should be done next
|
||||||
|
- what stage the project is currently in
|
||||||
|
|
||||||
|
## Install for local development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -e '.[dev]'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rdb init
|
||||||
|
rdb discover
|
||||||
|
rdb status
|
||||||
|
rdb next
|
||||||
|
rdb start TASK-001
|
||||||
|
rdb complete TASK-001
|
||||||
|
rdb handoff
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bootstrap workflow
|
||||||
|
|
||||||
|
1. Run `rdb init`
|
||||||
|
2. Run `rdb discover`
|
||||||
|
3. Run `rdb status`
|
||||||
|
4. Run `rdb next`
|
||||||
|
5. Give the next task to Claude Code or Cline
|
||||||
|
6. Commit after each completed task
|
||||||
|
|
||||||
|
## Principle
|
||||||
|
|
||||||
|
Markdown files are the source of truth. No database is required.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
Run Log
|
||||||
|
2026-06-01
|
||||||
|
Bootstrap project structure created.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# TASKS
|
||||||
|
|
||||||
|
## TASK-000 — Bootstrap RDB project standards
|
||||||
|
|
||||||
|
Status: Todo
|
||||||
|
|
||||||
|
Goal: Add the project control files used by RDB agent workflows.
|
||||||
|
|
||||||
|
Acceptance Criteria:
|
||||||
|
|
||||||
|
- PROJECT_STATE.md exists
|
||||||
|
- AGENT_HANDOFF.md exists
|
||||||
|
- .rdb/project.json exists
|
||||||
|
- context/repository-context.md exists
|
||||||
|
- TEST_PLAN.md exists
|
||||||
|
- RUN_LOG.md exists
|
||||||
|
- README.md explains the structure
|
||||||
|
|
||||||
|
## TASK-001 — Implement rdb init
|
||||||
|
|
||||||
|
Status: Todo
|
||||||
|
|
||||||
|
Goal: Create the command that initialises the standard RDB project structure.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Test Plan
|
||||||
|
|
||||||
|
## Bootstrap Validation
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -e '.[dev]'
|
||||||
|
pytest
|
||||||
|
rdb --help
|
||||||
|
|
||||||
|
Expected result:
|
||||||
|
|
||||||
|
Tests pass
|
||||||
|
CLI help displays
|
||||||
@@ -0,0 +1,269 @@
|
|||||||
|
# `/context/agent-guidelines.md`
|
||||||
|
|
||||||
|
# Agent Operating Guidelines
|
||||||
|
|
||||||
|
This file defines how AI coding agents should behave when working on RDB Solutions Ltd projects.
|
||||||
|
|
||||||
|
These rules apply to:
|
||||||
|
|
||||||
|
- OpenHands
|
||||||
|
- Claude Code
|
||||||
|
- Cursor Agents
|
||||||
|
- Copilot Agents
|
||||||
|
- Local coding agents
|
||||||
|
- Future autonomous development systems
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Core Rule
|
||||||
|
|
||||||
|
Make the smallest useful change possible.
|
||||||
|
|
||||||
|
Agents should favour many small successful changes over large risky changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Before Starting Work
|
||||||
|
|
||||||
|
Agents should first read:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/context/company-context.md
|
||||||
|
/context/infrastructure-context.md
|
||||||
|
/context/development-context.md
|
||||||
|
README.md
|
||||||
|
ARCHITECTURE.md
|
||||||
|
TASKS.md
|
||||||
|
```
|
||||||
|
|
||||||
|
If these files exist.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task Execution Model
|
||||||
|
|
||||||
|
Work should be completed using backlog items.
|
||||||
|
|
||||||
|
Recommended process:
|
||||||
|
|
||||||
|
1. Select task
|
||||||
|
2. Understand task
|
||||||
|
3. Implement task
|
||||||
|
4. Test task
|
||||||
|
5. Document task
|
||||||
|
6. Commit task
|
||||||
|
7. Move to next task
|
||||||
|
|
||||||
|
Avoid combining unrelated tasks.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Safe Change Policy
|
||||||
|
|
||||||
|
Agents should:
|
||||||
|
|
||||||
|
✅ Add functionality
|
||||||
|
|
||||||
|
✅ Fix defects
|
||||||
|
|
||||||
|
✅ Improve documentation
|
||||||
|
|
||||||
|
✅ Add tests
|
||||||
|
|
||||||
|
✅ Refactor locally
|
||||||
|
|
||||||
|
Agents should not:
|
||||||
|
|
||||||
|
❌ Rewrite entire systems
|
||||||
|
|
||||||
|
❌ Replace frameworks
|
||||||
|
|
||||||
|
❌ Change infrastructure architecture
|
||||||
|
|
||||||
|
❌ Change deployment methods
|
||||||
|
|
||||||
|
❌ Delete large amounts of code
|
||||||
|
|
||||||
|
Without explicit approval.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Code Generation Standards
|
||||||
|
|
||||||
|
Generated code should:
|
||||||
|
|
||||||
|
- Be readable
|
||||||
|
- Be maintainable
|
||||||
|
- Follow existing project patterns
|
||||||
|
- Include error handling
|
||||||
|
- Include logging where appropriate
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- Clever code
|
||||||
|
- Unnecessary abstractions
|
||||||
|
- Premature optimisation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Infrastructure Changes
|
||||||
|
|
||||||
|
Infrastructure changes require higher scrutiny.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- Jenkins
|
||||||
|
- Gitea
|
||||||
|
- Supabase
|
||||||
|
- Reverse proxies
|
||||||
|
- DNS
|
||||||
|
- Production deployments
|
||||||
|
|
||||||
|
For infrastructure work:
|
||||||
|
|
||||||
|
1. Explain proposed change
|
||||||
|
2. Explain risk
|
||||||
|
3. Explain rollback
|
||||||
|
4. Generate implementation plan
|
||||||
|
|
||||||
|
Do not execute destructive changes automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Git Rules
|
||||||
|
|
||||||
|
Preferred workflow:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Create branch
|
||||||
|
Make change
|
||||||
|
Run tests
|
||||||
|
Commit
|
||||||
|
Create PR
|
||||||
|
```
|
||||||
|
|
||||||
|
Commit frequently.
|
||||||
|
|
||||||
|
Commit messages should be descriptive.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Testing Requirements
|
||||||
|
|
||||||
|
Where practical:
|
||||||
|
|
||||||
|
- Unit tests
|
||||||
|
- Integration tests
|
||||||
|
- Build validation
|
||||||
|
|
||||||
|
Agents should never claim testing was performed if it was not.
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Verified
|
||||||
|
```
|
||||||
|
|
||||||
|
Only when actually verified.
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Not tested
|
||||||
|
```
|
||||||
|
|
||||||
|
When testing was not possible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Documentation Requirements
|
||||||
|
|
||||||
|
If behaviour changes:
|
||||||
|
|
||||||
|
Update:
|
||||||
|
|
||||||
|
- README
|
||||||
|
- Architecture docs
|
||||||
|
- API docs
|
||||||
|
- Task status
|
||||||
|
|
||||||
|
where applicable.
|
||||||
|
|
||||||
|
Documentation is part of the task.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Autonomous Work Limits
|
||||||
|
|
||||||
|
Agents may autonomously:
|
||||||
|
|
||||||
|
- Create files
|
||||||
|
- Modify files
|
||||||
|
- Add tests
|
||||||
|
- Add documentation
|
||||||
|
- Refactor small areas
|
||||||
|
|
||||||
|
Agents should request approval before:
|
||||||
|
|
||||||
|
- Deleting files
|
||||||
|
- Deleting databases
|
||||||
|
- Deploying to production
|
||||||
|
- Changing authentication
|
||||||
|
- Changing networking
|
||||||
|
- Modifying CI/CD pipelines
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Preferred Deliverables
|
||||||
|
|
||||||
|
When completing work, agents should provide:
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
What was changed.
|
||||||
|
|
||||||
|
## Files Modified
|
||||||
|
|
||||||
|
List of modified files.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
Tests executed and results.
|
||||||
|
|
||||||
|
## Risks
|
||||||
|
|
||||||
|
Potential side effects.
|
||||||
|
|
||||||
|
## Next Recommended Task
|
||||||
|
|
||||||
|
Small logical follow-up task.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# RDB-Specific Preferences
|
||||||
|
|
||||||
|
Remember:
|
||||||
|
|
||||||
|
- Gitea over GitHub
|
||||||
|
- Jenkins over cloud CI systems
|
||||||
|
- Docker preferred
|
||||||
|
- Proxmox preferred
|
||||||
|
- Local LLMs preferred
|
||||||
|
- Self-hosted services preferred
|
||||||
|
- Incremental change preferred
|
||||||
|
|
||||||
|
Do not recommend cloud replacements unless there is a significant advantage.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Success Criteria
|
||||||
|
|
||||||
|
A task is complete when:
|
||||||
|
|
||||||
|
- Requirements are met
|
||||||
|
- Tests pass
|
||||||
|
- Documentation is updated
|
||||||
|
- Changes are understandable
|
||||||
|
- Rollback is possible
|
||||||
|
|
||||||
|
Optimise for maintainability and long-term ownership rather than speed alone.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# `/context/company-context.md`
|
||||||
|
|
||||||
|
# RDB Solutions Ltd Context
|
||||||
|
|
||||||
|
RDB Solutions Ltd is developing internal and customer-facing software systems with a strong preference for self-hosted infrastructure, local control, and practical automation.
|
||||||
|
|
||||||
|
The company favours owning its development stack rather than depending heavily on third-party SaaS platforms where avoidable.
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
The main goals are:
|
||||||
|
|
||||||
|
- Improve development efficiency
|
||||||
|
- Use local and self-hosted tools where practical
|
||||||
|
- Automate repetitive development and deployment tasks
|
||||||
|
- Support LLM-assisted development
|
||||||
|
- Maintain control over source code, infrastructure, and data
|
||||||
|
- Build systems that are maintainable by a small team or solo developer
|
||||||
|
|
||||||
|
## Preferred Approach
|
||||||
|
|
||||||
|
RDB Solutions Ltd prefers:
|
||||||
|
|
||||||
|
- Self-hosted Git using Gitea
|
||||||
|
- Jenkins for CI/CD
|
||||||
|
- Docker-based deployments
|
||||||
|
- Proxmox for virtualisation
|
||||||
|
- Local LLMs where possible
|
||||||
|
- Clear task files and backlog-driven agent work
|
||||||
|
- Incremental changes over large risky rewrites
|
||||||
|
- Documentation that allows AI tools to understand the system quickly
|
||||||
|
|
||||||
|
## General Constraints
|
||||||
|
|
||||||
|
- Avoid assuming GitHub is used.
|
||||||
|
- Prefer Gitea-compatible workflows.
|
||||||
|
- Prefer local or self-hosted services where practical.
|
||||||
|
- Avoid vendor lock-in unless there is a clear benefit.
|
||||||
|
- Keep systems understandable and maintainable.
|
||||||
|
- Prefer simple architecture before complex orchestration.
|
||||||
@@ -0,0 +1,542 @@
|
|||||||
|
# `/context/current-environment.md`
|
||||||
|
|
||||||
|
# Current Environment
|
||||||
|
|
||||||
|
Last Updated: 2026-06-01
|
||||||
|
|
||||||
|
This file describes the current live RDB Solutions infrastructure.
|
||||||
|
|
||||||
|
Update whenever hardware, VMs, services, networking, or development tooling changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Network Overview
|
||||||
|
|
||||||
|
## Primary Site
|
||||||
|
|
||||||
|
Location:
|
||||||
|
|
||||||
|
- <Office/Home Lab>
|
||||||
|
|
||||||
|
Internet:
|
||||||
|
|
||||||
|
- ISP: Lightening Fibre
|
||||||
|
- Download: 2.5 Gbps
|
||||||
|
- Router: Zyxel EX5601-T0
|
||||||
|
- Internal Wifi Extender: Deco
|
||||||
|
- Static IP: 212.221.168.135
|
||||||
|
|
||||||
|
Domain(s):
|
||||||
|
|
||||||
|
- rdbsolutions.co.uk
|
||||||
|
- gitea.rdbcloud.co.uk
|
||||||
|
- prox.rdbcloud.co.uk
|
||||||
|
- pedw.rdbcloud.co.uk
|
||||||
|
|
||||||
|
Internal Network:
|
||||||
|
|
||||||
|
```text
|
||||||
|
LAN: 192.168.x.0/24
|
||||||
|
Gateway: 192.168.x.1
|
||||||
|
DNS: AdGuard
|
||||||
|
DHCP: <device>
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Physical Infrastructure
|
||||||
|
|
||||||
|
## Proxmox Host
|
||||||
|
|
||||||
|
Hostname:
|
||||||
|
|
||||||
|
- proxmox01
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Primary virtualisation host
|
||||||
|
|
||||||
|
Hardware:
|
||||||
|
|
||||||
|
CPU:
|
||||||
|
|
||||||
|
- <model>
|
||||||
|
|
||||||
|
RAM:
|
||||||
|
|
||||||
|
- 16 GB
|
||||||
|
|
||||||
|
Storage:
|
||||||
|
|
||||||
|
- <details>
|
||||||
|
|
||||||
|
Network:
|
||||||
|
|
||||||
|
- <IP>
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- Hosts infrastructure VMs and LXCs
|
||||||
|
- Main internal services
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## AI / Ollama Server
|
||||||
|
|
||||||
|
Hostname:
|
||||||
|
|
||||||
|
- rdbUltra
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Local LLM hosting
|
||||||
|
|
||||||
|
Hardware:
|
||||||
|
|
||||||
|
CPU:
|
||||||
|
|
||||||
|
- Intel I9
|
||||||
|
|
||||||
|
RAM:
|
||||||
|
|
||||||
|
- 32 GB
|
||||||
|
|
||||||
|
GPU:
|
||||||
|
|
||||||
|
- RTX 5070 Ti
|
||||||
|
- 16 GB VRAM
|
||||||
|
|
||||||
|
Network:
|
||||||
|
|
||||||
|
- 192.168.1.111
|
||||||
|
|
||||||
|
Services:
|
||||||
|
|
||||||
|
- Ollama
|
||||||
|
|
||||||
|
Models Installed:
|
||||||
|
|
||||||
|
- Qwen3
|
||||||
|
- Qwen Coder
|
||||||
|
- <others>
|
||||||
|
|
||||||
|
Endpoints:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://<ip>:11434
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development Workstation
|
||||||
|
|
||||||
|
Hostname:
|
||||||
|
|
||||||
|
- rdbmacbook
|
||||||
|
|
||||||
|
Type:
|
||||||
|
|
||||||
|
- Intel MacBook Pro
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Main software development workstation
|
||||||
|
|
||||||
|
Installed Tools:
|
||||||
|
|
||||||
|
- VS Code
|
||||||
|
- Claude Code
|
||||||
|
- Docker
|
||||||
|
- Git
|
||||||
|
- SSH
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## OpenWebUI Host
|
||||||
|
|
||||||
|
Hostname:
|
||||||
|
|
||||||
|
- rdboffice
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Browser-based LLM interface
|
||||||
|
|
||||||
|
Connected To:
|
||||||
|
|
||||||
|
- Ollama Server
|
||||||
|
|
||||||
|
URL:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://ai.rdbcloud.co.uk
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Virtual Machines
|
||||||
|
|
||||||
|
## VM Inventory
|
||||||
|
|
||||||
|
| VM Name | Purpose | CPU | RAM | IP |
|
||||||
|
| ---------- | -------- | --- | ---- | ------- |
|
||||||
|
| supabase01 | Database | 4 | 8 GB | x.x.x.x |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# LXC Containers
|
||||||
|
|
||||||
|
## Container Inventory
|
||||||
|
|
||||||
|
| IP | LXC Name | Proxmox ID | RAM |
|
||||||
|
|------------------------------------------------------------------------------------
|
||||||
|
| 192.168.68.100 | adguard | 100 (LXC) | 512 MB
|
||||||
|
| 192.168.68.102 | gitea | 104 (LXC) | 1.00 GB
|
||||||
|
| 192.168.68.79 | nginxproxymanager | 105 (LXC) | 1.00 GB
|
||||||
|
| 192.168.68.90 | jenkins | 106 (LXC) | 2.00 GB
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Infrastructure Services
|
||||||
|
|
||||||
|
## AdGuard
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- DNS
|
||||||
|
- Ad Blocking
|
||||||
|
|
||||||
|
URL:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://adguard.lan
|
||||||
|
```
|
||||||
|
|
||||||
|
Host:
|
||||||
|
|
||||||
|
- adguard01
|
||||||
|
|
||||||
|
Port:
|
||||||
|
|
||||||
|
- 3000
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Gitea
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Git repositories
|
||||||
|
- Source control
|
||||||
|
|
||||||
|
URL:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://gitea.rdbcloud.co.uk
|
||||||
|
```
|
||||||
|
|
||||||
|
Host:
|
||||||
|
|
||||||
|
- https://gitea.rdbcloud.co.uk
|
||||||
|
|
||||||
|
Version:
|
||||||
|
|
||||||
|
- v1.25.0
|
||||||
|
|
||||||
|
Repositories:
|
||||||
|
|
||||||
|
- RC Compatibility App
|
||||||
|
- RDB Mobile App
|
||||||
|
- Infrastructure
|
||||||
|
- robbond/pedwFrontend
|
||||||
|
- robbond/proxmox-monitor
|
||||||
|
- robbond/pleskSaas
|
||||||
|
- robbond/pedwV2
|
||||||
|
- robbond/rc-compat
|
||||||
|
- robbond/gacapi
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Jenkins
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- CI/CD
|
||||||
|
|
||||||
|
URL:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://jenkins.lan:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
Host:
|
||||||
|
|
||||||
|
- jenkins.lan
|
||||||
|
|
||||||
|
Jobs:
|
||||||
|
|
||||||
|
- RC Compatibility Build
|
||||||
|
- Mobile App Build
|
||||||
|
- Docker Deployments
|
||||||
|
- PEDW testing pipeline
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Supabase
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- PostgreSQL
|
||||||
|
- Authentication
|
||||||
|
- Storage
|
||||||
|
|
||||||
|
Host:
|
||||||
|
|
||||||
|
- supabase01
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
- Self-hosted
|
||||||
|
|
||||||
|
Database Version:
|
||||||
|
|
||||||
|
- PostgreSQL xx
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nginx Proxy Manager
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Reverse Proxy
|
||||||
|
- SSL
|
||||||
|
|
||||||
|
Host:
|
||||||
|
|
||||||
|
- npm01
|
||||||
|
|
||||||
|
Managed Hosts:
|
||||||
|
|
||||||
|
| Hostname | Target |
|
||||||
|
| ------------------------- | -------------------------- |
|
||||||
|
| \*.coolify.rdbcloud.co.uk | https://192.168.68.115:443 |
|
||||||
|
| ai.rdbcloud.co.uk | http://192.168.68.97:3001 |
|
||||||
|
| coolify.rdbcloud.co.uk | http://192.168.68.115:8001 |
|
||||||
|
| gitea.rdbcloud.co.uk | http://192.168.68.102:3000 |
|
||||||
|
| gitmcp.rdbcloud.co.uk | http://192.168.68.180:8080 |
|
||||||
|
| ha.rdbcloud.co.uk | http://192.168.68.96:8123 |
|
||||||
|
| jellyfin.rdbcloud.co.uk | http://192.168.68.101:8096 |
|
||||||
|
| nextcloud.rdbcloud.co.uk | http://192.168.68.55:80 |
|
||||||
|
| pedw.rdbcloud.co.uk | http://192.168.68.109:3000 |
|
||||||
|
| portal.rdbcloud.co.uk | http://192.168.68.116:3000 |
|
||||||
|
| prox.rdbcloud.co.uk | https://192.168.68.70:8006 |
|
||||||
|
| supabase.rdbcloud.co.uk | http://192.168.68.115:8000 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Development Stack
|
||||||
|
|
||||||
|
## Source Control
|
||||||
|
|
||||||
|
Primary:
|
||||||
|
|
||||||
|
- Gitea
|
||||||
|
|
||||||
|
Workflow:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Developer
|
||||||
|
↓
|
||||||
|
Feature Branch
|
||||||
|
↓
|
||||||
|
Commit
|
||||||
|
↓
|
||||||
|
Pull Request
|
||||||
|
↓
|
||||||
|
Merge
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
Primary:
|
||||||
|
|
||||||
|
- Jenkins
|
||||||
|
|
||||||
|
Build Flow:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Gitea
|
||||||
|
↓
|
||||||
|
Jenkins
|
||||||
|
↓
|
||||||
|
Tests
|
||||||
|
↓
|
||||||
|
Docker Build
|
||||||
|
↓
|
||||||
|
Deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Containers
|
||||||
|
|
||||||
|
Runtime:
|
||||||
|
|
||||||
|
- Docker
|
||||||
|
- Docker Compose
|
||||||
|
|
||||||
|
Container Registry:
|
||||||
|
|
||||||
|
- <local registry>
|
||||||
|
- Docker Hub
|
||||||
|
- Gitea Registry
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# AI Development Environment
|
||||||
|
|
||||||
|
## Local Models
|
||||||
|
|
||||||
|
| Model | Purpose |
|
||||||
|
| ----------------- | ------- |
|
||||||
|
| Qwen3.6:35b-a3b | Coding |
|
||||||
|
| Qwen2.5-coder:14b | Coding |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agent Platforms
|
||||||
|
|
||||||
|
Installed:
|
||||||
|
|
||||||
|
- OpenWebUI
|
||||||
|
- Claude Code
|
||||||
|
- Cline in VScode
|
||||||
|
|
||||||
|
Planned:
|
||||||
|
|
||||||
|
- OpenHands
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## OpenHands
|
||||||
|
|
||||||
|
Status:
|
||||||
|
|
||||||
|
- Planned / Testing / Production
|
||||||
|
|
||||||
|
Location:
|
||||||
|
|
||||||
|
- VM / LXC / Docker
|
||||||
|
|
||||||
|
Resources:
|
||||||
|
|
||||||
|
CPU:
|
||||||
|
|
||||||
|
- x
|
||||||
|
|
||||||
|
RAM:
|
||||||
|
|
||||||
|
- x GB
|
||||||
|
|
||||||
|
Connected Systems:
|
||||||
|
|
||||||
|
- Gitea
|
||||||
|
- Jenkins
|
||||||
|
- Ollama
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Security
|
||||||
|
|
||||||
|
## Secrets Storage
|
||||||
|
|
||||||
|
Current Method:
|
||||||
|
|
||||||
|
- <method>
|
||||||
|
|
||||||
|
Preferred Future:
|
||||||
|
|
||||||
|
- Vault
|
||||||
|
- 1Password
|
||||||
|
- Bitwarden
|
||||||
|
- Environment Variables
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backup Strategy
|
||||||
|
|
||||||
|
Infrastructure:
|
||||||
|
|
||||||
|
- Proxmox backups
|
||||||
|
- VM snapshots
|
||||||
|
|
||||||
|
Repositories:
|
||||||
|
|
||||||
|
- Gitea backups
|
||||||
|
|
||||||
|
Databases:
|
||||||
|
|
||||||
|
- PostgreSQL backups
|
||||||
|
|
||||||
|
Frequency:
|
||||||
|
|
||||||
|
- Daily
|
||||||
|
- Weekly
|
||||||
|
- Monthly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Monitoring
|
||||||
|
|
||||||
|
Current Tools:
|
||||||
|
|
||||||
|
- <tool>
|
||||||
|
|
||||||
|
Metrics:
|
||||||
|
|
||||||
|
- Host health
|
||||||
|
- VM health
|
||||||
|
- Disk usage
|
||||||
|
- Jenkins status
|
||||||
|
- Database health
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Known Constraints
|
||||||
|
|
||||||
|
Current Limitations:
|
||||||
|
|
||||||
|
1. Proxmox host has 16 GB RAM
|
||||||
|
2. AI server has single GPU
|
||||||
|
3. Limited staging environment
|
||||||
|
4. <additional constraints>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Improvement Opportunities
|
||||||
|
|
||||||
|
Potential Future Enhancements:
|
||||||
|
|
||||||
|
- Dedicated monitoring stack
|
||||||
|
- Centralised logging
|
||||||
|
- Local container registry
|
||||||
|
- OpenHands integration
|
||||||
|
- Automated deployment pipelines
|
||||||
|
- Infrastructure-as-Code
|
||||||
|
- Agent task orchestration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Notes For AI Agents
|
||||||
|
|
||||||
|
When making recommendations:
|
||||||
|
|
||||||
|
- Prefer self-hosted solutions
|
||||||
|
- Prefer Gitea integrations
|
||||||
|
- Prefer Jenkins automation
|
||||||
|
- Prefer Docker deployments
|
||||||
|
- Consider current RAM limitations
|
||||||
|
- Assume Ollama is available locally
|
||||||
|
- Assume local AI workflows are preferred over cloud alternatives
|
||||||
@@ -0,0 +1,294 @@
|
|||||||
|
# `/context/development-context.md`
|
||||||
|
|
||||||
|
# Development Environment Context
|
||||||
|
|
||||||
|
This document describes the preferred development workflow, tools, standards, and technology choices used by RDB Solutions Ltd.
|
||||||
|
|
||||||
|
AI coding assistants, IDE agents, and autonomous development tools should read this file before making recommendations or changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Primary Development Workstation
|
||||||
|
|
||||||
|
## MacBook Pro (Intel)
|
||||||
|
|
||||||
|
Primary software development machine.
|
||||||
|
|
||||||
|
Typical activities:
|
||||||
|
|
||||||
|
- Application development
|
||||||
|
- Repository management
|
||||||
|
- Code reviews
|
||||||
|
- Testing
|
||||||
|
- Infrastructure administration
|
||||||
|
- LLM-assisted development
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Source Control
|
||||||
|
|
||||||
|
## Gitea
|
||||||
|
|
||||||
|
Primary Git platform.
|
||||||
|
|
||||||
|
Preferences:
|
||||||
|
|
||||||
|
- Gitea is the source of truth.
|
||||||
|
- Do not assume GitHub is available.
|
||||||
|
- Do not recommend GitHub-specific workflows unless explicitly requested.
|
||||||
|
- Pull Requests should be used for significant changes.
|
||||||
|
- Commit messages should be clear and descriptive.
|
||||||
|
|
||||||
|
Preferred commit style:
|
||||||
|
|
||||||
|
```text
|
||||||
|
feat: add VM status endpoint
|
||||||
|
|
||||||
|
fix: correct Jenkins deployment script
|
||||||
|
|
||||||
|
docs: update infrastructure documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# CI/CD
|
||||||
|
|
||||||
|
## Jenkins
|
||||||
|
|
||||||
|
Primary automation platform.
|
||||||
|
|
||||||
|
Current and future responsibilities:
|
||||||
|
|
||||||
|
- Build applications
|
||||||
|
- Run tests
|
||||||
|
- Build Docker images
|
||||||
|
- Deploy services
|
||||||
|
- Run scheduled maintenance tasks
|
||||||
|
- Execute agent-generated work after review
|
||||||
|
|
||||||
|
Preferred pipeline behaviour:
|
||||||
|
|
||||||
|
1. Pull code from Gitea
|
||||||
|
2. Run validation
|
||||||
|
3. Run tests
|
||||||
|
4. Build artefacts
|
||||||
|
5. Deploy to target environment
|
||||||
|
|
||||||
|
Agents should favour Jenkins automation over manual deployment procedures.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Containerisation
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
Preferred deployment format.
|
||||||
|
|
||||||
|
Goals:
|
||||||
|
|
||||||
|
- Consistent environments
|
||||||
|
- Easier deployment
|
||||||
|
- Simpler rollback
|
||||||
|
- Portable services
|
||||||
|
|
||||||
|
When proposing software:
|
||||||
|
|
||||||
|
Prefer:
|
||||||
|
|
||||||
|
- Docker Compose
|
||||||
|
- Single-container deployments
|
||||||
|
- Simple architecture
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- Kubernetes unless there is a clear requirement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Database Platforms
|
||||||
|
|
||||||
|
## PostgreSQL
|
||||||
|
|
||||||
|
Preferred database platform.
|
||||||
|
|
||||||
|
Current implementation:
|
||||||
|
|
||||||
|
- Supabase-hosted PostgreSQL
|
||||||
|
|
||||||
|
Preferred characteristics:
|
||||||
|
|
||||||
|
- Relational data model
|
||||||
|
- Strong typing
|
||||||
|
- Auditable schema changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# IDEs and Editors
|
||||||
|
|
||||||
|
Current tools may include:
|
||||||
|
|
||||||
|
- VS Code
|
||||||
|
- Cursor
|
||||||
|
- Claude Code
|
||||||
|
- OpenWebUI
|
||||||
|
- Browser-based assistants
|
||||||
|
|
||||||
|
Recommendations should remain editor-agnostic where possible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Local LLM Infrastructure
|
||||||
|
|
||||||
|
## Ollama
|
||||||
|
|
||||||
|
Primary local inference platform.
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Local coding assistance
|
||||||
|
- Experimentation
|
||||||
|
- Agent backends
|
||||||
|
- Development support
|
||||||
|
|
||||||
|
## Available Hardware
|
||||||
|
|
||||||
|
LLM Server:
|
||||||
|
|
||||||
|
- RTX 5070 Ti
|
||||||
|
- 16 GB VRAM
|
||||||
|
- 32 GB RAM
|
||||||
|
|
||||||
|
Agents should assume local inference is available.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Preferred Models
|
||||||
|
|
||||||
|
Potential models include:
|
||||||
|
|
||||||
|
- Qwen Coder
|
||||||
|
- Qwen3
|
||||||
|
- DeepSeek Coder
|
||||||
|
- Future coding-focused local models
|
||||||
|
|
||||||
|
Model selection should prioritise:
|
||||||
|
|
||||||
|
1. Code quality
|
||||||
|
2. Reasoning ability
|
||||||
|
3. Low operational cost
|
||||||
|
4. Local execution
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# AI-Assisted Development
|
||||||
|
|
||||||
|
RDB actively uses AI-assisted development.
|
||||||
|
|
||||||
|
Expected uses:
|
||||||
|
|
||||||
|
- Code generation
|
||||||
|
- Refactoring
|
||||||
|
- Documentation
|
||||||
|
- Testing
|
||||||
|
- Architecture review
|
||||||
|
- Infrastructure planning
|
||||||
|
|
||||||
|
Agents should produce:
|
||||||
|
|
||||||
|
- Small reviewable changes
|
||||||
|
- Clear reasoning
|
||||||
|
- Minimal surprises
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- Massive rewrites
|
||||||
|
- Unrequested architecture changes
|
||||||
|
- Hidden behaviour
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Task Management
|
||||||
|
|
||||||
|
Preferred approach:
|
||||||
|
|
||||||
|
Backlog-driven development.
|
||||||
|
|
||||||
|
Work should be decomposed into:
|
||||||
|
|
||||||
|
- Small tasks
|
||||||
|
- Independent tasks
|
||||||
|
- Reviewable tasks
|
||||||
|
|
||||||
|
Good example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
TASK-001
|
||||||
|
Create API endpoint for VM status
|
||||||
|
|
||||||
|
TASK-002
|
||||||
|
Add frontend status widget
|
||||||
|
|
||||||
|
TASK-003
|
||||||
|
Write integration tests
|
||||||
|
```
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Rewrite the entire application
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Documentation Standards
|
||||||
|
|
||||||
|
Projects should contain:
|
||||||
|
|
||||||
|
```text
|
||||||
|
README.md
|
||||||
|
TASKS.md
|
||||||
|
ARCHITECTURE.md
|
||||||
|
CHANGELOG.md
|
||||||
|
/context/
|
||||||
|
```
|
||||||
|
|
||||||
|
Documentation should always be updated when functionality changes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Deployment Philosophy
|
||||||
|
|
||||||
|
Preferred order:
|
||||||
|
|
||||||
|
Development
|
||||||
|
→ Test
|
||||||
|
→ Staging
|
||||||
|
→ Production
|
||||||
|
|
||||||
|
Production deployments should be repeatable and automated.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- Manual server modifications
|
||||||
|
- Untracked configuration changes
|
||||||
|
- Snowflake servers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Development Principles
|
||||||
|
|
||||||
|
Prefer:
|
||||||
|
|
||||||
|
- Simplicity
|
||||||
|
- Maintainability
|
||||||
|
- Incremental improvements
|
||||||
|
- Clear documentation
|
||||||
|
- Automation
|
||||||
|
- Reproducibility
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- Unnecessary complexity
|
||||||
|
- Vendor lock-in
|
||||||
|
- Excessive dependencies
|
||||||
|
- Platform-specific assumptions
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
# `/context/infrastructure-context.md`
|
||||||
|
|
||||||
|
# RDB Solutions Ltd Infrastructure Context
|
||||||
|
|
||||||
|
## Physical Machines
|
||||||
|
|
||||||
|
### Proxmox Server
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Main virtualisation host
|
||||||
|
- Runs infrastructure services and VMs/LXCs
|
||||||
|
|
||||||
|
Current known services:
|
||||||
|
|
||||||
|
- AdGuard
|
||||||
|
- Jenkins
|
||||||
|
- Nginx Proxy Manager
|
||||||
|
- Supabase VM
|
||||||
|
- Potential future OpenHands runner
|
||||||
|
|
||||||
|
Current constraint:
|
||||||
|
|
||||||
|
- Proxmox host currently has 16 GB RAM, so resource allocation should be conservative.
|
||||||
|
|
||||||
|
Preferred usage:
|
||||||
|
|
||||||
|
- Infrastructure services
|
||||||
|
- CI/CD
|
||||||
|
- Reverse proxy
|
||||||
|
- Databases
|
||||||
|
- Lightweight agent runners
|
||||||
|
- Isolated test environments
|
||||||
|
|
||||||
|
### LLM / Ollama Machine
|
||||||
|
|
||||||
|
Hardware:
|
||||||
|
|
||||||
|
- NVIDIA RTX 5070 Ti with 16 GB VRAM
|
||||||
|
- 32 GB RAM
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Hosts Ollama
|
||||||
|
- Runs local LLMs such as Qwen
|
||||||
|
- Provides local model inference for development assistants and agent tooling
|
||||||
|
|
||||||
|
Preferred usage:
|
||||||
|
|
||||||
|
- Local coding models
|
||||||
|
- Agent backend model provider
|
||||||
|
- OpenWebUI integration
|
||||||
|
- Possible API endpoint for tools like Claude Code-compatible wrappers or OpenHands
|
||||||
|
|
||||||
|
### MacBook Pro Intel
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Main development workstation
|
||||||
|
|
||||||
|
Preferred usage:
|
||||||
|
|
||||||
|
- IDE work
|
||||||
|
- Local coding
|
||||||
|
- Git commits
|
||||||
|
- Testing frontend/mobile apps
|
||||||
|
- Managing repositories and project files
|
||||||
|
|
||||||
|
### Mini PC
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Hosts OpenWebUI
|
||||||
|
- Points to the Ollama machine for local LLM access
|
||||||
|
|
||||||
|
Preferred usage:
|
||||||
|
|
||||||
|
- Browser-based LLM interface
|
||||||
|
- Local AI assistant access
|
||||||
|
- Shared AI UI across the network
|
||||||
|
|
||||||
|
## Virtual Machines and Containers
|
||||||
|
|
||||||
|
### Jenkins
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- CI/CD automation
|
||||||
|
- Build pipelines
|
||||||
|
- Test execution
|
||||||
|
- Deployment workflows
|
||||||
|
|
||||||
|
Preferred future use:
|
||||||
|
|
||||||
|
- Pull code from Gitea
|
||||||
|
- Build Docker images
|
||||||
|
- Run tests
|
||||||
|
- Deploy to hosted or self-hosted targets
|
||||||
|
|
||||||
|
### Gitea
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Self-hosted Git server
|
||||||
|
- Source code control
|
||||||
|
- Replacement for Bitbucket/GitHub where possible
|
||||||
|
|
||||||
|
Preferences:
|
||||||
|
|
||||||
|
- Use Gitea as the source of truth
|
||||||
|
- Avoid GitHub-specific assumptions
|
||||||
|
- Use issues, milestones, and pull requests where useful
|
||||||
|
|
||||||
|
### Supabase VM
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Database backend
|
||||||
|
- Postgres services
|
||||||
|
- Possible authentication/storage/API support depending on project needs
|
||||||
|
|
||||||
|
Preferred use:
|
||||||
|
|
||||||
|
- Application database
|
||||||
|
- Internal APIs
|
||||||
|
- Development/staging database
|
||||||
|
- Storage where suitable
|
||||||
|
|
||||||
|
### Nginx Proxy Manager
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- Reverse proxy
|
||||||
|
- SSL termination
|
||||||
|
- Routing internal services to friendly hostnames
|
||||||
|
|
||||||
|
Preferred use:
|
||||||
|
|
||||||
|
- Route apps and tools through internal domains
|
||||||
|
- Manage certificates
|
||||||
|
- Avoid exposing unnecessary services directly
|
||||||
|
|
||||||
|
### AdGuard
|
||||||
|
|
||||||
|
Purpose:
|
||||||
|
|
||||||
|
- DNS filtering
|
||||||
|
- Local DNS support
|
||||||
|
- Network-wide ad/tracker blocking
|
||||||
|
|
||||||
|
Potential use:
|
||||||
|
|
||||||
|
- Internal DNS names for services
|
||||||
|
- Easier access to tools like Gitea, Jenkins, OpenWebUI, Supabase, etc.
|
||||||
|
|
||||||
|
## LLM and Agent Architecture
|
||||||
|
|
||||||
|
RDB Solutions Ltd is interested in using local LLMs and coding agents to improve productivity.
|
||||||
|
|
||||||
|
Candidate tools:
|
||||||
|
|
||||||
|
- Ollama
|
||||||
|
- Qwen models
|
||||||
|
- OpenWebUI
|
||||||
|
- OpenHands
|
||||||
|
- Claude Code-style workflows pointed at local models where possible
|
||||||
|
- IDE assistants
|
||||||
|
- Task/backlog-driven development agents
|
||||||
|
|
||||||
|
Important preference:
|
||||||
|
|
||||||
|
- Agents should work from clear task files, context files, and isolated environments.
|
||||||
|
- Agents should not make broad uncontrolled changes.
|
||||||
|
- Agents should be able to run in a VM, LXC, or Docker container depending on risk level.
|
||||||
|
|
||||||
|
## Recommended Isolation Model
|
||||||
|
|
||||||
|
For autonomous coding agents:
|
||||||
|
|
||||||
|
Preferred:
|
||||||
|
|
||||||
|
- Dedicated VM or LXC on Proxmox
|
||||||
|
- Access only to required repositories
|
||||||
|
- Limited credentials
|
||||||
|
- Network access restricted where possible
|
||||||
|
- Disposable working directories
|
||||||
|
- Git-based review before merge
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- Giving agents unrestricted access to the main development machine
|
||||||
|
- Giving agents broad production credentials
|
||||||
|
- Allowing agents to directly deploy without review
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Repository Context
|
||||||
|
|
||||||
|
Git Server:
|
||||||
|
|
||||||
|
https://gitea.rdbcloud.co.uk
|
||||||
|
|
||||||
|
Repository:
|
||||||
|
|
||||||
|
rdb-discovery
|
||||||
|
|
||||||
|
Primary Workflow:
|
||||||
|
|
||||||
|
Feature Branch
|
||||||
|
→ Commit
|
||||||
|
→ Pull Request
|
||||||
|
→ Merge
|
||||||
|
|
||||||
|
Branch Naming:
|
||||||
|
|
||||||
|
feature/TASK-001
|
||||||
|
fix/TASK-001
|
||||||
|
docs/TASK-001
|
||||||
|
|
||||||
|
Commit Format:
|
||||||
|
|
||||||
|
feat: add command
|
||||||
|
fix: correct behaviour
|
||||||
|
docs: update documentation
|
||||||
|
test: add tests
|
||||||
|
chore: project maintenance
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[project]
|
||||||
|
name = "rdb-discovery"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Markdown-first discovery and delivery workflow CLI for software projects."
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.11"
|
||||||
|
dependencies = [
|
||||||
|
"typer>=0.12.0",
|
||||||
|
"rich>=13.0.0"
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
dev = [
|
||||||
|
"pytest>=8.0.0"
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
rdb = "rdb_discovery.cli:app"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["setuptools>=68"]
|
||||||
|
build-backend = "setuptools.build_meta"
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
Metadata-Version: 2.4
|
||||||
|
Name: rdb-discovery
|
||||||
|
Version: 0.1.0
|
||||||
|
Summary: Markdown-first discovery and delivery workflow CLI for software projects.
|
||||||
|
Requires-Python: >=3.11
|
||||||
|
Description-Content-Type: text/markdown
|
||||||
|
Requires-Dist: typer>=0.12.0
|
||||||
|
Requires-Dist: rich>=13.0.0
|
||||||
|
Provides-Extra: dev
|
||||||
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
||||||
|
|
||||||
|
# rdb-discovery
|
||||||
|
|
||||||
|
A small CLI-first tool for repeatable software project discovery and delivery.
|
||||||
|
|
||||||
|
It creates markdown files that help humans and AI coding agents understand:
|
||||||
|
|
||||||
|
- what is being built
|
||||||
|
- why it exists
|
||||||
|
- what questions remain open
|
||||||
|
- what task should be done next
|
||||||
|
- what stage the project is currently in
|
||||||
|
|
||||||
|
## Install for local development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
pip install -e '.[dev]'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rdb init
|
||||||
|
rdb discover
|
||||||
|
rdb status
|
||||||
|
rdb next
|
||||||
|
rdb start TASK-001
|
||||||
|
rdb complete TASK-001
|
||||||
|
rdb handoff
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bootstrap workflow
|
||||||
|
|
||||||
|
1. Run `rdb init`
|
||||||
|
2. Run `rdb discover`
|
||||||
|
3. Run `rdb status`
|
||||||
|
4. Run `rdb next`
|
||||||
|
5. Give the next task to Claude Code or Cline
|
||||||
|
6. Commit after each completed task
|
||||||
|
|
||||||
|
## Principle
|
||||||
|
|
||||||
|
Markdown files are the source of truth. No database is required.
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
README.md
|
||||||
|
pyproject.toml
|
||||||
|
src/rdb_discovery/__init__.py
|
||||||
|
src/rdb_discovery/cli.py
|
||||||
|
src/rdb_discovery/discovery.py
|
||||||
|
src/rdb_discovery/handoff.py
|
||||||
|
src/rdb_discovery/status.py
|
||||||
|
src/rdb_discovery/tasks.py
|
||||||
|
src/rdb_discovery/templates.py
|
||||||
|
src/rdb_discovery.egg-info/PKG-INFO
|
||||||
|
src/rdb_discovery.egg-info/SOURCES.txt
|
||||||
|
src/rdb_discovery.egg-info/dependency_links.txt
|
||||||
|
src/rdb_discovery.egg-info/entry_points.txt
|
||||||
|
src/rdb_discovery.egg-info/requires.txt
|
||||||
|
src/rdb_discovery.egg-info/top_level.txt
|
||||||
|
tests/test_tasks.py
|
||||||
|
tests/test_templates.py
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
[console_scripts]
|
||||||
|
rdb = rdb_discovery.cli:app
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
typer>=0.12.0
|
||||||
|
rich>=13.0.0
|
||||||
|
|
||||||
|
[dev]
|
||||||
|
pytest>=8.0.0
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
rdb_discovery
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
__version__ = "0.1.0"
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,133 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import typer
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.table import Table
|
||||||
|
|
||||||
|
from .discovery import append_discovery_answer, core_questions
|
||||||
|
from .handoff import build_handoff
|
||||||
|
from .status import project_stage, task_counts
|
||||||
|
from .tasks import get_next_task, update_task_status
|
||||||
|
from .templates import CONTEXT_FILES, write_file_if_missing
|
||||||
|
|
||||||
|
app = typer.Typer(help="RDB discovery and delivery workflow CLI.")
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
|
||||||
|
def root_path() -> Path:
|
||||||
|
return Path.cwd()
|
||||||
|
|
||||||
|
|
||||||
|
def append_run_log(root: Path, event: str, task_id: str = "", notes: str = "") -> None:
|
||||||
|
path = root / "RUN_LOG.md"
|
||||||
|
if not path.exists():
|
||||||
|
path.write_text("# RUN_LOG.md\n\n| Date | Event | Task | Notes |\n|---|---|---|---|\n", encoding="utf-8")
|
||||||
|
line = f"| {datetime.now().isoformat(timespec='seconds')} | {event} | {task_id} | {notes} |\n"
|
||||||
|
with path.open("a", encoding="utf-8") as handle:
|
||||||
|
handle.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def init() -> None:
|
||||||
|
"""Create the initial markdown project structure."""
|
||||||
|
root = root_path()
|
||||||
|
created: list[str] = []
|
||||||
|
skipped: list[str] = []
|
||||||
|
|
||||||
|
for relative_path, content in CONTEXT_FILES.items():
|
||||||
|
if write_file_if_missing(root, relative_path, content):
|
||||||
|
created.append(relative_path)
|
||||||
|
else:
|
||||||
|
skipped.append(relative_path)
|
||||||
|
|
||||||
|
console.print("[bold green]Initialised rdb-discovery files.[/bold green]")
|
||||||
|
if created:
|
||||||
|
console.print("\nCreated:")
|
||||||
|
for item in created:
|
||||||
|
console.print(f"- {item}")
|
||||||
|
if skipped:
|
||||||
|
console.print("\nSkipped existing files:")
|
||||||
|
for item in skipped:
|
||||||
|
console.print(f"- {item}")
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def discover() -> None:
|
||||||
|
"""Ask the core discovery questions and append answers to the discovery ledger."""
|
||||||
|
root = root_path()
|
||||||
|
write_file_if_missing(root, "context/discovery-log.md", CONTEXT_FILES["context/discovery-log.md"])
|
||||||
|
|
||||||
|
for index, question in enumerate(core_questions(), start=1):
|
||||||
|
qid = f"Q-{index:03d}"
|
||||||
|
answer = typer.prompt(question)
|
||||||
|
confidence = typer.prompt("Confidence?", default="Medium")
|
||||||
|
follow_up = typer.prompt("Follow-up needed?", default="No")
|
||||||
|
append_discovery_answer(root, qid, question, answer, confidence, follow_up)
|
||||||
|
|
||||||
|
append_run_log(root, "Discovery completed", notes="Core questions answered")
|
||||||
|
console.print("[bold green]Discovery complete.[/bold green]")
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def status() -> None:
|
||||||
|
"""Show current project stage and task counts."""
|
||||||
|
root = root_path()
|
||||||
|
console.print(f"[bold]Project stage:[/bold] {project_stage(root)}")
|
||||||
|
|
||||||
|
counts = task_counts(root)
|
||||||
|
table = Table(title="Task Counts")
|
||||||
|
table.add_column("Status")
|
||||||
|
table.add_column("Count")
|
||||||
|
|
||||||
|
if counts:
|
||||||
|
for status_name, count in counts.items():
|
||||||
|
table.add_row(status_name, str(count))
|
||||||
|
else:
|
||||||
|
table.add_row("None", "0")
|
||||||
|
|
||||||
|
console.print(table)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(name="next")
|
||||||
|
def next_task() -> None:
|
||||||
|
"""Show the next Todo task."""
|
||||||
|
task = get_next_task(root_path())
|
||||||
|
if not task:
|
||||||
|
console.print("[yellow]No Todo task found.[/yellow]")
|
||||||
|
raise typer.Exit(code=0)
|
||||||
|
|
||||||
|
console.print(f"[bold]{task.task_id}[/bold] - {task.title}")
|
||||||
|
console.print(f"Status: {task.status}")
|
||||||
|
console.print(task.body)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def start(task_id: str) -> None:
|
||||||
|
"""Mark a task as In Progress."""
|
||||||
|
root = root_path()
|
||||||
|
if not update_task_status(root, task_id, "In Progress"):
|
||||||
|
console.print(f"[red]Task not found:[/red] {task_id}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
append_run_log(root, "Task started", task_id=task_id)
|
||||||
|
console.print(f"[green]Started {task_id}.[/green]")
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def complete(task_id: str) -> None:
|
||||||
|
"""Mark a task as Done and record validation notes."""
|
||||||
|
root = root_path()
|
||||||
|
notes = typer.prompt("Validation notes", default="Not tested")
|
||||||
|
if not update_task_status(root, task_id, "Done"):
|
||||||
|
console.print(f"[red]Task not found:[/red] {task_id}")
|
||||||
|
raise typer.Exit(code=1)
|
||||||
|
append_run_log(root, "Task completed", task_id=task_id, notes=notes)
|
||||||
|
console.print(f"[green]Completed {task_id}.[/green]")
|
||||||
|
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def handoff() -> None:
|
||||||
|
"""Print an AI-agent handoff summary."""
|
||||||
|
console.print(build_handoff(root_path()))
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import date
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from .templates import CORE_QUESTIONS
|
||||||
|
|
||||||
|
|
||||||
|
def append_discovery_answer(
|
||||||
|
root: Path,
|
||||||
|
question_id: str,
|
||||||
|
question: str,
|
||||||
|
answer: str,
|
||||||
|
confidence: str,
|
||||||
|
follow_up_needed: str,
|
||||||
|
) -> None:
|
||||||
|
log_path = root / "context" / "discovery-log.md"
|
||||||
|
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
if not log_path.exists():
|
||||||
|
log_path.write_text(
|
||||||
|
"# Discovery Log\n\n"
|
||||||
|
"| ID | Question | Answer | Confidence | Follow-up needed | Linked decision | Linked task | Date |\n"
|
||||||
|
"|---|---|---|---|---|---|---|---|\n",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
safe_answer = answer.replace("|", "\\|").replace("\n", " ").strip()
|
||||||
|
line = (
|
||||||
|
f"| {question_id} | {question} | {safe_answer} | {confidence} | "
|
||||||
|
f"{follow_up_needed} | | | {date.today().isoformat()} |\n"
|
||||||
|
)
|
||||||
|
with log_path.open("a", encoding="utf-8") as handle:
|
||||||
|
handle.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
def core_questions() -> list[str]:
|
||||||
|
return CORE_QUESTIONS
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from .status import project_stage, task_counts
|
||||||
|
from .tasks import get_next_task
|
||||||
|
|
||||||
|
|
||||||
|
def build_handoff(root: Path) -> str:
|
||||||
|
next_task = get_next_task(root)
|
||||||
|
counts = task_counts(root)
|
||||||
|
lines = [
|
||||||
|
"# AI Agent Handoff",
|
||||||
|
"",
|
||||||
|
f"Project stage: {project_stage(root)}",
|
||||||
|
"",
|
||||||
|
"## Task Counts",
|
||||||
|
]
|
||||||
|
if counts:
|
||||||
|
for status, count in counts.items():
|
||||||
|
lines.append(f"- {status}: {count}")
|
||||||
|
else:
|
||||||
|
lines.append("- No tasks found")
|
||||||
|
|
||||||
|
lines.extend(["", "## Next Task"])
|
||||||
|
if next_task:
|
||||||
|
lines.extend([
|
||||||
|
f"- ID: {next_task.task_id}",
|
||||||
|
f"- Title: {next_task.title}",
|
||||||
|
f"- Status: {next_task.status}",
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
lines.append("No Todo task found.")
|
||||||
|
|
||||||
|
lines.extend([
|
||||||
|
"",
|
||||||
|
"## Agent Rules",
|
||||||
|
"- Implement one task only.",
|
||||||
|
"- Make the smallest useful change possible.",
|
||||||
|
"- Do not rewrite unrelated code.",
|
||||||
|
"- Run relevant tests.",
|
||||||
|
"- Update documentation if behaviour changes.",
|
||||||
|
"- Report files changed, validation, risks, and next recommended task.",
|
||||||
|
])
|
||||||
|
return "\n".join(lines) + "\n"
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from .tasks import read_tasks
|
||||||
|
|
||||||
|
|
||||||
|
def project_stage(root: Path) -> str:
|
||||||
|
if not (root / "context" / "discovery-log.md").exists():
|
||||||
|
return "NOT_INITIALISED"
|
||||||
|
tasks = read_tasks(root)
|
||||||
|
if not tasks:
|
||||||
|
return "DISCOVERY"
|
||||||
|
if any(task.status.lower() == "in progress" for task in tasks):
|
||||||
|
return "BUILDING"
|
||||||
|
if any(task.status.lower() == "todo" for task in tasks):
|
||||||
|
return "TASKS_READY"
|
||||||
|
return "REVIEW_READY"
|
||||||
|
|
||||||
|
|
||||||
|
def task_counts(root: Path) -> dict[str, int]:
|
||||||
|
counts: dict[str, int] = {}
|
||||||
|
for task in read_tasks(root):
|
||||||
|
counts[task.status] = counts.get(task.status, 0) + 1
|
||||||
|
return counts
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
|
TASK_HEADING_RE = re.compile(r"^##\s+(TASK-\d+)\s+-\s+(.+)$", re.MULTILINE)
|
||||||
|
STATUS_RE = re.compile(r"^Status:\s*(.+)$", re.MULTILINE)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Task:
|
||||||
|
task_id: str
|
||||||
|
title: str
|
||||||
|
status: str
|
||||||
|
body: str
|
||||||
|
|
||||||
|
|
||||||
|
def read_tasks(root: Path) -> list[Task]:
|
||||||
|
tasks_path = root / "TASKS.md"
|
||||||
|
if not tasks_path.exists():
|
||||||
|
return []
|
||||||
|
|
||||||
|
text = tasks_path.read_text(encoding="utf-8")
|
||||||
|
matches = list(TASK_HEADING_RE.finditer(text))
|
||||||
|
tasks: list[Task] = []
|
||||||
|
|
||||||
|
for index, match in enumerate(matches):
|
||||||
|
start = match.start()
|
||||||
|
end = matches[index + 1].start() if index + 1 < len(matches) else len(text)
|
||||||
|
block = text[start:end]
|
||||||
|
status_match = STATUS_RE.search(block)
|
||||||
|
status = status_match.group(1).strip() if status_match else "Unknown"
|
||||||
|
tasks.append(Task(match.group(1), match.group(2).strip(), status, block))
|
||||||
|
|
||||||
|
return tasks
|
||||||
|
|
||||||
|
|
||||||
|
def get_next_task(root: Path) -> Task | None:
|
||||||
|
for task in read_tasks(root):
|
||||||
|
if task.status.lower() == "todo":
|
||||||
|
return task
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def update_task_status(root: Path, task_id: str, new_status: str) -> bool:
|
||||||
|
tasks_path = root / "TASKS.md"
|
||||||
|
if not tasks_path.exists():
|
||||||
|
return False
|
||||||
|
|
||||||
|
text = tasks_path.read_text(encoding="utf-8")
|
||||||
|
matches = list(TASK_HEADING_RE.finditer(text))
|
||||||
|
|
||||||
|
for index, match in enumerate(matches):
|
||||||
|
if match.group(1) != task_id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
start = match.start()
|
||||||
|
end = matches[index + 1].start() if index + 1 < len(matches) else len(text)
|
||||||
|
block = text[start:end]
|
||||||
|
if STATUS_RE.search(block):
|
||||||
|
new_block = STATUS_RE.sub(f"Status: {new_status}", block, count=1)
|
||||||
|
else:
|
||||||
|
lines = block.splitlines()
|
||||||
|
lines.insert(1, f"Status: {new_status}")
|
||||||
|
new_block = "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
tasks_path.write_text(text[:start] + new_block + text[end:], encoding="utf-8")
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
CORE_QUESTIONS = [
|
||||||
|
"What problem are we solving?",
|
||||||
|
"Who is the user?",
|
||||||
|
"What does success look like?",
|
||||||
|
"What is the minimum useful version?",
|
||||||
|
"What data do we need?",
|
||||||
|
"What systems must it connect to?",
|
||||||
|
"What are the risks?",
|
||||||
|
"What must not happen?",
|
||||||
|
"How will we test it?",
|
||||||
|
"How will it be deployed?",
|
||||||
|
]
|
||||||
|
|
||||||
|
CONTEXT_FILES: dict[str, str] = {
|
||||||
|
"context/discovery-log.md": """# Discovery Log
|
||||||
|
|
||||||
|
| ID | Question | Answer | Confidence | Follow-up needed | Linked decision | Linked task | Date |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
""",
|
||||||
|
"context/product-brief.md": """# Product Brief
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
## Users
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
## Minimum Useful Version
|
||||||
|
|
||||||
|
TBD
|
||||||
|
""",
|
||||||
|
"context/architecture.md": """# Architecture
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
## Integrations
|
||||||
|
|
||||||
|
TBD
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
TBD
|
||||||
|
""",
|
||||||
|
"context/decisions.md": """# Decisions
|
||||||
|
|
||||||
|
| ID | Decision | Reason | Date |
|
||||||
|
|---|---|---|---|
|
||||||
|
""",
|
||||||
|
"context/risks.md": """# Risks
|
||||||
|
|
||||||
|
| ID | Risk | Impact | Mitigation | Status |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
""",
|
||||||
|
"context/assumptions.md": """# Assumptions
|
||||||
|
|
||||||
|
| ID | Assumption | Confidence | Validation Needed |
|
||||||
|
|---|---|---|---|
|
||||||
|
""",
|
||||||
|
"context/open-questions.md": """# Open Questions
|
||||||
|
|
||||||
|
| ID | Question | Reason | Owner | Status |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
""",
|
||||||
|
"TASKS.md": """# TASKS.md
|
||||||
|
|
||||||
|
## TASK-001 - Create Python CLI project skeleton
|
||||||
|
Status: Done
|
||||||
|
|
||||||
|
Goal: Create the initial package structure, CLI entry point, and markdown-first bootstrap.
|
||||||
|
|
||||||
|
Acceptance Criteria:
|
||||||
|
- `rdb --help` runs
|
||||||
|
- `rdb init` creates project files
|
||||||
|
- README exists
|
||||||
|
|
||||||
|
## TASK-002 - Run initial project discovery
|
||||||
|
Status: Todo
|
||||||
|
|
||||||
|
Goal: Run `rdb discover` and capture the core project answers.
|
||||||
|
|
||||||
|
Acceptance Criteria:
|
||||||
|
- all 10 core questions are answered
|
||||||
|
- discovery-log.md contains ledger entries
|
||||||
|
- low-confidence answers are marked for follow-up
|
||||||
|
|
||||||
|
## TASK-003 - Review generated context files
|
||||||
|
Status: Todo
|
||||||
|
|
||||||
|
Goal: Review the generated markdown files and fill in obvious gaps.
|
||||||
|
|
||||||
|
Acceptance Criteria:
|
||||||
|
- product-brief.md reviewed
|
||||||
|
- architecture.md reviewed
|
||||||
|
- open-questions.md updated
|
||||||
|
|
||||||
|
## TASK-004 - Implement ask-more command
|
||||||
|
Status: Todo
|
||||||
|
|
||||||
|
Goal: Add a command that finds weak answers and asks deeper follow-up questions.
|
||||||
|
|
||||||
|
Acceptance Criteria:
|
||||||
|
- command reads discovery-log.md
|
||||||
|
- low-confidence answers are detected
|
||||||
|
- follow-up answers are appended to discovery-log.md
|
||||||
|
""",
|
||||||
|
"TEST_PLAN.md": """# TEST_PLAN.md
|
||||||
|
|
||||||
|
## Manual Tests
|
||||||
|
|
||||||
|
| ID | Test | Expected Result | Status |
|
||||||
|
|---|---|---|---|
|
||||||
|
| TEST-001 | Run `rdb --help` | CLI help is displayed | Not run |
|
||||||
|
| TEST-002 | Run `rdb init` | Markdown files are created | Not run |
|
||||||
|
| TEST-003 | Run `rdb status` | Project status is displayed | Not run |
|
||||||
|
| TEST-004 | Run `rdb next` | Next Todo task is shown | Not run |
|
||||||
|
|
||||||
|
## Automated Tests
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pytest
|
||||||
|
```
|
||||||
|
""",
|
||||||
|
"RUN_LOG.md": """# RUN_LOG.md
|
||||||
|
|
||||||
|
| Date | Event | Task | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
""",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def write_file_if_missing(root: Path, relative_path: str, content: str) -> bool:
|
||||||
|
target = root / relative_path
|
||||||
|
if target.exists():
|
||||||
|
return False
|
||||||
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
target.write_text(content, encoding="utf-8")
|
||||||
|
return True
|
||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,29 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from rdb_discovery.tasks import get_next_task, update_task_status
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_next_task(tmp_path: Path) -> None:
|
||||||
|
(tmp_path / "TASKS.md").write_text(
|
||||||
|
"# TASKS.md\n\n"
|
||||||
|
"## TASK-001 - First\nStatus: Done\n\n"
|
||||||
|
"## TASK-002 - Second\nStatus: Todo\n\n",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
task = get_next_task(tmp_path)
|
||||||
|
|
||||||
|
assert task is not None
|
||||||
|
assert task.task_id == "TASK-002"
|
||||||
|
assert task.title == "Second"
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_task_status(tmp_path: Path) -> None:
|
||||||
|
tasks = tmp_path / "TASKS.md"
|
||||||
|
tasks.write_text(
|
||||||
|
"# TASKS.md\n\n## TASK-001 - First\nStatus: Todo\n\n",
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert update_task_status(tmp_path, "TASK-001", "In Progress") is True
|
||||||
|
assert "Status: In Progress" in tasks.read_text(encoding="utf-8")
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from rdb_discovery.templates import write_file_if_missing
|
||||||
|
|
||||||
|
|
||||||
|
def test_write_file_if_missing(tmp_path: Path) -> None:
|
||||||
|
assert write_file_if_missing(tmp_path, "context/test.md", "hello") is True
|
||||||
|
assert (tmp_path / "context" / "test.md").read_text(encoding="utf-8") == "hello"
|
||||||
|
assert write_file_if_missing(tmp_path, "context/test.md", "changed") is False
|
||||||
|
assert (tmp_path / "context" / "test.md").read_text(encoding="utf-8") == "hello"
|
||||||
Reference in New Issue
Block a user