fix: feat: RESOURCES.md — infrastructure manifest for planner resource awareness (#23)
- Add RESOURCES.example.md: committed template showing Compute/Domains/Accounts/Budget structure - Gitignore RESOURCES.md so local infrastructure data is never committed - Planner phase 2 reads RESOURCES.md from factory root when present - Planner prompt instructs Claude to reference specific resource aliases in operational issues Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
211ccb0445
commit
26d6e1ae52
3 changed files with 54 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,6 +1,9 @@
|
||||||
# Secrets
|
# Secrets
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
# Infrastructure manifest (local only — commit RESOURCES.example.md instead)
|
||||||
|
RESOURCES.md
|
||||||
|
|
||||||
# Runtime state
|
# Runtime state
|
||||||
*.log
|
*.log
|
||||||
*.log.*
|
*.log.*
|
||||||
|
|
|
||||||
43
RESOURCES.example.md
Normal file
43
RESOURCES.example.md
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
# RESOURCES.md — Factory infrastructure inventory
|
||||||
|
# Copy to RESOURCES.md and fill in your actual values.
|
||||||
|
# RESOURCES.md is gitignored — never commit real hostnames, IPs, or credentials.
|
||||||
|
|
||||||
|
## Compute
|
||||||
|
|
||||||
|
### <host-alias>
|
||||||
|
- **Specs**: e.g. 8 GB RAM, 4 vCPU, 80 GB disk
|
||||||
|
- **Location**: e.g. region / datacenter
|
||||||
|
- **Access**: e.g. `ssh user@host-alias` (key in ~/.ssh/id_ed25519)
|
||||||
|
- **Running**: list current workloads, e.g. woodpecker-ci, disinto, postgres
|
||||||
|
- **Available for**: what it can still absorb, e.g. staging deploy, build cache
|
||||||
|
- **Projects**: which projects use this host, e.g. myorg/myproject
|
||||||
|
|
||||||
|
### <host-alias-2>
|
||||||
|
- **Specs**:
|
||||||
|
- **Location**:
|
||||||
|
- **Access**:
|
||||||
|
- **Running**:
|
||||||
|
- **Available for**:
|
||||||
|
- **Projects**:
|
||||||
|
|
||||||
|
## Domains
|
||||||
|
|
||||||
|
| Domain | Status | Project | Notes |
|
||||||
|
|--------|--------|---------|-------|
|
||||||
|
| example.com | active | myorg/myproject | main domain, auto-renew on |
|
||||||
|
| staging.example.com | active | myorg/myproject | points to staging server |
|
||||||
|
|
||||||
|
## External accounts
|
||||||
|
|
||||||
|
| Service | Purpose | Limits |
|
||||||
|
|---------|---------|--------|
|
||||||
|
| Codeberg | source hosting + CI triggers | 10 GB storage, 1000 min/mo CI |
|
||||||
|
| Anthropic | Claude API | $X/mo budget, rate limit: 100k TPM |
|
||||||
|
| Cloudflare | DNS + CDN | free tier |
|
||||||
|
|
||||||
|
## Budget
|
||||||
|
|
||||||
|
- **Compute**: e.g. €20/mo cap — current spend €12/mo (2 VPS)
|
||||||
|
- **Domains**: e.g. €30/yr — next renewal: 2025-11-01
|
||||||
|
- **APIs**: e.g. $50/mo Anthropic — alert at $40
|
||||||
|
- **Other**: any other constraints
|
||||||
|
|
@ -19,6 +19,7 @@ source "$FACTORY_ROOT/lib/env.sh"
|
||||||
LOG_FILE="$SCRIPT_DIR/planner.log"
|
LOG_FILE="$SCRIPT_DIR/planner.log"
|
||||||
CLAUDE_TIMEOUT="${CLAUDE_TIMEOUT:-3600}"
|
CLAUDE_TIMEOUT="${CLAUDE_TIMEOUT:-3600}"
|
||||||
VISION_FILE="${PROJECT_REPO_ROOT}/VISION.md"
|
VISION_FILE="${PROJECT_REPO_ROOT}/VISION.md"
|
||||||
|
RESOURCES_FILE="${FACTORY_ROOT}/RESOURCES.md"
|
||||||
|
|
||||||
log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%S)Z] $*" >> "$LOG_FILE"; }
|
log() { echo "[$(date -u +%Y-%m-%dT%H:%M:%S)Z] $*" >> "$LOG_FILE"; }
|
||||||
|
|
||||||
|
|
@ -178,6 +179,9 @@ if [ -z "$VISION" ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
RESOURCES=""
|
||||||
|
[ -f "$RESOURCES_FILE" ] && RESOURCES=$(cat "$RESOURCES_FILE")
|
||||||
|
|
||||||
# Fetch open issues (all labels)
|
# Fetch open issues (all labels)
|
||||||
OPEN_ISSUES=$(codeberg_api GET "/issues?state=open&type=issues&limit=50&sort=updated&direction=desc" 2>/dev/null || true)
|
OPEN_ISSUES=$(codeberg_api GET "/issues?state=open&type=issues&limit=50&sort=updated&direction=desc" 2>/dev/null || true)
|
||||||
if [ -z "$OPEN_ISSUES" ] || [ "$OPEN_ISSUES" = "null" ]; then
|
if [ -z "$OPEN_ISSUES" ] || [ "$OPEN_ISSUES" = "null" ]; then
|
||||||
|
|
@ -198,6 +202,9 @@ ${VISION}
|
||||||
## Current project state (AGENTS.md tree)
|
## Current project state (AGENTS.md tree)
|
||||||
${PROJECT_STATE}
|
${PROJECT_STATE}
|
||||||
|
|
||||||
|
## RESOURCES.md (shared factory infrastructure)
|
||||||
|
${RESOURCES:-"(not found — copy RESOURCES.example.md to RESOURCES.md and fill in your infrastructure)"}
|
||||||
|
|
||||||
## Vision-labeled issues (goal anchors)
|
## Vision-labeled issues (goal anchors)
|
||||||
${VISION_ISSUES:-"(none)"}
|
${VISION_ISSUES:-"(none)"}
|
||||||
|
|
||||||
|
|
@ -206,6 +213,7 @@ ${OPEN_SUMMARY}
|
||||||
|
|
||||||
## Task
|
## Task
|
||||||
Identify gaps — things implied by VISION.md that are neither reflected in the project state nor covered by an existing open issue.
|
Identify gaps — things implied by VISION.md that are neither reflected in the project state nor covered by an existing open issue.
|
||||||
|
When a gap involves deploying, hosting, or operating a service, reference the specific resource alias from RESOURCES.md (e.g. \"deploy to <host-alias>\") so issues are actionable.
|
||||||
|
|
||||||
For each gap, output a JSON object (one per line, no array wrapper):
|
For each gap, output a JSON object (one per line, no array wrapper):
|
||||||
{\"title\": \"action-oriented title\", \"body\": \"problem statement + why it matters + rough approach\", \"depends\": [list of blocking issue numbers or empty]}
|
{\"title\": \"action-oriented title\", \"body\": \"problem statement + why it matters + rough approach\", \"depends\": [list of blocking issue numbers or empty]}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue