Skip to content
Merged
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 .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
go-version: '1.24'
goreleaser-config: '.goreleaser.yaml'
goreleaser-args: 'release --clean'
secrets: inherit
permissions:
contents: write
packages: write
4 changes: 4 additions & 0 deletions .github/workflows/reusable-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ name: Reusable Build

on:
workflow_call:
secrets:
HOMEBREW_TAP_GITHUB_TOKEN:
required: false
inputs:
go-version:
type: string
Expand Down Expand Up @@ -73,4 +76,5 @@ jobs:
args: ${{ inputs.goreleaser-args }} --config=${{ inputs.goreleaser-config }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
RELEASE_NAME: ${{ inputs.release-name }}
41 changes: 41 additions & 0 deletions .github/workflows/tag-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Tag Release

on:
push:
branches:
- develop
paths:
- VERSION

permissions:
contents: write

jobs:
tag:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Read version
id: ver
run: echo "version=v$(cat VERSION | tr -d '[:space:]')" >> "$GITHUB_OUTPUT"

- name: Check if tag already exists
id: check
run: |
if git rev-parse "${{ steps.ver.outputs.version }}" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: Create and push tag
if: steps.check.outputs.exists == 'false'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "${{ steps.ver.outputs.version }}" -m "Release ${{ steps.ver.outputs.version }}"
git push origin "${{ steps.ver.outputs.version }}"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ go.work.sum
# Arc state directory
.arc/

# Local test workspaces (created by arc workspace init during development)
workspace/

# Legacy UI (kept as reference during 018-ui-design rebuild)
pkg/ui.legacy/

Expand Down
6 changes: 3 additions & 3 deletions .goreleaser.feature.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ builds:
goarch: arm64
ldflags:
- -s -w
- -X github.com/arc-framework/arc-cli/internal/version.Version={{.Version}}
- -X github.com/arc-framework/arc-cli/internal/version.GitCommit={{.Commit}}
- -X github.com/arc-framework/arc-cli/internal/version.BuildDate={{.Date}}
- -X github.com/arc-framework/arc-cli/pkg/version.Version={{.Version}}
- -X github.com/arc-framework/arc-cli/pkg/version.Commit={{.Commit}}
- -X github.com/arc-framework/arc-cli/pkg/version.BuildDate={{.Date}}

archives:
- id: arc-archive
Expand Down
6 changes: 3 additions & 3 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ builds:
goarch: arm64
ldflags:
- -s -w
- -X github.com/arc-framework/arc-cli/internal/version.Version={{.Version}}
- -X github.com/arc-framework/arc-cli/internal/version.GitCommit={{.Commit}}
- -X github.com/arc-framework/arc-cli/internal/version.BuildDate={{.Date}}
- -X github.com/arc-framework/arc-cli/pkg/version.Version={{.Version}}
- -X github.com/arc-framework/arc-cli/pkg/version.Commit={{.Commit}}
- -X github.com/arc-framework/arc-cli/pkg/version.BuildDate={{.Date}}

archives:
- id: arc-archive
Expand Down
9 changes: 8 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Auto-generated from all feature plans. Last updated: 2026-02-16

## Active Technologies
- Go 1.24.2 (go.mod declares 1.26.0) + cobra, charmbracelet/bubbletea v1.3.4, charmbracelet/huh, charmbracelet/lipgloss v1.1.1, charmbracelet/bubbles v0.21.0; `pkg/catalog` (existing internal package) (020-pre-release)
- `//go:embed` for `profiles.yaml` (new) and existing `services.yaml` (unchanged); no new DB (020-pre-release)

- Go 1.24.2 (016-ui-layout-fix)
- N/A (UI-only feature, no persistence required) (016-ui-layout-fix)
Expand All @@ -27,16 +29,21 @@ tests/
Go 1.24.0: Follow standard conventions

## Recent Changes
- 020-pre-release: Added Go 1.24.2 (go.mod declares 1.26.0) + cobra, charmbracelet/bubbletea v1.3.4, charmbracelet/huh, charmbracelet/lipgloss v1.1.1, charmbracelet/bubbles v0.21.0; `pkg/catalog` (existing internal package)

- 017-ui-engine: Added UI engine (pkg/ui/engine/), views (pkg/ui/views/), ARC_USE_LEGACY_UI env var for rollback

- 016-ui-layout-fix: Added Go 1.24.2

- 015-ui-refactor: Added Go 1.24.0 + charmbracelet/bubbletea v1.3.4, charmbracelet/bubbles v0.21.0,
charmbracelet/lipgloss v1.1.1, charmbracelet/glamour v0.10.0, charmbracelet/harmonica v0.2.0, charmbracelet/x/ansi
v0.8.0, charmbracelet/x/term v0.2.1, spf13/cobra, charmbracelet/huh (NEW — RECOMMENDED for interactive forms)

<!-- MANUAL ADDITIONS START -->
## Commit Conventions
- NEVER add `Co-Authored-By` trailers to commit messages or PR descriptions
- Commit messages use Conventional Commits: `type(scope): description`
- No AI attribution lines of any kind in commits or PRs

## UI Engine Architecture (017)
- New views: pkg/ui/views/ (dashboardview.go, serviceslistview.go, etc.)
- Engine: pkg/ui/engine/ (Render, TUIMode, JSONMode, ViewContext)
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
# Define Go packages to be used in tests
ALL_PKGS := $(shell go list ./cmd/... ./internal/... ./pkg/...)
CORE_PKGS := $(shell go list ./internal/... ./pkg/store/... ./pkg/log/... ./pkg/ui/...)
# pkg/store/local is excluded from race testing: its rotation test performs O(n²) disk
# reads (1000+ iterations × full YAML parse each) which times out under -race overhead.
RACE_PKGS := $(shell go list ./internal/... ./pkg/store \
./pkg/log/... ./pkg/ui/...)
CLI_PKGS := $(shell go list ./pkg/cli/...)

# Build flags
Expand Down Expand Up @@ -228,7 +232,9 @@ clean:
test:
$(call log_section,🧪 Running Tests)
$(call log_info,Running core package tests with race detector...)
@go test -v -race $(CORE_PKGS)
@go test -v -race $(RACE_PKGS)
$(call log_info,Running I/O packages without race detector \(O\(n²\) disk reads are too slow under -race\)...)
@go test -v ./pkg/store/local/...
$(call log_info,Running CLI tests (sequential)...)
@go test -v -p 1 $(CLI_PKGS)
$(call log_success,Tests complete)
Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.2.0
29 changes: 29 additions & 0 deletions arc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# A.R.C. Workspace Manifest
# Documentation: https://github.com/arc-framework/arc-cli

# Semantic version of arc.yaml format
version: "1.0.0"

# Platform tier — controls which services are started.
# Options: think (core only), reason (+ reasoning engine), ultra-instinct (all capabilities)
tier: "think"

# Optional capability bundles to add on top of the tier preset.
# Each capability unlocks additional services and resolves its own dependencies.
# Available: reasoner, voice, observe, security, storage
# capabilities:
# - reasoner # LLM reasoning engine — required by voice
# - voice # Voice agent (STT + TTS + LiveKit)
# - observe # Observability stack (SigNoz + OpenTelemetry)
# - security # Secrets vault + feature flags (OpenBao + Unleash)
# - storage # Object storage (MinIO)

# Service-specific overrides (optional)
# services:
# arc-gateway:
# enabled: true

# Environment variables injected into all services (optional)
# environment:
# LOG_LEVEL: "info"
# ENVIRONMENT: "development"
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ go 1.26.0
require (
github.com/charmbracelet/bubbles v1.0.0
github.com/charmbracelet/bubbletea v1.3.10
github.com/charmbracelet/harmonica v0.2.0
github.com/charmbracelet/huh v0.8.0
github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834
github.com/charmbracelet/log v0.4.2
Expand All @@ -24,6 +23,7 @@ require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/catppuccin/go v0.3.0 // indirect
github.com/charmbracelet/colorprofile v0.4.2 // indirect
github.com/charmbracelet/harmonica v0.2.0 // indirect
github.com/charmbracelet/x/ansi v0.11.6 // indirect
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
Expand Down
29 changes: 29 additions & 0 deletions internal/app/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
package app

import (
"sort"

"github.com/arc-framework/arc-cli/pkg/ui/engine"
"github.com/arc-framework/arc-cli/pkg/ui/theme"
"github.com/arc-framework/arc-cli/pkg/ui/view"
)

// EngineConfig builds an engine.Config from the application context.
Expand Down Expand Up @@ -33,3 +36,29 @@ func EngineConfig(
Loader: loader,
}
}

// BuildDefaultViews returns the full ordered view set for the ARC dashboard.
// InitWizard is included but NavHidden — it is activated via InitialView.
func BuildDefaultViews(loader *theme.Loader) []engine.View {
profiles := sortedProfiles(loader.GetProfiles())
return []engine.View{
view.NewHome(),
view.NewServicesList(),
view.NewWorkspaceInfo(),
view.NewWorkspaceHistory(),
view.NewConfigOverview(profiles, loader),
view.NewInitWizard(),
}
}

// sortedProfiles returns profiles sorted alphabetically by Name.
func sortedProfiles(m map[string]*theme.Profile) []*theme.Profile {
profiles := make([]*theme.Profile, 0, len(m))
for _, p := range m {
profiles = append(profiles, p)
}
sort.Slice(profiles, func(i, j int) bool {
return profiles[i].Name < profiles[j].Name
})
return profiles
}
22 changes: 16 additions & 6 deletions pkg/catalog/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,16 @@ const (
// FilterInfrastructure returns only infrastructure services.
FilterInfrastructure

// FilterData returns only data and memory services.
FilterData
// FilterService returns only AI workforce / service tier services.
FilterService

// FilterAI returns only AI workforce services.
FilterAI
// FilterSidecar returns only sidecar process services.
FilterSidecar

// FilterObservability returns only observability services.
FilterObservability
// Deprecated filters kept for backward compatibility.
FilterData // no services match this role in current catalog
FilterAI // no services match this role in current catalog
FilterObservability // no services match this role in current catalog
)

// ToRole converts a ServiceFilter to its corresponding ServiceRole.
Expand All @@ -150,6 +152,10 @@ func (f ServiceFilter) ToRole() ServiceRole {
switch f {
case FilterInfrastructure:
return RoleInfrastructure
case FilterService:
return RoleService
case FilterSidecar:
return RoleSidecar
case FilterData:
return RoleData
case FilterAI:
Expand All @@ -168,6 +174,10 @@ func (f ServiceFilter) String() string {
return "All"
case FilterInfrastructure:
return "Infrastructure"
case FilterService:
return "Service"
case FilterSidecar:
return "Sidecar"
case FilterData:
return "Data"
case FilterAI:
Expand Down
Loading
Loading