chore: bootstrap rdb-discovery

This commit is contained in:
2026-06-01 17:43:02 +01:00
commit dede6ecc60
45 changed files with 2101 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
{
"project_name": "rdb-discovery",
"stage": "DISCOVERY",
"current_task": "TASK-000",
"next_task": "TASK-001"
}
+18
View File
@@ -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
+10
View File
@@ -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
+44
View File
@@ -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.
+4
View File
@@ -0,0 +1,4 @@
Run Log
2026-06-01
Bootstrap project structure created.
+23
View File
@@ -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.
+17
View File
@@ -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
+269
View File
@@ -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.
View File
View File
+40
View File
@@ -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.
+542
View File
@@ -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
View File
+294
View File
@@ -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
View File
+193
View File
@@ -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
View File
View File
+31
View File
@@ -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
View File
+22
View File
@@ -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"
+55
View File
@@ -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.
+17
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
typer>=0.12.0
rich>=13.0.0
[dev]
pytest>=8.0.0
+1
View File
@@ -0,0 +1 @@
rdb_discovery
+1
View File
@@ -0,0 +1 @@
__version__ = "0.1.0"
Binary file not shown.
Binary file not shown.
Binary file not shown.
+133
View File
@@ -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()))
+38
View File
@@ -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
+45
View File
@@ -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"
+25
View File
@@ -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
+71
View File
@@ -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
+155
View File
@@ -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
+29
View File
@@ -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")
+10
View File
@@ -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"