workspace

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package workspace models a reel workspace on disk — the resumable unit of the authoring loop (spec 0001 §3.2, contract 0002 §2). A workspace is a directory the owning project commits; keryx is stateless and only requires the internal shape. All operations go through an afero.Fs so they unit-test in memory.

Index

Constants

View Source
const (
	KindVO    = "vo"
	KindCard  = "card"
	KindMusic = "music"
	KindCover = "cover"
)

Lock kinds — the selected asset kinds that can be reviewed/approved ("locked").

View Source
const (
	MetaFile       = "workspace.yaml"
	StoryboardFile = "storyboard.json"
	SocialFile     = "social.json"
	CoverFile      = "cover.png"
	MusicFile      = "music.mp3"
	ReelFile       = "reel.mp4"
	// SourceFile holds pasted source content for the reel — the subject material
	// when NO article is linked (a linked reel's subject is the article itself,
	// 0029 §9 note 44). Also seeds `storyboard draft` + the studio chat (R-UI-4).
	SourceFile = "source.md"
	// DirectionFile holds the reel's creative direction (0029 §9 note 44):
	// explicit intent — what the reel should convey, the emotions to invoke —
	// that grounds AI generation ALONGSIDE the subject (article or source).
	DirectionFile = "direction.md"
	VODir         = "vo"
	CardsDir      = "cards"
)

File / dir names within a workspace (the 0002 §2 contract).

View Source
const SchemaVersion = 1

SchemaVersion is recorded in workspace.yaml so an old workspace fails loudly rather than mis-rendering (R-WS-2).

Variables

View Source
var (
	ErrInvalidSlug = errors.NewSentinel("keyrx.invalid_slug", "invalid slug (want lowercase kebab-case)")
	ErrExists      = errors.NewSentinel("keyrx.exists", "workspace already exists")
	ErrNotFound    = errors.NewSentinel("keyrx.not_found", "workspace not found")
)

Sentinel errors.

Functions

func Dir

func Dir(root, slug string) string

Dir returns the workspace directory path under a reel root.

func Duplicate

func Duplicate(fs afero.Fs, root, srcSlug, dstSlug string) error

Duplicate copies a workspace's authoring inputs into a new slug but resets the posting status — a copy hasn't been posted, so social.json is not carried (R-WS-17). takes/ and .cache/ are skipped (regenerable).

func KindIndexed added in v0.4.0

func KindIndexed(kind string) (bool, error)

KindIndexed reports whether a lock kind is keyed by a 1-based index (vo/card) rather than being a singleton (music/cover); it also validates the kind, so the command layer can give a clear error before touching state.

func Link(fs afero.Fs, root, slug, bundle string) error

Link records an associated content directory (a page bundle or any dir) on the workspace (R-WS-19).

func LoadStoryboard

func LoadStoryboard(fs afero.Fs, dir string) (reel.Storyboard, error)

Load reads workspace.yaml from dir. LoadStoryboard reads + parses a workspace's storyboard.json — the one canonical loader shared by the gen, build, and make paths.

func New

func New(fs afero.Fs, root string, meta Meta, force bool) (string, error)

New scaffolds a workspace at root/<slug>: workspace.yaml, an empty schema-valid storyboard.json, the vo/ + cards/ dirs, and a .gitignore for takes/cache. It refuses to clobber an existing workspace unless force is set (R-WS-5).

func Relabel added in v0.9.0

func Relabel(fs afero.Fs, root, slug, label string) error

Relabel sets a reel's human label (spec 0033) — the id/dir stays stable; only the display name changes. An empty label clears it (the UI falls back to the slug).

func Remove

func Remove(fs afero.Fs, root, slug string) error

Remove deletes a workspace directory.

func Rename

func Rename(fs afero.Fs, root, oldSlug, newSlug string) error

Rename re-slugs a workspace (directory + meta.Slug). It refuses to clobber an existing destination (R-WS-18).

func Save

func Save(fs afero.Fs, dir string, meta Meta) error

Save writes workspace.yaml in dir.

func Status

func Status(fs afero.Fs, dir string) string

Status is a coarse workspace status for `reel list`. The detailed per-platform status (draft → approved → posted) is read from social.json once the posting layer (Phase 2) defines it; until then a workspace with no social.json is a plain "draft" and one with a social set is "social".

func ValidateSlug

func ValidateSlug(slug string) error

ValidateSlug checks a slug is short kebab-case with no path separators.

Types

type Locked added in v0.4.0

type Locked struct {
	VO    []int `yaml:"vo,omitempty"`
	Cards []int `yaml:"cards,omitempty"`
	Music bool  `yaml:"music,omitempty"`
	Cover bool  `yaml:"cover,omitempty"`
}

Locked records which selected assets have been approved and frozen, so tooling treats them as immutable (a re-roll/pick refuses without --force; `reel make` skips them). VO and cards are keyed by 1-based index; music and cover are singletons. Stored in workspace.yaml under `locked` (spec 0025).

func (*Locked) Add added in v0.4.0

func (l *Locked) Add(kind string, index int) error

Add locks the asset. For vo/card an index >= 1 is required; music/cover ignore it.

func (*Locked) Count added in v0.4.0

func (l *Locked) Count() int

Count is the total number of locked assets.

func (*Locked) Has added in v0.4.0

func (l *Locked) Has(kind string, index int) bool

Has reports whether the given asset is locked. index is ignored for singletons.

func (*Locked) Remove added in v0.4.0

func (l *Locked) Remove(kind string, index int) error

Remove unlocks the asset. Idempotent — unlocking something not locked is a no-op.

type Meta

type Meta struct {
	Slug string `yaml:"slug"`
	// Label is the reel's human name in the studio (spec 0033) — a post may have
	// several reels, distinguished by label; the id (Slug/dir) stays stable. Additive
	// and optional: a reel without a label falls back to its slug in the UI.
	Label string `yaml:"label,omitempty"`
	Theme string `yaml:"theme,omitempty"`
	// Avatars is the reel's cast — the avatar names (from the project registry) this
	// reel uses (spec 0034 D4). Scenes tick a subset of it; empty = no cast.
	Avatars []string `yaml:"avatars,omitempty"`
	// Aspect overrides the reel's frame shape ("W:H", 0029 §9 note 27). Empty =
	// the configured default (reel.aspect), itself defaulting to 9:16.
	Aspect        string `yaml:"aspect,omitempty"`
	Bundle        string `yaml:"bundle,omitempty"`
	SchemaVersion int    `yaml:"schema_version"`
	// Unreviewed marks a workspace whose storyboard is an unreviewed AI draft
	// (R-WS-8).
	Unreviewed bool `yaml:"unreviewed,omitempty"`
	// Locked records reviewed/approved assets that must not be re-rolled without
	// --force (spec 0025). Omitted from workspace.yaml when nothing is locked.
	Locked Locked `yaml:"locked,omitempty"`
}

Meta is workspace.yaml.

func List

func List(fs afero.Fs, root string) ([]Meta, error)

List returns the workspaces under a reel root, ordered by slug.

func Load

func Load(fs afero.Fs, dir string) (Meta, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL