Organization Customization¶
VisionSpec is designed for organizations to build their own prescriptive CLI tools. This guide explains how to create a custom CLI with organization-specific templates, rubrics, constitutions, and app type constraints.
Architecture Overview¶
┌─────────────────────────────────────────────────────────────────┐
│ Organization CLI │
│ (e.g., plexus-spec, acme-spec) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Org │ │ Org │ │ Org │ │
│ │ Templates │ │ Rubrics │ │ Constitutions│ │
│ │ (prescriptive)│ │ (strict) │ │ (defaults) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ ChainLoader (fallback) │ │
│ └─────────────────────────────────────────────────┘ │
└─────────┬────────────────┬────────────────┬─────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ visionspec (open source) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Default │ │ Default │ │ Built-in │ │
│ │ Templates │ │ Rubrics │ │ App Types │ │
│ │ (flexible) │ │ (choices) │ │ (generic) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Open Source vs. Organization¶
| Aspect | Open Source VisionSpec | Organization CLI |
|---|---|---|
| Templates | Choices and placeholders | Prescriptive with pre-filled values |
| Rubrics | "Database choice documented" | "MUST use PostgreSQL with RLS" |
| Constitutions | None provided | Built-in org/team/project defaults |
| App Types | Generic constraints | Stricter organization requirements |
| Commands | Standard visionspec commands | Standard + org-specific commands |
| Distribution | go install from public repo |
Single binary with embedded resources |
Project Structure¶
org-visionspec/
├── cmd/
│ └── org-spec/
│ └── main.go # CLI entry point
├── templates/ # Organization templates
│ ├── mrd.md
│ ├── prd.md
│ ├── ird.md # Pre-filled with Pulumi, PostgreSQL
│ └── ...
├── rubrics/ # Organization rubrics
│ ├── prd.rubric.yaml
│ ├── trd.rubric.yaml # Stricter criteria
│ └── ...
├── constitutions/ # Organization defaults
│ ├── organization/
│ │ └── acme.yaml # Org-wide defaults
│ ├── team/
│ │ └── platform.yaml # Team overrides
│ └── project/ # Project-specific (optional)
├── apptypes/ # App type constraints
│ ├── microservice.yaml
│ ├── website.yaml
│ └── ...
├── go.mod
└── README.md
Building an Organization CLI¶
Step 1: Create the Project¶
mkdir org-visionspec && cd org-visionspec
go mod init github.com/myorg/org-visionspec
go get github.com/ProductBuildersHQ/visionspec
Step 2: Embed Organization Resources¶
// cmd/org-spec/main.go
package main
import (
"embed"
"os"
"github.com/ProductBuildersHQ/visionspec/pkg/apptypes"
"github.com/ProductBuildersHQ/visionspec/pkg/cli"
"github.com/ProductBuildersHQ/visionspec/pkg/constitution"
"github.com/ProductBuildersHQ/visionspec/pkg/rubrics"
"github.com/ProductBuildersHQ/visionspec/pkg/templates"
"github.com/spf13/cobra"
)
//go:embed templates/*.md
var orgTemplates embed.FS
//go:embed rubrics/*.yaml
var orgRubrics embed.FS
//go:embed constitutions/**/*.yaml
var orgConstitutions embed.FS
//go:embed apptypes/*.yaml
var orgAppTypes embed.FS
func main() {
root := &cobra.Command{
Use: "org-spec",
Short: "Organization VisionSpec CLI",
Long: `Custom visionspec CLI with organization standards.
Enforced standards:
- Go backend with Huma+Chi for REST APIs
- PostgreSQL with RLS for multi-tenancy
- Pulumi (Go SDK) for Infrastructure as Code
- 99.9% availability minimum for microservices`,
}
cfg := orgConfig()
cli.AddCommandsTo(root, cfg)
// Add organization-specific commands
root.AddCommand(complianceCmd())
if err := root.Execute(); err != nil {
os.Exit(1)
}
}
Step 3: Configure Loaders with ChainLoader¶
The key pattern is ChainLoader: organization resources first, then fall back to visionspec defaults.
func orgConfig() *cli.Config {
cfg := cli.DefaultConfig()
cfg.Version = "1.0.0-acme"
// Templates: Org first, then visionspec defaults
cfg.TemplateLoader = templates.NewChainLoader(
templates.NewEmbedFSLoader(orgTemplates, "templates"),
templates.EmbeddedLoader(),
)
// Rubrics: Org first, then visionspec defaults
cfg.RubricLoader = rubrics.NewChainLoader(
rubrics.NewEmbedFSLoader(orgRubrics, "rubrics"),
rubrics.EmbeddedLoader(),
)
// Constitutions: Org-specific only (no fallback)
cfg.ConstitutionLoader = constitution.NewEmbeddedLoader(
orgConstitutions, "constitutions",
)
// App Types: Org first, then visionspec defaults
cfg.AppTypeLoader = apptypes.NewChainLoader(
apptypes.NewEmbeddedLoader(orgAppTypes, "apptypes"),
apptypes.DefaultLoader(),
)
return cfg
}
Step 4: Create Organization Templates¶
Organization templates are more prescriptive. Instead of placeholders, they have pre-filled values:
<!-- templates/ird.md -->
# Infrastructure Requirements Document (IRD)
## Required Declarations
### Infrastructure as Code (IaC) Declaration
| Choice | Tool | Justification |
|--------|------|---------------|
| [x] **Pulumi** | Go SDK | Organization standard: type-safe, Go-native |
### Observability Declaration
| Pillar | Declaration | Tool/Platform | Justification |
|--------|-------------|---------------|---------------|
| **Metrics** | [x] Implementing | Prometheus + Grafana | Organization standard |
| **Traces** | [x] Implementing | OpenTelemetry | Organization standard |
| **Logging** | [x] Implementing | Loki + Grafana | Organization standard |
## Database
- **Type:** PostgreSQL (organization standard)
- **Multi-tenancy:** Row Level Security (RLS)
- **Tenant context:** `SET app.current_tenant = :tenant_id`
Step 5: Create Organization Rubrics¶
Organization rubrics have stricter evaluation criteria:
# rubrics/trd.rubric.yaml
spec_type: trd
name: "Organization TRD Evaluation"
categories:
- id: language_choice
name: "Language Choice"
weight: 0.15
required: true
criteria:
pass: "Uses Go for backend services. Exceptions documented with approval."
partial: "Uses Go but missing exception documentation for non-Go components."
fail: "Uses non-Go backend without documented exception approval."
- id: database_choice
name: "Database Choice"
weight: 0.15
required: true
criteria:
pass: "Uses PostgreSQL with RLS for multi-tenancy."
partial: "Uses PostgreSQL but RLS not configured."
fail: "Uses non-PostgreSQL database without exception approval."
Constitution System¶
Constitutions define organizational defaults that flow through a hierarchy.
Hierarchy¶
org/acme.yaml # Organization-wide defaults
↓ inherits
team/platform.yaml # Team overrides
↓ inherits
project/myservice.yaml # Project-specific choices
Organization Constitution¶
# constitutions/organization/acme.yaml
apiVersion: visionspec/v1
kind: Constitution
metadata:
name: acme
level: organization
version: "1.0"
technical:
languages:
backend:
primary: go
allowed: [go, rust]
exceptionsRequire: approval
frontend:
primary: typescript
wasm: rust
apis:
rest:
framework: huma-chi
specFormat: openapi-3.1
styleGuide: google-api-design-guide
database:
relational: postgresql
multiTenancy: rls
tenancy:
model: multi-tenant
isolation: rls
tenantIdHeader: X-Tenant-ID
infrastructure:
iac:
tool: pulumi
language: go
availability:
target: "99.9"
rto: "1h"
rpo: "15m"
observability:
metrics:
platform: prometheus
visualization: grafana
traces:
collector: opentelemetry-collector
logging:
platform: loki
prompts:
languageChoice: |
Go is the primary backend language.
Consider Rust only for:
- CPU-intensive processing
- WASM modules
- Memory-critical components
Exceptions require tech lead approval.
Team Constitution¶
# constitutions/team/platform.yaml
apiVersion: visionspec/v1
kind: Constitution
metadata:
name: platform
level: team
inherits: organization/acme # Inherits from org
infrastructure:
# Team has higher availability requirement
availability:
target: "99.99"
multiAZ: true
Project Constitution¶
# constitutions/project/myservice.yaml
apiVersion: visionspec/v1
kind: Constitution
metadata:
name: myservice
level: project
inherits: team/platform
# Project-specific deployment targets
infrastructure:
localDev:
priority:
- binaries
- podman
- localstack # Need AWS emulation
# Documented exceptions
exceptions:
- field: technical.languages.backend
value: rust
component: wasm-inference
justification: "WASM performance requirements"
approvedBy: tech-lead
approvedAt: "2026-05-15"
Resolving Constitutions¶
// Resolve inheritance chain
resolver := constitution.NewResolver(cfg.ConstitutionLoader)
resolved, err := resolver.ResolveChain("project/myservice")
// Result has all inherited values merged
fmt.Println(resolved.Technical.Languages.Backend.Primary) // "go"
fmt.Println(resolved.Infrastructure.Availability.Target) // "99.99"
App Type Specifications¶
App types define constraints per application category:
# apptypes/microservice.yaml
apiVersion: visionspec/v1
kind: AppTypeSpec
metadata:
name: microservice
version: "1.0"
artifacts:
required:
- binary
- container-image
optional:
- openapi-spec
- helm-chart
defaults:
technical:
apiStyles: [rest, grpc]
embeddedDb: false
statefulAllowed: false
infrastructure:
containerized: true
horizontalScaling: true
minAvailabilityTarget: "99.9"
specs:
required: [mrd, prd, trd, ird]
optional: [uxd, press, faq]
constraints:
tenancy:
allowed: [single-tenant, multi-tenant]
availability:
minimum: "99.9"
Adding Organization Commands¶
func complianceCmd() *cobra.Command {
return &cobra.Command{
Use: "compliance",
Short: "Check project compliance with organization standards",
RunE: func(cmd *cobra.Command, args []string) error {
// 1. Load project constitution
// 2. Resolve inheritance chain
// 3. Validate against org requirements
// 4. Report deviations
return nil
},
}
}
Distribution¶
Build a single binary with all resources embedded:
# Build for current platform
go build -o org-spec ./cmd/org-spec
# Cross-compile for distribution
GOOS=linux GOARCH=amd64 go build -o org-spec-linux ./cmd/org-spec
GOOS=darwin GOARCH=arm64 go build -o org-spec-darwin ./cmd/org-spec
The binary is self-contained—no external files needed.
Best Practices¶
- Version constitutions - Use semantic versioning for constitution changes
- Document exceptions - Require justification and approval for deviations
- Gradual rollout - Use ChainLoader to fall back to defaults during migration
- Test rubrics - Ensure evaluation criteria are unambiguous
- Embed everything - Single binary distribution simplifies deployment