rdev/internal/sdlc/paths.go
jordan 425ef0f806 feat: add SDLC orchestration - library, CLI, and API integration
Implements deterministic feature lifecycle management for agent-driven
development. Agents use the CLI in pods; operators control via REST API.

Library (internal/sdlc/):
- Feature lifecycle with 10 phases (draft → released)
- Classifier engine with priority-ordered rules
- Artifact tracking with approval workflow
- Task management within features
- YAML-based state persistence

CLI (cmd/sdlc/):
- init, state, next, feature, artifact, task, query commands
- --json flag for machine-readable output
- Runs inside project pods

API (21 endpoints under /projects/{id}/sdlc/):
- State: GET /state, GET /next
- Features: CRUD + transition/block/unblock
- Artifacts: approve/reject per type
- Tasks: add/start/complete/block
- Queries: blocked/ready/needs-approval

Architecture:
- Port: SDLCExecutor interface (internal/port/)
- Adapter: kubectl exec into pods (internal/adapter/kubernetes/)
- Service: pod resolution + logging (internal/service/)
- Handlers: 5 files under 500-line limit (internal/handlers/)

Also includes template upgrades (chassis framework, UI components,
OpenAPI helpers, backend/frontend guides) and component improvements.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 09:57:05 -07:00

100 lines
2.4 KiB
Go

package sdlc
import (
"path/filepath"
"regexp"
)
const (
// SDLCDir is the root directory name for SDLC state.
SDLCDir = ".sdlc"
// StateFile is the filename for global state.
StateFile = "state.yaml"
// ConfigFile is the filename for project config.
ConfigFile = "config.yaml"
// FeaturesDir holds per-feature subdirectories.
FeaturesDir = "features"
// PatternsDir holds pattern definitions.
PatternsDir = "patterns"
// AuditsDir holds audit reports.
AuditsDir = "audits"
// BranchesDir holds branch tracking files.
BranchesDir = "branches"
// ArchivesDir holds archived (released) features.
ArchivesDir = "archives"
// RoadmapDir holds roadmap documents.
RoadmapDir = "roadmap"
// ManifestFile is the per-feature metadata file.
ManifestFile = "manifest.yaml"
)
var slugPattern = regexp.MustCompile(`^[a-z][a-z0-9-]*$`)
// ValidateSlug returns nil if the slug is valid, ErrInvalidSlug otherwise.
func ValidateSlug(slug string) error {
if slug == "" || len(slug) > 64 || !slugPattern.MatchString(slug) {
return ErrInvalidSlug
}
return nil
}
// SDLCRoot returns the .sdlc directory path within a project root.
func SDLCRoot(root string) string {
return filepath.Join(root, SDLCDir)
}
// StatePath returns the path to state.yaml.
func StatePath(root string) string {
return filepath.Join(root, SDLCDir, StateFile)
}
// ConfigPath returns the path to config.yaml.
func ConfigPath(root string) string {
return filepath.Join(root, SDLCDir, ConfigFile)
}
// FeaturesDirPath returns the features/ directory path.
func FeaturesDirPath(root string) string {
return filepath.Join(root, SDLCDir, FeaturesDir)
}
// FeatureDir returns the directory for a specific feature.
func FeatureDir(root, slug string) string {
return filepath.Join(root, SDLCDir, FeaturesDir, slug)
}
// ManifestPath returns the manifest.yaml path for a feature.
func ManifestPath(root, slug string) string {
return filepath.Join(root, SDLCDir, FeaturesDir, slug, ManifestFile)
}
// ArtifactPath returns the file path for a feature artifact.
func ArtifactPath(root, slug string, artifactType ArtifactType) string {
filename := ArtifactFilename(artifactType)
if filename == "" {
return ""
}
return filepath.Join(root, SDLCDir, FeaturesDir, slug, filename)
}
// SubDirs returns all subdirectories that sdlc init creates.
func SubDirs() []string {
return []string{
FeaturesDir,
PatternsDir,
AuditsDir,
BranchesDir,
ArchivesDir,
RoadmapDir,
}
}