Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ venv/
dist/
build/
*.egg-info/

# Ralph Wiggum
logs/ralph/
state/
*.tmp

# Night Nurse
logs/night-nurse.log
16 changes: 16 additions & 0 deletions .night-nurse/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "brand-os",
"path": "/home/deploy/scty-repos/brand-os",
"agents": {
"review": "claude",
"implement": "codex"
},
"maxIterations": 25,
"priorities": {
"sources": [
"sentry",
"specs",
"backlog"
]
}
}
12 changes: 12 additions & 0 deletions .night-nurse/priorities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Priorities

Items listed here will be picked up by Night Nurse (highest first).

## High Priority
<!-- Critical bugs, blockers -->

## Medium Priority
<!-- Features, improvements -->

## Low Priority
<!-- Nice to have, tech debt -->
11 changes: 11 additions & 0 deletions .night-nurse/state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"initialized": "2026-01-28T17:26:09Z",
"lastLearn": "2026-02-01T03:01:03Z",
"lastTreat": null,
"stats": {
"specsCompleted": 0,
"specsInProgress": 0,
"totalIterations": 0,
"learnings": 3
}
}
23 changes: 23 additions & 0 deletions .specify/memory/constitution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Constitution - brand-os

## Project Purpose
CLI-first brand operations toolkit - unified personas, intel, content, and publishing

## Tech Stack
Python

## Build & Test
```bash
# npm run build
pytest
```

## Principles
1. Keep changes minimal and focused
2. Don't break existing functionality
3. Add tests for new behavior

## Boundaries
- Don't modify production data directly
- Don't commit secrets
- Don't change CI/CD without review
3 changes: 3 additions & 0 deletions logs/improve.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/bin/sh: 1: /home/deploy/clawd/skills/ralph-wiggum/scripts/ai-review.sh: not found
/bin/sh: 1: /home/deploy/clawd/skills/ralph-wiggum/scripts/ai-review.sh: not found
/bin/sh: 1: /home/deploy/clawd/skills/ralph-wiggum/scripts/ai-review.sh: not found
3 changes: 3 additions & 0 deletions logs/ralph.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/bin/sh: 1: /home/deploy/clawd/skills/ralph-wiggum/scripts/ralph-loop-ai.sh: not found
/bin/sh: 1: /home/deploy/clawd/skills/ralph-wiggum/scripts/ralph-loop-ai.sh: not found
/bin/sh: 1: /home/deploy/clawd/skills/ralph-wiggum/scripts/ralph-loop-ai.sh: not found
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ publish = [
server = [
"fastapi>=0.115",
"uvicorn>=0.32",
"fastmcp<3",
]
email = [
"resend>=2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Log: MCP Server Implementation - Complete the MCP server to expose brand operations (personas, content, intel, decisions) as tools for AI assistants using FastMCP

## 2026-02-01
- Spec created

### Iteration 1 - 15:18:22
Task: 1.1 [Task]
Result: ✓ Complete

### Iteration 2 - 15:20:47
Task: 1.1 [Task]
Result: ✓ Complete
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Proposal: MCP Server Implementation - Complete the MCP server to expose brand operations (personas, content, intel, decisions) as tools for AI assistants using FastMCP

## Intent
<!-- Why we're doing this. The problem we're solving. -->

## Scope
**In scope:**
-

**Out of scope:**
-

## Approach
<!-- High-level how we'll tackle it. -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Spec: MCP Server Implementation - Complete the MCP server to expose brand operations (personas, content, intel, decisions) as tools for AI assistants using FastMCP

## Requirements

### Requirement: [Name]
The system SHALL [behavior].

#### Scenario: [Happy path]
- GIVEN [context]
- WHEN [action]
- THEN [result]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Tasks: MCP Server Implementation - Complete the MCP server to expose brand operations (personas, content, intel, decisions) as tools for AI assistants using FastMCP

## 1. Setup
- [ ] 1.1 [Task]

## 2. Implementation
- [ ] 2.1 [Task]

## 3. Testing
- [ ] 3.1 [Task]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Log: Content Producer Agent - Implement agent that takes Market Analyst outputs and generates brand-aligned content for publishing

## 2026-02-01
- Spec created
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Proposal: Content Producer Agent - Implement agent that takes Market Analyst outputs and generates brand-aligned content for publishing

## Intent
<!-- Why we're doing this. The problem we're solving. -->

## Scope
**In scope:**
-

**Out of scope:**
-

## Approach
<!-- High-level how we'll tackle it. -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Spec: Content Producer Agent - Implement agent that takes Market Analyst outputs and generates brand-aligned content for publishing

## Requirements

### Requirement: [Name]
The system SHALL [behavior].

#### Scenario: [Happy path]
- GIVEN [context]
- WHEN [action]
- THEN [result]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Tasks: Content Producer Agent - Implement agent that takes Market Analyst outputs and generates brand-aligned content for publishing

## 1. Setup
- [ ] 1.1 [Task]

## 2. Implementation
- [ ] 2.1 [Task]

## 3. Testing
- [ ] 3.1 [Task]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2026-01-28
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# [FIX] Implement notification in approval.py

## Task
In `src/brand_os/workflows/approval.py` line 114, replace the TODO comment with actual Slack notification code.

## Current Code (line 112-115)
```python
def _notify(self, message: str) -> None:
"""Send notification (placeholder for Slack/email integration)."""
# TODO: Implement notification via slack-sdk or email
pass
```

## Required Change
Replace the TODO and `pass` with code that sends a Slack webhook notification using httpx (already imported in the project). Use env var `SLACK_WEBHOOK_URL`. If not set, just log the message.

## Example Implementation
```python
def _notify(self, message: str) -> None:
"""Send notification via Slack webhook."""
import os
webhook_url = os.getenv("SLACK_WEBHOOK_URL")
if webhook_url:
try:
import httpx
httpx.post(webhook_url, json={"text": f"[BrandOS] {message}"}, timeout=10)
except Exception:
pass # Silent fail - notification is best-effort
```

## Completion Signal
```bash
grep -rn "# TODO: Implement notification via slack-sdk or email" src/brand_os/workflows/approval.py && exit 1 || echo "TODO resolved"
```

## Constraints
- Only modify the `_notify` method
- Keep it simple - just Slack webhook, no email
19 changes: 17 additions & 2 deletions src/brand_os/server/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@
def create_mcp_server():
"""Create MCP server for LLM integration.

This is a placeholder - implement with MCP SDK.
Requires: fastmcp optional dependency.
"""
raise NotImplementedError("MCP server not yet implemented")
try:
from fastmcp import FastMCP
except ImportError as exc:
raise ImportError("fastmcp required. Install with: pip install brand-os[server]") from exc

return FastMCP("brandos")


def run_server() -> None:
"""Run the MCP server with default stdio transport."""
mcp = create_mcp_server()
mcp.run()


if __name__ == "__main__":
run_server()
18 changes: 15 additions & 3 deletions src/brand_os/workflows/approval.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,21 @@ def _save(self) -> None:
get_decision_log().update(self.decision)

def _notify(self, message: str) -> None:
"""Send notification (placeholder for Slack/email integration)."""
# TODO: Implement notification via slack-sdk or email
pass
"""Send notification via Slack webhook."""
import os

webhook_url = os.getenv("SLACK_WEBHOOK_URL")
if not webhook_url:
logger.info("Approval notification: %s", message)
Comment on lines +116 to +118
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add missing logger import or initialization

When SLACK_WEBHOOK_URL is unset, _notify calls logger.info(...), but this module never defines logger. That means normal approval flows without a webhook will raise NameError instead of logging. This breaks the state machine paths that call _notify in non-webhook environments. Import and initialize a logger (or use the existing logging setup) before calling it.

Useful? React with 👍 / 👎.

return
try:
httpx.post(
webhook_url,
json={"text": f"[BrandOS] {message}"},
timeout=10,
Comment on lines +120 to +124
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import httpx before using it in notifications

When SLACK_WEBHOOK_URL is set, _notify calls httpx.post(...), but httpx is never imported in this file, so the first approval notification will raise NameError. This makes webhook notifications non-functional even though the dependency exists. Import httpx (module-level or inside the function) before invoking it.

Useful? React with 👍 / 👎.

)
except Exception:
pass # Best-effort notification

else:
# Fallback implementation without statemachine dependency
Expand Down