Skip to content
Closed
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ sessions/
kanban.db
config/runtime-config/live/
config/runtime-config/private/
tools/kurultai/buildroom/.generated/
148 changes: 148 additions & 0 deletions tests/kurultai/test_buildroom_foundation.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ def test_approved_build_plan_creates_kanban_task_packet_with_parent_refs(tmp_pat
assert packet["title"] == "buildroom: Buildroom foundation demo"
assert packet["assignee"] == "chagatai"
assert packet["parents"] == ["t_parent_one", "t_parent_two"]
assert packet["workspace_kind"] == "dir"
assert Path(packet["workspace_path"]).is_absolute()
assert "${" not in packet["workspace_path"]
assert packet["idempotency_key"] == "buildroom:build-buildroom-foundation-demo"
assert packet["metadata"]["build_id"] == "build-buildroom-foundation-demo"
assert "Allowed paths:" in packet["body"]
Expand Down Expand Up @@ -267,6 +270,9 @@ def test_independent_qa_task_packet_uses_build_plan_and_receipt_parent(tmp_path:
assert packet["title"] == "buildroom-qa: Buildroom foundation demo"
assert packet["assignee"] == "ogedei"
assert packet["parents"] == ["t_build123"]
assert packet["workspace_kind"] == "dir"
assert Path(packet["workspace_path"]).is_absolute()
assert "${" not in packet["workspace_path"]
assert packet["idempotency_key"] == "buildroom-qa:build-buildroom-foundation-demo"
assert packet["metadata"]["build_id"] == "build-buildroom-foundation-demo"
assert packet["metadata"]["independent_of"] == "chagatai"
Expand Down Expand Up @@ -521,3 +527,145 @@ def test_control_room_cron_fail_on_actionable_exit_code(tmp_path):
"--fail-on-actionable",
)
assert result.returncode == 2



def test_apply_kanban_drafts_dry_run_dedupes(tmp_path: Path) -> None:
drafts = tmp_path / "drafts.json"
state = tmp_path / "state.json"
ledger = tmp_path / "ledger.json"
write_json(drafts, {"drafts": [
{"title": "Review room", "metadata": {"attention_item_id": "same", "room_id": "demo-room", "severity": "high", "reason": "watch"}},
{"title": "Review room duplicate", "metadata": {"attention_item_id": "same", "room_id": "demo-room", "severity": "high", "reason": "watch"}},
]})
result = run_script("tools/kurultai/buildroom/scripts/apply_kanban_drafts.py", "--drafts", str(drafts), "--state", str(state), "--ledger", str(ledger))
assert result.returncode == 0, result.stdout
payload = read_json(ledger)
assert payload["mode"] == "dry-run"
assert payload["summary"]["drafts"] == 2
assert payload["summary"]["unique"] == 1
assert payload["summary"]["new"] == 1
task = payload["tasks"][0]
assert task["workspace_kind"] == "dir"
assert Path(task["workspace_path"]).is_absolute()
assert "${" not in task["workspace_path"]


def test_apply_kanban_drafts_apply_is_idempotent(tmp_path: Path) -> None:
import sqlite3
db = tmp_path / "kanban.db"
con = sqlite3.connect(db)
con.execute("CREATE TABLE tasks (id TEXT PRIMARY KEY, title TEXT NOT NULL, body TEXT, assignee TEXT, status TEXT NOT NULL, priority INTEGER DEFAULT 0, created_by TEXT, created_at INTEGER NOT NULL, started_at INTEGER, completed_at INTEGER, workspace_kind TEXT NOT NULL DEFAULT 'scratch', workspace_path TEXT, claim_lock TEXT, claim_expires INTEGER, tenant TEXT, result TEXT, idempotency_key TEXT, spawn_failures INTEGER NOT NULL DEFAULT 0, worker_pid INTEGER, last_spawn_error TEXT, max_runtime_seconds INTEGER, last_heartbeat_at INTEGER, current_run_id INTEGER, workflow_template_id TEXT, current_step_key TEXT, skills TEXT)")
con.execute("CREATE TABLE task_events (id INTEGER PRIMARY KEY AUTOINCREMENT, task_id TEXT NOT NULL, run_id INTEGER, kind TEXT NOT NULL, payload TEXT, created_at INTEGER NOT NULL)")
con.commit()
con.close()
drafts = tmp_path / "drafts.json"
state = tmp_path / "state.json"
ledger = tmp_path / "ledger.json"
write_json(drafts, {"drafts": [{"title": "Review room", "metadata": {"attention_item_id": "same", "room_id": "demo-room"}}]})
first = run_script("tools/kurultai/buildroom/scripts/apply_kanban_drafts.py", "--drafts", str(drafts), "--state", str(state), "--ledger", str(ledger), "--kanban-db", str(db), "--apply")
second = run_script("tools/kurultai/buildroom/scripts/apply_kanban_drafts.py", "--drafts", str(drafts), "--state", str(state), "--ledger", str(ledger), "--kanban-db", str(db), "--apply")
assert first.returncode == 0, first.stdout
assert second.returncode == 0, second.stdout
con = sqlite3.connect(db)
assert con.execute("select count(*) from tasks").fetchone()[0] == 1
workspace_kind, workspace_path = con.execute("select workspace_kind, workspace_path from tasks").fetchone()
assert workspace_kind == "dir"
assert Path(workspace_path).is_absolute()
assert "${" not in workspace_path
assert con.execute("select count(*) from task_events").fetchone()[0] == 1
con.close()


def test_retention_review_emits_non_destructive_followups(tmp_path: Path) -> None:
room = copy_demo_room(tmp_path, "retention-room")
retention = room / "retention" / "retention-review.json"
data = read_json(retention)
data["recommendation"] = "improve"
data["status"] = "pending"
write_json(retention, data)
output = tmp_path / "retention-items.json"
result = run_script("tools/kurultai/buildroom/scripts/retention_review.py", "--rooms", str(tmp_path), "--output", str(output))
assert result.returncode == 0, result.stdout
payload = read_json(output)
assert payload["summary"]["items"] == 1
assert payload["items"][0]["needs_receipt"] is True
assert payload["items"][0]["room_id"] == "retention-room"


def test_buildroom_healthcheck_quick_mode_passes() -> None:
result = run_script("tools/kurultai/buildroom/scripts/buildroom_healthcheck.py", "--skip-pytest")
assert result.returncode == 0, result.stdout
assert "buildroom healthcheck: PASS" in result.stdout



def test_opportunity_radar_generates_ranked_candidates(tmp_path: Path) -> None:
brain = tmp_path / "brain"
(brain / "docs" / "designs").mkdir(parents=True)
(brain / "docs" / "designs" / "radar.md").write_text(
"# Opportunity Radar\n\nAuto Think should rank what should we build next.\n",
encoding="utf-8",
)
json_out = tmp_path / "opportunity-radar.json"
md_out = tmp_path / "opportunity-radar.md"
drafts_out = tmp_path / "drafts.json"
result = subprocess.run(
[
"python3",
str(BUILDROOM / "scripts" / "opportunity_radar.py"),
"--brain-root",
str(brain),
"--buildroom-root",
str(BUILDROOM),
"--json-output",
str(json_out),
"--markdown-output",
str(md_out),
"--kanban-drafts-output",
str(drafts_out),
"--json",
],
cwd=ROOT,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=True,
)
payload = json.loads(json_out.read_text())
assert payload["recommended_next_action"] == "Buildroom Opportunity Radar v0"
assert payload["candidates"][0]["scores"]["total"] >= 38
assert "Buildroom Opportunity Radar" in md_out.read_text()
drafts = json.loads(drafts_out.read_text())
assert drafts["draft_count"] >= 1
assert "candidate_count" in result.stdout


def test_run_buildroom_cycle_completes_with_dry_run_receipt(tmp_path: Path) -> None:
receipt = tmp_path / "cycle-receipt.json"
result = subprocess.run(
[
"python3",
str(BUILDROOM / "scripts" / "run_buildroom_cycle.py"),
"--skip-pytest",
"--receipt-output",
str(receipt),
"--json",
],
cwd=ROOT,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=True,
)
summary = json.loads(result.stdout)
payload = json.loads(receipt.read_text())
assert summary["ok"] is True
assert payload["mode"] == "dry-run"
assert payload["ok"] is True
assert payload["step_count"] >= 6
assert "proposal_summary" in summary
assert "proposal_summary" in payload
assert summary["proposal_summary"]["outcome"]["opportunity_radar_candidates"] >= 1
assert summary["proposal_summary"]["proposals"][0]["title"] == "Buildroom Opportunity Radar v0"
assert summary["proposal_summary"]["proposals"][0]["summary"]
2 changes: 1 addition & 1 deletion tools/kurultai/buildroom/control-room-attention-items.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"summary": "Room is in watch state."
}
],
"generated_at": "2026-05-11T02:09:12Z",
"generated_at": "2026-05-11T02:29:48Z",
"items": [
{
"category": "operator_decision",
Expand Down
2 changes: 1 addition & 1 deletion tools/kurultai/buildroom/control-room-kanban-drafts.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@
"title": "Buildroom follow-up: 2026-05-10-gkisokay-auto-think-auto-build \u2014 trust"
}
],
"generated_at": "2026-05-11T02:09:12Z",
"generated_at": "2026-05-11T02:29:48Z",
"source": "buildroom-control-room-cron-v0"
}
31 changes: 31 additions & 0 deletions tools/kurultai/buildroom/control-room-retention-items.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"items": [
{
"id": "retention:2026-05-10-gkisokay-auto-think-auto-build",
"needs_receipt": true,
"next_action": "review retention recommendation and write receipt",
"receipt_template": "brain/receipts/kurultai/{date}-2026-05-10-gkisokay-auto-think-auto-build-retention-review.md",
"recommendation": "keep",
"room_id": "2026-05-10-gkisokay-auto-think-auto-build",
"severity": "medium",
"status": "pending",
"trust_state": "watch"
},
{
"id": "retention:demo-room",
"needs_receipt": true,
"next_action": "review retention recommendation and write receipt",
"receipt_template": "brain/receipts/kurultai/{date}-demo-room-retention-review.md",
"recommendation": "keep",
"room_id": "demo-room",
"severity": "low",
"status": "pending",
"trust_state": "clean"
}
],
"rooms_root": "rooms",
"summary": {
"items": 2,
"needs_receipt": 2
}
}
4 changes: 2 additions & 2 deletions tools/kurultai/buildroom/control-room.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<div>
<p class="eyebrow">Kurultai / Buildroom</p>
<h1>Control Room</h1>
<p class="subtitle">Generated 2026-05-11T02:09:12Z. Static, public-safe dashboard for buildroom trust and evidence.</p>
<p class="subtitle">Generated 2026-05-11T02:29:48Z. Static, public-safe dashboard for buildroom trust and evidence.</p>
</div>
</section>
<section class="summary">
Expand Down Expand Up @@ -239,7 +239,7 @@ <h2>Install a typed buildroom foundation for autonomous improvement work</h2>
}
],
&quot;summary&quot;: {
&quot;generated_at&quot;: &quot;2026-05-11T02:09:12Z&quot;,
&quot;generated_at&quot;: &quot;2026-05-11T02:29:48Z&quot;,
&quot;room_count&quot;: 2,
&quot;rooms_needing_decision&quot;: 1,
&quot;rooms_with_missing_evidence&quot;: 0,
Expand Down
2 changes: 1 addition & 1 deletion tools/kurultai/buildroom/control-room.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
}
],
"summary": {
"generated_at": "2026-05-11T02:09:12Z",
"generated_at": "2026-05-11T02:29:48Z",
"room_count": 2,
"rooms_needing_decision": 1,
"rooms_with_missing_evidence": 0,
Expand Down
2 changes: 1 addition & 1 deletion tools/kurultai/buildroom/control-room.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Kurultai Buildroom Control Room

Generated: 2026-05-11T02:09:12Z
Generated: 2026-05-11T02:29:48Z

## Summary

Expand Down
52 changes: 52 additions & 0 deletions tools/kurultai/buildroom/docs/control-room-operating-loop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Buildroom Control Room Operating Loop

The Control Room loop turns buildroom contracts into recurring caretaker work.

## Commands

Run from the Kurultai repo root:

- `python3 tools/kurultai/buildroom/scripts/control_room_cron.py`
- `python3 tools/kurultai/buildroom/scripts/apply_kanban_drafts.py`
- `python3 tools/kurultai/buildroom/scripts/retention_review.py`
- `python3 tools/kurultai/buildroom/scripts/buildroom_healthcheck.py`

## Loop phases

1. Regenerate the dashboard: `control-room.md/json/html`.
2. Emit attention items: `control-room-attention-items.json`.
3. Emit Kanban drafts: `control-room-kanban-drafts.json`.
4. Dry-run the Kanban bridge and write an apply ledger under `.generated/`.
5. Emit retention review items: `control-room-retention-items.json`.
6. Run the healthcheck canary before any PR or scheduled rollout.

## Kanban bridge safety

`apply_kanban_drafts.py` is dry-run by default. It only creates real Hermes Kanban tasks when `--apply` is passed.

Dedupe is based on a stable attention-item key and the Hermes task `idempotency_key`, prefixed with `buildroom-control-room:`. This prevents repeated cron runs from spamming duplicate tasks.

## Retention safety

`retention_review.py` never deletes buildroom artifacts. It only emits follow-up items and receipt templates for keep/improve/park/prune decisions.

## Healthcheck contract

`buildroom_healthcheck.py` verifies:

- demo room validates
- real gkisokay room validates
- Control Room generation succeeds
- Control Room Cron succeeds
- Kanban bridge dry-run succeeds
- generated files exist
- buildroom scripts compile
- focused buildroom pytest passes unless `--skip-pytest` is used

## Suggested Hermes cron

Conservative schedule: every 60 minutes.

Command shape: run healthcheck in quick mode, run Control Room Cron, dry-run the Kanban bridge, and emit retention review items.

Default behavior remains proposal-only. Add `--apply` to the Kanban bridge only after the dedupe ledger and task bodies are reviewed.
31 changes: 31 additions & 0 deletions tools/kurultai/buildroom/docs/opportunity-radar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Buildroom Opportunity Radar

Opportunity Radar is the Auto Think layer for the buildroom system. It ranks evidence-backed build candidates from Brain and buildroom state, emits inspectable JSON/markdown reports, and drafts follow-up work without applying side effects by default.

Run:

```bash
python3 tools/kurultai/buildroom/scripts/opportunity_radar.py
```

Outputs:

- `tools/kurultai/buildroom/opportunity-radar.json`
- `tools/kurultai/buildroom/opportunity-radar.md`
- `tools/kurultai/buildroom/opportunity-radar-kanban-drafts.json`

Buildroom cycle command:

```bash
python3 tools/kurultai/buildroom/scripts/run_buildroom_cycle.py
```

This validates rooms, regenerates Control Room outputs, runs cron extraction, runs Opportunity Radar, performs a Kanban bridge dry-run, runs retention review, runs healthcheck, and writes `buildroom-cycle-receipt.json`.

Real Kanban creation requires:

```bash
python3 tools/kurultai/buildroom/scripts/run_buildroom_cycle.py --apply-kanban
```

Safety defaults: local-first, dry-run by default, no external side effects, no hard deletes, inspectable generated artifacts, and explicit apply modes.
46 changes: 46 additions & 0 deletions tools/kurultai/buildroom/opportunity-radar-kanban-drafts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"draft_count": 3,
"drafts": [
{
"body": "Candidate: Buildroom Opportunity Radar v0\nType: system-improvement\nScore: 49.9\nDisposition: buildroom-candidate\nWhy now: Kurultai has a strong Auto Build loop, but candidate selection is still less inspectable than execution.\nExpected leverage: Turns Brain artifacts into recurring ranked build intent and reduces ad hoc operator steering.\nAcceptance criteria:\n- emit JSON and markdown reports\n- score candidates explainably\n- emit dry-run Kanban drafts\n- link recommendations to source refs\n- pass tests and leakage scan",
"candidate_id": "e5b14f92b7ca",
"labels": [
"buildroom",
"opportunity-radar",
"system-improvement",
"buildroom-candidate"
],
"priority": "high",
"source": "buildroom-opportunity-radar-v0",
"title": "Buildroom opportunity: Buildroom Opportunity Radar v0"
},
{
"body": "Candidate: Brain Compiler Coverage Ledger\nType: brain-compiler\nScore: 47.9\nDisposition: buildroom-candidate\nWhy now: The Brain has more durable artifacts; now it needs coverage accounting to prevent passive storage.\nExpected leverage: Enforces the invariant that memory only matters when it changes future behavior or gets a no-op receipt.\nAcceptance criteria:\n- scan queue/generated/reviews/proposals/receipts\n- identify missing dispositions\n- emit coverage report",
"candidate_id": "19eca945eb9b",
"labels": [
"buildroom",
"opportunity-radar",
"brain-compiler",
"buildroom-candidate"
],
"priority": "high",
"source": "buildroom-opportunity-radar-v0",
"title": "Buildroom opportunity: Brain Compiler Coverage Ledger"
},
{
"body": "Candidate: Agent Harness Maturity Scoreboard\nType: evaluation-candidate\nScore: 46.7\nDisposition: buildroom-candidate\nWhy now: The agent-engineering research argues that agent engineering is harness engineering.\nExpected leverage: Makes agent trust and hardening gaps visible before autonomy expands.\nAcceptance criteria:\n- produce explainable maturity scores\n- surface improvement recommendations\n- integrate with Control Room",
"candidate_id": "05b418059610",
"labels": [
"buildroom",
"opportunity-radar",
"evaluation-candidate",
"buildroom-candidate"
],
"priority": "high",
"source": "buildroom-opportunity-radar-v0",
"title": "Buildroom opportunity: Agent Harness Maturity Scoreboard"
}
],
"generated_at": "2026-05-11T03:21:25Z",
"source": "buildroom-opportunity-radar-v0"
}
Loading
Loading