Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions .bifrost.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
url: https://bifrost.ericsiebeneich.com
realm: bifrost
orchestrate:
dispatcher: /home/devzeebo/.config/bifrost/orchestrator
concurrency: 1
logging: verbose
Comment on lines +3 to +6

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Avoid committing a developer-specific absolute path.

dispatcher: /home/devzeebo/.config/bifrost/orchestrator is a hard-coded personal path that won't resolve for any other contributor, CI agent, or docker build; bf orchestrate will fail immediately with dispatcher script not found. Since the orchestrator lives in-repo at claude-orchestrator/dispatcher.py, point .bifrost.yaml at the in-tree script (or drop this block from the committed config and keep the absolute path in a local/untracked override).

🔧 Suggested fix
 orchestrate:
-  dispatcher: /home/devzeebo/.config/bifrost/orchestrator
+  dispatcher: claude-orchestrator/dispatcher.py
   concurrency: 1
   logging: verbose
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
orchestrate:
dispatcher: /home/devzeebo/.config/bifrost/orchestrator
concurrency: 1
logging: verbose
orchestrate:
dispatcher: claude-orchestrator/dispatcher.py
concurrency: 1
logging: verbose
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.bifrost.yaml around lines 3 - 6, Replace the developer-specific absolute
dispatcher path in .bifrost.yaml with the repository-relative orchestrator
script or remove the block; specifically update the dispatcher key (currently
pointing to /home/devzeebo/.config/bifrost/orchestrator) to reference the
in-tree script claude-orchestrator/dispatcher.py (or omit the
orchestrate/dispatcher entry so local untracked overrides can be used), ensuring
the value is a repo-relative path so CI and other contributors can resolve it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP -C3 '\b(Logging|logging|Verbose|verbose)\b' --type=go -g '!**/vendor/**'
rg -nP -C3 'OrchestrateConfig|orchestrate\.' --type=go -g '!**/vendor/**'

Repository: devzeebo/bifrost

Length of output: 2306


🏁 Script executed:

# Read the complete OrchestrateConfig struct definition
cat -n cli/orchestrate.go | sed -n '17,30p'

Repository: devzeebo/bifrost

Length of output: 680


🏁 Script executed:

# Find YAML unmarshalling code
rg -n 'Unmarshal|mapstructure|yaml' --type=go -A3 -B3 cli/config.go

Repository: devzeebo/bifrost

Length of output: 1731


🏁 Script executed:

# Check if Logging is referenced anywhere in the codebase
rg -n 'Logging|logging' --type=go -C2

Repository: devzeebo/bifrost

Length of output: 42


🏁 Script executed:

# Check Viper configuration for field handling
rg -n 'v\.' cli/config.go | head -20

Repository: devzeebo/bifrost

Length of output: 445


🏁 Script executed:

# Look for any error handling related to unknown fields
rg -n 'unknown|unmapped|extra.*field|field.*extra' --type=go -i

Repository: devzeebo/bifrost

Length of output: 9764


🌐 Web query:

Viper library default behavior unknown fields YAML unmarshalling

💡 Result:

The Viper library's default behavior for YAML unmarshalling regarding unknown fields is to ignore them silently. Viper reads YAML (or other formats) into its internal map[string]any representation, then uses the mapstructure library's Unmarshal (via viper.Unmarshal) to decode that map into a Go struct. By default, mapstructure ignores keys in the source map that do not match any struct fields, without error. To error on unknown fields instead, use viper.UnmarshalExact, which configures mapstructure with ErrorUnused=true, causing it to fail if there are unmapped keys. This applies specifically after YAML parsing; the YAML decoder itself (used by Viper for reading config files) is lenient and does not strict-unmarshal to structs directly—YAML goes to the map first.

Citations:


Remove or implement support for logging: verbose.

The Logging field is not present in OrchestrateConfig (cli/orchestrate.go). Because the code uses Viper's standard .Unmarshal() method (not .UnmarshalExact()), this unsupported key is silently ignored at runtime rather than raising a config error. Either remove logging: verbose from .bifrost.yaml if it's unintended, or add a Logging field to OrchestrateConfig with appropriate mapstructure tag if it should be honored.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.bifrost.yaml at line 6, The .bifrost.yaml contains an unsupported key
"logging: verbose" that is ignored because Viper's Unmarshal is used; either
remove the key from the YAML or add a Logging field to the OrchestrateConfig
struct in cli/orchestrate.go (with the proper `mapstructure:"logging"` tag and
an appropriate type, e.g., string or map[string]interface{}) so the setting is
recognized at runtime; update any related usage sites that read
OrchestrateConfig to handle the new field if you choose to implement it.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ node_modules
ui/dist
.worktrees/

**/__pycache__

# Ignore embedded UI dist artifacts but keep the folder
server/admin/ui/*
!server/admin/ui/.gitkeep
Expand Down
16 changes: 12 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ else
endif

.PHONY: deps build build-server build-cli build-ui ui-dist \
test test-go test-ui \
lint lint-go lint-ui \
test test-go test-ui test-py \
lint lint-go lint-ui lint-py \
vet tidy \
dev prod docker clean list help

Expand Down Expand Up @@ -56,7 +56,7 @@ build-ui: ui-dist

# ── Quality ───────────────────────────────────────────────────────────────────

test: test-go test-ui
test: test-go test-ui test-py

test-go:
@echo "» go test $(ARGS) $(GO_TARGETS)"
Expand All @@ -66,7 +66,11 @@ test-ui:
@echo "» vitest run"
cd ui && npm run test -- --run

lint: lint-go lint-ui
test-py:
@echo "» uv test"
cd claude-orchestrator && uv run python -m pytest

lint: lint-go lint-ui lint-py

lint-go:
@echo "» golangci-lint run $(ARGS) $(GO_TARGETS)"
Expand All @@ -76,6 +80,10 @@ lint-ui:
@echo "» oxlint"
cd ui && npm run lint

lint-py:
@echo "» uv run ruff"
cd claude-orchestrator && uv run ruff check --fix . && uv run ruff format .

vet:
@echo "» go vet $(ARGS) $(GO_TARGETS)"
go vet $(ARGS) $(GO_TARGETS)
Expand Down
17 changes: 17 additions & 0 deletions claude-orchestrator/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Claude Orchestrator

Uses the Claude Agent SDK (https://code.claude.com/docs/en/agent-sdk/overview)
to create an orchestrator. This orchestrator will receive a Rune description
via stdin:

```json
{"branch":"feat/test","created_at":"2026-04-10T20:23:37.222802Z","dependencies_count":0,"dependents_count":0,"id":"bf-7165","priority":0,"status":"open","tags":["worker:decompose"],"title":"Test Rune","type":"rune","updated_at":"2026-04-10T21:06:30.945272Z"}
```

We should extract the expected Agent from the tags such that
"worker:<agent-name>" invokes the "<agent-name>" agent via the Claude Code SDK,
and then wait for the completion.

# Architecture

Latest python, uv, always use latest packages
Loading
Loading